diff --git a/Documentation/devicetree/bindings/arm/idle-states.txt b/Documentation/devicetree/bindings/arm/idle-states.txt index b8e41c148a3c..a470c29a76e3 100644 --- a/Documentation/devicetree/bindings/arm/idle-states.txt +++ b/Documentation/devicetree/bindings/arm/idle-states.txt @@ -489,7 +489,7 @@ cpus { CPU15: cpu@100010101 { device_type = "cpu"; - compatible = "arm,cortex-a53"; + compatible = "arm,cortex-a73","arm,armv8"; reg = <0x1 0x10101>; enable-method = "psci"; cpu-idle-states = <&CPU_RETENTION_1_0 &CPU_SLEEP_1_0 diff --git a/Documentation/devicetree/bindings/clock/amlogic,meson-clkc.txt b/Documentation/devicetree/bindings/clock/amlogic,meson-clkc.txt index 651860382060..d9b8a3da5da5 100644 --- a/Documentation/devicetree/bindings/clock/amlogic,meson-clkc.txt +++ b/Documentation/devicetree/bindings/clock/amlogic,meson-clkc.txt @@ -22,6 +22,9 @@ Required Properties: "amlogic,tl1-clkc" - for tl1 ee clock "amlogic,tl1-aoclkc" - for tl1 ao clock "amlogic,tl1-measure" - for tl1 clock measurement + "amlogic,sm1-clkc-1" - for sm1 ee part1 clock + "amlogic,sm1-clkc-2" - for sm1 ee part2 clock + "amlogic,sm1-aoclkc" - for sm1 ao clock - reg: physical base address of the clock controller and length of memory mapped region. diff --git a/Documentation/devicetree/bindings/crypto/aml-crypto.txt b/Documentation/devicetree/bindings/crypto/aml-crypto.txt index bf76d17212b8..4d1cc941b76c 100644 --- a/Documentation/devicetree/bindings/crypto/aml-crypto.txt +++ b/Documentation/devicetree/bindings/crypto/aml-crypto.txt @@ -2,10 +2,12 @@ These are the HW cryptographic accelerators found on Amlogic products. +*For S805 series and S905 series + * Advanced Encryption Standard (AES) Required properties: -- compatible : Should be "amlogic,aes" for aes-128/192/256 or "amlogic,aes_g12a_dma" for aes-128/256 +- compatible : Should be "amlogic,aes" for aes-128/192/256 - dev_name : Should be "aml_aes" - interrupts: Should contain the IRQ line for the AES. - resets: Should contain the clock to enable the module @@ -25,10 +27,10 @@ aml_aes{ Required properties: - compatible : Should be "amlogic,des,tdes". -- dev_name : Should be "aml_aes" +- dev_name : Should be "aml_tdes" - interrupts: Should contain the IRQ line for the TDES. - resets: Should contain the clock to enable the module -- reg: Should contain the base address of regs +- reg: Should contain the base address of regs Example: aml_tdes{ @@ -40,29 +42,16 @@ aml_tdes{ 0x0 0xda832000 0x0 0xe4>; }; -* Secure Hash Algorithm (SHA1/SHA224/SHA256) +******************************************************************************** -Required properties: -- compatible : Should be "amlogic,sha". -- dev_name : Should be "aml_sha" -- interrupts: Should contain the IRQ line for the SHA. -- resets: Should contain the clock to enable the module -- reg: Should contain the base address of regs +* For S905X series and beyond +* S905X series use gxl +* T962X series use txlx +* S905X2 series use g12a -Example: -aml_sha{ - compatible = "amlogic,sha"; - dev_name = "aml_sha"; - interrupts = <0 36 1>; - resets = <&clock GCLK_IDX_BLK_MOV>; - reg = <0x0 0xc8832000 0x0 0x2c4 - 0x0 0xda832000 0x0 0xe4>; -}; - -* New DMA for GXL and beyond * Dma engine for crypto operations Required properties: -- compatible : Should be "amlogic,aml_gxl_dma" or "amlogic,aml_txlx_dma". +- compatible : Should be "amlogic,aml_gxl_dma" or "amlogic,aml_txlx_dma" - reg: Should contain the base address of regs - interrupts: Should contain the IRQ line for DMA. @@ -76,8 +65,9 @@ aml_dma { * Advanced Encryption Standard (AES) Required properties: -- compatible : Should be "amlogic,aes". -- dev_name : Should be "aml_aes" +- compatible : Should be "amlogic,aes_dma" for aes-128/192/256 + or "amlogic,aes_g12a_dma" for aes-128/256 +- dev_name : Should be "aml_aes_dma" Example: aml_aes{ @@ -89,8 +79,9 @@ aml_aes{ * Triple Data Encryption Standard (Triple DES) Required properties: -- compatible : Should be "amlogic,des,tdes". -- dev_name : Should be "aml_aes" +- compatible : Should be "amlogic,des_dma,tdes_dma" for gxl + or "amlogic,tdes_dma" for other series. +- dev_name : Should be "aml_tdes_dma" Example: aml_tdes{ @@ -100,8 +91,8 @@ aml_tdes{ * Secure Hash Algorithm (SHA1/SHA224/SHA256/HMAC) Required properties: -- compatible : Should be "amlogic,sha". -- dev_name : Should be "aml_sha" +- compatible : Should be "amlogic,sha_dma". +- dev_name : Should be "aml_sha_dma" Example: aml_sha{ diff --git a/Documentation/devicetree/bindings/interrupt-controller/amlogic,meson-gpio-intc.txt b/Documentation/devicetree/bindings/interrupt-controller/amlogic,meson-gpio-intc.txt index 4dfe69f26186..ec06f877cc5c 100644 --- a/Documentation/devicetree/bindings/interrupt-controller/amlogic,meson-gpio-intc.txt +++ b/Documentation/devicetree/bindings/interrupt-controller/amlogic,meson-gpio-intc.txt @@ -19,6 +19,8 @@ Required properties: “amlogic,meson-g12a-gpio-intc” for G12A SoCs (S905D2, S905X2, S905Y2) “amlogic,meson-txl-gpio-intc” for TXL SoCs (T950, T952, T960, T962) “amlogic,meson-tl1-gpio-intc” for TL1 SoCs (T962X2) + “amlogic,meson-sm1-gpio-intc” for SM1 SoCs (S905D3, S905X3, S905Y3) + “amlogic,meson-tm2-gpio-intc” for TM2 SoCs (T962X3, T962E2) - interrupt-parent : a phandle to the GIC the interrupts are routed to. Usually this is provided at the root level of the device tree as it is common to most of the SoC. diff --git a/MAINTAINERS b/MAINTAINERS index ceaa88a5c4ec..f0721818943c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -11487,7 +11487,6 @@ F: arch/alpha/kernel/srm_env.c STABLE BRANCH M: Greg Kroah-Hartman -M: Sasha Levin L: stable@vger.kernel.org S: Supported F: Documentation/stable_kernel_rules.txt @@ -13528,6 +13527,8 @@ F: drivers/amlogic/memory_ext/* F: include/linux/amlogic/ramdump.h F: include/linux/amlogic/vmap_stack.h F: drivers/amlogic/memory_ext/vmap_stack.c +F: drivers/amlogic/memory_ext/watch_point.c +F: include/linux/amlogic/watch_point.h AMLOGIC driver for memory extend M: Tao Zeng @@ -13545,6 +13546,11 @@ AMLOGIC boot config for M8B M: Tao Zeng F: arch/arm/mach-meson/Makefile.boot +AMLOGIC implementation for 32bit kasan +M: Tao Zeng +F: arch/arm/include/asm/kasan.h +F: arch/arm/mm/kasan_init.c + HDMITX OUTPUT DRIVER M: Yi Zhou M: Zongdong Jiao @@ -13558,6 +13564,7 @@ F: drivers/amlogic/esm/* AMLOGIC DWC_OTG USB M: Yue Wang F: drivers/amlogic/usb/* +F: drivers/amlogic/usb/phy/phy-aml-new-otg.c F: drivers/usb/phy/phy-aml-new-usb.h F: drivers/usb/phy/phy-aml-new-usb.c F: drivers/usb/phy/phy-aml-new-usb2.c @@ -13566,6 +13573,7 @@ F: drivers/usb/phy/phy-aml-new-usb-v2.h F: drivers/usb/phy/phy-aml-new-usb-v2.c F: drivers/usb/phy/phy-aml-new-usb2-v2.c F: drivers/usb/phy/phy-aml-new-usb3-v2.c +F: drivers/amlogic/usb/phy/phy-aml-new-usb3-v3.c F: drivers/usb/phy/phy-aml-usb.h F: drivers/usb/phy/phy-aml-usb.c F: drivers/usb/phy/phy-aml-usb2.c @@ -13798,27 +13806,21 @@ AMLOGIC M8b M: Jianxin Pan F: arch/arm/boot/dts/amlogic> -ANLOGIC AUDIO +ANLOGIC AUDIO DRIVER M: Xing Wang -F: arch/arm64/boot/dts/amlogic/gxl_p212_1g.dts -F: arch/arm64/boot/dts/amlogic/gxl_p212_2g.dts -F: arch/arm64/boot/dts/amlogic/gxl_p230_2g.dts -F: arch/arm64/boot/dts/amlogic/gxm_q200_2g.dts -F: arch/arm64/boot/dts/amlogic/gxm_skt.dts -F: arch/arm64/boot/dts/amlogic/mesongxl.dtsi -F: arch/arm64/boot/dts/amlogic/mesongxm.dtsi +M: Zhe Wang +F: arch/arm64/boot/dts/amlogic/* +F: arch/arm/boot/dts/amlogic/* F: arch/arm64/configs/meson64_defconfig -F: drivers/amlogic/clk/clk-mpll.c -F: drivers/amlogic/clk/clk_misc.c -F: drivers/amlogic/clk/clkc.h -F: drivers/amlogic/clk/gxl.c +F: drivers/amlogic/clk/* F: drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_main.c -F: drivers/amlogic/pinctrl/pinctrl_gxl.c -F: include/dt-bindings/clock/amlogic,gxl-clkc.h -F: include/linux/amlogic/media/sound/audin_regs.h +F: drivers/amlogic/pinctrl/* +F: include/dt-bindings/clock/* +F: include/linux/amlogic/media/sound/* F: sound/soc/Kconfig F: sound/soc/Makefile -F: sound/soc/amlogic/* +F: sound/soc/amlogic/auge/* +F: sound/soc/amlogic/meson/* F: sound/soc/codecs/Kconfig F: sound/soc/codecs/Makefile F: sound/soc/codecs/amlogic/* @@ -13925,6 +13927,7 @@ F: drivers/amlogic/media/enhancement/amvecm/arch/* F: drivers/amlogic/media/enhancement/amvecm/dnlp_algorithm/* F: include/linux/amlogic/media/amvecm/* F: drivers/amlogic/media/enhancement/amvecm/hdr/* +F: drivers/amlogic/media/enhancement/amvecm/amprime_sl/* AMLOGIC GXL ADD SKT DTS M: Yun Cai @@ -14413,6 +14416,7 @@ F: sound/soc/codecs/amlogic/ad82584f.h AMLOGIC CPUFREQS DRIVER M: hong guo +F: drivers/amlogic/cpufreq/meson-cpufreq.h F: drivers/amlogic/cpufreq/meson-cpufreq.c F: drivers/amlogic/clk/clk-cpu-fclk-composite.c @@ -14430,6 +14434,7 @@ F: include/linux/amlogic/meson_cooldev.h AMLOGIC G12A Audio DRIVER M: Xing Wang F: sound/soc/amlogic/auge/* +F: sound/soc/codec/amlogic/* AMLOGIC G12A BL_EXTERN LP8556 DRIVER M: Weiming Liu @@ -14440,6 +14445,11 @@ M: Zhilei Wu F: drivers/amlogic/media/enhancement/amdolby_vision* F: include/linux/amlogic/media/amdolbyvision/* +AMLOGIC HDR PRIMSE SL DRIVER +M: Yi Zhou +F: drivers/amlogic/media/enhancement/amprime_sl/* +F: include/linux/amlogic/media/amprime_sl/* + AMLOGIC G12A Media codec io bus M: Nanxin Qin F: include/linux/amlogic/media/registers/regs/efuse_regs.h @@ -14505,6 +14515,8 @@ F: drivers/amlogic/media/dtv_demod/* AMLOGIC DTV DEMOD DRIVER M: Zhiwei Yuan F: drivers/amlogic/media/dtv_demod/include/addr_atsc*.h +F: drivers/amlogic/media/dtv_demod/include/demod_dbg.h +F: drivers/amlogic/media/dtv_demod/demod_dbg.c AMLOGIC DEFENDKEY DRIVER M: Zhongfu Luo @@ -14512,7 +14524,9 @@ F: drivers/amlogic/defendkey/* AMLOGIC DEBUG M: Jianxin Pan +M: Tao Guo F: drivers/amlogic/debug/* +F: include/linux/amlogic/debug*.h AMLOGIC G12A spdif channel status M: xing wang @@ -14567,6 +14581,10 @@ AMLOGIC G12B w400 buildroot dts M: liangzhuo xie F: arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts +AMLOGIC G12B w411 buildroot dts +M: dianzhong.huo +F: arch/arm64/boot/dts/amlogic/g12b_a311d_w411_buildroot.dts + AMLOGIC P PARTITION DTSI M: Xindong Xu F: arch/arm64/boot/dts/amlogic/firmware_avb.dtsi @@ -14681,9 +14699,11 @@ AMLOGIC TL1 AUDIO EXTERANL INPUT/OUTPUT DRIVERS AMLOGIC TL1 NEW EQDRC AMLOGIC TL1 MIXER CONTROLS AMLOGIC TL1 VAD DRIVER -M: Xing Wang F: arch/arm/boot/dts/amlogic/tl1_pxp.dts F: include/dt-bindings/clock/amlogic,tl1-audio-clk.h +F: include/dt-bindings/clock/amlogic,sm1-audio-clk.h F: include/linux/amlogic/media/sound/misc.h F: include/linux/amlogic/major.h F: sound/soc/amlogic/auge/* @@ -14728,6 +14748,29 @@ F: arch/arm64/boot/dts/amlogic/partition_mbox_ab_P_32.dtsi AMLOGIC BACKLIGHT LDIM DRIVER M: Evoke Zhang F: drivers/amlogic/media/vout/backlight/aml_ldim/ldim_spi.c +F: drivers/amlogic/media/vout/backlight/aml_ldim/ldim_hw.c + +AMLOGIC MESON TL1 DTS +M: Xingyu Chen +M: Bo Yang +F: arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts +F: arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts +F: arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts +F: arch/arm64/boot/dts/amlogic/mesontl1* +F: arch/arm64/boot/dts/amlogic/tl1_t962x2_* + +AMLOGIC MESON TL1 PANEL DTS +M: Evoke Zhang +F: arch/arm/boot/dts/amlogic/mesontl1_skt-panel.dtsi +F: arch/arm/boot/dts/amlogic/mesontl1_x301-panel.dtsi +F: arch/arm/boot/dts/amlogic/mesontl1_t309-panel.dtsi +F: drivers/amlogic/media/vout/lcd/lcd_phy_config.c +F: drivers/amlogic/media/vout/lcd/lcd_phy_config.h + +AMLOGIC MESONAXG RSR DTS +M: Yeping Miao +F: arch/arm64/boot/dts/amlogic/axg_rsr.dts +F: arch/arm64/boot/dts/amlogic/axg_rsr_v03.dts AMLOGIC CAMERA DRIVER M: Guosong Zhou @@ -14742,6 +14785,97 @@ F: drivers/amlogic/media/common/canvas/canvas_mgr.c F: drivers/amlogic/media/common/vfm/vfm.c F: include/linux/amlogic/media/camera/* +AMLOGIC multimedia +M: Pengcheng Chen +F: drivers/amlogic/media/common/ge2d/ge2d_dmabuf.c +F: drivers/amlogic/media/common/ge2d/ge2d_dmabuf.h + +AMLOGIC GDC DRIVER +M: Pengcheng Chen +F: drivers/amlogic/media/gdc/app/gdc_dmabuf.c +F: drivers/amlogic/media/gdc/app/gdc_dmabuf.h +F: drivers/amlogic/media/gdc/src/platform/system_log.c + +AMLOGIC VIDEOSYNC +M: Jintao Xu +F: drivers/amlogic/media/video_processor/videosync/Kconfig +F: drivers/amlogic/media/video_processor/videosync/Makefile +F: drivers/amlogic/media/video_processor/videosync/vfp.h +F: drivers/amlogic/media/video_processor/videosync/videosync.h +F: drivers/amlogic/media/video_processor/videosync/videosync.c + +AMLOGIC G12B_A DTS +M: Jianxiong Pan +F: arch/arm/boot/dts/amlogic/g12b*_a.dts +F: arch/arm/boot/dts/amlogic/mesong12b.dtsi +F: arch/arm64/boot/dts/amlogic/g12b*_a.dts +F: arch/arm64/boot/dts/amlogic/mesong12b.dtsi + +AMLOGIC MESONAXG SBR DTS +M: Bing Jiang +F: arch/arm64/boot/dts/amlogic/axg_s400_v03sbr.dts +F: arch/arm/boot/dts/amlogic/axg_s400_v03sbr.dts +F: sound/soc/codecs/amlogic/tas5782m.c +F: sound/soc/codecs/amlogic/tas5782m.h + +AMLOGIC SM1 DTS +M: Zhiqiang Liang +F: arch/arm64/boot/dts/amlogic/mesongsm1.dtsi +F: arch/arm64/boot/dts/amlogic/sm1_pxp.dts +F: arch/arm/boot/dts/amlogic/mesonsm1.dtsi +F: arch/arm/boot/dts/amlogic/sm1_pxp.dts + +AMLOGIC SM1 CLOCK DRIVERS +M: Shunzhou Jiang +F: drivers/amlogic/clk/sm1/* + +AMLOGIC SM1 DTS +M: shaochan.liu +F: arch/arm64/boot/dts/amlogic/mesonsm1_skt-panel.dtsi +F: arch/arm/boot/dts/amlogic/mesonsm1_skt-panel.dtsi + +AMLOGIC SM1 POWER CTRL DRIVERS +M: Shunzhou Jiang +F: drivers/amlogic/power/power_ctrl.c +F: include/linux/amlogic/power_ctrl.h + +AMLOGIC MESONAXG S400 GVA SBR DTS +M: Yeping Miao +F: arch/arm64/boot/dts/amlogic/axg_s400_v03gva_sbr.dts +F: arch/arm/boot/dts/amlogic/axg_s400_v03gva_sbr.dts + +AMLOGIC TL1 DTS +M: Huijie Huang +F: arch/arm/boot/dts/amlogic/tl1_t962x2_x301_1g.dts +F: arch/arm/boot/dts/amlogic/tl1_t962x2_x301_2g.dts +F: arch/arm64/boot/dts/amlogic/tl1_t962x2_x301_1g.dts +F: arch/arm64/boot/dts/amlogic/tl1_t962x2_x301_2g.dts + +AMLOGIC TM2 PINCTRL DRIVER +M: Qianggui Song +F: drivers/amlogic/pinctrl/pinctrl-meson-tm2.c +F: include/dt-bindings/gpio/meson-tm2-gpio.h + +AMLOGIC MESON TM2 CLOCK DRIVER +M: Jian Hu +F: driver/amlogic/clk/tm2/* + +AMLOGIC MESON TM2 LCD DTS +M: Shaochan Liu +F: arch/arm64/boot/dts/amlogic/mesontm2_t962x3_ab301-panel.dtsi +F: arch/arm64/boot/dts/amlogic/mesontm2_t962x3_ab309-panel.dtsi +F: arch/arm/boot/dts/amlogic/mesontm2_t962x3_ab301-panel.dtsi +F: arch/arm/boot/dts/amlogic/mesontm2_t962x3_ab309-panel.dtsi + +AMLOGIC SM1 S905X3 DTS +M: Xiaoliang Wang +F: arch/arm/boot/dts/amlogic/g12a_s905x2_u212.dts +F: arch/arm/boot/dts/amlogic/g12a_s905x2_u212_1g.dts +F: arch/arm64/boot/dts/amlogic/g12a_s905x2_u212.dts +F: arch/arm64/boot/dts/amlogic/g12a_s905x2_u212_1g.dts +F: arch/arm/boot/dts/amlogic/sm1_s905x3_ac213.dts +F: arch/arm64/boot/dts/amlogic/sm1_s905x3_ac213.dts + HARDKERNEL S922D odroidn2 M: Joy Cho F: arch/arm64/configs/odroidn2_defconfig diff --git a/Makefile b/Makefile index b656d5962a9f..a5d29b9dd573 100644 --- a/Makefile +++ b/Makefile @@ -765,7 +765,7 @@ ifdef CONFIG_CC_STACKPROTECTOR_REGULAR stackp-flag := -fstack-protector stackp-name := REGULAR else -ifdef CONFIG_CC_STACKPROTECTOR_STRONG +ifdef CONFIG_CC_STACKPROTECTOR_STRONG_AMLOGIC stackp-flag := -fstack-protector-strong stackp-name := STRONG else diff --git a/arch/Kconfig b/arch/Kconfig index 2fa953f81ffb..20fd67d7d01c 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -450,6 +450,11 @@ config CC_STACKPROTECTOR_REGULAR by about 0.3%. config CC_STACKPROTECTOR_STRONG + bool "Strong" + help + Since this config will increase stack size. We repleace it + +config CC_STACKPROTECTOR_STRONG_AMLOGIC bool "Strong" select CC_STACKPROTECTOR help diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 787018c6c91c..1ee0ee67df03 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -90,6 +90,7 @@ config ARM select PERF_USE_VMALLOC select RTC_LIB select SYS_SUPPORTS_APM_EMULATION + select HAVE_ARCH_KASAN # Above selects are sorted alphabetically; please add new ones # according to that. Thanks. help @@ -1444,6 +1445,7 @@ config PAGE_OFFSET default 0x40000000 if VMSPLIT_1G default 0x80000000 if VMSPLIT_2G default 0xB0000000 if VMSPLIT_3G_OPT + default 0xD0000000 if AMLOGIC_KASAN32 default 0xC0000000 config NR_CPUS diff --git a/arch/arm/Makefile b/arch/arm/Makefile index a7645d4f0648..ca83dfdc362d 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -52,6 +52,10 @@ AS += -EL LD += -EL endif +ifeq ($(CONFIG_KASAN),y) +KASAN_SHADOW_OFFSET := 0xA0000000 +endif + # # The Scalar Replacement of Aggregates (SRA) optimization pass in GCC 4.9 and # later may result in code being generated that handles signed short and signed diff --git a/arch/arm/boot/Makefile b/arch/arm/boot/Makefile index 30fd2ed93978..e6aca688be20 100644 --- a/arch/arm/boot/Makefile +++ b/arch/arm/boot/Makefile @@ -21,6 +21,10 @@ ifeq ($(CONFIG_MACH_MESON8B),y) include $(srctree)/arch/arm/mach-meson/Makefile.boot endif +ifeq ($(CONFIG_ARM64_A32),y) +include $(srctree)/arch/arm/mach-meson/Makefile.boot +endif + include $(srctree)/arch/arm/boot/dts/Makefile # Note: the following conditions must always be true: diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile index 552c7d7f84ce..05fed5260e10 100644 --- a/arch/arm/boot/compressed/Makefile +++ b/arch/arm/boot/compressed/Makefile @@ -4,6 +4,8 @@ # create a compressed vmlinuz image from the original vmlinux # +KASAN_SANITIZE := n + OBJS = AFLAGS_head.o += -DTEXT_OFFSET=$(TEXT_OFFSET) diff --git a/arch/arm/boot/compressed/string.c b/arch/arm/boot/compressed/string.c index 689467448736..d7b27c5069e0 100644 --- a/arch/arm/boot/compressed/string.c +++ b/arch/arm/boot/compressed/string.c @@ -120,7 +120,9 @@ char *strchr(const char *s, int c) return (char *)s; } +#ifndef CONFIG_AMLOGIC_KASAN32 /* for compile problems */ #undef memset +#endif void *memset(void *s, int c, size_t count) { diff --git a/arch/arm/boot/dts/amlogic/atom.dts b/arch/arm/boot/dts/amlogic/atom.dts index 0b453304c69e..84357efa8f38 100644 --- a/arch/arm/boot/dts/amlogic/atom.dts +++ b/arch/arm/boot/dts/amlogic/atom.dts @@ -45,7 +45,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x100000 0x7ff00000>; + linux,usable-memory = <0x0 0x80000000>; }; reserved-memory { @@ -58,8 +58,7 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { compatible = "shared-dma-pool"; diff --git a/arch/arm/boot/dts/amlogic/axg_a113d_skt.dts b/arch/arm/boot/dts/amlogic/axg_a113d_skt.dts index 96e74c949c3a..0b3b51ccfd3e 100644 --- a/arch/arm/boot/dts/amlogic/axg_a113d_skt.dts +++ b/arch/arm/boot/dts/amlogic/axg_a113d_skt.dts @@ -36,7 +36,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x100000 0x3ff00000>; + linux,usable-memory = <0x0 0x40000000>; }; reserved-memory { @@ -49,8 +49,7 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm/boot/dts/amlogic/axg_a113x_skt.dts b/arch/arm/boot/dts/amlogic/axg_a113x_skt.dts index 1902ef3d8ac0..5d7728f24089 100644 --- a/arch/arm/boot/dts/amlogic/axg_a113x_skt.dts +++ b/arch/arm/boot/dts/amlogic/axg_a113x_skt.dts @@ -47,8 +47,7 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm/boot/dts/amlogic/axg_pxp.dts b/arch/arm/boot/dts/amlogic/axg_pxp.dts index 702352d18124..297963d0ab9a 100644 --- a/arch/arm/boot/dts/amlogic/axg_pxp.dts +++ b/arch/arm/boot/dts/amlogic/axg_pxp.dts @@ -32,7 +32,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x100000 0x3ff00000>; + linux,usable-memory = <0x0 0x40000000>; }; reserved-memory { diff --git a/arch/arm/boot/dts/amlogic/axg_s400.dts b/arch/arm/boot/dts/amlogic/axg_s400.dts index 3884ee3256c9..06011dbf03e1 100644 --- a/arch/arm/boot/dts/amlogic/axg_s400.dts +++ b/arch/arm/boot/dts/amlogic/axg_s400.dts @@ -47,8 +47,7 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm/boot/dts/amlogic/axg_s400_v03.dts b/arch/arm/boot/dts/amlogic/axg_s400_v03.dts index d8cf6fd0d07b..8fe15edbbc6f 100644 --- a/arch/arm/boot/dts/amlogic/axg_s400_v03.dts +++ b/arch/arm/boot/dts/amlogic/axg_s400_v03.dts @@ -47,8 +47,7 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm/boot/dts/amlogic/axg_s400_v03gva.dts b/arch/arm/boot/dts/amlogic/axg_s400_v03gva_sbr.dts similarity index 73% rename from arch/arm/boot/dts/amlogic/axg_s400_v03gva.dts rename to arch/arm/boot/dts/amlogic/axg_s400_v03gva_sbr.dts index 38895bcc911d..b8df36eec9d3 100644 --- a/arch/arm/boot/dts/amlogic/axg_s400_v03gva.dts +++ b/arch/arm/boot/dts/amlogic/axg_s400_v03gva_sbr.dts @@ -1,5 +1,5 @@ /* - * arch/arm/boot/dts/amlogic/axg_s400_v03gva.dts + * arch/arm/boot/dts/amlogic/axg_s400_v03gva_sbr.dts * * Copyright (C) 2017 Amlogic, Inc. All rights reserved. * @@ -18,10 +18,10 @@ /dts-v1/; #include "mesonaxg.dtsi" -#include "mesonaxg_s400-panel.dtsi" +/*#include "mesonaxg_s400-panel.dtsi" */ / { model = "Amlogic"; - amlogic-dt-id = "axg_s400_v03gva"; + amlogic-dt-id = "axg_s400_v03gva_sbr"; compatible = "amlogic, axg"; interrupt-parent = <&gic>; #address-cells = <1>; @@ -47,8 +47,7 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { @@ -348,7 +347,7 @@ "port"; /*reset-gpio-type 0:Shared pad(no reset)1:OD pad2:Normal pad*/ gpio-type = <2>; - status = "okay"; + status = "disabled"; }; pcie_B: pcieB@fa000000 { @@ -389,7 +388,7 @@ "port"; /*reset-gpio-type 0:Shared pad(no reset)1:OD pad2:Normal pad*/ gpio-type = <1>; - status = "okay"; + status = "disabled"; }; @@ -421,14 +420,6 @@ pinctrl-0 = <&b_uart_pins>; }; - meson-irblaster { - compatible = "amlogic, am_irblaster"; - dev_name = "meson-irblaster"; - status = "disable"; - pinctrl-names = "default"; - pinctrl-0 = <&irblaster_pins>; - }; - vpu { compatible = "amlogic, vpu-axg"; dev_name = "vpu"; @@ -515,8 +506,18 @@ //continuous-clock; //bitclock-inversion; //frame-inversion; - bitclock-master = <&aml_tdmb>; - frame-master = <&aml_tdmb>; + + /*A113D tdmb slave for HDMI*/ + bitclock-master = <&tdmbcodec>; + frame-master = <&tdmbcodec>; + + /*A113D tdmb master for LineIn*/ + /* + * bitclock-master = <&aml_tdmb>; + * frame-master = <&aml_tdmb>; + */ + + suffix-name = "alsaPORT-i2sCapture"; cpu { sound-dai = <&aml_tdmb>; dai-tdm-slot-tx-mask = <1 1>; @@ -525,7 +526,7 @@ dai-tdm-slot-width = <32>; system-clock-frequency = <12288000>; }; - codec { + tdmbcodec:codec { /* * prefix-names = "3101_A", "3101_B", * "3101_C", "3101_D"; @@ -534,14 +535,14 @@ * &tlv320adc3101_34 * &tlv320adc3101_36>; */ - sound-dai = <&tlv320adc3101_32 &dummy_codec>; + sound-dai = <&dummy_codec>; }; }; aml-audio-card,dai-link@2 { format = "i2s"; mclk-fs = <256>; - //continuous-clock; + continuous-clock; //bitclock-inversion; //frame-inversion; //bitclock-master = <&aml_tdmc>; @@ -555,9 +556,17 @@ system-clock-frequency = <12288000>; }; codec { - prefix-names = "5707_A", "5707_B"; - sound-dai = <&tas5707_36 &tas5707_3a - &dummy_codec>; + /* + *prefix-names = "5707_A", "5707_B"; + *sound-dai = <&tas5707_36 &tas5707_3a + * &dummy_codec>; + */ + prefix-names = "tas5782m_pu1", "tas5782m_pu2", + "tas5782m_pu3", "tas5782m_pu4", "tas5782m_pu5", + "tas5782m_pu6"; + sound-dai = <&tas5782m_pu1 &tas5782m_pu2 + &tas5782m_pu3 &tas5782m_pu4 &tas5782m_pu5 + &tas5782m_pu6>; }; }; @@ -667,6 +676,7 @@ f_max = <200000000>; max_req_size = <0x20000>; /**128KB*/ gpio_dat3 = <&gpio BOOT_3 GPIO_ACTIVE_HIGH>; + tx_delay = <4>; hw_reset = <&gpio BOOT_9 GPIO_ACTIVE_HIGH>; card_type = <1>; /* 1:mmc card(include eMMC), @@ -798,7 +808,7 @@ compatible = "amlogic, meson-axg"; memory-region = <&fb_reserved>; dev_name = "meson-fb"; - status = "okay"; + status = "disabled"; interrupts = <0 3 1 0 89 1>; interrupt-names = "viu-vsync", "rdma"; @@ -817,7 +827,7 @@ ge2d { compatible = "amlogic, ge2d-axg"; dev_name = "ge2d"; - status = "okay"; + status = "disabled"; interrupts = <0 150 1>; interrupt-names = "ge2d"; clocks = <&clkc CLKID_VAPB_MUX>, @@ -916,11 +926,55 @@ status = "okay"; }; + /*****************************************************************/ + tas5782m_pu1: tas5782m_pu1@48 { + compatible = "ti, tas5782m"; + #sound-dai-cells = <0>; + reg = <0x48>; + reset_pin = <&gpio_ao GPIOAO_4 GPIO_ACTIVE_LOW>; + status = "okay"; + codec_name = "tas5782m"; + work_mode = <0>; /*0: i2s 1:tdm*/ + chip_offset = <1>; /*chip_N [1,2....]*/ + }; + + tas5782m_pu2: tas5782m_pu2@49 { + compatible = "ti, tas5782m"; + #sound-dai-cells = <0>; + reg = <0x49>; + status = "okay"; + codec_name = "tas5782m"; + work_mode = <0>; /*0: i2s 1:tdm*/ + chip_offset = <2>; /*chip_N [1,2....]*/ + }; + + tas5782m_pu3: tas5782m_pu3@4a { + compatible = "ti, tas5782m"; + #sound-dai-cells = <0>; + reg = <0x4a>; + status = "okay"; + codec_name = "tas5782m"; + work_mode = <0>; /*0: i2s 1:tdm*/ + chip_offset = <3>; /*chip_N [1,2....]*/ + }; + + tas5782m_pu4: tas5782m_pu4@4b { + compatible = "ti, tas5782m"; + #sound-dai-cells = <0>; + reg = <0x4b>; + status = "okay"; + codec_name = "tas5782m"; + work_mode = <0>; /*0: i2s 1:tdm*/ + chip_offset = <4>; /*chip_N [1,2....]*/ + }; + /*****************************************************************/ + + tas5707_36: tas5707_36@36 { compatible = "ti,tas5707"; #sound-dai-cells = <0>; reg = <0x1b>; - status = "okay"; + status = "disabled"; reset_pin = <&gpio_ao GPIOAO_4 0>; }; @@ -928,7 +982,7 @@ compatible = "ti,tas5707"; #sound-dai-cells = <0>; reg = <0x1d>; - status = "okay"; + status = "disabled"; }; }; @@ -938,6 +992,33 @@ pinctrl-names="default"; pinctrl-0=<&ao_i2c_master_pin2>; + /*****************************************************************/ + mcu6350: mcu6350@40 { + reg = <0x40>; + status = "okay"; + }; + + /*****************************************************************/ + tas5782m_pu5: tas5782m_pu5@48 { + compatible = "ti, tas5782m"; + #sound-dai-cells = <0>; + reg = <0x48>; + status = "okay"; + codec_name = "tas5782m"; + work_mode = <0>; /*0: i2s 1:tdm*/ + chip_offset = <5>; /*chip_N [1,2....]*/ + }; + + tas5782m_pu6: tas5782m_pu6@49 { + compatible = "ti, tas5782m"; + #sound-dai-cells = <0>; + reg = <0x49>; + status = "okay"; + codec_name = "tas5782m"; + work_mode = <0>; /*0: i2s 1:tdm*/ + chip_offset = <6>; /*chip_N [1,2....]*/ + }; + /*****************************************************************/ aml_pca9557: aml_pca9557@0x1f { compatible = "amlogic,pca9557_keypad"; reg = <0x1f>; @@ -1064,27 +1145,34 @@ aml_tdmb: tdmb { compatible = "amlogic, axg-snd-tdmb"; #sound-dai-cells = <0>; - /*dai-tdm-lane-slot-mask-in = <1 1 1 1>;*/ - dai-tdm-lane-slot-mask-in = <0 0 0 1>; + dai-tdm-lane-slot-mask-in = <1 1 1 1>; + dai-tdm-lane-slot-mask-out = <0 0 0 0>; dai-tdm-clk-sel = <1>; clocks = <&clkaudio CLKID_AUDIO_MCLK_B &clkc CLKID_MPLL1>; clock-names = "mclk", "clk_srcpll"; pinctrl-names = "tdm_pins"; - pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; + + /*A113D tdmb slave for HDMI*/ + pinctrl-0 = <&tdmb_mclk &tdmin_b_slv &tdmin_b>; + + /*A113D tdmb master for LineIn*/ + /* + * pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; + */ }; aml_tdmc: tdmc { compatible = "amlogic, axg-snd-tdmc"; #sound-dai-cells = <0>; - dai-tdm-lane-slot-mask-in = <0 1 0 0>; - dai-tdm-lane-slot-mask-out = <0 0 1 1>; + dai-tdm-lane-slot-mask-in = <0 0 0 0>; + dai-tdm-lane-slot-mask-out = <1 1 1 1>; dai-tdm-clk-sel = <2>; clocks = <&clkaudio CLKID_AUDIO_MCLK_C &clkc CLKID_MPLL2>; clock-names = "mclk", "clk_srcpll"; pinctrl-names = "tdm_pins"; - pinctrl-0 = <&tdmc_mclk &tdmout_c &tdmin_c>; + pinctrl-0 = <&tdmc_mclk &tdmout_c>; }; aml_spdif: spdif { @@ -1104,6 +1192,20 @@ interrupt-names = "irq_spdifin"; pinctrl-names = "spdif_pins"; pinctrl-0 = <&spdifout &spdifin>; + + /* + * whether do asrc for pcm. + * if raw data, asrc is disabled automatically + * 0: "Disable", + * 1: "Enable:32K", + * 2: "Enable:44K", + * 3: "Enable:48K", + * 4: "Enable:88K", + * 5: "Enable:96K", + * 6: "Enable:176K", + * 7: "Enable:192K", + */ + auto_asrc = <3>; status = "okay"; }; aml_pdm: pdm { @@ -1150,8 +1252,8 @@ * 4: pdmin; */ datain_src = <4>; - datain_chnum = <4>; - datain_chmask = <0x3>; + datain_chnum = <8>; + datain_chmask = <0x7f>; /* tdmin_lb src * 0: tdmoutA @@ -1167,10 +1269,53 @@ datalb_chnum = <2>; /*config which data pin as loopback*/ /*datalb-lane-mask-in = <0 0 0 1>;*/ - datalb_chmask = <0x3>; + datalb_chmask = <0x1>; status = "okay"; }; + + audioresample: resample { + compatible = "amlogic, axg-resample"; + clocks = <&clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_MCLK_F + &clkaudio CLKID_AUDIO_RESAMPLE_CTRL>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + /*same with toddr_src + * TDMIN_A, + * TDMIN_B, + * TDMIN_C, + * SPDIFIN, + * PDMIN, + * NONE, + * TDMIN_LB, + * LOOPBACK, + */ + resample_module = <3>; + status = "okay"; + }; + aml_pwrdet: pwrdet { + compatible = "amlogic, axg-power-detect"; + + interrupts = ; + interrupt-names = "pwrdet_irq"; + + /* pwrdet source sel + * 7: loopback; + * 6: tdmin_lb; + * 5: reserved; + * 4: pdmin; + * 3: spdifin; + * 2: tdmin_c; + * 1: tdmin_b; + * 0: tdmin_a; + */ + pwrdet_src = <4>; + + hi_th = <0x70000>; + lo_th = <0x16000>; + + status = "disabled"; + }; }; /* end of audiobus */ &pinctrl_periphs { @@ -1210,6 +1355,14 @@ function = "tdmb_out"; }; }; + + tdmin_b_slv: tdmin_b_slv{ + mux { + groups = "tdmb_slv_sclk", "tdmb_slv_fs"; + function = "tdmb_in"; + }; + }; + // tdmin and tdmout are the same pins. can't use at same time tdmin_b:tdmin_b { mux { @@ -1233,6 +1386,7 @@ groups = "tdmc_sclk", "tdmc_fs", "tdmc_dout0", + "tdmc_dout1", "tdmc_dout2_a6", "tdmc_dout3_a7"; function = "tdmc_out"; @@ -1319,3 +1473,206 @@ &audio_data{ status = "okay"; }; + +&audio_data{ + status = "okay"; +}; + +&custom_maps{ + mapnum = <4>; + map0 = <&map_0>; + map1 = <&map_1>; + map2 = <&map_2>; + map3 = <&map_3>; + map_0: map_0{ + mapname = "amlogic-remote-1"; + customcode = <0xfb04>; + release_delay = <80>; + size = <50>; /*keymap size*/ + keymap = ; + }; + map_1: map_1{ + mapname = "amlogic-remote-2"; + customcode = <0xfe01>; + release_delay = <80>; + size = <53>; + keymap = ; + }; + map_2: map_2{ + mapname = "amlogic-remote-3"; + customcode = <0xbd02>; + release_delay = <80>; + size = <17>; + keymap = ; + }; + map_3: map_3{ + mapname = "amlogic-remote-3"; + customcode = <0xa4e8>; /* Reference Remote Control */ + release_delay = <80>; + size = <45>; + keymap = < + REMOTE_KEY(0xc7, 200) /* power */ + REMOTE_KEY(0x93, 201) /* eject-->input source */ + REMOTE_KEY(0xb2, 202) /* usb */ + REMOTE_KEY(0xb8, 203) /* coaxial */ + REMOTE_KEY(0xb7, 204) /* aux */ + REMOTE_KEY(0x8a, 205) /* scan-->hdmi arc */ + REMOTE_KEY(0x96, 206) /* dimmer */ + REMOTE_KEY(0x90, 207) /* hdmi1 */ + REMOTE_KEY(0xa8, 208) /* hdmi2 */ + REMOTE_KEY(0x85, 209) /* mute */ + REMOTE_KEY(0x80, 210) /* vol+ */ + REMOTE_KEY(0x81, 211) /* vol- */ + REMOTE_KEY(0x61, 212) /* DAP */ + REMOTE_KEY(0x62, 213) /* BM */ + REMOTE_KEY(0x63, 214) /* DRC */ + REMOTE_KEY(0x64, 215) /* POST */ + REMOTE_KEY(0x65, 216) /* UPMIX */ + REMOTE_KEY(0x66, 217) /* VIRT */ + REMOTE_KEY(0x67, 218) /* LEGACY */ + REMOTE_KEY(0x68, 219) /* HFILT */ + REMOTE_KEY(0x69, 220) /* Loundness */ + REMOTE_KEY(0x60, 221) /* Audio_info */ + REMOTE_KEY(0xb1, 222) /* CD */ + REMOTE_KEY(0xb4, 223) /* CD */ + REMOTE_KEY(0xb9, 224) /* CD */ + REMOTE_KEY(0xab, 225) /* CD */ + REMOTE_KEY(0x91, 226) /* CD */ + REMOTE_KEY(0x92, 227) /* CD */ + REMOTE_KEY(0x89, 228) /* CD */ + REMOTE_KEY(0x88, 229) /* CD */ + REMOTE_KEY(0xa5, 230) /* CD */ + REMOTE_KEY(0x84, 231) /* CD */ + REMOTE_KEY(0x72, 232) /* CD */ + REMOTE_KEY(0x73, 233) /* CD */ + REMOTE_KEY(0x9a, 234) /* CD */ + REMOTE_KEY(0x9b, 235) /* CD */ + REMOTE_KEY(0xa0, 236) /* CD */ + REMOTE_KEY(0x71, 237) /* CD */ + REMOTE_KEY(0x74, 238) /* CD */ + REMOTE_KEY(0x75, 239) /* CD */ + REMOTE_KEY(0x7e, 240) /* CD */ + REMOTE_KEY(0x7f, 241) /* CD */ + REMOTE_KEY(0x7a, 242) /* CD */ + REMOTE_KEY(0xa7, 243) /* CD */ + REMOTE_KEY(0xa9, 244) /* CD */ + >; + }; +}; diff --git a/arch/arm/boot/dts/amlogic/axg_s400_v03sbr.dts b/arch/arm/boot/dts/amlogic/axg_s400_v03sbr.dts new file mode 100644 index 000000000000..7727ce8768a4 --- /dev/null +++ b/arch/arm/boot/dts/amlogic/axg_s400_v03sbr.dts @@ -0,0 +1,1717 @@ +/* + * arch/arm/boot/dts/amlogic/axg_s400_v03sbr.dts + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +/dts-v1/; + +#include "mesonaxg.dtsi" +/*#include "mesonaxg_s400-panel.dtsi" */ +/ { + model = "Amlogic"; + amlogic-dt-id = "axg_s400_v03sbr"; + compatible = "amlogic, axg"; + interrupt-parent = <&gic>; + #address-cells = <1>; + #size-cells = <1>; + + aliases { + serial0 = &uart_AO; + serial1 = &uart_A; + }; + + memory@00000000 { + device_type = "memory"; + linux,usable-memory = <0x000000 0x40000000>; + }; + + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + /* global autoconfigured region for contiguous allocations */ + ramoops@0x07400000 { + compatible = "ramoops"; + reg = <0x07400000 0x00100000>; + record-size = <0x8000>; + console-size = <0x8000>; + ftrace-size = <0x20000>; + }; + + secmon_reserved:linux,secmon { + compatible = "shared-dma-pool"; + reusable; + size = <0x400000>; + alignment = <0x400000>; + alloc-ranges = <0x05000000 0x400000>; + }; + + secos_reserved:linux,secos { + status = "disabled"; + compatible = "amlogic, aml_secos_memory"; + reg = <0x05300000 0x2000000>; + no-map; + }; + fb_reserved:linux,meson-fb { + //compatible = "amlogic, fb-memory"; + //reg = <0x3e000000 0x1f00000>; + compatible = "shared-dma-pool"; + reusable; + size = <0x2000000>; + alignment = <0x400000>; + alloc-ranges = <0x3e000000 0x2000000>; + }; + }; + mtd_nand { + compatible = "amlogic, aml_mtd_nand"; + dev_name = "mtdnand"; + status = "okay"; + reg = <0xFFE07800 0x200>; + interrupts = < 0 34 1 >; + pinctrl-names = "nand_rb_mod","nand_norb_mod", "nand_cs_only"; + pinctrl-0 = <&all_nand_pins>; + pinctrl-1 = <&all_nand_pins>; + pinctrl-2 = <&nand_cs_pins>; + device_id = <0>; + + /*fip/tpl configurations, must be same + * with uboot if bl_mode was set as 1 + * bl_mode: 0 compact mode; 1 descrete mode + * if bl_mode was set as 1, fip configeration will work + */ + bl_mode = <1>; + /*copy count of fip*/ + fip_copies = <4>; + /*size of each fip copy */ + fip_size = <0x200000>; + nand_clk_ctrl = <0xFFE07000>; + plat-names = "bootloader","nandnormal"; + plat-num = <2>; + plat-part-0 = <&bootloader>; + plat-part-1 = <&nandnormal>; + bootloader: bootloader{ + enable_pad ="ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <1>; + part_num = <0>; + rb_detect = <1>; + }; + nandnormal: nandnormal{ + enable_pad ="ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + plane_mode = "twoplane"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <2>; + part_num = <3>; + partition = <&nand_partitions>; + rb_detect = <1>; + }; + nand_partitions:nand_partition{ + /* + * if bl_mode is 1, tpl size was generate by + * fip_copies * fip_size which + * will not skip bad when calculating + * the partition size; + * + * if bl_mode is 0, + * tpl partition must be comment out. + */ + tpl{ + offset=<0x0 0x0>; + size=<0x0 0x0>; + }; + misc{ + offset=<0x0 0x0>; + size=<0x0 0x200000>; + }; + logo{ + offset=<0x0 0x0>; + size=<0x0 0x200000>; + }; + recovery{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + boot{ + offset=<0x0 0x0>; + size=<0x0 0xF00000>; + }; + system{ + offset=<0x0 0x0>; + size=<0x0 0x11800000>; + }; + data{ + offset=<0xffffffff 0xffffffff>; + size=<0x0 0x0>; + }; + }; + }; + + + ethmac: ethernet@0xff3f0000 { + compatible = "amlogic, gxbb-eth-dwmac"; + reg = <0xff3f0000 0x10000 + 0xff634540 0x8>; + interrupts = <0 8 1>; + pinctrl-names = "external_eth_pins"; + pinctrl-0 = <&external_eth_pins>; + mc_val_internal_phy = <0x1800>; + mc_val_external_phy = <0x1621>; + interrupt-names = "macirq"; + clocks = <&clkc CLKID_ETH_CORE>; + clock-names = "ethclk81"; + internal_phy=<0>; + }; + + aml_sensor0: aml-sensor@0 { + compatible = "amlogic, aml-thermal"; + device_name = "thermal"; + #thermal-sensor-cells = <1>; + cooling_devices { + cpufreq_cool_cluster0 { + min_state = <1000000>; + dyn_coeff = <140>; + cluster_id = <0>; + node_name = "cpufreq_cool0"; + device_type = "cpufreq"; + }; + cpucore_cool_cluster0 { + min_state = <1>; + dyn_coeff = <0>; + cluster_id = <0>; + node_name = "cpucore_cool0"; + device_type = "cpucore"; + }; + }; + cpufreq_cool0:cpufreq_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + cpucore_cool0:cpucore_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + }; + thermal-zones { + soc_thermal { + polling-delay = <1000>; + polling-delay-passive = <100>; + sustainable-power = <1050>; + + thermal-sensors = <&aml_sensor0 3>; + + trips { + switch_on: trip-point@0 { + temperature = <70000>; + hysteresis = <1000>; + type = "passive"; + }; + control: trip-point@1 { + temperature = <80000>; + hysteresis = <1000>; + type = "passive"; + }; + hot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + critical: trip-point@3 { + temperature = <260000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + + cooling-maps { + cpufreq_cooling_map { + trip = <&control>; + cooling-device = <&cpufreq_cool0 0 4>; + contribution = <1024>; + }; + cpucore_cooling_map { + trip = <&control>; + cooling-device = <&cpucore_cool0 0 3>; + contribution = <1024>; + }; + }; + }; + }; + + dwc3: dwc3@ff500000 { + compatible = "synopsys, dwc3"; + status = "okay"; + reg = <0xff500000 0x100000>; + interrupts = <0 30 4>; + usb-phy = <&usb2_phy>, <&usb3_phy>; + cpu-type = "gxl"; + clock-src = "usb3.0"; + clocks = <&clkc CLKID_USB_GENERAL>; + clock-names = "dwc_general"; + }; + + usb2_phy: usb2phy@ffe09000 { + compatible = "amlogic, amlogic-new-usb2"; + status = "okay"; + portnum = <4>; + reg = <0xffe09000 0x80 + 0xffd01008 0x4>; + }; + + usb3_phy: usb3phy@ffe09080 { + compatible = "amlogic, amlogic-new-usb3"; + status = "okay"; + portnum = <0>; + reg = <0xffe09080 0x20>; + interrupts = <0 16 4>; + otg = <1>; + gpio-vbus-power = "GPIOAO_5"; + gpios = <&gpio_ao GPIOAO_5 GPIO_ACTIVE_HIGH>; + }; + + dwc2_a { + compatible = "amlogic, dwc2"; + device_name = "dwc2_a"; + reg = <0xff400000 0x40000>; + status = "okay"; + interrupts = <0 31 4>; + pl-periph-id = <0>; /** lm name */ + clock-src = "usb0"; /** clock src */ + port-id = <0>; /** ref to mach/usb.h */ + port-type = <2>; /** 0: otg, 1: host, 2: slave */ + port-speed = <0>; /** 0: default, high, 1: full */ + port-config = <0>; /** 0: default */ + /*0:default,1:single,2:incr,3:incr4,4:incr8,5:incr16,6:disable*/ + port-dma = <0>; + port-id-mode = <0>; /** 0: hardware, 1: sw_host, 2: sw_slave*/ + usb-fifo = <728>; + cpu-type = "gxl"; + /** 0: normal, 1: otg+dwc3 host only, 2: otg+dwc3 device only*/ + controller-type = <3>; + phy-reg = <0xffe09000>; + phy-reg-size = <0xa0>; + clocks = <&clkc CLKID_USB_GENERAL + &clkc CLKID_USB1_TO_DDR + &clkc CLKID_USB1>; + clock-names = "usb_general", + "usb1", + "usb1_to_ddr"; + }; + + pcie_A: pcieA@f9800000 { + compatible = "amlogic, amlogic-pcie", "snps,dw-pcie"; + reg = <0xf9800000 0x400000 + 0xff646000 0x2000 + 0xf9f00000 0x100000 + PCIE_PHY_REG PCIE_PHY_SIZE + PCIE_RESET_REG PCIE_RESET_SIZE>; + reg-names = "elbi", "cfg", "config", "phy", "reset"; + reset-gpio = <&gpio GPIOX_19 GPIO_ACTIVE_HIGH>; + interrupts = <0 177 0>; + #interrupt-cells = <1>; + bus-range = <0x0 0xff>; + #address-cells = <3>; + #size-cells = <2>; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &gic GIC_SPI 179 IRQ_TYPE_EDGE_RISING>; + device_type = "pci"; + ranges = <0x82000000 0 0 0xf9c00000 0 0x00300000>; + /* non-prefetchable memory */ + num-lanes = <1>; + pcie-num = <1>; + + clocks = <&clkc CLKID_USB_GENERAL + &clkc CLKID_PCIE_PLL + &clkc CLKID_MIPI_ENABLE_GATE + &clkc CLKID_MIPI_BANDGAP_GATE + &clkc CLKID_PCIE_A + &clkc CLKID_PCIE_CML_EN0>; + clock-names = "pcie_general", + "pcie_refpll", + "pcie_mipi_enable_gate", + "pcie_mipi_bandgap_gate", + "pcie", + "port"; + /*reset-gpio-type 0:Shared pad(no reset)1:OD pad2:Normal pad*/ + gpio-type = <2>; + status = "disabled"; + }; + + pcie_B: pcieB@fa000000 { + compatible = "amlogic, amlogic-pcie", "snps,dw-pcie"; + reg = <0xfa000000 0x400000 + 0xff648000 0x2000 + 0xfa400000 0x100000 + PCIE_PHY_REG PCIE_PHY_SIZE + PCIE_RESET_REG PCIE_RESET_SIZE>; + reg-names = "elbi", "cfg", "config", "phy", "reset"; + reset-gpio = <&gpio GPIOZ_10 GPIO_ACTIVE_HIGH>; + interrupts = <0 167 0>; + #interrupt-cells = <1>; + bus-range = <0x0 0xff>; + #address-cells = <3>; + #size-cells = <2>; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &gic GIC_SPI 169 IRQ_TYPE_EDGE_RISING>; + device_type = "pci"; + ranges = <0x81000000 0 0 0xfa500000 0x0 0x10000 + /* downstream I/O */ + 0x82000000 0 0xfa510000 0xfa510000 0 0x002f0000>; + /* non-prefetchable memory */ + num-lanes = <1>; + pcie-num = <2>; + + clocks = <&clkc CLKID_USB_GENERAL + &clkc CLKID_PCIE_PLL + &clkc CLKID_MIPI_ENABLE_GATE + &clkc CLKID_MIPI_BANDGAP_GATE + &clkc CLKID_PCIE_B + &clkc CLKID_PCIE_CML_EN1>; + clock-names = "pcie_general", + "pcie_refpll", + "pcie_mipi_enable_gate", + "pcie_mipi_bandgap_gate", + "pcie", + "port"; + /*reset-gpio-type 0:Shared pad(no reset)1:OD pad2:Normal pad*/ + gpio-type = <1>; + status = "disabled"; + }; + + + uart_A: serial@ffd24000 { + compatible = "amlogic, meson-uart"; + reg = <0xffd24000 0x18>; + interrupts = <0 26 1>; + status = "okay"; + clocks = <&xtal + &clkc CLKID_UART0>; + clock-names = "clk_uart", + "clk_gate"; + fifosize = < 128 >; + pinctrl-names = "default"; + pinctrl-0 = <&a_uart_pins>; + }; + + uart_B: serial@ffd23000 { + compatible = "amlogic, meson-uart"; + reg = <0xffd23000 0x18>; + interrupts = <0 75 1>; + status = "disabled"; + clocks = <&xtal + &clkc CLKID_UART1>; + clock-names = "clk_uart", + "clk_gate"; + fifosize = < 64 >; + pinctrl-names = "default"; + pinctrl-0 = <&b_uart_pins>; + }; + + vpu { + compatible = "amlogic, vpu-axg"; + dev_name = "vpu"; + status = "okay"; + clocks = <&clkc CLKID_VAPB_MUX>, + <&clkc CLKID_VPU_INTR>, + <&clkc CLKID_VPU_P0_COMP>, + <&clkc CLKID_VPU_P1_COMP>, + <&clkc CLKID_VPU_MUX>; + clock-names = "vapb_clk", + "vpu_intr_gate", + "vpu_clk0", + "vpu_clk1", + "vpu_clk"; + clk_level = <3>; + /* 0: 100.0M 1: 166.7M 2: 200.0M 3: 250.0M */ + }; + + vout { + compatible = "amlogic, vout"; + dev_name = "vout"; + status = "okay"; + }; + + /* Sound iomap */ + aml_snd_iomap { + compatible = "amlogic, snd-iomap"; + status = "okay"; + #address-cells=<1>; + #size-cells=<1>; + ranges; + pdm_bus { + reg = <0xFF632000 0x2000>; + }; + audiobus_base { + reg = <0xFF642000 0x2000>; + }; + }; + pdm_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, pdm_dummy_codec"; + status = "okay"; + }; + dummy_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, aml_dummy_codec"; + status = "okay"; + }; + + auge_sound { + compatible = "amlogic, axg-sound-card"; + aml-audio-card,name = "AML-AUGESOUND"; + + aml-audio-card,loopback = <&aml_loopback>; + + aml-audio-card,hp-det-gpio = <&gpio GPIOZ_7 GPIO_ACTIVE_LOW>; + + aml-audio-card,dai-link@0 { + format = "dsp_a"; + mclk-fs = <512>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + //bitclock-master = <&tdmacodec>; + //frame-master = <&tdmacodec>; + tdmacpu: cpu { + sound-dai = <&aml_tdma>; + dai-tdm-slot-tx-mask = + <1>; + dai-tdm-slot-rx-mask = + <1>; + dai-tdm-slot-num = <1>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <512000>; + }; + tdmacodec: codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@1 { + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + + /*A113D tdmb slave for HDMI*/ + bitclock-master = <&tdmbcodec>; + frame-master = <&tdmbcodec>; + + /*A113D tdmb master for LineIn*/ + /* + * bitclock-master = <&aml_tdmb>; + * frame-master = <&aml_tdmb>; + */ + + suffix-name = "alsaPORT-i2sCapture"; + cpu { + sound-dai = <&aml_tdmb>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmbcodec:codec { + /* + * prefix-names = "3101_A", "3101_B", + * "3101_C", "3101_D"; + * sound-dai = <&tlv320adc3101_32 + * &tlv320adc3101_30 + * &tlv320adc3101_34 + * &tlv320adc3101_36>; + */ + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@2 { + format = "i2s"; + mclk-fs = <256>; + continuous-clock; + //bitclock-inversion; + //frame-inversion; + //bitclock-master = <&aml_tdmc>; + //frame-master = <&aml_tdmc>; + cpu { + sound-dai = <&aml_tdmc>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + codec { + /* + *prefix-names = "5707_A", "5707_B"; + *sound-dai = <&tas5707_36 &tas5707_3a + * &dummy_codec>; + */ + prefix-names = "tas5782m_pu1", "tas5782m_pu2", + "tas5782m_pu3", "tas5782m_pu4", "tas5782m_pu5", + "tas5782m_pu6"; + sound-dai = <&tas5782m_pu1 &tas5782m_pu2 + &tas5782m_pu3 &tas5782m_pu4 &tas5782m_pu5 + &tas5782m_pu6>; + }; + }; + + aml-audio-card,dai-link@3 { + mclk-fs = <256>; + cpu { + sound-dai = <&aml_pdm>; + }; + codec { + /* + *enable external loopback + *and tlv320adc3101 as loopback + */ + /*sound-dai = <&pdm_codec &tlv320adc3101_32>;*/ + /* + * enable internal loopback + * or disable loopback + */ + sound-dai = <&pdm_codec>; + }; + }; + + aml-audio-card,dai-link@4 { + mclk-fs = <128>; + cpu { + sound-dai = <&aml_spdif>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + }; + + bt-dev{ + compatible = "amlogic, bt-dev"; + dev_name = "bt-dev"; + status = "okay"; + gpio_reset = <&gpio GPIOX_21 GPIO_ACTIVE_HIGH>; + }; + + wifi{ + compatible = "amlogic, aml_wifi"; + dev_name = "aml_wifi"; + status = "okay"; + interrupt_pin = <&gpio GPIOX_6 GPIO_ACTIVE_HIGH>; + interrupts = < 0 67 4>; + irq_trigger_type = "GPIO_IRQ_LOW"; + power_on_pin2 = <&gpio GPIOX_16 GPIO_ACTIVE_HIGH>; + power_on_pin = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; + dhd_static_buf; //if use bcm wifi, config dhd_static_buf + pinctrl-names = "default"; + pinctrl-0 = <&wifi_32k_pins>; + pwm_config = <&wifi_pwm_conf>; + }; + + wifi_pwm_conf:wifi_pwm_conf{ + pwm_channel1_conf { + pwms = <&pwm_ab MESON_PWM_0 30541 0>; + duty-cycle = <15270>; + times = <10>; + }; + pwm_channel2_conf { + pwms = <&pwm_ab MESON_PWM_2 30500 0>; + duty-cycle = <15250>; + times = <12>; + }; + }; + + sd_emmc_c: emmc@ffe07000 { + status = "disabled"; + compatible = "amlogic, meson-mmc-axg"; + reg = <0xffe07000 0x2000>; + interrupts = <0 218 1>; + pinctrl-names = "emmc_clk_cmd_pins", "emmc_all_pins"; + pinctrl-0 = <&emmc_clk_cmd_pins>; + pinctrl-1 = <&emmc_conf_pull_up &emmc_conf_pull_done>; + clocks = <&clkc CLKID_SD_EMMC_C>, + <&clkc CLKID_SD_EMMC_C_P0_COMP>, + <&clkc CLKID_FCLK_DIV2>, + <&clkc CLKID_FCLK_DIV5>, + <&xtal>; + clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + + bus-width = <8>; + cap-sd-highspeed; + cap-mmc-highspeed; + mmc-ddr-1_8v; + mmc-hs200-1_8v; + + max-frequency = <200000000>; + non-removable; + disable-wp; + emmc { + pinname = "emmc"; + ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ + caps = "MMC_CAP_8_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + "MMC_CAP_1_8V_DDR", + "MMC_CAP_HW_RESET", + "MMC_CAP_ERASE", + "MMC_CAP_CMD23"; + caps2 = "MMC_CAP2_HS200", "MMC_CAP2_HS400"; + f_min = <400000>; + f_max = <200000000>; + max_req_size = <0x20000>; /**128KB*/ + gpio_dat3 = <&gpio BOOT_3 GPIO_ACTIVE_HIGH>; + tx_delay = <4>; + hw_reset = <&gpio BOOT_9 GPIO_ACTIVE_HIGH>; + card_type = <1>; + /* 1:mmc card(include eMMC), + * 2:sd card(include tSD) + */ + }; + }; + + sd_emmc_b:sdio@ffe05000 { + status = "okay"; + compatible = "amlogic, meson-mmc-axg"; + reg = <0xffe05000 0x2000>; + interrupts = <0 217 4>; + pinctrl-names = "sdio_clk_cmd_pins", "sdio_all_pins"; + pinctrl-0 = <&sdio_clk_cmd_pins>; + pinctrl-1 = <&sdio_all_pins>; + clocks = <&clkc CLKID_SD_EMMC_B>, + <&clkc CLKID_SD_EMMC_B_P0_COMP>, + <&clkc CLKID_FCLK_DIV2>, + <&clkc CLKID_FCLK_DIV5>, + <&xtal>; + clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + + bus-width = <4>; + cap-sd-highspeed; + cap-mmc-highspeed; + max-frequency = <100000000>; + non-removable; + disable-wp; + sdio { + pinname = "sdio"; + ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + "MMC_CAP_UHS_SDR12", + "MMC_CAP_UHS_SDR25", + "MMC_CAP_UHS_SDR50", + "MMC_CAP_UHS_SDR104", + "MMC_PM_KEEP_POWER", + "MMC_CAP_SDIO_IRQ"; + f_min = <400000>; + f_max = <200000000>; + max_req_size = <0x20000>; /**128KB*/ + card_type = <3>; + /* 3:sdio device(ie:sdio-wifi), + * 4:SD combo (IO+mem) card + */ + }; + }; + + partitions: partitions{ + parts = <11>; + part-0 = <&logo>; + part-1 = <&recovery>; + part-2 = <&rsv>; + part-3 = <&tee>; + part-4 = <&crypt>; + part-5 = <&misc>; + part-6 = <&instaboot>; + part-7 = <&boot>; + part-8 = <&system>; + part-9 = <&cache>; + part-10 = <&data>; + + logo:logo{ + pname = "logo"; + size = <0x0 0x2000000>; + mask = <1>; + }; + recovery:recovery{ + pname = "recovery"; + size = <0x0 0x2000000>; + mask = <1>; + }; + rsv:rsv{ + pname = "rsv"; + size = <0x0 0x800000>; + mask = <1>; + }; + tee:tee{ + pname = "tee"; + size = <0x0 0x800000>; + mask = <1>; + }; + crypt:crypt{ + pname = "crypt"; + size = <0x0 0x2000000>; + mask = <1>; + }; + misc:misc{ + pname = "misc"; + size = <0x0 0x2000000>; + mask = <1>; + }; + instaboot:instaboot{ + pname = "instaboot"; + size = <0x0 0x400000>; + mask = <1>; + }; + boot:boot + { + pname = "boot"; + size = <0x0 0x2000000>; + mask = <1>; + }; + system:system + { + pname = "system"; + size = <0x0 0x80000000>; + mask = <1>; + }; + cache:cache + { + pname = "cache"; + size = <0x0 0x20000000>; + mask = <2>; + }; + data:data + { + pname = "data"; + size = <0xffffffff 0xffffffff>; + mask = <4>; + }; + }; + + meson-fb { + compatible = "amlogic, meson-axg"; + memory-region = <&fb_reserved>; + dev_name = "meson-fb"; + status = "disabled"; + interrupts = <0 3 1 + 0 89 1>; + interrupt-names = "viu-vsync", "rdma"; + mem_size = <0x00300000 0x1800000 0x00000000>; + /* uboot logo,fb0/fb1 memory size */ + display_mode_default = "1080p60hz"; + scale_mode = <0>; + /** 0:VPU free scale 1:OSD free scale 2:OSD super scale */ + display_size_default = <768 1024 768 2048 32>; + /*768*1024*4*2 = 0x600000*/ + mem_alloc = <1>; + logo_addr = "0x3e000000"; + pxp_mode = <0>; /** 0:normal mode 1:pxp mode */ + }; + + ge2d { + compatible = "amlogic, ge2d-axg"; + dev_name = "ge2d"; + status = "disabled"; + interrupts = <0 150 1>; + interrupt-names = "ge2d"; + clocks = <&clkc CLKID_VAPB_MUX>, + <&clkc CLKID_G2D>, + <&clkc CLKID_GE2D_GATE>; + clock-names = "clk_vapb_0", + "clk_ge2d", + "clk_ge2d_gate"; + reg = <0xff940000 0x10000>; + }; + + adc_keypad { + compatible = "amlogic, adc_keypad"; + status = "okay"; + key_name = "power", "vol-", "sos+", "wifi", "<<", ">>", "vol+"; + key_num = <7>; + io-channels = <&saradc SARADC_CH0>; + io-channel-names = "key-chan-0"; + key_chan = ; + key_code = <116 114 115 139 105 106 107>; + key_val = <0 143 266 389 512 635 840>; //val=voltage/1800mV*1023 + key_tolerance = <40 40 40 40 40 40 40>; + }; + + unifykey{ + compatible = "amlogic, unifykey"; + status = "okay"; + + unifykey-num = <6>; + unifykey-index-0 = <&keysn_0>; + unifykey-index-1 = <&keysn_1>; + unifykey-index-2 = <&keysn_2>; + unifykey-index-3 = <&keysn_3>; + unifykey-index-4 = <&keysn_4>; + unifykey-index-5 = <&keysn_5>; + + keysn_0: key_0{ + key-name = "usid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_1:key_1{ + key-name = "mac"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_2:key_2{ + key-name = "secure_boot_set"; + key-device = "efuse"; + key-permit = "write"; + }; + keysn_3:key_3{ + key-name = "mac_bt"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_4:key_4{ + key-name = "mac_wifi"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_5:key_5{ + key-name = "deviceid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + };//End unifykey + +}; /* end of / */ +&efuse { + status = "ok"; +}; + +&pwm_ab { + status = "okay"; +}; +/* Audio Related start */ +/* for spk board */ +&i2c1 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&b_i2c_master>; + + tlv320adc3101_32: tlv320adc3101_32@32 { + compatible = "ti,tlv320adc3101"; + #sound-dai-cells = <0>; + reg = <0x19>; + differential_pair = <1>; + status = "okay"; + }; + + /*****************************************************************/ + tas5782m_pu1: tas5782m_pu1@48 { + compatible = "ti, tas5782m"; + #sound-dai-cells = <0>; + reg = <0x48>; + reset_pin = <&gpio_ao GPIOAO_4 GPIO_ACTIVE_LOW>; + status = "okay"; + codec_name = "tas5782m"; + work_mode = <0>; /*0: i2s 1:tdm*/ + chip_offset = <1>; /*chip_N [1,2....]*/ + }; + + tas5782m_pu2: tas5782m_pu2@49 { + compatible = "ti, tas5782m"; + #sound-dai-cells = <0>; + reg = <0x49>; + status = "okay"; + codec_name = "tas5782m"; + work_mode = <0>; /*0: i2s 1:tdm*/ + chip_offset = <2>; /*chip_N [1,2....]*/ + }; + + tas5782m_pu3: tas5782m_pu3@4a { + compatible = "ti, tas5782m"; + #sound-dai-cells = <0>; + reg = <0x4a>; + status = "okay"; + codec_name = "tas5782m"; + work_mode = <0>; /*0: i2s 1:tdm*/ + chip_offset = <3>; /*chip_N [1,2....]*/ + }; + + tas5782m_pu4: tas5782m_pu4@4b { + compatible = "ti, tas5782m"; + #sound-dai-cells = <0>; + reg = <0x4b>; + status = "okay"; + codec_name = "tas5782m"; + work_mode = <0>; /*0: i2s 1:tdm*/ + chip_offset = <4>; /*chip_N [1,2....]*/ + }; + /*****************************************************************/ + + tas5707_36: tas5707_36@36 { + compatible = "ti,tas5707"; + #sound-dai-cells = <0>; + reg = <0x1b>; + status = "disabled"; + reset_pin = <&gpio_ao GPIOAO_4 0>; + }; + + tas5707_3a: tas5707_3a@3a { + compatible = "ti,tas5707"; + #sound-dai-cells = <0>; + reg = <0x1d>; + status = "disabled"; + }; +}; + +/* for mic board */ +&i2c_AO { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&ao_i2c_master_pin2>; + + /*****************************************************************/ + mcu6350: mcu6350@40 { + reg = <0x40>; + status = "okay"; + }; + + /*****************************************************************/ + tas5782m_pu5: tas5782m_pu5@48 { + compatible = "ti, tas5782m"; + #sound-dai-cells = <0>; + reg = <0x48>; + status = "okay"; + codec_name = "tas5782m"; + work_mode = <0>; /*0: i2s 1:tdm*/ + chip_offset = <5>; /*chip_N [1,2....]*/ + }; + + tas5782m_pu6: tas5782m_pu6@49 { + compatible = "ti, tas5782m"; + #sound-dai-cells = <0>; + reg = <0x49>; + status = "okay"; + codec_name = "tas5782m"; + work_mode = <0>; /*0: i2s 1:tdm*/ + chip_offset = <6>; /*chip_N [1,2....]*/ + }; + /*****************************************************************/ + + aml_pca9557: aml_pca9557@0x1f { + compatible = "aml, ledring"; + reg = <0x1f>; + mode = <0>; /*0: 6-led 1: 4key+2led */ + key_num = <4>; + led_dev_name = "aml_ledring"; + key_dev_name = "aml_pca_key"; + key_name = "mute", "pause", "vol+", "vol-"; + key_value = <200 201 202 203>; + status = "okay"; + }; + + tlv320adc3101_30: tlv320adc3101_30@30 { + compatible = "ti,tlv320adc3101"; + #sound-dai-cells = <0>; + reg = <0x18>; + status = "disabled"; + }; + tlv320adc3101_34: tlv320adc3101_34@30 { + compatible = "ti,tlv320adc3101"; + #sound-dai-cells = <0>; + reg = <0x1a>; + status = "disabled"; + }; + tlv320adc3101_36: tlv320adc3101_36@30 { + compatible = "ti,tlv320adc3101"; + #sound-dai-cells = <0>; + reg = <0x1b>; + status = "disabled"; + }; + + es7243_10: es7243_10@10 { + compatible = "MicArray_0"; + #sound-dai-cells = <0>; + reg = <0x10>; + status = "disabled"; + }; + es7243_12: es7243_12@12 { + compatible = "MicArray_1"; + #sound-dai-cells = <0>; + reg = <0x12>; + status = "disabled"; + }; + es7243_13: es7243_13@13 { + compatible = "MicArray_2"; + #sound-dai-cells = <0>; + reg = <0x13>; + status = "disabled"; + }; + is31fl3236a: is31f3236a@0x78 { + compatible = "issi,is31fl3236"; + reg = <0x3c>; + status = "disabled"; + led1_r { + label="LED1_R"; + reg_offset = <24>; + }; + led1_g { + label="LED1_G"; + reg_offset = <23>; + }; + led1_b { + label="LED1_B"; + reg_offset = <22>; + }; + led2_r { + label="LED2_R"; + reg_offset = <21>; + }; + led2_g { + label="LED2_G"; + reg_offset = <20>; + }; + led2_b { + label="LED2_B"; + reg_offset = <19>; + }; + led3_r { + label="LED3_R"; + reg_offset = <18>; + }; + led3_g { + label="LED3_G"; + reg_offset = <17>; + }; + led3_b { + label="LED3_B"; + reg_offset = <16>; + }; + led4_r { + label="LED4_R"; + reg_offset = <15>; + }; + led4_g { + label="LED4_G"; + reg_offset = <14>; + }; + led4_b { + label="LED4_B"; + reg_offset = <13>; + }; + led5_r { + label="LED5_R"; + reg_offset = <36>; + }; + led5_g { + label="LED5_G"; + reg_offset = <35>; + }; + led5_b { + label="LED5_B"; + reg_offset = <34>; + }; + led6_r { + label="LED6_R"; + reg_offset = <33>; + }; + led6_g { + label="LED6_G"; + reg_offset = <32>; + }; + led6_b { + label="LED6_B"; + reg_offset = <31>; + }; + led7_r { + label="LED7_R"; + reg_offset = <30>; + }; + led7_g { + label="LED7_G"; + reg_offset = <29>; + }; + led7_b { + label="LED7_B"; + reg_offset = <28>; + }; + led8_r { + label="LED8_R"; + reg_offset = <27>; + }; + led8_g { + label="LED8_G"; + reg_offset = <26>; + }; + led8_b { + label="LED8_B"; + reg_offset = <25>; + }; + }; +}; + +&audiobus { + aml_tdma: tdma { + compatible = "amlogic, axg-snd-tdma"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <1 0>; + dai-tdm-lane-slot-mask-out = <0 1>; + dai-tdm-clk-sel = <0>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_A + &clkc CLKID_MPLL0>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmout_a &tdmin_a &tdmout_a_data>; + }; + + aml_tdmb: tdmb { + compatible = "amlogic, axg-snd-tdmb"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <1 1 1 1>; + dai-tdm-lane-slot-mask-out = <0 0 0 0>; + dai-tdm-clk-sel = <1>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_B + &clkc CLKID_MPLL1>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + + /*A113D tdmb slave for HDMI*/ + pinctrl-0 = <&tdmb_mclk &tdmin_b_slv &tdmin_b>; + + /*A113D tdmb master for LineIn*/ + /* + * pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; + */ + }; + + aml_tdmc: tdmc { + compatible = "amlogic, axg-snd-tdmc"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 0 0 0>; + dai-tdm-lane-slot-mask-out = <1 1 1 1>; + dai-tdm-clk-sel = <2>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmc_mclk &tdmout_c>; + }; + + aml_spdif: spdif { + compatible = "amlogic, axg-snd-spdif"; + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 + &clkc CLKID_FCLK_DIV4 + &clkaudio CLKID_AUDIO_SPDIFIN + &clkaudio CLKID_AUDIO_SPDIFOUT + &clkaudio CLKID_AUDIO_SPDIFIN_CTRL + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "sysclk", "fixed_clk", "gate_spdifin", + "gate_spdifout", "clk_spdifin", "clk_spdifout"; + interrupts = + ; + + interrupt-names = "irq_spdifin"; + pinctrl-names = "spdif_pins"; + pinctrl-0 = <&spdifout &spdifin>; + + /* + * whether do asrc for pcm. + * if raw data, asrc is disabled automatically + * 0: "Disable", + * 1: "Enable:32K", + * 2: "Enable:44K", + * 3: "Enable:48K", + * 4: "Enable:88K", + * 5: "Enable:96K", + * 6: "Enable:176K", + * 7: "Enable:192K", + */ + auto_asrc = <3>; + status = "okay"; + }; + aml_pdm: pdm { + compatible = "amlogic, axg-snd-pdm"; + #sound-dai-cells = <0>; + clocks = <&clkaudio CLKID_AUDIO_PDM + &clkc CLKID_FCLK_DIV3 + &clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_PDMIN0 + &clkaudio CLKID_AUDIO_PDMIN1>; + clock-names = "gate", + "sysclk_srcpll", + "dclk_srcpll", + "pdm_dclk", + "pdm_sysclk"; + pinctrl-names = "pdm_pins"; + pinctrl-0 = <&pdmin>; + filter_mode = <1>; /* mode 0~4, defalut:1 */ + status = "okay"; + }; + + aml_loopback: loopback { + compatible = "amlogic, snd-loopback"; + + /* + * external loopback clock config + * enable clk while pdm record data + */ + /*clocks = <&clkc CLKID_MPLL1>;*/ + /*clock-names = "datalb_mpll";*/ + + /* + * 0: out rate = in data rate; + * 1: out rate = loopback data rate; + */ + + lb_mode = <0>; + + /* datain src + * 0: tdmin_a; + * 1: tdmin_b; + * 2: tdmin_c; + * 3: spdifin; + * 4: pdmin; + */ + datain_src = <4>; + datain_chnum = <8>; + datain_chmask = <0x7f>; + + /* tdmin_lb src + * 0: tdmoutA + * 1: tdmoutB + * 2: tdmoutC + * 3: PAD_tdminA + * 4: PAD_tdminB + * 5: PAD_tdminC + */ + + /*if tdmin_lb >= 3, use external loopback*/ + datalb_src = <2>; + datalb_chnum = <2>; + /*config which data pin as loopback*/ + /*datalb-lane-mask-in = <0 0 0 1>;*/ + datalb_chmask = <0x1>; + + status = "okay"; + }; + + audioresample: resample { + compatible = "amlogic, axg-resample"; + clocks = <&clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_MCLK_F + &clkaudio CLKID_AUDIO_RESAMPLE_CTRL>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + /*same with toddr_src + * TDMIN_A, + * TDMIN_B, + * TDMIN_C, + * SPDIFIN, + * PDMIN, + * NONE, + * TDMIN_LB, + * LOOPBACK, + */ + resample_module = <3>; + status = "okay"; + }; + aml_pwrdet: pwrdet { + compatible = "amlogic, axg-power-detect"; + + interrupts = ; + interrupt-names = "pwrdet_irq"; + + /* pwrdet source sel + * 7: loopback; + * 6: tdmin_lb; + * 5: reserved; + * 4: pdmin; + * 3: spdifin; + * 2: tdmin_c; + * 1: tdmin_b; + * 0: tdmin_a; + */ + pwrdet_src = <4>; + + hi_th = <0x70000>; + lo_th = <0x16000>; + + status = "disabled"; + }; +}; /* end of audiobus */ + +&pinctrl_periphs { + tdmout_a: tdmout_a { + mux { + groups = "tdma_sclk", + "tdma_fs"; + function = "tdma_out"; + }; + }; + + tdmout_a_data: tdmout_a_data { + mux { + groups = "tdma_dout1_x15"; + function = "tdma_out"; + }; + }; + + tdmin_a: tdmin_a { + mux { + groups = "tdma_din0"; + function = "tdma_in"; + }; + }; + + tdmb_mclk: tdmb_mclk { + mux { + groups = "mclk_b"; + function = "mclk_b"; + }; + }; + + tdmout_b: tdmout_b { + mux { + groups = "tdmb_sclk", + "tdmb_fs"; + function = "tdmb_out"; + }; + }; + + tdmin_b_slv: tdmin_b_slv{ + mux { + groups = "tdmb_slv_sclk", "tdmb_slv_fs"; + function = "tdmb_in"; + }; + }; + + // tdmin and tdmout are the same pins. can't use at same time + tdmin_b:tdmin_b { + mux { + groups = "tdmb_din0", + "tdmb_din1", + "tdmb_din2_a12", + "tdmb_din3_a13"; + function = "tdmb_in"; + }; + }; + + tdmc_mclk: tdmc_mclk { + mux { + groups = "mclk_a"; + function = "mclk_a"; + }; + }; + + tdmout_c:tdmout_c { + mux { + groups = "tdmc_sclk", + "tdmc_fs", + "tdmc_dout0", + "tdmc_dout1", + "tdmc_dout2_a6", + "tdmc_dout3_a7"; + function = "tdmc_out"; + }; + }; + + + tdmin_c:tdmin_c { + mux { + groups = "tdmc_din1"; + function = "tdmc_in"; + }; + }; + + spdifout: spidfout { + mux { + groups = "spdif_out_a20"; + function = "spdif_out"; + }; + }; + + spdifin: spidfin { + mux { + groups = "spdif_in_a19"; + function = "spdif_in"; + }; + }; + + pdmin: pdmin { + mux { + groups = "pdm_dclk_a14", + "pdm_din0", + "pdm_din1", + "pdm_din2", + "pdm_din3"; + function = "pdm"; + }; + }; + + bl_pwm_on_pins: bl_pwm_on_pin { + mux { + groups = "pwm_b_z"; + function = "pwm_b"; + }; + }; + bl_pwm_off_pins:bl_pwm_off_pin { + mux { + pins = "GPIOZ_4"; + function = "gpio_periphs"; + output-high; + }; + }; +}; /* end of pinctrl_periphs */ +/* Audio Related End */ + +&aobus{ + uart_AO: serial@3000 { + compatible = "amlogic, meson-uart"; + reg = <0x3000 0x18>; + interrupts = <0 193 1>; + status = "okay"; + clocks = <&xtal>; + clock-names = "clk_uart"; + xtal_tick_en = <1>; + fifosize = < 64 >; + pinctrl-names = "default"; + pinctrl-0 = <&ao_uart_pins>; + support-sysrq = <0>; /* 0 not support , 1 support */ + }; + + uart_AO_B: serial@4000 { + compatible = "amlogic, meson-uart"; + reg = <0x4000 0x18>; + interrupts = <0 197 1>; + status = "disable"; + clocks = <&xtal>; + clock-names = "clk_uart"; + fifosize = < 64 >; + pinctrl-names = "default"; + pinctrl-0 = <&ao_b_uart_pins>; + }; +}; + +&audio_data{ + status = "okay"; +}; + +&custom_maps{ + mapnum = <4>; + map0 = <&map_0>; + map1 = <&map_1>; + map2 = <&map_2>; + map3 = <&map_3>; + map_0: map_0{ + mapname = "amlogic-remote-1"; + customcode = <0xfb04>; + release_delay = <80>; + size = <50>; /*keymap size*/ + keymap = ; + }; + map_1: map_1{ + mapname = "amlogic-remote-2"; + customcode = <0xfe01>; + release_delay = <80>; + size = <53>; + keymap = ; + }; + map_2: map_2{ + mapname = "amlogic-remote-3"; + customcode = <0xbd02>; + release_delay = <80>; + size = <17>; + keymap = ; + }; + map_3: map_3{ + mapname = "amlogic-remote-3"; + customcode = <0xa4e8>; /* Reference Remote Control */ + release_delay = <80>; + size = <45>; + keymap = < + REMOTE_KEY(0xc7, 200) /* power */ + REMOTE_KEY(0x93, 201) /* eject-->input source */ + REMOTE_KEY(0xb2, 202) /* usb */ + REMOTE_KEY(0xb8, 203) /* coaxial */ + REMOTE_KEY(0xb7, 204) /* aux */ + REMOTE_KEY(0x8a, 205) /* scan-->hdmi arc */ + REMOTE_KEY(0x96, 206) /* dimmer */ + REMOTE_KEY(0x90, 207) /* hdmi1 */ + REMOTE_KEY(0xa8, 208) /* hdmi2 */ + REMOTE_KEY(0x85, 209) /* mute */ + REMOTE_KEY(0x80, 210) /* vol+ */ + REMOTE_KEY(0x81, 211) /* vol- */ + REMOTE_KEY(0x61, 212) /* DAP */ + REMOTE_KEY(0x62, 213) /* BM */ + REMOTE_KEY(0x63, 214) /* DRC */ + REMOTE_KEY(0x64, 215) /* POST */ + REMOTE_KEY(0x65, 216) /* UPMIX */ + REMOTE_KEY(0x66, 217) /* VIRT */ + REMOTE_KEY(0x67, 218) /* LEGACY */ + REMOTE_KEY(0x68, 219) /* HFILT */ + REMOTE_KEY(0x69, 220) /* Loundness */ + REMOTE_KEY(0x60, 221) /* Audio_info */ + REMOTE_KEY(0xb1, 222) /* CD */ + REMOTE_KEY(0xb4, 223) /* CD */ + REMOTE_KEY(0xb9, 224) /* CD */ + REMOTE_KEY(0xab, 225) /* CD */ + REMOTE_KEY(0x91, 226) /* CD */ + REMOTE_KEY(0x92, 227) /* CD */ + REMOTE_KEY(0x89, 228) /* CD */ + REMOTE_KEY(0x88, 229) /* CD */ + REMOTE_KEY(0xa5, 230) /* CD */ + REMOTE_KEY(0x84, 231) /* CD */ + REMOTE_KEY(0x72, 232) /* CD */ + REMOTE_KEY(0x73, 233) /* CD */ + REMOTE_KEY(0x9a, 234) /* CD */ + REMOTE_KEY(0x9b, 235) /* CD */ + REMOTE_KEY(0xa0, 236) /* CD */ + REMOTE_KEY(0x71, 237) /* CD */ + REMOTE_KEY(0x74, 238) /* CD */ + REMOTE_KEY(0x75, 239) /* CD */ + REMOTE_KEY(0x7e, 240) /* CD */ + REMOTE_KEY(0x7f, 241) /* CD */ + REMOTE_KEY(0x7a, 242) /* CD */ + REMOTE_KEY(0xa7, 243) /* CD */ + REMOTE_KEY(0xa9, 244) /* CD */ + >; + }; + }; diff --git a/arch/arm/boot/dts/amlogic/axg_s420.dts b/arch/arm/boot/dts/amlogic/axg_s420.dts index 104e35fa2746..fda588bb3b3e 100644 --- a/arch/arm/boot/dts/amlogic/axg_s420.dts +++ b/arch/arm/boot/dts/amlogic/axg_s420.dts @@ -47,8 +47,7 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm/boot/dts/amlogic/axg_s420_v03.dts b/arch/arm/boot/dts/amlogic/axg_s420_v03.dts index f9da32c0821a..05ab48dde9d9 100644 --- a/arch/arm/boot/dts/amlogic/axg_s420_v03.dts +++ b/arch/arm/boot/dts/amlogic/axg_s420_v03.dts @@ -47,8 +47,7 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm/boot/dts/amlogic/axg_s420_v03gva.dts b/arch/arm/boot/dts/amlogic/axg_s420_v03gva.dts index 594190f2d64b..83595b360b8b 100644 --- a/arch/arm/boot/dts/amlogic/axg_s420_v03gva.dts +++ b/arch/arm/boot/dts/amlogic/axg_s420_v03gva.dts @@ -47,8 +47,7 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { @@ -316,14 +315,6 @@ pinctrl-0 = <&b_uart_pins>; }; - meson-irblaster { - compatible = "amlogic, am_irblaster"; - dev_name = "meson-irblaster"; - status = "disable"; - pinctrl-names = "default"; - pinctrl-0 = <&irblaster_pins>; - }; - /* Sound iomap */ aml_snd_iomap { compatible = "amlogic, snd-iomap"; diff --git a/arch/arm/boot/dts/amlogic/firmware_avb_ab.dtsi b/arch/arm/boot/dts/amlogic/firmware_avb_ab.dtsi index d1154cca4a93..bcbede9eeb58 100644 --- a/arch/arm/boot/dts/amlogic/firmware_avb_ab.dtsi +++ b/arch/arm/boot/dts/amlogic/firmware_avb_ab.dtsi @@ -39,7 +39,7 @@ firmware { dev = "/dev/block/product"; type = "ext4"; mnt_flags = "ro,barrier=1,inode_readahead_blks=8"; - fsmgr_flags = "wait,slotselect"; + fsmgr_flags = "wait,slotselect,avb"; }; odm { compatible = "android,odm"; diff --git a/arch/arm/boot/dts/amlogic/g12a_pxp.dts b/arch/arm/boot/dts/amlogic/g12a_pxp.dts index 28c98cb1b4c1..4973402c90e9 100644 --- a/arch/arm/boot/dts/amlogic/g12a_pxp.dts +++ b/arch/arm/boot/dts/amlogic/g12a_pxp.dts @@ -37,7 +37,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x100000 0x3ff00000>; + linux,usable-memory = <0x0 0x40000000>; }; reserved-memory { diff --git a/arch/arm/boot/dts/amlogic/g12a_s905d2_skt.dts b/arch/arm/boot/dts/amlogic/g12a_s905d2_skt.dts index c511bb41f9a4..3ce2558e9538 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905d2_skt.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905d2_skt.dts @@ -23,6 +23,7 @@ / { model = "Amlogic"; + amlogic-dt-id = "g12a_skt_2g"; compatible = "amlogic, g12a"; interrupt-parent = <&gic>; #address-cells = <1>; @@ -45,7 +46,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x100000 0x7ff00000>; + linux,usable-memory = <0x0 0x80000000>; }; reserved-memory { @@ -58,8 +59,7 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { @@ -233,6 +233,21 @@ status = "okay"; }; + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + ppmgr { compatible = "amlogic, ppmgr"; memory-region = <&ppmgr_reserved>; @@ -792,8 +807,10 @@ dai-tdm-clk-sel = <1>; clocks = <&clkaudio CLKID_AUDIO_MCLK_B &clkc CLKID_MPLL1 - &clkc CLKID_MPLL0>; - clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; /* @@ -837,8 +854,10 @@ ; interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; pinctrl-0 = <&spdifout &spdifin>; + pinctrl-1 = <&spdifout_a_mute>; status = "okay"; }; aml_spdif_b: spdif_b { @@ -1060,6 +1079,13 @@ function = "spdif_out_ao"; }; }; + + spdifout_a_mute: spdifout_a_mute { + mux { /* gpiao_10 */ + groups = "GPIOAO_10"; + function = "gpio_aobus"; + }; + }; }; /* end of pinctrl_aobus */ &audio_data { diff --git a/arch/arm/boot/dts/amlogic/g12a_s905d2_skt_buildroot.dts b/arch/arm/boot/dts/amlogic/g12a_s905d2_skt_buildroot.dts index 6955c4592030..b412fe1f3230 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905d2_skt_buildroot.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905d2_skt_buildroot.dts @@ -46,7 +46,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x100000 0x7ff00000>; + linux,usable-memory = <0x0 0x80000000>; }; reserved-memory { @@ -213,6 +213,14 @@ }; }; + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + codec_mm { compatible = "amlogic, codec, mm"; memory-region = <&codec_mm_cma &codec_mm_reserved>; @@ -220,6 +228,13 @@ status = "okay"; }; + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + ppmgr { compatible = "amlogic, ppmgr"; memory-region = <&ppmgr_reserved>; @@ -784,8 +799,10 @@ ; interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; pinctrl-0 = <&spdifout &spdifin>; + pinctrl-1 = <&spdifout_a_mute>; status = "okay"; }; aml_spdif_b: spdif_b { @@ -1007,6 +1024,13 @@ function = "spdif_out_ao"; }; }; + + spdifout_a_mute: spdifout_a_mute { + mux { /* gpiao_10 */ + groups = "GPIOAO_10"; + function = "gpio_aobus"; + }; + }; }; /* end of pinctrl_aobus */ &audio_data { diff --git a/arch/arm/boot/dts/amlogic/g12a_s905d2_u200.dts b/arch/arm/boot/dts/amlogic/g12a_s905d2_u200.dts index 03a40b29b100..39979b7caf8e 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905d2_u200.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905d2_u200.dts @@ -23,6 +23,7 @@ / { model = "Amlogic"; + amlogic-dt-id = "g12a_u200_2g"; compatible = "amlogic, g12a"; interrupt-parent = <&gic>; #address-cells = <1>; @@ -45,7 +46,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x000000 0x80000000>; + linux,usable-memory = <0x100000 0x7ff00000>; }; reserved-memory { @@ -58,8 +59,7 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { @@ -154,8 +154,8 @@ vm0_cma_reserved:linux,vm0_cma { compatible = "shared-dma-pool"; reusable; - size = <0x2000000>; - alignment = <0x400000>; + size = <0x0 0x2000000>; + alignment = <0x0 0x400000>; }; }; @@ -167,8 +167,6 @@ label="sys_led"; gpios=<&gpio_ao GPIOAO_11 GPIO_ACTIVE_HIGH>; default-state ="on"; - retain-state-suspended; - linux,default-trigger="cpu0"; }; }; @@ -247,6 +245,14 @@ }; }; + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + codec_mm { compatible = "amlogic, codec, mm"; memory-region = <&codec_mm_cma &codec_mm_reserved>; @@ -254,6 +260,13 @@ status = "okay"; }; + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + ppmgr { compatible = "amlogic, ppmgr"; memory-region = <&ppmgr_reserved>; @@ -303,7 +316,7 @@ compatible = "amlogic, amvdec_656in"; dev_name = "amvdec_656in"; status = "disabled"; - reg = <0xffe02000 0x7c>; + reg = <0x0 0xffe02000 0x0 0x7c>; clocks = <&clkc CLKID_BT656_COMP>, <&clkc CLKID_BT656>; clock-names = "cts_bt656_clk1", @@ -795,6 +808,122 @@ }; }; + cpu_opp_table1: cpu_opp_table1 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <731000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <731000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <731000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <731000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <731000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <731000>; + }; + opp06 { + opp-hz = /bits/ 64 <1398000000>; + opp-microvolt = <761000>; + }; + opp07 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <791000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <831000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <861000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <981000>; + }; + opp11 { + opp-hz = /bits/ 64 <1908000000>; + opp-microvolt = <991000>; + }; + }; + + cpu_opp_table2: cpu_opp_table2 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <731000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <731000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <731000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <731000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <731000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <731000>; + }; + opp06 { + opp-hz = /bits/ 64 <1398000000>; + opp-microvolt = <761000>; + }; + opp07 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <791000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <831000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <861000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <981000>; + }; + opp11 { + opp-hz = /bits/ 64 <1908000000>; + opp-microvolt = <991000>; + }; + opp12 { + opp-hz = /bits/ 64 <2016000000>; + opp-microvolt = <1011000>; + }; + opp13 { + opp-hz = /bits/ 64 <2100000000>; + opp-microvolt = <1011000>; + }; + }; + cpufreq-meson { compatible = "amlogic, cpufreq-meson"; pinctrl-names = "default"; @@ -804,6 +933,50 @@ }; /* end of / */ +&CPU0 { + /*set differents table cpufreq max*/ + diff_tables_supply; + hispeed_cpufreq_max = <2100>; + medspeed_cpufreq_max = <1908>; + lospeed_cpufreq_max = <1800>; + operating-points-v2 = <&cpu_opp_table0>, + <&cpu_opp_table1>, + <&cpu_opp_table2>; +}; + +&CPU1 { + /*set differents table cpufreq max*/ + diff_tables_supply; + hispeed_cpufreq_max = <2100>; + medspeed_cpufreq_max = <1908>; + lospeed_cpufreq_max = <1800>; + operating-points-v2 = <&cpu_opp_table0>, + <&cpu_opp_table1>, + <&cpu_opp_table2>; +}; + +&CPU2 { + /*set differents table cpufreq max*/ + diff_tables_supply; + hispeed_cpufreq_max = <2100>; + medspeed_cpufreq_max = <1908>; + lospeed_cpufreq_max = <1800>; + operating-points-v2 = <&cpu_opp_table0>, + <&cpu_opp_table1>, + <&cpu_opp_table2>; +}; + +&CPU3 { + /*set differents table cpufreq max*/ + diff_tables_supply; + hispeed_cpufreq_max = <2100>; + medspeed_cpufreq_max = <1908>; + lospeed_cpufreq_max = <1800>; + operating-points-v2 = <&cpu_opp_table0>, + <&cpu_opp_table1>, + <&cpu_opp_table2>; +}; + &meson_fb { status = "okay"; display_size_default = <1920 1080 1920 2160 32>; @@ -911,8 +1084,10 @@ dai-tdm-clk-sel = <1>; clocks = <&clkaudio CLKID_AUDIO_MCLK_B &clkc CLKID_MPLL1 - &clkc CLKID_MPLL0>; - clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; /* @@ -970,8 +1145,10 @@ ; interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; pinctrl-0 = <&spdifout &spdifin>; + pinctrl-1 = <&spdifout_a_mute>; status = "okay"; }; aml_spdif_b: spdif_b { @@ -1220,6 +1397,13 @@ function = "spdif_out_ao"; }; }; + + spdifout_a_mute: spdifout_a_mute { + mux { /* gpiao_10 */ + groups = "GPIOAO_10"; + function = "gpio_aobus"; + }; + }; }; /* end of pinctrl_aobus */ &audio_data { diff --git a/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_1g.dts b/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_1g.dts index 70a6efda37fc..6fd0b595c93e 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_1g.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_1g.dts @@ -23,6 +23,7 @@ / { model = "Amlogic"; + amlogic-dt-id = "g12a_u200_1g"; compatible = "amlogic, g12a"; interrupt-parent = <&gic>; #address-cells = <1>; @@ -45,7 +46,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x000000 0x40000000>; + linux,usable-memory = <0x100000 0x3ff00000>; }; reserved-memory { @@ -58,8 +59,7 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { @@ -171,8 +171,6 @@ label="sys_led"; gpios=<&gpio_ao GPIOAO_11 GPIO_ACTIVE_HIGH>; default-state ="on"; - retain-state-suspended; - linux,default-trigger="cpu0"; }; }; @@ -251,6 +249,14 @@ }; }; + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + codec_mm { compatible = "amlogic, codec, mm"; memory-region = <&codec_mm_cma &codec_mm_reserved>; @@ -258,6 +264,13 @@ status = "okay"; }; + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + ppmgr { compatible = "amlogic, ppmgr"; memory-region = <&ppmgr_reserved>; @@ -915,8 +928,10 @@ dai-tdm-clk-sel = <1>; clocks = <&clkaudio CLKID_AUDIO_MCLK_B &clkc CLKID_MPLL1 - &clkc CLKID_MPLL0>; - clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; /* @@ -974,8 +989,10 @@ ; interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; pinctrl-0 = <&spdifout &spdifin>; + pinctrl-1 = <&spdifout_a_mute>; status = "okay"; }; aml_spdif_b: spdif_b { @@ -1224,6 +1241,13 @@ function = "spdif_out_ao"; }; }; + + spdifout_a_mute: spdifout_a_mute { + mux { /* gpiao_10 */ + groups = "GPIOAO_10"; + function = "gpio_aobus"; + }; + }; }; /* end of pinctrl_aobus */ &audio_data { diff --git a/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_buildroot.dts b/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_buildroot.dts index 4441fcc9b185..e5202d8e88f8 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_buildroot.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_buildroot.dts @@ -19,6 +19,7 @@ #include "mesong12a.dtsi" #include "mesong12a_skt-panel.dtsi" +#include "mesong12a_drm.dtsi" / { model = "Amlogic"; @@ -44,7 +45,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x100000 0x7ff00000>; + linux,usable-memory = <0x0 0x80000000>; }; reserved-memory { @@ -149,8 +150,6 @@ label="sys_led"; gpios=<&gpio_ao GPIOAO_11 GPIO_ACTIVE_HIGH>; default-state ="on"; - retain-state-suspended; - linux,default-trigger="cpu0"; }; }; @@ -224,6 +223,14 @@ }; }; + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + codec_mm { compatible = "amlogic, codec, mm"; memory-region = <&codec_mm_cma &codec_mm_reserved>; @@ -231,6 +238,13 @@ status = "okay"; }; + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + ppmgr { compatible = "amlogic, ppmgr"; memory-region = <&ppmgr_reserved>; @@ -882,8 +896,10 @@ dai-tdm-clk-sel = <1>; clocks = <&clkaudio CLKID_AUDIO_MCLK_B &clkc CLKID_MPLL1 - &clkc CLKID_MPLL0>; - clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; /* @@ -927,8 +943,10 @@ ; interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; pinctrl-0 = <&spdifout &spdifin>; + pinctrl-1 = <&spdifout_a_mute>; status = "okay"; }; aml_spdif_b: spdif_b { @@ -1151,6 +1169,13 @@ function = "spdif_out_ao"; }; }; + + spdifout_a_mute: spdifout_a_mute { + mux { /* gpiao_10 */ + groups = "GPIOAO_10"; + function = "gpio_aobus"; + }; + }; }; /* end of pinctrl_aobus */ &audio_data { diff --git a/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_buildroot_vccktest.dts b/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_buildroot_vccktest.dts index a960b7439f0e..7204b6f6ab18 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_buildroot_vccktest.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_buildroot_vccktest.dts @@ -19,6 +19,7 @@ #include "mesong12a.dtsi" #include "mesong12a_skt-panel.dtsi" +#include "mesong12a_drm.dtsi" / { model = "Amlogic"; @@ -44,7 +45,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x100000 0x7ff00000>; + linux,usable-memory = <0x0 0x80000000>; }; reserved-memory { @@ -150,8 +151,6 @@ label="sys_led"; gpios=<&gpio_ao GPIOAO_11 GPIO_ACTIVE_HIGH>; default-state ="on"; - retain-state-suspended; - linux,default-trigger="cpu0"; }; }; @@ -901,8 +900,10 @@ dai-tdm-clk-sel = <1>; clocks = <&clkaudio CLKID_AUDIO_MCLK_B &clkc CLKID_MPLL1 - &clkc CLKID_MPLL0>; - clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; /* @@ -946,8 +947,10 @@ ; interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; pinctrl-0 = <&spdifout &spdifin>; + pinctrl-1 = <&spdifout_a_mute>; status = "okay"; }; aml_spdif_b: spdif_b { @@ -1170,6 +1173,13 @@ function = "spdif_out_ao"; }; }; + + spdifout_a_mute: spdifout_a_mute { + mux { /* gpiao_10 */ + groups = "GPIOAO_10"; + function = "gpio_aobus"; + }; + }; }; /* end of pinctrl_aobus */ &audio_data { diff --git a/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_drm_buildroot.dts b/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_drm_buildroot.dts index f533037eb344..bb768ee939a4 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_drm_buildroot.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_drm_buildroot.dts @@ -45,7 +45,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x100000 0x7ff00000>; + linux,usable-memory = <0x0 0x80000000>; }; reserved-memory { @@ -150,8 +150,6 @@ label="sys_led"; gpios=<&gpio_ao GPIOAO_11 GPIO_ACTIVE_HIGH>; default-state ="on"; - retain-state-suspended; - linux,default-trigger="cpu0"; }; }; @@ -225,6 +223,14 @@ }; }; + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + codec_mm { compatible = "amlogic, codec, mm"; memory-region = <&codec_mm_cma &codec_mm_reserved>; @@ -232,6 +238,13 @@ status = "okay"; }; + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + ppmgr { compatible = "amlogic, ppmgr"; memory-region = <&ppmgr_reserved>; @@ -897,8 +910,10 @@ dai-tdm-clk-sel = <1>; clocks = <&clkaudio CLKID_AUDIO_MCLK_B &clkc CLKID_MPLL1 - &clkc CLKID_MPLL0>; - clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; /* @@ -942,8 +957,10 @@ ; interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; pinctrl-0 = <&spdifout &spdifin>; + pinctrl-1 = <&spdifout_a_mute>; status = "okay"; }; aml_spdif_b: spdif_b { @@ -1166,6 +1183,13 @@ function = "spdif_out_ao"; }; }; + + spdifout_a_mute: spdifout_a_mute { + mux { /* gpiao_10 */ + groups = "GPIOAO_10"; + function = "gpio_aobus"; + }; + }; }; /* end of pinctrl_aobus */ &audio_data { diff --git a/arch/arm/boot/dts/amlogic/g12a_s905x2_u211.dts b/arch/arm/boot/dts/amlogic/g12a_s905x2_u211.dts index c3e236146c7b..e15e7125e640 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905x2_u211.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905x2_u211.dts @@ -45,7 +45,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x100000 0x7ff00000>; + linux,usable-memory = <0x0 0x80000000>; }; reserved-memory { @@ -58,8 +58,7 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { @@ -188,8 +187,6 @@ label="sys_led"; gpios=<&gpio_ao GPIOAO_11 GPIO_ACTIVE_LOW>; default-state ="on"; - retain-state-suspended; - linux,default-trigger="cpu0"; }; }; @@ -263,6 +260,14 @@ }; }; + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + codec_mm { compatible = "amlogic, codec, mm"; memory-region = <&codec_mm_cma &codec_mm_reserved>; @@ -270,6 +275,13 @@ status = "okay"; }; + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + ppmgr { compatible = "amlogic, ppmgr"; memory-region = <&ppmgr_reserved>; @@ -842,8 +854,10 @@ dai-tdm-clk-sel = <1>; clocks = <&clkaudio CLKID_AUDIO_MCLK_B &clkc CLKID_MPLL1 - &clkc CLKID_MPLL0>; - clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; /* @@ -901,8 +915,10 @@ ; interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; pinctrl-0 = <&spdifout>; + pinctrl-1 = <&spdifout_a_mute>; status = "okay"; }; aml_spdif_b: spdif_b { @@ -1095,6 +1111,13 @@ }; }; + spdifout_a_mute: spdifout_a_mute { + mux { /* GPIOH_4 */ + groups = "GPIOH_4"; + function = "gpio_periphs"; + }; + }; + pdmin: pdmin { mux { /* gpioa_5, gpioa_6, gpioa_7, gpioa_8, gpioa_9*/ groups = "pdm_din0_a", diff --git a/arch/arm/boot/dts/amlogic/g12a_s905x2_u211_1g.dts b/arch/arm/boot/dts/amlogic/g12a_s905x2_u211_1g.dts index cd970a2bbb0c..b38fec03dbd2 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905x2_u211_1g.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905x2_u211_1g.dts @@ -45,7 +45,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x100000 0x3ff00000>; + linux,usable-memory = <0x0 0x40000000>; }; @@ -59,8 +59,7 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { @@ -189,8 +188,6 @@ label="sys_led"; gpios=<&gpio_ao GPIOAO_11 GPIO_ACTIVE_LOW>; default-state ="on"; - retain-state-suspended; - linux,default-trigger="cpu0"; }; }; @@ -257,6 +254,14 @@ }; }; + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + codec_mm { compatible = "amlogic, codec, mm"; memory-region = <&codec_mm_cma &codec_mm_reserved>; @@ -264,6 +269,13 @@ status = "okay"; }; + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + ppmgr { compatible = "amlogic, ppmgr"; memory-region = <&ppmgr_reserved>; @@ -833,8 +845,10 @@ dai-tdm-clk-sel = <1>; clocks = <&clkaudio CLKID_AUDIO_MCLK_B &clkc CLKID_MPLL1 - &clkc CLKID_MPLL0>; - clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; /* @@ -892,8 +906,10 @@ ; interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; pinctrl-0 = <&spdifout>; + pinctrl-1 = <&spdifout_a_mute>; status = "okay"; }; aml_spdif_b: spdif_b { @@ -1086,6 +1102,13 @@ }; }; + spdifout_a_mute: spdifout_a_mute { + mux { /* GPIOH_4 */ + groups = "GPIOH_4"; + function = "gpio_periphs"; + }; + }; + pdmin: pdmin { mux { /* gpioa_5, gpioa_6, gpioa_7, gpioa_8, gpioa_9*/ groups = "pdm_din0_a", diff --git a/arch/arm/boot/dts/amlogic/g12a_s905x2_u211_512m.dts b/arch/arm/boot/dts/amlogic/g12a_s905x2_u211_512m.dts index 231f350a8064..ef84c49e8ecd 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905x2_u211_512m.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905x2_u211_512m.dts @@ -57,8 +57,7 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { @@ -177,8 +176,6 @@ label="sys_led"; gpios=<&gpio_ao GPIOAO_11 GPIO_ACTIVE_LOW>; default-state ="on"; - retain-state-suspended; - linux,default-trigger="cpu0"; }; }; @@ -252,6 +249,14 @@ }; }; + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + codec_mm { compatible = "amlogic, codec, mm"; memory-region = <&codec_mm_cma &codec_mm_reserved>; @@ -259,6 +264,13 @@ status = "okay"; }; + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + ppmgr { compatible = "amlogic, ppmgr"; memory-region = <&ppmgr_reserved>; @@ -829,8 +841,10 @@ dai-tdm-clk-sel = <1>; clocks = <&clkaudio CLKID_AUDIO_MCLK_B &clkc CLKID_MPLL1 - &clkc CLKID_MPLL0>; - clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; /* @@ -888,8 +902,10 @@ ; interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; pinctrl-0 = <&spdifout>; + pinctrl-1 = <&spdifout_a_mute>; status = "okay"; }; aml_spdif_b: spdif_b { @@ -1082,6 +1098,13 @@ }; }; + spdifout_a_mute: spdifout_a_mute { + mux { /* GPIOH_4 */ + groups = "GPIOH_4"; + function = "gpio_periphs"; + }; + }; + pdmin: pdmin { mux { /* gpioa_5, gpioa_6, gpioa_7, gpioa_8, gpioa_9*/ groups = "pdm_din0_a", diff --git a/arch/arm/boot/dts/amlogic/g12a_s905x2_u211_buildroot.dts b/arch/arm/boot/dts/amlogic/g12a_s905x2_u211_buildroot.dts index a3ae0f1f1cfb..d2909abb4e3a 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905x2_u211_buildroot.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905x2_u211_buildroot.dts @@ -18,9 +18,11 @@ /dts-v1/; #include "mesong12a.dtsi" +#include "mesong12a_drm.dtsi" / { model = "Amlogic"; + amlogic-dt-id = "g12a_u211_2g"; compatible = "amlogic, g12a"; interrupt-parent = <&gic>; #address-cells = <1>; @@ -43,7 +45,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x100000 0x7ff00000>; + linux,usable-memory = <0x0 0x80000000>; }; reserved-memory { @@ -167,8 +169,6 @@ label="sys_led"; gpios=<&gpio_ao GPIOAO_11 GPIO_ACTIVE_LOW>; default-state ="on"; - retain-state-suspended; - linux,default-trigger="cpu0"; }; }; @@ -236,6 +236,14 @@ }; }; + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + codec_mm { compatible = "amlogic, codec, mm"; memory-region = <&codec_mm_cma &codec_mm_reserved>; @@ -243,6 +251,13 @@ status = "okay"; }; + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + ppmgr { compatible = "amlogic, ppmgr"; memory-region = <&ppmgr_reserved>; @@ -883,8 +898,10 @@ dai-tdm-clk-sel = <1>; clocks = <&clkaudio CLKID_AUDIO_MCLK_B &clkc CLKID_MPLL1 - &clkc CLKID_MPLL0>; - clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; /* @@ -928,8 +945,10 @@ ; interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; pinctrl-0 = <&spdifout>; + pinctrl-1 = <&spdifout_a_mute>; status = "okay"; }; aml_spdif_b: spdif_b { @@ -1122,6 +1141,13 @@ }; }; + spdifout_a_mute: spdifout_a_mute { + mux { /* GPIOH_4 */ + groups = "GPIOH_4"; + function = "gpio_periphs"; + }; + }; + pdmin: pdmin { mux { /* gpioa_5, gpioa_6, gpioa_7, gpioa_8, gpioa_9*/ groups = "pdm_din0_a", diff --git a/arch/arm/boot/dts/amlogic/g12a_s905x2_u212.dts b/arch/arm/boot/dts/amlogic/g12a_s905x2_u212.dts index 58073e20078b..fdaeda8ca429 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905x2_u212.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905x2_u212.dts @@ -22,7 +22,7 @@ / { model = "Amlogic"; - amlogic-dt-id = "g12a_s905x2_u212"; + amlogic-dt-id = "g12a_u212_2g"; compatible = "amlogic, g12a"; interrupt-parent = <&gic>; #address-cells = <1>; @@ -45,7 +45,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x000000 0x80000000>; + linux,usable-memory = <0x100000 0x7ff00000>; }; reserved-memory { @@ -58,8 +58,7 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { @@ -163,17 +162,17 @@ gpioleds { compatible = "gpio-leds"; - status = "okay"; + status = "disabled"; net_red { label="net_red"; - gpios=<&gpio GPIOA_14 GPIO_ACTIVE_LOW>; + /*gpios=<&gpio GPIOA_14 GPIO_ACTIVE_LOW>;*/ default-state ="on"; }; net_green { label="net_green"; - gpios=<&gpio GPIOA_15 GPIO_ACTIVE_HIGH>; + /*gpios=<&gpio GPIOA_15 GPIO_ACTIVE_HIGH>;*/ default-state ="on"; }; @@ -188,8 +187,6 @@ label="sys_led"; gpios=<&gpio_ao GPIOAO_11 GPIO_ACTIVE_LOW>; default-state ="on"; - retain-state-suspended; - linux,default-trigger="cpu0"; }; }; @@ -263,6 +260,14 @@ }; }; + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + codec_mm { compatible = "amlogic, codec, mm"; memory-region = <&codec_mm_cma &codec_mm_reserved>; @@ -270,6 +275,13 @@ status = "okay"; }; + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + ppmgr { compatible = "amlogic, ppmgr"; memory-region = <&ppmgr_reserved>; @@ -306,43 +318,47 @@ dev_name = "ionvideo"; status = "okay"; }; - /*dvb { - * compatible = "amlogic, dvb"; - * dev_name = "dvb"; - * - * fe0_mode = "external"; - * fe0_demod = "Atbm8881"; - * fe0_i2c_adap_id = <&i2c2>; - * fe0_demod_i2c_addr = <0xc0>; - * fe0_ts = <1>; - * fe0_reset_value = <0>; - * fe0_reset_gpio = <&gpio GPIOZ_1 GPIO_ACTIVE_HIGH>; - * - * ts1 = "parallel"; - * ts1_control = <0>; - * ts1_invert = <0>; - * interrupts = <0 23 1 - * 0 5 1 - * 0 21 1 - * 0 19 1 - * 0 25 1 - * 0 18 1 - * 0 24 1>; - * interrupt-names = "demux0_irq", - * "demux1_irq", - * "demux2_irq", - * "dvr0_irq", - * "dvr1_irq", - * "dvrfill0_fill", - * "dvrfill1_flush"; - * pinctrl-names = "p_ts1"; - * pinctrl-0 = <&dvb_p_ts1_pins>; - * clocks = <&clkc CLKID_DEMUX - * &clkc CLKID_AHB_ARB0 - * &clkc CLKID_DOS_PARSER>; - * clock-names = "demux", "ahbarb0", "parser_top"; - *}; - */ + dvb { + compatible = "amlogic, dvb"; + dev_name = "dvb"; + status = "ok"; + + ts0 = "serial"; + ts0_control = <0x800>; + ts0_invert = <0>; + pinctrl-names = "s_ts0"; + pinctrl-0 = <&dvb_s_ts0_pins>; + + interrupts = <0 23 1 + 0 5 1 + 0 53 1 + 0 19 1 + 0 25 1 + 0 18 1 + 0 24 1>; + interrupt-names = "demux0_irq", + "demux1_irq", + "demux2_irq", + "dvr0_irq", + "dvr1_irq", + "dvrfill0_fill", + "dvrfill1_flush"; + }; + dvbfe { + compatible = "amlogic, dvbfe"; + dev_name = "dvbfe"; + dtv_demod0 = "Avl6762"; + dtv_demod0_i2c_adap = <&i2c3>; + dtv_demod0_i2c_addr = <0x14>; + dtv_demod0_reset_value = <0>; + dtv_demod0_reset_gpio = <&gpio GPIOZ_10 GPIO_ACTIVE_HIGH>; + dtv_demod0_ant_poweron_value = <0>; + dtv_demod0_ant_power_gpio = <&gpio GPIOH_5 GPIO_ACTIVE_HIGH>; + dtv_demod0_tuner_type = <52>; + fe0_dtv_demod = <0>; + fe0_ts = <0>; + fe0_dev = <0>; + }; unifykey{ compatible = "amlogic, unifykey"; status = "ok"; @@ -830,7 +846,7 @@ */ &i2c3 { - status = "disabled"; + status = "ok"; pinctrl-names="default"; pinctrl-0=<&i2c3_master_pins2>; clock-frequency = <100000>; /* default 100k */ @@ -882,8 +898,10 @@ dai-tdm-clk-sel = <1>; clocks = <&clkaudio CLKID_AUDIO_MCLK_B &clkc CLKID_MPLL1 - &clkc CLKID_MPLL0>; - clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; /* @@ -941,8 +959,10 @@ ; interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; pinctrl-0 = <&spdifout>; + pinctrl-1 = <&spdifout_a_mute>; status = "okay"; }; aml_spdif_b: spdif_b { @@ -1135,6 +1155,13 @@ }; }; + spdifout_a_mute: spdifout_a_mute { + mux { /* GPIOH_4 */ + groups = "GPIOH_4"; + function = "gpio_periphs"; + }; + }; + pdmin: pdmin { mux { /* gpioa_5, gpioa_6, gpioa_7, gpioa_8, gpioa_9*/ groups = "pdm_din0_a", @@ -1386,3 +1413,14 @@ status = "okay"; }; +&pinctrl_aobus { + dvb_s_ts0_pins: dvb_s_ts0_pins { + tsin_a { + groups = "tsin_a_sop_ao", + "tsin_a_valid_ao", + "tsin_a_clk_ao", + "tsin_a_din0_ao"; + function = "tsin_a_ao"; + }; + }; +}; diff --git a/arch/arm/boot/dts/amlogic/g12a_s905x2_u212_1g.dts b/arch/arm/boot/dts/amlogic/g12a_s905x2_u212_1g.dts index aed00d038bc7..f9e7e6c2a43b 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905x2_u212_1g.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905x2_u212_1g.dts @@ -22,7 +22,7 @@ / { model = "Amlogic"; - amlogic-dt-id = "g12a_s905x2_u212_1g"; + amlogic-dt-id = "g12a_u212_1g"; compatible = "amlogic, g12a"; interrupt-parent = <&gic>; #address-cells = <1>; @@ -45,7 +45,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x000000 0x40000000>; + linux,usable-memory = <0x100000 0x3ff00000>; }; @@ -59,8 +59,7 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { @@ -168,17 +167,17 @@ gpioleds { compatible = "gpio-leds"; - status = "okay"; + status = "disabled"; net_red { label="net_red"; - gpios=<&gpio GPIOA_14 GPIO_ACTIVE_LOW>; + /*gpios=<&gpio GPIOA_14 GPIO_ACTIVE_LOW>;*/ default-state ="on"; }; net_green { label="net_green"; - gpios=<&gpio GPIOA_15 GPIO_ACTIVE_HIGH>; + /*gpios=<&gpio GPIOA_15 GPIO_ACTIVE_HIGH>;*/ default-state ="on"; }; @@ -193,8 +192,6 @@ label="sys_led"; gpios=<&gpio_ao GPIOAO_11 GPIO_ACTIVE_LOW>; default-state ="on"; - retain-state-suspended; - linux,default-trigger="cpu0"; }; }; @@ -261,6 +258,14 @@ }; }; + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + codec_mm { compatible = "amlogic, codec, mm"; memory-region = <&codec_mm_cma &codec_mm_reserved>; @@ -268,6 +273,13 @@ status = "okay"; }; + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + ppmgr { compatible = "amlogic, ppmgr"; memory-region = <&ppmgr_reserved>; @@ -304,43 +316,47 @@ dev_name = "ionvideo"; status = "okay"; }; - /*dvb { - * compatible = "amlogic, dvb"; - * dev_name = "dvb"; - * - * fe0_mode = "external"; - * fe0_demod = "Atbm8881"; - * fe0_i2c_adap_id = <&i2c2>; - * fe0_demod_i2c_addr = <0xc0>; - * fe0_ts = <1>; - * fe0_reset_value = <0>; - * fe0_reset_gpio = <&gpio GPIOZ_1 GPIO_ACTIVE_HIGH>; - * - * ts1 = "parallel"; - * ts1_control = <0>; - * ts1_invert = <0>; - * interrupts = <0 23 1 - * 0 5 1 - * 0 21 1 - * 0 19 1 - * 0 25 1 - * 0 18 1 - * 0 24 1>; - * interrupt-names = "demux0_irq", - * "demux1_irq", - * "demux2_irq", - * "dvr0_irq", - * "dvr1_irq", - * "dvrfill0_fill", - * "dvrfill1_flush"; - * pinctrl-names = "p_ts1"; - * pinctrl-0 = <&dvb_p_ts1_pins>; - * clocks = <&clkc CLKID_DEMUX - * &clkc CLKID_AHB_ARB0 - * &clkc CLKID_DOS_PARSER>; - * clock-names = "demux", "ahbarb0", "parser_top"; - *}; - */ + dvb { + compatible = "amlogic, dvb"; + dev_name = "dvb"; + status = "ok"; + + ts0 = "serial"; + ts0_control = <0x800>; + ts0_invert = <0>; + pinctrl-names = "s_ts0"; + pinctrl-0 = <&dvb_s_ts0_pins>; + + interrupts = <0 23 1 + 0 5 1 + 0 53 1 + 0 19 1 + 0 25 1 + 0 18 1 + 0 24 1>; + interrupt-names = "demux0_irq", + "demux1_irq", + "demux2_irq", + "dvr0_irq", + "dvr1_irq", + "dvrfill0_fill", + "dvrfill1_flush"; + }; + dvbfe { + compatible = "amlogic, dvbfe"; + dev_name = "dvbfe"; + dtv_demod0 = "Avl6762"; + dtv_demod0_i2c_adap = <&i2c3>; + dtv_demod0_i2c_addr = <0x14>; + dtv_demod0_reset_value = <0>; + dtv_demod0_reset_gpio = <&gpio GPIOZ_10 GPIO_ACTIVE_HIGH>; + dtv_demod0_ant_poweron_value = <0>; + dtv_demod0_ant_power_gpio = <&gpio GPIOH_5 GPIO_ACTIVE_HIGH>; + dtv_demod0_tuner_type = <52>; + fe0_dtv_demod = <0>; + fe0_ts = <0>; + fe0_dev = <0>; + }; unifykey{ compatible = "amlogic, unifykey"; status = "ok"; @@ -826,7 +842,7 @@ */ &i2c3 { - status = "disabled"; + status = "okay"; pinctrl-names="default"; pinctrl-0=<&i2c3_master_pins2>; clock-frequency = <100000>; /* default 100k */ @@ -878,8 +894,10 @@ dai-tdm-clk-sel = <1>; clocks = <&clkaudio CLKID_AUDIO_MCLK_B &clkc CLKID_MPLL1 - &clkc CLKID_MPLL0>; - clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; /* @@ -937,8 +955,10 @@ ; interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; pinctrl-0 = <&spdifout>; + pinctrl-1 = <&spdifout_a_mute>; status = "okay"; }; aml_spdif_b: spdif_b { @@ -1131,6 +1151,13 @@ }; }; + spdifout_a_mute: spdifout_a_mute { + mux { /* GPIOH_4 */ + groups = "GPIOH_4"; + function = "gpio_periphs"; + }; + }; + pdmin: pdmin { mux { /* gpioa_5, gpioa_6, gpioa_7, gpioa_8, gpioa_9*/ groups = "pdm_din0_a", @@ -1376,3 +1403,14 @@ &saradc { status = "disabled"; }; +&pinctrl_aobus { + dvb_s_ts0_pins: dvb_s_ts0_pins { + tsin_a { + groups = "tsin_a_sop_ao", + "tsin_a_valid_ao", + "tsin_a_clk_ao", + "tsin_a_din0_ao"; + function = "tsin_a_ao"; + }; + }; +}; diff --git a/arch/arm/boot/dts/amlogic/g12a_s905x2_u212_buildroot.dts b/arch/arm/boot/dts/amlogic/g12a_s905x2_u212_buildroot.dts index f3fd8d376006..0baccdddc62e 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905x2_u212_buildroot.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905x2_u212_buildroot.dts @@ -18,6 +18,7 @@ /dts-v1/; #include "mesong12a.dtsi" +#include "mesong12a_drm.dtsi" / { model = "Amlogic"; @@ -43,7 +44,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x100000 0x7ff00000>; + linux,usable-memory = <0x0 0x80000000>; }; reserved-memory { @@ -167,8 +168,6 @@ label="sys_led"; gpios=<&gpio_ao GPIOAO_11 GPIO_ACTIVE_LOW>; default-state ="on"; - retain-state-suspended; - linux,default-trigger="cpu0"; }; }; @@ -236,6 +235,14 @@ }; }; + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + codec_mm { compatible = "amlogic, codec, mm"; memory-region = <&codec_mm_cma &codec_mm_reserved>; @@ -243,6 +250,13 @@ status = "okay"; }; + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + ppmgr { compatible = "amlogic, ppmgr"; memory-region = <&ppmgr_reserved>; @@ -883,8 +897,10 @@ dai-tdm-clk-sel = <1>; clocks = <&clkaudio CLKID_AUDIO_MCLK_B &clkc CLKID_MPLL1 - &clkc CLKID_MPLL0>; - clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; /* @@ -928,8 +944,10 @@ ; interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; pinctrl-0 = <&spdifout>; + pinctrl-1 = <&spdifout_a_mute>; status = "okay"; }; aml_spdif_b: spdif_b { @@ -1122,6 +1140,13 @@ }; }; + spdifout_a_mute: spdifout_a_mute { + mux { /* GPIOH_4 */ + groups = "GPIOH_4"; + function = "gpio_periphs"; + }; + }; + pdmin: pdmin { mux { /* gpioa_5, gpioa_6, gpioa_7, gpioa_8, gpioa_9*/ groups = "pdm_din0_a", diff --git a/arch/arm/boot/dts/amlogic/g12a_s905x2_u212_drm_buildroot.dts b/arch/arm/boot/dts/amlogic/g12a_s905x2_u212_drm_buildroot.dts new file mode 100644 index 000000000000..730acc80d9fa --- /dev/null +++ b/arch/arm/boot/dts/amlogic/g12a_s905x2_u212_drm_buildroot.dts @@ -0,0 +1,1398 @@ +/* + * arch/arm/boot/dts/amlogic/g12a_s905x2_u212_buildroot.dts + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +/dts-v1/; + +#include "mesong12a.dtsi" +#include "mesong12a_drm.dtsi" + +/ { + model = "Amlogic"; + compatible = "amlogic, g12a"; + interrupt-parent = <&gic>; + #address-cells = <1>; + #size-cells = <1>; + + aliases { + serial0 = &uart_AO; + serial1 = &uart_A; + serial2 = &uart_B; + serial3 = &uart_C; + serial4 = &uart_AO_B; + tsensor0 = &p_tsensor; + tsensor1 = &d_tsensor; + i2c0 = &i2c0; + i2c1 = &i2c1; + i2c2 = &i2c2; + i2c3 = &i2c3; + i2c4 = &i2c_AO; + }; + + memory@00000000 { + device_type = "memory"; + linux,usable-memory = <0x0 0x80000000>; + }; + + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + /* global autoconfigured region for contiguous allocations */ + secmon_reserved:linux,secmon { + compatible = "shared-dma-pool"; + reusable; + size = <0x400000>; + alignment = <0x400000>; + alloc-ranges = <0x05000000 0x400000>; + }; + secos_reserved:linux,secos { + status = "disable"; + compatible = "amlogic, aml_secos_memory"; + reg = <0x05300000 0x2000000>; + no-map; + }; + logo_reserved:linux,meson-fb { + compatible = "shared-dma-pool"; + reusable; + size = <0x800000>; + alignment = <0x400000>; + alloc-ranges = <0x7f800000 0x800000>; + }; + ion_cma_reserved:linux,ion-dev { + compatible = "shared-dma-pool"; + reusable; + size = <0x8000000>; + alignment = <0x400000>; + }; + //di_reserved:linux,di { + //compatible = "amlogic, di-mem"; + /* buffer_size = 3621952(yuv422 8bit) */ + /* 4179008(yuv422 10bit full pack mode) */ + /** 10x3621952=34.6M(0x23) support 8bit **/ + /** 10x4736064=45.2M(0x2e) support 12bit **/ + /** 10x4179008=40M(0x28) support 10bit **/ + //size = <0x2800000>; + //no-map; + //}; + /*di CMA pool */ + di_cma_reserved:linux,di_cma { + compatible = "shared-dma-pool"; + reusable; + /* buffer_size = 3621952(yuv422 8bit) + * | 4736064(yuv422 10bit) + * | 4074560(yuv422 10bit full pack mode) + * 10x3621952=34.6M(0x23) support 8bit + * 10x4736064=45.2M(0x2e) support 12bit + * 10x4074560=40M(0x28) support 10bit + */ + size = <0x02800000>; + alignment = <0x400000>; + }; + /* POST PROCESS MANAGER */ + ppmgr_reserved:linux,ppmgr { + compatible = "shared-dma-pool"; + size = <0x0>; + }; + + codec_mm_cma:linux,codec_mm_cma { + compatible = "shared-dma-pool"; + reusable; + /* ion_codec_mm max can alloc size 80M*/ + size = <0x13400000>; + alignment = <0x400000>; + linux,contiguous-region; + }; + /* codec shared reserved */ + codec_mm_reserved:linux,codec_mm_reserved { + compatible = "amlogic, codec-mm-reserved"; + size = <0x0>; + alignment = <0x100000>; + //no-map; + }; + /* vdin0 CMA pool */ + vdin0_cma_reserved:linux,vdin0_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16+4 M */ + size = <0x04000000>; + alignment = <0x400000>; + }; + /* vdin1 CMA pool */ + vdin1_cma_reserved:linux,vdin1_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16 M */ + size = <0x04000000>; + alignment = <0x400000>; + }; + }; + + gpioleds { + compatible = "gpio-leds"; + status = "okay"; + + net_red { + label="net_red"; + gpios=<&gpio GPIOA_14 GPIO_ACTIVE_LOW>; + default-state ="on"; + }; + + net_green { + label="net_green"; + gpios=<&gpio GPIOA_15 GPIO_ACTIVE_HIGH>; + default-state ="on"; + }; + + remote_led { + label = "remote_led"; + gpios = <&gpio_ao GPIOAO_10 GPIO_ACTIVE_LOW>; + default-state = "off"; + linux,default-trigger = "rc_feedback"; + }; + + sys_led { + label="sys_led"; + gpios=<&gpio_ao GPIOAO_11 GPIO_ACTIVE_LOW>; + default-state ="on"; + }; + }; + + cvbsout { + compatible = "amlogic, cvbsout-g12a"; + dev_name = "cvbsout"; + status = "okay"; + clocks = <&clkc CLKID_VCLK2_ENCI + &clkc CLKID_VCLK2_VENCI0 + &clkc CLKID_VCLK2_VENCI1 + &clkc CLKID_DAC_CLK>; + clock-names = "venci_top_gate", + "venci_0_gate", + "venci_1_gate", + "vdac_clk_gate"; + clk_path = <0>; + + /* performance: reg_address, reg_value */ + /* g12a */ + performance = <0x1bf0 0x9 + 0x1b56 0x343 + 0x1b12 0x0 + 0x1b05 0x9 + 0x1c59 0xfc48 + 0xffff 0x0>; /* ending flag */ + performance_telecom = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x8080 + 0x1b05 0xfd + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + }; + + bt-dev{ + compatible = "amlogic, bt-dev"; + dev_name = "bt-dev"; + status = "okay"; + gpio_reset = <&gpio GPIOX_17 GPIO_ACTIVE_HIGH>; + gpio_hostwake = <&gpio GPIOX_19 GPIO_ACTIVE_HIGH>; + }; + + wifi{ + compatible = "amlogic, aml_wifi"; + dev_name = "aml_wifi"; + status = "okay"; + interrupt_pin = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; + irq_trigger_type = "GPIO_IRQ_LOW"; + power_on_pin = <&gpio GPIOX_6 GPIO_ACTIVE_HIGH>; + dhd_static_buf; //if use bcm wifi, config dhd_static_buf + pinctrl-names = "default"; + pinctrl-0 = <&pwm_e_pins>; + pwm_config = <&wifi_pwm_conf>; + }; + + wifi_pwm_conf:wifi_pwm_conf{ + pwm_channel1_conf { + pwms = <&pwm_ef MESON_PWM_0 30541 0>; + duty-cycle = <15270>; + times = <10>; + }; + pwm_channel2_conf { + pwms = <&pwm_ef MESON_PWM_2 30500 0>; + duty-cycle = <15250>; + times = <12>; + }; + }; + + codec_mm { + compatible = "amlogic, codec, mm"; + memory-region = <&codec_mm_cma &codec_mm_reserved>; + dev_name = "codec_mm"; + status = "okay"; + }; + + ppmgr { + compatible = "amlogic, ppmgr"; + memory-region = <&ppmgr_reserved>; + dev_name = "ppmgr"; + status = "okay"; + }; + + deinterlace { + compatible = "amlogic, deinterlace"; + status = "okay"; + /* 0:use reserved; 1:use cma; 2:use cma as reserved */ + flag_cma = <1>; + //memory-region = <&di_reserved>; + memory-region = <&di_cma_reserved>; + interrupts = <0 46 1 + 0 40 1>; + interrupt-names = "pre_irq", "post_irq"; + clocks = <&clkc CLKID_VPU_CLKB_TMP_COMP>, + <&clkc CLKID_VPU_CLKB_COMP>; + clock-names = "vpu_clkb_tmp_composite", + "vpu_clkb_composite"; + clock-range = <334 667>; + /* buffer-size = <3621952>;(yuv422 8bit) */ + buffer-size = <4074560>;/*yuv422 fullpack*/ + /* reserve-iomap = "true"; */ + /* if enable nr10bit, set nr10bit-support to 1 */ + post-wr-support = <1>; + nr10bit-support = <1>; + nrds-enable = <1>; + pps-enable = <1>; + }; + ionvideo { + compatible = "amlogic, ionvideo"; + dev_name = "ionvideo"; + status = "okay"; + }; + + + partitions: partitions{ + parts = <14>; + part-0 = <&logo>; + part-1 = <&recovery>; + part-2 = <&misc>; + part-3 = <&dto>; + part-4 = <&cri_data>; + part-5 = <¶m>; + part-6 = <&boot>; + part-7 = <&rsv>; + part-8 = <&tee>; + part-9 = <&vendor>; + part-10 = <&odm>; + part-11 = <&system>; + part-12 = <&cache>; + part-13 = <&data>; + + logo:logo{ + pname = "logo"; + size = <0x0 0x800000>; + mask = <1>; + }; + recovery:recovery{ + pname = "recovery"; + size = <0x0 0x1800000>; + mask = <1>; + }; + misc:misc{ + pname = "misc"; + size = <0x0 0x800000>; + mask = <1>; + }; + dto:dto{ + pname = "dto"; + size = <0x0 0x800000>; + mask = <1>; + }; + cri_data:cri_data{ + pname = "cri_data"; + size = <0x0 0x800000>; + mask = <2>; + }; + rsv:rsv{ + pname = "rsv"; + size = <0x0 0x1000000>; + mask = <1>; + }; + param:param{ + pname = "param"; + size = <0x0 0x1000000>; + mask = <2>; + }; + boot:boot{ + pname = "boot"; + size = <0x0 0x1000000>; + mask = <1>; + }; + tee:tee{ + pname = "tee"; + size = <0x0 0x2000000>; + mask = <1>; + }; + vendor:vendor{ + pname = "vendor"; + size = <0x0 0x10000000>; + mask = <1>; + }; + odm:odm{ + pname = "odm"; + size = <0x0 0x10000000>; + mask = <1>; + }; + system:system{ + pname = "system"; + size = <0x0 0x80000000>; + mask = <1>; + }; + cache:cache{ + pname = "cache"; + size = <0x0 0x46000000>; + mask = <2>; + }; + data:data{ + pname = "data"; + size = <0xffffffff 0xffffffff>; + mask = <4>; + }; + }; + unifykey{ + compatible = "amlogic, unifykey"; + status = "ok"; + unifykey-num = <16>; + unifykey-index-0 = <&keysn_0>; + unifykey-index-1 = <&keysn_1>; + unifykey-index-2 = <&keysn_2>; + unifykey-index-3 = <&keysn_3>; + unifykey-index-4 = <&keysn_4>; + unifykey-index-5 = <&keysn_5>; + unifykey-index-6 = <&keysn_6>; + unifykey-index-7 = <&keysn_7>; + unifykey-index-8 = <&keysn_8>; + unifykey-index-9 = <&keysn_9>; + unifykey-index-10= <&keysn_10>; + unifykey-index-11= <&keysn_11>; + unifykey-index-12= <&keysn_12>; + unifykey-index-13= <&keysn_13>; + unifykey-index-14= <&keysn_14>; + unifykey-index-15= <&keysn_15>; + + keysn_0: key_0{ + key-name = "usid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_1:key_1{ + key-name = "mac"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_2:key_2{ + key-name = "hdcp"; + key-device = "secure"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_3:key_3{ + key-name = "secure_boot_set"; + key-device = "efuse"; + key-permit = "write"; + }; + keysn_4:key_4{ + key-name = "mac_bt"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_5:key_5{ + key-name = "mac_wifi"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_6:key_6{ + key-name = "hdcp2_tx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_7:key_7{ + key-name = "hdcp2_rx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_8:key_8{ + key-name = "widevinekeybox"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_9:key_9{ + key-name = "deviceid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_10:key_10{ + key-name = "hdcp22_fw_private"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_11:key_11{ + key-name = "PlayReadykeybox25"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_12:key_12{ + key-name = "prpubkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_13:key_13{ + key-name = "prprivkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_14:key_14{ + key-name = "attestationkeybox";// attestation key + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_15:key_15{ + key-name = "netflix_mgkid"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + };//End unifykey + + efusekey:efusekey{ + keynum = <4>; + key0 = <&key_0>; + key1 = <&key_1>; + key2 = <&key_2>; + key3 = <&key_3>; + key_0:key_0{ + keyname = "mac"; + offset = <0>; + size = <6>; + }; + key_1:key_1{ + keyname = "mac_bt"; + offset = <6>; + size = <6>; + }; + key_2:key_2{ + keyname = "mac_wifi"; + offset = <12>; + size = <6>; + }; + key_3:key_3{ + keyname = "usid"; + offset = <18>; + size = <16>; + }; + };//End efusekey + + amlvecm { + compatible = "amlogic, vecm"; + dev_name = "aml_vecm"; + status = "okay"; + gamma_en = <0>;/*1:enabel ;0:disable*/ + wb_en = <0>;/*1:enabel ;0:disable*/ + cm_en = <0>;/*1:enabel ;0:disable*/ + /*0: 709/601 1: bt2020*/ + tx_op_color_primary = <0>; + }; + + amdolby_vision { + compatible = "amlogic, dolby_vision_g12a"; + dev_name = "aml_amdolby_vision_driver"; + status = "okay"; + tv_mode = <0>;/*1:enabel ;0:disable*/ + }; + + meson-fb { + compatible = "amlogic, meson-g12a"; + /*memory-region = <&logo_reserved>;*/ + dev_name = "meson-fb"; + status = "okay"; + interrupts = <0 3 1 + 0 56 1 + 0 89 1>; + interrupt-names = "viu-vsync", "viu2-vsync", "rdma"; + mem_size = <0x00800000 0x1980000 0x100000 0x100000 0x800000>; + /* uboot logo,fb0/fb1 memory size,if afbcd fb0=0x01851000*/ + display_mode_default = "1080p60hz"; + scale_mode = <1>; + /** 0:VPU free scale 1:OSD free scale 2:OSD super scale */ + display_size_default = <1920 1080 1920 2160 32>; + /*1920*1080*4*3 = 0x17BB000*/ + pxp_mode = <0>; /** 0:normal mode 1:pxp mode */ + mem_alloc = <1>; + logo_addr = "0x3f800000"; + clocks = <&clkc CLKID_VPU_CLKC_MUX>; + clock-names = "vpu_clkc"; + }; + + /* Audio Related start */ + pdm_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, pdm_dummy_codec"; + status = "okay"; + }; + dummy_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, aml_dummy_codec"; + status = "okay"; + }; + amlogic_codec:t9015{ + #sound-dai-cells = <0>; + compatible = "amlogic, aml_codec_T9015"; + reg = <0xFF632000 0x2000>; + is_auge_used = <1>; /* meson or auge chipset used */ + tdmout_index = <1>; + status = "okay"; + }; + audio_effect:eqdrc{ + /*eq_enable = <1>;*/ + /*drc_enable = <1>;*/ + /* + * 0:tdmout_a + * 1:tdmout_b + * 2:tdmout_c + * 3:spdifout + * 4:spdifout_b + */ + eqdrc_module = <1>; + /* max 0xf, each bit for one lane, usually one lane */ + lane_mask = <0x1>; + /* max 0xff, each bit for one channel */ + channel_mask = <0x3>; + }; + auge_sound { + compatible = "amlogic, g12a-sound-card"; + aml-audio-card,name = "AML-AUGESOUND"; + + aml-audio-card,loopback = <&aml_loopback>; + aml-audio-card,aux-devs = <&amlogic_codec>; + /*avout mute gpio*/ + avout_mute-gpios = <&gpio_ao GPIOAO_2 GPIO_ACTIVE_HIGH>; + /*for audio effect ,eqdrc */ + aml-audio-card,effect = <&audio_effect>; + + aml-audio-card,dai-link@0 { + format = "dsp_a"; + mclk-fs = <512>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + //bitclock-master = <&tdmacodec>; + //frame-master = <&tdmacodec>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-pcm"; + tdmacpu: cpu { + sound-dai = <&aml_tdma>; + dai-tdm-slot-tx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-rx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-num = <8>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <24576000>; + }; + tdmacodec: codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@1 { + format = "i2s";// "dsp_a"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + bitclock-master = <&aml_tdmb>; + frame-master = <&aml_tdmb>; + //bitclock-master = <&tdmbcodec>; + //frame-master = <&tdmbcodec>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-i2s"; + cpu { + sound-dai = <&aml_tdmb>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + /* + * dai-tdm-slot-tx-mask = + * <1 1 1 1 1 1 1 1>; + * dai-tdm-slot-rx-mask = + * <1 1 1 1 1 1 1 1>; + * dai-tdm-slot-num = <8>; + */ + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmbcodec: codec { + sound-dai = <&dummy_codec &dummy_codec + &amlogic_codec>; + }; + }; + + aml-audio-card,dai-link@2 { + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + bitclock-master = <&aml_tdmc>; + frame-master = <&aml_tdmc>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + //suffix-name = "alsaPORT-tdm"; + cpu { + sound-dai = <&aml_tdmc>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@3 { + mclk-fs = <64>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-pdm"; + cpu { + sound-dai = <&aml_pdm>; + }; + codec { + sound-dai = <&pdm_codec>; + }; + }; + + aml-audio-card,dai-link@4 { + mclk-fs = <128>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-spdif"; + cpu { + sound-dai = <&aml_spdif>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + /* spdif_b to hdmi, only playback */ + aml-audio-card,dai-link@5 { + mclk-fs = <128>; + continuous-clock; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-spdifb2hdmi"; + cpu { + sound-dai = <&aml_spdif_b>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + }; + audiolocker: locker { + compatible = "amlogic, audiolocker"; + clocks = <&clkaudio CLKID_AUDIO_LOCKER_OUT + &clkaudio CLKID_AUDIO_LOCKER_IN + &clkaudio CLKID_AUDIO_MCLK_D + &clkaudio CLKID_AUDIO_MCLK_E + &clkc CLKID_MPLL1 + &clkc CLKID_MPLL2>; + clock-names = "lock_out", "lock_in", "out_src", + "in_src", "out_calc", "in_ref"; + interrupts = ; + interrupt-names = "irq"; + frequency = <49000000>; /* pll */ + dividor = <49>; /* locker's parent */ + status = "okay"; + }; + /* Audio Related end */ + + /*DCDC for SY8120B1ABC*/ + cpu_opp_table0: cpu_opp_table0 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <731000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <731000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <731000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <731000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <731000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <731000>; + }; + opp06 { + opp-hz = /bits/ 64 <1398000000>; + opp-microvolt = <761000>; + }; + opp07 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <791000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <831000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <861000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <981000>; + }; + }; + + cpufreq-meson { + compatible = "amlogic, cpufreq-meson"; + pinctrl-names = "default"; + pinctrl-0 = <&pwm_ao_d_pins3>; + status = "okay"; + }; + +}; /* end of / */ + +&pwm_AO_cd { + status = "okay"; +}; + +&i2c0 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&i2c0_master_pins2>; + clock-frequency = <400000>; + + gt9xx@5d { + compatible = "goodix,gt9xx"; + status = "disabled"; + reg = <0x5d>; + reset-gpio = <&gpio GPIOZ_9 0x00>; + irq-gpio = <&gpio GPIOZ_3 0x00>; + }; + + ftxx@38 { + compatible = "focaltech,fts"; + status = "disabled"; + reg = <0x38>; + reset-gpio = <&gpio GPIOZ_9 0x00>; + irq-gpio = <&gpio GPIOZ_3 0x00>; + x_max = <600>; + y_max = <1024>; + max-touch-number = <10>; + }; +}; + +&i2c3 { + status = "disabled"; + pinctrl-names="default"; + pinctrl-0=<&i2c3_master_pins2>; + clock-frequency = <100000>; /* default 100k */ + + /* for ref board */ + ad82584f_62: ad82584f_62@62 { + compatible = "ESMT, ad82584f"; + #sound-dai-cells = <0>; + reg = <0x31>; + status = "disabled"; + reset_pin = <&gpio GPIOA_5 0>; + }; + + tas5707_36: tas5707_36@36 { + compatible = "ti,tas5707"; + #sound-dai-cells = <0>; + reg = <0x1b>; + status = "disabled"; + reset_pin = <&gpio GPIOA_5 0>; + }; + + bl_extern_i2c { + compatible = "amlogic, bl_extern_i2c"; + status = "disabled"; + reg = <0x2c>; /*reg_address for lp8556*/ + dev_name = "lp8556"; + }; +}; + +&audiobus { + aml_tdma: tdma { + compatible = "amlogic, g12a-snd-tdma"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 1>; + dai-tdm-oe-lane-slot-mask-out = <1 0>; + dai-tdm-clk-sel = <0>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_A + &clkc CLKID_MPLL0>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmout_a &tdmin_a>; + }; + + aml_tdmb: tdmb { + compatible = "amlogic, g12a-snd-tdmb"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 1 0 0>; + dai-tdm-lane-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <1>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_B + &clkc CLKID_MPLL1 + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; + /* + * 0: tdmout_a; + * 1: tdmout_b; + * 2: tdmout_c; + * 3: spdifout; + * 4: spdifout_b; + */ + samesource_sel = <3>; + }; + + aml_tdmc: tdmc { + compatible = "amlogic, g12a-snd-tdmc"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 1 0 0>; + #dai-tdm-lane-slot-mask-out = <1 0 1 1>; + #dai-tdm-lane-oe-slot-mask-in = <0 0 0 0>; + dai-tdm-lane-oe-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <2>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmc_mclk &tdmout_c &tdmin_c>; + }; + + + aml_spdif: spdif { + compatible = "amlogic, g12a-snd-spdif-a"; + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 + &clkc CLKID_FCLK_DIV4 + &clkaudio CLKID_AUDIO_SPDIFIN + &clkaudio CLKID_AUDIO_SPDIFOUT + &clkaudio CLKID_AUDIO_SPDIFIN_CTRL + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "sysclk", "fixed_clk", "gate_spdifin", + "gate_spdifout", "clk_spdifin", "clk_spdifout"; + interrupts = + ; + + interrupt-names = "irq_spdifin"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; + pinctrl-0 = <&spdifout>; + pinctrl-1 = <&spdifout_a_mute>; + status = "okay"; + }; + aml_spdif_b: spdif_b { + compatible = "amlogic, g12a-snd-spdif-b"; + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 /*CLKID_HIFI_PLL*/ + &clkaudio CLKID_AUDIO_SPDIFOUTB + &clkaudio CLKID_AUDIO_SPDIFOUTB_CTRL>; + clock-names = "sysclk", + "gate_spdifout", "clk_spdifout"; + status = "okay"; + }; + aml_pdm: pdm { + compatible = "amlogic, g12a-snd-pdm"; + #sound-dai-cells = <0>; + clocks = <&clkaudio CLKID_AUDIO_PDM + &clkc CLKID_FCLK_DIV3 + &clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_PDMIN0 + &clkaudio CLKID_AUDIO_PDMIN1>; + clock-names = "gate", + "sysclk_srcpll", + "dclk_srcpll", + "pdm_dclk", + "pdm_sysclk"; + pinctrl-names = "pdm_pins"; + pinctrl-0 = <&pdmin>; + filter_mode = <1>; /* mode 0~4, defalut:1 */ + status = "okay"; + }; + aml_loopback: loopback { + compatible = "amlogic, snd-loopback"; + /* + * 0: out rate = in data rate; + * 1: out rate = loopback data rate; + */ + lb_mode = <0>; + + /* datain src + * 0: tdmin_a; + * 1: tdmin_b; + * 2: tdmin_c; + * 3: spdifin; + * 4: pdmin; + */ + datain_src = <4>; + datain_chnum = <8>; + datain_chmask = <0x3f>; + + /* tdmin_lb src + * 0: tdmoutA + * 1: tdmoutB + * 2: tdmoutC + * 3: PAD_tdminA + * 4: PAD_tdminB + * 5: PAD_tdminC + */ + datalb_src = <2>; + datalb_chnum = <8>; + datalb_chmask = <0x3>; + + status = "okay"; + }; + + audioresample: resample { + compatible = "amlogic, g12a-resample"; + clocks = <&clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_MCLK_F + &clkaudio CLKID_AUDIO_RESAMPLE_CTRL>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + /*same with toddr_src + * TDMIN_A, 0 + * TDMIN_B, 1 + * TDMIN_C, 2 + * SPDIFIN, 3 + * PDMIN, 4 + * NONE, + * TDMIN_LB, 6 + * LOOPBACK, 7 + */ + resample_module = <4>; + status = "okay"; + }; + aml_pwrdet: pwrdet { + compatible = "amlogic, g12a-power-detect"; + + interrupts = ; + interrupt-names = "pwrdet_irq"; + + /* pwrdet source sel + * 7: loopback; + * 6: tdmin_lb; + * 5: reserved; + * 4: pdmin; + * 3: spdifin; + * 2: tdmin_c; + * 1: tdmin_b; + * 0: tdmin_a; + */ + pwrdet_src = <4>; + + hi_th = <0x70000>; + lo_th = <0x16000>; + + status = "okay"; + }; +}; /* end of audiobus */ + +&pinctrl_periphs { + tdmout_a: tdmout_a { + mux { /* GPIOX_11, GPIOX_10, GPIOX_9 */ + groups = "tdma_sclk", + "tdma_fs", + "tdma_dout0"; + function = "tdma_out"; + }; + }; + + tdmin_a: tdmin_a { + mux { /* GPIOX_8 */ + groups = "tdma_din1"; + function = "tdma_in"; + }; + }; + + tdmb_mclk: tdmb_mclk { + mux { + groups = "mclk0_a"; + function = "mclk0"; + drive-strength = <2>; + }; + }; + tdmout_b: tdmout_b { + mux { /* GPIOA_1, GPIOA_2, GPIOA_3 */ + groups = "tdmb_sclk", + "tdmb_fs", + "tdmb_dout0"; + function = "tdmb_out"; + drive-strength = <2>; + }; + }; + + tdmin_b:tdmin_b { + mux { /* GPIOA_4 */ + groups = "tdmb_din1" + /*,"tdmb_slv_sclk", "tdmb_slv_fs"*/; + function = "tdmb_in"; + drive-strength = <2>; + }; + }; + + tdmc_mclk: tdmc_mclk { + mux { /* GPIOA_11 */ + groups = "mclk1_a"; + function = "mclk1"; + }; + }; + + tdmout_c:tdmout_c { + mux { /* GPIOA_12, GPIOA_13, GPIOA_10, GPIOA_8, GPIOA_7*/ + groups = "tdmc_sclk_a", + "tdmc_fs_a", + "tdmc_dout0_a" + /*, "tdmc_dout2", + * "tdmc_dout3" + */; + function = "tdmc_out"; + }; + }; + + tdmin_c:tdmin_c { + mux { /* GPIOA_9 */ + groups = "tdmc_din1_a"; + function = "tdmc_in"; + }; + }; + + spdifin: spdifin { + mux {/* GPIOH_5 */ + groups = "spdif_in_h"; + function = "spdif_in"; + }; + }; + + /* GPIOH_4 */ + spdifout: spdifout { + mux { + groups = "spdif_out_h"; + function = "spdif_out"; + }; + }; + + spdifout_a_mute: spdifout_a_mute { + mux { /* GPIOH_4 */ + groups = "GPIOH_4"; + function = "gpio_periphs"; + }; + }; + + pdmin: pdmin { + mux { /* gpioa_5, gpioa_6, gpioa_7, gpioa_8, gpioa_9*/ + groups = "pdm_din0_a", + /*"pdm_din1_a",*/ + "pdm_din2_a", + /*"pdm_din3_a",*/ + "pdm_dclk_a"; + function = "pdm"; + }; + }; + + +}; /* end of pinctrl_periphs */ +&pinctrl_aobus { + /*gpiao_10*/ + /*spdifout: spdifout { */ + /* mux { */ + /* groups = "spdif_out_ao"; */ + /* function = "spdif_out_ao";*/ + /* }; */ + /*}; */ +}; /* end of pinctrl_aobus */ + +&audio_data { + status = "okay"; +}; + +/* Audio Related End */ + +&pwm_ef { + status = "okay"; +}; + +&dwc3 { + status = "okay"; +}; + +&usb2_phy_v2 { + status = "okay"; + portnum = <2>; +}; + +&usb3_phy_v2 { + status = "okay"; + portnum = <1>; + otg = <0>; +}; + +&dwc2_a { + status = "okay"; + /** 0: normal, 1: otg+dwc3 host only, 2: otg+dwc3 device only*/ + controller-type = <1>; +}; +ðmac { + status = "okay"; + pinctrl-names = "internal_eth_pins"; + pinctrl-0 = <&internal_eth_pins>; + mc_val = <0x4be04>; + + internal_phy=<1>; +}; + +&uart_A { + status = "okay"; +}; + +/*if you want to use vdin just modify status to "ok"*/ +&vdin0 { + memory-region = <&vdin0_cma_reserved>; + status = "okay"; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + *bit4:support yuv422 10bit full pack mode (from txl new add) + */ + tv_bit_mode = <0x15>; +}; +&vdin1 { + memory-region = <&vdin1_cma_reserved>; + status = "okay"; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + */ + tv_bit_mode = <1>; +}; + + +&sd_emmc_c { + status = "okay"; + emmc { + caps = "MMC_CAP_8_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + /* "MMC_CAP_1_8V_DDR", */ + "MMC_CAP_HW_RESET", + "MMC_CAP_ERASE", + "MMC_CAP_CMD23"; + caps2 = "MMC_CAP2_HS200"; + /* "MMC_CAP2_HS400";*/ + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&sd_emmc_b1 { + status = "disabled"; + sd { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED"; + f_min = <400000>; + f_max = <50000000>; + }; +}; + +&sd_emmc_b2 { + status = "disabled"; + sd { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED"; + f_min = <400000>; + f_max = <50000000>; + }; + + sdio { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + "MMC_CAP_UHS_SDR12", + "MMC_CAP_UHS_SDR25", + "MMC_CAP_UHS_SDR50", + "MMC_CAP_UHS_SDR104", + "MMC_PM_KEEP_POWER", + "MMC_CAP_SDIO_IRQ"; + + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&sd_emmc_a { + status = "disabled"; + sdio { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + "MMC_CAP_UHS_SDR12", + "MMC_CAP_UHS_SDR25", + "MMC_CAP_UHS_SDR50", + "MMC_CAP_UHS_SDR104", + "MMC_PM_KEEP_POWER", + "MMC_CAP_SDIO_IRQ"; + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&nand { + status = "disabled"; + plat-names = "bootloader","nandnormal"; + plat-num = <2>; + plat-part-0 = <&bootloader>; + plat-part-1 = <&nandnormal>; + bootloader: bootloader{ + enable_pad ="ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <1>; + part_num = <0>; + rb_detect = <1>; + }; + nandnormal: nandnormal{ + enable_pad ="ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + plane_mode = "twoplane"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <2>; + part_num = <3>; + partition = <&nand_partitions>; + rb_detect = <1>; + }; + nand_partitions:nand_partition{ + /* + * if bl_mode is 1, tpl size was generate by + * fip_copies * fip_size which + * will not skip bad when calculating + * the partition size; + * + * if bl_mode is 0, + * tpl partition must be comment out. + */ + tpl{ + offset=<0x0 0x0>; + size=<0x0 0x0>; + }; + logo{ + offset=<0x0 0x0>; + size=<0x0 0x200000>; + }; + recovery{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + boot{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + system{ + offset=<0x0 0x0>; + size=<0x0 0x4000000>; + }; + data{ + offset=<0xffffffff 0xffffffff>; + size=<0x0 0x0>; + }; + }; +}; + +&pcie_A { + reset-gpio = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; + status = "disable"; +}; + +&meson_cooldev { + status = "okay"; +}; + +&defendkey { + status = "okay"; +}; + +&meson_fb { + status = "disable"; +}; + +&drm_vpu { + status = "okay"; + compatible = "amlogic,meson-g12b-vpu"; + logo_addr = "0x7f800000"; +}; + +&drm_amhdmitx { + status = "okay"; + hdcp = "disabled"; +}; + +&drm_lcd { + status = "disable"; +}; diff --git a/arch/arm/boot/dts/amlogic/g12a_s905y2_u220.dts b/arch/arm/boot/dts/amlogic/g12a_s905y2_u220.dts index a734db686b5f..631b434a2a04 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905y2_u220.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905y2_u220.dts @@ -44,7 +44,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x100000 0x7ff00000>; + linux,usable-memory = <0x0 0x80000000>; }; reserved-memory { @@ -57,8 +57,7 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { @@ -220,6 +219,14 @@ }; }; + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + codec_mm { compatible = "amlogic, codec, mm"; memory-region = <&codec_mm_cma &codec_mm_reserved>; @@ -227,6 +234,13 @@ status = "okay"; }; + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + ppmgr { compatible = "amlogic, ppmgr"; memory-region = <&ppmgr_reserved>; @@ -823,8 +837,10 @@ dai-tdm-clk-sel = <1>; clocks = <&clkaudio CLKID_AUDIO_MCLK_B &clkc CLKID_MPLL1 - &clkc CLKID_MPLL0>; - clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; /* @@ -882,8 +898,10 @@ ; interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; pinctrl-0 = <&spdifout &spdifin>; + pinctrl-1 = <&spdifout_a_mute>; status = "okay"; }; aml_spdif_b: spdif_b { @@ -1098,6 +1116,13 @@ function = "spdif_out_ao"; }; }; + + spdifout_a_mute: spdifout_a_mute { + mux { /* gpiao_10 */ + groups = "GPIOAO_10"; + function = "gpio_aobus"; + }; + }; }; /* end of pinctrl_aobus */ &audio_data { diff --git a/arch/arm/boot/dts/amlogic/g12a_s905y2_u221.dts b/arch/arm/boot/dts/amlogic/g12a_s905y2_u221.dts index caadd28dbe5d..b78771e6d19d 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905y2_u221.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905y2_u221.dts @@ -44,7 +44,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x000000 0x80000000>; + linux,usable-memory = <0x100000 0x7ff00000>; }; reserved-memory { @@ -212,6 +212,14 @@ }; }; + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + codec_mm { compatible = "amlogic, codec, mm"; memory-region = <&codec_mm_cma &codec_mm_reserved>; @@ -219,6 +227,13 @@ status = "okay"; }; + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + ppmgr { compatible = "amlogic, ppmgr"; memory-region = <&ppmgr_reserved>; @@ -669,18 +684,20 @@ opp-hz = /bits/ 64 <1512000000>; opp-microvolt = <831000>; }; - opp08 { - opp-hz = /bits/ 64 <1608000000>; - opp-microvolt = <871000>; - }; - opp09 { - opp-hz = /bits/ 64 <1704000000>; - opp-microvolt = <921000>; - }; - opp10 { - opp-hz = /bits/ 64 <1800000000>; - opp-microvolt = <981000>; - }; +/* + * opp08 { + * opp-hz = /bits/ 64 <1608000000>; + * opp-microvolt = <871000>; + * }; + * opp09 { + * opp-hz = /bits/ 64 <1704000000>; + * opp-microvolt = <921000>; + * }; + * opp10 { + * opp-hz = /bits/ 64 <1800000000>; + * opp-microvolt = <981000>; + * }; + */ }; cpufreq-meson { @@ -784,8 +801,10 @@ dai-tdm-clk-sel = <1>; clocks = <&clkaudio CLKID_AUDIO_MCLK_B &clkc CLKID_MPLL1 - &clkc CLKID_MPLL0>; - clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; /* @@ -843,8 +862,10 @@ ; interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; pinctrl-0 = <&spdifout &spdifin>; + pinctrl-1 = <&spdifout_a_mute>; status = "okay"; }; aml_spdif_b: spdif_b { @@ -1059,6 +1080,13 @@ function = "spdif_out_ao"; }; }; + + spdifout_a_mute: spdifout_a_mute { + mux { /* gpiao_10 */ + groups = "GPIOAO_10"; + function = "gpio_aobus"; + }; + }; }; /* end of pinctrl_aobus */ &audio_data { @@ -1287,3 +1315,13 @@ status = "okay"; }; +&gpu{ + /*max gpu is 500MHz*/ + tbl = <&dvfs285_cfg + &dvfs400_cfg + &dvfs500_cfg>; +}; + +&amhdmitx { + dongle_mode = <1>; +}; diff --git a/arch/arm/boot/dts/amlogic/g12b-sched-energy-a.dtsi b/arch/arm/boot/dts/amlogic/g12b-sched-energy-a.dtsi new file mode 100644 index 000000000000..184be9d06b57 --- /dev/null +++ b/arch/arm/boot/dts/amlogic/g12b-sched-energy-a.dtsi @@ -0,0 +1,87 @@ + +/ { + energy-costs { + CPU_COST_A73: core-cost0 { + busy-cost-data = < + 54 17 + 135 110 + 270 202 + 360 264 + 540 396 + 648 470 + 755 557 + 816 620 + 868 699 + 920 759 + /*1024 1024*/ + >; + idle-cost-data = < + 5 + 0 + 0 + >; + }; + CPU_COST_A53: core-cost1 { + busy-cost-data = < + 33 4 + 83 23 + 166 41 + 221 54 + 332 78 + 399 92 + 465 116 + 503 135 + 535 162 + 567 184 + 599 224 + 631 279 + >; + idle-cost-data = < + 3 + 0 + 0 + >; + }; + CLUSTER_COST_A73: cluster-cost0 { + busy-cost-data = < + 54 17 + 135 20 + 270 25 + 360 27 + 540 35 + 648 40 + 755 49 + 816 57 + 868 54 + 920 64 + /*1024 79*/ + >; + idle-cost-data = < + 10 + 10 + 0 + >; + }; + CLUSTER_COST_A53: cluster-cost1 { + busy-cost-data = < + 33 7 + 83 8 + 166 9 + 221 10 + 332 13 + 399 15 + 465 19 + 503 23 + 535 26 + 567 31 + 599 36 + 631 42 + >; + idle-cost-data = < + 6 + 6 + 0 + >; + }; + }; +}; diff --git a/arch/arm/boot/dts/amlogic/g12b-sched-energy.dtsi b/arch/arm/boot/dts/amlogic/g12b-sched-energy.dtsi index 796f592ae9f7..9177949abde1 100644 --- a/arch/arm/boot/dts/amlogic/g12b-sched-energy.dtsi +++ b/arch/arm/boot/dts/amlogic/g12b-sched-energy.dtsi @@ -13,7 +13,11 @@ 816 620 868 699 920 759 - /*1024 1024*/ + 972 819 + 1030 887 + 1088 937 + 1134 976 + 1192 1048 >; idle-cost-data = < 5 @@ -33,6 +37,7 @@ 503 135 535 162 567 184 + 599 224 631 279 >; idle-cost-data = < @@ -53,7 +58,11 @@ 816 57 868 54 920 64 - /*1024 79*/ + 972 75 + 1030 86 + 1088 97 + 1134 108 + 1192 110 >; idle-cost-data = < 10 @@ -73,6 +82,7 @@ 503 23 535 26 567 31 + 599 36 631 42 >; idle-cost-data = < diff --git a/arch/arm/boot/dts/amlogic/g12b_a311d_skt.dts b/arch/arm/boot/dts/amlogic/g12b_a311d_skt.dts index d707eb07f111..69825190259d 100644 --- a/arch/arm/boot/dts/amlogic/g12b_a311d_skt.dts +++ b/arch/arm/boot/dts/amlogic/g12b_a311d_skt.dts @@ -23,6 +23,7 @@ / { model = "Amlogic"; + amlogic-dt-id = "g12b_skt_b"; compatible = "amlogic, g12b"; interrupt-parent = <&gic>; #address-cells = <1>; @@ -45,7 +46,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x100000 0x7ff00000>; + linux,usable-memory = <0x0 0x80000000>; }; reserved-memory { @@ -58,8 +59,7 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { @@ -483,11 +483,11 @@ }; amlogic_codec:t9015{ #sound-dai-cells = <0>; - /*compatible = "amlogic, aml_codec_T9015";*/ + compatible = "amlogic, aml_codec_T9015"; reg = <0xFF632000 0x2000>; is_auge_used = <1>; /* meson or auge chipset used */ tdmout_index = <1>; - status = "disabled"; + status = "okay"; }; audio_effect:eqdrc{ /*eq_enable = <1>;*/ @@ -567,7 +567,7 @@ }; tdmbcodec: codec { sound-dai = <&dummy_codec &dummy_codec - &dummy_codec &ad82584f_62>; + &amlogic_codec &ad82584f_62>; }; }; @@ -665,31 +665,31 @@ }; opp04 { opp-hz = /bits/ 64 <1000000000>; - opp-microvolt = <731000>; + opp-microvolt = <761000>; }; opp05 { opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <731000>; + opp-microvolt = <781000>; }; opp06 { opp-hz = /bits/ 64 <1398000000>; - opp-microvolt = <761000>; + opp-microvolt = <811000>; }; opp07 { opp-hz = /bits/ 64 <1512000000>; - opp-microvolt = <791000>; + opp-microvolt = <861000>; }; opp08 { opp-hz = /bits/ 64 <1608000000>; - opp-microvolt = <831000>; + opp-microvolt = <901000>; }; opp09 { opp-hz = /bits/ 64 <1704000000>; - opp-microvolt = <861000>; + opp-microvolt = <951000>; }; opp10 { opp-hz = /bits/ 64 <1800000000>; - opp-microvolt = <981000>; + opp-microvolt = <1001000>; }; }; @@ -699,43 +699,63 @@ opp00 { opp-hz = /bits/ 64 <100000000>; - opp-microvolt = <751000>; + opp-microvolt = <731000>; }; opp01 { opp-hz = /bits/ 64 <250000000>; - opp-microvolt = <751000>; + opp-microvolt = <731000>; }; opp02 { opp-hz = /bits/ 64 <500000000>; - opp-microvolt = <751000>; + opp-microvolt = <731000>; }; opp03 { opp-hz = /bits/ 64 <667000000>; - opp-microvolt = <751000>; + opp-microvolt = <731000>; }; opp04 { opp-hz = /bits/ 64 <1000000000>; - opp-microvolt = <771000>; + opp-microvolt = <731000>; }; opp05 { opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <771000>; + opp-microvolt = <751000>; }; opp06 { opp-hz = /bits/ 64 <1398000000>; - opp-microvolt = <791000>; + opp-microvolt = <771000>; }; opp07 { opp-hz = /bits/ 64 <1512000000>; - opp-microvolt = <821000>; + opp-microvolt = <771000>; }; opp08 { opp-hz = /bits/ 64 <1608000000>; - opp-microvolt = <861000>; + opp-microvolt = <781000>; }; opp09 { opp-hz = /bits/ 64 <1704000000>; - opp-microvolt = <891000>; + opp-microvolt = <791000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <831000>; + }; + opp11 { + opp-hz = /bits/ 64 <1908000000>; + opp-microvolt = <861000>; + }; + opp12 { + opp-hz = /bits/ 64 <2016000000>; + opp-microvolt = <911000>; + }; + opp13 { + opp-hz = /bits/ 64 <2100000000>; + opp-microvolt = <951000>; + }; + opp14 { + opp-hz = /bits/ 64 <2208000000>; + opp-microvolt = <1011000>; }; }; @@ -893,8 +913,10 @@ dai-tdm-clk-sel = <1>; clocks = <&clkaudio CLKID_AUDIO_MCLK_B &clkc CLKID_MPLL1 - &clkc CLKID_MPLL0>; - clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; /* @@ -904,7 +926,7 @@ * 3: spdifout; * 4: spdifout_b; */ - samesource_sel = <4>; + /*samesource_sel = <4>; */ }; aml_tdmc: tdmc { @@ -952,8 +974,10 @@ ; interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; pinctrl-0 = <&spdifout &spdifin>; + pinctrl-1 = <&spdifout_a_mute>; status = "okay"; }; aml_spdif_b: spdif_b { @@ -1184,6 +1208,13 @@ function = "spdif_out_ao"; }; }; + + spdifout_a_mute: spdifout_a_mute { + mux { /* gpiao_10 */ + groups = "GPIOAO_10"; + function = "gpio_aobus"; + }; + }; }; /* end of pinctrl_aobus */ &irblaster { diff --git a/arch/arm/boot/dts/amlogic/g12b_a311d_skt_a.dts b/arch/arm/boot/dts/amlogic/g12b_a311d_skt_a.dts new file mode 100644 index 000000000000..d6044c90d6b5 --- /dev/null +++ b/arch/arm/boot/dts/amlogic/g12b_a311d_skt_a.dts @@ -0,0 +1,1397 @@ +/* + * arch/arm/boot/dts/amlogic/g12b_a311d_skt_a.dts + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +/dts-v1/; + +#include "partition_mbox_normal.dtsi" +#include "mesong12b_a.dtsi" +#include "mesong12b_skt-panel.dtsi" + +/ { + model = "Amlogic"; + amlogic-dt-id = "g12b_skt_a"; + compatible = "amlogic, g12b"; + interrupt-parent = <&gic>; + #address-cells = <1>; + #size-cells = <1>; + + aliases { + serial0 = &uart_AO; + serial1 = &uart_A; + serial2 = &uart_B; + serial3 = &uart_C; + serial4 = &uart_AO_B; + i2c0 = &i2c0; + i2c1 = &i2c1; + i2c2 = &i2c2; + i2c3 = &i2c3; + i2c4 = &i2c_AO; + tsensor0 = &p_tsensor; + tsensor1 = &d_tsensor; + }; + + memory@00000000 { + device_type = "memory"; + linux,usable-memory = <0x100000 0x7ff00000>; + }; + + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + /* global autoconfigured region for contiguous allocations */ + ramoops@0x07400000 { + compatible = "ramoops"; + reg = <0x07400000 0x00100000>; + record-size = <0x8000>; + console-size = <0x8000>; + ftrace-size = <0x20000>; + }; + + secmon_reserved:linux,secmon { + compatible = "shared-dma-pool"; + reusable; + size = <0x400000>; + alignment = <0x400000>; + alloc-ranges = <0x05000000 0x400000>; + clear-map; + }; + + secos_reserved:linux,secos { + status = "disable"; + compatible = "amlogic, aml_secos_memory"; + reg = <0x05300000 0x2000000>; + no-map; + }; + logo_reserved:linux,meson-fb { + compatible = "shared-dma-pool"; + reusable; + size = <0x800000>; + alignment = <0x400000>; + alloc-ranges = <0x7f800000 0x800000>; + }; + ion_cma_reserved:linux,ion-dev { + compatible = "shared-dma-pool"; + reusable; + size = <0x8000000>; + alignment = <0x400000>; + }; + + //di_reserved:linux,di { + //compatible = "amlogic, di-mem"; + /* buffer_size = 3621952(yuv422 8bit) */ + /* 4179008(yuv422 10bit full pack mode) */ + /** 10x3621952=34.6M(0x23) support 8bit **/ + /** 10x4736064=45.2M(0x2e) support 12bit **/ + /** 10x4179008=40M(0x28) support 10bit **/ + //size = <0x2800000>; + //no-map; + //}; + /*di CMA pool */ + di_cma_reserved:linux,di_cma { + compatible = "shared-dma-pool"; + reusable; + /* buffer_size = 3621952(yuv422 8bit) + * | 4736064(yuv422 10bit) + * | 4074560(yuv422 10bit full pack mode) + * 10x3621952=34.6M(0x23) support 8bit + * 10x4736064=45.2M(0x2e) support 12bit + * 10x4074560=40M(0x28) support 10bit + */ + size = <0x02800000>; + alignment = <0x400000>; + }; + /* POST PROCESS MANAGER */ + ppmgr_reserved:linux,ppmgr { + compatible = "shared-dma-pool"; + size = <0x0>; + }; + codec_mm_cma:linux,codec_mm_cma { + compatible = "shared-dma-pool"; + reusable; + /* ion_codec_mm max can alloc size 80M*/ + size = <0x13400000>; + alignment = <0x400000>; + linux,contiguous-region; + }; + /* codec shared reserved */ + codec_mm_reserved:linux,codec_mm_reserved { + compatible = "amlogic, codec-mm-reserved"; + size = <0x0>; + alignment = <0x100000>; + //no-map; + }; + /* vdin0 CMA pool */ + vdin0_cma_reserved:linux,vdin0_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16+4 M */ + size = <0x04000000>; + alignment = <0x400000>; + }; + /* vdin1 CMA pool */ + vdin1_cma_reserved:linux,vdin1_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16 M */ + size = <0x04000000>; + alignment = <0x400000>; + }; + galcore_reserved:linux,galcore { + compatible = "shared-dma-pool"; + reusable; + size = <0x1000000>; + alignment = <0x400000>; + linux,contiguous-region; + }; + + isp_cma_reserved:linux,isp_cma { + compatible = "shared-dma-pool"; + reusable; + status = "okay"; + size = <0x1f000000>; + alignment = <0x400000>; + }; + + adapt_cma_reserved:linux,adapt_cma { + compatible = "shared-dma-pool"; + reusable; + status = "okay"; + size = <0x03000000>; + alignment = <0x400000>; + }; + gdc_cma_reserved:linux,gdc_cma { + compatible = "shared-dma-pool"; + reusable; + status = "okay"; + size = <0x04000000>; + alignment = <0x400000>; + }; + }; + galcore { + status = "okay"; + memory-region = <&galcore_reserved>; + }; + cvbsout { + compatible = "amlogic, cvbsout-g12b"; + dev_name = "cvbsout"; + status = "okay"; + clocks = <&clkc CLKID_VCLK2_ENCI + &clkc CLKID_VCLK2_VENCI0 + &clkc CLKID_VCLK2_VENCI1 + &clkc CLKID_DAC_CLK>; + clock-names = "venci_top_gate", + "venci_0_gate", + "venci_1_gate", + "vdac_clk_gate"; + clk_path = <0>; + + /* performance: reg_address, reg_value */ + /* g12b */ + performance = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x8080 + 0x1b05 0xfd + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + performance_sarft = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x0 + 0x1b05 0x9 + 0x1c59 0xfc48 + 0xffff 0x0>; /* ending flag */ + }; + + bt-dev{ + compatible = "amlogic, bt-dev"; + dev_name = "bt-dev"; + status = "okay"; + gpio_reset = <&gpio GPIOX_17 GPIO_ACTIVE_HIGH>; + gpio_hostwake = <&gpio GPIOX_19 GPIO_ACTIVE_HIGH>; + }; + + wifi{ + compatible = "amlogic, aml_wifi"; + dev_name = "aml_wifi"; + status = "okay"; + interrupt_pin = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; + irq_trigger_type = "GPIO_IRQ_LOW"; + power_on_pin = <&gpio GPIOX_6 GPIO_ACTIVE_HIGH>; + dhd_static_buf; //if use bcm wifi, config dhd_static_buf + pinctrl-names = "default"; + pinctrl-0 = <&pwm_e_pins>; + pwm_config = <&wifi_pwm_conf>; + }; + + wifi_pwm_conf:wifi_pwm_conf{ + pwm_channel1_conf { + pwms = <&pwm_ef MESON_PWM_0 30541 0>; + duty-cycle = <15270>; + times = <10>; + }; + pwm_channel2_conf { + pwms = <&pwm_ef MESON_PWM_2 30500 0>; + duty-cycle = <15250>; + times = <12>; + }; + }; + + codec_mm { + compatible = "amlogic, codec, mm"; + memory-region = <&codec_mm_cma &codec_mm_reserved>; + dev_name = "codec_mm"; + status = "okay"; + }; + + ppmgr { + compatible = "amlogic, ppmgr"; + memory-region = <&ppmgr_reserved>; + dev_name = "ppmgr"; + status = "okay"; + }; + + deinterlace { + compatible = "amlogic, deinterlace"; + status = "okay"; + /* 0:use reserved; 1:use cma; 2:use cma as reserved */ + flag_cma = <1>; + //memory-region = <&di_reserved>; + memory-region = <&di_cma_reserved>; + interrupts = <0 46 1 + 0 40 1>; + interrupt-names = "pre_irq", "post_irq"; + clocks = <&clkc CLKID_VPU_CLKB_TMP_COMP>, + <&clkc CLKID_VPU_CLKB_COMP>; + clock-names = "vpu_clkb_tmp_composite", + "vpu_clkb_composite"; + clock-range = <334 667>; + /* buffer-size = <3621952>;(yuv422 8bit) */ + buffer-size = <4074560>;/*yuv422 fullpack*/ + /* reserve-iomap = "true"; */ + /* if enable nr10bit, set nr10bit-support to 1 */ + post-wr-support = <1>; + nr10bit-support = <1>; + nrds-enable = <1>; + pps-enable = <1>; + }; + ionvideo { + compatible = "amlogic, ionvideo"; + dev_name = "ionvideo"; + status = "okay"; + }; + + gpio_keypad { + compatible = "amlogic, gpio_keypad"; + status = "okay"; + scan_period = <20>; + key_num = <1>; + key_name = "power"; + key_code = <116>; + key-gpios = <&gpio_ao GPIOAO_3 GPIO_ACTIVE_HIGH>; + detect_mode = <0>;/*0:polling mode, 1:irq mode*/ + }; + + adc_keypad { + compatible = "amlogic, adc_keypad"; + status = "okay"; + key_name = "menu", "vol-", "vol+", "esc", "home"; + key_num = <5>; + io-channels = <&saradc SARADC_CH2>; + io-channel-names = "key-chan-2"; + key_chan = ; + key_code = <139 114 115 1 102>; + key_val = <0 143 266 389 512>; //val=voltage/1800mV*1023 + key_tolerance = <40 40 40 40 40>; + }; + + unifykey{ + compatible = "amlogic, unifykey"; + status = "ok"; + unifykey-num = <16>; + unifykey-index-0 = <&keysn_0>; + unifykey-index-1 = <&keysn_1>; + unifykey-index-2 = <&keysn_2>; + unifykey-index-3 = <&keysn_3>; + unifykey-index-4 = <&keysn_4>; + unifykey-index-5 = <&keysn_5>; + unifykey-index-6 = <&keysn_6>; + unifykey-index-7 = <&keysn_7>; + unifykey-index-8 = <&keysn_8>; + unifykey-index-9 = <&keysn_9>; + unifykey-index-10= <&keysn_10>; + unifykey-index-11= <&keysn_11>; + unifykey-index-12= <&keysn_12>; + unifykey-index-13= <&keysn_13>; + unifykey-index-14= <&keysn_14>; + unifykey-index-15= <&keysn_15>; + + + keysn_0: key_0{ + key-name = "usid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_1:key_1{ + key-name = "mac"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_2:key_2{ + key-name = "hdcp"; + key-device = "secure"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_3:key_3{ + key-name = "secure_boot_set"; + key-device = "efuse"; + key-permit = "write"; + }; + keysn_4:key_4{ + key-name = "mac_bt"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_5:key_5{ + key-name = "mac_wifi"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_6:key_6{ + key-name = "hdcp2_tx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_7:key_7{ + key-name = "hdcp2_rx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_8:key_8{ + key-name = "widevinekeybox"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_9:key_9{ + key-name = "deviceid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_10:key_10{ + key-name = "hdcp22_fw_private"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_11:key_11{ + key-name = "PlayReadykeybox25"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_12:key_12{ + key-name = "prpubkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_13:key_13{ + key-name = "prprivkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_14:key_14{ + key-name = "attestationkeybox";// attestation key + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_15:key_15{ + key-name = "netflix_mgkid"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + };//End unifykey + + efusekey:efusekey{ + keynum = <4>; + key0 = <&key_0>; + key1 = <&key_1>; + key2 = <&key_2>; + key3 = <&key_3>; + key_0:key_0{ + keyname = "mac"; + offset = <0>; + size = <6>; + }; + key_1:key_1{ + keyname = "mac_bt"; + offset = <6>; + size = <6>; + }; + key_2:key_2{ + keyname = "mac_wifi"; + offset = <12>; + size = <6>; + }; + key_3:key_3{ + keyname = "usid"; + offset = <18>; + size = <16>; + }; + };//End efusekey + + + amlvecm { + compatible = "amlogic, vecm"; + dev_name = "aml_vecm"; + status = "okay"; + gamma_en = <0>;/*1:enabel ;0:disable*/ + wb_en = <0>;/*1:enabel ;0:disable*/ + cm_en = <0>;/*1:enabel ;0:disable*/ + }; + amdolby_vision { + compatible = "amlogic, dolby_vision_g12a"; + dev_name = "aml_amdolby_vision_driver"; + status = "okay"; + tv_mode = <0>;/*1:enabel ;0:disable*/ + }; + + /* Audio Related start */ + pdm_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, pdm_dummy_codec"; + status = "okay"; + }; + dummy_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, aml_dummy_codec"; + status = "okay"; + }; + amlogic_codec:t9015{ + #sound-dai-cells = <0>; + /*compatible = "amlogic, aml_codec_T9015";*/ + reg = <0xFF632000 0x2000>; + is_auge_used = <1>; /* meson or auge chipset used */ + tdmout_index = <1>; + status = "disabled"; + }; + audio_effect:eqdrc{ + /*eq_enable = <1>;*/ + /*drc_enable = <1>;*/ + /* + * 0:tdmout_a + * 1:tdmout_b + * 2:tdmout_c + * 3:spdifout + * 4:spdifout_b + */ + eqdrc_module = <1>; + /* max 0xf, each bit for one lane, usually one lane */ + lane_mask = <0x1>; + /* max 0xff, each bit for one channel */ + channel_mask = <0x3>; + }; + auge_sound { + compatible = "amlogic, g12a-sound-card"; + aml-audio-card,name = "AML-AUGESOUND"; + + //aml-audio-card,loopback = <&aml_loopback>; + //aml-audio-card,aux-devs = <&amlogic_codec>; + /*avout mute gpio*/ + avout_mute-gpios = <&gpio_ao GPIOAO_2 GPIO_ACTIVE_HIGH>; + /*for audio effect ,eqdrc */ + aml-audio-card,effect = <&audio_effect>; + + aml-audio-card,dai-link@0 { + format = "dsp_a"; + mclk-fs = <512>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + //bitclock-master = <&tdmacodec>; + //frame-master = <&tdmacodec>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-pcm"; + tdmacpu: cpu { + sound-dai = <&aml_tdma>; + dai-tdm-slot-tx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-rx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-num = <8>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <24576000>; + }; + tdmacodec: codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@1 { + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + bitclock-master = <&aml_tdmb>; + frame-master = <&aml_tdmb>; + //bitclock-master = <&tdmbcodec>; + //frame-master = <&tdmbcodec>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-i2s"; + cpu { + sound-dai = <&aml_tdmb>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmbcodec: codec { + sound-dai = <&dummy_codec &dummy_codec + &dummy_codec &ad82584f_62>; + }; + }; + + aml-audio-card,dai-link@2 { + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + bitclock-master = <&aml_tdmc>; + frame-master = <&aml_tdmc>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + //suffix-name = "alsaPORT-tdm"; + cpu { + sound-dai = <&aml_tdmc>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@3 { + mclk-fs = <64>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-pdm"; + cpu { + sound-dai = <&aml_pdm>; + }; + codec { + sound-dai = <&pdm_codec>; + }; + }; + + aml-audio-card,dai-link@4 { + mclk-fs = <128>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-spdif"; + cpu { + sound-dai = <&aml_spdif>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + }; + audiolocker: locker { + compatible = "amlogic, audiolocker"; + clocks = <&clkaudio CLKID_AUDIO_LOCKER_OUT + &clkaudio CLKID_AUDIO_LOCKER_IN + &clkaudio CLKID_AUDIO_MCLK_D + &clkaudio CLKID_AUDIO_MCLK_E + &clkc CLKID_MPLL1 + &clkc CLKID_MPLL2>; + clock-names = "lock_out", "lock_in", "out_src", + "in_src", "out_calc", "in_ref"; + interrupts = ; + interrupt-names = "irq"; + frequency = <49000000>; /* pll */ + dividor = <49>; /* locker's parent */ + status = "okay"; + }; + /* Audio Related end */ + + cpu_opp_table0: cpu_opp_table0 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <731000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <731000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <731000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <731000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <731000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <731000>; + }; + opp06 { + opp-hz = /bits/ 64 <1398000000>; + opp-microvolt = <761000>; + }; + opp07 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <791000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <831000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <861000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <981000>; + }; + }; + + cpu_opp_table1: cpu_opp_table1 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <751000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <751000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <751000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <751000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <771000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <771000>; + }; + opp06 { + opp-hz = /bits/ 64 <1398000000>; + opp-microvolt = <791000>; + }; + opp07 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <821000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <861000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <891000>; + }; + }; + + cpufreq-meson { + compatible = "amlogic, cpufreq-meson"; + status = "okay"; + }; + + sensor: sensor { + compatible = "soc, sensor"; + status = "okay"; + sensor-name = "imx290"; /*imx290;os08a10;imx227*/ + pinctrl-names="default"; + pinctrl-0=<&clk12_24_z_pins>; + clocks = <&clkc CLKID_24M>; + clock-names = "g12a_24m"; + reset = <&gpio GPIOZ_12 GPIO_ACTIVE_HIGH>; + ir_cut_gpio = <&gpio GPIOZ_11 GPIO_ACTIVE_HIGH + &gpio GPIOZ_7 GPIO_ACTIVE_HIGH>; + }; + + iq: iq { + compatible = "soc, iq"; + status = "okay"; + sensor-name = "imx290"; /*imx290;os08a10;imx227*/ + }; +}; /* end of / */ +&i2c2 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&i2c2_master_pins2>; + clock-frequency = <100000>; /* default 100k */ + sensor-i2c@6c { + compatible = "arm, i2c-sensor"; + reg = <0x6c>; + reg-names = "i2c-sensor"; + slave-addr = <0x6c>; + reg-type = <2>; + reg-data-type = <1>; + link-device = <&phycsi>; + }; + + lcd_extern_i2c0: lcd_extern_i2c@0 { + compatible = "lcd_ext, i2c"; + dev_name = "i2c_LT8912_0"; + reg = <0x48>; + status = "disabled"; + }; + + lcd_extern_i2c1: lcd_extern_i2c@1 { + compatible = "lcd_ext, i2c"; + dev_name = "i2c_LT8912_1"; + reg = <0x49>; + status = "disabled"; + }; +}; + +&isp { + status = "okay"; + memory-region = <&isp_cma_reserved>; +}; + +&adapter { + status = "okay"; + memory-region = <&adapt_cma_reserved>; +}; + +&gdc { + status = "okay"; + memory-region = <&gdc_cma_reserved>; +}; + +&meson_fb { + status = "okay"; + display_size_default = <1920 1080 1920 2160 32>; + mem_size = <0x00800000 0x1980000 0x100000 0x100000 0x800000>; + logo_addr = "0x7f800000"; + mem_alloc = <1>; + pxp_mode = <0>; /** 0:normal mode 1:pxp mode */ +}; + +&pwm_ab { + status = "okay"; + }; + +&pwm_ef { + status = "okay"; + }; + +&pwm_AO_cd { + status = "okay"; + }; + +&i2c0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_master_pins2>; + clock-frequency = <400000>; + + touchscreen@38 { + compatible = "focaltech,fts"; + status = "disabled"; + reg = <0x38>; + reset-gpio = <&gpio GPIOZ_9 GPIO_ACTIVE_HIGH>; + irq-gpio = <&gpio GPIOZ_3 GPIO_ACTIVE_HIGH>; + x_max = <720>; + y_max = <1280>; + max-touch-number = <10>; + }; +}; + +&i2c3 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&i2c3_master_pins2>; + clock-frequency = <100000>; /* default 100k */ + + /* for ref board */ + ad82584f_62: ad82584f_62@62 { + compatible = "ESMT, ad82584f"; + #sound-dai-cells = <0>; + reg = <0x31>; + status = "okay"; + reset_pin = <&gpio GPIOA_5 0>; + }; + + tlv320adc3101_32: tlv320adc3101_32@32 { + compatible = "ti,tlv320adc3101"; + #sound-dai-cells = <0>; + reg = <0x19>; + differential_pair = <1>; + status = "disabled"; + }; +}; + +&audiobus { + aml_tdma: tdma { + compatible = "amlogic, g12a-snd-tdma"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 1>; + dai-tdm-oe-lane-slot-mask-out = <1 0>; + dai-tdm-clk-sel = <0>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_A + &clkc CLKID_MPLL0>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmout_a &tdmin_a>; + }; + + aml_tdmb: tdmb { + compatible = "amlogic, g12a-snd-tdmb"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 1 0 0>; + dai-tdm-lane-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <1>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_B + &clkc CLKID_MPLL1 + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; + /* + * 0: tdmout_a; + * 1: tdmout_b; + * 2: tdmout_c; + * 3: spdifout; + * 4: spdifout_b; + */ + samesource_sel = <4>; + }; + + aml_tdmc: tdmc { + compatible = "amlogic, g12a-snd-tdmc"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <1 0 0 0>; + #dai-tdm-lane-slot-mask-out = <1 0 1 1>; + #dai-tdm-lane-oe-slot-mask-in = <0 0 0 0>; + #dai-tdm-lane-oe-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <2>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmc_mclk &tdmout_c &tdmin_c>; + }; + + /* copy a useless tdm to output for hdmi, no pinmux */ + aml_i2s2hdmi: i2s2hdmi { + compatible = "amlogic, g12a-snd-tdmc"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-out = <1 1 1 1>; + dai-tdm-clk-sel = <2>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + + i2s2hdmi = <1>; + + status = "okay"; + }; + + aml_spdif: spdif { + compatible = "amlogic, g12a-snd-spdif-a"; + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 + &clkc CLKID_FCLK_DIV4 + &clkaudio CLKID_AUDIO_SPDIFIN + &clkaudio CLKID_AUDIO_SPDIFOUT + &clkaudio CLKID_AUDIO_SPDIFIN_CTRL + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "sysclk", "fixed_clk", "gate_spdifin", + "gate_spdifout", "clk_spdifin", "clk_spdifout"; + interrupts = + ; + + interrupt-names = "irq_spdifin"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; + pinctrl-0 = <&spdifout &spdifin>; + pinctrl-1 = <&spdifout_a_mute>; + status = "okay"; + }; + aml_spdif_b: spdif_b { + compatible = "amlogic, g12a-snd-spdif-b"; + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 /*CLKID_HIFI_PLL*/ + &clkaudio CLKID_AUDIO_SPDIFOUTB + &clkaudio CLKID_AUDIO_SPDIFOUTB_CTRL>; + clock-names = "sysclk", + "gate_spdifout", "clk_spdifout"; + status = "disabled"; + }; + aml_pdm: pdm { + compatible = "amlogic, g12a-snd-pdm"; + #sound-dai-cells = <0>; + clocks = <&clkaudio CLKID_AUDIO_PDM + &clkc CLKID_FCLK_DIV3 + &clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_PDMIN0 + &clkaudio CLKID_AUDIO_PDMIN1>; + clock-names = "gate", + "sysclk_srcpll", + "dclk_srcpll", + "pdm_dclk", + "pdm_sysclk"; + pinctrl-names = "pdm_pins"; + pinctrl-0 = <&pdmin>; + filter_mode = <1>; /* mode 0~4, defalut:1 */ + status = "okay"; + }; + aml_loopback: loopback { + compatible = "amlogic, snd-loopback"; + /* + * 0: out rate = in data rate; + * 1: out rate = loopback data rate; + */ + lb_mode = <0>; + + /* datain src + * 0: tdmin_a; + * 1: tdmin_b; + * 2: tdmin_c; + * 3: spdifin; + * 4: pdmin; + */ + datain_src = <4>; + datain_chnum = <8>; + datain_chmask = <0x3f>; + + /* tdmin_lb src + * 0: tdmoutA + * 1: tdmoutB + * 2: tdmoutC + * 3: PAD_tdminA + * 4: PAD_tdminB + * 5: PAD_tdminC + */ + datalb_src = <2>; + datalb_chnum = <8>; + datalb_chmask = <0x3>; + + status = "disabled"; + }; + + audioresample: resample { + compatible = "amlogic, g12a-resample"; + clocks = <&clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_MCLK_F + &clkaudio CLKID_AUDIO_RESAMPLE_CTRL>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + /*same with toddr_src + * TDMIN_A, 0 + * TDMIN_B, 1 + * TDMIN_C, 2 + * SPDIFIN, 3 + * PDMIN, 4 + * NONE, + * TDMIN_LB, 6 + * LOOPBACK, 7 + */ + resample_module = <4>; + status = "disabled"; + }; + aml_pwrdet: pwrdet { + compatible = "amlogic, g12a-power-detect"; + + interrupts = ; + interrupt-names = "pwrdet_irq"; + + /* pwrdet source sel + * 7: loopback; + * 6: tdmin_lb; + * 5: reserved; + * 4: pdmin; + * 3: spdifin; + * 2: tdmin_c; + * 1: tdmin_b; + * 0: tdmin_a; + */ + pwrdet_src = <4>; + + hi_th = <0x70000>; + lo_th = <0x16000>; + + status = "disabled"; + }; +}; /* end of audiobus */ + +&pinctrl_periphs { + tdmout_a: tdmout_a { + mux { /* GPIOX_11, GPIOX_10, GPIOX_9 */ + groups = "tdma_sclk", + "tdma_fs", + "tdma_dout0"; + function = "tdma_out"; + }; + }; + + tdmin_a: tdmin_a { + mux { /* GPIOX_8 */ + groups = "tdma_din1"; + function = "tdma_in"; + }; + }; + + tdmb_mclk: tdmb_mclk { + mux { + groups = "mclk0_a"; + function = "mclk0"; + drive-strength = <2>; + }; + }; + tdmout_b: tdmout_b { + mux { /* GPIOA_1, GPIOA_2, GPIOA_3 */ + groups = "tdmb_sclk", + "tdmb_fs", + "tdmb_dout0"; + function = "tdmb_out"; + drive-strength = <2>; + }; + }; + + tdmin_b:tdmin_b { + mux { /* GPIOA_4 */ + groups = "tdmb_din1" + /*,"tdmb_slv_sclk", "tdmb_slv_fs"*/; + function = "tdmb_in"; + drive-strength = <2>; + }; + }; + + tdmc_mclk: tdmc_mclk { + mux { /* GPIOA_11 */ + groups = "mclk1_a"; + function = "mclk1"; + }; + }; + + clk12_24_z_pins:clk12_24_z_pins { + mux { + groups = "clk12_24_z"; + function = "clk12_24_ee"; + drive-strength = <3>; + }; + }; + + tdmout_c:tdmout_c { + mux { /* GPIOA_12, GPIOA_13, GPIOA_8, GPIOA_7*/ + groups = "tdmc_sclk_a", + "tdmc_fs_a", + "tdmc_dout0_a" + /*, "tdmc_dout2", + * "tdmc_dout3" + */; + function = "tdmc_out"; + }; + }; + + tdmin_c:tdmin_c { + mux { /* GPIOA_10 */ + groups = "tdmc_din0_a"; + function = "tdmc_in"; + }; + }; + + spdifin: spdifin { + mux {/* GPIOH_5 */ + groups = "spdif_in_h"; + function = "spdif_in"; + }; + }; + + /* GPIOH_4 */ + /* + * spdifout: spdifout { + * mux { + * groups = "spdif_out_h"; + * function = "spdif_out"; + * }; + *}; + */ + + pdmin: pdmin { + mux { /* gpioa_5, gpioa_6, gpioa_7, gpioa_8, gpioa_9*/ + groups = "pdm_din0_a", + /*"pdm_din1_a",*/ + "pdm_din2_a", + /*"pdm_din3_a",*/ + "pdm_dclk_a"; + function = "pdm"; + }; + }; + + bl_pwm_off_pins:bl_pwm_off_pin { + mux { + pins = "GPIOH_5"; + function = "gpio_periphs"; + output-high; + }; + }; + +}; /* end of pinctrl_periphs */ + +&pinctrl_aobus { + spdifout: spdifout { + mux { /* gpiao_10 */ + groups = "spdif_out_ao"; + function = "spdif_out_ao"; + }; + }; + + spdifout_a_mute: spdifout_a_mute { + mux { /* gpiao_10 */ + groups = "GPIOAO_10"; + function = "gpio_aobus"; + }; + }; +}; /* end of pinctrl_aobus */ + +&irblaster { + status = "disabled"; +}; + +&audio_data { + status = "okay"; +}; + +/*if you want to use vdin just modify status to "ok"*/ +&vdin0 { + memory-region = <&vdin0_cma_reserved>; + status = "okay"; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + *bit4:support yuv422 10bit full pack mode (from txl new add) + */ + tv_bit_mode = <0x15>; +}; +&vdin1 { + memory-region = <&vdin1_cma_reserved>; + status = "okay"; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + */ + tv_bit_mode = <1>; +}; + +&sd_emmc_c { + status = "okay"; + emmc { + caps = "MMC_CAP_8_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + /* "MMC_CAP_1_8V_DDR", */ + "MMC_CAP_HW_RESET", + "MMC_CAP_ERASE", + "MMC_CAP_CMD23"; + caps2 = "MMC_CAP2_HS200"; + /* "MMC_CAP2_HS400";*/ + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&sd_emmc_b { + status = "okay"; + sd { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED"; + f_min = <400000>; + f_max = <50000000>; + }; +}; + +&sd_emmc_a { + status = "okay"; + sdio { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + "MMC_CAP_UHS_SDR12", + "MMC_CAP_UHS_SDR25", + "MMC_CAP_UHS_SDR50", + "MMC_CAP_UHS_SDR104", + "MMC_PM_KEEP_POWER", + "MMC_CAP_SDIO_IRQ"; + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&nand { + status = "disabled"; + plat-names = "bootloader","nandnormal"; + plat-num = <2>; + plat-part-0 = <&bootloader>; + plat-part-1 = <&nandnormal>; + bootloader: bootloader{ + enable_pad ="ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <1>; + part_num = <0>; + rb_detect = <1>; + }; + nandnormal: nandnormal{ + enable_pad ="ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + plane_mode = "twoplane"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <2>; + part_num = <3>; + partition = <&nand_partitions>; + rb_detect = <1>; + }; + nand_partitions:nand_partition{ + /* + * if bl_mode is 1, tpl size was generate by + * fip_copies * fip_size which + * will not skip bad when calculating + * the partition size; + * + * if bl_mode is 0, + * tpl partition must be comment out. + */ + tpl{ + offset=<0x0 0x0>; + size=<0x0 0x0>; + }; + logo{ + offset=<0x0 0x0>; + size=<0x0 0x200000>; + }; + recovery{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + boot{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + system{ + offset=<0x0 0x0>; + size=<0x0 0x4000000>; + }; + data{ + offset=<0xffffffff 0xffffffff>; + size=<0x0 0x0>; + }; + }; +}; +&dwc3 { + status = "okay"; +}; + +&usb2_phy_v2 { + status = "okay"; + portnum = <2>; +}; + +&usb3_phy_v2 { + status = "okay"; + portnum = <0>; + otg = <1>; + gpio-vbus-power = "GPIOH_6"; + gpios = <&gpio GPIOH_6 GPIO_ACTIVE_HIGH>; +}; + +&dwc2_a { + status = "okay"; + /** 0: normal, 1: otg+dwc3 host only, 2: otg+dwc3 device only*/ + controller-type = <3>; +}; +ðmac { + status = "okay"; +/* //conflict with isp i2c + * pinctrl-names = "internal_eth_pins"; + * pinctrl-0 = <&internal_eth_pins>; + */ + mc_val = <0x4be04>; + + internal_phy=<1>; +}; + +&uart_A { + status = "okay"; +}; + +&pcie_A { + reset-gpio = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; + status = "disabled"; +}; + +&saradc { + status = "okay"; +}; + +&spicc1 { + status = "disabled"; + pinctrl-names = "default"; + pinctrl-0 = <&spicc1_pins>; + cs-gpios = <&gpio GPIOH_6 0>; +}; diff --git a/arch/arm/boot/dts/amlogic/g12b_a311d_w400.dts b/arch/arm/boot/dts/amlogic/g12b_a311d_w400.dts index af55b1cb15e4..0a4eece69d97 100644 --- a/arch/arm/boot/dts/amlogic/g12b_a311d_w400.dts +++ b/arch/arm/boot/dts/amlogic/g12b_a311d_w400.dts @@ -23,6 +23,7 @@ / { model = "Amlogic"; + amlogic-dt-id = "g12b_w400_b"; compatible = "amlogic, g12b"; interrupt-parent = <&gic>; #address-cells = <1>; @@ -45,7 +46,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x000000 0x80000000>; + linux,usable-memory = <0x100000 0x7ff00000>; }; reserved-memory { @@ -58,8 +59,7 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { @@ -146,6 +146,18 @@ size = <0x04000000>; alignment = <0x400000>; }; + galcore_reserved:linux,galcore { + compatible = "shared-dma-pool"; + reusable; + size = <0x1000000>; + alignment = <0x400000>; + linux,contiguous-region; + }; + }; + + galcore { + status = "okay"; + memory-region = <&galcore_reserved>; }; gpioleds { @@ -234,6 +246,21 @@ status = "okay"; }; + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + deinterlace { compatible = "amlogic, deinterlace"; status = "okay"; @@ -633,31 +660,31 @@ }; opp04 { opp-hz = /bits/ 64 <1000000000>; - opp-microvolt = <731000>; + opp-microvolt = <761000>; }; opp05 { opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <731000>; + opp-microvolt = <781000>; }; opp06 { opp-hz = /bits/ 64 <1398000000>; - opp-microvolt = <761000>; + opp-microvolt = <811000>; }; opp07 { opp-hz = /bits/ 64 <1512000000>; - opp-microvolt = <791000>; + opp-microvolt = <861000>; }; opp08 { opp-hz = /bits/ 64 <1608000000>; - opp-microvolt = <831000>; + opp-microvolt = <901000>; }; opp09 { opp-hz = /bits/ 64 <1704000000>; - opp-microvolt = <861000>; + opp-microvolt = <951000>; }; opp10 { opp-hz = /bits/ 64 <1800000000>; - opp-microvolt = <981000>; + opp-microvolt = <1001000>; }; }; @@ -667,43 +694,63 @@ opp00 { opp-hz = /bits/ 64 <100000000>; - opp-microvolt = <751000>; + opp-microvolt = <731000>; }; opp01 { opp-hz = /bits/ 64 <250000000>; - opp-microvolt = <751000>; + opp-microvolt = <731000>; }; opp02 { opp-hz = /bits/ 64 <500000000>; - opp-microvolt = <751000>; + opp-microvolt = <731000>; }; opp03 { opp-hz = /bits/ 64 <667000000>; - opp-microvolt = <751000>; + opp-microvolt = <731000>; }; opp04 { opp-hz = /bits/ 64 <1000000000>; - opp-microvolt = <771000>; + opp-microvolt = <731000>; }; opp05 { opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <771000>; + opp-microvolt = <751000>; }; opp06 { opp-hz = /bits/ 64 <1398000000>; - opp-microvolt = <791000>; + opp-microvolt = <771000>; }; opp07 { opp-hz = /bits/ 64 <1512000000>; - opp-microvolt = <821000>; + opp-microvolt = <771000>; }; opp08 { opp-hz = /bits/ 64 <1608000000>; - opp-microvolt = <861000>; + opp-microvolt = <781000>; }; opp09 { opp-hz = /bits/ 64 <1704000000>; - opp-microvolt = <891000>; + opp-microvolt = <791000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <831000>; + }; + opp11 { + opp-hz = /bits/ 64 <1908000000>; + opp-microvolt = <861000>; + }; + opp12 { + opp-hz = /bits/ 64 <2016000000>; + opp-microvolt = <911000>; + }; + opp13 { + opp-hz = /bits/ 64 <2100000000>; + opp-microvolt = <951000>; + }; + opp14 { + opp-hz = /bits/ 64 <2208000000>; + opp-microvolt = <1011000>; }; }; @@ -833,8 +880,10 @@ dai-tdm-clk-sel = <1>; clocks = <&clkaudio CLKID_AUDIO_MCLK_B &clkc CLKID_MPLL1 - &clkc CLKID_MPLL0>; - clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; /* @@ -892,8 +941,10 @@ ; interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; pinctrl-0 = <&spdifout &spdifin>; + pinctrl-1 = <&spdifout_a_mute>; status = "okay"; }; aml_spdif_b: spdif_b { @@ -1116,6 +1167,13 @@ function = "spdif_out_ao"; }; }; + + spdifout_a_mute: spdifout_a_mute { + mux { /* gpiao_10 */ + groups = "GPIOAO_10"; + function = "gpio_aobus"; + }; + }; }; /* end of pinctrl_aobus */ &irblaster { @@ -1161,9 +1219,9 @@ /* "MMC_CAP_1_8V_DDR", */ "MMC_CAP_HW_RESET", "MMC_CAP_ERASE", - "MMC_CAP_CMD23"; - caps2 = "MMC_CAP2_HS200"; - /* "MMC_CAP2_HS400";*/ + "MMC_CAP_CMD23", + "MMC_CAP_DRIVER_TYPE_A"; + caps2 = "MMC_CAP2_HS200", "MMC_CAP2_HS400"; f_min = <400000>; f_max = <200000000>; }; @@ -1275,7 +1333,7 @@ &usb3_phy_v2 { status = "okay"; - portnum = <0>; + portnum = <1>; otg = <1>; gpio-vbus-power = "GPIOH_6"; gpios = <&gpio GPIOH_6 GPIO_ACTIVE_HIGH>; @@ -1301,7 +1359,7 @@ &pcie_A { reset-gpio = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; - status = "okay"; + status = "disable"; }; &saradc { diff --git a/arch/arm/boot/dts/amlogic/g12b_a311d_w400_a.dts b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_a.dts new file mode 100644 index 000000000000..f92c26d42cf6 --- /dev/null +++ b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_a.dts @@ -0,0 +1,1348 @@ +/* + * arch/arm/boot/dts/amlogic/g12b_a311d_w400_a.dts + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +/dts-v1/; + +#include "partition_mbox_normal.dtsi" +#include "mesong12b_a.dtsi" +#include "mesong12b_skt-panel.dtsi" + +/ { + model = "Amlogic"; + amlogic-dt-id = "g12b_w400_a"; + compatible = "amlogic, g12b"; + interrupt-parent = <&gic>; + #address-cells = <1>; + #size-cells = <1>; + + aliases { + serial0 = &uart_AO; + serial1 = &uart_A; + serial2 = &uart_B; + serial3 = &uart_C; + serial4 = &uart_AO_B; + i2c0 = &i2c0; + i2c1 = &i2c1; + i2c2 = &i2c2; + i2c3 = &i2c3; + i2c4 = &i2c_AO; + tsensor0 = &p_tsensor; + tsensor1 = &d_tsensor; + }; + + memory@00000000 { + device_type = "memory"; + linux,usable-memory = <0x000000 0x80000000>; + }; + + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + /* global autoconfigured region for contiguous allocations */ + ramoops@0x07400000 { + compatible = "ramoops"; + reg = <0x07400000 0x00100000>; + record-size = <0x8000>; + console-size = <0x8000>; + ftrace-size = <0x20000>; + }; + + secmon_reserved:linux,secmon { + compatible = "shared-dma-pool"; + reusable; + size = <0x400000>; + alignment = <0x400000>; + alloc-ranges = <0x05000000 0x400000>; + clear-map; + }; + + secos_reserved:linux,secos { + status = "disable"; + compatible = "amlogic, aml_secos_memory"; + reg = <0x05300000 0x2000000>; + no-map; + }; + logo_reserved:linux,meson-fb { + compatible = "shared-dma-pool"; + reusable; + size = <0x800000>; + alignment = <0x400000>; + alloc-ranges = <0x7f800000 0x800000>; + }; + ion_cma_reserved:linux,ion-dev { + compatible = "shared-dma-pool"; + reusable; + size = <0x8000000>; + alignment = <0x400000>; + }; + + //di_reserved:linux,di { + //compatible = "amlogic, di-mem"; + /* buffer_size = 3621952(yuv422 8bit) */ + /* 4179008(yuv422 10bit full pack mode) */ + /** 10x3621952=34.6M(0x23) support 8bit **/ + /** 10x4736064=45.2M(0x2e) support 12bit **/ + /** 10x4179008=40M(0x28) support 10bit **/ + //size = <0x2800000>; + //no-map; + //}; + /*di CMA pool */ + di_cma_reserved:linux,di_cma { + compatible = "shared-dma-pool"; + reusable; + /* buffer_size = 3621952(yuv422 8bit) + * | 4736064(yuv422 10bit) + * | 4074560(yuv422 10bit full pack mode) + * 10x3621952=34.6M(0x23) support 8bit + * 10x4736064=45.2M(0x2e) support 12bit + * 10x4074560=40M(0x28) support 10bit + */ + size = <0x02800000>; + alignment = <0x400000>; + }; + codec_mm_cma:linux,codec_mm_cma { + compatible = "shared-dma-pool"; + reusable; + /* ion_codec_mm max can alloc size 80M*/ + size = <0x13400000>; + alignment = <0x400000>; + linux,contiguous-region; + }; + /* codec shared reserved */ + codec_mm_reserved:linux,codec_mm_reserved { + compatible = "amlogic, codec-mm-reserved"; + size = <0x0>; + alignment = <0x100000>; + //no-map; + }; + /* vdin0 CMA pool */ + vdin0_cma_reserved:linux,vdin0_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16+4 M */ + size = <0x04000000>; + alignment = <0x400000>; + }; + /* vdin1 CMA pool */ + vdin1_cma_reserved:linux,vdin1_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16 M */ + size = <0x04000000>; + alignment = <0x400000>; + }; + galcore_reserved:linux,galcore { + compatible = "shared-dma-pool"; + reusable; + size = <0x1000000>; + alignment = <0x400000>; + linux,contiguous-region; + }; + }; + + galcore { + status = "okay"; + memory-region = <&galcore_reserved>; + }; + + gpioleds { + compatible = "gpio-leds"; + status = "okay"; + sys_led { + label="sys_led"; + gpios=<&gpio_ao GPIOAO_11 GPIO_ACTIVE_HIGH>; + default-state ="on"; + }; + }; + + cvbsout { + compatible = "amlogic, cvbsout-g12b"; + dev_name = "cvbsout"; + status = "okay"; + clocks = <&clkc CLKID_VCLK2_ENCI + &clkc CLKID_VCLK2_VENCI0 + &clkc CLKID_VCLK2_VENCI1 + &clkc CLKID_DAC_CLK>; + clock-names = "venci_top_gate", + "venci_0_gate", + "venci_1_gate", + "vdac_clk_gate"; + /* clk path */ + /* 0:vid_pll vid2_clk */ + /* 1:gp0_pll vid2_clk */ + /* 2:vid_pll vid1_clk */ + /* 3:gp0_pll vid1_clk */ + clk_path = <0>; + + /* performance: reg_address, reg_value */ + /* g12b */ + performance = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x8080 + 0x1b05 0xfd + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + performance_sarft = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x0 + 0x1b05 0x9 + 0x1c59 0xfc48 + 0xffff 0x0>; /* ending flag */ + }; + + bt-dev{ + compatible = "amlogic, bt-dev"; + dev_name = "bt-dev"; + status = "okay"; + gpio_reset = <&gpio GPIOX_17 GPIO_ACTIVE_HIGH>; + gpio_hostwake = <&gpio GPIOX_19 GPIO_ACTIVE_HIGH>; + }; + + wifi{ + compatible = "amlogic, aml_wifi"; + dev_name = "aml_wifi"; + status = "okay"; + interrupt_pin = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; + irq_trigger_type = "GPIO_IRQ_LOW"; + power_on_pin = <&gpio GPIOX_6 GPIO_ACTIVE_HIGH>; + dhd_static_buf; //if use bcm wifi, config dhd_static_buf + pinctrl-names = "default"; + pinctrl-0 = <&pwm_e_pins>; + pwm_config = <&wifi_pwm_conf>; + }; + + wifi_pwm_conf:wifi_pwm_conf{ + pwm_channel1_conf { + pwms = <&pwm_ef MESON_PWM_0 30541 0>; + duty-cycle = <15270>; + times = <10>; + }; + pwm_channel2_conf { + pwms = <&pwm_ef MESON_PWM_2 30500 0>; + duty-cycle = <15250>; + times = <12>; + }; + }; + + codec_mm { + compatible = "amlogic, codec, mm"; + memory-region = <&codec_mm_cma &codec_mm_reserved>; + dev_name = "codec_mm"; + status = "okay"; + }; + + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + + deinterlace { + compatible = "amlogic, deinterlace"; + status = "okay"; + /* 0:use reserved; 1:use cma; 2:use cma as reserved */ + flag_cma = <1>; + //memory-region = <&di_reserved>; + memory-region = <&di_cma_reserved>; + interrupts = <0 46 1 + 0 40 1>; + interrupt-names = "pre_irq", "post_irq"; + clocks = <&clkc CLKID_VPU_CLKB_TMP_COMP>, + <&clkc CLKID_VPU_CLKB_COMP>; + clock-names = "vpu_clkb_tmp_composite", + "vpu_clkb_composite"; + clock-range = <334 667>; + /* buffer-size = <3621952>;(yuv422 8bit) */ + buffer-size = <4074560>;/*yuv422 fullpack*/ + /* reserve-iomap = "true"; */ + /* if enable nr10bit, set nr10bit-support to 1 */ + post-wr-support = <1>; + nr10bit-support = <1>; + nrds-enable = <1>; + pps-enable = <1>; + }; + ionvideo { + compatible = "amlogic, ionvideo"; + dev_name = "ionvideo"; + status = "okay"; + }; + + gpio_keypad { + compatible = "amlogic, gpio_keypad"; + status = "okay"; + scan_period = <20>; + key_num = <1>; + key_name = "power"; + key_code = <116>; + key-gpios = <&gpio_ao GPIOAO_3 GPIO_ACTIVE_HIGH>; + detect_mode = <0>;/*0:polling mode, 1:irq mode*/ + }; + + adc_keypad { + compatible = "amlogic, adc_keypad"; + status = "okay"; + key_name = "vol-", "vol+", "enter"; + key_num = <3>; + io-channels = <&saradc SARADC_CH2>; + io-channel-names = "key-chan-2"; + key_chan = ; + key_code = <114 115 28>; + key_val = <143 266 389>; //val=voltage/1800mV*1023 + key_tolerance = <40 40 40>; + }; + + unifykey{ + compatible = "amlogic, unifykey"; + status = "ok"; + unifykey-num = <16>; + unifykey-index-0 = <&keysn_0>; + unifykey-index-1 = <&keysn_1>; + unifykey-index-2 = <&keysn_2>; + unifykey-index-3 = <&keysn_3>; + unifykey-index-4 = <&keysn_4>; + unifykey-index-5 = <&keysn_5>; + unifykey-index-6 = <&keysn_6>; + unifykey-index-7 = <&keysn_7>; + unifykey-index-8 = <&keysn_8>; + unifykey-index-9 = <&keysn_9>; + unifykey-index-10= <&keysn_10>; + unifykey-index-11= <&keysn_11>; + unifykey-index-12= <&keysn_12>; + unifykey-index-13= <&keysn_13>; + unifykey-index-14= <&keysn_14>; + unifykey-index-15= <&keysn_15>; + + keysn_0: key_0{ + key-name = "usid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_1:key_1{ + key-name = "mac"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_2:key_2{ + key-name = "hdcp"; + key-device = "secure"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_3:key_3{ + key-name = "secure_boot_set"; + key-device = "efuse"; + key-permit = "write"; + }; + keysn_4:key_4{ + key-name = "mac_bt"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_5:key_5{ + key-name = "mac_wifi"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_6:key_6{ + key-name = "hdcp2_tx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_7:key_7{ + key-name = "hdcp2_rx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_8:key_8{ + key-name = "widevinekeybox"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_9:key_9{ + key-name = "deviceid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_10:key_10{ + key-name = "hdcp22_fw_private"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_11:key_11{ + key-name = "PlayReadykeybox25"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_12:key_12{ + key-name = "prpubkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_13:key_13{ + key-name = "prprivkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_14:key_14{ + key-name = "attestationkeybox";// attestation key + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_15:key_15{ + key-name = "netflix_mgkid"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + };//End unifykey + + efusekey:efusekey{ + keynum = <4>; + key0 = <&key_0>; + key1 = <&key_1>; + key2 = <&key_2>; + key3 = <&key_3>; + key_0:key_0{ + keyname = "mac"; + offset = <0>; + size = <6>; + }; + key_1:key_1{ + keyname = "mac_bt"; + offset = <6>; + size = <6>; + }; + key_2:key_2{ + keyname = "mac_wifi"; + offset = <12>; + size = <6>; + }; + key_3:key_3{ + keyname = "usid"; + offset = <18>; + size = <16>; + }; + };//End efusekey + + amlvecm { + compatible = "amlogic, vecm"; + dev_name = "aml_vecm"; + status = "okay"; + gamma_en = <0>;/*1:enabel ;0:disable*/ + wb_en = <0>;/*1:enabel ;0:disable*/ + cm_en = <0>;/*1:enabel ;0:disable*/ + }; + amdolby_vision { + compatible = "amlogic, dolby_vision_g12a"; + dev_name = "aml_amdolby_vision_driver"; + status = "okay"; + tv_mode = <0>;/*1:enabel ;0:disable*/ + }; + + /* Audio Related start */ + pdm_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, pdm_dummy_codec"; + status = "okay"; + }; + dummy_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, aml_dummy_codec"; + status = "okay"; + }; + amlogic_codec:t9015{ + #sound-dai-cells = <0>; + compatible = "amlogic, aml_codec_T9015"; + reg = <0xFF632000 0x2000>; + is_auge_used = <1>; /* meson or auge chipset used */ + tdmout_index = <1>; + status = "okay"; + }; + audio_effect:eqdrc{ + /*eq_enable = <1>;*/ + /*drc_enable = <1>;*/ + /* + * 0:tdmout_a + * 1:tdmout_b + * 2:tdmout_c + * 3:spdifout + * 4:spdifout_b + */ + eqdrc_module = <1>; + /* max 0xf, each bit for one lane, usually one lane */ + lane_mask = <0x1>; + /* max 0xff, each bit for one channel */ + channel_mask = <0x3>; + }; + auge_sound { + compatible = "amlogic, g12a-sound-card"; + aml-audio-card,name = "AML-AUGESOUND"; + + //aml-audio-card,loopback = <&aml_loopback>; + //aml-audio-card,aux-devs = <&amlogic_codec>; + /*avout mute gpio*/ + avout_mute-gpios = <&gpio_ao GPIOAO_2 GPIO_ACTIVE_HIGH>; + /*for audio effect ,eqdrc */ + aml-audio-card,effect = <&audio_effect>; + + aml-audio-card,dai-link@0 { + format = "dsp_a"; + mclk-fs = <512>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + //bitclock-master = <&tdmacodec>; + //frame-master = <&tdmacodec>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-pcm"; + tdmacpu: cpu { + sound-dai = <&aml_tdma>; + dai-tdm-slot-tx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-rx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-num = <8>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <24576000>; + }; + tdmacodec: codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@1 { + format = "i2s"; + mclk-fs = <256>; + continuous-clock; + //bitclock-inversion; + //frame-inversion; + bitclock-master = <&aml_tdmb>; + frame-master = <&aml_tdmb>; + //bitclock-master = <&tdmbcodec>; + //frame-master = <&tdmbcodec>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-i2s"; + cpu { + sound-dai = <&aml_tdmb>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmbcodec: codec { + sound-dai = <&dummy_codec &dummy_codec + &amlogic_codec &ad82584f_62>; + }; + }; + + aml-audio-card,dai-link@2 { + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + bitclock-master = <&aml_tdmc>; + frame-master = <&aml_tdmc>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + //suffix-name = "alsaPORT-tdm"; + cpu { + sound-dai = <&aml_tdmc>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@3 { + mclk-fs = <64>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-pdm"; + cpu { + sound-dai = <&aml_pdm>; + }; + codec { + sound-dai = <&pdm_codec>; + }; + }; + + aml-audio-card,dai-link@4 { + mclk-fs = <128>; + continuous-clock; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-spdif"; + cpu { + sound-dai = <&aml_spdif>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + }; + audiolocker: locker { + compatible = "amlogic, audiolocker"; + clocks = <&clkaudio CLKID_AUDIO_LOCKER_OUT + &clkaudio CLKID_AUDIO_LOCKER_IN + &clkaudio CLKID_AUDIO_MCLK_D + &clkaudio CLKID_AUDIO_MCLK_E + &clkc CLKID_MPLL1 + &clkc CLKID_MPLL2>; + clock-names = "lock_out", "lock_in", "out_src", + "in_src", "out_calc", "in_ref"; + interrupts = ; + interrupt-names = "irq"; + frequency = <49000000>; /* pll */ + dividor = <49>; /* locker's parent */ + status = "okay"; + }; + /* Audio Related end */ + + cpu_opp_table0: cpu_opp_table0 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <731000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <731000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <731000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <731000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <731000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <731000>; + }; + opp06 { + opp-hz = /bits/ 64 <1398000000>; + opp-microvolt = <761000>; + }; + opp07 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <791000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <831000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <861000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <981000>; + }; + }; + + cpu_opp_table1: cpu_opp_table1 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <751000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <751000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <751000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <751000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <771000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <771000>; + }; + opp06 { + opp-hz = /bits/ 64 <1398000000>; + opp-microvolt = <791000>; + }; + opp07 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <821000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <861000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <891000>; + }; + }; + + cpufreq-meson { + compatible = "amlogic, cpufreq-meson"; + status = "okay"; + }; + + +}; /* end of / */ + +&meson_fb { + status = "okay"; + display_size_default = <1920 1080 1920 2160 32>; + mem_size = <0x00800000 0x1980000 0x100000 0x100000 0x800000>; + logo_addr = "0x7f800000"; + mem_alloc = <0>; + pxp_mode = <0>; /** 0:normal mode 1:pxp mode */ +}; + +&pwm_ab { + status = "okay"; + }; + +&pwm_ef { + status = "okay"; + }; + +&pwm_AO_cd { + status = "okay"; + }; + +&i2c0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_master_pins2>; + clock-frequency = <400000>; + + touchscreen@5d { + compatible = "goodix,gt9xx"; + status = "disabled"; + reg = <0x5d>; + reset-gpio = <&gpio GPIOZ_9 GPIO_ACTIVE_HIGH>; + irq-gpio = <&gpio GPIOZ_3 GPIO_ACTIVE_HIGH>; + goodix,cfg-group0 = [ + 41 00 04 58 02 05 0C 00 02 54 07 + 0F 50 2D 03 05 00 00 00 00 40 00 + 04 20 10 F3 AA 07 28 0A 2C 2E 7C + 06 00 00 00 C9 03 24 00 01 00 00 + 00 00 FF 5D 66 98 32 28 64 94 C5 + 02 08 00 00 01 91 2C 00 8A 34 00 + 8A 3F 00 7E 4C 00 78 5B 00 78 00 + 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 + 00 00 02 04 06 08 0A 0C 0E 10 12 + 14 FF FF FF FF 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 + 02 04 06 08 0A 0C 1D 1E 1F 20 21 + 22 24 26 FF FF FF FF FF FF FF FF + FF FF FF 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 E3 01]; + }; + + touchscreen@38 { + compatible = "focaltech,fts"; + status = "disabled"; + reg = <0x38>; + reset-gpio = <&gpio GPIOZ_9 GPIO_ACTIVE_HIGH>; + irq-gpio = <&gpio GPIOZ_3 GPIO_ACTIVE_HIGH>; + x_max = <720>; + y_max = <1280>; + max-touch-number = <10>; + }; +}; + +&i2c3 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&i2c3_master_pins2>; + clock-frequency = <100000>; /* default 100k */ + + /* for ref board */ + ad82584f_62: ad82584f_62@62 { + compatible = "ESMT, ad82584f"; + #sound-dai-cells = <0>; + reg = <0x31>; + status = "okay"; + reset_pin = <&gpio GPIOA_5 0>; + }; + + tlv320adc3101_32: tlv320adc3101_32@32 { + compatible = "ti,tlv320adc3101"; + #sound-dai-cells = <0>; + reg = <0x19>; + differential_pair = <1>; + status = "disabled"; + }; + + bl_extern_i2c { + compatible = "bl_extern, i2c"; + dev_name = "lp8556"; + reg = <0x2c>; + status = "disabled"; + }; +}; + +&audiobus { + aml_tdma: tdma { + compatible = "amlogic, g12a-snd-tdma"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 1>; + dai-tdm-oe-lane-slot-mask-out = <1 0>; + dai-tdm-clk-sel = <0>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_A + &clkc CLKID_MPLL0>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmout_a &tdmin_a>; + }; + + aml_tdmb: tdmb { + compatible = "amlogic, g12a-snd-tdmb"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 1 0 0>; + dai-tdm-lane-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <1>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_B + &clkc CLKID_MPLL1 + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; + /* + * 0: tdmout_a; + * 1: tdmout_b; + * 2: tdmout_c; + * 3: spdifout; + * 4: spdifout_b; + */ + samesource_sel = <3>; + }; + + aml_tdmc: tdmc { + compatible = "amlogic, g12a-snd-tdmc"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <1 0 0 0>; + #dai-tdm-lane-slot-mask-out = <1 0 1 1>; + #dai-tdm-lane-oe-slot-mask-in = <0 0 0 0>; + #dai-tdm-lane-oe-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <2>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmc_mclk &tdmout_c &tdmin_c>; + }; + + /* copy a useless tdm to output for hdmi, no pinmux */ + aml_i2s2hdmi: i2s2hdmi { + compatible = "amlogic, g12a-snd-tdmc"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-out = <1 1 1 1>; + dai-tdm-clk-sel = <2>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + + i2s2hdmi = <1>; + + status = "okay"; + }; + + aml_spdif: spdif { + compatible = "amlogic, g12a-snd-spdif-a"; + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 + &clkc CLKID_FCLK_DIV4 + &clkaudio CLKID_AUDIO_SPDIFIN + &clkaudio CLKID_AUDIO_SPDIFOUT + &clkaudio CLKID_AUDIO_SPDIFIN_CTRL + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "sysclk", "fixed_clk", "gate_spdifin", + "gate_spdifout", "clk_spdifin", "clk_spdifout"; + interrupts = + ; + + interrupt-names = "irq_spdifin"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; + pinctrl-0 = <&spdifout &spdifin>; + pinctrl-1 = <&spdifout_a_mute>; + status = "okay"; + }; + aml_spdif_b: spdif_b { + compatible = "amlogic, g12a-snd-spdif-b"; + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 /*CLKID_HIFI_PLL*/ + &clkaudio CLKID_AUDIO_SPDIFOUTB + &clkaudio CLKID_AUDIO_SPDIFOUTB_CTRL>; + clock-names = "sysclk", + "gate_spdifout", "clk_spdifout"; + status = "disabled"; + }; + aml_pdm: pdm { + compatible = "amlogic, g12a-snd-pdm"; + #sound-dai-cells = <0>; + clocks = <&clkaudio CLKID_AUDIO_PDM + &clkc CLKID_FCLK_DIV3 + &clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_PDMIN0 + &clkaudio CLKID_AUDIO_PDMIN1>; + clock-names = "gate", + "sysclk_srcpll", + "dclk_srcpll", + "pdm_dclk", + "pdm_sysclk"; + pinctrl-names = "pdm_pins"; + pinctrl-0 = <&pdmin>; + filter_mode = <1>; /* mode 0~4, defalut:1 */ + status = "okay"; + }; + aml_loopback: loopback { + compatible = "amlogic, snd-loopback"; + /* + * 0: out rate = in data rate; + * 1: out rate = loopback data rate; + */ + lb_mode = <0>; + + /* datain src + * 0: tdmin_a; + * 1: tdmin_b; + * 2: tdmin_c; + * 3: spdifin; + * 4: pdmin; + */ + datain_src = <4>; + datain_chnum = <8>; + datain_chmask = <0x3f>; + + /* tdmin_lb src + * 0: tdmoutA + * 1: tdmoutB + * 2: tdmoutC + * 3: PAD_tdminA + * 4: PAD_tdminB + * 5: PAD_tdminC + */ + datalb_src = <2>; + datalb_chnum = <8>; + datalb_chmask = <0x3>; + + status = "disabled"; + }; + + audioresample: resample { + compatible = "amlogic, g12a-resample"; + clocks = <&clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_MCLK_F + &clkaudio CLKID_AUDIO_RESAMPLE_CTRL>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + /*same with toddr_src + * TDMIN_A, 0 + * TDMIN_B, 1 + * TDMIN_C, 2 + * SPDIFIN, 3 + * PDMIN, 4 + * NONE, + * TDMIN_LB, 6 + * LOOPBACK, 7 + */ + resample_module = <4>; + status = "disabled"; + }; + aml_pwrdet: pwrdet { + compatible = "amlogic, g12a-power-detect"; + + interrupts = ; + interrupt-names = "pwrdet_irq"; + + /* pwrdet source sel + * 7: loopback; + * 6: tdmin_lb; + * 5: reserved; + * 4: pdmin; + * 3: spdifin; + * 2: tdmin_c; + * 1: tdmin_b; + * 0: tdmin_a; + */ + pwrdet_src = <4>; + + hi_th = <0x70000>; + lo_th = <0x16000>; + + status = "disabled"; + }; +}; /* end of audiobus */ + +&pinctrl_periphs { + tdmout_a: tdmout_a { + mux { /* GPIOX_11, GPIOX_10, GPIOX_9 */ + groups = "tdma_sclk", + "tdma_fs", + "tdma_dout0"; + function = "tdma_out"; + }; + }; + + tdmin_a: tdmin_a { + mux { /* GPIOX_8 */ + groups = "tdma_din1"; + function = "tdma_in"; + }; + }; + + tdmb_mclk: tdmb_mclk { + mux { + groups = "mclk0_a"; + function = "mclk0"; + drive-strength = <2>; + }; + }; + tdmout_b: tdmout_b { + mux { /* GPIOA_1, GPIOA_2, GPIOA_3 */ + groups = "tdmb_sclk", + "tdmb_fs", + "tdmb_dout0"; + function = "tdmb_out"; + drive-strength = <2>; + }; + }; + + tdmin_b:tdmin_b { + mux { /* GPIOA_4 */ + groups = "tdmb_din1" + /*,"tdmb_slv_sclk", "tdmb_slv_fs"*/; + function = "tdmb_in"; + drive-strength = <2>; + }; + }; + + tdmc_mclk: tdmc_mclk { + mux { /* GPIOA_11 */ + groups = "mclk1_a"; + function = "mclk1"; + }; + }; + + tdmout_c:tdmout_c { + mux { /* GPIOA_12, GPIOA_13, GPIOA_8, GPIOA_7*/ + groups = "tdmc_sclk_a", + "tdmc_fs_a", + "tdmc_dout0_a" + /*, "tdmc_dout2", + * "tdmc_dout3" + */; + function = "tdmc_out"; + }; + }; + + tdmin_c:tdmin_c { + mux { /* GPIOA_10 */ + groups = "tdmc_din0_a"; + function = "tdmc_in"; + }; + }; + + spdifin: spdifin { + mux {/* GPIOH_5 */ + groups = "spdif_in_h"; + function = "spdif_in"; + }; + }; + + /* GPIOH_4 */ + /* + * spdifout: spdifout { + * mux { + * groups = "spdif_out_h"; + * function = "spdif_out"; + * }; + *}; + */ + + pdmin: pdmin { + mux { /* gpioa_5, gpioa_6, gpioa_7, gpioa_8, gpioa_9*/ + groups = "pdm_din0_a", + /*"pdm_din1_a",*/ + "pdm_din2_a", + /*"pdm_din3_a",*/ + "pdm_dclk_a"; + function = "pdm"; + }; + }; + + bl_pwm_off_pins:bl_pwm_off_pin { + mux { + pins = "GPIOH_5"; + function = "gpio_periphs"; + output-high; + }; + }; + +}; /* end of pinctrl_periphs */ + +&pinctrl_aobus { + spdifout: spdifout { + mux { /* gpiao_10 */ + groups = "spdif_out_ao"; + function = "spdif_out_ao"; + }; + }; + + spdifout_a_mute: spdifout_a_mute { + mux { /* gpiao_10 */ + groups = "GPIOAO_10"; + function = "gpio_aobus"; + }; + }; +}; /* end of pinctrl_aobus */ + +&irblaster { + status = "disabled"; +}; + +&audio_data { + status = "okay"; +}; + +/*if you want to use vdin just modify status to "ok"*/ +&vdin0 { + memory-region = <&vdin0_cma_reserved>; + status = "okay"; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + *bit4:support yuv422 10bit full pack mode (from txl new add) + */ + tv_bit_mode = <0x15>; +}; +&vdin1 { + memory-region = <&vdin1_cma_reserved>; + status = "okay"; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + */ + tv_bit_mode = <1>; +}; + +&sd_emmc_c { + status = "okay"; + emmc { + caps = "MMC_CAP_8_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + /* "MMC_CAP_1_8V_DDR", */ + "MMC_CAP_HW_RESET", + "MMC_CAP_ERASE", + "MMC_CAP_CMD23"; + caps2 = "MMC_CAP2_HS200"; + /* "MMC_CAP2_HS400";*/ + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&sd_emmc_b { + status = "okay"; + sd { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED"; + f_min = <400000>; + f_max = <50000000>; + }; +}; + +&sd_emmc_a { + status = "okay"; + sdio { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + "MMC_CAP_UHS_SDR12", + "MMC_CAP_UHS_SDR25", + "MMC_CAP_UHS_SDR50", + "MMC_CAP_UHS_SDR104", + "MMC_PM_KEEP_POWER", + "MMC_CAP_SDIO_IRQ"; + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&nand { + status = "disabled"; + plat-names = "bootloader","nandnormal"; + plat-num = <2>; + plat-part-0 = <&bootloader>; + plat-part-1 = <&nandnormal>; + bootloader: bootloader{ + enable_pad ="ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <1>; + part_num = <0>; + rb_detect = <1>; + }; + nandnormal: nandnormal{ + enable_pad ="ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + plane_mode = "twoplane"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <2>; + part_num = <3>; + partition = <&nand_partitions>; + rb_detect = <1>; + }; + nand_partitions:nand_partition{ + /* + * if bl_mode is 1, tpl size was generate by + * fip_copies * fip_size which + * will not skip bad when calculating + * the partition size; + * + * if bl_mode is 0, + * tpl partition must be comment out. + */ + tpl{ + offset=<0x0 0x0>; + size=<0x0 0x0>; + }; + logo{ + offset=<0x0 0x0>; + size=<0x0 0x200000>; + }; + recovery{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + boot{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + system{ + offset=<0x0 0x0>; + size=<0x0 0x4000000>; + }; + data{ + offset=<0xffffffff 0xffffffff>; + size=<0x0 0x0>; + }; + }; +}; +&dwc3 { + status = "okay"; +}; + +&usb2_phy_v2 { + status = "okay"; + portnum = <2>; +}; + +&usb3_phy_v2 { + status = "okay"; + portnum = <1>; + otg = <1>; + gpio-vbus-power = "GPIOH_6"; + gpios = <&gpio GPIOH_6 GPIO_ACTIVE_HIGH>; +}; + +&dwc2_a { + status = "okay"; + /** 0: normal, 1: otg+dwc3 host only, 2: otg+dwc3 device only*/ + controller-type = <3>; +}; +ðmac { + status = "okay"; + pinctrl-names = "internal_eth_pins"; + pinctrl-0 = <&internal_eth_pins>; + mc_val = <0x4be04>; + + internal_phy=<1>; +}; + +&uart_A { + status = "okay"; +}; + +&pcie_A { + reset-gpio = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; + status = "disable"; +}; + +&saradc { + status = "okay"; +}; + diff --git a/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts index 83937103b82e..c1b36a44699f 100644 --- a/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts +++ b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts @@ -22,6 +22,7 @@ / { model = "Amlogic"; + amlogic-dt-id = "g12b_w400_b"; compatible = "amlogic, g12b"; interrupt-parent = <&gic>; #address-cells = <1>; @@ -44,7 +45,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x100000 0x7ff00000>; + linux,usable-memory = <0x0 0x80000000>; }; reserved-memory { @@ -57,8 +58,7 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { @@ -193,8 +193,6 @@ label="sys_led"; gpios=<&gpio_ao GPIOAO_11 GPIO_ACTIVE_HIGH>; default-state ="on"; - retain-state-suspended; - linux,default-trigger="cpu0"; }; }; @@ -261,6 +259,14 @@ }; }; + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + codec_mm { compatible = "amlogic, codec, mm"; memory-region = <&codec_mm_cma &codec_mm_reserved>; @@ -268,6 +274,13 @@ status = "okay"; }; + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + ppmgr { compatible = "amlogic, ppmgr"; memory-region = <&ppmgr_reserved>; @@ -730,31 +743,31 @@ }; opp04 { opp-hz = /bits/ 64 <1000000000>; - opp-microvolt = <731000>; + opp-microvolt = <761000>; }; opp05 { opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <731000>; + opp-microvolt = <781000>; }; opp06 { opp-hz = /bits/ 64 <1398000000>; - opp-microvolt = <761000>; + opp-microvolt = <811000>; }; opp07 { opp-hz = /bits/ 64 <1512000000>; - opp-microvolt = <791000>; + opp-microvolt = <861000>; }; opp08 { opp-hz = /bits/ 64 <1608000000>; - opp-microvolt = <831000>; + opp-microvolt = <901000>; }; opp09 { opp-hz = /bits/ 64 <1704000000>; - opp-microvolt = <861000>; + opp-microvolt = <951000>; }; opp10 { opp-hz = /bits/ 64 <1800000000>; - opp-microvolt = <981000>; + opp-microvolt = <1001000>; }; }; @@ -764,43 +777,63 @@ opp00 { opp-hz = /bits/ 64 <100000000>; - opp-microvolt = <751000>; + opp-microvolt = <731000>; }; opp01 { opp-hz = /bits/ 64 <250000000>; - opp-microvolt = <751000>; + opp-microvolt = <731000>; }; opp02 { opp-hz = /bits/ 64 <500000000>; - opp-microvolt = <751000>; + opp-microvolt = <731000>; }; opp03 { opp-hz = /bits/ 64 <667000000>; - opp-microvolt = <751000>; + opp-microvolt = <731000>; }; opp04 { opp-hz = /bits/ 64 <1000000000>; - opp-microvolt = <771000>; + opp-microvolt = <731000>; }; opp05 { opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <771000>; + opp-microvolt = <751000>; }; opp06 { opp-hz = /bits/ 64 <1398000000>; - opp-microvolt = <791000>; + opp-microvolt = <771000>; }; opp07 { opp-hz = /bits/ 64 <1512000000>; - opp-microvolt = <821000>; + opp-microvolt = <771000>; }; opp08 { opp-hz = /bits/ 64 <1608000000>; - opp-microvolt = <861000>; + opp-microvolt = <781000>; }; opp09 { opp-hz = /bits/ 64 <1704000000>; - opp-microvolt = <891000>; + opp-microvolt = <791000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <831000>; + }; + opp11 { + opp-hz = /bits/ 64 <1908000000>; + opp-microvolt = <861000>; + }; + opp12 { + opp-hz = /bits/ 64 <2016000000>; + opp-microvolt = <911000>; + }; + opp13 { + opp-hz = /bits/ 64 <2100000000>; + opp-microvolt = <951000>; + }; + opp14 { + opp-hz = /bits/ 64 <2208000000>; + opp-microvolt = <1011000>; }; }; @@ -818,6 +851,8 @@ clocks = <&clkc CLKID_24M>; clock-names = "g12a_24m"; reset = <&gpio GPIOZ_12 GPIO_ACTIVE_HIGH>; + ir_cut_gpio = <&gpio GPIOZ_11 GPIO_ACTIVE_HIGH + &gpio GPIOZ_7 GPIO_ACTIVE_HIGH>; }; iq: iq { @@ -950,8 +985,10 @@ dai-tdm-clk-sel = <1>; clocks = <&clkaudio CLKID_AUDIO_MCLK_B &clkc CLKID_MPLL1 - &clkc CLKID_MPLL0>; - clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; /* @@ -1009,8 +1046,10 @@ ; interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; pinctrl-0 = <&spdifout &spdifin>; + pinctrl-1 = <&spdifout_a_mute>; status = "okay"; }; aml_spdif_b: spdif_b { @@ -1241,6 +1280,13 @@ function = "spdif_out_ao"; }; }; + + spdifout_a_mute: spdifout_a_mute { + mux { /* gpiao_10 */ + groups = "GPIOAO_10"; + function = "gpio_aobus"; + }; + }; }; /* end of pinctrl_aobus */ &irblaster { diff --git a/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_a.dts b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_a.dts new file mode 100644 index 000000000000..c972c12c8a58 --- /dev/null +++ b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_a.dts @@ -0,0 +1,1456 @@ +/* + * arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_a.dts + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +/dts-v1/; + +#include "mesong12b_a.dtsi" +#include "mesong12b_skt-panel.dtsi" + +/ { + model = "Amlogic"; + amlogic-dt-id = "g12b_w400_a"; + compatible = "amlogic, g12b"; + interrupt-parent = <&gic>; + #address-cells = <1>; + #size-cells = <1>; + + aliases { + serial0 = &uart_AO; + serial1 = &uart_A; + serial2 = &uart_B; + serial3 = &uart_C; + serial4 = &uart_AO_B; + i2c0 = &i2c0; + i2c1 = &i2c1; + i2c2 = &i2c2; + i2c3 = &i2c3; + i2c4 = &i2c_AO; + tsensor0 = &p_tsensor; + tsensor1 = &d_tsensor; + }; + + memory@00000000 { + device_type = "memory"; + linux,usable-memory = <0x100000 0x7ff00000>; + }; + + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + /* global autoconfigured region for contiguous allocations */ + ramoops@0x07400000 { + compatible = "ramoops"; + reg = <0x07400000 0x00100000>; + record-size = <0x8000>; + console-size = <0x8000>; + ftrace-size = <0x20000>; + }; + + secmon_reserved:linux,secmon { + compatible = "shared-dma-pool"; + reusable; + size = <0x400000>; + alignment = <0x400000>; + alloc-ranges = <0x05000000 0x400000>; + clear-map; + }; + + secos_reserved:linux,secos { + status = "disable"; + compatible = "amlogic, aml_secos_memory"; + reg = <0x05300000 0x2000000>; + no-map; + }; + logo_reserved:linux,meson-fb { + compatible = "shared-dma-pool"; + reusable; + size = <0x800000>; + alignment = <0x400000>; + alloc-ranges = <0x7f800000 0x800000>; + }; + ion_cma_reserved:linux,ion-dev { + compatible = "shared-dma-pool"; + reusable; + size = <0x8000000>; + alignment = <0x400000>; + }; + + //di_reserved:linux,di { + //compatible = "amlogic, di-mem"; + /* buffer_size = 3621952(yuv422 8bit) */ + /* 4179008(yuv422 10bit full pack mode) */ + /** 10x3621952=34.6M(0x23) support 8bit **/ + /** 10x4736064=45.2M(0x2e) support 12bit **/ + /** 10x4179008=40M(0x28) support 10bit **/ + //size = <0x2800000>; + //no-map; + //}; + /*di CMA pool */ + di_cma_reserved:linux,di_cma { + compatible = "shared-dma-pool"; + reusable; + /* buffer_size = 3621952(yuv422 8bit) + * | 4736064(yuv422 10bit) + * | 4074560(yuv422 10bit full pack mode) + * 10x3621952=34.6M(0x23) support 8bit + * 10x4736064=45.2M(0x2e) support 12bit + * 10x4074560=40M(0x28) support 10bit + */ + size = <0x02800000>; + alignment = <0x400000>; + }; + /* POST PROCESS MANAGER */ + ppmgr_reserved:linux,ppmgr { + compatible = "shared-dma-pool"; + size = <0x0>; + }; + codec_mm_cma:linux,codec_mm_cma { + compatible = "shared-dma-pool"; + reusable; + /* ion_codec_mm max can alloc size 80M*/ + size = <0x13400000>; + alignment = <0x400000>; + linux,contiguous-region; + }; + /* codec shared reserved */ + codec_mm_reserved:linux,codec_mm_reserved { + compatible = "amlogic, codec-mm-reserved"; + size = <0x0>; + alignment = <0x100000>; + //no-map; + }; + /* vdin0 CMA pool */ + vdin0_cma_reserved:linux,vdin0_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16+4 M */ + size = <0x04000000>; + alignment = <0x400000>; + }; + /* vdin1 CMA pool */ + vdin1_cma_reserved:linux,vdin1_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16 M */ + size = <0x04000000>; + alignment = <0x400000>; + }; + galcore_reserved:linux,galcore { + compatible = "shared-dma-pool"; + reusable; + size = <0x1000000>; + alignment = <0x400000>; + linux,contiguous-region; + }; + + isp_cma_reserved:linux,isp_cma { + compatible = "shared-dma-pool"; + reusable; + status = "okay"; + size = <0x1f000000>; + alignment = <0x400000>; + }; + + adapt_cma_reserved:linux,adapt_cma { + compatible = "shared-dma-pool"; + reusable; + status = "okay"; + size = <0x03000000>; + alignment = <0x400000>; + }; + gdc_cma_reserved:linux,gdc_cma { + compatible = "shared-dma-pool"; + reusable; + status = "okay"; + size = <0x04000000>; + alignment = <0x400000>; + }; + }; + galcore { + status = "okay"; + memory-region = <&galcore_reserved>; + }; + gpioleds { + compatible = "gpio-leds"; + status = "okay"; + + sys_led { + label="sys_led"; + gpios=<&gpio_ao GPIOAO_11 GPIO_ACTIVE_HIGH>; + default-state ="on"; + retain-state-suspended; + linux,default-trigger="cpu0"; + }; + }; + + cvbsout { + compatible = "amlogic, cvbsout-g12b"; + dev_name = "cvbsout"; + status = "okay"; + clocks = <&clkc CLKID_VCLK2_ENCI + &clkc CLKID_VCLK2_VENCI0 + &clkc CLKID_VCLK2_VENCI1 + &clkc CLKID_DAC_CLK>; + clock-names = "venci_top_gate", + "venci_0_gate", + "venci_1_gate", + "vdac_clk_gate"; + + /* performance: reg_address, reg_value */ + /* g12b */ + performance = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x8080 + 0x1b05 0xfd + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + performance_sarft = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x0 + 0x1b05 0x9 + 0x1c59 0xfc48 + 0xffff 0x0>; /* ending flag */ + }; + + bt-dev{ + compatible = "amlogic, bt-dev"; + dev_name = "bt-dev"; + status = "okay"; + gpio_reset = <&gpio GPIOX_17 GPIO_ACTIVE_HIGH>; + gpio_hostwake = <&gpio GPIOX_19 GPIO_ACTIVE_HIGH>; + }; + + wifi{ + compatible = "amlogic, aml_wifi"; + dev_name = "aml_wifi"; + status = "okay"; + interrupt_pin = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; + irq_trigger_type = "GPIO_IRQ_LOW"; + power_on_pin = <&gpio GPIOX_6 GPIO_ACTIVE_HIGH>; + dhd_static_buf; //if use bcm wifi, config dhd_static_buf + pinctrl-names = "default"; + pinctrl-0 = <&pwm_e_pins>; + pwm_config = <&wifi_pwm_conf>; + }; + + wifi_pwm_conf:wifi_pwm_conf{ + pwm_channel1_conf { + pwms = <&pwm_ef MESON_PWM_0 30541 0>; + duty-cycle = <15270>; + times = <10>; + }; + pwm_channel2_conf { + pwms = <&pwm_ef MESON_PWM_2 30500 0>; + duty-cycle = <15250>; + times = <12>; + }; + }; + + codec_mm { + compatible = "amlogic, codec, mm"; + memory-region = <&codec_mm_cma &codec_mm_reserved>; + dev_name = "codec_mm"; + status = "okay"; + }; + + ppmgr { + compatible = "amlogic, ppmgr"; + memory-region = <&ppmgr_reserved>; + dev_name = "ppmgr"; + status = "okay"; + }; + + deinterlace { + compatible = "amlogic, deinterlace"; + status = "okay"; + /* 0:use reserved; 1:use cma; 2:use cma as reserved */ + flag_cma = <1>; + //memory-region = <&di_reserved>; + memory-region = <&di_cma_reserved>; + interrupts = <0 46 1 + 0 40 1>; + interrupt-names = "pre_irq", "post_irq"; + clocks = <&clkc CLKID_VPU_CLKB_TMP_COMP>, + <&clkc CLKID_VPU_CLKB_COMP>; + clock-names = "vpu_clkb_tmp_composite", + "vpu_clkb_composite"; + clock-range = <334 667>; + /* buffer-size = <3621952>;(yuv422 8bit) */ + buffer-size = <4074560>;/*yuv422 fullpack*/ + /* reserve-iomap = "true"; */ + /* if enable nr10bit, set nr10bit-support to 1 */ + post-wr-support = <1>; + nr10bit-support = <1>; + nrds-enable = <1>; + pps-enable = <1>; + }; + ionvideo { + compatible = "amlogic, ionvideo"; + dev_name = "ionvideo"; + status = "okay"; + }; + + + partitions: partitions{ + parts = <14>; + part-0 = <&logo>; + part-1 = <&recovery>; + part-2 = <&misc>; + part-3 = <&dto>; + part-4 = <&cri_data>; + part-5 = <¶m>; + part-6 = <&boot>; + part-7 = <&rsv>; + part-8 = <&tee>; + part-9 = <&vendor>; + part-10 = <&odm>; + part-11 = <&system>; + part-12 = <&cache>; + part-13 = <&data>; + + logo:logo{ + pname = "logo"; + size = <0x0 0x800000>; + mask = <1>; + }; + recovery:recovery{ + pname = "recovery"; + size = <0x0 0x1800000>; + mask = <1>; + }; + misc:misc{ + pname = "misc"; + size = <0x0 0x800000>; + mask = <1>; + }; + dto:dto{ + pname = "dto"; + size = <0x0 0x800000>; + mask = <1>; + }; + cri_data:cri_data{ + pname = "cri_data"; + size = <0x0 0x800000>; + mask = <2>; + }; + rsv:rsv{ + pname = "rsv"; + size = <0x0 0x1000000>; + mask = <1>; + }; + param:param{ + pname = "param"; + size = <0x0 0x1000000>; + mask = <2>; + }; + boot:boot{ + pname = "boot"; + size = <0x0 0x1000000>; + mask = <1>; + }; + tee:tee{ + pname = "tee"; + size = <0x0 0x2000000>; + mask = <1>; + }; + vendor:vendor{ + pname = "vendor"; + size = <0x0 0x10000000>; + mask = <1>; + }; + odm:odm{ + pname = "odm"; + size = <0x0 0x10000000>; + mask = <1>; + }; + system:system{ + pname = "system"; + size = <0x0 0x80000000>; + mask = <1>; + }; + cache:cache{ + pname = "cache"; + size = <0x0 0x46000000>; + mask = <2>; + }; + data:data{ + pname = "data"; + size = <0xffffffff 0xffffffff>; + mask = <4>; + }; + }; + + gpio_keypad { + compatible = "amlogic, gpio_keypad"; + status = "okay"; + scan_period = <20>; + key_num = <1>; + key_name = "power"; + key_code = <116>; + key-gpios = <&gpio_ao GPIOAO_3 GPIO_ACTIVE_HIGH>; + detect_mode = <0>;/*0:polling mode, 1:irq mode*/ + }; + + adc_keypad { + compatible = "amlogic, adc_keypad"; + status = "okay"; + key_name = "vol-", "vol+", "enter"; + key_num = <3>; + io-channels = <&saradc SARADC_CH2>; + io-channel-names = "key-chan-2"; + key_chan = ; + key_code = <114 115 28>; + key_val = <143 266 389>; //val=voltage/1800mV*1023 + key_tolerance = <40 40 40>; + }; + + unifykey{ + compatible = "amlogic, unifykey"; + status = "ok"; + unifykey-num = <15>; + unifykey-index-0 = <&keysn_0>; + unifykey-index-1 = <&keysn_1>; + unifykey-index-2 = <&keysn_2>; + unifykey-index-3 = <&keysn_3>; + unifykey-index-4 = <&keysn_4>; + unifykey-index-5 = <&keysn_5>; + unifykey-index-6 = <&keysn_6>; + unifykey-index-7 = <&keysn_7>; + unifykey-index-8 = <&keysn_8>; + unifykey-index-9 = <&keysn_9>; + unifykey-index-10= <&keysn_10>; + unifykey-index-11= <&keysn_11>; + unifykey-index-12= <&keysn_12>; + unifykey-index-13= <&keysn_13>; + unifykey-index-14= <&keysn_14>; + + keysn_0: key_0{ + key-name = "usid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_1:key_1{ + key-name = "mac"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_2:key_2{ + key-name = "hdcp"; + key-device = "secure"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_3:key_3{ + key-name = "secure_boot_set"; + key-device = "efuse"; + key-permit = "write"; + }; + keysn_4:key_4{ + key-name = "mac_bt"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_5:key_5{ + key-name = "mac_wifi"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_6:key_6{ + key-name = "hdcp2_tx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_7:key_7{ + key-name = "hdcp2_rx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_8:key_8{ + key-name = "widevinekeybox"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_9:key_9{ + key-name = "deviceid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_10:key_10{ + key-name = "hdcp22_fw_private"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_11:key_11{ + key-name = "PlayReadykeybox25"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_12:key_12{ + key-name = "prpubkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_13:key_13{ + key-name = "prprivkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_14:key_14{ + key-name = "netflix_mgkid"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + };//End unifykey + + amlvecm { + compatible = "amlogic, vecm"; + dev_name = "aml_vecm"; + status = "okay"; + gamma_en = <0>;/*1:enabel ;0:disable*/ + wb_en = <0>;/*1:enabel ;0:disable*/ + cm_en = <0>;/*1:enabel ;0:disable*/ + }; + amdolby_vision { + compatible = "amlogic, dolby_vision_g12a"; + dev_name = "aml_amdolby_vision_driver"; + status = "okay"; + tv_mode = <0>;/*1:enabel ;0:disable*/ + }; + + /* Audio Related start */ + pdm_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, pdm_dummy_codec"; + status = "okay"; + }; + dummy_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, aml_dummy_codec"; + status = "okay"; + }; + amlogic_codec:t9015{ + #sound-dai-cells = <0>; + compatible = "amlogic, aml_codec_T9015"; + reg = <0xFF632000 0x2000>; + is_auge_used = <1>; /* meson or auge chipset used */ + tdmout_index = <1>; + status = "okay"; + }; + audio_effect:eqdrc{ + /*eq_enable = <1>;*/ + /*drc_enable = <1>;*/ + /* + * 0:tdmout_a + * 1:tdmout_b + * 2:tdmout_c + * 3:spdifout + * 4:spdifout_b + */ + eqdrc_module = <1>; + /* max 0xf, each bit for one lane, usually one lane */ + lane_mask = <0x1>; + /* max 0xff, each bit for one channel */ + channel_mask = <0x3>; + }; + auge_sound { + compatible = "amlogic, g12a-sound-card"; + aml-audio-card,name = "AML-AUGESOUND"; + + //aml-audio-card,loopback = <&aml_loopback>; + //aml-audio-card,aux-devs = <&amlogic_codec>; + /*avout mute gpio*/ + avout_mute-gpios = <&gpio_ao GPIOAO_2 GPIO_ACTIVE_HIGH>; + /*for audio effect ,eqdrc */ + aml-audio-card,effect = <&audio_effect>; + + aml-audio-card,dai-link@0 { + format = "dsp_a"; + mclk-fs = <512>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + //bitclock-master = <&tdmacodec>; + //frame-master = <&tdmacodec>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-pcm"; + tdmacpu: cpu { + sound-dai = <&aml_tdma>; + dai-tdm-slot-tx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-rx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-num = <8>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <24576000>; + }; + tdmacodec: codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@1 { + format = "i2s"; + mclk-fs = <256>; + continuous-clock; + //bitclock-inversion; + //frame-inversion; + bitclock-master = <&aml_tdmb>; + frame-master = <&aml_tdmb>; + //bitclock-master = <&tdmbcodec>; + //frame-master = <&tdmbcodec>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-i2s"; + cpu { + sound-dai = <&aml_tdmb>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmbcodec: codec { + sound-dai = <&dummy_codec &dummy_codec + &amlogic_codec &ad82584f_62>; + }; + }; + + aml-audio-card,dai-link@2 { + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + bitclock-master = <&aml_tdmc>; + frame-master = <&aml_tdmc>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + //suffix-name = "alsaPORT-tdm"; + cpu { + sound-dai = <&aml_tdmc>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@3 { + mclk-fs = <64>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-pdm"; + cpu { + sound-dai = <&aml_pdm>; + }; + codec { + sound-dai = <&pdm_codec>; + }; + }; + + aml-audio-card,dai-link@4 { + mclk-fs = <128>; + continuous-clock; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-spdif"; + cpu { + sound-dai = <&aml_spdif>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + }; + audiolocker: locker { + compatible = "amlogic, audiolocker"; + clocks = <&clkaudio CLKID_AUDIO_LOCKER_OUT + &clkaudio CLKID_AUDIO_LOCKER_IN + &clkaudio CLKID_AUDIO_MCLK_D + &clkaudio CLKID_AUDIO_MCLK_E + &clkc CLKID_MPLL1 + &clkc CLKID_MPLL2>; + clock-names = "lock_out", "lock_in", "out_src", + "in_src", "out_calc", "in_ref"; + interrupts = ; + interrupt-names = "irq"; + frequency = <49000000>; /* pll */ + dividor = <49>; /* locker's parent */ + status = "okay"; + }; + /* Audio Related end */ + + cpu_opp_table0: cpu_opp_table0 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <731000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <731000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <731000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <731000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <731000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <731000>; + }; + opp06 { + opp-hz = /bits/ 64 <1398000000>; + opp-microvolt = <761000>; + }; + opp07 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <791000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <831000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <861000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <981000>; + }; + }; + + cpu_opp_table1: cpu_opp_table1 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <751000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <751000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <751000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <751000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <771000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <771000>; + }; + opp06 { + opp-hz = /bits/ 64 <1398000000>; + opp-microvolt = <791000>; + }; + opp07 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <821000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <861000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <891000>; + }; + }; + + cpufreq-meson { + compatible = "amlogic, cpufreq-meson"; + status = "okay"; + }; + + sensor: sensor { + compatible = "soc, sensor"; + status = "okay"; + sensor-name = "imx290"; /*imx290;os08a10;imx227*/ + pinctrl-names="default"; + pinctrl-0=<&clk12_24_z_pins>; + clocks = <&clkc CLKID_24M>; + clock-names = "g12a_24m"; + reset = <&gpio GPIOZ_12 GPIO_ACTIVE_HIGH>; + ir_cut_gpio = <&gpio GPIOZ_11 GPIO_ACTIVE_HIGH + &gpio GPIOZ_7 GPIO_ACTIVE_HIGH>; + }; + + iq: iq { + compatible = "soc, iq"; + status = "okay"; + sensor-name = "imx290"; /*imx290;os08a10;imx227*/ + }; +}; /* end of / */ + +&i2c2 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&i2c2_master_pins2>; + clock-frequency = <100000>; /* default 100k */ + sensor-i2c@6c { + compatible = "arm, i2c-sensor"; + reg = <0x6c>; + reg-names = "i2c-sensor"; + slave-addr = <0x6c>; + reg-type = <2>; + reg-data-type = <1>; + link-device = <&phycsi>; + }; +}; + +&isp { + status = "okay"; + memory-region = <&isp_cma_reserved>; +}; + +&adapter { + status = "okay"; + memory-region = <&adapt_cma_reserved>; +}; + +&gdc { + status = "okay"; + memory-region = <&gdc_cma_reserved>; +}; + +&meson_fb { + status = "okay"; + display_size_default = <1920 1080 1920 2160 32>; + mem_size = <0x00800000 0x1980000 0x100000 0x100000 0x800000>; + logo_addr = "0x7f800000"; + mem_alloc = <1>; + pxp_mode = <0>; /** 0:normal mode 1:pxp mode */ +}; + +&pwm_ab { + status = "okay"; + }; + +&pwm_ef { + status = "okay"; + }; + +&pwm_AO_cd { + status = "okay"; + }; + +&i2c0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_master_pins2>; + clock-frequency = <400000>; + + touchscreen@38 { + compatible = "focaltech,fts"; + status = "disabled"; + reg = <0x38>; + reset-gpio = <&gpio GPIOZ_9 GPIO_ACTIVE_HIGH>; + irq-gpio = <&gpio GPIOZ_3 GPIO_ACTIVE_HIGH>; + x_max = <720>; + y_max = <1280>; + max-touch-number = <10>; + }; +}; + +&i2c3 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&i2c3_master_pins2>; + clock-frequency = <100000>; /* default 100k */ + + /* for ref board */ + ad82584f_62: ad82584f_62@62 { + compatible = "ESMT, ad82584f"; + #sound-dai-cells = <0>; + reg = <0x31>; + status = "okay"; + reset_pin = <&gpio GPIOA_5 0>; + }; + + tlv320adc3101_32: tlv320adc3101_32@32 { + compatible = "ti,tlv320adc3101"; + #sound-dai-cells = <0>; + reg = <0x19>; + differential_pair = <1>; + status = "disabled"; + }; + + bl_extern_i2c { + compatible = "bl_extern, i2c"; + dev_name = "lp8556"; + reg = <0x2c>; + status = "disabled"; + }; +}; + +&audiobus { + aml_tdma: tdma { + compatible = "amlogic, g12a-snd-tdma"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 1>; + dai-tdm-oe-lane-slot-mask-out = <1 0>; + dai-tdm-clk-sel = <0>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_A + &clkc CLKID_MPLL0>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmout_a &tdmin_a>; + }; + + aml_tdmb: tdmb { + compatible = "amlogic, g12a-snd-tdmb"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 1 0 0>; + dai-tdm-lane-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <1>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_B + &clkc CLKID_MPLL1 + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; + /* + * 0: tdmout_a; + * 1: tdmout_b; + * 2: tdmout_c; + * 3: spdifout; + * 4: spdifout_b; + */ + samesource_sel = <3>; + }; + + aml_tdmc: tdmc { + compatible = "amlogic, g12a-snd-tdmc"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <1 0 0 0>; + #dai-tdm-lane-slot-mask-out = <1 0 1 1>; + #dai-tdm-lane-oe-slot-mask-in = <0 0 0 0>; + #dai-tdm-lane-oe-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <2>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmc_mclk &tdmout_c &tdmin_c>; + }; + + /* copy a useless tdm to output for hdmi, no pinmux */ + aml_i2s2hdmi: i2s2hdmi { + compatible = "amlogic, g12a-snd-tdmc"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-out = <1 1 1 1>; + dai-tdm-clk-sel = <2>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + + i2s2hdmi = <1>; + + status = "okay"; + }; + + aml_spdif: spdif { + compatible = "amlogic, g12a-snd-spdif-a"; + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 + &clkc CLKID_FCLK_DIV4 + &clkaudio CLKID_AUDIO_SPDIFIN + &clkaudio CLKID_AUDIO_SPDIFOUT + &clkaudio CLKID_AUDIO_SPDIFIN_CTRL + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "sysclk", "fixed_clk", "gate_spdifin", + "gate_spdifout", "clk_spdifin", "clk_spdifout"; + interrupts = + ; + + interrupt-names = "irq_spdifin"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; + pinctrl-0 = <&spdifout &spdifin>; + pinctrl-1 = <&spdifout_a_mute>; + status = "okay"; + }; + aml_spdif_b: spdif_b { + compatible = "amlogic, g12a-snd-spdif-b"; + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 /*CLKID_HIFI_PLL*/ + &clkaudio CLKID_AUDIO_SPDIFOUTB + &clkaudio CLKID_AUDIO_SPDIFOUTB_CTRL>; + clock-names = "sysclk", + "gate_spdifout", "clk_spdifout"; + status = "disabled"; + }; + aml_pdm: pdm { + compatible = "amlogic, g12a-snd-pdm"; + #sound-dai-cells = <0>; + clocks = <&clkaudio CLKID_AUDIO_PDM + &clkc CLKID_FCLK_DIV3 + &clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_PDMIN0 + &clkaudio CLKID_AUDIO_PDMIN1>; + clock-names = "gate", + "sysclk_srcpll", + "dclk_srcpll", + "pdm_dclk", + "pdm_sysclk"; + pinctrl-names = "pdm_pins"; + pinctrl-0 = <&pdmin>; + filter_mode = <1>; /* mode 0~4, defalut:1 */ + status = "okay"; + }; + aml_loopback: loopback { + compatible = "amlogic, snd-loopback"; + /* + * 0: out rate = in data rate; + * 1: out rate = loopback data rate; + */ + lb_mode = <0>; + + /* datain src + * 0: tdmin_a; + * 1: tdmin_b; + * 2: tdmin_c; + * 3: spdifin; + * 4: pdmin; + */ + datain_src = <4>; + datain_chnum = <8>; + datain_chmask = <0x3f>; + + /* tdmin_lb src + * 0: tdmoutA + * 1: tdmoutB + * 2: tdmoutC + * 3: PAD_tdminA + * 4: PAD_tdminB + * 5: PAD_tdminC + */ + datalb_src = <2>; + datalb_chnum = <8>; + datalb_chmask = <0x3>; + + status = "disabled"; + }; + + audioresample: resample { + compatible = "amlogic, g12a-resample"; + clocks = <&clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_MCLK_F + &clkaudio CLKID_AUDIO_RESAMPLE_CTRL>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + /*same with toddr_src + * TDMIN_A, 0 + * TDMIN_B, 1 + * TDMIN_C, 2 + * SPDIFIN, 3 + * PDMIN, 4 + * NONE, + * TDMIN_LB, 6 + * LOOPBACK, 7 + */ + resample_module = <4>; + status = "disabled"; + }; + aml_pwrdet: pwrdet { + compatible = "amlogic, g12a-power-detect"; + + interrupts = ; + interrupt-names = "pwrdet_irq"; + + /* pwrdet source sel + * 7: loopback; + * 6: tdmin_lb; + * 5: reserved; + * 4: pdmin; + * 3: spdifin; + * 2: tdmin_c; + * 1: tdmin_b; + * 0: tdmin_a; + */ + pwrdet_src = <4>; + + hi_th = <0x70000>; + lo_th = <0x16000>; + + status = "disabled"; + }; +}; /* end of audiobus */ + +&pinctrl_periphs { + tdmout_a: tdmout_a { + mux { /* GPIOX_11, GPIOX_10, GPIOX_9 */ + groups = "tdma_sclk", + "tdma_fs", + "tdma_dout0"; + function = "tdma_out"; + }; + }; + + tdmin_a: tdmin_a { + mux { /* GPIOX_8 */ + groups = "tdma_din1"; + function = "tdma_in"; + }; + }; + + tdmb_mclk: tdmb_mclk { + mux { + groups = "mclk0_a"; + function = "mclk0"; + drive-strength = <2>; + }; + }; + tdmout_b: tdmout_b { + mux { /* GPIOA_1, GPIOA_2, GPIOA_3 */ + groups = "tdmb_sclk", + "tdmb_fs", + "tdmb_dout0"; + function = "tdmb_out"; + drive-strength = <2>; + }; + }; + + tdmin_b:tdmin_b { + mux { /* GPIOA_4 */ + groups = "tdmb_din1" + /*,"tdmb_slv_sclk", "tdmb_slv_fs"*/; + function = "tdmb_in"; + drive-strength = <2>; + }; + }; + + tdmc_mclk: tdmc_mclk { + mux { /* GPIOA_11 */ + groups = "mclk1_a"; + function = "mclk1"; + }; + }; + + clk12_24_z_pins:clk12_24_z_pins { + mux { + groups = "clk12_24_z"; + function = "clk12_24_ee"; + drive-strength = <3>; + }; + }; + + tdmout_c:tdmout_c { + mux { /* GPIOA_12, GPIOA_13, GPIOA_8, GPIOA_7*/ + groups = "tdmc_sclk_a", + "tdmc_fs_a", + "tdmc_dout0_a" + /*, "tdmc_dout2", + * "tdmc_dout3" + */; + function = "tdmc_out"; + }; + }; + + tdmin_c:tdmin_c { + mux { /* GPIOA_10 */ + groups = "tdmc_din0_a"; + function = "tdmc_in"; + }; + }; + + spdifin: spdifin { + mux {/* GPIOH_5 */ + groups = "spdif_in_h"; + function = "spdif_in"; + }; + }; + + /* GPIOH_4 */ + /* + * spdifout: spdifout { + * mux { + * groups = "spdif_out_h"; + * function = "spdif_out"; + * }; + *}; + */ + + pdmin: pdmin { + mux { /* gpioa_5, gpioa_6, gpioa_7, gpioa_8, gpioa_9*/ + groups = "pdm_din0_a", + /*"pdm_din1_a",*/ + "pdm_din2_a", + /*"pdm_din3_a",*/ + "pdm_dclk_a"; + function = "pdm"; + }; + }; + + bl_pwm_off_pins:bl_pwm_off_pin { + mux { + pins = "GPIOH_5"; + function = "gpio_periphs"; + output-high; + }; + }; + +}; /* end of pinctrl_periphs */ + +&pinctrl_aobus { + spdifout: spdifout { + mux { /* gpiao_10 */ + groups = "spdif_out_ao"; + function = "spdif_out_ao"; + }; + }; + + spdifout_a_mute: spdifout_a_mute { + mux { /* gpiao_10 */ + groups = "GPIOAO_10"; + function = "gpio_aobus"; + }; + }; +}; /* end of pinctrl_aobus */ + +&irblaster { + status = "disabled"; +}; + +&audio_data { + status = "okay"; +}; + +/*if you want to use vdin just modify status to "ok"*/ +&vdin0 { + memory-region = <&vdin0_cma_reserved>; + status = "okay"; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + *bit4:support yuv422 10bit full pack mode (from txl new add) + */ + tv_bit_mode = <0x15>; +}; +&vdin1 { + memory-region = <&vdin1_cma_reserved>; + status = "okay"; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + */ + tv_bit_mode = <1>; +}; + +&sd_emmc_c { + status = "okay"; + emmc { + caps = "MMC_CAP_8_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + /* "MMC_CAP_1_8V_DDR", */ + "MMC_CAP_HW_RESET", + "MMC_CAP_ERASE", + "MMC_CAP_CMD23"; + caps2 = "MMC_CAP2_HS200"; + /* "MMC_CAP2_HS400";*/ + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&sd_emmc_b { + status = "okay"; + sd { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED"; + f_min = <400000>; + f_max = <50000000>; + }; +}; + +&sd_emmc_a { + status = "okay"; + sdio { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + "MMC_CAP_UHS_SDR12", + "MMC_CAP_UHS_SDR25", + "MMC_CAP_UHS_SDR50", + "MMC_CAP_UHS_SDR104", + "MMC_PM_KEEP_POWER", + "MMC_CAP_SDIO_IRQ"; + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&nand { + status = "disabled"; + plat-names = "bootloader","nandnormal"; + plat-num = <2>; + plat-part-0 = <&bootloader>; + plat-part-1 = <&nandnormal>; + bootloader: bootloader{ + enable_pad ="ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <1>; + part_num = <0>; + rb_detect = <1>; + }; + nandnormal: nandnormal{ + enable_pad ="ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + plane_mode = "twoplane"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <2>; + part_num = <3>; + partition = <&nand_partitions>; + rb_detect = <1>; + }; + nand_partitions:nand_partition{ + /* + * if bl_mode is 1, tpl size was generate by + * fip_copies * fip_size which + * will not skip bad when calculating + * the partition size; + * + * if bl_mode is 0, + * tpl partition must be comment out. + */ + tpl{ + offset=<0x0 0x0>; + size=<0x0 0x0>; + }; + logo{ + offset=<0x0 0x0>; + size=<0x0 0x200000>; + }; + recovery{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + boot{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + system{ + offset=<0x0 0x0>; + size=<0x0 0x4000000>; + }; + data{ + offset=<0xffffffff 0xffffffff>; + size=<0x0 0x0>; + }; + }; +}; +&dwc3 { + status = "okay"; +}; + +&usb2_phy_v2 { + status = "okay"; + portnum = <2>; +}; + +&usb3_phy_v2 { + status = "okay"; + portnum = <0>; + otg = <1>; + gpio-vbus-power = "GPIOH_6"; + gpios = <&gpio GPIOH_6 GPIO_ACTIVE_HIGH>; +}; + +&dwc2_a { + status = "okay"; + /** 0: normal, 1: otg+dwc3 host only, 2: otg+dwc3 device only*/ + controller-type = <3>; +}; +ðmac { + status = "okay"; +/* //conflict with isp i2c + * pinctrl-names = "internal_eth_pins"; + * pinctrl-0 = <&internal_eth_pins>; + */ + mc_val = <0x4be04>; + + internal_phy=<1>; +}; + +&uart_A { + status = "okay"; +}; + +&pcie_A { + reset-gpio = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; + status = "okay"; +}; + +&saradc { + status = "okay"; +}; + +&spicc1 { + status = "disabled"; + pinctrl-names = "default"; + pinctrl-0 = <&spicc1_pins>; + cs-gpios = <&gpio GPIOH_6 0>; +}; diff --git a/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest.dts b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest.dts index b1b2676c8b2b..8e469c08a44d 100644 --- a/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest.dts +++ b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest.dts @@ -22,6 +22,7 @@ / { model = "Amlogic"; + amlogic-dt-id = "g12b_w400_b"; compatible = "amlogic, g12b"; interrupt-parent = <&gic>; #address-cells = <1>; @@ -44,7 +45,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x100000 0x7ff00000>; + linux,usable-memory = <0x0 0x80000000>; }; reserved-memory { @@ -57,10 +58,8 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; - secmon_reserved:linux,secmon { compatible = "shared-dma-pool"; reusable; @@ -159,8 +158,6 @@ label="sys_led"; gpios=<&gpio_ao GPIOAO_11 GPIO_ACTIVE_HIGH>; default-state ="on"; - retain-state-suspended; - linux,default-trigger="cpu0"; }; }; @@ -227,6 +224,14 @@ }; }; + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + codec_mm { compatible = "amlogic, codec, mm"; memory-region = <&codec_mm_cma &codec_mm_reserved>; @@ -234,6 +239,13 @@ status = "okay"; }; + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + ppmgr { compatible = "amlogic, ppmgr"; memory-region = <&ppmgr_reserved>; @@ -695,39 +707,31 @@ }; opp04 { opp-hz = /bits/ 64 <1000000000>; - opp-microvolt = <731000>; + opp-microvolt = <761000>; }; opp05 { opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <731000>; + opp-microvolt = <781000>; }; opp06 { opp-hz = /bits/ 64 <1398000000>; - opp-microvolt = <761000>; + opp-microvolt = <811000>; }; opp07 { opp-hz = /bits/ 64 <1512000000>; - opp-microvolt = <791000>; + opp-microvolt = <861000>; }; opp08 { opp-hz = /bits/ 64 <1608000000>; - opp-microvolt = <831000>; + opp-microvolt = <901000>; }; opp09 { opp-hz = /bits/ 64 <1704000000>; - opp-microvolt = <861000>; + opp-microvolt = <951000>; }; opp10 { - opp-hz = /bits/ 64 <1896000000>; - opp-microvolt = <981000>; - }; - opp11 { - opp-hz = /bits/ 64 <2016000000>; - opp-microvolt = <1011000>; - }; - opp12 { - opp-hz = /bits/ 64 <2100000000>; - opp-microvolt = <1011000>; + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <1001000>; }; }; @@ -737,54 +741,62 @@ opp00 { opp-hz = /bits/ 64 <100000000>; - opp-microvolt = <751000>; + opp-microvolt = <731000>; }; opp01 { opp-hz = /bits/ 64 <250000000>; - opp-microvolt = <751000>; + opp-microvolt = <731000>; }; opp02 { opp-hz = /bits/ 64 <500000000>; - opp-microvolt = <751000>; + opp-microvolt = <731000>; }; opp03 { opp-hz = /bits/ 64 <667000000>; - opp-microvolt = <751000>; + opp-microvolt = <731000>; }; opp04 { opp-hz = /bits/ 64 <1000000000>; - opp-microvolt = <771000>; + opp-microvolt = <731000>; }; opp05 { opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <771000>; + opp-microvolt = <751000>; }; opp06 { opp-hz = /bits/ 64 <1398000000>; - opp-microvolt = <791000>; + opp-microvolt = <771000>; }; opp07 { opp-hz = /bits/ 64 <1512000000>; - opp-microvolt = <821000>; + opp-microvolt = <771000>; }; opp08 { opp-hz = /bits/ 64 <1608000000>; - opp-microvolt = <861000>; + opp-microvolt = <781000>; }; opp09 { opp-hz = /bits/ 64 <1704000000>; - opp-microvolt = <891000>; + opp-microvolt = <791000>; }; opp10 { opp-hz = /bits/ 64 <1800000000>; - opp-microvolt = <1011000>; + opp-microvolt = <831000>; }; opp11 { opp-hz = /bits/ 64 <1908000000>; - opp-microvolt = <1011000>; + opp-microvolt = <861000>; }; opp12 { opp-hz = /bits/ 64 <2016000000>; + opp-microvolt = <911000>; + }; + opp13 { + opp-hz = /bits/ 64 <2100000000>; + opp-microvolt = <951000>; + }; + opp14 { + opp-hz = /bits/ 64 <2208000000>; opp-microvolt = <1011000>; }; }; @@ -864,8 +876,10 @@ dai-tdm-clk-sel = <1>; clocks = <&clkaudio CLKID_AUDIO_MCLK_B &clkc CLKID_MPLL1 - &clkc CLKID_MPLL0>; - clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; /* @@ -923,8 +937,10 @@ ; interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; pinctrl-0 = <&spdifout &spdifin>; + pinctrl-1 = <&spdifout_a_mute>; status = "okay"; }; aml_spdif_b: spdif_b { @@ -1147,6 +1163,13 @@ function = "spdif_out_ao"; }; }; + + spdifout_a_mute: spdifout_a_mute { + mux { /* gpiao_10 */ + groups = "GPIOAO_10"; + function = "gpio_aobus"; + }; + }; }; /* end of pinctrl_aobus */ &irblaster { diff --git a/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest_a.dts b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest_a.dts new file mode 100644 index 000000000000..7edfad7e86b7 --- /dev/null +++ b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest_a.dts @@ -0,0 +1,1351 @@ +/* + * arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest_a.dts + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +/dts-v1/; + +#include "mesong12b_a.dtsi" +#include "mesong12b_skt-panel.dtsi" + +/ { + model = "Amlogic"; + amlogic-dt-id = "g12b_w400_a"; + compatible = "amlogic, g12b"; + interrupt-parent = <&gic>; + #address-cells = <1>; + #size-cells = <1>; + + aliases { + serial0 = &uart_AO; + serial1 = &uart_A; + serial2 = &uart_B; + serial3 = &uart_C; + serial4 = &uart_AO_B; + i2c0 = &i2c0; + i2c1 = &i2c1; + i2c2 = &i2c2; + i2c3 = &i2c3; + i2c4 = &i2c_AO; + tsensor0 = &p_tsensor; + tsensor1 = &d_tsensor; + }; + + memory@00000000 { + device_type = "memory"; + linux,usable-memory = <0x100000 0x7ff00000>; + }; + + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + /* global autoconfigured region for contiguous allocations */ + ramoops@0x07400000 { + compatible = "ramoops"; + reg = <0x07400000 0x00100000>; + record-size = <0x8000>; + console-size = <0x8000>; + ftrace-size = <0x20000>; + }; + + secmon_reserved:linux,secmon { + compatible = "shared-dma-pool"; + reusable; + size = <0x400000>; + alignment = <0x400000>; + alloc-ranges = <0x05000000 0x400000>; + }; + + secos_reserved:linux,secos { + status = "disable"; + compatible = "amlogic, aml_secos_memory"; + reg = <0x05300000 0x2000000>; + no-map; + }; + logo_reserved:linux,meson-fb { + compatible = "shared-dma-pool"; + reusable; + size = <0x800000>; + alignment = <0x400000>; + alloc-ranges = <0x7f800000 0x800000>; + }; + ion_cma_reserved:linux,ion-dev { + compatible = "shared-dma-pool"; + reusable; + size = <0x8000000>; + alignment = <0x400000>; + }; + + //di_reserved:linux,di { + //compatible = "amlogic, di-mem"; + /* buffer_size = 3621952(yuv422 8bit) */ + /* 4179008(yuv422 10bit full pack mode) */ + /** 10x3621952=34.6M(0x23) support 8bit **/ + /** 10x4736064=45.2M(0x2e) support 12bit **/ + /** 10x4179008=40M(0x28) support 10bit **/ + //size = <0x2800000>; + //no-map; + //}; + /*di CMA pool */ + di_cma_reserved:linux,di_cma { + compatible = "shared-dma-pool"; + reusable; + /* buffer_size = 3621952(yuv422 8bit) + * | 4736064(yuv422 10bit) + * | 4074560(yuv422 10bit full pack mode) + * 10x3621952=34.6M(0x23) support 8bit + * 10x4736064=45.2M(0x2e) support 12bit + * 10x4074560=40M(0x28) support 10bit + */ + size = <0x02800000>; + alignment = <0x400000>; + }; + /* POST PROCESS MANAGER */ + ppmgr_reserved:linux,ppmgr { + compatible = "shared-dma-pool"; + size = <0x0>; + }; + codec_mm_cma:linux,codec_mm_cma { + compatible = "shared-dma-pool"; + reusable; + /* ion_codec_mm max can alloc size 80M*/ + size = <0x13400000>; + alignment = <0x400000>; + linux,contiguous-region; + }; + /* codec shared reserved */ + codec_mm_reserved:linux,codec_mm_reserved { + compatible = "amlogic, codec-mm-reserved"; + size = <0x0>; + alignment = <0x100000>; + //no-map; + }; + /* vdin0 CMA pool */ + vdin0_cma_reserved:linux,vdin0_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16+4 M */ + size = <0x04000000>; + alignment = <0x400000>; + }; + /* vdin1 CMA pool */ + vdin1_cma_reserved:linux,vdin1_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16 M */ + size = <0x04000000>; + alignment = <0x400000>; + }; + }; + + gpioleds { + compatible = "gpio-leds"; + status = "okay"; + + sys_led { + label="sys_led"; + gpios=<&gpio_ao GPIOAO_11 GPIO_ACTIVE_HIGH>; + default-state ="on"; + retain-state-suspended; + linux,default-trigger="cpu0"; + }; + }; + + cvbsout { + compatible = "amlogic, cvbsout-g12b"; + dev_name = "cvbsout"; + status = "okay"; + clocks = <&clkc CLKID_VCLK2_ENCI + &clkc CLKID_VCLK2_VENCI0 + &clkc CLKID_VCLK2_VENCI1 + &clkc CLKID_DAC_CLK>; + clock-names = "venci_top_gate", + "venci_0_gate", + "venci_1_gate", + "vdac_clk_gate"; + + /* performance: reg_address, reg_value */ + /* g12b */ + performance = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x8080 + 0x1b05 0xfd + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + performance_sarft = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x0 + 0x1b05 0x9 + 0x1c59 0xfc48 + 0xffff 0x0>; /* ending flag */ + }; + + bt-dev{ + compatible = "amlogic, bt-dev"; + dev_name = "bt-dev"; + status = "okay"; + gpio_reset = <&gpio GPIOX_17 GPIO_ACTIVE_HIGH>; + gpio_hostwake = <&gpio GPIOX_19 GPIO_ACTIVE_HIGH>; + }; + + wifi{ + compatible = "amlogic, aml_wifi"; + dev_name = "aml_wifi"; + status = "okay"; + interrupt_pin = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; + irq_trigger_type = "GPIO_IRQ_LOW"; + power_on_pin = <&gpio GPIOX_6 GPIO_ACTIVE_HIGH>; + dhd_static_buf; //if use bcm wifi, config dhd_static_buf + pinctrl-names = "default"; + pinctrl-0 = <&pwm_e_pins>; + pwm_config = <&wifi_pwm_conf>; + }; + + wifi_pwm_conf:wifi_pwm_conf{ + pwm_channel1_conf { + pwms = <&pwm_ef MESON_PWM_0 30541 0>; + duty-cycle = <15270>; + times = <10>; + }; + pwm_channel2_conf { + pwms = <&pwm_ef MESON_PWM_2 30500 0>; + duty-cycle = <15250>; + times = <12>; + }; + }; + + codec_mm { + compatible = "amlogic, codec, mm"; + memory-region = <&codec_mm_cma &codec_mm_reserved>; + dev_name = "codec_mm"; + status = "okay"; + }; + + ppmgr { + compatible = "amlogic, ppmgr"; + memory-region = <&ppmgr_reserved>; + dev_name = "ppmgr"; + status = "okay"; + }; + + deinterlace { + compatible = "amlogic, deinterlace"; + status = "okay"; + /* 0:use reserved; 1:use cma; 2:use cma as reserved */ + flag_cma = <1>; + //memory-region = <&di_reserved>; + memory-region = <&di_cma_reserved>; + interrupts = <0 46 1 + 0 40 1>; + interrupt-names = "pre_irq", "post_irq"; + clocks = <&clkc CLKID_VPU_CLKB_TMP_COMP>, + <&clkc CLKID_VPU_CLKB_COMP>; + clock-names = "vpu_clkb_tmp_composite", + "vpu_clkb_composite"; + clock-range = <334 667>; + /* buffer-size = <3621952>;(yuv422 8bit) */ + buffer-size = <4074560>;/*yuv422 fullpack*/ + /* reserve-iomap = "true"; */ + /* if enable nr10bit, set nr10bit-support to 1 */ + post-wr-support = <1>; + nr10bit-support = <1>; + nrds-enable = <1>; + pps-enable = <1>; + }; + ionvideo { + compatible = "amlogic, ionvideo"; + dev_name = "ionvideo"; + status = "okay"; + }; + + + partitions: partitions{ + parts = <14>; + part-0 = <&logo>; + part-1 = <&recovery>; + part-2 = <&misc>; + part-3 = <&dto>; + part-4 = <&cri_data>; + part-5 = <¶m>; + part-6 = <&boot>; + part-7 = <&rsv>; + part-8 = <&tee>; + part-9 = <&vendor>; + part-10 = <&odm>; + part-11 = <&system>; + part-12 = <&cache>; + part-13 = <&data>; + + logo:logo{ + pname = "logo"; + size = <0x0 0x800000>; + mask = <1>; + }; + recovery:recovery{ + pname = "recovery"; + size = <0x0 0x1800000>; + mask = <1>; + }; + misc:misc{ + pname = "misc"; + size = <0x0 0x800000>; + mask = <1>; + }; + dto:dto{ + pname = "dto"; + size = <0x0 0x800000>; + mask = <1>; + }; + cri_data:cri_data{ + pname = "cri_data"; + size = <0x0 0x800000>; + mask = <2>; + }; + rsv:rsv{ + pname = "rsv"; + size = <0x0 0x1000000>; + mask = <1>; + }; + param:param{ + pname = "param"; + size = <0x0 0x1000000>; + mask = <2>; + }; + boot:boot{ + pname = "boot"; + size = <0x0 0x1000000>; + mask = <1>; + }; + tee:tee{ + pname = "tee"; + size = <0x0 0x2000000>; + mask = <1>; + }; + vendor:vendor{ + pname = "vendor"; + size = <0x0 0x10000000>; + mask = <1>; + }; + odm:odm{ + pname = "odm"; + size = <0x0 0x10000000>; + mask = <1>; + }; + system:system{ + pname = "system"; + size = <0x0 0x80000000>; + mask = <1>; + }; + cache:cache{ + pname = "cache"; + size = <0x0 0x46000000>; + mask = <2>; + }; + data:data{ + pname = "data"; + size = <0xffffffff 0xffffffff>; + mask = <4>; + }; + }; + + gpio_keypad { + compatible = "amlogic, gpio_keypad"; + status = "okay"; + scan_period = <20>; + key_num = <1>; + key_name = "power"; + key_code = <116>; + key-gpios = <&gpio_ao GPIOAO_3 GPIO_ACTIVE_HIGH>; + detect_mode = <0>;/*0:polling mode, 1:irq mode*/ + }; + + adc_keypad { + compatible = "amlogic, adc_keypad"; + status = "okay"; + key_name = "vol-", "vol+", "enter"; + key_num = <3>; + io-channels = <&saradc SARADC_CH2>; + io-channel-names = "key-chan-2"; + key_chan = ; + key_code = <114 115 28>; + key_val = <143 266 389>; //val=voltage/1800mV*1023 + key_tolerance = <40 40 40>; + }; + + unifykey{ + compatible = "amlogic, unifykey"; + status = "ok"; + unifykey-num = <15>; + unifykey-index-0 = <&keysn_0>; + unifykey-index-1 = <&keysn_1>; + unifykey-index-2 = <&keysn_2>; + unifykey-index-3 = <&keysn_3>; + unifykey-index-4 = <&keysn_4>; + unifykey-index-5 = <&keysn_5>; + unifykey-index-6 = <&keysn_6>; + unifykey-index-7 = <&keysn_7>; + unifykey-index-8 = <&keysn_8>; + unifykey-index-9 = <&keysn_9>; + unifykey-index-10= <&keysn_10>; + unifykey-index-11= <&keysn_11>; + unifykey-index-12= <&keysn_12>; + unifykey-index-13= <&keysn_13>; + unifykey-index-14= <&keysn_14>; + + keysn_0: key_0{ + key-name = "usid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_1:key_1{ + key-name = "mac"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_2:key_2{ + key-name = "hdcp"; + key-device = "secure"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_3:key_3{ + key-name = "secure_boot_set"; + key-device = "efuse"; + key-permit = "write"; + }; + keysn_4:key_4{ + key-name = "mac_bt"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_5:key_5{ + key-name = "mac_wifi"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_6:key_6{ + key-name = "hdcp2_tx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_7:key_7{ + key-name = "hdcp2_rx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_8:key_8{ + key-name = "widevinekeybox"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_9:key_9{ + key-name = "deviceid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_10:key_10{ + key-name = "hdcp22_fw_private"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_11:key_11{ + key-name = "PlayReadykeybox25"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_12:key_12{ + key-name = "prpubkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_13:key_13{ + key-name = "prprivkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_14:key_14{ + key-name = "netflix_mgkid"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + };//End unifykey + + amlvecm { + compatible = "amlogic, vecm"; + dev_name = "aml_vecm"; + status = "okay"; + gamma_en = <0>;/*1:enabel ;0:disable*/ + wb_en = <0>;/*1:enabel ;0:disable*/ + cm_en = <0>;/*1:enabel ;0:disable*/ + }; + amdolby_vision { + compatible = "amlogic, dolby_vision_g12a"; + dev_name = "aml_amdolby_vision_driver"; + status = "okay"; + tv_mode = <0>;/*1:enabel ;0:disable*/ + }; + + /* Audio Related start */ + pdm_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, pdm_dummy_codec"; + status = "okay"; + }; + dummy_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, aml_dummy_codec"; + status = "okay"; + }; + amlogic_codec:t9015{ + #sound-dai-cells = <0>; + compatible = "amlogic, aml_codec_T9015"; + reg = <0xFF632000 0x2000>; + is_auge_used = <1>; /* meson or auge chipset used */ + tdmout_index = <1>; + status = "okay"; + }; + audio_effect:eqdrc{ + /*eq_enable = <1>;*/ + /*drc_enable = <1>;*/ + /* + * 0:tdmout_a + * 1:tdmout_b + * 2:tdmout_c + * 3:spdifout + * 4:spdifout_b + */ + eqdrc_module = <1>; + /* max 0xf, each bit for one lane, usually one lane */ + lane_mask = <0x1>; + /* max 0xff, each bit for one channel */ + channel_mask = <0x3>; + }; + auge_sound { + compatible = "amlogic, g12a-sound-card"; + aml-audio-card,name = "AML-AUGESOUND"; + + //aml-audio-card,loopback = <&aml_loopback>; + //aml-audio-card,aux-devs = <&amlogic_codec>; + /*avout mute gpio*/ + avout_mute-gpios = <&gpio_ao GPIOAO_2 GPIO_ACTIVE_HIGH>; + /*for audio effect ,eqdrc */ + aml-audio-card,effect = <&audio_effect>; + + aml-audio-card,dai-link@0 { + format = "dsp_a"; + mclk-fs = <512>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + //bitclock-master = <&tdmacodec>; + //frame-master = <&tdmacodec>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-pcm"; + tdmacpu: cpu { + sound-dai = <&aml_tdma>; + dai-tdm-slot-tx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-rx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-num = <8>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <24576000>; + }; + tdmacodec: codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@1 { + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + bitclock-master = <&aml_tdmb>; + frame-master = <&aml_tdmb>; + //bitclock-master = <&tdmbcodec>; + //frame-master = <&tdmbcodec>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-i2s"; + cpu { + sound-dai = <&aml_tdmb>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmbcodec: codec { + sound-dai = <&dummy_codec &dummy_codec + &amlogic_codec &ad82584f_62>; + }; + }; + + aml-audio-card,dai-link@2 { + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + bitclock-master = <&aml_tdmc>; + frame-master = <&aml_tdmc>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + //suffix-name = "alsaPORT-tdm"; + cpu { + sound-dai = <&aml_tdmc>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@3 { + mclk-fs = <64>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-pdm"; + cpu { + sound-dai = <&aml_pdm>; + }; + codec { + sound-dai = <&pdm_codec>; + }; + }; + + aml-audio-card,dai-link@4 { + mclk-fs = <128>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-spdif"; + cpu { + sound-dai = <&aml_spdif>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + }; + audiolocker: locker { + compatible = "amlogic, audiolocker"; + clocks = <&clkaudio CLKID_AUDIO_LOCKER_OUT + &clkaudio CLKID_AUDIO_LOCKER_IN + &clkaudio CLKID_AUDIO_MCLK_D + &clkaudio CLKID_AUDIO_MCLK_E + &clkc CLKID_MPLL1 + &clkc CLKID_MPLL2>; + clock-names = "lock_out", "lock_in", "out_src", + "in_src", "out_calc", "in_ref"; + interrupts = ; + interrupt-names = "irq"; + frequency = <49000000>; /* pll */ + dividor = <49>; /* locker's parent */ + status = "okay"; + }; + /* Audio Related end */ + + cpu_opp_table0: cpu_opp_table0 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <731000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <731000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <731000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <731000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <731000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <731000>; + }; + opp06 { + opp-hz = /bits/ 64 <1398000000>; + opp-microvolt = <761000>; + }; + opp07 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <791000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <831000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <861000>; + }; + opp10 { + opp-hz = /bits/ 64 <1896000000>; + opp-microvolt = <981000>; + }; + opp11 { + opp-hz = /bits/ 64 <2016000000>; + opp-microvolt = <1011000>; + }; + opp12 { + opp-hz = /bits/ 64 <2100000000>; + opp-microvolt = <1011000>; + }; + }; + + cpu_opp_table1: cpu_opp_table1 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <751000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <751000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <751000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <751000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <771000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <771000>; + }; + opp06 { + opp-hz = /bits/ 64 <1398000000>; + opp-microvolt = <791000>; + }; + opp07 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <821000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <861000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <891000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <1011000>; + }; + opp11 { + opp-hz = /bits/ 64 <1908000000>; + opp-microvolt = <1011000>; + }; + opp12 { + opp-hz = /bits/ 64 <2016000000>; + opp-microvolt = <1011000>; + }; + }; + + cpufreq-meson { + compatible = "amlogic, cpufreq-meson"; + status = "okay"; + }; + + +}; /* end of / */ + +&meson_fb { + status = "okay"; + display_size_default = <1920 1080 1920 2160 32>; + mem_size = <0x00800000 0x1980000 0x100000 0x100000 0x800000>; + logo_addr = "0x7f800000"; + mem_alloc = <1>; + pxp_mode = <0>; /** 0:normal mode 1:pxp mode */ +}; + +&pwm_ab { + status = "okay"; + }; + +&pwm_ef { + status = "okay"; + }; + +&pwm_AO_cd { + status = "okay"; + }; + +&i2c3 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&i2c3_master_pins2>; + clock-frequency = <100000>; /* default 100k */ + + /* for ref board */ + ad82584f_62: ad82584f_62@62 { + compatible = "ESMT, ad82584f"; + #sound-dai-cells = <0>; + reg = <0x31>; + status = "okay"; + reset_pin = <&gpio GPIOA_5 0>; + }; + + tlv320adc3101_32: tlv320adc3101_32@32 { + compatible = "ti,tlv320adc3101"; + #sound-dai-cells = <0>; + reg = <0x19>; + differential_pair = <1>; + status = "disabled"; + }; +}; + +&audiobus { + aml_tdma: tdma { + compatible = "amlogic, g12a-snd-tdma"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 1>; + dai-tdm-oe-lane-slot-mask-out = <1 0>; + dai-tdm-clk-sel = <0>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_A + &clkc CLKID_MPLL0>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmout_a &tdmin_a>; + }; + + aml_tdmb: tdmb { + compatible = "amlogic, g12a-snd-tdmb"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 1 0 0>; + dai-tdm-lane-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <1>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_B + &clkc CLKID_MPLL1 + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; + /* + * 0: tdmout_a; + * 1: tdmout_b; + * 2: tdmout_c; + * 3: spdifout; + * 4: spdifout_b; + */ + samesource_sel = <3>; + }; + + aml_tdmc: tdmc { + compatible = "amlogic, g12a-snd-tdmc"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <1 0 0 0>; + #dai-tdm-lane-slot-mask-out = <1 0 1 1>; + #dai-tdm-lane-oe-slot-mask-in = <0 0 0 0>; + #dai-tdm-lane-oe-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <2>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmc_mclk &tdmout_c &tdmin_c>; + }; + + /* copy a useless tdm to output for hdmi, no pinmux */ + aml_i2s2hdmi: i2s2hdmi { + compatible = "amlogic, g12a-snd-tdmc"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-out = <1 1 1 1>; + dai-tdm-clk-sel = <2>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + + i2s2hdmi = <1>; + + status = "okay"; + }; + + aml_spdif: spdif { + compatible = "amlogic, g12a-snd-spdif-a"; + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 + &clkc CLKID_FCLK_DIV4 + &clkaudio CLKID_AUDIO_SPDIFIN + &clkaudio CLKID_AUDIO_SPDIFOUT + &clkaudio CLKID_AUDIO_SPDIFIN_CTRL + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "sysclk", "fixed_clk", "gate_spdifin", + "gate_spdifout", "clk_spdifin", "clk_spdifout"; + interrupts = + ; + + interrupt-names = "irq_spdifin"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; + pinctrl-0 = <&spdifout &spdifin>; + pinctrl-1 = <&spdifout_a_mute>; + status = "okay"; + }; + aml_spdif_b: spdif_b { + compatible = "amlogic, g12a-snd-spdif-b"; + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 /*CLKID_HIFI_PLL*/ + &clkaudio CLKID_AUDIO_SPDIFOUTB + &clkaudio CLKID_AUDIO_SPDIFOUTB_CTRL>; + clock-names = "sysclk", + "gate_spdifout", "clk_spdifout"; + status = "disabled"; + }; + aml_pdm: pdm { + compatible = "amlogic, g12a-snd-pdm"; + #sound-dai-cells = <0>; + clocks = <&clkaudio CLKID_AUDIO_PDM + &clkc CLKID_FCLK_DIV3 + &clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_PDMIN0 + &clkaudio CLKID_AUDIO_PDMIN1>; + clock-names = "gate", + "sysclk_srcpll", + "dclk_srcpll", + "pdm_dclk", + "pdm_sysclk"; + pinctrl-names = "pdm_pins"; + pinctrl-0 = <&pdmin>; + filter_mode = <1>; /* mode 0~4, defalut:1 */ + status = "okay"; + }; + aml_loopback: loopback { + compatible = "amlogic, snd-loopback"; + /* + * 0: out rate = in data rate; + * 1: out rate = loopback data rate; + */ + lb_mode = <0>; + + /* datain src + * 0: tdmin_a; + * 1: tdmin_b; + * 2: tdmin_c; + * 3: spdifin; + * 4: pdmin; + */ + datain_src = <4>; + datain_chnum = <8>; + datain_chmask = <0x3f>; + + /* tdmin_lb src + * 0: tdmoutA + * 1: tdmoutB + * 2: tdmoutC + * 3: PAD_tdminA + * 4: PAD_tdminB + * 5: PAD_tdminC + */ + datalb_src = <2>; + datalb_chnum = <8>; + datalb_chmask = <0x3>; + + status = "disabled"; + }; + + audioresample: resample { + compatible = "amlogic, g12a-resample"; + clocks = <&clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_MCLK_F + &clkaudio CLKID_AUDIO_RESAMPLE_CTRL>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + /*same with toddr_src + * TDMIN_A, 0 + * TDMIN_B, 1 + * TDMIN_C, 2 + * SPDIFIN, 3 + * PDMIN, 4 + * NONE, + * TDMIN_LB, 6 + * LOOPBACK, 7 + */ + resample_module = <4>; + status = "disabled"; + }; + aml_pwrdet: pwrdet { + compatible = "amlogic, g12a-power-detect"; + + interrupts = ; + interrupt-names = "pwrdet_irq"; + + /* pwrdet source sel + * 7: loopback; + * 6: tdmin_lb; + * 5: reserved; + * 4: pdmin; + * 3: spdifin; + * 2: tdmin_c; + * 1: tdmin_b; + * 0: tdmin_a; + */ + pwrdet_src = <4>; + + hi_th = <0x70000>; + lo_th = <0x16000>; + + status = "disabled"; + }; +}; /* end of audiobus */ + +&pinctrl_periphs { + tdmout_a: tdmout_a { + mux { /* GPIOX_11, GPIOX_10, GPIOX_9 */ + groups = "tdma_sclk", + "tdma_fs", + "tdma_dout0"; + function = "tdma_out"; + }; + }; + + tdmin_a: tdmin_a { + mux { /* GPIOX_8 */ + groups = "tdma_din1"; + function = "tdma_in"; + }; + }; + + tdmb_mclk: tdmb_mclk { + mux { + groups = "mclk0_a"; + function = "mclk0"; + drive-strength = <2>; + }; + }; + tdmout_b: tdmout_b { + mux { /* GPIOA_1, GPIOA_2, GPIOA_3 */ + groups = "tdmb_sclk", + "tdmb_fs", + "tdmb_dout0"; + function = "tdmb_out"; + drive-strength = <2>; + }; + }; + + tdmin_b:tdmin_b { + mux { /* GPIOA_4 */ + groups = "tdmb_din1" + /*,"tdmb_slv_sclk", "tdmb_slv_fs"*/; + function = "tdmb_in"; + drive-strength = <2>; + }; + }; + + tdmc_mclk: tdmc_mclk { + mux { /* GPIOA_11 */ + groups = "mclk1_a"; + function = "mclk1"; + }; + }; + + tdmout_c:tdmout_c { + mux { /* GPIOA_12, GPIOA_13, GPIOA_8, GPIOA_7*/ + groups = "tdmc_sclk_a", + "tdmc_fs_a", + "tdmc_dout0_a" + /*, "tdmc_dout2", + * "tdmc_dout3" + */; + function = "tdmc_out"; + }; + }; + + tdmin_c:tdmin_c { + mux { /* GPIOA_10 */ + groups = "tdmc_din0_a"; + function = "tdmc_in"; + }; + }; + + spdifin: spdifin { + mux {/* GPIOH_5 */ + groups = "spdif_in_h"; + function = "spdif_in"; + }; + }; + + /* GPIOH_4 */ + /* + * spdifout: spdifout { + * mux { + * groups = "spdif_out_h"; + * function = "spdif_out"; + * }; + *}; + */ + + pdmin: pdmin { + mux { /* gpioa_5, gpioa_6, gpioa_7, gpioa_8, gpioa_9*/ + groups = "pdm_din0_a", + /*"pdm_din1_a",*/ + "pdm_din2_a", + /*"pdm_din3_a",*/ + "pdm_dclk_a"; + function = "pdm"; + }; + }; + + bl_pwm_off_pins:bl_pwm_off_pin { + mux { + pins = "GPIOH_5"; + function = "gpio_periphs"; + output-high; + }; + }; + +}; /* end of pinctrl_periphs */ + +&pinctrl_aobus { + spdifout: spdifout { + mux { /* gpiao_10 */ + groups = "spdif_out_ao"; + function = "spdif_out_ao"; + }; + }; + + spdifout_a_mute: spdifout_a_mute { + mux { /* gpiao_10 */ + groups = "GPIOAO_10"; + function = "gpio_aobus"; + }; + }; +}; /* end of pinctrl_aobus */ + +&irblaster { + status = "disabled"; +}; + +&audio_data { + status = "okay"; +}; + +/*if you want to use vdin just modify status to "ok"*/ +&vdin0 { + memory-region = <&vdin0_cma_reserved>; + status = "okay"; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + *bit4:support yuv422 10bit full pack mode (from txl new add) + */ + tv_bit_mode = <0x15>; +}; +&vdin1 { + memory-region = <&vdin1_cma_reserved>; + status = "okay"; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + */ + tv_bit_mode = <1>; +}; + +&sd_emmc_c { + status = "okay"; + emmc { + caps = "MMC_CAP_8_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + /* "MMC_CAP_1_8V_DDR", */ + "MMC_CAP_HW_RESET", + "MMC_CAP_ERASE", + "MMC_CAP_CMD23"; + caps2 = "MMC_CAP2_HS200"; + /* "MMC_CAP2_HS400";*/ + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&sd_emmc_b { + status = "okay"; + sd { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED"; + f_min = <400000>; + f_max = <50000000>; + }; +}; + +&sd_emmc_a { + status = "okay"; + sdio { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + "MMC_CAP_UHS_SDR12", + "MMC_CAP_UHS_SDR25", + "MMC_CAP_UHS_SDR50", + "MMC_CAP_UHS_SDR104", + "MMC_PM_KEEP_POWER", + "MMC_CAP_SDIO_IRQ"; + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&nand { + status = "disabled"; + plat-names = "bootloader","nandnormal"; + plat-num = <2>; + plat-part-0 = <&bootloader>; + plat-part-1 = <&nandnormal>; + bootloader: bootloader{ + enable_pad ="ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <1>; + part_num = <0>; + rb_detect = <1>; + }; + nandnormal: nandnormal{ + enable_pad ="ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + plane_mode = "twoplane"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <2>; + part_num = <3>; + partition = <&nand_partitions>; + rb_detect = <1>; + }; + nand_partitions:nand_partition{ + /* + * if bl_mode is 1, tpl size was generate by + * fip_copies * fip_size which + * will not skip bad when calculating + * the partition size; + * + * if bl_mode is 0, + * tpl partition must be comment out. + */ + tpl{ + offset=<0x0 0x0>; + size=<0x0 0x0>; + }; + logo{ + offset=<0x0 0x0>; + size=<0x0 0x200000>; + }; + recovery{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + boot{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + system{ + offset=<0x0 0x0>; + size=<0x0 0x4000000>; + }; + data{ + offset=<0xffffffff 0xffffffff>; + size=<0x0 0x0>; + }; + }; +}; +&dwc3 { + status = "okay"; +}; + +&usb2_phy_v2 { + status = "okay"; + portnum = <2>; +}; + +&usb3_phy_v2 { + status = "okay"; + portnum = <0>; + otg = <1>; + gpio-vbus-power = "GPIOH_6"; + gpios = <&gpio GPIOH_6 GPIO_ACTIVE_HIGH>; +}; + +&dwc2_a { + status = "okay"; + /** 0: normal, 1: otg+dwc3 host only, 2: otg+dwc3 device only*/ + controller-type = <3>; +}; +ðmac { + status = "okay"; + pinctrl-names = "internal_eth_pins"; + pinctrl-0 = <&internal_eth_pins>; + mc_val = <0x4be04>; + + internal_phy=<1>; +}; + +&uart_A { + status = "okay"; +}; + +&pcie_A { + reset-gpio = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; + status = "okay"; +}; + +&saradc { + status = "okay"; +}; diff --git a/arch/arm/boot/dts/amlogic/g12b_a311d_w400_drm_buildroot.dts b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_drm_buildroot.dts new file mode 100644 index 000000000000..10b88c0b4f98 --- /dev/null +++ b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_drm_buildroot.dts @@ -0,0 +1,1467 @@ +/* + * arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_a.dts + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +/dts-v1/; + +#include "mesong12b_a.dtsi" +#include "mesong12b_skt-panel.dtsi" +#include "mesong12a_drm.dtsi" + +/ { + model = "Amlogic"; + amlogic-dt-id = "g12b_w400_a"; + compatible = "amlogic, g12b"; + interrupt-parent = <&gic>; + #address-cells = <1>; + #size-cells = <1>; + + aliases { + serial0 = &uart_AO; + serial1 = &uart_A; + serial2 = &uart_B; + serial3 = &uart_C; + serial4 = &uart_AO_B; + i2c0 = &i2c0; + i2c1 = &i2c1; + i2c2 = &i2c2; + i2c3 = &i2c3; + i2c4 = &i2c_AO; + tsensor0 = &p_tsensor; + tsensor1 = &d_tsensor; + }; + + memory@00000000 { + device_type = "memory"; + linux,usable-memory = <0x100000 0x7ff00000>; + }; + + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + /* global autoconfigured region for contiguous allocations */ + ramoops@0x07400000 { + compatible = "ramoops"; + reg = <0x07400000 0x00100000>; + record-size = <0x8000>; + console-size = <0x8000>; + ftrace-size = <0x20000>; + }; + + secmon_reserved:linux,secmon { + compatible = "shared-dma-pool"; + reusable; + size = <0x400000>; + alignment = <0x400000>; + alloc-ranges = <0x05000000 0x400000>; + clear-map; + }; + + secos_reserved:linux,secos { + status = "disable"; + compatible = "amlogic, aml_secos_memory"; + reg = <0x05300000 0x2000000>; + no-map; + }; + logo_reserved:linux,meson-fb { + compatible = "shared-dma-pool"; + reusable; + size = <0x800000>; + alignment = <0x400000>; + alloc-ranges = <0x7f800000 0x800000>; + }; + ion_cma_reserved:linux,ion-dev { + compatible = "shared-dma-pool"; + reusable; + size = <0x8000000>; + alignment = <0x400000>; + }; + + //di_reserved:linux,di { + //compatible = "amlogic, di-mem"; + /* buffer_size = 3621952(yuv422 8bit) */ + /* 4179008(yuv422 10bit full pack mode) */ + /** 10x3621952=34.6M(0x23) support 8bit **/ + /** 10x4736064=45.2M(0x2e) support 12bit **/ + /** 10x4179008=40M(0x28) support 10bit **/ + //size = <0x2800000>; + //no-map; + //}; + /*di CMA pool */ + di_cma_reserved:linux,di_cma { + compatible = "shared-dma-pool"; + reusable; + /* buffer_size = 3621952(yuv422 8bit) + * | 4736064(yuv422 10bit) + * | 4074560(yuv422 10bit full pack mode) + * 10x3621952=34.6M(0x23) support 8bit + * 10x4736064=45.2M(0x2e) support 12bit + * 10x4074560=40M(0x28) support 10bit + */ + size = <0x02800000>; + alignment = <0x400000>; + }; + /* POST PROCESS MANAGER */ + ppmgr_reserved:linux,ppmgr { + compatible = "shared-dma-pool"; + size = <0x0>; + }; + codec_mm_cma:linux,codec_mm_cma { + compatible = "shared-dma-pool"; + reusable; + /* ion_codec_mm max can alloc size 80M*/ + size = <0x13400000>; + alignment = <0x400000>; + linux,contiguous-region; + }; + /* codec shared reserved */ + codec_mm_reserved:linux,codec_mm_reserved { + compatible = "amlogic, codec-mm-reserved"; + size = <0x0>; + alignment = <0x100000>; + //no-map; + }; + /* vdin0 CMA pool */ + vdin0_cma_reserved:linux,vdin0_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16+4 M */ + size = <0x04000000>; + alignment = <0x400000>; + }; + /* vdin1 CMA pool */ + vdin1_cma_reserved:linux,vdin1_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16 M */ + size = <0x04000000>; + alignment = <0x400000>; + }; + galcore_reserved:linux,galcore { + compatible = "shared-dma-pool"; + reusable; + size = <0x1000000>; + alignment = <0x400000>; + linux,contiguous-region; + }; + + isp_cma_reserved:linux,isp_cma { + compatible = "shared-dma-pool"; + reusable; + status = "okay"; + size = <0x1f000000>; + alignment = <0x400000>; + }; + + adapt_cma_reserved:linux,adapt_cma { + compatible = "shared-dma-pool"; + reusable; + status = "okay"; + size = <0x03000000>; + alignment = <0x400000>; + }; + gdc_cma_reserved:linux,gdc_cma { + compatible = "shared-dma-pool"; + reusable; + status = "okay"; + size = <0x04000000>; + alignment = <0x400000>; + }; + }; + galcore { + status = "okay"; + memory-region = <&galcore_reserved>; + }; + gpioleds { + compatible = "gpio-leds"; + status = "okay"; + + sys_led { + label="sys_led"; + gpios=<&gpio_ao GPIOAO_11 GPIO_ACTIVE_HIGH>; + default-state ="on"; + retain-state-suspended; + linux,default-trigger="cpu0"; + }; + }; + + cvbsout { + compatible = "amlogic, cvbsout-g12b"; + dev_name = "cvbsout"; + status = "okay"; + clocks = <&clkc CLKID_VCLK2_ENCI + &clkc CLKID_VCLK2_VENCI0 + &clkc CLKID_VCLK2_VENCI1 + &clkc CLKID_DAC_CLK>; + clock-names = "venci_top_gate", + "venci_0_gate", + "venci_1_gate", + "vdac_clk_gate"; + + /* performance: reg_address, reg_value */ + /* g12b */ + performance = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x8080 + 0x1b05 0xfd + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + performance_sarft = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x0 + 0x1b05 0x9 + 0x1c59 0xfc48 + 0xffff 0x0>; /* ending flag */ + }; + + bt-dev{ + compatible = "amlogic, bt-dev"; + dev_name = "bt-dev"; + status = "okay"; + gpio_reset = <&gpio GPIOX_17 GPIO_ACTIVE_HIGH>; + gpio_hostwake = <&gpio GPIOX_19 GPIO_ACTIVE_HIGH>; + }; + + wifi{ + compatible = "amlogic, aml_wifi"; + dev_name = "aml_wifi"; + status = "okay"; + interrupt_pin = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; + irq_trigger_type = "GPIO_IRQ_LOW"; + power_on_pin = <&gpio GPIOX_6 GPIO_ACTIVE_HIGH>; + dhd_static_buf; //if use bcm wifi, config dhd_static_buf + pinctrl-names = "default"; + pinctrl-0 = <&pwm_e_pins>; + pwm_config = <&wifi_pwm_conf>; + }; + + wifi_pwm_conf:wifi_pwm_conf{ + pwm_channel1_conf { + pwms = <&pwm_ef MESON_PWM_0 30541 0>; + duty-cycle = <15270>; + times = <10>; + }; + pwm_channel2_conf { + pwms = <&pwm_ef MESON_PWM_2 30500 0>; + duty-cycle = <15250>; + times = <12>; + }; + }; + + codec_mm { + compatible = "amlogic, codec, mm"; + memory-region = <&codec_mm_cma &codec_mm_reserved>; + dev_name = "codec_mm"; + status = "okay"; + }; + + ppmgr { + compatible = "amlogic, ppmgr"; + memory-region = <&ppmgr_reserved>; + dev_name = "ppmgr"; + status = "okay"; + }; + + deinterlace { + compatible = "amlogic, deinterlace"; + status = "okay"; + /* 0:use reserved; 1:use cma; 2:use cma as reserved */ + flag_cma = <1>; + //memory-region = <&di_reserved>; + memory-region = <&di_cma_reserved>; + interrupts = <0 46 1 + 0 40 1>; + interrupt-names = "pre_irq", "post_irq"; + clocks = <&clkc CLKID_VPU_CLKB_TMP_COMP>, + <&clkc CLKID_VPU_CLKB_COMP>; + clock-names = "vpu_clkb_tmp_composite", + "vpu_clkb_composite"; + clock-range = <334 667>; + /* buffer-size = <3621952>;(yuv422 8bit) */ + buffer-size = <4074560>;/*yuv422 fullpack*/ + /* reserve-iomap = "true"; */ + /* if enable nr10bit, set nr10bit-support to 1 */ + post-wr-support = <1>; + nr10bit-support = <1>; + nrds-enable = <1>; + pps-enable = <1>; + }; + ionvideo { + compatible = "amlogic, ionvideo"; + dev_name = "ionvideo"; + status = "okay"; + }; + + + partitions: partitions{ + parts = <14>; + part-0 = <&logo>; + part-1 = <&recovery>; + part-2 = <&misc>; + part-3 = <&dto>; + part-4 = <&cri_data>; + part-5 = <¶m>; + part-6 = <&boot>; + part-7 = <&rsv>; + part-8 = <&tee>; + part-9 = <&vendor>; + part-10 = <&odm>; + part-11 = <&system>; + part-12 = <&cache>; + part-13 = <&data>; + + logo:logo{ + pname = "logo"; + size = <0x0 0x800000>; + mask = <1>; + }; + recovery:recovery{ + pname = "recovery"; + size = <0x0 0x1800000>; + mask = <1>; + }; + misc:misc{ + pname = "misc"; + size = <0x0 0x800000>; + mask = <1>; + }; + dto:dto{ + pname = "dto"; + size = <0x0 0x800000>; + mask = <1>; + }; + cri_data:cri_data{ + pname = "cri_data"; + size = <0x0 0x800000>; + mask = <2>; + }; + rsv:rsv{ + pname = "rsv"; + size = <0x0 0x1000000>; + mask = <1>; + }; + param:param{ + pname = "param"; + size = <0x0 0x1000000>; + mask = <2>; + }; + boot:boot{ + pname = "boot"; + size = <0x0 0x1000000>; + mask = <1>; + }; + tee:tee{ + pname = "tee"; + size = <0x0 0x2000000>; + mask = <1>; + }; + vendor:vendor{ + pname = "vendor"; + size = <0x0 0x10000000>; + mask = <1>; + }; + odm:odm{ + pname = "odm"; + size = <0x0 0x10000000>; + mask = <1>; + }; + system:system{ + pname = "system"; + size = <0x0 0x80000000>; + mask = <1>; + }; + cache:cache{ + pname = "cache"; + size = <0x0 0x46000000>; + mask = <2>; + }; + data:data{ + pname = "data"; + size = <0xffffffff 0xffffffff>; + mask = <4>; + }; + }; + + gpio_keypad { + compatible = "amlogic, gpio_keypad"; + status = "okay"; + scan_period = <20>; + key_num = <1>; + key_name = "power"; + key_code = <116>; + key-gpios = <&gpio_ao GPIOAO_3 GPIO_ACTIVE_HIGH>; + detect_mode = <0>;/*0:polling mode, 1:irq mode*/ + }; + + adc_keypad { + compatible = "amlogic, adc_keypad"; + status = "okay"; + key_name = "vol-", "vol+", "enter"; + key_num = <3>; + io-channels = <&saradc SARADC_CH2>; + io-channel-names = "key-chan-2"; + key_chan = ; + key_code = <114 115 28>; + key_val = <143 266 389>; //val=voltage/1800mV*1023 + key_tolerance = <40 40 40>; + }; + + unifykey{ + compatible = "amlogic, unifykey"; + status = "ok"; + unifykey-num = <15>; + unifykey-index-0 = <&keysn_0>; + unifykey-index-1 = <&keysn_1>; + unifykey-index-2 = <&keysn_2>; + unifykey-index-3 = <&keysn_3>; + unifykey-index-4 = <&keysn_4>; + unifykey-index-5 = <&keysn_5>; + unifykey-index-6 = <&keysn_6>; + unifykey-index-7 = <&keysn_7>; + unifykey-index-8 = <&keysn_8>; + unifykey-index-9 = <&keysn_9>; + unifykey-index-10= <&keysn_10>; + unifykey-index-11= <&keysn_11>; + unifykey-index-12= <&keysn_12>; + unifykey-index-13= <&keysn_13>; + unifykey-index-14= <&keysn_14>; + + keysn_0: key_0{ + key-name = "usid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_1:key_1{ + key-name = "mac"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_2:key_2{ + key-name = "hdcp"; + key-device = "secure"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_3:key_3{ + key-name = "secure_boot_set"; + key-device = "efuse"; + key-permit = "write"; + }; + keysn_4:key_4{ + key-name = "mac_bt"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_5:key_5{ + key-name = "mac_wifi"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_6:key_6{ + key-name = "hdcp2_tx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_7:key_7{ + key-name = "hdcp2_rx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_8:key_8{ + key-name = "widevinekeybox"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_9:key_9{ + key-name = "deviceid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_10:key_10{ + key-name = "hdcp22_fw_private"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_11:key_11{ + key-name = "PlayReadykeybox25"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_12:key_12{ + key-name = "prpubkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_13:key_13{ + key-name = "prprivkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_14:key_14{ + key-name = "netflix_mgkid"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + };//End unifykey + + amlvecm { + compatible = "amlogic, vecm"; + dev_name = "aml_vecm"; + status = "okay"; + gamma_en = <0>;/*1:enabel ;0:disable*/ + wb_en = <0>;/*1:enabel ;0:disable*/ + cm_en = <0>;/*1:enabel ;0:disable*/ + }; + amdolby_vision { + compatible = "amlogic, dolby_vision_g12a"; + dev_name = "aml_amdolby_vision_driver"; + status = "okay"; + tv_mode = <0>;/*1:enabel ;0:disable*/ + }; + + /* Audio Related start */ + pdm_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, pdm_dummy_codec"; + status = "okay"; + }; + dummy_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, aml_dummy_codec"; + status = "okay"; + }; + amlogic_codec:t9015{ + #sound-dai-cells = <0>; + compatible = "amlogic, aml_codec_T9015"; + reg = <0xFF632000 0x2000>; + is_auge_used = <1>; /* meson or auge chipset used */ + tdmout_index = <1>; + status = "okay"; + }; + audio_effect:eqdrc{ + /*eq_enable = <1>;*/ + /*drc_enable = <1>;*/ + /* + * 0:tdmout_a + * 1:tdmout_b + * 2:tdmout_c + * 3:spdifout + * 4:spdifout_b + */ + eqdrc_module = <1>; + /* max 0xf, each bit for one lane, usually one lane */ + lane_mask = <0x1>; + /* max 0xff, each bit for one channel */ + channel_mask = <0x3>; + }; + auge_sound { + compatible = "amlogic, g12a-sound-card"; + aml-audio-card,name = "AML-AUGESOUND"; + + //aml-audio-card,loopback = <&aml_loopback>; + //aml-audio-card,aux-devs = <&amlogic_codec>; + /*avout mute gpio*/ + avout_mute-gpios = <&gpio_ao GPIOAO_2 GPIO_ACTIVE_HIGH>; + /*for audio effect ,eqdrc */ + aml-audio-card,effect = <&audio_effect>; + + aml-audio-card,dai-link@0 { + format = "dsp_a"; + mclk-fs = <512>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + //bitclock-master = <&tdmacodec>; + //frame-master = <&tdmacodec>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-pcm"; + tdmacpu: cpu { + sound-dai = <&aml_tdma>; + dai-tdm-slot-tx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-rx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-num = <8>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <24576000>; + }; + tdmacodec: codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@1 { + format = "i2s"; + mclk-fs = <256>; + continuous-clock; + //bitclock-inversion; + //frame-inversion; + bitclock-master = <&aml_tdmb>; + frame-master = <&aml_tdmb>; + //bitclock-master = <&tdmbcodec>; + //frame-master = <&tdmbcodec>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-i2s"; + cpu { + sound-dai = <&aml_tdmb>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmbcodec: codec { + sound-dai = <&dummy_codec &dummy_codec + &amlogic_codec &ad82584f_62>; + }; + }; + + aml-audio-card,dai-link@2 { + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + bitclock-master = <&aml_tdmc>; + frame-master = <&aml_tdmc>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + //suffix-name = "alsaPORT-tdm"; + cpu { + sound-dai = <&aml_tdmc>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@3 { + mclk-fs = <64>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-pdm"; + cpu { + sound-dai = <&aml_pdm>; + }; + codec { + sound-dai = <&pdm_codec>; + }; + }; + + aml-audio-card,dai-link@4 { + mclk-fs = <128>; + continuous-clock; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-spdif"; + cpu { + sound-dai = <&aml_spdif>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + }; + audiolocker: locker { + compatible = "amlogic, audiolocker"; + clocks = <&clkaudio CLKID_AUDIO_LOCKER_OUT + &clkaudio CLKID_AUDIO_LOCKER_IN + &clkaudio CLKID_AUDIO_MCLK_D + &clkaudio CLKID_AUDIO_MCLK_E + &clkc CLKID_MPLL1 + &clkc CLKID_MPLL2>; + clock-names = "lock_out", "lock_in", "out_src", + "in_src", "out_calc", "in_ref"; + interrupts = ; + interrupt-names = "irq"; + frequency = <49000000>; /* pll */ + dividor = <49>; /* locker's parent */ + status = "okay"; + }; + /* Audio Related end */ + + cpu_opp_table0: cpu_opp_table0 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <731000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <731000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <731000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <731000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <731000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <731000>; + }; + opp06 { + opp-hz = /bits/ 64 <1398000000>; + opp-microvolt = <761000>; + }; + opp07 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <791000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <831000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <861000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <981000>; + }; + }; + + cpu_opp_table1: cpu_opp_table1 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <751000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <751000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <751000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <751000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <771000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <771000>; + }; + opp06 { + opp-hz = /bits/ 64 <1398000000>; + opp-microvolt = <791000>; + }; + opp07 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <821000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <861000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <891000>; + }; + }; + + cpufreq-meson { + compatible = "amlogic, cpufreq-meson"; + status = "okay"; + }; + + sensor: sensor { + compatible = "soc, sensor"; + status = "okay"; + sensor-name = "imx290"; /*imx290;os08a10;imx227*/ + pinctrl-names="default"; + pinctrl-0=<&clk12_24_z_pins>; + clocks = <&clkc CLKID_24M>; + clock-names = "g12a_24m"; + reset = <&gpio GPIOZ_12 GPIO_ACTIVE_HIGH>; + ir_cut_gpio = <&gpio GPIOZ_11 GPIO_ACTIVE_HIGH + &gpio GPIOZ_7 GPIO_ACTIVE_HIGH>; + }; + + iq: iq { + compatible = "soc, iq"; + status = "okay"; + sensor-name = "imx290"; /*imx290;os08a10;imx227*/ + }; +}; /* end of / */ + +&i2c2 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&i2c2_master_pins2>; + clock-frequency = <100000>; /* default 100k */ + sensor-i2c@6c { + compatible = "arm, i2c-sensor"; + reg = <0x6c>; + reg-names = "i2c-sensor"; + slave-addr = <0x6c>; + reg-type = <2>; + reg-data-type = <1>; + link-device = <&phycsi>; + }; +}; + +&isp { + status = "okay"; + memory-region = <&isp_cma_reserved>; +}; + +&adapter { + status = "okay"; + memory-region = <&adapt_cma_reserved>; +}; + +&gdc { + status = "okay"; + memory-region = <&gdc_cma_reserved>; +}; + +&pwm_ab { + status = "okay"; + }; + +&pwm_ef { + status = "okay"; + }; + +&pwm_AO_cd { + status = "okay"; + }; + +&i2c0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_master_pins2>; + clock-frequency = <400000>; + + touchscreen@38 { + compatible = "focaltech,fts"; + status = "disabled"; + reg = <0x38>; + reset-gpio = <&gpio GPIOZ_9 GPIO_ACTIVE_HIGH>; + irq-gpio = <&gpio GPIOZ_3 GPIO_ACTIVE_HIGH>; + x_max = <720>; + y_max = <1280>; + max-touch-number = <10>; + }; +}; + +&i2c3 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&i2c3_master_pins2>; + clock-frequency = <100000>; /* default 100k */ + + /* for ref board */ + ad82584f_62: ad82584f_62@62 { + compatible = "ESMT, ad82584f"; + #sound-dai-cells = <0>; + reg = <0x31>; + status = "okay"; + reset_pin = <&gpio GPIOA_5 0>; + }; + + tlv320adc3101_32: tlv320adc3101_32@32 { + compatible = "ti,tlv320adc3101"; + #sound-dai-cells = <0>; + reg = <0x19>; + differential_pair = <1>; + status = "disabled"; + }; + + bl_extern_i2c { + compatible = "bl_extern, i2c"; + dev_name = "lp8556"; + reg = <0x2c>; + status = "disabled"; + }; +}; + +&audiobus { + aml_tdma: tdma { + compatible = "amlogic, g12a-snd-tdma"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 1>; + dai-tdm-oe-lane-slot-mask-out = <1 0>; + dai-tdm-clk-sel = <0>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_A + &clkc CLKID_MPLL0>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmout_a &tdmin_a>; + }; + + aml_tdmb: tdmb { + compatible = "amlogic, g12a-snd-tdmb"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 1 0 0>; + dai-tdm-lane-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <1>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_B + &clkc CLKID_MPLL1 + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; + /* + * 0: tdmout_a; + * 1: tdmout_b; + * 2: tdmout_c; + * 3: spdifout; + * 4: spdifout_b; + */ + samesource_sel = <3>; + }; + + aml_tdmc: tdmc { + compatible = "amlogic, g12a-snd-tdmc"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <1 0 0 0>; + #dai-tdm-lane-slot-mask-out = <1 0 1 1>; + #dai-tdm-lane-oe-slot-mask-in = <0 0 0 0>; + #dai-tdm-lane-oe-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <2>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmc_mclk &tdmout_c &tdmin_c>; + }; + + /* copy a useless tdm to output for hdmi, no pinmux */ + aml_i2s2hdmi: i2s2hdmi { + compatible = "amlogic, g12a-snd-tdmc"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-out = <1 1 1 1>; + dai-tdm-clk-sel = <2>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + + i2s2hdmi = <1>; + + status = "okay"; + }; + + aml_spdif: spdif { + compatible = "amlogic, g12a-snd-spdif-a"; + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 + &clkc CLKID_FCLK_DIV4 + &clkaudio CLKID_AUDIO_SPDIFIN + &clkaudio CLKID_AUDIO_SPDIFOUT + &clkaudio CLKID_AUDIO_SPDIFIN_CTRL + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "sysclk", "fixed_clk", "gate_spdifin", + "gate_spdifout", "clk_spdifin", "clk_spdifout"; + interrupts = + ; + + interrupt-names = "irq_spdifin"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; + pinctrl-0 = <&spdifout &spdifin>; + pinctrl-1 = <&spdifout_a_mute>; + status = "okay"; + }; + aml_spdif_b: spdif_b { + compatible = "amlogic, g12a-snd-spdif-b"; + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 /*CLKID_HIFI_PLL*/ + &clkaudio CLKID_AUDIO_SPDIFOUTB + &clkaudio CLKID_AUDIO_SPDIFOUTB_CTRL>; + clock-names = "sysclk", + "gate_spdifout", "clk_spdifout"; + status = "disabled"; + }; + aml_pdm: pdm { + compatible = "amlogic, g12a-snd-pdm"; + #sound-dai-cells = <0>; + clocks = <&clkaudio CLKID_AUDIO_PDM + &clkc CLKID_FCLK_DIV3 + &clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_PDMIN0 + &clkaudio CLKID_AUDIO_PDMIN1>; + clock-names = "gate", + "sysclk_srcpll", + "dclk_srcpll", + "pdm_dclk", + "pdm_sysclk"; + pinctrl-names = "pdm_pins"; + pinctrl-0 = <&pdmin>; + filter_mode = <1>; /* mode 0~4, defalut:1 */ + status = "okay"; + }; + aml_loopback: loopback { + compatible = "amlogic, snd-loopback"; + /* + * 0: out rate = in data rate; + * 1: out rate = loopback data rate; + */ + lb_mode = <0>; + + /* datain src + * 0: tdmin_a; + * 1: tdmin_b; + * 2: tdmin_c; + * 3: spdifin; + * 4: pdmin; + */ + datain_src = <4>; + datain_chnum = <8>; + datain_chmask = <0x3f>; + + /* tdmin_lb src + * 0: tdmoutA + * 1: tdmoutB + * 2: tdmoutC + * 3: PAD_tdminA + * 4: PAD_tdminB + * 5: PAD_tdminC + */ + datalb_src = <2>; + datalb_chnum = <8>; + datalb_chmask = <0x3>; + + status = "disabled"; + }; + + audioresample: resample { + compatible = "amlogic, g12a-resample"; + clocks = <&clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_MCLK_F + &clkaudio CLKID_AUDIO_RESAMPLE_CTRL>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + /*same with toddr_src + * TDMIN_A, 0 + * TDMIN_B, 1 + * TDMIN_C, 2 + * SPDIFIN, 3 + * PDMIN, 4 + * NONE, + * TDMIN_LB, 6 + * LOOPBACK, 7 + */ + resample_module = <4>; + status = "disabled"; + }; + aml_pwrdet: pwrdet { + compatible = "amlogic, g12a-power-detect"; + + interrupts = ; + interrupt-names = "pwrdet_irq"; + + /* pwrdet source sel + * 7: loopback; + * 6: tdmin_lb; + * 5: reserved; + * 4: pdmin; + * 3: spdifin; + * 2: tdmin_c; + * 1: tdmin_b; + * 0: tdmin_a; + */ + pwrdet_src = <4>; + + hi_th = <0x70000>; + lo_th = <0x16000>; + + status = "disabled"; + }; +}; /* end of audiobus */ + +&pinctrl_periphs { + tdmout_a: tdmout_a { + mux { /* GPIOX_11, GPIOX_10, GPIOX_9 */ + groups = "tdma_sclk", + "tdma_fs", + "tdma_dout0"; + function = "tdma_out"; + }; + }; + + tdmin_a: tdmin_a { + mux { /* GPIOX_8 */ + groups = "tdma_din1"; + function = "tdma_in"; + }; + }; + + tdmb_mclk: tdmb_mclk { + mux { + groups = "mclk0_a"; + function = "mclk0"; + drive-strength = <2>; + }; + }; + tdmout_b: tdmout_b { + mux { /* GPIOA_1, GPIOA_2, GPIOA_3 */ + groups = "tdmb_sclk", + "tdmb_fs", + "tdmb_dout0"; + function = "tdmb_out"; + drive-strength = <2>; + }; + }; + + tdmin_b:tdmin_b { + mux { /* GPIOA_4 */ + groups = "tdmb_din1" + /*,"tdmb_slv_sclk", "tdmb_slv_fs"*/; + function = "tdmb_in"; + drive-strength = <2>; + }; + }; + + tdmc_mclk: tdmc_mclk { + mux { /* GPIOA_11 */ + groups = "mclk1_a"; + function = "mclk1"; + }; + }; + + clk12_24_z_pins:clk12_24_z_pins { + mux { + groups = "clk12_24_z"; + function = "clk12_24_ee"; + drive-strength = <3>; + }; + }; + + tdmout_c:tdmout_c { + mux { /* GPIOA_12, GPIOA_13, GPIOA_8, GPIOA_7*/ + groups = "tdmc_sclk_a", + "tdmc_fs_a", + "tdmc_dout0_a" + /*, "tdmc_dout2", + * "tdmc_dout3" + */; + function = "tdmc_out"; + }; + }; + + tdmin_c:tdmin_c { + mux { /* GPIOA_10 */ + groups = "tdmc_din0_a"; + function = "tdmc_in"; + }; + }; + + spdifin: spdifin { + mux {/* GPIOH_5 */ + groups = "spdif_in_h"; + function = "spdif_in"; + }; + }; + + /* GPIOH_4 */ + /* + * spdifout: spdifout { + * mux { + * groups = "spdif_out_h"; + * function = "spdif_out"; + * }; + *}; + */ + + pdmin: pdmin { + mux { /* gpioa_5, gpioa_6, gpioa_7, gpioa_8, gpioa_9*/ + groups = "pdm_din0_a", + /*"pdm_din1_a",*/ + "pdm_din2_a", + /*"pdm_din3_a",*/ + "pdm_dclk_a"; + function = "pdm"; + }; + }; + + bl_pwm_off_pins:bl_pwm_off_pin { + mux { + pins = "GPIOH_5"; + function = "gpio_periphs"; + output-high; + }; + }; + +}; /* end of pinctrl_periphs */ + +&pinctrl_aobus { + spdifout: spdifout { + mux { /* gpiao_10 */ + groups = "spdif_out_ao"; + function = "spdif_out_ao"; + }; + }; + + spdifout_a_mute: spdifout_a_mute { + mux { /* gpiao_10 */ + groups = "GPIOAO_10"; + function = "gpio_aobus"; + }; + }; +}; /* end of pinctrl_aobus */ + +&irblaster { + status = "disabled"; +}; + +&audio_data { + status = "okay"; +}; + +/*if you want to use vdin just modify status to "ok"*/ +&vdin0 { + memory-region = <&vdin0_cma_reserved>; + status = "okay"; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + *bit4:support yuv422 10bit full pack mode (from txl new add) + */ + tv_bit_mode = <0x15>; +}; +&vdin1 { + memory-region = <&vdin1_cma_reserved>; + status = "okay"; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + */ + tv_bit_mode = <1>; +}; + +&sd_emmc_c { + status = "okay"; + emmc { + caps = "MMC_CAP_8_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + /* "MMC_CAP_1_8V_DDR", */ + "MMC_CAP_HW_RESET", + "MMC_CAP_ERASE", + "MMC_CAP_CMD23"; + caps2 = "MMC_CAP2_HS200"; + /* "MMC_CAP2_HS400";*/ + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&sd_emmc_b { + status = "okay"; + sd { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED"; + f_min = <400000>; + f_max = <50000000>; + }; +}; + +&sd_emmc_a { + status = "okay"; + sdio { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + "MMC_CAP_UHS_SDR12", + "MMC_CAP_UHS_SDR25", + "MMC_CAP_UHS_SDR50", + "MMC_CAP_UHS_SDR104", + "MMC_PM_KEEP_POWER", + "MMC_CAP_SDIO_IRQ"; + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&nand { + status = "disabled"; + plat-names = "bootloader","nandnormal"; + plat-num = <2>; + plat-part-0 = <&bootloader>; + plat-part-1 = <&nandnormal>; + bootloader: bootloader{ + enable_pad ="ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <1>; + part_num = <0>; + rb_detect = <1>; + }; + nandnormal: nandnormal{ + enable_pad ="ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + plane_mode = "twoplane"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <2>; + part_num = <3>; + partition = <&nand_partitions>; + rb_detect = <1>; + }; + nand_partitions:nand_partition{ + /* + * if bl_mode is 1, tpl size was generate by + * fip_copies * fip_size which + * will not skip bad when calculating + * the partition size; + * + * if bl_mode is 0, + * tpl partition must be comment out. + */ + tpl{ + offset=<0x0 0x0>; + size=<0x0 0x0>; + }; + logo{ + offset=<0x0 0x0>; + size=<0x0 0x200000>; + }; + recovery{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + boot{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + system{ + offset=<0x0 0x0>; + size=<0x0 0x4000000>; + }; + data{ + offset=<0xffffffff 0xffffffff>; + size=<0x0 0x0>; + }; + }; +}; +&dwc3 { + status = "okay"; +}; + +&usb2_phy_v2 { + status = "okay"; + portnum = <2>; +}; + +&usb3_phy_v2 { + status = "okay"; + portnum = <0>; + otg = <1>; + gpio-vbus-power = "GPIOH_6"; + gpios = <&gpio GPIOH_6 GPIO_ACTIVE_HIGH>; +}; + +&dwc2_a { + status = "okay"; + /** 0: normal, 1: otg+dwc3 host only, 2: otg+dwc3 device only*/ + controller-type = <3>; +}; +ðmac { + status = "okay"; +/* //conflict with isp i2c + * pinctrl-names = "internal_eth_pins"; + * pinctrl-0 = <&internal_eth_pins>; + */ + mc_val = <0x4be04>; + + internal_phy=<1>; +}; + +&uart_A { + status = "okay"; +}; + +&pcie_A { + reset-gpio = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; + status = "okay"; +}; + +&saradc { + status = "okay"; +}; + +&spicc1 { + status = "disabled"; + pinctrl-names = "default"; + pinctrl-0 = <&spicc1_pins>; + cs-gpios = <&gpio GPIOH_6 0>; +}; + +&meson_fb { + status = "disable"; +}; + +&drm_vpu { + status = "okay"; + compatible = "amlogic,meson-g12b-vpu"; + logo_addr = "0x7f800000"; +}; + +&drm_amhdmitx { + status = "okay"; + hdcp = "disabled"; +}; + +&drm_lcd { + status = "disable"; +}; diff --git a/arch/arm/boot/dts/amlogic/g12b_pxp.dts b/arch/arm/boot/dts/amlogic/g12b_pxp.dts index e3c62014853e..f75d525e77e5 100644 --- a/arch/arm/boot/dts/amlogic/g12b_pxp.dts +++ b/arch/arm/boot/dts/amlogic/g12b_pxp.dts @@ -21,6 +21,7 @@ / { model = "Amlogic"; + amlogic-dt-id = "g12b_skt_b"; compatible = "amlogic, g12b"; interrupt-parent = <&gic>; #address-cells = <1>; @@ -37,7 +38,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x100000 0x3ff00000>; + linux,usable-memory = <0x0 0x40000000>; }; reserved-memory { @@ -367,31 +368,31 @@ }; opp04 { opp-hz = /bits/ 64 <1000000000>; - opp-microvolt = <731000>; + opp-microvolt = <761000>; }; opp05 { opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <731000>; + opp-microvolt = <781000>; }; opp06 { opp-hz = /bits/ 64 <1398000000>; - opp-microvolt = <761000>; + opp-microvolt = <811000>; }; opp07 { opp-hz = /bits/ 64 <1512000000>; - opp-microvolt = <791000>; + opp-microvolt = <861000>; }; opp08 { opp-hz = /bits/ 64 <1608000000>; - opp-microvolt = <831000>; + opp-microvolt = <901000>; }; opp09 { opp-hz = /bits/ 64 <1704000000>; - opp-microvolt = <861000>; + opp-microvolt = <951000>; }; opp10 { opp-hz = /bits/ 64 <1800000000>; - opp-microvolt = <981000>; + opp-microvolt = <1001000>; }; }; @@ -401,43 +402,63 @@ opp00 { opp-hz = /bits/ 64 <100000000>; - opp-microvolt = <751000>; + opp-microvolt = <731000>; }; opp01 { opp-hz = /bits/ 64 <250000000>; - opp-microvolt = <751000>; + opp-microvolt = <731000>; }; opp02 { opp-hz = /bits/ 64 <500000000>; - opp-microvolt = <751000>; + opp-microvolt = <731000>; }; opp03 { opp-hz = /bits/ 64 <667000000>; - opp-microvolt = <751000>; + opp-microvolt = <731000>; }; opp04 { opp-hz = /bits/ 64 <1000000000>; - opp-microvolt = <771000>; + opp-microvolt = <731000>; }; opp05 { opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <771000>; + opp-microvolt = <751000>; }; opp06 { opp-hz = /bits/ 64 <1398000000>; - opp-microvolt = <791000>; + opp-microvolt = <771000>; }; opp07 { opp-hz = /bits/ 64 <1512000000>; - opp-microvolt = <821000>; + opp-microvolt = <771000>; }; opp08 { opp-hz = /bits/ 64 <1608000000>; - opp-microvolt = <861000>; + opp-microvolt = <781000>; }; opp09 { opp-hz = /bits/ 64 <1704000000>; - opp-microvolt = <891000>; + opp-microvolt = <791000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <831000>; + }; + opp11 { + opp-hz = /bits/ 64 <1908000000>; + opp-microvolt = <861000>; + }; + opp12 { + opp-hz = /bits/ 64 <2016000000>; + opp-microvolt = <911000>; + }; + opp13 { + opp-hz = /bits/ 64 <2100000000>; + opp-microvolt = <951000>; + }; + opp14 { + opp-hz = /bits/ 64 <2208000000>; + opp-microvolt = <1011000>; }; }; diff --git a/arch/arm/boot/dts/amlogic/g12b_pxp_a.dts b/arch/arm/boot/dts/amlogic/g12b_pxp_a.dts new file mode 100644 index 000000000000..593d51b6b906 --- /dev/null +++ b/arch/arm/boot/dts/amlogic/g12b_pxp_a.dts @@ -0,0 +1,737 @@ +/* + * arch/arm/boot/dts/amlogic/g12b_pxp_a.dts + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +/dts-v1/; + +#include "mesong12b_a.dtsi" + +/ { + model = "Amlogic"; + amlogic-dt-id = "g12b_skt_a"; + compatible = "amlogic, g12b"; + interrupt-parent = <&gic>; + #address-cells = <1>; + #size-cells = <1>; + + aliases { + serial0 = &uart_AO; + i2c0 = &i2c0; + i2c1 = &i2c1; + i2c2 = &i2c2; + i2c3 = &i2c3; + i2c4 = &i2c_AO; + }; + + memory@00000000 { + device_type = "memory"; + linux,usable-memory = <0x100000 0x3ff00000>; + }; + + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + /* global autoconfigured region for contiguous allocations */ + secmon_reserved:linux,secmon { + compatible = "shared-dma-pool"; + reusable; + size = <0x400000>; + alignment = <0x400000>; + alloc-ranges = <0x05000000 0x400000>; + }; + + secos_reserved:linux,secos { + status = "disable"; + compatible = "amlogic, aml_secos_memory"; + reg = <0x05300000 0x2000000>; + no-map; + }; + logo_reserved:linux,meson-fb { + compatible = "shared-dma-pool"; + reusable; + size = <0x800000>; + alignment = <0x400000>; + alloc-ranges = <0x3f800000 0x800000>; + }; + ion_cma_reserved:linux,ion-dev { + compatible = "shared-dma-pool"; + reusable; + size = <0x8000000>; + alignment = <0x400000>; + }; + + //di_reserved:linux,di { + //compatible = "amlogic, di-mem"; + /* buffer_size = 3621952(yuv422 8bit) */ + /* 4179008(yuv422 10bit full pack mode) */ + /** 10x3621952=34.6M(0x23) support 8bit **/ + /** 10x4736064=45.2M(0x2e) support 12bit **/ + /** 10x4179008=40M(0x28) support 10bit **/ + //size = <0x2800000>; + //no-map; + //}; + /*di CMA pool */ + di_cma_reserved:linux,di_cma { + compatible = "shared-dma-pool"; + reusable; + /* buffer_size = 3621952(yuv422 8bit) + * | 4736064(yuv422 10bit) + * | 4074560(yuv422 10bit full pack mode) + * 10x3621952=34.6M(0x23) support 8bit + * 10x4736064=45.2M(0x2e) support 12bit + * 10x4074560=40M(0x28) support 10bit + */ + size = <0x02800000>; + alignment = <0x400000>; + }; + codec_mm_cma:linux,codec_mm_cma { + compatible = "shared-dma-pool"; + reusable; + /* ion_codec_mm max can alloc size 80M*/ + size = <0xd000000>; + alignment = <0x400000>; + linux,contiguous-region; + alloc-ranges = <0x0 0x30000000>; + }; + /* codec shared reserved */ + codec_mm_reserved:linux,codec_mm_reserved { + compatible = "amlogic, codec-mm-reserved"; + size = <0x0>; + alignment = <0x100000>; + //no-map; + }; + /* vdin0 CMA pool */ + vdin0_cma_reserved:linux,vdin0_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16+4 M */ + size = <0x04000000>; + alignment = <0x400000>; + }; + /* vdin1 CMA pool */ + vdin1_cma_reserved:linux,vdin1_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16 M */ + size = <0x04000000>; + alignment = <0x400000>; + }; + }; + + cvbsout { + compatible = "amlogic, cvbsout-g12b"; + dev_name = "cvbsout"; + status = "okay"; + clocks = <&clkc CLKID_VCLK2_ENCI + &clkc CLKID_VCLK2_VENCI0 + &clkc CLKID_VCLK2_VENCI1 + &clkc CLKID_DAC_CLK>; + clock-names = "venci_top_gate", + "venci_0_gate", + "venci_1_gate", + "vdac_clk_gate"; + clk_path = <0>; + + /* performance: reg_address, reg_value */ + /* g12b */ + performance = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x8080 + 0x1b05 0xfd + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + performance_sarft = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x0 + 0x1b05 0x9 + 0x1c59 0xfc48 + 0xffff 0x0>; /* ending flag */ + }; + + codec_mm { + compatible = "amlogic, codec, mm"; + memory-region = <&codec_mm_cma &codec_mm_reserved>; + dev_name = "codec_mm"; + status = "okay"; + }; + + deinterlace { + compatible = "amlogic, deinterlace"; + status = "disabled"; + /* 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>; + }; + + amlvecm { + compatible = "amlogic, vecm"; + dev_name = "aml_vecm"; + status = "disabled"; + gamma_en = <0>;/*1:enabel ;0:disable*/ + wb_en = <0>;/*1:enabel ;0:disable*/ + cm_en = <0>;/*1:enabel ;0:disable*/ + }; + amdolby_vision { + compatible = "amlogic, dolby_vision_g12a"; + dev_name = "aml_amdolby_vision_driver"; + status = "disabled"; + tv_mode = <0>;/*1:enabel ;0:disable*/ + }; + + /* Audio Related start */ + pdm_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, pdm_dummy_codec"; + status = "disabled"; + }; + dummy_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, aml_dummy_codec"; + status = "disabled"; + }; + amlogic_codec:t9015{ + #sound-dai-cells = <0>; + /*compatible = "amlogic, aml_codec_T9015";*/ + reg = <0xFF632000 0x2000>; + is_auge_used = <1>; /* meson or auge chipset used */ + tdmout_index = <0>; + status = "disabled"; + }; + auge_sound { + /*compatible = "amlogic, g12a-sound-card";*/ + aml-audio-card,name = "AML-AUGESOUND"; + + aml-audio-card,dai-link@0 { + format = "dsp_a"; + mclk-fs = <512>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + //bitclock-master = <&tdmacodec>; + //frame-master = <&tdmacodec>; + tdmacpu: cpu { + sound-dai = <&aml_tdma>; + dai-tdm-slot-tx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-rx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-num = <8>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <24576000>; + }; + tdmacodec: codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@1 { + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + bitclock-master = <&aml_tdmb>; + frame-master = <&aml_tdmb>; + cpu { + sound-dai = <&aml_tdmb>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@2 { + format = "i2s"; + mclk-fs = <256>; + continuous-clock; + //bitclock-inversion; + //frame-inversion; + bitclock-master = <&aml_tdmc>; + frame-master = <&aml_tdmc>; + cpu { + sound-dai = <&aml_tdmc>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@3 { + mclk-fs = <64>; + cpu { + sound-dai = <&aml_pdm>; + }; + codec { + sound-dai = <&pdm_codec>; + }; + }; + + aml-audio-card,dai-link@4 { + mclk-fs = <128>; + cpu { + sound-dai = <&aml_spdif>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + aml-audio-card,dai-link@5 { + mclk-fs = <128>; + cpu { + sound-dai = <&aml_spdif_b>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + }; + audiolocker: locker { + compatible = "amlogic, audiolocker"; + clocks = <&clkaudio CLKID_AUDIO_LOCKER_OUT + &clkaudio CLKID_AUDIO_LOCKER_IN + &clkaudio CLKID_AUDIO_MCLK_D + &clkaudio CLKID_AUDIO_MCLK_E + &clkc CLKID_MPLL1 + &clkc CLKID_MPLL2>; + clock-names = "lock_out", "lock_in", "out_src", + "in_src", "out_calc", "in_ref"; + interrupts = ; + interrupt-names = "irq"; + frequency = <49000000>; /* pll */ + dividor = <49>; /* locker's parent */ + status = "disabled"; + }; + /* Audio Related end */ + + cpu_opp_table0: cpu_opp_table0 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <731000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <731000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <731000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <731000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <731000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <731000>; + }; + opp06 { + opp-hz = /bits/ 64 <1398000000>; + opp-microvolt = <761000>; + }; + opp07 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <791000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <831000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <861000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <981000>; + }; + }; + + cpu_opp_table1: cpu_opp_table1 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <751000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <751000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <751000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <751000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <771000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <771000>; + }; + opp06 { + opp-hz = /bits/ 64 <1398000000>; + opp-microvolt = <791000>; + }; + opp07 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <821000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <861000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <891000>; + }; + }; + + cpufreq-meson { + compatible = "amlogic, cpufreq-meson"; + status = "okay"; + }; + + +}; /* end of / */ + +&meson_fb { + status = "okay"; + display_size_default = <1920 1080 1920 2160 32>; + mem_size = <0x00800000 0x1980000 0x100000 0x100000 0x800000>; + logo_addr = "0x3f800000"; + mem_alloc = <1>; + pxp_mode = <1>; /** 0:normal mode 1:pxp mode */ +}; + +&pwm_AO_cd { + status = "okay"; +}; + +&pwm_ab { + status = "okay"; +}; + + +&audiobus { + aml_tdma: tdma { + /*compatible = "amlogic, g12a-snd-tdma";*/ + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <1 0>; + dai-tdm-lane-slot-mask-out = <0 1>; + dai-tdm-clk-sel = <0>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_A + &clkc CLKID_MPLL0>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmout_a &tdmin_a>; + }; + + aml_tdmb: tdmb { + /*compatible = "amlogic, g12a-snd-tdmb";*/ + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <1 1 1 1>; + dai-tdm-clk-sel = <1>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_B + &clkc CLKID_MPLL1>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmb_mclk /*&tdmout_b &tdmin_b*/>; + }; + + aml_tdmc: tdmc { + /*compatible = "amlogic, g12a-snd-tdmc";*/ + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 1 0 0>; + #dai-tdm-lane-slot-mask-out = <1 0 1 1>; + #dai-tdm-lane-oe-slot-mask-in = <0 0 0 0>; + dai-tdm-lane-oe-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <2>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmc_mclk &tdmout_c &tdmin_c>; + }; + + aml_spdif: spdif { + /*compatible = "amlogic, g12a-snd-spdif-a";*/ + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 + &clkc CLKID_FCLK_DIV4 + &clkaudio CLKID_AUDIO_SPDIFIN + &clkaudio CLKID_AUDIO_SPDIFOUT + &clkaudio CLKID_AUDIO_SPDIFIN_CTRL + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "sysclk", "fixed_clk", "gate_spdifin", + "gate_spdifout", "clk_spdifin", "clk_spdifout"; + interrupts = + ; + + interrupt-names = "irq_spdifin"; + pinctrl-names = "spdif_pins"; + pinctrl-0 = <&spdifout &spdifin>; + status = "disabled"; + }; + aml_spdif_b: spdif_b { + /*compatible = "amlogic, g12a-snd-spdif-b";*/ + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 /*CLKID_HIFI_PLL*/ + &clkaudio CLKID_AUDIO_SPDIFOUTB + &clkaudio CLKID_AUDIO_SPDIFOUTB_CTRL>; + clock-names = "sysclk", + "gate_spdifout", "clk_spdifout"; + pinctrl-names = "spdif_pins"; + pinctrl-0 = <&spdifout_b>; + status = "disabled"; + }; + aml_pdm: pdm { + /*compatible = "amlogic, g12a-snd-pdm";*/ + #sound-dai-cells = <0>; + clocks = <&clkaudio CLKID_AUDIO_PDM + &clkc CLKID_FCLK_DIV3 + &clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_PDMIN0 + &clkaudio CLKID_AUDIO_PDMIN1>; + clock-names = "gate", + "sysclk_srcpll", + "dclk_srcpll", + "pdm_dclk", + "pdm_sysclk"; + pinctrl-names = "pdm_pins"; + pinctrl-0 = <&pdmin>; + filter_mode = <1>; /* mode 0~4, defalut:1 */ + status = "disabled"; + }; + aml_pwrdet: pwrdet { + compatible = "amlogic, g12a-power-detect"; + + interrupts = ; + interrupt-names = "pwrdet_irq"; + + /* pwrdet source sel + * 7: loopback; + * 6: tdmin_lb; + * 5: reserved; + * 4: pdmin; + * 3: spdifin; + * 2: tdmin_c; + * 1: tdmin_b; + * 0: tdmin_a; + */ + pwrdet_src = <4>; + + hi_th = <0x70000>; + lo_th = <0x16000>; + + status = "disabled"; + }; +}; /* end of audiobus */ + +&pinctrl_periphs { + tdmout_a: tdmout_a { + mux { /* GPIOX_11, GPIOX_10, GPIOX_8 */ + groups = "tdma_sclk", + "tdma_fs", + "tdma_dout1"; + function = "tdma_out"; + }; + }; + + tdmin_a: tdmin_a { + mux { /* GPIOX_9 */ + groups = "tdma_din0"; + function = "tdma_in"; + }; + }; + + tdmb_mclk: tdmb_mclk { + mux { + groups = "mclk0_a"; + function = "mclk0"; + }; + }; + + tdmc_mclk: tdmc_mclk { + mux { /* GPIOZ_8 */ + groups = "mclk1_z"; + function = "mclk1"; + }; + }; + + tdmout_c:tdmout_c { + mux { /* gpioz_7, gpioz_6, GPIOZ_2, GPIOZ_4, GPIOZ_5*/ + groups = "tdmc_sclk_z", + "tdmc_fs_z", + "tdmc_dout0_z" + /*,"tdmc_dout2_z", + *"tdmc_dout3_z" + */; + function = "tdmc_out"; + }; + }; + + tdmin_c:tdmin_c { + mux { /* GPIOZ_3 */ + groups = "tdmc_din1_z"; + function = "tdmc_in"; + }; + }; + + spdifin: spdifin { + mux {/* gpioa_10 */ + groups = "spdif_in_a10"; + function = "spdif_in"; + }; + }; + + spdifout: spdifout { + mux {/* gpioa_11 */ + groups = "spdif_out_a11"; + function = "spdif_out"; + }; + }; + + spdifout_b: spdifout_b { + mux { /* gpioa_13 */ + groups = "spdif_out_a13"; + function = "spdif_out"; + }; + }; + + pdmin: pdmin { + mux { /* gpioa_5, gpioa_6, gpioa_7, gpioa_8, gpioa_9*/ + groups = "pdm_din0_a", + "pdm_din1_a", + "pdm_din2_a", + "pdm_din3_a", + "pdm_dclk_a"; + function = "pdm"; + }; + }; + +}; /* end of pinctrl_periphs */ + +&pinctrl_aobus { + tdmout_b: tdmout_b { + mux { /* GPIOAO_7, GPIOAO_8, GPIOAO_4 */ + groups = "tdmb_fs_ao", + "tdmb_fs_ao", + "tdmb_dout0_ao"; + function = "tdmb_out_ao"; + }; + }; + + tdmin_b:tdmin_b { + mux { + groups = "tdmb_din2_ao"; + function = "tdmb_in_ao"; + }; + }; +}; /* end of pinctrl_aobus */ +/* Audio Related End */ + +&aobus{ + +}; + +&irblaster { + status = "disabled"; +}; + +/*if you want to use vdin just modify status to "ok"*/ +&vdin0 { + memory-region = <&vdin0_cma_reserved>; + status = "disabled"; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + *bit4:support yuv422 10bit full pack mode (from txl new add) + */ + tv_bit_mode = <0x15>; +}; +&vdin1 { + memory-region = <&vdin1_cma_reserved>; + status = "disabled"; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + */ + tv_bit_mode = <1>; +}; +&sd_emmc_b { + status = "disabled"; + sd { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + "MMC_CAP_UHS_SDR12", + "MMC_CAP_UHS_SDR25", + "MMC_CAP_UHS_SDR50", + "MMC_PM_KEEP_POWER", + "MMC_CAP_NONREMOVABLE"; /**ptm debug */ + f_min = <400000>; + f_max = <200000000>; + }; +}; + diff --git a/arch/arm/boot/dts/amlogic/gxl_p212_2g.dts b/arch/arm/boot/dts/amlogic/gxl_p212_2g.dts index c03256ed4713..336df9026d36 100644 --- a/arch/arm/boot/dts/amlogic/gxl_p212_2g.dts +++ b/arch/arm/boot/dts/amlogic/gxl_p212_2g.dts @@ -56,9 +56,9 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; + secmon_reserved:linux,secmon { compatible = "shared-dma-pool"; reusable; diff --git a/arch/arm/boot/dts/amlogic/gxl_p230_2g.dts b/arch/arm/boot/dts/amlogic/gxl_p230_2g.dts index c1944cc88ba5..fe328fc6093f 100644 --- a/arch/arm/boot/dts/amlogic/gxl_p230_2g.dts +++ b/arch/arm/boot/dts/amlogic/gxl_p230_2g.dts @@ -56,8 +56,7 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { compatible = "shared-dma-pool"; diff --git a/arch/arm/boot/dts/amlogic/gxl_p230_2g_buildroot.dts b/arch/arm/boot/dts/amlogic/gxl_p230_2g_buildroot.dts index bdb46750131d..535dd4e5bf46 100644 --- a/arch/arm/boot/dts/amlogic/gxl_p230_2g_buildroot.dts +++ b/arch/arm/boot/dts/amlogic/gxl_p230_2g_buildroot.dts @@ -56,10 +56,8 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; - secmon_reserved:linux,secmon { compatible = "shared-dma-pool"; reusable; diff --git a/arch/arm/boot/dts/amlogic/gxl_p231_1g.dts b/arch/arm/boot/dts/amlogic/gxl_p231_1g.dts index 5fdbc780e00e..de8e236c9d66 100644 --- a/arch/arm/boot/dts/amlogic/gxl_p231_1g.dts +++ b/arch/arm/boot/dts/amlogic/gxl_p231_1g.dts @@ -56,8 +56,7 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm/boot/dts/amlogic/gxl_p231_2g.dts b/arch/arm/boot/dts/amlogic/gxl_p231_2g.dts index 0a35a0dfe4f7..396c7592ebd4 100644 --- a/arch/arm/boot/dts/amlogic/gxl_p231_2g.dts +++ b/arch/arm/boot/dts/amlogic/gxl_p231_2g.dts @@ -56,8 +56,7 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm/boot/dts/amlogic/gxl_p231_2g_buildroot.dts b/arch/arm/boot/dts/amlogic/gxl_p231_2g_buildroot.dts index 2365af310a9a..5fb51e8e1171 100644 --- a/arch/arm/boot/dts/amlogic/gxl_p231_2g_buildroot.dts +++ b/arch/arm/boot/dts/amlogic/gxl_p231_2g_buildroot.dts @@ -53,8 +53,7 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm/boot/dts/amlogic/gxl_p241_1g.dts b/arch/arm/boot/dts/amlogic/gxl_p241_1g.dts index feab09e7e205..5aa26fa17678 100644 --- a/arch/arm/boot/dts/amlogic/gxl_p241_1g.dts +++ b/arch/arm/boot/dts/amlogic/gxl_p241_1g.dts @@ -55,8 +55,7 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm/boot/dts/amlogic/gxl_p241_1g_buildroot.dts b/arch/arm/boot/dts/amlogic/gxl_p241_1g_buildroot.dts index af46fd2edaec..b3c37a77262e 100644 --- a/arch/arm/boot/dts/amlogic/gxl_p241_1g_buildroot.dts +++ b/arch/arm/boot/dts/amlogic/gxl_p241_1g_buildroot.dts @@ -55,8 +55,7 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm/boot/dts/amlogic/gxl_p241_v2-1g.dts b/arch/arm/boot/dts/amlogic/gxl_p241_v2-1g.dts index aa85f76b0ef2..99991056161b 100644 --- a/arch/arm/boot/dts/amlogic/gxl_p241_v2-1g.dts +++ b/arch/arm/boot/dts/amlogic/gxl_p241_v2-1g.dts @@ -55,8 +55,7 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm/boot/dts/amlogic/gxl_p241_v2_1g_buildroot.dts b/arch/arm/boot/dts/amlogic/gxl_p241_v2_1g_buildroot.dts index bd8fa63f3cc1..102e11007bba 100644 --- a/arch/arm/boot/dts/amlogic/gxl_p241_v2_1g_buildroot.dts +++ b/arch/arm/boot/dts/amlogic/gxl_p241_v2_1g_buildroot.dts @@ -55,8 +55,7 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm/boot/dts/amlogic/gxl_p400_2g.dts b/arch/arm/boot/dts/amlogic/gxl_p400_2g.dts index 46a4b3276009..2e82adb434d6 100644 --- a/arch/arm/boot/dts/amlogic/gxl_p400_2g.dts +++ b/arch/arm/boot/dts/amlogic/gxl_p400_2g.dts @@ -51,8 +51,7 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm/boot/dts/amlogic/gxl_p401_2g.dts b/arch/arm/boot/dts/amlogic/gxl_p401_2g.dts index 2bb9708797db..8fa3a3f97578 100644 --- a/arch/arm/boot/dts/amlogic/gxl_p401_2g.dts +++ b/arch/arm/boot/dts/amlogic/gxl_p401_2g.dts @@ -51,8 +51,7 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm/boot/dts/amlogic/gxl_sei210_2g.dts b/arch/arm/boot/dts/amlogic/gxl_sei210_2g.dts index f68747e8b572..e7468cd8a789 100644 --- a/arch/arm/boot/dts/amlogic/gxl_sei210_2g.dts +++ b/arch/arm/boot/dts/amlogic/gxl_sei210_2g.dts @@ -56,8 +56,7 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { compatible = "shared-dma-pool"; diff --git a/arch/arm/boot/dts/amlogic/gxm-sched-energy.dtsi b/arch/arm/boot/dts/amlogic/gxm-sched-energy.dtsi new file mode 100644 index 000000000000..30fca0951f28 --- /dev/null +++ b/arch/arm/boot/dts/amlogic/gxm-sched-energy.dtsi @@ -0,0 +1,68 @@ +/ { + energy-costs { + CPU_COST_A53_HS: core-cost0 { + busy-cost-data = < + 33 4 + 83 23 + 166 41 + 221 54 + 332 78 + 399 92 + 503 135 + >; + idle-cost-data = < + 3 + 0 + 0 + >; + }; + + CPU_COST_A53: core-cost1 { + busy-cost-data = < + 33 4 + 83 23 + 166 41 + 221 54 + 332 78 + >; + idle-cost-data = < + 3 + 0 + 0 + >; + }; + + CLUSTER_COST_A53_HS: cluster-cost0 { + busy-cost-data = < + 33 7 + 83 8 + 166 9 + 221 10 + 332 13 + 399 15 + 503 23 + >; + idle-cost-data = < + 6 + 6 + 0 + >; + }; + + CLUSTER_COST_A53: cluster-cost1 { + busy-cost-data = < + 33 7 + 83 8 + 166 9 + 221 10 + 332 13 + >; + idle-cost-data = < + 6 + 6 + 0 + >; + }; + + }; +}; diff --git a/arch/arm/boot/dts/amlogic/gxm_q200_2g.dts b/arch/arm/boot/dts/amlogic/gxm_q200_2g.dts index 722771f0e370..78687fb85166 100644 --- a/arch/arm/boot/dts/amlogic/gxm_q200_2g.dts +++ b/arch/arm/boot/dts/amlogic/gxm_q200_2g.dts @@ -55,8 +55,7 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { compatible = "shared-dma-pool"; diff --git a/arch/arm/boot/dts/amlogic/gxm_q200_2g_buildroot.dts b/arch/arm/boot/dts/amlogic/gxm_q200_2g_buildroot.dts index e695359c349b..32725adaacfd 100644 --- a/arch/arm/boot/dts/amlogic/gxm_q200_2g_buildroot.dts +++ b/arch/arm/boot/dts/amlogic/gxm_q200_2g_buildroot.dts @@ -54,8 +54,7 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm/boot/dts/amlogic/gxm_q201_1g.dts b/arch/arm/boot/dts/amlogic/gxm_q201_1g.dts index c1ac3945fdd6..46823dce61e4 100644 --- a/arch/arm/boot/dts/amlogic/gxm_q201_1g.dts +++ b/arch/arm/boot/dts/amlogic/gxm_q201_1g.dts @@ -55,9 +55,8 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; -}; + ftrace-size = <0x20000>; + }; secmon_reserved:linux,secmon { compatible = "shared-dma-pool"; diff --git a/arch/arm/boot/dts/amlogic/gxm_q201_2g.dts b/arch/arm/boot/dts/amlogic/gxm_q201_2g.dts index b70073f2e5c6..0b77e079f71c 100644 --- a/arch/arm/boot/dts/amlogic/gxm_q201_2g.dts +++ b/arch/arm/boot/dts/amlogic/gxm_q201_2g.dts @@ -55,8 +55,7 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm/boot/dts/amlogic/gxm_skt.dts b/arch/arm/boot/dts/amlogic/gxm_skt.dts index b6ff2bba3430..4eba9826cd4a 100644 --- a/arch/arm/boot/dts/amlogic/gxm_skt.dts +++ b/arch/arm/boot/dts/amlogic/gxm_skt.dts @@ -55,8 +55,7 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm/boot/dts/amlogic/meson8b.dtsi b/arch/arm/boot/dts/amlogic/meson8b.dtsi index 320c4986f625..4c12955cb565 100644 --- a/arch/arm/boot/dts/amlogic/meson8b.dtsi +++ b/arch/arm/boot/dts/amlogic/meson8b.dtsi @@ -124,15 +124,10 @@ compatible = "amlogic, jtag"; status = "okay"; reg = <0xda004004 0x4>; - select = "apao"; /* disable apao apee */ - jtagao-gpios = <&gpio_ao GPIOAO_8 0 - &gpio_ao GPIOAO_9 0 - &gpio_ao GPIOAO_10 0 - &gpio_ao GPIOAO_11 0>; - jtagee-gpios = <&gpio CARD_0 0 - &gpio CARD_1 0 - &gpio CARD_2 0 - &gpio CARD_3 0>; + select = "disable"; /* disable/apao/apee */ + pinctrl-names="jtag_apao_pins", "jtag_apee_pins"; + pinctrl-0=<&jtag_apao_pins>; + pinctrl-1=<&jtag_apee_pins>; }; securitykey { @@ -623,6 +618,15 @@ bias-pull-up; }; }; + jtag_apee_pins:jtag_apee_pin { + mux { + groups = "CARD_0", + "CARD_1", + "CARD_2", + "CARD_3"; + function = "gpio_periphs"; + }; + }; }; pinctrl_aobus: pinctrl@c8100084 { compatible = "amlogic,meson8b-aobus-pinctrl"; @@ -681,6 +685,15 @@ function = "spdif_2"; }; }; + jtag_apao_pins:jtag_apao_pin { + mux { + groups = "GPIOAO_8", + "GPIOAO_9", + "GPIOAO_10", + "GPIOAO_11"; + function = "gpio_aobus"; + }; + }; }; dwc2_b { compatible = "amlogic,dwc2"; diff --git a/arch/arm/boot/dts/amlogic/meson8b_m200.dts b/arch/arm/boot/dts/amlogic/meson8b_m200.dts index e74829a1c5ad..f701561d0005 100644 --- a/arch/arm/boot/dts/amlogic/meson8b_m200.dts +++ b/arch/arm/boot/dts/amlogic/meson8b_m200.dts @@ -631,7 +631,7 @@ "GPIOX_3", "GPIOX_8", "GPIOX_9"; - function = "gpio"; + function = "gpio_periphs"; }; }; @@ -653,7 +653,7 @@ "GPIOX_3", "GPIOX_8", "GPIOX_9"; - function = "gpio"; + function = "gpio_periphs"; }; }; @@ -676,7 +676,7 @@ "BOOT_7", "BOOT_8", "BOOT_10"; - function = "gpio"; + function = "gpio_periphs"; }; }; @@ -702,7 +702,7 @@ "BOOT_7", "BOOT_8", "BOOT_10"; - function = "gpio"; + function = "gpio_periphs"; }; }; }; diff --git a/arch/arm/boot/dts/amlogic/mesonaxg.dtsi b/arch/arm/boot/dts/amlogic/mesonaxg.dtsi index 0c9b2c5e905e..50f35d5820ec 100644 --- a/arch/arm/boot/dts/amlogic/mesonaxg.dtsi +++ b/arch/arm/boot/dts/amlogic/mesonaxg.dtsi @@ -51,7 +51,7 @@ CPU0:cpu@0 { device_type = "cpu"; compatible = "arm,cortex-a53","arm,armv8"; - reg = <0x0 0x0>; + reg = <0x0>; enable-method = "psci"; clocks = <&scpi_dvfs 0>; clock-names = "cpu-cluster.0"; @@ -61,7 +61,7 @@ CPU1:cpu@1 { device_type = "cpu"; compatible = "arm,cortex-a53","arm,armv8"; - reg = <0x0 0x1>; + reg = <0x1>; enable-method = "psci"; clocks = <&scpi_dvfs 0>; clock-names = "cpu-cluster.0"; @@ -70,7 +70,7 @@ CPU2:cpu@2 { device_type = "cpu"; compatible = "arm,cortex-a53","arm,armv8"; - reg = <0x0 0x2>; + reg = <0x2>; enable-method = "psci"; clocks = <&scpi_dvfs 0>; clock-names = "cpu-cluster.0"; @@ -80,7 +80,7 @@ CPU3:cpu@3 { device_type = "cpu"; compatible = "arm,cortex-a53","arm,armv8"; - reg = <0x0 0x3>; + reg = <0x3>; enable-method = "psci"; clocks = <&scpi_dvfs 0>; clock-names = "cpu-cluster.0"; @@ -119,24 +119,19 @@ bit_mode=<12>; bit_resolution=<0>; }; + arm_pmu { compatible = "arm,cortex-a15-pmu"; - interrupts = <0 137 4>; - reg = <0xff634400 0x1000>; - - /* addr = base + offset << 2 */ - sys_cpu_status0_offset = <0xa0>; - - sys_cpu_status0_pmuirq_mask = <0xf>; - + /* clusterb-enabled; */ + interrupts = ; + reg = <0xff634680 0x4>; + cpumasks = <0xf>; /* default 10ms */ - relax_timer_ns = <10000000>; - + relax-timer-ns = <10000000>; /* default 10000us */ - max_wait_cnt = <10000>; + max-wait-cnt = <10000>; }; - gic: interrupt-controller@2c001000 { compatible = "arm,cortex-a15-gic", "arm,cortex-a9-gic"; #interrupt-cells = <3>; @@ -152,15 +147,14 @@ method = "smc"; }; - meson_suspend:pm { + aml_pm { compatible = "amlogic, pm"; device_name = "aml_pm"; status = "okay"; - reg = <0xff8000a8 0x4>, - <0xff80023c 0x4>; + debug_reg = <0xff8000a8>; + exit_reg = <0xff80023c>; }; - secmon { compatible = "amlogic, secmon"; memory-region = <&secmon_reserved>; @@ -285,6 +279,18 @@ ram-dump { compatible = "amlogic, ram_dump"; status = "okay"; + reg = <0xFF6345E0 4>; + reg-names = "PREG_STICKY_REG8"; + store_device = "data"; + }; + + jtag { + compatible = "amlogic, jtag"; + status = "okay"; + select = "disable"; /* disable/apao/apee */ + pinctrl-names="jtag_apao_pins", "jtag_apee_pins"; + pinctrl-0=<&jtag_apao_pins>; + pinctrl-1=<&jtag_apee_pins>; }; pinctrl_aobus: pinctrl@ff800014{ @@ -462,6 +468,16 @@ clock-names = "clk_i2c"; clock-frequency = <100000>; }; + + irblaster: meson-irblaster@c0 { + compatible = "amlogic, aml_irblaster"; + reg = <0xc0 0xc>, + <0x40 0x4>; + #irblaster-cells = <2>; + pinctrl-names = "default"; + pinctrl-0 = <&irblaster_pins>; + status = "disabled"; + }; };/* end of aobus */ periphs: periphs@ff634400 { @@ -737,16 +753,6 @@ }; }; - irblaster: meson-irblaster { - compatible = "amlogic, meson_irblaster"; - reg = <0xff8000c0 0x10>, - <0xff800040 0x4>; - pinctrl-names = "default"; - pinctrl-0 = <&irblaster_pins>; - interrupts = <0 198 1>; - status = "disabled"; - }; - saradc:saradc { compatible = "amlogic,meson-axg-saradc"; status = "okay"; @@ -884,6 +890,16 @@ }; }; + jtag_apao_pins:jtag_apao_pin { + mux { + groups = "jtag_ao_tdi", + "jtag_ao_tdo", + "jtag_ao_clk", + "jtag_ao_tms"; + function = "jtag_ao"; + }; + }; + }; /* end of pinctrl_aobus */ &pinctrl_periphs { @@ -1145,5 +1161,15 @@ }; }; + jtag_apee_pins:jtag_apee_pin { + mux { + groups = "jtag_tdo_x", + "jtag_tdi_x", + "jtag_clk_x", + "jtag_tms_x"; + function = "jtag_ee"; + }; + }; + }; /* end of pinctrl_periphs */ diff --git a/arch/arm/boot/dts/amlogic/mesong12a.dtsi b/arch/arm/boot/dts/amlogic/mesong12a.dtsi index 1be1e4e34299..9dbd9237d9ab 100644 --- a/arch/arm/boot/dts/amlogic/mesong12a.dtsi +++ b/arch/arm/boot/dts/amlogic/mesong12a.dtsi @@ -155,21 +155,17 @@ bit_mode=<12>; bit_resolution=<0>; }; + arm_pmu { compatible = "arm,cortex-a15-pmu"; - interrupts = <0 137 4>; - reg = <0xff634400 0x1000>; - - /* addr = base + offset << 2 */ - sys_cpu_status0_offset = <0xa0>; - - sys_cpu_status0_pmuirq_mask = <0xf>; - + /* clusterb-enabled; */ + interrupts = ; + reg = <0xff634680 0x4>; + cpumasks = <0xf>; /* default 10ms */ - relax_timer_ns = <10000000>; - + relax-timer-ns = <10000000>; /* default 10000us */ - max_wait_cnt = <10000>; + max-wait-cnt = <10000>; }; gic: interrupt-controller@2c001000 { @@ -187,12 +183,12 @@ method = "smc"; }; - meson_suspend:pm { + aml_pm { compatible = "amlogic, pm"; status = "okay"; device_name = "aml_pm"; - reg = <0xff8000a8 0x4>, - <0xff80023c 0x4>; + debug_reg = <0xff8000a8>; + exit_reg = <0xff80023c>; }; secmon { @@ -446,20 +442,18 @@ ram-dump { compatible = "amlogic, ram_dump"; status = "okay"; + reg = <0xFF6345E0 4>; + reg-names = "PREG_STICKY_REG8"; + store_device = "data"; }; jtag { compatible = "amlogic, jtag"; status = "okay"; - select = "apao"; /* disable/apao/apee */ - jtagao-gpios = <&gpio_ao GPIOAO_6 0 - &gpio_ao GPIOAO_7 0 - &gpio_ao GPIOAO_8 0 - &gpio_ao GPIOAO_9 0>; - jtagee-gpios = <&gpio GPIOC_0 0 - &gpio GPIOC_1 0 - &gpio GPIOC_4 0 - &gpio GPIOC_5 0>; + select = "disable"; /* disable/apao/apee */ + pinctrl-names="jtag_apao_pins", "jtag_apee_pins"; + pinctrl-0=<&jtag_apao_pins>; + pinctrl-1=<&jtag_apee_pins>; }; saradc:saradc { @@ -753,6 +747,17 @@ pinctrl-names = "default"; pinctrl-0 = <&ao_b_uart_pins>; }; + + irblaster: meson-irblaster@14c { + compatible = "amlogic, meson_irblaster"; + reg = <0x14c 0x10>, + <0x40 0x4>; + #irblaster-cells = <2>; + pinctrl-names = "default"; + pinctrl-0 = <&irblaster_pins>; + interrupts = ; + status = "disabled"; + }; };/* end of aobus */ periphs: periphs@ff634400 { @@ -1032,9 +1037,9 @@ interrupt-map-mask = <0 0 0 0>; interrupt-map = <0 0 0 0 &gic GIC_SPI 223 IRQ_TYPE_EDGE_RISING>; device_type = "pci"; - ranges = <0x81000000 0 0 0 0xfc600000 0x0 0x100000 + ranges = <0x81000000 0 0 0xfc600000 0x0 0x100000 /* downstream I/O */ - 0x82000000 0 0xfc700000 0x0 0xfc700000 0 0x1900000>; + 0x82000000 0xfc700000 0x0 0xfc700000 0 0x1900000>; /* non-prefetchable memory */ num-lanes = <1>; pcie-num = <1>; @@ -1079,6 +1084,7 @@ * 10:G12A */ ic_type = <10>; + dongle_mode = <0>; vend_data: vend_data{ /* Should modified by Customer */ vendor_name = "Amlogic"; /* Max Chars: 8 */ /* standards.ieee.org/develop/regauth/oui/oui.txt */ @@ -1086,6 +1092,12 @@ }; }; + amprime_sl:amprime_sl { + compatible = "amlogic, prime_sl_g12"; + dev_name = "amprime_sl"; + status = "disabled"; + }; + aocec: aocec { compatible = "amlogic, aocec-g12a"; device_name = "aocec"; @@ -1329,15 +1341,6 @@ clocks = <&clkc CLKID_VPU_CLKC_MUX>; clock-names = "vpu_clkc"; }; - irblaster: meson-irblaster { - compatible = "amlogic, meson_irblaster"; - reg = <0xff80014c 0x10>, - <0xff800040 0x4>; - pinctrl-names = "default"; - pinctrl-0 = <&irblaster_pins>; - interrupts = <0 198 1>; - status = "okay"; - }; sd_emmc_c: emmc@ffe07000 { status = "disabled"; @@ -1372,7 +1375,7 @@ calc_f = <1>; max_req_size = <0x20000>; /**128KB*/ gpio_dat3 = <&gpio BOOT_3 GPIO_ACTIVE_HIGH>; - hw_reset = <&gpio BOOT_9 GPIO_ACTIVE_HIGH>; + hw_reset = <&gpio BOOT_12 GPIO_ACTIVE_HIGH>; card_type = <1>; /* 1:mmc card(include eMMC), * 2:sd card(include tSD) @@ -1820,6 +1823,12 @@ dev_name = "aml_sha_dma"; status = "okay"; }; + + aml_tdes { + compatible = "amlogic,tdes_dma"; + dev_name = "aml_tdes_dma"; + status = "okay"; + }; }; rng { @@ -1984,6 +1993,16 @@ function = "cec_ao"; }; }; + + jtag_apao_pins:jtag_apao_pin { + mux { + groups = "jtag_a_tdi", + "jtag_a_tdo", + "jtag_a_clk", + "jtag_a_tms"; + function = "jtag_a"; + }; + }; }; &pinctrl_periphs { @@ -2558,6 +2577,16 @@ drive-strength = <3>; }; }; + + jtag_apee_pins:jtag_apee_pin { + mux { + groups = "jtag_b_tdi", + "jtag_b_tdo", + "jtag_b_clk", + "jtag_b_tms"; + function = "jtag_b"; + }; + }; }; &pinctrl_aobus { diff --git a/arch/arm/boot/dts/amlogic/mesong12a_drm.dtsi b/arch/arm/boot/dts/amlogic/mesong12a_drm.dtsi index b6597c677d88..00beafaba1a2 100644 --- a/arch/arm/boot/dts/amlogic/mesong12a_drm.dtsi +++ b/arch/arm/boot/dts/amlogic/mesong12a_drm.dtsi @@ -107,3 +107,24 @@ }; }; +&gpu{ + /*gpu max freq is 850M*/ + def_clk = <1>; + tbl = <&dvfs285_cfg &dvfs666_cfg &dvfs850_cfg &dvfs850_cfg>; + + dvfs285_cfg:dvfs285_cfg { + keep_count = <2>; + threshold = <100 200>; + }; + + dvfs666_cfg:dvfs666_cfg { + keep_count = <1>; + threshold = <85 200>; + }; + + dvfs850_cfg:dvfs850_cfg { + keep_count = <1>; + threshold = <179 255>; + }; + +}; diff --git a/arch/arm/boot/dts/amlogic/mesong12a_skt-panel.dtsi b/arch/arm/boot/dts/amlogic/mesong12a_skt-panel.dtsi index 9ee5bcb3a810..bac3b8b8dbb9 100644 --- a/arch/arm/boot/dts/amlogic/mesong12a_skt-panel.dtsi +++ b/arch/arm/boot/dts/amlogic/mesong12a_skt-panel.dtsi @@ -34,8 +34,8 @@ "encl_top_gate", "encl_int_gate", "gp0_pll"; - reg = <0x0 0xffd07000 0x0 0x400 /* dsi_host */ - 0x0 0xff644000 0x0 0x200>; /* dsi_phy */ + reg = <0xffd07000 0x400 /* dsi_host */ + 0xff644000 0x200>; /* dsi_phy */ interrupts = <0 3 1 0 56 1>; interrupt-names = "vsync","vsync2"; diff --git a/arch/arm/boot/dts/amlogic/mesong12b.dtsi b/arch/arm/boot/dts/amlogic/mesong12b.dtsi index 0ef83d40bf6a..d8de3401792d 100644 --- a/arch/arm/boot/dts/amlogic/mesong12b.dtsi +++ b/arch/arm/boot/dts/amlogic/mesong12b.dtsi @@ -196,7 +196,7 @@ }; timer { - compatible = "arm,armv8-timer"; + compatible = "arm,armv7-timer"; interrupts = , , , @@ -215,9 +215,19 @@ bit_mode=<12>; bit_resolution=<0>; }; + arm_pmu { - compatible = "arm,armv8-pmuv3"; - interrupts = <0 137 4>; + compatible = "arm,cortex-a15-pmu"; + clusterb-enabled; + interrupts = , + ; + reg = <0xff634680 0x4>, + <0xff6347c0 0x04>; + cpumasks = <0x3 0x3C>; + /* default 10ms */ + relax-timer-ns = <10000000>; + /* default 10000us */ + max-wait-cnt = <10000>; }; gic: interrupt-controller@2c001000 { @@ -235,12 +245,12 @@ method = "smc"; }; - meson_suspend:pm { + aml_pm { compatible = "amlogic, pm"; status = "okay"; device_name = "aml_pm"; - reg = <0xff8000a8 0x4>, - <0xff80023c 0x4>; + debug_reg = <0xff8000a8>; + exit_reg = <0xff80023c>; }; secmon { @@ -311,6 +321,14 @@ #clock-cells = <0>; }; + rtc{ + compatible = "amlogic, aml_vrtc"; + alarm_reg_addr = <0xff8000a8>; + timer_e_addr = <0xffd0f188>; + init_date = "2019/01/01"; + status = "okay"; + }; + cpu_info { compatible = "amlogic, cpuinfo"; status = "okay"; @@ -484,6 +502,15 @@ clocks = <&xtal>; }; + jtag { + compatible = "amlogic, jtag"; + status = "okay"; + select = "disable"; /* disable/apao/apee */ + pinctrl-names="jtag_apao_pins", "jtag_apee_pins"; + pinctrl-0=<&jtag_apao_pins>; + pinctrl-1=<&jtag_apee_pins>; + }; + saradc:saradc { compatible = "amlogic,meson-g12a-saradc"; status = "disabled"; @@ -530,6 +557,14 @@ #thermal-sensor-cells = <1>; }; + ram-dump { + compatible = "amlogic, ram_dump"; + status = "okay"; + reg = <0xFF6345E0 4>; + reg-names = "PREG_STICKY_REG8"; + store_device = "data"; + }; + soc { compatible = "simple-bus"; #address-cells = <1>; @@ -776,6 +811,15 @@ pinctrl-names = "default"; pinctrl-0 = <&ao_b_uart_pins>; }; + + irblaster: meson-irblaster@14c { + compatible = "amlogic, meson_irblaster"; + reg = <0x14c 0x10>, + <0x40 0x4>; + #irblaster-cells = <2>; + interrupts = ; + status = "disabled"; + }; };/* end of aobus */ periphs: periphs@ff634400 { @@ -838,6 +882,29 @@ }; };/* end of audiobus*/ + aml_dma { + compatible = "amlogic,aml_txlx_dma"; + reg = <0xff63e000 0x48>; + interrupts = <0 180 1>; + + aml_aes { + compatible = "amlogic,aes_g12a_dma"; + dev_name = "aml_aes_dma"; + status = "okay"; + }; + + aml_sha { + compatible = "amlogic,sha_dma"; + dev_name = "aml_sha_dma"; + status = "okay"; + }; + + aml_tdes { + compatible = "amlogic,tdes_dma"; + dev_name = "aml_tdes_dma"; + status = "okay"; + }; + }; }; /* end of soc*/ remote:rc@0xff808040 { @@ -1112,6 +1179,12 @@ }; }; + amprime_sl:amprime_sl { + compatible = "amlogic, prime_sl_g12"; + dev_name = "amprime_sl"; + status = "disabled"; + }; + galcore { compatible = "amlogic, galcore"; dev_name = "galcore"; @@ -1120,7 +1193,7 @@ <&clkc CLKID_VNANOQ_CORE_CLK_COMP>; clock-names = "cts_vipnanoq_axi_clk_composite", "cts_vipnanoq_core_clk_composite"; - interrupts = <0 147 1>; + interrupts = <0 147 4>; interrupt-names = "galcore"; reg = <0xff100000 0x800 0xff000000 0x400000>; @@ -1350,7 +1423,7 @@ }; rdma{ - compatible = "amlogic, meson, rdma"; + compatible = "amlogic, meson-g12b, rdma"; dev_name = "amlogic-rdma"; status = "okay"; interrupts = <0 89 1>; @@ -1375,15 +1448,6 @@ clocks = <&clkc CLKID_VPU_CLKC_MUX>; clock-names = "vpu_clkc"; }; - irblaster: meson-irblaster { - compatible = "amlogic, meson_irblaster"; - reg = <0xff80014c 0x10>, - <0xff800040 0x4>; - pinctrl-names = "default"; - pinctrl-0 = <&irblaster_pins>; - interrupts = <0 198 1>; - status = "disabled"; - }; sd_emmc_c: emmc@ffe07000 { status = "disabled"; @@ -1396,9 +1460,9 @@ clocks = <&clkc CLKID_SD_EMMC_C>, <&clkc CLKID_SD_EMMC_C_P0_COMP>, <&clkc CLKID_FCLK_DIV2>, - <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_FCLK_DIV2P5>, <&xtal>; - clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + clock-names = "core","clkin0","clkin1","clkin2","xtal"; bus-width = <8>; cap-sd-highspeed; @@ -1562,20 +1626,11 @@ node_name = "cpufreq_cool1"; device_type = "cpufreq"; }; - cpucore_cool_cluster0 { + cpucore_cool_cluster { min_state = <1>; dyn_coeff = <0>; - cluster_id = <0>; gpu_pp = <2>; - node_name = "cpucore_cool0"; - device_type = "cpucore"; - }; - cpucore_cool_cluster1 { - min_state = <0>; - dyn_coeff = <0>; - cluster_id = <1>; - gpu_pp = <2>; - node_name = "cpucore_cool1"; + node_name = "cpucore_cool"; device_type = "cpucore"; }; gpufreq_cool { @@ -1601,10 +1656,7 @@ cpufreq_cool1:cpufreq_cool1 { #cooling-cells = <2>; /* min followed by max */ }; - cpucore_cool0:cpucore_cool0 { - #cooling-cells = <2>; /* min followed by max */ - }; - cpucore_cool1:cpucore_cool1 { + cpucore_cool:cpucore_cool { #cooling-cells = <2>; /* min followed by max */ }; gpufreq_cool0:gpufreq_cool0 { @@ -1656,14 +1708,9 @@ cooling-device = <&cpufreq_cool1 0 9>; contribution = <1024>; }; - cpucore_cooling_map0 { + cpucore_cooling_map { trip = <&pcontrol>; - cooling-device = <&cpucore_cool0 0 1>; - contribution = <1024>; - }; - cpucore_cooling_map1 { - trip = <&pcontrol>; - cooling-device = <&cpucore_cool1 0 4>; + cooling-device = <&cpucore_cool 0 5>; contribution = <1024>; }; gpufreq_cooling_map { @@ -1876,6 +1923,7 @@ reg-names = "adapter"; interrupts = <0 179 0>; interrupt-names = "adapter-irq"; + mem_alloc = <48>; }; phycsi: phy-csi@ff650000 { @@ -2037,6 +2085,16 @@ function = "pwm_a_gpioe"; }; }; + + jtag_apao_pins:jtag_apao_pin { + mux { + groups = "jtag_a_tdi", + "jtag_a_tdo", + "jtag_a_clk", + "jtag_a_tms"; + function = "jtag_a"; + }; + }; }; &pinctrl_periphs { @@ -2544,6 +2602,16 @@ function = "remote_out"; }; }; + + jtag_apee_pins:jtag_apee_pin { + mux { + groups = "jtag_b_tdi", + "jtag_b_tdo", + "jtag_b_clk", + "jtag_b_tms"; + function = "jtag_b"; + }; + }; }; &gpu{ diff --git a/arch/arm/boot/dts/amlogic/mesong12b_a.dtsi b/arch/arm/boot/dts/amlogic/mesong12b_a.dtsi new file mode 100644 index 000000000000..32ba3e4542e4 --- /dev/null +++ b/arch/arm/boot/dts/amlogic/mesong12b_a.dtsi @@ -0,0 +1,2620 @@ +/* + * arch/arm/boot/dts/amlogic/mesong12b_a.dtsi + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "mesong12a-bifrost.dtsi" +#include "g12b-sched-energy-a.dtsi" + +/ { + cpus:cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu-map { + cluster0:cluster0 { + core0 { + cpu = <&CPU0>; + }; + core1 { + cpu = <&CPU1>; + }; + }; + cluster1:cluster1 { + core0 { + cpu = <&CPU2>; + }; + core1 { + cpu = <&CPU3>; + }; + core2 { + cpu = <&CPU4>; + }; + core3 { + cpu = <&CPU5>; + }; + }; + }; + + CPU0:cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a53","arm,armv8"; + reg = <0x0>; + enable-method = "psci"; + //cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; + sched-energy-costs = <&CPU_COST_A53 &CLUSTER_COST_A53>; + clocks = <&clkc CLKID_CPU_CLK>, + <&clkc CLKID_CPU_FCLK_P>, + <&clkc CLKID_SYS1_PLL>; + clock-names = "core_clk", + "low_freq_clk_parent", + "high_freq_clk_parent"; + operating-points-v2 = <&cpu_opp_table0>; + cpu-supply = <&vddcpu0>; + voltage-tolerance = <0>; + clock-latency = <50000>; + }; + + CPU1:cpu@1 { + device_type = "cpu"; + compatible = "arm,cortex-a53","arm,armv8"; + reg = <0x1>; + enable-method = "psci"; + sched-energy-costs = <&CPU_COST_A53 &CLUSTER_COST_A53>; + clocks = <&clkc CLKID_CPU_CLK>, + <&clkc CLKID_CPU_FCLK_P>, + <&clkc CLKID_SYS1_PLL>; + clock-names = "core_clk", + "low_freq_clk_parent", + "high_freq_clk_parent"; + operating-points-v2 = <&cpu_opp_table0>; + cpu-supply = <&vddcpu0>; + voltage-tolerance = <0>; + clock-latency = <50000>; + }; + + CPU2:cpu@100 { + device_type = "cpu"; + compatible = "arm,cortex-a73","arm,armv8"; + reg = <0x100>; + enable-method = "psci"; + //cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; + sched-energy-costs = <&CPU_COST_A73 &CLUSTER_COST_A73>; + clocks = <&clkc CLKID_CPUB_CLK>, + <&clkc CLKID_CPUB_FCLK_P>, + <&clkc CLKID_SYS_PLL>; + clock-names = "core_clk", + "low_freq_clk_parent", + "high_freq_clk_parent"; + operating-points-v2 = <&cpu_opp_table1>; + cpu-supply = <&vddcpu1>; + voltage-tolerance = <0>; + clock-latency = <50000>; + }; + + CPU3:cpu@101 { + device_type = "cpu"; + compatible = "arm,cortex-a73","arm,armv8"; + reg = <0x101>; + enable-method = "psci"; + //cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; + sched-energy-costs = <&CPU_COST_A73 &CLUSTER_COST_A73>; + clocks = <&clkc CLKID_CPUB_CLK>, + <&clkc CLKID_CPUB_FCLK_P>, + <&clkc CLKID_SYS_PLL>; + clock-names = "core_clk", + "low_freq_clk_parent", + "high_freq_clk_parent"; + operating-points-v2 = <&cpu_opp_table1>; + cpu-supply = <&vddcpu1>; + voltage-tolerance = <0>; + clock-latency = <50000>; + }; + + CPU4:cpu@102 { + device_type = "cpu"; + compatible = "arm,cortex-a73","arm,armv8"; + reg = <0x102>; + enable-method = "psci"; + //cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; + sched-energy-costs = <&CPU_COST_A73 &CLUSTER_COST_A73>; + clocks = <&clkc CLKID_CPUB_CLK>, + <&clkc CLKID_CPUB_FCLK_P>, + <&clkc CLKID_SYS_PLL>; + clock-names = "core_clk", + "low_freq_clk_parent", + "high_freq_clk_parent"; + operating-points-v2 = <&cpu_opp_table1>; + cpu-supply = <&vddcpu1>; + voltage-tolerance = <0>; + clock-latency = <50000>; + }; + + CPU5:cpu@103 { + device_type = "cpu"; + compatible = "arm,cortex-a73","arm,armv8"; + reg = <0x103>; + enable-method = "psci"; + //cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; + sched-energy-costs = <&CPU_COST_A73 &CLUSTER_COST_A73>; + clocks = <&clkc CLKID_CPUB_CLK>, + <&clkc CLKID_CPUB_FCLK_P>, + <&clkc CLKID_SYS_PLL>; + clock-names = "core_clk", + "low_freq_clk_parent", + "high_freq_clk_parent"; + operating-points-v2 = <&cpu_opp_table1>; + cpu-supply = <&vddcpu1>; + voltage-tolerance = <0>; + clock-latency = <50000>; + }; + + idle-states { + entry-method = "arm,psci"; + + CPU_SLEEP_0: cpu-sleep-0 { + compatible = "arm,idle-state"; + arm,psci-suspend-param = <0x0010000>; + local-timer-stop; + entry-latency-us = <8000>; + exit-latency-us = <8000>; + min-residency-us = <20000>; + }; + + CLUSTER_SLEEP_0: cluster-sleep-0 { + compatible = "arm,idle-state"; + arm,psci-suspend-param = <0x1010000>; + local-timer-stop; + entry-latency-us = <9000>; + exit-latency-us = <9000>; + min-residency-us = <25000>; + }; + }; + }; + + timer { + compatible = "arm,armv7-timer"; + interrupts = , + , + , + ; + }; + + timer_bc { + compatible = "arm, meson-bc-timer"; + reg= <0xffd0f190 0x4 0xffd0f194 0x4>; + timer_name = "Meson TimerF"; + clockevent-rating=<300>; + clockevent-shift=<20>; + clockevent-features=<0x23>; + interrupts = <0 60 1>; + bit_enable=<16>; + bit_mode=<12>; + bit_resolution=<0>; + }; + + arm_pmu { + compatible = "arm,cortex-a15-pmu"; + clusterb-enabled; + interrupts = , + ; + reg = <0xff634680 0x4>, + <0xff6347c0 0x04>; + cpumasks = <0x3 0x3C>; + /* default 10ms */ + relax-timer-ns = <10000000>; + /* default 10000us */ + max-wait-cnt = <10000>; + }; + + gic: interrupt-controller@2c001000 { + compatible = "arm,cortex-a15-gic", "arm,cortex-a9-gic"; + #interrupt-cells = <3>; + #address-cells = <0>; + interrupt-controller; + reg = <0xffc01000 0x1000>, + <0xffc02000 0x0100>; + interrupts = ; + }; + + psci { + compatible = "arm,psci-0.2"; + method = "smc"; + }; + + aml_pm { + compatible = "amlogic, pm"; + status = "okay"; + device_name = "aml_pm"; + debug_reg = <0xff8000a8>; + exit_reg = <0xff80023c>; + }; + + secmon { + compatible = "amlogic, secmon"; + memory-region = <&secmon_reserved>; + in_base_func = <0x82000020>; + out_base_func = <0x82000021>; + reserve_mem_size = <0x00300000>; + clear_range = <0x05100000 0x200000>; + }; + + securitykey { + compatible = "aml, securitykey"; + storage_query = <0x82000060>; + storage_read = <0x82000061>; + storage_write = <0x82000062>; + storage_tell = <0x82000063>; + storage_verify = <0x82000064>; + storage_status = <0x82000065>; + storage_list = <0x82000067>; + storage_remove = <0x82000068>; + storage_in_func = <0x82000023>; + storage_out_func = <0x82000024>; + storage_block_func = <0x82000025>; + storage_size_func = <0x82000027>; + storage_set_enctype = <0x8200006A>; + storage_get_enctype = <0x8200006B>; + storage_version = <0x8200006C>; + }; + + mailbox: mhu@c883c400 { + compatible = "amlogic, meson_mhu"; + reg = <0xff63c400 0x4c>, /* MHU registers */ + <0xfffe7000 0x800>; /* Payload area */ + interrupts = <0 209 1>, /* low priority interrupt */ + <0 210 1>; /* high priority interrupt */ + #mbox-cells = <1>; + mbox-names = "cpu_to_scp_low", "cpu_to_scp_high"; + mboxes = <&mailbox 0 &mailbox 1>; + }; + + cpu_iomap { + compatible = "amlogic, iomap"; + #address-cells=<1>; + #size-cells=<1>; + ranges; + io_cbus_base { + reg = <0xffd00000 0x26000>; + }; + io_apb_base { + reg = <0xffe01000 0x7f000>; + }; + io_aobus_base { + reg = <0xff800000 0xb000>; + }; + io_vapb_base { + reg = <0xff900000 0x50000>; + }; + io_hiu_base { + reg = <0xff63c000 0x2000>; + }; + }; + + xtal: xtal-clk { + compatible = "fixed-clock"; + clock-frequency = <24000000>; + clock-output-names = "xtal"; + #clock-cells = <0>; + }; + + cpu_info { + compatible = "amlogic, cpuinfo"; + status = "okay"; + cpuinfo_cmd = <0x82000044>; + }; + + aml_reboot{ + compatible = "aml, reboot"; + sys_reset = <0x84000009>; + sys_poweroff = <0x84000008>; + }; + + vpu { + compatible = "amlogic, vpu-g12b"; + dev_name = "vpu"; + status = "okay"; + clocks = <&clkc CLKID_VAPB_MUX>, + <&clkc CLKID_VPU_INTR>, + <&clkc CLKID_VPU_P0_COMP>, + <&clkc CLKID_VPU_P1_COMP>, + <&clkc CLKID_VPU_MUX>; + clock-names = "vapb_clk", + "vpu_intr_gate", + "vpu_clk0", + "vpu_clk1", + "vpu_clk"; + clk_level = <7>; + /* 0: 100.0M 1: 166.7M 2: 200.0M 3: 250.0M */ + /* 4: 333.3M 5: 400.0M 6: 500.0M 7: 666.7M */ + }; + + ethmac: ethernet@ff3f0000 { + compatible = "amlogic, g12a-eth-dwmac","snps,dwmac"; + reg = <0xff3f0000 0x10000 + 0xff634540 0x8 + 0xff64c000 0xa0>; + reg-names = "eth_base", "eth_cfg", "eth_pll"; + interrupts = <0 8 1>; + interrupt-names = "macirq"; + status = "disabled"; + clocks = <&clkc CLKID_ETH_CORE>; + clock-names = "ethclk81"; + pll_val = <0x9c0040a 0x927e0000 0xac5f49e5>; + analog_val = <0x20200000 0x0000c000 0x00000023>; + }; + + pinctrl_aobus: pinctrl@ff800014{ + compatible = "amlogic,meson-g12a-aobus-pinctrl"; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + gpio_ao: ao-bank@ff800014{ + reg = <0xff800014 0x8>, + <0xff800024 0x14>, + <0xff80001c 0x8>; + reg-names = "mux","gpio", "drive-strength"; + gpio-controller; + #gpio-cells = <2>; + }; + }; + + pinctrl_periphs: pinctrl@ff634480{ + compatible = "amlogic,meson-g12a-periphs-pinctrl"; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + gpio: banks@ff6346c0{ + reg = <0xff6346c0 0x40>, + <0xff6344e8 0x18>, + <0xff634520 0x18>, + <0xff634440 0x4c>, + <0xff634740 0x1c>; + reg-names = "mux", + "pull", + "pull-enable", + "gpio", + "drive-strength"; + gpio-controller; + #gpio-cells = <2>; + }; + }; + + audio_data: audio_data { + compatible = "amlogic, audio_data"; + query_licence_cmd = <0x82000050>; + status = "disabled"; + }; + + dwc3: dwc3@ff500000 { + compatible = "synopsys, dwc3"; + status = "disabled"; + reg = <0xff500000 0x100000>; + interrupts = <0 30 4>; + usb-phy = <&usb2_phy_v2>, <&usb3_phy_v2>; + cpu-type = "gxl"; + clock-src = "usb3.0"; + clocks = <&clkc CLKID_USB_GENERAL>; + clock-names = "dwc_general"; + }; + + usb2_phy_v2: usb2phy@ffe09000 { + compatible = "amlogic, amlogic-new-usb2-v2"; + status = "disabled"; + reg = <0xffe09000 0x80 + 0xffd01008 0x100 + 0xff636000 0x2000 + 0xff63a000 0x2000>; + pll-setting-1 = <0x09400414>; + pll-setting-2 = <0x927E0000>; + pll-setting-3 = <0xac5f69e5>; + pll-setting-4 = <0xfe18>; + pll-setting-5 = <0x8000fff>; + pll-setting-6 = <0x78000>; + pll-setting-7 = <0xe0004>; + pll-setting-8 = <0xe000c>; + }; + + usb3_phy_v2: usb3phy@ffe09080 { + compatible = "amlogic, amlogic-new-usb3-v2"; + status = "disabled"; + reg = <0xffe09080 0x20>; + phy-reg = <0xff646000>; + phy-reg-size = <0x2000>; + usb2-phy-reg = <0xffe09000>; + usb2-phy-reg-size = <0x80>; + interrupts = <0 16 4>; + clocks = <&clkc CLKID_PCIE_PLL>; + clock-names = "pcie_refpll"; + }; + + dwc2_a: dwc2_a@ff400000 { + compatible = "amlogic, dwc2"; + status = "disabled"; + device_name = "dwc2_a"; + reg = <0xff400000 0x40000>; + interrupts = <0 31 4>; + pl-periph-id = <0>; /** lm name */ + clock-src = "usb0"; /** clock src */ + port-id = <0>; /** ref to mach/usb.h */ + port-type = <2>; /** 0: otg, 1: host, 2: slave */ + port-speed = <0>; /** 0: default, high, 1: full */ + port-config = <0>; /** 0: default */ + /*0:default,1:single,2:incr,3:incr4,4:incr8,5:incr16,6:disable*/ + port-dma = <0>; + port-id-mode = <0>; /** 0: hardware, 1: sw_host, 2: sw_slave*/ + usb-fifo = <728>; + cpu-type = "v2"; + phy-reg = <0xffe09000>; + phy-reg-size = <0xa0>; + /** phy-interface: 0x0: amlogic phy, 0x1: synopsys phy **/ + phy-interface = <0x0>; + clocks = <&clkc CLKID_USB_GENERAL + &clkc CLKID_USB1_TO_DDR>; + clock-names = "usb_general", + "usb1"; + }; + + wdt: watchdog@0xffd0f0d0 { + compatible = "amlogic, meson-wdt"; + status = "okay"; + default_timeout=<10>; + reset_watchdog_method=<1>; /* 0:sysfs,1:kernel */ + reset_watchdog_time=<2>; + shutdown_timeout=<10>; + firmware_timeout=<6>; + suspend_timeout=<6>; + reg = <0xffd0f0d0 0x10>; + clock-names = "xtal"; + clocks = <&xtal>; + }; + + jtag { + compatible = "amlogic, jtag"; + status = "okay"; + select = "disable"; /* disable/apao/apee */ + pinctrl-names="jtag_apao_pins", "jtag_apee_pins"; + pinctrl-0=<&jtag_apao_pins>; + pinctrl-1=<&jtag_apee_pins>; + }; + + saradc:saradc { + compatible = "amlogic,meson-g12a-saradc"; + status = "disabled"; + #io-channel-cells = <1>; + clocks = <&xtal>, <&clkc CLKID_SARADC_GATE>; + clock-names = "xtal", "saradc_clk"; + interrupts = ; + reg = <0xff809000 0x48>; + }; + + p_tsensor: p_tsensor@ff634594 { + compatible = "amlogic, r1p1-tsensor"; + device_name = "meson-pthermal"; + status = "okay"; + reg = <0xff634800 0x50>, + <0xff800268 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 35 0>; + clocks = <&clkc CLKID_TS_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + d_tsensor: d_tsensor@ff800228 { + compatible = "amlogic, r1p1-tsensor"; + device_name = "meson-dthermal"; + status = "okay"; + reg = <0xff634c00 0x50>, + <0xff800230 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 36 0>; + clocks = <&clkc CLKID_TS_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + soc { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + cbus: cbus@ffd00000 { + compatible = "simple-bus"; + reg = <0xffd00000 0x26000>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0xffd00000 0x26000>; + + gpio_intc: interrupt-controller@f080 { + compatible = "amlogic,meson-gpio-intc", + "amlogic,meson-g12a-gpio-intc"; + reg = <0xf080 0x10>; + interrupt-controller; + #interrupt-cells = <2>; + amlogic,channel-interrupts = + <64 65 66 67 68 69 70 71>; + status = "okay"; + }; + + meson_clk_msr { + compatible = "amlogic, gxl_measure"; + reg = <0x18004 0x4 + 0x1800c 0x4>; + }; + + pwm_ab: pwm@1b000 { + compatible = "amlogic,g12b-ee-pwm"; + reg = <0x1b000 0x20>; + #pwm-cells = <3>; + clocks = <&xtal>, + <&xtal>, + <&xtal>, + <&xtal>; + clock-names = "clkin0", + "clkin1", + "clkin2", + "clkin3"; + /* default xtal 24m clkin0-clkin2 and + * clkin1-clkin3 should be set the same + */ + status = "disabled"; + }; + + pwm_cd: pwm@1a000 { + compatible = "amlogic,g12b-ee-pwm"; + reg = <0x1a000 0x20>; + #pwm-cells = <3>; + clocks = <&xtal>, + <&xtal>, + <&xtal>, + <&xtal>; + clock-names = "clkin0", + "clkin1", + "clkin2", + "clkin3"; + status = "disabled"; + }; + + pwm_ef: pwm@19000 { + compatible = "amlogic,g12b-ee-pwm"; + reg = <0x19000 0x20>; + #pwm-cells = <3>; + clocks = <&xtal>, + <&xtal>, + <&xtal>, + <&xtal>; + clock-names = "clkin0", + "clkin1", + "clkin2", + "clkin3"; + status = "disabled"; + }; + + i2c0: i2c@1f000 { + compatible = "amlogic,meson-g12b-i2c"; + status = "disabled"; + reg = <0x1f000 0x20>; + interrupts = , + ; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&clkc CLKID_I2C>; + clock-names = "clk_i2c"; + }; + + i2c1: i2c@1e000 { + compatible = "amlogic,meson-g12b-i2c"; + status = "disabled"; + reg = <0x1e000 0x20>; + interrupts = , + ; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&clkc CLKID_I2C>; + clock-names = "clk_i2c"; + }; + + i2c2: i2c@1d000 { + compatible = "amlogic,meson-g12b-i2c"; + status = "disabled"; + reg = <0x1d000 0x20>; + interrupts = , + ; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&clkc CLKID_I2C>; + clock-names = "clk_i2c"; + }; + + i2c3: i2c@1c000 { + compatible = "amlogic,meson-g12b-i2c"; + status = "disabled"; + reg = <0x1c000 0x20>; + interrupts = , + ; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&clkc CLKID_I2C>; + clock-names = "clk_i2c"; + }; + + spicc0: spi@13000 { + compatible = "amlogic,meson-g12b-spicc", + "amlogic,meson-g12a-spicc"; + reg = <0x13000 0x44>; + interrupts = ; + clocks = <&clkc CLKID_SPICC0>, + <&clkc CLKID_SPICC0_COMP>; + clock-names = "core", "comp"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + spicc1: spi@15000 { + compatible = "amlogic,meson-g12b-spicc", + "amlogic,meson-g12a-spicc"; + reg = <0x15000 0x44>; + interrupts = ; + clocks = <&clkc CLKID_SPICC1>, + <&clkc CLKID_SPICC1_COMP>; + clock-names = "core", "comp"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + }; /* end of cbus */ + + aobus: aobus@ff800000 { + compatible = "simple-bus"; + reg = <0xff800000 0xb000>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0xff800000 0xb000>; + + cpu_version { + reg=<0x220 0x4>; + }; + + aoclkc: clock-controller@0 { + compatible = "amlogic,g12b-aoclkc"; + #clock-cells = <1>; + reg = <0x0 0x320>; + }; + + pwm_AO_ab: pwm@7000 { + compatible = "amlogic,g12b-ao-pwm"; + reg = <0x7000 0x20>; + #pwm-cells = <3>; + clocks = <&xtal>, + <&xtal>, + <&xtal>, + <&xtal>; + clock-names = "clkin0", + "clkin1", + "clkin2", + "clkin3"; + status = "disabled"; + }; + + pwm_AO_cd: pwm@2000 { + compatible = "amlogic,g12b-ao-pwm"; + reg = <0x2000 0x20>; + #pwm-cells = <3>; + clocks = <&xtal>, + <&xtal>, + <&xtal>, + <&xtal>; + clock-names = "clkin0", + "clkin1", + "clkin2", + "clkin3"; + status = "disabled"; + }; + + i2c_AO: i2c@5000 { + compatible = "amlogic,meson-g12b-i2c"; + status = "disabled"; + reg = <0x05000 0x20>; + interrupts = , + ; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&clkc CLKID_I2C>; + clock-names = "clk_i2c"; + }; + + i2c_AO_slave:i2c_slave@6000 { + compatible = "amlogic, meson-i2c-slave"; + status = "disabled"; + reg = <0x6000 0x20>; + interrupts = <0 194 1>; + pinctrl-names="default"; + pinctrl-0=<&ao_i2c_slave_pins>; + }; + + uart_AO: serial@3000 { + compatible = "amlogic, meson-uart"; + reg = <0x3000 0x18>; + interrupts = <0 193 1>; + status = "okay"; + clocks = <&xtal>; + clock-names = "clk_uart"; + xtal_tick_en = <2>; + fifosize = < 64 >; + pinctrl-names = "default"; + /*pinctrl-0 = <&ao_uart_pins>;*/ + support-sysrq = <0>; /* 0 not support*/ + }; + + uart_AO_B: serial@4000 { + compatible = "amlogic, meson-uart"; + reg = <0x4000 0x18>; + interrupts = <0 197 1>; + status = "disabled"; + clocks = <&xtal>; + clock-names = "clk_uart"; + fifosize = < 64 >; + pinctrl-names = "default"; + pinctrl-0 = <&ao_b_uart_pins>; + }; + };/* end of aobus */ + + periphs: periphs@ff634400 { + compatible = "simple-bus"; + reg = <0xff634400 0x400>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0xff634400 0x400>; + + };/* end of periphs */ + + hiubus: hiubus@ff63c000 { + compatible = "simple-bus"; + reg = <0xff63c000 0x2000>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0xff63c000 0x2000>; + + clkc: clock-controller@0 { + compatible = "amlogic,g12b-clkc-1"; + #clock-cells = <1>; + reg = <0x0 0x3dc>; + }; + clkc_b: clock-controller@1 { + compatible = "amlogic,g12b-clkc-2"; + #clock-cells = <1>; + reg = <0x0 0x3dc>; + }; + };/* end of hiubus*/ + + ion_dev { + compatible = "amlogic, ion_dev"; + memory-region = <&ion_cma_reserved>; + };/* end of ion_dev*/ + + audiobus: audiobus@0xff642000 { + compatible = "amlogic, audio-controller", "simple-bus"; + reg = <0xff642000 0x2000>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0xff642000 0x2000>; + clkaudio: audio_clocks { + compatible = "amlogic, g12a-audio-clocks"; + #clock-cells = <1>; + reg = <0x0 0xb0>; + }; + ddr_manager { + compatible = "amlogic, g12a-audio-ddr-manager"; + interrupts = < + GIC_SPI 148 IRQ_TYPE_EDGE_RISING + GIC_SPI 149 IRQ_TYPE_EDGE_RISING + GIC_SPI 150 IRQ_TYPE_EDGE_RISING + GIC_SPI 152 IRQ_TYPE_EDGE_RISING + GIC_SPI 153 IRQ_TYPE_EDGE_RISING + GIC_SPI 154 IRQ_TYPE_EDGE_RISING + >; + interrupt-names = + "toddr_a", "toddr_b", "toddr_c", + "frddr_a", "frddr_b", "frddr_c"; + }; + };/* end of audiobus*/ + + }; /* end of soc*/ + + remote:rc@0xff808040 { + compatible = "amlogic, aml_remote"; + dev_name = "meson-remote"; + reg = <0xff808040 0x44>, /*Multi-format IR controller*/ + <0xff808000 0x20>; /*Legacy IR controller*/ + status = "okay"; + protocol = ; + interrupts = <0 196 1>; + pinctrl-names = "default"; + pinctrl-0 = <&remote_pins>; + map = <&custom_maps>; + max_frame_time = <200>; /*set software decoder max frame time*/ + }; + + custom_maps:custom_maps { + mapnum = <3>; + map0 = <&map_0>; + map1 = <&map_1>; + map2 = <&map_2>; + map_0: map_0{ + mapname = "amlogic-remote-1"; + customcode = <0xfb04>; + release_delay = <80>; + size = <50>; /*keymap size*/ + keymap = ; + }; + map_1: map_1{ + mapname = "amlogic-remote-2"; + customcode = <0xfe01>; + release_delay = <80>; + size = <53>; + keymap = ; + }; + map_2: map_2{ + mapname = "amlogic-remote-3"; + customcode = <0xbd02>; + release_delay = <80>; + size = <17>; + keymap = ; + }; + }; + + uart_A: serial@ffd24000 { + compatible = "amlogic, meson-uart"; + reg = <0xffd24000 0x18>; + interrupts = <0 26 1>; + status = "disabled"; + clocks = <&xtal + &clkc CLKID_UART0>; + clock-names = "clk_uart", + "clk_gate"; + fifosize = < 128 >; + pinctrl-names = "default"; + pinctrl-0 = <&a_uart_pins>; + }; + + uart_B: serial@ffd23000 { + compatible = "amlogic, meson-uart"; + reg = <0xffd23000 0x18>; + interrupts = <0 75 1>; + status = "disabled"; + clocks = <&xtal + &clkc CLKID_UART1>; + clock-names = "clk_uart", + "clk_gate"; + fifosize = < 64 >; + pinctrl-names = "default"; + pinctrl-0 = <&b_uart_pins>; + }; + + uart_C: serial@ffd22000 { + compatible = "amlogic, meson-uart"; + reg = <0xffd22000 0x18>; + interrupts = <0 93 1>; + status = "disabled"; + clocks = <&xtal + &clkc CLKID_UART1>; + clock-names = "clk_uart", + "clk_gate"; + fifosize = < 64 >; + pinctrl-names = "default"; + pinctrl-0 = <&c_uart_pins>; + }; + + + pcie_A: pcieA@fc000000 { + compatible = "amlogic, amlogic-pcie-v2", "snps,dw-pcie"; + reg = <0xfc000000 0x400000 + 0xff648000 0x2000 + 0xfc400000 0x200000 + 0xff646000 0x2000 + 0xffd01080 0x10>; + reg-names = "elbi", "cfg", "config", "phy", "reset"; + interrupts = <0 221 0>; + #interrupt-cells = <1>; + bus-range = <0x0 0xff>; + #address-cells = <3>; + #size-cells = <2>; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &gic GIC_SPI 223 IRQ_TYPE_EDGE_RISING>; + device_type = "pci"; + ranges = <0x81000000 0 0 0xfc600000 0x0 0x100000 + /* downstream I/O */ + 0x82000000 0 0xfc700000 0xfc700000 0 0x1900000>; + /* non-prefetchable memory */ + num-lanes = <1>; + pcie-num = <1>; + + clocks = <&clkc CLKID_PCIE_PLL + &clkc CLKID_PCIE_COMB + &clkc CLKID_PCIE_PHY>; + clock-names = "pcie_refpll", + "pcie", + "pcie_phy"; + /*reset-gpio-type 0:Shared pad(no reset)1:OD pad2:Normal pad*/ + gpio-type = <2>; + pcie-apb-rst-bit = <15>; + pcie-phy-rst-bit = <14>; + pcie-ctrl-a-rst-bit = <12>; + status = "disabled"; + }; + + amhdmitx: amhdmitx{ + compatible = "amlogic, amhdmitx"; + dev_name = "amhdmitx"; + status = "okay"; + vend-data = <&vend_data>; + pinctrl-names="default", "hdmitx_i2c"; + pinctrl-0=<&hdmitx_hpd &hdmitx_ddc>; + pinctrl-1=<&hdmitx_hpd_gpio &i2c3_master_pins1>; + clocks = <&clkc CLKID_VCLK2_ENCI + &clkc CLKID_VCLK2_VENCI0 + &clkc CLKID_VCLK2_VENCI1 + &clkc CLKID_VAPB_MUX + &clkc CLKID_VPU_MUX>; + clock-names = "venci_top_gate", + "venci_0_gate", + "venci_1_gate", + "hdmi_vapb_clk", + "hdmi_vpu_clk"; + /* HPD, 57 + 32 = 89; CEC, 151 + 32 = 183*/ + interrupts = <0 57 1>; + interrupt-names = "hdmitx_hpd"; + /* 0:M8B 1:GXBB 2:GXTVBB 3:GXL 4:GXM + * 5:TXL 6:TXLX 7:AXG 8:GXLX 9:TXHD + * 10:G12A 11:G12B + */ + ic_type = <11>; + vend_data: vend_data{ /* Should modified by Customer */ + vendor_name = "Amlogic"; /* Max Chars: 8 */ + /* standards.ieee.org/develop/regauth/oui/oui.txt */ + vendor_id = <0x000000>; + }; + }; + + galcore { + compatible = "amlogic, galcore"; + dev_name = "galcore"; + status = "disabled"; + clocks = <&clkc CLKID_VNANOQ_AXI_CLK_COMP>, + <&clkc CLKID_VNANOQ_CORE_CLK_COMP>; + clock-names = "cts_vipnanoq_axi_clk_composite", + "cts_vipnanoq_core_clk_composite"; + interrupts = <0 147 4>; + interrupt-names = "galcore"; + reg = <0xff100000 0x800 + 0xff000000 0x400000>; + }; + + aocec: aocec { + compatible = "amlogic, aocec-g12a"; + device_name = "aocec"; + status = "okay"; + vendor_name = "Amlogic"; /* Max Chars: 8 */ + /* Refer to the following URL at: + * http://standards.ieee.org/develop/regauth/oui/oui.txt + */ + vendor_id = <0x000000>; + product_desc = "G12B"; /* Max Chars: 16 */ + cec_osd_string = "AML_MBOX"; /* Max Chars: 14 */ + port_num = <1>; + ee_cec; + arc_port_mask = <0x2>; + interrupts = <0 203 1 + 0 199 1>; /*0:snps 1:ts*/ + interrupt-names = "hdmi_aocecb","hdmi_aocec"; + pinctrl-names = "default","hdmitx_aocecb","cec_pin_sleep"; + pinctrl-0=<&eecec_a>; + pinctrl-1=<&eecec_b>; + pinctrl-2=<&eecec_b>; + reg = <0xFF80023c 0x4 + 0xFF800000 0x400 + 0xFF634400 0x26>; + reg-names = "ao_exit","ao","periphs"; + }; + + /*if you want to use vdin just modify status to "ok"*/ + vdin0: vdin0 { + compatible = "amlogic, vdin"; + dev_name = "vdin0"; + status = "disabled"; + reserve-iomap = "true"; + flag_cma = <0>;/*1:share with codec_mm;2:cma alone*/ + /*MByte, if 10bit disable: 64M(YUV422), + *if 10bit enable: 64*1.5 = 96M(YUV422) + *if support 4K2K-YUV444-10bit-WR:3840*2160*4*4 ~= 128M + *if support 4K2K-YUV422-10bit-wr:3840*2160*3*4 ~= 96M + *if support 4K2K-YUV422-8BIT-WR:3840*2160*2*4 ~= 64M + *if support 1080p-YUV422-8BIT-WR:1920*1080*2*4 ~= 16M + */ + /*cma_size = <16>;*/ + interrupts = <0 83 1>; + rdma-irq = <2>; + /*clocks = <&clock CLK_FPLL_DIV5>, + * <&clock CLK_VDIN_MEAS_CLK>; + *clock-names = "fclk_div5", "cts_vdin_meas_clk"; + */ + vdin_id = <0>; + }; + vdin1: vdin1 { + compatible = "amlogic, vdin"; + dev_name = "vdin1"; + status = "disabled"; + reserve-iomap = "true"; + flag_cma = <0>;/*1:share with codec_mm;0:cma alone*/ + interrupts = <0 85 1>; + rdma-irq = <4>; + /*clocks = <&clock CLK_FPLL_DIV5>, + * <&clock CLK_VDIN_MEAS_CLK>; + *clock-names = "fclk_div5", "cts_vdin_meas_clk"; + */ + vdin_id = <1>; + }; + + vout { + compatible = "amlogic, vout"; + dev_name = "vout"; + status = "okay"; + }; + + vout2 { + compatible = "amlogic, vout2"; + dev_name = "vout"; + status = "okay"; + clocks = <&clkc CLKID_VPU_CLKC_P0_COMP>, + <&clkc CLKID_VPU_CLKC_MUX>; + clock-names = "vpu_clkc0", + "vpu_clkc"; + }; + + vdac { + compatible = "amlogic, vdac-g12b"; + status = "okay"; + }; + + canvas: canvas{ + compatible = "amlogic, meson, canvas"; + dev_name = "amlogic-canvas"; + status = "okay"; + reg = <0xff638000 0x2000>; + }; + + ge2d { + compatible = "amlogic, ge2d-g12a"; + dev_name = "ge2d"; + status = "okay"; + interrupts = <0 146 1>; + interrupt-names = "ge2d"; + clocks = <&clkc CLKID_VAPB_MUX>, + <&clkc CLKID_G2D>, + <&clkc CLKID_GE2D_GATE>; + clock-names = "clk_vapb_0", + "clk_ge2d", + "clk_ge2d_gate"; + reg = <0xff940000 0x10000>; + }; + + meson-amvideom { + compatible = "amlogic, amvideom"; + dev_name = "amvideom"; + status = "okay"; + interrupts = <0 3 1>; + interrupt-names = "vsync"; + }; + + codec_io: codec_io { + compatible = "amlogic, codec_io"; + status = "okay"; + #address-cells=<1>; + #size-cells=<1>; + ranges; + io_cbus_base{ + reg = <0xffd00000 0x100000>; + }; + io_dos_base{ + reg = <0xff620000 0x10000>; + }; + io_hiubus_base{ + reg = <0xff63c000 0x2000>; + }; + io_aobus_base{ + reg = <0xff800000 0x10000>; + }; + io_vcbus_base{ + reg = <0xff900000 0x40000>; + }; + io_dmc_base{ + reg = <0xff638000 0x2000>; + }; + io_efuse_base{ + reg = <0xff630000 0x2000>; + }; + }; + + gdc:gdc { + #address-cells=<1>; + #size-cells=<1>; + status = "ok"; + compatible = "amlogic, g12b-gdc"; + reg = <0xFF950000 0x0000100 + 0xFF63C16C 0x0000004 + 0xFF63C100 0x0000004>; + interrupts = <0 144 1>; + interrupt-names = "GDC"; + clocks = <&clkc CLKID_GDC_CORE_CLK_COMP + &clkc CLKID_GDC_AXI_CLK_COMP >; + clock-names = "core","axi"; + }; + + mesonstream { + compatible = "amlogic, codec, streambuf"; + dev_name = "mesonstream"; + status = "okay"; + clocks = <&clkc CLKID_DOS_PARSER + &clkc CLKID_DEMUX + &clkc CLKID_AHB_ARB0 + &clkc CLKID_DOS + &clkc CLKID_VDEC_MUX + &clkc CLKID_HCODEC_MUX + &clkc CLKID_HEVC_MUX + &clkc CLKID_HEVCF_MUX>; + clock-names = "parser_top", + "demux", + "ahbarb0", + "vdec", + "clk_vdec_mux", + "clk_hcodec_mux", + "clk_hevc_mux", + "clk_hevcb_mux"; + }; + + vdec { + compatible = "amlogic, vdec"; + dev_name = "vdec.0"; + status = "okay"; + interrupts = <0 3 1 + 0 23 1 + 0 32 1 + 0 43 1 + 0 44 1 + 0 45 1>; + interrupt-names = "vsync", + "demux", + "parser", + "mailbox_0", + "mailbox_1", + "mailbox_2"; + }; + + amvenc_avc{ + compatible = "amlogic, amvenc_avc"; + dev_name = "amvenc_avc"; + status = "okay"; + interrupts = <0 45 1>; + interrupt-names = "mailbox_2"; + }; + + hevc_enc{ + compatible = "cnm, HevcEnc"; + //memory-region = <&hevc_enc_reserved>; + dev_name = "HevcEnc"; + status = "okay"; + interrupts = <0 187 1>; + interrupt-names = "wave420l_irq"; + #address-cells=<1>; + #size-cells=<1>; + ranges; + io_reg_base{ + reg = <0xff610000 0x4000>; + }; + }; + + rdma{ + compatible = "amlogic, meson, rdma"; + dev_name = "amlogic-rdma"; + status = "okay"; + interrupts = <0 89 1>; + interrupt-names = "rdma"; + }; + + meson_fb: meson-fb { + compatible = "amlogic, meson-g12b"; + memory-region = <&logo_reserved>; + dev_name = "meson-fb"; + status = "disable"; + interrupts = <0 3 1 + 0 56 1 + 0 89 1>; + interrupt-names = "viu-vsync", "viu2-vsync", "rdma"; + /* uboot logo,fb0/fb1 memory size,if afbcd fb0=0x01851000*/ + display_mode_default = "1080p60hz"; + scale_mode = <1>; + /** 0:VPU free scale 1:OSD free scale 2:OSD super scale */ + display_size_default = <1920 1080 1920 2160 32>; + /*1920*1080*4*3 = 0x17BB000*/ + clocks = <&clkc CLKID_VPU_CLKC_MUX>; + clock-names = "vpu_clkc"; + }; + irblaster: meson-irblaster { + compatible = "amlogic, meson_irblaster"; + reg = <0xff80014c 0x10>, + <0xff800040 0x4>; + pinctrl-names = "default"; + pinctrl-0 = <&irblaster_pins>; + interrupts = <0 198 1>; + status = "disabled"; + }; + + sd_emmc_c: emmc@ffe07000 { + status = "disabled"; + compatible = "amlogic, meson-mmc-g12b-a"; + reg = <0xffe07000 0x800>; + interrupts = <0 191 1>; + pinctrl-names = "emmc_clk_cmd_pins", "emmc_all_pins"; + pinctrl-0 = <&emmc_clk_cmd_pins>; + pinctrl-1 = <&emmc_conf_pull_up &emmc_conf_pull_done>; + clocks = <&clkc CLKID_SD_EMMC_C>, + <&clkc CLKID_SD_EMMC_C_P0_COMP>, + <&clkc CLKID_FCLK_DIV2>, + <&clkc CLKID_FCLK_DIV5>, + <&xtal>; + clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + + bus-width = <8>; + cap-sd-highspeed; + cap-mmc-highspeed; + /* mmc-ddr-1_8v; */ + /* mmc-hs200-1_8v; */ + + max-frequency = <200000000>; + non-removable; + disable-wp; + emmc { + pinname = "emmc"; + ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ + /*caps defined in dts*/ + tx_delay = <0>; + max_req_size = <0x20000>; /**128KB*/ + gpio_dat3 = <&gpio BOOT_3 GPIO_ACTIVE_HIGH>; + hw_reset = <&gpio BOOT_9 GPIO_ACTIVE_HIGH>; + card_type = <1>; + /* 1:mmc card(include eMMC), + * 2:sd card(include tSD) + */ + }; + }; + + sd_emmc_b:sd@ffe05000 { + status = "disabled"; + compatible = "amlogic, meson-mmc-g12b"; + reg = <0xffe05000 0x800>; + interrupts = <0 190 1>; + + pinctrl-names = "sd_all_pins", + "sd_clk_cmd_pins", + "sd_1bit_pins", + "sd_clk_cmd_uart_pins", + "sd_1bit_uart_pins", + "sd_to_ao_uart_pins", + "ao_to_sd_uart_pins", + "sd_to_ao_jtag_pins", + "ao_to_sd_jtag_pins"; + pinctrl-0 = <&sd_all_pins>; + pinctrl-1 = <&sd_clk_cmd_pins>; + pinctrl-2 = <&sd_1bit_pins>; + pinctrl-3 = <&sd_to_ao_uart_clr_pins + &sd_clk_cmd_pins &ao_to_sd_uart_pins>; + pinctrl-4 = <&sd_to_ao_uart_clr_pins + &sd_1bit_pins &ao_to_sd_uart_pins>; + pinctrl-5 = <&sd_all_pins &sd_to_ao_uart_pins>; + pinctrl-6 = <&sd_to_ao_uart_clr_pins &ao_to_sd_uart_pins>; + pinctrl-7 = <&sd_all_pins &sd_to_ao_uart_pins>; + pinctrl-8 = <&sd_to_ao_uart_clr_pins &ao_to_sd_uart_pins>; + + clocks = <&clkc CLKID_SD_EMMC_B>, + <&clkc CLKID_SD_EMMC_B_P0_COMP>, + <&clkc CLKID_FCLK_DIV2>, + <&clkc CLKID_FCLK_DIV5>, + <&xtal>; + clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + + bus-width = <4>; + cap-sd-highspeed; + cap-mmc-highspeed; + max-frequency = <100000000>; + disable-wp; + sd { + pinname = "sd"; + ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ + max_req_size = <0x20000>; /**128KB*/ + gpio_dat3 = <&gpio GPIOC_3 GPIO_ACTIVE_HIGH>; + jtag_pin = <&gpio GPIOC_0 GPIO_ACTIVE_HIGH>; + gpio_cd = <&gpio GPIOC_6 GPIO_ACTIVE_HIGH>; + card_type = <5>; + /* 3:sdio device(ie:sdio-wifi), + * 4:SD combo (IO+mem) card + */ + }; + }; + + sd_emmc_a:sdio@ffe03000 { + status = "disabled"; + compatible = "amlogic, meson-mmc-g12b"; + reg = <0xffe03000 0x800>; + interrupts = <0 189 4>; + + pinctrl-names = "sdio_all_pins", + "sdio_clk_cmd_pins"; + pinctrl-0 = <&sdio_all_pins>; + pinctrl-1 = <&sdio_clk_cmd_pins>; + + clocks = <&clkc CLKID_SD_EMMC_A>, + <&clkc CLKID_SD_EMMC_A_P0_COMP>, + <&clkc CLKID_FCLK_DIV2>, + <&clkc CLKID_FCLK_DIV5>, + <&xtal>; + clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + + bus-width = <4>; + cap-sd-highspeed; + cap-mmc-highspeed; + max-frequency = <100000000>; + disable-wp; + sdio { + pinname = "sdio"; + ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ + max_req_size = <0x20000>; /**128KB*/ + card_type = <3>; + /* 3:sdio device(ie:sdio-wifi), + * 4:SD combo (IO+mem) card + */ + }; + }; + + nand: nfc@0 { + compatible = "amlogic, aml_mtd_nand"; + dev_name = "mtdnand"; + status = "disabled"; + reg = <0xFFE07800 0x200>; + interrupts = <0 34 1>; + + pinctrl-names = "nand_rb_mod","nand_norb_mod", "nand_cs_only"; + pinctrl-0 = <&all_nand_pins>; + pinctrl-1 = <&all_nand_pins>; + pinctrl-2 = <&nand_cs_pins>; + clocks = <&clkc CLKID_SD_EMMC_C>, + <&clkc CLKID_SD_EMMC_C_P0_COMP>; + clock-names = "core", "clkin"; + + device_id = <0>; + /*fip/tpl configurations, must be same + * with uboot if bl_mode was set as 1 + * bl_mode: 0 compact mode; 1 descrete mode + * if bl_mode was set as 1, fip configuration will work + */ + bl_mode = <1>; + /*copy count of fip*/ + fip_copies = <4>; + /*size of each fip copy */ + fip_size = <0x200000>; + nand_clk_ctrl = <0xFFE07000>; + /*partions defined in dts */ + }; + + meson_cooldev: meson-cooldev@0 { + status = "okay"; + compatible = "amlogic, meson-cooldev"; + device_name = "mcooldev"; + cooling_devices { + cpufreq_cool_cluster0 { + min_state = <1000000>; + dyn_coeff = <120>; + cluster_id = <0>; + gpu_pp = <2>; + node_name = "cpufreq_cool0"; + device_type = "cpufreq"; + }; + cpufreq_cool_cluster1 { + min_state = <1000000>; + dyn_coeff = <460>; + cluster_id = <1>; + gpu_pp = <2>; + node_name = "cpufreq_cool1"; + device_type = "cpufreq"; + }; + cpucore_cool_cluster { + min_state = <1>; + dyn_coeff = <0>; + gpu_pp = <2>; + node_name = "cpucore_cool"; + device_type = "cpucore"; + }; + gpufreq_cool { + min_state = <400>; + dyn_coeff = <358>; + cluster_id = <0>; + gpu_pp = <2>; + node_name = "gpufreq_cool0"; + device_type = "gpufreq"; + }; + gpucore_cool { + min_state = <1>; + dyn_coeff = <0>; + cluster_id = <0>; + gpu_pp = <2>; + node_name = "gpucore_cool0"; + device_type = "gpucore"; + }; + }; + cpufreq_cool0:cpufreq_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + cpufreq_cool1:cpufreq_cool1 { + #cooling-cells = <2>; /* min followed by max */ + }; + cpucore_cool:cpucore_cool { + #cooling-cells = <2>; /* min followed by max */ + }; + gpufreq_cool0:gpufreq_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + gpucore_cool0:gpucore_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + }; + /*meson cooling devices end*/ + + thermal-zones { + soc_thermal: soc_thermal { + polling-delay = <1000>; + polling-delay-passive = <100>; + sustainable-power = <3550>; + thermal-sensors = <&p_tsensor 0>; + trips { + pswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + pcontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + phot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + pcritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + + cooling-maps { + cpufreq_cooling_map0 { + trip = <&pcontrol>; + cooling-device = <&cpufreq_cool0 0 10>; + contribution = <1024>; + }; + cpufreq_cooling_map1 { + trip = <&pcontrol>; + cooling-device = <&cpufreq_cool1 0 9>; + contribution = <1024>; + }; + cpucore_cooling_map { + trip = <&pcontrol>; + cooling-device = <&cpucore_cool 0 5>; + contribution = <1024>; + }; + gpufreq_cooling_map { + trip = <&pcontrol>; + cooling-device = <&gpufreq_cool0 0 4>; + contribution = <1024>; + }; + gpucore_cooling_map { + trip = <&pcontrol>; + cooling-device = <&gpucore_cool0 0 2>; + contribution = <1024>; + }; + }; + }; + ddr_thermal: ddr_thermal { + polling-delay = <1000>; + polling-delay-passive = <100>; + sustainable-power = <3550>; + thermal-sensors = <&d_tsensor 1>; + trips { + dswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + dcontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + dhot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + dcritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + + }; + }; + /*thermal zone end*/ + + /* Sound iomap */ + aml_snd_iomap { + compatible = "amlogic, snd-iomap"; + status = "okay"; + #address-cells=<1>; + #size-cells=<1>; + ranges; + pdm_bus { + reg = <0xFF640000 0x2000>; + }; + audiobus_base { + reg = <0xFF642000 0x2000>; + }; + audiolocker_base { + reg = <0xFF64A000 0x2000>; + }; + eqdrc_base { + reg = <0xFF656000 0x1800>; + }; + reset_base { + reg = <0xFFD01000 0x1000>; + }; + }; + + vddcpu0: pwmao_d-regulator { + compatible = "pwm-regulator"; + pinctrl-names = "default"; + pinctrl-0 = <&pwm_ao_d_pins3>; + pwms = <&pwm_AO_cd MESON_PWM_1 1250 0>; + regulator-name = "vddcpu0"; + regulator-min-microvolt = <721000>; + regulator-max-microvolt = <1022000>; + regulator-always-on; + max-duty-cycle = <1250>; + /* Voltage Duty-Cycle */ + voltage-table = <1022000 0>, + <1011000 3>, + <1001000 6>, + <991000 10>, + <981000 13>, + <971000 16>, + <961000 20>, + <951000 23>, + <941000 26>, + <931000 30>, + <921000 33>, + <911000 36>, + <901000 40>, + <891000 43>, + <881000 46>, + <871000 50>, + <861000 53>, + <851000 56>, + <841000 60>, + <831000 63>, + <821000 67>, + <811000 70>, + <801000 73>, + <791000 76>, + <781000 80>, + <771000 83>, + <761000 86>, + <751000 90>, + <741000 93>, + <731000 96>, + <721000 100>; + status = "okay"; + }; + + vddcpu1: pwmab_a-regulator { + compatible = "pwm-regulator"; + pinctrl-names = "default"; + pinctrl-0 = <&pwm_a_e2>; + pwms = <&pwm_ab MESON_PWM_0 1250 0>; + regulator-name = "vddcpu1"; + regulator-min-microvolt = <721000>; + regulator-max-microvolt = <1022000>; + regulator-always-on; + max-duty-cycle = <1250>; + /* Voltage Duty-Cycle */ + voltage-table = <1022000 0>, + <1011000 3>, + <1001000 6>, + <991000 10>, + <981000 13>, + <971000 16>, + <961000 20>, + <951000 23>, + <941000 26>, + <931000 30>, + <921000 33>, + <911000 36>, + <901000 40>, + <891000 43>, + <881000 46>, + <871000 50>, + <861000 53>, + <851000 56>, + <841000 60>, + <831000 63>, + <821000 67>, + <811000 70>, + <801000 73>, + <791000 76>, + <781000 80>, + <771000 83>, + <761000 86>, + <751000 90>, + <741000 93>, + <731000 96>, + <721000 100>; + status = "okay"; + }; + + rng { + compatible = "amlogic,meson-rng"; + status = "okay"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0xff630218 0x4>; + quality = /bits/ 16 <1000>; + }; + + ddr_bandwidth { + compatible = "amlogic, ddr-bandwidth"; + status = "okay"; + reg = <0xff638000 0x100 + 0xff638c00 0x100>; + interrupts = <0 52 1>; + interrupt-names = "ddr_bandwidth"; + }; + dmc_monitor { + compatible = "amlogic, dmc_monitor"; + status = "okay"; + reg_base = <0xff639000>; + interrupts = <0 51 1>; + }; + + isp_sc: isp-sc@ff655400 { + compatible = "amlogic, isp-sc"; + reg = <0xff655400 0x00001000>; + reg-names = "isp_sc"; + interrupts = <0 17 0>; + interrupt-names = "isp_sc"; + }; + + isp: isp@ff140000 { + compatible = "arm, isp"; + reg = <0xff140000 0x00040000>; + reg-names = "ISP"; + interrupts = <0 142 4>; + interrupt-names = "ISP"; + temper-buf-size = <24>; + clocks = <&clkc CLKID_MIPI_ISP_CLK_COMP>, + <&clkc CLKID_MIPI_CSI_PHY_CLK0_COMP>; + clock-names = "cts_mipi_isp_clk_composite", + "cts_mipi_csi_phy_clk0_composite"; + link-device = <&isp_sc>; + }; + + adapter: isp-adapter@ff650000 { + compatible = "amlogic, isp-adapter"; + reg = <0xff650000 0x00006000>; + reg-names = "adapter"; + interrupts = <0 179 0>; + interrupt-names = "adapter-irq"; + }; + + phycsi: phy-csi@ff650000 { + compatible = "amlogic, phy-csi"; + reg = <0xff650000 0x00002000>, + <0xff652000 0x00002000>, + <0xff63c300 0x00000100>, + <0xff654000 0x00000100>, + <0xff654400 0x00000100>; + reg-names = "csi2_phy0", "csi2_phy1", "aphy_reg", + "csi0_host", "csi1_host"; + interrupts = <0 41 0>, + <0 42 0>, + <0 72 0>, + <0 74 0>, + <0 87 0>, + <0 88 0>; + interrupt-names = "phy0-irq", + "phy1-irq", + "csi-host0-intr2", + "csi-host0-intr1", + "csi-host1-intr2", + "csi-host1-intr1"; + link-device = <&adapter>; + }; + + defendkey: defendkey { + compatible = "amlogic, defendkey"; + reg = <0xff630218 0x4>; /*RNG_USR_DATA*/ + mem_size = <0 0x100000>; + status = "okay"; + }; +};/* end of / */ + +&pinctrl_aobus { + ao_uart_pins:ao_uart { + mux { + groups = "uart_ao_tx_a", + "uart_ao_rx_a"; + function = "uart_ao_a"; + }; + }; + + ao_b_uart_pins:ao_b_uart { + mux { + groups = "uart_ao_tx_b_2", + "uart_ao_rx_b_3"; + function = "uart_ao_b"; + }; + }; + + ao_i2c_master_pins1:ao_i2c_pins1 { + mux { + groups = "i2c_ao_sck", + "i2c_ao_sda"; + function = "i2c_ao"; + bias-pull-up; + drive-strength = <2>; + }; + }; + + ao_i2c_master_pins2:ao_i2c_pins2 { + mux { + groups = "i2c_ao_sck_e", + "i2c_ao_sda_e"; + function = "i2c_ao"; + bias-pull-up; + drive-strength = <2>; + }; + }; + + ao_i2c_slave_pins:ao_i2c_slave_pins { + mux { + groups = "i2c_ao_slave_sck", + "i2c_ao_slave_sda"; + function = "i2c_ao_slave"; + }; + }; + + pwm_ao_a_pins: pwm_ao_a { + mux { + groups = "pwm_ao_a"; + function = "pwm_ao_a"; + }; + }; + + pwm_ao_a_hiz_pins: pwm_ao_a_hiz { + mux { + groups = "pwm_ao_a_hiz"; + function = "pwm_ao_a"; + }; + }; + + pwm_ao_b_pins: pwm_ao_b { + mux { + groups = "pwm_ao_b"; + function = "pwm_ao_b"; + }; + }; + + pwm_ao_c_pins1: pwm_ao_c_pins1 { + mux { + groups = "pwm_ao_c_4"; + function = "pwm_ao_c"; + }; + }; + + pwm_ao_c_pins2: pwm_ao_c_pins2 { + mux { + groups = "pwm_ao_c_6"; + function = "pwm_ao_c"; + }; + }; + + pwm_ao_c_hiz_pins: pwm_ao_c_hiz { + mux { + groups = "pwm_ao_c_hiz_4"; + function = "pwm_ao_c"; + }; + }; + + pwm_ao_d_pins1: pwm_ao_d_pins1 { + mux { + groups = "pwm_ao_d_5"; + function = "pwm_ao_d"; + }; + }; + + pwm_ao_d_pins2: pwm_ao_d_pins2 { + mux { + groups = "pwm_ao_d_10"; + function = "pwm_ao_d"; + }; + }; + + pwm_ao_d_pins3: pwm_ao_d_pins3 { + mux { + groups = "pwm_ao_d_e"; + function = "pwm_ao_d"; + }; + }; + + aocec_a: ao_ceca { + mux { + groups = "cec_ao_a"; + function = "cec_ao"; + }; + }; + + aocec_b: ao_cecb { + mux { + groups = "cec_ao_b"; + function = "cec_ao"; + }; + }; + pwm_a_e2: pwm_a_e2 { + mux { + groups = "pwm_a_e2"; + function = "pwm_a_gpioe"; + }; + }; + + jtag_apao_pins:jtag_apao_pin { + mux { + groups = "jtag_a_tdi", + "jtag_a_tdo", + "jtag_a_clk", + "jtag_a_tms"; + function = "jtag_a"; + }; + }; +}; + +&pinctrl_periphs { + /* sdemmc portC */ + emmc_clk_cmd_pins:emmc_clk_cmd_pins { + mux { + groups = "emmc_clk", + "emmc_cmd"; + function = "emmc"; + input-enable; + bias-pull-up; + drive-strength = <3>; + }; + }; + + emmc_conf_pull_up:emmc_conf_pull_up { + mux { + groups = "emmc_nand_d7", + "emmc_nand_d6", + "emmc_nand_d5", + "emmc_nand_d4", + "emmc_nand_d3", + "emmc_nand_d2", + "emmc_nand_d1", + "emmc_nand_d0", + "emmc_clk", + "emmc_cmd"; + function = "emmc"; + input-enable; + bias-pull-up; + drive-strength = <3>; + }; + }; + + emmc_conf_pull_done:emmc_conf_pull_done { + mux { + groups = "emmc_nand_ds"; + function = "emmc"; + input-enable; + bias-pull-down; + drive-strength = <3>; + }; + }; + + /* sdemmc portB */ + sd_clk_cmd_pins:sd_clk_cmd_pins { + mux { + groups = "sdcard_cmd_c", + "sdcard_clk_c"; + function = "sdcard"; + input-enable; + bias-pull-up; + drive-strength = <3>; + }; + }; + + sd_all_pins:sd_all_pins { + mux { + groups = "sdcard_d0_c", + "sdcard_d1_c", + "sdcard_d2_c", + "sdcard_d3_c", + "sdcard_cmd_c", + "sdcard_clk_c"; + function = "sdcard"; + input-enable; + bias-pull-up; + drive-strength = <3>; + }; + }; + sd_1bit_pins:sd_1bit_pins { + mux { + groups = "sdcard_d0_c", + "sdcard_cmd_c", + "sdcard_clk_c"; + function = "sdcard"; + input-enable; + bias-pull-up; + drive-strength = <3>; + }; + }; + + ao_to_sd_uart_pins:ao_to_sd_uart_pins { + mux { + groups = "uart_ao_tx_a_c3", + "uart_ao_rx_a_c2"; + function = "uart_ao_a_ee"; + bias-pull-up; + input-enable; + }; + }; + /* sdemmc portA */ + sdio_clk_cmd_pins:sdio_clk_cmd_pins { + mux { + groups = "sdio_clk", + "sdio_cmd"; + function = "sdio"; + input-enable; + bias-pull-up; + drive-strength = <3>; + }; + }; + + sdio_all_pins:sdio_all_pins { + mux { + groups = "sdio_d0", + "sdio_d1", + "sdio_d2", + "sdio_d3", + "sdio_clk", + "sdio_cmd"; + function = "sdio"; + input-enable; + bias-pull-up; + drive-strength = <3>; + }; + }; + all_nand_pins: all_nand_pins { + mux { + groups = "emmc_nand_d0", + "emmc_nand_d1", + "emmc_nand_d2", + "emmc_nand_d3", + "emmc_nand_d4", + "emmc_nand_d5", + "emmc_nand_d6", + "emmc_nand_d7", + "nand_ce0", + "nand_ale", + "nand_cle", + "nand_wen_clk", + "nand_ren_wr", + "nand_rb0"; + function = "nand"; + input-enable; + }; + }; + + nand_cs_pins: nand_cs { + mux { + groups = "nand_ce0"; + function = "nand"; + }; + }; + + i2c0_master_pins1:i2c0_pins1 { + mux { + groups = "i2c0_sda_c", + "i2c0_sck_c"; + function = "i2c0"; + bias-pull-up; + drive-strength = <2>; + }; + }; + + i2c0_master_pins2:i2c0_pins2 { + mux { + groups = "i2c0_sda_z0", + "i2c0_sck_z1"; + function = "i2c0"; + bias-pull-up; + drive-strength = <2>; + }; + }; + + i2c0_master_pins3:i2c0_pins3 { + mux { + groups = "i2c0_sda_z7", + "i2c0_sck_z8"; + function = "i2c0"; + bias-pull-up; + drive-strength = <2>; + }; + }; + + i2c1_master_pins1:i2c1_pins1 { + mux { + groups = "i2c1_sda_x", + "i2c1_sck_x"; + function = "i2c1"; + bias-pull-up; + drive-strength = <2>; + }; + }; + + i2c1_master_pins2:i2c1_pins2 { + mux { + groups = "i2c1_sda_h2", + "i2c1_sck_h3"; + function = "i2c1"; + bias-pull-up; + drive-strength = <2>; + }; + }; + + i2c1_master_pins3:i2c1_pins3 { + mux { + groups = "i2c1_sda_h6", + "i2c1_sck_h7"; + function = "i2c1"; + bias-pull-up; + drive-strength = <2>; + }; + }; + + i2c2_master_pins1:i2c2_pins1 { + mux { + groups = "i2c2_sda_x", + "i2c2_sck_x"; + function = "i2c2"; + bias-pull-up; + drive-strength = <2>; + }; + }; + + i2c2_master_pins2:i2c2_pins2 { + mux { + groups = "i2c2_sda_z", + "i2c2_sck_z"; + function = "i2c2"; + bias-pull-up; + drive-strength = <2>; + }; + }; + + i2c3_master_pins1:i2c3_pins1 { + mux { + groups = "i2c3_sda_h", + "i2c3_sck_h"; + function = "i2c3"; + bias-pull-up; + drive-strength = <2>; + }; + }; + + i2c3_master_pins2:i2c3_pins2 { + mux { + groups = "i2c3_sda_a", + "i2c3_sck_a"; + function = "i2c3"; + bias-pull-up; + drive-strength = <2>; + }; + }; + + pwm_a_pins: pwm_a { + mux { + groups = "pwm_a"; + function = "pwm_a"; + }; + }; + + pwm_b_pins1: pwm_b_pins1 { + mux { + groups = "pwm_b_x7"; + function = "pwm_b"; + }; + }; + + pwm_b_pins2: pwm_b_pins2 { + mux { + groups = "pwm_b_x19"; + function = "pwm_b"; + }; + }; + + pwm_b_pins3: pwm_b_pins3 { + mux { + groups = "pwm_b_h"; + function = "pwm_b"; + }; + }; + + pwm_b_pins4: pwm_b_pins4 { + mux { + groups = "pwm_b_z0"; + function = "pwm_b"; + }; + }; + + pwm_b_pins5: pwm_b_pins5 { + mux { + groups = "pwm_b_z13"; + function = "pwm_b"; + }; + }; + + pwm_c_pins1: pwm_c_pins1 { + mux { + groups = "pwm_c_c4"; + function = "pwm_c"; + }; + }; + + pwm_c_pins2: pwm_c_pins2 { + mux { + groups = "pwm_c_x5"; + function = "pwm_c"; + }; + }; + + pwm_c_pins3: pwm_c_pins3 { + mux { + groups = "pwm_c_x8"; + function = "pwm_c"; + }; + }; + + pwm_c_pins4: pwm_c_pins4 { + mux { + groups = "pwm_c_z"; + function = "pwm_c"; + }; + }; + + pwm_d_pins1: pwm_d_pins1 { + mux { + groups = "pwm_d_x3"; + function = "pwm_d"; + }; + }; + + pwm_d_pins2: pwm_d_pins2 { + mux { + groups = "pwm_d_x6"; + function = "pwm_d"; + }; + }; + + pwm_d_pins3: pwm_d_pins3 { + mux { + groups = "pwm_d_z"; + function = "pwm_d"; + }; + }; + + pwm_d_pins4: pwm_d_pins4 { + mux { + groups = "pwm_d_a4"; + function = "pwm_d"; + }; + }; + + pwm_e_pins: pwm_e { + mux { + groups = "pwm_e"; + function = "pwm_e"; + }; + }; + + pwm_f_pins1: pwm_f_pins1 { + mux { + groups = "pwm_f_x"; + function = "pwm_f"; + }; + }; + + pwm_f_pins2: pwm_f_pins2 { + mux { + groups = "pwm_f_h"; + function = "pwm_f"; + }; + }; + + pwm_f_pins3: pwm_f_pins3 { + mux { + groups = "pwm_f_z"; + function = "pwm_f"; + }; + }; + + pwm_f_pins4: pwm_f_pins4 { + mux { + groups = "pwm_f_a11"; + function = "pwm_f"; + }; + }; + + spicc0_pins_x: spicc0_pins_x { + mux { + groups = "spi0_mosi_x", + "spi0_miso_x", + //"spi0_ss0_x", + "spi0_clk_x"; + function = "spi0"; + drive-strength = <1>; + }; + }; + + spicc1_pins: spicc1_pins { + mux { + groups = "spi1_mosi", + "spi1_miso", + //"spi1_ss0", + "spi1_clk"; + function = "spi1"; + drive-strength = <1>; + }; + }; + + a_uart_pins:a_uart { + mux { + groups = "uart_tx_a", + "uart_rx_a", + "uart_cts_a", + "uart_rts_a"; + function = "uart_a"; + }; + }; + + b_uart_pins:b_uart { + mux { + groups = "uart_tx_b", + "uart_rx_b"; + function = "uart_b"; + }; + }; + + c_uart_pins:c_uart { + mux { + groups = "uart_tx_c", + "uart_rx_c"; + function = "uart_c"; + }; + }; + + hdmitx_hpd: hdmitx_hpd { + mux { + groups = "hdmitx_hpd_in"; + function = "hdmitx"; + bias-disable; + }; + }; + + hdmitx_hpd_gpio: hdmitx_hpd_gpio { + mux { + groups = "GPIOH_1"; + function = "gpio_periphs"; + bias-disable; + }; + }; + + hdmitx_ddc: hdmitx_ddc { + mux { + groups = "hdmitx_sda", + "hdmitx_sck"; + function = "hdmitx"; + bias-disable; + }; + }; + + eecec_a: ee_ceca { + mux { + groups = "cec_ao_a_ee"; + function = "cec_ao_ee"; + }; + }; + + eecec_b: ee_cecb { + mux { + groups = "cec_ao_b_ee"; + function = "cec_ao_ee"; + }; + }; + + internal_eth_pins: internal_eth_pins { + mux { + groups = "eth_link_led", + "eth_act_led"; + function = "eth"; + }; + }; + + external_eth_pins: external_eth_pins { + mux { + groups = "eth_mdio", + "eth_mdc", + "eth_rgmii_rx_clk", + "eth_rx_dv", + "eth_rxd0", + "eth_rxd1", + "eth_rxd2_rgmii", + "eth_rxd3_rgmii", + "eth_rgmii_tx_clk", + "eth_txen", + "eth_txd0", + "eth_txd1", + "eth_txd2_rgmii", + "eth_txd3_rgmii"; + function = "eth"; + drive-strength = <3>; + }; + }; + + irblaster_pins2:irblaster_pins2 { + mux { + groups = "remote_out_h"; + function = "remote_out"; + }; + }; + + irblaster_pins3:irblaster_pins3 { + mux { + groups = "remote_out_z"; + function = "remote_out"; + }; + }; + + jtag_apee_pins:jtag_apee_pin { + mux { + groups = "jtag_b_tdi", + "jtag_b_tdo", + "jtag_b_clk", + "jtag_b_tms"; + function = "jtag_b"; + }; + }; +}; + +&gpu{ + system-coherency = <0>; + tbl = <&dvfs285_cfg + &dvfs400_cfg + &dvfs500_cfg + &dvfs666_cfg + &dvfs800_cfg + &dvfs800_cfg>; +}; + +&pinctrl_aobus { + sd_to_ao_uart_clr_pins:sd_to_ao_uart_clr_pins { + mux { + groups = "GPIOAO_0", + "GPIOAO_1"; + function = "gpio_aobus"; + }; + }; + + sd_to_ao_uart_pins:sd_to_ao_uart_pins { + mux { + groups = "uart_ao_tx_a", + "uart_ao_rx_a"; + function = "uart_ao_a"; + bias-pull-up; + input-enable; + }; + }; + + remote_pins:remote_pin { + mux { + groups = "remote_input_ao"; + function = "remote_input_ao"; + }; + }; + + irblaster_pins:irblaster_pin { + mux { + groups = "remote_out_ao"; + function = "remote_out_ao"; + }; + }; + + irblaster_pins1:irblaster_pin1 { + mux { + groups = "remote_out_ao9"; + function = "remote_out_ao"; + }; + }; +}; /* end of pinctrl_aobus */ diff --git a/arch/arm/boot/dts/amlogic/mesongxl.dtsi b/arch/arm/boot/dts/amlogic/mesongxl.dtsi index a220ea1c4fd3..e159aa654d17 100644 --- a/arch/arm/boot/dts/amlogic/mesongxl.dtsi +++ b/arch/arm/boot/dts/amlogic/mesongxl.dtsi @@ -134,19 +134,14 @@ arm_pmu { compatible = "arm,cortex-a15-pmu"; - interrupts = <0 137 4>; - reg = <0xc8834400 0x1000>; - - /* addr = base + offset << 2 */ - sys_cpu_status0_offset = <0xa0>; - - sys_cpu_status0_pmuirq_mask = <0xf>; - + /* clusterb-enabled; */ + interrupts = ; + reg = <0xc8834680 0x4>; + cpumasks = <0xf>; /* default 10ms */ - relax_timer_ns = <10000000>; - + relax-timer-ns = <10000000>; /* default 10000us */ - max_wait_cnt = <10000>; + max-wait-cnt = <10000>; }; gic: interrupt-controller@2c001000 { @@ -164,11 +159,12 @@ method = "smc"; }; - meson_suspend:pm{ + aml_pm { compatible = "amlogic, pm"; + status = "okay"; device_name = "aml_pm"; - reg = <0xc81000a8 0x4>, - <0xc810023c 0x4>; + debug_reg = <0xc81000a8>; + exit_reg = <0xc810023c>; }; secmon { @@ -250,20 +246,21 @@ ram-dump { compatible = "amlogic, ram_dump"; status = "okay"; + reg = <0xC88345E0 4>; + reg-names = "PREG_STICKY_REG8"; + store_device = "data"; }; jtag { compatible = "amlogic, jtag"; status = "okay"; - select = "apao"; /* disable/apao/apee */ - jtagao-gpios = <&gpio GPIOH_6 0 - &gpio GPIOH_7 0 - &gpio GPIOH_8 0 - &gpio GPIOH_9 0>; - jtagee-gpios = <&gpio CARD_0 0 - &gpio CARD_1 0 - &gpio CARD_2 0 - &gpio CARD_3 0>; + select = "disable"; /* disable/apao/apee */ + /* both sets of jtags for the GXL platform */ + /* are in the ee domain, this is named apao */ + /* just to match the jtag driver */ + pinctrl-names="jtag_apao_pins", "jtag_apee_pins"; + pinctrl-0=<&jtag_a_pins>; + pinctrl-1=<&jtag_b_pins>; }; mailbox: mhu@c883c400 { @@ -527,6 +524,14 @@ clocks = <&clkc CLKID_I2C>; clock-names = "clk_i2c"; }; + + irblaster: meson-irblaster@c0 { + compatible = "amlogic, aml_irblaster"; + reg = <0xc0 0xc>, + <0x40 0x4>; + #irblaster-cells = <2>; + status = "disabled"; + }; }; periphs: periphs@c8834000 { @@ -639,6 +644,20 @@ function = "ee_cec"; }; }; + + irblaster_pins:irblaster_pin { + mux { + groups = "ir_out_ao7"; + function = "ir_out"; + }; + }; + + irblaster_pins1:irblaster_pin1 { + mux { + groups = "ir_out_ao9"; + function = "ir_out"; + }; + }; }; /* end of pinctrl_aobus*/ &pinctrl_periphs { @@ -662,23 +681,23 @@ }; }; - jtag_apao_pins:jtag_apao_pin { + jtag_a_pins:jtag_a_pin { mux { - groups = "jtag_tdi_0", - "jtag_tdo_0", - "jtag_clk_0", - "jtag_tms_0"; - function = "jtag"; + groups = "GPIOH_6", + "GPIOH_7", + "GPIOH_8", + "GPIOH_9"; + function = "gpio_periphs"; }; }; - jtag_apee_pins:jtag_apee_pin { + jtag_b_pins:jtag_b_pin { mux { - groups ="jtag_tdi_1", - "jtag_tdo_1", - "jtag_clk_1", - "jtag_tms_1"; - function = "jtag"; + groups = "CARD_0", + "CARD_1", + "CARD_2", + "CARD_3"; + function = "gpio_periphs"; }; }; diff --git a/arch/arm/boot/dts/amlogic/mesongxl_sei210.dtsi b/arch/arm/boot/dts/amlogic/mesongxl_sei210.dtsi index 9f4e451d488d..dfc36e9bce33 100644 --- a/arch/arm/boot/dts/amlogic/mesongxl_sei210.dtsi +++ b/arch/arm/boot/dts/amlogic/mesongxl_sei210.dtsi @@ -115,7 +115,7 @@ }; timer { - compatible = "arm,armv8-timer"; + compatible = "arm,armv7-timer"; interrupts = , , , @@ -133,12 +133,17 @@ bit_mode=<12>; bit_resolution=<0>; }; + arm_pmu { - compatible = "arm,armv8-pmuv3"; - interrupts = <0 137 4>, - <0 138 4>, - <0 153 4>, - <0 154 4>; + compatible = "arm,cortex-a15-pmu"; + /* clusterb-enabled; */ + interrupts = ; + reg = <0xc8834680 0x4>; + cpumasks = <0xf>; + /* default 10ms */ + relax-timer-ns = <10000000>; + /* default 10000us */ + max-wait-cnt = <10000>; }; gic: interrupt-controller@2c001000 { @@ -156,11 +161,12 @@ method = "smc"; }; - meson_suspend:pm{ + aml_pm { compatible = "amlogic, pm"; + status = "okay"; device_name = "aml_pm"; - reg = <0xc81000a8 0x4 - 0xc810023c 0x4>; + debug_reg = <0xc81000a8>; + exit_reg = <0xc810023c>; }; secmon { @@ -235,15 +241,13 @@ jtag { compatible = "amlogic, jtag"; status = "okay"; - select = "apao"; /* disable/apao/apee */ - jtagao-gpios = <&gpio GPIOH_6 0 - &gpio GPIOH_7 0 - &gpio GPIOH_8 0 - &gpio GPIOH_9 0>; - jtagee-gpios = <&gpio CARD_0 0 - &gpio CARD_1 0 - &gpio CARD_2 0 - &gpio CARD_3 0>; + select = "disable"; /* disable/apao/apee */ + /* both sets of jtags for the GXL platform */ + /* are in the ee domain, this is named apao */ + /* just to match the jtag driver */ + pinctrl-names="jtag_apao_pins", "jtag_apee_pins"; + pinctrl-0=<&jtag_a_pins>; + pinctrl-1=<&jtag_b_pins>; }; mailbox: mhu@c883c400 { @@ -638,23 +642,23 @@ }; }; - jtag_apao_pins:jtag_apao_pin { + jtag_a_pins:jtag_a_pin { mux { - groups = "jtag_tdi_0", - "jtag_tdo_0", - "jtag_clk_0", - "jtag_tms_0"; - function = "jtag"; + groups = "GPIOH_6", + "GPIOH_7", + "GPIOH_8", + "GPIOH_9"; + function = "gpio_periphs"; }; }; - jtag_apee_pins:jtag_apee_pin { + jtag_b_pins:jtag_b_pin { mux { - groups ="jtag_tdi_1", - "jtag_tdo_1", - "jtag_clk_1", - "jtag_tms_1"; - function = "jtag"; + groups = "CARD_0", + "CARD_1", + "CARD_2", + "CARD_3"; + function = "gpio_periphs"; }; }; diff --git a/arch/arm/boot/dts/amlogic/mesongxm.dtsi b/arch/arm/boot/dts/amlogic/mesongxm.dtsi index 91a1e260630b..0fe9914d6301 100644 --- a/arch/arm/boot/dts/amlogic/mesongxm.dtsi +++ b/arch/arm/boot/dts/amlogic/mesongxm.dtsi @@ -26,6 +26,7 @@ #include #include #include "mesongxm-gpu-t82x.dtsi" +#include "gxm-sched-energy.dtsi" / { cpus:cpus { #address-cells = <1>; @@ -69,6 +70,8 @@ clocks = <&scpi_dvfs 0>; clock-names = "cpu-cluster.0"; cpu-idle-states = <&SYSTEM_SLEEP_0>; + sched-energy-costs = <&CPU_COST_A53_HS + &CLUSTER_COST_A53_HS>; /* * cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0 * &SYSTEM_SLEEP_0>; @@ -83,6 +86,8 @@ clocks = <&scpi_dvfs 0>; clock-names = "cpu-cluster.0"; cpu-idle-states = <&SYSTEM_SLEEP_0>; + sched-energy-costs = <&CPU_COST_A53_HS + &CLUSTER_COST_A53_HS>; /* * cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0 * &SYSTEM_SLEEP_0>; @@ -97,6 +102,8 @@ clocks = <&scpi_dvfs 0>; clock-names = "cpu-cluster.0"; cpu-idle-states = <&SYSTEM_SLEEP_0>; + sched-energy-costs = <&CPU_COST_A53_HS + &CLUSTER_COST_A53_HS>; /* * cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0 * &SYSTEM_SLEEP_0>; @@ -111,6 +118,8 @@ clocks = <&scpi_dvfs 0>; clock-names = "cpu-cluster.0"; cpu-idle-states = <&SYSTEM_SLEEP_0>; + sched-energy-costs = <&CPU_COST_A53_HS + &CLUSTER_COST_A53_HS>; /* * cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0 * &SYSTEM_SLEEP_0>; @@ -125,6 +134,8 @@ clocks = <&scpi_dvfs 1>; clock-names = "cpu-cluster.1"; cpu-idle-states = <&SYSTEM_SLEEP_0>; + sched-energy-costs = <&CPU_COST_A53 + &CLUSTER_COST_A53>; /* * cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0 * &SYSTEM_SLEEP_0>; @@ -139,6 +150,8 @@ clocks = <&scpi_dvfs 1>; clock-names = "cpu-cluster.1"; cpu-idle-states = <&SYSTEM_SLEEP_0>; + sched-energy-costs = <&CPU_COST_A53 + &CLUSTER_COST_A53>; /* * cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0 * &SYSTEM_SLEEP_0>; @@ -152,6 +165,8 @@ clocks = <&scpi_dvfs 1>; clock-names = "cpu-cluster.1"; cpu-idle-states = <&SYSTEM_SLEEP_0>; + sched-energy-costs = <&CPU_COST_A53 + &CLUSTER_COST_A53>; /* * cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0 * &SYSTEM_SLEEP_0>; @@ -166,6 +181,8 @@ clocks = <&scpi_dvfs 1>; clock-names = "cpu-cluster.1"; cpu-idle-states = <&SYSTEM_SLEEP_0>; + sched-energy-costs = <&CPU_COST_A53 + &CLUSTER_COST_A53>; /* * cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0 * &SYSTEM_SLEEP_0>; @@ -205,7 +222,7 @@ }; timer { - compatible = "arm,armv8-timer"; + compatible = "arm,armv7-timer"; interrupts = , , , @@ -223,12 +240,17 @@ bit_mode=<12>; bit_resolution=<0>; }; + arm_pmu { - compatible = "arm,armv8-pmuv3"; - interrupts = <0 137 4>, - <0 138 4>, - <0 153 4>, - <0 154 4>; + compatible = "arm,cortex-a15-pmu"; + /* clusterb-enabled; */ + interrupts = ; + reg = <0xc8834680 0x4>; + cpumasks = <0xf>; + /* default 10ms */ + relax-timer-ns = <10000000>; + /* default 10000us */ + max-wait-cnt = <10000>; }; gic: interrupt-controller@2c001000 { @@ -258,14 +280,21 @@ ram-dump { compatible = "amlogic, ram_dump"; status = "okay"; + reg = <0xC88345E0 4>; + reg-names = "PREG_STICKY_REG8"; + store_device = "data"; }; jtag { compatible = "amlogic, jtag"; - status = "disabled"; + status = "okay"; + select = "disable"; /* disable/apao/apee */ + /* both sets of jtags for the GXM platform */ + /* are in the ee domain, this is named apao */ + /* just to match the jtag driver */ pinctrl-names = "jtag_apao_pins", "jtag_apee_pins"; - pinctrl-0 = <&jtag_apao_pins>; - pinctrl-1 = <&jtag_apee_pins>; + pinctrl-0 = <&jtag_a_pins>; + pinctrl-1 = <&jtag_b_pins>; }; psci { @@ -273,11 +302,12 @@ method = "smc"; }; - meson_suspend:pm{ + aml_pm { compatible = "amlogic, pm"; + status = "okay"; device_name = "aml_pm"; - reg = <0xc81000a8 0x4>, - <0xc810023c 0x4>; + debug_reg = <0xc81000a8>; + exit_reg = <0xc810023c>; }; secmon { @@ -601,6 +631,14 @@ clocks = <&clkc CLKID_I2C>; clock-names = "clk_i2c"; }; + + irblaster: meson-irblaster@c0 { + compatible = "amlogic, aml_irblaster"; + reg = <0xc0 0xc>, + <0x40 0x4>; + #irblaster-cells = <2>; + status = "disabled"; + }; }; periphs: periphs@c8834000 { @@ -706,6 +744,20 @@ function = "ee_cec"; }; }; + + irblaster_pins:irblaster_pin { + mux { + groups = "ir_out_ao7"; + function = "ir_out"; + }; + }; + + irblaster_pins1:irblaster_pin1 { + mux { + groups = "ir_out_ao9"; + function = "ir_out"; + }; + }; }; /* end of pinctrl_aobus*/ &pinctrl_periphs { @@ -729,23 +781,23 @@ }; }; - jtag_apao_pins:jtag_apao_pin { + jtag_a_pins:jtag_a_pin { mux { - groups = "jtag_tdi_0", - "jtag_tdo_0", - "jtag_clk_0", - "jtag_tms_0"; - function = "jtag"; + groups = "GPIOH_6", + "GPIOH_7", + "GPIOH_8", + "GPIOH_9"; + function = "gpio_periphs"; }; }; - jtag_apee_pins:jtag_apee_pin { + jtag_b_pins:jtag_b_pin { mux { - groups ="jtag_tdi_1", - "jtag_tdo_1", - "jtag_clk_1", - "jtag_tms_1"; - function = "jtag"; + groups = "CARD_0", + "CARD_1", + "CARD_2", + "CARD_3"; + function = "gpio_periphs"; }; }; diff --git a/arch/arm/boot/dts/amlogic/mesonsm1.dtsi b/arch/arm/boot/dts/amlogic/mesonsm1.dtsi new file mode 100644 index 000000000000..0092cbe0741d --- /dev/null +++ b/arch/arm/boot/dts/amlogic/mesonsm1.dtsi @@ -0,0 +1,2415 @@ +/* + * arch/arm/boot/dts/amlogic/mesonsm1.dtsi + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "mesong12a-bifrost.dtsi" + +/ { + cpus:cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu-map { + cluster0:cluster0 { + core0 { + cpu = <&CPU0>; + }; + core1 { + cpu = <&CPU1>; + }; + core2 { + cpu = <&CPU2>; + }; + core3 { + cpu = <&CPU3>; + }; + }; + }; + + CPU0:cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a53","arm,armv8"; + reg = <0x0>; + enable-method = "psci"; + cpu-idle-states = <&CPU_SLEEP_0>; + clocks = <&clkc CLKID_CPU_CLK>, + <&clkc CLKID_CPU_FCLK_P>, + <&clkc CLKID_SYS_PLL>; + clock-names = "core_clk", + "low_freq_clk_parent", + "high_freq_clk_parent"; + operating-points-v2 = <&cpu_opp_table0>; + cpu-supply = <&vddcpu0>; + voltage-tolerance = <0>; + clock-latency = <50000>; + }; + + CPU1:cpu@1 { + device_type = "cpu"; + compatible = "arm,cortex-a53","arm,armv8"; + reg = <0x1>; + enable-method = "psci"; + cpu-idle-states = <&CPU_SLEEP_0>; + clocks = <&clkc CLKID_CPU_CLK>, + <&clkc CLKID_CPU_FCLK_P>, + <&clkc CLKID_SYS_PLL>; + clock-names = "core_clk", + "low_freq_clk_parent", + "high_freq_clk_parent"; + operating-points-v2 = <&cpu_opp_table0>; + cpu-supply = <&vddcpu0>; + voltage-tolerance = <0>; + clock-latency = <50000>; + }; + + CPU2:cpu@2 { + device_type = "cpu"; + compatible = "arm,cortex-a53","arm,armv8"; + reg = <0x2>; + enable-method = "psci"; + cpu-idle-states = <&CPU_SLEEP_0>; + clocks = <&clkc CLKID_CPU_CLK>, + <&clkc CLKID_CPU_FCLK_P>, + <&clkc CLKID_SYS_PLL>; + clock-names = "core_clk", + "low_freq_clk_parent", + "high_freq_clk_parent"; + operating-points-v2 = <&cpu_opp_table0>; + cpu-supply = <&vddcpu0>; + voltage-tolerance = <0>; + clock-latency = <50000>; + }; + + CPU3:cpu@3 { + device_type = "cpu"; + compatible = "arm,cortex-a53","arm,armv8"; + reg = <0x3>; + enable-method = "psci"; + cpu-idle-states = <&CPU_SLEEP_0>; + clocks = <&clkc CLKID_CPU_CLK>, + <&clkc CLKID_CPU_FCLK_P>, + <&clkc CLKID_SYS_PLL>; + clock-names = "core_clk", + "low_freq_clk_parent", + "high_freq_clk_parent"; + operating-points-v2 = <&cpu_opp_table0>; + cpu-supply = <&vddcpu0>; + voltage-tolerance = <0>; + clock-latency = <50000>; + }; + + idle-states { + entry-method = "arm,psci-0.2"; + CPU_SLEEP_0: cpu-sleep-0 { + compatible = "arm,idle-state"; + arm,psci-suspend-param = <0x0010000>; + local-timer-stop; + entry-latency-us = <4000>; + exit-latency-us = <5000>; + min-residency-us = <10000>; + }; + }; + }; + + timer { + compatible = "arm,armv7-timer"; + interrupts = , + , + , + ; + }; + + timer_bc { + compatible = "arm, meson-bc-timer"; + reg= <0xffd0f190 0x4 0xffd0f194 0x4>; + timer_name = "Meson TimerF"; + clockevent-rating=<300>; + clockevent-shift=<20>; + clockevent-features=<0x23>; + interrupts = <0 60 1>; + bit_enable=<16>; + bit_mode=<12>; + bit_resolution=<0>; + }; + + arm_pmu { + compatible = "arm,cortex-a15-pmu"; + /* clusterb-enabled; */ + interrupts = ; + reg = <0xff634680 0x4>; + cpumasks = <0xf>; + /* default 10ms */ + relax-timer-ns = <10000000>; + /* default 10000us */ + max-wait-cnt = <10000>; + }; + + gic: interrupt-controller@2c001000 { + compatible = "arm,cortex-a15-gic", "arm,cortex-a9-gic"; + #interrupt-cells = <3>; + #address-cells = <0>; + interrupt-controller; + reg = <0xffc01000 0x1000>, + <0xffc02000 0x0100>; + interrupts = ; + }; + + psci { + compatible = "arm,psci-0.2"; + method = "smc"; + }; + + aml_pm { + compatible = "amlogic, pm"; + status = "okay"; + device_name = "aml_pm"; + debug_reg = <0xff8000a8>; + exit_reg = <0xff80023c>; + }; + + secmon { + compatible = "amlogic, secmon"; + memory-region = <&secmon_reserved>; + in_base_func = <0x82000020>; + out_base_func = <0x82000021>; + reserve_mem_size = <0x00300000>; + }; + + securitykey { + compatible = "aml, securitykey"; + storage_query = <0x82000060>; + storage_read = <0x82000061>; + storage_write = <0x82000062>; + storage_tell = <0x82000063>; + storage_verify = <0x82000064>; + storage_status = <0x82000065>; + storage_list = <0x82000067>; + storage_remove = <0x82000068>; + storage_in_func = <0x82000023>; + storage_out_func = <0x82000024>; + storage_block_func = <0x82000025>; + storage_size_func = <0x82000027>; + storage_set_enctype = <0x8200006A>; + storage_get_enctype = <0x8200006B>; + storage_version = <0x8200006C>; + }; + + mailbox: mhu@c883c400 { + compatible = "amlogic, meson_mhu"; + reg = <0xff63c400 0x4c>, /* MHU registers */ + <0xfffe7000 0x800>; /* Payload area */ + interrupts = <0 209 1>, /* low priority interrupt */ + <0 210 1>; /* high priority interrupt */ + #mbox-cells = <1>; + mbox-names = "cpu_to_scp_low", "cpu_to_scp_high"; + mboxes = <&mailbox 0 &mailbox 1>; + }; + + cpu_iomap { + compatible = "amlogic, iomap"; + #address-cells=<1>; + #size-cells=<1>; + ranges; + io_cbus_base { + reg = <0xffd00000 0x26fff>; + }; + io_apb_base { + reg = <0xffe01000 0x7f000>; + }; + io_aobus_base { + reg = <0xff800000 0xb000>; + }; + io_vapb_base { + reg = <0xff900000 0x50000>; + }; + io_hiu_base { + reg = <0xff63c000 0x2000>; + }; + }; + + xtal: xtal-clk { + compatible = "fixed-clock"; + clock-frequency = <24000000>; + clock-output-names = "xtal"; + #clock-cells = <0>; + }; + + rtc{ + compatible = "amlogic, aml_vrtc"; + alarm_reg_addr = <0xff8000a8>; + timer_e_addr = <0xffd0f188>; + init_date = "2015/01/01"; + status = "okay"; + }; + + cpu_info { + compatible = "amlogic, cpuinfo"; + status = "okay"; + cpuinfo_cmd = <0x82000044>; + }; + + aml_reboot{ + compatible = "aml, reboot"; + sys_reset = <0x84000009>; + sys_poweroff = <0x84000008>; + }; + + vpu: vpu { + compatible = "amlogic, vpu-sm1"; + dev_name = "vpu"; + status = "okay"; + clocks = <&clkc CLKID_VAPB_MUX>, + <&clkc CLKID_VPU_INTR>, + <&clkc CLKID_VPU_P0_COMP>, + <&clkc CLKID_VPU_P1_COMP>, + <&clkc CLKID_VPU_MUX>; + clock-names = "vapb_clk", + "vpu_intr_gate", + "vpu_clk0", + "vpu_clk1", + "vpu_clk"; + clk_level = <7>; + /* 0: 100.0M 1: 166.7M 2: 200.0M 3: 250.0M */ + /* 4: 333.3M 5: 400.0M 6: 500.0M 7: 666.7M */ + }; + + ethmac: ethernet@ff3f0000 { + compatible = "amlogic, g12a-eth-dwmac","snps,dwmac"; + reg = <0xff3f0000 0x10000 + 0xff634540 0x8 + 0xff64c000 0xa0>; + reg-names = "eth_base", "eth_cfg", "eth_pll"; + interrupts = <0 8 1>; + interrupt-names = "macirq"; + status = "disabled"; + clocks = <&clkc CLKID_ETH_CORE>; + clock-names = "ethclk81"; + pll_val = <0x9c0040a 0x927e0000 0xac5f49e5>; + analog_val = <0x20200000 0x0000c000 0x00000023>; + }; + + pinctrl_aobus: pinctrl@ff800014{ + compatible = "amlogic,meson-g12a-aobus-pinctrl"; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + gpio_ao: ao-bank@ff800014{ + reg = <0xff800014 0x8>, + <0xff800024 0x14>, + <0xff80001c 0x8>; + reg-names = "mux","gpio", "drive-strength"; + gpio-controller; + #gpio-cells = <2>; + }; + }; + + pinctrl_periphs: pinctrl@ff634480{ + compatible = "amlogic,meson-g12a-periphs-pinctrl"; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + gpio: banks@ff6346c0{ + reg = <0xff6346c0 0x40>, + <0xff6344e8 0x18>, + <0xff634520 0x18>, + <0xff634440 0x4c>, + <0xff634740 0x1c>; + reg-names = "mux", + "pull", + "pull-enable", + "gpio", + "drive-strength"; + gpio-controller; + #gpio-cells = <2>; + }; + }; + + audio_data: audio_data { + compatible = "amlogic, audio_data"; + query_licence_cmd = <0x82000050>; + status = "disabled"; + }; + + dwc3: dwc3@ff500000 { + compatible = "synopsys, dwc3"; + status = "disable"; + reg = <0xff500000 0x100000>; + interrupts = <0 30 4>; + usb-phy = <&usb2_phy_v2>, <&usb3_phy_v2>; + cpu-type = "gxl"; + clock-src = "usb3.0"; + clocks = <&clkc CLKID_USB_GENERAL>; + clock-names = "dwc_general"; + }; + + usb2_phy_v2: usb2phy@ffe09000 { + compatible = "amlogic, amlogic-new-usb2-v2"; + status = "disable"; + reg = <0xffe09000 0x80 + 0xffd01008 0x100 + 0xff636000 0x2000 + 0xff63a000 0x2000>; + pll-setting-1 = <0x09400414>; + pll-setting-2 = <0x927E0000>; + pll-setting-3 = <0xac5f69e5>; + pll-setting-4 = <0xfe18>; + pll-setting-5 = <0x8000fff>; + pll-setting-6 = <0x78000>; + pll-setting-7 = <0xe0004>; + pll-setting-8 = <0xe000c>; + version = <2>; + pwr-ctl = <1>; + u2-ctrl-sleep-shift = <17>; + u2-hhi-mem-pd-shift = <30>; + u2-hhi-mem-pd-mask = <0x3>; + u2-ctrl-iso-shift = <17>; + }; + + usb3_phy_v2: usb3phy@ffe09080 { + compatible = "amlogic, amlogic-new-usb3-v2"; + status = "disable"; + reg = <0xffe09080 0x20 + 0xffd01008 0x100>; + phy-reg = <0xff646000>; + phy-reg-size = <0x2000>; + usb2-phy-reg = <0xffe09000>; + usb2-phy-reg-size = <0x80>; + interrupts = <0 16 4>; + clocks = <&clkc CLKID_PCIE_PLL>; + clock-names = "pcie_refpll"; + pwr-ctl = <1>; + u3-ctrl-sleep-shift = <18>; + u3-hhi-mem-pd-shift = <26>; + u3-hhi-mem-pd-mask = <0xf>; + u3-ctrl-iso-shift = <18>; + }; + + dwc2_a: dwc2_a@ff400000 { + compatible = "amlogic, dwc2"; + status = "disable"; + device_name = "dwc2_a"; + reg = <0xff400000 0x40000>; + interrupts = <0 31 4>; + pl-periph-id = <0>; /** lm name */ + clock-src = "usb0"; /** clock src */ + port-id = <0>; /** ref to mach/usb.h */ + port-type = <2>; /** 0: otg, 1: host, 2: slave */ + port-speed = <0>; /** 0: default, high, 1: full */ + port-config = <0>; /** 0: default */ + /*0:default,1:single,2:incr,3:incr4,4:incr8,5:incr16,6:disable*/ + port-dma = <0>; + port-id-mode = <0>; /** 0: hardware, 1: sw_host, 2: sw_slave*/ + usb-fifo = <728>; + cpu-type = "v2"; + phy-reg = <0xffe09000>; + phy-reg-size = <0xa0>; + /** phy-interface: 0x0: amlogic phy, 0x1: synopsys phy **/ + phy-interface = <0x2>; + clocks = <&clkc CLKID_USB_GENERAL + &clkc CLKID_USB1_TO_DDR>; + clock-names = "usb_general", + "usb1"; + }; + + wdt: watchdog@0xffd0f0d0 { + compatible = "amlogic, meson-wdt"; + status = "okay"; + default_timeout=<10>; + reset_watchdog_method=<1>; /* 0:sysfs,1:kernel */ + reset_watchdog_time=<2>; + shutdown_timeout=<10>; + firmware_timeout=<6>; + suspend_timeout=<6>; + reg = <0xffd0f0d0 0x10>; + clock-names = "xtal"; + clocks = <&xtal>; + }; + + ram-dump { + compatible = "amlogic, ram_dump"; + status = "okay"; + reg = <0xFF6345E0 4>; + reg-names = "PREG_STICKY_REG8"; + store_device = "data"; + }; + + jtag { + compatible = "amlogic, jtag"; + status = "okay"; + select = "disable"; /* disable/apao/apee */ + pinctrl-names="jtag_apao_pins", "jtag_apee_pins"; + pinctrl-0=<&jtag_apao_pins>; + pinctrl-1=<&jtag_apee_pins>; + }; + + saradc:saradc { + compatible = "amlogic,meson-g12a-saradc"; + status = "okay"; + #io-channel-cells = <1>; + clocks = <&xtal>, <&clkc CLKID_SARADC_GATE>; + clock-names = "xtal", "saradc_clk"; + interrupts = ; + reg = <0xff809000 0x48>; + }; + + power_ctrl: power_ctrl@ff8000e8 { + compatible = "amlogic, sm1-powerctrl"; + reg = <0xff8000e8 0x10>, + <0xff63c100 0x10>; + }; + + soc { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + cbus: cbus@ffd00000 { + compatible = "simple-bus"; + reg = <0xffd00000 0x26000>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0xffd00000 0x26000>; + + gpio_intc: interrupt-controller@f080 { + compatible = "amlogic,meson-gpio-intc", + "amlogic,meson-sm1-gpio-intc"; + reg = <0xf080 0x10>; + interrupt-controller; + #interrupt-cells = <2>; + amlogic,channel-interrupts = + <64 65 66 67 68 69 70 71>; + status = "okay"; + }; + + meson_clk_msr { + compatible = "amlogic, sm1-measure"; + reg = <0x18004 0x4 + 0x1800c 0x4>; + ringctrl = <0xff6345fc>; + }; + + pwm_ab: pwm@1b000 { + compatible = "amlogic,g12a-ee-pwm"; + reg = <0x1b000 0x20>; + #pwm-cells = <3>; + clocks = <&xtal>, + <&xtal>, + <&xtal>, + <&xtal>; + clock-names = "clkin0", + "clkin1", + "clkin2", + "clkin3"; + /* default xtal 24m clkin0-clkin2 and + * clkin1-clkin3 should be set the same + */ + status = "disabled"; + }; + + pwm_cd: pwm@1a000 { + compatible = "amlogic,g12a-ee-pwm"; + reg = <0x1a000 0x20>; + #pwm-cells = <3>; + clocks = <&xtal>, + <&xtal>, + <&xtal>, + <&xtal>; + clock-names = "clkin0", + "clkin1", + "clkin2", + "clkin3"; + status = "disabled"; + }; + + pwm_ef: pwm@19000 { + compatible = "amlogic,g12a-ee-pwm"; + reg = <0x19000 0x20>; + #pwm-cells = <3>; + clocks = <&xtal>, + <&xtal>, + <&xtal>, + <&xtal>; + clock-names = "clkin0", + "clkin1", + "clkin2", + "clkin3"; + status = "disabled"; + }; + + i2c0: i2c@1f000 { + compatible = "amlogic,meson-g12a-i2c"; + status = "disabled"; + reg = <0x1f000 0x20>; + interrupts = , + ; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&clkc CLKID_I2C>; + clock-names = "clk_i2c"; + }; + + i2c1: i2c@1e000 { + compatible = "amlogic,meson-g12a-i2c"; + status = "disabled"; + reg = <0x1e000 0x20>; + interrupts = , + ; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&clkc CLKID_I2C>; + clock-names = "clk_i2c"; + }; + + i2c2: i2c@1d000 { + compatible = "amlogic,meson-g12a-i2c"; + status = "disabled"; + reg = <0x1d000 0x20>; + interrupts = , + ; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&clkc CLKID_I2C>; + clock-names = "clk_i2c"; + }; + + i2c3: i2c@1c000 { + compatible = "amlogic,meson-g12a-i2c"; + status = "disabled"; + reg = <0x1c000 0x20>; + interrupts = , + ; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&clkc CLKID_I2C>; + clock-names = "clk_i2c"; + }; + + spicc0: spi@13000 { + compatible = "amlogic,meson-g12a-spicc"; + reg = <0x13000 0x44>; + interrupts = ; + clocks = <&clkc CLKID_SPICC0>, + <&clkc CLKID_SPICC0_COMP>; + clock-names = "core", "comp"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + spicc1: spi@15000 { + compatible = "amlogic,meson-g12a-spicc"; + reg = <0x15000 0x44>; + interrupts = ; + clocks = <&clkc CLKID_SPICC1>, + <&clkc CLKID_SPICC1_COMP>; + clock-names = "core", "comp"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + }; /* end of cbus */ + + aobus: aobus@ff800000 { + compatible = "simple-bus"; + reg = <0xff800000 0xb000>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0xff800000 0xb000>; + + cpu_version { + reg=<0x220 0x4>; + }; + + aoclkc: clock-controller@0 { + compatible = "amlogic,sm1-aoclkc"; + #clock-cells = <1>; + reg = <0x0 0x3dc>; + }; + + pwm_AO_ab: pwm@7000 { + compatible = "amlogic,g12a-ao-pwm"; + reg = <0x7000 0x20>; + #pwm-cells = <3>; + clocks = <&xtal>, + <&xtal>, + <&xtal>, + <&xtal>; + clock-names = "clkin0", + "clkin1", + "clkin2", + "clkin3"; + status = "disabled"; + }; + + pwm_AO_cd: pwm@2000 { + compatible = "amlogic,g12a-ao-pwm"; + reg = <0x2000 0x20>; + #pwm-cells = <3>; + clocks = <&xtal>, + <&xtal>, + <&xtal>, + <&xtal>; + clock-names = "clkin0", + "clkin1", + "clkin2", + "clkin3"; + status = "disabled"; + }; + + i2c_AO: i2c@5000 { + compatible = "amlogic,meson-g12a-i2c"; + status = "disabled"; + reg = <0x05000 0x20>; + interrupts = , + ; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&clkc CLKID_I2C>; + clock-names = "clk_i2c"; + }; + + i2c_AO_slave:i2c_slave@6000 { + compatible = "amlogic, meson-i2c-slave"; + status = "disabled"; + reg = <0x6000 0x20>; + interrupts = <0 194 1>; + pinctrl-names="default"; + pinctrl-0=<&ao_i2c_slave_pins>; + }; + + uart_AO: serial@3000 { + compatible = "amlogic, meson-uart"; + reg = <0x3000 0x18>; + interrupts = <0 193 1>; + status = "okay"; + clocks = <&xtal>; + clock-names = "clk_uart"; + xtal_tick_en = <2>; + fifosize = < 64 >; + pinctrl-names = "default"; + /*pinctrl-0 = <&ao_uart_pins>;*/ + support-sysrq = <0>; /* 0 not support*/ + }; + + uart_AO_B: serial@4000 { + compatible = "amlogic, meson-uart"; + reg = <0x4000 0x18>; + interrupts = <0 197 1>; + status = "disabled"; + clocks = <&xtal>; + clock-names = "clk_uart"; + fifosize = < 64 >; + pinctrl-names = "default"; + pinctrl-0 = <&ao_b_uart_pins>; + }; + };/* end of aobus */ + + periphs: periphs@ff634400 { + compatible = "simple-bus"; + reg = <0xff634400 0x400>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0xff634400 0x400>; + + };/* end of periphs */ + + hiubus: hiubus@ff63c000 { + compatible = "simple-bus"; + reg = <0xff63c000 0x2000>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0xff63c000 0x2000>; + + clkc: clock-controller@0 { + compatible = "amlogic,sm1-clkc-1"; + #clock-cells = <1>; + reg = <0x0 0x3dc>; + }; + + clkc_b: clock-controller@1 { + compatible = "amlogic,sm1-clkc-2"; + #clock-cells = <1>; + reg = <0x0 0x3dc>; + }; + };/* end of hiubus*/ + + ion_dev { + compatible = "amlogic, ion_dev"; + memory-region = <&ion_cma_reserved>; + };/* end of ion_dev*/ + + audiobus: audiobus@0xFF660000 { + compatible = "amlogic, audio-controller", "simple-bus"; + reg = <0xFF660000 0x4000>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0xFF660000 0x4000>; + clkaudio: audio_clocks { + compatible = "amlogic, sm1-audio-clocks"; + #clock-cells = <1>; + reg = <0x0 0xb0>; + }; + ddr_manager { + compatible = "amlogic, sm1-audio-ddr-manager"; + interrupts = < + GIC_SPI 148 IRQ_TYPE_EDGE_RISING + GIC_SPI 149 IRQ_TYPE_EDGE_RISING + GIC_SPI 150 IRQ_TYPE_EDGE_RISING + GIC_SPI 49 IRQ_TYPE_EDGE_RISING + GIC_SPI 152 IRQ_TYPE_EDGE_RISING + GIC_SPI 153 IRQ_TYPE_EDGE_RISING + GIC_SPI 154 IRQ_TYPE_EDGE_RISING + GIC_SPI 50 IRQ_TYPE_EDGE_RISING + >; + interrupt-names = + "toddr_a", "toddr_b", "toddr_c", + "toddr_d", + "frddr_a", "frddr_b", "frddr_c", + "frddr_d"; + }; + };/* end of audiobus*/ + + }; /* end of soc*/ + + remote:rc@0xff808040 { + compatible = "amlogic, aml_remote"; + dev_name = "meson-remote"; + reg = <0xff808040 0x44>, /*Multi-format IR controller*/ + <0xff808000 0x20>; /*Legacy IR controller*/ + status = "okay"; + protocol = ; + led_blink = <1>; + led_blink_frq = <100>; + interrupts = <0 196 1>; + pinctrl-names = "default"; + pinctrl-0 = <&remote_pins>; + map = <&custom_maps>; + max_frame_time = <200>; /*set software decoder max frame time*/ + }; + + custom_maps:custom_maps { + mapnum = <3>; + map0 = <&map_0>; + map1 = <&map_1>; + map2 = <&map_2>; + map_0: map_0{ + mapname = "amlogic-remote-1"; + customcode = <0xfb04>; + release_delay = <80>; + size = <50>; /*keymap size*/ + keymap = ; + }; + map_1: map_1{ + mapname = "amlogic-remote-2"; + customcode = <0xfe01>; + release_delay = <80>; + size = <53>; + keymap = ; + }; + map_2: map_2{ + mapname = "amlogic-remote-3"; + customcode = <0xbd02>; + release_delay = <80>; + size = <17>; + keymap = ; + }; + }; + + uart_A: serial@ffd24000 { + compatible = "amlogic, meson-uart"; + reg = <0xffd24000 0x18>; + interrupts = <0 26 1>; + status = "disabled"; + clocks = <&xtal + &clkc CLKID_UART0>; + clock-names = "clk_uart", + "clk_gate"; + fifosize = < 128 >; + pinctrl-names = "default"; + pinctrl-0 = <&a_uart_pins>; + }; + + uart_B: serial@ffd23000 { + compatible = "amlogic, meson-uart"; + reg = <0xffd23000 0x18>; + interrupts = <0 75 1>; + status = "disabled"; + clocks = <&xtal + &clkc CLKID_UART1>; + clock-names = "clk_uart", + "clk_gate"; + fifosize = < 64 >; + pinctrl-names = "default"; + pinctrl-0 = <&b_uart_pins>; + }; + + uart_C: serial@ffd22000 { + compatible = "amlogic, meson-uart"; + reg = <0xffd22000 0x18>; + interrupts = <0 93 1>; + status = "disabled"; + clocks = <&xtal + &clkc CLKID_UART1>; + clock-names = "clk_uart", + "clk_gate"; + fifosize = < 64 >; + pinctrl-names = "default"; + pinctrl-0 = <&c_uart_pins>; + }; + + + pcie_A: pcieA@fc000000 { + compatible = "amlogic, amlogic-pcie-v2", "snps,dw-pcie"; + reg = <0xfc000000 0x400000 + 0xff648000 0x2000 + 0xfc400000 0x200000 + 0xff646000 0x2000 + 0xffd01080 0x10>; + reg-names = "elbi", "cfg", "config", "phy", + "reset"; + interrupts = <0 221 0>; + #interrupt-cells = <1>; + bus-range = <0x0 0xff>; + #address-cells = <3>; + #size-cells = <2>; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &gic GIC_SPI 223 IRQ_TYPE_EDGE_RISING>; + device_type = "pci"; + ranges = <0x81000000 0 0 0xfc600000 0x0 0x100000 + /* downstream I/O */ + 0x82000000 0xfc700000 0x0 0xfc700000 0 0x1900000>; + /* non-prefetchable memory */ + num-lanes = <1>; + pcie-num = <1>; + + clocks = <&clkc CLKID_PCIE_PLL + &clkc CLKID_PCIE_COMB + &clkc CLKID_PCIE_PHY>; + clock-names = "pcie_refpll", + "pcie", + "pcie_phy"; + /*reset-gpio-type 0:Shared pad(no reset)1:OD pad2:Normal pad*/ + gpio-type = <2>; + pcie-apb-rst-bit = <15>; + pcie-phy-rst-bit = <14>; + pcie-ctrl-a-rst-bit = <12>; + pwr-ctl = <1>; + pcie-ctrl-sleep-shift = <18>; + pcie-hhi-mem-pd-shift = <26>; + pcie-hhi-mem-pd-mask = <0xf>; + pcie-ctrl-iso-shift = <18>; + status = "disabled"; + }; + + amhdmitx: amhdmitx{ + compatible = "amlogic, amhdmitx"; + dev_name = "amhdmitx"; + status = "okay"; + vend-data = <&vend_data>; + pinctrl-names="default", "hdmitx_i2c"; + pinctrl-0=<&hdmitx_hpd &hdmitx_ddc>; + pinctrl-1=<&hdmitx_hpd_gpio &i2c3_master_pins1>; + clocks = <&clkc CLKID_VCLK2_ENCI + &clkc CLKID_VCLK2_VENCI0 + &clkc CLKID_VCLK2_VENCI1 + &clkc CLKID_VAPB_MUX + &clkc CLKID_VPU_MUX>; + clock-names = "venci_top_gate", + "venci_0_gate", + "venci_1_gate", + "hdmi_vapb_clk", + "hdmi_vpu_clk"; + /* HPD, 57 + 32 = 89; CEC, 151 + 32 = 183*/ + interrupts = <0 57 1>; + interrupt-names = "hdmitx_hpd"; + /* 0:M8B 1:GXBB 2:GXTVBB 3:GXL 4:GXM + * 5:TXL 6:TXLX 7:AXG 8:GXLX 9:TXHD + * 10:G12A 11:G12B 12:SM1 + */ + ic_type = <12>; + vend_data: vend_data{ /* Should modified by Customer */ + vendor_name = "Amlogic"; /* Max Chars: 8 */ + /* standards.ieee.org/develop/regauth/oui/oui.txt */ + vendor_id = <0x000000>; + }; + }; + + galcore { + compatible = "amlogic, galcore"; + dev_name = "galcore"; + status = "disabled"; + clocks = <&clkc CLKID_VNANOQ_AXI_CLK_COMP>, + <&clkc CLKID_VNANOQ_CORE_CLK_COMP>; + clock-names = "cts_vipnanoq_axi_clk_composite", + "cts_vipnanoq_core_clk_composite"; + interrupts = <0 186 4>; + interrupt-names = "galcore"; + reg = <0xff100000 0x800 + /*reg base value:0xff100000 */ + 0xff000000 0x400000 + /*Sram bse value:0xff000000*/ + 0xff63c118 0x0 + 0xff63c11c 0x0 + /*0xff63c118,0xff63c11c :nanoq mem regs*/ + 0xffd01088 0x0 + /*0xffd01088:reset reg*/ + >; + }; + aocec: aocec { + compatible = "amlogic, aocec-sm1"; + device_name = "aocec"; + status = "okay"; + vendor_name = "Amlogic"; /* Max Chars: 8 */ + /* Refer to the following URL at: + * http://standards.ieee.org/develop/regauth/oui/oui.txt + */ + vendor_id = <0x000000>; + product_desc = "SM1"; /* Max Chars: 16 */ + cec_osd_string = "AML_MBOX"; /* Max Chars: 14 */ + cec_version = <5>;/*5:1.4;6:2.0*/ + port_num = <1>; + ee_cec; + arc_port_mask = <0x2>; + interrupts = <0 203 1 + 0 199 1>; /*0:snps 1:ts*/ + interrupt-names = "hdmi_aocecb","hdmi_aocec"; + pinctrl-names = "default","hdmitx_aocecb","cec_pin_sleep"; + pinctrl-0=<&eecec_a>; + pinctrl-1=<&eecec_b>; + pinctrl-2=<&eecec_b>; + reg = <0xFF80023c 0x4 + 0xFF800000 0x400 + 0xFF634400 0x70>; + reg-names = "ao_exit","ao","periphs"; + }; + + /*if you want to use vdin just modify status to "ok"*/ + vdin0: vdin0 { + compatible = "amlogic, vdin"; + dev_name = "vdin0"; + status = "disabled"; + reserve-iomap = "true"; + flag_cma = <0>;/*1:share with codec_mm;2:cma alone*/ + /*MByte, if 10bit disable: 64M(YUV422), + *if 10bit enable: 64*1.5 = 96M(YUV422) + *if support 4K2K-YUV444-10bit-WR:3840*2160*4*4 ~= 128M + *if support 4K2K-YUV422-10bit-wr:3840*2160*3*4 ~= 96M + *if support 4K2K-YUV422-8BIT-WR:3840*2160*2*4 ~= 64M + *if support 1080p-YUV422-8BIT-WR:1920*1080*2*4 ~= 16M + */ + /*cma_size = <16>;*/ + interrupts = <0 83 1>; + rdma-irq = <2>; + /*clocks = <&clock CLK_FPLL_DIV5>, + * <&clock CLK_VDIN_MEAS_CLK>; + *clock-names = "fclk_div5", "cts_vdin_meas_clk"; + */ + vdin_id = <0>; + }; + vdin1: vdin1 { + compatible = "amlogic, vdin"; + dev_name = "vdin1"; + status = "disabled"; + reserve-iomap = "true"; + flag_cma = <0>;/*1:share with codec_mm;0:cma alone*/ + interrupts = <0 85 1>; + rdma-irq = <4>; + /*clocks = <&clock CLK_FPLL_DIV5>, + * <&clock CLK_VDIN_MEAS_CLK>; + *clock-names = "fclk_div5", "cts_vdin_meas_clk"; + */ + vdin_id = <1>; + }; + + vout { + compatible = "amlogic, vout"; + dev_name = "vout"; + status = "okay"; + }; + + vout2 { + compatible = "amlogic, vout2"; + dev_name = "vout"; + status = "okay"; + clocks = <&clkc CLKID_VPU_CLKC_P0_COMP>, + <&clkc CLKID_VPU_CLKC_MUX>; + clock-names = "vpu_clkc0", + "vpu_clkc"; + }; + + vdac { + compatible = "amlogic, vdac-sm1"; + status = "okay"; + }; + + canvas: canvas{ + compatible = "amlogic, meson, canvas"; + dev_name = "amlogic-canvas"; + status = "okay"; + reg = <0xff638000 0x2000>; + }; + + ge2d { + compatible = "amlogic, ge2d-sm1"; + dev_name = "ge2d"; + status = "okay"; + interrupts = <0 146 1>; + interrupt-names = "ge2d"; + clocks = <&clkc CLKID_VAPB_MUX>, + <&clkc CLKID_G2D>, + <&clkc CLKID_GE2D_GATE>; + clock-names = "clk_vapb_0", + "clk_ge2d", + "clk_ge2d_gate"; + reg = <0xff940000 0x10000>; + }; + + meson-amvideom { + compatible = "amlogic, amvideom"; + dev_name = "amvideom"; + status = "okay"; + interrupts = <0 3 1>; + interrupt-names = "vsync"; + }; + + codec_io: codec_io { + compatible = "amlogic, codec_io"; + status = "okay"; + #address-cells=<1>; + #size-cells=<1>; + ranges; + io_cbus_base{ + reg = <0xffd00000 0x100000>; + }; + io_dos_base{ + reg = <0xff620000 0x10000>; + }; + io_hiubus_base{ + reg = <0xff63c000 0x2000>; + }; + io_aobus_base{ + reg = <0xff800000 0x10000>; + }; + io_vcbus_base{ + reg = <0xff900000 0x40000>; + }; + io_dmc_base{ + reg = <0xff638000 0x2000>; + }; + io_efuse_base{ + reg = <0xff630000 0x2000>; + }; + }; + + mesonstream { + compatible = "amlogic, codec, streambuf"; + dev_name = "mesonstream"; + status = "okay"; + clocks = <&clkc CLKID_DOS_PARSER + &clkc CLKID_DEMUX + &clkc CLKID_AHB_ARB0 + &clkc CLKID_DOS + &clkc CLKID_CLK81 + &clkc CLKID_VDEC_MUX + &clkc CLKID_HCODEC_MUX + &clkc CLKID_HEVC_MUX + &clkc CLKID_HEVCF_MUX>; + clock-names = "parser_top", + "demux", + "ahbarb0", + "vdec", + "clk_81", + "clk_vdec_mux", + "clk_hcodec_mux", + "clk_hevc_mux", + "clk_hevcb_mux"; + }; + + vdec { + compatible = "amlogic, vdec"; + dev_name = "vdec.0"; + status = "okay"; + interrupts = <0 3 1 + 0 23 1 + 0 32 1 + 0 43 1 + 0 44 1 + 0 45 1 + 0 72 1>; + interrupt-names = "vsync", + "demux", + "parser", + "mailbox_0", + "mailbox_1", + "mailbox_2", + "parser_b"; + }; + + vcodec_dec { + compatible = "amlogic, vcodec-dec"; + dev_name = "aml-vcodec-dec"; + status = "okay"; + }; + + amvenc_avc{ + compatible = "amlogic, amvenc_avc"; + dev_name = "amvenc_avc"; + status = "okay"; + interrupts = <0 45 1>; + interrupt-names = "mailbox_2"; + }; + + hevc_enc{ + compatible = "cnm, HevcEnc"; + //memory-region = <&hevc_enc_reserved>; + dev_name = "HevcEnc"; + status = "okay"; + interrupts = <0 187 1>; + interrupt-names = "wave420l_irq"; + #address-cells=<1>; + #size-cells=<1>; + ranges; + io_reg_base{ + reg = <0xff610000 0x4000>; + }; + }; + + rdma{ + compatible = "amlogic, meson, rdma"; + dev_name = "amlogic-rdma"; + status = "okay"; + interrupts = <0 89 1>; + interrupt-names = "rdma"; + }; + + meson_fb: fb { + compatible = "amlogic, meson-sm1"; + memory-region = <&logo_reserved>; + dev_name = "meson-fb"; + status = "disable"; + interrupts = <0 3 1 + 0 56 1 + 0 89 1>; + interrupt-names = "viu-vsync", "viu2-vsync", "rdma"; + /* uboot logo,fb0/fb1 memory size,if afbcd fb0=0x01851000*/ + display_mode_default = "1080p60hz"; + scale_mode = <1>; + /** 0:VPU free scale 1:OSD free scale 2:OSD super scale */ + display_size_default = <1920 1080 1920 2160 32>; + /*1920*1080*4*3 = 0x17BB000*/ + clocks = <&clkc CLKID_VPU_CLKC_MUX>; + clock-names = "vpu_clkc"; + }; + irblaster: meson-irblaster { + compatible = "amlogic, meson_irblaster"; + reg = <0xff80014c 0x10>, + <0xff800040 0x4>; + pinctrl-names = "default"; + pinctrl-0 = <&irblaster_pins>; + interrupts = <0 198 1>; + status = "okay"; + }; + + sd_emmc_c: emmc@ffe07000 { + status = "disabled"; + compatible = "amlogic, meson-mmc-sm1"; + reg = <0xffe07000 0x800>; + interrupts = <0 191 1>; + pinctrl-names = "emmc_clk_cmd_pins", "emmc_all_pins"; + pinctrl-0 = <&emmc_clk_cmd_pins>; + pinctrl-1 = <&emmc_conf_pull_up &emmc_conf_pull_done>; + clocks = <&clkc CLKID_SD_EMMC_C>, + <&clkc CLKID_SD_EMMC_C_P0_COMP>, + <&clkc CLKID_FCLK_DIV2>, + <&clkc CLKID_FCLK_DIV5>, + <&xtal>; + clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + + bus-width = <8>; + cap-sd-highspeed; + cap-mmc-highspeed; + /* mmc-ddr-1_8v; */ + /* mmc-hs200-1_8v; */ + + max-frequency = <200000000>; + non-removable; + disable-wp; + emmc { + pinname = "emmc"; + ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ + /*caps defined in dts*/ + tx_delay = <0>; + co_phase = <3>; + max_req_size = <0x20000>; /**128KB*/ + gpio_dat3 = <&gpio BOOT_3 GPIO_ACTIVE_HIGH>; + hw_reset = <&gpio BOOT_12 GPIO_ACTIVE_HIGH>; + card_type = <1>; + /* 1:mmc card(include eMMC), + * 2:sd card(include tSD) + */ + }; + }; + + sd_emmc_b:sd@ffe05000 { + status = "disabled"; + compatible = "amlogic, meson-mmc-sm1"; + reg = <0xffe05000 0x800>; + interrupts = <0 190 1>; + + pinctrl-names = "sd_all_pins", + "sd_clk_cmd_pins", + "sd_1bit_pins", + "sd_clk_cmd_uart_pins", + "sd_1bit_uart_pins", + "sd_to_ao_uart_pins", + "ao_to_sd_uart_pins", + "sd_to_ao_jtag_pins", + "ao_to_sd_jtag_pins"; + + pinctrl-0 = <&sd_all_pins>; + pinctrl-1 = <&sd_clk_cmd_pins>; + pinctrl-2 = <&sd_1bit_pins>; + pinctrl-3 = <&sd_to_ao_uart_clr_pins + &sd_clk_cmd_pins &ao_to_sd_uart_pins>; + pinctrl-4 = <&sd_to_ao_uart_clr_pins + &sd_1bit_pins &ao_to_sd_uart_pins>; + pinctrl-5 = <&sd_all_pins &sd_to_ao_uart_pins>; + pinctrl-6 = <&sd_to_ao_uart_clr_pins + &ao_to_sd_uart_pins>; + pinctrl-7 = <&sd_all_pins &sd_to_ao_uart_pins>; + pinctrl-8 = <&sd_to_ao_uart_clr_pins + &ao_to_sd_uart_pins>; + + clocks = <&clkc CLKID_SD_EMMC_B>, + <&clkc CLKID_SD_EMMC_B_P0_COMP>, + <&clkc CLKID_FCLK_DIV2>, + <&clkc CLKID_FCLK_DIV5>, + <&xtal>; + clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + + bus-width = <4>; + cap-sd-highspeed; + cap-mmc-highspeed; + max-frequency = <100000000>; + disable-wp; + sd { + pinname = "sd"; + ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ + max_req_size = <0x20000>; /**128KB*/ + gpio_dat3 = <&gpio GPIOC_3 GPIO_ACTIVE_HIGH>; + jtag_pin = <&gpio GPIOC_0 GPIO_ACTIVE_HIGH>; + gpio_cd = <&gpio GPIOC_6 GPIO_ACTIVE_HIGH>; + card_type = <5>; + /* 3:sdio device(ie:sdio-wifi), + * 4:SD combo (IO+mem) card + */ + }; + }; + + + sd_emmc_a:sdio@ffe03000 { + status = "disabled"; + compatible = "amlogic, meson-mmc-sm1"; + reg = <0xffe03000 0x800>; + interrupts = <0 189 4>; + + pinctrl-names = "sdio_all_pins", + "sdio_clk_cmd_pins"; + pinctrl-0 = <&sdio_all_pins>; + pinctrl-1 = <&sdio_clk_cmd_pins>; + + clocks = <&clkc CLKID_SD_EMMC_A>, + <&clkc CLKID_SD_EMMC_A_P0_COMP>, + <&clkc CLKID_FCLK_DIV2>, + <&clkc CLKID_FCLK_DIV5>, + <&xtal>; + clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + + bus-width = <4>; + cap-sd-highspeed; + cap-mmc-highspeed; + max-frequency = <100000000>; + disable-wp; + sdio { + pinname = "sdio"; + ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ + max_req_size = <0x20000>; /**128KB*/ + card_type = <3>; + /* 3:sdio device(ie:sdio-wifi), + * 4:SD combo (IO+mem) card + */ + }; + }; + + nand: nfc@0 { + compatible = "amlogic, aml_mtd_nand"; + dev_name = "mtdnand"; + status = "disabled"; + reg = <0xFFE07800 0x200>; + interrupts = <0 34 1>; + + pinctrl-names = "nand_rb_mod","nand_norb_mod", "nand_cs_only"; + pinctrl-0 = <&all_nand_pins>; + pinctrl-1 = <&all_nand_pins>; + pinctrl-2 = <&nand_cs_pins>; + clocks = <&clkc CLKID_SD_EMMC_C>, + <&clkc CLKID_SD_EMMC_C_P0_COMP>; + clock-names = "core", "clkin"; + + device_id = <0>; + /*fip/tpl configurations, must be same + * with uboot if bl_mode was set as 1 + * bl_mode: 0 compact mode; 1 descrete mode + * if bl_mode was set as 1, fip configuration will work + */ + bl_mode = <1>; + /*copy count of fip*/ + fip_copies = <4>; + /*size of each fip copy */ + fip_size = <0x200000>; + nand_clk_ctrl = <0xFFE07000>; + /*partions defined in dts */ + }; + + /* Sound iomap */ + aml_snd_iomap { + compatible = "amlogic, snd-iomap"; + status = "okay"; + #address-cells=<1>; + #size-cells=<1>; + ranges; + pdm_bus { + reg = <0xFF661000 0x400>; + }; + audiobus_base { + reg = <0xFF660000 0x1000>; + }; + audiolocker_base { + reg = <0xFF661400 0x400>; + }; + eqdrc_base { + reg = <0xFF662000 0x1000>; + }; + reset_base { + reg = <0xFFD01000 0x1000>; + }; + vad_base { + reg = <0xFF661800 0x400>; + }; + earcrx_cdmc_base { + reg = <0xFF663800 0x30>; + }; + earcrx_dmac_base { + reg = <0xFF663C00 0x20>; + }; + earcrx_top_base { + reg = <0xFF663E00 0x10>; + }; + }; + + vddcpu0: pwmao_d-regulator { + compatible = "pwm-regulator"; + pwms = <&pwm_AO_cd MESON_PWM_1 1500 0>; + regulator-name = "vddcpu0"; + regulator-min-microvolt = <690000>; + regulator-max-microvolt = <1050000>; + regulator-always-on; + max-duty-cycle = <1500>; + /* Voltage Duty-Cycle */ + voltage-table = <1050000 0>, + <1040000 3>, + <1030000 6>, + <1020000 8>, + <1010000 11>, + <1000000 14>, + <990000 17>, + <980000 20>, + <970000 23>, + <960000 26>, + <950000 29>, + <940000 31>, + <930000 34>, + <920000 37>, + <910000 40>, + <900000 43>, + <890000 45>, + <880000 48>, + <870000 51>, + <860000 54>, + <850000 56>, + <840000 59>, + <830000 62>, + <820000 65>, + <810000 68>, + <800000 70>, + <790000 73>, + <780000 76>, + <770000 79>, + <760000 81>, + <750000 84>, + <740000 87>, + <730000 89>, + <720000 92>, + <710000 95>, + <700000 98>, + <690000 100>; + status = "okay"; + }; + + ddr_bandwidth { + compatible = "amlogic, ddr-bandwidth"; + status = "okay"; + reg = <0xff638000 0x100 + 0xff638c00 0x100>; + interrupts = <0 52 1>; + interrupt-names = "ddr_bandwidth"; + }; + dmc_monitor { + compatible = "amlogic, dmc_monitor"; + status = "okay"; + reg_base = <0xff639000>; + interrupts = <0 51 1>; + }; + + defendkey: defendkey { + compatible = "amlogic, defendkey"; + reg = <0xff630218 0x4>; /*RNG_USR_DATA*/ + mem_size = <0 0x100000>; + status = "okay"; + }; + + aml_dma { + compatible = "amlogic,aml_txlx_dma"; + reg = <0xff63e000 0x48>; + interrupts = <0 180 1>; + + aml_aes { + compatible = "amlogic,aes_g12a_dma"; + dev_name = "aml_aes_dma"; + status = "okay"; + }; + + aml_sha { + compatible = "amlogic,sha_dma"; + dev_name = "aml_sha_dma"; + status = "okay"; + }; + }; + + rng { + compatible = "amlogic,meson-rng"; + status = "okay"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0xff630218 0x4>; + quality = /bits/ 16 <1000>; + }; + + efuse: efuse{ + compatible = "amlogic, efuse"; + read_cmd = <0x82000030>; + write_cmd = <0x82000031>; + get_max_cmd = <0x82000033>; + key = <&efusekey>; + clocks = <&clkc CLKID_EFUSE>; + clock-names = "efuse_clk"; + status = "disabled"; + }; + + cpu_ver_name { + compatible = "amlogic, cpu-major-id-sm1"; + }; +};/* end of / */ + +&pinctrl_aobus { + sd_to_ao_uart_clr_pins:sd_to_ao_uart_clr_pins { + mux { + groups = "GPIOAO_0", + "GPIOAO_1"; + function = "gpio_aobus"; + }; + }; + + sd_to_ao_uart_pins:sd_to_ao_uart_pins { + mux { + groups = "uart_ao_tx_a", + "uart_ao_rx_a"; + function = "uart_ao_a"; + bias-pull-up; + input-enable; + }; + }; + + ao_uart_pins:ao_uart { + mux { + groups = "uart_ao_tx_a", + "uart_ao_rx_a"; + function = "uart_ao_a"; + }; + }; + + ao_b_uart_pins:ao_b_uart { + mux { + groups = "uart_ao_tx_b_2", + "uart_ao_rx_b_3"; + function = "uart_ao_b"; + }; + }; + + ao_i2c_master_pins1:ao_i2c_pins1 { + mux { + groups = "i2c_ao_sck", + "i2c_ao_sda"; + function = "i2c_ao"; + drive-strength = <2>; + }; + }; + + ao_i2c_master_pins2:ao_i2c_pins2 { + mux { + groups = "i2c_ao_sck_e", + "i2c_ao_sda_e"; + function = "i2c_ao"; + drive-strength = <2>; + }; + }; + + ao_i2c_slave_pins:ao_i2c_slave_pins { + mux { + groups = "i2c_ao_slave_sck", + "i2c_ao_slave_sda"; + function = "i2c_ao_slave"; + }; + }; + + pwm_ao_a_pins: pwm_ao_a { + mux { + groups = "pwm_ao_a"; + function = "pwm_ao_a"; + }; + }; + + pwm_ao_a_hiz_pins: pwm_ao_a_hiz { + mux { + groups = "pwm_ao_a_hiz"; + function = "pwm_ao_a"; + }; + }; + + pwm_ao_b_pins: pwm_ao_b { + mux { + groups = "pwm_ao_b"; + function = "pwm_ao_b"; + }; + }; + + pwm_ao_c_pins1: pwm_ao_c_pins1 { + mux { + groups = "pwm_ao_c_4"; + function = "pwm_ao_c"; + }; + }; + + pwm_ao_c_pins2: pwm_ao_c_pins2 { + mux { + groups = "pwm_ao_c_6"; + function = "pwm_ao_c"; + }; + }; + + pwm_ao_c_hiz_pins: pwm_ao_c_hiz { + mux { + groups = "pwm_ao_c_hiz_4"; + function = "pwm_ao_c"; + }; + }; + + pwm_ao_d_pins1: pwm_ao_d_pins1 { + mux { + groups = "pwm_ao_d_5"; + function = "pwm_ao_d"; + }; + }; + + pwm_ao_d_pins2: pwm_ao_d_pins2 { + mux { + groups = "pwm_ao_d_10"; + function = "pwm_ao_d"; + }; + }; + + pwm_ao_d_pins3: pwm_ao_d_pins3 { + mux { + groups = "pwm_ao_d_e"; + function = "pwm_ao_d"; + }; + }; + + aocec_a: ao_ceca { + mux { + groups = "cec_ao_a"; + function = "cec_ao"; + }; + }; + + aocec_b: ao_cecb { + mux { + groups = "cec_ao_b"; + function = "cec_ao"; + }; + }; + + jtag_apao_pins:jtag_apao_pin { + mux { + groups = "jtag_a_tdi", + "jtag_a_tdo", + "jtag_a_clk", + "jtag_a_tms"; + function = "jtag_a"; + }; + }; +}; + +&pinctrl_periphs { + /* sdemmc portC */ + emmc_clk_cmd_pins:emmc_clk_cmd_pins { + mux { + groups = "emmc_clk", + "emmc_cmd"; + function = "emmc"; + input-enable; + bias-pull-up; + }; + }; + + emmc_conf_pull_up:emmc_conf_pull_up { + mux { + groups = "emmc_nand_d7", + "emmc_nand_d6", + "emmc_nand_d5", + "emmc_nand_d4", + "emmc_nand_d3", + "emmc_nand_d2", + "emmc_nand_d1", + "emmc_nand_d0", + "emmc_clk", + "emmc_cmd"; + function = "emmc"; + input-enable; + bias-pull-up; + }; + }; + + emmc_conf_pull_done:emmc_conf_pull_done { + mux { + groups = "emmc_nand_ds"; + function = "emmc"; + input-enable; + bias-pull-down; + }; + }; + + /* sdemmc portB */ + sd_clk_cmd_pins:sd_clk_cmd_pins { + mux { + groups = "sdcard_cmd_c"; + function = "sdcard"; + input-enable; + bias-pull-up; + drive-strength = <3>; + }; + mux1 { + groups = "sdcard_clk_c"; + function = "sdcard"; + bias-pull-up; + output-high; + drive-strength = <3>; + }; + }; + + sd_all_pins:sd_all_pins { + mux { + groups = "sdcard_d0_c", + "sdcard_d1_c", + "sdcard_d2_c", + "sdcard_d3_c", + "sdcard_cmd_c"; + function = "sdcard"; + input-enable; + bias-pull-up; + drive-strength = <3>; + }; + mux1 { + groups = "sdcard_clk_c"; + function = "sdcard"; + bias-pull-up; + output-high; + drive-strength = <3>; + }; + }; + + sd_1bit_pins:sd_1bit_pins { + mux { + groups = "sdcard_d0_c", + "sdcard_cmd_c"; + function = "sdcard"; + input-enable; + bias-pull-up; + drive-strength = <3>; + }; + mux1 { + groups = "sdcard_clk_c"; + function = "sdcard"; + bias-pull-up; + output-high; + drive-strength = <3>; + }; + }; + + sd_clr_all_pins:sd_clr_all_pins { + mux { + groups = "GPIOC_0", + "GPIOC_1", + "GPIOC_2", + "GPIOC_3", + "GPIOC_5"; + function = "gpio_periphs"; + output-high; + }; + mux1 { + groups = "GPIOC_4"; + function = "gpio_periphs"; + output-low; + }; + }; + + sd_clr_noall_pins:sd_clr_noall_pins { + mux { + groups = "GPIOC_0", + "GPIOC_1", + "GPIOC_4", + "GPIOC_5"; + function = "gpio_periphs"; + output-high; + }; + }; + + ao_to_sd_uart_pins:ao_to_sd_uart_pins { + mux { + groups = "uart_ao_tx_a_c3", + "uart_ao_rx_a_c2"; + function = "uart_ao_a_ee"; + bias-pull-up; + input-enable; + }; + }; + + /* sdemmc portA */ + sdio_clk_cmd_pins:sdio_clk_cmd_pins { + mux { + groups = "sdio_clk", + "sdio_cmd"; + function = "sdio"; + input-enable; + bias-pull-up; + drive-strength = <3>; + }; + }; + + sdio_all_pins:sdio_all_pins { + mux { + groups = "sdio_d0", + "sdio_d1", + "sdio_d2", + "sdio_d3", + "sdio_clk", + "sdio_cmd"; + function = "sdio"; + input-enable; + bias-pull-up; + drive-strength = <3>; + }; + }; + + sdio_x_clk_cmd_pins:sdio_x_clk_cmd_pins { + mux { + groups = "GPIOX_5"; + function = "gpio_periphs"; + input-enable; + bias-pull-up; + drive-strength = <3>; + }; + mux1 { + groups = "GPIOX_4"; + function = "gpio_periphs"; + bias-pull-up; + output-high; + drive-strength = <3>; + }; + }; + + sdio_x_all_pins:sdio_x_all_pins { + mux { + groups = "GPIOX_0", + "GPIOX_1", + "GPIOX_2", + "GPIOX_3", + "GPIOX_5"; + function = "gpio_periphs"; + input-enable; + bias-pull-up; + drive-strength = <3>; + }; + mux1 { + groups = "GPIOX_4"; + function = "gpio_periphs"; + bias-pull-up; + output-high; + drive-strength = <3>; + }; + }; + + sdio_x_en_pins:sdio_x_en_pins { + mux { + groups = "sdio_dummy"; + function = "sdio"; + bias-pull-up; + output-high; + }; + }; + + sdio_x_clr_pins:sdio_x_clr_pins { + mux { + groups = "GPIOV_0"; + function = "gpio_periphs"; + bias-pull-up; + output-low; + }; + mux1 { + groups = "GPIOX_4"; + function = "gpio_periphs"; + output-low; + }; + }; + + all_nand_pins: all_nand_pins { + mux { + groups = "emmc_nand_d0", + "emmc_nand_d1", + "emmc_nand_d2", + "emmc_nand_d3", + "emmc_nand_d4", + "emmc_nand_d5", + "emmc_nand_d6", + "emmc_nand_d7", + "nand_ce0", + "nand_ale", + "nand_cle", + "nand_wen_clk", + "nand_ren_wr", + "nand_rb0"; + function = "nand"; + input-enable; + }; + }; + + nand_cs_pins: nand_cs { + mux { + groups = "nand_ce0"; + function = "nand"; + }; + }; + + i2c0_master_pins1:i2c0_pins1 { + mux { + groups = "i2c0_sda_c", + "i2c0_sck_c"; + function = "i2c0"; + drive-strength = <2>; + }; + }; + + i2c0_master_pins2:i2c0_pins2 { + mux { + groups = "i2c0_sda_z0", + "i2c0_sck_z1"; + function = "i2c0"; + drive-strength = <2>; + }; + }; + + i2c0_master_pins3:i2c0_pins3 { + mux { + groups = "i2c0_sda_z7", + "i2c0_sck_z8"; + function = "i2c0"; + drive-strength = <2>; + }; + }; + + i2c1_master_pins1:i2c1_pins1 { + mux { + groups = "i2c1_sda_x", + "i2c1_sck_x"; + function = "i2c1"; + drive-strength = <2>; + }; + }; + + i2c1_master_pins2:i2c1_pins2 { + mux { + groups = "i2c1_sda_h2", + "i2c1_sck_h3"; + function = "i2c1"; + drive-strength = <2>; + }; + }; + + i2c1_master_pins3:i2c1_pins3 { + mux { + groups = "i2c1_sda_h6", + "i2c1_sck_h7"; + function = "i2c1"; + drive-strength = <2>; + }; + }; + + i2c2_master_pins1:i2c2_pins1 { + mux { + groups = "i2c2_sda_x", + "i2c2_sck_x"; + function = "i2c2"; + drive-strength = <2>; + }; + }; + + i2c2_master_pins2:i2c2_pins2 { + mux { + groups = "i2c2_sda_z", + "i2c2_sck_z"; + function = "i2c2"; + drive-strength = <2>; + }; + }; + + i2c3_master_pins1:i2c3_pins1 { + mux { + groups = "i2c3_sda_h", + "i2c3_sck_h"; + function = "i2c3"; + drive-strength = <2>; + }; + }; + + i2c3_master_pins2:i2c3_pins2 { + mux { + groups = "i2c3_sda_a", + "i2c3_sck_a"; + function = "i2c3"; + drive-strength = <2>; + }; + }; + + /*dvb_p_ts1_pins: dvb_p_ts1_pins { + * tsin_b { + * groups = "tsin_b_sop_z", + * "tsin_b_valid_z", + * "tsin_b_clk_z", + * "tsin_b_din0_z", + * "tsin_b_din1", + * "tsin_b_din2", + * "tsin_b_din3", + * "tsin_b_din4", + * "tsin_b_din5", + * "tsin_b_din6", + * "tsin_b_din7"; + * function = "tsin_b"; + * }; + *}; + */ + + pwm_a_pins: pwm_a { + mux { + groups = "pwm_a"; + function = "pwm_a"; + }; + }; + + pwm_b_pins1: pwm_b_pins1 { + mux { + groups = "pwm_b_x7"; + function = "pwm_b"; + }; + }; + + pwm_b_pins2: pwm_b_pins2 { + mux { + groups = "pwm_b_x19"; + function = "pwm_b"; + }; + }; + + pwm_c_pins1: pwm_c_pins1 { + mux { + groups = "pwm_c_c4"; + function = "pwm_c"; + }; + }; + + pwm_c_pins2: pwm_c_pins2 { + mux { + groups = "pwm_c_x5"; + function = "pwm_c"; + }; + }; + + pwm_c_pins3: pwm_c_pins3 { + mux { + groups = "pwm_c_x8"; + function = "pwm_c"; + }; + }; + + pwm_d_pins1: pwm_d_pins1 { + mux { + groups = "pwm_d_x3"; + function = "pwm_d"; + }; + }; + + pwm_d_pins2: pwm_d_pins2 { + mux { + groups = "pwm_d_x6"; + function = "pwm_d"; + }; + }; + + pwm_e_pins: pwm_e { + mux { + groups = "pwm_e"; + function = "pwm_e"; + }; + }; + + pwm_f_pins1: pwm_f_pins1 { + mux { + groups = "pwm_f_x"; + function = "pwm_f"; + }; + }; + + pwm_f_pins2: pwm_f_pins2 { + mux { + groups = "pwm_f_h"; + function = "pwm_f"; + }; + }; + + spicc0_pins_x: spicc0_pins_x { + mux { + groups = "spi0_mosi_x", + "spi0_miso_x", + //"spi0_ss0_x", + "spi0_clk_x"; + function = "spi0"; + drive-strength = <1>; + }; + }; + + spicc0_pins_c: spicc0_pins_c { + mux { + groups = "spi0_mosi_c", + "spi0_miso_c", + "spi0_ss0_c", + "spi0_clk_c"; + function = "spi0"; + drive-strength = <1>; + }; + }; + + spicc1_pins: spicc1_pins { + mux { + groups = "spi1_mosi", + "spi1_miso", + //"spi1_ss0", + "spi1_clk"; + function = "spi1"; + drive-strength = <1>; + }; + }; + + a_uart_pins:a_uart { + mux { + groups = "uart_tx_a", + "uart_rx_a", + "uart_cts_a", + "uart_rts_a"; + function = "uart_a"; + }; + }; + + b_uart_pins:b_uart { + mux { + groups = "uart_tx_b", + "uart_rx_b"; + function = "uart_b"; + }; + }; + + c_uart_pins:c_uart { + mux { + groups = "uart_tx_c", + "uart_rx_c"; + function = "uart_c"; + }; + }; + + hdmitx_hpd: hdmitx_hpd { + mux { + groups = "hdmitx_hpd_in"; + function = "hdmitx"; + bias-disable; + }; + }; + + hdmitx_hpd_gpio: hdmitx_hpd_gpio { + mux { + groups = "GPIOH_1"; + function = "gpio_periphs"; + bias-disable; + }; + }; + + hdmitx_ddc: hdmitx_ddc { + mux { + groups = "hdmitx_sda", + "hdmitx_sck"; + function = "hdmitx"; + bias-disable; + drive-strength = <3>; + }; + }; + + eecec_a: ee_ceca { + mux { + groups = "cec_ao_a_ee"; + function = "cec_ao_ee"; + }; + }; + + eecec_b: ee_cecb { + mux { + groups = "cec_ao_b_ee"; + function = "cec_ao_ee"; + }; + }; + + internal_eth_pins: internal_eth_pins { + mux { + groups = "eth_link_led", + "eth_act_led"; + function = "eth"; + }; + }; + + internal_gpio_pins: internal_gpio_pins { + mux { + groups = "GPIOZ_14", + "GPIOZ_15"; + function = "gpio_periphs"; + bias-disable; + input-enable; + }; + }; + + external_eth_pins: external_eth_pins { + mux { + groups = "eth_mdio", + "eth_mdc", + "eth_rgmii_rx_clk", + "eth_rx_dv", + "eth_rxd0", + "eth_rxd1", + "eth_rxd2_rgmii", + "eth_rxd3_rgmii", + "eth_rgmii_tx_clk", + "eth_txen", + "eth_txd0", + "eth_txd1", + "eth_txd2_rgmii", + "eth_txd3_rgmii"; + function = "eth"; + drive-strength = <3>; + }; + }; + + jtag_apee_pins:jtag_apee_pin { + mux { + groups = "jtag_b_tdi", + "jtag_b_tdo", + "jtag_b_clk", + "jtag_b_tms"; + function = "jtag_b"; + }; + }; +}; + +&pinctrl_aobus { + remote_pins:remote_pin { + mux { + groups = "remote_input_ao"; + function = "remote_input_ao"; + }; + }; + + irblaster_pins:irblaster_pin { + mux { + groups = "remote_out_ao"; + function = "remote_out_ao"; + }; + }; +}; /* end of pinctrl_aobus */ diff --git a/arch/arm/boot/dts/amlogic/mesonsm1_skt-panel.dtsi b/arch/arm/boot/dts/amlogic/mesonsm1_skt-panel.dtsi new file mode 100644 index 000000000000..5975ceac5b97 --- /dev/null +++ b/arch/arm/boot/dts/amlogic/mesonsm1_skt-panel.dtsi @@ -0,0 +1,503 @@ +/* + * arch/arm64/boot/dts/amlogic/mesong12a_skt-panel.dtsi + * + * Copyright (C) 2016 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +/ { + lcd{ + compatible = "amlogic, sm1"; + dev_name = "lcd"; + mode = "tablet"; + status = "okay"; + key_valid = <0>; + clocks = <&clkc CLKID_MIPI_DSI_HOST + &clkc CLKID_MIPI_DSI_PHY + &clkc CLKID_DSI_MEAS_COMP + &clkc CLKID_VCLK2_ENCL + &clkc CLKID_VCLK2_VENCL + &clkc CLKID_GP0_PLL>; + clock-names = "dsi_host_gate", + "dsi_phy_gate", + "dsi_meas", + "encl_top_gate", + "encl_int_gate", + "gp0_pll"; + reg = <0xffd07000 0x400 /* dsi_host */ + 0xff644000 0x200>; /* dsi_phy */ + interrupts = <0 3 1 + 0 56 1>; + interrupt-names = "vsync","vsync2"; + pinctrl_version = <2>; /* for uboot */ + + /* power type: + * (0=cpu_gpio, 1=pmu_gpio, 2=signal,3=extern, 0xff=ending) + * power index: + * (point gpios_index, or extern_index,0xff=invalid) + * power value:(0=output low, 1=output high, 2=input) + * power delay:(unit in ms) + */ + lcd_cpu-gpios = <&gpio GPIOZ_9 GPIO_ACTIVE_HIGH + &gpio GPIOZ_8 GPIO_ACTIVE_HIGH>; + lcd_cpu_gpio_names = "GPIOZ_9","GPIOZ_8"; + + lcd_0{ + model_name = "B080XAN01"; + interface = "mipi"; + basic_setting = <768 1024 /*h_active, v_active*/ + 948 1140 /*h_period, v_period*/ + 8 /*lcd_bits*/ + 119 159>; /*screen_widht, screen_height*/ + lcd_timing = <64 56 0 /*hs_width, hs_bp, hs_pol*/ + 50 30 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = <0 /*fr_adj_type(0=clk, 1=htotal, 2=vtotal)*/ + 0 /*clk_ss_level */ + 1 /*clk_auto_generate*/ + 64843200>; /*pixel_clk(unit in Hz)*/ + mipi_attr = <4 /*lane_num*/ + 550 /*bit_rate_max(MHz)*/ + 0 /*factor(*100, default 0 for auto)*/ + 1 /*operation_mode_init(0=video, 1=command)*/ + 0 /*operation_mode_display(0=video, 1=command)*/ + 2 /* + *video_mode_type + *(0=sync_pulse,1=sync_event,2=burst) + */ + 1 /*clk_always_hs(0=disable,1=enable)*/ + 0>; /*phy_switch(0=auto,1=standard,2=slow)*/ + + /* dsi_init: data_type, num, data... */ + dsi_init_on = <0x05 1 0x11 + 0xff 20 /*delay(ms)*/ + 0x05 1 0x29 + 0xff 20 /*delay(ms)*/ + 0xff 0xff>; /*ending*/ + dsi_init_off = <0x05 1 0x28 + 0xff 10 /*delay(ms)*/ + 0x05 1 0x10 + 0xff 10 /*delay(ms)*/ + 0xff 0xff>; /*ending*/ + extern_init = <0xff>; /*0xff for invalid*/ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 1 0 100 + 0 0 0 10 + 0 0 1 20 + 2 0 0 0 + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 50 + 0 0 0 10 + 0 1 1 100 + 0xff 0 0 0>; /*ending*/ + backlight_index = <0>; + }; + + lcd_1{ + model_name = "P070ACB_FT"; + interface = "mipi"; + basic_setting = <600 1024 /*h_active, v_active*/ + 770 1070 /*h_period, v_period*/ + 8 /*lcd_bits*/ + 3 5>; /*screen_widht, screen_height*/ + lcd_timing = <10 80 0 /*hs_width,hs_bp,hs_pol*/ + 6 20 0>; /*vs_width,vs_bp,vs_pol*/ + clk_attr = <0 /*fr_adj_type(0=clock,1=htotal,2=vtotal)*/ + 0 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 49434000>; /*pixel_clk(unit in Hz)*/ + mipi_attr = <4 /*lane_num*/ + 400 /*bit_rate_max(MHz)*/ + 0 /*factor(*100, default 0 for auto)*/ + 1 /*operation_mode_init(0=video, 1=command)*/ + 0 /*operation_mode_display(0=video, 1=command)*/ + 2 /* + *video_mode_type + *(0=sync_pulse,1=sync_event,2=burst) + */ + 0 /*clk_always_hs(0=disable,1=enable)*/ + 0>; /*phy_switch(0=auto,1=standard,2=slow)*/ + /* dsi_init: data_type, num, data... */ + dsi_init_on = < + 0xff 10 + 0xf0 3 0 1 30 /* reset high, delay 30ms */ + 0xf0 3 0 0 10 /* reset low, delay 10ms */ + 0xf0 3 0 1 30 /* reset high, delay 30ms */ + 0xfc 2 0x04 3 /* check_reg, check_cnt */ + 0xff 0xff>; /* ending flag */ + dsi_init_off = <0xff 0xff>; /* ending flag */ + /* extern_init: 0xff for invalid */ + extern_init = <5>; + /* power step: type,index,value,delay(ms) */ + power_on_step = < + 0 1 0 200 /* panel power on */ + 2 0 0 0 + 0xff 0 0 0>; + power_off_step = < + 2 0 0 0 + 0 0 0 20 /* reset low */ + 0 1 1 100 /* panel power off */ + 0xff 0 0 0>; + backlight_index = <0>; + }; + }; + + lcd_extern{ + compatible = "amlogic, lcd_extern"; + dev_name = "lcd_extern"; + status = "okay"; + i2c_bus = "i2c_bus_0"; + key_valid = <0>; + + extern_0{ + index = <0>; + extern_name = "mipi_default";/*default*/ + status = "okay"; + type = <2>; /* 0=i2c, 1=spi, 2=mipi */ + cmd_size = <0xff>; + init_on = < + 0xff 10 + 0x05 1 0x11 + 0xff 120 /* delay 120ms */ + 0x05 1 0x29 + 0xff 0xff>; /*ending*/ + init_off = < + 0x05 1 0x28 /* display off */ + 0xff 10 /* delay 10ms */ + 0x05 1 0x10 /* sleep in */ + 0xff 150 /* delay 150ms */ + 0xff 0xff>; /*ending*/ + }; + + extern_1{ + index = <1>; + extern_name = "mipi_default";/*P070ACB_FT*/ + status = "okay"; + type = <2>; /* 0=i2c, 1=spi, 2=mipi */ + cmd_size = <0xff>; + init_on = < + 0x23 2 0xE0 0x00 /* Page 0 */ + 0x23 2 0xE1 0x93 /* PASSWORD */ + 0x23 2 0xE2 0x65 + 0x23 2 0xE3 0xF8 + 0x23 2 0x80 0x03 + 0x23 2 0xE0 0x01 /* Page 01 */ + 0x23 2 0x0C 0x74 /* Set PWRIC */ + 0x23 2 0x17 0x00 /* Set Gamma Power */ + 0x23 2 0x18 0xEF /* VGMP=5.1V */ + 0x23 2 0x19 0x00 + 0x23 2 0x1A 0x00 + 0x23 2 0x1B 0xEF /* VGMN=-5.1V */ + 0x23 2 0x1C 0x00 + 0x23 2 0x1F 0x70 /* Set Gate Power */ + 0x23 2 0x20 0x2D + 0x23 2 0x21 0x2D + 0x23 2 0x22 0x7E + 0x23 2 0x26 0xF3 /* VDDD from IOVCC */ + 0x23 2 0x37 0x09 /* SetPanel */ + 0x23 2 0x38 0x04 /* SET RGBCYC */ + 0x23 2 0x39 0x00 + 0x23 2 0x3A 0x01 + 0x23 2 0x3C 0x90 + 0x23 2 0x3D 0xFF + 0x23 2 0x3E 0xFF + 0x23 2 0x3F 0xFF + 0x23 2 0x40 0x02 /* Set TCON */ + 0x23 2 0x41 0x80 + 0x23 2 0x42 0x99 + 0x23 2 0x43 0x14 + 0x23 2 0x44 0x19 + 0x23 2 0x45 0x5A + 0x23 2 0x4B 0x04 + 0x23 2 0x55 0x02 /* power voltage */ + 0x23 2 0x56 0x01 + 0x23 2 0x57 0x69 + 0x23 2 0x58 0x0A + 0x23 2 0x59 0x0A + 0x23 2 0x5A 0x2E /* VGH = 16.2V */ + 0x23 2 0x5B 0x19 /* VGL = -12V */ + 0x23 2 0x5C 0x15 + 0x23 2 0x5D 0x77 /* Gamma */ + 0x23 2 0x5E 0x56 + 0x23 2 0x5F 0x45 + 0x23 2 0x60 0x38 + 0x23 2 0x61 0x35 + 0x23 2 0x62 0x27 + 0x23 2 0x63 0x2D + 0x23 2 0x64 0x18 + 0x23 2 0x65 0x33 + 0x23 2 0x66 0x34 + 0x23 2 0x67 0x35 + 0x23 2 0x68 0x56 + 0x23 2 0x69 0x45 + 0x23 2 0x6A 0x4F + 0x23 2 0x6B 0x42 + 0x23 2 0x6C 0x40 + 0x23 2 0x6D 0x34 + 0x23 2 0x6E 0x25 + 0x23 2 0x6F 0x02 + 0x23 2 0x70 0x77 + 0x23 2 0x71 0x56 + 0x23 2 0x72 0x45 + 0x23 2 0x73 0x38 + 0x23 2 0x74 0x35 + 0x23 2 0x75 0x27 + 0x23 2 0x76 0x2D + 0x23 2 0x77 0x18 + 0x23 2 0x78 0x33 + 0x23 2 0x79 0x34 + 0x23 2 0x7A 0x35 + 0x23 2 0x7B 0x56 + 0x23 2 0x7C 0x45 + 0x23 2 0x7D 0x4F + 0x23 2 0x7E 0x42 + 0x23 2 0x7F 0x40 + 0x23 2 0x80 0x34 + 0x23 2 0x81 0x25 + 0x23 2 0x82 0x02 + 0x23 2 0xE0 0x02 /* Page2 */ + 0x23 2 0x00 0x53 + /* GIP_L Pin mapping RESET_EVEN */ + 0x23 2 0x01 0x55 /* VSSG_EVEN */ + 0x23 2 0x02 0x55 /* VSSA_EVEN */ + 0x23 2 0x03 0x51 /* STV2_EVEN */ + 0x23 2 0x04 0x77 /* VDD2_EVEN */ + 0x23 2 0x05 0x57 /* VDD1_EVEN */ + 0x23 2 0x06 0x1F + 0x23 2 0x07 0x4F /* CK12 */ + 0x23 2 0x08 0x4D /* CK10 */ + 0x23 2 0x09 0x1F + 0x23 2 0x0A 0x4B /* CK8 */ + 0x23 2 0x0B 0x49 /* CK6 */ + 0x23 2 0x0C 0x1F + 0x23 2 0x0D 0x47 /* CK4 */ + 0x23 2 0x0E 0x45 /* CK2 */ + 0x23 2 0x0F 0x41 /* STV1_EVEN */ + 0x23 2 0x10 0x1F + 0x23 2 0x11 0x1F + 0x23 2 0x12 0x1F + 0x23 2 0x13 0x55 /* VGG */ + 0x23 2 0x14 0x1F + 0x23 2 0x15 0x1F + 0x23 2 0x16 0x52 + /* GIP_R Pin mapping RESET_ODD */ + 0x23 2 0x17 0x55 /* VSSG_ODD */ + 0x23 2 0x18 0x55 /* VSSA_ODD */ + 0x23 2 0x19 0x50 /* STV2_ODD */ + 0x23 2 0x1A 0x77 /* VDD2_ODD */ + 0x23 2 0x1B 0x57 /* VDD1_ODD */ + 0x23 2 0x1C 0x1F + 0x23 2 0x1D 0x4E /* CK11 */ + 0x23 2 0x1E 0x4C /* CK9 */ + 0x23 2 0x1F 0x1F + 0x23 2 0x20 0x4A /* CK7 */ + 0x23 2 0x21 0x48 /* CK5 */ + 0x23 2 0x22 0x1F + 0x23 2 0x23 0x46 /* CK3 */ + 0x23 2 0x24 0x44 /* CK1 */ + 0x23 2 0x25 0x40 /* STV1_ODD */ + 0x23 2 0x26 0x1F + 0x23 2 0x27 0x1F + 0x23 2 0x28 0x1F + 0x23 2 0x29 0x1F + 0x23 2 0x2A 0x1F + 0x23 2 0x2B 0x55 /* VGG */ + 0x23 2 0x2C 0x12 /* GIP_L_GS Pin mapping */ + 0x23 2 0x2D 0x15 + 0x23 2 0x2E 0x15 + 0x23 2 0x2F 0x00 + 0x23 2 0x30 0x37 + 0x23 2 0x31 0x17 + 0x23 2 0x32 0x1F + 0x23 2 0x33 0x08 + 0x23 2 0x34 0x0A + 0x23 2 0x35 0x1F + 0x23 2 0x36 0x0C + 0x23 2 0x37 0x0E + 0x23 2 0x38 0x1F + 0x23 2 0x39 0x04 + 0x23 2 0x3A 0x06 + 0x23 2 0x3B 0x10 + 0x23 2 0x3C 0x1F + 0x23 2 0x3D 0x1F + 0x23 2 0x3E 0x1F + 0x23 2 0x3F 0x15 + 0x23 2 0x40 0x1F + 0x23 2 0x41 0x1F + 0x23 2 0x42 0x13 /* GIP_R_GS Pin mapping */ + 0x23 2 0x43 0x15 + 0x23 2 0x44 0x15 + 0x23 2 0x45 0x01 + 0x23 2 0x46 0x37 + 0x23 2 0x47 0x17 + 0x23 2 0x48 0x1F + 0x23 2 0x49 0x09 + 0x23 2 0x4A 0x0B + 0x23 2 0x4B 0x1F + 0x23 2 0x4C 0x0D + 0x23 2 0x4D 0x0F + 0x23 2 0x4E 0x1F + 0x23 2 0x4F 0x05 + 0x23 2 0x50 0x07 + 0x23 2 0x51 0x11 + 0x23 2 0x52 0x1F + 0x23 2 0x53 0x1F + 0x23 2 0x54 0x1F + 0x23 2 0x55 0x1F + 0x23 2 0x56 0x1F + 0x23 2 0x57 0x15 + 0x23 2 0x58 0x40 /* GIP Timing */ + 0x23 2 0x59 0x00 + 0x23 2 0x5A 0x00 + 0x23 2 0x5B 0x10 + 0x23 2 0x5C 0x14 + 0x23 2 0x5D 0x40 + 0x23 2 0x5E 0x01 + 0x23 2 0x5F 0x02 + 0x23 2 0x60 0x40 + 0x23 2 0x61 0x03 + 0x23 2 0x62 0x04 + 0x23 2 0x63 0x7A + 0x23 2 0x64 0x7A + 0x23 2 0x65 0x74 + 0x23 2 0x66 0x16 + 0x23 2 0x67 0xB4 + 0x23 2 0x68 0x16 + 0x23 2 0x69 0x7A + 0x23 2 0x6A 0x7A + 0x23 2 0x6B 0x0C + 0x23 2 0x6C 0x00 + 0x23 2 0x6D 0x04 + 0x23 2 0x6E 0x04 + 0x23 2 0x6F 0x88 + 0x23 2 0x70 0x00 + 0x23 2 0x71 0x00 + 0x23 2 0x72 0x06 + 0x23 2 0x73 0x7B + 0x23 2 0x74 0x00 + 0x23 2 0x75 0xBC + 0x23 2 0x76 0x00 + 0x23 2 0x77 0x04 + 0x23 2 0x78 0x2C + 0x23 2 0x79 0x00 + 0x23 2 0x7A 0x00 + 0x23 2 0x7B 0x00 + 0x23 2 0x7C 0x00 + 0x23 2 0x7D 0x03 + 0x23 2 0x7E 0x7B + 0x23 2 0xE0 0x04 /* Page4 */ + 0x23 2 0x09 0x11 /* Set RGBCYC2 */ + 0x23 2 0x0E 0x48 + 0x23 2 0x2B 0x2B /* ESD Protect */ + 0x23 2 0x2E 0x44 + 0x23 2 0xE0 0x00 /* Page0 */ + 0x23 2 0xE6 0x02 /* Watch dog */ + 0x23 2 0xE7 0x0C + 0x05 1 0x11 /* sleep out */ + 0xff 120 + 0x05 1 0x29 /* display on */ + 0x05 1 0x35 + 0xFF 20 /* delay(ms) */ + 0xFF 0xFF>; /*ending*/ + init_off = < + 0x05 1 0x28 /* display off */ + 0xff 10 /* delay 10ms */ + 0x05 1 0x10 /* sleep in */ + 0xff 150 /* delay 150ms */ + 0xff 0xff>; /*ending*/ + }; + }; + + backlight{ + compatible = "amlogic, backlight-sm1"; + dev_name = "backlight"; + status = "okay"; + key_valid = <0>; + pinctrl-names = "pwm_on","pwm_off"; + pinctrl-0 = <&pwm_f_pins2>; + pinctrl-1 = <&bl_pwm_off_pins>; + pinctrl_version = <2>; /* for uboot */ + bl_pwm_config = <&bl_pwm_conf>; + bl-gpios = <&gpio GPIOH_4 GPIO_ACTIVE_HIGH + &gpio GPIOH_5 GPIO_ACTIVE_HIGH>; + bl_gpio_names = "GPIOH_4","GPIOH_5"; + + /* pwm port: PWM_A, PWM_B, PWM_C, PWM_D, PWM_E, PWM_F, PWM_VS*/ + /* power index:(point gpios_index, 0xff=invalid) + * power value:(0=output low, 1=output high, 2=input) + * power delay:(unit in ms) + */ + + backlight_0{ + index = <0>; + bl_name = "backlight_pwm"; + bl_level_default_uboot_kernel = <100 100>; + bl_level_attr = <255 10 /*max, min*/ + 128 128>; /*mid, mid_mapping*/ + bl_ctrl_method = <1>; /* 1=pwm, 2=pwm_combo, 4=extern */ + bl_power_attr = <0 /*en_gpio_index*/ + 1 0 /*on_value, off_value*/ + 200 200>; /*on_delay(ms), off_delay(ms)*/ + bl_pwm_port = "PWM_F"; + bl_pwm_attr = <0 /*pwm_method*/ + 180 /*pwm_freq(pwm:Hz, pwm_vs:multiple of vs)*/ + 100 25>; /*duty_max(%), duty_min(%)*/ + bl_pwm_power = <1 1 /*pwm_gpio_index, pwm_gpio_off*/ + 10 10>; /*pwm_on_delay(ms), pwm_off_delay(ms)*/ + bl_pwm_en_sequence_reverse = <0>; /* 1 for reverse */ + }; + backlight_1{ + index = <1>; + bl_name = "bl_extern"; + bl_level_default_uboot_kernel = <100 100>; + bl_level_attr = <255 10 /*max, min*/ + 128 128>; /*mid, mid_mapping*/ + bl_ctrl_method = <4>; /*1=pwm, 2=pwm_combo, 4=extern*/ + bl_power_attr = <1 /*en_gpio_index*/ + 1 0 /*on_value, off_value*/ + 200 200>; /*on_delay(ms), off_delay(ms)*/ + bl_extern_index = <0>; + }; + }; + bl_pwm_conf:bl_pwm_conf{ + pwm_channel_0 { + pwm_port_index = <5>; + pwms = <&pwm_ef MESON_PWM_1 30040 0>; + }; + }; + + bl_extern{ + compatible = "amlogic, bl_extern"; + dev_name = "bl_extern"; + status = "disabled"; + i2c_bus = "i2c_bus_3"; + + extern_0{ + index = <0>; + extern_name = "i2c_lp8556"; + type = <0>; /*0=i2c, 1=spi, 2=mipi*/ + i2c_address = <0x2c>; /*7bit i2c address*/ + dim_max_min = <255 10>; + }; + + extern_1{ + index = <1>; + extern_name = "mipi_lt070me05"; + type = <2>; /*0=i2c, 1=spi, 2=mipi*/ + dim_max_min = <255 10>; + }; + }; +};/* end of panel */ + diff --git a/arch/arm/boot/dts/amlogic/mesontl1_pxp-panel.dtsi b/arch/arm/boot/dts/amlogic/mesontl1_pxp-panel.dtsi deleted file mode 100644 index 765211c88d49..000000000000 --- a/arch/arm/boot/dts/amlogic/mesontl1_pxp-panel.dtsi +++ /dev/null @@ -1,92 +0,0 @@ -/* - * arch/arm64/boot/dts/amlogic/mesontl1_pxp-panel.dtsi - * - * Copyright (C) 2016 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - */ - -/ { - lcd { - compatible = "amlogic, lcd-tl1"; - status = "okay"; - mode = "tv"; - fr_auto_policy = <0>; /* 0=disable, 1=60/50hz, 2=60/50/48hz */ - key_valid = <0>; - clocks = <&clkc CLKID_VCLK2_ENCL - &clkc CLKID_VCLK2_VENCL - &clkc CLKID_TCON - &clkc CLKID_FCLK_DIV5 - &clkc CLKID_TCON_PLL_COMP>; - clock-names = "encl_top_gate", - "encl_int_gate", - "tcon_gate", - "fclk_div5", - "clk_tcon"; - reg = <0xff660000 0x8100 - 0xff634400 0x100>; - interrupts = <0 3 1 - 0 78 1 - 0 88 1>; - interrupt-names = "vsync","vbyone","tcon"; - pinctrl_version = <2>; /* for uboot */ - - /* power type:(0=cpu_gpio, 2=signal, 3=extern, 0xff=ending) */ - /* power index:(gpios_index, or extern_index, 0xff=invalid) */ - /* power value:(0=output low, 1=output high, 2=input) */ - /* power delay:(unit in ms) */ - - lvds_0{ - model_name = "1080p-vfreq"; - interface = "lvds"; /*lcd_interface(lvds, vbyone)*/ - basic_setting = < - 1920 1080 /*h_active, v_active*/ - 2200 1125 /*h_period, v_period*/ - 8 /*lcd_bits */ - 16 9>; /*screen_widht, screen_height*/ - range_setting = < - 2060 2650 /*h_period_min,max*/ - 1100 1480 /*v_period_min,max*/ - 120000000 160000000>; /*pclk_min,max*/ - lcd_timing = < - 44 148 0 /*hs_width, hs_bp, hs_pol*/ - 5 30 0>; /*vs_width, vs_bp, vs_pol*/ - clk_attr = < - 2 /*fr_adj_type - *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, - * 4=hdmi_mode) - */ - 0 /*clk_ss_level*/ - 1 /*clk_auto_generate*/ - 0>; /*pixel_clk(unit in Hz)*/ - lvds_attr = < - 1 /*lvds_repack*/ - 1 /*dual_port*/ - 0 /*pn_swap*/ - 0 /*port_swap*/ - 0>; /*lane_reverse*/ - phy_attr=< - 3 0 /*vswing_level, preem_level*/ - 0 0>; /*clk vswing_level, preem_level*/ - - /* power step: type, index, value, delay(ms) */ - power_on_step = < - 2 0 0 0 /*signal enable*/ - 0xff 0 0 0>; /*ending*/ - power_off_step = < - 2 0 0 10 /*signal disable*/ - 0xff 0 0 0>; /*ending*/ - backlight_index = <0xff>; - }; - }; /* end of lcd */ - -}; /* end of / */ diff --git a/arch/arm/boot/dts/amlogic/mesontl1_t309-panel.dtsi b/arch/arm/boot/dts/amlogic/mesontl1_t309-panel.dtsi new file mode 100644 index 000000000000..61ad4836468c --- /dev/null +++ b/arch/arm/boot/dts/amlogic/mesontl1_t309-panel.dtsi @@ -0,0 +1,1036 @@ +/* + * arch/arm/boot/dts/amlogic/mesontl1_t309-panel.dtsi + * + * Copyright (C) 2016 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +/ { + lcd { + compatible = "amlogic, lcd-tl1"; + status = "okay"; + mode = "tv"; + fr_auto_policy = <1>; /* 0=disable, 1=60/50hz, 2=60/50/48hz */ + key_valid = <1>; + clocks = <&clkc CLKID_VCLK2_ENCL + &clkc CLKID_VCLK2_VENCL + &clkc CLKID_TCON + &clkc CLKID_FCLK_DIV5 + &clkc CLKID_TCON_PLL_COMP>; + clock-names = "encl_top_gate", + "encl_int_gate", + "tcon_gate", + "fclk_div5", + "clk_tcon"; + reg = <0xff660000 0x8100 + 0xff634400 0x300>; + interrupts = <0 3 1 + 0 78 1 + 0 88 1>; + interrupt-names = "vsync","vbyone","tcon"; + pinctrl-names = "vbyone","vbyone_off","tcon","tcon_off"; + pinctrl-0 = <&lcd_vbyone_pins>; + pinctrl-1 = <&lcd_vbyone_off_pins>; + pinctrl-2 = <&lcd_tcon_pins>; + pinctrl-3 = <&lcd_tcon_off_pins>; + pinctrl_version = <2>; /* for uboot */ + memory-region = <&lcd_tcon_reserved>; + + /* power type:(0=cpu_gpio, 2=signal, 3=extern, 0xff=ending) */ + /* power index:(gpios_index, or extern_index, 0xff=invalid) */ + /* power value:(0=output low, 1=output high, 2=input) */ + /* power delay:(unit in ms) */ + lcd_cpu-gpios = <&gpio_ao GPIOAO_4 GPIO_ACTIVE_HIGH + &gpio GPIOH_2 GPIO_ACTIVE_HIGH + &gpio GPIOH_3 GPIO_ACTIVE_HIGH + &gpio GPIOH_8 GPIO_ACTIVE_HIGH + &gpio GPIOH_14 GPIO_ACTIVE_HIGH>; + lcd_cpu_gpio_names = "GPIOAO_4","GPIOH_2","GPIOH_3", + "GPIOH_8","GPIOH_14"; + + lvds_0{ + model_name = "1080p-vfreq"; + interface = "lvds"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 1920 1080 /*h_active, v_active*/ + 2200 1125 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 2060 2650 /*h_period_min,max*/ + 1100 1480 /*v_period_min,max*/ + 120000000 160000000>; /*pclk_min,max*/ + lcd_timing = < + 44 148 0 /*hs_width, hs_bp, hs_pol*/ + 5 30 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 15 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + lvds_attr = < + 1 /*lvds_repack*/ + 1 /*dual_port*/ + 0 /*pn_swap*/ + 0 /*port_swap*/ + 0>; /*lane_reverse*/ + phy_attr=<0xf 0>; /*vswing_level, preem_level*/ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 0 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0>; + }; + + lvds_1{ + model_name = "1080p-hfreq_hdmi"; + interface = "lvds"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 1920 1080 /*h_active, v_active*/ + 2200 1125 /*h_period, v_period*/ + 8 /*lcd_bits*/ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 2080 2720 /*h_period min, max*/ + 1100 1380 /*v_period min, max*/ + 133940000 156000000>; /*pclk_min, max*/ + lcd_timing = < + 44 148 0 /*hs_width, hs_bp, hs_pol*/ + 5 30 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 4 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 0 /*clk_ss_level */ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + lvds_attr = < + 1 /*lvds_repack*/ + 1 /*dual_port*/ + 0 /*pn_swap*/ + 0 /*port_swap*/ + 0>; /*lane_reverse*/ + phy_attr=<0xf 0>; /*vswing_level, preem_level*/ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 0 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0>; + }; + lvds_2{ + model_name = "768p-vfreq"; + interface = "lvds"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 1366 768 /*h_active, v_active*/ + 1560 806 /*h_period, v_period*/ + 8 /*lcd_bits*/ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 1460 2000 /*h_period_min, max */ + 784 1015 /*v_period_min, max */ + 50000000 85000000>; /*pclk_min, max*/ + lcd_timing = < + 56 64 0 /*hs_width, hs_bp, hs_pol*/ + 3 28 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 15 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + lvds_attr = < + 1 /*lvds_repack*/ + 0 /*dual_port*/ + 0 /*pn_swap*/ + 0 /*port_swap*/ + 0>; /*lane_reverse*/ + phy_attr=<0xf 0>; /*vswing_level, preem_level*/ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 0 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0>; + }; + vbyone_0{ + model_name = "public_2region"; + interface = "vbyone"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 10 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 4800 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 33 477 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + vbyone_attr = < + 8 /*lane_count*/ + 2 /*region_num*/ + 4 /*byte_mode*/ + 4>; /*color_fmt*/ + vbyone_intr_enable = < + 1 /*vbyone_intr_enable */ + 3>; /*vbyone_vsync_intr_enable*/ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = <0 0 1 50 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = <2 0 0 10 /*signal disable*/ + 0 0 0 200 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <2>; + }; + vbyone_1{ + model_name = "public_1region"; + interface = "vbyone"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 10 /*lcd_bits*/ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 4800 /*h_period_min, max*/ + 2200 2790 /*v_period_min, max*/ + 552000000 632000000>; /*pclk_min,max*/ + lcd_timing = < + 33 477 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + vbyone_attr = < + 8 /*lane_count*/ + 1 /*region_num*/ + 4 /*byte_mode*/ + 4>; /*color_fmt*/ + vbyone_intr_enable = < + 1 /*vbyone_intr_enable*/ + 3>; /*vbyone_vsync_intr_enable*/ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 50 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 200 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <2>; + }; + vbyone_2{ + model_name = "public_2region_hdmi"; + interface = "vbyone"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 10 /*lcd_bits*/ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 4800 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*v_period_min, max*/ + lcd_timing = < + 33 477 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 4 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 0 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + vbyone_attr = < + 8 /*lane_count*/ + 2 /*region_num*/ + 4 /*byte_mode*/ + 4>; /*color_fmt*/ + vbyone_intr_enable = < + 1 /*vbyone_intr_enable*/ + 3>; /*vbyone_vsync_intr_enable*/ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 50 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 200 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <2>; + }; + vbyone_3{ + model_name = "BOE_HV550QU2"; + interface = "vbyone"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 10 /*lcd_bits*/ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 4800 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 560000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 33 477 1 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + vbyone_attr = < + 8 /*lane_count*/ + 2 /*region_num*/ + 4 /*byte_mode*/ + 4>; /*color_fmt*/ + vbyone_intr_enable = < + 1 /*vbyone_intr_enable*/ + 3>; /*vbyone_vsync_intr_enable*/ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 0 3 0 10 /*3d_disable*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 3 2 0 /*3d_disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <2>; + }; + vbyone_4{ + model_name = "BOE_HV550QU2_1region"; + interface = "vbyone"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 10 /*lcd_bits*/ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 4800 /*h_period_min,max*/ + 2200 2760 /*v_period_min,max*/ + 560000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 33 477 1 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + vbyone_attr = < + 8 /*lane_count*/ + 1 /*region_num*/ + 4 /*byte_mode*/ + 4>; /*color_fmt*/ + vbyone_intr_enable = < + 1 /*vbyone_intr_enable*/ + 3>; /*vbyone_vsync_intr_enable*/ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 0 3 0 10 /*3d_disable*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 3 2 0 /*3d_disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <2>; + }; + p2p_0{ + model_name = "p2p_ceds"; + interface = "p2p"; /*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 5000 2250 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 5100 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 16 29 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + p2p_attr = < + 0 /* teyp: 0=ceds, 1=cmpi, 2=isp, 3=epi, + * 10=chpi, 11=cspi, 12=usit + */ + 12 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 3 2 0 200 /* extern init voltage */ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + p2p_1{ + model_name = "p2p_ceds"; + interface = "p2p"; /*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 5000 2250 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 5100 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 16 29 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + p2p_attr = < + 0 /* teyp: 0=ceds, 1=cmpi, 2=isp, 3=epi, + * 10=chpi, 11=cspi, 12=usit + */ + 6 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + p2p_2{ + model_name = "p2p_chpi"; + interface = "p2p"; /*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 5100 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 16 29 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + p2p_attr = < + 10 /* teyp: 0=ceds, 1=cmpi, 2=isp, 3=epi, + * 10=chpi, 11=cspi, 12=usit + */ + 6 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + p2p_3{ + model_name = "p2p_chpi"; + interface = "p2p"; /*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 5100 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 16 29 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + p2p_attr = < + 10 /* teyp: 0=ceds, 1=cmpi, 2=isp, 3=epi, + * 10=chpi, 11=cspi, 12=usit + */ + 12 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + mlvds_0{ + model_name = "mlvds_1080p"; + interface = "minilvds"; /*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 1920 1080 /*h_active, v_active*/ + 2200 1125 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 2080 2720 /*h_period_min, max*/ + 2200 1125 /*v_period_min, max*/ + 133940000 156000000>; /*pclk_min, max*/ + lcd_timing = < + 44 148 0 /*hs_width, hs_bp, hs_pol*/ + 5 30 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + minilvds_attr = < + 6 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0x660 /* clk_phase */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 0>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + mlvds_1{ + model_name = "mlvds_768p"; + interface = "minilvds";/*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 1366 768 /*h_active, v_active*/ + 1560 806 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 1460 2000 /*h_period_min, max*/ + 784 1015 /*v_period_min, max*/ + 50000000 85000000>; /*pclk_min, max*/ + lcd_timing = < + 56 64 0 /*hs_width, hs_bp, hs_pol*/ + 3 28 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + minilvds_attr = < + 6 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0x660 /* clk_phase */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 0>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + }; + + lcd_extern{ + compatible = "amlogic, lcd_extern"; + status = "okay"; + key_valid = <1>; + i2c_bus = "i2c_bus_1"; + + extern_0{ + index = <0>; + extern_name = "ext_default"; + status = "disabled"; + type = <0>; /*0=i2c, 1=spi, 2=mipi*/ + i2c_address = <0x1c>; /*7bit i2c_addr*/ + i2c_address2 = <0xff>; + cmd_size = <0xff>; /*dynamic cmd_size*/ + + /* init on/off: + * fixed cmd_size: (type, value...); + * cmd_size include all data. + * dynamic cmd_size: (type, cmd_size, value...); + * cmd_size include value. + */ + /* type: 0x00=cmd with delay(bit[3:0]=1 for address2), + * 0xc0=cmd(bit[3:0]=1 for address2), + * 0xf0=gpio, + * 0xfd=delay, + * 0xff=ending + */ + /* value: i2c or spi cmd, or gpio index & level */ + /* delay: unit ms */ + init_on = < + 0xc0 7 0x20 0x01 0x02 0x00 0x40 0xFF 0x00 + 0xc0 7 0x80 0x02 0x00 0x40 0x62 0x51 0x73 + 0xc0 7 0x61 0x06 0x00 0x00 0x00 0x00 0x00 + 0xc0 7 0xC1 0x05 0x0F 0x00 0x08 0x70 0x00 + 0xc0 7 0x13 0x01 0x00 0x00 0x00 0x00 0x00 + 0xc0 7 0x3D 0x02 0x01 0x00 0x00 0x00 0x00 + 0xc0 7 0xED 0x0D 0x01 0x00 0x00 0x00 0x00 + 0xc0 7 0x23 0x02 0x00 0x00 0x00 0x00 0x00 + 0xfd 1 10 /* delay 10ms */ + 0xff 0>; /*ending*/ + init_off = <0xff 0>; /*ending*/ + }; + extern_1{ + index = <1>; + extern_name = "i2c_T5800Q"; + status = "disabled"; + type = <0>; /* 0=i2c, 1=spi, 2=mipi */ + i2c_address = <0x1c>; /* 7bit i2c address */ + }; + extern_2{ + index = <2>; + extern_name = "i2c_ANX6862_7911"; + status = "okay"; + type = <0>; /* 0=i2c, 1=spi, 2=mipi */ + i2c_address = <0x20>; /* 7bit i2c address */ + i2c_address2 = <0x74>; /* 7bit i2c address */ + cmd_size = <0xff>; + + init_on = < + 0xc0 2 0x01 0x2b + 0xc0 2 0x02 0x05 + 0xc0 2 0x03 0x00 + 0xc0 2 0x04 0x00 + 0xc0 2 0x05 0x0c + 0xc0 2 0x06 0x04 + 0xc0 2 0x07 0x21 + 0xc0 2 0x08 0x0f + 0xc0 2 0x09 0x04 + 0xc0 2 0x0a 0x00 + 0xc0 2 0x0b 0x04 + 0xc0 2 0xff 0x00 + 0xfd 1 100 /* delay 100ms */ + + 0xc1 2 0x01 0xca + 0xc1 2 0x02 0x3b + 0xc1 2 0x03 0x33 + 0xc1 2 0x04 0x05 + 0xc1 2 0x05 0x2c + 0xc1 2 0x06 0xf2 + 0xc1 2 0x07 0x9c + 0xc1 2 0x08 0x1b + 0xc1 2 0x09 0x82 + 0xc1 2 0x0a 0x3d + 0xc1 2 0x0b 0x20 + 0xc1 2 0x0c 0x11 + 0xc1 2 0x0d 0xc4 + 0xc1 2 0x0e 0x1a + 0xc1 2 0x0f 0x31 + 0xc1 2 0x10 0x4c + 0xc1 2 0x11 0x12 + 0xc1 2 0x12 0x90 + 0xc1 2 0x13 0xf7 + 0xc1 2 0x14 0x0c + 0xc1 2 0x15 0x20 + 0xc1 2 0x16 0x13 + 0xff 0>; /*ending*/ + init_off = <0xff 0>; /*ending*/ + }; + }; + + backlight{ + compatible = "amlogic, backlight-tl1"; + status = "okay"; + key_valid = <1>; + pinctrl-names = "pwm_on","pwm_vs_on", + "pwm_combo_0_1_on", + "pwm_combo_0_vs_1_on", + "pwm_combo_0_1_vs_on", + "pwm_off", + "pwm_combo_off"; + pinctrl-0 = <&pwm_c_pins3>; + pinctrl-1 = <&bl_pwm_vs_on_pins>; + pinctrl-2 = <&pwm_c_pins3 &pwm_d_pins2>; + pinctrl-3 = <&bl_pwm_combo_0_vs_on_pins &pwm_d_pins2>; + pinctrl-4 = <&pwm_c_pins3 &bl_pwm_combo_1_vs_on_pins>; + pinctrl-5 = <&bl_pwm_off_pins>; + pinctrl-6 = <&bl_pwm_combo_off_pins>; + pinctrl_version = <2>; /* for uboot */ + interrupts = <0 3 1>; + interrupt-names = "ldim_vsync"; + bl_pwm_config = <&bl_pwm_conf>; + + /* pwm port: PWM_A, PWM_B, PWM_C, PWM_D, PWM_E, PWM_F, PWM_VS*/ + /* power index:(point gpios_index, 0xff=invalid) */ + /* power value:(0=output low, 1=output high, 2=input) */ + /* power delay:(unit in ms) */ + bl-gpios = <&gpio_ao GPIOAO_11 GPIO_ACTIVE_HIGH + &gpio GPIOZ_5 GPIO_ACTIVE_HIGH + &gpio GPIOZ_6 GPIO_ACTIVE_HIGH>; + bl_gpio_names = "GPIOAO_11","GPIOZ_5","GPIOZ_6"; + + backlight_0{ + index = <0>; + bl_name = "backlight_pwm"; + bl_level_default_uboot_kernel = <100 100>; + bl_level_attr = <255 10 /*max, min*/ + 128 128>; /*mid, mid_mapping*/ + bl_ctrl_method = <1>; /*1=pwm,2=pwm_combo,3=ldim*/ + bl_power_attr = <0 /*en_gpio_index*/ + 1 0 /*on_value, off_value*/ + 200 200>; /*on_delay(ms), off_delay(ms)*/ + bl_pwm_port = "PWM_C"; + bl_pwm_attr = <1 /*pwm_method(0=negative, 1=positvie)*/ + 180 /*pwm_freq(pwm:Hz, pwm_vs:multiple of vs)*/ + 100 25>; /*duty_max(%), duty_min(%)*/ + bl_pwm_power = <1 0 /*pwm_gpio_index, pwm_gpio_off*/ + 10 10>; /*pwm_on_delay(ms), pwm_off_delay(ms)*/ + bl_pwm_en_sequence_reverse = <0>; /* 1 for reverse */ + }; + backlight_1{ + index = <1>; + bl_name = "backlight_pwm_vs"; + bl_level_default_uboot_kernel = <100 100>; + bl_level_attr = <255 10 /*max, min*/ + 128 128>; /*mid, mid_mapping*/ + bl_ctrl_method = <1>; /*1=pwm,2=pwm_combo,3=ldim*/ + bl_power_attr = <0 /*en_gpio_index*/ + 1 0 /*on_value, off_value*/ + 200 200>; /* on_delay(ms), off_delay(ms)*/ + bl_pwm_port = "PWM_VS"; + bl_pwm_attr = <1 /*pwm_method(0=negative, 1=positvie)*/ + 2 /*pwm_freq(pwm:Hz, pwm_vs:multiple of vs)*/ + 100 25>; /*duty_max(%), duty_min(%)*/ + bl_pwm_power = <1 0 /*pwm_gpio_index, pwm_gpio_off*/ + 10 10>; /*pwm_on_delay(ms), pwm_off_delay(ms)*/ + bl_pwm_en_sequence_reverse = <0>; /* 1 for reverse */ + }; + backlight_2{ + index = <2>; + bl_name = "backlight_pwm_combo"; + bl_level_default_uboot_kernel = <31 100>; + bl_level_attr = <255 10 /*max, min*/ + 128 128>; /*mid, mid_mapping*/ + bl_ctrl_method = <2>; /*1=pwm,2=pwm_combo,3=ldim*/ + bl_power_attr = <0 /*en_gpio_index*/ + 1 0 /*on_value, off_value*/ + 410 110>; /*on_delay(ms), off_delay(ms)*/ + bl_pwm_combo_level_mapping = <255 10 /*pwm_0 range*/ + 0 0>; /*pwm_1 range*/ + bl_pwm_combo_port = "PWM_C","PWM_D"; + bl_pwm_combo_attr = <1 /*pwm0 method*/ + 180 /*pwm0 freq(pwm:Hz, pwm_vs:multiple of vs)*/ + 100 25 /*pwm0 duty_max(%), duty_min(%)*/ + 1 /*pwm1 method*/ + 18000 /*pwm1 freq(pwm:Hz, pwm_vs:multi of vs)*/ + 80 80>; /*pwm1 duty_max(%), duty_min(%)*/ + bl_pwm_combo_power = <1 0 /*pwm0 gpio_index, gpio_off*/ + 2 0 /*pwm1 gpio_index, gpio_off*/ + 10 10>; /*pwm_on_delay(ms), pwm_off_delay(ms)*/ + bl_ldim_region_row_col = <2 10>; + }; + backlight_4{ + index = <4>; + bl_name = "ldim_global"; + bl_level_default_uboot_kernel = <100 100>; + bl_level_attr = <255 10 /*max, min*/ + 128 128>; /*mid, mid_mapping*/ + bl_ctrl_method = <3>; /*1=pwm,2=pwm_combo,3=ldim*/ + bl_power_attr = <0xff /*en_gpio_index*/ + 1 0 /*on_value, off_value*/ + 200 200>; /*on_delay(ms), off_delay(ms)*/ + bl_ldim_region_row_col = <1 1>; + bl_ldim_mode = <1>; /*0=left/right side + *1=top/bottom side + *2=direct + */ + ldim_dev_index = <1>; + }; + backlight_5{ + index = <5>; + bl_name = "ldim_iw7027"; + bl_level_default_uboot_kernel = <100 100>; + bl_level_attr = <255 10 /*max, min*/ + 128 128>; /*mid, mid_mapping*/ + bl_ctrl_method = <3>; /*1=pwm,2=pwm_combo,3=ldim*/ + bl_power_attr = <0 /*en_gpio_index*/ + 1 0 /*on_value, off_value*/ + 200 200>; /*on_delay(ms), off_delay(ms)*/ + bl_ldim_region_row_col = <1 10>; + bl_ldim_mode = <1>; /*0=left/right side + *1=top/bottom side + *2=direct + */ + ldim_dev_index = <2>; + }; + }; + + bl_pwm_conf:bl_pwm_conf{ + pwm_channel_0 { + pwm_port_index = <2>; + pwms = <&pwm_cd MESON_PWM_0 30040 0>; + }; + pwm_channel_1 { + pwm_port_index = <3>; + pwms = <&pwm_cd MESON_PWM_1 30040 0>; + }; + }; + + local_dimming_device { + compatible = "amlogic, ldim_dev"; + status = "okay"; + pinctrl-names = "ldim_pwm", + "ldim_pwm_vs", + "ldim_pwm_combo", + "ldim_pwm_vs_combo", + "ldim_pwm_off", + "ldim_pwm_combo_off"; + pinctrl-0 = <&pwm_c_pins3>; + pinctrl-1 = <&bl_pwm_vs_on_pins>; + pinctrl-2 = <&pwm_c_pins3 &pwm_d_pins2>; + pinctrl-3 = <&bl_pwm_vs_on_pins &pwm_d_pins2>; + pinctrl-4 = <&bl_pwm_off_pins>; + pinctrl-5 = <&bl_pwm_combo_off_pins>; + pinctrl_version = <1>; /* for uboot */ + ldim_pwm_config = <&bl_pwm_conf>; + + /* pwm port: PWM_A, PWM_B, PWM_C, PWM_D, PWM_E, PWM_F, PWM_VS*/ + ldim_dev-gpios = <&gpio_ao GPIOAO_11 GPIO_ACTIVE_HIGH + &gpio GPIOZ_5 GPIO_ACTIVE_HIGH + &gpio GPIOZ_6 GPIO_ACTIVE_HIGH>; + ldim_dev_gpio_names = "GPIOAO_11","GPIOZ_5","GPIOZ_6"; + + ldim_dev_0 { + index = <0>; + type = <0>; /*0=normal, 1=spi, 2=i2c*/ + ldim_dev_name = "ob3350"; + ldim_pwm_port = "PWM_C"; + ldim_pwm_attr = <0 /* pol */ + 200 /*freq(pwm:Hz, pwm_vs:multiple of vs)*/ + 50>;/*default duty(%)*/ + en_gpio_on_off = <0 /*ldim_dev-gpios index*/ + 1 0>; /*on_level, off_level*/ + dim_max_min = <100 20>; /*dim_max, dim_min*/ + }; + ldim_dev_1 { + index = <1>; + type = <0>; /*0=normal, 1=spi, 2=i2c*/ + ldim_dev_name = "global"; + ldim_pwm_port = "PWM_C"; + ldim_pwm_attr = <1 /* pol */ + 180 /*freq(pwm:Hz, pwm_vs:multiple of vs)*/ + 50>;/*default duty(%)*/ + analog_pwm_port = "PWM_D"; + analog_pwm_attr = <1 /*pol(0=negative, 1=positvie)*/ + 18000 /*freq(pwm:Hz)*/ + 100 25 /*duty_max(%), duty_min(%)*/ + 80>; /*default duty(%)*/ + en_gpio_on_off = <0 /*ldim_dev-gpios index*/ + 1 0>; /*on_level, off_level*/ + dim_max_min = <100 20>; /*dim_max, dim_min*/ + }; + + ldim_dev_2 { + index = <2>; + type = <1>; /* 0=normal,1=spi,2=i2c */ + ldim_dev_name = "iw7027"; + ldim_pwm_port = "PWM_VS"; + ldim_pwm_attr = <1 /* pol */ + 2 /*freq(pwm:Hz, pwm_vs:multiple of vs)*/ + 50>;/*default duty(%)*/ + spi_bus_num = <0>; + spi_chip_select = <0>; + spi_max_frequency = <1000000>; /* unit: hz */ + spi_mode = <0>; /* mode: 0, 1, 2, 3 */ + spi_cs_delay = <10 /* hold_high_delay */ + 100>; /* clk_cs_delay (unit: us) */ + en_gpio_on_off = <0 /* ldim_dev-gpios index */ + 1 /* on_level */ + 0>; /* off_level */ + lamp_err_gpio = <0xff>; + /* ldim_dev-gpios index, 0xff=invalid */ + spi_write_check = <0>; /* 0=disable, 1=enable */ + + dim_max_min = <0xfff 0x7f>; /* dim_max, dim_min */ + ldim_region_mapping = <0 1 2 3 4 5 6 7 8 9>; + + cmd_size = <0xff>; + /* init: (type, data...) */ + /* type: 0x00=cmd with delay, + * 0xc0=cmd, + * 0xfd=delay, + * 0xff=ending + */ + /* data: spi data, fill 0x0 for no use */ + /* delay: unit ms */ + init_on = < + 0xc0 2 0x23 0x03 + 0xc0 2 0x24 0xff + 0xc0 2 0x25 0x00 + 0xc0 2 0x26 0x00 + 0xc0 2 0x27 0x60 + 0xc0 2 0x29 0x00 + 0xc0 2 0x2a 0x00 + 0xc0 2 0x2b 0x00 + 0xc0 2 0x2c 0x73 + 0xc0 2 0x2d 0x37 + 0xc0 2 0x31 0x93 + 0xc0 2 0x32 0x0f + 0xc0 2 0x33 0xff + 0xc0 2 0x34 0xc8 + 0xc0 2 0x35 0xbf + 0xff 0>; + init_off = <0xff 0>; + }; + }; +}; /* end of / */ diff --git a/arch/arm/boot/dts/amlogic/mesontl1_x301-panel.dtsi b/arch/arm/boot/dts/amlogic/mesontl1_x301-panel.dtsi new file mode 100644 index 000000000000..94e1f33e507c --- /dev/null +++ b/arch/arm/boot/dts/amlogic/mesontl1_x301-panel.dtsi @@ -0,0 +1,1121 @@ +/* + * arch/arm64/boot/dts/amlogic/mesontl1_x301-panel.dtsi + * + * Copyright (C) 2016 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +/ { + lcd { + compatible = "amlogic, lcd-tl1"; + status = "okay"; + mode = "tv"; + fr_auto_policy = <1>; /* 0=disable, 1=60/50hz, 2=60/50/48hz */ + key_valid = <1>; + clocks = <&clkc CLKID_VCLK2_ENCL + &clkc CLKID_VCLK2_VENCL + &clkc CLKID_TCON + &clkc CLKID_FCLK_DIV5 + &clkc CLKID_TCON_PLL_COMP>; + clock-names = "encl_top_gate", + "encl_int_gate", + "tcon_gate", + "fclk_div5", + "clk_tcon"; + reg = <0xff660000 0x8100 + 0xff634400 0x300>; + interrupts = <0 3 1 + 0 78 1 + 0 88 1>; + interrupt-names = "vsync","vbyone","tcon"; + pinctrl-names = "vbyone","vbyone_off","tcon","tcon_off"; + pinctrl-0 = <&lcd_vbyone_pins>; + pinctrl-1 = <&lcd_vbyone_off_pins>; + pinctrl-2 = <&lcd_tcon_pins>; + pinctrl-3 = <&lcd_tcon_off_pins>; + pinctrl_version = <2>; /* for uboot */ + memory-region = <&lcd_tcon_reserved>; + tcon_mem_addr = <0x71000000>; + + /* power type:(0=cpu_gpio, 2=signal, 3=extern, 0xff=ending) */ + /* power index:(gpios_index, or extern_index, 0xff=invalid) */ + /* power value:(0=output low, 1=output high, 2=input) */ + /* power delay:(unit in ms) */ + lcd_cpu-gpios = <&gpio_ao GPIOAO_4 GPIO_ACTIVE_HIGH + &gpio GPIOH_2 GPIO_ACTIVE_HIGH + &gpio GPIOH_3 GPIO_ACTIVE_HIGH + &gpio GPIOH_12 GPIO_ACTIVE_HIGH + &gpio GPIOH_8 GPIO_ACTIVE_HIGH + &gpio GPIOH_10 GPIO_ACTIVE_HIGH + &gpio GPIOH_11 GPIO_ACTIVE_HIGH + &gpio GPIOH_14 GPIO_ACTIVE_HIGH>; + lcd_cpu_gpio_names = "GPIOAO_4","GPIOH_2","GPIOH_3","GPIOH_12", + "GPIOH_8","GPIOH_10","GPIOH_11","GPIOH_14"; + + lvds_0{ + model_name = "1080p-vfreq"; + interface = "lvds"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 1920 1080 /*h_active, v_active*/ + 2200 1125 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 2060 2650 /*h_period_min,max*/ + 1100 1480 /*v_period_min,max*/ + 120000000 160000000>; /*pclk_min,max*/ + lcd_timing = < + 44 148 0 /*hs_width, hs_bp, hs_pol*/ + 5 30 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 15 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + lvds_attr = < + 1 /*lvds_repack*/ + 1 /*dual_port*/ + 0 /*pn_swap*/ + 0 /*port_swap*/ + 0>; /*lane_reverse*/ + phy_attr=<0xf 0>; /*vswing_level, preem_level*/ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 0 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0>; + }; + + lvds_1{ + model_name = "1080p-hfreq_hdmi"; + interface = "lvds"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 1920 1080 /*h_active, v_active*/ + 2200 1125 /*h_period, v_period*/ + 8 /*lcd_bits*/ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 2080 2720 /*h_period min, max*/ + 1100 1380 /*v_period min, max*/ + 133940000 156000000>; /*pclk_min, max*/ + lcd_timing = < + 44 148 0 /*hs_width, hs_bp, hs_pol*/ + 5 30 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 4 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 0 /*clk_ss_level */ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + lvds_attr = < + 1 /*lvds_repack*/ + 1 /*dual_port*/ + 0 /*pn_swap*/ + 0 /*port_swap*/ + 0>; /*lane_reverse*/ + phy_attr=<0xf 0>; /*vswing_level, preem_level*/ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 0 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0>; + }; + lvds_2{ + model_name = "768p-vfreq"; + interface = "lvds"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 1366 768 /*h_active, v_active*/ + 1560 806 /*h_period, v_period*/ + 8 /*lcd_bits*/ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 1460 2000 /*h_period_min, max */ + 784 1015 /*v_period_min, max */ + 50000000 85000000>; /*pclk_min, max*/ + lcd_timing = < + 56 64 0 /*hs_width, hs_bp, hs_pol*/ + 3 28 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 15 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + lvds_attr = < + 1 /*lvds_repack*/ + 0 /*dual_port*/ + 0 /*pn_swap*/ + 0 /*port_swap*/ + 0>; /*lane_reverse*/ + phy_attr=<0xf 0>; /*vswing_level, preem_level*/ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 0 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0>; + }; + vbyone_0{ + model_name = "public_2region"; + interface = "vbyone"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 10 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 4800 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 33 477 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + vbyone_attr = < + 8 /*lane_count*/ + 2 /*region_num*/ + 4 /*byte_mode*/ + 4>; /*color_fmt*/ + vbyone_intr_enable = < + 1 /*vbyone_intr_enable */ + 3>; /*vbyone_vsync_intr_enable*/ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = <0 0 1 50 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = <2 0 0 10 /*signal disable*/ + 0 0 0 200 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <2>; + }; + vbyone_1{ + model_name = "public_1region"; + interface = "vbyone"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 10 /*lcd_bits*/ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 4800 /*h_period_min, max*/ + 2200 2790 /*v_period_min, max*/ + 552000000 632000000>; /*pclk_min,max*/ + lcd_timing = < + 33 477 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + vbyone_attr = < + 8 /*lane_count*/ + 1 /*region_num*/ + 4 /*byte_mode*/ + 4>; /*color_fmt*/ + vbyone_intr_enable = < + 1 /*vbyone_intr_enable*/ + 3>; /*vbyone_vsync_intr_enable*/ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 50 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 200 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <2>; + }; + vbyone_2{ + model_name = "public_2region_hdmi"; + interface = "vbyone"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 10 /*lcd_bits*/ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 4800 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*v_period_min, max*/ + lcd_timing = < + 33 477 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 4 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 0 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + vbyone_attr = < + 8 /*lane_count*/ + 2 /*region_num*/ + 4 /*byte_mode*/ + 4>; /*color_fmt*/ + vbyone_intr_enable = < + 1 /*vbyone_intr_enable*/ + 3>; /*vbyone_vsync_intr_enable*/ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 50 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 200 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <2>; + }; + vbyone_3{ + model_name = "BOE_HV550QU2"; + interface = "vbyone"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 10 /*lcd_bits*/ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 4800 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 560000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 33 477 1 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + vbyone_attr = < + 8 /*lane_count*/ + 2 /*region_num*/ + 4 /*byte_mode*/ + 4>; /*color_fmt*/ + vbyone_intr_enable = < + 1 /*vbyone_intr_enable*/ + 3>; /*vbyone_vsync_intr_enable*/ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 0 3 0 10 /*3d_disable*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 3 2 0 /*3d_disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <2>; + }; + vbyone_4{ + model_name = "BOE_HV550QU2_1region"; + interface = "vbyone"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 10 /*lcd_bits*/ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 4800 /*h_period_min,max*/ + 2200 2760 /*v_period_min,max*/ + 560000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 33 477 1 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + vbyone_attr = < + 8 /*lane_count*/ + 1 /*region_num*/ + 4 /*byte_mode*/ + 4>; /*color_fmt*/ + vbyone_intr_enable = < + 1 /*vbyone_intr_enable*/ + 3>; /*vbyone_vsync_intr_enable*/ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 0 3 0 10 /*3d_disable*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 3 2 0 /*3d_disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <2>; + }; + p2p_0{ + model_name = "p2p_ceds"; + interface = "p2p"; /*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 5000 2250 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 5100 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 16 29 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + p2p_attr = < + 0 /* teyp: 0=ceds, 1=cmpi, 2=isp, 3=epi, + * 10=chpi, 11=cspi, 12=usit + */ + 12 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 3 2 0 200 /* extern init voltage */ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + p2p_1{ + model_name = "p2p_ceds"; + interface = "p2p"; /*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 5000 2250 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 5100 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 16 29 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + p2p_attr = < + 0 /* teyp: 0=ceds, 1=cmpi, 2=isp, 3=epi, + * 10=chpi, 11=cspi, 12=usit + */ + 6 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + p2p_2{ + model_name = "p2p_chpi"; + interface = "p2p"; /*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 5100 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 16 29 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + p2p_attr = < + 10 /* teyp: 0=ceds, 1=cmpi, 2=isp, 3=epi, + * 10=chpi, 11=cspi, 12=usit + */ + 6 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + p2p_3{ + model_name = "p2p_chpi"; + interface = "p2p"; /*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 5100 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 16 29 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + p2p_attr = < + 10 /* teyp: 0=ceds, 1=cmpi, 2=isp, 3=epi, + * 10=chpi, 11=cspi, 12=usit + */ + 12 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + mlvds_0{ + model_name = "mlvds_1080p"; + interface = "minilvds"; /*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 1920 1080 /*h_active, v_active*/ + 2200 1125 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 2080 2720 /*h_period_min, max*/ + 2200 1125 /*v_period_min, max*/ + 133940000 156000000>; /*pclk_min, max*/ + lcd_timing = < + 44 148 0 /*hs_width, hs_bp, hs_pol*/ + 5 30 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + minilvds_attr = < + 6 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0x660 /* clk_phase */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 0>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + mlvds_1{ + model_name = "mlvds_768p"; + interface = "minilvds";/*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 1366 768 /*h_active, v_active*/ + 1560 806 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 1460 2000 /*h_period_min, max*/ + 784 1015 /*v_period_min, max*/ + 50000000 85000000>; /*pclk_min, max*/ + lcd_timing = < + 56 64 0 /*hs_width, hs_bp, hs_pol*/ + 3 28 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + minilvds_attr = < + 6 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0x660 /* clk_phase */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 0>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + }; + + lcd_extern{ + compatible = "amlogic, lcd_extern"; + status = "okay"; + key_valid = <1>; + i2c_bus = "i2c_bus_1"; + + extern_0{ + index = <0>; + extern_name = "ext_default"; + status = "disabled"; + type = <0>; /*0=i2c, 1=spi, 2=mipi*/ + i2c_address = <0x1c>; /*7bit i2c_addr*/ + i2c_address2 = <0xff>; + cmd_size = <0xff>; /*dynamic cmd_size*/ + + /* init on/off: + * fixed cmd_size: (type, value...); + * cmd_size include all data. + * dynamic cmd_size: (type, cmd_size, value...); + * cmd_size include value. + */ + /* type: 0x00=cmd with delay(bit[3:0]=1 for address2), + * 0xc0=cmd(bit[3:0]=1 for address2), + * 0xf0=gpio, + * 0xfd=delay, + * 0xff=ending + */ + /* value: i2c or spi cmd, or gpio index & level */ + /* delay: unit ms */ + init_on = < + 0xc0 7 0x20 0x01 0x02 0x00 0x40 0xFF 0x00 + 0xc0 7 0x80 0x02 0x00 0x40 0x62 0x51 0x73 + 0xc0 7 0x61 0x06 0x00 0x00 0x00 0x00 0x00 + 0xc0 7 0xC1 0x05 0x0F 0x00 0x08 0x70 0x00 + 0xc0 7 0x13 0x01 0x00 0x00 0x00 0x00 0x00 + 0xc0 7 0x3D 0x02 0x01 0x00 0x00 0x00 0x00 + 0xc0 7 0xED 0x0D 0x01 0x00 0x00 0x00 0x00 + 0xc0 7 0x23 0x02 0x00 0x00 0x00 0x00 0x00 + 0xfd 1 10 /* delay 10ms */ + 0xff 0>; /*ending*/ + init_off = <0xff 0>; /*ending*/ + }; + extern_1{ + index = <1>; + extern_name = "i2c_T5800Q"; + status = "disabled"; + type = <0>; /* 0=i2c, 1=spi, 2=mipi */ + i2c_address = <0x1c>; /* 7bit i2c address */ + }; + extern_2{ + index = <2>; + extern_name = "i2c_ANX6862_7911"; + status = "okay"; + type = <0>; /* 0=i2c, 1=spi, 2=mipi */ + i2c_address = <0x20>; /* 7bit i2c address */ + i2c_address2 = <0x74>; /* 7bit i2c address */ + cmd_size = <0xff>; + + init_on = < + 0xc0 2 0x01 0x2b + 0xc0 2 0x02 0x05 + 0xc0 2 0x03 0x00 + 0xc0 2 0x04 0x00 + 0xc0 2 0x05 0x0c + 0xc0 2 0x06 0x04 + 0xc0 2 0x07 0x21 + 0xc0 2 0x08 0x0f + 0xc0 2 0x09 0x04 + 0xc0 2 0x0a 0x00 + 0xc0 2 0x0b 0x04 + 0xc0 2 0xff 0x00 + 0xfd 1 100 /* delay 100ms */ + + 0xc1 2 0x01 0xca + 0xc1 2 0x02 0x3b + 0xc1 2 0x03 0x33 + 0xc1 2 0x04 0x05 + 0xc1 2 0x05 0x2c + 0xc1 2 0x06 0xf2 + 0xc1 2 0x07 0x9c + 0xc1 2 0x08 0x1b + 0xc1 2 0x09 0x82 + 0xc1 2 0x0a 0x3d + 0xc1 2 0x0b 0x20 + 0xc1 2 0x0c 0x11 + 0xc1 2 0x0d 0xc4 + 0xc1 2 0x0e 0x1a + 0xc1 2 0x0f 0x31 + 0xc1 2 0x10 0x4c + 0xc1 2 0x11 0x12 + 0xc1 2 0x12 0x90 + 0xc1 2 0x13 0xf7 + 0xc1 2 0x14 0x0c + 0xc1 2 0x15 0x20 + 0xc1 2 0x16 0x13 + 0xff 0>; /*ending*/ + init_off = <0xff 0>; /*ending*/ + }; + }; + + backlight{ + compatible = "amlogic, backlight-tl1"; + status = "okay"; + key_valid = <1>; + pinctrl-names = "pwm_on","pwm_vs_on", + "pwm_combo_0_1_on", + "pwm_combo_0_vs_1_on", + "pwm_combo_0_1_vs_on", + "pwm_off", + "pwm_combo_off"; + pinctrl-0 = <&pwm_c_pins3>; + pinctrl-1 = <&bl_pwm_vs_on_pins>; + pinctrl-2 = <&pwm_c_pins3 &pwm_d_pins2>; + pinctrl-3 = <&bl_pwm_combo_0_vs_on_pins &pwm_d_pins2>; + pinctrl-4 = <&pwm_c_pins3 &bl_pwm_combo_1_vs_on_pins>; + pinctrl-5 = <&bl_pwm_off_pins>; + pinctrl-6 = <&bl_pwm_combo_off_pins>; + pinctrl_version = <2>; /* for uboot */ + interrupts = <0 3 1>; + interrupt-names = "ldim_vsync"; + bl_pwm_config = <&bl_pwm_conf>; + + /* pwm port: PWM_A, PWM_B, PWM_C, PWM_D, PWM_E, PWM_F, PWM_VS*/ + /* power index:(point gpios_index, 0xff=invalid) */ + /* power value:(0=output low, 1=output high, 2=input) */ + /* power delay:(unit in ms) */ + bl-gpios = <&gpio_ao GPIOAO_11 GPIO_ACTIVE_HIGH + &gpio GPIOZ_5 GPIO_ACTIVE_HIGH + &gpio GPIOZ_6 GPIO_ACTIVE_HIGH>; + bl_gpio_names = "GPIOAO_11","GPIOZ_5","GPIOZ_6"; + + backlight_0{ + index = <0>; + bl_name = "backlight_pwm"; + bl_level_default_uboot_kernel = <100 100>; + bl_level_attr = <255 10 /*max, min*/ + 128 128>; /*mid, mid_mapping*/ + bl_ctrl_method = <1>; /*1=pwm,2=pwm_combo,3=ldim*/ + bl_power_attr = <0 /*en_gpio_index*/ + 1 0 /*on_value, off_value*/ + 200 200>; /*on_delay(ms), off_delay(ms)*/ + bl_pwm_port = "PWM_C"; + bl_pwm_attr = <1 /*pwm_method(0=negative, 1=positvie)*/ + 180 /*pwm_freq(pwm:Hz, pwm_vs:multiple of vs)*/ + 100 25>; /*duty_max(%), duty_min(%)*/ + bl_pwm_power = <1 0 /*pwm_gpio_index, pwm_gpio_off*/ + 10 10>; /*pwm_on_delay(ms), pwm_off_delay(ms)*/ + bl_pwm_en_sequence_reverse = <0>; /* 1 for reverse */ + }; + backlight_1{ + index = <1>; + bl_name = "backlight_pwm_vs"; + bl_level_default_uboot_kernel = <100 100>; + bl_level_attr = <255 10 /*max, min*/ + 128 128>; /*mid, mid_mapping*/ + bl_ctrl_method = <1>; /*1=pwm,2=pwm_combo,3=ldim*/ + bl_power_attr = <0 /*en_gpio_index*/ + 1 0 /*on_value, off_value*/ + 200 200>; /* on_delay(ms), off_delay(ms)*/ + bl_pwm_port = "PWM_VS"; + bl_pwm_attr = <1 /*pwm_method(0=negative, 1=positvie)*/ + 2 /*pwm_freq(pwm:Hz, pwm_vs:multiple of vs)*/ + 100 25>; /*duty_max(%), duty_min(%)*/ + bl_pwm_power = <1 0 /*pwm_gpio_index, pwm_gpio_off*/ + 10 10>; /*pwm_on_delay(ms), pwm_off_delay(ms)*/ + bl_pwm_en_sequence_reverse = <0>; /* 1 for reverse */ + }; + backlight_2{ + index = <2>; + bl_name = "backlight_pwm_combo"; + bl_level_default_uboot_kernel = <31 100>; + bl_level_attr = <255 10 /*max, min*/ + 128 128>; /*mid, mid_mapping*/ + bl_ctrl_method = <2>; /*1=pwm,2=pwm_combo,3=ldim*/ + bl_power_attr = <0 /*en_gpio_index*/ + 1 0 /*on_value, off_value*/ + 410 110>; /*on_delay(ms), off_delay(ms)*/ + bl_pwm_combo_level_mapping = <255 10 /*pwm_0 range*/ + 0 0>; /*pwm_1 range*/ + bl_pwm_combo_port = "PWM_B","PWM_C"; + bl_pwm_combo_attr = <1 /*pwm0 method*/ + 180 /*pwm0 freq(pwm:Hz, pwm_vs:multiple of vs)*/ + 100 25 /*pwm0 duty_max(%), duty_min(%)*/ + 1 /*pwm1 method*/ + 18000 /*pwm1 freq(pwm:Hz, pwm_vs:multi of vs)*/ + 80 80>; /*pwm1 duty_max(%), duty_min(%)*/ + bl_pwm_combo_power = <1 0 /*pwm0 gpio_index, gpio_off*/ + 2 0 /*pwm1 gpio_index, gpio_off*/ + 10 10>; /*pwm_on_delay(ms), pwm_off_delay(ms)*/ + }; + backlight_3{ + index = <3>; + bl_name = "pwm_combo_ldim_test"; + bl_level_default_uboot_kernel = <31 100>; + bl_level_attr = <255 10 /*max, min*/ + 128 128>; /*mid, mid_mapping*/ + bl_ctrl_method = <2>; /*1=pwm,2=pwm_combo,3=ldim*/ + bl_power_attr = <0 /*en_gpio_index*/ + 1 0 /*on_value, off_value*/ + 410 110>; /*on_delay(ms), off_delay(ms)*/ + bl_pwm_combo_level_mapping = <255 10 /*pwm_0 range*/ + 0 0>; /*pwm_1 range*/ + bl_pwm_combo_port = "PWM_C","PWM_D"; + bl_pwm_combo_attr = <1 /*pwm0 method*/ + 180 /*pwm0 freq(pwm:Hz, pwm_vs:multiple of vs)*/ + 100 25 /*pwm0 duty_max(%), duty_min(%)*/ + 1 /*pwm1 method*/ + 18000 /*pwm1 freq(pwm:Hz, pwm_vs:multi of vs)*/ + 80 80>; /*pwm1 duty_max(%), duty_min(%)*/ + bl_pwm_combo_power = <1 0 /*pwm0 gpio_index, gpio_off*/ + 2 0 /*pwm1 gpio_index, gpio_off*/ + 10 10>; /*pwm_on_delay(ms), pwm_off_delay(ms)*/ + bl_ldim_region_row_col = <2 10>; + }; + backlight_4{ + index = <4>; + bl_name = "ldim_global"; + bl_level_default_uboot_kernel = <100 100>; + bl_level_attr = <255 10 /*max, min*/ + 128 128>; /*mid, mid_mapping*/ + bl_ctrl_method = <3>; /*1=pwm,2=pwm_combo,3=ldim*/ + bl_power_attr = <0xff /*en_gpio_index*/ + 1 0 /*on_value, off_value*/ + 200 200>; /*on_delay(ms), off_delay(ms)*/ + bl_ldim_region_row_col = <1 1>; + bl_ldim_mode = <1>; /*0=left/right side + *1=top/bottom side + *2=direct + */ + ldim_dev_index = <1>; + }; + backlight_5{ + index = <5>; + bl_name = "ldim_iw7027"; + bl_level_default_uboot_kernel = <100 100>; + bl_level_attr = <255 10 /*max, min*/ + 128 128>; /*mid, mid_mapping*/ + bl_ctrl_method = <3>; /*1=pwm,2=pwm_combo,3=ldim*/ + bl_power_attr = <0 /*en_gpio_index*/ + 1 0 /*on_value, off_value*/ + 200 200>; /*on_delay(ms), off_delay(ms)*/ + bl_ldim_region_row_col = <1 10>; + bl_ldim_mode = <1>; /*0=left/right side + *1=top/bottom side + *2=direct + */ + ldim_dev_index = <2>; + }; + backlight_3{ + index = <3>; + bl_name = "pwm_combo_ldim_test"; + bl_level_default_uboot_kernel = <31 100>; + bl_level_attr = <255 10 /*max, min*/ + 128 128>; /*mid, mid_mapping*/ + bl_ctrl_method = <2>; /*1=pwm,2=pwm_combo,3=ldim*/ + bl_power_attr = <0 /*en_gpio_index*/ + 1 0 /*on_value, off_value*/ + 410 110>; /*on_delay(ms), off_delay(ms)*/ + bl_pwm_combo_level_mapping = <255 10 /*pwm_0 range*/ + 0 0>; /*pwm_1 range*/ + bl_pwm_combo_port = "PWM_C","PWM_D"; + bl_pwm_combo_attr = <1 /*pwm0 method*/ + 180 /*pwm0 freq(pwm:Hz, pwm_vs:multiple of vs)*/ + 100 25 /*pwm0 duty_max(%), duty_min(%)*/ + 1 /*pwm1 method*/ + 18000 /*pwm1 freq(pwm:Hz, pwm_vs:multi of vs)*/ + 80 80>; /*pwm1 duty_max(%), duty_min(%)*/ + bl_pwm_combo_power = <1 0 /*pwm0 gpio_index, gpio_off*/ + 2 0 /*pwm1 gpio_index, gpio_off*/ + 10 10>; /*pwm_on_delay(ms), pwm_off_delay(ms)*/ + bl_ldim_region_row_col = <2 10>; + }; + backlight_4{ + index = <4>; + bl_name = "ldim_global"; + bl_level_default_uboot_kernel = <100 100>; + bl_level_attr = <255 10 /*max, min*/ + 128 128>; /*mid, mid_mapping*/ + bl_ctrl_method = <3>; /*1=pwm,2=pwm_combo,3=ldim*/ + bl_power_attr = <0xff /*en_gpio_index*/ + 1 0 /*on_value, off_value*/ + 200 200>; /*on_delay(ms), off_delay(ms)*/ + bl_ldim_region_row_col = <1 1>; + bl_ldim_mode = <1>; /*0=left/right side + *1=top/bottom side + *2=direct + */ + ldim_dev_index = <1>; + }; + backlight_5{ + index = <5>; + bl_name = "ldim_iw7027"; + bl_level_default_uboot_kernel = <100 100>; + bl_level_attr = <255 10 /*max, min*/ + 128 128>; /*mid, mid_mapping*/ + bl_ctrl_method = <3>; /*1=pwm,2=pwm_combo,3=ldim*/ + bl_power_attr = <0 /*en_gpio_index*/ + 1 0 /*on_value, off_value*/ + 200 200>; /*on_delay(ms), off_delay(ms)*/ + bl_ldim_region_row_col = <1 10>; + bl_ldim_mode = <1>; /*0=left/right side + *1=top/bottom side + *2=direct + */ + ldim_dev_index = <2>; + }; + }; + + bl_pwm_conf:bl_pwm_conf{ + pwm_channel_0 { + pwm_port_index = <2>; + pwms = <&pwm_cd MESON_PWM_0 30040 0>; + }; + pwm_channel_1 { + pwm_port_index = <3>; + pwms = <&pwm_cd MESON_PWM_1 30040 0>; + }; + }; + + local_dimming_device { + compatible = "amlogic, ldim_dev"; + status = "okay"; + pinctrl-names = "ldim_pwm", + "ldim_pwm_vs", + "ldim_pwm_combo", + "ldim_pwm_vs_combo", + "ldim_pwm_off", + "ldim_pwm_combo_off"; + pinctrl-0 = <&pwm_c_pins3>; + pinctrl-1 = <&bl_pwm_vs_on_pins>; + pinctrl-2 = <&pwm_c_pins3 &pwm_d_pins2>; + pinctrl-3 = <&bl_pwm_vs_on_pins &pwm_d_pins2>; + pinctrl-4 = <&bl_pwm_off_pins>; + pinctrl-5 = <&bl_pwm_combo_off_pins>; + pinctrl_version = <1>; /* for uboot */ + ldim_pwm_config = <&bl_pwm_conf>; + + /* pwm port: PWM_A, PWM_B, PWM_C, PWM_D, PWM_E, PWM_F, PWM_VS*/ + ldim_dev-gpios = <&gpio_ao GPIOAO_11 GPIO_ACTIVE_HIGH + &gpio GPIOZ_5 GPIO_ACTIVE_HIGH + &gpio GPIOZ_6 GPIO_ACTIVE_HIGH>; + ldim_dev_gpio_names = "GPIOAO_11","GPIOZ_5","GPIOZ_6"; + + ldim_dev_0 { + index = <0>; + type = <0>; /*0=normal, 1=spi, 2=i2c*/ + ldim_dev_name = "ob3350"; + ldim_pwm_port = "PWM_C"; + ldim_pwm_attr = <0 /* pol */ + 200 /*freq(pwm:Hz, pwm_vs:multiple of vs)*/ + 50>;/*default duty(%)*/ + en_gpio_on_off = <0 /*ldim_dev-gpios index*/ + 1 0>; /*on_level, off_level*/ + dim_max_min = <100 20>; /*dim_max, dim_min*/ + }; + ldim_dev_1 { + index = <1>; + type = <0>; /*0=normal, 1=spi, 2=i2c*/ + ldim_dev_name = "global"; + ldim_pwm_port = "PWM_C"; + ldim_pwm_attr = <1 /* pol */ + 180 /*freq(pwm:Hz, pwm_vs:multiple of vs)*/ + 50>;/*default duty(%)*/ + analog_pwm_port = "PWM_D"; + analog_pwm_attr = <1 /*pol(0=negative, 1=positvie)*/ + 18000 /*freq(pwm:Hz)*/ + 100 25 /*duty_max(%), duty_min(%)*/ + 80>; /*default duty(%)*/ + en_gpio_on_off = <0 /*ldim_dev-gpios index*/ + 1 0>; /*on_level, off_level*/ + dim_max_min = <100 20>; /*dim_max, dim_min*/ + }; + + ldim_dev_2 { + index = <2>; + type = <1>; /* 0=normal,1=spi,2=i2c */ + ldim_dev_name = "iw7027"; + ldim_pwm_port = "PWM_VS"; + ldim_pwm_attr = <1 /* pol */ + 2 /*freq(pwm:Hz, pwm_vs:multiple of vs)*/ + 50>;/*default duty(%)*/ + spi_bus_num = <0>; + spi_chip_select = <0>; + spi_max_frequency = <1000000>; /* unit: hz */ + spi_mode = <0>; /* mode: 0, 1, 2, 3 */ + spi_cs_delay = <10 /* hold_high_delay */ + 100>; /* clk_cs_delay (unit: us) */ + en_gpio_on_off = <0 /* ldim_dev-gpios index */ + 1 /* on_level */ + 0>; /* off_level */ + lamp_err_gpio = <0xff>; + /* ldim_dev-gpios index, 0xff=invalid */ + spi_write_check = <0>; /* 0=disable, 1=enable */ + + dim_max_min = <0xfff 0x7f>; /* dim_max, dim_min */ + ldim_region_mapping = <0 1 2 3 4 5 6 7 8 9>; + + cmd_size = <0xff>; + /* init: (type, data...) */ + /* type: 0x00=cmd with delay, + * 0xc0=cmd, + * 0xfd=delay, + * 0xff=ending + */ + /* data: spi data, fill 0x0 for no use */ + /* delay: unit ms */ + init_on = < + 0xc0 2 0x23 0x03 + 0xc0 2 0x24 0xff + 0xc0 2 0x25 0x00 + 0xc0 2 0x26 0x00 + 0xc0 2 0x27 0x60 + 0xc0 2 0x29 0x00 + 0xc0 2 0x2a 0x00 + 0xc0 2 0x2b 0x00 + 0xc0 2 0x2c 0x73 + 0xc0 2 0x2d 0x37 + 0xc0 2 0x31 0x93 + 0xc0 2 0x32 0x0f + 0xc0 2 0x33 0xff + 0xc0 2 0x34 0xc8 + 0xc0 2 0x35 0xbf + 0xff 0>; + init_off = <0xff 0>; + }; + }; +}; /* end of / */ diff --git a/arch/arm/boot/dts/amlogic/mesontl1.dtsi b/arch/arm/boot/dts/amlogic/mesontm2.dtsi similarity index 64% rename from arch/arm/boot/dts/amlogic/mesontl1.dtsi rename to arch/arm/boot/dts/amlogic/mesontm2.dtsi index ed116df1b2bb..9fe495b604dd 100644 --- a/arch/arm/boot/dts/amlogic/mesontl1.dtsi +++ b/arch/arm/boot/dts/amlogic/mesontm2.dtsi @@ -23,9 +23,10 @@ #include #include #include -#include +#include +#include #include "mesong12a-bifrost.dtsi" - +#include / { interrupt-parent = <&gic>; #address-cells = <1>; @@ -41,9 +42,17 @@ reg = <0x0>; //timer=<&timer_a>; enable-method = "psci"; - clocks = <&scpi_dvfs 0>; - clock-names = "cpu-cluster.0"; + clocks = <&clkc CLKID_CPU_CLK>, + <&clkc CLKID_CPU_FCLK_P>, + <&clkc CLKID_SYS_PLL>; + clock-names = "core_clk", + "low_freq_clk_parent", + "high_freq_clk_parent"; + operating-points-v2 = <&cpu_opp_table0>; + cpu-supply = <&vddcpu0>; //cpu-idle-states = <&SYSTEM_SLEEP_0>; + voltage-tolerance = <0>; + clock-latency = <50000>; }; CPU1:cpu@1 { @@ -52,9 +61,17 @@ reg = <0x1>; //timer=<&timer_b>; enable-method = "psci"; - clocks = <&scpi_dvfs 0>; - clock-names = "cpu-cluster.0"; + clocks = <&clkc CLKID_CPU_CLK>, + <&clkc CLKID_CPU_FCLK_P>, + <&clkc CLKID_SYS_PLL>; + clock-names = "core_clk", + "low_freq_clk_parent", + "high_freq_clk_parent"; + operating-points-v2 = <&cpu_opp_table0>; + cpu-supply = <&vddcpu0>; //cpu-idle-states = <&SYSTEM_SLEEP_0>; + voltage-tolerance = <0>; + clock-latency = <50000>; }; CPU2:cpu@2 { @@ -63,25 +80,41 @@ reg = <0x2>; //timer=<&timer_c>; enable-method = "psci"; - clocks = <&scpi_dvfs 0>; - clock-names = "cpu-cluster.0"; + clocks = <&clkc CLKID_CPU_CLK>, + <&clkc CLKID_CPU_FCLK_P>, + <&clkc CLKID_SYS_PLL>; + clock-names = "core_clk", + "low_freq_clk_parent", + "high_freq_clk_parent"; + operating-points-v2 = <&cpu_opp_table0>; + cpu-supply = <&vddcpu0>; //cpu-idle-states = <&SYSTEM_SLEEP_0>; + voltage-tolerance = <0>; + clock-latency = <50000>; }; CPU3:cpu@3 { device_type = "cpu"; compatible = "arm,cortex-a9"; - reg = <0x0 0x3>; + reg = <0x3>; //timer=<&timer_d>; enable-method = "psci"; - clocks = <&scpi_dvfs 0>; - clock-names = "cpu-cluster.0"; + clocks = <&clkc CLKID_CPU_CLK>, + <&clkc CLKID_CPU_FCLK_P>, + <&clkc CLKID_SYS_PLL>; + clock-names = "core_clk", + "low_freq_clk_parent", + "high_freq_clk_parent"; + operating-points-v2 = <&cpu_opp_table0>; + cpu-supply = <&vddcpu0>; //cpu-idle-states = <&SYSTEM_SLEEP_0>; + voltage-tolerance = <0>; + clock-latency = <50000>; }; }; timer { - compatible = "arm,armv8-timer"; + compatible = "arm,armv7-timer"; interrupts = , , , @@ -101,6 +134,18 @@ bit_resolution =<0>; }; + arm_pmu { + compatible = "arm,cortex-a15-pmu"; + /* clusterb-enabled; */ + interrupts = ; + reg = <0xff634680 0x4>; + cpumasks = <0xf>; + /* default 10ms */ + relax-timer-ns = <10000000>; + /* default 10000us */ + max-wait-cnt = <10000>; + }; + gic: interrupt-controller@2c001000 { compatible = "arm,cortex-a15-gic", "arm,cortex-a9-gic"; #interrupt-cells = <3>; @@ -155,6 +200,18 @@ storage_version = <0x8200006C>; }; + mailbox: mhu@ff63c400 { + status = "okay"; + compatible = "amlogic, meson_mhu"; + reg = <0xff63c400 0x4c>, /* MHU registers */ + <0xfffdf000 0x800>; /* Payload area */ + interrupts = <0 209 1>, /* low priority interrupt */ + <0 210 1>; /* high priority interrupt */ + #mbox-cells = <1>; + mbox-names = "cpu_to_scp_low", "cpu_to_scp_high"; + mboxes = <&mailbox 0 &mailbox 1>; + }; + cpu_iomap { compatible = "amlogic, iomap"; #address-cells = <1>; @@ -185,12 +242,12 @@ #clock-cells = <0>; }; - meson_suspend: pm { + aml_pm { compatible = "amlogic, pm"; - /*gxbaby-suspend;*/ status = "okay"; - reg = <0xff8000a8 0x4>, - <0xff80023c 0x4>; + device_name = "aml_pm"; + debug_reg = <0xff8000a8>; + exit_reg = <0xff80023c>; }; cpuinfo { @@ -199,6 +256,14 @@ cpuinfo_cmd = <0x82000044>; }; + rtc{ + compatible = "amlogic, aml_vrtc"; + alarm_reg_addr = <0xff8000a8>; + timer_e_addr = <0xffd0f188>; + init_date = "2018/01/01"; + status = "disabled"; + }; + reboot { compatible = "amlogic,reboot"; sys_reset = <0x84000009>; @@ -208,10 +273,12 @@ ram-dump { compatible = "amlogic, ram_dump"; status = "okay"; + reg = <0xFF6345E0 4>; + reg-names = "PREG_STICKY_REG8"; }; vpu { - compatible = "amlogic, vpu-tl1"; + compatible = "amlogic, vpu-tm2"; status = "okay"; clocks = <&clkc CLKID_VAPB_MUX>, <&clkc CLKID_VPU_INTR>, @@ -228,6 +295,21 @@ /* 4: 333.3M 5: 400.0M 6: 500.0M 7: 666.7M */ }; + ethmac: ethernet@ff3f0000 { + compatible = "amlogic, g12a-eth-dwmac","snps,dwmac"; + reg = <0xff3f0000 0x10000 + 0xff634540 0x8 + 0xff64c000 0xa0>; + reg-names = "eth_base", "eth_cfg", "eth_pll"; + interrupts = <0 8 1>; + interrupt-names = "macirq"; + status = "disabled"; + clocks = <&clkc CLKID_ETH_CORE>; + clock-names = "ethclk81"; + pll_val = <0x9c0040a 0x927e0000 0xac5f49e5>; + analog_val = <0x20200000 0x0000c000 0x00000023>; + }; + pinctrl_aobus: pinctrl@ff800014 { compatible = "amlogic,meson-tl1-aobus-pinctrl"; #address-cells = <1>; @@ -306,9 +388,113 @@ }; + dwc3: dwc3@ff500000 { + compatible = "synopsys, dwc3"; + status = "disabled"; + reg = <0xff500000 0x100000>; + interrupts = <0 30 4>; + usb-phy = <&usb2_phy_v2>, <&usb3_phy_v2>; + cpu-type = "gxl"; + clock-src = "usb3.0"; + clocks = <&clkc CLKID_USB_GENERAL>; + clock-names = "dwc_general"; + snps,quirk-frame-length-adjustment = <0x20>; + }; + + usb2_phy_v2: usb2phy@ffe09000 { + compatible = "amlogic, amlogic-new-usb2-v2"; + status = "disabled"; + reg = <0xffe09000 0x80 + 0xffd01008 0x100 + 0xff636000 0x2000 + 0xff63a000 0x2000 + 0xff658000 0x2000>; + pll-setting-1 = <0x09400414>; + pll-setting-2 = <0x927E0000>; + pll-setting-3 = <0xac5f69e5>; + pll-setting-4 = <0xfe18>; + pll-setting-5 = <0x8000fff>; + pll-setting-6 = <0x78000>; + pll-setting-7 = <0xe0004>; + pll-setting-8 = <0xe000c>; + version = <2>; + pwr-ctl = <1>; + u2-ctrl-sleep-shift = <17>; + u2-hhi-mem-pd-shift = <30>; + u2-hhi-mem-pd-mask = <0x3>; + u2-ctrl-iso-shift = <17>; + }; + + usb3_phy_v2: usb3phy@ffe09080 { + compatible = "amlogic, amlogic-new-usb3-v3"; + status = "disable"; + reg = <0xffe09080 0x20>; + phy0-reg = <0xff646000>; + phy0-reg-size = <0x2000>; + phy1-reg = <0xff65c000>; + phy1-reg-size = <0x2000>; + reset-reg = <0xffd01008>; + reset-reg-size = <0x100>; + clocks = <&clkc CLKID_PCIE0_GATE + &clkc CLKID_PCIE_PLL + &clkc CLKID_PCIE1_GATE>; + clock-names = "pcie0_gate", + "pcie_refpll", + "pcie1_gate"; + pwr-ctl = <1>; + u30-ctrl-sleep-shift = <18>; + u30-hhi-mem-pd-shift = <26>; + u30-hhi-mem-pd-mask = <0xf>; + u30-ctrl-iso-shift = <18>; + usb30-ctrl-a-rst-bit = <12>; + u31-ctrl-sleep-shift = <20>; + u31-hhi-mem-pd-shift = <4>; + u31-hhi-mem-pd-mask = <0xf>; + u31-ctrl-iso-shift = <20>; + usb31-ctrl-a-rst-bit = <28>; + }; + + usb_otg: usbotg@ffe09080 { + compatible = "amlogic, amlogic-new-otg"; + status = "disabled"; + usb2-phy-reg = <0xffe09000>; + usb2-phy-reg-size = <0x100>; + interrupts = <0 16 4>; + }; + + + dwc2_a: dwc2_a@ff400000 { + compatible = "amlogic, dwc2"; + status = "disabled"; + device_name = "dwc2_a"; + reg = <0xff400000 0x40000>; + interrupts = <0 31 4>; + pl-periph-id = <0>; /** lm name */ + clock-src = "usb0"; /** clock src */ + port-id = <0>; /** ref to mach/usb.h */ + port-type = <2>; /** 0: otg, 1: host, 2: slave */ + port-speed = <0>; /** 0: default, high, 1: full */ + port-config = <0>; /** 0: default */ + /*0:default,1:single,2:incr,3:incr4,4:incr8,5:incr16,6:disable*/ + port-dma = <0>; + port-id-mode = <0>; /** 0: hardware, 1: sw_host, 2: sw_slave*/ + usb-fifo = <728>; + cpu-type = "v2"; + phy-reg = <0xffe09000>; + phy-reg-size = <0xa0>; + /** phy-interface: 0x0: amlogic-v1 phy, 0x1: synopsys phy **/ + /** 0x2: amlogic-v2 phy **/ + phy-interface = <0x2>; + phy-otg = <0x1>; + clocks = <&clkc CLKID_USB_GENERAL + &clkc CLKID_USB1_TO_DDR>; + clock-names = "usb_general", + "usb1"; + }; + wdt: watchdog@0xffd0f0d0 { compatible = "amlogic, meson-wdt"; - status = "okay"; + status = "disabled"; default_timeout=<10>; reset_watchdog_method=<1>; /* 0:sysfs,1:kernel */ reset_watchdog_time=<2>; @@ -322,16 +508,102 @@ jtag { compatible = "amlogic, jtag"; + status = "okay"; + select = "disable"; /* disable/apao */ + pinctrl-names="jtag_apao_pins"; + pinctrl-0=<&jtag_apao_pins>; + }; + + saradc:saradc { + compatible = "amlogic,meson-g12a-saradc"; status = "disabled"; - select = "apao"; /* disable/apao/apee */ - jtagao-gpios = <&gpio_ao GPIOAO_6 0 - &gpio_ao GPIOAO_7 0 - &gpio_ao GPIOAO_8 0 - &gpio_ao GPIOAO_9 0>; - jtagee-gpios = <&gpio GPIOC_0 0 - &gpio GPIOC_1 0 - &gpio GPIOC_4 0 - &gpio GPIOC_5 0>; + #io-channel-cells = <1>; + clocks = <&xtal>, <&clkc CLKID_SARADC_GATE>; + clock-names = "xtal", "saradc_clk"; + interrupts = ; + reg = <0xff809000 0x48>; + }; + + vddcpu0: pwmao_d-regulator { + compatible = "pwm-regulator"; + pwms = <&pwm_AO_cd MESON_PWM_1 1500 0>; + regulator-name = "vddcpu0"; + regulator-min-microvolt = <690000>; + regulator-max-microvolt = <1050000>; + regulator-always-on; + max-duty-cycle = <1500>; + /* Voltage Duty-Cycle */ + voltage-table = <1050000 0>, + <1040000 3>, + <1030000 6>, + <1020000 8>, + <1010000 11>, + <1000000 14>, + <990000 17>, + <980000 20>, + <970000 23>, + <960000 26>, + <950000 29>, + <940000 31>, + <930000 34>, + <920000 37>, + <910000 40>, + <900000 43>, + <890000 45>, + <880000 48>, + <870000 51>, + <860000 54>, + <850000 56>, + <840000 59>, + <830000 62>, + <820000 65>, + <810000 68>, + <800000 70>, + <790000 73>, + <780000 76>, + <770000 79>, + <760000 81>, + <750000 84>, + <740000 87>, + <730000 89>, + <720000 92>, + <710000 95>, + <700000 98>, + <690000 100>; + status = "okay"; + }; + + aml_dma { + compatible = "amlogic,aml_txlx_dma"; + reg = <0xff63e000 0x48>; + interrupts = <0 180 1>; + + aml_aes { + compatible = "amlogic,aes_g12a_dma"; + dev_name = "aml_aes_dma"; + status = "okay"; + }; + + aml_sha { + compatible = "amlogic,sha_dma"; + dev_name = "aml_sha_dma"; + status = "okay"; + }; + }; + + rng { + compatible = "amlogic,meson-rng"; + status = "okay"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0xff630218 0x4>; + quality = /bits/ 16 <1000>; + }; + + power_ctrl: power_ctrl@ff8000e8 { + compatible = "amlogic, sm1-powerctrl"; + reg = <0xff8000e8 0x10>, + <0xff63c100 0x10>; }; soc { @@ -362,7 +634,7 @@ ranges = <0x0 0xff600000 0x10000>; clkaudio:audio_clocks { - compatible = "amlogic, tl1-audio-clocks"; + compatible = "amlogic, tm2-audio-clocks"; #clock-cells = <1>; reg = <0x0 0xb0>; }; @@ -404,13 +676,22 @@ reg = <0xFF601400 0x400>; }; eqdrc_base { - reg = <0xFF602000 0x2000>; + reg = <0xFF602000 0x1000>; }; reset_base { reg = <0xFFD01000 0x1000>; }; vad_base { - reg = <0xFF601800 0x800>; + reg = <0xFF601800 0x400>; + }; + earcrx_cdmc_base { + reg = <0xFF603800 0x30>; + }; + earcrx_dmac_base { + reg = <0xFF603C00 0x20>; + }; + earcrx_top_base { + reg = <0xFF603E00 0x10>; }; }; @@ -476,7 +757,7 @@ gpio_intc: interrupt-controller@f080 { compatible = "amlogic,meson-gpio-intc", - "amlogic,meson-tl1-gpio-intc"; + "amlogic,meson-tm2-gpio-intc"; reg = <0xf080 0x10>; interrupt-controller; #interrupt-cells = <2>; @@ -614,7 +895,7 @@ status = "okay"; clocks = <&xtal>; clock-names = "clk_uart"; - xtal_tick_en = <1>; + xtal_tick_en = <2>; fifosize = < 64 >; //pinctrl-names = "default"; //pinctrl-0 = <&ao_a_uart_pins>; @@ -622,6 +903,18 @@ support-sysrq = <0>; }; + uart_AO_B: serial@4000 { + compatible = "amlogic, meson-uart"; + reg = <0x4000 0x18>; + interrupts = <0 197 1>; + status = "disabled"; + clocks = <&xtal>; + clock-names = "clk_uart"; + fifosize = < 64 >; + pinctrl-names = "default"; + pinctrl-0 = <&ao_b_uart_pins1>; + }; + remote: rc@8040 { compatible = "amlogic, aml_remote"; reg = <0x8040 0x44>, @@ -635,6 +928,15 @@ max_frame_time = <200>; }; + irblaster: meson-irblaster@14c { + compatible = "amlogic, meson_irblaster"; + reg = <0x14c 0x10>, + <0x40 0x4>; + #irblaster-cells = <2>; + interrupts = ; + status = "disabled"; + }; + i2c_AO: i2c@5000 { compatible = "amlogic,meson-i2c"; status = "disabled"; @@ -650,7 +952,7 @@ i2c_AO_slave:i2c_slave@6000 { compatible = "amlogic, meson-i2c-slave"; status = "disabled"; - reg = <0x0 0x6000 0x0 0x20>; + reg = <0x6000 0x20>; interrupts = ; pinctrl-names="default"; pinctrl-0=<&i2c_ao_slave_pins>; @@ -815,9 +1117,153 @@ }; }; + uart_A: serial@ffd24000 { + compatible = "amlogic, meson-uart"; + reg = <0xffd24000 0x18>; + interrupts = <0 26 1>; + status = "disabled"; + clocks = <&xtal + &clkc CLKID_UART0>; + clock-names = "clk_uart", + "clk_gate"; + fifosize = < 128 >; + pinctrl-names = "default"; + pinctrl-0 = <&a_uart_pins>; + }; + + uart_B: serial@ffd23000 { + compatible = "amlogic, meson-uart"; + reg = <0xffd23000 0x18>; + interrupts = <0 75 1>; + status = "disabled"; + clocks = <&xtal + &clkc CLKID_UART1>; + clock-names = "clk_uart", + "clk_gate"; + fifosize = < 64 >; + pinctrl-names = "default"; + pinctrl-0 = <&b_uart_pins>; + }; + + uart_C: serial@ffd22000 { + compatible = "amlogic, meson-uart"; + reg = <0xffd22000 0x18>; + interrupts = <0 93 1>; + status = "disabled"; + clocks = <&xtal + &clkc CLKID_UART1>; + clock-names = "clk_uart", + "clk_gate"; + fifosize = < 64 >; + pinctrl-names = "default"; + pinctrl-0 = <&c_uart_pins>; + }; + + + pcie_A: pcieA@fc000000 { + compatible = "amlogic, amlogic-pcie-v2", "snps,dw-pcie"; + reg = <0xfc000000 0x400000 + 0xff648000 0x2000 + 0xfc400000 0x200000 + 0xff646000 0x2000 + 0xffd01080 0x10>; + reg-names = "elbi", "cfg", "config", "phy", "reset"; + interrupts = <0 221 0>; + #interrupt-cells = <1>; + bus-range = <0x0 0xff>; + #address-cells = <3>; + #size-cells = <2>; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &gic GIC_SPI 223 IRQ_TYPE_EDGE_RISING>; + device_type = "pci"; + ranges = <0x81000000 0 0 0xfc600000 0x0 0x100000 + /* downstream I/O */ + 0x82000000 0xfc700000 0x0 0xfc700000 0 0x1900000>; + /* non-prefetchable memory */ + num-lanes = <1>; + pcie-num = <1>; + + clocks = <&clkc CLKID_PCIE0_GATE + &clkc CLKID_PCIE1 + &clkc CLKID_PCIE0PHY>; + clock-names = "pcie_refpll", + "pcie", + "pcie_phy"; + /*reset-gpio-type 0:Shared pad(no reset)1:OD pad2:Normal pad*/ + gpio-type = <2>; + pcie-apb-rst-bit = <15>; + pcie-phy-rst-bit = <14>; + pcie-ctrl-a-rst-bit = <12>; + pwr-ctl = <1>; + pcie-ctrl-sleep-shift = <18>; + pcie-hhi-mem-pd-shift = <26>; + pcie-hhi-mem-pd-mask = <0xf>; + pcie-ctrl-iso-shift = <18>; + status = "disabled"; + }; + + pcie_B: pcieB@fc000000 { + compatible = "amlogic, amlogic-pcie-v2", "snps,dw-pcie"; + reg = <0xfA000000 0x400000 + 0xff65E000 0x2000 + 0xfA400000 0x200000 + 0xff65C000 0x2000 + 0xffd01080 0x10>; + reg-names = "elbi", "cfg", "config", "phy", + "reset"; + interrupts = <0 229 0>; + #interrupt-cells = <1>; + bus-range = <0x0 0xff>; + #address-cells = <3>; + #size-cells = <2>; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &gic GIC_SPI 231 IRQ_TYPE_EDGE_RISING>; + device_type = "pci"; + ranges = <0x81000000 0 0 0xfA600000 0x0 0x100000 + /* downstream I/O */ + 0x82000000 0xfA700000 0x0 0xfA700000 0 0x1900000>; + /* non-prefetchable memory */ + num-lanes = <1>; + pcie-num = <1>; + + clocks = <&clkc CLKID_PCIE1_GATE + &clkc CLKID_PCIE1 + &clkc CLKID_PCIE1PHY>; + clock-names = "pcie_refpll", + "pcie", + "pcie_phy"; + /*reset-gpio-type 0:Shared pad(no reset)1:OD pad2:Normal pad*/ + gpio-type = <2>; + pcie-apb-rst-bit = <30>; + pcie-phy-rst-bit = <29>; + pcie-ctrl-a-rst-bit = <28>; + pwr-ctl = <1>; + pcie-ctrl-sleep-shift = <20>; + pcie-hhi-mem-pd-shift = <4>; + pcie-hhi-mem-pd-mask = <0xf>; + pcie-ctrl-iso-shift = <20>; + status = "disabled"; + }; + galcore { + compatible = "amlogic, galcore"; + dev_name = "galcore"; + status = "disabled"; + interrupts = <0 147 4>; + interrupt-names = "galcore"; + reg = <0xff100000 0x800 + /*reg base value:0xff100000 */ + 0xff000000 0x400000 + /*Sram bse value:0xff000000*/ + 0xff63c118 0x0 + 0xff63c11c 0x0 + /*0xff63c118,0xff63c11c :nanoq mem regs*/ + 0xffd01088 0x0 + /*0xffd01088:reset reg*/ + >; + }; sd_emmc_c: emmc@ffe07000 { - status = "okay"; - compatible = "amlogic, meson-mmc-tl1"; + status = "disabled"; + compatible = "amlogic, meson-mmc-tm2"; reg = <0xffe07000 0x800>; interrupts = <0 191 1>; pinctrl-names = "emmc_clk_cmd_pins", "emmc_all_pins"; @@ -826,9 +1272,9 @@ clocks = <&clkc CLKID_SD_EMMC_C>, <&clkc CLKID_SD_EMMC_C_P0_COMP>, <&clkc CLKID_FCLK_DIV2>, - <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_FCLK_DIV2P5>, <&xtal>; - clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + clock-names = "core","clkin0","clkin1","clkin2","xtal"; bus-width = <8>; cap-sd-highspeed; @@ -846,7 +1292,7 @@ tx_delay = <0>; max_req_size = <0x20000>; /**128KB*/ gpio_dat3 = <&gpio BOOT_3 GPIO_ACTIVE_HIGH>; - hw_reset = <&gpio BOOT_9 GPIO_ACTIVE_HIGH>; + hw_reset = <&gpio BOOT_12 GPIO_ACTIVE_HIGH>; card_type = <1>; /* 1:mmc card(include eMMC), * 2:sd card(include tSD) @@ -854,64 +1300,12 @@ }; }; - sd_emmc_b: sd@ffe05000 { - status = "okay"; - compatible = "amlogic, meson-mmc-tl1"; - reg = <0xffe05000 0x800>; - interrupts = <0 190 1>; - - pinctrl-names = "sd_all_pins", - "sd_clk_cmd_pins", - "sd_1bit_pins", - "sd_clk_cmd_uart_pins", - "sd_1bit_uart_pins", - "sd_to_ao_uart_pins", - "ao_to_sd_uart_pins", - "sd_to_ao_jtag_pins", - "ao_to_sd_jtag_pins"; - pinctrl-0 = <&sd_all_pins>; - pinctrl-1 = <&sd_clk_cmd_pins>; - pinctrl-2 = <&sd_1bit_pins>; - pinctrl-3 = <&sd_to_ao_uart_clr_pins - &sd_clk_cmd_pins &ao_to_sd_uart_pins>; - pinctrl-4 = <&sd_to_ao_uart_clr_pins - &sd_1bit_pins &ao_to_sd_uart_pins>; - pinctrl-5 = <&sd_all_pins &sd_to_ao_uart_pins>; - pinctrl-6 = <&sd_to_ao_uart_clr_pins &ao_to_sd_uart_pins>; - pinctrl-7 = <&sd_all_pins &sd_to_ao_uart_pins>; - pinctrl-8 = <&sd_to_ao_uart_clr_pins &ao_to_sd_uart_pins>; - - clocks = <&clkc CLKID_SD_EMMC_B>, - <&clkc CLKID_SD_EMMC_B_P0_COMP>, - <&clkc CLKID_FCLK_DIV2>, - <&clkc CLKID_FCLK_DIV5>, - <&xtal>; - clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; - - bus-width = <4>; - cap-sd-highspeed; - cap-mmc-highspeed; - max-frequency = <100000000>; - disable-wp; - sd { - pinname = "sd"; - ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ - max_req_size = <0x20000>; /**128KB*/ - gpio_dat3 = <&gpio GPIOC_3 GPIO_ACTIVE_HIGH>; - jtag_pin = <&gpio GPIOC_0 GPIO_ACTIVE_HIGH>; - gpio_cd = <&gpio GPIOC_6 GPIO_ACTIVE_HIGH>; - card_type = <5>; - /* 3:sdio device(ie:sdio-wifi), - * 4:SD combo (IO+mem) card - */ - }; - }; spifc: spifc@ffd14000 { compatible = "amlogic,aml-spi-nor"; status = "disabled"; - reg = <0x0 0xffd14000 0x0 0x80>; + reg = <0xffd14000 0x80>; pinctrl-names = "default"; pinctrl-0 = <&spifc_all_pins>; clock-names = "core"; @@ -927,8 +1321,8 @@ slc_nand: nand-controller@0xFFE07800 { compatible = "amlogic, aml_mtd_nand"; - status = "okay"; - reg = <0x0 0xFFE07800 0x0 0x200>; + status = "disabled"; + reg = <0xFFE07800 0x200>; interrupts = <0 34 1>; pinctrl-names = "nand_rb_mod", "nand_norb_mod", "nand_cs_only"; @@ -960,6 +1354,7 @@ clocks = <&clkc CLKID_U_PARSER &clkc CLKID_DEMUX &clkc CLKID_AHB_ARB0 + &clkc CLKID_CLK81 &clkc CLKID_DOS &clkc CLKID_VDEC_MUX &clkc CLKID_HCODEC_MUX @@ -968,6 +1363,7 @@ clock-names = "parser_top", "demux", "ahbarb0", + "clk_81", "vdec", "clk_vdec_mux", "clk_hcodec_mux", @@ -988,13 +1384,22 @@ 0 32 1 0 43 1 0 44 1 - 0 45 1>; + 0 45 1 + 0 74 1>; interrupt-names = "vsync", "demux", "parser", "mailbox_0", "mailbox_1", - "mailbox_2"; + "mailbox_2", + "parser_b"; + }; + amvenc_avc{ + compatible = "amlogic, amvenc_avc"; + dev_name = "amvenc_avc"; + status = "okay"; + interrupts = <0 45 1>; + interrupt-names = "mailbox_2"; }; canvas: canvas { @@ -1040,7 +1445,7 @@ }; meson_fb: fb { - compatible = "amlogic, meson-tl1"; + compatible = "amlogic, meson-tm2"; memory-region = <&logo_reserved>; status = "disabled"; interrupts = <0 3 1 @@ -1058,7 +1463,7 @@ }; ge2d { - compatible = "amlogic, ge2d-g12a"; + compatible = "amlogic, ge2d-sm1"; status = "okay"; interrupts = <0 146 1>; interrupt-names = "ge2d"; @@ -1078,14 +1483,33 @@ interrupt-names = "vsync"; }; + ionvideo { + compatible = "amlogic, ionvideo"; + status = "okay"; + }; + + amlvideo { + compatible = "amlogic, amlvideo"; + status = "okay"; + }; + vdac { compatible = "amlogic, vdac-tl1"; status = "okay"; }; + ddr_bandwidth { + compatible = "amlogic, ddr-bandwidth"; + status = "okay"; + reg = <0xff638000 0x100 + 0xff638c00 0x100>; + interrupts = <0 52 1>; + interrupt-names = "ddr_bandwidth"; + }; + dmc_monitor { compatible = "amlogic, dmc_monitor"; - status = "okay"; + status = "disabled"; reg_base = <0xff638800>; interrupts = ; }; @@ -1134,6 +1558,15 @@ query_licence_cmd = <0x82000050>; status = "disabled"; }; + + defendkey: defendkey { + compatible = "amlogic, defendkey"; + mem_size = <0 0x100000>; + status = "okay"; + }; + cpu_ver_name { + compatible = "amlogic, cpu-major-id-tm2"; + }; }; /* end of / */ &pinctrl_aobus { @@ -1257,25 +1690,77 @@ i2c_ao_2_pins:i2c_ao_2 { mux { - groups = "i2c_ao_sck_2", - "i2c_ao_sda_3"; - function = "i2c_ao"; + groups = "i2c_ao_sck_2", + "i2c_ao_sda_3"; + function = "i2c_ao"; + bias-pull-up; + drive-strength = <3>; }; }; i2c_ao_e_pins:i2c_ao_e { mux { - groups = "i2c_ao_sck_e", - "i2c_ao_sda_e"; - function = "i2c_ao"; + groups = "i2c_ao_sck_e", + "i2c_ao_sda_e"; + function = "i2c_ao"; + bias-pull-up; + drive-strength = <3>; }; }; i2c_ao_slave_pins:i2c_ao_slave { mux { - groups = "i2c_ao_slave_sck", - "i2c_ao_slave_sda"; - function = "i2c_ao_slave"; + groups = "i2c_ao_slave_sck", + "i2c_ao_slave_sda"; + function = "i2c_ao_slave"; + }; + }; + + ao_uart_pins:ao_uart { + mux { + groups = "uart_ao_a_rx", + "uart_ao_a_tx"; + function = "uart_ao_a"; + }; + }; + + ao_b_uart_pins1:ao_b_uart1 { + mux { + groups = "uart_ao_b_tx_2", + "uart_ao_b_rx_3"; + function = "uart_ao_b"; + }; + }; + + ao_b_uart_pins2:ao_b_uart2 { + mux { + groups = "uart_ao_b_tx_8", + "uart_ao_b_rx_9"; + function = "uart_ao_b"; + }; + }; + + irblaster_pins:irblaster_pin { + mux { + groups = "remote_out_ao"; + function = "remote_out_ao"; + }; + }; + + irblaster_pins1:irblaster_pin1 { + mux { + groups = "remote_out_ao9"; + function = "remote_out_ao"; + }; + }; + + jtag_apao_pins:jtag_apao_pin { + mux { + groups = "jtag_a_tdi", + "jtag_a_tdo", + "jtag_a_clk", + "jtag_a_tms"; + function = "jtag_a"; }; }; }; @@ -1289,7 +1774,7 @@ function = "emmc"; input-enable; bias-pull-up; - drive-strength = <3>; + drive-strength = <2>; }; }; @@ -1308,7 +1793,7 @@ function = "emmc"; input-enable; bias-pull-up; - drive-strength = <3>; + drive-strength = <2>; }; }; @@ -1318,7 +1803,7 @@ function = "emmc"; input-enable; bias-pull-down; - drive-strength = <3>; + drive-strength = <2>; }; }; @@ -1363,9 +1848,7 @@ ao_to_sd_uart_pins: ao_to_sd_uart_pins { mux { - groups = "uart_ao_a_rx_c", - "uart_ao_a_tx_c", - "uart_ao_a_rx_w3", + groups ="uart_ao_a_rx_w3", "uart_ao_a_tx_w2", "uart_ao_a_rx_w7", "uart_ao_a_tx_w6", @@ -1406,12 +1889,12 @@ }; }; - /* sdemmc portA */ + /* sdemmc port */ sdio_clk_cmd_pins: sdio_clk_cmd_pins { mux { - groups = "sdio_clk", - "sdio_cmd"; - function = "sdio"; + groups = "sdcard_clk", + "sdcard_cmd"; + function = "sdcard"; input-enable; bias-pull-up; drive-strength = <3>; @@ -1420,13 +1903,13 @@ sdio_all_pins: sdio_all_pins { mux { - groups = "sdio_d0", - "sdio_d1", - "sdio_d2", - "sdio_d3", - "sdio_clk", - "sdio_cmd"; - function = "sdio"; + groups = "sdcard_d0", + "sdcard_d1", + "sdcard_d2", + "sdcard_d3", + "sdcard_clk", + "sdcard_cmd"; + function = "sdcard"; input-enable; bias-pull-up; drive-strength = <3>; @@ -1561,6 +2044,8 @@ groups = "i2c0_sda_c", "i2c0_sck_c"; function = "i2c0"; + bias-pull-up; + drive-strength = <3>; }; }; @@ -1569,6 +2054,8 @@ groups = "i2c0_sda_dv", "i2c0_sck_dv"; function = "i2c0"; + bias-pull-up; + drive-strength = <3>; }; }; @@ -1577,6 +2064,8 @@ groups = "i2c1_sda_z", "i2c1_sck_z"; function = "i2c1"; + bias-pull-up; + drive-strength = <3>; }; }; @@ -1585,6 +2074,8 @@ groups = "i2c1_sda_h", "i2c1_sck_h"; function = "i2c1"; + bias-pull-up; + drive-strength = <3>; }; }; @@ -1593,6 +2084,8 @@ groups = "i2c2_sda_h", "i2c2_sck_h"; function = "i2c2"; + bias-pull-up; + drive-strength = <3>; }; }; @@ -1601,6 +2094,8 @@ groups = "i2c2_sda_z", "i2c2_sck_z"; function = "i2c2"; + bias-pull-up; + drive-strength = <3>; }; }; @@ -1609,6 +2104,8 @@ groups = "i2c3_sda_h1", "i2c3_sck_h0"; function = "i2c3"; + bias-pull-up; + drive-strength = <3>; }; }; @@ -1617,6 +2114,8 @@ groups = "i2c3_sda_h20", "i2c3_sck_h19"; function = "i2c3"; + bias-pull-up; + drive-strength = <3>; }; }; @@ -1625,6 +2124,8 @@ groups = "i2c3_sda_dv", "i2c3_sck_dv"; function = "i2c3"; + bias-pull-up; + drive-strength = <3>; }; }; @@ -1633,6 +2134,8 @@ groups = "i2c3_sda_c", "i2c3_sck_c"; function = "i2c3"; + bias-pull-up; + drive-strength = <3>; }; }; @@ -1655,4 +2158,131 @@ drive-strength = <1>; }; }; + + internal_eth_pins: internal_eth_pins { + mux { + groups = "eth_link_led", + "eth_act_led"; + function = "eth"; + }; + }; + + internal_gpio_pins: internal_gpio_pins { + mux { + groups = "GPIOZ_14", + "GPIOZ_15"; + function = "gpio_periphs"; + bias-disable; + input-enable; + }; + }; + + external_eth_pins: external_eth_pins { + mux { + groups = "eth_mdio", + "eth_mdc", + "eth_rgmii_rx_clk", + "eth_rx_dv", + "eth_rxd0", + "eth_rxd1", + "eth_rxd2_rgmii", + "eth_rxd3_rgmii", + "eth_rgmii_tx_clk", + "eth_txen", + "eth_txd0", + "eth_txd1", + "eth_txd2_rgmii", + "eth_txd3_rgmii"; + function = "eth"; + drive-strength = <3>; + }; + }; + + a_uart_pins:a_uart { + mux { + groups = "uart_a_tx", + "uart_a_rx", + "uart_a_cts", + "uart_a_rts"; + function = "uart_a"; + }; + }; + + b_uart_pins:b_uart { + mux { + groups = "uart_b_tx", + "uart_b_rx"; + function = "uart_b"; + }; + }; + + c_uart_pins:c_uart { + mux { + groups = "uart_c_tx", + "uart_c_rx"; + function = "uart_c"; + }; + }; + + atvdemod_agc_pins: atvdemod_agc_pins { + mux { + groups = "atv_if_agc_dv"; + function = "atv"; + }; + }; + + dtvdemod_agc_pins: dtvdemod_agc_pins { + mux { + groups = "dtv_if_agc_dv2"; + function = "dtv"; + }; + }; + + lcd_vbyone_pins: lcd_vbyone_pin { + mux { + groups = "vx1_lockn","vx1_htpdn"; + function = "vx1"; + }; + }; + + lcd_vbyone_off_pins: lcd_vbyone_off_pin { + mux { + groups = "GPIOH_15","GPIOH_16"; + function = "gpio_periphs"; + input-enable; + }; + }; + + lcd_tcon_pins: lcd_tcon_pin { + mux { + groups = "tcon_0","tcon_1","tcon_2","tcon_3", + "tcon_4","tcon_5","tcon_6","tcon_7", + "tcon_8","tcon_9","tcon_10","tcon_11", + "tcon_12","tcon_13","tcon_14","tcon_15", + "tcon_lock","tcon_spi_mo","tcon_spi_mi", + "tcon_spi_clk","tcon_spi_ss"; + function = "tcon"; + }; + }; + lcd_tcon_off_pins: lcd_tcon_off_pin { + mux { + groups = "GPIOH_0","GPIOH_1","GPIOH_2","GPIOH_3", + "GPIOH_4","GPIOH_5","GPIOH_6","GPIOH_7", + "GPIOH_8","GPIOH_9","GPIOH_10","GPIOH_11", + "GPIOH_12","GPIOH_13","GPIOH_14","GPIOH_15", + "GPIOH_16","GPIOH_17","GPIOH_18","GPIOH_19", + "GPIOH_20"; + function = "gpio_periphs"; + input-enable; + }; + }; +}; + +&gpu{ + tbl = <&dvfs285_cfg + &dvfs400_cfg + &dvfs500_cfg + &dvfs666_cfg + &dvfs800_cfg + &dvfs800_cfg>; }; diff --git a/arch/arm/boot/dts/amlogic/mesontm2_t962x3_ab301-panel.dtsi b/arch/arm/boot/dts/amlogic/mesontm2_t962x3_ab301-panel.dtsi new file mode 100644 index 000000000000..e190a8a91098 --- /dev/null +++ b/arch/arm/boot/dts/amlogic/mesontm2_t962x3_ab301-panel.dtsi @@ -0,0 +1,1066 @@ +/* + * arch/arm/boot/dts/amlogic/mesontm2_t962x3_ab301-panel.dtsi + * + * Copyright (C) 2016 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +/ { + lcd { + compatible = "amlogic, lcd-tm2"; + status = "okay"; + mode = "tv"; + fr_auto_policy = <1>; /* 0=disable, 1=60/50hz, 2=60/50/48hz */ + key_valid = <0>; + clocks = <&clkc CLKID_VCLK2_ENCL + &clkc CLKID_VCLK2_VENCL + &clkc CLKID_TCON + &clkc CLKID_FCLK_DIV5 + &clkc CLKID_TCON_PLL_COMP>; + clock-names = "encl_top_gate", + "encl_int_gate", + "tcon_gate", + "fclk_div5", + "clk_tcon"; + reg = <0xff660000 0x8100 + 0xff634400 0x300>; + interrupts = <0 3 1 + 0 78 1 + 0 88 1>; + interrupt-names = "vsync","vbyone","tcon"; + pinctrl-names = "vbyone","vbyone_off","tcon","tcon_off"; + pinctrl-0 = <&lcd_vbyone_pins>; + pinctrl-1 = <&lcd_vbyone_off_pins>; + pinctrl-2 = <&lcd_tcon_pins>; + pinctrl-3 = <&lcd_tcon_off_pins>; + pinctrl_version = <2>; /* for uboot */ + memory-region = <&lcd_tcon_reserved>; + + /* power type:(0=cpu_gpio, 2=signal, 3=extern, 0xff=ending) */ + /* power index:(gpios_index, or extern_index, 0xff=invalid) */ + /* power value:(0=output low, 1=output high, 2=input) */ + /* power delay:(unit in ms) */ + lcd_cpu-gpios = <&gpio_ao GPIOAO_4 GPIO_ACTIVE_HIGH + &gpio GPIOH_2 GPIO_ACTIVE_HIGH + &gpio GPIOH_3 GPIO_ACTIVE_HIGH + &gpio GPIOH_12 GPIO_ACTIVE_HIGH + &gpio GPIOH_8 GPIO_ACTIVE_HIGH + &gpio GPIOH_10 GPIO_ACTIVE_HIGH + &gpio GPIOH_11 GPIO_ACTIVE_HIGH + &gpio GPIOH_14 GPIO_ACTIVE_HIGH>; + lcd_cpu_gpio_names = "GPIOAO_4","GPIOH_2","GPIOH_3","GPIOH_12", + "GPIOH_8","GPIOH_10","GPIOH_11","GPIOH_14"; + + lvds_0{ + model_name = "1080p-vfreq"; + interface = "lvds"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 1920 1080 /*h_active, v_active*/ + 2200 1125 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 2060 2650 /*h_period_min,max*/ + 1100 1480 /*v_period_min,max*/ + 120000000 160000000>; /*pclk_min,max*/ + lcd_timing = < + 44 148 0 /*hs_width, hs_bp, hs_pol*/ + 5 30 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 15 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + lvds_attr = < + 1 /*lvds_repack*/ + 1 /*dual_port*/ + 0 /*pn_swap*/ + 0 /*port_swap*/ + 0>; /*lane_reverse*/ + phy_attr=<0xf 0>; /*vswing_level, preem_level*/ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 0 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0>; + }; + + lvds_1{ + model_name = "1080p-hfreq_hdmi"; + interface = "lvds"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 1920 1080 /*h_active, v_active*/ + 2200 1125 /*h_period, v_period*/ + 8 /*lcd_bits*/ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 2080 2720 /*h_period min, max*/ + 1100 1380 /*v_period min, max*/ + 133940000 156000000>; /*pclk_min, max*/ + lcd_timing = < + 44 148 0 /*hs_width, hs_bp, hs_pol*/ + 5 30 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 4 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 0 /*clk_ss_level */ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + lvds_attr = < + 1 /*lvds_repack*/ + 1 /*dual_port*/ + 0 /*pn_swap*/ + 0 /*port_swap*/ + 0>; /*lane_reverse*/ + phy_attr=<0xf 0>; /*vswing_level, preem_level*/ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 0 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0>; + }; + lvds_2{ + model_name = "768p-vfreq"; + interface = "lvds"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 1366 768 /*h_active, v_active*/ + 1560 806 /*h_period, v_period*/ + 8 /*lcd_bits*/ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 1460 2000 /*h_period_min, max */ + 784 1015 /*v_period_min, max */ + 50000000 85000000>; /*pclk_min, max*/ + lcd_timing = < + 56 64 0 /*hs_width, hs_bp, hs_pol*/ + 3 28 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 15 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + lvds_attr = < + 1 /*lvds_repack*/ + 0 /*dual_port*/ + 0 /*pn_swap*/ + 0 /*port_swap*/ + 0>; /*lane_reverse*/ + phy_attr=<0xf 0>; /*vswing_level, preem_level*/ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 0 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0>; + }; + vbyone_0{ + model_name = "public_2region"; + interface = "vbyone"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 10 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 4800 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 33 477 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + vbyone_attr = < + 8 /*lane_count*/ + 2 /*region_num*/ + 4 /*byte_mode*/ + 4>; /*color_fmt*/ + vbyone_intr_enable = < + 1 /*vbyone_intr_enable */ + 3>; /*vbyone_vsync_intr_enable*/ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = <0 0 1 50 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = <2 0 0 10 /*signal disable*/ + 0 0 0 200 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <2>; + }; + vbyone_1{ + model_name = "public_1region"; + interface = "vbyone"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 10 /*lcd_bits*/ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 4800 /*h_period_min, max*/ + 2200 2790 /*v_period_min, max*/ + 552000000 632000000>; /*pclk_min,max*/ + lcd_timing = < + 33 477 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + vbyone_attr = < + 8 /*lane_count*/ + 1 /*region_num*/ + 4 /*byte_mode*/ + 4>; /*color_fmt*/ + vbyone_intr_enable = < + 1 /*vbyone_intr_enable*/ + 3>; /*vbyone_vsync_intr_enable*/ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 50 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 200 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <2>; + }; + vbyone_2{ + model_name = "public_2region_hdmi"; + interface = "vbyone"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 10 /*lcd_bits*/ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 4800 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*v_period_min, max*/ + lcd_timing = < + 33 477 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 4 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 0 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + vbyone_attr = < + 8 /*lane_count*/ + 2 /*region_num*/ + 4 /*byte_mode*/ + 4>; /*color_fmt*/ + vbyone_intr_enable = < + 1 /*vbyone_intr_enable*/ + 3>; /*vbyone_vsync_intr_enable*/ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 50 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 200 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <2>; + }; + vbyone_3{ + model_name = "BOE_HV550QU2"; + interface = "vbyone"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 10 /*lcd_bits*/ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 4800 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 560000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 33 477 1 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + vbyone_attr = < + 8 /*lane_count*/ + 2 /*region_num*/ + 4 /*byte_mode*/ + 4>; /*color_fmt*/ + vbyone_intr_enable = < + 1 /*vbyone_intr_enable*/ + 3>; /*vbyone_vsync_intr_enable*/ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 0 3 0 10 /*3d_disable*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 3 2 0 /*3d_disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <2>; + }; + vbyone_4{ + model_name = "BOE_HV550QU2_1region"; + interface = "vbyone"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 10 /*lcd_bits*/ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 4800 /*h_period_min,max*/ + 2200 2760 /*v_period_min,max*/ + 560000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 33 477 1 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + vbyone_attr = < + 8 /*lane_count*/ + 1 /*region_num*/ + 4 /*byte_mode*/ + 4>; /*color_fmt*/ + vbyone_intr_enable = < + 1 /*vbyone_intr_enable*/ + 3>; /*vbyone_vsync_intr_enable*/ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 0 3 0 10 /*3d_disable*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 3 2 0 /*3d_disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <2>; + }; + p2p_0{ + model_name = "p2p_ceds"; + interface = "p2p"; /*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 5000 2250 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 5100 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 16 29 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + p2p_attr = < + 0x0 /* p2p_teyp: + * 0x0=ceds, 0x1=cmpi, 0x2=isp, 0x3=epi, + * 0x10=chpi, 0x11=cspi, 0x12=usit + */ + 12 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 3 2 0 200 /* extern init voltage */ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + p2p_1{ + model_name = "p2p_ceds"; + interface = "p2p"; /*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 5000 2250 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 5100 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 16 29 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + p2p_attr = < + 0x0 /* p2p_teyp: + * 0x0=ceds, 0x1=cmpi, 0x2=isp, 0x3=epi, + * 0x10=chpi, 0x11=cspi, 0x12=usit + */ + 6 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + p2p_2{ + model_name = "p2p_chpi"; + interface = "p2p"; /*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 5100 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 16 29 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + p2p_attr = < + 0x10 /* p2p_teyp: + * 0x0=ceds, 0x1=cmpi, 0x2=isp, 0x3=epi, + * 0x10=chpi, 0x11=cspi, 0x12=usit + */ + 6 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + p2p_3{ + model_name = "p2p_chpi"; + interface = "p2p"; /*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 5100 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 16 29 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + p2p_attr = < + 0x10 /* p2p_teyp: + * 0x0=ceds, 0x1=cmpi, 0x2=isp, 0x3=epi, + * 0x10=chpi, 0x11=cspi, 0x12=usit + */ + 12 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + mlvds_0{ + model_name = "mlvds_1080p"; + interface = "minilvds"; /*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 1920 1080 /*h_active, v_active*/ + 2200 1125 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 2080 2720 /*h_period_min, max*/ + 2200 1125 /*v_period_min, max*/ + 133940000 156000000>; /*pclk_min, max*/ + lcd_timing = < + 44 148 0 /*hs_width, hs_bp, hs_pol*/ + 5 30 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + minilvds_attr = < + 6 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0x660 /* clk_phase */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 0>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + mlvds_1{ + model_name = "mlvds_768p"; + interface = "minilvds";/*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 1366 768 /*h_active, v_active*/ + 1560 806 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 1460 2000 /*h_period_min, max*/ + 784 1015 /*v_period_min, max*/ + 50000000 85000000>; /*pclk_min, max*/ + lcd_timing = < + 56 64 0 /*hs_width, hs_bp, hs_pol*/ + 3 28 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + minilvds_attr = < + 6 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0x660 /* clk_phase */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 0>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + }; + + lcd_extern{ + compatible = "amlogic, lcd_extern"; + status = "okay"; + key_valid = <0>; + i2c_bus = "i2c_bus_1"; + + extern_0{ + index = <0>; + extern_name = "ext_default"; + status = "disabled"; + type = <0>; /*0=i2c, 1=spi, 2=mipi*/ + i2c_address = <0x1c>; /*7bit i2c_addr*/ + i2c_address2 = <0xff>; + cmd_size = <0xff>; /*dynamic cmd_size*/ + + /* init on/off: + * fixed cmd_size: (type, value...); + * cmd_size include all data. + * dynamic cmd_size: (type, cmd_size, value...); + * cmd_size include value. + */ + /* type: 0x00=cmd with delay(bit[3:0]=1 for address2), + * 0xc0=cmd(bit[3:0]=1 for address2), + * 0xf0=gpio, + * 0xfd=delay, + * 0xff=ending + */ + /* value: i2c or spi cmd, or gpio index & level */ + /* delay: unit ms */ + init_on = < + 0xc0 7 0x20 0x01 0x02 0x00 0x40 0xFF 0x00 + 0xc0 7 0x80 0x02 0x00 0x40 0x62 0x51 0x73 + 0xc0 7 0x61 0x06 0x00 0x00 0x00 0x00 0x00 + 0xc0 7 0xC1 0x05 0x0F 0x00 0x08 0x70 0x00 + 0xc0 7 0x13 0x01 0x00 0x00 0x00 0x00 0x00 + 0xc0 7 0x3D 0x02 0x01 0x00 0x00 0x00 0x00 + 0xc0 7 0xED 0x0D 0x01 0x00 0x00 0x00 0x00 + 0xc0 7 0x23 0x02 0x00 0x00 0x00 0x00 0x00 + 0xfd 1 10 /* delay 10ms */ + 0xff 0>; /*ending*/ + init_off = <0xff 0>; /*ending*/ + }; + extern_1{ + index = <1>; + extern_name = "i2c_T5800Q"; + status = "disabled"; + type = <0>; /* 0=i2c, 1=spi, 2=mipi */ + i2c_address = <0x1c>; /* 7bit i2c address */ + }; + extern_2{ + index = <2>; + extern_name = "i2c_ANX6862_7911"; + status = "okay"; + type = <0>; /* 0=i2c, 1=spi, 2=mipi */ + i2c_address = <0x20>; /* 7bit i2c address */ + i2c_address2 = <0x74>; /* 7bit i2c address */ + cmd_size = <0xff>; + + init_on = < + 0xc0 2 0x01 0x2b + 0xc0 2 0x02 0x05 + 0xc0 2 0x03 0x00 + 0xc0 2 0x04 0x00 + 0xc0 2 0x05 0x0c + 0xc0 2 0x06 0x04 + 0xc0 2 0x07 0x21 + 0xc0 2 0x08 0x0f + 0xc0 2 0x09 0x04 + 0xc0 2 0x0a 0x00 + 0xc0 2 0x0b 0x04 + 0xc0 2 0xff 0x00 + 0xfd 1 100 /* delay 100ms */ + + 0xc1 2 0x01 0xca + 0xc1 2 0x02 0x3b + 0xc1 2 0x03 0x33 + 0xc1 2 0x04 0x05 + 0xc1 2 0x05 0x2c + 0xc1 2 0x06 0xf2 + 0xc1 2 0x07 0x9c + 0xc1 2 0x08 0x1b + 0xc1 2 0x09 0x82 + 0xc1 2 0x0a 0x3d + 0xc1 2 0x0b 0x20 + 0xc1 2 0x0c 0x11 + 0xc1 2 0x0d 0xc4 + 0xc1 2 0x0e 0x1a + 0xc1 2 0x0f 0x31 + 0xc1 2 0x10 0x4c + 0xc1 2 0x11 0x12 + 0xc1 2 0x12 0x90 + 0xc1 2 0x13 0xf7 + 0xc1 2 0x14 0x0c + 0xc1 2 0x15 0x20 + 0xc1 2 0x16 0x13 + 0xff 0>; /*ending*/ + init_off = <0xff 0>; /*ending*/ + }; + }; + + backlight{ + compatible = "amlogic, backlight-tm2"; + status = "okay"; + key_valid = <0>; + pinctrl-names = "pwm_on","pwm_vs_on", + "pwm_combo_0_1_on", + "pwm_combo_0_vs_1_on", + "pwm_combo_0_1_vs_on", + "pwm_off", + "pwm_combo_off"; + pinctrl-0 = <&pwm_c_pins3>; + pinctrl-1 = <&bl_pwm_vs_on_pins>; + pinctrl-2 = <&pwm_c_pins3 &pwm_d_pins2>; + pinctrl-3 = <&bl_pwm_combo_0_vs_on_pins &pwm_d_pins2>; + pinctrl-4 = <&pwm_c_pins3 &bl_pwm_combo_1_vs_on_pins>; + pinctrl-5 = <&bl_pwm_off_pins>; + pinctrl-6 = <&bl_pwm_combo_off_pins>; + pinctrl_version = <2>; /* for uboot */ + interrupts = <0 3 1>; + interrupt-names = "ldim_vsync"; + bl_pwm_config = <&bl_pwm_conf>; + + /* pwm port: PWM_A, PWM_B, PWM_C, PWM_D, PWM_E, PWM_F, PWM_VS*/ + /* power index:(point gpios_index, 0xff=invalid) */ + /* power value:(0=output low, 1=output high, 2=input) */ + /* power delay:(unit in ms) */ + bl-gpios = <&gpio_ao GPIOAO_11 GPIO_ACTIVE_HIGH + &gpio GPIOZ_5 GPIO_ACTIVE_HIGH + &gpio GPIOZ_6 GPIO_ACTIVE_HIGH>; + bl_gpio_names = "GPIOAO_11","GPIOZ_5","GPIOZ_6"; + + backlight_0{ + index = <0>; + bl_name = "backlight_pwm"; + bl_level_default_uboot_kernel = <100 100>; + bl_level_attr = <255 10 /*max, min*/ + 128 128>; /*mid, mid_mapping*/ + bl_ctrl_method = <1>; /*1=pwm,2=pwm_combo,3=ldim*/ + bl_power_attr = <0 /*en_gpio_index*/ + 1 0 /*on_value, off_value*/ + 200 200>; /*on_delay(ms), off_delay(ms)*/ + bl_pwm_port = "PWM_C"; + bl_pwm_attr = <1 /*pwm_method(0=negative, 1=positvie)*/ + 180 /*pwm_freq(pwm:Hz, pwm_vs:multiple of vs)*/ + 100 25>; /*duty_max(%), duty_min(%)*/ + bl_pwm_power = <1 0 /*pwm_gpio_index, pwm_gpio_off*/ + 10 10>; /*pwm_on_delay(ms), pwm_off_delay(ms)*/ + bl_pwm_en_sequence_reverse = <0>; /* 1 for reverse */ + }; + backlight_1{ + index = <1>; + bl_name = "backlight_pwm_vs"; + bl_level_default_uboot_kernel = <100 100>; + bl_level_attr = <255 10 /*max, min*/ + 128 128>; /*mid, mid_mapping*/ + bl_ctrl_method = <1>; /*1=pwm,2=pwm_combo,3=ldim*/ + bl_power_attr = <0 /*en_gpio_index*/ + 1 0 /*on_value, off_value*/ + 200 200>; /* on_delay(ms), off_delay(ms)*/ + bl_pwm_port = "PWM_VS"; + bl_pwm_attr = <1 /*pwm_method(0=negative, 1=positvie)*/ + 2 /*pwm_freq(pwm:Hz, pwm_vs:multiple of vs)*/ + 100 25>; /*duty_max(%), duty_min(%)*/ + bl_pwm_power = <1 0 /*pwm_gpio_index, pwm_gpio_off*/ + 10 10>; /*pwm_on_delay(ms), pwm_off_delay(ms)*/ + bl_pwm_en_sequence_reverse = <0>; /* 1 for reverse */ + }; + backlight_2{ + index = <2>; + bl_name = "backlight_pwm_combo"; + bl_level_default_uboot_kernel = <31 100>; + bl_level_attr = <255 10 /*max, min*/ + 128 128>; /*mid, mid_mapping*/ + bl_ctrl_method = <2>; /*1=pwm,2=pwm_combo,3=ldim*/ + bl_power_attr = <0 /*en_gpio_index*/ + 1 0 /*on_value, off_value*/ + 410 110>; /*on_delay(ms), off_delay(ms)*/ + bl_pwm_combo_level_mapping = <255 10 /*pwm_0 range*/ + 0 0>; /*pwm_1 range*/ + bl_pwm_combo_port = "PWM_C","PWM_D"; + bl_pwm_combo_attr = <1 /*pwm0 method*/ + 180 /*pwm0 freq(pwm:Hz, pwm_vs:multiple of vs)*/ + 100 25 /*pwm0 duty_max(%), duty_min(%)*/ + 1 /*pwm1 method*/ + 18000 /*pwm1 freq(pwm:Hz, pwm_vs:multi of vs)*/ + 80 80>; /*pwm1 duty_max(%), duty_min(%)*/ + bl_pwm_combo_power = <1 0 /*pwm0 gpio_index, gpio_off*/ + 2 0 /*pwm1 gpio_index, gpio_off*/ + 10 10>; /*pwm_on_delay(ms), pwm_off_delay(ms)*/ + }; + backlight_3{ + index = <3>; + bl_name = "pwm_combo_ldim_test"; + bl_level_default_uboot_kernel = <31 100>; + bl_level_attr = <255 10 /*max, min*/ + 128 128>; /*mid, mid_mapping*/ + bl_ctrl_method = <2>; /*1=pwm,2=pwm_combo,3=ldim*/ + bl_power_attr = <0 /*en_gpio_index*/ + 1 0 /*on_value, off_value*/ + 410 110>; /*on_delay(ms), off_delay(ms)*/ + bl_pwm_combo_level_mapping = <255 10 /*pwm_0 range*/ + 0 0>; /*pwm_1 range*/ + bl_pwm_combo_port = "PWM_C","PWM_D"; + bl_pwm_combo_attr = <1 /*pwm0 method*/ + 180 /*pwm0 freq(pwm:Hz, pwm_vs:multiple of vs)*/ + 100 25 /*pwm0 duty_max(%), duty_min(%)*/ + 1 /*pwm1 method*/ + 18000 /*pwm1 freq(pwm:Hz, pwm_vs:multi of vs)*/ + 80 80>; /*pwm1 duty_max(%), duty_min(%)*/ + bl_pwm_combo_power = <1 0 /*pwm0 gpio_index, gpio_off*/ + 2 0 /*pwm1 gpio_index, gpio_off*/ + 10 10>; /*pwm_on_delay(ms), pwm_off_delay(ms)*/ + bl_ldim_region_row_col = <2 10>; + }; + backlight_4{ + index = <4>; + bl_name = "ldim_global"; + bl_level_default_uboot_kernel = <100 100>; + bl_level_attr = <255 10 /*max, min*/ + 128 128>; /*mid, mid_mapping*/ + bl_ctrl_method = <3>; /*1=pwm,2=pwm_combo,3=ldim*/ + bl_power_attr = <0xff /*en_gpio_index*/ + 1 0 /*on_value, off_value*/ + 200 200>; /*on_delay(ms), off_delay(ms)*/ + bl_ldim_region_row_col = <1 1>; + bl_ldim_mode = <1>; /*0=left/right side + *1=top/bottom side + *2=direct + */ + ldim_dev_index = <1>; + }; + backlight_5{ + index = <5>; + bl_name = "ldim_iw7027"; + bl_level_default_uboot_kernel = <100 100>; + bl_level_attr = <255 10 /*max, min*/ + 128 128>; /*mid, mid_mapping*/ + bl_ctrl_method = <3>; /*1=pwm,2=pwm_combo,3=ldim*/ + bl_power_attr = <0 /*en_gpio_index*/ + 1 0 /*on_value, off_value*/ + 200 200>; /*on_delay(ms), off_delay(ms)*/ + bl_ldim_region_row_col = <1 10>; + bl_ldim_mode = <1>; /*0=left/right side + *1=top/bottom side + *2=direct + */ + ldim_dev_index = <2>; + }; + }; + + bl_pwm_conf:bl_pwm_conf{ + pwm_channel_0 { + pwm_port_index = <2>; + pwms = <&pwm_cd MESON_PWM_0 30040 0>; + }; + pwm_channel_1 { + pwm_port_index = <3>; + pwms = <&pwm_cd MESON_PWM_1 30040 0>; + }; + }; + + local_dimming_device { + compatible = "amlogic, ldim_dev"; + status = "okay"; + pinctrl-names = "ldim_pwm", + "ldim_pwm_vs", + "ldim_pwm_combo", + "ldim_pwm_vs_combo", + "ldim_pwm_off", + "ldim_pwm_combo_off"; + pinctrl-0 = <&pwm_c_pins3>; + pinctrl-1 = <&bl_pwm_vs_on_pins>; + pinctrl-2 = <&pwm_c_pins3 &pwm_d_pins2>; + pinctrl-3 = <&bl_pwm_vs_on_pins &pwm_d_pins2>; + pinctrl-4 = <&bl_pwm_off_pins>; + pinctrl-5 = <&bl_pwm_combo_off_pins>; + pinctrl_version = <1>; /* for uboot */ + ldim_pwm_config = <&bl_pwm_conf>; + + /* pwm port: PWM_A, PWM_B, PWM_C, PWM_D, PWM_E, PWM_F, PWM_VS*/ + ldim_dev-gpios = <&gpio_ao GPIOAO_11 GPIO_ACTIVE_HIGH + &gpio GPIOZ_5 GPIO_ACTIVE_HIGH + &gpio GPIOZ_6 GPIO_ACTIVE_HIGH>; + ldim_dev_gpio_names = "GPIOAO_11","GPIOZ_5","GPIOZ_6"; + + ldim_dev_0 { + index = <0>; + type = <0>; /*0=normal, 1=spi, 2=i2c*/ + ldim_dev_name = "ob3350"; + ldim_pwm_port = "PWM_C"; + ldim_pwm_attr = <0 /* pol */ + 200 /*freq(pwm:Hz, pwm_vs:multiple of vs)*/ + 50>;/*default duty(%)*/ + en_gpio_on_off = <0 /*ldim_dev-gpios index*/ + 1 0>; /*on_level, off_level*/ + dim_max_min = <100 20>; /*dim_max, dim_min*/ + }; + ldim_dev_1 { + index = <1>; + type = <0>; /*0=normal, 1=spi, 2=i2c*/ + ldim_dev_name = "global"; + ldim_pwm_port = "PWM_C"; + ldim_pwm_attr = <1 /* pol */ + 180 /*freq(pwm:Hz, pwm_vs:multiple of vs)*/ + 50>;/*default duty(%)*/ + analog_pwm_port = "PWM_D"; + analog_pwm_attr = <1 /*pol(0=negative, 1=positvie)*/ + 18000 /*freq(pwm:Hz)*/ + 100 25 /*duty_max(%), duty_min(%)*/ + 80>; /*default duty(%)*/ + en_gpio_on_off = <0 /*ldim_dev-gpios index*/ + 1 0>; /*on_level, off_level*/ + dim_max_min = <100 20>; /*dim_max, dim_min*/ + }; + + ldim_dev_2 { + index = <2>; + type = <1>; /* 0=normal,1=spi,2=i2c */ + ldim_dev_name = "iw7027"; + ldim_pwm_port = "PWM_VS"; + ldim_pwm_attr = <1 /* pol */ + 2 /*freq(pwm:Hz, pwm_vs:multiple of vs)*/ + 50>;/*default duty(%)*/ + spi_bus_num = <0>; + spi_chip_select = <0>; + spi_max_frequency = <1000000>; /* unit: hz */ + spi_mode = <0>; /* mode: 0, 1, 2, 3 */ + spi_cs_delay = <10 /* hold_high_delay */ + 100>; /* clk_cs_delay (unit: us) */ + en_gpio_on_off = <0 /* ldim_dev-gpios index */ + 1 /* on_level */ + 0>; /* off_level */ + lamp_err_gpio = <0xff>; + /* ldim_dev-gpios index, 0xff=invalid */ + spi_write_check = <0>; /* 0=disable, 1=enable */ + + dim_max_min = <0xfff 0x7f>; /* dim_max, dim_min */ + ldim_region_mapping = <0 1 2 3 4 5 6 7 8 9>; + + cmd_size = <0xff>; + /* init: (type, data...) */ + /* type: 0x00=cmd with delay, + * 0xc0=cmd, + * 0xfd=delay, + * 0xff=ending + */ + /* data: spi data, fill 0x0 for no use */ + /* delay: unit ms */ + init_on = < + 0xc0 2 0x23 0x03 + 0xc0 2 0x24 0xff + 0xc0 2 0x25 0x00 + 0xc0 2 0x26 0x00 + 0xc0 2 0x27 0x60 + 0xc0 2 0x29 0x00 + 0xc0 2 0x2a 0x00 + 0xc0 2 0x2b 0x00 + 0xc0 2 0x2c 0x73 + 0xc0 2 0x2d 0x37 + 0xc0 2 0x31 0x93 + 0xc0 2 0x32 0x0f + 0xc0 2 0x33 0xff + 0xc0 2 0x34 0xc8 + 0xc0 2 0x35 0xbf + 0xff 0>; + init_off = <0xff 0>; + }; + }; +}; /* end of / */ diff --git a/arch/arm/boot/dts/amlogic/mesontm2_t962x3_ab309-panel.dtsi b/arch/arm/boot/dts/amlogic/mesontm2_t962x3_ab309-panel.dtsi new file mode 100644 index 000000000000..4bf042efe1bc --- /dev/null +++ b/arch/arm/boot/dts/amlogic/mesontm2_t962x3_ab309-panel.dtsi @@ -0,0 +1,585 @@ +/* + * arch/arm/boot/dts/amlogic/mesontm2_t962x3_ab309-panel.dtsi + * + * Copyright (C) 2016 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +/ { + lcd { + compatible = "amlogic, lcd-tm2"; + status = "okay"; + mode = "tv"; + fr_auto_policy = <0>; /* 0=disable, 1=60/50hz, 2=60/50/48hz */ + key_valid = <0>; + clocks = <&clkc CLKID_VCLK2_ENCL + &clkc CLKID_VCLK2_VENCL + &clkc CLKID_TCON + &clkc CLKID_FCLK_DIV5 + &clkc CLKID_TCON_PLL_COMP>; + clock-names = "encl_top_gate", + "encl_int_gate", + "tcon_gate", + "fclk_div5", + "clk_tcon"; + reg = <0xff660000 0x8100 + 0xff634400 0x300>; + interrupts = <0 3 1 + 0 78 1 + 0 88 1>; + interrupt-names = "vsync","vbyone","tcon"; + pinctrl-names = "vbyone","vbyone_off","tcon","tcon_off"; + pinctrl-0 = <&lcd_vbyone_pins>; + pinctrl-1 = <&lcd_vbyone_off_pins>; + pinctrl-2 = <&lcd_tcon_pins>; + pinctrl-3 = <&lcd_tcon_off_pins>; + pinctrl_version = <2>; /* for uboot */ + + /* power type:(0=cpu_gpio, 2=signal, 3=extern, 0xff=ending) */ + /* power index:(gpios_index, or extern_index, 0xff=invalid) */ + /* power value:(0=output low, 1=output high, 2=input) */ + /* power delay:(unit in ms) */ + + lvds_0{ + model_name = "1080p-vfreq"; + interface = "lvds"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 1920 1080 /*h_active, v_active*/ + 2200 1125 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 2060 2650 /*h_period_min,max*/ + 1100 1480 /*v_period_min,max*/ + 120000000 160000000>; /*pclk_min,max*/ + lcd_timing = < + 44 148 0 /*hs_width, hs_bp, hs_pol*/ + 5 30 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 0 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + lvds_attr = < + 1 /*lvds_repack*/ + 1 /*dual_port*/ + 0 /*pn_swap*/ + 0 /*port_swap*/ + 0>; /*lane_reverse*/ + phy_attr=<0xf 0>; /*vswing_level, preem_level*/ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 2 0 0 0 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + lvds_1{ + model_name = "1080p-hfreq_hdmi"; + interface = "lvds"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 1920 1080 /*h_active, v_active*/ + 2200 1125 /*h_period, v_period*/ + 8 /*lcd_bits*/ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 2080 2720 /*h_period min, max*/ + 1100 1380 /*v_period min, max*/ + 133940000 156000000>; /*pclk_min, max*/ + lcd_timing = < + 44 148 0 /*hs_width, hs_bp, hs_pol*/ + 5 30 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 4 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 0 /*clk_ss_level */ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + lvds_attr = < + 1 /*lvds_repack*/ + 1 /*dual_port*/ + 0 /*pn_swap*/ + 0 /*port_swap*/ + 0>; /*lane_reverse*/ + phy_attr=<0xf 0>; /*vswing_level, preem_level*/ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 2 0 0 0 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + vbyone_0{ + model_name = "public_2region"; + interface = "vbyone"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 10 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 4800 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 33 477 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 0 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + vbyone_attr = < + 8 /*lane_count*/ + 2 /*region_num*/ + 4 /*byte_mode*/ + 4>; /*color_fmt*/ + vbyone_intr_enable = < + 1 /*vbyone_intr_enable */ + 3>; /*vbyone_vsync_intr_enable*/ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + vbyone_1{ + model_name = "public_1region"; + interface = "vbyone"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 10 /*lcd_bits*/ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 4800 /*h_period_min, max*/ + 2200 2790 /*v_period_min, max*/ + 552000000 632000000>; /*pclk_min,max*/ + lcd_timing = < + 33 477 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 0 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + vbyone_attr = < + 8 /*lane_count*/ + 1 /*region_num*/ + 4 /*byte_mode*/ + 4>; /*color_fmt*/ + vbyone_intr_enable = < + 1 /*vbyone_intr_enable*/ + 3>; /*vbyone_vsync_intr_enable*/ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + p2p_0{ + model_name = "p2p_ceds"; + interface = "p2p"; /*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 5000 2250 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 5100 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 16 29 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 0 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + p2p_attr = < + 0 /* teyp: 0=ceds, 1=cmpi, 2=isp, 3=epi, + * 10=chpi, 11=cspi, 12=usit + */ + 12 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + p2p_1{ + model_name = "p2p_ceds"; + interface = "p2p"; /*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 5000 2250 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 5100 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 16 29 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 0 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + p2p_attr = < + 0 /* teyp: 0=ceds, 1=cmpi, 2=isp, 3=epi, + * 10=chpi, 11=cspi, 12=usit + */ + 6 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + p2p_2{ + model_name = "p2p_chpi"; + interface = "p2p"; /*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 5100 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 16 29 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 0 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + p2p_attr = < + 10 /* teyp: 0=ceds, 1=cmpi, 2=isp, 3=epi, + * 10=chpi, 11=cspi, 12=usit + */ + 6 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + p2p_3{ + model_name = "p2p_chpi"; + interface = "p2p"; /*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 5100 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 16 29 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 0 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + p2p_attr = < + 10 /* teyp: 0=ceds, 1=cmpi, 2=isp, 3=epi, + * 10=chpi, 11=cspi, 12=usit + */ + 12 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + mlvds_0{ + model_name = "mlvds_1080p"; + interface = "minilvds"; /*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 1920 1080 /*h_active, v_active*/ + 2200 1125 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 2080 2720 /*h_period_min, max*/ + 2200 1125 /*v_period_min, max*/ + 133940000 156000000>; /*pclk_min, max*/ + lcd_timing = < + 44 148 0 /*hs_width, hs_bp, hs_pol*/ + 5 30 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 0 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + minilvds_attr = < + 6 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0x660 /* clk_phase */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 0>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + mlvds_1{ + model_name = "mlvds_768p"; + interface = "minilvds"; /*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 1366 768 /*h_active, v_active*/ + 1560 806 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 1460 2000 /*h_period_min, max*/ + 784 1015 /*v_period_min, max*/ + 50000000 85000000>; /*pclk_min, max*/ + lcd_timing = < + 56 64 0 /*hs_width, hs_bp, hs_pol*/ + 3 28 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 0 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + minilvds_attr = < + 6 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0x660 /* clk_phase */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 0>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + }; + + lcd_extern{ + compatible = "amlogic, lcd_extern"; + status = "okay"; + key_valid = <0>; + i2c_bus = "i2c_bus_1"; + + extern_0{ + index = <0>; + extern_name = "ext_default"; + status = "disabled"; + type = <0>; /*0=i2c, 1=spi, 2=mipi*/ + i2c_address = <0x1c>; /*7bit i2c_addr*/ + i2c_address2 = <0xff>; + cmd_size = <0xff>; /*dynamic cmd_size*/ + + /* init on/off: + * fixed cmd_size: (type, value...); + * cmd_size include all data. + * dynamic cmd_size: (type, cmd_size, value...); + * cmd_size include value. + */ + /* type: 0x00=cmd with delay(bit[3:0]=1 for address2), + * 0xc0=cmd(bit[3:0]=1 for address2), + * 0xf0=gpio, + * 0xfd=delay, + * 0xff=ending + */ + /* value: i2c or spi cmd, or gpio index & level */ + /* delay: unit ms */ + init_on = < + 0xc0 7 0x20 0x01 0x02 0x00 0x40 0xFF 0x00 + 0xc0 7 0x80 0x02 0x00 0x40 0x62 0x51 0x73 + 0xc0 7 0x61 0x06 0x00 0x00 0x00 0x00 0x00 + 0xc0 7 0xC1 0x05 0x0F 0x00 0x08 0x70 0x00 + 0xc0 7 0x13 0x01 0x00 0x00 0x00 0x00 0x00 + 0xc0 7 0x3D 0x02 0x01 0x00 0x00 0x00 0x00 + 0xc0 7 0xED 0x0D 0x01 0x00 0x00 0x00 0x00 + 0xc0 7 0x23 0x02 0x00 0x00 0x00 0x00 0x00 + 0xfd 1 10 /* delay 10ms */ + 0xff 0>; /*ending*/ + init_off = <0xff 0>; /*ending*/ + }; + extern_1{ + index = <1>; + extern_name = "i2c_T5800Q"; + status = "disabled"; + type = <0>; /* 0=i2c, 1=spi, 2=mipi */ + i2c_address = <0x1c>; /* 7bit i2c address */ + }; + extern_2{ + index = <2>; + extern_name = "i2c_ANX6862_7911"; + status = "okay"; + type = <0>; /* 0=i2c, 1=spi, 2=mipi */ + i2c_address = <0x20>; /* 7bit i2c address */ + i2c_address2 = <0x74>; /* 7bit i2c address */ + cmd_size = <0xff>; + + init_on = < + 0xc0 2 0x01 0x2b + 0xc0 2 0x02 0x05 + 0xc0 2 0x03 0x00 + 0xc0 2 0x04 0x00 + 0xc0 2 0x05 0x0c + 0xc0 2 0x06 0x04 + 0xc0 2 0x07 0x21 + 0xc0 2 0x08 0x0f + 0xc0 2 0x09 0x04 + 0xc0 2 0x0a 0x00 + 0xc0 2 0x0b 0x04 + 0xc0 2 0xff 0x00 + 0xfd 1 100 /* delay 100ms */ + + 0xc1 2 0x01 0xca + 0xc1 2 0x02 0x3b + 0xc1 2 0x03 0x33 + 0xc1 2 0x04 0x05 + 0xc1 2 0x05 0x2c + 0xc1 2 0x06 0xf2 + 0xc1 2 0x07 0x9c + 0xc1 2 0x08 0x1b + 0xc1 2 0x09 0x82 + 0xc1 2 0x0a 0x3d + 0xc1 2 0x0b 0x20 + 0xc1 2 0x0c 0x11 + 0xc1 2 0x0d 0xc4 + 0xc1 2 0x0e 0x1a + 0xc1 2 0x0f 0x31 + 0xc1 2 0x10 0x4c + 0xc1 2 0x11 0x12 + 0xc1 2 0x12 0x90 + 0xc1 2 0x13 0xf7 + 0xc1 2 0x14 0x0c + 0xc1 2 0x15 0x20 + 0xc1 2 0x16 0x13 + 0xff 0>; /*ending*/ + init_off = <0xff 0>; /*ending*/ + }; + }; + +}; /* end of / */ diff --git a/arch/arm/boot/dts/amlogic/mesontxl.dtsi b/arch/arm/boot/dts/amlogic/mesontxl.dtsi deleted file mode 100644 index 9cb47c6bcc9b..000000000000 --- a/arch/arm/boot/dts/amlogic/mesontxl.dtsi +++ /dev/null @@ -1,1536 +0,0 @@ -/* - * arch/arm/boot/dts/amlogic/mesontxl.dtsi - * - * Copyright (C) 2018 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 -#include -#include -#include -#include -#include -#include -#include -#include "mesongxbb-gpu-mali450.dtsi" -#include - -/ { - interrupt-parent = <&gic>; - #address-cells = <1>; - #size-cells = <1>; - - cpus:cpus { - #address-cells = <1>; - #size-cells = <0>; - #cooling-cells = <2>; - - /*cpu-map { - cluster0:cluster0 { - core0 { - cpu = <&CPU0>; - }; - core1 { - cpu = <&CPU1>; - }; - core2 { - cpu = <&CPU2>; - }; - core3 { - cpu = <&CPU3>; - }; - }; - };*/ - - CPU0:cpu@0 { - device_type = "cpu"; - compatible = "arm,cortex-a53","arm,armv8"; - reg = <0x0>; - enable-method = "psci"; - clocks = <&scpi_dvfs 0>; - clock-names = "cpu-cluster.0"; - cpu-idle-states = <&SYSTEM_SLEEP_0>; - }; - - CPU1:cpu@1 { - device_type = "cpu"; - compatible = "arm,cortex-a53","arm,armv8"; - reg = <0x1>; - enable-method = "psci"; - clocks = <&scpi_dvfs 0>; - clock-names = "cpu-cluster.0"; - cpu-idle-states = <&SYSTEM_SLEEP_0>; - }; - - CPU2:cpu@2 { - device_type = "cpu"; - compatible = "arm,cortex-a53","arm,armv8"; - reg = <0x2>; - enable-method = "psci"; - clocks = <&scpi_dvfs 0>; - clock-names = "cpu-cluster.0"; - cpu-idle-states = <&SYSTEM_SLEEP_0>; - }; - - CPU3:cpu@3 { - device_type = "cpu"; - compatible = "arm,cortex-a53","arm,armv8"; - reg = <0x3>; - enable-method = "psci"; - clocks = <&scpi_dvfs 0>; - clock-names = "cpu-cluster.0"; - cpu-idle-states = <&SYSTEM_SLEEP_0>; - }; - - idle-states { - entry-method = "arm,psci"; -/* - CPU_SLEEP_0: cpu-sleep-0 { - compatible = "arm,idle-state"; - arm,psci-suspend-param = <0x0010000>; - local-timer-stop; - entry-latency-us = <3000>; - exit-latency-us = <3000>; - min-residency-us = <8000>; - }; -*/ - - SYSTEM_SLEEP_0: system-sleep-0 { - compatible = "arm,idle-state"; - arm,psci-suspend-param = <0x0020000>; - local-timer-stop; - entry-latency-us = <0x3fffffff>; - exit-latency-us = <0x40000000>; - min-residency-us = <0xffffffff>; - }; - - }; - }; - - timer { - compatible = "arm,armv8-timer"; - interrupts = , - , - , - ; - }; - - timer_bc: timer@c1109990 { - compatible = "arm, meson-bc-timer"; - reg = <0xc1109990 0x4 0xc1109994 0x4>; - timer_name = "Meson TimerF"; - clockevent-rating = <300>; - clockevent-shift = <20>; - clockevent-features = <0x23>; - interrupts = <0 60 1>; - bit_enable = <16>; - bit_mode = <12>; - bit_resolution = <0>; - }; - - pmu { - compatible = "arm,armv8-pmuv3"; - interrupts = , - , - , - ; - }; - - psci { - compatible = "arm,psci-0.2"; - method = "smc"; - }; - - gic: interrupt-controller@2c001000 { - compatible = "arm,cortex-a15-gic", "arm,cortex-a9-gic"; - #interrupt-cells = <3>; - #address-cells = <0>; - interrupt-controller; - reg = <0xc4301000 0x1000>, - <0xc4302000 0x0100>; - interrupts = ; - }; - - clocks { - xtal: xtal-clk { - compatible = "fixed-clock"; - clock-frequency = <24000000>; - clock-output-names = "xtal"; - #clock-cells = <0>; - }; - }; - - cpu_iomap { - compatible = "amlogic, iomap"; - #address-cells=<1>; - #size-cells=<1>; - ranges; - io_cbus_base { - reg = <0xc1100000 0x100000>; - }; - io_apb_base { - reg = <0xd0000000 0x100000>; - }; - io_aobus_base { - reg = <0xc8100000 0x100000>; - }; - io_vapb_base { - reg = <0xd0100000 0x100000>; - }; - io_hiu_base { - reg = <0xc883c000 0x2000>; - }; - }; - - cpuinfo { - compatible = "amlogic, cpuinfo"; - cpuinfo_cmd = <0x82000044>; - }; - - ram-dump { - compatible = "amlogic, ram_dump"; - status = "okay"; - }; - - securitykey { - compatible = "amlogic, securitykey"; - status = "okay"; - storage_query = <0x82000060>; - storage_read = <0x82000061>; - storage_write = <0x82000062>; - storage_tell = <0x82000063>; - storage_verify = <0x82000064>; - storage_status = <0x82000065>; - storage_list = <0x82000067>; - storage_remove = <0x82000068>; - storage_in_func = <0x82000023>; - storage_out_func = <0x82000024>; - storage_block_func = <0x82000025>; - storage_size_func = <0x82000027>; - storage_set_enctype = <0x8200006A>; - storage_get_enctype = <0x8200006B>; - storage_version = <0x8200006C>; - }; - - mailbox: mhu@c883c400 { - compatible = "amlogic, meson_mhu"; - reg = <0xc883c400 0x4c>, /* MHU registers */ - <0xc8013000 0x800>; /* Payload area */ - interrupts = <0 209 1>, /* low priority interrupt */ - <0 210 1>; /* high priority interrupt */ - #mbox-cells = <1>; - mbox-names = "cpu_to_scp_low", "cpu_to_scp_high"; - mboxes = <&mailbox 0 &mailbox 1>; - }; - - scpi_clocks { - compatible = "arm, scpi-clks"; - - scpi_dvfs: scpi_clocks@0 { - compatible = "arm, scpi-clk-indexed"; - #clock-cells = <1>; - clock-indices = <0>; - clock-output-names = "vcpu"; - }; - - }; - - pinctrl_aobus: pinctrl@c8100014{ - compatible = "amlogic,meson-txl-aobus-pinctrl"; - #address-cells = <1>; - #size-cells = <1>; - ranges; - - gpio_ao: ao-bank@c8100014{ - reg = <0xc8100014 0x8>, - <0xc810002c 0x4>, - <0xc8100024 0x8>; - reg-names = "mux", "pull", "gpio"; - gpio-controller; - #gpio-cells = <2>; - }; - }; - - pinctrl_periphs: pinctrl@c88344b0{ - compatible = "amlogic,meson-txl-periphs-pinctrl"; - #address-cells = <1>; - #size-cells = <1>; - ranges; - - gpio: banks@c88344b0{ - reg = <0xc88344b0 0x28>, - <0xc88344e8 0x14>, - <0xc8834520 0x14>, - <0xc8834430 0x40>; - reg-names = "mux", - "pull", - "pull-enable", - "gpio"; - gpio-controller; - #gpio-cells = <2>; - }; - }; - - dwc3: dwc3@c9000000 { - compatible = "synopsys, dwc3"; - status = "disable"; - reg = <0xc9000000 0x100000>; - interrupts = <0 30 4>; - usb-phy = <&usb2_phy>, <&usb3_phy>; - cpu-type = "gxl"; - clock-src = "usb3.0"; - }; - - usb2_phy: usb2phy@d0078000 { - compatible = "amlogic, amlogic-new-usb2"; - status = "disable"; - portnum = <4>; - reg = <0xd0078000 0x80 - 0xc1104408 0x4>; - }; - - usb3_phy: usb3phy@d0078080 { - compatible = "amlogic, amlogic-new-usb3"; - status = "disable"; - portnum = <0>; - reg = <0xd0078080 0x20>; - }; - - dwc2_a: dwc2_a@c9100000 { - compatible = "amlogic, dwc2"; - status = "disable"; - reg = <0xc9100000 0x40000>; - interrupts = <0 31 4>; - pl-periph-id = <0>; /** lm name */ - clock-src = "usb0"; /** clock src */ - port-id = <0>; /** ref to mach/usb.h */ - port-type = <2>; /** 0: otg, 1: host, 2: slave */ - port-speed = <0>; /** 0: default, high, 1: full */ - port-config = <0>; /** 0: default */ - port-dma = <0>; - port-id-mode = <0>; /** 0: hardware, 1: sw_host, 2: sw_slave*/ - usb-fifo = <728>; - cpu-type = "gxl"; - phy-reg = <0xd0078000>; - phy-reg-size = <0xa0>; - clocks = <&clkc CLKID_USB_GENERAL - &clkc CLKID_USB1_TO_DDR - &clkc CLKID_USB1>; - clock-names = "usb_general", - "usb1", - "usb1_to_ddr"; - }; - - ethmac: ethernet@0xc9410000 { - compatible = "amlogic, gxbb-eth-dwmac"; - status = "disable"; - reg = <0xc9410000 0x10000 - 0xc8834540 0x8 - 0xc8834558 0xc - 0xc1104484 0x4>; - interrupts = <0 8 1 - 0 9 1>; - phy-mode= "rmii"; - mc_val_internal_phy = <0x1800>; - mc_val_external_phy = <0x1621>; - interrupt-names = "macirq", - "phyirq"; - clocks = <&clkc CLKID_ETH_CORE>; - clock-names = "ethclk81"; - internal_phy=<1>; - }; - - saradc: saradc { - compatible = "amlogic,meson-txl-saradc"; - status = "okay"; - #io-channel-cells = <1>; - clocks = <&xtal>, <&clkc CLKID_SARADC_GATE>; - clock-names = "xtal", "saradc_clk"; - interrupts = ; - reg = <0xc8100600 0x38>; - }; - - jtag { - compatible = "amlogic, jtag"; - status = "okay"; - select = "apao"; /* disable/apao/apee */ - jtagao-gpios = <&gpio_ao GPIOAO_3 0 - &gpio_ao GPIOAO_4 0 - &gpio_ao GPIOAO_5 0 - &gpio_ao GPIOAO_7 0>; - jtagee-gpios = <&gpio CARD_0 0 - &gpio CARD_1 0 - &gpio CARD_2 0 - &gpio CARD_3 0>; - }; - - meson_suspend: pm { - compatible = "amlogic, pm"; - status = "okay"; - reg = <0xc81000a8 0x4>, - <0xc810023c 0x4>; - }; - - reboot { - compatible = "amlogic,reboot"; - sys_reset = <0x84000009>; - sys_poweroff = <0x84000008>; - }; - - rtc { - compatible = "amlogic, aml_vrtc"; - alarm_reg_addr = <0xc81000a8>; - timer_e_addr = <0xc1109988>; - init_date = "2018/01/01"; - status = "okay"; - }; - - soc { - compatible = "simple-bus"; - #address-cells = <1>; - #size-cells = <1>; - ranges; - - cbus: bus@c1100000 { - compatible = "simple-bus"; - #address-cells = <1>; - #size-cells = <1>; - reg = <0xc1100000 0x100000>; - ranges = <0x0 0xc1100000 0x100000>; - - meson_clk_msr@875c{ - compatible = "amlogic, gxl_measure"; - reg = <0x875c 0x4 - 0x8764 0x4>; - }; - - /*i2c-A*/ - i2c0: i2c@8500 { - compatible = "amlogic,meson-txl-i2c"; - status = "disabled"; - reg = <0x8500 0x20>; - interrupts = , - ; - #address-cells = <1>; - #size-cells = <0>; - clocks = <&clkc CLKID_I2C>; - }; - - /*i2c-B*/ - i2c1: i2c@87c0 { - compatible = "amlogic,meson-txl-i2c"; - status = "disabled"; - reg = <0x87c0 0x20>; - interrupts = , - ; - #address-cells = <1>; - #size-cells = <0>; - clocks = <&clkc CLKID_I2C>; - }; - - /*i2c-C*/ - i2c2: i2c@87e0 { - compatible = "amlogic,meson-txl-i2c"; - status = "disabled"; - reg = <0x87e0 0x20>; - interrupts = , - ; - #address-cells = <1>; - #size-cells = <0>; - clocks = <&clkc CLKID_I2C>; - }; - - /*i2c-D*/ - i2c3: i2c@8d20 { - compatible = "amlogic,meson-txl-i2c"; - status = "disabled"; - reg = <0x8d20 0x20>; - interrupts = , - ; - #address-cells = <1>; - #size-cells = <0>; - clocks = <&clkc CLKID_I2C>; - }; - - pwm_ab: pwm@8550 { - compatible = "amlogic,txl-ee-pwm"; - reg = <0x8550 0x1c>; - #pwm-cells = <3>; - clocks = <&xtal>, - <&xtal>, - <&xtal>, - <&xtal>; - clock-names = "clkin0", - "clkin1", - "clkin2", - "clkin3"; - status = "disabled"; - }; - - pwm_cd: pwm@8640 { - compatible = "amlogic,txl-ee-pwm"; - reg = <0x8640 0x1c>; - #pwm-cells = <3>; - clocks = <&xtal>, - <&xtal>, - <&xtal>, - <&xtal>; - clock-names = "clkin0", - "clkin1", - "clkin2", - "clkin3"; - status = "disabled"; - }; - - pwm_ef: pwm@86c0 { - compatible = "amlogic,txl-ee-pwm"; - reg = <0x86c0 0x1c>; - #pwm-cells = <3>; - status = "disabled"; - }; - - spicc: spi@8d80 { - compatible = "amlogic,meson-txl-spicc", - "amlogic,meson-txlx-spicc"; - reg = <0x8d80 0x3c>; - interrupts = ; - clocks = <&clkc CLKID_SPICC0>; - clock-names = "core"; - #address-cells = <1>; - #size-cells = <0>; - status = "disabled"; - }; - - uart_A: serial@84c0 { - compatible = "amlogic, meson-uart"; - reg = <0x84c0 0x18>; - interrupts = <0 26 1>; - status = "disabled"; - clocks = <&xtal &clkc CLKID_UART0>; - clock-names = "clk_uart", "clk_gate"; - fifosize = < 128 >; - pinctrl-names = "default"; - pinctrl-0 = <&a_uart_pins>; - }; - - uart_B: serial@84dc { - compatible = "amlogic, meson-uart"; - reg = <0x84dc 0x18>; - interrupts = <0 75 1>; - status = "disabled"; - clocks = <&xtal &clkc CLKID_UART1>; - clock-names = "clk_uart", "clk_gate"; - fifosize = < 64 >; - pinctrl-names = "default"; - pinctrl-0 = <&b_uart_pins>; - }; - - uart_C: serial@8700 { - compatible = "amlogic, meson-uart"; - reg = <0x8700 0x18>; - interrupts = <0 93 1>; - status = "disabled"; - clocks = <&xtal &clkc CLKID_UART2>; - clock-names = "clk_uart", "clk_gate"; - fifosize = < 64 >; - pinctrl-names = "default"; - pinctrl-0 = <&c_uart_pins>; - }; - - gpio_intc: interrupt-controller@9880 { - compatible = "amlogic,meson-gpio-intc", - "amlogic,meson-txl-gpio-intc"; - reg = <0x9880 0x10>; - interrupt-controller; - #interrupt-cells = <2>; - amlogic,channel-interrupts = - <64 65 66 67 68 69 70 71>; - status = "okay"; - }; - - wdt_ee: watchdog@98d0 { - compatible = "amlogic, meson-wdt"; - status = "okay"; - default_timeout=<10>; - reset_watchdog_method=<1>;/*0:sysfs,1:kernel*/ - reset_watchdog_time=<2>; - shutdown_timeout=<10>; - firmware_timeout=<6>; - suspend_timeout=<6>; - reg = <0x98d0 0x10>; - clock-names = "xtal"; - clocks = <&xtal>; - }; - - }; /* end of cbus */ - - aobus: bus@c8100000 { - compatible = "simple-bus"; - #address-cells = <1>; - #size-cells = <1>; - reg = <0xc8100000 0x100000>; - ranges = <0x0 0xc8100000 0x100000>; - - cpu_version { - reg=<0x220 0x4>; - }; - - aoclkc: clock-controller@0 { - compatible = "amlogic,txl-aoclkc"; - #clock-cells = <1>; - reg = <0x0 0x1000>; - }; - - uart_AO: serial@4c0 { - compatible = "amlogic, meson-uart"; - reg = <0x4c0 0x18>; - interrupts = <0 193 1>; - status = "okay"; - clocks = <&xtal>; - clock-names = "clk_uart"; - xtal_tick_en = <1>; - fifosize = < 64 >; - pinctrl-names = "default"; - /*pinctrl-0 = <&ao_uart_pins>;*/ - /* 0 not support;1 support */ - support-sysrq = <0>; - }; - - uart_AO_B: serial@04e0 { - compatible = "amlogic, meson-uart"; - reg = <0x04e0 0x18>; - interrupts = <0 197 1>; - status = "disabled"; - clocks = <&xtal>; - clock-names = "clk_uart"; - fifosize = < 64 >; - pinctrl-names = "default"; - pinctrl-0 = <&ao_b_uart_pins>; - }; - - i2c_AO: i2c@0500 { - compatible = "amlogic,meson-txl-i2c"; - status = "disabled"; - reg = <0x0500 0x20>; - interrupts = ; - #address-cells = <1>; - #size-cells = <0>; - clocks = <&clkc CLKID_I2C>; - }; - - pwm_aoab: pwm@0550 { - compatible = "amlogic,txl-ao-pwm"; - reg = <0x0550 0x1c>; - #pwm-cells = <3>; - clocks = <&xtal>, - <&xtal>, - <&xtal>, - <&xtal>; - clock-names = "clkin0", - "clkin1", - "clkin2", - "clkin3"; - status = "disabled"; - }; - - remote:rc@0580 { - compatible = "amlogic, aml_remote"; - dev_name = "meson-remote"; - reg = <0x0580 0x44>, - <0x0480 0x20>; - status = "okay"; - protocol = ; - interrupts = <0 196 1>; - pinctrl-names = "default"; - pinctrl-0 = <&remote_pins>; - map = <&custom_maps>; - max_frame_time = <200>; - }; - }; /* end of aobus*/ - - periphs: periphs@c8834000 { - compatible = "simple-bus"; - reg = <0xc8834000 0x2000>; - #address-cells = <1>; - #size-cells = <1>; - ranges = <0x0 0xc8834000 0x2000>; - - rng { - compatible = "amlogic,meson-rng"; - reg = <0x0 0x4>; - quality = /bits/ 16 <1000>; - }; - };/* end of periphs */ - - hiubus: bus@c883c000 { - compatible = "simple-bus"; - #address-cells = <1>; - #size-cells = <1>; - reg = <0xc883c000 0x2000>; - ranges = <0x0 0xc883c000 0x2000>; - - clkc: clock-controller@0 { - compatible = "amlogic,txl-clkc"; - #clock-cells = <1>; - reg = <0x0 0x3fc>; - }; - };/* end of hiubus*/ - - }; /* end of soc*/ - - custom_maps: custom_maps { - mapnum = <3>; - map0 = <&map_0>; - map1 = <&map_1>; - map2 = <&map_2>; - map_0: map_0{ - mapname = "amlogic-remote-1"; - customcode = <0xfb04>; - release_delay = <80>; - size = <44>; /*keymap size*/ - keymap = ; - }; - - map_1: map_1{ - mapname = "amlogic-remote-2"; - customcode = <0xfe01>; - release_delay = <80>; - size = <53>; - keymap = ; - }; - - map_2: map_2{ - mapname = "amlogic-remote-3"; - customcode = <0xbd02>; - release_delay = <80>; - size = <17>; - keymap = ; - }; - }; - - aocec: aocec@0xc8100000 { - compatible = "amlogic, aocec-txl"; - status = "okay"; - vendor_name = "Amlogic"; /* Max Chars: 8 */ - /* Refer to the following URL at: - * http://standards.ieee.org/develop/regauth/oui/oui.txt - */ - vendor_id = <0x000000>; - product_desc = "TXL"; /* Max Chars: 16 */ - cec_osd_string = "AML_TV"; /* Max Chars: 14 */ - port_num = <3>; - ee_cec; - arc_port_mask = <0x2>; - interrupts = <0 56 1 - 0 199 1>; - interrupt-names = "hdmi_aocecb","hdmi_aocec"; - pinctrl-names = "default","hdmitx_aocecb","cec_pin_sleep"; - pinctrl-0=<&hdmitx_aocec>; - pinctrl-1=<&hdmitx_aocecb>; - pinctrl-2=<&hdmitx_aocec>; - reg = <0xc810023c 0x4 - 0xc8100000 0x200 - 0xda83e000 0x10 - 0xc883c000 0x400>; - reg-names = "ao_exit","ao","hdmirx","hhi"; - }; - - canvas: canvas{ - compatible = "amlogic, meson, canvas"; - dev_name = "amlogic-canvas"; - status = "okay"; - reg = <0xc8838000 0x2000>; - }; - - codec_io: codec_io { - compatible = "amlogic, codec_io"; - status = "okay"; - #address-cells=<1>; - #size-cells=<1>; - ranges; - io_cbus_base{ - reg = <0xC1100000 0x100000>; - }; - io_dos_base{ - reg = <0xc8820000 0x10000>; - }; - io_hiubus_base{ - reg = <0xc883c000 0x2000>; - }; - io_aobus_base{ - reg = <0xc8100000 0x100000>; - }; - io_vcbus_base{ - reg = <0xd0100000 0x40000>; - }; - io_dmc_base{ - reg = <0xc8838000 0x400>; - }; - }; - - vpu { - compatible = "amlogic, vpu-txl"; - dev_name = "vpu"; - status = "okay"; - clocks = <&clkc CLKID_VAPB_MUX>, - <&clkc CLKID_VPU_INTR>, - <&clkc CLKID_VPU_P0_COMP>, - <&clkc CLKID_VPU_P1_COMP>, - <&clkc CLKID_VPU_MUX>; - clock-names = "vapb_clk", - "vpu_intr_gate", - "vpu_clk0", - "vpu_clk1", - "vpu_clk"; - clk_level = <7>; - /* 0: 100.0M 1: 166.7M 2: 200.0M 3: 250.0M */ - /* 4: 333.3M 5: 400.0M 6: 500.0M 7: 666.7M */ - }; - - ge2d { - compatible = "amlogic, ge2d-txl"; - status = "okay"; - interrupts = <0 146 1>; - interrupt-names = "ge2d"; - clocks = <&clkc CLKID_VAPB_MUX>, - <&clkc CLKID_G2D>, - <&clkc CLKID_GE2D_GATE>; - clock-names = "clk_vapb_0", - "clk_ge2d", - "clk_ge2d_gate"; - reg = <0xd0160000 0x10000>; - }; - - meson-amvideom { - compatible = "amlogic, amvideom"; - status = "okay"; - interrupts = <0 3 1>; - interrupt-names = "vsync"; - }; - - mesonstream { - compatible = "amlogic, codec, streambuf"; - status = "okay"; - clocks = <&clkc CLKID_DOS_PARSER - &clkc CLKID_DEMUX - &clkc CLKID_DOS - &clkc CLKID_CLK81 - &clkc CLKID_VDEC_MUX - &clkc CLKID_HCODEC_MUX - &clkc CLKID_HEVC_MUX>; - clock-names = "parser_top", - "demux", - "vdec", - "clk_81", - "clk_vdec_mux", - "clk_hcodec_mux", - "clk_hevc_mux"; - }; - - codec_mm { - compatible = "amlogic, codec, mm"; - status = "okay"; - memory-region = <&codec_mm_cma &codec_mm_reserved>; - }; - - vdec { - compatible = "amlogic, vdec"; - status = "okay"; - interrupts = <0 3 1 - 0 23 1 - 0 32 1 - 0 43 1 - 0 44 1 - 0 45 1>; - interrupt-names = "vsync", - "demux", - "parser", - "mailbox_0", - "mailbox_1", - "mailbox_2"; - }; - - amvenc_avc { - compatible = "amlogic, amvenc_avc"; - status = "okay"; - //memory-region = <&amvenc_avc_reserved>; - //memory-region = <&avc_cma_reserved>; - interrupts = <0 45 1>; - interrupt-names = "mailbox_2"; - }; - - rdma { - compatible = "amlogic, meson, rdma"; - dev_name = "amlogic-rdma"; - status = "okay"; - interrupts = <0 89 1>; - interrupt-names = "rdma"; - }; - - audio_data: audio_data { - compatible = "amlogic, audio_data"; - query_licence_cmd = <0x82000050>; - status = "disabled"; - }; - - efuse: efuse { - compatible = "amlogic, efuse"; - read_cmd = <0x82000030>; - write_cmd = <0x82000031>; - get_max_cmd = <0x82000033>; - key = <&efusekey>; - clocks = <&clkc CLKID_EFUSE>; - clock-names = "efuse_clk"; - status = "disabled"; - }; - - efusekey:efusekey { - keynum = <4>; - key0 = <&key_0>; - key1 = <&key_1>; - key2 = <&key_2>; - key3 = <&key_3>; - key_0:key_0 { - keyname = "mac"; - offset = <0>; - size = <6>; - }; - key_1:key_1 { - keyname = "mac_bt"; - offset = <6>; - size = <6>; - }; - key_2:key_2 { - keyname = "mac_wifi"; - offset = <12>; - size = <6>; - }; - key_3:key_3 { - keyname = "usid"; - offset = <18>; - size = <16>; - }; - }; - - cpu_ver_name { - compatible = "amlogic, cpu-major-id-txl"; - status = "okay"; - }; - - ddr_bandwidth { - compatible = "amlogic, ddr-bandwidth"; - status = "okay"; - reg = <0xc8838000 0x100 - 0xc8837000 0x100>; - interrupts = <0 52 1>; - interrupt-names = "ddr_bandwidth"; - }; - dmc_monitor { - compatible = "amlogic, dmc_monitor"; - status = "okay"; - reg_base = <0xda838400>; - interrupts = <0 51 1>; - }; - - vdac { - compatible = "amlogic, vdac-txl"; - status = "okay"; - }; -}; /* end of / */ - -&gpu{ - /*gpu max freq is 750M*/ - tbl = <&clk285_cfg &clk400_cfg &clk500_cfg &clk666_cfg &clk750_cfg>; -}; - -&pinctrl_aobus { - - pwm_ao_a_ao3_pins: pwm_ao_a_ao3 { - mux { - groups = "pwm_ao_a_ao3"; - function = "pwm_ao_a"; - }; - }; - - pwm_ao_a_ao7_pins: pwm_ao_a_ao7 { - mux { - groups = "pwm_ao_a_ao7"; - function = "pwm_ao_a"; - }; - }; - - pwm_ao_b_ao8_pins: pwm_ao_b_ao8 { - mux { - groups = "pwm_ao_b_ao8"; - function = "pwm_ao_b"; - }; - }; - - pwm_ao_b_ao9_pins: pwm_ao_b_ao9 { - mux { - groups = "pwm_ao_b_ao9"; - function = "pwm_ao_b"; - }; - }; - - remote_pins:remote_pin { - mux { - groups = "remote_in"; - function = "ir_in"; - }; - - }; - - sd_to_ao_uart_clr_pins:sd_to_ao_uart_clr_pins { - mux { - groups = "GPIOAO_0", - "GPIOAO_1"; - function = "gpio_aobus"; - }; - }; - - sd_to_ao_uart_pins:sd_to_ao_uart_pins { - mux { - groups = "uart_tx_ao_a", - "uart_rx_ao_a"; - function = "uart_ao_a"; - bias-pull-up; - input-enable; - }; - }; - - i2c_AO_pins:i2c_AO { - mux { - groups = "i2c_sck_ao", - "i2c_sda_ao"; - function = "i2c_ao"; - }; - }; - - ao_uart_pins:ao_uart { - mux { - groups = "uart_tx_ao_a", - "uart_rx_ao_a"; - function = "uart_ao_a"; - }; - }; - - ao_b_uart_pins:ao_b_uart { - mux { - groups = "uart_tx_ao_b_ao4", - "uart_rx_ao_b_ao5"; - function = "uart_ao_b"; - }; - }; - - hdmitx_aocec: ao_cec { - mux { - groups = "ao_cec"; - function = "ao_cec"; - }; - }; - - hdmitx_aocecb: ao_cecb { - mux { - groups = "ee_cec"; - function = "ee_cec"; - }; - }; -}; - -&pinctrl_periphs { - - pwm_a_z5_pins: pwm_a_z5 { - mux { - groups = "pwm_a_z"; - function = "pwm_a"; - }; - }; - - pwm_a_dv2_pins: pwm_a_dv2 { - mux { - groups = "pwm_a_dv"; - function = "pwm_a"; - }; - }; - - pwm_b_z6_pins: pwm_b_z6 { - mux { - groups = "pwm_b_z"; - function = "pwm_b"; - }; - }; - - pwm_b_dv3_pins: pwm_b_dv3 { - mux { - groups = "pwm_b_dv"; - function = "pwm_b"; - }; - }; - - pwm_c_z7_pins: pwm_c_z7 { - mux { - groups = "pwm_c"; - function = "pwm_c"; - }; - }; - - pwm_d_z4_pins: pwm_d_z4 { - mux { - groups = "pwm_d_z4"; - function = "pwm_d"; - }; - }; - - pwm_d_z19_pins: pwm_d_z19 { - mux { - groups = "pwm_d_z19"; - function = "pwm_d"; - }; - }; - - pwm_e_h4_pins: pwm_e_h4 { - mux { - groups = "pwm_e_h4"; - function = "pwm_e"; - }; - }; - - pwm_e_h8_pins: pwm_e_h8 { - mux { - groups = "pwm_e_h8"; - function = "pwm_e"; - }; - }; - - pwm_f_h9_pins: pwm_f_h9 { - mux { - groups = "pwm_f_h"; - function = "pwm_f"; - }; - }; - - pwm_f_clk_pins: pwm_f_clk { - mux { - groups = "pwm_f_clk"; - function = "pwm_f"; - }; - }; - - pwm_vs_dv2_pins: pwm_vs_dv2 { - mux { - groups = "pwm_vs_dv2"; - function = "pwm_vs"; - }; - }; - - pwm_vs_dv3_pins: pwm_vs_dv3 { - mux { - groups = "pwm_vs_dv3"; - function = "pwm_vs"; - }; - }; - - pwm_vs_z4_pins: pwm_vs_z4 { - mux { - groups = "pwm_vs_z4"; - function = "pwm_vs"; - }; - }; - - pwm_vs_z6_pins: pwm_vs_z6 { - mux { - groups = "pwm_vs_z6"; - function = "pwm_vs"; - }; - }; - - pwm_vs_z7_pins: pwm_vs_z7 { - mux { - groups = "pwm_vs_z7"; - function = "pwm_vs"; - }; - }; - - pwm_vs_z19_pins: pwm_vs_z19 { - mux { - groups = "pwm_vs_z19"; - function = "pwm_vs"; - }; - }; - - ao_to_sd_uart_clr_pins:ao_to_sd_uart_clr_pins { - mux { - groups = "sdcard_d2", - "sdcard_d3"; - function = "sdcard"; - input-enable; - bias-pull-up; - }; - }; - - sd_1bit_pins:sd_1bit_pins { - mux { - groups = "sdcard_d0", - "sdcard_cmd", - "sdcard_clk"; - function = "sdcard"; - input-enable; - bias-pull-up; - }; - }; - - ao_to_sd_uart_pins:ao_to_sd_uart_pins { - mux { - groups = "uart_tx_ao_a_c4", - "uart_rx_ao_a_c5"; - function = "uart_ao_a_ee"; - bias-pull-up; - input-enable; - }; - }; - - emmc_clk_cmd_pins:emmc_clk_cmd_pins { - mux { - groups = "emmc_cmd", - "emmc_clk"; - function = "emmc"; - input-enable; - bias-pull-up; - }; - }; - - - emmc_conf_pull_up:emmc_conf_pull_up { - mux { - groups = "emmc_nand_d07", - "emmc_clk", - "emmc_cmd"; - function = "emmc"; - input-enable; - bias-pull-up; - }; - }; - - emmc_conf_pull_done:emmc_conf_pull_done { - mux { - groups = "emmc_ds"; - function = "emmc"; - input-enable; - bias-pull-down; - }; - }; - - spifc_cs_pin:spifc_cs_pin { - mux { - groups = "nor_cs"; - function = "nor"; - bias-pull-up; - }; - }; - - spifc_pulldown: spifc_pulldown { - mux { - groups = "nor_d", - "nor_q", - "nor_c"; - function = "nor"; - bias-pull-down; - }; - }; - - spifc_pullup: spifc_pullup { - mux { - groups = "nor_cs"; - function = "nor"; - bias-pull-up; - }; - }; - - spifc_all_pins: spifc_all_pins { - mux { - groups = "nor_d", - "nor_q", - "nor_c"; - function = "nor"; - input-enable; - bias-pull-down; - }; - }; - - sd_clk_cmd_pins:sd_clk_cmd_pins{ - mux { - groups = "sdcard_cmd", - "sdcard_clk"; - function = "sdcard"; - input-enable; - bias-pull-up; - }; - }; - - sd_all_pins:sd_all_pins{ - mux { - groups = "sdcard_d0", - "sdcard_d1", - "sdcard_d2", - "sdcard_d3", - "sdcard_cmd", - "sdcard_clk"; - function = "sdcard"; - input-enable; - bias-pull-up; - }; - }; - - hdmirx_a_mux:hdmirx_a_mux { - mux { - groups = "hdmirx_hpd_a", "hdmirx_det_a", - "hdmirx_sda_a", "hdmirx_sck_a"; - function = "hdmirx_a"; - }; - }; - - hdmirx_b_mux:hdmirx_b_mux { - mux { - groups = "hdmirx_hpd_b", "hdmirx_det_b", - "hdmirx_sda_b", "hdmirx_sck_b"; - function = "hdmirx_b"; - }; - }; - - hdmirx_c_mux:hdmirx_c_mux { - mux { - groups = "hdmirx_hpd_c", "hdmirx_det_c", - "hdmirx_sda_c", "hdmirx_sck_c"; - function = "hdmirx_c"; - }; - }; - - hdmirx_d_mux:hdmirx_d_mux { - mux { - groups = "hdmirx_hpd_d", "hdmirx_det_d", - "hdmirx_sda_d", "hdmirx_sck_d"; - function = "hdmirx_d"; - }; - }; - - i2c0_z_pins:i2c0_z { - mux { - groups = "i2c0_sda", - "i2c0_sck"; - function = "i2c0"; - }; - }; - - i2c1_dv_pins:i2c1_z { - mux { - groups = "i2c1_sda", - "i2c1_sck"; - function = "i2c1"; - }; - }; - - i2c2_h_pins:i2c2_h { - mux { - groups = "i2c2_sda", - "i2c2_sck"; - function = "i2c2"; - }; - }; - - i2c3_z_pins:i2c3_z { - mux { - groups = "i2c3_sda", - "i2c3_sck"; - function = "i2c3"; - }; - }; - - a_uart_pins:a_uart { - mux { - groups = "uart_tx_a", - "uart_rx_a", - "uart_cts_a", - "uart_rts_a"; - function = "uart_a"; - }; - }; - - b_uart_pins:b_uart { - mux { - groups = "uart_tx_b", - "uart_rx_b"; - function = "uart_b"; - }; - }; - - c_uart_pins:c_uart { - mux { - groups = "uart_tx_c", - "uart_rx_c"; - function = "uart_c"; - }; - }; - - lcd_vbyone_pins: lcd_vbyone_pin { - mux { - groups = "vx1_lockn","vx1_htpdn"; - function = "vbyone"; - }; - }; - - atvdemod_agc_pins: atvdemod_agc_pins { - mux { - groups = "atv_if_agc"; - function = "atv"; - }; - }; - - dtvdemod_agc_pins: dtvdemod_agc_pins { - mux { - groups = "dtv_if_agc"; - function = "dtv"; - }; - }; - - spicc_pins: spicc { - mux { - groups = "spi_miso_a", - "spi_mosi_a", - "spi_clk_a"; - function = "spi_a"; - }; - }; -}; diff --git a/arch/arm/boot/dts/amlogic/mesontxlx.dtsi b/arch/arm/boot/dts/amlogic/mesontxlx.dtsi index 6db6187ca2fa..3c862a26570d 100644 --- a/arch/arm/boot/dts/amlogic/mesontxlx.dtsi +++ b/arch/arm/boot/dts/amlogic/mesontxlx.dtsi @@ -79,7 +79,7 @@ CPU3:cpu@3 { device_type = "cpu"; compatible = "arm,cortex-a53","arm,armv8"; - reg = <0x0 0x3>; + reg = <0x3>; enable-method = "psci"; clocks = <&scpi_dvfs 0>; clock-names = "cpu-cluster.0"; @@ -134,19 +134,14 @@ arm_pmu { compatible = "arm,cortex-a15-pmu"; - interrupts = <0 137 4>; - reg = <0xff634400 0x1000>; - - /* addr = base + offset << 2 */ - sys_cpu_status0_offset = <0xa0>; - - sys_cpu_status0_pmuirq_mask = <0xf>; - + /* clusterb-enabled; */ + interrupts = ; + reg = <0xff634680 0x4>; + cpumasks = <0xf>; /* default 10ms */ - relax_timer_ns = <10000000>; - + relax-timer-ns = <10000000>; /* default 10000us */ - max_wait_cnt = <10000>; + max-wait-cnt = <10000>; }; gic: interrupt-controller@2c001000 { @@ -164,13 +159,12 @@ method = "smc"; }; - meson_suspend:pm { + aml_pm { compatible = "amlogic, pm"; - device_name = "aml_pm"; - /*gxbaby-suspend;*/ status = "okay"; - reg = <0xff8000a8 0x4>, - <0xff80023c 0x4>; + device_name = "aml_pm"; + debug_reg = <0xff8000a8>; + exit_reg = <0xff80023c>; }; secmon { @@ -288,11 +282,18 @@ ram-dump { compatible = "amlogic, ram_dump"; status = "okay"; + reg = <0xFF6345E0 4>; + reg-names = "PREG_STICKY_REG8"; + store_device = "data"; }; - amlogic-jtag { + jtag { compatible = "amlogic, jtag"; status = "okay"; + select = "disable"; /* disable/apao/apee */ + pinctrl-names="jtag_apao_pins", "jtag_apee_pins"; + pinctrl-0=<&jtag_apao_pins>; + pinctrl-1=<&jtag_apee_pins>; }; vpu { @@ -839,12 +840,12 @@ status = "disabled"; }; - meson-irblaster { - compatible = "amlogic, am_irblaster"; - dev_name = "meson-irblaster"; - status = "disable"; - pinctrl-names = "default"; - pinctrl-0 = <&irblaster_pins>; + irblaster: meson-irblaster@c0 { + compatible = "amlogic, aml_irblaster"; + reg = <0xc0 0xc>, + <0x40 0x4>; + #irblaster-cells = <2>; + status = "disabled"; }; @@ -943,6 +944,13 @@ compatible = "amlogic, vdac-txlx"; status = "okay"; }; + + defendkey: defendkey { + compatible = "amlogic, defendkey"; + reg = <0xff634500 0x4>; /*RNG_USR_DATA*/ + mem_size = <0x0 0x100000>; + status = "okay"; + }; }; /* end of / */ &pinctrl_aobus { @@ -1022,6 +1030,13 @@ }; }; + irblaster_pins1:irblaster_pin1 { + mux { + groups = "remote_out_ao6"; + function = "ir_out"; + }; + }; + pwmleds_pins:pwmleds { mux { @@ -1045,6 +1060,16 @@ function = "i2c_ao"; }; }; + + jtag_apao_pins:jtag_apao_pin { + mux { + groups = "GPIOAO_3", + "GPIOAO_4", + "GPIOAO_5", + "GPIOAO_7"; + function = "gpio_aobus"; + }; + }; }; &pinctrl_periphs { @@ -1385,6 +1410,16 @@ function = "pwm_d"; }; }; + + jtag_apee_pins:jtag_apee_pin { + mux { + groups = "GPIOC_0", + "GPIOC_1", + "GPIOC_2", + "GPIOC_3"; + function = "gpio_periphs"; + }; + }; }; &gpu{ diff --git a/arch/arm/boot/dts/amlogic/mesontxlx_r311-panel.dtsi b/arch/arm/boot/dts/amlogic/mesontxlx_r311-panel.dtsi index 73df62601014..ea0e28527e84 100644 --- a/arch/arm/boot/dts/amlogic/mesontxlx_r311-panel.dtsi +++ b/arch/arm/boot/dts/amlogic/mesontxlx_r311-panel.dtsi @@ -678,7 +678,7 @@ }; backlight_4{ index = <4>; - bl_name = "ldim_iw7027"; + bl_name = "ldim_global"; bl_level_default_uboot_kernel = <100 100>; bl_level_attr = <255 10 /*max, min*/ 128 128>; /*mid, mid_mapping*/ @@ -687,15 +687,15 @@ 1 0 /*on_value, off_value*/ 200 200>; /*on_delay(ms), off_delay(ms)*/ bl_ldim_region_row_col = <1 10>; - bl_ldim_mode = <1>; /*1=single_side - * (top, bottom, left or right), - *2=uniform(top/bottom, left/right) + bl_ldim_mode = <1>; /*0=left/right side + *1=top/bottom side + *2=direct */ - ldim_dev_index = <2>; + ldim_dev_index = <1>; }; backlight_5{ index = <5>; - bl_name = "ldim_global"; + bl_name = "ldim_iw7027"; bl_level_default_uboot_kernel = <100 100>; bl_level_attr = <255 10 /*max, min*/ 128 128>; /*mid, mid_mapping*/ @@ -704,11 +704,11 @@ 1 0 /*on_value, off_value*/ 200 200>; /* on_delay(ms), off_delay(ms)*/ bl_ldim_region_row_col = <1 1>; - bl_ldim_mode = <1>; /*1=single_side - * (top, bottom, left or right), - *2=uniform(top/bottom, left/right) + bl_ldim_mode = <1>; /*0=left/right side + *1=top/bottom side + *2=direct */ - ldim_dev_index = <1>; + ldim_dev_index = <2>; }; }; @@ -728,54 +728,63 @@ status = "okay"; pinctrl-names = "ldim_pwm", "ldim_pwm_vs", - "ldim_pwm_off"; + "ldim_pwm_combo", + "ldim_pwm_vs_combo", + "ldim_pwm_off", + "ldim_pwm_combo_off"; pinctrl-0 = <&bl_pwm_on_pins>; pinctrl-1 = <&bl_pwm_vs_on_pins>; - pinctrl-2 = <&bl_pwm_off_pins>; + pinctrl-2 = <&bl_pwm_on_pins &bl_pwm_combo_1_on_pins>; + pinctrl-3 = <&bl_pwm_vs_on_pins &bl_pwm_combo_1_on_pins>; + pinctrl-4 = <&bl_pwm_off_pins>; + pinctrl-5 = <&bl_pwm_combo_off_pins>; pinctrl_version = <1>; /* for uboot */ ldim_pwm_config = <&bl_pwm_conf>; /* pwm port: PWM_A, PWM_B, PWM_C, PWM_D, PWM_E, PWM_F, PWM_VS*/ ldim_dev-gpios = <&gpio GPIOZ_12 GPIO_ACTIVE_HIGH &gpio GPIOZ_6 GPIO_ACTIVE_HIGH - &gpio GPIOZ_7 GPIO_ACTIVE_HIGH>; - ldim_dev_gpio_names = "GPIOZ_12","GPIOZ_6","GPIOZ_7"; + &gpio GPIOZ_7 GPIO_ACTIVE_HIGH + &gpio GPIOZ_4 GPIO_ACTIVE_HIGH>; + ldim_dev_gpio_names = "GPIOZ_12","GPIOZ_6","GPIOZ_7","GPIOZ_4"; ldim_dev_0 { index = <0>; type = <0>; /*0=normal, 1=spi, 2=i2c*/ ldim_dev_name = "ob3350"; - ldim_pwm_pinmux_sel = "ldim_pwm"; ldim_pwm_port = "PWM_B"; ldim_pwm_attr = <0 /* pol */ 200 /*freq(pwm:Hz, pwm_vs:multiple of vs)*/ - 50>;/*duty(%)*/ - dim_max_min = <100 20>; /*dim_max, dim_min*/ + 50>;/*default duty(%)*/ en_gpio_on_off = <0 /*ldim_dev-gpios index*/ 1 0>; /*on_level, off_level*/ + dim_max_min = <100 20>; /*dim_max, dim_min*/ }; ldim_dev_1 { index = <1>; type = <0>; /*0=normal, 1=spi, 2=i2c*/ ldim_dev_name = "global"; - ldim_pwm_pinmux_sel = "ldim_pwm"; ldim_pwm_port = "PWM_B"; ldim_pwm_attr = <1 /* pol */ 180 /*freq(pwm:Hz, pwm_vs:multiple of vs)*/ - 50>;/*duty(%)*/ - dim_max_min = <100 20>; /*dim_max, dim_min*/ - en_gpio_on_off = <2 /*ldim_dev-gpios index*/ + 50>;/*default duty(%)*/ + analog_pwm_port = "PWM_C"; + analog_pwm_attr = <1 /*pol(0=negative, 1=positvie)*/ + 18000 /*freq(pwm:Hz)*/ + 100 25 /*duty_max(%), duty_min(%)*/ + 80>; /*default duty(%)*/ + en_gpio_on_off = <3 /*ldim_dev-gpios index*/ 1 0>; /*on_level, off_level*/ + dim_max_min = <100 20>; /*dim_max, dim_min*/ }; ldim_dev_2 { index = <2>; type = <1>; /* 0=normal,1=spi,2=i2c */ ldim_dev_name = "iw7027"; - ldim_pwm_pinmux_sel = "ldim_pwm_vs"; ldim_pwm_port = "PWM_VS"; ldim_pwm_attr = <1 /* pol */ 2 /*freq(pwm:Hz, pwm_vs:multiple of vs)*/ - 50>;/*duty(%)*/ + 50>;/*default duty(%)*/ spi_bus_num = <0>; spi_chip_select = <0>; spi_max_frequency = <1000000>; /* unit: hz */ diff --git a/arch/arm/boot/dts/amlogic/partition_mbox_ab.dtsi b/arch/arm/boot/dts/amlogic/partition_mbox_ab.dtsi index a78cd67fdc23..d917b8fa3f70 100644 --- a/arch/arm/boot/dts/amlogic/partition_mbox_ab.dtsi +++ b/arch/arm/boot/dts/amlogic/partition_mbox_ab.dtsi @@ -88,13 +88,13 @@ vendor_a:vendor_a { pname = "vendor_a"; - size = <0x0 0x10000000>; + size = <0x0 0x14000000>; mask = <1>; }; vendor_b:vendor_b { pname = "vendor_b"; - size = <0x0 0x10000000>; + size = <0x0 0x14000000>; mask = <1>; }; odm_a:odm_a diff --git a/arch/arm/boot/dts/amlogic/partition_mbox_ab_P_32.dtsi b/arch/arm/boot/dts/amlogic/partition_mbox_ab_P_32.dtsi index d210d928d4a1..3047ed5c0dca 100644 --- a/arch/arm/boot/dts/amlogic/partition_mbox_ab_P_32.dtsi +++ b/arch/arm/boot/dts/amlogic/partition_mbox_ab_P_32.dtsi @@ -120,13 +120,13 @@ vendor_a:vendor_a { pname = "vendor_a"; - size = <0x0 0x10000000>; + size = <0x0 0x14000000>; mask = <1>; }; vendor_b:vendor_b { pname = "vendor_b"; - size = <0x0 0x10000000>; + size = <0x0 0x14000000>; mask = <1>; }; odm_a:odm_a diff --git a/arch/arm/boot/dts/amlogic/partition_mbox_normal_P_32.dtsi b/arch/arm/boot/dts/amlogic/partition_mbox_normal_P_32.dtsi index f2c574203d53..6cbedc415e4f 100644 --- a/arch/arm/boot/dts/amlogic/partition_mbox_normal_P_32.dtsi +++ b/arch/arm/boot/dts/amlogic/partition_mbox_normal_P_32.dtsi @@ -90,7 +90,7 @@ vendor:vendor { pname = "vendor"; - size = <0x0 0x10000000>; + size = <0x0 0x14000000>; mask = <1>; }; odm:odm diff --git a/arch/arm/boot/dts/amlogic/partition_mbox_normal_P_64.dtsi b/arch/arm/boot/dts/amlogic/partition_mbox_normal_P_64.dtsi index 2b8e7304cac6..13e510e4e931 100644 --- a/arch/arm/boot/dts/amlogic/partition_mbox_normal_P_64.dtsi +++ b/arch/arm/boot/dts/amlogic/partition_mbox_normal_P_64.dtsi @@ -90,7 +90,7 @@ vendor:vendor { pname = "vendor"; - size = <0x0 0x10000000>; + size = <0x0 0x14000000>; mask = <1>; }; odm:odm diff --git a/arch/arm/boot/dts/amlogic/partition_mbox_p241_P.dtsi b/arch/arm/boot/dts/amlogic/partition_mbox_p241_P.dtsi index aeb1dee501f9..3b0796a9cf21 100644 --- a/arch/arm/boot/dts/amlogic/partition_mbox_p241_P.dtsi +++ b/arch/arm/boot/dts/amlogic/partition_mbox_p241_P.dtsi @@ -90,7 +90,7 @@ vendor:vendor { pname = "vendor"; - size = <0x0 0x10000000>; + size = <0x0 0x14000000>; mask = <1>; }; odm:odm diff --git a/arch/arm/boot/dts/amlogic/sm1_pxp.dts b/arch/arm/boot/dts/amlogic/sm1_pxp.dts new file mode 100644 index 000000000000..a4c02804c226 --- /dev/null +++ b/arch/arm/boot/dts/amlogic/sm1_pxp.dts @@ -0,0 +1,741 @@ +/* + * arch/arm/boot/dts/amlogic/sm1_pxp.dts + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +/dts-v1/; + +#include "mesonsm1.dtsi" + +/ { + model = "Amlogic"; + compatible = "amlogic, g12a"; + interrupt-parent = <&gic>; + #address-cells = <1>; + #size-cells = <1>; + + aliases { + serial0 = &uart_AO; + i2c0 = &i2c0; + i2c1 = &i2c1; + i2c2 = &i2c2; + i2c3 = &i2c3; + i2c4 = &i2c_AO; + }; + + memory@00000000 { + device_type = "memory"; + linux,usable-memory = <0x0 0x40000000>; + }; + + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + /* global autoconfigured region for contiguous allocations */ + secmon_reserved:linux,secmon { + compatible = "shared-dma-pool"; + reusable; + size = <0x400000>; + alignment = <0x400000>; + alloc-ranges = <0x05000000 0x400000>; + }; + + secos_reserved:linux,secos { + status = "disable"; + compatible = "amlogic, aml_secos_memory"; + reg = <0x05300000 0x2000000>; + no-map; + }; + logo_reserved:linux,meson-fb { + compatible = "shared-dma-pool"; + reusable; + size = <0x800000>; + alignment = <0x400000>; + alloc-ranges = <0x3f800000 0x800000>; + }; + ion_cma_reserved:linux,ion-dev { + compatible = "shared-dma-pool"; + reusable; + size = <0x8000000>; + alignment = <0x400000>; + }; + + //di_reserved:linux,di { + //compatible = "amlogic, di-mem"; + /* buffer_size = 3621952(yuv422 8bit) */ + /* 4179008(yuv422 10bit full pack mode) */ + /** 10x3621952=34.6M(0x23) support 8bit **/ + /** 10x4736064=45.2M(0x2e) support 12bit **/ + /** 10x4179008=40M(0x28) support 10bit **/ + //size = <0x2800000>; + //no-map; + //}; + /*di CMA pool */ + di_cma_reserved:linux,di_cma { + compatible = "shared-dma-pool"; + reusable; + /* buffer_size = 3621952(yuv422 8bit) + * | 4736064(yuv422 10bit) + * | 4074560(yuv422 10bit full pack mode) + * 10x3621952=34.6M(0x23) support 8bit + * 10x4736064=45.2M(0x2e) support 12bit + * 10x4074560=40M(0x28) support 10bit + */ + size = <0x02800000>; + alignment = <0x400000>; + }; + codec_mm_cma:linux,codec_mm_cma { + compatible = "shared-dma-pool"; + reusable; + /* ion_codec_mm max can alloc size 80M*/ + size = <0x13400000>; + alignment = <0x400000>; + linux,contiguous-region; + }; + /* codec shared reserved */ + codec_mm_reserved:linux,codec_mm_reserved { + compatible = "amlogic, codec-mm-reserved"; + size = <0x0>; + alignment = <0x100000>; + //no-map; + }; + /* vdin0 CMA pool */ + vdin0_cma_reserved:linux,vdin0_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16+4 M */ + size = <0x04000000>; + alignment = <0x400000>; + }; + /* vdin1 CMA pool */ + vdin1_cma_reserved:linux,vdin1_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16 M */ + size = <0x04000000>; + alignment = <0x400000>; + }; + }; + + cvbsout { + compatible = "amlogic, cvbsout-sm1"; + dev_name = "cvbsout"; + status = "okay"; + clocks = <&clkc CLKID_VCLK2_ENCI + &clkc CLKID_VCLK2_VENCI0 + &clkc CLKID_VCLK2_VENCI1 + &clkc CLKID_DAC_CLK>; + clock-names = "venci_top_gate", + "venci_0_gate", + "venci_1_gate", + "vdac_clk_gate"; + clk_path = <0>; + + /* performance: reg_address, reg_value */ + /* sm1 */ + performance = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x8080 + 0x1b05 0xfd + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + performance_sarft = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x0 + 0x1b05 0x9 + 0x1c59 0xfc48 + 0xffff 0x0>; /* ending flag */ + performance_revB_telecom = <0x1bf0 0x9 + 0x1b56 0x546 + 0x1b12 0x8080 + 0x1b05 0x9 + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + }; + + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + + codec_mm { + compatible = "amlogic, codec, mm"; + memory-region = <&codec_mm_cma &codec_mm_reserved>; + dev_name = "codec_mm"; + status = "okay"; + }; + + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + + deinterlace { + compatible = "amlogic, deinterlace"; + status = "okay"; + /* 0:use reserved; 1:use cma; 2:use cma as reserved */ + flag_cma = <1>; + //memory-region = <&di_reserved>; + memory-region = <&di_cma_reserved>; + interrupts = <0 46 1 + 0 40 1>; + interrupt-names = "pre_irq", "post_irq"; + clocks = <&clkc CLKID_VPU_CLKB_TMP_COMP>, + <&clkc CLKID_VPU_CLKB_COMP>; + clock-names = "vpu_clkb_tmp_composite", + "vpu_clkb_composite"; + clock-range = <334 667>; + /* buffer-size = <3621952>;(yuv422 8bit) */ + buffer-size = <4074560>;/*yuv422 fullpack*/ + /* reserve-iomap = "true"; */ + /* if enable nr10bit, set nr10bit-support to 1 */ + post-wr-support = <1>; + nr10bit-support = <1>; + nrds-enable = <1>; + pps-enable = <1>; + }; + + efusekey:efusekey{ + keynum = <4>; + key0 = <&key_0>; + key1 = <&key_1>; + key2 = <&key_2>; + key3 = <&key_3>; + key_0:key_0{ + keyname = "mac"; + offset = <0>; + size = <6>; + }; + key_1:key_1{ + keyname = "mac_bt"; + offset = <6>; + size = <6>; + }; + key_2:key_2{ + keyname = "mac_wifi"; + offset = <12>; + size = <6>; + }; + key_3:key_3{ + keyname = "usid"; + offset = <18>; + size = <16>; + }; + };//End efusekey + + amlvecm { + compatible = "amlogic, vecm"; + dev_name = "aml_vecm"; + status = "okay"; + gamma_en = <0>;/*1:enabel ;0:disable*/ + wb_en = <0>;/*1:enabel ;0:disable*/ + cm_en = <0>;/*1:enabel ;0:disable*/ + /*0: 709/601 1: bt2020*/ + tx_op_color_primary = <0>; + }; + amdolby_vision { + compatible = "amlogic, dolby_vision_sm1"; + dev_name = "aml_amdolby_vision_driver"; + status = "okay"; + tv_mode = <0>;/*1:enabel ;0:disable*/ + }; + + /* Audio Related start */ + + pdm_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, pdm_dummy_codec"; + status = "okay"; + }; + dummy_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, aml_dummy_codec"; + status = "okay"; + }; + amlogic_codec:t9015{ + #sound-dai-cells = <0>; + compatible = "amlogic, aml_codec_T9015"; + reg = <0xFF632000 0x2000>; + is_auge_used = <1>; /* meson or auge chipset used */ + tdmout_index = <0>; + status = "disabled"; + }; + auge_sound { + compatible = "amlogic, g12a-sound-card"; + aml-audio-card,name = "AML-AUGESOUND"; + + aml-audio-card,dai-link@0 { + format = "dsp_a"; + mclk-fs = <512>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdma>; + frame-master = <&tdma>; + /* slave mode */ + /* + * bitclock-master = <&tdmacodec>; + * frame-master = <&tdmacodec>; + */ + tdmacpu: cpu { + sound-dai = <&tdma>; + dai-tdm-slot-tx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-rx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-num = <8>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <24576000>; + }; + tdmacodec: codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@1 { + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdmb>; + frame-master = <&tdmb>; + /* slave mode */ + //bitclock-master = <&tdmbcodec>; + //frame-master = <&tdmbcodec>; + cpu { + sound-dai = <&tdmb>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmbcodec: codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@2 { + format = "i2s"; + mclk-fs = <256>; + continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdmc>; + frame-master = <&tdmc>; + /* slave mode */ + //bitclock-master = <&tdmccodec>; + //frame-master = <&tdmccodec>; + cpu { + sound-dai = <&tdmc>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmccodec: codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@3 { + mclk-fs = <64>; + cpu { + sound-dai = <&pdm>; + }; + codec { + sound-dai = <&pdm_codec>; + }; + }; + + aml-audio-card,dai-link@4 { + mclk-fs = <128>; + cpu { + sound-dai = <&spdifa>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + aml-audio-card,dai-link@5 { + mclk-fs = <128>; + cpu { + sound-dai = <&spdifb>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + }; + audiolocker: locker { + compatible = "amlogic, audiolocker"; + clocks = <&clkaudio CLKID_AUDIO_LOCKER_OUT + &clkaudio CLKID_AUDIO_LOCKER_IN + &clkaudio CLKID_AUDIO_MCLK_D + &clkaudio CLKID_AUDIO_MCLK_E + &clkc CLKID_MPLL1 + &clkc CLKID_MPLL2>; + clock-names = "lock_out", "lock_in", "out_src", + "in_src", "out_calc", "in_ref"; + interrupts = ; + interrupt-names = "irq"; + frequency = <49000000>; /* pll */ + dividor = <49>; /* locker's parent */ + status = "disabled"; + }; + /* Audio Related end */ + + cpu_opp_table0: cpu_opp_table0 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <730000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <730000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <730000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <750000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <770000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <780000>; + }; + opp06 { + opp-hz = /bits/ 64 <1404000000>; + opp-microvolt = <790000>; + }; + opp07 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <800000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <810000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <850000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <900000>; + }; + opp11 { + opp-hz = /bits/ 64 <1908000000>; + opp-microvolt = <950000>; + }; + }; + + cpufreq-meson { + compatible = "amlogic, cpufreq-meson"; + pinctrl-names = "default"; + pinctrl-0 = <&pwm_ao_d_pins3>; + status = "okay"; + }; + + +}; /* end of / */ + +&meson_fb { + status = "okay"; + display_size_default = <1920 1080 1920 2160 32>; + mem_size = <0x00800000 0x1980000 0x100000 0x100000 0x800000>; + logo_addr = "0x7f800000"; + mem_alloc = <1>; + pxp_mode = <1>; /** 0:normal mode 1:pxp mode */ +}; + +&pwm_AO_cd { + status = "okay"; + }; + +&audiobus { + tdma: tdm@0 { + compatible = "amlogic, sm1-snd-tdma"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <1 0>; + dai-tdm-lane-slot-mask-out = <0 1>; + dai-tdm-clk-sel = <0>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_A + &clkc CLKID_MPLL0>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmout_a &tdmin_a>; + + status = "okay"; + }; + + tdmb: tdm@1 { + compatible = "amlogic, sm1-snd-tdmb"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <1 1 1 1>; + dai-tdm-clk-sel = <1>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_B + &clkc CLKID_MPLL1>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmb_mclk /*&tdmout_b &tdmin_b*/>; + }; + + tdmc: tdm@2 { + compatible = "amlogic, sm1-snd-tdmc"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 1 0 0>; + #dai-tdm-lane-slot-mask-out = <1 0 1 1>; + #dai-tdm-lane-oe-slot-mask-in = <0 0 0 0>; + dai-tdm-lane-oe-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <2>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmc_mclk &tdmout_c &tdmin_c>; + + status = "okay"; + }; + + spdifa: spdif@0 { + compatible = "amlogic, sm1-snd-spdif-a"; + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 + &clkc CLKID_FCLK_DIV4 + &clkaudio CLKID_AUDIO_GATE_SPDIFIN + &clkaudio CLKID_AUDIO_GATE_SPDIFOUT_A + &clkaudio CLKID_AUDIO_SPDIFIN + &clkaudio CLKID_AUDIO_SPDIFOUT_A>; + clock-names = "sysclk", "fixed_clk", "gate_spdifin", + "gate_spdifout", "clk_spdifin", "clk_spdifout"; + interrupts = + ; + + interrupt-names = "irq_spdifin"; + pinctrl-names = "spdif_pins"; + pinctrl-0 = <&spdifout &spdifin>; + + status = "okay"; + }; + spdifb: spdif@1 { + compatible = "amlogic, sm1-snd-spdif-b"; + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 /*CLKID_HIFI_PLL*/ + &clkaudio CLKID_AUDIO_GATE_SPDIFOUT_B + &clkaudio CLKID_AUDIO_SPDIFOUT_B>; + clock-names = "sysclk", + "gate_spdifout", "clk_spdifout"; + + status = "okay"; + }; + pdm: pdm { + compatible = "amlogic, sm1-snd-pdm"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_PDM + &clkc CLKID_FCLK_DIV3 + &clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_PDMIN0 + &clkaudio CLKID_AUDIO_PDMIN1>; + clock-names = "gate", + "sysclk_srcpll", + "dclk_srcpll", + "pdm_dclk", + "pdm_sysclk"; + + pinctrl-names = "pdm_pins"; + pinctrl-0 = <&pdmin>; + + /* mode 0~4, defalut:1 */ + filter_mode = <1>; + + status = "okay"; + }; +}; /* end of audiobus */ + +&pinctrl_periphs { + tdmout_a: tdmout_a { + mux { /* GPIOX_11, GPIOX_10, GPIOX_8 */ + groups = "tdma_sclk", + "tdma_fs", + "tdma_dout1"; + function = "tdma_out"; + }; + }; + + tdmin_a: tdmin_a { + mux { /* GPIOX_9 */ + groups = "tdma_din0"; + function = "tdma_in"; + }; + }; + + tdmb_mclk: tdmb_mclk { + mux { + groups = "mclk0_a"; + function = "mclk0"; + }; + }; + + tdmc_mclk: tdmc_mclk { + mux { /* GPIOZ_8 */ + groups = "mclk1_z"; + function = "mclk1"; + }; + }; + + tdmout_c:tdmout_c { + mux { /* gpioz_7, gpioz_6, GPIOZ_2, GPIOZ_4, GPIOZ_5*/ + groups = "tdmc_sclk_z", + "tdmc_fs_z", + "tdmc_dout0_z" + /*,"tdmc_dout2_z", + *"tdmc_dout3_z" + */; + function = "tdmc_out"; + }; + }; + + tdmin_c:tdmin_c { + mux { /* GPIOZ_3 */ + groups = "tdmc_din1_z"; + function = "tdmc_in"; + }; + }; + + spdifin: spdifin { + mux {/* gpioa_10 */ + groups = "spdif_in_a10"; + function = "spdif_in"; + }; + }; + + spdifout: spdifout { + mux {/* gpioa_11 */ + groups = "spdif_out_a11"; + function = "spdif_out"; + }; + }; + + spdifout_b: spdifout_b { + mux { /* gpioa_13 */ + groups = "spdif_out_a13"; + function = "spdif_out"; + }; + }; + + pdmin: pdmin { + mux { /* gpioa_5, gpioa_6, gpioa_7, gpioa_8, gpioa_9*/ + groups = "pdm_din0_a", + "pdm_din1_a", + "pdm_din2_a", + "pdm_din3_a", + "pdm_dclk_a"; + function = "pdm"; + }; + }; + +}; /* end of pinctrl_periphs */ + +&pinctrl_aobus { + tdmout_b: tdmout_b { + mux { /* GPIOAO_7, GPIOAO_8, GPIOAO_4 */ + groups = "tdmb_fs_ao", + "tdmb_fs_ao", + "tdmb_dout0_ao"; + function = "tdmb_out_ao"; + }; + }; + + tdmin_b:tdmin_b { + mux { + groups = "tdmb_din2_ao"; + function = "tdmb_in_ao"; + }; + }; +}; /* end of pinctrl_aobus */ +/* Audio Related End */ + +&aobus{ + +}; + +&irblaster { + status = "disabled"; +}; + +/*if you want to use vdin just modify status to "ok"*/ +&vdin0 { + memory-region = <&vdin0_cma_reserved>; + status = "okay"; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + *bit4:support yuv422 10bit full pack mode (from txl new add) + */ + tv_bit_mode = <0x15>; +}; +&vdin1 { + memory-region = <&vdin1_cma_reserved>; + status = "okay"; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + */ + tv_bit_mode = <1>; +}; +&sd_emmc_b { + status = "okay"; + sd { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED"; + f_min = <400000>; + f_max = <200000000>; + }; +}; + + +&defendkey { + status = "okay"; +}; + diff --git a/arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts b/arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts new file mode 100644 index 000000000000..4cd84e09025b --- /dev/null +++ b/arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts @@ -0,0 +1,1626 @@ +/* + * arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +/dts-v1/; + +#include "mesonsm1.dtsi" +#include "partition_mbox_normal.dtsi" +#include "mesonsm1_skt-panel.dtsi" + +/ { + model = "Amlogic"; + amlogic-dt-id = "sm1_ac200_2g"; + compatible = "amlogic, g12a"; + interrupt-parent = <&gic>; + #address-cells = <1>; + #size-cells = <1>; + + aliases { + serial0 = &uart_AO; + serial1 = &uart_A; + serial2 = &uart_B; + serial3 = &uart_C; + serial4 = &uart_AO_B; + tsensor0 = &p_tsensor; + tsensor1 = &d_tsensor; + i2c0 = &i2c0; + i2c1 = &i2c1; + i2c2 = &i2c2; + i2c3 = &i2c3; + i2c4 = &i2c_AO; + }; + + memory@00000000 { + device_type = "memory"; + linux,usable-memory = <0x000000 0x80000000>; + }; + + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + /* global autoconfigured region for contiguous allocations */ + ramoops@0x07400000 { + compatible = "ramoops"; + reg = <0x07400000 0x00100000>; + record-size = <0x8000>; + console-size = <0x8000>; + ftrace-size = <0x20000>; + }; + + secmon_reserved:linux,secmon { + compatible = "shared-dma-pool"; + reusable; + size = <0x400000>; + alignment = <0x400000>; + alloc-ranges = <0x05000000 0x400000>; + }; + secos_reserved:linux,secos { + status = "disable"; + compatible = "amlogic, aml_secos_memory"; + reg = <0x05300000 0x2000000>; + no-map; + }; + logo_reserved:linux,meson-fb { + compatible = "shared-dma-pool"; + reusable; + size = <0x800000>; + alignment = <0x400000>; + alloc-ranges = <0x30000000 0x50000000>; + }; + ion_cma_reserved:linux,ion-dev { + compatible = "shared-dma-pool"; + reusable; + size = <0x8000000>; + alignment = <0x400000>; + alloc-ranges = <0x30000000 0x50000000>; + }; + //di_reserved:linux,di { + //compatible = "amlogic, di-mem"; + /* buffer_size = 3621952(yuv422 8bit) */ + /* 4179008(yuv422 10bit full pack mode) */ + /** 10x3621952=34.6M(0x23) support 8bit **/ + /** 10x4736064=45.2M(0x2e) support 12bit **/ + /** 10x4179008=40M(0x28) support 10bit **/ + //size = <0x2800000>; + //no-map; + //}; + /*di CMA pool */ + di_cma_reserved:linux,di_cma { + compatible = "shared-dma-pool"; + reusable; + /* buffer_size = 3621952(yuv422 8bit) + * | 4736064(yuv422 10bit) + * | 4074560(yuv422 10bit full pack mode) + * 10x3621952=34.6M(0x23) support 8bit + * 10x4736064=45.2M(0x2e) support 12bit + * 10x4074560=40M(0x28) support 10bit + */ + size = <0x02800000>; + alignment = <0x400000>; + }; + /* POST PROCESS MANAGER */ + ppmgr_reserved:linux,ppmgr { + compatible = "shared-dma-pool"; + size = <0x0>; + }; + + codec_mm_cma:linux,codec_mm_cma { + compatible = "shared-dma-pool"; + reusable; + /* ion_codec_mm max can alloc size 80M*/ + size = <0x13400000>; + alignment = <0x400000>; + linux,contiguous-region; + alloc-ranges = <0x30000000 0x50000000>; + }; + /* codec shared reserved */ + codec_mm_reserved:linux,codec_mm_reserved { + compatible = "amlogic, codec-mm-reserved"; + size = <0x0>; + alignment = <0x100000>; + //no-map; + }; + /* vdin0 CMA pool */ + vdin0_cma_reserved:linux,vdin0_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16+4 M */ + size = <0x04000000>; + alignment = <0x400000>; + }; + /* vdin1 CMA pool */ + vdin1_cma_reserved:linux,vdin1_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16 M */ + size = <0x04000000>; + alignment = <0x400000>; + }; + vm0_cma_reserved:linux,vm0_cma { + compatible = "shared-dma-pool"; + reusable; + size = <0x2000000>; + alignment = <0x400000>; + }; + }; + + galcore { + status = "okay"; + }; + gpioleds { + compatible = "gpio-leds"; + status = "okay"; + + sys_led { + label="sys_led"; + gpios=<&gpio_ao GPIOAO_11 GPIO_ACTIVE_HIGH>; + default-state ="on"; + }; + }; + + cvbsout { + compatible = "amlogic, cvbsout-sm1"; + dev_name = "cvbsout"; + status = "okay"; + clocks = <&clkc CLKID_VCLK2_ENCI + &clkc CLKID_VCLK2_VENCI0 + &clkc CLKID_VCLK2_VENCI1 + &clkc CLKID_DAC_CLK>; + clock-names = "venci_top_gate", + "venci_0_gate", + "venci_1_gate", + "vdac_clk_gate"; + /* clk path */ + /* 0:vid_pll vid2_clk */ + /* 1:gp0_pll vid2_clk */ + /* 2:vid_pll vid1_clk */ + /* 3:gp0_pll vid1_clk */ + clk_path = <0>; + + /* performance: reg_address, reg_value */ + /* sm1 */ + performance = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x8080 + 0x1b05 0xfd + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + performance_sarft = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x0 + 0x1b05 0x9 + 0x1c59 0xfc48 + 0xffff 0x0>; /* ending flag */ + performance_revB_telecom = <0x1bf0 0x9 + 0x1b56 0x546 + 0x1b12 0x8080 + 0x1b05 0x9 + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + }; + + bt-dev{ + compatible = "amlogic, bt-dev"; + dev_name = "bt-dev"; + status = "okay"; + gpio_reset = <&gpio GPIOX_17 GPIO_ACTIVE_HIGH>; + gpio_hostwake = <&gpio GPIOX_19 GPIO_ACTIVE_HIGH>; + }; + + wifi{ + compatible = "amlogic, aml_wifi"; + dev_name = "aml_wifi"; + status = "okay"; + interrupt_pin = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; + irq_trigger_type = "GPIO_IRQ_LOW"; + power_on_pin = <&gpio GPIOX_6 GPIO_ACTIVE_HIGH>; + dhd_static_buf; //if use bcm wifi, config dhd_static_buf + pinctrl-names = "default"; + pinctrl-0 = <&pwm_e_pins>; + pwm_config = <&wifi_pwm_conf>; + }; + + wifi_pwm_conf:wifi_pwm_conf{ + pwm_channel1_conf { + pwms = <&pwm_ef MESON_PWM_0 30541 0>; + duty-cycle = <15270>; + times = <10>; + }; + pwm_channel2_conf { + pwms = <&pwm_ef MESON_PWM_2 30500 0>; + duty-cycle = <15250>; + times = <12>; + }; + }; + + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + + codec_mm { + compatible = "amlogic, codec, mm"; + memory-region = <&codec_mm_cma &codec_mm_reserved>; + dev_name = "codec_mm"; + status = "okay"; + }; + + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + + ppmgr { + compatible = "amlogic, ppmgr"; + memory-region = <&ppmgr_reserved>; + dev_name = "ppmgr"; + status = "okay"; + }; + + deinterlace { + compatible = "amlogic, deinterlace"; + status = "okay"; + /* 0:use reserved; 1:use cma; 2:use cma as reserved */ + flag_cma = <1>; + //memory-region = <&di_reserved>; + memory-region = <&di_cma_reserved>; + interrupts = <0 46 1 + 0 40 1>; + interrupt-names = "pre_irq", "post_irq"; + clocks = <&clkc CLKID_VPU_CLKB_TMP_COMP>, + <&clkc CLKID_VPU_CLKB_COMP>; + clock-names = "vpu_clkb_tmp_composite", + "vpu_clkb_composite"; + clock-range = <334 667>; + /* buffer-size = <3621952>;(yuv422 8bit) */ + buffer-size = <4074560>;/*yuv422 fullpack*/ + /* reserve-iomap = "true"; */ + /* if enable nr10bit, set nr10bit-support to 1 */ + post-wr-support = <1>; + nr10bit-support = <1>; + nrds-enable = <1>; + pps-enable = <1>; + }; + ionvideo { + compatible = "amlogic, ionvideo"; + dev_name = "ionvideo"; + status = "okay"; + }; + vm0 { + compatible = "amlogic, vm"; + memory-region = <&vm0_cma_reserved>; + dev_name = "vm0"; + status = "disabled"; + vm_id = <0>; + }; + + amvdec_656in { + /*bt656 gpio conflict with i2c0*/ + compatible = "amlogic, amvdec_656in"; + dev_name = "amvdec_656in"; + status = "disabled"; + reg = <0xffe02000 0x7c>; + clocks = <&clkc CLKID_BT656_COMP>, + <&clkc CLKID_BT656>; + clock-names = "cts_bt656_clk1", + "clk_gate_bt656"; + /* bt656in1, bt656in2 */ + bt656in1 { + bt656_id = <1>; + status = "disabled"; + }; + }; + + aml_cams { + compatible = "amlogic, cams_prober"; + status = "disabled"; + pinctrl-names="default"; + pinctrl-0=<&cam_dvp_pins &gen_clk_ee_z>; + clocks = <&clkc CLKID_GEN_CLK>; + clock-names = "g12a_24m"; + cam_0{ + cam_name = "gc2145"; + front_back = <0>; + /*u200 i2c2 gpio conflict with ethmac*/ + camera-i2c-bus = <&i2c2>; + gpio_pwdn-gpios = <&gpio GPIOZ_2 GPIO_ACTIVE_HIGH>; + gpio_rst-gpios = <&gpio GPIOZ_12 GPIO_ACTIVE_HIGH>; + mirror_flip = <1>; + vertical_flip = <1>; + spread_spectrum = <0>; + bt_path = "gpio"; + bt_path_count = <1>; + vdin_path = <0>; + status = "okay"; + }; + }; + + gpio_keypad{ + compatible = "amlogic, gpio_keypad"; + status = "okay"; + scan_period = <20>; + key_num = <1>; + key_name = "power"; + key_code = <116>; + key-gpios = <&gpio_ao GPIOAO_3 GPIO_ACTIVE_HIGH>; + detect_mode = <0>;/*0:polling mode, 1:irq mode*/ + }; + + adc_keypad { + compatible = "amlogic, adc_keypad"; + status = "okay"; + key_name = "vol-", "vol+", "enter"; + key_num = <3>; + io-channels = <&saradc SARADC_CH2>; + io-channel-names = "key-chan-2"; + key_chan = ; + key_code = <114 115 97>; + key_val = <143 266 389>; //val=voltage/1800mV*1023 + key_tolerance = <40 40 40>; + }; + + unifykey{ + compatible = "amlogic, unifykey"; + status = "ok"; + unifykey-num = <17>; + unifykey-index-0 = <&keysn_0>; + unifykey-index-1 = <&keysn_1>; + unifykey-index-2 = <&keysn_2>; + unifykey-index-3 = <&keysn_3>; + unifykey-index-4 = <&keysn_4>; + unifykey-index-5 = <&keysn_5>; + unifykey-index-6 = <&keysn_6>; + unifykey-index-7 = <&keysn_7>; + unifykey-index-8 = <&keysn_8>; + unifykey-index-9 = <&keysn_9>; + unifykey-index-10= <&keysn_10>; + unifykey-index-11= <&keysn_11>; + unifykey-index-12= <&keysn_12>; + unifykey-index-13= <&keysn_13>; + unifykey-index-14= <&keysn_14>; + unifykey-index-15= <&keysn_15>; + unifykey-index-16= <&keysn_16>; + + keysn_0: key_0{ + key-name = "usid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_1:key_1{ + key-name = "mac"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_2:key_2{ + key-name = "hdcp"; + key-device = "secure"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_3:key_3{ + key-name = "secure_boot_set"; + key-device = "efuse"; + key-permit = "write"; + }; + keysn_4:key_4{ + key-name = "mac_bt"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_5:key_5{ + key-name = "mac_wifi"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_6:key_6{ + key-name = "hdcp2_tx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_7:key_7{ + key-name = "hdcp2_rx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_8:key_8{ + key-name = "widevinekeybox"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_9:key_9{ + key-name = "deviceid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_10:key_10{ + key-name = "hdcp22_fw_private"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_11:key_11{ + key-name = "PlayReadykeybox25"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_12:key_12{ + key-name = "prpubkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_13:key_13{ + key-name = "prprivkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_14:key_14{ + key-name = "attestationkeybox";// attestation key + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_15:key_15{ + key-name = "region_code"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_16:key_16{ + key-name = "netflix_mgkid"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + };//End unifykey + + efusekey:efusekey{ + keynum = <4>; + key0 = <&key_0>; + key1 = <&key_1>; + key2 = <&key_2>; + key3 = <&key_3>; + key_0:key_0{ + keyname = "mac"; + offset = <0>; + size = <6>; + }; + key_1:key_1{ + keyname = "mac_bt"; + offset = <6>; + size = <6>; + }; + key_2:key_2{ + keyname = "mac_wifi"; + offset = <12>; + size = <6>; + }; + key_3:key_3{ + keyname = "usid"; + offset = <18>; + size = <16>; + }; + };//End efusekey + + amlvecm { + compatible = "amlogic, vecm"; + dev_name = "aml_vecm"; + status = "okay"; + gamma_en = <0>;/*1:enabel ;0:disable*/ + wb_en = <0>;/*1:enabel ;0:disable*/ + cm_en = <0>;/*1:enabel ;0:disable*/ + /*0: 709/601 1: bt2020*/ + tx_op_color_primary = <0>; + }; + + amdolby_vision { + compatible = "amlogic, dolby_vision_sm1"; + dev_name = "aml_amdolby_vision_driver"; + status = "okay"; + tv_mode = <0>;/*1:enabel ;0:disable*/ + }; + + /* Audio Related start */ + pdm_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, pdm_dummy_codec"; + status = "okay"; + }; + dummy_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, aml_dummy_codec"; + status = "okay"; + }; + amlogic_codec:t9015{ + #sound-dai-cells = <0>; + compatible = "amlogic, aml_codec_T9015"; + reg = <0xFF632000 0x2000>; + is_auge_used = <1>; /* meson or auge chipset used */ + tocodec_inout = <1>; + tdmout_index = <1>; + ch0_sel = <0>; + ch1_sel = <1>; + + status = "okay"; + }; + + auge_sound { + compatible = "amlogic, g12a-sound-card"; + aml-audio-card,name = "AML-AUGESOUND"; + + /*avout mute gpio*/ + avout_mute-gpios = <&gpio_ao GPIOAO_2 GPIO_ACTIVE_HIGH>; + + aml-audio-card,dai-link@0 { + format = "dsp_a"; + mclk-fs = <512>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdma>; + frame-master = <&tdma>; + /* slave mode */ + /* + * bitclock-master = <&tdmacodec>; + * frame-master = <&tdmacodec>; + */ + suffix-name = "alsaPORT-pcm"; + tdmacpu: cpu { + sound-dai = <&tdma>; + dai-tdm-slot-tx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-rx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-num = <8>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <24576000>; + }; + tdmacodec: codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@1 { + format = "i2s";// "dsp_a"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdmb>; + frame-master = <&tdmb>; + /* slave mode */ + //bitclock-master = <&tdmbcodec>; + //frame-master = <&tdmbcodec>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-i2s"; + cpu { + sound-dai = <&tdmb>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + /* + * dai-tdm-slot-tx-mask = + * <1 1 1 1 1 1 1 1>; + * dai-tdm-slot-rx-mask = + * <1 1 1 1 1 1 1 1>; + * dai-tdm-slot-num = <8>; + */ + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmbcodec: codec { + sound-dai = <&dummy_codec &dummy_codec + &amlogic_codec &ad82584f_62>; + }; + }; + + aml-audio-card,dai-link@2 { + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdmc>; + frame-master = <&tdmc>; + /* slave mode */ + //bitclock-master = <&tdmccodec>; + //frame-master = <&tdmccodec>; + /* suffix-name, sync with android audio hal used for */ + //suffix-name = "alsaPORT-tdm"; + cpu { + sound-dai = <&tdmc>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmccodec: codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@3 { + mclk-fs = <64>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-pdm"; + cpu { + sound-dai = <&pdm>; + }; + codec { + sound-dai = <&pdm_codec>; + }; + }; + + aml-audio-card,dai-link@4 { + mclk-fs = <128>; + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-spdif"; + cpu { + sound-dai = <&spdifa>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@5 { + mclk-fs = <128>; + continuous-clock; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-spdifb"; + cpu { + sound-dai = <&spdifb>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + aml-audio-card,dai-link@6 { + mclk-fs = <256>; + suffix-name = "alsaPORT-earc"; + cpu { + sound-dai = <&earc>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + }; + audiolocker: locker { + compatible = "amlogic, audiolocker"; + clocks = <&clkaudio CLKID_AUDIO_LOCKER_OUT + &clkaudio CLKID_AUDIO_LOCKER_IN + &clkaudio CLKID_AUDIO_MCLK_D + &clkaudio CLKID_AUDIO_MCLK_E + &clkc CLKID_MPLL1 + &clkc CLKID_MPLL2>; + clock-names = "lock_out", "lock_in", "out_src", + "in_src", "out_calc", "in_ref"; + interrupts = ; + interrupt-names = "irq"; + frequency = <49000000>; /* pll */ + dividor = <49>; /* locker's parent */ + status = "disabled"; + }; + /* Audio Related end */ + dvb { + compatible = "amlogic, dvb"; + dev_name = "dvb"; + status = "okay"; +// fe0_mode = "internal"; +// fe0_tuner = <&tuner>; + /*"parallel","serial","disable"*/ +// ts2 = "parallel"; +// ts2_control = <0>; +// ts2_invert = <0>; + interrupts = <0 23 1 + 0 5 1 + 0 53 1 + 0 19 1 + 0 25 1 + 0 18 1 + 0 24 1>; + interrupt-names = "demux0_irq", + "demux1_irq", + "demux2_irq", + "dvr0_irq", + "dvr1_irq", + "dvrfill0_fill", + "dvrfill1_flush"; + clocks = <&clkc CLKID_DEMUX + &clkc CLKID_AHB_ARB0 + &clkc CLKID_DOS_PARSER>; + clock-names = "demux", "ahbarb0", "uparsertop"; + }; + tuner: tuner { + compatible = "amlogic, tuner"; + status = "okay"; + tuner_name = "mxl661_tuner"; + tuner_i2c_adap = <&i2c1>; + tuner_i2c_addr = <0x60>; + tuner_xtal = <0>; /* 0: 16MHz, 1: 24MHz */ + tuner_xtal_mode = <0>; + /* NO_SHARE_XTAL(0) + * SLAVE_XTAL_SHARE(1) + */ + tuner_xtal_cap = <30>; /* when tuner_xtal_mode = 1, set 25 */ + }; + + p_tsensor: p_tsensor@ff634800 { + compatible = "amlogic, r1p1-tsensor"; + device_name = "meson-pthermal"; + status = "okay"; + reg = <0xff634800 0x50>, + <0xff800268 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 35 0>; + clocks = <&clkc CLKID_TS_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + d_tsensor: d_tsensor@ff634c00 { + compatible = "amlogic, r1p1-tsensor"; + device_name = "meson-dthermal"; + status = "okay"; + reg = <0xff634c00 0x50>, + <0xff800230 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 36 0>; + clocks = <&clkc CLKID_TS_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + meson_cooldev: meson-cooldev@0 { + status = "okay"; + compatible = "amlogic, meson-cooldev"; + device_name = "mcooldev"; + cooling_devices { + cpufreq_cool_cluster0 { + min_state = <1000000>; + dyn_coeff = <125>; + cluster_id = <0>; + node_name = "cpufreq_cool0"; + device_type = "cpufreq"; + }; + cpucore_cool_cluster0 { + min_state = <1>; + dyn_coeff = <0>; + cluster_id = <0>; + node_name = "cpucore_cool0"; + device_type = "cpucore"; + }; + gpufreq_cool { + min_state = <400>; + dyn_coeff = <215>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "gpufreq_cool0"; + device_type = "gpufreq"; + }; + gpucore_cool { + min_state = <1>; + dyn_coeff = <0>; + cluster_id = <0>; + node_name = "gpucore_cool0"; + device_type = "gpucore"; + }; + }; + cpufreq_cool0:cpufreq_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + cpucore_cool0:cpucore_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + gpufreq_cool0:gpufreq_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + gpucore_cool0:gpucore_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + }; + /*meson cooling devices end*/ + + thermal-zones { + soc_thermal: soc_thermal { + polling-delay = <1000>; + polling-delay-passive = <100>; + sustainable-power = <1410>; + thermal-sensors = <&p_tsensor 0>; + trips { + pswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + pcontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + phot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + pcritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + + cooling-maps { + cpufreq_cooling_map { + trip = <&pcontrol>; + cooling-device = <&cpufreq_cool0 0 4>; + contribution = <1024>; + }; + cpucore_cooling_map { + trip = <&pcontrol>; + cooling-device = <&cpucore_cool0 0 3>; + contribution = <1024>; + }; + gpufreq_cooling_map { + trip = <&pcontrol>; + cooling-device = <&gpufreq_cool0 0 4>; + contribution = <1024>; + }; + gpucore_cooling_map { + trip = <&pcontrol>; + cooling-device = <&gpucore_cool0 0 2>; + contribution = <1024>; + }; + }; + }; + ddr_thermal: ddr_thermal { + polling-delay = <2000>; + polling-delay-passive = <1000>; + sustainable-power = <1410>; + thermal-sensors = <&d_tsensor 1>; + trips { + dswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + dcontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + dhot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + dcritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + + }; + }; + /*thermal zone end*/ + + cpu_opp_table0: cpu_opp_table0 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <730000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <730000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <730000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <750000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <770000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <780000>; + }; + opp06 { + opp-hz = /bits/ 64 <1404000000>; + opp-microvolt = <790000>; + }; + opp07 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <800000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <810000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <850000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <900000>; + }; + opp11 { + opp-hz = /bits/ 64 <1908000000>; + opp-microvolt = <950000>; + }; + }; + + cpufreq-meson { + compatible = "amlogic, cpufreq-meson"; + pinctrl-names = "default"; + pinctrl-0 = <&pwm_ao_d_pins3>; + status = "okay"; + }; + +}; /* end of / */ + +&meson_fb { + status = "okay"; + display_size_default = <1920 1080 1920 2160 32>; + mem_size = <0x00800000 0x1980000 0x100000 0x100000 0x800000>; + logo_addr = "0x7f800000"; + mem_alloc = <0>; + pxp_mode = <0>; /** 0:normal mode 1:pxp mode */ +}; + +&pwm_AO_cd { + status = "okay"; +}; + +&i2c0 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&i2c0_master_pins2>; + clock-frequency = <400000>; + + gt9xx@5d { + compatible = "goodix,gt9xx"; + status = "disabled"; + reg = <0x5d>; + reset-gpio = <&gpio GPIOZ_9 0x00>; + irq-gpio = <&gpio GPIOZ_3 0x00>; + }; + + ftxx@38 { + compatible = "focaltech,fts"; + status = "disabled"; + reg = <0x38>; + reset-gpio = <&gpio GPIOZ_9 0x00>; + irq-gpio = <&gpio GPIOZ_3 0x00>; + x_max = <600>; + y_max = <1024>; + max-touch-number = <10>; + }; +}; + +&i2c2 { + status = "disabled"; + pinctrl-names="default"; + pinctrl-0=<&i2c2_master_pins2>; + clock-frequency = <100000>; +}; + +&i2c3 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&i2c3_master_pins2>; + clock-frequency = <100000>; /* default 100k */ + + /* for ref board */ + ad82584f_62: ad82584f_62@62 { + compatible = "ESMT, ad82584f"; + #sound-dai-cells = <0>; + reg = <0x31>; + status = "okay"; + reset_pin = <&gpio GPIOA_5 0>; + no_mclk; + }; + + bl_extern_i2c { + compatible = "bl_extern, i2c"; + dev_name = "lp8556"; + reg = <0x2c>; + status = "disabled"; + }; +}; + +&audiobus { + tdma: tdm@0 { + compatible = "amlogic, sm1-snd-tdma"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 1>; + dai-tdm-oe-lane-slot-mask-out = <1 0>; + dai-tdm-clk-sel = <0>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_A + &clkc CLKID_MPLL0>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmout_a &tdmin_a>; + + status = "okay"; + }; + + tdmb: tdm@1 { + compatible = "amlogic, sm1-snd-tdmb"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 1 0 0>; + dai-tdm-lane-slot-mask-out = <1 0 0 0>; + //dai-tdm-lane-slot-mask-in = <0 0 0 0 0 0 0 0>; + //dai-tdm-lane-slot-mask-out = <1 1 1 1 1 1 1 1>; + dai-tdm-clk-sel = <1>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_B + &clkc CLKID_MPLL1 + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_A>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; + + mclk_pad = <0>; /* 0: mclk_0; 1: mclk_1 */ + + /* + * 0: tdmout_a; + * 1: tdmout_b; + * 2: tdmout_c; + * 3: spdifout; + * 4: spdifout_b; + */ + samesource_sel = <3>; + + status = "okay"; + }; + + tdmc: tdm@2 { + compatible = "amlogic, sm1-snd-tdmc"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <1 0 0 0>; + #dai-tdm-lane-slot-mask-out = <1 0 1 1>; + #dai-tdm-lane-oe-slot-mask-in = <0 0 0 0>; + #dai-tdm-lane-oe-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <2>; + + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmc_mclk &tdmout_c &tdmin_c>; + mclk_pad = <0>; /* 0: mclk_0; 1: mclk_1 */ + + status = "okay"; + }; + + spdifa: spdif@0 { + compatible = "amlogic, sm1-snd-spdif-a"; + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 + &clkc CLKID_FCLK_DIV4 + &clkaudio CLKID_AUDIO_GATE_SPDIFIN + &clkaudio CLKID_AUDIO_GATE_SPDIFOUT_A + &clkaudio CLKID_AUDIO_SPDIFIN + &clkaudio CLKID_AUDIO_SPDIFOUT_A>; + clock-names = "sysclk", "fixed_clk", "gate_spdifin", + "gate_spdifout", "clk_spdifin", "clk_spdifout"; + interrupts = + ; + + interrupt-names = "irq_spdifin"; + pinctrl-names = "spdif_pins"; + pinctrl-0 = <&spdifout &spdifin>; + + status = "okay"; + }; + spdifb: spdif@1 { + compatible = "amlogic, sm1-snd-spdif-b"; + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 /*CLKID_HIFI_PLL*/ + &clkaudio CLKID_AUDIO_GATE_SPDIFOUT_B + &clkaudio CLKID_AUDIO_SPDIFOUT_B>; + clock-names = "sysclk", + "gate_spdifout", "clk_spdifout"; + + status = "okay"; + }; + pdm: pdm { + compatible = "amlogic, sm1-snd-pdm"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_PDM + &clkc CLKID_FCLK_DIV3 + &clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_PDMIN0 + &clkaudio CLKID_AUDIO_PDMIN1>; + clock-names = "gate", + "sysclk_srcpll", + "dclk_srcpll", + "pdm_dclk", + "pdm_sysclk"; + + pinctrl-names = "pdm_pins"; + pinctrl-0 = <&pdmin>; + + /* mode 0~4, defalut:1 */ + filter_mode = <1>; + + status = "okay"; + }; + + earc:earc { + compatible = "amlogic, sm1-snd-earc"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_EARCRX + &clkaudio CLKID_EARCRX_CMDC + &clkaudio CLKID_EARCRX_DMAC + &clkc CLKID_FCLK_DIV5 + &clkc CLKID_FCLK_DIV3 + >; + clock-names = "rx_gate", + "rx_cmdc", + "rx_dmac", + "rx_cmdc_srcpll", + "rx_dmac_srcpll"; + + interrupts = < + GIC_SPI 88 IRQ_TYPE_EDGE_RISING + GIC_SPI 87 IRQ_TYPE_EDGE_RISING + >; + interrupt-names = "rx_cmdc", "rx_dmac"; + + status = "okay"; + }; + + asrca: resample@0 { + compatible = "amlogic, sm1-resample"; + clocks = <&clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_MCLK_F + &clkaudio CLKID_AUDIO_RESAMPLE_A>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + /*same with toddr_src + * TDMIN_A, 0 + * TDMIN_B, 1 + * TDMIN_C, 2 + * SPDIFIN, 3 + * PDMIN, 4 + * NONE, + * TDMIN_LB, 6 + * LOOPBACK, 7 + */ + resample_module = <4>; + status = "disabled"; + }; + + vad:vad { + compatible = "amlogic, snd-vad"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_TOVAD + &clkc CLKID_FCLK_DIV5 + &clkaudio CLKID_AUDIO_VAD>; + clock-names = "gate", "pll", "clk"; + + interrupts = ; + interrupt-names = "irq_wakeup", "irq_frame_sync"; + + /* + * Data src sel: + * 0: tdmin_a; + * 1: tdmin_b; + * 2: tdmin_c; + * 3: spdifin; + * 4: pdmin; + * 5: loopback_b; + * 6: tdmin_lb; + * 7: loopback_a; + */ + src = <4>; + + /* + * deal with hot word in user space or kernel space + * 0: in user space + * 1: in kernel space + */ + level = <1>; + + status = "okay"; + }; +}; /* end of audiobus */ + +&pinctrl_periphs { + tdmout_a: tdmout_a { + mux { /* GPIOX_11, GPIOX_10, GPIOX_9 */ + groups = "tdma_sclk", + "tdma_fs", + "tdma_dout0"; + function = "tdma_out"; + }; + }; + + tdmin_a: tdmin_a { + mux { /* GPIOX_8 */ + groups = "tdma_din1"; + function = "tdma_in"; + }; + }; + + tdmb_mclk: tdmb_mclk { + mux { + groups = "mclk0_a"; + function = "mclk0"; + drive-strength = <2>; + }; + }; + + tdmout_b: tdmout_b { + mux { /* GPIOA_1, GPIOA_2, GPIOA_3, GPIOA_4, */ + /* GPIOA_5, GPIOA_6, GPIOA_7, GPIOA_8, */ + /* GPIOA_9, GPIOA_0*/ + groups = "tdmb_sclk", + "tdmb_fs", + "tdmb_dout0"; + //"tdmb_dout1", + //"tdmb_dout2", + //"tdmb_dout3_a", + //"tdmb_dout4_a", + //"tdmb_dout5_a", + //"tdmb_dout6_a", + //"tdmb_dout7_a0"; + function = "tdmb_out"; + drive-strength = <2>; + }; + }; + + tdmin_b:tdmin_b { + mux { /* GPIOA_4 */ + groups = "tdmb_din1" + /*,"tdmb_slv_sclk", "tdmb_slv_fs"*/; + function = "tdmb_in"; + drive-strength = <2>; + }; + }; + + tdmc_mclk: tdmc_mclk { + mux { /* GPIOA_11 */ + groups = "mclk1_a"; + function = "mclk1"; + }; + }; + + tdmout_c:tdmout_c { + mux { /* GPIOA_12, GPIOA_13, GPIOA_8, GPIOA_7*/ + groups = "tdmc_sclk_a", + "tdmc_fs_a", + "tdmc_dout0_a" + /*, "tdmc_dout2", + * "tdmc_dout3" + */; + function = "tdmc_out"; + }; + }; + + tdmin_c:tdmin_c { + mux { /* GPIOA_10 */ + groups = "tdmc_din0_a"; + function = "tdmc_in"; + }; + }; + + spdifin: spdifin { + mux {/* GPIOH_5 */ + groups = "spdif_in_h"; + function = "spdif_in"; + }; + }; + + pdmin: pdmin { + mux { /* GPIOA_5, GPIOA_6, GPIOA_8, GPIOA_9, GPIOA_7 */ + groups = "pdm_din0_a", + /*"pdm_din1_a",*/ + "pdm_din2_a", + /*"pdm_din3_a",*/ + "pdm_dclk_a"; + function = "pdm"; + }; + }; + + bl_pwm_off_pins:bl_pwm_off_pin { + mux { + pins = "GPIOH_5"; + function = "gpio_periphs"; + output-high; + }; + }; + + clk12_24_z_pins:clk12_24_z_pins { + mux { + groups = "clk12_24_z"; + function = "clk12_24_ee"; + drive-strength = <3>; + }; + }; + + gen_clk_ee_z: gen_clk_ee_z { + mux { + groups="gen_clk_ee_z"; + function="gen_clk_ee"; + drive-strength = <3>; + }; + }; + + cam_dvp_pins:cam_dvp_pins { + mux { + groups = "bt656_a_vs", "bt656_a_hs", "bt656_a_clk", + "bt656_a_din0", "bt656_a_din1", "bt656_a_din2", + "bt656_a_din3", "bt656_a_din4", "bt656_a_din5", + "bt656_a_din6", "bt656_a_din7"; + function = "bt656"; + }; + }; + + +}; /* end of pinctrl_periphs */ + +&pinctrl_aobus { + spdifout: spdifout { + mux { /* GPIOAO_10 */ + groups = "spdif_out_ao"; + function = "spdif_out_ao"; + }; + }; +}; /* end of pinctrl_aobus */ + +&audio_data { + status = "okay"; +}; + +/* Audio Related End */ + +&pwm_ef { + status = "okay"; +}; + +&dwc3 { + status = "okay"; +}; + +&usb2_phy_v2 { + status = "okay"; + portnum = <2>; +}; + +&usb3_phy_v2 { + status = "okay"; + portnum = <1>; + otg = <1>; + gpio-vbus-power = "GPIOH_6"; + gpios = <&gpio GPIOH_6 GPIO_ACTIVE_HIGH>; +}; + +&dwc2_a { + status = "okay"; + /** 0: normal, 1: otg+dwc3 host only, 2: otg+dwc3 device only*/ + controller-type = <3>; +}; +ðmac { + status = "okay"; + pinctrl-names = "internal_eth_pins"; + pinctrl-0 = <&internal_eth_pins>; + mc_val = <0x4be04>; + + internal_phy=<1>; +}; + +&uart_A { + status = "okay"; +}; + +/*if you want to use vdin just modify status to "ok"*/ +&vdin0 { + memory-region = <&vdin0_cma_reserved>; + status = "okay"; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + *bit4:support yuv422 10bit full pack mode (from txl new add) + */ + tv_bit_mode = <0x15>; +}; +&vdin1 { + memory-region = <&vdin1_cma_reserved>; + status = "okay"; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + */ + tv_bit_mode = <1>; +}; + + +&sd_emmc_c { + status = "okay"; + emmc { + caps = "MMC_CAP_8_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + /* "MMC_CAP_1_8V_DDR", */ + "MMC_CAP_HW_RESET", + "MMC_CAP_ERASE", + "MMC_CAP_CMD23"; + caps2 = "MMC_CAP2_HS200"; + /* "MMC_CAP2_HS400";*/ + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&sd_emmc_b { + status = "okay"; + sd { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED"; + f_min = <400000>; + f_max = <50000000>; + }; +}; + + +&sd_emmc_a { + status = "okay"; + sdio { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + "MMC_CAP_UHS_SDR12", + "MMC_CAP_UHS_SDR25", + "MMC_CAP_UHS_SDR50", + "MMC_CAP_UHS_SDR104", + "MMC_PM_KEEP_POWER", + "MMC_CAP_SDIO_IRQ"; + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&nand { + status = "disabled"; + plat-names = "bootloader","nandnormal"; + plat-num = <2>; + plat-part-0 = <&bootloader>; + plat-part-1 = <&nandnormal>; + bootloader: bootloader{ + enable_pad ="ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <1>; + part_num = <0>; + rb_detect = <1>; + }; + nandnormal: nandnormal{ + enable_pad ="ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + plane_mode = "twoplane"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <2>; + part_num = <3>; + partition = <&nand_partitions>; + rb_detect = <1>; + }; + nand_partitions:nand_partition{ + /* + * if bl_mode is 1, tpl size was generate by + * fip_copies * fip_size which + * will not skip bad when calculating + * the partition size; + * + * if bl_mode is 0, + * tpl partition must be comment out. + */ + tpl{ + offset=<0x0 0x0>; + size=<0x0 0x0>; + }; + logo{ + offset=<0x0 0x0>; + size=<0x0 0x200000>; + }; + recovery{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + boot{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + system{ + offset=<0x0 0x0>; + size=<0x0 0x4000000>; + }; + data{ + offset=<0xffffffff 0xffffffff>; + size=<0x0 0x0>; + }; + }; +}; + +&pcie_A { + reset-gpio = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; + status = "disable"; +}; + +&meson_cooldev { + status = "okay"; +}; + +&defendkey { + status = "okay"; +}; + diff --git a/arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts b/arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts new file mode 100644 index 000000000000..6e45aa64729f --- /dev/null +++ b/arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts @@ -0,0 +1,1613 @@ +/* + * arch/arm/boot/dts/amlogic/sm1_s905d3_skt.dts + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +/dts-v1/; + +#include "mesonsm1.dtsi" +#include "partition_mbox_normal.dtsi" +#include "mesonsm1_skt-panel.dtsi" + +/ { + model = "Amlogic"; + amlogic-dt-id = "sm1_skt_2g"; + compatible = "amlogic, g12a"; + interrupt-parent = <&gic>; + #address-cells = <1>; + #size-cells = <1>; + + aliases { + serial0 = &uart_AO; + serial1 = &uart_A; + serial2 = &uart_B; + serial3 = &uart_C; + serial4 = &uart_AO_B; + tsensor0 = &p_tsensor; + tsensor1 = &d_tsensor; + i2c0 = &i2c0; + i2c1 = &i2c1; + i2c2 = &i2c2; + i2c3 = &i2c3; + i2c4 = &i2c_AO; + }; + + memory@00000000 { + device_type = "memory"; + linux,usable-memory = <0x000000 0x80000000>; + }; + + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + /* global autoconfigured region for contiguous allocations */ + ramoops@0x07400000 { + compatible = "ramoops"; + reg = <0x07400000 0x00100000>; + record-size = <0x8000>; + console-size = <0x8000>; + ftrace-size = <0x20000>; + }; + + secmon_reserved:linux,secmon { + compatible = "shared-dma-pool"; + reusable; + size = <0x400000>; + alignment = <0x400000>; + alloc-ranges = <0x05000000 0x400000>; + }; + secos_reserved:linux,secos { + status = "disable"; + compatible = "amlogic, aml_secos_memory"; + reg = <0x05300000 0x2000000>; + no-map; + }; + logo_reserved:linux,meson-fb { + compatible = "shared-dma-pool"; + reusable; + size = <0x800000>; + alignment = <0x400000>; + alloc-ranges = <0x30000000 0x50000000>; + }; + ion_cma_reserved:linux,ion-dev { + compatible = "shared-dma-pool"; + reusable; + size = <0x8000000>; + alignment = <0x400000>; + alloc-ranges = <0x30000000 0x50000000>; + }; + //di_reserved:linux,di { + //compatible = "amlogic, di-mem"; + /* buffer_size = 3621952(yuv422 8bit) */ + /* 4179008(yuv422 10bit full pack mode) */ + /** 10x3621952=34.6M(0x23) support 8bit **/ + /** 10x4736064=45.2M(0x2e) support 12bit **/ + /** 10x4179008=40M(0x28) support 10bit **/ + //size = <0x2800000>; + //no-map; + //}; + /*di CMA pool */ + di_cma_reserved:linux,di_cma { + compatible = "shared-dma-pool"; + reusable; + /* buffer_size = 3621952(yuv422 8bit) + * | 4736064(yuv422 10bit) + * | 4074560(yuv422 10bit full pack mode) + * 10x3621952=34.6M(0x23) support 8bit + * 10x4736064=45.2M(0x2e) support 12bit + * 10x4074560=40M(0x28) support 10bit + */ + size = <0x02800000>; + alignment = <0x400000>; + }; + /* POST PROCESS MANAGER */ + ppmgr_reserved:linux,ppmgr { + compatible = "shared-dma-pool"; + size = <0x0>; + }; + + codec_mm_cma:linux,codec_mm_cma { + compatible = "shared-dma-pool"; + reusable; + /* ion_codec_mm max can alloc size 80M*/ + size = <0x13400000>; + alignment = <0x400000>; + linux,contiguous-region; + alloc-ranges = <0x30000000 0x50000000>; + }; + /* codec shared reserved */ + codec_mm_reserved:linux,codec_mm_reserved { + compatible = "amlogic, codec-mm-reserved"; + size = <0x0>; + alignment = <0x100000>; + //no-map; + }; + /* vdin0 CMA pool */ + vdin0_cma_reserved:linux,vdin0_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16+4 M */ + size = <0x04000000>; + alignment = <0x400000>; + }; + /* vdin1 CMA pool */ + vdin1_cma_reserved:linux,vdin1_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16 M */ + size = <0x04000000>; + alignment = <0x400000>; + }; + vm0_cma_reserved:linux,vm0_cma { + compatible = "shared-dma-pool"; + reusable; + size = <0x2000000>; + alignment = <0x400000>; + }; + }; + + galcore { + status = "okay"; + }; + gpioleds { + compatible = "gpio-leds"; + status = "okay"; + + sys_led { + label="sys_led"; + gpios=<&gpio_ao GPIOAO_11 GPIO_ACTIVE_HIGH>; + default-state ="on"; + }; + }; + + cvbsout { + compatible = "amlogic, cvbsout-sm1"; + dev_name = "cvbsout"; + status = "okay"; + clocks = <&clkc CLKID_VCLK2_ENCI + &clkc CLKID_VCLK2_VENCI0 + &clkc CLKID_VCLK2_VENCI1 + &clkc CLKID_DAC_CLK>; + clock-names = "venci_top_gate", + "venci_0_gate", + "venci_1_gate", + "vdac_clk_gate"; + /* clk path */ + /* 0:vid_pll vid2_clk */ + /* 1:gp0_pll vid2_clk */ + /* 2:vid_pll vid1_clk */ + /* 3:gp0_pll vid1_clk */ + clk_path = <0>; + + /* performance: reg_address, reg_value */ + /* sm1 */ + performance = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x8080 + 0x1b05 0xfd + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + performance_sarft = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x0 + 0x1b05 0x9 + 0x1c59 0xfc48 + 0xffff 0x0>; /* ending flag */ + performance_revB_telecom = <0x1bf0 0x9 + 0x1b56 0x546 + 0x1b12 0x8080 + 0x1b05 0x9 + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + }; + + bt-dev{ + compatible = "amlogic, bt-dev"; + dev_name = "bt-dev"; + status = "okay"; + gpio_reset = <&gpio GPIOX_17 GPIO_ACTIVE_HIGH>; + gpio_hostwake = <&gpio GPIOX_19 GPIO_ACTIVE_HIGH>; + }; + + wifi{ + compatible = "amlogic, aml_wifi"; + dev_name = "aml_wifi"; + status = "okay"; + interrupt_pin = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; + irq_trigger_type = "GPIO_IRQ_LOW"; + power_on_pin = <&gpio GPIOX_6 GPIO_ACTIVE_HIGH>; + dhd_static_buf; //if use bcm wifi, config dhd_static_buf + pinctrl-names = "default"; + pinctrl-0 = <&pwm_e_pins>; + pwm_config = <&wifi_pwm_conf>; + }; + + wifi_pwm_conf:wifi_pwm_conf{ + pwm_channel1_conf { + pwms = <&pwm_ef MESON_PWM_0 30541 0>; + duty-cycle = <15270>; + times = <10>; + }; + pwm_channel2_conf { + pwms = <&pwm_ef MESON_PWM_2 30500 0>; + duty-cycle = <15250>; + times = <12>; + }; + }; + + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + + codec_mm { + compatible = "amlogic, codec, mm"; + memory-region = <&codec_mm_cma &codec_mm_reserved>; + dev_name = "codec_mm"; + status = "okay"; + }; + + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + + ppmgr { + compatible = "amlogic, ppmgr"; + memory-region = <&ppmgr_reserved>; + dev_name = "ppmgr"; + status = "okay"; + }; + + deinterlace { + compatible = "amlogic, deinterlace"; + status = "okay"; + /* 0:use reserved; 1:use cma; 2:use cma as reserved */ + flag_cma = <1>; + //memory-region = <&di_reserved>; + memory-region = <&di_cma_reserved>; + interrupts = <0 46 1 + 0 40 1>; + interrupt-names = "pre_irq", "post_irq"; + clocks = <&clkc CLKID_VPU_CLKB_TMP_COMP>, + <&clkc CLKID_VPU_CLKB_COMP>; + clock-names = "vpu_clkb_tmp_composite", + "vpu_clkb_composite"; + clock-range = <334 667>; + /* buffer-size = <3621952>;(yuv422 8bit) */ + buffer-size = <4074560>;/*yuv422 fullpack*/ + /* reserve-iomap = "true"; */ + /* if enable nr10bit, set nr10bit-support to 1 */ + post-wr-support = <1>; + nr10bit-support = <1>; + nrds-enable = <1>; + pps-enable = <1>; + }; + ionvideo { + compatible = "amlogic, ionvideo"; + dev_name = "ionvideo"; + status = "okay"; + }; + vm0 { + compatible = "amlogic, vm"; + memory-region = <&vm0_cma_reserved>; + dev_name = "vm0"; + status = "disabled"; + vm_id = <0>; + }; + + amvdec_656in { + /*bt656 gpio conflict with i2c0*/ + compatible = "amlogic, amvdec_656in"; + dev_name = "amvdec_656in"; + status = "disabled"; + reg = <0xffe02000 0x7c>; + clocks = <&clkc CLKID_BT656_COMP>, + <&clkc CLKID_BT656>; + clock-names = "cts_bt656_clk1", + "clk_gate_bt656"; + /* bt656in1, bt656in2 */ + bt656in1 { + bt656_id = <1>; + status = "disabled"; + }; + }; + + aml_cams { + compatible = "amlogic, cams_prober"; + status = "disabled"; + pinctrl-names="default"; + pinctrl-0=<&cam_dvp_pins &gen_clk_ee_z>; + clocks = <&clkc CLKID_GEN_CLK>; + clock-names = "g12a_24m"; + cam_0{ + cam_name = "gc2145"; + front_back = <0>; + /*u200 i2c2 gpio conflict with ethmac*/ + camera-i2c-bus = <&i2c2>; + gpio_pwdn-gpios = <&gpio GPIOZ_2 GPIO_ACTIVE_HIGH>; + gpio_rst-gpios = <&gpio GPIOZ_12 GPIO_ACTIVE_HIGH>; + mirror_flip = <1>; + vertical_flip = <1>; + spread_spectrum = <0>; + bt_path = "gpio"; + bt_path_count = <1>; + vdin_path = <0>; + status = "okay"; + }; + }; + + gpio_keypad{ + compatible = "amlogic, gpio_keypad"; + status = "okay"; + scan_period = <20>; + key_num = <1>; + key_name = "power"; + key_code = <116>; + key-gpios = <&gpio_ao GPIOAO_3 GPIO_ACTIVE_HIGH>; + detect_mode = <0>;/*0:polling mode, 1:irq mode*/ + }; + + adc_keypad { + compatible = "amlogic, adc_keypad"; + status = "okay"; + key_name = "vol-", "vol+", "enter"; + key_num = <3>; + io-channels = <&saradc SARADC_CH2>; + io-channel-names = "key-chan-2"; + key_chan = ; + key_code = <114 115 28>; + key_val = <143 266 389>; //val=voltage/1800mV*1023 + key_tolerance = <40 40 40>; + }; + + unifykey{ + compatible = "amlogic, unifykey"; + status = "ok"; + unifykey-num = <17>; + unifykey-index-0 = <&keysn_0>; + unifykey-index-1 = <&keysn_1>; + unifykey-index-2 = <&keysn_2>; + unifykey-index-3 = <&keysn_3>; + unifykey-index-4 = <&keysn_4>; + unifykey-index-5 = <&keysn_5>; + unifykey-index-6 = <&keysn_6>; + unifykey-index-7 = <&keysn_7>; + unifykey-index-8 = <&keysn_8>; + unifykey-index-9 = <&keysn_9>; + unifykey-index-10= <&keysn_10>; + unifykey-index-11= <&keysn_11>; + unifykey-index-12= <&keysn_12>; + unifykey-index-13= <&keysn_13>; + unifykey-index-14= <&keysn_14>; + unifykey-index-15= <&keysn_15>; + unifykey-index-16= <&keysn_16>; + + keysn_0: key_0{ + key-name = "usid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_1:key_1{ + key-name = "mac"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_2:key_2{ + key-name = "hdcp"; + key-device = "secure"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_3:key_3{ + key-name = "secure_boot_set"; + key-device = "efuse"; + key-permit = "write"; + }; + keysn_4:key_4{ + key-name = "mac_bt"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_5:key_5{ + key-name = "mac_wifi"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_6:key_6{ + key-name = "hdcp2_tx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_7:key_7{ + key-name = "hdcp2_rx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_8:key_8{ + key-name = "widevinekeybox"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_9:key_9{ + key-name = "deviceid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_10:key_10{ + key-name = "hdcp22_fw_private"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_11:key_11{ + key-name = "PlayReadykeybox25"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_12:key_12{ + key-name = "prpubkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_13:key_13{ + key-name = "prprivkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_14:key_14{ + key-name = "attestationkeybox";// attestation key + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_15:key_15{ + key-name = "region_code"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_16:key_16{ + key-name = "netflix_mgkid"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + };//End unifykey + + efusekey:efusekey{ + keynum = <4>; + key0 = <&key_0>; + key1 = <&key_1>; + key2 = <&key_2>; + key3 = <&key_3>; + key_0:key_0{ + keyname = "mac"; + offset = <0>; + size = <6>; + }; + key_1:key_1{ + keyname = "mac_bt"; + offset = <6>; + size = <6>; + }; + key_2:key_2{ + keyname = "mac_wifi"; + offset = <12>; + size = <6>; + }; + key_3:key_3{ + keyname = "usid"; + offset = <18>; + size = <16>; + }; + };//End efusekey + + amlvecm { + compatible = "amlogic, vecm"; + dev_name = "aml_vecm"; + status = "okay"; + gamma_en = <0>;/*1:enabel ;0:disable*/ + wb_en = <0>;/*1:enabel ;0:disable*/ + cm_en = <0>;/*1:enabel ;0:disable*/ + /*0: 709/601 1: bt2020*/ + tx_op_color_primary = <0>; + }; + + amdolby_vision { + compatible = "amlogic, dolby_vision_sm1"; + dev_name = "aml_amdolby_vision_driver"; + status = "okay"; + tv_mode = <0>;/*1:enabel ;0:disable*/ + }; + + /* Audio Related start */ + pdm_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, pdm_dummy_codec"; + status = "okay"; + }; + dummy_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, aml_dummy_codec"; + status = "okay"; + }; + amlogic_codec:t9015{ + #sound-dai-cells = <0>; + compatible = "amlogic, aml_codec_T9015"; + reg = <0xFF632000 0x2000>; + is_auge_used = <1>; /* meson or auge chipset used */ + tocodec_inout = <1>; + tdmout_index = <1>; + ch0_sel = <0>; + ch1_sel = <1>; + + status = "okay"; + }; + + auge_sound { + compatible = "amlogic, g12a-sound-card"; + aml-audio-card,name = "AML-AUGESOUND"; + + /*avout mute gpio*/ + avout_mute-gpios = <&gpio_ao GPIOAO_2 GPIO_ACTIVE_HIGH>; + + aml-audio-card,dai-link@0 { + format = "dsp_a"; + mclk-fs = <512>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdma>; + frame-master = <&tdma>; + /* slave mode */ + /* + * bitclock-master = <&tdmacodec>; + * frame-master = <&tdmacodec>; + */ + suffix-name = "alsaPORT-pcm"; + tdmacpu: cpu { + sound-dai = <&tdma>; + dai-tdm-slot-tx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-rx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-num = <8>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <24576000>; + }; + tdmacodec: codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@1 { + format = "i2s";// "dsp_a"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdmb>; + frame-master = <&tdmb>; + /* slave mode */ + //bitclock-master = <&tdmbcodec>; + //frame-master = <&tdmbcodec>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-i2s"; + cpu { + sound-dai = <&tdmb>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + /* + * dai-tdm-slot-tx-mask = + * <1 1 1 1 1 1 1 1>; + * dai-tdm-slot-rx-mask = + * <1 1 1 1 1 1 1 1>; + * dai-tdm-slot-num = <8>; + */ + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmbcodec: codec { + sound-dai = <&dummy_codec &dummy_codec + &amlogic_codec &ad82584f_62>; + }; + }; + + aml-audio-card,dai-link@2 { + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdmc>; + frame-master = <&tdmc>; + /* slave mode */ + //bitclock-master = <&tdmccodec>; + //frame-master = <&tdmccodec>; + /* suffix-name, sync with android audio hal used for */ + //suffix-name = "alsaPORT-tdm"; + cpu { + sound-dai = <&tdmc>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmccodec: codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@3 { + mclk-fs = <64>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-pdm"; + cpu { + sound-dai = <&pdm>; + }; + codec { + sound-dai = <&pdm_codec>; + }; + }; + + aml-audio-card,dai-link@4 { + mclk-fs = <128>; + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-spdif"; + cpu { + sound-dai = <&spdifa>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@5 { + mclk-fs = <128>; + continuous-clock; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-spdifb"; + cpu { + sound-dai = <&spdifb>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + aml-audio-card,dai-link@6 { + mclk-fs = <256>; + suffix-name = "alsaPORT-earc"; + cpu { + sound-dai = <&earc>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + }; + audiolocker: locker { + compatible = "amlogic, audiolocker"; + clocks = <&clkaudio CLKID_AUDIO_LOCKER_OUT + &clkaudio CLKID_AUDIO_LOCKER_IN + &clkaudio CLKID_AUDIO_MCLK_D + &clkaudio CLKID_AUDIO_MCLK_E + &clkc CLKID_MPLL1 + &clkc CLKID_MPLL2>; + clock-names = "lock_out", "lock_in", "out_src", + "in_src", "out_calc", "in_ref"; + interrupts = ; + interrupt-names = "irq"; + frequency = <49000000>; /* pll */ + dividor = <49>; /* locker's parent */ + status = "disabled"; + }; + /* Audio Related end */ + dvb { + compatible = "amlogic, dvb"; + dev_name = "dvb"; + status = "okay"; +// fe0_mode = "internal"; +// fe0_tuner = <&tuner>; + /*"parallel","serial","disable"*/ +// ts2 = "parallel"; +// ts2_control = <0>; +// ts2_invert = <0>; + interrupts = <0 23 1 + 0 5 1 + 0 53 1 + 0 19 1 + 0 25 1 + 0 18 1 + 0 24 1>; + interrupt-names = "demux0_irq", + "demux1_irq", + "demux2_irq", + "dvr0_irq", + "dvr1_irq", + "dvrfill0_fill", + "dvrfill1_flush"; + clocks = <&clkc CLKID_DEMUX + &clkc CLKID_AHB_ARB0 + &clkc CLKID_DOS_PARSER>; + clock-names = "demux", "ahbarb0", "uparsertop"; + }; + tuner: tuner { + compatible = "amlogic, tuner"; + status = "okay"; + tuner_name = "mxl661_tuner"; + tuner_i2c_adap = <&i2c1>; + tuner_i2c_addr = <0x60>; + tuner_xtal = <0>; /* 0: 16MHz, 1: 24MHz */ + tuner_xtal_mode = <0>; + /* NO_SHARE_XTAL(0) + * SLAVE_XTAL_SHARE(1) + */ + tuner_xtal_cap = <30>; /* when tuner_xtal_mode = 1, set 25 */ + }; + + p_tsensor: p_tsensor@ff634800 { + compatible = "amlogic, r1p1-tsensor"; + device_name = "meson-pthermal"; + status = "okay"; + reg = <0xff634800 0x50>, + <0xff800268 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 35 0>; + clocks = <&clkc CLKID_TS_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + d_tsensor: d_tsensor@ff634c00 { + compatible = "amlogic, r1p1-tsensor"; + device_name = "meson-dthermal"; + status = "okay"; + reg = <0xff634c00 0x50>, + <0xff800230 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 36 0>; + clocks = <&clkc CLKID_TS_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + meson_cooldev: meson-cooldev@0 { + status = "okay"; + compatible = "amlogic, meson-cooldev"; + device_name = "mcooldev"; + cooling_devices { + cpufreq_cool_cluster0 { + min_state = <1000000>; + dyn_coeff = <125>; + cluster_id = <0>; + node_name = "cpufreq_cool0"; + device_type = "cpufreq"; + }; + cpucore_cool_cluster0 { + min_state = <1>; + dyn_coeff = <0>; + cluster_id = <0>; + node_name = "cpucore_cool0"; + device_type = "cpucore"; + }; + gpufreq_cool { + min_state = <400>; + dyn_coeff = <215>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "gpufreq_cool0"; + device_type = "gpufreq"; + }; + gpucore_cool { + min_state = <1>; + dyn_coeff = <0>; + cluster_id = <0>; + node_name = "gpucore_cool0"; + device_type = "gpucore"; + }; + }; + cpufreq_cool0:cpufreq_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + cpucore_cool0:cpucore_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + gpufreq_cool0:gpufreq_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + gpucore_cool0:gpucore_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + }; + /*meson cooling devices end*/ + + thermal-zones { + soc_thermal: soc_thermal { + polling-delay = <1000>; + polling-delay-passive = <100>; + sustainable-power = <1410>; + thermal-sensors = <&p_tsensor 0>; + trips { + pswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + pcontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + phot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + pcritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + + cooling-maps { + cpufreq_cooling_map { + trip = <&pcontrol>; + cooling-device = <&cpufreq_cool0 0 4>; + contribution = <1024>; + }; + cpucore_cooling_map { + trip = <&pcontrol>; + cooling-device = <&cpucore_cool0 0 3>; + contribution = <1024>; + }; + gpufreq_cooling_map { + trip = <&pcontrol>; + cooling-device = <&gpufreq_cool0 0 4>; + contribution = <1024>; + }; + gpucore_cooling_map { + trip = <&pcontrol>; + cooling-device = <&gpucore_cool0 0 2>; + contribution = <1024>; + }; + }; + }; + ddr_thermal: ddr_thermal { + polling-delay = <2000>; + polling-delay-passive = <1000>; + sustainable-power = <1410>; + thermal-sensors = <&d_tsensor 1>; + trips { + dswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + dcontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + dhot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + dcritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + + }; + }; + /*thermal zone end*/ + + cpu_opp_table0: cpu_opp_table0 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <730000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <730000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <730000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <750000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <770000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <780000>; + }; + opp06 { + opp-hz = /bits/ 64 <1404000000>; + opp-microvolt = <790000>; + }; + opp07 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <800000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <810000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <850000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <900000>; + }; + opp11 { + opp-hz = /bits/ 64 <1908000000>; + opp-microvolt = <950000>; + }; + }; + + cpufreq-meson { + compatible = "amlogic, cpufreq-meson"; + pinctrl-names = "default"; + pinctrl-0 = <&pwm_ao_d_pins3>; + status = "okay"; + }; + +}; /* end of / */ + +&meson_fb { + status = "okay"; + display_size_default = <1920 1080 1920 2160 32>; + mem_size = <0x00800000 0x1980000 0x100000 0x100000 0x800000>; + logo_addr = "0x7f800000"; + mem_alloc = <0>; + pxp_mode = <0>; /** 0:normal mode 1:pxp mode */ +}; + +&pwm_AO_cd { + status = "okay"; +}; + +&i2c0 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&i2c0_master_pins2>; + clock-frequency = <400000>; + + gt9xx@5d { + compatible = "goodix,gt9xx"; + status = "disabled"; + reg = <0x5d>; + reset-gpio = <&gpio GPIOZ_9 0x00>; + irq-gpio = <&gpio GPIOZ_3 0x00>; + }; + + ftxx@38 { + compatible = "focaltech,fts"; + status = "disabled"; + reg = <0x38>; + reset-gpio = <&gpio GPIOZ_9 0x00>; + irq-gpio = <&gpio GPIOZ_3 0x00>; + x_max = <600>; + y_max = <1024>; + max-touch-number = <10>; + }; +}; + +&i2c2 { + status = "disabled"; + pinctrl-names="default"; + pinctrl-0=<&i2c2_master_pins2>; + clock-frequency = <100000>; +}; + +&i2c3 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&i2c3_master_pins2>; + clock-frequency = <100000>; /* default 100k */ + + /* for ref board */ + ad82584f_62: ad82584f_62@62 { + compatible = "ESMT, ad82584f"; + #sound-dai-cells = <0>; + reg = <0x31>; + status = "okay"; + reset_pin = <&gpio GPIOA_5 0>; + no_mclk; + }; + + bl_extern_i2c { + compatible = "bl_extern, i2c"; + dev_name = "lp8556"; + reg = <0x2c>; + status = "disabled"; + }; +}; + +&audiobus { + tdma: tdm@0 { + compatible = "amlogic, sm1-snd-tdma"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 1>; + dai-tdm-oe-lane-slot-mask-out = <1 0>; + dai-tdm-clk-sel = <0>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_A + &clkc CLKID_MPLL0>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmout_a &tdmin_a>; + + status = "okay"; + }; + + tdmb: tdm@1 { + compatible = "amlogic, sm1-snd-tdmb"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 1 0 0>; + dai-tdm-lane-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <1>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_B + &clkc CLKID_MPLL1 + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_A>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; + + mclk_pad = <0>; /* 0: mclk_0; 1: mclk_1 */ + + /* + * 0: tdmout_a; + * 1: tdmout_b; + * 2: tdmout_c; + * 3: spdifout; + * 4: spdifout_b; + */ + samesource_sel = <3>; + + status = "okay"; + }; + + tdmc: tdm@2 { + compatible = "amlogic, sm1-snd-tdmc"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <1 0 0 0>; + #dai-tdm-lane-slot-mask-out = <1 0 1 1>; + #dai-tdm-lane-oe-slot-mask-in = <0 0 0 0>; + #dai-tdm-lane-oe-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <2>; + + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmc_mclk &tdmout_c &tdmin_c>; + mclk_pad = <0>; /* 0: mclk_0; 1: mclk_1 */ + + status = "okay"; + }; + + spdifa: spdif@0 { + compatible = "amlogic, sm1-snd-spdif-a"; + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 + &clkc CLKID_FCLK_DIV4 + &clkaudio CLKID_AUDIO_GATE_SPDIFIN + &clkaudio CLKID_AUDIO_GATE_SPDIFOUT_A + &clkaudio CLKID_AUDIO_SPDIFIN + &clkaudio CLKID_AUDIO_SPDIFOUT_A>; + clock-names = "sysclk", "fixed_clk", "gate_spdifin", + "gate_spdifout", "clk_spdifin", "clk_spdifout"; + interrupts = + ; + + interrupt-names = "irq_spdifin"; + pinctrl-names = "spdif_pins"; + pinctrl-0 = <&spdifout &spdifin>; + + status = "okay"; + }; + spdifb: spdif@1 { + compatible = "amlogic, sm1-snd-spdif-b"; + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 /*CLKID_HIFI_PLL*/ + &clkaudio CLKID_AUDIO_GATE_SPDIFOUT_B + &clkaudio CLKID_AUDIO_SPDIFOUT_B>; + clock-names = "sysclk", + "gate_spdifout", "clk_spdifout"; + + status = "okay"; + }; + pdm: pdm { + compatible = "amlogic, sm1-snd-pdm"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_PDM + &clkc CLKID_FCLK_DIV3 + &clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_PDMIN0 + &clkaudio CLKID_AUDIO_PDMIN1>; + clock-names = "gate", + "sysclk_srcpll", + "dclk_srcpll", + "pdm_dclk", + "pdm_sysclk"; + + pinctrl-names = "pdm_pins"; + pinctrl-0 = <&pdmin>; + + /* mode 0~4, defalut:1 */ + filter_mode = <1>; + + status = "okay"; + }; + + earc:earc { + compatible = "amlogic, sm1-snd-earc"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_EARCRX + &clkaudio CLKID_EARCRX_CMDC + &clkaudio CLKID_EARCRX_DMAC + &clkc CLKID_FCLK_DIV5 + &clkc CLKID_FCLK_DIV3 + >; + clock-names = "rx_gate", + "rx_cmdc", + "rx_dmac", + "rx_cmdc_srcpll", + "rx_dmac_srcpll"; + + interrupts = < + GIC_SPI 88 IRQ_TYPE_EDGE_RISING + GIC_SPI 87 IRQ_TYPE_EDGE_RISING + >; + interrupt-names = "rx_cmdc", "rx_dmac"; + + status = "okay"; + }; + + asrca: resample@0 { + compatible = "amlogic, sm1-resample"; + clocks = <&clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_MCLK_F + &clkaudio CLKID_AUDIO_RESAMPLE_A>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + /*same with toddr_src + * TDMIN_A, 0 + * TDMIN_B, 1 + * TDMIN_C, 2 + * SPDIFIN, 3 + * PDMIN, 4 + * NONE, + * TDMIN_LB, 6 + * LOOPBACK, 7 + */ + resample_module = <4>; + status = "disabled"; + }; + + vad:vad { + compatible = "amlogic, snd-vad"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_TOVAD + &clkc CLKID_FCLK_DIV5 + &clkaudio CLKID_AUDIO_VAD>; + clock-names = "gate", "pll", "clk"; + + interrupts = ; + interrupt-names = "irq_wakeup", "irq_frame_sync"; + + /* + * Data src sel: + * 0: tdmin_a; + * 1: tdmin_b; + * 2: tdmin_c; + * 3: spdifin; + * 4: pdmin; + * 5: loopback_b; + * 6: tdmin_lb; + * 7: loopback_a; + */ + src = <4>; + + /* + * deal with hot word in user space or kernel space + * 0: in user space + * 1: in kernel space + */ + level = <1>; + + status = "okay"; + }; +}; /* end of audiobus */ + +&pinctrl_periphs { + tdmout_a: tdmout_a { + mux { /* GPIOX_11, GPIOX_10, GPIOX_9 */ + groups = "tdma_sclk", + "tdma_fs", + "tdma_dout0"; + function = "tdma_out"; + }; + }; + + tdmin_a: tdmin_a { + mux { /* GPIOX_8 */ + groups = "tdma_din1"; + function = "tdma_in"; + }; + }; + + tdmb_mclk: tdmb_mclk { + mux { + groups = "mclk0_a"; + function = "mclk0"; + drive-strength = <2>; + }; + }; + tdmout_b: tdmout_b { + mux { /* GPIOA_1, GPIOA_2, GPIOA_3 */ + groups = "tdmb_sclk", + "tdmb_fs", + "tdmb_dout0"; + function = "tdmb_out"; + drive-strength = <2>; + }; + }; + + tdmin_b:tdmin_b { + mux { /* GPIOA_4 */ + groups = "tdmb_din1" + /*,"tdmb_slv_sclk", "tdmb_slv_fs"*/; + function = "tdmb_in"; + drive-strength = <2>; + }; + }; + + tdmc_mclk: tdmc_mclk { + mux { /* GPIOA_11 */ + groups = "mclk1_a"; + function = "mclk1"; + }; + }; + + tdmout_c:tdmout_c { + mux { /* GPIOA_12, GPIOA_13, GPIOA_8, GPIOA_7*/ + groups = "tdmc_sclk_a", + "tdmc_fs_a", + "tdmc_dout0_a" + /*, "tdmc_dout2", + * "tdmc_dout3" + */; + function = "tdmc_out"; + }; + }; + + tdmin_c:tdmin_c { + mux { /* GPIOA_10 */ + groups = "tdmc_din0_a"; + function = "tdmc_in"; + }; + }; + + spdifin: spdifin { + mux {/* GPIOH_5 */ + groups = "spdif_in_h"; + function = "spdif_in"; + }; + }; + + pdmin: pdmin { + mux { /* GPIOA_5, GPIOA_6, GPIOA_8, GPIOA_9, GPIOA_7 */ + groups = "pdm_din0_a", + /*"pdm_din1_a",*/ + "pdm_din2_a", + /*"pdm_din3_a",*/ + "pdm_dclk_a"; + function = "pdm"; + }; + }; + + bl_pwm_off_pins:bl_pwm_off_pin { + mux { + pins = "GPIOH_5"; + function = "gpio_periphs"; + output-high; + }; + }; + + clk12_24_z_pins:clk12_24_z_pins { + mux { + groups = "clk12_24_z"; + function = "clk12_24_ee"; + drive-strength = <3>; + }; + }; + + gen_clk_ee_z: gen_clk_ee_z { + mux { + groups="gen_clk_ee_z"; + function="gen_clk_ee"; + drive-strength = <3>; + }; + }; + + cam_dvp_pins:cam_dvp_pins { + mux { + groups = "bt656_a_vs", "bt656_a_hs", "bt656_a_clk", + "bt656_a_din0", "bt656_a_din1", "bt656_a_din2", + "bt656_a_din3", "bt656_a_din4", "bt656_a_din5", + "bt656_a_din6", "bt656_a_din7"; + function = "bt656"; + }; + }; + + +}; /* end of pinctrl_periphs */ + +&pinctrl_aobus { + spdifout: spdifout { + mux { /* GPIOAO_10 */ + groups = "spdif_out_ao"; + function = "spdif_out_ao"; + }; + }; +}; /* end of pinctrl_aobus */ + +&audio_data { + status = "okay"; +}; + +/* Audio Related End */ + +&pwm_ef { + status = "okay"; +}; + +&dwc3 { + status = "okay"; +}; + +&usb2_phy_v2 { + status = "okay"; + portnum = <2>; +}; + +&usb3_phy_v2 { + status = "okay"; + portnum = <0>; + otg = <1>; + gpio-vbus-power = "GPIOH_6"; + gpios = <&gpio GPIOH_6 GPIO_ACTIVE_HIGH>; +}; + +&dwc2_a { + status = "okay"; + /** 0: normal, 1: otg+dwc3 host only, 2: otg+dwc3 device only*/ + controller-type = <3>; +}; +ðmac { + status = "okay"; + pinctrl-names = "internal_eth_pins"; + pinctrl-0 = <&internal_eth_pins>; + mc_val = <0x4be04>; + + internal_phy=<1>; +}; + +&uart_A { + status = "okay"; +}; + +/*if you want to use vdin just modify status to "ok"*/ +&vdin0 { + memory-region = <&vdin0_cma_reserved>; + status = "okay"; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + *bit4:support yuv422 10bit full pack mode (from txl new add) + */ + tv_bit_mode = <0x15>; +}; +&vdin1 { + memory-region = <&vdin1_cma_reserved>; + status = "okay"; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + */ + tv_bit_mode = <1>; +}; + + +&sd_emmc_c { + status = "okay"; + emmc { + caps = "MMC_CAP_8_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + /* "MMC_CAP_1_8V_DDR", */ + "MMC_CAP_HW_RESET", + "MMC_CAP_ERASE", + "MMC_CAP_CMD23"; + caps2 = "MMC_CAP2_HS200"; + /* "MMC_CAP2_HS400";*/ + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&sd_emmc_b { + status = "okay"; + sd { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED"; + f_min = <400000>; + f_max = <50000000>; + }; +}; + +&sd_emmc_a { + status = "okay"; + sdio { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + "MMC_CAP_UHS_SDR12", + "MMC_CAP_UHS_SDR25", + "MMC_CAP_UHS_SDR50", + "MMC_CAP_UHS_SDR104", + "MMC_PM_KEEP_POWER", + "MMC_CAP_SDIO_IRQ"; + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&nand { + status = "disabled"; + plat-names = "bootloader","nandnormal"; + plat-num = <2>; + plat-part-0 = <&bootloader>; + plat-part-1 = <&nandnormal>; + bootloader: bootloader{ + enable_pad ="ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <1>; + part_num = <0>; + rb_detect = <1>; + }; + nandnormal: nandnormal{ + enable_pad ="ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + plane_mode = "twoplane"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <2>; + part_num = <3>; + partition = <&nand_partitions>; + rb_detect = <1>; + }; + nand_partitions:nand_partition{ + /* + * if bl_mode is 1, tpl size was generate by + * fip_copies * fip_size which + * will not skip bad when calculating + * the partition size; + * + * if bl_mode is 0, + * tpl partition must be comment out. + */ + tpl{ + offset=<0x0 0x0>; + size=<0x0 0x0>; + }; + logo{ + offset=<0x0 0x0>; + size=<0x0 0x200000>; + }; + recovery{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + boot{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + system{ + offset=<0x0 0x0>; + size=<0x0 0x4000000>; + }; + data{ + offset=<0xffffffff 0xffffffff>; + size=<0x0 0x0>; + }; + }; +}; + +&pcie_A { + reset-gpio = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; + status = "okay"; +}; + +&meson_cooldev { + status = "okay"; +}; + +&defendkey { + status = "okay"; +}; + diff --git a/arch/arm/boot/dts/amlogic/sm1_s905x3_ac213.dts b/arch/arm/boot/dts/amlogic/sm1_s905x3_ac213.dts new file mode 100644 index 000000000000..09ae70cc028b --- /dev/null +++ b/arch/arm/boot/dts/amlogic/sm1_s905x3_ac213.dts @@ -0,0 +1,1624 @@ +/* + * arch/arm64/boot/dts/amlogic/sm1_s905x3_ac213.dts + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +/dts-v1/; + +#include "mesonsm1.dtsi" +#include "partition_mbox_normal.dtsi" +#include "mesonsm1_skt-panel.dtsi" + +/ { + model = "Amlogic"; + amlogic-dt-id = "sm1_ac213_2g"; + compatible = "amlogic, g12a"; + interrupt-parent = <&gic>; + #address-cells = <1>; + #size-cells = <1>; + + aliases { + serial0 = &uart_AO; + serial1 = &uart_A; + serial2 = &uart_B; + serial3 = &uart_C; + serial4 = &uart_AO_B; + tsensor0 = &p_tsensor; + tsensor1 = &d_tsensor; + i2c0 = &i2c0; + i2c1 = &i2c1; + i2c2 = &i2c2; + i2c3 = &i2c3; + i2c4 = &i2c_AO; + }; + + memory@00000000 { + device_type = "memory"; + linux,usable-memory = <0x000000 0x80000000>; + }; + + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + /* global autoconfigured region for contiguous allocations */ + ramoops@0x07400000 { + compatible = "ramoops"; + reg = <0x07400000 0x00100000>; + record-size = <0x8000>; + console-size = <0x8000>; + ftrace-size = <0x20000>; + }; + + secmon_reserved:linux,secmon { + compatible = "shared-dma-pool"; + reusable; + size = <0x400000>; + alignment = <0x400000>; + alloc-ranges = <0x05000000 0x400000>; + }; + secos_reserved:linux,secos { + status = "disable"; + compatible = "amlogic, aml_secos_memory"; + reg = <0x05300000 0x2000000>; + no-map; + }; + logo_reserved:linux,meson-fb { + compatible = "shared-dma-pool"; + reusable; + size = <0x800000>; + alignment = <0x400000>; + alloc-ranges = <0x7f800000 0x800000>; + }; + ion_cma_reserved:linux,ion-dev { + compatible = "shared-dma-pool"; + reusable; + size = <0x8000000>; + alignment = <0x400000>; + alloc-ranges = <0x30000000 0x50000000>; + }; + //di_reserved:linux,di { + //compatible = "amlogic, di-mem"; + /* buffer_size = 3621952(yuv422 8bit) */ + /* 4179008(yuv422 10bit full pack mode) */ + /** 10x3621952=34.6M(0x23) support 8bit **/ + /** 10x4736064=45.2M(0x2e) support 12bit **/ + /** 10x4179008=40M(0x28) support 10bit **/ + //size = <0x2800000>; + //no-map; + //}; + /*di CMA pool */ + di_cma_reserved:linux,di_cma { + compatible = "shared-dma-pool"; + reusable; + /* buffer_size = 3621952(yuv422 8bit) + * | 4736064(yuv422 10bit) + * | 4074560(yuv422 10bit full pack mode) + * 10x3621952=34.6M(0x23) support 8bit + * 10x4736064=45.2M(0x2e) support 12bit + * 10x4074560=40M(0x28) support 10bit + */ + size = <0x02800000>; + alignment = <0x400000>; + }; + /* POST PROCESS MANAGER */ + ppmgr_reserved:linux,ppmgr { + compatible = "shared-dma-pool"; + size = <0x0>; + }; + + codec_mm_cma:linux,codec_mm_cma { + compatible = "shared-dma-pool"; + reusable; + /* ion_codec_mm max can alloc size 80M*/ + size = <0x13400000>; + alignment = <0x400000>; + linux,contiguous-region; + alloc-ranges = <0x30000000 0x50000000>; + }; + /* codec shared reserved */ + codec_mm_reserved:linux,codec_mm_reserved { + compatible = "amlogic, codec-mm-reserved"; + size = <0x0>; + alignment = <0x100000>; + //no-map; + }; + /* vdin0 CMA pool */ + vdin0_cma_reserved:linux,vdin0_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16+4 M */ + size = <0x04000000>; + alignment = <0x400000>; + }; + /* vdin1 CMA pool */ + vdin1_cma_reserved:linux,vdin1_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16 M */ + size = <0x04000000>; + alignment = <0x400000>; + }; + vm0_cma_reserved:linux,vm0_cma { + compatible = "shared-dma-pool"; + reusable; + size = <0x2000000>; + alignment = <0x400000>; + }; + }; + + amlogic_battery:dummy-battery { + compatible = "amlogic, dummy-battery"; + status = "disabled"; + }; + + amlogic_charger:dummy-charger { + compatible = "amlogic, dummy-charger"; + status = "disabled"; + }; + + gpioleds { + compatible = "gpio-leds"; + status = "disabled"; + + net_red { + label="net_red"; + /*gpios=<&gpio GPIOA_14 GPIO_ACTIVE_LOW>;*/ + default-state ="on"; + }; + + net_green { + label="net_green"; + /*gpios=<&gpio GPIOA_15 GPIO_ACTIVE_HIGH>;*/ + default-state ="on"; + }; + + remote_led { + label = "remote_led"; + gpios = <&gpio_ao GPIOAO_10 GPIO_ACTIVE_LOW>; + default-state = "off"; + linux,default-trigger = "rc_feedback"; + }; + + sys_led { + label="sys_led"; + gpios=<&gpio_ao GPIOAO_11 GPIO_ACTIVE_LOW>; + default-state ="on"; + }; + }; + + cvbsout { + compatible = "amlogic, cvbsout-sm1"; + dev_name = "cvbsout"; + status = "okay"; + clocks = <&clkc CLKID_VCLK2_ENCI + &clkc CLKID_VCLK2_VENCI0 + &clkc CLKID_VCLK2_VENCI1 + &clkc CLKID_DAC_CLK>; + clock-names = "venci_top_gate", + "venci_0_gate", + "venci_1_gate", + "vdac_clk_gate"; + /* clk path */ + /* 0:vid_pll vid2_clk */ + /* 1:gp0_pll vid2_clk */ + /* 2:vid_pll vid1_clk */ + /* 3:gp0_pll vid1_clk */ + clk_path = <0>; + + /* performance: reg_address, reg_value */ + /* sm1 */ + performance = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x8080 + 0x1b05 0xfd + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + performance_sarft = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x0 + 0x1b05 0x9 + 0x1c59 0xfc48 + 0xffff 0x0>; /* ending flag */ + performance_revB_telecom = <0x1bf0 0x9 + 0x1b56 0x546 + 0x1b12 0x8080 + 0x1b05 0x9 + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + }; + + bt-dev{ + compatible = "amlogic, bt-dev"; + dev_name = "bt-dev"; + status = "okay"; + gpio_reset = <&gpio GPIOX_17 GPIO_ACTIVE_HIGH>; + gpio_hostwake = <&gpio GPIOX_19 GPIO_ACTIVE_HIGH>; + }; + + wifi{ + compatible = "amlogic, aml_wifi"; + dev_name = "aml_wifi"; + status = "okay"; + interrupt_pin = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; + irq_trigger_type = "GPIO_IRQ_LOW"; + power_on_pin = <&gpio GPIOX_6 GPIO_ACTIVE_HIGH>; + dhd_static_buf; //if use bcm wifi, config dhd_static_buf + pinctrl-names = "default"; + pinctrl-0 = <&pwm_e_pins>; + pwm_config = <&wifi_pwm_conf>; + }; + + wifi_pwm_conf:wifi_pwm_conf{ + pwm_channel1_conf { + pwms = <&pwm_ef MESON_PWM_0 30541 0>; + duty-cycle = <15270>; + times = <10>; + }; + pwm_channel2_conf { + pwms = <&pwm_ef MESON_PWM_2 30500 0>; + duty-cycle = <15250>; + times = <12>; + }; + }; + + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + + codec_mm { + compatible = "amlogic, codec, mm"; + memory-region = <&codec_mm_cma &codec_mm_reserved>; + dev_name = "codec_mm"; + status = "okay"; + }; + + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + + ppmgr { + compatible = "amlogic, ppmgr"; + memory-region = <&ppmgr_reserved>; + dev_name = "ppmgr"; + status = "okay"; + }; + + deinterlace { + compatible = "amlogic, deinterlace"; + status = "okay"; + /* 0:use reserved; 1:use cma; 2:use cma as reserved */ + flag_cma = <1>; + //memory-region = <&di_reserved>; + memory-region = <&di_cma_reserved>; + interrupts = <0 46 1 + 0 40 1>; + interrupt-names = "pre_irq", "post_irq"; + clocks = <&clkc CLKID_VPU_CLKB_TMP_COMP>, + <&clkc CLKID_VPU_CLKB_COMP>; + clock-names = "vpu_clkb_tmp_composite", + "vpu_clkb_composite"; + clock-range = <334 667>; + /* buffer-size = <3621952>;(yuv422 8bit) */ + buffer-size = <4074560>;/*yuv422 fullpack*/ + /* reserve-iomap = "true"; */ + /* if enable nr10bit, set nr10bit-support to 1 */ + post-wr-support = <1>; + nr10bit-support = <1>; + nrds-enable = <1>; + pps-enable = <1>; + }; + ionvideo { + compatible = "amlogic, ionvideo"; + dev_name = "ionvideo"; + status = "okay"; + }; + dvb { + compatible = "amlogic, dvb"; + dev_name = "dvb"; + status = "ok"; + + ts0 = "serial"; + ts0_control = <0x800>; + ts0_invert = <0>; + pinctrl-names = "s_ts0"; + pinctrl-0 = <&dvb_s_ts0_pins>; + + interrupts = <0 23 1 + 0 5 1 + 0 53 1 + 0 19 1 + 0 25 1 + 0 18 1 + 0 24 1>; + interrupt-names = "demux0_irq", + "demux1_irq", + "demux2_irq", + "dvr0_irq", + "dvr1_irq", + "dvrfill0_fill", + "dvrfill1_flush"; + }; + dvbfe { + compatible = "amlogic, dvbfe"; + dev_name = "dvbfe"; + dtv_demod0 = "Avl6762"; + dtv_demod0_i2c_adap = <&i2c3>; + dtv_demod0_i2c_addr = <0x14>; + dtv_demod0_reset_value = <0>; + dtv_demod0_reset_gpio = <&gpio GPIOZ_10 GPIO_ACTIVE_HIGH>; + dtv_demod0_ant_poweron_value = <0>; + dtv_demod0_ant_power_gpio = <&gpio GPIOH_5 GPIO_ACTIVE_HIGH>; + dtv_demod0_tuner_type = <52>; + fe0_dtv_demod = <0>; + fe0_ts = <0>; + fe0_dev = <0>; + }; + unifykey{ + compatible = "amlogic, unifykey"; + status = "ok"; + unifykey-num = <16>; + unifykey-index-0 = <&keysn_0>; + unifykey-index-1 = <&keysn_1>; + unifykey-index-2 = <&keysn_2>; + unifykey-index-3 = <&keysn_3>; + unifykey-index-4 = <&keysn_4>; + unifykey-index-5 = <&keysn_5>; + unifykey-index-6 = <&keysn_6>; + unifykey-index-7 = <&keysn_7>; + unifykey-index-8 = <&keysn_8>; + unifykey-index-9 = <&keysn_9>; + unifykey-index-10= <&keysn_10>; + unifykey-index-11= <&keysn_11>; + unifykey-index-12= <&keysn_12>; + unifykey-index-13= <&keysn_13>; + unifykey-index-14= <&keysn_14>; + unifykey-index-15= <&keysn_15>; + keysn_0: key_0{ + key-name = "usid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_1:key_1{ + key-name = "mac"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_2:key_2{ + key-name = "hdcp"; + key-device = "secure"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_3:key_3{ + key-name = "secure_boot_set"; + key-device = "efuse"; + key-permit = "write"; + }; + keysn_4:key_4{ + key-name = "mac_bt"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_5:key_5{ + key-name = "mac_wifi"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_6:key_6{ + key-name = "hdcp2_tx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_7:key_7{ + key-name = "hdcp2_rx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_8:key_8{ + key-name = "widevinekeybox"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_9:key_9{ + key-name = "deviceid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_10:key_10{ + key-name = "hdcp22_fw_private"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_11:key_11{ + key-name = "PlayReadykeybox25"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_12:key_12{ + key-name = "prpubkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_13:key_13{ + key-name = "prprivkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_14:key_14{ + key-name = "attestationkeybox";// attestation key + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_15:key_15{ + key-name = "netflix_mgkid"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + };//End unifykey + + efusekey:efusekey{ + keynum = <4>; + key0 = <&key_0>; + key1 = <&key_1>; + key2 = <&key_2>; + key3 = <&key_3>; + key_0:key_0{ + keyname = "mac"; + offset = <0>; + size = <6>; + }; + key_1:key_1{ + keyname = "mac_bt"; + offset = <6>; + size = <6>; + }; + key_2:key_2{ + keyname = "mac_wifi"; + offset = <12>; + size = <6>; + }; + key_3:key_3{ + keyname = "usid"; + offset = <18>; + size = <16>; + }; + };//End efusekey + + amlvecm { + compatible = "amlogic, vecm"; + dev_name = "aml_vecm"; + status = "okay"; + gamma_en = <0>;/*1:enabel ;0:disable*/ + wb_en = <0>;/*1:enabel ;0:disable*/ + cm_en = <0>;/*1:enabel ;0:disable*/ + /*0: 709/601 1: bt2020*/ + tx_op_color_primary = <0>; + }; + + amdolby_vision { + compatible = "amlogic, dolby_vision_sm1"; + dev_name = "aml_amdolby_vision_driver"; + status = "okay"; + tv_mode = <0>;/*1:enabel ;0:disable*/ + }; + + /* Audio Related start */ + pdm_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, pdm_dummy_codec"; + status = "okay"; + }; + dummy_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, aml_dummy_codec"; + status = "okay"; + }; + amlogic_codec:t9015{ + #sound-dai-cells = <0>; + compatible = "amlogic, aml_codec_T9015"; + reg = <0xFF632000 0x2000>; + is_auge_used = <1>; /* meson or auge chipset used */ + tocodec_inout = <1>; + tdmout_index = <1>; + ch0_sel = <0>; + ch1_sel = <1>; + + status = "okay"; + }; + audio_effect:eqdrc{ + /*eq_enable = <1>;*/ + /*drc_enable = <1>;*/ + /* + * 0:tdmout_a + * 1:tdmout_b + * 2:tdmout_c + * 3:spdifout + * 4:spdifout_b + */ + eqdrc_module = <1>; + /* max 0xf, each bit for one lane, usually one lane */ + lane_mask = <0x1>; + /* max 0xff, each bit for one channel */ + channel_mask = <0x3>; + }; + auge_sound { + compatible = "amlogic, g12a-sound-card"; + aml-audio-card,name = "AML-AUGESOUND"; + + /*avout mute gpio*/ + avout_mute-gpios = <&gpio_ao GPIOAO_2 GPIO_ACTIVE_HIGH>; + + aml-audio-card,dai-link@0 { + format = "dsp_a"; + mclk-fs = <512>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdma>; + frame-master = <&tdma>; + /* slave mode */ + /* + * bitclock-master = <&tdmacodec>; + * frame-master = <&tdmacodec>; + */ + suffix-name = "alsaPORT-pcm"; + tdmacpu: cpu { + sound-dai = <&tdma>; + dai-tdm-slot-tx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-rx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-num = <8>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <24576000>; + }; + tdmacodec: codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@1 { + format = "i2s";// "dsp_a"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdmb>; + frame-master = <&tdmb>; + /* slave mode */ + //bitclock-master = <&tdmbcodec>; + //frame-master = <&tdmbcodec>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-i2s"; + cpu { + sound-dai = <&tdmb>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + /* + * dai-tdm-slot-tx-mask = + * <1 1 1 1 1 1 1 1>; + * dai-tdm-slot-rx-mask = + * <1 1 1 1 1 1 1 1>; + * dai-tdm-slot-num = <8>; + */ + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmbcodec: codec { + sound-dai = <&dummy_codec &dummy_codec + &amlogic_codec /*&ad82584f_62*/>; + }; + }; + + aml-audio-card,dai-link@2 { + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdmc>; + frame-master = <&tdmc>; + /* slave mode */ + //bitclock-master = <&tdmccodec>; + //frame-master = <&tdmccodec>; + /* suffix-name, sync with android audio hal used for */ + //suffix-name = "alsaPORT-tdm"; + cpu { + sound-dai = <&tdmc>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmccodec: codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@3 { + mclk-fs = <64>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-pdm"; + cpu { + sound-dai = <&pdm>; + }; + codec { + sound-dai = <&pdm_codec>; + }; + }; + + aml-audio-card,dai-link@4 { + mclk-fs = <128>; + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-spdif"; + cpu { + sound-dai = <&spdifa>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + /* spdif_b to hdmi, only playback */ + aml-audio-card,dai-link@5 { + mclk-fs = <128>; + continuous-clock; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-spdifb"; + cpu { + sound-dai = <&spdifb>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + aml-audio-card,dai-link@6 { + mclk-fs = <256>; + suffix-name = "alsaPORT-earc"; + cpu { + sound-dai = <&earc>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + }; + audiolocker: locker { + compatible = "amlogic, audiolocker"; + clocks = <&clkaudio CLKID_AUDIO_LOCKER_OUT + &clkaudio CLKID_AUDIO_LOCKER_IN + &clkaudio CLKID_AUDIO_MCLK_D + &clkaudio CLKID_AUDIO_MCLK_E + &clkc CLKID_MPLL1 + &clkc CLKID_MPLL2>; + clock-names = "lock_out", "lock_in", "out_src", + "in_src", "out_calc", "in_ref"; + interrupts = ; + interrupt-names = "irq"; + frequency = <49000000>; /* pll */ + dividor = <49>; /* locker's parent */ + status = "disabled"; + }; + /* Audio Related end */ + p_tsensor: p_tsensor@ff634594 { + compatible = "amlogic, r1p1-tsensor"; + device_name = "meson-pthermal"; + status = "okay"; + reg = <0xff634800 0x50>, + <0xff800268 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 35 0>; + clocks = <&clkc CLKID_TS_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + d_tsensor: d_tsensor@ff800228 { + compatible = "amlogic, r1p1-tsensor"; + device_name = "meson-dthermal"; + status = "okay"; + reg = <0xff634c00 0x50>, + <0xff800230 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 36 0>; + clocks = <&clkc CLKID_TS_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + meson_cooldev: meson-cooldev@0 { + status = "okay"; + compatible = "amlogic, meson-cooldev"; + device_name = "mcooldev"; + cooling_devices { + cpufreq_cool_cluster0 { + min_state = <1000000>; + dyn_coeff = <125>; + cluster_id = <0>; + node_name = "cpufreq_cool0"; + device_type = "cpufreq"; + }; + cpucore_cool_cluster0 { + min_state = <1>; + dyn_coeff = <0>; + cluster_id = <0>; + node_name = "cpucore_cool0"; + device_type = "cpucore"; + }; + gpufreq_cool { + min_state = <400>; + dyn_coeff = <215>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "gpufreq_cool0"; + device_type = "gpufreq"; + }; + gpucore_cool { + min_state = <1>; + dyn_coeff = <0>; + cluster_id = <0>; + node_name = "gpucore_cool0"; + device_type = "gpucore"; + }; + }; + cpufreq_cool0:cpufreq_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + cpucore_cool0:cpucore_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + gpufreq_cool0:gpufreq_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + gpucore_cool0:gpucore_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + }; + /*meson cooling devices end*/ + + thermal-zones { + soc_thermal: soc_thermal { + polling-delay = <1000>; + polling-delay-passive = <100>; + sustainable-power = <1410>; + thermal-sensors = <&p_tsensor 0>; + trips { + pswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + pcontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + phot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + pcritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + + cooling-maps { + cpufreq_cooling_map { + trip = <&pcontrol>; + cooling-device = <&cpufreq_cool0 0 4>; + contribution = <1024>; + }; + cpucore_cooling_map { + trip = <&pcontrol>; + cooling-device = <&cpucore_cool0 0 3>; + contribution = <1024>; + }; + gpufreq_cooling_map { + trip = <&pcontrol>; + cooling-device = <&gpufreq_cool0 0 4>; + contribution = <1024>; + }; + gpucore_cooling_map { + trip = <&pcontrol>; + cooling-device = <&gpucore_cool0 0 2>; + contribution = <1024>; + }; + }; + }; + ddr_thermal: ddr_thermal { + polling-delay = <2000>; + polling-delay-passive = <1000>; + sustainable-power = <1410>; + thermal-sensors = <&d_tsensor 1>; + trips { + dswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + dcontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + dhot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + dcritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + + }; + }; + /*thermal zone end*/ + + cpu_opp_table0: cpu_opp_table0 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <730000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <730000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <730000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <750000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <770000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <780000>; + }; + opp06 { + opp-hz = /bits/ 64 <1404000000>; + opp-microvolt = <790000>; + }; + opp07 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <800000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <810000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <850000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <900000>; + }; + opp11 { + opp-hz = /bits/ 64 <1908000000>; + opp-microvolt = <950000>; + }; + }; + + cpufreq-meson { + compatible = "amlogic, cpufreq-meson"; + pinctrl-names = "default"; + pinctrl-0 = <&pwm_ao_d_pins3>; + status = "okay"; + }; + +}; /* end of / */ + +&meson_fb { + status = "okay"; + display_size_default = <1920 1080 1920 2160 32>; + mem_size = <0x00800000 0x1980000 0x100000 0x100000 0x800000>; + logo_addr = "0x7f800000"; + mem_alloc = <0>; + pxp_mode = <0>; /** 0:normal mode 1:pxp mode */ +}; + +&pwm_AO_cd { + status = "okay"; +}; + +&i2c0 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&i2c0_master_pins2>; + clock-frequency = <400000>; + + gt9xx@5d { + compatible = "goodix,gt9xx"; + status = "disabled"; + reg = <0x5d>; + reset-gpio = <&gpio GPIOZ_9 0x00>; + irq-gpio = <&gpio GPIOZ_3 0x00>; + }; + + ftxx@38 { + compatible = "focaltech,fts"; + status = "disabled"; + reg = <0x38>; + reset-gpio = <&gpio GPIOZ_9 0x00>; + irq-gpio = <&gpio GPIOZ_3 0x00>; + x_max = <600>; + y_max = <1024>; + max-touch-number = <10>; + }; +}; + +/*&i2c2 { + * status = "okay"; + * pinctrl-names="default"; + * pinctrl-0=<&i2c2_master_pins2>; + * clock-frequency = <300000>; + *}; + */ + +&i2c3 { + status = "ok"; + pinctrl-names="default"; + pinctrl-0=<&i2c3_master_pins2>; + clock-frequency = <100000>; /* default 100k */ + + /* for ref board */ + ad82584f_62: ad82584f_62@62 { + compatible = "ESMT, ad82584f"; + #sound-dai-cells = <0>; + reg = <0x31>; + status = "disabled"; + reset_pin = <&gpio GPIOA_5 0>; + no_mclk; + }; + + bl_extern_i2c { + compatible = "bl_extern, i2c"; + dev_name = "lp8556"; + reg = <0x2c>; + status = "disabled"; + }; +}; + +&audiobus { + tdma: tdm@0 { + compatible = "amlogic, sm1-snd-tdma"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 1>; + dai-tdm-oe-lane-slot-mask-out = <1 0>; + dai-tdm-clk-sel = <0>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_A + &clkc CLKID_MPLL0>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmout_a &tdmin_a>; + + status = "okay"; + }; + + tdmb: tdm@1 { + compatible = "amlogic, sm1-snd-tdmb"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 1 0 0>; + dai-tdm-lane-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <1>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_B + &clkc CLKID_MPLL1 + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_A>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; + + mclk_pad = <0>; /* 0: mclk_0; 1: mclk_1 */ + + /* + * 0: tdmout_a; + * 1: tdmout_b; + * 2: tdmout_c; + * 3: spdifout; + * 4: spdifout_b; + */ + samesource_sel = <3>; + + status = "okay"; + }; + + tdmc: tdm@2 { + compatible = "amlogic, sm1-snd-tdmc"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <1 0 0 0>; + #dai-tdm-lane-slot-mask-out = <1 0 1 1>; + #dai-tdm-lane-oe-slot-mask-in = <0 0 0 0>; + #dai-tdm-lane-oe-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <2>; + + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmc_mclk &tdmout_c &tdmin_c>; + mclk_pad = <0>; /* 0: mclk_0; 1: mclk_1 */ + status = "okay"; + }; + + spdifa: spdif@0 { + compatible = "amlogic, sm1-snd-spdif-a"; + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 + &clkc CLKID_FCLK_DIV4 + &clkaudio CLKID_AUDIO_GATE_SPDIFIN + &clkaudio CLKID_AUDIO_GATE_SPDIFOUT_A + &clkaudio CLKID_AUDIO_SPDIFIN + &clkaudio CLKID_AUDIO_SPDIFOUT_A>; + clock-names = "sysclk", "fixed_clk", "gate_spdifin", + "gate_spdifout", "clk_spdifin", "clk_spdifout"; + interrupts = + ; + + interrupt-names = "irq_spdifin"; + pinctrl-names = "spdif_pins"; + pinctrl-0 = <&spdifout &spdifin>; + + status = "okay"; + }; + spdifb: spdif@1 { + compatible = "amlogic, sm1-snd-spdif-b"; + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 /*CLKID_HIFI_PLL*/ + &clkaudio CLKID_AUDIO_GATE_SPDIFOUT_B + &clkaudio CLKID_AUDIO_SPDIFOUT_B>; + clock-names = "sysclk", + "gate_spdifout", "clk_spdifout"; + + status = "okay"; + }; + pdm: pdm { + compatible = "amlogic, sm1-snd-pdm"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_PDM + &clkc CLKID_FCLK_DIV3 + &clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_PDMIN0 + &clkaudio CLKID_AUDIO_PDMIN1>; + clock-names = "gate", + "sysclk_srcpll", + "dclk_srcpll", + "pdm_dclk", + "pdm_sysclk"; + + pinctrl-names = "pdm_pins"; + pinctrl-0 = <&pdmin>; + + /* mode 0~4, defalut:1 */ + filter_mode = <1>; + status = "okay"; + }; + aml_loopback: loopback { + compatible = "amlogic, snd-loopback"; + /* + * 0: out rate = in data rate; + * 1: out rate = loopback data rate; + */ + lb_mode = <0>; + + /* datain src + * 0: tdmin_a; + * 1: tdmin_b; + * 2: tdmin_c; + * 3: spdifin; + * 4: pdmin; + */ + datain_src = <4>; + datain_chnum = <8>; + datain_chmask = <0x3f>; + + /* tdmin_lb src + * 0: tdmoutA + * 1: tdmoutB + * 2: tdmoutC + * 3: PAD_tdminA + * 4: PAD_tdminB + * 5: PAD_tdminC + */ + datalb_src = <2>; + datalb_chnum = <8>; + datalb_chmask = <0x3>; + + status = "okay"; + }; + earc:earc { + compatible = "amlogic, sm1-snd-earc"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_EARCRX + &clkaudio CLKID_EARCRX_CMDC + &clkaudio CLKID_EARCRX_DMAC + &clkc CLKID_FCLK_DIV5 + &clkc CLKID_FCLK_DIV3 + >; + clock-names = "rx_gate", + "rx_cmdc", + "rx_dmac", + "rx_cmdc_srcpll", + "rx_dmac_srcpll"; + + interrupts = < + GIC_SPI 88 IRQ_TYPE_EDGE_RISING + GIC_SPI 87 IRQ_TYPE_EDGE_RISING + >; + interrupt-names = "rx_cmdc", "rx_dmac"; + + status = "okay"; + }; + + asrca: resample@0 { + compatible = "amlogic, sm1-resample"; + clocks = <&clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_MCLK_F + &clkaudio CLKID_AUDIO_RESAMPLE_A>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + /*same with toddr_src + * TDMIN_A, 0 + * TDMIN_B, 1 + * TDMIN_C, 2 + * SPDIFIN, 3 + * PDMIN, 4 + * NONE, + * TDMIN_LB, 6 + * LOOPBACK, 7 + */ + resample_module = <4>; + status = "okay"; + }; + + vad:vad { + compatible = "amlogic, snd-vad"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_TOVAD + &clkc CLKID_FCLK_DIV5 + &clkaudio CLKID_AUDIO_VAD>; + clock-names = "gate", "pll", "clk"; + + interrupts = ; + interrupt-names = "irq_wakeup", "irq_frame_sync"; + + /* + * Data src sel: + * 0: tdmin_a; + * 1: tdmin_b; + * 2: tdmin_c; + * 3: spdifin; + * 4: pdmin; + * 5: loopback_b; + * 6: tdmin_lb; + * 7: loopback_a; + */ + src = <4>; + + /* + * deal with hot word in user space or kernel space + * 0: in user space + * 1: in kernel space + */ + level = <1>; + + status = "okay"; + }; +}; /* end of audiobus */ + +&pinctrl_periphs { + tdmout_a: tdmout_a { + mux { /* GPIOX_11, GPIOX_10, GPIOX_9 */ + groups = "tdma_sclk", + "tdma_fs", + "tdma_dout0"; + function = "tdma_out"; + }; + }; + + tdmin_a: tdmin_a { + mux { /* GPIOX_8 */ + groups = "tdma_din1"; + function = "tdma_in"; + }; + }; + + tdmb_mclk: tdmb_mclk { + mux { + groups = "mclk0_a"; + function = "mclk0"; + drive-strength = <2>; + }; + }; + tdmout_b: tdmout_b { + mux { /* GPIOA_1, GPIOA_2, GPIOA_3 */ + groups = "tdmb_sclk", + "tdmb_fs", + "tdmb_dout0"; + function = "tdmb_out"; + drive-strength = <2>; + }; + }; + + tdmin_b:tdmin_b { + mux { /* GPIOA_4 */ + groups = "tdmb_din1" + /*,"tdmb_slv_sclk", "tdmb_slv_fs"*/; + function = "tdmb_in"; + drive-strength = <2>; + }; + }; + + tdmc_mclk: tdmc_mclk { + mux { /* GPIOA_11 */ + groups = "mclk1_a"; + function = "mclk1"; + }; + }; + + tdmout_c:tdmout_c { + mux { /* GPIOA_12, GPIOA_13, GPIOA_8, GPIOA_7*/ + groups = "tdmc_sclk_a", + "tdmc_fs_a", + "tdmc_dout0_a" + /*, "tdmc_dout2", + * "tdmc_dout3" + */; + function = "tdmc_out"; + }; + }; + + tdmin_c:tdmin_c { + mux { /* GPIOA_10 */ + groups = "tdmc_din0_a"; + function = "tdmc_in"; + }; + }; + + spdifin: spdifin { + mux {/* GPIOH_5 */ + groups = "spdif_in_h"; + function = "spdif_in"; + }; + }; + + pdmin: pdmin { + mux { /* GPIOA_5, GPIOA_6, GPIOA_8, GPIOA_9, GPIOA_7 */ + groups = "pdm_din0_a", + /*"pdm_din1_a",*/ + "pdm_din2_a", + /*"pdm_din3_a",*/ + "pdm_dclk_a"; + function = "pdm"; + }; + }; + + bl_pwm_off_pins:bl_pwm_off_pin { + mux { + pins = "GPIOH_5"; + function = "gpio_periphs"; + output-high; + }; + }; + + clk12_24_z_pins:clk12_24_z_pins { + mux { + groups = "clk12_24_z"; + function = "clk12_24_ee"; + drive-strength = <3>; + }; + }; + + gen_clk_ee_z: gen_clk_ee_z { + mux { + groups="gen_clk_ee_z"; + function="gen_clk_ee"; + drive-strength = <3>; + }; + }; + + cam_dvp_pins:cam_dvp_pins { + mux { + groups = "bt656_a_vs", "bt656_a_hs", "bt656_a_clk", + "bt656_a_din0", "bt656_a_din1", "bt656_a_din2", + "bt656_a_din3", "bt656_a_din4", "bt656_a_din5", + "bt656_a_din6", "bt656_a_din7"; + function = "bt656"; + }; + }; + + spdifout: spdifout { + mux { /* GPIOH_4 */ + groups = "spdif_out_h"; + function = "spdif_out"; + }; + }; + +}; /* end of pinctrl_periphs */ + +//&pinctrl_aobus { +// spdifout: spdifout { +// mux { /* gpiao_10 */ +// groups = "spdif_out_ao"; +// function = "spdif_out_ao"; +// }; +// }; +//}; /* end of pinctrl_aobus */ + +&audio_data { + status = "okay"; +}; + +/* Audio Related End */ + +&pwm_ef { + status = "okay"; +}; + +&dwc3 { + status = "okay"; +}; + +&usb2_phy_v2 { + status = "okay"; + portnum = <2>; +}; + +&usb3_phy_v2 { + status = "okay"; + portnum = <1>; + otg = <0>; +}; + +&dwc2_a { + status = "okay"; + /** 0: normal, 1: otg+dwc3 host only, 2: otg+dwc3 device only*/ + controller-type = <1>; +}; +ðmac { + status = "okay"; + pinctrl-names = "internal_eth_pins", "internal_gpio_pins"; + pinctrl-0 = <&internal_eth_pins>; + pinctrl-1 = <&internal_gpio_pins>; + mc_val = <0x4be04>; + + internal_phy=<1>; +}; + +&uart_A { + status = "okay"; +}; + +/*if you want to use vdin just modify status to "ok"*/ +&vdin0 { + memory-region = <&vdin0_cma_reserved>; + status = "okay"; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + *bit4:support yuv422 10bit full pack mode (from txl new add) + */ + tv_bit_mode = <0x15>; +}; +&vdin1 { + memory-region = <&vdin1_cma_reserved>; + status = "okay"; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + */ + tv_bit_mode = <1>; +}; + + +&sd_emmc_c { + status = "okay"; + emmc { + caps = "MMC_CAP_8_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + /* "MMC_CAP_1_8V_DDR", */ + "MMC_CAP_HW_RESET", + "MMC_CAP_ERASE", + "MMC_CAP_CMD23"; + caps2 = "MMC_CAP2_HS200"; + /* "MMC_CAP2_HS400";*/ + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&sd_emmc_b { + status = "okay"; + sd { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED"; + f_min = <400000>; + f_max = <50000000>; + }; +}; + + +&sd_emmc_a { + status = "okay"; + sdio { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + "MMC_CAP_UHS_SDR12", + "MMC_CAP_UHS_SDR25", + "MMC_CAP_UHS_SDR50", + "MMC_CAP_UHS_SDR104", + "MMC_PM_KEEP_POWER", + "MMC_CAP_SDIO_IRQ"; + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&nand { + status = "disabled"; + plat-names = "bootloader","nandnormal"; + plat-num = <2>; + plat-part-0 = <&bootloader>; + plat-part-1 = <&nandnormal>; + bootloader: bootloader{ + enable_pad ="ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <1>; + part_num = <0>; + rb_detect = <1>; + }; + nandnormal: nandnormal{ + enable_pad ="ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + plane_mode = "twoplane"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <2>; + part_num = <3>; + partition = <&nand_partitions>; + rb_detect = <1>; + }; + nand_partitions:nand_partition{ + /* + * if bl_mode is 1, tpl size was generate by + * fip_copies * fip_size which + * will not skip bad when calculating + * the partition size; + * + * if bl_mode is 0, + * tpl partition must be comment out. + */ + tpl{ + offset=<0x0 0x0>; + size=<0x0 0x0>; + }; + logo{ + offset=<0x0 0x0>; + size=<0x0 0x200000>; + }; + recovery{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + boot{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + system{ + offset=<0x0 0x0>; + size=<0x0 0x4000000>; + }; + data{ + offset=<0xffffffff 0xffffffff>; + size=<0x0 0x0>; + }; + }; +}; + +&pcie_A { + reset-gpio = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; + status = "disable"; +}; + +&meson_cooldev { + status = "okay"; +}; + +&saradc { + status = "disabled"; +}; + +&defendkey { + status = "okay"; +}; + +&pinctrl_aobus { + dvb_s_ts0_pins: dvb_s_ts0_pins { + tsin_a { + groups = "tsin_a_sop_ao", + "tsin_a_valid_ao", + "tsin_a_clk_ao", + "tsin_a_din0_ao"; + function = "tsin_a_ao"; + }; + }; +}; diff --git a/arch/arm/boot/dts/amlogic/tl1_pxp.dts b/arch/arm/boot/dts/amlogic/tl1_pxp.dts index aacb76768dc4..fe0ded0bce4a 100644 --- a/arch/arm/boot/dts/amlogic/tl1_pxp.dts +++ b/arch/arm/boot/dts/amlogic/tl1_pxp.dts @@ -101,6 +101,21 @@ alignment = <0x400000>; }; + /*di CMA pool */ + di_cma_reserved:linux,di_cma { + compatible = "shared-dma-pool"; + reusable; + /* buffer_size = 3621952(yuv422 8bit) + * | 4736064(yuv422 10bit) + * | 4074560(yuv422 10bit full pack mode) + * 10x3621952=34.6M(0x23) support 8bit + * 10x4736064=45.2M(0x2e) support 12bit + * 10x4074560=40M(0x28) support 10bit + */ + size = <0x02800000>; + alignment = <0x400000>; + }; + /* for hdmi rx emp use */ hdmirx_emp_cma_reserved:linux,emp_cma { compatible = "shared-dma-pool"; @@ -119,6 +134,38 @@ memory-region = <&codec_mm_cma &codec_mm_reserved>; }; + + ppmgr { + compatible = "amlogic, ppmgr"; + memory-region = <&ppmgr_reserved>; + status = "okay"; + }; + + deinterlace { + compatible = "amlogic, deinterlace"; + status = "okay"; + /* 0:use reserved; 1:use cma; 2:use cma as reserved */ + flag_cma = <1>; + //memory-region = <&di_reserved>; + memory-region = <&di_cma_reserved>; + interrupts = <0 46 1 + 0 40 1>; + interrupt-names = "pre_irq", "post_irq"; + clocks = <&clkc CLKID_VPU_CLKB_TMP_COMP>, + <&clkc CLKID_VPU_CLKB_COMP>; + clock-names = "vpu_clkb_tmp_composite", + "vpu_clkb_composite"; + clock-range = <334 667>; + /* buffer-size = <3621952>;(yuv422 8bit) */ + buffer-size = <4074560>;/*yuv422 fullpack*/ + /* reserve-iomap = "true"; */ + /* if enable nr10bit, set nr10bit-support to 1 */ + post-wr-support = <1>; + nr10bit-support = <1>; + nrds-enable = <1>; + pps-enable = <1>; + }; + vout { compatible = "amlogic, vout"; status = "okay"; @@ -471,6 +518,143 @@ reg-names = "ao_exit","ao"; }; + /*DCDC for MP8756GD*/ + cpu_opp_table0: cpu_opp_table0 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <739000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <739000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <739000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <769000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <789000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <809000>; + }; + opp06 { + opp-hz = /bits/ 64 <1398000000>; + opp-microvolt = <839000>; + }; + opp07 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <869000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <899000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <929000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <989000>; + }; + opp11 { + opp-hz = /bits/ 64 <1908000000>; + opp-microvolt = <1019000>; + }; + }; + + cpufreq-meson { + compatible = "amlogic, cpufreq-meson"; + pinctrl-names = "default"; + pinctrl-0 = <&pwm_ao_d_pins3>; + status = "okay"; + }; + + tuner: tuner { + compatible = "amlogic, tuner"; + status = "okay"; + tuner_cur = <0>; /* default use tuner */ + tuner_num = <1>; /* tuner number, multi tuner support */ + tuner_name_0 = "mxl661_tuner"; + tuner_i2c_adap_0 = <&i2c0>; + tuner_i2c_addr_0 = <0x60>; + tuner_xtal_0 = <1>; /* 0: 16MHz, 1: 24MHz */ + tuner_xtal_mode_0 = <3>; + /* NO_SHARE_XTAL(0) + * SLAVE_XTAL_SHARE(3) + */ + tuner_xtal_cap_0 = <25>; /* when tuner_xtal_mode = 3, set 25 */ + }; + + atv-demod { + compatible = "amlogic, atv-demod"; + status = "okay"; + tuner = <&tuner>; + btsc_sap_mode = <1>; + /* pinctrl-names="atvdemod_agc_pins"; */ + /* pinctrl-0=<&atvdemod_agc_pins>; */ + reg = <0xff656000 0x2000 /* demod reg */ + 0xff63c000 0x2000 /* hiu reg */ + 0xff634000 0x2000 /* periphs reg */ + 0xff64a000 0x2000>; /* audio reg */ + reg_23cf = <0x88188832>; + /*default:0x88188832;r840 on haier:0x48188832*/ + }; + + sd_emmc_b: sd@ffe05000 { + status = "okay"; + compatible = "amlogic, meson-mmc-tl1"; + reg = <0xffe05000 0x800>; + interrupts = <0 190 1>; + + pinctrl-names = "sd_all_pins", + "sd_clk_cmd_pins", + "sd_1bit_pins"; + pinctrl-0 = <&sd_all_pins>; + pinctrl-1 = <&sd_clk_cmd_pins>; + pinctrl-2 = <&sd_1bit_pins>; + + clocks = <&clkc CLKID_SD_EMMC_B>, + <&clkc CLKID_SD_EMMC_B_P0_COMP>, + <&clkc CLKID_FCLK_DIV2>, + <&clkc CLKID_FCLK_DIV5>, + <&xtal>; + clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + + bus-width = <4>; + cap-sd-highspeed; + cap-mmc-highspeed; + max-frequency = <100000000>; + disable-wp; + sd { + pinname = "sd"; + ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE"; /**ptm debug */ + f_min = <400000>; + f_max = <200000000>; + max_req_size = <0x20000>; /**128KB*/ + gpio_dat3 = <&gpio GPIOC_3 GPIO_ACTIVE_HIGH>; + jtag_pin = <&gpio GPIOC_0 GPIO_ACTIVE_HIGH>; + gpio_cd = <&gpio GPIOC_10 GPIO_ACTIVE_HIGH>; + card_type = <5>; + /* 3:sdio device(ie:sdio-wifi), + * 4:SD combo (IO+mem) card + */ + }; + }; }; /* end of / */ &audiobus { @@ -849,6 +1033,27 @@ }; }; +&dwc3 { + status = "okay"; +}; + +&usb2_phy_v2 { + status = "okay"; + portnum = <3>; +}; + +&usb3_phy_v2 { + status = "okay"; + portnum = <0>; + otg = <0>; +}; + +&dwc2_a { + status = "okay"; + /** 0: normal, 1: otg+dwc3 host only, 2: otg+dwc3 device only*/ + controller-type = <1>; +}; + &spicc0 { status = "okay"; pinctrl-names = "default"; diff --git a/arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts b/arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts index 140070b93c3c..d522d468e1ff 100644 --- a/arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts +++ b/arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts @@ -43,7 +43,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x100000 0x7ff00000>; + linux,usable-memory = <0x0 0x80000000>; }; reserved-memory { @@ -51,6 +51,14 @@ #size-cells = <1>; ranges; /* global autoconfigured region for contiguous allocations */ + ramoops@0x07400000 { + compatible = "ramoops"; + reg = <0x07400000 0x00100000>; + record-size = <0x8000>; + console-size = <0x8000>; + ftrace-size = <0x20000>; + }; + secmon_reserved: linux,secmon { compatible = "shared-dma-pool"; reusable; @@ -66,7 +74,7 @@ size = <0x13400000>; alignment = <0x400000>; linux,contiguous-region; - alloc-ranges = <0x12000000 0x13400000>; + alloc-ranges = <0x30000000 0x50000000>; }; /* codec shared reserved */ @@ -110,6 +118,53 @@ alignment = <0x400000>; }; + /*demod_reserved:linux,demod { + * compatible = "amlogic, demod-mem"; + * size = <0x800000>; //8M //100m 0x6400000 + * alloc-ranges = <0x0 0x30000000>; + * //multi-use; + * //no-map; + *}; + */ + + demod_cma_reserved:linux,demod_cma { + compatible = "shared-dma-pool"; + reusable; + /* 8M */ + size = <0x0800000>; + alignment = <0x400000>; + }; + + /*di CMA pool */ + di_cma_reserved:linux,di_cma { + compatible = "shared-dma-pool"; + reusable; + /* buffer_size = 3621952(yuv422 8bit) + * | 4736064(yuv422 10bit) + * | 4074560(yuv422 10bit full pack mode) + * 10x3621952=34.6M(0x23) support 8bit + * 10x4736064=45.2M(0x2e) support 12bit + * 10x4074560=40M(0x28) support 10bit + */ + size = <0x02800000>; + alignment = <0x400000>; + }; + + /*di CMA pool */ + di_cma_reserved:linux,di_cma { + compatible = "shared-dma-pool"; + reusable; + /* buffer_size = 3621952(yuv422 8bit) + * | 4736064(yuv422 10bit) + * | 4074560(yuv422 10bit full pack mode) + * 10x3621952=34.6M(0x23) support 8bit + * 10x4736064=45.2M(0x2e) support 12bit + * 10x4074560=40M(0x28) support 10bit + */ + size = <0x02800000>; + alignment = <0x400000>; + }; + /* for hdmi rx emp use */ hdmirx_emp_cma_reserved:linux,emp_cma { compatible = "shared-dma-pool"; @@ -141,6 +196,31 @@ status = "okay"; }; + deinterlace { + compatible = "amlogic, deinterlace"; + status = "okay"; + /* 0:use reserved; 1:use cma; 2:use cma as reserved */ + flag_cma = <1>; + //memory-region = <&di_reserved>; + memory-region = <&di_cma_reserved>; + interrupts = <0 46 1 + 0 40 1>; + interrupt-names = "pre_irq", "post_irq"; + clocks = <&clkc CLKID_VPU_CLKB_TMP_COMP>, + <&clkc CLKID_VPU_CLKB_COMP>; + clock-names = "vpu_clkb_tmp_composite", + "vpu_clkb_composite"; + clock-range = <334 667>; + /* buffer-size = <3621952>;(yuv422 8bit) */ + buffer-size = <4074560>;/*yuv422 fullpack*/ + /* reserve-iomap = "true"; */ + /* if enable nr10bit, set nr10bit-support to 1 */ + post-wr-support = <1>; + nr10bit-support = <1>; + nrds-enable = <1>; + pps-enable = <1>; + }; + vout { compatible = "amlogic, vout"; status = "okay"; @@ -173,11 +253,13 @@ compatible = "amlogic, tl1-sound-card"; aml-audio-card,name = "AML-AUGESOUND"; + avout_mute-gpios = <&gpio GPIODV_3 GPIO_ACTIVE_HIGH>; + aml-audio-card,dai-link@0 { format = "i2s"; mclk-fs = <256>; - //continuous-clock; - bitclock-inversion; + continuous-clock; + //bitclock-inversion; //frame-inversion; /* master mode */ bitclock-master = <&tdma>; @@ -188,7 +270,7 @@ * frame-master = <&tdmacodec>; */ /* suffix-name, sync with android audio hal used for */ - suffix-name = "alsaPORT-pcm"; + suffix-name = "alsaPORT-i2s"; tdmacpu: cpu { sound-dai = <&tdma>; dai-tdm-slot-tx-mask = @@ -201,11 +283,13 @@ }; tdmacodec: codec { //sound-dai = <&dummy_codec>; - sound-dai = <&tl1_codec>; + sound-dai = ; }; }; aml-audio-card,dai-link@1 { + status = "disabled"; + format = "i2s"; mclk-fs = <256>; //continuous-clock; @@ -218,7 +302,7 @@ //bitclock-master = <&tdmbcodec>; //frame-master = <&tdmbcodec>; /* suffix-name, sync with android audio hal used for */ - suffix-name = "alsaPORT-i2s"; + suffix-name = "alsaPORT-pcm"; cpu { sound-dai = <&tdmb>; dai-tdm-slot-tx-mask = <1 1>; @@ -240,6 +324,8 @@ }; aml-audio-card,dai-link@2 { + status = "disabled"; + format = "i2s"; mclk-fs = <256>; //continuous-clock; @@ -304,6 +390,7 @@ aml-audio-card,dai-link@6 { mclk-fs = <256>; + suffix-name = "alsaPORT-tv"; cpu { sound-dai = <&extn>; system-clock-frequency = <12288000>; @@ -438,11 +525,93 @@ tv_bit_mode = <0x15>; }; + tvafe { + compatible = "amlogic, tvafe-tl1"; + /*memory-region = <&tvafe_cma_reserved>;*/ + status = "okay"; + flag_cma = <1>;/*1:share with codec_mm;0:cma alone*/ + cma_size = <5>;/*MByte*/ + reg = <0xff654000 0x2000>;/*tvafe reg base*/ + reserve-iomap = "true"; + tvafe_id = <0>; + //pinctrl-names = "default"; + /*!!particular sequence, no more and no less!!!*/ + tvafe_pin_mux = < + 3 /* TVAFE_CVBS_IN2, CVBS_IN0 = 0 */ + 1 /* TVAFE_CVBS_IN0, CVBS_IN1 */ + 2 /* TVAFE_CVBS_IN1, CVBS_IN2 */ + 4 /* TVAFE_CVBS_IN3, CVBS_IN3 */ + >; + clocks = <&clkc CLKID_DAC_CLK>; + clock-names = "vdac_clk_gate"; + }; + + vbi { + compatible = "amlogic, vbi"; + status = "okay"; + interrupts = <0 83 1>; + }; + + cvbsout { + compatible = "amlogic, cvbsout-tl1"; + status = "disabled"; + clocks = <&clkc CLKID_VCLK2_ENCI + &clkc CLKID_VCLK2_VENCI0 + &clkc CLKID_VCLK2_VENCI1 + &clkc CLKID_DAC_CLK>; + clock-names = "venci_top_gate", + "venci_0_gate", + "venci_1_gate", + "vdac_clk_gate"; + /* clk path */ + /* 0:vid_pll vid2_clk */ + /* 1:gp0_pll vid2_clk */ + /* 2:vid_pll vid1_clk */ + /* 3:gp0_pll vid1_clk */ + clk_path = <0>; + + /* performance: reg_address, reg_value */ + /* tl1 */ + performance = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x8080 + 0x1b05 0xfd + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + performance_sarft = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x0 + 0x1b05 0x9 + 0x1c59 0xfc48 + 0xffff 0x0>; /* ending flag */ + performance_revB_telecom = <0x1bf0 0x9 + 0x1b56 0x546 + 0x1b12 0x8080 + 0x1b05 0x9 + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + }; + + adc_keypad { + compatible = "amlogic, adc_keypad"; + status = "okay"; + key_name = "vol-", "vol+", "ch+", "ch-", + "menu", "source", "exit"; + key_num = <7>; + io-channels = <&saradc SARADC_CH2 &saradc SARADC_CH3>; + io-channel-names = "key-chan-2", "key-chan-3"; + key_chan = ; + key_code = <114 115 192 193 139 466 174>; + key_val = <0 143 266 389 0 143 266>; //val=voltage/1800mV*1023 + key_tolerance = <40 40 40 40 40 40 40>; + }; + unifykey { compatible = "amlogic, unifykey"; status = "okay"; - unifykey-num = <19>; + unifykey-num = <20>; unifykey-index-0 = <&keysn_0>; unifykey-index-1 = <&keysn_1>; unifykey-index-2 = <&keysn_2>; @@ -462,6 +631,7 @@ unifykey-index-16 = <&keysn_16>; unifykey-index-17 = <&keysn_17>; unifykey-index-18 = <&keysn_18>; + unifykey-index-19 = <&keysn_19>; keysn_0: key_0{ key-name = "usid"; @@ -563,6 +733,11 @@ key-device = "normal"; key-permit = "read","write","del"; }; + keysn_19:key_19{ + key-name = "lcd_tcon"; + key-device = "normal"; + key-permit = "read","write","del"; + }; }; /* End unifykey */ hdmirx { @@ -810,51 +985,51 @@ opp00 { opp-hz = /bits/ 64 <100000000>; - opp-microvolt = <731000>; + opp-microvolt = <739000>; }; opp01 { opp-hz = /bits/ 64 <250000000>; - opp-microvolt = <731000>; + opp-microvolt = <739000>; }; opp02 { opp-hz = /bits/ 64 <500000000>; - opp-microvolt = <731000>; + opp-microvolt = <739000>; }; opp03 { opp-hz = /bits/ 64 <667000000>; - opp-microvolt = <761000>; + opp-microvolt = <769000>; }; opp04 { opp-hz = /bits/ 64 <1000000000>; - opp-microvolt = <791000>; + opp-microvolt = <799000>; }; opp05 { opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <801000>; + opp-microvolt = <809000>; }; opp06 { opp-hz = /bits/ 64 <1404000000>; - opp-microvolt = <831000>; + opp-microvolt = <839000>; }; opp07 { opp-hz = /bits/ 64 <1500000000>; - opp-microvolt = <861000>; + opp-microvolt = <869000>; }; opp08 { opp-hz = /bits/ 64 <1608000000>; - opp-microvolt = <891000>; + opp-microvolt = <899000>; }; opp09 { opp-hz = /bits/ 64 <1704000000>; - opp-microvolt = <921000>; + opp-microvolt = <929000>; }; opp10 { opp-hz = /bits/ 64 <1800000000>; - opp-microvolt = <981000>; + opp-microvolt = <989000>; }; opp11 { opp-hz = /bits/ 64 <1908000000>; - opp-microvolt = <1011000>; + opp-microvolt = <1019000>; }; }; @@ -866,46 +1041,63 @@ }; tuner: tuner { + compatible = "amlogic, tuner"; status = "okay"; - tuner_name = "mxl661_tuner"; - tuner_i2c_adap = <&i2c0>; - tuner_i2c_addr = <0x60>; - tuner_xtal = <1>; /* 0: 16MHz, 1: 24MHz */ - tuner_xtal_mode = <3>; + tuner_cur = <0>; /* default use tuner */ + tuner_num = <1>; /* tuner number, multi tuner support */ + tuner_name_0 = "mxl661_tuner"; + tuner_i2c_adap_0 = <&i2c0>; + tuner_i2c_addr_0 = <0x60>; + tuner_xtal_0 = <0>; /* 0: 16MHz, 1: 24MHz */ + tuner_xtal_mode_0 = <0>; /* NO_SHARE_XTAL(0) * SLAVE_XTAL_SHARE(3) */ - tuner_xtal_cap = <25>; /* when tuner_xtal_mode = 3, set 25 */ + tuner_xtal_cap_0 = <25>; /* when tuner_xtal_mode = 3, set 25 */ }; - bt-dev{ - compatible = "amlogic, bt-dev"; + sd_emmc_b: sd@ffe05000 { status = "okay"; - gpio_reset = <&gpio GPIOC_13 GPIO_ACTIVE_HIGH>; - }; + compatible = "amlogic, meson-mmc-tl1"; + reg = <0xffe05000 0x800>; + interrupts = <0 190 1>; - wifi{ - compatible = "amlogic, aml_wifi"; - status = "okay"; - interrupt_pin = <&gpio GPIOC_12 GPIO_ACTIVE_HIGH>; - irq_trigger_type = "GPIO_IRQ_LOW"; - dhd_static_buf; //dhd_static_buf support - power_on_pin = <&gpio GPIOC_11 GPIO_ACTIVE_HIGH>; - pinctrl-names = "default"; - pinctrl-0 = <&pwm_b_pins1>; - pwm_config = <&wifi_pwm_conf>; - }; + pinctrl-names = "sd_all_pins", + "sd_clk_cmd_pins", + "sd_1bit_pins"; + pinctrl-0 = <&sd_all_pins>; + pinctrl-1 = <&sd_clk_cmd_pins>; + pinctrl-2 = <&sd_1bit_pins>; - wifi_pwm_conf:wifi_pwm_conf{ - pwm_channel1_conf { - pwms = <&pwm_ab MESON_PWM_1 30040 0>; - duty-cycle = <15020>; - times = <8>; - }; - pwm_channel2_conf { - pwms = <&pwm_ab MESON_PWM_3 30030 0>; - duty-cycle = <15015>; - times = <12>; + clocks = <&clkc CLKID_SD_EMMC_B>, + <&clkc CLKID_SD_EMMC_B_P0_COMP>, + <&clkc CLKID_FCLK_DIV2>, + <&clkc CLKID_FCLK_DIV5>, + <&xtal>; + clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + + bus-width = <4>; + cap-sd-highspeed; + cap-mmc-highspeed; + max-frequency = <100000000>; + disable-wp; + sd { + pinname = "sd"; + ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED"; + //"MMC_CAP_NONREMOVABLE"; /**ptm debug */ + f_min = <400000>; + f_max = <200000000>; + max_req_size = <0x20000>; /**128KB*/ + gpio_dat3 = <&gpio GPIOC_3 GPIO_ACTIVE_HIGH>; + jtag_pin = <&gpio GPIOC_0 GPIO_ACTIVE_HIGH>; + gpio_cd = <&gpio GPIOC_10 GPIO_ACTIVE_HIGH>; + card_type = <5>; + /* 3:sdio device(ie:sdio-wifi), + * 4:SD combo (IO+mem) card + */ }; }; @@ -924,17 +1116,38 @@ #sound-dai-cells = <0>; dai-tdm-lane-slot-mask-in = <1 0>; - dai-tdm-lane-slot-mask-out = <1 0>; + dai-tdm-lane-slot-mask-out = <1 1 1 1>; dai-tdm-clk-sel = <0>; clocks = <&clkaudio CLKID_AUDIO_MCLK_A - &clkc CLKID_MPLL0>; - clock-names = "mclk", "clk_srcpll"; + &clkc CLKID_MPLL0 + &clkc CLKID_MPLL1 + &clkaudio CLKID_AUDIO_SPDIFOUT_A>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; pinctrl-names = "tdm_pins"; - pinctrl-0 = <&tdma_mclk &tdmout_a &tdmin_a>; + pinctrl-0 = <&tdma_mclk &tdmout_a>; + + /* + * 0: tdmout_a; + * 1: tdmout_b; + * 2: tdmout_c; + * 3: spdifout; + * 4: spdifout_b; + */ + samesource_sel = <3>; + + /* In for ACODEC_ADC */ + acodec_adc = <1>; status = "okay"; + + /* !!!For --TV platform-- ONLY */ + Channel_Mask { + /*i2s has 4 pins, 8channel, mux output*/ + Spdif_samesource_Channel_Mask = "i2s_2/3"; + }; }; tdmb:tdm@1 { @@ -987,8 +1200,11 @@ ; interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; + pinctrl-0 = <&spdifout_a &spdifin_a>; + pinctrl-1 = <&spdifout_a_mute>; /* * whether do asrc for pcm and resample a or b @@ -1086,8 +1302,8 @@ asrca: resample@0 { compatible = "amlogic, tl1-resample-a"; - clocks = <&clkc CLKID_MPLL3 - &clkaudio CLKID_AUDIO_MCLK_F + clocks = <&clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_MCLK_A &clkaudio CLKID_AUDIO_RESAMPLE_A>; clock-names = "resample_pll", "resample_src", "resample_clk"; /*same with toddr_src @@ -1102,7 +1318,7 @@ */ resample_module = <3>; - status = "disabled"; + status = "okay"; }; asrcb: resample@1 { @@ -1154,6 +1370,13 @@ */ src = <4>; + /* + * deal with hot word in user space or kernel space + * 0: in user space + * 1: in kernel space + */ + level = <0>; + status = "disabled"; }; }; /* end of audiobus */ @@ -1176,6 +1399,7 @@ "tdma_dout2_z", "tdma_dout3_z"; function = "tdma_out"; + bias-pull-down; }; }; @@ -1223,6 +1447,13 @@ }; }; + spdifout_a_mute: spdifout_a_mute { + mux { /* GPIODV_4 */ + groups = "GPIODV_4"; + function = "gpio_periphs"; + }; + }; + pdmin: pdmin { mux { /* GPIOZ_7, GPIOZ_8, pdm_din2_z4 */ groups = "pdm_dclk_z", @@ -1244,10 +1475,6 @@ }; }; /* end of pinctrl_aobus */ -&audio_data{ - status = "okay"; -}; - &sd_emmc_c { status = "okay"; emmc { @@ -1266,18 +1493,6 @@ }; }; -&sd_emmc_b { - status = "okay"; - sd { - caps = "MMC_CAP_4_BIT_DATA", - "MMC_CAP_MMC_HIGHSPEED", - "MMC_CAP_SD_HIGHSPEED", - "MMC_CAP_NONREMOVABLE"; /**ptm debug */ - f_min = <400000>; - f_max = <200000000>; - }; -}; - &spifc { status = "disabled"; spi-nor@0 { @@ -1410,8 +1625,32 @@ status = "okay"; }; -&pwm_ab { +&i2c1 { status = "okay"; + clock-frequency = <300000>; + pinctrl-names="default"; + pinctrl-0=<&i2c1_h_pins>; + + lcd_extern_i2c0: lcd_extern_i2c@0 { + compatible = "lcd_ext, i2c"; + dev_name = "i2c_T5800Q"; + reg = <0x1c>; + status = "okay"; + }; + + lcd_extern_i2c1: lcd_extern_i2c@1 { + compatible = "lcd_ext, i2c"; + dev_name = "i2c_ANX6862"; + reg = <0x20>; + status = "okay"; + }; + + lcd_extern_i2c2: lcd_extern_i2c@2 { + compatible = "lcd_ext, i2c"; + dev_name = "i2c_ANX7911"; + reg = <0x74>; + status = "okay"; + }; }; &efuse { diff --git a/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts b/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts index 355d25ee4d92..8804f2322a20 100644 --- a/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts +++ b/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts @@ -44,7 +44,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x100000 0x7ff00000>; + linux,usable-memory = <0x0 0x80000000>; }; reserved-memory { @@ -52,6 +52,14 @@ #size-cells = <1>; ranges; /* global autoconfigured region for contiguous allocations */ + ramoops@0x07400000 { + compatible = "ramoops"; + reg = <0x07400000 0x00100000>; + record-size = <0x8000>; + console-size = <0x8000>; + ftrace-size = <0x20000>; + }; + secmon_reserved: linux,secmon { compatible = "shared-dma-pool"; reusable; @@ -60,24 +68,6 @@ alloc-ranges = <0x05000000 0x400000>; }; - codec_mm_cma:linux,codec_mm_cma { - compatible = "shared-dma-pool"; - reusable; - /* ion_codec_mm max can alloc size 80M*/ - size = <0x13400000>; - alignment = <0x400000>; - linux,contiguous-region; - alloc-ranges = <0x12000000 0x13400000>; - }; - - /* codec shared reserved */ - codec_mm_reserved:linux,codec_mm_reserved { - compatible = "amlogic, codec-mm-reserved"; - size = <0x0>; - alignment = <0x100000>; - //no-map; - }; - logo_reserved:linux,meson-fb { compatible = "shared-dma-pool"; reusable; @@ -91,13 +81,31 @@ reusable; size = <0xc00000>; alignment = <0x400000>; - alloc-ranges = <0x71000000 0xc00000>; + alloc-ranges = <0x7ec00000 0xc00000>; + }; + + codec_mm_cma:linux,codec_mm_cma { + compatible = "shared-dma-pool"; + reusable; + /* ion_codec_mm max can alloc size 80M*/ + size = <0x13400000>; + alignment = <0x400000>; + linux,contiguous-region; + alloc-ranges = <0x30000000 0x50000000>; + }; + + /* codec shared reserved */ + codec_mm_reserved:linux,codec_mm_reserved { + compatible = "amlogic, codec-mm-reserved"; + size = <0x0>; + alignment = <0x100000>; + //no-map; }; ion_cma_reserved:linux,ion-dev { compatible = "shared-dma-pool"; reusable; - size = <0x8000000>; + size = <0x2000000>; alignment = <0x400000>; }; @@ -136,13 +144,6 @@ alignment = <0x400000>; }; - /*vbi reserved mem*/ - vbi_reserved:linux,vbi { - compatible = "amlogic, vbi-mem"; - size = <0x100000>; - alloc-ranges = <0x0e000000 0x800000>; - }; - /*di CMA pool */ di_cma_reserved:linux,di_cma { compatible = "shared-dma-pool"; @@ -301,6 +302,7 @@ }; tdmacodec: codec { //sound-dai = <&dummy_codec>; + prefix-names = "AMP"; sound-dai = <&ad82584f &tl1_codec>; }; }; @@ -496,7 +498,7 @@ *if support 4K2K-YUV422-8BIT-WR:3840*2160*2*4 ~= 64M *if support 1080p-YUV422-8BIT-WR:1920*1080*2*4 ~= 16M */ - cma_size = <190>; + cma_size = <160>; interrupts = <0 83 1>; rdma-irq = <2>; clocks = <&clkc CLKID_FCLK_DIV5>, @@ -571,10 +573,8 @@ vbi { compatible = "amlogic, vbi"; - memory-region = <&vbi_reserved>; status = "okay"; interrupts = <0 83 1>; - reserve-iomap = "true"; }; cvbsout { @@ -1004,9 +1004,9 @@ }; }; ddr_thermal: ddr_thermal { - polling-delay = <1000>; - polling-delay-passive = <250>; - sustainable-power = <1680>; + polling-delay = <2000>; + polling-delay-passive = <1000>; + sustainable-power = <1322>; thermal-sensors = <&d_tsensor 1>; trips { dswitch_on: trip-point@0 { @@ -1032,9 +1032,9 @@ }; }; sar_thermal: sar_thermal { - polling-delay = <1000>; - polling-delay-passive = <250>; - sustainable-power = <1680>; + polling-delay = <2000>; + polling-delay-passive = <1000>; + sustainable-power = <1322>; thermal-sensors = <&s_tsensor 2>; trips { sswitch_on: trip-point@0 { @@ -1068,51 +1068,51 @@ opp00 { opp-hz = /bits/ 64 <100000000>; - opp-microvolt = <731000>; + opp-microvolt = <739000>; }; opp01 { opp-hz = /bits/ 64 <250000000>; - opp-microvolt = <731000>; + opp-microvolt = <739000>; }; opp02 { opp-hz = /bits/ 64 <500000000>; - opp-microvolt = <731000>; + opp-microvolt = <739000>; }; opp03 { opp-hz = /bits/ 64 <667000000>; - opp-microvolt = <761000>; + opp-microvolt = <769000>; }; opp04 { opp-hz = /bits/ 64 <1000000000>; - opp-microvolt = <791000>; + opp-microvolt = <799000>; }; opp05 { opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <801000>; + opp-microvolt = <809000>; }; opp06 { opp-hz = /bits/ 64 <1404000000>; - opp-microvolt = <831000>; + opp-microvolt = <839000>; }; opp07 { opp-hz = /bits/ 64 <1500000000>; - opp-microvolt = <861000>; + opp-microvolt = <869000>; }; opp08 { opp-hz = /bits/ 64 <1608000000>; - opp-microvolt = <891000>; + opp-microvolt = <899000>; }; opp09 { opp-hz = /bits/ 64 <1704000000>; - opp-microvolt = <921000>; + opp-microvolt = <929000>; }; opp10 { opp-hz = /bits/ 64 <1800000000>; - opp-microvolt = <981000>; + opp-microvolt = <989000>; }; opp11 { opp-hz = /bits/ 64 <1908000000>; - opp-microvolt = <1011000>; + opp-microvolt = <1019000>; }; }; @@ -1125,15 +1125,19 @@ tuner: tuner { status = "okay"; - tuner_name = "mxl661_tuner"; - tuner_i2c_adap = <&i2c0>; - tuner_i2c_addr = <0x60>; - tuner_xtal = <1>; /* 0: 16MHz, 1: 24MHz */ - tuner_xtal_mode = <3>; + tuner_cur = <0>; /* default use tuner */ + tuner_num = <1>; /* tuner number, multi tuner support */ + tuner_name_0 = "r842_tuner"; + tuner_i2c_adap_0 = <&i2c0>; + tuner_i2c_addr_0 = <0xf6>; + tuner_xtal_0 = <1>; /* 0: 16MHz, 1: 24MHz */ + tuner_xtal_mode_0 = <0>; /* NO_SHARE_XTAL(0) - * SLAVE_XTAL_SHARE(3) + * MASTER_TO_SLAVE_XTAL_IN(1) + * MASTER_TO_SLAVE_XTAL_OUT(2) + * SLAVE_XTAL_OUT(3) */ - tuner_xtal_cap = <25>; /* when tuner_xtal_mode = 3, set 25 */ + tuner_xtal_cap_0 = <38>; /* when tuner_xtal_mode = 3, set 25 */ }; atv-demod { @@ -1266,6 +1270,12 @@ acodec_adc = <1>; status = "okay"; + + /* !!!For --TV platform-- ONLY */ + Channel_Mask { + /*i2s has 4 pins, 8channel, mux output*/ + Spdif_samesource_Channel_Mask = "i2s_2/3"; + }; }; tdmb:tdm@1 { @@ -1305,7 +1315,7 @@ compatible = "amlogic, tl1-snd-spdif-a"; #sound-dai-cells = <0>; - clocks = <&clkc CLKID_MPLL0 + clocks = <&clkc CLKID_MPLL1 &clkc CLKID_FCLK_DIV4 &clkaudio CLKID_AUDIO_GATE_SPDIFIN &clkaudio CLKID_AUDIO_GATE_SPDIFOUT_A @@ -1318,8 +1328,11 @@ ; interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; pinctrl-0 = <&spdifout_a>; + pinctrl-1 = <&spdifout_a_mute>; + /* * whether do asrc for pcm and resample a or b @@ -1396,9 +1409,6 @@ &clkaudio CLKID_AUDIO_EQDRC>; clock-names = "gate", "srcpll", "eqdrc"; - eq_enable = <1>; - multiband_drc_enable = <0>; - fullband_drc_enable = <0>; /* * 0:tdmout_a * 1:tdmout_b @@ -1410,7 +1420,7 @@ /* max 0xf, each bit for one lane, usually one lane */ lane_mask = <0x1>; /* max 0xff, each bit for one channel */ - channel_mask = <0x3>; + channel_mask = <0xff>; status = "okay"; }; @@ -1430,8 +1440,9 @@ * NONE, * TDMIN_LB, 6 * LOOPBACK, 7 + * FRHDMIRX, 8 */ - resample_module = <3>; + resample_module = <8>; status = "okay"; }; @@ -1477,6 +1488,7 @@ "tdma_fs_z", "tdma_dout0_z"; function = "tdma_out"; + bias-pull-down; }; }; @@ -1517,6 +1529,13 @@ }; }; + spdifout_a_mute: spdifout_a_mute { + mux { /* GPIODV_4 */ + groups = "GPIODV_4"; + function = "gpio_periphs"; + }; + }; + pdmin: pdmin { mux { /* GPIOZ_7, GPIOZ_8, pdm_din2_z4 */ groups = "pdm_dclk_z", @@ -1593,11 +1612,12 @@ "MMC_CAP_1_8V_DDR", "MMC_CAP_HW_RESET", "MMC_CAP_ERASE", - "MMC_CAP_CMD23"; + "MMC_CAP_CMD23", + "MMC_CAP_DRIVER_TYPE_D"; caps2 = "MMC_CAP2_HS200"; /* "MMC_CAP2_HS400";*/ f_min = <400000>; - f_max = <200000000>; + f_max = <198000000>; }; }; diff --git a/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts b/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts index 6ddf8823143f..451945169e29 100644 --- a/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts +++ b/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts @@ -19,7 +19,7 @@ #include "mesontl1.dtsi" #include "partition_mbox_normal_P_32.dtsi" -#include "mesontl1_skt-panel.dtsi" +#include "mesontl1_x301-panel.dtsi" / { model = "Amlogic TL1 T962X2 X301"; @@ -39,11 +39,13 @@ i2c2 = &i2c2; i2c3 = &i2c3; i2c4 = &i2c_AO; + spi0 = &spicc0; + spi1 = &spicc1; }; memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x100000 0x7ff00000>; + linux,usable-memory = <0x0 0x80000000>; }; reserved-memory { @@ -59,6 +61,22 @@ alloc-ranges = <0x05000000 0x400000>; }; + logo_reserved:linux,meson-fb { + compatible = "shared-dma-pool"; + reusable; + size = <0x800000>; + alignment = <0x400000>; + alloc-ranges = <0x7f800000 0x800000>; + }; + + lcd_tcon_reserved:linux,lcd_tcon { + compatible = "shared-dma-pool"; + reusable; + size = <0xc00000>; + alignment = <0x400000>; + alloc-ranges = <0x7ec00000 0xc00000>; + }; + codec_mm_cma:linux,codec_mm_cma { compatible = "shared-dma-pool"; reusable; @@ -66,7 +84,7 @@ size = <0x13400000>; alignment = <0x400000>; linux,contiguous-region; - alloc-ranges = <0x12000000 0x13400000>; + alloc-ranges = <0x30000000 0x50000000>; }; /* codec shared reserved */ @@ -85,10 +103,18 @@ alloc-ranges = <0x7f800000 0x800000>; }; + lcd_tcon_reserved:linux,lcd_tcon { + compatible = "shared-dma-pool"; + reusable; + size = <0xc00000>; + alignment = <0x400000>; + alloc-ranges = <0x71000000 0xc00000>; + }; + ion_cma_reserved:linux,ion-dev { compatible = "shared-dma-pool"; reusable; - size = <0x8000000>; + size = <0x2000000>; alignment = <0x400000>; }; @@ -110,6 +136,44 @@ alignment = <0x400000>; }; + demod_reserved:linux,demod { + compatible = "amlogic, demod-mem"; + size = <0x800000>; //8M //100m 0x6400000 + alloc-ranges = <0x0 0x30000000>; + //multi-use; + //no-map; + }; + + /*di CMA pool */ + di_cma_reserved:linux,di_cma { + compatible = "shared-dma-pool"; + reusable; + /* buffer_size = 3621952(yuv422 8bit) + * | 4736064(yuv422 10bit) + * | 4074560(yuv422 10bit full pack mode) + * 10x3621952=34.6M(0x23) support 8bit + * 10x4736064=45.2M(0x2e) support 12bit + * 10x4074560=40M(0x28) support 10bit + */ + size = <0x02800000>; + alignment = <0x400000>; + }; + + /*di CMA pool */ + di_cma_reserved:linux,di_cma { + compatible = "shared-dma-pool"; + reusable; + /* buffer_size = 3621952(yuv422 8bit) + * | 4736064(yuv422 10bit) + * | 4074560(yuv422 10bit full pack mode) + * 10x3621952=34.6M(0x23) support 8bit + * 10x4736064=45.2M(0x2e) support 12bit + * 10x4074560=40M(0x28) support 10bit + */ + size = <0x02800000>; + alignment = <0x400000>; + }; + /* for hdmi rx emp use */ hdmirx_emp_cma_reserved:linux,emp_cma { compatible = "shared-dma-pool"; @@ -141,6 +205,31 @@ status = "okay"; }; + deinterlace { + compatible = "amlogic, deinterlace"; + status = "okay"; + /* 0:use reserved; 1:use cma; 2:use cma as reserved */ + flag_cma = <1>; + //memory-region = <&di_reserved>; + memory-region = <&di_cma_reserved>; + interrupts = <0 46 1 + 0 40 1>; + interrupt-names = "pre_irq", "post_irq"; + clocks = <&clkc CLKID_VPU_CLKB_TMP_COMP>, + <&clkc CLKID_VPU_CLKB_COMP>; + clock-names = "vpu_clkb_tmp_composite", + "vpu_clkb_composite"; + clock-range = <334 667>; + /* buffer-size = <3621952>;(yuv422 8bit) */ + buffer-size = <4074560>;/*yuv422 fullpack*/ + /* reserve-iomap = "true"; */ + /* if enable nr10bit, set nr10bit-support to 1 */ + post-wr-support = <1>; + nr10bit-support = <1>; + nrds-enable = <1>; + pps-enable = <1>; + }; + vout { compatible = "amlogic, vout"; status = "okay"; @@ -204,6 +293,7 @@ }; tdmacodec: codec { //sound-dai = <&dummy_codec>; + prefix-names = "AMP"; sound-dai = <&ad82584f &tl1_codec>; }; }; @@ -287,6 +377,7 @@ aml-audio-card,dai-link@4 { mclk-fs = <128>; + continuous-clock; /* suffix-name, sync with android audio hal used for */ suffix-name = "alsaPORT-spdif"; cpu { @@ -399,7 +490,7 @@ *if support 4K2K-YUV422-8BIT-WR:3840*2160*2*4 ~= 64M *if support 1080p-YUV422-8BIT-WR:1920*1080*2*4 ~= 16M */ - cma_size = <190>; + cma_size = <160>; interrupts = <0 83 1>; rdma-irq = <2>; clocks = <&clkc CLKID_FCLK_DIV5>, @@ -447,11 +538,93 @@ tv_bit_mode = <0x15>; }; + tvafe { + compatible = "amlogic, tvafe-tl1"; + /*memory-region = <&tvafe_cma_reserved>;*/ + status = "okay"; + flag_cma = <1>;/*1:share with codec_mm;0:cma alone*/ + cma_size = <5>;/*MByte*/ + reg = <0xff654000 0x2000>;/*tvafe reg base*/ + reserve-iomap = "true"; + tvafe_id = <0>; + //pinctrl-names = "default"; + /*!!particular sequence, no more and no less!!!*/ + tvafe_pin_mux = < + 3 /* TVAFE_CVBS_IN2, CVBS_IN0 = 0 */ + 1 /* TVAFE_CVBS_IN0, CVBS_IN1 */ + 2 /* TVAFE_CVBS_IN1, CVBS_IN2 */ + 4 /* TVAFE_CVBS_IN3, CVBS_IN3 */ + >; + clocks = <&clkc CLKID_DAC_CLK>; + clock-names = "vdac_clk_gate"; + }; + + vbi { + compatible = "amlogic, vbi"; + status = "okay"; + interrupts = <0 83 1>; + }; + + cvbsout { + compatible = "amlogic, cvbsout-tl1"; + status = "disabled"; + clocks = <&clkc CLKID_VCLK2_ENCI + &clkc CLKID_VCLK2_VENCI0 + &clkc CLKID_VCLK2_VENCI1 + &clkc CLKID_DAC_CLK>; + clock-names = "venci_top_gate", + "venci_0_gate", + "venci_1_gate", + "vdac_clk_gate"; + /* clk path */ + /* 0:vid_pll vid2_clk */ + /* 1:gp0_pll vid2_clk */ + /* 2:vid_pll vid1_clk */ + /* 3:gp0_pll vid1_clk */ + clk_path = <0>; + + /* performance: reg_address, reg_value */ + /* tl1 */ + performance = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x8080 + 0x1b05 0xfd + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + performance_sarft = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x0 + 0x1b05 0x9 + 0x1c59 0xfc48 + 0xffff 0x0>; /* ending flag */ + performance_revB_telecom = <0x1bf0 0x9 + 0x1b56 0x546 + 0x1b12 0x8080 + 0x1b05 0x9 + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + }; + + /* for external keypad */ + adc_keypad { + compatible = "amlogic, adc_keypad"; + status = "okay"; + key_name = "power","up","down","enter","left","right","home"; + key_num = <7>; + io-channels = <&saradc SARADC_CH2>,<&saradc SARADC_CH3>; + io-channel-names = "key-chan-2", "key-chan-3"; + key_chan = ; + key_code = <116 103 108 28 105 106 102>; + key_val = <0 143 266 389 512 143 266>; //val=voltage/1800mV*1023 + key_tolerance = <40 40 40 40 40 40 40>; + }; + unifykey { compatible = "amlogic, unifykey"; status = "okay"; - unifykey-num = <19>; + unifykey-num = <20>; unifykey-index-0 = <&keysn_0>; unifykey-index-1 = <&keysn_1>; unifykey-index-2 = <&keysn_2>; @@ -471,6 +644,7 @@ unifykey-index-16 = <&keysn_16>; unifykey-index-17 = <&keysn_17>; unifykey-index-18 = <&keysn_18>; + unifykey-index-19 = <&keysn_19>; keysn_0: key_0{ key-name = "usid"; @@ -572,6 +746,11 @@ key-device = "normal"; key-permit = "read","write","del"; }; + keysn_19:key_19{ + key-name = "lcd_tcon"; + key-device = "normal"; + key-permit = "read","write","del"; + }; }; /* End unifykey */ hdmirx { @@ -783,9 +962,9 @@ }; }; ddr_thermal: ddr_thermal { - polling-delay = <1000>; - polling-delay-passive = <250>; - sustainable-power = <1460>; + polling-delay = <2000>; + polling-delay-passive = <1000>; + sustainable-power = <1322>; thermal-sensors = <&d_tsensor 1>; trips { dswitch_on: trip-point@0 { @@ -810,6 +989,34 @@ }; }; }; + sar_thermal: sar_thermal { + polling-delay = <2000>; + polling-delay-passive = <1000>; + sustainable-power = <1322>; + thermal-sensors = <&s_tsensor 2>; + trips { + sswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + scontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + shot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + scritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + }; }; /*thermal zone end*/ /*DCDC for MP8756GD*/ @@ -819,51 +1026,51 @@ opp00 { opp-hz = /bits/ 64 <100000000>; - opp-microvolt = <731000>; + opp-microvolt = <739000>; }; opp01 { opp-hz = /bits/ 64 <250000000>; - opp-microvolt = <731000>; + opp-microvolt = <739000>; }; opp02 { opp-hz = /bits/ 64 <500000000>; - opp-microvolt = <731000>; + opp-microvolt = <739000>; }; opp03 { opp-hz = /bits/ 64 <667000000>; - opp-microvolt = <761000>; + opp-microvolt = <769000>; }; opp04 { opp-hz = /bits/ 64 <1000000000>; - opp-microvolt = <791000>; + opp-microvolt = <799000>; }; opp05 { opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <801000>; + opp-microvolt = <809000>; }; opp06 { opp-hz = /bits/ 64 <1404000000>; - opp-microvolt = <831000>; + opp-microvolt = <839000>; }; opp07 { opp-hz = /bits/ 64 <1500000000>; - opp-microvolt = <861000>; + opp-microvolt = <869000>; }; opp08 { opp-hz = /bits/ 64 <1608000000>; - opp-microvolt = <891000>; + opp-microvolt = <899000>; }; opp09 { opp-hz = /bits/ 64 <1704000000>; - opp-microvolt = <921000>; + opp-microvolt = <929000>; }; opp10 { opp-hz = /bits/ 64 <1800000000>; - opp-microvolt = <981000>; + opp-microvolt = <989000>; }; opp11 { opp-hz = /bits/ 64 <1908000000>; - opp-microvolt = <1011000>; + opp-microvolt = <1019000>; }; }; @@ -875,16 +1082,19 @@ }; tuner: tuner { + compatible = "amlogic, tuner"; status = "okay"; - tuner_name = "mxl661_tuner"; - tuner_i2c_adap = <&i2c0>; - tuner_i2c_addr = <0x60>; - tuner_xtal = <1>; /* 0: 16MHz, 1: 24MHz */ - tuner_xtal_mode = <3>; + tuner_cur = <0>; /* default use tuner */ + tuner_num = <1>; /* tuner number, multi tuner support */ + tuner_name_0 = "mxl661_tuner"; + tuner_i2c_adap_0 = <&i2c0>; + tuner_i2c_addr_0 = <0x60>; + tuner_xtal_0 = <1>; /* 0: 16MHz, 1: 24MHz */ + tuner_xtal_mode_0 = <3>; /* NO_SHARE_XTAL(0) * SLAVE_XTAL_SHARE(3) */ - tuner_xtal_cap = <25>; /* when tuner_xtal_mode = 3, set 25 */ + tuner_xtal_cap_0 = <25>; /* when tuner_xtal_mode = 3, set 25 */ }; bt-dev{ @@ -907,17 +1117,62 @@ wifi_pwm_conf:wifi_pwm_conf{ pwm_channel1_conf { - pwms = <&pwm_ab MESON_PWM_1 30040 0>; - duty-cycle = <15020>; + pwms = <&pwm_ab MESON_PWM_1 30541 0>; + duty-cycle = <15270>; times = <8>; }; pwm_channel2_conf { - pwms = <&pwm_ab MESON_PWM_3 30030 0>; - duty-cycle = <15015>; + pwms = <&pwm_ab MESON_PWM_3 30500 0>; + duty-cycle = <15250>; times = <12>; }; }; + sd_emmc_b: sdio@ffe05000 { + status = "okay"; + compatible = "amlogic, meson-mmc-tl1"; + reg = <0xffe05000 0x800>; + interrupts = <0 190 4>; + + pinctrl-names = "sdio_all_pins", + "sdio_clk_cmd_pins"; + pinctrl-0 = <&sdio_all_pins>; + pinctrl-1 = <&sdio_clk_cmd_pins>; + + clocks = <&clkc CLKID_SD_EMMC_B>, + <&clkc CLKID_SD_EMMC_B_P0_COMP>, + <&clkc CLKID_FCLK_DIV2>, + <&clkc CLKID_FCLK_DIV5>, + <&xtal>; + clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + + bus-width = <4>; + cap-sd-highspeed; + cap-mmc-highspeed; + max-frequency = <100000000>; + disable-wp; + sdio { + pinname = "sdio"; + ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", /**ptm debug */ + "MMC_CAP_UHS_SDR12", + "MMC_CAP_UHS_SDR25", + "MMC_CAP_UHS_SDR50", + "MMC_CAP_UHS_SDR104", + "MMC_PM_KEEP_POWER", + "MMC_CAP_SDIO_IRQ"; + f_min = <400000>; + f_max = <200000000>; + max_req_size = <0x20000>; /**128KB*/ + card_type = <3>; + /* 3:sdio device(ie:sdio-wifi), + * 4:SD combo (IO+mem) card + */ + }; + }; }; /* end of / */ &i2c0 { @@ -957,6 +1212,12 @@ acodec_adc = <1>; status = "okay"; + + /* !!!For --TV platform-- ONLY */ + Channel_Mask { + /*i2s has 4 pins, 8channel, mux output*/ + Spdif_samesource_Channel_Mask = "i2s_2/3"; + }; }; tdmb:tdm@1 { @@ -996,7 +1257,7 @@ compatible = "amlogic, tl1-snd-spdif-a"; #sound-dai-cells = <0>; - clocks = <&clkc CLKID_MPLL0 + clocks = <&clkc CLKID_MPLL1 &clkc CLKID_FCLK_DIV4 &clkaudio CLKID_AUDIO_GATE_SPDIFIN &clkaudio CLKID_AUDIO_GATE_SPDIFOUT_A @@ -1009,8 +1270,10 @@ ; interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; pinctrl-0 = <&spdifout_a>; + pinctrl-1 = <&spdifout_a_mute>; /* * whether do asrc for pcm and resample a or b @@ -1087,9 +1350,6 @@ &clkaudio CLKID_AUDIO_EQDRC>; clock-names = "gate", "srcpll", "eqdrc"; - eq_enable = <1>; - multiband_drc_enable = <0>; - fullband_drc_enable = <0>; /* * 0:tdmout_a * 1:tdmout_b @@ -1101,7 +1361,7 @@ /* max 0xf, each bit for one lane, usually one lane */ lane_mask = <0x1>; /* max 0xff, each bit for one channel */ - channel_mask = <0x3>; + channel_mask = <0xff>; status = "okay"; }; @@ -1121,8 +1381,9 @@ * NONE, * TDMIN_LB, 6 * LOOPBACK, 7 + * FRHDMIRX, 8 */ - resample_module = <3>; + resample_module = <8>; status = "okay"; }; @@ -1181,7 +1442,7 @@ * 0: in user space * 1: in kernel space */ - level = <0>; + level = <1>; status = "disabled"; }; @@ -1203,6 +1464,7 @@ "tdma_fs_z", "tdma_dout0_z"; function = "tdma_out"; + bias-pull-down; }; }; @@ -1243,6 +1505,13 @@ }; }; + spdifout_a_mute: spdifout_a_mute { + mux { /* GPIODV_4 */ + groups = "GPIODV_4"; + function = "gpio_periphs"; + }; + }; + pdmin: pdmin { mux { /* GPIOZ_7, GPIOZ_8, pdm_din2_z4 */ groups = "pdm_dclk_z", @@ -1252,6 +1521,40 @@ }; }; + /*backlight*/ + bl_pwm_vs_on_pins:bl_pwm_vs_on_pin { + mux { + groups = "pwm_vs_z5"; + function = "pwm_vs"; + }; + }; + bl_pwm_off_pins:bl_pwm_off_pin { + mux { + groups = "GPIOZ_5"; + function = "gpio_periphs"; + output-low; + }; + }; + bl_pwm_combo_0_vs_on_pins:bl_pwm_combo_0_vs_on_pin { + mux { + groups = "pwm_vs_z5"; + function = "pwm_vs"; + }; + }; + bl_pwm_combo_1_vs_on_pins:bl_pwm_combo_1_vs_on_pin { + mux { + groups = "pwm_vs_z6"; + function = "pwm_vs"; + }; + }; + bl_pwm_combo_off_pins:bl_pwm_combo_off_pin { + mux { + groups = "GPIOZ_5", + "GPIOZ_6"; + function = "gpio_periphs"; + output-low; + }; + }; }; /* end of pinctrl_periphs */ @@ -1283,6 +1586,24 @@ }; +&sd_emmc_c { + status = "okay"; + emmc { + caps = "MMC_CAP_8_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + /* "MMC_CAP_1_8V_DDR", */ + "MMC_CAP_HW_RESET", + "MMC_CAP_ERASE", + "MMC_CAP_CMD23", + "MMC_CAP_DRIVER_TYPE_D"; + caps2 = "MMC_CAP2_HS200", "MMC_CAP2_HS400"; + f_min = <400000>; + f_max = <198000000>; + }; +}; + &sd_emmc_c { status = "okay"; emmc { @@ -1301,17 +1622,6 @@ }; }; -&sd_emmc_b { - status = "okay"; - sd { - caps = "MMC_CAP_4_BIT_DATA", - "MMC_CAP_MMC_HIGHSPEED", - "MMC_CAP_SD_HIGHSPEED", - "MMC_CAP_NONREMOVABLE"; /**ptm debug */ - f_min = <400000>; - f_max = <200000000>; - }; -}; &spifc { status = "disabled"; @@ -1445,6 +1755,34 @@ status = "okay"; }; +&i2c1 { + status = "okay"; + clock-frequency = <300000>; + pinctrl-names="default"; + pinctrl-0=<&i2c1_h_pins>; + + lcd_extern_i2c0: lcd_extern_i2c@0 { + compatible = "lcd_ext, i2c"; + dev_name = "i2c_T5800Q"; + reg = <0x1c>; + status = "okay"; + }; + + lcd_extern_i2c1: lcd_extern_i2c@1 { + compatible = "lcd_ext, i2c"; + dev_name = "i2c_ANX6862"; + reg = <0x20>; + status = "okay"; + }; + + lcd_extern_i2c2: lcd_extern_i2c@2 { + compatible = "lcd_ext, i2c"; + dev_name = "i2c_ANX7911"; + reg = <0x74>; + status = "okay"; + }; +}; + &pwm_ab { status = "okay"; }; diff --git a/arch/arm/boot/dts/amlogic/tl1_t962x2_x301_1g.dts b/arch/arm/boot/dts/amlogic/tl1_t962x2_x301_1g.dts new file mode 100644 index 000000000000..44d93df9490e --- /dev/null +++ b/arch/arm/boot/dts/amlogic/tl1_t962x2_x301_1g.dts @@ -0,0 +1,1920 @@ +/* + * arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts + * + * Copyright (C) 2018 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +/dts-v1/; + +#include "mesontl1.dtsi" +#include "partition_mbox_normal_P_32.dtsi" +#include "mesontl1_x301-panel.dtsi" + +/ { + model = "Amlogic TL1 T962X2 X301"; + amlogic-dt-id = "tl1_t962x2_x301-1g"; + compatible = "amlogic, tl1_t962x2_x301"; + + aliases { + serial0 = &uart_AO; + serial1 = &uart_A; + serial2 = &uart_B; + serial3 = &uart_C; + serial4 = &uart_AO_B; + tsensor0 = &p_tsensor; + tsensor1 = &d_tsensor; + tsensor2 = &s_tsensor; + i2c0 = &i2c0; + i2c1 = &i2c1; + i2c2 = &i2c2; + i2c3 = &i2c3; + i2c4 = &i2c_AO; + spi0 = &spicc0; + spi1 = &spicc1; + }; + + memory@00000000 { + device_type = "memory"; + linux,usable-memory = <0x0 0x40000000>; + }; + + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + /* global autoconfigured region for contiguous allocations */ + ramoops@0x07400000 { + compatible = "ramoops"; + reg = <0x07400000 0x00100000>; + record-size = <0x8000>; + console-size = <0x8000>; + ftrace-size = <0x20000>; + }; + + secmon_reserved: linux,secmon { + compatible = "shared-dma-pool"; + reusable; + size = <0x400000>; + alignment = <0x400000>; + alloc-ranges = <0x05000000 0x400000>; + }; + + logo_reserved:linux,meson-fb { + compatible = "shared-dma-pool"; + reusable; + size = <0x800000>; + alignment = <0x400000>; + alloc-ranges = <0x3f800000 0x800000>; + }; + + lcd_tcon_reserved:linux,lcd_tcon { + compatible = "shared-dma-pool"; + reusable; + size = <0xc00000>; + alignment = <0x400000>; + alloc-ranges = <0x3ec00000 0xc00000>; + }; + + codec_mm_cma:linux,codec_mm_cma { + compatible = "shared-dma-pool"; + reusable; + /* ion_codec_mm max can alloc size 80M*/ + size = <0xd000000>; + alignment = <0x400000>; + linux,contiguous-region; + alloc-ranges = <0x30000000 0x10000000>; + }; + + /* codec shared reserved */ + codec_mm_reserved:linux,codec_mm_reserved { + compatible = "amlogic, codec-mm-reserved"; + size = <0x0>; + alignment = <0x100000>; + //no-map; + }; + + ion_cma_reserved:linux,ion-dev { + compatible = "shared-dma-pool"; + reusable; + size = <0x2000000>; + alignment = <0x400000>; + alloc-ranges = <0x00000000 0x30000000>; + }; + + /* vdin0 CMA pool */ + //vdin0_cma_reserved:linux,vdin0_cma { + // compatible = "shared-dma-pool"; + // reusable; + /* 3840x2160x4x4 ~=128 M */ + // size = <0xc400000>; + // alignment = <0x400000>; + //}; + + /* vdin1 CMA pool */ + vdin1_cma_reserved:linux,vdin1_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16 M */ + size = <0x1400000>; + alignment = <0x400000>; + alloc-ranges = <0x30000000 0x10000000>; + }; + + /*demod_reserved:linux,demod { + * compatible = "amlogic, demod-mem"; + * size = <0x800000>; //8M //100m 0x6400000 + * alloc-ranges = <0x0 0x30000000>; + * //multi-use; + * //no-map; + *}; + */ + + demod_cma_reserved:linux,demod_cma { + compatible = "shared-dma-pool"; + reusable; + /* 8M */ + size = <0x0800000>; + alignment = <0x400000>; + alloc-ranges = <0x30000000 0x10000000>; + }; + + /*di CMA pool */ + di_cma_reserved:linux,di_cma { + compatible = "shared-dma-pool"; + reusable; + /* buffer_size = 3621952(yuv422 8bit) + * | 4736064(yuv422 10bit) + * | 4074560(yuv422 10bit full pack mode) + * 10x3621952=34.6M(0x23) support 8bit + * 10x4736064=45.2M(0x2e) support 12bit + * 10x4074560=40M(0x28) support 10bit + */ + size = <0x02800000>; + alignment = <0x400000>; + alloc-ranges = <0x00000000 0x30000000>; + }; + + /* for hdmi rx emp use */ + hdmirx_emp_cma_reserved:linux,emp_cma { + compatible = "shared-dma-pool"; + /*linux,phandle = <5>;*/ + reusable; + /* 4M for emp to ddr */ + /* 32M for tmds to ddr */ + size = <0x400000>; + alignment = <0x400000>; + /* alloc-ranges = <0x400000 0x2000000>; */ + alloc-ranges = <0x00000000 0x30000000>; + }; + + /* POST PROCESS MANAGER */ + ppmgr_reserved:linux,ppmgr { + compatible = "amlogic, ppmgr_memory"; + size = <0x0>; + }; + + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + }; /* end of reserved-memory */ + + codec_mm { + compatible = "amlogic, codec, mm"; + status = "okay"; + memory-region = <&codec_mm_cma &codec_mm_reserved>; + }; + + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + + ppmgr { + compatible = "amlogic, ppmgr"; + memory-region = <&ppmgr_reserved>; + status = "okay"; + }; + + deinterlace { + compatible = "amlogic, deinterlace"; + status = "okay"; + /* 0:use reserved; 1:use cma; 2:use cma as reserved */ + flag_cma = <1>; + //memory-region = <&di_reserved>; + memory-region = <&di_cma_reserved>; + interrupts = <0 46 1 + 0 40 1>; + interrupt-names = "pre_irq", "post_irq"; + clocks = <&clkc CLKID_VPU_CLKB_TMP_COMP>, + <&clkc CLKID_VPU_CLKB_COMP>; + clock-names = "vpu_clkb_tmp_composite", + "vpu_clkb_composite"; + clock-range = <334 667>; + /* buffer-size = <3621952>;(yuv422 8bit) */ + buffer-size = <4074560>;/*yuv422 fullpack*/ + /* reserve-iomap = "true"; */ + /* if enable nr10bit, set nr10bit-support to 1 */ + post-wr-support = <1>; + nr10bit-support = <1>; + nrds-enable = <1>; + pps-enable = <1>; + }; + + vout { + compatible = "amlogic, vout"; + status = "okay"; + fr_auto_policy = <0>; + }; + + /* Audio Related start */ + pdm_codec:dummy { + #sound-dai-cells = <0>; + compatible = "amlogic, pdm_dummy_codec"; + status = "okay"; + }; + + dummy_codec:dummy { + #sound-dai-cells = <0>; + compatible = "amlogic, aml_dummy_codec"; + status = "okay"; + }; + + tl1_codec:codec { + #sound-dai-cells = <0>; + compatible = "amlogic, tl1_acodec"; + status = "okay"; + reg = <0xff632000 0x1c>; + tdmout_index = <0>; + tdmin_index = <0>; + dat1_ch_sel = <1>; + }; + + aml_dtv_demod { + compatible = "amlogic, ddemod-tl1"; + dev_name = "aml_dtv_demod"; + status = "okay"; + + //pinctrl-names="dtvdemod_agc"; + //pinctrl-0=<&dtvdemod_agc>; + + clocks = <&clkc CLKID_DAC_CLK>; + clock-names = "vdac_clk_gate"; + + reg = <0xff650000 0x4000 /*dtv demod base*/ + 0xff63c000 0x2000 /*hiu reg base*/ + 0xff800000 0x1000 /*io_aobus_base*/ + 0xffd01000 0x1000 /*reset*/ + >; + + dtv_demod0_mem = <0>; // need move to aml_dtv_demod ? + spectrum = <1>; + cma_flag = <1>; + cma_mem_size = <8>; + memory-region = <&demod_cma_reserved>;//<&demod_reserved>; + }; + + auge_sound { + compatible = "amlogic, tl1-sound-card"; + aml-audio-card,name = "AML-AUGESOUND"; + + avout_mute-gpios = <&gpio GPIODV_3 GPIO_ACTIVE_HIGH>; + + aml-audio-card,dai-link@0 { + format = "i2s"; + mclk-fs = <256>; + continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdma>; + frame-master = <&tdma>; + /* slave mode */ + /* + * bitclock-master = <&tdmacodec>; + * frame-master = <&tdmacodec>; + */ + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-i2s"; + tdmacpu: cpu { + sound-dai = <&tdma>; + dai-tdm-slot-tx-mask = + <1 1>; + dai-tdm-slot-rx-mask = + <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmacodec: codec { + //sound-dai = <&dummy_codec>; + prefix-names = "AMP"; + sound-dai = <&ad82584f &tl1_codec>; + }; + }; + + aml-audio-card,dai-link@1 { + status = "disabled"; + + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdmb>; + frame-master = <&tdmb>; + /* slave mode */ + //bitclock-master = <&tdmbcodec>; + //frame-master = <&tdmbcodec>; + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-pcm"; + cpu { + sound-dai = <&tdmb>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + /* + * dai-tdm-slot-tx-mask = + * <1 1 1 1 1 1 1 1>; + * dai-tdm-slot-rx-mask = + * <1 1 1 1 1 1 1 1>; + * dai-tdm-slot-num = <8>; + */ + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmbcodec: codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@2 { + status = "disabled"; + + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdmc>; + frame-master = <&tdmc>; + /* slave mode */ + //bitclock-master = <&tdmccodec>; + //frame-master = <&tdmccodec>; + /* suffix-name, sync with android audio hal used for */ + //suffix-name = "alsaPORT-tdm"; + cpu { + sound-dai = <&tdmc>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmccodec: codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@3 { + mclk-fs = <64>; + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-pdm"; + cpu { + sound-dai = <&pdm>; + }; + codec { + sound-dai = <&pdm_codec>; + }; + }; + + aml-audio-card,dai-link@4 { + mclk-fs = <128>; + continuous-clock; + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-spdif"; + cpu { + sound-dai = <&spdifa>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@5 { + mclk-fs = <128>; + cpu { + sound-dai = <&spdifb>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@6 { + mclk-fs = <256>; + suffix-name = "alsaPORT-tv"; + cpu { + sound-dai = <&extn>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + + }; + /* Audio Related end */ + + dvb { + compatible = "amlogic, dvb"; + status = "okay"; + fe0_mode = "internal"; + fe0_tuner = <&tuner>; + + /*"parallel","serial","disable"*/ + ts2 = "parallel"; + ts2_control = <0>; + ts2_invert = <0>; + interrupts = <0 23 1 + 0 5 1 + 0 53 1 + 0 19 1 + 0 25 1 + 0 17 1>; + interrupt-names = "demux0_irq", + "demux1_irq", + "demux2_irq", + "dvr0_irq", + "dvr1_irq", + "dvr2_irq"; + clocks = <&clkc CLKID_DEMUX + &clkc CLKID_ASYNC_FIFO + &clkc CLKID_AHB_ARB0 +/* &clkc CLKID_DOS_PARSER>;*/ + &clkc CLKID_U_PARSER>; + clock-names = "demux", "asyncfifo", "ahbarb0", "uparsertop"; + }; + + tvafe_avin_detect { + compatible = "amlogic, tl1_tvafe_avin_detect"; + status = "okay"; + device_mask = <1>;/*bit0:ch1;bit1:ch2*/ + interrupts = <0 12 1>, + <0 13 1>; + }; + + amlvecm { + compatible = "amlogic, vecm-tl1"; + dev_name = "aml_vecm"; + status = "okay"; + gamma_en = <1>;/*1:enabel ;0:disable*/ + wb_en = <1>;/*1:enabel ;0:disable*/ + cm_en = <1>;/*1:enabel ;0:disable*/ + wb_sel = <1>;/*1:mtx ;0:gainoff*/ + vlock_en = <1>;/*1:enable;0:disable*/ + vlock_mode = <0x4>; + /* vlock work mode: + *bit0:auto ENC + *bit1:auto PLL + *bit2:manual PLL + *bit3:manual ENC + *bit4:manual soft ENC + *bit5:manual MIX PLL ENC + */ + vlock_pll_m_limit = <1>; + vlock_line_limit = <3>; + }; + + vdin@0 { + compatible = "amlogic, vdin"; + /*memory-region = <&vdin0_cma_reserved>;*/ + status = "okay"; + /*bit0:(1:share with codec_mm;0:cma alone) + *bit8:(1:alloc in discontinus way;0:alone in continuous way) + */ + flag_cma = <0x101>; + /*MByte, if 10bit disable: 64M(YUV422), + *if 10bit enable: 64*1.5 = 96M(YUV422) + *if support 4K2K-YUV444-10bit-WR:3840*2160*4*4 ~= 128M + *if support 4K2K-YUV422-10bit-wr:3840*2160*3*4 ~= 96M + *if support 4K2K-YUV422-8BIT-WR:3840*2160*2*4 ~= 64M + *if support 1080p-YUV422-8BIT-WR:1920*1080*2*4 ~= 16M + */ + cma_size = <160>; + interrupts = <0 83 1>; + rdma-irq = <2>; + clocks = <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_VDIN_MEAS_COMP>; + clock-names = "fclk_div5", "cts_vdin_meas_clk"; + vdin_id = <0>; + /*vdin write mem color depth support: + * bit0:support 8bit + * bit1:support 9bit + * bit2:support 10bit + * bit3:support 12bit + * bit4:support yuv422 10bit full pack mode (from txl new add) + * bit8:use 8bit at 4k_50/60hz_10bit + * bit9:use 10bit at 4k_50/60hz_10bit + */ + tv_bit_mode = <0x215>; + /* afbce_bit_mode: (amlogic frame buff compression encoder) + * bit 0~3: + * 0 -- normal mode, not use afbce + * 1 -- use afbce non-mmu mode + * 2 -- use afbce mmu mode + * bit 4: + * 0 -- afbce compression-lossy disable + * 1 -- afbce compression-lossy enable + */ + afbce_bit_mode = <0x1>; + }; + + vdin@1 { + compatible = "amlogic, vdin"; + memory-region = <&vdin1_cma_reserved>; + status = "okay"; + /*bit0:(1:share with codec_mm;0:cma alone) + *bit8:(1:alloc in discontinus way;0:alone in continuous way) + */ + flag_cma = <0>; + interrupts = <0 85 1>; + rdma-irq = <4>; + clocks = <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_VDIN_MEAS_COMP>; + clock-names = "fclk_div5", "cts_vdin_meas_clk"; + vdin_id = <1>; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + */ + tv_bit_mode = <0x15>; + }; + + tvafe { + compatible = "amlogic, tvafe-tl1"; + /*memory-region = <&tvafe_cma_reserved>;*/ + status = "okay"; + flag_cma = <1>;/*1:share with codec_mm;0:cma alone*/ + cma_size = <5>;/*MByte*/ + reg = <0xff654000 0x2000>;/*tvafe reg base*/ + reserve-iomap = "true"; + tvafe_id = <0>; + //pinctrl-names = "default"; + /*!!particular sequence, no more and no less!!!*/ + tvafe_pin_mux = < + 3 /* TVAFE_CVBS_IN2, CVBS_IN0 = 0 */ + 1 /* TVAFE_CVBS_IN0, CVBS_IN1 */ + 2 /* TVAFE_CVBS_IN1, CVBS_IN2 */ + 4 /* TVAFE_CVBS_IN3, CVBS_IN3 */ + >; + clocks = <&clkc CLKID_DAC_CLK>; + clock-names = "vdac_clk_gate"; + }; + + vbi { + compatible = "amlogic, vbi"; + status = "okay"; + interrupts = <0 83 1>; + }; + + cvbsout { + compatible = "amlogic, cvbsout-tl1"; + status = "disabled"; + clocks = <&clkc CLKID_VCLK2_ENCI + &clkc CLKID_VCLK2_VENCI0 + &clkc CLKID_VCLK2_VENCI1 + &clkc CLKID_DAC_CLK>; + clock-names = "venci_top_gate", + "venci_0_gate", + "venci_1_gate", + "vdac_clk_gate"; + /* clk path */ + /* 0:vid_pll vid2_clk */ + /* 1:gp0_pll vid2_clk */ + /* 2:vid_pll vid1_clk */ + /* 3:gp0_pll vid1_clk */ + clk_path = <0>; + + /* performance: reg_address, reg_value */ + /* tl1 */ + performance = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x8080 + 0x1b05 0xfd + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + performance_sarft = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x0 + 0x1b05 0x9 + 0x1c59 0xfc48 + 0xffff 0x0>; /* ending flag */ + performance_revB_telecom = <0x1bf0 0x9 + 0x1b56 0x546 + 0x1b12 0x8080 + 0x1b05 0x9 + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + }; + + /* for external keypad */ + adc_keypad { + compatible = "amlogic, adc_keypad"; + status = "okay"; + key_name = "power","up","down","enter","left","right","home"; + key_num = <7>; + io-channels = <&saradc SARADC_CH2>,<&saradc SARADC_CH3>; + io-channel-names = "key-chan-2", "key-chan-3"; + key_chan = ; + key_code = <116 103 108 28 105 106 102>; + key_val = <0 143 266 389 512 143 266>; //val=voltage/1800mV*1023 + key_tolerance = <40 40 40 40 40 40 40>; +}; + + unifykey { + compatible = "amlogic, unifykey"; + status = "okay"; + + unifykey-num = <21>; + unifykey-index-0 = <&keysn_0>; + unifykey-index-1 = <&keysn_1>; + unifykey-index-2 = <&keysn_2>; + unifykey-index-3 = <&keysn_3>; + unifykey-index-4 = <&keysn_4>; + unifykey-index-5 = <&keysn_5>; + unifykey-index-6 = <&keysn_6>; + unifykey-index-7 = <&keysn_7>; + unifykey-index-8 = <&keysn_8>; + unifykey-index-9 = <&keysn_9>; + unifykey-index-10= <&keysn_10>; + unifykey-index-11 = <&keysn_11>; + unifykey-index-12 = <&keysn_12>; + unifykey-index-13 = <&keysn_13>; + unifykey-index-14 = <&keysn_14>; + unifykey-index-15 = <&keysn_15>; + unifykey-index-16 = <&keysn_16>; + unifykey-index-17 = <&keysn_17>; + unifykey-index-18 = <&keysn_18>; + unifykey-index-19 = <&keysn_19>; + unifykey-index-20 = <&keysn_20>; + + keysn_0: key_0{ + key-name = "usid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_1:key_1{ + key-name = "mac"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_2:key_2{ + key-name = "hdcp"; + key-device = "secure"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_3:key_3{ + key-name = "secure_boot_set"; + key-device = "efuse"; + key-permit = "write"; + }; + keysn_4:key_4{ + key-name = "mac_bt"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_5:key_5{ + key-name = "mac_wifi"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_6:key_6{ + key-name = "hdcp2_tx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_7:key_7{ + key-name = "hdcp2_rx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_8:key_8{ + key-name = "widevinekeybox"; + key-device = "secure"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_9:key_9{ + key-name = "deviceid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_10:key_10{ + key-name = "hdcp22_fw_private"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_11:key_11{ + key-name = "hdcp22_rx_private"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_12:key_12{ + key-name = "hdcp22_rx_fw"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_13:key_13{ + key-name = "hdcp14_rx"; + key-device = "normal"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_14:key_14{ + key-name = "prpubkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_15:key_15{ + key-name = "prprivkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_16:key_16{ + key-name = "lcd"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_17:key_17{ + key-name = "lcd_extern"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_18:key_18{ + key-name = "backlight"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_19:key_19{ + key-name = "lcd_tcon"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_20:key_20{ + key-name = "attestationkeybox";// attestation key + key-device = "secure"; + key-permit = "read","write","del"; + }; + }; /* End unifykey */ + + amlvideo2_0 { + compatible = "amlogic, amlvideo2"; + dev_name = "amlvideo2"; + status = "okay"; + amlvideo2_id = <0>; + cma_mode = <1>; + }; + + amlvideo2_1 { + compatible = "amlogic, amlvideo2"; + dev_name = "amlvideo2"; + status = "okay"; + amlvideo2_id = <1>; + cma_mode = <1>; + }; + + hdmirx { + compatible = "amlogic, hdmirx_tl1"; + #address-cells=<1>; + #size-cells=<1>; + memory-region = <&hdmirx_emp_cma_reserved>; + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&hdmirx_a_mux &hdmirx_b_mux + &hdmirx_c_mux>; + repeat = <0>; + interrupts = <0 41 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clkc CLKID_HDMIRX_MODET_COMP>, + <&clkc CLKID_HDMIRX_CFG_COMP>, + <&clkc CLKID_HDMIRX_ACR_COMP>, + <&clkc CLKID_HDMIRX_METER_COMP>, + <&clkc CLKID_HDMIRX_AXI_COMP>, + <&xtal>, + <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_FCLK_DIV7>, + <&clkc CLKID_HDCP22_SKP_COMP>, + <&clkc CLKID_HDCP22_ESM_COMP>; + // <&clkc CLK_AUD_PLL2FS>, + // <&clkc CLK_AUD_PLL4FS>, + // <&clkc CLK_AUD_OUT>; + clock-names = "hdmirx_modet_clk", + "hdmirx_cfg_clk", + "hdmirx_acr_ref_clk", + "cts_hdmirx_meter_clk", + "cts_hdmi_axi_clk", + "xtal", + "fclk_div5", + "fclk_div7", + "hdcp_rx22_skp", + "hdcp_rx22_esm"; + // "hdmirx_aud_pll2fs", + // "hdmirx_aud_pll4f", + // "clk_aud_out"; + hdmirx_id = <0>; + en_4k_2_2k = <0>; + hpd_low_cec_off = <1>; + /* bit4: enable feature, bit3~0: port number */ + disable_port = <0x0>; + /* MAP_ADDR_MODULE_CBUS */ + /* MAP_ADDR_MODULE_HIU */ + /* MAP_ADDR_MODULE_HDMIRX_CAPB3 */ + /* MAP_ADDR_MODULE_SEC_AHB */ + /* MAP_ADDR_MODULE_SEC_AHB2 */ + /* MAP_ADDR_MODULE_APB4 */ + /* MAP_ADDR_MODULE_TOP */ + reg = < 0x0 0x0 + 0xff63C000 0x2000 + 0xffe0d000 0x2000 + 0x0 0x0 + 0x0 0x0 + 0x0 0x0 + 0xff610000 0xa000>; + }; + + aocec: aocec { + compatible = "amlogic, aocec-tl1"; + /*device_name = "aocec";*/ + status = "okay"; + vendor_name = "Amlogic"; /* Max Chars: 8 */ + /* Refer to the following URL at: + * http://standards.ieee.org/develop/regauth/oui/oui.txt + */ + vendor_id = <0x000000>; + product_desc = "TL1"; /* Max Chars: 16 */ + cec_osd_string = "AML_TV"; /* Max Chars: 14 */ + port_num = <3>; + ee_cec; + arc_port_mask = <0x2>; + interrupts = <0 205 1 + 0 199 1>; + interrupt-names = "hdmi_aocecb","hdmi_aocec"; + pinctrl-names = "default","hdmitx_aocecb","cec_pin_sleep"; + pinctrl-0=<&aoceca_mux>; + pinctrl-1=<&aocecb_mux>; + pinctrl-2=<&aoceca_mux>; + reg = <0xFF80023c 0x4 + 0xFF800000 0x400>; + reg-names = "ao_exit","ao"; + }; + + p_tsensor: p_tsensor@ff634800 { + compatible = "amlogic, r1p1-tsensor"; + status = "okay"; + reg = <0xff634800 0x50>, + <0xff800268 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 35 0>; + clocks = <&clkc CLKID_TS_CLK_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + d_tsensor: d_tsensor@ff634c00 { + compatible = "amlogic, r1p1-tsensor"; + status = "okay"; + reg = <0xff634c00 0x50>, + <0xff800230 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 36 0>; + clocks = <&clkc CLKID_TS_CLK_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + s_tsensor: s_tsensor@ff635000 { + compatible = "amlogic, r1p1-tsensor"; + status = "okay"; + reg = <0xff635000 0x50>, + <0xff80026c 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 38 0>; + clocks = <&clkc CLKID_TS_CLK_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + meson_cooldev: meson-cooldev@0 { + status = "okay"; + compatible = "amlogic, meson-cooldev"; + cooling_devices { + cpufreq_cool_cluster0 { + min_state = <1000000>; + dyn_coeff = <140>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "cpufreq_cool0"; + device_type = "cpufreq"; + }; + cpucore_cool_cluster0 { + min_state = <1>; + dyn_coeff = <0>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "cpucore_cool0"; + device_type = "cpucore"; + }; + gpufreq_cool { + min_state = <400>; + dyn_coeff = <140>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "gpufreq_cool0"; + device_type = "gpufreq"; + }; + gpucore_cool { + min_state = <1>; + dyn_coeff = <0>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "gpucore_cool0"; + device_type = "gpucore"; + }; + }; + cpufreq_cool0:cpufreq_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + cpucore_cool0:cpucore_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + gpufreq_cool0:gpufreq_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + gpucore_cool0:gpucore_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + };/*meson cooling devices end*/ + + thermal-zones { + pll_thermal: pll_thermal { + polling-delay = <1000>; + polling-delay-passive = <100>; + sustainable-power = <1322>; + thermal-sensors = <&p_tsensor 0>; + trips { + pswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + pcontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + phot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + pcritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + cooling-maps { + cpufreq_cooling_map { + trip = <&pcontrol>; + cooling-device = <&cpufreq_cool0 0 11>; + contribution = <1024>; + }; + cpucore_cooling_map { + trip = <&pcontrol>; + cooling-device = <&cpucore_cool0 0 4>; + contribution = <1024>; + }; + gpufreq_cooling_map { + trip = <&pcontrol>; + cooling-device = <&gpufreq_cool0 0 4>; + contribution = <1024>; + }; + }; + }; + ddr_thermal: ddr_thermal { + polling-delay = <2000>; + polling-delay-passive = <1000>; + sustainable-power = <1322>; + thermal-sensors = <&d_tsensor 1>; + trips { + dswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + dcontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + dhot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + dcritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + }; + sar_thermal: sar_thermal { + polling-delay = <2000>; + polling-delay-passive = <1000>; + sustainable-power = <1322>; + thermal-sensors = <&s_tsensor 2>; + trips { + sswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + scontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + shot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + scritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + }; + }; /*thermal zone end*/ + + /*DCDC for MP8756GD*/ + cpu_opp_table0: cpu_opp_table0 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <729000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <729000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <729000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <749000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <769000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <779000>; + }; + opp06 { + opp-hz = /bits/ 64 <1404000000>; + opp-microvolt = <789000>; + }; + opp07 { + opp-hz = /bits/ 64 <1500000000>; + opp-microvolt = <799000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <809000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <849000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <899000>; + }; + opp11 { + opp-hz = /bits/ 64 <1908000000>; + opp-microvolt = <949000>; + }; + }; + + cpufreq-meson { + compatible = "amlogic, cpufreq-meson"; + pinctrl-names = "default"; + pinctrl-0 = <&pwm_ao_d_pins3>; + status = "okay"; + }; + + tuner: tuner { + compatible = "amlogic, tuner"; + status = "okay"; + tuner_cur = <0>; /* default use tuner */ + tuner_num = <1>; /* tuner number, multi tuner support */ + tuner_name_0 = "mxl661_tuner"; + tuner_i2c_adap_0 = <&i2c0>; + tuner_i2c_addr_0 = <0x60>; + tuner_xtal_0 = <1>; /* 0: 16MHz, 1: 24MHz */ + tuner_xtal_mode_0 = <3>; + /* NO_SHARE_XTAL(0) + * SLAVE_XTAL_SHARE(3) + */ + tuner_xtal_cap_0 = <25>; /* when tuner_xtal_mode = 3, set 25 */ + }; + + atv-demod { + compatible = "amlogic, atv-demod"; + status = "okay"; + tuner = <&tuner>; + btsc_sap_mode = <1>; + /* pinctrl-names="atvdemod_agc_pins"; */ + /* pinctrl-0=<&atvdemod_agc_pins>; */ + reg = <0xff656000 0x2000 /* demod reg */ + 0xff63c000 0x2000 /* hiu reg */ + 0xff634000 0x2000 /* periphs reg */ + 0xff64a000 0x2000>; /* audio reg */ + reg_23cf = <0x88188832>; + /*default:0x88188832;r840 on haier:0x48188832*/ + }; + + bt-dev{ + compatible = "amlogic, bt-dev"; + status = "okay"; + gpio_reset = <&gpio GPIOC_13 GPIO_ACTIVE_HIGH>; + }; + + wifi{ + compatible = "amlogic, aml_wifi"; + status = "okay"; + interrupt_pin = <&gpio GPIOC_12 GPIO_ACTIVE_HIGH>; + irq_trigger_type = "GPIO_IRQ_LOW"; + dhd_static_buf; //dhd_static_buf support + power_on_pin = <&gpio GPIOC_11 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&pwm_b_pins1>; + pwm_config = <&wifi_pwm_conf>; + }; + + wifi_pwm_conf:wifi_pwm_conf{ + pwm_channel1_conf { + pwms = <&pwm_ab MESON_PWM_1 30541 0>; + duty-cycle = <15270>; + times = <8>; + }; + pwm_channel2_conf { + pwms = <&pwm_ab MESON_PWM_3 30500 0>; + duty-cycle = <15250>; + times = <12>; + }; + }; + + sd_emmc_b: sdio@ffe05000 { + status = "okay"; + compatible = "amlogic, meson-mmc-tl1"; + reg = <0xffe05000 0x800>; + interrupts = <0 190 4>; + + pinctrl-names = "sdio_all_pins", + "sdio_clk_cmd_pins"; + pinctrl-0 = <&sdio_all_pins>; + pinctrl-1 = <&sdio_clk_cmd_pins>; + + clocks = <&clkc CLKID_SD_EMMC_B>, + <&clkc CLKID_SD_EMMC_B_P0_COMP>, + <&clkc CLKID_FCLK_DIV2>, + <&clkc CLKID_FCLK_DIV5>, + <&xtal>; + clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + + bus-width = <4>; + cap-sd-highspeed; + cap-mmc-highspeed; + max-frequency = <100000000>; + disable-wp; + sdio { + pinname = "sdio"; + ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", /**ptm debug */ + "MMC_CAP_UHS_SDR12", + "MMC_CAP_UHS_SDR25", + "MMC_CAP_UHS_SDR50", + "MMC_CAP_UHS_SDR104", + "MMC_PM_KEEP_POWER", + "MMC_CAP_SDIO_IRQ"; + f_min = <400000>; + f_max = <200000000>; + max_req_size = <0x20000>; /**128KB*/ + card_type = <3>; + /* 3:sdio device(ie:sdio-wifi), + * 4:SD combo (IO+mem) card + */ + }; + }; + +/* sd_emmc_b: sd@ffe05000 { + * status = "okay"; + * compatible = "amlogic, meson-mmc-tl1"; + * reg = <0xffe05000 0x800>; + * interrupts = <0 190 1>; + * + * pinctrl-names = "sd_all_pins", + * "sd_clk_cmd_pins", + * "sd_1bit_pins"; + * pinctrl-0 = <&sd_all_pins>; + * pinctrl-1 = <&sd_clk_cmd_pins>; + * pinctrl-2 = <&sd_1bit_pins>; + * + * clocks = <&clkc CLKID_SD_EMMC_B>, + * <&clkc CLKID_SD_EMMC_B_P0_COMP>, + * <&clkc CLKID_FCLK_DIV2>, + * <&clkc CLKID_FCLK_DIV5>, + * <&xtal>; + * clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + * + * bus-width = <4>; + * cap-sd-highspeed; + * cap-mmc-highspeed; + * max-frequency = <100000000>; + * disable-wp; + * sd { + * pinname = "sd"; + * ocr_avail = <0x200080>; + * caps = "MMC_CAP_4_BIT_DATA", + * "MMC_CAP_MMC_HIGHSPEED", + * "MMC_CAP_SD_HIGHSPEED"; + * f_min = <400000>; + * f_max = <200000000>; + * max_req_size = <0x20000>; + * no_sduart = <1>; + * gpio_dat3 = <&gpio GPIOC_3 GPIO_ACTIVE_HIGH>; + * jtag_pin = <&gpio GPIOC_0 GPIO_ACTIVE_HIGH>; + * gpio_cd = <&gpio GPIOC_10 GPIO_ACTIVE_HIGH>; + * card_type = <5>; + * }; + * }; + */ + +}; /* end of / */ + +&i2c0 { + status = "okay"; + clock-frequency = <300000>; + pinctrl-names="default"; + pinctrl-0=<&i2c0_dv_pins>; +}; + +&audiobus { + tdma:tdm@0 { + compatible = "amlogic, tl1-snd-tdma"; + #sound-dai-cells = <0>; + + dai-tdm-lane-slot-mask-in = <1 0>; + dai-tdm-lane-slot-mask-out = <1 1 1 1>; + dai-tdm-clk-sel = <0>; + + clocks = <&clkaudio CLKID_AUDIO_MCLK_A + &clkc CLKID_MPLL0 + &clkc CLKID_MPLL1 + &clkaudio CLKID_AUDIO_SPDIFOUT_A>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; + + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdma_mclk &tdmout_a>; + + /* + * 0: tdmout_a; + * 1: tdmout_b; + * 2: tdmout_c; + * 3: spdifout; + * 4: spdifout_b; + */ + samesource_sel = <3>; + + /* In for ACODEC_ADC */ + acodec_adc = <1>; + + status = "okay"; + + /* !!!For --TV platform-- ONLY */ + Channel_Mask { + /*i2s has 4 pins, 8channel, mux output*/ + Spdif_samesource_Channel_Mask = "i2s_2/3"; + }; + }; + + tdmb:tdm@1 { + compatible = "amlogic, tl1-snd-tdmb"; + #sound-dai-cells = <0>; + + dai-tdm-lane-slot-mask-in = <1 0 0 0>; + dai-tdm-lane-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <1>; + + clocks = <&clkaudio CLKID_AUDIO_MCLK_B + &clkc CLKID_MPLL1>; + clock-names = "mclk", "clk_srcpll"; + + status = "okay"; + }; + + tdmc:tdm@2 { + compatible = "amlogic, tl1-snd-tdmc"; + #sound-dai-cells = <0>; + + dai-tdm-lane-slot-mask-in = <1 0 0 0>; + dai-tdm-lane-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <2>; + + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmout_c &tdmin_c>; + + status = "okay"; + }; + + spdifa:spdif@0 { + compatible = "amlogic, tl1-snd-spdif-a"; + #sound-dai-cells = <0>; + + clocks = <&clkc CLKID_MPLL1 + &clkc CLKID_FCLK_DIV4 + &clkaudio CLKID_AUDIO_GATE_SPDIFIN + &clkaudio CLKID_AUDIO_GATE_SPDIFOUT_A + &clkaudio CLKID_AUDIO_SPDIFIN + &clkaudio CLKID_AUDIO_SPDIFOUT_A>; + clock-names = "sysclk", "fixed_clk", "gate_spdifin", + "gate_spdifout", "clk_spdifin", "clk_spdifout"; + + interrupts = + ; + interrupt-names = "irq_spdifin"; + + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; + pinctrl-0 = <&spdifout_a>; + pinctrl-1 = <&spdifout_a_mute>; + + /* + * whether do asrc for pcm and resample a or b + * if raw data, asrc is disabled automatically + * 0: "Disable", + * 1: "Enable:32K", + * 2: "Enable:44K", + * 3: "Enable:48K", + * 4: "Enable:88K", + * 5: "Enable:96K", + * 6: "Enable:176K", + * 7: "Enable:192K", + */ + asrc_id = <0>; + auto_asrc = <3>; + + status = "okay"; + }; + + spdifb:spdif@1 { + compatible = "amlogic, tl1-snd-spdif-b"; + #sound-dai-cells = <0>; + + clocks = <&clkc CLKID_MPLL0 /*CLKID_HIFI_PLL*/ + &clkaudio CLKID_AUDIO_GATE_SPDIFOUT_B + &clkaudio CLKID_AUDIO_SPDIFOUT_B>; + clock-names = "sysclk", + "gate_spdifout", "clk_spdifout"; + + status = "okay"; + }; + + pdm:pdm { + compatible = "amlogic, tl1-snd-pdm"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_PDM + &clkc CLKID_FCLK_DIV3 + &clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_PDMIN0 + &clkaudio CLKID_AUDIO_PDMIN1>; + clock-names = "gate", + "sysclk_srcpll", + "dclk_srcpll", + "pdm_dclk", + "pdm_sysclk"; + + pinctrl-names = "pdm_pins"; + pinctrl-0 = <&pdmin>; + + /* mode 0~4, defalut:1 */ + filter_mode = <1>; + + status = "okay"; + }; + + extn:extn { + compatible = "amlogic, snd-extn"; + #sound-dai-cells = <0>; + + interrupts = + ; + interrupt-names = "irq_frhdmirx"; + + status = "okay"; + }; + + aed:effect { + compatible = "amlogic, snd-effect-v2"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_EQDRC + &clkc CLKID_FCLK_DIV5 + &clkaudio CLKID_AUDIO_EQDRC>; + clock-names = "gate", "srcpll", "eqdrc"; + + /* + * 0:tdmout_a + * 1:tdmout_b + * 2:tdmout_c + * 3:spdifout + * 4:spdifout_b + */ + eqdrc_module = <0>; + /* max 0xf, each bit for one lane, usually one lane */ + lane_mask = <0x1>; + /* max 0xff, each bit for one channel */ + channel_mask = <0xff>; + + status = "okay"; + }; + + asrca: resample@0 { + compatible = "amlogic, tl1-resample-a"; + clocks = <&clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_MCLK_A + &clkaudio CLKID_AUDIO_RESAMPLE_A>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + /*same with toddr_src + * TDMIN_A, 0 + * TDMIN_B, 1 + * TDMIN_C, 2 + * SPDIFIN, 3 + * PDMIN, 4 + * NONE, + * TDMIN_LB, 6 + * LOOPBACK, 7 + */ + resample_module = <3>; + + status = "okay"; + }; + + asrcb: resample@1 { + compatible = "amlogic, tl1-resample-b"; + + clocks = <&clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_MCLK_F + &clkaudio CLKID_AUDIO_RESAMPLE_B>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + + /*same with toddr_src + * TDMIN_A, 0 + * TDMIN_B, 1 + * TDMIN_C, 2 + * SPDIFIN, 3 + * PDMIN, 4 + * NONE, + * TDMIN_LB, 6 + * LOOPBACK, 7 + */ + resample_module = <3>; + + status = "disabled"; + }; + + vad:vad { + compatible = "amlogic, snd-vad"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_TOVAD + &clkc CLKID_FCLK_DIV5 + &clkaudio CLKID_AUDIO_VAD>; + clock-names = "gate", "pll", "clk"; + + interrupts = ; + interrupt-names = "irq_wakeup", "irq_frame_sync"; + + /* + * Data src sel: + * 0: tdmin_a; + * 1: tdmin_b; + * 2: tdmin_c; + * 3: spdifin; + * 4: pdmin; + * 5: loopback_b; + * 6: tdmin_lb; + * 7: loopback_a; + */ + src = <4>; + + /* + * deal with hot word in user space or kernel space + * 0: in user space + * 1: in kernel space + */ + level = <1>; + + status = "disabled"; + }; +}; /* end of audiobus */ + +&pinctrl_periphs { + /* audio pin mux */ + + tdma_mclk: tdma_mclk { + mux { /* GPIOZ_0 */ + groups = "mclk0_z"; + function = "mclk0"; + }; + }; + + tdmout_a: tdmout_a { + mux { /* GPIOZ_1, GPIOZ_2, GPIOZ_3 */ + groups = "tdma_sclk_z", + "tdma_fs_z", + "tdma_dout0_z"; + function = "tdma_out"; + bias-pull-down; + }; + }; + + tdmin_a: tdmin_a { + mux { /* GPIOZ_9 */ + groups = "tdma_din2_z"; + function = "tdma_in"; + }; + }; + + tdmout_c: tdmout_c { + mux { /* GPIODV_7, GPIODV_8, GPIODV_9 */ + groups = "tdmc_sclk", + "tdmc_fs", + "tdmc_dout0"; + function = "tdmc_out"; + }; + }; + + tdmin_c: tdmin_c { + mux { /* GPIODV_10 */ + groups = "tdmc_din1"; + function = "tdmc_in"; + }; + }; + + spdifin_a: spdifin_a { + mux { /* GPIODV_5 */ + groups = "spdif_in"; + function = "spdif_in"; + }; + }; + + spdifout_a: spdifout_a { + mux { /* GPIODV_4 */ + groups = "spdif_out_dv4"; + function = "spdif_out"; + }; + }; + + spdifout_a_mute: spdifout_a_mute { + mux { /* GPIODV_4 */ + groups = "GPIODV_4"; + function = "gpio_periphs"; + }; + }; + + pdmin: pdmin { + mux { /* GPIOZ_7, GPIOZ_8, pdm_din2_z4 */ + groups = "pdm_dclk_z", + "pdm_din0_z", + "pdm_din2_z4"; + function = "pdm"; + }; + }; + + /*backlight*/ + bl_pwm_vs_on_pins:bl_pwm_vs_on_pin { + mux { + groups = "pwm_vs_z5"; + function = "pwm_vs"; + }; + }; + bl_pwm_off_pins:bl_pwm_off_pin { + mux { + groups = "GPIOZ_5"; + function = "gpio_periphs"; + output-low; + }; + }; + bl_pwm_combo_0_vs_on_pins:bl_pwm_combo_0_vs_on_pin { + mux { + groups = "pwm_vs_z5"; + function = "pwm_vs"; + }; + }; + bl_pwm_combo_1_vs_on_pins:bl_pwm_combo_1_vs_on_pin { + mux { + groups = "pwm_vs_z6"; + function = "pwm_vs"; + }; + }; + bl_pwm_combo_off_pins:bl_pwm_combo_off_pin { + mux { + groups = "GPIOZ_5", + "GPIOZ_6"; + function = "gpio_periphs"; + output-low; + }; + }; + +}; /* end of pinctrl_periphs */ + +&audio_data{ + status = "okay"; +}; + +&i2c2 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&i2c2_z_pins>; + clock-frequency = <400000>; + + tas5805: tas5805@36 { + compatible = "ti,tas5805"; + #sound-dai-cells = <0>; + codec_name = "tas5805"; + reg = <0x2d>; + status = "disable"; + }; + + ad82584f: ad82584f@62 { + compatible = "ESMT, ad82584f"; + #sound-dai-cells = <0>; + reg = <0x31>; + status = "okay"; + reset_pin = <&gpio_ao GPIOAO_6 0>; + }; + +}; + +&sd_emmc_c { + status = "okay"; + emmc { + caps = "MMC_CAP_8_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + "MMC_CAP_1_8V_DDR", + "MMC_CAP_HW_RESET", + "MMC_CAP_ERASE", + "MMC_CAP_CMD23", + "MMC_CAP_DRIVER_TYPE_D"; + caps2 = "MMC_CAP2_HS200", "MMC_CAP2_HS400"; + f_min = <400000>; + f_max = <198000000>; + }; +}; + + + +&spifc { + status = "disabled"; + spi-nor@0 { + cs_gpios = <&gpio BOOT_13 GPIO_ACTIVE_HIGH>; + }; +}; + +&slc_nand { + status = "disabled"; + plat-names = "bootloader", "nandnormal"; + plat-num = <2>; + plat-part-0 = <&bootloader>; + plat-part-1 = <&nandnormal>; + bootloader: bootloader{ + enable_pad = "ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <1>; + part_num = <0>; + rb_detect = <1>; + }; + nandnormal: nandnormal{ + enable_pad = "ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + plane_mode = "twoplane"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <2>; + part_num = <3>; + partition = <&nand_partitions>; + rb_detect = <1>; + }; + nand_partitions:nand_partition{ + /* + * if bl_mode is 1, tpl size was generate by + * fip_copies * fip_size which + * will not skip bad when calculating + * the partition size; + * + * if bl_mode is 0, + * tpl partition must be comment out. + */ + tpl{ + offset=<0x0 0x0>; + size=<0x0 0x0>; + }; + logo{ + offset=<0x0 0x0>; + size=<0x0 0x200000>; + }; + recovery{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + boot{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + system{ + offset=<0x0 0x0>; + size=<0x0 0x4000000>; + }; + data{ + offset=<0xffffffff 0xffffffff>; + size=<0x0 0x0>; + }; + }; +}; + +ðmac { + status = "okay"; + pinctrl-names = "internal_eth_pins"; + pinctrl-0 = <&internal_eth_pins>; + mc_val = <0x4be04>; + + internal_phy=<1>; +}; + +&uart_A { + status = "okay"; +}; + +&dwc3 { + status = "okay"; +}; + +&usb2_phy_v2 { + status = "okay"; + portnum = <3>; +}; + +&usb3_phy_v2 { + status = "okay"; + portnum = <0>; + otg = <0>; +}; + +&dwc2_a { + status = "okay"; + /** 0: normal, 1: otg+dwc3 host only, 2: otg+dwc3 device only*/ + controller-type = <1>; +}; + +&spicc0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&spicc0_pins_h>; + cs-gpios = <&gpio GPIOH_20 0>; +}; + +&meson_fb { + status = "okay"; + display_size_default = <1920 1080 1920 2160 32>; + mem_size = <0x00800000 0x1980000 0x100000 0x800000>; + logo_addr = "0x3f800000"; + mem_alloc = <0>; + pxp_mode = <0>; /** 0:normal mode 1:pxp mode */ +}; + +&pwm_AO_cd { + status = "okay"; +}; + +&saradc { + status = "okay"; +}; + +&i2c1 { + status = "okay"; + clock-frequency = <300000>; + pinctrl-names="default"; + pinctrl-0=<&i2c1_h_pins>; + + lcd_extern_i2c0: lcd_extern_i2c@0 { + compatible = "lcd_ext, i2c"; + dev_name = "i2c_T5800Q"; + reg = <0x1c>; + status = "okay"; + }; + + lcd_extern_i2c1: lcd_extern_i2c@1 { + compatible = "lcd_ext, i2c"; + dev_name = "i2c_ANX6862"; + reg = <0x20>; + status = "okay"; + }; + + lcd_extern_i2c2: lcd_extern_i2c@2 { + compatible = "lcd_ext, i2c"; + dev_name = "i2c_ANX7911"; + reg = <0x74>; + status = "okay"; + }; +}; + +&pwm_ab { + status = "okay"; +}; + +&pwm_cd { + status = "okay"; +}; + +&efuse { + status = "okay"; +}; diff --git a/arch/arm/boot/dts/amlogic/tm2_pxp.dts b/arch/arm/boot/dts/amlogic/tm2_pxp.dts new file mode 100644 index 000000000000..e812ec0f7cb5 --- /dev/null +++ b/arch/arm/boot/dts/amlogic/tm2_pxp.dts @@ -0,0 +1,1142 @@ +/* + * arch/arm/boot/dts/amlogic/tl1_pxp.dts + * + * Copyright (C) 2018 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +/dts-v1/; + +#include "mesontm2.dtsi" +#include "partition_mbox_normal_P_32.dtsi" +#include "mesontl1_skt-panel.dtsi" + +/ { + model = "Amlogic TL1 PXP"; + amlogic-dt-id = "tl1_pxp"; + compatible = "amlogic, tl1_pxp"; + + aliases { + serial0 = &uart_AO; + i2c0 = &i2c0; + i2c1 = &i2c1; + i2c2 = &i2c2; + i2c3 = &i2c3; + i2c4 = &i2c_AO; + }; + + memory@00000000 { + device_type = "memory"; + linux,usable-memory = <0x000000 0x80000000>; + }; + + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + /* global autoconfigured region for contiguous allocations */ + secmon_reserved: linux,secmon { + compatible = "shared-dma-pool"; + reusable; + size = <0x400000>; + alignment = <0x400000>; + alloc-ranges = <0x05000000 0x400000>; + }; + + codec_mm_cma:linux,codec_mm_cma { + compatible = "shared-dma-pool"; + reusable; + /* ion_codec_mm max can alloc size 80M*/ + size = <0x13400000>; + alignment = <0x400000>; + linux,contiguous-region; + /*alloc-ranges = <0x30000000 0x50000000>;*/ + }; + + logo_reserved:linux,meson-fb { + compatible = "shared-dma-pool"; + reusable; + size = <0x800000>; + alignment = <0x400000>; + alloc-ranges = <0x7f800000 0x800000>; + }; + + /* codec shared reserved */ + codec_mm_reserved:linux,codec_mm_reserved { + compatible = "amlogic, codec-mm-reserved"; + size = <0x0>; + alignment = <0x100000>; + //no-map; + }; + + ion_cma_reserved:linux,ion-dev { + compatible = "shared-dma-pool"; + reusable; + size = <0x8000000>; + alignment = <0x400000>; + }; + + /* vdin0 CMA pool */ + //vdin0_cma_reserved:linux,vdin0_cma { + // compatible = "shared-dma-pool"; + // reusable; + /* 3840x2160x4x4 ~=128 M */ + // size = <0xc400000>; + // alignment = <0x400000>; + //}; + + /* vdin1 CMA pool */ + vdin1_cma_reserved:linux,vdin1_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16 M */ + size = <0x1400000>; + alignment = <0x400000>; + }; + + /*di CMA pool */ + di_cma_reserved:linux,di_cma { + compatible = "shared-dma-pool"; + reusable; + /* buffer_size = 3621952(yuv422 8bit) + * | 4736064(yuv422 10bit) + * | 4074560(yuv422 10bit full pack mode) + * 10x3621952=34.6M(0x23) support 8bit + * 10x4736064=45.2M(0x2e) support 12bit + * 10x4074560=40M(0x28) support 10bit + */ + size = <0x02800000>; + alignment = <0x400000>; + }; + + /* for hdmi rx emp use */ + hdmirx_emp_cma_reserved:linux,emp_cma { + compatible = "shared-dma-pool"; + /*linux,phandle = <5>;*/ + reusable; + /* 4M for emp to ddr */ + /* 32M for tmds to ddr */ + size = <0x400000>; + alignment = <0x400000>; + /* alloc-ranges = <0x400000 0x2000000>; */ + }; + + /* POST PROCESS MANAGER */ + ppmgr_reserved:linux,ppmgr { + compatible = "amlogic, ppmgr_memory"; + size = <0x0>; + }; + + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + }; /* end of reserved-memory */ + + codec_mm { + status = "disabled"; + compatible = "amlogic, codec, mm"; + memory-region = <&codec_mm_cma &codec_mm_reserved>; + }; + + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "disabled"; + }; + + ppmgr { + status = "disabled"; + compatible = "amlogic, ppmgr"; + memory-region = <&ppmgr_reserved>; + }; + + deinterlace { + compatible = "amlogic, deinterlace"; + + status = "disabled"; + /* 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>; + }; + + vout { + compatible = "amlogic, vout"; + status = "okay"; + fr_auto_policy = <0>; + }; +/* Audio Related start */ + pdm_codec:dummy { + #sound-dai-cells = <0>; + compatible = "amlogic, pdm_dummy_codec"; + status = "okay"; + }; + + dummy_codec:dummy { + #sound-dai-cells = <0>; + compatible = "amlogic, aml_dummy_codec"; + status = "okay"; + }; + + tl1_codec:codec { + #sound-dai-cells = <0>; + compatible = "amlogic, tl1_acodec"; + status = "disabled"; + reg = <0xff632000 0x1c>; + tdmout_index = <1>; + tdmin_index = <1>; + }; + + aml_dtv_demod { + compatible = "amlogic, ddemod-tl1"; + dev_name = "aml_dtv_demod"; + status = "okay"; + + //pinctrl-names="dtvdemod_agc"; + //pinctrl-0=<&dtvdemod_agc>; + + clocks = <&clkc CLKID_DAC_CLK>; + clock-names = "vdac_clk_gate"; + + reg = <0xff650000 0x4000 /*dtv demod base*/ + 0xff63c000 0x2000 /*hiu reg base*/ + 0xff800000 0x1000 /*io_aobus_base*/ + 0xffd01000 0x1000 /*reset*/ + >; + + /*move from dvbfe*/ + dtv_demod0_mem = <0>; // need move to aml_dtv_demod ? + spectrum = <1>; + cma_flag = <1>; + cma_mem_size = <8>; + //memory-region = <&demod_cma_reserved>;//<&demod_reserved>; + }; + + auge_sound { + compatible = "amlogic, tl1-sound-card"; + aml-audio-card,name = "AML-AUGESOUND"; + + aml-audio-card,dai-link@0 { + format = "dsp_a"; + mclk-fs = <512>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdma>; + frame-master = <&tdma>; + /* slave mode */ + /* + * bitclock-master = <&tdmacodec>; + * frame-master = <&tdmacodec>; + */ + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-pcm"; + tdmacpu: cpu { + sound-dai = <&tdma>; + dai-tdm-slot-tx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-rx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-num = <8>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <24576000>; + }; + tdmacodec: codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@1 { + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdmb>; + frame-master = <&tdmb>; + /* slave mode */ + //bitclock-master = <&tdmbcodec>; + //frame-master = <&tdmbcodec>; + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-i2s"; + cpu { + sound-dai = <&tdmb>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + /* + * dai-tdm-slot-tx-mask = + * <1 1 1 1 1 1 1 1>; + * dai-tdm-slot-rx-mask = + * <1 1 1 1 1 1 1 1>; + * dai-tdm-slot-num = <8>; + */ + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmbcodec: codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@2 { + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdmc>; + frame-master = <&tdmc>; + /* slave mode */ + //bitclock-master = <&tdmccodec>; + //frame-master = <&tdmccodec>; + /* suffix-name, sync with android audio hal used for */ + //suffix-name = "alsaPORT-tdm"; + cpu { + sound-dai = <&tdmc>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmccodec: codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@3 { + mclk-fs = <64>; + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-pdm"; + cpu { + sound-dai = <&pdm>; + }; + codec { + sound-dai = <&pdm_codec>; + }; + }; + + aml-audio-card,dai-link@4 { + mclk-fs = <128>; + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-spdif"; + cpu { + sound-dai = <&spdifa>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@5 { + mclk-fs = <128>; + cpu { + sound-dai = <&spdifb>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@6 { + mclk-fs = <256>; + cpu { + sound-dai = <&extn>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + + }; + /* Audio Related end */ + + tvafe_avin_detect { + compatible = "amlogic, tl1_tvafe_avin_detect"; + status = "okay"; + device_mask = <1>;/*bit0:ch1;bit1:ch2*/ + interrupts = <0 12 1>, + <0 13 1>; + }; + + amlvecm { + compatible = "amlogic, vecm"; + dev_name = "aml_vecm"; + status = "okay"; + gamma_en = <1>;/*1:enabel ;0:disable*/ + wb_en = <1>;/*1:enabel ;0:disable*/ + cm_en = <1>;/*1:enabel ;0:disable*/ + wb_sel = <1>;/*1:mtx ;0:gainoff*/ + vlock_en = <1>;/*1:enable;0:disable*/ + vlock_mode = <0x4>; + /* vlock work mode: + *bit0:auto ENC + *bit1:auto PLL + *bit2:manual PLL + *bit3:manual ENC + *bit4:manual soft ENC + *bit5:manual MIX PLL ENC + */ + vlock_pll_m_limit = <1>; + vlock_line_limit = <3>; + }; + + amdolby_vision { + compatible = "amlogic, dolby_vision_tm2"; + dev_name = "aml_amdolby_vision_driver"; + status = "okay"; + tv_mode = <0>;/*1:enabel ;0:disable*/ + }; + + vdin@0 { + compatible = "amlogic, vdin"; + /*memory-region = <&vdin0_cma_reserved>;*/ + status = "disabled"; + /*bit0:(1:share with codec_mm;0:cma alone) + *bit8:(1:alloc in discontinus way;0:alone in continuous way) + */ + flag_cma = <0x101>; + /*MByte, if 10bit disable: 64M(YUV422), + *if 10bit enable: 64*1.5 = 96M(YUV422) + *if support 4K2K-YUV444-10bit-WR:3840*2160*4*4 ~= 128M + *if support 4K2K-YUV422-10bit-wr:3840*2160*3*4 ~= 96M + *if support 4K2K-YUV422-8BIT-WR:3840*2160*2*4 ~= 64M + *if support 1080p-YUV422-8BIT-WR:1920*1080*2*4 ~= 16M + */ + cma_size = <190>; + interrupts = <0 83 1>; + rdma-irq = <2>; + clocks = <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_VDIN_MEAS_COMP>; + clock-names = "fclk_div5", "cts_vdin_meas_clk"; + vdin_id = <0>; + /*vdin write mem color depth support: + * bit0:support 8bit + * bit1:support 9bit + * bit2:support 10bit + * bit3:support 12bit + * bit4:support yuv422 10bit full pack mode (from txl new add) + * bit8:use 8bit at 4k_50/60hz_10bit + * bit9:use 10bit at 4k_50/60hz_10bit + */ + tv_bit_mode = <0x215>; + /* afbce_bit_mode: (amlogic frame buff compression encoder) + * 0: normal mode, not use afbce + * 1: use afbce non-mmu mode + * 2: use afbce mmu mode + */ + afbce_bit_mode = <0>; + }; + + vdin@1 { + compatible = "amlogic, vdin"; + memory-region = <&vdin1_cma_reserved>; + status = "disabled"; + /*bit0:(1:share with codec_mm;0:cma alone) + *bit8:(1:alloc in discontinus way;0:alone in continuous way) + */ + flag_cma = <0>; + interrupts = <0 85 1>; + rdma-irq = <4>; + clocks = <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_VDIN_MEAS_COMP>; + clock-names = "fclk_div5", "cts_vdin_meas_clk"; + vdin_id = <1>; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + */ + tv_bit_mode = <0x15>; + }; + + hdmirx { + compatible = "amlogic, hdmirx_tl1"; + #address-cells=<1>; + #size-cells=<1>; + memory-region = <&hdmirx_emp_cma_reserved>; + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&hdmirx_a_mux &hdmirx_b_mux + &hdmirx_c_mux>; + repeat = <0>; + interrupts = <0 41 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clkc CLKID_HDMIRX_MODET_COMP>, + <&clkc CLKID_HDMIRX_CFG_COMP>, + <&clkc CLKID_HDMIRX_ACR_COMP>, + <&clkc CLKID_HDMIRX_METER_COMP>, + <&clkc CLKID_HDMIRX_AXI_COMP>, + <&xtal>, + <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_FCLK_DIV7>, + <&clkc CLKID_HDCP22_SKP_COMP>, + <&clkc CLKID_HDCP22_ESM_COMP>; + // <&clkc CLK_AUD_PLL2FS>, + // <&clkc CLK_AUD_PLL4FS>, + // <&clkc CLK_AUD_OUT>; + clock-names = "hdmirx_modet_clk", + "hdmirx_cfg_clk", + "hdmirx_acr_ref_clk", + "cts_hdmirx_meter_clk", + "cts_hdmi_axi_clk", + "xtal", + "fclk_div5", + "fclk_div7", + "hdcp_rx22_skp", + "hdcp_rx22_esm"; + // "hdmirx_aud_pll2fs", + // "hdmirx_aud_pll4f", + // "clk_aud_out"; + hdmirx_id = <0>; + en_4k_2_2k = <0>; + hpd_low_cec_off = <1>; + /* bit4: enable feature, bit3~0: port number */ + disable_port = <0x0>; + /* MAP_ADDR_MODULE_CBUS */ + /* MAP_ADDR_MODULE_HIU */ + /* MAP_ADDR_MODULE_HDMIRX_CAPB3 */ + /* MAP_ADDR_MODULE_SEC_AHB */ + /* MAP_ADDR_MODULE_SEC_AHB2 */ + /* MAP_ADDR_MODULE_APB4 */ + /* MAP_ADDR_MODULE_TOP */ + reg = < 0x0 0x0 + 0xff63C000 0x2000 + 0xffe0d000 0x2000 + 0x0 0x0 + 0x0 0x0 + 0x0 0x0 + 0xff610000 0xa000>; + }; + + aocec: aocec { + compatible = "amlogic, aocec-tm2"; + /*device_name = "aocec";*/ + status = "okay"; + vendor_name = "Amlogic"; /* Max Chars: 8 */ + /* Refer to the following URL at: + * http://standards.ieee.org/develop/regauth/oui/oui.txt + */ + vendor_id = <0x000000>; + product_desc = "TM2"; /* Max Chars: 16 */ + cec_osd_string = "AML_TV"; /* Max Chars: 14 */ + port_num = <3>; + ee_cec; + /*cec_sel = <2>;*/ + output = <1>; /*output port number*/ + arc_port_mask = <0x2>; + interrupts = <0 205 1 + 0 199 1>; + interrupt-names = "hdmi_aocecb","hdmi_aocec"; + pinctrl-names = "default","hdmitx_aocecb","cec_pin_sleep"; + pinctrl-0=<&aoceca_mux>; + pinctrl-1=<&aocecb_mux>; + pinctrl-2=<&aoceca_mux>; + reg = <0xFF80023c 0x4 + 0xFF800000 0x400>; + reg-names = "ao_exit","ao"; + }; + + cpu_opp_table0: cpu_opp_table0 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <730000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <730000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <730000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <750000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <770000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <780000>; + }; + opp06 { + opp-hz = /bits/ 64 <1404000000>; + opp-microvolt = <790000>; + }; + opp07 { + opp-hz = /bits/ 64 <1500000000>; + opp-microvolt = <800000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <810000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <850000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <900000>; + }; + opp11 { + opp-hz = /bits/ 64 <1908000000>; + opp-microvolt = <950000>; + }; + }; + + cpufreq-meson { + compatible = "amlogic, cpufreq-meson"; + pinctrl-names = "default"; + pinctrl-0 = <&pwm_ao_d_pins3>; + status = "okay"; + }; + + tuner: tuner { + compatible = "amlogic, tuner"; + status = "okay"; + tuner_cur = <0>; /* default use tuner */ + tuner_num = <1>; /* tuner number, multi tuner support */ + tuner_name_0 = "mxl661_tuner"; + tuner_i2c_adap_0 = <&i2c0>; + tuner_i2c_addr_0 = <0x60>; + tuner_xtal_0 = <1>; /* 0: 16MHz, 1: 24MHz */ + tuner_xtal_mode_0 = <3>; + /* NO_SHARE_XTAL(0) + * SLAVE_XTAL_SHARE(3) + */ + tuner_xtal_cap_0 = <25>; /* when tuner_xtal_mode = 3, set 25 */ + }; + + atv-demod { + compatible = "amlogic, atv-demod"; + status = "okay"; + tuner = <&tuner>; + btsc_sap_mode = <1>; + /* pinctrl-names="atvdemod_agc_pins"; */ + /* pinctrl-0=<&atvdemod_agc_pins>; */ + reg = <0xff656000 0x2000 /* demod reg */ + 0xff63c000 0x2000 /* hiu reg */ + 0xff634000 0x2000 /* periphs reg */ + 0xff64a000 0x2000>; /* audio reg */ + reg_23cf = <0x88188832>; + /*default:0x88188832;r840 on haier:0x48188832*/ + }; + + sd_emmc_b: sd@ffe05000 { + status = "disabled"; + compatible = "amlogic, meson-mmc-tl1"; + reg = <0xffe05000 0x800>; + interrupts = <0 190 1>; + + pinctrl-names = "sd_all_pins", + "sd_clk_cmd_pins", + "sd_1bit_pins"; + pinctrl-0 = <&sd_all_pins>; + pinctrl-1 = <&sd_clk_cmd_pins>; + pinctrl-2 = <&sd_1bit_pins>; + + clocks = <&clkc CLKID_SD_EMMC_B>, + <&clkc CLKID_SD_EMMC_B_P0_COMP>, + <&clkc CLKID_FCLK_DIV2>, + <&clkc CLKID_FCLK_DIV5>, + <&xtal>; + clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + + bus-width = <4>; + cap-sd-highspeed; + cap-mmc-highspeed; + max-frequency = <100000000>; + disable-wp; + sd { + pinname = "sd"; + ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE"; /**ptm debug */ + f_min = <400000>; + f_max = <200000000>; + max_req_size = <0x20000>; /**128KB*/ + no_sduart = <1>; + gpio_dat3 = <&gpio GPIOC_3 GPIO_ACTIVE_HIGH>; + jtag_pin = <&gpio GPIOC_0 GPIO_ACTIVE_HIGH>; + gpio_cd = <&gpio GPIOC_10 GPIO_ACTIVE_HIGH>; + card_type = <5>; + /* 3:sdio device(ie:sdio-wifi), + * 4:SD combo (IO+mem) card + */ + }; + }; +}; /* end of / */ + +&i2c0 { + status = "okay"; + clock-frequency = <300000>; + pinctrl-names="default"; + pinctrl-0=<&i2c0_dv_pins>; +}; + +&audiobus { + tdma:tdm@0 { + compatible = "amlogic, tl1-snd-tdma"; + #sound-dai-cells = <0>; + + dai-tdm-lane-slot-mask-in = <1 0>; + dai-tdm-lane-slot-mask-out = <1 0>; + dai-tdm-clk-sel = <0>; + + clocks = <&clkaudio CLKID_AUDIO_MCLK_A + &clkc CLKID_MPLL0>; + clock-names = "mclk", "clk_srcpll"; + + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdma_mclk &tdmout_a &tdmin_a>; + + status = "okay"; + }; + + tdmb:tdm@1 { + compatible = "amlogic, tl1-snd-tdmb"; + #sound-dai-cells = <0>; + + dai-tdm-lane-slot-mask-in = <1 0 0 0>; + dai-tdm-lane-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <1>; + + clocks = <&clkaudio CLKID_AUDIO_MCLK_B + &clkc CLKID_MPLL1>; + clock-names = "mclk", "clk_srcpll"; + + status = "okay"; + }; + + tdmc:tdm@2 { + compatible = "amlogic, tl1-snd-tdmc"; + #sound-dai-cells = <0>; + + dai-tdm-lane-slot-mask-in = <1 0 0 0>; + dai-tdm-lane-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <2>; + + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmout_c &tdmin_c>; + + status = "okay"; + }; + + spdifa:spdif@0 { + compatible = "amlogic, tl1-snd-spdif-a"; + #sound-dai-cells = <0>; + + clocks = <&clkc CLKID_MPLL0 + &clkc CLKID_FCLK_DIV4 + &clkaudio CLKID_AUDIO_GATE_SPDIFIN + &clkaudio CLKID_AUDIO_GATE_SPDIFOUT_A + &clkaudio CLKID_AUDIO_SPDIFIN + &clkaudio CLKID_AUDIO_SPDIFOUT_A>; + clock-names = "sysclk", "fixed_clk", "gate_spdifin", + "gate_spdifout", "clk_spdifin", "clk_spdifout"; + + interrupts = + ; + interrupt-names = "irq_spdifin"; + + pinctrl-names = "spdif_pins"; + pinctrl-0 = <&spdifout_a &spdifin_a>; + + /* + * whether do asrc for pcm and resample a or b + * if raw data, asrc is disabled automatically + * 0: "Disable", + * 1: "Enable:32K", + * 2: "Enable:44K", + * 3: "Enable:48K", + * 4: "Enable:88K", + * 5: "Enable:96K", + * 6: "Enable:176K", + * 7: "Enable:192K", + */ + asrc_id = <0>; + auto_asrc = <0>; + + status = "okay"; + }; + + spdifb:spdif@1 { + compatible = "amlogic, tl1-snd-spdif-b"; + #sound-dai-cells = <0>; + + clocks = <&clkc CLKID_MPLL0 /*CLKID_HIFI_PLL*/ + &clkaudio CLKID_AUDIO_GATE_SPDIFOUT_B + &clkaudio CLKID_AUDIO_SPDIFOUT_B>; + clock-names = "sysclk", + "gate_spdifout", "clk_spdifout"; + + status = "okay"; + }; + + pdm:pdm { + compatible = "amlogic, tl1-snd-pdm"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_PDM + &clkc CLKID_FCLK_DIV3 + &clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_PDMIN0 + &clkaudio CLKID_AUDIO_PDMIN1>; + clock-names = "gate", + "sysclk_srcpll", + "dclk_srcpll", + "pdm_dclk", + "pdm_sysclk"; + + pinctrl-names = "pdm_pins"; + pinctrl-0 = <&pdmin>; + + /* mode 0~4, defalut:1 */ + filter_mode = <1>; + + status = "okay"; + }; + + extn:extn { + compatible = "amlogic, snd-extn"; + #sound-dai-cells = <0>; + + interrupts = + ; + interrupt-names = "irq_frhdmirx"; + + status = "okay"; + }; + + aed:effect { + compatible = "amlogic, snd-effect-v2"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_EQDRC + &clkc CLKID_FCLK_DIV5 + &clkaudio CLKID_AUDIO_EQDRC>; + clock-names = "gate", "clk_srcpll", "eqdrc"; + + eq_enable = <1>; + multiband_drc_enable = <0>; + fullband_drc_enable = <0>; + /* + * 0:tdmout_a + * 1:tdmout_b + * 2:tdmout_c + * 3:spdifout + * 4:spdifout_b + */ + eqdrc_module = <1>; + /* max 0xf, each bit for one lane, usually one lane */ + lane_mask = <0x1>; + /* max 0xff, each bit for one channel */ + channel_mask = <0x3>; + + status = "disabled"; + }; + + asrca: resample@0 { + compatible = "amlogic, tl1-resample-a"; + clocks = <&clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_MCLK_F + &clkaudio CLKID_AUDIO_RESAMPLE_A>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + /*same with toddr_src + * TDMIN_A, 0 + * TDMIN_B, 1 + * TDMIN_C, 2 + * SPDIFIN, 3 + * PDMIN, 4 + * NONE, + * TDMIN_LB, 6 + * LOOPBACK, 7 + */ + resample_module = <3>; + + status = "disabled"; + }; + + asrcb: resample@1 { + compatible = "amlogic, tl1-resample-b"; + + clocks = <&clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_MCLK_F + &clkaudio CLKID_AUDIO_RESAMPLE_B>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + + /*same with toddr_src + * TDMIN_A, 0 + * TDMIN_B, 1 + * TDMIN_C, 2 + * SPDIFIN, 3 + * PDMIN, 4 + * NONE, + * TDMIN_LB, 6 + * LOOPBACK, 7 + */ + resample_module = <3>; + + status = "disabled"; + }; + +}; /* end of audiobus */ +&pinctrl_periphs { + /* audio pin mux */ + + tdma_mclk: tdma_mclk { + mux { /* GPIOZ_0 */ + groups = "mclk0_z"; + function = "mclk0"; + }; + }; + + tdmout_a: tdmout_a { + mux { /* GPIOZ_1, GPIOZ_2, GPIOZ_3, GPIOZ_5, GPIOZ_6 */ + groups = "tdma_sclk_z", + "tdma_fs_z", + "tdma_dout0_z", + "tdma_dout2_z", + "tdma_dout3_z"; + function = "tdma_out"; + }; + }; + + tdmin_a: tdmin_a { + mux { /* GPIOZ_9 */ + groups = "tdma_din2_z"; + function = "tdma_in"; + }; + }; + + tdmout_c: tdmout_c { + mux { /* GPIODV_7, GPIODV_8, GPIODV_9 */ + groups = "tdmc_sclk", + "tdmc_fs", + "tdmc_dout0"; + function = "tdmc_out"; + }; + }; + + tdmin_c: tdmin_c { + mux { /* GPIODV_10 */ + groups = "tdmc_din1"; + function = "tdmc_in"; + }; + }; + + spdifin_a: spdifin_a { + mux { /* GPIODV_5 */ + groups = "spdif_in"; + function = "spdif_in"; + }; + }; + + spdifout_a: spdifout_a { + mux { /* GPIODV_4 */ + groups = "spdif_out_dv4"; + function = "spdif_out"; + }; + }; + + pdmin: pdmin { + mux { /* GPIOZ_7, GPIOZ_8*/ + groups = "pdm_dclk_z", + "pdm_din0_z"; + function = "pdm"; + }; + }; + + +}; /* end of pinctrl_periphs */ + +&pinctrl_aobus { + spdifout: spdifout { + mux { /* gpiao_10 */ + groups = "spdif_out_ao"; + function = "spdif_out_ao"; + }; + }; +}; /* end of pinctrl_aobus */ + +&sd_emmc_b { + status = "okay"; + sd { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE"; /**ptm debug */ + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&spifc { + status = "disabled"; + spi-nor@0 { + cs_gpios = <&gpio BOOT_13 GPIO_ACTIVE_HIGH>; + }; +}; + +&slc_nand { + status = "disabled"; + plat-names = "bootloader", "nandnormal"; + plat-num = <2>; + plat-part-0 = <&bootloader>; + plat-part-1 = <&nandnormal>; + bootloader: bootloader{ + enable_pad = "ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <1>; + part_num = <0>; + rb_detect = <1>; + }; + nandnormal: nandnormal{ + enable_pad = "ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + plane_mode = "twoplane"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <2>; + part_num = <3>; + partition = <&nand_partitions>; + rb_detect = <1>; + }; + nand_partitions:nand_partition{ + /* + * if bl_mode is 1, tpl size was generate by + * fip_copies * fip_size which + * will not skip bad when calculating + * the partition size; + * + * if bl_mode is 0, + * tpl partition must be comment out. + */ + tpl{ + offset=<0x0 0x0>; + size=<0x0 0x0>; + }; + logo{ + offset=<0x0 0x0>; + size=<0x0 0x200000>; + }; + recovery{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + boot{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + system{ + offset=<0x0 0x0>; + size=<0x0 0x4000000>; + }; + data{ + offset=<0xffffffff 0xffffffff>; + size=<0x0 0x0>; + }; + }; +}; + +&dwc3 { + status = "disabled"; +}; + +&usb2_phy_v2 { + status = "disabled"; + portnum = <3>; +}; + +&usb3_phy_v2 { + status = "disabled"; + portnum = <0>; + otg = <0>; +}; + +&dwc2_a { + status = "disabled"; + /** 0: normal, 1: otg+dwc3 host only, 2: otg+dwc3 device only*/ + controller-type = <1>; +}; + +&spicc0 { + status = "disabled"; + pinctrl-names = "default"; + pinctrl-0 = <&spicc0_pins_h>; + cs-gpios = <&gpio GPIOH_20 0>; +}; + +&meson_fb { + status = "okay"; + display_size_default = <1920 1080 1920 2160 32>; + mem_size = <0x00800000 0x1980000 0x100000 0x100000 0x800000>; + logo_addr = "0x7f800000"; + mem_alloc = <1>; + pxp_mode = <1>; /** 0:normal mode 1:pxp mode */ +}; + +&pwm_AO_cd { + status = "disabled"; +}; + +&efuse { + status = "disabled"; +}; diff --git a/arch/arm/boot/dts/amlogic/tm2_t962e2_ab311.dts b/arch/arm/boot/dts/amlogic/tm2_t962e2_ab311.dts new file mode 100644 index 000000000000..198bcf976d6f --- /dev/null +++ b/arch/arm/boot/dts/amlogic/tm2_t962e2_ab311.dts @@ -0,0 +1,1993 @@ +/* + * arch/arm/boot/dts/amlogic/tm2_t962e2_ab311.dts + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +/dts-v1/; + +#include "mesontm2.dtsi" +#include "partition_mbox_normal.dtsi" + +/ { + model = "Amlogic TM2 T962E2 AB311"; + amlogic-dt-id = "tm2_t962e2_ab311"; + compatible = "amlogic, tm2_t962e2_ab311"; + + aliases { + serial0 = &uart_AO; + serial1 = &uart_A; + serial2 = &uart_B; + serial3 = &uart_C; + serial4 = &uart_AO_B; + tsensor0 = &p_tsensor; + tsensor1 = &d_tsensor; + tsensor2 = &s_tsensor; + i2c0 = &i2c0; + i2c1 = &i2c1; + i2c2 = &i2c2; + i2c3 = &i2c3; + i2c4 = &i2c_AO; + spi0 = &spicc0; + spi1 = &spicc1; + }; + + memory@00000000 { + device_type = "memory"; + linux,usable-memory = <0x0 0x80000000>; + }; + + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + /* global autoconfigured region for contiguous allocations */ + ramoops@0x07400000 { + compatible = "ramoops"; + reg = <0x07400000 0x00100000>; + record-size = <0x8000>; + console-size = <0x8000>; + ftrace-size = <0x20000>; + }; + + secmon_reserved: linux,secmon { + compatible = "shared-dma-pool"; + reusable; + size = <0x400000>; + alignment = <0x400000>; + alloc-ranges = <0x05000000 0x400000>; + }; + + logo_reserved:linux,meson-fb { + compatible = "shared-dma-pool"; + reusable; + size = <0x800000>; + alignment = <0x400000>; + alloc-ranges = <0x7f800000 0x800000>; + }; + + lcd_tcon_reserved:linux,lcd_tcon { + compatible = "shared-dma-pool"; + reusable; + size = <0xc00000>; + alignment = <0x400000>; + alloc-ranges = <0x7ec00000 0xc00000>; + }; + + codec_mm_cma:linux,codec_mm_cma { + compatible = "shared-dma-pool"; + reusable; + /* ion_codec_mm max can alloc size 80M*/ + size = <0x13400000>; + alignment = <0x400000>; + linux,contiguous-region; + alloc-ranges = <0x30000000 0x50000000>; + }; + + /* codec shared reserved */ + codec_mm_reserved:linux,codec_mm_reserved { + compatible = "amlogic, codec-mm-reserved"; + size = <0x0>; + alignment = <0x100000>; + //no-map; + }; + + ion_cma_reserved:linux,ion-dev { + compatible = "shared-dma-pool"; + reusable; + size = <0x2000000>; + alignment = <0x400000>; + }; + + /* vdin0 CMA pool */ + //vdin0_cma_reserved:linux,vdin0_cma { + // compatible = "shared-dma-pool"; + // reusable; + /* 3840x2160x4x4 ~=128 M */ + // size = <0xc400000>; + // alignment = <0x400000>; + //}; + + /* vdin1 CMA pool */ + vdin1_cma_reserved:linux,vdin1_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16 M */ + size = <0x1400000>; + alignment = <0x400000>; + }; + + /*demod_reserved:linux,demod { + * compatible = "amlogic, demod-mem"; + * size = <0x800000>; //8M //100m 0x6400000 + * alloc-ranges = <0x0 0x30000000>; + * //multi-use; + * //no-map; + *}; + */ + + demod_cma_reserved:linux,demod_cma { + compatible = "shared-dma-pool"; + reusable; + /* 8M */ + size = <0x0800000>; + alignment = <0x400000>; + }; + + /*di CMA pool */ + di_cma_reserved:linux,di_cma { + compatible = "shared-dma-pool"; + reusable; + /* buffer_size = 3621952(yuv422 8bit) + * | 4736064(yuv422 10bit) + * | 4074560(yuv422 10bit full pack mode) + * 10x3621952=34.6M(0x23) support 8bit + * 10x4736064=45.2M(0x2e) support 12bit + * 10x4074560=40M(0x28) support 10bit + */ + size = <0x02800000>; + alignment = <0x400000>; + }; + + /* for hdmi rx emp use */ + hdmirx_emp_cma_reserved:linux,emp_cma { + compatible = "shared-dma-pool"; + /*linux,phandle = <5>;*/ + reusable; + /* 4M for emp to ddr */ + /* 32M for tmds to ddr */ + size = <0x400000>; + alignment = <0x400000>; + /* alloc-ranges = <0x400000 0x2000000>; */ + }; + + /* POST PROCESS MANAGER */ + ppmgr_reserved:linux,ppmgr { + compatible = "amlogic, ppmgr_memory"; + size = <0x0>; + }; + + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + }; /* end of reserved-memory */ + galcore { + status = "okay"; + }; + codec_mm { + compatible = "amlogic, codec, mm"; + status = "okay"; + memory-region = <&codec_mm_cma &codec_mm_reserved>; + }; + + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + + ppmgr { + compatible = "amlogic, ppmgr"; + memory-region = <&ppmgr_reserved>; + status = "okay"; + }; + + deinterlace { + compatible = "amlogic, deinterlace"; + status = "okay"; + /* 0:use reserved; 1:use cma; 2:use cma as reserved */ + flag_cma = <1>; + //memory-region = <&di_reserved>; + memory-region = <&di_cma_reserved>; + interrupts = <0 46 1 + 0 40 1>; + interrupt-names = "pre_irq", "post_irq"; + clocks = <&clkc CLKID_VPU_CLKB_TMP_COMP>, + <&clkc CLKID_VPU_CLKB_COMP>; + clock-names = "vpu_clkb_tmp_composite", + "vpu_clkb_composite"; + clock-range = <334 667>; + /* buffer-size = <3621952>;(yuv422 8bit) */ + buffer-size = <4074560>;/*yuv422 fullpack*/ + /* reserve-iomap = "true"; */ + /* if enable nr10bit, set nr10bit-support to 1 */ + post-wr-support = <1>; + nr10bit-support = <1>; + nrds-enable = <1>; + pps-enable = <1>; + }; + + vout { + compatible = "amlogic, vout"; + status = "okay"; + fr_auto_policy = <0>; + }; + + /* Audio Related start */ + pdm_codec:dummy { + #sound-dai-cells = <0>; + compatible = "amlogic, pdm_dummy_codec"; + status = "okay"; + }; + + dummy_codec:dummy { + #sound-dai-cells = <0>; + compatible = "amlogic, aml_dummy_codec"; + status = "okay"; + }; + + tl1_codec:codec { + #sound-dai-cells = <0>; + compatible = "amlogic, tl1_acodec"; + status = "okay"; + reg = <0xff632000 0x1c>; + tdmout_index = <0>; + tdmin_index = <0>; + dat1_ch_sel = <1>; + }; + + aml_dtv_demod { + compatible = "amlogic, ddemod-tl1"; + dev_name = "aml_dtv_demod"; + status = "okay"; + + //pinctrl-names="dtvdemod_agc"; + //pinctrl-0=<&dtvdemod_agc>; + + clocks = <&clkc CLKID_DAC_CLK>; + clock-names = "vdac_clk_gate"; + + reg = <0xff650000 0x4000 /*dtv demod base*/ + 0xff63c000 0x2000 /*hiu reg base*/ + 0xff800000 0x1000 /*io_aobus_base*/ + 0xffd01000 0x1000 /*reset*/ + >; + + dtv_demod0_mem = <0>; // need move to aml_dtv_demod ? + spectrum = <1>; + cma_flag = <1>; + cma_mem_size = <8>; + memory-region = <&demod_cma_reserved>;//<&demod_reserved>; + }; + + auge_sound { + compatible = "amlogic, tm2-sound-card"; + aml-audio-card,name = "AML-AUGESOUND"; + + avout_mute-gpios = <&gpio GPIODV_3 GPIO_ACTIVE_HIGH>; + + aml-audio-card,dai-link@0 { + format = "i2s"; + mclk-fs = <256>; + continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdma>; + frame-master = <&tdma>; + /* slave mode */ + /* + * bitclock-master = <&tdmacodec>; + * frame-master = <&tdmacodec>; + */ + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-i2s"; + tdmacpu: cpu { + sound-dai = <&tdma>; + dai-tdm-slot-tx-mask = + <1 1>; + dai-tdm-slot-rx-mask = + <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmacodec: codec { + //sound-dai = <&dummy_codec>; + prefix-names = "AMP", "AMP1"; + sound-dai = <&ad82584f &ad82584f1 &tl1_codec>; + }; + }; + + aml-audio-card,dai-link@1 { + + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdmb>; + frame-master = <&tdmb>; + /* slave mode */ + //bitclock-master = <&tdmbcodec>; + //frame-master = <&tdmbcodec>; + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-pcm"; + cpu { + sound-dai = <&tdmb>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + /* + * dai-tdm-slot-tx-mask = + * <1 1 1 1 1 1 1 1>; + * dai-tdm-slot-rx-mask = + * <1 1 1 1 1 1 1 1>; + * dai-tdm-slot-num = <8>; + */ + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmbcodec: codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@2 { + + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdmc>; + frame-master = <&tdmc>; + /* slave mode */ + //bitclock-master = <&tdmccodec>; + //frame-master = <&tdmccodec>; + /* suffix-name, sync with android audio hal used for */ + //suffix-name = "alsaPORT-tdm"; + cpu { + sound-dai = <&tdmc>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmccodec: codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@3 { + mclk-fs = <64>; + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-pdm"; + cpu { + sound-dai = <&pdm>; + }; + codec { + sound-dai = <&pdm_codec>; + }; + }; + + aml-audio-card,dai-link@4 { + mclk-fs = <128>; + continuous-clock; + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-spdif"; + cpu { + sound-dai = <&spdifa>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@5 { + mclk-fs = <128>; + suffix-name = "alsaPORT-spdifb"; + cpu { + sound-dai = <&spdifb>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@6 { + mclk-fs = <256>; + suffix-name = "alsaPORT-tv"; + cpu { + sound-dai = <&extn>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@7 { + mclk-fs = <256>; + suffix-name = "alsaPORT-earc"; + cpu { + sound-dai = <&earc>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + }; + /* Audio Related end */ + + dvb { + compatible = "amlogic, dvb"; + status = "okay"; + fe0_mode = "internal"; + fe0_tuner = <&tuner>; + + /*"parallel","serial","disable"*/ + ts2 = "parallel"; + ts2_control = <0>; + ts2_invert = <0>; + interrupts = <0 23 1 + 0 5 1 + 0 53 1 + 0 19 1 + 0 25 1 + 0 17 1>; + interrupt-names = "demux0_irq", + "demux1_irq", + "demux2_irq", + "dvr0_irq", + "dvr1_irq", + "dvr2_irq"; + clocks = <&clkc CLKID_DEMUX + &clkc CLKID_ASYNC_FIFO + &clkc CLKID_AHB_ARB0 +/* &clkc CLKID_DOS_PARSER>;*/ + &clkc CLKID_U_PARSER>; + clock-names = "demux", "asyncfifo", "ahbarb0", "uparsertop"; + }; + + tvafe_avin_detect { + compatible = "amlogic, tl1_tvafe_avin_detect"; + status = "okay"; + device_mask = <1>;/*bit0:ch1;bit1:ch2*/ + interrupts = <0 12 1>, + <0 13 1>; + }; + + amlvecm { + compatible = "amlogic, vecm-tl1"; + dev_name = "aml_vecm"; + status = "okay"; + gamma_en = <1>;/*1:enabel ;0:disable*/ + wb_en = <1>;/*1:enabel ;0:disable*/ + cm_en = <0>;/*1:enabel ;0:disable*/ + wb_sel = <1>;/*1:mtx ;0:gainoff*/ + vlock_en = <1>;/*1:enable;0:disable*/ + vlock_mode = <0x4>; + /* vlock work mode: + *bit0:auto ENC + *bit1:auto PLL + *bit2:manual PLL + *bit3:manual ENC + *bit4:manual soft ENC + *bit5:manual MIX PLL ENC + */ + vlock_pll_m_limit = <1>; + vlock_line_limit = <3>; + }; + + amdolby_vision { + compatible = "amlogic, dolby_vision_tm2"; + dev_name = "aml_amdolby_vision_driver"; + status = "okay"; + tv_mode = <0>;/*1:enabel ;0:disable*/ + }; + + vdin@0 { + compatible = "amlogic, vdin"; + /*memory-region = <&vdin0_cma_reserved>;*/ + status = "okay"; + /*bit0:(1:share with codec_mm;0:cma alone) + *bit8:(1:alloc in discontinus way;0:alone in continuous way) + */ + flag_cma = <0x101>; + /*MByte, if 10bit disable: 64M(YUV422), + *if 10bit enable: 64*1.5 = 96M(YUV422) + *if support 4K2K-YUV444-10bit-WR:3840*2160*4*4 ~= 128M + *if support 4K2K-YUV422-10bit-wr:3840*2160*3*4 ~= 96M + *if support 4K2K-YUV422-8BIT-WR:3840*2160*2*4 ~= 64M + *if support 1080p-YUV422-8BIT-WR:1920*1080*2*4 ~= 16M + */ + cma_size = <160>; + interrupts = <0 83 1>; + rdma-irq = <2>; + clocks = <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_VDIN_MEAS_COMP>; + clock-names = "fclk_div5", "cts_vdin_meas_clk"; + vdin_id = <0>; + /*vdin write mem color depth support: + * bit0:support 8bit + * bit1:support 9bit + * bit2:support 10bit + * bit3:support 12bit + * bit4:support yuv422 10bit full pack mode (from txl new add) + * bit8:use 8bit at 4k_50/60hz_10bit + * bit9:use 10bit at 4k_50/60hz_10bit + */ + tv_bit_mode = <0x215>; + /* afbce_bit_mode: (amlogic frame buff compression encoder) + * bit 0~3: + * 0 -- normal mode, not use afbce + * 1 -- use afbce non-mmu mode + * 2 -- use afbce mmu mode + * bit 4: + * 0 -- afbce compression-lossy disable + * 1 -- afbce compression-lossy enable + */ + afbce_bit_mode = <0x0>; + }; + + vdin@1 { + compatible = "amlogic, vdin"; + memory-region = <&vdin1_cma_reserved>; + status = "okay"; + /*bit0:(1:share with codec_mm;0:cma alone) + *bit8:(1:alloc in discontinus way;0:alone in continuous way) + */ + flag_cma = <0>; + interrupts = <0 85 1>; + rdma-irq = <4>; + clocks = <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_VDIN_MEAS_COMP>; + clock-names = "fclk_div5", "cts_vdin_meas_clk"; + vdin_id = <1>; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + */ + tv_bit_mode = <0x15>; + }; + + tvafe { + compatible = "amlogic, tvafe-tl1"; + /*memory-region = <&tvafe_cma_reserved>;*/ + status = "okay"; + flag_cma = <1>;/*1:share with codec_mm;0:cma alone*/ + cma_size = <5>;/*MByte*/ + reg = <0xff654000 0x2000>;/*tvafe reg base*/ + reserve-iomap = "true"; + tvafe_id = <0>; + //pinctrl-names = "default"; + /*!!particular sequence, no more and no less!!!*/ + tvafe_pin_mux = < + 3 /* TVAFE_CVBS_IN2, CVBS_IN0 = 0 */ + 1 /* TVAFE_CVBS_IN0, CVBS_IN1 */ + 2 /* TVAFE_CVBS_IN1, CVBS_IN2 */ + 4 /* TVAFE_CVBS_IN3, CVBS_IN3 */ + >; + clocks = <&clkc CLKID_DAC_CLK>; + clock-names = "vdac_clk_gate"; + }; + + vbi { + compatible = "amlogic, vbi"; + status = "okay"; + interrupts = <0 83 1>; + }; + + cvbsout { + compatible = "amlogic, cvbsout-tl1"; + status = "disabled"; + clocks = <&clkc CLKID_VCLK2_ENCI + &clkc CLKID_VCLK2_VENCI0 + &clkc CLKID_VCLK2_VENCI1 + &clkc CLKID_DAC_CLK>; + clock-names = "venci_top_gate", + "venci_0_gate", + "venci_1_gate", + "vdac_clk_gate"; + /* clk path */ + /* 0:vid_pll vid2_clk */ + /* 1:gp0_pll vid2_clk */ + /* 2:vid_pll vid1_clk */ + /* 3:gp0_pll vid1_clk */ + clk_path = <0>; + + /* performance: reg_address, reg_value */ + /* tl1 */ + performance = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x8080 + 0x1b05 0xfd + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + performance_sarft = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x0 + 0x1b05 0x9 + 0x1c59 0xfc48 + 0xffff 0x0>; /* ending flag */ + performance_revB_telecom = <0x1bf0 0x9 + 0x1b56 0x546 + 0x1b12 0x8080 + 0x1b05 0x9 + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + }; + + /* for external keypad */ + adc_keypad { + compatible = "amlogic, adc_keypad"; + status = "okay"; + key_name = "power","up","down","enter","left","right","home"; + key_num = <7>; + io-channels = <&saradc SARADC_CH2>,<&saradc SARADC_CH3>; + io-channel-names = "key-chan-2", "key-chan-3"; + key_chan = ; + key_code = <116 103 108 28 105 106 102>; + key_val = <0 143 266 389 512 143 266>; //val=voltage/1800mV*1023 + key_tolerance = <40 40 40 40 40 40 40>; +}; + + unifykey { + compatible = "amlogic, unifykey"; + status = "okay"; + + unifykey-num = <21>; + unifykey-index-0 = <&keysn_0>; + unifykey-index-1 = <&keysn_1>; + unifykey-index-2 = <&keysn_2>; + unifykey-index-3 = <&keysn_3>; + unifykey-index-4 = <&keysn_4>; + unifykey-index-5 = <&keysn_5>; + unifykey-index-6 = <&keysn_6>; + unifykey-index-7 = <&keysn_7>; + unifykey-index-8 = <&keysn_8>; + unifykey-index-9 = <&keysn_9>; + unifykey-index-10= <&keysn_10>; + unifykey-index-11 = <&keysn_11>; + unifykey-index-12 = <&keysn_12>; + unifykey-index-13 = <&keysn_13>; + unifykey-index-14 = <&keysn_14>; + unifykey-index-15 = <&keysn_15>; + unifykey-index-16 = <&keysn_16>; + unifykey-index-17 = <&keysn_17>; + unifykey-index-18 = <&keysn_18>; + unifykey-index-19 = <&keysn_19>; + unifykey-index-20 = <&keysn_20>; + + keysn_0: key_0{ + key-name = "usid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_1:key_1{ + key-name = "mac"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_2:key_2{ + key-name = "hdcp"; + key-device = "secure"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_3:key_3{ + key-name = "secure_boot_set"; + key-device = "efuse"; + key-permit = "write"; + }; + keysn_4:key_4{ + key-name = "mac_bt"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_5:key_5{ + key-name = "mac_wifi"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_6:key_6{ + key-name = "hdcp2_tx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_7:key_7{ + key-name = "hdcp2_rx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_8:key_8{ + key-name = "widevinekeybox"; + key-device = "secure"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_9:key_9{ + key-name = "deviceid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_10:key_10{ + key-name = "hdcp22_fw_private"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_11:key_11{ + key-name = "hdcp22_rx_private"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_12:key_12{ + key-name = "hdcp22_rx_fw"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_13:key_13{ + key-name = "hdcp14_rx"; + key-device = "normal"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_14:key_14{ + key-name = "prpubkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_15:key_15{ + key-name = "prprivkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_16:key_16{ + key-name = "lcd"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_17:key_17{ + key-name = "lcd_extern"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_18:key_18{ + key-name = "backlight"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_19:key_19{ + key-name = "lcd_tcon"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_20:key_20{ + key-name = "attestationkeybox";// attestation key + key-device = "secure"; + key-permit = "read","write","del"; + }; + }; /* End unifykey */ + + amlvideo2_0 { + compatible = "amlogic, amlvideo2"; + dev_name = "amlvideo2"; + status = "okay"; + amlvideo2_id = <0>; + cma_mode = <1>; + }; + + amlvideo2_1 { + compatible = "amlogic, amlvideo2"; + dev_name = "amlvideo2"; + status = "okay"; + amlvideo2_id = <1>; + cma_mode = <1>; + }; + + hdmirx { + compatible = "amlogic, hdmirx_tl1"; + #address-cells=<1>; + #size-cells=<1>; + memory-region = <&hdmirx_emp_cma_reserved>; + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&hdmirx_a_mux &hdmirx_b_mux + &hdmirx_c_mux>; + repeat = <0>; + interrupts = <0 41 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clkc CLKID_HDMIRX_MODET_COMP>, + <&clkc CLKID_HDMIRX_CFG_COMP>, + <&clkc CLKID_HDMIRX_ACR_COMP>, + <&clkc CLKID_HDMIRX_METER_COMP>, + <&clkc CLKID_HDMIRX_AXI_COMP>, + <&xtal>, + <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_FCLK_DIV7>, + <&clkc CLKID_HDCP22_SKP_COMP>, + <&clkc CLKID_HDCP22_ESM_COMP>; + // <&clkc CLK_AUD_PLL2FS>, + // <&clkc CLK_AUD_PLL4FS>, + // <&clkc CLK_AUD_OUT>; + clock-names = "hdmirx_modet_clk", + "hdmirx_cfg_clk", + "hdmirx_acr_ref_clk", + "cts_hdmirx_meter_clk", + "cts_hdmi_axi_clk", + "xtal", + "fclk_div5", + "fclk_div7", + "hdcp_rx22_skp", + "hdcp_rx22_esm"; + // "hdmirx_aud_pll2fs", + // "hdmirx_aud_pll4f", + // "clk_aud_out"; + hdmirx_id = <0>; + en_4k_2_2k = <0>; + hpd_low_cec_off = <1>; + /* bit4: enable feature, bit3~0: port number */ + disable_port = <0x0>; + /* MAP_ADDR_MODULE_CBUS */ + /* MAP_ADDR_MODULE_HIU */ + /* MAP_ADDR_MODULE_HDMIRX_CAPB3 */ + /* MAP_ADDR_MODULE_SEC_AHB */ + /* MAP_ADDR_MODULE_SEC_AHB2 */ + /* MAP_ADDR_MODULE_APB4 */ + /* MAP_ADDR_MODULE_TOP */ + reg = < 0x0 0x0 + 0xff63C000 0x2000 + 0xffe0d000 0x2000 + 0x0 0x0 + 0x0 0x0 + 0x0 0x0 + 0xff610000 0xa000>; + }; + + aocec: aocec { + compatible = "amlogic, aocec-tm2"; + /*device_name = "aocec";*/ + status = "okay"; + vendor_name = "Amlogic"; /* Max Chars: 8 */ + /* Refer to the following URL at: + * http://standards.ieee.org/develop/regauth/oui/oui.txt + */ + vendor_id = <0x000000>; + product_desc = "TM2"; /* Max Chars: 16 */ + cec_osd_string = "AML_TV"; /* Max Chars: 14 */ + port_num = <3>; + ee_cec; + /*cec_sel = <2>;*/ + output = <1>; /*output port number*/ + arc_port_mask = <0x2>; + interrupts = <0 205 1 + 0 199 1>; + interrupt-names = "hdmi_aocecb","hdmi_aocec"; + pinctrl-names = "default","hdmitx_aocecb","cec_pin_sleep"; + pinctrl-0=<&aoceca_mux>; + pinctrl-1=<&aocecb_mux>; + pinctrl-2=<&aoceca_mux>; + reg = <0xFF80023c 0x4 + 0xFF800000 0x400>; + reg-names = "ao_exit","ao"; + }; + + p_tsensor: p_tsensor@ff634800 { + compatible = "amlogic, r1p1-tsensor"; + status = "okay"; + reg = <0xff634800 0x50>, + <0xff800268 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 35 0>; + clocks = <&clkc CLKID_TS_CLK_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + d_tsensor: d_tsensor@ff634c00 { + compatible = "amlogic, r1p1-tsensor"; + status = "okay"; + reg = <0xff634c00 0x50>, + <0xff800230 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 36 0>; + clocks = <&clkc CLKID_TS_CLK_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + s_tsensor: s_tsensor@ff635000 { + compatible = "amlogic, r1p1-tsensor"; + status = "okay"; + reg = <0xff635000 0x50>, + <0xff80026c 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 38 0>; + clocks = <&clkc CLKID_TS_CLK_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + meson_cooldev: meson-cooldev@0 { + status = "okay"; + compatible = "amlogic, meson-cooldev"; + cooling_devices { + cpufreq_cool_cluster0 { + min_state = <1000000>; + dyn_coeff = <140>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "cpufreq_cool0"; + device_type = "cpufreq"; + }; + cpucore_cool_cluster0 { + min_state = <1>; + dyn_coeff = <0>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "cpucore_cool0"; + device_type = "cpucore"; + }; + gpufreq_cool { + min_state = <400>; + dyn_coeff = <140>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "gpufreq_cool0"; + device_type = "gpufreq"; + }; + gpucore_cool { + min_state = <1>; + dyn_coeff = <0>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "gpucore_cool0"; + device_type = "gpucore"; + }; + }; + cpufreq_cool0:cpufreq_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + cpucore_cool0:cpucore_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + gpufreq_cool0:gpufreq_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + gpucore_cool0:gpucore_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + };/*meson cooling devices end*/ + + thermal-zones { + pll_thermal: pll_thermal { + polling-delay = <1000>; + polling-delay-passive = <100>; + sustainable-power = <1322>; + thermal-sensors = <&p_tsensor 0>; + trips { + pswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + pcontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + phot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + pcritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + cooling-maps { + cpufreq_cooling_map { + trip = <&pcontrol>; + cooling-device = <&cpufreq_cool0 0 11>; + contribution = <1024>; + }; + cpucore_cooling_map { + trip = <&pcontrol>; + cooling-device = <&cpucore_cool0 0 4>; + contribution = <1024>; + }; + gpufreq_cooling_map { + trip = <&pcontrol>; + cooling-device = <&gpufreq_cool0 0 4>; + contribution = <1024>; + }; + }; + }; + ddr_thermal: ddr_thermal { + polling-delay = <2000>; + polling-delay-passive = <1000>; + sustainable-power = <1322>; + thermal-sensors = <&d_tsensor 1>; + trips { + dswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + dcontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + dhot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + dcritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + }; + sar_thermal: sar_thermal { + polling-delay = <2000>; + polling-delay-passive = <1000>; + sustainable-power = <1322>; + thermal-sensors = <&s_tsensor 2>; + trips { + sswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + scontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + shot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + scritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + }; + }; /*thermal zone end*/ + + cpu_opp_table0: cpu_opp_table0 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <730000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <730000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <730000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <750000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <770000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <780000>; + }; + opp06 { + opp-hz = /bits/ 64 <1404000000>; + opp-microvolt = <790000>; + }; + opp07 { + opp-hz = /bits/ 64 <1500000000>; + opp-microvolt = <800000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <810000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <850000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <900000>; + }; + opp11 { + opp-hz = /bits/ 64 <1908000000>; + opp-microvolt = <950000>; + }; + }; + + cpufreq-meson { + compatible = "amlogic, cpufreq-meson"; + pinctrl-names = "default"; + pinctrl-0 = <&pwm_ao_d_pins3>; + status = "okay"; + }; + + tuner: tuner { + compatible = "amlogic, tuner"; + status = "okay"; + tuner_cur = <0>; /* default use tuner */ + tuner_num = <1>; /* tuner number, multi tuner support */ + tuner_name_0 = "mxl661_tuner"; + tuner_i2c_adap_0 = <&i2c0>; + tuner_i2c_addr_0 = <0x60>; + tuner_xtal_0 = <1>; /* 0: 16MHz, 1: 24MHz */ + tuner_xtal_mode_0 = <3>; + /* NO_SHARE_XTAL(0) + * SLAVE_XTAL_SHARE(3) + */ + tuner_xtal_cap_0 = <25>; /* when tuner_xtal_mode = 3, set 25 */ + }; + + atv-demod { + compatible = "amlogic, atv-demod"; + status = "okay"; + tuner = <&tuner>; + btsc_sap_mode = <1>; + /* pinctrl-names="atvdemod_agc_pins"; */ + /* pinctrl-0=<&atvdemod_agc_pins>; */ + reg = <0xff656000 0x2000 /* demod reg */ + 0xff63c000 0x2000 /* hiu reg */ + 0xff634000 0x2000 /* periphs reg */ + 0xff64a000 0x2000>; /* audio reg */ + reg_23cf = <0x88188832>; + /*default:0x88188832;r840 on haier:0x48188832*/ + }; + + bt-dev{ + compatible = "amlogic, bt-dev"; + status = "okay"; + gpio_reset = <&gpio GPIOC_13 GPIO_ACTIVE_HIGH>; + }; + + wifi{ + compatible = "amlogic, aml_wifi"; + status = "okay"; + interrupt_pin = <&gpio GPIOC_12 GPIO_ACTIVE_HIGH>; + irq_trigger_type = "GPIO_IRQ_LOW"; + dhd_static_buf; //dhd_static_buf support + power_on_pin = <&gpio GPIOC_11 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&pwm_b_pins1>; + pwm_config = <&wifi_pwm_conf>; + }; + + wifi_pwm_conf:wifi_pwm_conf{ + pwm_channel1_conf { + pwms = <&pwm_ab MESON_PWM_1 30541 0>; + duty-cycle = <15270>; + times = <8>; + }; + pwm_channel2_conf { + pwms = <&pwm_ab MESON_PWM_3 30500 0>; + duty-cycle = <15250>; + times = <12>; + }; + }; + + sd_emmc_b: sdio@ffe05000 { + status = "okay"; + compatible = "amlogic, meson-mmc-tm2"; + reg = <0xffe05000 0x800>; + interrupts = <0 190 4>; + + pinctrl-names = "sdio_all_pins", + "sdio_clk_cmd_pins"; + pinctrl-0 = <&sdio_all_pins>; + pinctrl-1 = <&sdio_clk_cmd_pins>; + + clocks = <&clkc CLKID_SD_EMMC_B>, + <&clkc CLKID_SD_EMMC_B_P0_COMP>, + <&clkc CLKID_FCLK_DIV2>, + <&clkc CLKID_FCLK_DIV5>, + <&xtal>; + clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + + bus-width = <4>; + cap-sd-highspeed; + cap-mmc-highspeed; + max-frequency = <100000000>; + disable-wp; + sdio { + pinname = "sdio"; + ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", /**ptm debug */ + "MMC_CAP_UHS_SDR12", + "MMC_CAP_UHS_SDR25", + "MMC_CAP_UHS_SDR50", + "MMC_CAP_UHS_SDR104", + "MMC_PM_KEEP_POWER", + "MMC_CAP_SDIO_IRQ"; + f_min = <400000>; + f_max = <200000000>; + max_req_size = <0x20000>; /**128KB*/ + card_type = <3>; + /* 3:sdio device(ie:sdio-wifi), + * 4:SD combo (IO+mem) card + */ + }; + }; + +/* sd_emmc_b: sd@ffe05000 { + * status = "okay"; + * compatible = "amlogic, meson-mmc-tm2"; + * reg = <0xffe05000 0x800>; + * interrupts = <0 190 1>; + * + * pinctrl-names = "sd_all_pins", + * "sd_clk_cmd_pins", + * "sd_1bit_pins"; + * pinctrl-0 = <&sd_all_pins>; + * pinctrl-1 = <&sd_clk_cmd_pins>; + * pinctrl-2 = <&sd_1bit_pins>; + * + * clocks = <&clkc CLKID_SD_EMMC_B>, + * <&clkc CLKID_SD_EMMC_B_P0_COMP>, + * <&clkc CLKID_FCLK_DIV2>, + * <&clkc CLKID_FCLK_DIV5>, + * <&xtal>; + * clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + * + * bus-width = <4>; + * cap-sd-highspeed; + * cap-mmc-highspeed; + * max-frequency = <100000000>; + * disable-wp; + * sd { + * pinname = "sd"; + * ocr_avail = <0x200080>; + * caps = "MMC_CAP_4_BIT_DATA", + * "MMC_CAP_MMC_HIGHSPEED", + * "MMC_CAP_SD_HIGHSPEED"; + * f_min = <400000>; + * f_max = <200000000>; + * max_req_size = <0x20000>; + * no_sduart = <1>; + * gpio_dat3 = <&gpio GPIOC_3 GPIO_ACTIVE_HIGH>; + * jtag_pin = <&gpio GPIOC_0 GPIO_ACTIVE_HIGH>; + * gpio_cd = <&gpio GPIOC_10 GPIO_ACTIVE_HIGH>; + * card_type = <5>; + * }; + * }; + */ + +}; /* end of / */ + +&i2c0 { + status = "okay"; + clock-frequency = <300000>; + pinctrl-names="default"; + pinctrl-0=<&i2c0_dv_pins>; +}; + +&audiobus { + tdma:tdm@0 { + compatible = "amlogic, tm2-snd-tdma"; + #sound-dai-cells = <0>; + + dai-tdm-lane-slot-mask-in = <1 0>; + dai-tdm-lane-slot-mask-out = <1 1 1 1>; + dai-tdm-clk-sel = <0>; + + clocks = <&clkaudio CLKID_AUDIO_MCLK_A + &clkc CLKID_MPLL0 + &clkc CLKID_MPLL1 + &clkaudio CLKID_AUDIO_SPDIFOUT_A>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; + + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdma_mclk &tdmout_a>; + + /* + * 0: tdmout_a; + * 1: tdmout_b; + * 2: tdmout_c; + * 3: spdifout; + * 4: spdifout_b; + */ + samesource_sel = <3>; + + /* In for ACODEC_ADC */ + acodec_adc = <1>; + + status = "okay"; + + /* !!!For --TV platform-- ONLY */ + Channel_Mask { + /*i2s has 4 pins, 8channel, mux output*/ + Spdif_samesource_Channel_Mask = "i2s_2/3"; + }; + }; + + tdmb:tdm@1 { + compatible = "amlogic, tm2-snd-tdmb"; + #sound-dai-cells = <0>; + + dai-tdm-lane-slot-mask-in = <1 0 0 0>; + dai-tdm-lane-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <1>; + + clocks = <&clkaudio CLKID_AUDIO_MCLK_B + &clkc CLKID_MPLL1>; + clock-names = "mclk", "clk_srcpll"; + + status = "okay"; + }; + + tdmc:tdm@2 { + compatible = "amlogic, tm2-snd-tdmc"; + #sound-dai-cells = <0>; + + dai-tdm-lane-slot-mask-in = <1 0 0 0>; + dai-tdm-lane-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <2>; + + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmout_c &tdmin_c>; + + status = "okay"; + }; + + pdm:pdm { + compatible = "amlogic, tm2-snd-pdm"; + #sound-dai-cells = <0>; + clocks = <&clkaudio CLKID_AUDIO_GATE_PDM + &clkc CLKID_FCLK_DIV3 + &clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_PDMIN0 + &clkaudio CLKID_AUDIO_PDMIN1>; + clock-names = "gate", + "sysclk_srcpll", + "dclk_srcpll", + "pdm_dclk", + "pdm_sysclk"; + pinctrl-names = "pdm_pins"; + pinctrl-0 = <&pdmin>; + /* mode 0~4, defalut:1 */ + filter_mode = <1>; + status = "okay"; + }; + spdifa:spdif@0 { + compatible = "amlogic, tm2-snd-spdif-a"; + #sound-dai-cells = <0>; + + clocks = <&clkc CLKID_MPLL1 + &clkc CLKID_FCLK_DIV4 + &clkaudio CLKID_AUDIO_GATE_SPDIFIN + &clkaudio CLKID_AUDIO_GATE_SPDIFOUT_A + &clkaudio CLKID_AUDIO_SPDIFIN + &clkaudio CLKID_AUDIO_SPDIFOUT_A>; + clock-names = "sysclk", "fixed_clk", "gate_spdifin", + "gate_spdifout", "clk_spdifin", "clk_spdifout"; + + interrupts = + ; + interrupt-names = "irq_spdifin"; + + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; + pinctrl-0 = <&spdifin_a>; + //pinctrl-1 = <&spdifout_a_mute>; + + /* + * whether do asrc for pcm and resample a or b + * if raw data, asrc is disabled automatically + * 0: "Disable", + * 1: "Enable:32K", + * 2: "Enable:44K", + * 3: "Enable:48K", + * 4: "Enable:88K", + * 5: "Enable:96K", + * 6: "Enable:176K", + * 7: "Enable:192K", + */ + asrc_id = <0>; + auto_asrc = <3>; + + status = "okay"; + }; + + spdifb:spdif@1 { + compatible = "amlogic, tm2-snd-spdif-b"; + #sound-dai-cells = <0>; + + clocks = <&clkc CLKID_MPLL0 /*CLKID_HIFI_PLL*/ + &clkaudio CLKID_AUDIO_GATE_SPDIFOUT_B + &clkaudio CLKID_AUDIO_SPDIFOUT_B>; + clock-names = "sysclk", + "gate_spdifout", "clk_spdifout"; + + status = "okay"; + }; + + extn:extn { + compatible = "amlogic, snd-extn"; + #sound-dai-cells = <0>; + + + interrupts = + ; + interrupt-names = "irq_frhdmirx"; + + status = "okay"; + }; + + earc:earc { + compatible = "amlogic, tm2-snd-earc"; + #sound-dai-cells = <0>; + + clocks = < &clkaudio CLKID_EARCRX_CMDC + &clkaudio CLKID_EARCRX_DMAC + &clkc CLKID_FCLK_DIV5 + &clkc CLKID_FCLK_DIV3 + &clkaudio CLKID_EARCTX_CMDC + &clkaudio CLKID_EARCTX_DMAC + &clkc CLKID_FCLK_DIV5 + &clkc CLKID_FCLK_DIV3 + >; + clock-names = + "rx_cmdc", + "rx_dmac", + "rx_cmdc_srcpll", + "rx_dmac_srcpll", + "tx_cmdc", + "tx_dmac", + "tx_cmdc_srcpll", + "tx_dmac_srcpll"; + interrupts = < + GIC_SPI 88 IRQ_TYPE_EDGE_RISING + GIC_SPI 87 IRQ_TYPE_EDGE_RISING + >; + interrupt-names = "rx_cmdc", "rx_dmac"; + + status = "okay"; + }; + + aed:effect { + compatible = "amlogic, snd-effect-v2"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_EQDRC + &clkc CLKID_FCLK_DIV5 + &clkaudio CLKID_AUDIO_EQDRC>; + clock-names = "gate", "srcpll", "eqdrc"; + + /* + * 0:tdmout_a + * 1:tdmout_b + * 2:tdmout_c + * 3:spdifout + * 4:spdifout_b + */ + eqdrc_module = <0>; + /* max 0xf, each bit for one lane, usually one lane */ + lane_mask = <0x1>; + /* max 0xff, each bit for one channel */ + channel_mask = <0xff>; + + status = "disable"; + }; + + asrca: resample@0 { + compatible = "amlogic, tl1-resample-a"; + clocks = <&clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_MCLK_A + &clkaudio CLKID_AUDIO_RESAMPLE_A>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + /*same with toddr_src + * TDMIN_A, 0 + * TDMIN_B, 1 + * TDMIN_C, 2 + * SPDIFIN, 3 + * PDMIN, 4 + * NONE, + * TDMIN_LB, 6 + * LOOPBACK, 7 + */ + resample_module = <3>; + + status = "disabled"; + }; + + asrcb: resample@1 { + compatible = "amlogic, tl1-resample-b"; + + clocks = <&clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_MCLK_F + &clkaudio CLKID_AUDIO_RESAMPLE_B>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + + /*same with toddr_src + * TDMIN_A, 0 + * TDMIN_B, 1 + * TDMIN_C, 2 + * SPDIFIN, 3 + * PDMIN, 4 + * NONE, + * TDMIN_LB, 6 + * LOOPBACK, 7 + */ + resample_module = <3>; + + status = "disabled"; + }; + + vad:vad { + compatible = "amlogic, snd-vad"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_TOVAD + &clkc CLKID_FCLK_DIV5 + &clkaudio CLKID_AUDIO_VAD>; + clock-names = "gate", "pll", "clk"; + + interrupts = ; + interrupt-names = "irq_wakeup", "irq_frame_sync"; + + /* + * Data src sel: + * 0: tdmin_a; + * 1: tdmin_b; + * 2: tdmin_c; + * 3: spdifin; + * 4: pdmin; + * 5: loopback_b; + * 6: tdmin_lb; + * 7: loopback_a; + */ + src = <4>; + + /* + * deal with hot word in user space or kernel space + * 0: in user space + * 1: in kernel space + */ + level = <1>; + + status = "disabled"; + }; +}; /* end of audiobus */ + +&pinctrl_periphs { + /* audio pin mux */ + + tdma_mclk: tdma_mclk { + mux { /* GPIOH_4 */ + groups = "mclk0_h"; + function = "mclk0"; + }; + }; + + tdmout_a: tdmout_a { + mux { /* GPIOH_5, GPIOH_6, GPIOH_7, GPIOH_8*/ + groups = "tdma_fs_h", + "tdma_sclk_h", + "tdma_dout0_h", + "tdma_dout1_h"; + function = "tdma_out"; + bias-pull-down; + }; + }; + + tdmin_a: tdmin_a { + mux { /* GPIOH_11, GPIOH_12 */ + groups = "tdma_din0_h", + "tdma_din1_h"; + function = "tdma_in"; + }; + }; + + tdmout_c: tdmout_c { + mux { /* GPIODV_7, GPIODV_8, GPIODV_9 */ + groups = "tdmc_sclk", + "tdmc_fs", + "tdmc_dout0"; + function = "tdmc_out"; + }; + }; + + tdmin_c: tdmin_c { + mux { /* GPIODV_10 */ + groups = "tdmc_din1"; + function = "tdmc_in"; + }; + }; + + spdifin_a: spdifin_a { + mux { /* GPIODV_5 */ + groups = "spdif_in"; + function = "spdif_in"; + }; + }; + + spdifout_a: spdifout_a { + mux { /* GPIODV_4 */ + groups = "spdif_out_dv4"; + function = "spdif_out"; + }; + }; + + spdifout_a_mute: spdifout_a_mute { + mux { /* GPIODV_4 */ + groups = "GPIODV_4"; + function = "gpio_periphs"; + }; + }; + + pdmin: pdmin { + mux { /* GPIOZ_7, GPIOZ_8, pdm_din2_z4 */ + groups = "pdm_dclk_z", + "pdm_din0_z", + "pdm_din2_z4"; + function = "pdm"; + }; + }; + + /*backlight*/ + bl_pwm_vs_on_pins:bl_pwm_vs_on_pin { + mux { + groups = "pwm_vs_z5"; + function = "pwm_vs"; + }; + }; + bl_pwm_off_pins:bl_pwm_off_pin { + mux { + groups = "GPIOZ_5"; + function = "gpio_periphs"; + output-low; + }; + }; + bl_pwm_combo_0_vs_on_pins:bl_pwm_combo_0_vs_on_pin { + mux { + groups = "pwm_vs_z5"; + function = "pwm_vs"; + }; + }; + bl_pwm_combo_1_vs_on_pins:bl_pwm_combo_1_vs_on_pin { + mux { + groups = "pwm_vs_z6"; + function = "pwm_vs"; + }; + }; + bl_pwm_combo_off_pins:bl_pwm_combo_off_pin { + mux { + groups = "GPIOZ_5", + "GPIOZ_6"; + function = "gpio_periphs"; + output-low; + }; + }; + +}; /* end of pinctrl_periphs */ + +&audio_data{ + status = "okay"; +}; + +&i2c2 { + status = "disabled"; + pinctrl-names="default"; + pinctrl-0=<&i2c2_z_pins>; + clock-frequency = <400000>; + + tas5805: tas5805@36 { + compatible = "ti,tas5805"; + #sound-dai-cells = <0>; + codec_name = "tas5805"; + reg = <0x2d>; + status = "disable"; + }; +}; + +&i2c3 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&i2c3_h1_pins>; + clock-frequency = <400000>; + + ad82584f: ad82584f@60 { + compatible = "ESMT, ad82584f"; + #sound-dai-cells = <0>; + reg = <0x30>; + status = "okay"; + reset_pin = <&gpio GPIOH_13 0>; + no_mclk; + }; + ad82584f1: ad82584f@62 { + compatible = "ESMT, ad82584f"; + #sound-dai-cells = <0>; + reg = <0x31>; + status = "okay"; + no_mclk; + }; +}; + +&sd_emmc_c { + status = "okay"; + emmc { + caps = "MMC_CAP_8_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + "MMC_CAP_1_8V_DDR", + "MMC_CAP_HW_RESET", + "MMC_CAP_ERASE", + "MMC_CAP_CMD23"; + caps2 = "MMC_CAP2_HS200"; + /* "MMC_CAP2_HS400";*/ + f_min = <400000>; + f_max = <200000000>; + }; +}; + + + +&spifc { + status = "disabled"; + spi-nor@0 { + cs_gpios = <&gpio BOOT_13 GPIO_ACTIVE_HIGH>; + }; +}; + +&slc_nand { + status = "disabled"; + plat-names = "bootloader", "nandnormal"; + plat-num = <2>; + plat-part-0 = <&bootloader>; + plat-part-1 = <&nandnormal>; + bootloader: bootloader{ + enable_pad = "ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <1>; + part_num = <0>; + rb_detect = <1>; + }; + nandnormal: nandnormal{ + enable_pad = "ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + plane_mode = "twoplane"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <2>; + part_num = <3>; + partition = <&nand_partitions>; + rb_detect = <1>; + }; + nand_partitions:nand_partition{ + /* + * if bl_mode is 1, tpl size was generate by + * fip_copies * fip_size which + * will not skip bad when calculating + * the partition size; + * + * if bl_mode is 0, + * tpl partition must be comment out. + */ + tpl{ + offset=<0x0 0x0>; + size=<0x0 0x0>; + }; + logo{ + offset=<0x0 0x0>; + size=<0x0 0x200000>; + }; + recovery{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + boot{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + system{ + offset=<0x0 0x0>; + size=<0x0 0x4000000>; + }; + data{ + offset=<0xffffffff 0xffffffff>; + size=<0x0 0x0>; + }; + }; +}; + +ðmac { + status = "okay"; + //pinctrl-names = "internal_eth_pins"; + //pinctrl-0 = <&internal_eth_pins>; + mc_val = <0x4be04>; + + internal_phy=<1>; +}; + +&uart_A { + status = "okay"; +}; + +&dwc3 { + status = "okay"; +}; + +&usb2_phy_v2 { + status = "okay"; + portnum = <3>; +}; + +&usb3_phy_v2 { + status = "okay"; + portnum = <2>; + portconfig-30 = <1>; + portconfig-31 = <1>; +}; + +&usb_otg { + status = "okay"; + otg = <0>; +}; + +&dwc2_a { + status = "okay"; + /** 0: normal, 1: otg+dwc3 host only, 2: otg+dwc3 device only*/ + controller-type = <1>; +}; + +&pcie_A { + reset-gpio = <&gpio_ao GPIOAO_4 GPIO_ACTIVE_HIGH>; + status = "disable"; +}; + +&pcie_B { + /* ab311 only pcie a, no pcie b */ + status = "disable"; +}; + +&spicc0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&spicc0_pins_h>; + cs-gpios = <&gpio GPIOH_20 0>; +}; + +&meson_fb { + status = "okay"; + display_size_default = <1920 1080 1920 2160 32>; + mem_size = <0x00800000 0x1980000 0x100000 0x100000 0x800000>; + logo_addr = "0x7f800000"; + mem_alloc = <0>; + pxp_mode = <0>; /** 0:normal mode 1:pxp mode */ +}; + +&pwm_AO_cd { + status = "okay"; +}; + +&saradc { + status = "okay"; +}; + +&i2c1 { + status = "okay"; + clock-frequency = <300000>; + pinctrl-names="default"; + pinctrl-0=<&i2c1_h_pins>; + + lcd_extern_i2c0: lcd_extern_i2c@0 { + compatible = "lcd_ext, i2c"; + dev_name = "i2c_T5800Q"; + reg = <0x1c>; + status = "okay"; + }; + + lcd_extern_i2c1: lcd_extern_i2c@1 { + compatible = "lcd_ext, i2c"; + dev_name = "i2c_ANX6862"; + reg = <0x20>; + status = "okay"; + }; + + lcd_extern_i2c2: lcd_extern_i2c@2 { + compatible = "lcd_ext, i2c"; + dev_name = "i2c_ANX7911"; + reg = <0x74>; + status = "okay"; + }; +}; + +&pwm_ab { + status = "okay"; +}; + +&pwm_cd { + status = "okay"; +}; + +&efuse { + status = "okay"; +}; diff --git a/arch/arm/boot/dts/amlogic/tm2_t962e2_ab319.dts b/arch/arm/boot/dts/amlogic/tm2_t962e2_ab319.dts new file mode 100644 index 000000000000..05e180596693 --- /dev/null +++ b/arch/arm/boot/dts/amlogic/tm2_t962e2_ab319.dts @@ -0,0 +1,1852 @@ +/* + * arch/arm/boot/dts/amlogic/tm2_t962e2_ab319.dts + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +/dts-v1/; + +#include "mesontm2.dtsi" +#include "partition_mbox_normal.dtsi" + +/ { + model = "Amlogic TM2 T962E2 AB319"; + amlogic-dt-id = "tm2_t962e2_ab319"; + compatible = "amlogic, tm2_t962e2_ab319"; + + aliases { + serial0 = &uart_AO; + serial1 = &uart_A; + serial2 = &uart_B; + serial3 = &uart_C; + serial4 = &uart_AO_B; + tsensor0 = &p_tsensor; + tsensor1 = &d_tsensor; + tsensor2 = &s_tsensor; + i2c0 = &i2c0; + i2c1 = &i2c1; + i2c2 = &i2c2; + i2c3 = &i2c3; + i2c4 = &i2c_AO; + }; + + memory@00000000 { + device_type = "memory"; + linux,usable-memory = <0x0 0x80000000>; + }; + + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + /* global autoconfigured region for contiguous allocations */ + ramoops@0x07400000 { + compatible = "ramoops"; + reg = <0x07400000 0x00100000>; + record-size = <0x8000>; + console-size = <0x8000>; + ftrace-size = <0x20000>; + }; + + secmon_reserved: linux,secmon { + compatible = "shared-dma-pool"; + reusable; + size = <0x400000>; + alignment = <0x400000>; + alloc-ranges = <0x05000000 0x400000>; + }; + + logo_reserved:linux,meson-fb { + compatible = "shared-dma-pool"; + reusable; + size = <0x800000>; + alignment = <0x400000>; + alloc-ranges = <0x7f800000 0x800000>; + }; + + lcd_tcon_reserved:linux,lcd_tcon { + compatible = "shared-dma-pool"; + reusable; + size = <0xc00000>; + alignment = <0x400000>; + alloc-ranges = <0x7ec00000 0xc00000>; + }; + + codec_mm_cma:linux,codec_mm_cma { + compatible = "shared-dma-pool"; + reusable; + /* ion_codec_mm max can alloc size 80M*/ + size = <0x13400000>; + alignment = <0x400000>; + linux,contiguous-region; + }; + + /* codec shared reserved */ + codec_mm_reserved:linux,codec_mm_reserved { + compatible = "amlogic, codec-mm-reserved"; + size = <0x0>; + alignment = <0x100000>; + //no-map; + }; + + ion_cma_reserved:linux,ion-dev { + compatible = "shared-dma-pool"; + reusable; + size = <0x8000000>; + alignment = <0x400000>; + }; + + /* vdin0 CMA pool */ + //vdin0_cma_reserved:linux,vdin0_cma { + // compatible = "shared-dma-pool"; + // reusable; + /* 3840x2160x4x4 ~=128 M */ + // size = <0xc400000>; + // alignment = <0x400000>; + //}; + + /* vdin1 CMA pool */ + vdin1_cma_reserved:linux,vdin1_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16 M */ + size = <0x1400000>; + alignment = <0x400000>; + }; + + /*demod_reserved:linux,demod { + * compatible = "amlogic, demod-mem"; + * size = <0x800000>; //8M //100m 0x6400000 + * alloc-ranges = <0x0 0x30000000>; + * //multi-use; + * //no-map; + *}; + */ + + demod_cma_reserved:linux,demod_cma { + compatible = "shared-dma-pool"; + reusable; + /* 8M */ + size = <0x0800000>; + alignment = <0x400000>; + }; + + /*di CMA pool */ + di_cma_reserved:linux,di_cma { + compatible = "shared-dma-pool"; + reusable; + /* buffer_size = 3621952(yuv422 8bit) + * | 4736064(yuv422 10bit) + * | 4074560(yuv422 10bit full pack mode) + * 10x3621952=34.6M(0x23) support 8bit + * 10x4736064=45.2M(0x2e) support 12bit + * 10x4074560=40M(0x28) support 10bit + */ + size = <0x02800000>; + alignment = <0x400000>; + }; + + /* for hdmi rx emp use */ + hdmirx_emp_cma_reserved:linux,emp_cma { + compatible = "shared-dma-pool"; + /*linux,phandle = <5>;*/ + reusable; + /* 4M for emp to ddr */ + /* 32M for tmds to ddr */ + size = <0x400000>; + alignment = <0x400000>; + /* alloc-ranges = <0x400000 0x2000000>; */ + }; + + /* POST PROCESS MANAGER */ + ppmgr_reserved:linux,ppmgr { + compatible = "amlogic, ppmgr_memory"; + size = <0x0>; + }; + + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + }; /* end of reserved-memory */ + galcore { + status = "okay"; + }; + codec_mm { + compatible = "amlogic, codec, mm"; + status = "okay"; + memory-region = <&codec_mm_cma &codec_mm_reserved>; + }; + + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + + ppmgr { + compatible = "amlogic, ppmgr"; + memory-region = <&ppmgr_reserved>; + status = "okay"; + }; + + deinterlace { + compatible = "amlogic, deinterlace"; + status = "okay"; + /* 0:use reserved; 1:use cma; 2:use cma as reserved */ + flag_cma = <1>; + //memory-region = <&di_reserved>; + memory-region = <&di_cma_reserved>; + interrupts = <0 46 1 + 0 40 1>; + interrupt-names = "pre_irq", "post_irq"; + clocks = <&clkc CLKID_VPU_CLKB_TMP_COMP>, + <&clkc CLKID_VPU_CLKB_COMP>; + clock-names = "vpu_clkb_tmp_composite", + "vpu_clkb_composite"; + clock-range = <334 667>; + /* buffer-size = <3621952>;(yuv422 8bit) */ + buffer-size = <4074560>;/*yuv422 fullpack*/ + /* reserve-iomap = "true"; */ + /* if enable nr10bit, set nr10bit-support to 1 */ + post-wr-support = <1>; + nr10bit-support = <1>; + nrds-enable = <1>; + pps-enable = <1>; + }; + + vout { + compatible = "amlogic, vout"; + status = "okay"; + fr_auto_policy = <0>; + }; + + /* Audio Related start */ + pdm_codec:dummy { + #sound-dai-cells = <0>; + compatible = "amlogic, pdm_dummy_codec"; + status = "okay"; + }; + + dummy_codec:dummy { + #sound-dai-cells = <0>; + compatible = "amlogic, aml_dummy_codec"; + status = "okay"; + }; + + tl1_codec:codec { + #sound-dai-cells = <0>; + compatible = "amlogic, tl1_acodec"; + status = "okay"; + reg = <0xff632000 0x1c>; + tdmout_index = <0>; + tdmin_index = <0>; + dat1_ch_sel = <1>; + }; + + aml_dtv_demod { + compatible = "amlogic, ddemod-tl1"; + dev_name = "aml_dtv_demod"; + status = "okay"; + + //pinctrl-names="dtvdemod_agc"; + //pinctrl-0=<&dtvdemod_agc>; + + clocks = <&clkc CLKID_DAC_CLK>; + clock-names = "vdac_clk_gate"; + + reg = <0xff650000 0x4000 /*dtv demod base*/ + 0xff63c000 0x2000 /*hiu reg base*/ + 0xff800000 0x1000 /*io_aobus_base*/ + 0xffd01000 0x1000 /*reset*/ + >; + + /*move from dvbfe*/ + dtv_demod0_mem = <0>; // need move to aml_dtv_demod ? + spectrum = <1>; + cma_flag = <1>; + cma_mem_size = <8>; + memory-region = <&demod_cma_reserved>;//<&demod_reserved>; + }; + + auge_sound { + compatible = "amlogic, tm2-sound-card"; + aml-audio-card,name = "AML-AUGESOUND"; + + avout_mute-gpios = <&gpio GPIODV_3 GPIO_ACTIVE_HIGH>; + + aml-audio-card,dai-link@0 { + format = "i2s"; + mclk-fs = <256>; + continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdma>; + frame-master = <&tdma>; + /* slave mode */ + /* + * bitclock-master = <&tdmacodec>; + * frame-master = <&tdmacodec>; + */ + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-i2s"; + tdmacpu: cpu { + sound-dai = <&tdma>; + dai-tdm-slot-tx-mask = + <1 1>; + dai-tdm-slot-rx-mask = + <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmacodec: codec { + //sound-dai = <&dummy_codec>; + sound-dai = ; + }; + }; + + aml-audio-card,dai-link@1 { + + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdmb>; + frame-master = <&tdmb>; + /* slave mode */ + //bitclock-master = <&tdmbcodec>; + //frame-master = <&tdmbcodec>; + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-pcm"; + cpu { + sound-dai = <&tdmb>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + /* + * dai-tdm-slot-tx-mask = + * <1 1 1 1 1 1 1 1>; + * dai-tdm-slot-rx-mask = + * <1 1 1 1 1 1 1 1>; + * dai-tdm-slot-num = <8>; + */ + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmbcodec: codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@2 { + + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdmc>; + frame-master = <&tdmc>; + /* slave mode */ + //bitclock-master = <&tdmccodec>; + //frame-master = <&tdmccodec>; + /* suffix-name, sync with android audio hal used for */ + //suffix-name = "alsaPORT-tdm"; + cpu { + sound-dai = <&tdmc>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmccodec: codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@3 { + mclk-fs = <64>; + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-pdm"; + cpu { + sound-dai = <&pdm>; + }; + codec { + sound-dai = <&pdm_codec>; + }; + }; + + aml-audio-card,dai-link@4 { + mclk-fs = <128>; + continuous-clock; + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-spdif"; + cpu { + sound-dai = <&spdifa>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@5 { + mclk-fs = <128>; + suffix-name = "alsaPORT-spdifb"; + cpu { + sound-dai = <&spdifb>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@6 { + mclk-fs = <256>; + suffix-name = "alsaPORT-tv"; + cpu { + sound-dai = <&extn>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + aml-audio-card,dai-link@7 { + mclk-fs = <256>; + suffix-name = "alsaPORT-earc"; + cpu { + sound-dai = <&earc>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + }; + + /* Audio Related end */ + dvb { + compatible = "amlogic, dvb"; + status = "okay"; + fe0_mode = "internal"; + fe0_tuner = <&tuner>; + + /*"parallel","serial","disable"*/ + ts2 = "parallel"; + ts2_control = <0>; + ts2_invert = <0>; + interrupts = <0 23 1 + 0 5 1 + 0 53 1 + 0 19 1 + 0 25 1 + 0 17 1>; + interrupt-names = "demux0_irq", + "demux1_irq", + "demux2_irq", + "dvr0_irq", + "dvr1_irq", + "dvr2_irq"; + clocks = <&clkc CLKID_DEMUX + &clkc CLKID_ASYNC_FIFO + &clkc CLKID_AHB_ARB0 + /*&clkc CLKID_DOS_PARSER>;*/ + &clkc CLKID_U_PARSER>; + clock-names = "demux", "asyncfifo", "ahbarb0", "uparsertop"; + }; + + tvafe_avin_detect { + compatible = "amlogic, tl1_tvafe_avin_detect"; + status = "okay"; + device_mask = <1>;/*bit0:ch1;bit1:ch2*/ + interrupts = <0 12 1>, + <0 13 1>; + }; + + amlvecm { + compatible = "amlogic, vecm-tl1"; + dev_name = "aml_vecm"; + status = "okay"; + gamma_en = <1>;/*1:enabel ;0:disable*/ + wb_en = <1>;/*1:enabel ;0:disable*/ + cm_en = <0>;/*1:enabel ;0:disable*/ + wb_sel = <1>;/*1:mtx ;0:gainoff*/ + vlock_en = <1>;/*1:enable;0:disable*/ + vlock_mode = <0x4>; + /* vlock work mode: + *bit0:auto ENC + *bit1:auto PLL + *bit2:manual PLL + *bit3:manual ENC + *bit4:manual soft ENC + *bit5:manual MIX PLL ENC + */ + vlock_pll_m_limit = <1>; + vlock_line_limit = <3>; + }; + + amdolby_vision { + compatible = "amlogic, dolby_vision_tm2"; + dev_name = "aml_amdolby_vision_driver"; + status = "okay"; + tv_mode = <0>;/*1:enabel ;0:disable*/ + }; + + vdin@0 { + compatible = "amlogic, vdin"; + /*memory-region = <&vdin0_cma_reserved>;*/ + status = "okay"; + /*bit0:(1:share with codec_mm;0:cma alone) + *bit8:(1:alloc in discontinus way;0:alone in continuous way) + */ + flag_cma = <0x101>; + /*MByte, if 10bit disable: 64M(YUV422), + *if 10bit enable: 64*1.5 = 96M(YUV422) + *if support 4K2K-YUV444-10bit-WR:3840*2160*4*4 ~= 128M + *if support 4K2K-YUV422-10bit-wr:3840*2160*3*4 ~= 96M + *if support 4K2K-YUV422-8BIT-WR:3840*2160*2*4 ~= 64M + *if support 1080p-YUV422-8BIT-WR:1920*1080*2*4 ~= 16M + */ + cma_size = <190>; + interrupts = <0 83 1>; + rdma-irq = <2>; + clocks = <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_VDIN_MEAS_COMP>; + clock-names = "fclk_div5", "cts_vdin_meas_clk"; + vdin_id = <0>; + /*vdin write mem color depth support: + * bit0:support 8bit + * bit1:support 9bit + * bit2:support 10bit + * bit3:support 12bit + * bit4:support yuv422 10bit full pack mode (from txl new add) + * bit8:use 8bit at 4k_50/60hz_10bit + * bit9:use 10bit at 4k_50/60hz_10bit + */ + tv_bit_mode = <0x215>; + /* afbce_bit_mode: (amlogic frame buff compression encoder) + * bit 0~3: + * 0 -- normal mode, not use afbce + * 1 -- use afbce non-mmu mode + * 2 -- use afbce mmu mode + * bit 4: + * 0 -- afbce compression-lossy disable + * 1 -- afbce compression-lossy enable + */ + afbce_bit_mode = <0>; + }; + + vdin@1 { + compatible = "amlogic, vdin"; + memory-region = <&vdin1_cma_reserved>; + status = "okay"; + /*bit0:(1:share with codec_mm;0:cma alone) + *bit8:(1:alloc in discontinus way;0:alone in continuous way) + */ + flag_cma = <0>; + interrupts = <0 85 1>; + rdma-irq = <4>; + clocks = <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_VDIN_MEAS_COMP>; + clock-names = "fclk_div5", "cts_vdin_meas_clk"; + vdin_id = <1>; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + */ + tv_bit_mode = <0x15>; + }; + + tvafe { + compatible = "amlogic, tvafe-tl1"; + /*memory-region = <&tvafe_cma_reserved>;*/ + status = "okay"; + flag_cma = <1>;/*1:share with codec_mm;0:cma alone*/ + cma_size = <5>;/*MByte*/ + reg = <0xff654000 0x2000>;/*tvafe reg base*/ + reserve-iomap = "true"; + tvafe_id = <0>; + //pinctrl-names = "default"; + /*!!particular sequence, no more and no less!!!*/ + tvafe_pin_mux = < + 3 /* TVAFE_CVBS_IN2, CVBS_IN0 = 0 */ + 1 /* TVAFE_CVBS_IN0, CVBS_IN1 */ + 2 /* TVAFE_CVBS_IN1, CVBS_IN2 */ + 4 /* TVAFE_CVBS_IN3, CVBS_IN3 */ + >; + clocks = <&clkc CLKID_DAC_CLK>; + clock-names = "vdac_clk_gate"; + }; + + vbi { + compatible = "amlogic, vbi"; + status = "okay"; + interrupts = <0 83 1>; + }; + + cvbsout { + compatible = "amlogic, cvbsout-tl1"; + status = "disabled"; + clocks = <&clkc CLKID_VCLK2_ENCI + &clkc CLKID_VCLK2_VENCI0 + &clkc CLKID_VCLK2_VENCI1 + &clkc CLKID_DAC_CLK>; + clock-names = "venci_top_gate", + "venci_0_gate", + "venci_1_gate", + "vdac_clk_gate"; + /* clk path */ + /* 0:vid_pll vid2_clk */ + /* 1:gp0_pll vid2_clk */ + /* 2:vid_pll vid1_clk */ + /* 3:gp0_pll vid1_clk */ + clk_path = <0>; + + /* performance: reg_address, reg_value */ + /* tl1 */ + performance = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x8080 + 0x1b05 0xfd + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + performance_sarft = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x0 + 0x1b05 0x9 + 0x1c59 0xfc48 + 0xffff 0x0>; /* ending flag */ + performance_revB_telecom = <0x1bf0 0x9 + 0x1b56 0x546 + 0x1b12 0x8080 + 0x1b05 0x9 + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + }; + + adc_keypad { + compatible = "amlogic, adc_keypad"; + status = "okay"; + key_name = "vol-", "vol+", "ch+", "ch-", + "menu", "source", "exit"; + key_num = <7>; + io-channels = <&saradc SARADC_CH2 &saradc SARADC_CH3>; + io-channel-names = "key-chan-2", "key-chan-3"; + key_chan = ; + key_code = <114 115 192 193 139 466 174>; + key_val = <0 143 266 389 0 143 266>; //val=voltage/1800mV*1023 + key_tolerance = <40 40 40 40 40 40 40>; + }; + + unifykey { + compatible = "amlogic, unifykey"; + status = "okay"; + + unifykey-num = <21>; + unifykey-index-0 = <&keysn_0>; + unifykey-index-1 = <&keysn_1>; + unifykey-index-2 = <&keysn_2>; + unifykey-index-3 = <&keysn_3>; + unifykey-index-4 = <&keysn_4>; + unifykey-index-5 = <&keysn_5>; + unifykey-index-6 = <&keysn_6>; + unifykey-index-7 = <&keysn_7>; + unifykey-index-8 = <&keysn_8>; + unifykey-index-9 = <&keysn_9>; + unifykey-index-10= <&keysn_10>; + unifykey-index-11 = <&keysn_11>; + unifykey-index-12 = <&keysn_12>; + unifykey-index-13 = <&keysn_13>; + unifykey-index-14 = <&keysn_14>; + unifykey-index-15 = <&keysn_15>; + unifykey-index-16 = <&keysn_16>; + unifykey-index-17 = <&keysn_17>; + unifykey-index-18 = <&keysn_18>; + unifykey-index-19 = <&keysn_19>; + unifykey-index-20 = <&keysn_20>; + + keysn_0: key_0{ + key-name = "usid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_1:key_1{ + key-name = "mac"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_2:key_2{ + key-name = "hdcp"; + key-device = "secure"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_3:key_3{ + key-name = "secure_boot_set"; + key-device = "efuse"; + key-permit = "write"; + }; + keysn_4:key_4{ + key-name = "mac_bt"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_5:key_5{ + key-name = "mac_wifi"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_6:key_6{ + key-name = "hdcp2_tx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_7:key_7{ + key-name = "hdcp2_rx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_8:key_8{ + key-name = "widevinekeybox"; + key-device = "secure"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_9:key_9{ + key-name = "deviceid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_10:key_10{ + key-name = "hdcp22_fw_private"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_11:key_11{ + key-name = "hdcp22_rx_private"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_12:key_12{ + key-name = "hdcp22_rx_fw"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_13:key_13{ + key-name = "hdcp14_rx"; + key-device = "normal"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_14:key_14{ + key-name = "prpubkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_15:key_15{ + key-name = "prprivkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_16:key_16{ + key-name = "lcd"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_17:key_17{ + key-name = "lcd_extern"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_18:key_18{ + key-name = "backlight"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_19:key_19{ + key-name = "lcd_tcon"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_20:key_20{ + key-name = "attestationkeybox";// attestation key + key-device = "secure"; + key-permit = "read","write","del"; + }; + }; /* End unifykey */ + + hdmirx { + compatible = "amlogic, hdmirx_tl1"; + #address-cells=<1>; + #size-cells=<1>; + memory-region = <&hdmirx_emp_cma_reserved>; + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&hdmirx_a_mux &hdmirx_b_mux + &hdmirx_c_mux>; + repeat = <0>; + interrupts = <0 41 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clkc CLKID_HDMIRX_MODET_COMP>, + <&clkc CLKID_HDMIRX_CFG_COMP>, + <&clkc CLKID_HDMIRX_ACR_COMP>, + <&clkc CLKID_HDMIRX_METER_COMP>, + <&clkc CLKID_HDMIRX_AXI_COMP>, + <&xtal>, + <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_FCLK_DIV7>, + <&clkc CLKID_HDCP22_SKP_COMP>, + <&clkc CLKID_HDCP22_ESM_COMP>; + // <&clkc CLK_AUD_PLL2FS>, + // <&clkc CLK_AUD_PLL4FS>, + // <&clkc CLK_AUD_OUT>; + clock-names = "hdmirx_modet_clk", + "hdmirx_cfg_clk", + "hdmirx_acr_ref_clk", + "cts_hdmirx_meter_clk", + "cts_hdmi_axi_clk", + "xtal", + "fclk_div5", + "fclk_div7", + "hdcp_rx22_skp", + "hdcp_rx22_esm"; + // "hdmirx_aud_pll2fs", + // "hdmirx_aud_pll4f", + // "clk_aud_out"; + hdmirx_id = <0>; + en_4k_2_2k = <0>; + hpd_low_cec_off = <1>; + /* bit4: enable feature, bit3~0: port number */ + disable_port = <0x0>; + /* MAP_ADDR_MODULE_CBUS */ + /* MAP_ADDR_MODULE_HIU */ + /* MAP_ADDR_MODULE_HDMIRX_CAPB3 */ + /* MAP_ADDR_MODULE_SEC_AHB */ + /* MAP_ADDR_MODULE_SEC_AHB2 */ + /* MAP_ADDR_MODULE_APB4 */ + /* MAP_ADDR_MODULE_TOP */ + reg = < 0x0 0x0 + 0xff63C000 0x2000 + 0xffe0d000 0x2000 + 0x0 0x0 + 0x0 0x0 + 0x0 0x0 + 0xff610000 0xa000>; + }; + + aocec: aocec { + compatible = "amlogic, aocec-tm2"; + /*device_name = "aocec";*/ + status = "okay"; + vendor_name = "Amlogic"; /* Max Chars: 8 */ + /* Refer to the following URL at: + * http://standards.ieee.org/develop/regauth/oui/oui.txt + */ + vendor_id = <0x000000>; + product_desc = "TM2"; /* Max Chars: 16 */ + cec_osd_string = "AML_TV"; /* Max Chars: 14 */ + port_num = <3>; + ee_cec; + /*cec_sel = <2>;*/ + output = <1>; /*output port number*/ + arc_port_mask = <0x2>; + interrupts = <0 205 1 + 0 199 1>; + interrupt-names = "hdmi_aocecb","hdmi_aocec"; + pinctrl-names = "default","hdmitx_aocecb","cec_pin_sleep"; + pinctrl-0=<&aoceca_mux>; + pinctrl-1=<&aocecb_mux>; + pinctrl-2=<&aoceca_mux>; + reg = <0xFF80023c 0x4 + 0xFF800000 0x400>; + reg-names = "ao_exit","ao"; + }; + + p_tsensor: p_tsensor@ff634800 { + compatible = "amlogic, r1p1-tsensor"; + status = "okay"; + reg = <0xff634800 0x50>, + <0xff800268 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 35 0>; + clocks = <&clkc CLKID_TS_CLK_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + d_tsensor: d_tsensor@ff634c00 { + compatible = "amlogic, r1p1-tsensor"; + status = "okay"; + reg = <0xff634c00 0x50>, + <0xff800230 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 36 0>; + clocks = <&clkc CLKID_TS_CLK_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + s_tsensor: s_tsensor@ff635000 { + compatible = "amlogic, r1p1-tsensor"; + status = "okay"; + reg = <0xff635000 0x50>, + <0xff80026c 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 38 0>; + clocks = <&clkc CLKID_TS_CLK_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + meson_cooldev: meson-cooldev@0 { + status = "okay"; + compatible = "amlogic, meson-cooldev"; + cooling_devices { + cpufreq_cool_cluster0 { + min_state = <1000000>; + dyn_coeff = <140>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "cpufreq_cool0"; + device_type = "cpufreq"; + }; + cpucore_cool_cluster0 { + min_state = <1>; + dyn_coeff = <0>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "cpucore_cool0"; + device_type = "cpucore"; + }; + gpufreq_cool { + min_state = <400>; + dyn_coeff = <140>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "gpufreq_cool0"; + device_type = "gpufreq"; + }; + gpucore_cool { + min_state = <1>; + dyn_coeff = <0>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "gpucore_cool0"; + device_type = "gpucore"; + }; + }; + cpufreq_cool0:cpufreq_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + cpucore_cool0:cpucore_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + gpufreq_cool0:gpufreq_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + gpucore_cool0:gpucore_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + };/*meson cooling devices end*/ + + thermal-zones { + pll_thermal: pll_thermal { + polling-delay = <1000>; + polling-delay-passive = <100>; + sustainable-power = <1322>; + thermal-sensors = <&p_tsensor 0>; + trips { + pswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + pcontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + phot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + pcritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + cooling-maps { + cpufreq_cooling_map { + trip = <&pcontrol>; + cooling-device = <&cpufreq_cool0 0 11>; + contribution = <1024>; + }; + cpucore_cooling_map { + trip = <&pcontrol>; + cooling-device = <&cpucore_cool0 0 4>; + contribution = <1024>; + }; + gpufreq_cooling_map { + trip = <&pcontrol>; + cooling-device = <&gpufreq_cool0 0 4>; + contribution = <1024>; + }; + }; + }; + ddr_thermal: ddr_thermal { + polling-delay = <2000>; + polling-delay-passive = <1000>; + sustainable-power = <1322>; + thermal-sensors = <&d_tsensor 1>; + trips { + dswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + dcontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + dhot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + dcritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + }; + sar_thermal: sar_thermal { + polling-delay = <2000>; + polling-delay-passive = <1000>; + sustainable-power = <1322>; + thermal-sensors = <&s_tsensor 2>; + trips { + sswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + scontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + shot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + scritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + }; + };/*thermal zone end*/ + + cpu_opp_table0: cpu_opp_table0 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <730000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <730000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <730000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <750000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <770000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <780000>; + }; + opp06 { + opp-hz = /bits/ 64 <1404000000>; + opp-microvolt = <790000>; + }; + opp07 { + opp-hz = /bits/ 64 <1500000000>; + opp-microvolt = <800000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <810000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <850000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <900000>; + }; + opp11 { + opp-hz = /bits/ 64 <1908000000>; + opp-microvolt = <950000>; + }; + }; + + cpufreq-meson { + compatible = "amlogic, cpufreq-meson"; + pinctrl-names = "default"; + pinctrl-0 = <&pwm_ao_d_pins3>; + status = "okay"; + }; + + tuner: tuner { + compatible = "amlogic, tuner"; + status = "okay"; + tuner_cur = <0>; /* default use tuner */ + tuner_num = <1>; /* tuner number, multi tuner support */ + tuner_name_0 = "mxl661_tuner"; + tuner_i2c_adap_0 = <&i2c0>; + tuner_i2c_addr_0 = <0x60>; + tuner_xtal_0 = <0>; /* 0: 16MHz, 1: 24MHz */ + tuner_xtal_mode_0 = <0>; + /* NO_SHARE_XTAL(0) + * SLAVE_XTAL_SHARE(3) + */ + tuner_xtal_cap_0 = <25>; /* when tuner_xtal_mode = 3, set 25 */ + }; + + atv-demod { + compatible = "amlogic, atv-demod"; + status = "okay"; + tuner = <&tuner>; + btsc_sap_mode = <1>; + /* pinctrl-names="atvdemod_agc_pins"; */ + /* pinctrl-0=<&atvdemod_agc_pins>; */ + reg = <0xff656000 0x2000 /* demod reg */ + 0xff63c000 0x2000 /* hiu reg */ + 0xff634000 0x2000 /* periphs reg */ + 0xff64a000 0x2000>; /* audio reg */ + reg_23cf = <0x88188832>; + /*default:0x88188832;r840 on haier:0x48188832*/ + }; + + sd_emmc_b: sd@ffe05000 { + status = "okay"; + compatible = "amlogic, meson-mmc-tm2"; + reg = <0xffe05000 0x800>; + interrupts = <0 190 1>; + + pinctrl-names = "sd_all_pins", + "sd_clk_cmd_pins", + "sd_1bit_pins"; + pinctrl-0 = <&sd_all_pins>; + pinctrl-1 = <&sd_clk_cmd_pins>; + pinctrl-2 = <&sd_1bit_pins>; + + clocks = <&clkc CLKID_SD_EMMC_B>, + <&clkc CLKID_SD_EMMC_B_P0_COMP>, + <&clkc CLKID_FCLK_DIV2>, + <&clkc CLKID_FCLK_DIV5>, + <&xtal>; + clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + + bus-width = <4>; + cap-sd-highspeed; + cap-mmc-highspeed; + max-frequency = <100000000>; + disable-wp; + sd { + pinname = "sd"; + ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED"; + //"MMC_CAP_NONREMOVABLE"; /**ptm debug */ + f_min = <400000>; + f_max = <200000000>; + max_req_size = <0x20000>; /**128KB*/ + no_sduart = <1>; + gpio_dat3 = <&gpio GPIOC_3 GPIO_ACTIVE_HIGH>; + jtag_pin = <&gpio GPIOC_0 GPIO_ACTIVE_HIGH>; + gpio_cd = <&gpio GPIOC_10 GPIO_ACTIVE_HIGH>; + card_type = <5>; + /* 3:sdio device(ie:sdio-wifi), + * 4:SD combo (IO+mem) card + */ + }; + }; + +}; /* end of / */ + +&i2c0 { + status = "okay"; + clock-frequency = <300000>; + pinctrl-names="default"; + pinctrl-0=<&i2c0_dv_pins>; +}; + +&audiobus { + tdma:tdm@0 { + compatible = "amlogic, tm2-snd-tdma"; + #sound-dai-cells = <0>; + + dai-tdm-lane-slot-mask-in = <1 0>; + dai-tdm-lane-slot-mask-out = <1 1 1 1>; + dai-tdm-clk-sel = <0>; + + clocks = <&clkaudio CLKID_AUDIO_MCLK_A + &clkc CLKID_MPLL0 + &clkc CLKID_MPLL1 + &clkaudio CLKID_AUDIO_SPDIFOUT_A>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; + + pinctrl-names = "tdm_pins"; + pinctrl-0 = ; + + /* + * 0: tdmout_a; + * 1: tdmout_b; + * 2: tdmout_c; + * 3: spdifout; + * 4: spdifout_b; + */ + samesource_sel = <3>; + + /* In for ACODEC_ADC */ + acodec_adc = <1>; + + status = "okay"; + + /* !!!For --TV platform-- ONLY */ + Channel_Mask { + /*i2s has 4 pins, 8channel, mux output*/ + Spdif_samesource_Channel_Mask = "i2s_2/3"; + }; + }; + + tdmb:tdm@1 { + compatible = "amlogic, tm2-snd-tdmb"; + #sound-dai-cells = <0>; + + dai-tdm-lane-slot-mask-in = <1 0 0 0>; + dai-tdm-lane-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <1>; + + clocks = <&clkaudio CLKID_AUDIO_MCLK_B + &clkc CLKID_MPLL1>; + clock-names = "mclk", "clk_srcpll"; + + status = "okay"; + }; + + tdmc:tdm@2 { + compatible = "amlogic, tm2-snd-tdmc"; + #sound-dai-cells = <0>; + + dai-tdm-lane-slot-mask-in = <1 0 0 0>; + dai-tdm-lane-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <2>; + + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + + pinctrl-names = "tdm_pins"; + pinctrl-0 = ; + + status = "okay"; + }; + + pdm:pdm { + compatible = "amlogic, tm2-snd-pdm"; + #sound-dai-cells = <0>; + clocks = <&clkaudio CLKID_AUDIO_GATE_PDM + &clkc CLKID_FCLK_DIV3 + &clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_PDMIN0 + &clkaudio CLKID_AUDIO_PDMIN1>; + clock-names = "gate", + "sysclk_srcpll", + "dclk_srcpll", + "pdm_dclk", + "pdm_sysclk"; + pinctrl-names = "pdm_pins"; + pinctrl-0 = <&pdmin>; + /* mode 0~4, defalut:1 */ + filter_mode = <1>; + status = "okay"; + }; + spdifa:spdif@0 { + compatible = "amlogic, tm2-snd-spdif-a"; + #sound-dai-cells = <0>; + + clocks = <&clkc CLKID_MPLL1 + &clkc CLKID_FCLK_DIV4 + &clkaudio CLKID_AUDIO_GATE_SPDIFIN + &clkaudio CLKID_AUDIO_GATE_SPDIFOUT_A + &clkaudio CLKID_AUDIO_SPDIFIN + &clkaudio CLKID_AUDIO_SPDIFOUT_A>; + clock-names = "sysclk", "fixed_clk", "gate_spdifin", + "gate_spdifout", "clk_spdifin", "clk_spdifout"; + + interrupts = + ; + interrupt-names = "irq_spdifin"; + + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; + + pinctrl-0 = <&spdifout_a &spdifin_a>; + pinctrl-1 = <&spdifout_a_mute>; + + /* + * whether do asrc for pcm and resample a or b + * if raw data, asrc is disabled automatically + * 0: "Disable", + * 1: "Enable:32K", + * 2: "Enable:44K", + * 3: "Enable:48K", + * 4: "Enable:88K", + * 5: "Enable:96K", + * 6: "Enable:176K", + * 7: "Enable:192K", + */ + asrc_id = <0>; + auto_asrc = <3>; + + status = "okay"; + }; + + spdifb:spdif@1 { + compatible = "amlogic, tm2-snd-spdif-b"; + #sound-dai-cells = <0>; + + clocks = <&clkc CLKID_MPLL0 /*CLKID_HIFI_PLL*/ + &clkaudio CLKID_AUDIO_GATE_SPDIFOUT_B + &clkaudio CLKID_AUDIO_SPDIFOUT_B>; + clock-names = "sysclk", + "gate_spdifout", "clk_spdifout"; + + status = "okay"; + }; + + extn:extn { + compatible = "amlogic, snd-extn"; + #sound-dai-cells = <0>; + + + interrupts = + ; + interrupt-names = "irq_frhdmirx"; + + status = "okay"; + }; + + earc:earc { + compatible = "amlogic, tm2-snd-earc"; + #sound-dai-cells = <0>; + + clocks = < &clkaudio CLKID_EARCRX_CMDC + &clkaudio CLKID_EARCRX_DMAC + &clkc CLKID_FCLK_DIV5 + &clkc CLKID_FCLK_DIV3 + &clkaudio CLKID_EARCTX_CMDC + &clkaudio CLKID_EARCTX_DMAC + &clkc CLKID_FCLK_DIV5 + &clkc CLKID_FCLK_DIV3 + >; + clock-names = + "rx_cmdc", + "rx_dmac", + "rx_cmdc_srcpll", + "rx_dmac_srcpll", + "tx_cmdc", + "tx_dmac", + "tx_cmdc_srcpll", + "tx_dmac_srcpll"; + interrupts = < + GIC_SPI 88 IRQ_TYPE_EDGE_RISING + GIC_SPI 87 IRQ_TYPE_EDGE_RISING + >; + interrupt-names = "rx_cmdc", "rx_dmac"; + + status = "okay"; + }; + + aed:effect { + compatible = "amlogic, snd-effect-v2"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_EQDRC + &clkc CLKID_FCLK_DIV5 + &clkaudio CLKID_AUDIO_EQDRC>; + clock-names = "gate", "srcpll", "eqdrc"; + + /* + * 0:tdmout_a + * 1:tdmout_b + * 2:tdmout_c + * 3:spdifout + * 4:spdifout_b + */ + eqdrc_module = <0>; + /* max 0xf, each bit for one lane, usually one lane */ + lane_mask = <0x1>; + /* max 0xff, each bit for one channel */ + channel_mask = <0xff>; + + status = "disable"; + }; + + asrca: resample@0 { + compatible = "amlogic, tl1-resample-a"; + clocks = <&clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_MCLK_A + &clkaudio CLKID_AUDIO_RESAMPLE_A>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + /*same with toddr_src + * TDMIN_A, 0 + * TDMIN_B, 1 + * TDMIN_C, 2 + * SPDIFIN, 3 + * PDMIN, 4 + * NONE, + * TDMIN_LB, 6 + * LOOPBACK, 7 + */ + resample_module = <3>; + + status = "disabled"; + }; + + asrcb: resample@1 { + compatible = "amlogic, tl1-resample-b"; + + clocks = <&clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_MCLK_F + &clkaudio CLKID_AUDIO_RESAMPLE_B>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + + /*same with toddr_src + * TDMIN_A, 0 + * TDMIN_B, 1 + * TDMIN_C, 2 + * SPDIFIN, 3 + * PDMIN, 4 + * NONE, + * TDMIN_LB, 6 + * LOOPBACK, 7 + */ + resample_module = <3>; + + status = "disabled"; + }; + + vad:vad { + compatible = "amlogic, snd-vad"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_TOVAD + &clkc CLKID_FCLK_DIV5 + &clkaudio CLKID_AUDIO_VAD>; + clock-names = "gate", "pll", "clk"; + + interrupts = ; + interrupt-names = "irq_wakeup", "irq_frame_sync"; + + /* + * Data src sel: + * 0: tdmin_a; + * 1: tdmin_b; + * 2: tdmin_c; + * 3: spdifin; + * 4: pdmin; + * 5: loopback_b; + * 6: tdmin_lb; + * 7: loopback_a; + */ + src = <4>; + + /* + * deal with hot word in user space or kernel space + * 0: in user space + * 1: in kernel space + */ + level = <1>; + + status = "disabled"; + }; +}; /* end of audiobus */ + +&pinctrl_periphs { + /* audio pin mux */ + + tdma_mclk: tdma_mclk { + mux { /* GPIOH_4 */ + groups = "mclk0_h"; + function = "mclk0"; + }; + }; + + tdmout_a: tdmout_a { + mux { /* GPIOH_5, GPIOH_6, GPIOH_7, GPIOH_8*/ + groups = "tdma_fs_h", + "tdma_sclk_h", + "tdma_dout0_h", + "tdma_dout1_h"; + function = "tdma_out"; + bias-pull-down; + }; + }; + + tdmin_a: tdmin_a { + mux { /* GPIOH_11, GPIOH_12 */ + groups = "tdma_din0_h", + "tdma_din1_h"; + function = "tdma_in"; + }; + }; + + tdmout_c: tdmout_c { + mux { /* GPIODV_7, GPIODV_8, GPIODV_9 */ + groups = "tdmc_sclk", + "tdmc_fs", + "tdmc_dout0"; + function = "tdmc_out"; + }; + }; + + tdmin_c: tdmin_c { + mux { /* GPIODV_10 */ + groups = "tdmc_din1"; + function = "tdmc_in"; + }; + }; + + spdifin_a: spdifin_a { + mux { /* GPIODV_5 */ + groups = "spdif_in"; + function = "spdif_in"; + }; + }; + + spdifout_a: spdifout_a { + mux { /* GPIODV_4 */ + groups = "spdif_out_dv4"; + function = "spdif_out"; + }; + }; + + spdifout_a_mute: spdifout_a_mute { + mux { /* GPIODV_4 */ + groups = "GPIODV_4"; + function = "gpio_periphs"; + }; + }; + + pdmin: pdmin { + mux { /* GPIOZ_7, GPIOZ_8, pdm_din2_z4 */ + groups = "pdm_dclk_z", + "pdm_din0_z", + "pdm_din2_z4"; + function = "pdm"; + }; + }; + + +}; /* end of pinctrl_periphs */ + +&pinctrl_aobus { + spdifout: spdifout { + mux { /* gpiao_10 */ + groups = "spdif_out_ao"; + function = "spdif_out_ao"; + }; + }; +}; /* end of pinctrl_aobus */ + +&audio_data{ + status = "okay"; +}; + +&i2c2 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&i2c2_z_pins>; + clock-frequency = <400000>; + + tas5805: tas5805@36 { + compatible = "ti,tas5805"; + #sound-dai-cells = <0>; + codec_name = "tas5805"; + reg = <0x2d>; + status = "disable"; + }; + + ad82584f: ad82584f@62 { + compatible = "ESMT, ad82584f"; + #sound-dai-cells = <0>; + reg = <0x31>; + status = "disabled"; + reset_pin = <&gpio_ao GPIOAO_6 0>; + }; + +}; + +&sd_emmc_c { + status = "okay"; + emmc { + caps = "MMC_CAP_8_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + "MMC_CAP_1_8V_DDR", + "MMC_CAP_HW_RESET", + "MMC_CAP_ERASE", + "MMC_CAP_CMD23"; + caps2 = "MMC_CAP2_HS200"; + /* "MMC_CAP2_HS400";*/ + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&spifc { + status = "disabled"; + spi-nor@0 { + cs_gpios = <&gpio BOOT_13 GPIO_ACTIVE_HIGH>; + }; +}; + +&slc_nand { + status = "disabled"; + plat-names = "bootloader", "nandnormal"; + plat-num = <2>; + plat-part-0 = <&bootloader>; + plat-part-1 = <&nandnormal>; + bootloader: bootloader{ + enable_pad = "ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <1>; + part_num = <0>; + rb_detect = <1>; + }; + nandnormal: nandnormal{ + enable_pad = "ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + plane_mode = "twoplane"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <2>; + part_num = <3>; + partition = <&nand_partitions>; + rb_detect = <1>; + }; + nand_partitions:nand_partition{ + /* + * if bl_mode is 1, tpl size was generate by + * fip_copies * fip_size which + * will not skip bad when calculating + * the partition size; + * + * if bl_mode is 0, + * tpl partition must be comment out. + */ + tpl{ + offset=<0x0 0x0>; + size=<0x0 0x0>; + }; + logo{ + offset=<0x0 0x0>; + size=<0x0 0x200000>; + }; + recovery{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + boot{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + system{ + offset=<0x0 0x0>; + size=<0x0 0x4000000>; + }; + data{ + offset=<0xffffffff 0xffffffff>; + size=<0x0 0x0>; + }; + }; +}; + +ðmac { + status = "okay"; + pinctrl-names = "internal_eth_pins"; + pinctrl-0 = <&internal_eth_pins>; + mc_val = <0x4be04>; + + internal_phy=<1>; +}; + +&uart_A { + status = "okay"; +}; + +&dwc3 { + status = "okay"; +}; + +&usb2_phy_v2 { + status = "okay"; + portnum = <3>; +}; + +&usb3_phy_v2 { + status = "okay"; + portnum = <2>; + portconfig-30 = <1>; + portconfig-31 = <1>; +}; + +&usb_otg { + status = "okay"; + otg = <0>; +}; + +&dwc2_a { + status = "okay"; + /** 0: normal, 1: otg+dwc3 host only, 2: otg+dwc3 device only*/ + controller-type = <1>; +}; + +&pcie_A { + reset-gpio = <&gpio_ao GPIOAO_11 GPIO_ACTIVE_HIGH>; + status = "disable"; +}; + +&pcie_B { + /* pcie b reset gpio is the oe pad, must be changed */ + reset-gpio = <&gpio GPIOH_22 GPIO_ACTIVE_HIGH>; + status = "disable"; +}; + +&spicc0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&spicc0_pins_h>; + cs-gpios = <&gpio GPIOH_20 0>; +}; + +&meson_fb { + status = "okay"; + display_size_default = <1920 1080 1920 2160 32>; + mem_size = <0x00800000 0x1980000 0x100000 0x100000 0x800000>; + logo_addr = "0x7f800000"; + mem_alloc = <0>; + pxp_mode = <0>; /** 0:normal mode 1:pxp mode */ +}; + +&pwm_AO_cd { + status = "okay"; +}; + +&saradc { + status = "okay"; +}; + +&i2c1 { + status = "okay"; + clock-frequency = <300000>; + pinctrl-names="default"; + pinctrl-0=<&i2c1_h_pins>; + + lcd_extern_i2c0: lcd_extern_i2c@0 { + compatible = "lcd_ext, i2c"; + dev_name = "i2c_T5800Q"; + reg = <0x1c>; + status = "okay"; + }; + + lcd_extern_i2c1: lcd_extern_i2c@1 { + compatible = "lcd_ext, i2c"; + dev_name = "i2c_ANX6862"; + reg = <0x20>; + status = "okay"; + }; + + lcd_extern_i2c2: lcd_extern_i2c@2 { + compatible = "lcd_ext, i2c"; + dev_name = "i2c_ANX7911"; + reg = <0x74>; + status = "okay"; + }; +}; + +&efuse { + status = "okay"; +}; diff --git a/arch/arm/boot/dts/amlogic/tm2_t962x3_ab301.dts b/arch/arm/boot/dts/amlogic/tm2_t962x3_ab301.dts new file mode 100644 index 000000000000..150fcd11af7f --- /dev/null +++ b/arch/arm/boot/dts/amlogic/tm2_t962x3_ab301.dts @@ -0,0 +1,1986 @@ +/* + * arch/arm/boot/dts/amlogic/tm2_t962e2_ab301.dts + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +/dts-v1/; + +#include "mesontm2.dtsi" +#include "partition_mbox_normal.dtsi" +#include "mesontm2_t962x3_ab301-panel.dtsi" + +/ { + model = "Amlogic TM2 T962E2 AB301"; + amlogic-dt-id = "tm2_t962e2_ab301"; + compatible = "amlogic, tm2_t962e2_ab301"; + + aliases { + serial0 = &uart_AO; + serial1 = &uart_A; + serial2 = &uart_B; + serial3 = &uart_C; + serial4 = &uart_AO_B; + tsensor0 = &p_tsensor; + tsensor1 = &d_tsensor; + tsensor2 = &s_tsensor; + i2c0 = &i2c0; + i2c1 = &i2c1; + i2c2 = &i2c2; + i2c3 = &i2c3; + i2c4 = &i2c_AO; + spi0 = &spicc0; + spi1 = &spicc1; + }; + + memory@00000000 { + device_type = "memory"; + linux,usable-memory = <0x0 0x80000000>; + }; + + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + /* global autoconfigured region for contiguous allocations */ + ramoops@0x07400000 { + compatible = "ramoops"; + reg = <0x07400000 0x00100000>; + record-size = <0x8000>; + console-size = <0x8000>; + ftrace-size = <0x20000>; + }; + + secmon_reserved: linux,secmon { + compatible = "shared-dma-pool"; + reusable; + size = <0x400000>; + alignment = <0x400000>; + alloc-ranges = <0x05000000 0x400000>; + }; + + logo_reserved:linux,meson-fb { + compatible = "shared-dma-pool"; + reusable; + size = <0x800000>; + alignment = <0x400000>; + alloc-ranges = <0x7f800000 0x800000>; + }; + + lcd_tcon_reserved:linux,lcd_tcon { + compatible = "shared-dma-pool"; + reusable; + size = <0xc00000>; + alignment = <0x400000>; + alloc-ranges = <0x7ec00000 0xc00000>; + }; + + codec_mm_cma:linux,codec_mm_cma { + compatible = "shared-dma-pool"; + reusable; + /* ion_codec_mm max can alloc size 80M*/ + size = <0x13400000>; + alignment = <0x400000>; + linux,contiguous-region; + alloc-ranges = <0x30000000 0x50000000>; + }; + + /* codec shared reserved */ + codec_mm_reserved:linux,codec_mm_reserved { + compatible = "amlogic, codec-mm-reserved"; + size = <0x0>; + alignment = <0x100000>; + //no-map; + }; + + ion_cma_reserved:linux,ion-dev { + compatible = "shared-dma-pool"; + reusable; + size = <0x2000000>; + alignment = <0x400000>; + }; + + /* vdin0 CMA pool */ + //vdin0_cma_reserved:linux,vdin0_cma { + // compatible = "shared-dma-pool"; + // reusable; + /* 3840x2160x4x4 ~=128 M */ + // size = <0xc400000>; + // alignment = <0x400000>; + //}; + + /* vdin1 CMA pool */ + vdin1_cma_reserved:linux,vdin1_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16 M */ + size = <0x1400000>; + alignment = <0x400000>; + }; + + /*demod_reserved:linux,demod { + * compatible = "amlogic, demod-mem"; + * size = <0x800000>; //8M //100m 0x6400000 + * alloc-ranges = <0x0 0x30000000>; + * //multi-use; + * //no-map; + *}; + */ + + demod_cma_reserved:linux,demod_cma { + compatible = "shared-dma-pool"; + reusable; + /* 8M */ + size = <0x0800000>; + alignment = <0x400000>; + }; + + /*di CMA pool */ + di_cma_reserved:linux,di_cma { + compatible = "shared-dma-pool"; + reusable; + /* buffer_size = 3621952(yuv422 8bit) + * | 4736064(yuv422 10bit) + * | 4074560(yuv422 10bit full pack mode) + * 10x3621952=34.6M(0x23) support 8bit + * 10x4736064=45.2M(0x2e) support 12bit + * 10x4074560=40M(0x28) support 10bit + */ + size = <0x02800000>; + alignment = <0x400000>; + }; + + /* for hdmi rx emp use */ + hdmirx_emp_cma_reserved:linux,emp_cma { + compatible = "shared-dma-pool"; + /*linux,phandle = <5>;*/ + reusable; + /* 4M for emp to ddr */ + /* 32M for tmds to ddr */ + size = <0x400000>; + alignment = <0x400000>; + /* alloc-ranges = <0x400000 0x2000000>; */ + }; + + /* POST PROCESS MANAGER */ + ppmgr_reserved:linux,ppmgr { + compatible = "amlogic, ppmgr_memory"; + size = <0x0>; + }; + + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + }; /* end of reserved-memory */ + galcore { + status = "okay"; + }; + codec_mm { + compatible = "amlogic, codec, mm"; + status = "okay"; + memory-region = <&codec_mm_cma &codec_mm_reserved>; + }; + + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + + ppmgr { + compatible = "amlogic, ppmgr"; + memory-region = <&ppmgr_reserved>; + status = "okay"; + }; + + deinterlace { + compatible = "amlogic, deinterlace"; + status = "okay"; + /* 0:use reserved; 1:use cma; 2:use cma as reserved */ + flag_cma = <1>; + //memory-region = <&di_reserved>; + memory-region = <&di_cma_reserved>; + interrupts = <0 46 1 + 0 40 1>; + interrupt-names = "pre_irq", "post_irq"; + clocks = <&clkc CLKID_VPU_CLKB_TMP_COMP>, + <&clkc CLKID_VPU_CLKB_COMP>, + <&clkc CLKID_VPU_MUX>; + clock-names = "vpu_clkb_tmp_composite", + "vpu_clkb_composite", + "vpu_mux"; + 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>; + }; + + vout { + compatible = "amlogic, vout"; + status = "okay"; + fr_auto_policy = <0>; + }; + + /* Audio Related start */ + pdm_codec:dummy { + #sound-dai-cells = <0>; + compatible = "amlogic, pdm_dummy_codec"; + status = "okay"; + }; + + dummy_codec:dummy { + #sound-dai-cells = <0>; + compatible = "amlogic, aml_dummy_codec"; + status = "okay"; + }; + + tl1_codec:codec { + #sound-dai-cells = <0>; + compatible = "amlogic, tl1_acodec"; + status = "okay"; + reg = <0xff632000 0x1c>; + tdmout_index = <0>; + tdmin_index = <0>; + dat1_ch_sel = <1>; + }; + + aml_dtv_demod { + compatible = "amlogic, ddemod-tl1"; + dev_name = "aml_dtv_demod"; + status = "okay"; + + //pinctrl-names="dtvdemod_agc"; + //pinctrl-0=<&dtvdemod_agc>; + + clocks = <&clkc CLKID_DAC_CLK>; + clock-names = "vdac_clk_gate"; + + reg = <0xff650000 0x4000 /*dtv demod base*/ + 0xff63c000 0x2000 /*hiu reg base*/ + 0xff800000 0x1000 /*io_aobus_base*/ + 0xffd01000 0x1000 /*reset*/ + >; + + dtv_demod0_mem = <0>; // need move to aml_dtv_demod ? + spectrum = <1>; + cma_flag = <1>; + cma_mem_size = <8>; + memory-region = <&demod_cma_reserved>;//<&demod_reserved>; + }; + + auge_sound { + compatible = "amlogic, tm2-sound-card"; + aml-audio-card,name = "AML-AUGESOUND"; + + avout_mute-gpios = <&gpio GPIODV_3 GPIO_ACTIVE_HIGH>; + + aml-audio-card,dai-link@0 { + format = "i2s"; + mclk-fs = <256>; + continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdma>; + frame-master = <&tdma>; + /* slave mode */ + /* + * bitclock-master = <&tdmacodec>; + * frame-master = <&tdmacodec>; + */ + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-i2s"; + tdmacpu: cpu { + sound-dai = <&tdma>; + dai-tdm-slot-tx-mask = + <1 1>; + dai-tdm-slot-rx-mask = + <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmacodec: codec { + //sound-dai = <&dummy_codec>; + prefix-names = "AMP"; + sound-dai = <&tas5805 &tl1_codec>; + }; + }; + + aml-audio-card,dai-link@1 { + + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdmb>; + frame-master = <&tdmb>; + /* slave mode */ + //bitclock-master = <&tdmbcodec>; + //frame-master = <&tdmbcodec>; + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-pcm"; + cpu { + sound-dai = <&tdmb>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + /* + * dai-tdm-slot-tx-mask = + * <1 1 1 1 1 1 1 1>; + * dai-tdm-slot-rx-mask = + * <1 1 1 1 1 1 1 1>; + * dai-tdm-slot-num = <8>; + */ + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmbcodec: codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@2 { + + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdmc>; + frame-master = <&tdmc>; + /* slave mode */ + //bitclock-master = <&tdmccodec>; + //frame-master = <&tdmccodec>; + /* suffix-name, sync with android audio hal used for */ + //suffix-name = "alsaPORT-tdm"; + cpu { + sound-dai = <&tdmc>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmccodec: codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@3 { + mclk-fs = <64>; + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-pdm"; + cpu { + sound-dai = <&pdm>; + }; + codec { + sound-dai = <&pdm_codec>; + }; + }; + + aml-audio-card,dai-link@4 { + mclk-fs = <128>; + continuous-clock; + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-spdif"; + cpu { + sound-dai = <&spdifa>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@5 { + mclk-fs = <128>; + suffix-name = "alsaPORT-spdifb"; + cpu { + sound-dai = <&spdifb>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@6 { + mclk-fs = <256>; + suffix-name = "alsaPORT-tv"; + cpu { + sound-dai = <&extn>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@7 { + mclk-fs = <256>; + suffix-name = "alsaPORT-earc"; + cpu { + sound-dai = <&earc>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + }; + /* Audio Related end */ + + dvb { + compatible = "amlogic, dvb"; + status = "okay"; + fe0_mode = "internal"; + fe0_tuner = <&tuner>; + + /*"parallel","serial","disable"*/ + ts2 = "parallel"; + ts2_control = <0>; + ts2_invert = <0>; + interrupts = <0 23 1 + 0 5 1 + 0 53 1 + 0 19 1 + 0 25 1 + 0 17 1>; + interrupt-names = "demux0_irq", + "demux1_irq", + "demux2_irq", + "dvr0_irq", + "dvr1_irq", + "dvr2_irq"; + clocks = <&clkc CLKID_DEMUX + &clkc CLKID_ASYNC_FIFO + &clkc CLKID_AHB_ARB0 +/* &clkc CLKID_DOS_PARSER>;*/ + &clkc CLKID_U_PARSER>; + clock-names = "demux", "asyncfifo", "ahbarb0", "uparsertop"; + }; + + tvafe_avin_detect { + compatible = "amlogic, tl1_tvafe_avin_detect"; + status = "okay"; + device_mask = <1>;/*bit0:ch1;bit1:ch2*/ + interrupts = <0 12 1>, + <0 13 1>; + }; + + amlvecm { + compatible = "amlogic, vecm-tl1"; + dev_name = "aml_vecm"; + status = "okay"; + gamma_en = <1>;/*1:enabel ;0:disable*/ + wb_en = <1>;/*1:enabel ;0:disable*/ + cm_en = <0>;/*1:enabel ;0:disable*/ + wb_sel = <1>;/*1:mtx ;0:gainoff*/ + vlock_en = <1>;/*1:enable;0:disable*/ + vlock_mode = <0x4>; + /* vlock work mode: + *bit0:auto ENC + *bit1:auto PLL + *bit2:manual PLL + *bit3:manual ENC + *bit4:manual soft ENC + *bit5:manual MIX PLL ENC + */ + vlock_pll_m_limit = <1>; + vlock_line_limit = <3>; + }; + + amdolby_vision { + compatible = "amlogic, dolby_vision_tm2"; + dev_name = "aml_amdolby_vision_driver"; + status = "okay"; + tv_mode = <1>;/*1:enabel ;0:disable*/ + }; + + vdin@0 { + compatible = "amlogic, vdin"; + /*memory-region = <&vdin0_cma_reserved>;*/ + status = "okay"; + /*bit0:(1:share with codec_mm;0:cma alone) + *bit8:(1:alloc in discontinus way;0:alone in continuous way) + */ + flag_cma = <0x101>; + /*MByte, if 10bit disable: 64M(YUV422), + *if 10bit enable: 64*1.5 = 96M(YUV422) + *if support 4K2K-YUV444-10bit-WR:3840*2160*4*4 ~= 128M + *if support 4K2K-YUV422-10bit-wr:3840*2160*3*4 ~= 96M + *if support 4K2K-YUV422-8BIT-WR:3840*2160*2*4 ~= 64M + *if support 1080p-YUV422-8BIT-WR:1920*1080*2*4 ~= 16M + */ + cma_size = <160>; + interrupts = <0 83 1>; + rdma-irq = <2>; + clocks = <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_VDIN_MEAS_COMP>; + clock-names = "fclk_div5", "cts_vdin_meas_clk"; + vdin_id = <0>; + /*vdin write mem color depth support: + * bit0:support 8bit + * bit1:support 9bit + * bit2:support 10bit + * bit3:support 12bit + * bit4:support yuv422 10bit full pack mode (from txl new add) + * bit8:use 8bit at 4k_50/60hz_10bit + * bit9:use 10bit at 4k_50/60hz_10bit + */ + tv_bit_mode = <0x215>; + /* afbce_bit_mode: (amlogic frame buff compression encoder) + * bit 0~3: + * 0 -- normal mode, not use afbce + * 1 -- use afbce non-mmu mode + * 2 -- use afbce mmu mode + * bit 4: + * 0 -- afbce compression-lossy disable + * 1 -- afbce compression-lossy enable + */ + afbce_bit_mode = <0x0>; + }; + + vdin@1 { + compatible = "amlogic, vdin"; + memory-region = <&vdin1_cma_reserved>; + status = "okay"; + /*bit0:(1:share with codec_mm;0:cma alone) + *bit8:(1:alloc in discontinus way;0:alone in continuous way) + */ + flag_cma = <0>; + interrupts = <0 85 1>; + rdma-irq = <4>; + clocks = <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_VDIN_MEAS_COMP>; + clock-names = "fclk_div5", "cts_vdin_meas_clk"; + vdin_id = <1>; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + */ + tv_bit_mode = <0x15>; + }; + + tvafe { + compatible = "amlogic, tvafe-tl1"; + /*memory-region = <&tvafe_cma_reserved>;*/ + status = "okay"; + flag_cma = <1>;/*1:share with codec_mm;0:cma alone*/ + cma_size = <5>;/*MByte*/ + reg = <0xff654000 0x2000>;/*tvafe reg base*/ + reserve-iomap = "true"; + tvafe_id = <0>; + //pinctrl-names = "default"; + /*!!particular sequence, no more and no less!!!*/ + tvafe_pin_mux = < + 3 /* TVAFE_CVBS_IN2, CVBS_IN0 = 0 */ + 1 /* TVAFE_CVBS_IN0, CVBS_IN1 */ + 2 /* TVAFE_CVBS_IN1, CVBS_IN2 */ + 4 /* TVAFE_CVBS_IN3, CVBS_IN3 */ + >; + clocks = <&clkc CLKID_DAC_CLK>; + clock-names = "vdac_clk_gate"; + }; + + vbi { + compatible = "amlogic, vbi"; + status = "okay"; + interrupts = <0 83 1>; + }; + + cvbsout { + compatible = "amlogic, cvbsout-tl1"; + status = "disabled"; + clocks = <&clkc CLKID_VCLK2_ENCI + &clkc CLKID_VCLK2_VENCI0 + &clkc CLKID_VCLK2_VENCI1 + &clkc CLKID_DAC_CLK>; + clock-names = "venci_top_gate", + "venci_0_gate", + "venci_1_gate", + "vdac_clk_gate"; + /* clk path */ + /* 0:vid_pll vid2_clk */ + /* 1:gp0_pll vid2_clk */ + /* 2:vid_pll vid1_clk */ + /* 3:gp0_pll vid1_clk */ + clk_path = <0>; + + /* performance: reg_address, reg_value */ + /* tl1 */ + performance = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x8080 + 0x1b05 0xfd + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + performance_sarft = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x0 + 0x1b05 0x9 + 0x1c59 0xfc48 + 0xffff 0x0>; /* ending flag */ + performance_revB_telecom = <0x1bf0 0x9 + 0x1b56 0x546 + 0x1b12 0x8080 + 0x1b05 0x9 + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + }; + + /* for external keypad */ + adc_keypad { + compatible = "amlogic, adc_keypad"; + status = "okay"; + key_name = "power","up","down","enter","left","right","home"; + key_num = <7>; + io-channels = <&saradc SARADC_CH2>,<&saradc SARADC_CH3>; + io-channel-names = "key-chan-2", "key-chan-3"; + key_chan = ; + key_code = <116 103 108 28 105 106 102>; + key_val = <0 143 266 389 512 143 266>; //val=voltage/1800mV*1023 + key_tolerance = <40 40 40 40 40 40 40>; +}; + + unifykey { + compatible = "amlogic, unifykey"; + status = "okay"; + + unifykey-num = <21>; + unifykey-index-0 = <&keysn_0>; + unifykey-index-1 = <&keysn_1>; + unifykey-index-2 = <&keysn_2>; + unifykey-index-3 = <&keysn_3>; + unifykey-index-4 = <&keysn_4>; + unifykey-index-5 = <&keysn_5>; + unifykey-index-6 = <&keysn_6>; + unifykey-index-7 = <&keysn_7>; + unifykey-index-8 = <&keysn_8>; + unifykey-index-9 = <&keysn_9>; + unifykey-index-10= <&keysn_10>; + unifykey-index-11 = <&keysn_11>; + unifykey-index-12 = <&keysn_12>; + unifykey-index-13 = <&keysn_13>; + unifykey-index-14 = <&keysn_14>; + unifykey-index-15 = <&keysn_15>; + unifykey-index-16 = <&keysn_16>; + unifykey-index-17 = <&keysn_17>; + unifykey-index-18 = <&keysn_18>; + unifykey-index-19 = <&keysn_19>; + unifykey-index-20 = <&keysn_20>; + + keysn_0: key_0{ + key-name = "usid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_1:key_1{ + key-name = "mac"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_2:key_2{ + key-name = "hdcp"; + key-device = "secure"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_3:key_3{ + key-name = "secure_boot_set"; + key-device = "efuse"; + key-permit = "write"; + }; + keysn_4:key_4{ + key-name = "mac_bt"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_5:key_5{ + key-name = "mac_wifi"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_6:key_6{ + key-name = "hdcp2_tx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_7:key_7{ + key-name = "hdcp2_rx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_8:key_8{ + key-name = "widevinekeybox"; + key-device = "secure"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_9:key_9{ + key-name = "deviceid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_10:key_10{ + key-name = "hdcp22_fw_private"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_11:key_11{ + key-name = "hdcp22_rx_private"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_12:key_12{ + key-name = "hdcp22_rx_fw"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_13:key_13{ + key-name = "hdcp14_rx"; + key-device = "normal"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_14:key_14{ + key-name = "prpubkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_15:key_15{ + key-name = "prprivkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_16:key_16{ + key-name = "lcd"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_17:key_17{ + key-name = "lcd_extern"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_18:key_18{ + key-name = "backlight"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_19:key_19{ + key-name = "lcd_tcon"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_20:key_20{ + key-name = "attestationkeybox";// attestation key + key-device = "secure"; + key-permit = "read","write","del"; + }; + }; /* End unifykey */ + + amlvideo2_0 { + compatible = "amlogic, amlvideo2"; + dev_name = "amlvideo2"; + status = "okay"; + amlvideo2_id = <0>; + cma_mode = <1>; + }; + + amlvideo2_1 { + compatible = "amlogic, amlvideo2"; + dev_name = "amlvideo2"; + status = "okay"; + amlvideo2_id = <1>; + cma_mode = <1>; + }; + + hdmirx { + compatible = "amlogic, hdmirx_tl1"; + #address-cells=<1>; + #size-cells=<1>; + memory-region = <&hdmirx_emp_cma_reserved>; + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&hdmirx_a_mux &hdmirx_b_mux + &hdmirx_c_mux>; + repeat = <0>; + interrupts = <0 41 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clkc CLKID_HDMIRX_MODET_COMP>, + <&clkc CLKID_HDMIRX_CFG_COMP>, + <&clkc CLKID_HDMIRX_ACR_COMP>, + <&clkc CLKID_HDMIRX_METER_COMP>, + <&clkc CLKID_HDMIRX_AXI_COMP>, + <&xtal>, + <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_FCLK_DIV7>, + <&clkc CLKID_HDCP22_SKP_COMP>, + <&clkc CLKID_HDCP22_ESM_COMP>; + // <&clkc CLK_AUD_PLL2FS>, + // <&clkc CLK_AUD_PLL4FS>, + // <&clkc CLK_AUD_OUT>; + clock-names = "hdmirx_modet_clk", + "hdmirx_cfg_clk", + "hdmirx_acr_ref_clk", + "cts_hdmirx_meter_clk", + "cts_hdmi_axi_clk", + "xtal", + "fclk_div5", + "fclk_div7", + "hdcp_rx22_skp", + "hdcp_rx22_esm"; + // "hdmirx_aud_pll2fs", + // "hdmirx_aud_pll4f", + // "clk_aud_out"; + hdmirx_id = <0>; + en_4k_2_2k = <0>; + hpd_low_cec_off = <1>; + /* bit4: enable feature, bit3~0: port number */ + disable_port = <0x0>; + /* MAP_ADDR_MODULE_CBUS */ + /* MAP_ADDR_MODULE_HIU */ + /* MAP_ADDR_MODULE_HDMIRX_CAPB3 */ + /* MAP_ADDR_MODULE_SEC_AHB */ + /* MAP_ADDR_MODULE_SEC_AHB2 */ + /* MAP_ADDR_MODULE_APB4 */ + /* MAP_ADDR_MODULE_TOP */ + reg = < 0x0 0x0 + 0xff63C000 0x2000 + 0xffe0d000 0x2000 + 0x0 0x0 + 0x0 0x0 + 0x0 0x0 + 0xff610000 0xa000>; + }; + + aocec: aocec { + compatible = "amlogic, aocec-tm2"; + /*device_name = "aocec";*/ + status = "okay"; + vendor_name = "Amlogic"; /* Max Chars: 8 */ + /* Refer to the following URL at: + * http://standards.ieee.org/develop/regauth/oui/oui.txt + */ + vendor_id = <0x000000>; + product_desc = "TM2"; /* Max Chars: 16 */ + cec_osd_string = "AML_TV"; /* Max Chars: 14 */ + port_num = <3>; + ee_cec; + /*cec_sel = <2>;*/ + arc_port_mask = <0x2>; + output = <1>; /*output port number*/ + interrupts = <0 205 1 + 0 199 1>; + interrupt-names = "hdmi_aocecb","hdmi_aocec"; + pinctrl-names = "default","hdmitx_aocecb","cec_pin_sleep"; + pinctrl-0=<&aoceca_mux>; + pinctrl-1=<&aocecb_mux>; + pinctrl-2=<&aoceca_mux>; + reg = <0xFF80023c 0x4 + 0xFF800000 0x400>; + reg-names = "ao_exit","ao"; + }; + + p_tsensor: p_tsensor@ff634800 { + compatible = "amlogic, r1p1-tsensor"; + status = "okay"; + reg = <0xff634800 0x50>, + <0xff800268 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 35 0>; + clocks = <&clkc CLKID_TS_CLK_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + d_tsensor: d_tsensor@ff634c00 { + compatible = "amlogic, r1p1-tsensor"; + status = "okay"; + reg = <0xff634c00 0x50>, + <0xff800230 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 36 0>; + clocks = <&clkc CLKID_TS_CLK_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + s_tsensor: s_tsensor@ff635000 { + compatible = "amlogic, r1p1-tsensor"; + status = "okay"; + reg = <0xff635000 0x50>, + <0xff80026c 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 38 0>; + clocks = <&clkc CLKID_TS_CLK_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + meson_cooldev: meson-cooldev@0 { + status = "okay"; + compatible = "amlogic, meson-cooldev"; + cooling_devices { + cpufreq_cool_cluster0 { + min_state = <1000000>; + dyn_coeff = <140>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "cpufreq_cool0"; + device_type = "cpufreq"; + }; + cpucore_cool_cluster0 { + min_state = <1>; + dyn_coeff = <0>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "cpucore_cool0"; + device_type = "cpucore"; + }; + gpufreq_cool { + min_state = <400>; + dyn_coeff = <140>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "gpufreq_cool0"; + device_type = "gpufreq"; + }; + gpucore_cool { + min_state = <1>; + dyn_coeff = <0>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "gpucore_cool0"; + device_type = "gpucore"; + }; + }; + cpufreq_cool0:cpufreq_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + cpucore_cool0:cpucore_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + gpufreq_cool0:gpufreq_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + gpucore_cool0:gpucore_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + };/*meson cooling devices end*/ + + thermal-zones { + pll_thermal: pll_thermal { + polling-delay = <1000>; + polling-delay-passive = <100>; + sustainable-power = <1322>; + thermal-sensors = <&p_tsensor 0>; + trips { + pswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + pcontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + phot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + pcritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + cooling-maps { + cpufreq_cooling_map { + trip = <&pcontrol>; + cooling-device = <&cpufreq_cool0 0 11>; + contribution = <1024>; + }; + cpucore_cooling_map { + trip = <&pcontrol>; + cooling-device = <&cpucore_cool0 0 4>; + contribution = <1024>; + }; + gpufreq_cooling_map { + trip = <&pcontrol>; + cooling-device = <&gpufreq_cool0 0 4>; + contribution = <1024>; + }; + }; + }; + ddr_thermal: ddr_thermal { + polling-delay = <2000>; + polling-delay-passive = <1000>; + sustainable-power = <1322>; + thermal-sensors = <&d_tsensor 1>; + trips { + dswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + dcontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + dhot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + dcritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + }; + sar_thermal: sar_thermal { + polling-delay = <2000>; + polling-delay-passive = <1000>; + sustainable-power = <1322>; + thermal-sensors = <&s_tsensor 2>; + trips { + sswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + scontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + shot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + scritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + }; + }; /*thermal zone end*/ + + cpu_opp_table0: cpu_opp_table0 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <730000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <730000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <730000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <750000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <770000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <780000>; + }; + opp06 { + opp-hz = /bits/ 64 <1404000000>; + opp-microvolt = <790000>; + }; + opp07 { + opp-hz = /bits/ 64 <1500000000>; + opp-microvolt = <800000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <810000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <850000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <900000>; + }; + opp11 { + opp-hz = /bits/ 64 <1908000000>; + opp-microvolt = <950000>; + }; + }; + + cpufreq-meson { + compatible = "amlogic, cpufreq-meson"; + pinctrl-names = "default"; + pinctrl-0 = <&pwm_ao_d_pins3>; + status = "okay"; + }; + + tuner: tuner { + compatible = "amlogic, tuner"; + status = "okay"; + tuner_cur = <0>; /* default use tuner */ + tuner_num = <1>; /* tuner number, multi tuner support */ + tuner_name_0 = "mxl661_tuner"; + tuner_i2c_adap_0 = <&i2c0>; + tuner_i2c_addr_0 = <0x60>; + tuner_xtal_0 = <1>; /* 0: 16MHz, 1: 24MHz */ + tuner_xtal_mode_0 = <3>; + /* NO_SHARE_XTAL(0) + * SLAVE_XTAL_SHARE(3) + */ + tuner_xtal_cap_0 = <25>; /* when tuner_xtal_mode = 3, set 25 */ + }; + + atv-demod { + compatible = "amlogic, atv-demod"; + status = "okay"; + tuner = <&tuner>; + btsc_sap_mode = <1>; + /* pinctrl-names="atvdemod_agc_pins"; */ + /* pinctrl-0=<&atvdemod_agc_pins>; */ + reg = <0xff656000 0x2000 /* demod reg */ + 0xff63c000 0x2000 /* hiu reg */ + 0xff634000 0x2000 /* periphs reg */ + 0xff64a000 0x2000>; /* audio reg */ + reg_23cf = <0x88188832>; + /*default:0x88188832;r840 on haier:0x48188832*/ + }; + + bt-dev{ + compatible = "amlogic, bt-dev"; + status = "okay"; + gpio_reset = <&gpio GPIOC_13 GPIO_ACTIVE_HIGH>; + }; + + wifi{ + compatible = "amlogic, aml_wifi"; + status = "okay"; + interrupt_pin = <&gpio GPIOC_12 GPIO_ACTIVE_HIGH>; + irq_trigger_type = "GPIO_IRQ_LOW"; + dhd_static_buf; //dhd_static_buf support + power_on_pin = <&gpio GPIOC_11 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&pwm_b_pins1>; + pwm_config = <&wifi_pwm_conf>; + }; + + wifi_pwm_conf:wifi_pwm_conf{ + pwm_channel1_conf { + pwms = <&pwm_ab MESON_PWM_1 30541 0>; + duty-cycle = <15270>; + times = <8>; + }; + pwm_channel2_conf { + pwms = <&pwm_ab MESON_PWM_3 30500 0>; + duty-cycle = <15250>; + times = <12>; + }; + }; + + sd_emmc_b: sdio@ffe05000 { + status = "okay"; + compatible = "amlogic, meson-mmc-tm2"; + reg = <0xffe05000 0x800>; + interrupts = <0 190 4>; + + pinctrl-names = "sdio_all_pins", + "sdio_clk_cmd_pins"; + pinctrl-0 = <&sdio_all_pins>; + pinctrl-1 = <&sdio_clk_cmd_pins>; + + clocks = <&clkc CLKID_SD_EMMC_B>, + <&clkc CLKID_SD_EMMC_B_P0_COMP>, + <&clkc CLKID_FCLK_DIV2>, + <&clkc CLKID_FCLK_DIV5>, + <&xtal>; + clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + + bus-width = <4>; + cap-sd-highspeed; + cap-mmc-highspeed; + max-frequency = <100000000>; + disable-wp; + sdio { + pinname = "sdio"; + ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", /**ptm debug */ + "MMC_CAP_UHS_SDR12", + "MMC_CAP_UHS_SDR25", + "MMC_CAP_UHS_SDR50", + "MMC_CAP_UHS_SDR104", + "MMC_PM_KEEP_POWER", + "MMC_CAP_SDIO_IRQ"; + f_min = <400000>; + f_max = <200000000>; + max_req_size = <0x20000>; /**128KB*/ + card_type = <3>; + /* 3:sdio device(ie:sdio-wifi), + * 4:SD combo (IO+mem) card + */ + }; + }; + +/* sd_emmc_b: sd@ffe05000 { + * status = "okay"; + * compatible = "amlogic, meson-mmc-tm2"; + * reg = <0xffe05000 0x800>; + * interrupts = <0 190 1>; + * + * pinctrl-names = "sd_all_pins", + * "sd_clk_cmd_pins", + * "sd_1bit_pins"; + * pinctrl-0 = <&sd_all_pins>; + * pinctrl-1 = <&sd_clk_cmd_pins>; + * pinctrl-2 = <&sd_1bit_pins>; + * + * clocks = <&clkc CLKID_SD_EMMC_B>, + * <&clkc CLKID_SD_EMMC_B_P0_COMP>, + * <&clkc CLKID_FCLK_DIV2>, + * <&clkc CLKID_FCLK_DIV5>, + * <&xtal>; + * clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + * + * bus-width = <4>; + * cap-sd-highspeed; + * cap-mmc-highspeed; + * max-frequency = <100000000>; + * disable-wp; + * sd { + * pinname = "sd"; + * ocr_avail = <0x200080>; + * caps = "MMC_CAP_4_BIT_DATA", + * "MMC_CAP_MMC_HIGHSPEED", + * "MMC_CAP_SD_HIGHSPEED"; + * f_min = <400000>; + * f_max = <200000000>; + * max_req_size = <0x20000>; + * no_sduart = <1>; + * gpio_dat3 = <&gpio GPIOC_3 GPIO_ACTIVE_HIGH>; + * jtag_pin = <&gpio GPIOC_0 GPIO_ACTIVE_HIGH>; + * gpio_cd = <&gpio GPIOC_10 GPIO_ACTIVE_HIGH>; + * card_type = <5>; + * }; + * }; + */ + +}; /* end of / */ + +&i2c0 { + status = "okay"; + clock-frequency = <300000>; + pinctrl-names="default"; + pinctrl-0=<&i2c0_dv_pins>; +}; + +&audiobus { + tdma:tdm@0 { + compatible = "amlogic, tm2-snd-tdma"; + #sound-dai-cells = <0>; + + dai-tdm-lane-slot-mask-in = <1 0>; + dai-tdm-lane-slot-mask-out = <1 1 1 1>; + dai-tdm-clk-sel = <0>; + + clocks = <&clkaudio CLKID_AUDIO_MCLK_A + &clkc CLKID_MPLL0 + &clkc CLKID_MPLL1 + &clkaudio CLKID_AUDIO_SPDIFOUT_A>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; + + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdma_mclk &tdmout_a>; + + /* + * 0: tdmout_a; + * 1: tdmout_b; + * 2: tdmout_c; + * 3: spdifout; + * 4: spdifout_b; + */ + samesource_sel = <3>; + + /* In for ACODEC_ADC */ + acodec_adc = <1>; + + status = "okay"; + + /* !!!For --TV platform-- ONLY */ + Channel_Mask { + /*i2s has 4 pins, 8channel, mux output*/ + Spdif_samesource_Channel_Mask = "i2s_2/3"; + }; + }; + + tdmb:tdm@1 { + compatible = "amlogic, tm2-snd-tdmb"; + #sound-dai-cells = <0>; + + dai-tdm-lane-slot-mask-in = <1 0 0 0>; + dai-tdm-lane-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <1>; + + clocks = <&clkaudio CLKID_AUDIO_MCLK_B + &clkc CLKID_MPLL1>; + clock-names = "mclk", "clk_srcpll"; + + status = "okay"; + }; + + tdmc:tdm@2 { + compatible = "amlogic, tm2-snd-tdmc"; + #sound-dai-cells = <0>; + + dai-tdm-lane-slot-mask-in = <1 0 0 0>; + dai-tdm-lane-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <2>; + + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmout_c &tdmin_c>; + + status = "okay"; + }; + + pdm:pdm { + compatible = "amlogic, tm2-snd-pdm"; + #sound-dai-cells = <0>; + clocks = <&clkaudio CLKID_AUDIO_GATE_PDM + &clkc CLKID_FCLK_DIV3 + &clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_PDMIN0 + &clkaudio CLKID_AUDIO_PDMIN1>; + clock-names = "gate", + "sysclk_srcpll", + "dclk_srcpll", + "pdm_dclk", + "pdm_sysclk"; + pinctrl-names = "pdm_pins"; + pinctrl-0 = <&pdmin>; + /* mode 0~4, defalut:1 */ + filter_mode = <1>; + status = "okay"; + }; + spdifa:spdif@0 { + compatible = "amlogic, tm2-snd-spdif-a"; + #sound-dai-cells = <0>; + + clocks = <&clkc CLKID_MPLL1 + &clkc CLKID_FCLK_DIV4 + &clkaudio CLKID_AUDIO_GATE_SPDIFIN + &clkaudio CLKID_AUDIO_GATE_SPDIFOUT_A + &clkaudio CLKID_AUDIO_SPDIFIN + &clkaudio CLKID_AUDIO_SPDIFOUT_A>; + clock-names = "sysclk", "fixed_clk", "gate_spdifin", + "gate_spdifout", "clk_spdifin", "clk_spdifout"; + + interrupts = + ; + interrupt-names = "irq_spdifin"; + + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; + pinctrl-0 = <&spdifout_a>; + pinctrl-1 = <&spdifout_a_mute>; + + /* + * whether do asrc for pcm and resample a or b + * if raw data, asrc is disabled automatically + * 0: "Disable", + * 1: "Enable:32K", + * 2: "Enable:44K", + * 3: "Enable:48K", + * 4: "Enable:88K", + * 5: "Enable:96K", + * 6: "Enable:176K", + * 7: "Enable:192K", + */ + asrc_id = <0>; + auto_asrc = <3>; + + status = "okay"; + }; + + spdifb:spdif@1 { + compatible = "amlogic, tm2-snd-spdif-b"; + #sound-dai-cells = <0>; + + clocks = <&clkc CLKID_MPLL0 /*CLKID_HIFI_PLL*/ + &clkaudio CLKID_AUDIO_GATE_SPDIFOUT_B + &clkaudio CLKID_AUDIO_SPDIFOUT_B>; + clock-names = "sysclk", + "gate_spdifout", "clk_spdifout"; + + status = "okay"; + }; + + extn:extn { + compatible = "amlogic, snd-extn"; + #sound-dai-cells = <0>; + + + interrupts = + ; + interrupt-names = "irq_frhdmirx"; + + status = "okay"; + }; + + earc:earc { + compatible = "amlogic, tm2-snd-earc"; + #sound-dai-cells = <0>; + + clocks = < &clkaudio CLKID_EARCRX_CMDC + &clkaudio CLKID_EARCRX_DMAC + &clkc CLKID_FCLK_DIV5 + &clkc CLKID_FCLK_DIV3 + &clkaudio CLKID_EARCTX_CMDC + &clkaudio CLKID_EARCTX_DMAC + &clkc CLKID_FCLK_DIV5 + &clkc CLKID_FCLK_DIV3 + >; + clock-names = + "rx_cmdc", + "rx_dmac", + "rx_cmdc_srcpll", + "rx_dmac_srcpll", + "tx_cmdc", + "tx_dmac", + "tx_cmdc_srcpll", + "tx_dmac_srcpll"; + interrupts = < + GIC_SPI 88 IRQ_TYPE_EDGE_RISING + GIC_SPI 87 IRQ_TYPE_EDGE_RISING + >; + interrupt-names = "rx_cmdc", "rx_dmac"; + + status = "okay"; + }; + + aed:effect { + compatible = "amlogic, snd-effect-v2"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_EQDRC + &clkc CLKID_FCLK_DIV5 + &clkaudio CLKID_AUDIO_EQDRC>; + clock-names = "gate", "srcpll", "eqdrc"; + + /* + * 0:tdmout_a + * 1:tdmout_b + * 2:tdmout_c + * 3:spdifout + * 4:spdifout_b + */ + eqdrc_module = <0>; + /* max 0xf, each bit for one lane, usually one lane */ + lane_mask = <0x1>; + /* max 0xff, each bit for one channel */ + channel_mask = <0xff>; + + status = "disable"; + }; + + asrca: resample@0 { + compatible = "amlogic, tl1-resample-a"; + clocks = <&clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_MCLK_A + &clkaudio CLKID_AUDIO_RESAMPLE_A>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + /*same with toddr_src + * TDMIN_A, 0 + * TDMIN_B, 1 + * TDMIN_C, 2 + * SPDIFIN, 3 + * PDMIN, 4 + * NONE, + * TDMIN_LB, 6 + * LOOPBACK, 7 + */ + resample_module = <3>; + + status = "disabled"; + }; + + asrcb: resample@1 { + compatible = "amlogic, tl1-resample-b"; + + clocks = <&clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_MCLK_F + &clkaudio CLKID_AUDIO_RESAMPLE_B>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + + /*same with toddr_src + * TDMIN_A, 0 + * TDMIN_B, 1 + * TDMIN_C, 2 + * SPDIFIN, 3 + * PDMIN, 4 + * NONE, + * TDMIN_LB, 6 + * LOOPBACK, 7 + */ + resample_module = <3>; + + status = "disabled"; + }; + + vad:vad { + compatible = "amlogic, snd-vad"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_TOVAD + &clkc CLKID_FCLK_DIV5 + &clkaudio CLKID_AUDIO_VAD>; + clock-names = "gate", "pll", "clk"; + + interrupts = ; + interrupt-names = "irq_wakeup", "irq_frame_sync"; + + /* + * Data src sel: + * 0: tdmin_a; + * 1: tdmin_b; + * 2: tdmin_c; + * 3: spdifin; + * 4: pdmin; + * 5: loopback_b; + * 6: tdmin_lb; + * 7: loopback_a; + */ + src = <4>; + + /* + * deal with hot word in user space or kernel space + * 0: in user space + * 1: in kernel space + */ + level = <1>; + + status = "disabled"; + }; +}; /* end of audiobus */ + +&pinctrl_periphs { + /* audio pin mux */ + + tdma_mclk: tdma_mclk { + mux { /* GPIOZ_0 */ + groups = "mclk0_z"; + function = "mclk0"; + }; + }; + + tdmout_a: tdmout_a { + mux { /* GPIOZ_1, GPIOZ_2, GPIOZ_3*/ + groups = "tdma_sclk_z", + "tdma_fs_z", + "tdma_dout0_z"; + function = "tdma_out"; + bias-pull-down; + }; + }; + + tdmin_a: tdmin_a { + mux { /* GPIOH_11, GPIOH_12 */ + groups = "tdma_din0_h", + "tdma_din1_h"; + function = "tdma_in"; + }; + }; + + tdmout_c: tdmout_c { + mux { /* GPIODV_7, GPIODV_8, GPIODV_9 */ + groups = "tdmc_sclk", + "tdmc_fs", + "tdmc_dout0"; + function = "tdmc_out"; + }; + }; + + tdmin_c: tdmin_c { + mux { /* GPIODV_10 */ + groups = "tdmc_din1"; + function = "tdmc_in"; + }; + }; + + spdifin_a: spdifin_a { + mux { /* GPIODV_5 */ + groups = "spdif_in"; + function = "spdif_in"; + }; + }; + + spdifout_a: spdifout_a { + mux { /* GPIODV_4 */ + groups = "spdif_out_dv4"; + function = "spdif_out"; + }; + }; + + spdifout_a_mute: spdifout_a_mute { + mux { /* GPIODV_4 */ + groups = "GPIODV_4"; + function = "gpio_periphs"; + }; + }; + + pdmin: pdmin { + mux { /* GPIOZ_7, GPIOZ_8, pdm_din2_z4 */ + groups = "pdm_dclk_z", + "pdm_din0_z", + "pdm_din2_z4"; + function = "pdm"; + }; + }; + + /*backlight*/ + bl_pwm_vs_on_pins:bl_pwm_vs_on_pin { + mux { + groups = "pwm_vs_z5"; + function = "pwm_vs"; + }; + }; + bl_pwm_off_pins:bl_pwm_off_pin { + mux { + groups = "GPIOZ_5"; + function = "gpio_periphs"; + output-low; + }; + }; + bl_pwm_combo_0_vs_on_pins:bl_pwm_combo_0_vs_on_pin { + mux { + groups = "pwm_vs_z5"; + function = "pwm_vs"; + }; + }; + bl_pwm_combo_1_vs_on_pins:bl_pwm_combo_1_vs_on_pin { + mux { + groups = "pwm_vs_z6"; + function = "pwm_vs"; + }; + }; + bl_pwm_combo_off_pins:bl_pwm_combo_off_pin { + mux { + groups = "GPIOZ_5", + "GPIOZ_6"; + function = "gpio_periphs"; + output-low; + }; + }; + +}; /* end of pinctrl_periphs */ + +&audio_data{ + status = "okay"; +}; + +&i2c2 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&i2c2_z_pins>; + clock-frequency = <400000>; + + tas5805: tas5805@5c { + compatible = "ti,tas5805"; + #sound-dai-cells = <0>; + codec_name = "tas5805"; + reg = <0x2e>; + reset_pin = <&gpio_ao GPIOAO_6 GPIO_ACTIVE_HIGH>; + status = "okay"; + }; + + ad82584f: ad82584f@62 { + compatible = "ESMT, ad82584f"; + #sound-dai-cells = <0>; + reg = <0x31>; + status = "disabled"; + reset_pin = <&gpio_ao GPIOAO_6 0>; + }; + +}; + +&sd_emmc_c { + status = "okay"; + emmc { + caps = "MMC_CAP_8_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + "MMC_CAP_1_8V_DDR", + "MMC_CAP_HW_RESET", + "MMC_CAP_ERASE", + "MMC_CAP_CMD23"; + caps2 = "MMC_CAP2_HS200"; + /* "MMC_CAP2_HS400";*/ + f_min = <400000>; + f_max = <200000000>; + }; +}; + + + +&spifc { + status = "disabled"; + spi-nor@0 { + cs_gpios = <&gpio BOOT_13 GPIO_ACTIVE_HIGH>; + }; +}; + +&slc_nand { + status = "disabled"; + plat-names = "bootloader", "nandnormal"; + plat-num = <2>; + plat-part-0 = <&bootloader>; + plat-part-1 = <&nandnormal>; + bootloader: bootloader{ + enable_pad = "ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <1>; + part_num = <0>; + rb_detect = <1>; + }; + nandnormal: nandnormal{ + enable_pad = "ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + plane_mode = "twoplane"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <2>; + part_num = <3>; + partition = <&nand_partitions>; + rb_detect = <1>; + }; + nand_partitions:nand_partition{ + /* + * if bl_mode is 1, tpl size was generate by + * fip_copies * fip_size which + * will not skip bad when calculating + * the partition size; + * + * if bl_mode is 0, + * tpl partition must be comment out. + */ + tpl{ + offset=<0x0 0x0>; + size=<0x0 0x0>; + }; + logo{ + offset=<0x0 0x0>; + size=<0x0 0x200000>; + }; + recovery{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + boot{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + system{ + offset=<0x0 0x0>; + size=<0x0 0x4000000>; + }; + data{ + offset=<0xffffffff 0xffffffff>; + size=<0x0 0x0>; + }; + }; +}; + +ðmac { + status = "okay"; + pinctrl-names = "internal_eth_pins"; + pinctrl-0 = <&internal_eth_pins>; + mc_val = <0x4be04>; + + internal_phy=<1>; +}; + +&uart_A { + status = "okay"; +}; + +&dwc3 { + status = "okay"; +}; + +&usb2_phy_v2 { + status = "okay"; + portnum = <3>; +}; + +&usb3_phy_v2 { + status = "okay"; + portnum = <2>; + portconfig-30 = <1>; + portconfig-31 = <1>; +}; + +&usb_otg { + status = "okay"; + otg = <0>; +}; + +&dwc2_a { + status = "okay"; + /** 0: normal, 1: otg+dwc3 host only, 2: otg+dwc3 device only*/ + controller-type = <1>; +}; + +&pcie_A { + reset-gpio = <&gpio_ao GPIOAO_4 GPIO_ACTIVE_HIGH>; + status = "disable"; +}; + +&pcie_B { + /* ab311 only pcie a, no pcie b */ + status = "disable"; +}; + +&spicc0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&spicc0_pins_h>; + cs-gpios = <&gpio GPIOH_20 0>; +}; + +&meson_fb { + status = "okay"; + display_size_default = <1920 1080 1920 2160 32>; + mem_size = <0x00800000 0x1980000 0x100000 0x100000 0x800000>; + logo_addr = "0x7f800000"; + mem_alloc = <0>; + pxp_mode = <0>; /** 0:normal mode 1:pxp mode */ +}; + +&pwm_AO_cd { + status = "okay"; +}; + +&pwm_cd { + status = "okay"; +}; + +&saradc { + status = "okay"; +}; + +&i2c1 { + status = "okay"; + clock-frequency = <300000>; + pinctrl-names="default"; + pinctrl-0=<&i2c1_h_pins>; + + lcd_extern_i2c0: lcd_extern_i2c@0 { + compatible = "lcd_ext, i2c"; + dev_name = "i2c_T5800Q"; + reg = <0x1c>; + status = "okay"; + }; + + lcd_extern_i2c1: lcd_extern_i2c@1 { + compatible = "lcd_ext, i2c"; + dev_name = "i2c_ANX6862"; + reg = <0x20>; + status = "okay"; + }; + + lcd_extern_i2c2: lcd_extern_i2c@2 { + compatible = "lcd_ext, i2c"; + dev_name = "i2c_ANX7911"; + reg = <0x74>; + status = "okay"; + }; +}; + +&pwm_ab { + status = "okay"; +}; + +&pwm_cd { + status = "okay"; +}; + +&efuse { + status = "okay"; +}; diff --git a/arch/arm/boot/dts/amlogic/tm2_t962x3_ab309.dts b/arch/arm/boot/dts/amlogic/tm2_t962x3_ab309.dts new file mode 100644 index 000000000000..246c3c4333f1 --- /dev/null +++ b/arch/arm/boot/dts/amlogic/tm2_t962x3_ab309.dts @@ -0,0 +1,1854 @@ +/* + * arch/arm/boot/dts/amlogic/tm2_t962x3_ab309.dts + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +/dts-v1/; + +#include "mesontm2.dtsi" +#include "partition_mbox_normal.dtsi" +#include "mesontm2_t962x3_ab309-panel.dtsi" + +/ { + model = "Amlogic TM2 T962X3 AB309"; + amlogic-dt-id = "tm2_t962x3_ab309"; + compatible = "amlogic, tm2_t962x3_ab309"; + + aliases { + serial0 = &uart_AO; + serial1 = &uart_A; + serial2 = &uart_B; + serial3 = &uart_C; + serial4 = &uart_AO_B; + tsensor0 = &p_tsensor; + tsensor1 = &d_tsensor; + tsensor2 = &s_tsensor; + i2c0 = &i2c0; + i2c1 = &i2c1; + i2c2 = &i2c2; + i2c3 = &i2c3; + i2c4 = &i2c_AO; + }; + + memory@00000000 { + device_type = "memory"; + linux,usable-memory = <0x0 0x80000000>; + }; + + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + /* global autoconfigured region for contiguous allocations */ + ramoops@0x07400000 { + compatible = "ramoops"; + reg = <0x07400000 0x00100000>; + record-size = <0x8000>; + console-size = <0x8000>; + ftrace-size = <0x20000>; + }; + + secmon_reserved: linux,secmon { + compatible = "shared-dma-pool"; + reusable; + size = <0x400000>; + alignment = <0x400000>; + alloc-ranges = <0x05000000 0x400000>; + }; + + logo_reserved:linux,meson-fb { + compatible = "shared-dma-pool"; + reusable; + size = <0x800000>; + alignment = <0x400000>; + alloc-ranges = <0x7f800000 0x800000>; + }; + + lcd_tcon_reserved:linux,lcd_tcon { + compatible = "shared-dma-pool"; + reusable; + size = <0xc00000>; + alignment = <0x400000>; + alloc-ranges = <0x7ec00000 0xc00000>; + }; + + codec_mm_cma:linux,codec_mm_cma { + compatible = "shared-dma-pool"; + reusable; + /* ion_codec_mm max can alloc size 80M*/ + size = <0x13400000>; + alignment = <0x400000>; + linux,contiguous-region; + }; + + /* codec shared reserved */ + codec_mm_reserved:linux,codec_mm_reserved { + compatible = "amlogic, codec-mm-reserved"; + size = <0x0>; + alignment = <0x100000>; + //no-map; + }; + + ion_cma_reserved:linux,ion-dev { + compatible = "shared-dma-pool"; + reusable; + size = <0x8000000>; + alignment = <0x400000>; + }; + + /* vdin0 CMA pool */ + //vdin0_cma_reserved:linux,vdin0_cma { + // compatible = "shared-dma-pool"; + // reusable; + /* 3840x2160x4x4 ~=128 M */ + // size = <0xc400000>; + // alignment = <0x400000>; + //}; + + /* vdin1 CMA pool */ + vdin1_cma_reserved:linux,vdin1_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16 M */ + size = <0x1400000>; + alignment = <0x400000>; + }; + + /*demod_reserved:linux,demod { + * compatible = "amlogic, demod-mem"; + * size = <0x800000>; //8M //100m 0x6400000 + * alloc-ranges = <0x0 0x30000000>; + * //multi-use; + * //no-map; + *}; + */ + + demod_cma_reserved:linux,demod_cma { + compatible = "shared-dma-pool"; + reusable; + /* 8M */ + size = <0x0800000>; + alignment = <0x400000>; + }; + + /*di CMA pool */ + di_cma_reserved:linux,di_cma { + compatible = "shared-dma-pool"; + reusable; + /* buffer_size = 3621952(yuv422 8bit) + * | 4736064(yuv422 10bit) + * | 4074560(yuv422 10bit full pack mode) + * 10x3621952=34.6M(0x23) support 8bit + * 10x4736064=45.2M(0x2e) support 12bit + * 10x4074560=40M(0x28) support 10bit + */ + size = <0x02800000>; + alignment = <0x400000>; + }; + + /* for hdmi rx emp use */ + hdmirx_emp_cma_reserved:linux,emp_cma { + compatible = "shared-dma-pool"; + /*linux,phandle = <5>;*/ + reusable; + /* 4M for emp to ddr */ + /* 32M for tmds to ddr */ + size = <0x400000>; + alignment = <0x400000>; + /* alloc-ranges = <0x400000 0x2000000>; */ + }; + + /* POST PROCESS MANAGER */ + ppmgr_reserved:linux,ppmgr { + compatible = "amlogic, ppmgr_memory"; + size = <0x0>; + }; + + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + }; /* end of reserved-memory */ + galcore { + status = "okay"; + }; + codec_mm { + compatible = "amlogic, codec, mm"; + status = "okay"; + memory-region = <&codec_mm_cma &codec_mm_reserved>; + }; + + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + + ppmgr { + compatible = "amlogic, ppmgr"; + memory-region = <&ppmgr_reserved>; + status = "okay"; + }; + + deinterlace { + compatible = "amlogic, deinterlace"; + status = "okay"; + /* 0:use reserved; 1:use cma; 2:use cma as reserved */ + flag_cma = <1>; + //memory-region = <&di_reserved>; + memory-region = <&di_cma_reserved>; + interrupts = <0 46 1 + 0 40 1>; + interrupt-names = "pre_irq", "post_irq"; + clocks = <&clkc CLKID_VPU_CLKB_TMP_COMP>, + <&clkc CLKID_VPU_CLKB_COMP>; + clock-names = "vpu_clkb_tmp_composite", + "vpu_clkb_composite"; + clock-range = <334 667>; + /* buffer-size = <3621952>;(yuv422 8bit) */ + buffer-size = <4074560>;/*yuv422 fullpack*/ + /* reserve-iomap = "true"; */ + /* if enable nr10bit, set nr10bit-support to 1 */ + post-wr-support = <1>; + nr10bit-support = <1>; + nrds-enable = <1>; + pps-enable = <1>; + }; + + vout { + compatible = "amlogic, vout"; + status = "okay"; + fr_auto_policy = <0>; + }; + + /* Audio Related start */ + pdm_codec:dummy { + #sound-dai-cells = <0>; + compatible = "amlogic, pdm_dummy_codec"; + status = "okay"; + }; + + dummy_codec:dummy { + #sound-dai-cells = <0>; + compatible = "amlogic, aml_dummy_codec"; + status = "okay"; + }; + + tl1_codec:codec { + #sound-dai-cells = <0>; + compatible = "amlogic, tl1_acodec"; + status = "okay"; + reg = <0xff632000 0x1c>; + tdmout_index = <0>; + tdmin_index = <0>; + dat1_ch_sel = <1>; + }; + + aml_dtv_demod { + compatible = "amlogic, ddemod-tl1"; + dev_name = "aml_dtv_demod"; + status = "okay"; + + //pinctrl-names="dtvdemod_agc"; + //pinctrl-0=<&dtvdemod_agc>; + + clocks = <&clkc CLKID_DAC_CLK>; + clock-names = "vdac_clk_gate"; + + reg = <0xff650000 0x4000 /*dtv demod base*/ + 0xff63c000 0x2000 /*hiu reg base*/ + 0xff800000 0x1000 /*io_aobus_base*/ + 0xffd01000 0x1000 /*reset*/ + >; + + /*move from dvbfe*/ + dtv_demod0_mem = <0>; // need move to aml_dtv_demod ? + spectrum = <1>; + cma_flag = <1>; + cma_mem_size = <8>; + memory-region = <&demod_cma_reserved>;//<&demod_reserved>; + }; + + auge_sound { + compatible = "amlogic, tm2-sound-card"; + aml-audio-card,name = "AML-AUGESOUND"; + + avout_mute-gpios = <&gpio GPIODV_3 GPIO_ACTIVE_HIGH>; + + aml-audio-card,dai-link@0 { + format = "i2s"; + mclk-fs = <256>; + continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdma>; + frame-master = <&tdma>; + /* slave mode */ + /* + * bitclock-master = <&tdmacodec>; + * frame-master = <&tdmacodec>; + */ + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-i2s"; + tdmacpu: cpu { + sound-dai = <&tdma>; + dai-tdm-slot-tx-mask = + <1 1>; + dai-tdm-slot-rx-mask = + <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmacodec: codec { + //sound-dai = <&dummy_codec>; + sound-dai = ; + }; + }; + + aml-audio-card,dai-link@1 { + + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdmb>; + frame-master = <&tdmb>; + /* slave mode */ + //bitclock-master = <&tdmbcodec>; + //frame-master = <&tdmbcodec>; + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-pcm"; + cpu { + sound-dai = <&tdmb>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + /* + * dai-tdm-slot-tx-mask = + * <1 1 1 1 1 1 1 1>; + * dai-tdm-slot-rx-mask = + * <1 1 1 1 1 1 1 1>; + * dai-tdm-slot-num = <8>; + */ + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmbcodec: codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@2 { + + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdmc>; + frame-master = <&tdmc>; + /* slave mode */ + //bitclock-master = <&tdmccodec>; + //frame-master = <&tdmccodec>; + /* suffix-name, sync with android audio hal used for */ + //suffix-name = "alsaPORT-tdm"; + cpu { + sound-dai = <&tdmc>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmccodec: codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@3 { + mclk-fs = <64>; + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-pdm"; + cpu { + sound-dai = <&pdm>; + }; + codec { + sound-dai = <&pdm_codec>; + }; + }; + + aml-audio-card,dai-link@4 { + mclk-fs = <128>; + continuous-clock; + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-spdif"; + cpu { + sound-dai = <&spdifa>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@5 { + mclk-fs = <128>; + suffix-name = "alsaPORT-spdifb"; + cpu { + sound-dai = <&spdifb>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@6 { + mclk-fs = <256>; + suffix-name = "alsaPORT-tv"; + cpu { + sound-dai = <&extn>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + aml-audio-card,dai-link@7 { + mclk-fs = <256>; + suffix-name = "alsaPORT-earc"; + cpu { + sound-dai = <&earc>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + }; + + /* Audio Related end */ + dvb { + compatible = "amlogic, dvb"; + status = "okay"; + fe0_mode = "internal"; + fe0_tuner = <&tuner>; + + /*"parallel","serial","disable"*/ + ts2 = "parallel"; + ts2_control = <0>; + ts2_invert = <0>; + interrupts = <0 23 1 + 0 5 1 + 0 53 1 + 0 19 1 + 0 25 1 + 0 17 1>; + interrupt-names = "demux0_irq", + "demux1_irq", + "demux2_irq", + "dvr0_irq", + "dvr1_irq", + "dvr2_irq"; + clocks = <&clkc CLKID_DEMUX + &clkc CLKID_ASYNC_FIFO + &clkc CLKID_AHB_ARB0 + /*&clkc CLKID_DOS_PARSER>;*/ + &clkc CLKID_U_PARSER>; + clock-names = "demux", "asyncfifo", "ahbarb0", "uparsertop"; + }; + + tvafe_avin_detect { + compatible = "amlogic, tl1_tvafe_avin_detect"; + status = "okay"; + device_mask = <1>;/*bit0:ch1;bit1:ch2*/ + interrupts = <0 12 1>, + <0 13 1>; + }; + + amlvecm { + compatible = "amlogic, vecm-tl1"; + dev_name = "aml_vecm"; + status = "okay"; + gamma_en = <1>;/*1:enabel ;0:disable*/ + wb_en = <1>;/*1:enabel ;0:disable*/ + cm_en = <0>;/*1:enabel ;0:disable*/ + wb_sel = <1>;/*1:mtx ;0:gainoff*/ + vlock_en = <1>;/*1:enable;0:disable*/ + vlock_mode = <0x4>; + /* vlock work mode: + *bit0:auto ENC + *bit1:auto PLL + *bit2:manual PLL + *bit3:manual ENC + *bit4:manual soft ENC + *bit5:manual MIX PLL ENC + */ + vlock_pll_m_limit = <1>; + vlock_line_limit = <3>; + }; + + amdolby_vision { + compatible = "amlogic, dolby_vision_tm2"; + dev_name = "aml_amdolby_vision_driver"; + status = "okay"; + tv_mode = <1>;/*1:enabel ;0:disable*/ + }; + + vdin@0 { + compatible = "amlogic, vdin"; + /*memory-region = <&vdin0_cma_reserved>;*/ + status = "okay"; + /*bit0:(1:share with codec_mm;0:cma alone) + *bit8:(1:alloc in discontinus way;0:alone in continuous way) + */ + flag_cma = <0x101>; + /*MByte, if 10bit disable: 64M(YUV422), + *if 10bit enable: 64*1.5 = 96M(YUV422) + *if support 4K2K-YUV444-10bit-WR:3840*2160*4*4 ~= 128M + *if support 4K2K-YUV422-10bit-wr:3840*2160*3*4 ~= 96M + *if support 4K2K-YUV422-8BIT-WR:3840*2160*2*4 ~= 64M + *if support 1080p-YUV422-8BIT-WR:1920*1080*2*4 ~= 16M + */ + cma_size = <190>; + interrupts = <0 83 1>; + rdma-irq = <2>; + clocks = <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_VDIN_MEAS_COMP>; + clock-names = "fclk_div5", "cts_vdin_meas_clk"; + vdin_id = <0>; + /*vdin write mem color depth support: + * bit0:support 8bit + * bit1:support 9bit + * bit2:support 10bit + * bit3:support 12bit + * bit4:support yuv422 10bit full pack mode (from txl new add) + * bit8:use 8bit at 4k_50/60hz_10bit + * bit9:use 10bit at 4k_50/60hz_10bit + */ + tv_bit_mode = <0x215>; + /* afbce_bit_mode: (amlogic frame buff compression encoder) + * bit 0~3: + * 0 -- normal mode, not use afbce + * 1 -- use afbce non-mmu mode + * 2 -- use afbce mmu mode + * bit 4: + * 0 -- afbce compression-lossy disable + * 1 -- afbce compression-lossy enable + */ + afbce_bit_mode = <0>; + }; + + vdin@1 { + compatible = "amlogic, vdin"; + memory-region = <&vdin1_cma_reserved>; + status = "okay"; + /*bit0:(1:share with codec_mm;0:cma alone) + *bit8:(1:alloc in discontinus way;0:alone in continuous way) + */ + flag_cma = <0>; + interrupts = <0 85 1>; + rdma-irq = <4>; + clocks = <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_VDIN_MEAS_COMP>; + clock-names = "fclk_div5", "cts_vdin_meas_clk"; + vdin_id = <1>; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + */ + tv_bit_mode = <0x15>; + }; + + tvafe { + compatible = "amlogic, tvafe-tl1"; + /*memory-region = <&tvafe_cma_reserved>;*/ + status = "okay"; + flag_cma = <1>;/*1:share with codec_mm;0:cma alone*/ + cma_size = <5>;/*MByte*/ + reg = <0xff654000 0x2000>;/*tvafe reg base*/ + reserve-iomap = "true"; + tvafe_id = <0>; + //pinctrl-names = "default"; + /*!!particular sequence, no more and no less!!!*/ + tvafe_pin_mux = < + 3 /* TVAFE_CVBS_IN2, CVBS_IN0 = 0 */ + 1 /* TVAFE_CVBS_IN0, CVBS_IN1 */ + 2 /* TVAFE_CVBS_IN1, CVBS_IN2 */ + 4 /* TVAFE_CVBS_IN3, CVBS_IN3 */ + >; + clocks = <&clkc CLKID_DAC_CLK>; + clock-names = "vdac_clk_gate"; + }; + + vbi { + compatible = "amlogic, vbi"; + status = "okay"; + interrupts = <0 83 1>; + }; + + cvbsout { + compatible = "amlogic, cvbsout-tl1"; + status = "disabled"; + clocks = <&clkc CLKID_VCLK2_ENCI + &clkc CLKID_VCLK2_VENCI0 + &clkc CLKID_VCLK2_VENCI1 + &clkc CLKID_DAC_CLK>; + clock-names = "venci_top_gate", + "venci_0_gate", + "venci_1_gate", + "vdac_clk_gate"; + /* clk path */ + /* 0:vid_pll vid2_clk */ + /* 1:gp0_pll vid2_clk */ + /* 2:vid_pll vid1_clk */ + /* 3:gp0_pll vid1_clk */ + clk_path = <0>; + + /* performance: reg_address, reg_value */ + /* tl1 */ + performance = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x8080 + 0x1b05 0xfd + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + performance_sarft = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x0 + 0x1b05 0x9 + 0x1c59 0xfc48 + 0xffff 0x0>; /* ending flag */ + performance_revB_telecom = <0x1bf0 0x9 + 0x1b56 0x546 + 0x1b12 0x8080 + 0x1b05 0x9 + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + }; + + adc_keypad { + compatible = "amlogic, adc_keypad"; + status = "okay"; + key_name = "vol-", "vol+", "ch+", "ch-", + "menu", "source", "exit"; + key_num = <7>; + io-channels = <&saradc SARADC_CH2 &saradc SARADC_CH3>; + io-channel-names = "key-chan-2", "key-chan-3"; + key_chan = ; + key_code = <114 115 192 193 139 466 174>; + key_val = <0 143 266 389 0 143 266>; //val=voltage/1800mV*1023 + key_tolerance = <40 40 40 40 40 40 40>; + }; + + unifykey { + compatible = "amlogic, unifykey"; + status = "okay"; + + unifykey-num = <21>; + unifykey-index-0 = <&keysn_0>; + unifykey-index-1 = <&keysn_1>; + unifykey-index-2 = <&keysn_2>; + unifykey-index-3 = <&keysn_3>; + unifykey-index-4 = <&keysn_4>; + unifykey-index-5 = <&keysn_5>; + unifykey-index-6 = <&keysn_6>; + unifykey-index-7 = <&keysn_7>; + unifykey-index-8 = <&keysn_8>; + unifykey-index-9 = <&keysn_9>; + unifykey-index-10= <&keysn_10>; + unifykey-index-11 = <&keysn_11>; + unifykey-index-12 = <&keysn_12>; + unifykey-index-13 = <&keysn_13>; + unifykey-index-14 = <&keysn_14>; + unifykey-index-15 = <&keysn_15>; + unifykey-index-16 = <&keysn_16>; + unifykey-index-17 = <&keysn_17>; + unifykey-index-18 = <&keysn_18>; + unifykey-index-19 = <&keysn_19>; + unifykey-index-20 = <&keysn_20>; + + keysn_0: key_0{ + key-name = "usid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_1:key_1{ + key-name = "mac"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_2:key_2{ + key-name = "hdcp"; + key-device = "secure"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_3:key_3{ + key-name = "secure_boot_set"; + key-device = "efuse"; + key-permit = "write"; + }; + keysn_4:key_4{ + key-name = "mac_bt"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_5:key_5{ + key-name = "mac_wifi"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_6:key_6{ + key-name = "hdcp2_tx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_7:key_7{ + key-name = "hdcp2_rx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_8:key_8{ + key-name = "widevinekeybox"; + key-device = "secure"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_9:key_9{ + key-name = "deviceid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_10:key_10{ + key-name = "hdcp22_fw_private"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_11:key_11{ + key-name = "hdcp22_rx_private"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_12:key_12{ + key-name = "hdcp22_rx_fw"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_13:key_13{ + key-name = "hdcp14_rx"; + key-device = "normal"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_14:key_14{ + key-name = "prpubkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_15:key_15{ + key-name = "prprivkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_16:key_16{ + key-name = "lcd"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_17:key_17{ + key-name = "lcd_extern"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_18:key_18{ + key-name = "backlight"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_19:key_19{ + key-name = "lcd_tcon"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_20:key_20{ + key-name = "attestationkeybox";// attestation key + key-device = "secure"; + key-permit = "read","write","del"; + }; + }; /* End unifykey */ + + hdmirx { + compatible = "amlogic, hdmirx_tl1"; + #address-cells=<1>; + #size-cells=<1>; + memory-region = <&hdmirx_emp_cma_reserved>; + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&hdmirx_a_mux &hdmirx_b_mux + &hdmirx_c_mux>; + repeat = <0>; + interrupts = <0 41 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clkc CLKID_HDMIRX_MODET_COMP>, + <&clkc CLKID_HDMIRX_CFG_COMP>, + <&clkc CLKID_HDMIRX_ACR_COMP>, + <&clkc CLKID_HDMIRX_METER_COMP>, + <&clkc CLKID_HDMIRX_AXI_COMP>, + <&xtal>, + <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_FCLK_DIV7>, + <&clkc CLKID_HDCP22_SKP_COMP>, + <&clkc CLKID_HDCP22_ESM_COMP>; + // <&clkc CLK_AUD_PLL2FS>, + // <&clkc CLK_AUD_PLL4FS>, + // <&clkc CLK_AUD_OUT>; + clock-names = "hdmirx_modet_clk", + "hdmirx_cfg_clk", + "hdmirx_acr_ref_clk", + "cts_hdmirx_meter_clk", + "cts_hdmi_axi_clk", + "xtal", + "fclk_div5", + "fclk_div7", + "hdcp_rx22_skp", + "hdcp_rx22_esm"; + // "hdmirx_aud_pll2fs", + // "hdmirx_aud_pll4f", + // "clk_aud_out"; + hdmirx_id = <0>; + en_4k_2_2k = <0>; + hpd_low_cec_off = <1>; + /* bit4: enable feature, bit3~0: port number */ + disable_port = <0x0>; + /* MAP_ADDR_MODULE_CBUS */ + /* MAP_ADDR_MODULE_HIU */ + /* MAP_ADDR_MODULE_HDMIRX_CAPB3 */ + /* MAP_ADDR_MODULE_SEC_AHB */ + /* MAP_ADDR_MODULE_SEC_AHB2 */ + /* MAP_ADDR_MODULE_APB4 */ + /* MAP_ADDR_MODULE_TOP */ + reg = < 0x0 0x0 + 0xff63C000 0x2000 + 0xffe0d000 0x2000 + 0x0 0x0 + 0x0 0x0 + 0x0 0x0 + 0xff610000 0xa000>; + }; + + aocec: aocec { + compatible = "amlogic, aocec-tm2"; + /*device_name = "aocec";*/ + status = "okay"; + vendor_name = "Amlogic"; /* Max Chars: 8 */ + /* Refer to the following URL at: + * http://standards.ieee.org/develop/regauth/oui/oui.txt + */ + vendor_id = <0x000000>; + product_desc = "TM2"; /* Max Chars: 16 */ + cec_osd_string = "AML_TV"; /* Max Chars: 14 */ + port_num = <3>; + ee_cec; + /*cec_sel = <2>;*/ + arc_port_mask = <0x2>; + output = <1>; /*output port number*/ + interrupts = <0 205 1 + 0 199 1>; + interrupt-names = "hdmi_aocecb","hdmi_aocec"; + pinctrl-names = "default","hdmitx_aocecb","cec_pin_sleep"; + pinctrl-0=<&aoceca_mux>; + pinctrl-1=<&aocecb_mux>; + pinctrl-2=<&aoceca_mux>; + reg = <0xFF80023c 0x4 + 0xFF800000 0x400>; + reg-names = "ao_exit","ao"; + }; + + p_tsensor: p_tsensor@ff634800 { + compatible = "amlogic, r1p1-tsensor"; + status = "okay"; + reg = <0xff634800 0x50>, + <0xff800268 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 35 0>; + clocks = <&clkc CLKID_TS_CLK_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + d_tsensor: d_tsensor@ff634c00 { + compatible = "amlogic, r1p1-tsensor"; + status = "okay"; + reg = <0xff634c00 0x50>, + <0xff800230 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 36 0>; + clocks = <&clkc CLKID_TS_CLK_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + s_tsensor: s_tsensor@ff635000 { + compatible = "amlogic, r1p1-tsensor"; + status = "okay"; + reg = <0xff635000 0x50>, + <0xff80026c 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 38 0>; + clocks = <&clkc CLKID_TS_CLK_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + meson_cooldev: meson-cooldev@0 { + status = "okay"; + compatible = "amlogic, meson-cooldev"; + cooling_devices { + cpufreq_cool_cluster0 { + min_state = <1000000>; + dyn_coeff = <140>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "cpufreq_cool0"; + device_type = "cpufreq"; + }; + cpucore_cool_cluster0 { + min_state = <1>; + dyn_coeff = <0>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "cpucore_cool0"; + device_type = "cpucore"; + }; + gpufreq_cool { + min_state = <400>; + dyn_coeff = <140>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "gpufreq_cool0"; + device_type = "gpufreq"; + }; + gpucore_cool { + min_state = <1>; + dyn_coeff = <0>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "gpucore_cool0"; + device_type = "gpucore"; + }; + }; + cpufreq_cool0:cpufreq_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + cpucore_cool0:cpucore_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + gpufreq_cool0:gpufreq_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + gpucore_cool0:gpucore_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + };/*meson cooling devices end*/ + + thermal-zones { + pll_thermal: pll_thermal { + polling-delay = <1000>; + polling-delay-passive = <100>; + sustainable-power = <1322>; + thermal-sensors = <&p_tsensor 0>; + trips { + pswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + pcontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + phot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + pcritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + cooling-maps { + cpufreq_cooling_map { + trip = <&pcontrol>; + cooling-device = <&cpufreq_cool0 0 11>; + contribution = <1024>; + }; + cpucore_cooling_map { + trip = <&pcontrol>; + cooling-device = <&cpucore_cool0 0 4>; + contribution = <1024>; + }; + gpufreq_cooling_map { + trip = <&pcontrol>; + cooling-device = <&gpufreq_cool0 0 4>; + contribution = <1024>; + }; + }; + }; + ddr_thermal: ddr_thermal { + polling-delay = <2000>; + polling-delay-passive = <1000>; + sustainable-power = <1322>; + thermal-sensors = <&d_tsensor 1>; + trips { + dswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + dcontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + dhot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + dcritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + }; + sar_thermal: sar_thermal { + polling-delay = <2000>; + polling-delay-passive = <1000>; + sustainable-power = <1322>; + thermal-sensors = <&s_tsensor 2>; + trips { + sswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + scontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + shot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + scritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + }; + };/*thermal zone end*/ + + cpu_opp_table0: cpu_opp_table0 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <730000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <730000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <730000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <750000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <770000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <780000>; + }; + opp06 { + opp-hz = /bits/ 64 <1404000000>; + opp-microvolt = <790000>; + }; + opp07 { + opp-hz = /bits/ 64 <1500000000>; + opp-microvolt = <800000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <810000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <850000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <900000>; + }; + opp11 { + opp-hz = /bits/ 64 <1908000000>; + opp-microvolt = <950000>; + }; + }; + + cpufreq-meson { + compatible = "amlogic, cpufreq-meson"; + pinctrl-names = "default"; + pinctrl-0 = <&pwm_ao_d_pins3>; + status = "okay"; + }; + + tuner: tuner { + compatible = "amlogic, tuner"; + status = "okay"; + tuner_cur = <0>; /* default use tuner */ + tuner_num = <1>; /* tuner number, multi tuner support */ + tuner_name_0 = "mxl661_tuner"; + tuner_i2c_adap_0 = <&i2c0>; + tuner_i2c_addr_0 = <0x60>; + tuner_xtal_0 = <0>; /* 0: 16MHz, 1: 24MHz */ + tuner_xtal_mode_0 = <0>; + /* NO_SHARE_XTAL(0) + * SLAVE_XTAL_SHARE(3) + */ + tuner_xtal_cap_0 = <25>; /* when tuner_xtal_mode = 3, set 25 */ + }; + + atv-demod { + compatible = "amlogic, atv-demod"; + status = "okay"; + tuner = <&tuner>; + btsc_sap_mode = <1>; + /* pinctrl-names="atvdemod_agc_pins"; */ + /* pinctrl-0=<&atvdemod_agc_pins>; */ + reg = <0xff656000 0x2000 /* demod reg */ + 0xff63c000 0x2000 /* hiu reg */ + 0xff634000 0x2000 /* periphs reg */ + 0xff64a000 0x2000>; /* audio reg */ + reg_23cf = <0x88188832>; + /*default:0x88188832;r840 on haier:0x48188832*/ + }; + + sd_emmc_b: sd@ffe05000 { + status = "okay"; + compatible = "amlogic, meson-mmc-tm2"; + reg = <0xffe05000 0x800>; + interrupts = <0 190 1>; + + pinctrl-names = "sd_all_pins", + "sd_clk_cmd_pins", + "sd_1bit_pins"; + pinctrl-0 = <&sd_all_pins>; + pinctrl-1 = <&sd_clk_cmd_pins>; + pinctrl-2 = <&sd_1bit_pins>; + + clocks = <&clkc CLKID_SD_EMMC_B>, + <&clkc CLKID_SD_EMMC_B_P0_COMP>, + <&clkc CLKID_FCLK_DIV2>, + <&clkc CLKID_FCLK_DIV5>, + <&xtal>; + clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + + bus-width = <4>; + cap-sd-highspeed; + cap-mmc-highspeed; + max-frequency = <100000000>; + disable-wp; + sd { + pinname = "sd"; + ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED"; + //"MMC_CAP_NONREMOVABLE"; /**ptm debug */ + f_min = <400000>; + f_max = <200000000>; + max_req_size = <0x20000>; /**128KB*/ + no_sduart = <1>; + gpio_dat3 = <&gpio GPIOC_3 GPIO_ACTIVE_HIGH>; + jtag_pin = <&gpio GPIOC_0 GPIO_ACTIVE_HIGH>; + gpio_cd = <&gpio GPIOC_10 GPIO_ACTIVE_HIGH>; + card_type = <5>; + /* 3:sdio device(ie:sdio-wifi), + * 4:SD combo (IO+mem) card + */ + }; + }; + +}; /* end of / */ + +&i2c0 { + status = "okay"; + clock-frequency = <300000>; + pinctrl-names="default"; + pinctrl-0=<&i2c0_dv_pins>; +}; + +&audiobus { + tdma:tdm@0 { + compatible = "amlogic, tm2-snd-tdma"; + #sound-dai-cells = <0>; + + dai-tdm-lane-slot-mask-in = <1 0>; + dai-tdm-lane-slot-mask-out = <1 1 1 1>; + dai-tdm-clk-sel = <0>; + + clocks = <&clkaudio CLKID_AUDIO_MCLK_A + &clkc CLKID_MPLL0 + &clkc CLKID_MPLL1 + &clkaudio CLKID_AUDIO_SPDIFOUT_A>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; + + pinctrl-names = "tdm_pins"; + pinctrl-0 = ; + + /* + * 0: tdmout_a; + * 1: tdmout_b; + * 2: tdmout_c; + * 3: spdifout; + * 4: spdifout_b; + */ + samesource_sel = <3>; + + /* In for ACODEC_ADC */ + acodec_adc = <1>; + + status = "okay"; + + /* !!!For --TV platform-- ONLY */ + Channel_Mask { + /*i2s has 4 pins, 8channel, mux output*/ + Spdif_samesource_Channel_Mask = "i2s_2/3"; + }; + }; + + tdmb:tdm@1 { + compatible = "amlogic, tm2-snd-tdmb"; + #sound-dai-cells = <0>; + + dai-tdm-lane-slot-mask-in = <1 0 0 0>; + dai-tdm-lane-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <1>; + + clocks = <&clkaudio CLKID_AUDIO_MCLK_B + &clkc CLKID_MPLL1>; + clock-names = "mclk", "clk_srcpll"; + + status = "okay"; + }; + + tdmc:tdm@2 { + compatible = "amlogic, tm2-snd-tdmc"; + #sound-dai-cells = <0>; + + dai-tdm-lane-slot-mask-in = <1 0 0 0>; + dai-tdm-lane-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <2>; + + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + + pinctrl-names = "tdm_pins"; + pinctrl-0 = ; + + status = "okay"; + }; + + pdm:pdm { + compatible = "amlogic, tm2-snd-pdm"; + #sound-dai-cells = <0>; + clocks = <&clkaudio CLKID_AUDIO_GATE_PDM + &clkc CLKID_FCLK_DIV3 + &clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_PDMIN0 + &clkaudio CLKID_AUDIO_PDMIN1>; + clock-names = "gate", + "sysclk_srcpll", + "dclk_srcpll", + "pdm_dclk", + "pdm_sysclk"; + pinctrl-names = "pdm_pins"; + pinctrl-0 = <&pdmin>; + /* mode 0~4, defalut:1 */ + filter_mode = <1>; + status = "okay"; + }; + spdifa:spdif@0 { + compatible = "amlogic, tm2-snd-spdif-a"; + #sound-dai-cells = <0>; + + clocks = <&clkc CLKID_MPLL1 + &clkc CLKID_FCLK_DIV4 + &clkaudio CLKID_AUDIO_GATE_SPDIFIN + &clkaudio CLKID_AUDIO_GATE_SPDIFOUT_A + &clkaudio CLKID_AUDIO_SPDIFIN + &clkaudio CLKID_AUDIO_SPDIFOUT_A>; + clock-names = "sysclk", "fixed_clk", "gate_spdifin", + "gate_spdifout", "clk_spdifin", "clk_spdifout"; + + interrupts = + ; + interrupt-names = "irq_spdifin"; + + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; + + pinctrl-0 = <&spdifout_a &spdifin_a>; + pinctrl-1 = <&spdifout_a_mute>; + + /* + * whether do asrc for pcm and resample a or b + * if raw data, asrc is disabled automatically + * 0: "Disable", + * 1: "Enable:32K", + * 2: "Enable:44K", + * 3: "Enable:48K", + * 4: "Enable:88K", + * 5: "Enable:96K", + * 6: "Enable:176K", + * 7: "Enable:192K", + */ + asrc_id = <0>; + auto_asrc = <3>; + + status = "okay"; + }; + + spdifb:spdif@1 { + compatible = "amlogic, tm2-snd-spdif-b"; + #sound-dai-cells = <0>; + + clocks = <&clkc CLKID_MPLL0 /*CLKID_HIFI_PLL*/ + &clkaudio CLKID_AUDIO_GATE_SPDIFOUT_B + &clkaudio CLKID_AUDIO_SPDIFOUT_B>; + clock-names = "sysclk", + "gate_spdifout", "clk_spdifout"; + + status = "okay"; + }; + + extn:extn { + compatible = "amlogic, snd-extn"; + #sound-dai-cells = <0>; + + + interrupts = + ; + interrupt-names = "irq_frhdmirx"; + + status = "okay"; + }; + + earc:earc { + compatible = "amlogic, tm2-snd-earc"; + #sound-dai-cells = <0>; + + clocks = < &clkaudio CLKID_EARCRX_CMDC + &clkaudio CLKID_EARCRX_DMAC + &clkc CLKID_FCLK_DIV5 + &clkc CLKID_FCLK_DIV3 + &clkaudio CLKID_EARCTX_CMDC + &clkaudio CLKID_EARCTX_DMAC + &clkc CLKID_FCLK_DIV5 + &clkc CLKID_FCLK_DIV3 + >; + clock-names = + "rx_cmdc", + "rx_dmac", + "rx_cmdc_srcpll", + "rx_dmac_srcpll", + "tx_cmdc", + "tx_dmac", + "tx_cmdc_srcpll", + "tx_dmac_srcpll"; + interrupts = < + GIC_SPI 88 IRQ_TYPE_EDGE_RISING + GIC_SPI 87 IRQ_TYPE_EDGE_RISING + >; + interrupt-names = "rx_cmdc", "rx_dmac"; + + status = "okay"; + }; + + aed:effect { + compatible = "amlogic, snd-effect-v2"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_EQDRC + &clkc CLKID_FCLK_DIV5 + &clkaudio CLKID_AUDIO_EQDRC>; + clock-names = "gate", "srcpll", "eqdrc"; + + /* + * 0:tdmout_a + * 1:tdmout_b + * 2:tdmout_c + * 3:spdifout + * 4:spdifout_b + */ + eqdrc_module = <0>; + /* max 0xf, each bit for one lane, usually one lane */ + lane_mask = <0x1>; + /* max 0xff, each bit for one channel */ + channel_mask = <0xff>; + + status = "disable"; + }; + + asrca: resample@0 { + compatible = "amlogic, tl1-resample-a"; + clocks = <&clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_MCLK_A + &clkaudio CLKID_AUDIO_RESAMPLE_A>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + /*same with toddr_src + * TDMIN_A, 0 + * TDMIN_B, 1 + * TDMIN_C, 2 + * SPDIFIN, 3 + * PDMIN, 4 + * NONE, + * TDMIN_LB, 6 + * LOOPBACK, 7 + */ + resample_module = <3>; + + status = "disabled"; + }; + + asrcb: resample@1 { + compatible = "amlogic, tl1-resample-b"; + + clocks = <&clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_MCLK_F + &clkaudio CLKID_AUDIO_RESAMPLE_B>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + + /*same with toddr_src + * TDMIN_A, 0 + * TDMIN_B, 1 + * TDMIN_C, 2 + * SPDIFIN, 3 + * PDMIN, 4 + * NONE, + * TDMIN_LB, 6 + * LOOPBACK, 7 + */ + resample_module = <3>; + + status = "disabled"; + }; + + vad:vad { + compatible = "amlogic, snd-vad"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_TOVAD + &clkc CLKID_FCLK_DIV5 + &clkaudio CLKID_AUDIO_VAD>; + clock-names = "gate", "pll", "clk"; + + interrupts = ; + interrupt-names = "irq_wakeup", "irq_frame_sync"; + + /* + * Data src sel: + * 0: tdmin_a; + * 1: tdmin_b; + * 2: tdmin_c; + * 3: spdifin; + * 4: pdmin; + * 5: loopback_b; + * 6: tdmin_lb; + * 7: loopback_a; + */ + src = <4>; + + /* + * deal with hot word in user space or kernel space + * 0: in user space + * 1: in kernel space + */ + level = <1>; + + status = "disabled"; + }; +}; /* end of audiobus */ + +&pinctrl_periphs { + /* audio pin mux */ + + tdma_mclk: tdma_mclk { + mux { /* GPIOZ_0 */ + groups = "mclk0_z"; + function = "mclk0"; + }; + }; + + tdmout_a: tdmout_a { + mux { /* GPIOZ_1, GPIOZ_2, GPIOZ_3, GPIOZ_5, GPIOZ_6 */ + groups = "tdma_sclk_z", + "tdma_fs_z", + "tdma_dout0_z", + "tdma_dout2_z", + "tdma_dout3_z"; + function = "tdma_out"; + bias-pull-down; + }; + }; + + tdmin_a: tdmin_a { + mux { /* GPIOZ_9 */ + groups = "tdma_din2_z"; + function = "tdma_in"; + }; + }; + + tdmout_c: tdmout_c { + mux { /* GPIODV_7, GPIODV_8, GPIODV_9 */ + groups = "tdmc_sclk", + "tdmc_fs", + "tdmc_dout0"; + function = "tdmc_out"; + }; + }; + + tdmin_c: tdmin_c { + mux { /* GPIODV_10 */ + groups = "tdmc_din1"; + function = "tdmc_in"; + }; + }; + + spdifin_a: spdifin_a { + mux { /* GPIODV_5 */ + groups = "spdif_in"; + function = "spdif_in"; + }; + }; + + spdifout_a: spdifout_a { + mux { /* GPIODV_4 */ + groups = "spdif_out_dv4"; + function = "spdif_out"; + }; + }; + + spdifout_a_mute: spdifout_a_mute { + mux { /* GPIODV_4 */ + groups = "GPIODV_4"; + function = "gpio_periphs"; + }; + }; + + pdmin: pdmin { + mux { /* GPIOZ_7, GPIOZ_8, pdm_din2_z4 */ + groups = "pdm_dclk_z", + "pdm_din0_z", + "pdm_din2_z4"; + function = "pdm"; + }; + }; + + +}; /* end of pinctrl_periphs */ + +&pinctrl_aobus { + spdifout: spdifout { + mux { /* gpiao_10 */ + groups = "spdif_out_ao"; + function = "spdif_out_ao"; + }; + }; +}; /* end of pinctrl_aobus */ + +&audio_data{ + status = "okay"; +}; + +&i2c2 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&i2c2_z_pins>; + clock-frequency = <400000>; + + tas5805: tas5805@36 { + compatible = "ti,tas5805"; + #sound-dai-cells = <0>; + codec_name = "tas5805"; + reg = <0x2d>; + status = "disable"; + }; + + ad82584f: ad82584f@62 { + compatible = "ESMT, ad82584f"; + #sound-dai-cells = <0>; + reg = <0x31>; + status = "disabled"; + reset_pin = <&gpio_ao GPIOAO_6 0>; + }; + +}; + +&sd_emmc_c { + status = "okay"; + emmc { + caps = "MMC_CAP_8_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + "MMC_CAP_1_8V_DDR", + "MMC_CAP_HW_RESET", + "MMC_CAP_ERASE", + "MMC_CAP_CMD23"; + caps2 = "MMC_CAP2_HS200"; + /* "MMC_CAP2_HS400";*/ + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&spifc { + status = "disabled"; + spi-nor@0 { + cs_gpios = <&gpio BOOT_13 GPIO_ACTIVE_HIGH>; + }; +}; + +&slc_nand { + status = "disabled"; + plat-names = "bootloader", "nandnormal"; + plat-num = <2>; + plat-part-0 = <&bootloader>; + plat-part-1 = <&nandnormal>; + bootloader: bootloader{ + enable_pad = "ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <1>; + part_num = <0>; + rb_detect = <1>; + }; + nandnormal: nandnormal{ + enable_pad = "ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + plane_mode = "twoplane"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <2>; + part_num = <3>; + partition = <&nand_partitions>; + rb_detect = <1>; + }; + nand_partitions:nand_partition{ + /* + * if bl_mode is 1, tpl size was generate by + * fip_copies * fip_size which + * will not skip bad when calculating + * the partition size; + * + * if bl_mode is 0, + * tpl partition must be comment out. + */ + tpl{ + offset=<0x0 0x0>; + size=<0x0 0x0>; + }; + logo{ + offset=<0x0 0x0>; + size=<0x0 0x200000>; + }; + recovery{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + boot{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + system{ + offset=<0x0 0x0>; + size=<0x0 0x4000000>; + }; + data{ + offset=<0xffffffff 0xffffffff>; + size=<0x0 0x0>; + }; + }; +}; + +ðmac { + status = "okay"; + pinctrl-names = "internal_eth_pins"; + pinctrl-0 = <&internal_eth_pins>; + mc_val = <0x4be04>; + + internal_phy=<1>; +}; + +&uart_A { + status = "okay"; +}; + +&dwc3 { + status = "okay"; +}; + +&usb2_phy_v2 { + status = "okay"; + portnum = <3>; +}; + +&usb3_phy_v2 { + status = "okay"; + portnum = <2>; + portconfig-30 = <1>; + portconfig-31 = <1>; +}; + +&usb_otg { + status = "okay"; + otg = <0>; +}; + +&dwc2_a { + status = "okay"; + /** 0: normal, 1: otg+dwc3 host only, 2: otg+dwc3 device only*/ + controller-type = <1>; +}; + +&pcie_A { + /* pcie a reset gpio must be updated */ + reset-gpio = <&gpio_ao GPIOAO_11 GPIO_ACTIVE_HIGH>; + status = "disable"; +}; + +&pcie_B { + /* pcie b reset gpio must be updated */ + reset-gpio = <&gpio GPIOH_22 GPIO_ACTIVE_HIGH>; + status = "disable"; +}; + +&spicc0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&spicc0_pins_h>; + cs-gpios = <&gpio GPIOH_20 0>; +}; + +&meson_fb { + status = "okay"; + display_size_default = <1920 1080 1920 2160 32>; + mem_size = <0x00800000 0x1980000 0x100000 0x100000 0x800000>; + logo_addr = "0x7f800000"; + mem_alloc = <0>; + pxp_mode = <0>; /** 0:normal mode 1:pxp mode */ +}; + +&pwm_AO_cd { + status = "okay"; +}; + +&saradc { + status = "okay"; +}; + +&i2c1 { + status = "okay"; + clock-frequency = <300000>; + pinctrl-names="default"; + pinctrl-0=<&i2c1_h_pins>; + + lcd_extern_i2c0: lcd_extern_i2c@0 { + compatible = "lcd_ext, i2c"; + dev_name = "i2c_T5800Q"; + reg = <0x1c>; + status = "okay"; + }; + + lcd_extern_i2c1: lcd_extern_i2c@1 { + compatible = "lcd_ext, i2c"; + dev_name = "i2c_ANX6862"; + reg = <0x20>; + status = "okay"; + }; + + lcd_extern_i2c2: lcd_extern_i2c@2 { + compatible = "lcd_ext, i2c"; + dev_name = "i2c_ANX7911"; + reg = <0x74>; + status = "okay"; + }; +}; + +&efuse { + status = "okay"; +}; diff --git a/arch/arm/boot/dts/amlogic/txl_t950_p341.dts b/arch/arm/boot/dts/amlogic/txl_t950_p341.dts index 4f53cadaa1f1..065c204a1e9f 100644 --- a/arch/arm/boot/dts/amlogic/txl_t950_p341.dts +++ b/arch/arm/boot/dts/amlogic/txl_t950_p341.dts @@ -436,18 +436,21 @@ }; tuner: tuner { + compatible = "amlogic, tuner"; status = "okay"; - tuner_name = "r842_tuner"; - tuner_i2c_adap = <&i2c1>; - tuner_i2c_addr = <0xf6>; - tuner_xtal = <1>; /* 0: 16MHz, 1: 24MHz, 3: 27MHz */ - tuner_xtal_mode = <3>; + tuner_cur = <0>; /* default use tuner */ + tuner_num = <1>; /* tuner number, multi tuner support */ + tuner_name_0 = "r842_tuner"; + tuner_i2c_adap_0 = <&i2c1>; + tuner_i2c_addr_0 = <0xf6>; + tuner_xtal_0 = <1>; /* 0: 16MHz, 1: 24MHz, 3: 27MHz */ + tuner_xtal_mode_0 = <3>; /* NO_SHARE_XTAL(0) * MASTER_TO_SLAVE_XTAL_IN(1) * MASTER_TO_SLAVE_XTAL_OUT(2) * SLAVE_XTAL_OUT(3) */ - tuner_xtal_cap = <0>; /* 0 ~ 41 (pf) */ + tuner_xtal_cap_0 = <0>; /* 0 ~ 41 (pf) */ }; atv-demod { diff --git a/arch/arm/boot/dts/amlogic/txl_t960_p346.dts b/arch/arm/boot/dts/amlogic/txl_t960_p346.dts index 454b1f112f5f..9c05ca3ebea2 100644 --- a/arch/arm/boot/dts/amlogic/txl_t960_p346.dts +++ b/arch/arm/boot/dts/amlogic/txl_t960_p346.dts @@ -437,18 +437,21 @@ }; tuner: tuner { + compatible = "amlogic, tuner"; status = "okay"; - tuner_name = "r842_tuner"; - tuner_i2c_adap = <&i2c1>; - tuner_i2c_addr = <0xf6>; - tuner_xtal = <1>; /* 0: 16MHz, 1: 24MHz, 3: 27MHz */ - tuner_xtal_mode = <3>; + tuner_cur = <0>; /* default use tuner */ + tuner_num = <1>; /* tuner number, multi tuner support */ + tuner_name_0 = "r842_tuner"; + tuner_i2c_adap_0 = <&i2c1>; + tuner_i2c_addr_0 = <0xf6>; + tuner_xtal_0 = <1>; /* 0: 16MHz, 1: 24MHz, 3: 27MHz */ + tuner_xtal_mode_0 = <3>; /* NO_SHARE_XTAL(0) * MASTER_TO_SLAVE_XTAL_IN(1) * MASTER_TO_SLAVE_XTAL_OUT(2) * SLAVE_XTAL_OUT(3) */ - tuner_xtal_cap = <0>; /* 0 ~ 41 (pf) */ + tuner_xtal_cap_0 = <0>; /* 0 ~ 41 (pf) */ }; atv-demod { diff --git a/arch/arm/boot/dts/amlogic/txl_t962_p320.dts b/arch/arm/boot/dts/amlogic/txl_t962_p320.dts index 154b9f41532c..79f71365fc7d 100644 --- a/arch/arm/boot/dts/amlogic/txl_t962_p320.dts +++ b/arch/arm/boot/dts/amlogic/txl_t962_p320.dts @@ -427,13 +427,16 @@ }; tuner: tuner { + compatible = "amlogic, tuner"; status = "okay"; - tuner_name = "si2151_tuner"; - tuner_i2c_adap = <&i2c1>; - tuner_i2c_addr = <0x60>; - /* tuner_xtal = <0>; */ /* unuse for si2151 */ - /* tuner_xtal_mode = <0>; */ - /* tuner_xtal_cap = <0>; */ + tuner_cur = <0>; /* default use tuner */ + tuner_num = <1>; /* tuner number, multi tuner support */ + tuner_name_0 = "si2151_tuner"; + tuner_i2c_adap_0 = <&i2c1>; + tuner_i2c_addr_0 = <0x60>; + /* tuner_xtal_0 = <0>; */ /* unuse for si2151 */ + /* tuner_xtal_mode_0 = <0>; */ + /* tuner_xtal_cap_0 = <0>; */ }; atv-demod { diff --git a/arch/arm/boot/dts/amlogic/txl_t962_p321.dts b/arch/arm/boot/dts/amlogic/txl_t962_p321.dts index c896f12a95d0..43f3db1cdad5 100644 --- a/arch/arm/boot/dts/amlogic/txl_t962_p321.dts +++ b/arch/arm/boot/dts/amlogic/txl_t962_p321.dts @@ -280,6 +280,22 @@ status = "okay"; }; + amlvideo2_0 { + compatible = "amlogic, amlvideo2"; + dev_name = "amlvideo2"; + status = "okay"; + amlvideo2_id = <0>; + cma_mode = <1>; + }; + + amlvideo2_1 { + compatible = "amlogic, amlvideo2"; + dev_name = "amlvideo2"; + status = "okay"; + amlvideo2_id = <1>; + cma_mode = <1>; + }; + hdmirx { compatible = "amlogic, hdmirx-txl"; status = "okay"; @@ -432,18 +448,21 @@ }; tuner: tuner { + compatible = "amlogic, tuner"; status = "okay"; - tuner_name = "r842_tuner"; - tuner_i2c_adap = <&i2c1>; - tuner_i2c_addr = <0xf6>; - tuner_xtal = <1>; /* 0: 16MHz, 1: 24MHz, 3: 27MHz */ - tuner_xtal_mode = <0>; + tuner_cur = <0>; /* default use tuner */ + tuner_num = <1>; /* tuner number, multi tuner support */ + tuner_name_0 = "r842_tuner"; + tuner_i2c_adap_0 = <&i2c1>; + tuner_i2c_addr_0 = <0xf6>; + tuner_xtal_0 = <1>; /* 0: 16MHz, 1: 24MHz, 3: 27MHz */ + tuner_xtal_mode_0 = <0>; /* NO_SHARE_XTAL(0) * MASTER_TO_SLAVE_XTAL_IN(1) * MASTER_TO_SLAVE_XTAL_OUT(2) * SLAVE_XTAL_OUT(3) */ - tuner_xtal_cap = <38>; /* 0 ~ 41 (pf) */ + tuner_xtal_cap_0 = <38>; /* 0 ~ 41 (pf) */ }; atv-demod { diff --git a/arch/arm/boot/dts/amlogic/txl_t962_p321_720p.dts b/arch/arm/boot/dts/amlogic/txl_t962_p321_720p.dts index d961b2423ba8..590514c96443 100644 --- a/arch/arm/boot/dts/amlogic/txl_t962_p321_720p.dts +++ b/arch/arm/boot/dts/amlogic/txl_t962_p321_720p.dts @@ -80,7 +80,7 @@ reusable; size = <0x400000>; alignment = <0x400000>; - alloc-ranges = <0x0 0x30000000>; + alloc-ranges = <0x2FC00000 0x400000>; }; codec_mm_cma:linux,codec_mm_cma { compatible = "shared-dma-pool"; @@ -233,7 +233,7 @@ /*1280*720*4*3 = 0xA8C000*/ display_size_default = <1280 720 1280 2160 32>; pxp_mode = <0>; /** 0:normal mode 1:pxp mode */ - logo_addr = "0x3fc00000"; + logo_addr = "0x2FC00000"; }; picdec { @@ -280,6 +280,22 @@ status = "okay"; }; + amlvideo2_0 { + compatible = "amlogic, amlvideo2"; + dev_name = "amlvideo2"; + status = "okay"; + amlvideo2_id = <0>; + cma_mode = <1>; + }; + + amlvideo2_1 { + compatible = "amlogic, amlvideo2"; + dev_name = "amlvideo2"; + status = "okay"; + amlvideo2_id = <1>; + cma_mode = <1>; + }; + hdmirx { compatible = "amlogic, hdmirx-txl"; status = "okay"; @@ -432,18 +448,21 @@ }; tuner: tuner { + compatible = "amlogic, tuner"; status = "okay"; - tuner_name = "r842_tuner"; - tuner_i2c_adap = <&i2c1>; - tuner_i2c_addr = <0xf6>; - tuner_xtal = <1>; /* 0: 16MHz, 1: 24MHz, 3: 27MHz */ - tuner_xtal_mode = <0>; + tuner_cur = <0>; /* default use tuner */ + tuner_num = <1>; /* tuner number, multi tuner support */ + tuner_name_0 = "r842_tuner"; + tuner_i2c_adap_0 = <&i2c1>; + tuner_i2c_addr_0 = <0xf6>; + tuner_xtal_0 = <1>; /* 0: 16MHz, 1: 24MHz, 3: 27MHz */ + tuner_xtal_mode_0 = <0>; /* NO_SHARE_XTAL(0) * MASTER_TO_SLAVE_XTAL_IN(1) * MASTER_TO_SLAVE_XTAL_OUT(2) * SLAVE_XTAL_OUT(3) */ - tuner_xtal_cap = <38>; /* 0 ~ 41 (pf) */ + tuner_xtal_cap_0 = <38>; /* 0 ~ 41 (pf) */ }; atv-demod { @@ -1180,3 +1199,7 @@ cs-gpios = <&gpio GPIOZ_3 0>; }; +&defendkey { + memory-region = <&defendkey_reserved>; + status = "okay"; +}; diff --git a/arch/arm/boot/dts/amlogic/txlx_t962e_r321.dts b/arch/arm/boot/dts/amlogic/txlx_t962e_r321.dts index 3d8cb6352dac..64ab38cfbda2 100644 --- a/arch/arm/boot/dts/amlogic/txlx_t962e_r321.dts +++ b/arch/arm/boot/dts/amlogic/txlx_t962e_r321.dts @@ -58,8 +58,7 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { compatible = "shared-dma-pool"; @@ -162,12 +161,6 @@ alignment = <0x400000>; }; - /*vbi reserved mem*/ - vbi_reserved:linux,vbi { - compatible = "amlogic, vbi-mem"; - size = <0x100000>; - alloc-ranges = <0x1f800000 0x800000>; - }; }; /* for external keypad */ @@ -568,11 +561,9 @@ vbi { compatible = "amlogic, vbi"; - memory-region = <&vbi_reserved>; dev_name = "vbi"; status = "okay"; interrupts = <0 83 1>; - reserve-iomap = "true"; }; tvafe_avin_detect { @@ -626,13 +617,16 @@ }; tuner: tuner { + compatible = "amlogic, tuner"; status = "okay"; - tuner_name = "si2151_tuner"; - tuner_i2c_adap = <&i2c1>; - tuner_i2c_addr = <0x60>; - /* tuner_xtal = <0>; */ /* unuse for si2151 */ - /* tuner_xtal_mode = <0>; */ - /* tuner_xtal_cap = <0>; */ + tuner_cur = <0>; /* default use tuner */ + tuner_num = <1>; /* tuner number, multi tuner support */ + tuner_name_0 = "si2151_tuner"; + tuner_i2c_adap_0 = <&i2c1>; + tuner_i2c_addr_0 = <0x60>; + /* tuner_xtal_0 = <0>; */ /* unuse for si2151 */ + /* tuner_xtal_mode_0 = <0>; */ + /* tuner_xtal_cap_0 = <0>; */ }; atv-demod { diff --git a/arch/arm/boot/dts/amlogic/txlx_t962e_r321_buildroot.dts b/arch/arm/boot/dts/amlogic/txlx_t962e_r321_buildroot.dts index 48ac144d59e7..5b9852267027 100644 --- a/arch/arm/boot/dts/amlogic/txlx_t962e_r321_buildroot.dts +++ b/arch/arm/boot/dts/amlogic/txlx_t962e_r321_buildroot.dts @@ -44,7 +44,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x100000 0x7ff00000>; + linux,usable-memory = <0x0 0x80000000>; }; reserved-memory { @@ -57,8 +57,7 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { @@ -153,12 +152,6 @@ alignment = <0x400000>; }; - /*vbi reserved mem*/ - vbi_reserved:linux,vbi { - compatible = "amlogic, vbi-mem"; - size = <0x100000>; - alloc-ranges = <0x0 0x30000000>; - }; }; /* for external keypad */ @@ -611,11 +604,9 @@ vbi { compatible = "amlogic, vbi"; - memory-region = <&vbi_reserved>; dev_name = "vbi"; status = "okay"; interrupts = <0 83 1>; - reserve-iomap = "true"; }; tvafe_avin_detect { @@ -670,13 +661,16 @@ }; tuner: tuner { + compatible = "amlogic, tuner"; status = "okay"; - tuner_name = "si2151_tuner"; - tuner_i2c_adap = <&i2c1>; - tuner_i2c_addr = <0x60>; - /* tuner_xtal = <0>; */ /* unuse for si2151 */ - /* tuner_xtal_mode = <0>; */ - /* tuner_xtal_cap = <0>; */ + tuner_cur = <0>; /* default use tuner */ + tuner_num = <1>; /* tuner number, multi tuner support */ + tuner_name_0 = "si2151_tuner"; + tuner_i2c_adap_0 = <&i2c1>; + tuner_i2c_addr_0 = <0x60>; + /* tuner_xtal_0 = <0>; */ /* unuse for si2151 */ + /* tuner_xtal_mode_0 = <0>; */ + /* tuner_xtal_cap_0 = <0>; */ }; atv-demod { diff --git a/arch/arm/boot/dts/amlogic/txlx_t962x_r311_1g.dts b/arch/arm/boot/dts/amlogic/txlx_t962x_r311_1g.dts index 8a65f4161541..72b29a7a7e8c 100644 --- a/arch/arm/boot/dts/amlogic/txlx_t962x_r311_1g.dts +++ b/arch/arm/boot/dts/amlogic/txlx_t962x_r311_1g.dts @@ -48,7 +48,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x000000 0x40000000>; + linux,usable-memory = <0x0 0x40000000>; }; reserved-memory { @@ -61,8 +61,7 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { compatible = "shared-dma-pool"; @@ -169,13 +168,6 @@ alignment = <0x400000>; alloc-ranges = <0x0 0x30000000>; }; - - /*vbi reserved mem*/ - vbi_reserved:linux,vbi { - compatible = "amlogic, vbi-mem"; - size = <0x100000>; - alloc-ranges = <0x0e000000 0x800000>; - }; }; amlogic_battery:dummy-battery { @@ -578,11 +570,9 @@ vbi { compatible = "amlogic, vbi"; - memory-region = <&vbi_reserved>; dev_name = "vbi"; status = "okay"; interrupts = <0 83 1>; - reserve-iomap = "true"; }; tvafe_avin_detect { @@ -632,16 +622,19 @@ }; tuner: tuner { + compatible = "amlogic, tuner"; status = "okay"; - tuner_name = "mxl661_tuner"; - tuner_i2c_adap = <&i2c1>; - tuner_i2c_addr = <0x60>; - tuner_xtal = <0>; /* 0: 16MHz, 1: 24MHz */ - tuner_xtal_mode = <0>; + tuner_cur = <0>; /* default use tuner */ + tuner_num = <1>; /* tuner number, multi tuner support */ + tuner_name_0 = "mxl661_tuner"; + tuner_i2c_adap_0 = <&i2c1>; + tuner_i2c_addr_0 = <0x60>; + tuner_xtal_0 = <0>; /* 0: 16MHz, 1: 24MHz */ + tuner_xtal_mode_0 = <0>; /* NO_SHARE_XTAL(0) * SLAVE_XTAL_SHARE(1) */ - tuner_xtal_cap = <30>; /* when tuner_xtal_mode = 1, set 25 */ + tuner_xtal_cap_0 = <30>; /* when tuner_xtal_mode = 1, set 25 */ }; atv-demod { @@ -818,7 +811,7 @@ compatible = "amlogic, unifykey"; status = "okay"; - unifykey-num = <20>; + unifykey-num = <21>; unifykey-index-0 = <&keysn_0>; unifykey-index-1 = <&keysn_1>; unifykey-index-2 = <&keysn_2>; @@ -839,6 +832,7 @@ unifykey-index-17 = <&keysn_17>; unifykey-index-18 = <&keysn_18>; unifykey-index-19 = <&keysn_19>; + unifykey-index-20 = <&keysn_20>; keysn_0: key_0{ key-name = "usid"; @@ -945,6 +939,11 @@ key-device = "secure"; key-permit = "read","write","del"; }; + keysn_20:key_20{ + key-name = "region_code"; + key-device = "normal"; + key-permit = "read","write","del"; + }; }; /* End unifykey */ cvbsout { @@ -1370,6 +1369,52 @@ &clkc CLKID_DOS_PARSER>; clock-names = "demux", "asyncfifo", "ahbarb0", "uparsertop"; }; + + dvb_swdmx { + compatible = "amlogic, dvb-swdmx"; + dev_name = "dvb_swdmx"; + status = "okay"; + cbus_base = <0x1800>; + asyncfifo0_reg_base = <0x2800>; + asyncfifo1_reg_base = <0x9800>; + asyncfifo2_reg_base = <0x2400>; + reset_base = <0x0400>; + parser_sub_ptr_base = <0x3800>; + + ts_in_count = <3>; + s2p_count = <2>; + asyncfifo_count = <2>; + + asyncfifo_buf_len = <0x80000>; + + path_num = <2>; + path0_ts = <2>;/*0~2 for ts, 16 for hiu */ + path0_dmx = <0>; + path0_asyncfifo = <0>; + path1_ts = <2>; + path1_dmx = <1>; + path1_asyncfifo = <1>; + + /*dmxdev_num = <4>;*/ + + fe0_mode = "internal"; + fe0_tuner = <&tuner>; + /*"parallel","serial","disable"*/ + ts2 = "parallel"; + ts2_control = <0>; + ts2_invert = <0>; + interrupts = <0 23 1 + 0 5 1 + 0 53 1>; + interrupt-names = "demux0_irq", + "demux1_irq", + "demux2_irq"; + clocks = <&clkc CLKID_DEMUX + &clkc CLKID_ASYNC_FIFO + &clkc CLKID_AHB_ARB0 + &clkc CLKID_DOS_PARSER>; + clock-names = "demux", "asyncfifo", "ahbarb0", "uparsertop"; + }; aml_dtv_demod { compatible = "amlogic, ddemod-txlx"; dev_name = "aml_dtv_demod"; @@ -1560,7 +1605,7 @@ /*lcd_extern*/ lcd_extern_off_pins:lcd_extern_off_pin { mux { - pins = "GPIOH_2", + groups = "GPIOH_2", "GPIOH_3"; function = "gpio_periphs"; /*output-high;*/ @@ -1572,50 +1617,50 @@ /*backlight*/ bl_pwm_on_pins:bl_pwm_on_pin { mux { - pins = "pwm_b"; + groups = "pwm_b"; function = "pwm_b"; }; }; bl_pwm_vs_on_pins:bl_pwm_vs_on_pin { mux { - pins = "pwm_vs_z6"; + groups = "pwm_vs_z6"; function = "pwm_vs"; }; }; bl_pwm_off_pins:bl_pwm_off_pin { mux { - pins = "GPIOZ_6"; + groups = "GPIOZ_6"; function = "gpio_periphs"; output-low; }; }; bl_pwm_combo_0_on_pins:bl_pwm_combo_0_on_pin { mux { - pins = "pwm_b"; + groups = "pwm_b"; function = "pwm_b"; }; }; bl_pwm_combo_1_on_pins:bl_pwm_combo_1_on_pin { mux { - pins = "pwm_c_z"; + groups = "pwm_c_z"; function = "pwm_c"; }; }; bl_pwm_combo_0_vs_on_pins:bl_pwm_combo_0_vs_on_pin { mux { - pins = "pwm_vs_z6"; + groups = "pwm_vs_z6"; function = "pwm_vs"; }; }; bl_pwm_combo_1_vs_on_pins:bl_pwm_combo_1_vs_on_pin { mux { - pins = "pwm_vs_z7"; + groups = "pwm_vs_z7"; function = "pwm_vs"; }; }; bl_pwm_combo_off_pins:bl_pwm_combo_off_pin { mux { - pins = "GPIOZ_6", + groups = "GPIOZ_6", "GPIOZ_7"; function = "gpio_periphs"; output-low; diff --git a/arch/arm/boot/dts/amlogic/txlx_t962x_r311_2g.dts b/arch/arm/boot/dts/amlogic/txlx_t962x_r311_2g.dts index 95753b5f5542..600835e2d8e9 100644 --- a/arch/arm/boot/dts/amlogic/txlx_t962x_r311_2g.dts +++ b/arch/arm/boot/dts/amlogic/txlx_t962x_r311_2g.dts @@ -61,8 +61,7 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { compatible = "shared-dma-pool"; @@ -166,13 +165,6 @@ size = <0x01400000>; alignment = <0x400000>; }; - - /*vbi reserved mem*/ - vbi_reserved:linux,vbi { - compatible = "amlogic, vbi-mem"; - size = <0x100000>; - alloc-ranges = <0x0e000000 0x800000>; - }; }; amlogic_battery:dummy-battery { @@ -575,11 +567,9 @@ vbi { compatible = "amlogic, vbi"; - memory-region = <&vbi_reserved>; dev_name = "vbi"; status = "okay"; interrupts = <0 83 1>; - reserve-iomap = "true"; }; tvafe_avin_detect { @@ -629,16 +619,19 @@ }; tuner: tuner { + compatible = "amlogic, tuner"; status = "okay"; - tuner_name = "mxl661_tuner"; - tuner_i2c_adap = <&i2c1>; - tuner_i2c_addr = <0x60>; - tuner_xtal = <0>; /* 0: 16MHz, 1: 24MHz */ - tuner_xtal_mode = <0>; + tuner_cur = <0>; /* default use tuner */ + tuner_num = <1>; /* tuner number, multi tuner support */ + tuner_name_0 = "mxl661_tuner"; + tuner_i2c_adap_0 = <&i2c1>; + tuner_i2c_addr_0 = <0x60>; + tuner_xtal_0 = <0>; /* 0: 16MHz, 1: 24MHz */ + tuner_xtal_mode_0 = <0>; /* NO_SHARE_XTAL(0) * SLAVE_XTAL_SHARE(1) */ - tuner_xtal_cap = <30>; /* when tuner_xtal_mode = 1, set 25 */ + tuner_xtal_cap_0 = <30>; /* when tuner_xtal_mode = 1, set 25 */ }; atv-demod { @@ -1563,7 +1556,7 @@ /*lcd_extern*/ lcd_extern_off_pins:lcd_extern_off_pin { mux { - pins = "GPIOH_2", + groups = "GPIOH_2", "GPIOH_3"; function = "gpio_periphs"; /*output-high;*/ @@ -1575,50 +1568,50 @@ /*backlight*/ bl_pwm_on_pins:bl_pwm_on_pin { mux { - pins = "pwm_b"; + groups = "pwm_b"; function = "pwm_b"; }; }; bl_pwm_vs_on_pins:bl_pwm_vs_on_pin { mux { - pins = "pwm_vs_z6"; + groups = "pwm_vs_z6"; function = "pwm_vs"; }; }; bl_pwm_off_pins:bl_pwm_off_pin { mux { - pins = "GPIOZ_6"; + groups = "GPIOZ_6"; function = "gpio_periphs"; output-low; }; }; bl_pwm_combo_0_on_pins:bl_pwm_combo_0_on_pin { mux { - pins = "pwm_b"; + groups = "pwm_b"; function = "pwm_b"; }; }; bl_pwm_combo_1_on_pins:bl_pwm_combo_1_on_pin { mux { - pins = "pwm_c_z"; + groups = "pwm_c_z"; function = "pwm_c"; }; }; bl_pwm_combo_0_vs_on_pins:bl_pwm_combo_0_vs_on_pin { mux { - pins = "pwm_vs_z6"; + groups = "pwm_vs_z6"; function = "pwm_vs"; }; }; bl_pwm_combo_1_vs_on_pins:bl_pwm_combo_1_vs_on_pin { mux { - pins = "pwm_vs_z7"; + groups = "pwm_vs_z7"; function = "pwm_vs"; }; }; bl_pwm_combo_off_pins:bl_pwm_combo_off_pin { mux { - pins = "GPIOZ_6", + groups = "GPIOZ_6", "GPIOZ_7"; function = "gpio_periphs"; output-low; diff --git a/arch/arm/boot/dts/amlogic/txlx_t962x_r311_720p.dts b/arch/arm/boot/dts/amlogic/txlx_t962x_r311_720p.dts index eccb9cb8b13f..d5e262d28dc8 100644 --- a/arch/arm/boot/dts/amlogic/txlx_t962x_r311_720p.dts +++ b/arch/arm/boot/dts/amlogic/txlx_t962x_r311_720p.dts @@ -46,7 +46,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x100000 0x3ff00000>; + linux,usable-memory = <0x0 0x40000000>; }; reserved-memory { @@ -59,8 +59,7 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { compatible = "shared-dma-pool"; @@ -163,13 +162,6 @@ size = <0x01400000>; alignment = <0x400000>; }; - - /*vbi reserved mem*/ - vbi_reserved:linux,vbi { - compatible = "amlogic, vbi-mem"; - size = <0x100000>; - alloc-ranges = <0x0 0x30000000>; - }; }; amlogic_battery:dummy-battery { @@ -571,11 +563,9 @@ vbi { compatible = "amlogic, vbi"; - memory-region = <&vbi_reserved>; dev_name = "vbi"; status = "okay"; interrupts = <0 83 1>; - reserve-iomap = "true"; }; tvafe_avin_detect { @@ -625,16 +615,19 @@ }; tuner: tuner { + compatible = "amlogic, tuner"; status = "okay"; - tuner_name = "mxl661_tuner"; - tuner_i2c_adap = <&i2c1>; - tuner_i2c_addr = <0x60>; - tuner_xtal = <0>; /* 0: 16MHz, 1: 24MHz */ - tuner_xtal_mode = <0>; + tuner_cur = <0>; /* default use tuner */ + tuner_num = <1>; /* tuner number, multi tuner support */ + tuner_name_0 = "mxl661_tuner"; + tuner_i2c_adap_0 = <&i2c1>; + tuner_i2c_addr_0 = <0x60>; + tuner_xtal_0 = <0>; /* 0: 16MHz, 1: 24MHz */ + tuner_xtal_mode_0 = <0>; /* NO_SHARE_XTAL(0) * SLAVE_XTAL_SHARE(1) */ - tuner_xtal_cap = <30>; /* when tuner_xtal_mode = 1, set 25 */ + tuner_xtal_cap_0 = <30>; /* when tuner_xtal_mode = 1, set 25 */ }; atv-demod { @@ -1552,7 +1545,7 @@ /*lcd_extern*/ lcd_extern_off_pins:lcd_extern_off_pin { mux { - pins = "GPIOH_2", + groups = "GPIOH_2", "GPIOH_3"; function = "gpio_periphs"; /*output-high;*/ @@ -1564,50 +1557,50 @@ /*backlight*/ bl_pwm_on_pins:bl_pwm_on_pin { mux { - pins = "pwm_b"; + groups = "pwm_b"; function = "pwm_b"; }; }; bl_pwm_vs_on_pins:bl_pwm_vs_on_pin { mux { - pins = "pwm_vs_z6"; + groups = "pwm_vs_z6"; function = "pwm_vs"; }; }; bl_pwm_off_pins:bl_pwm_off_pin { mux { - pins = "GPIOZ_6"; + groups = "GPIOZ_6"; function = "gpio_periphs"; output-low; }; }; bl_pwm_combo_0_on_pins:bl_pwm_combo_0_on_pin { mux { - pins = "pwm_b"; + groups = "pwm_b"; function = "pwm_b"; }; }; bl_pwm_combo_1_on_pins:bl_pwm_combo_1_on_pin { mux { - pins = "pwm_c_z"; + groups = "pwm_c_z"; function = "pwm_c"; }; }; bl_pwm_combo_0_vs_on_pins:bl_pwm_combo_0_vs_on_pin { mux { - pins = "pwm_vs_z6"; + groups = "pwm_vs_z6"; function = "pwm_vs"; }; }; bl_pwm_combo_1_vs_on_pins:bl_pwm_combo_1_vs_on_pin { mux { - pins = "pwm_vs_z7"; + groups = "pwm_vs_z7"; function = "pwm_vs"; }; }; bl_pwm_combo_off_pins:bl_pwm_combo_off_pin { mux { - pins = "GPIOZ_6", + groups = "GPIOZ_6", "GPIOZ_7"; function = "gpio_periphs"; output-low; diff --git a/arch/arm/boot/dts/amlogic/txlx_t962x_r314.dts b/arch/arm/boot/dts/amlogic/txlx_t962x_r314.dts index 53cc709a26a9..10289ebbab0d 100644 --- a/arch/arm/boot/dts/amlogic/txlx_t962x_r314.dts +++ b/arch/arm/boot/dts/amlogic/txlx_t962x_r314.dts @@ -48,7 +48,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x100000 0x5ff00000>; + linux,usable-memory = <0x0 0x60000000>; }; reserved-memory { @@ -61,8 +61,7 @@ reg = <0x07400000 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { compatible = "shared-dma-pool"; @@ -169,13 +168,6 @@ alignment = <0x400000>; alloc-ranges = <0x0 0x30000000>; }; - - /*vbi reserved mem*/ - vbi_reserved:linux,vbi { - compatible = "amlogic, vbi-mem"; - size = <0x100000>; - alloc-ranges = <0x0e000000 0x800000>; - }; }; amlogic_battery:dummy-battery { @@ -578,11 +570,9 @@ vbi { compatible = "amlogic, vbi"; - memory-region = <&vbi_reserved>; dev_name = "vbi"; status = "okay"; interrupts = <0 83 1>; - reserve-iomap = "true"; }; tvafe_avin_detect { @@ -632,21 +622,33 @@ }; tuner: tuner { + compatible = "amlogic, tuner"; +<<<<<<< HEAD status = "okay"; tuner_name = "mxl661_tuner"; tuner_i2c_adap = <&i2c1>; tuner_i2c_addr = <0x60>; tuner_xtal = <0>; /* 0: 16MHz, 1: 24MHz */ tuner_xtal_mode = <0>; +======= + status = "disabled"; + tuner_cur = <0>; /* default use tuner */ + tuner_num = <1>; /* tuner number, multi tuner support */ + tuner_name_0 = "mxl661_tuner"; + tuner_i2c_adap_0 = <&i2c1>; + tuner_i2c_addr_0 = <0x60>; + tuner_xtal_0 = <0>; /* 0: 16MHz, 1: 24MHz */ + tuner_xtal_mode_0 = <0>; +>>>>>>> 374c6b2... atv_demod: modify atv demod support multi tuner load [1/3] /* NO_SHARE_XTAL(0) * SLAVE_XTAL_SHARE(1) */ - tuner_xtal_cap = <30>; /* when tuner_xtal_mode = 1, set 25 */ + tuner_xtal_cap_0 = <30>; /* when tuner_xtal_mode = 1, set 25 */ }; atv-demod { compatible = "amlogic, atv-demod"; - status = "okay"; + status = "disabled"; tuner = <&tuner>; btsc_sap_mode = <1>; /* pinctrl-names="atvdemod_agc_pins"; */ @@ -1216,8 +1218,9 @@ #sound-dai-cells = <0>; compatible = "amlogic, aml-spdif-codec"; pinctrl-names = "audio_spdif_out", "audio_spdif_out_mute"; - pinctrl-0 = <&audio_spdif_out_pins>; - pinctrl-1 = <&audio_spdif_out_mute_pins>; + /* disable spdif pin mux temporary, enable it if necessary */ + /*pinctrl-0 = <&audio_spdif_out_pins>;*/ + /*pinctrl-1 = <&audio_spdif_out_mute_pins>;*/ }; pcm_codec: pcm_codec{ @@ -1282,8 +1285,8 @@ Channel_Mask { /*i2s has 4 pins, 8channel, mux output*/ Speaker0_Channel_Mask = "i2s_2/3"; - DAC0_Channel_Mask = "i2s_2/3"; - DAC1_Channel_Mask = "i2s_2/3"; + DAC0_Channel_Mask = "i2s_4/5"; + DAC1_Channel_Mask = "i2s_4/5"; EQ_DRC_Channel_Mask = "i2s_2/3"; Spdif_samesource_Channel_Mask = "i2s_0/1"; }; @@ -1344,12 +1347,17 @@ compatible = "amlogic, dvb"; dev_name = "dvb"; status = "okay"; - fe0_mode = "internal"; - fe0_tuner = <&tuner>; - /*"parallel","serial","disable"*/ - ts2 = "parallel"; - ts2_control = <0>; - ts2_invert = <0>; + fe0_mode = "external"; + fe0_demod = "Si2168"; + fe0_i2c_adap_id = <&i2c1>; + fe0_demod_i2c_addr = <0x64>; + fe0_ts = <0>; + fe0_reset_value = <0>; + fe0_reset_gpio = <&gpio GPIODV_6 GPIO_ACTIVE_HIGH>; + + ts0 = "serial"; + ts0_control = <0x800>; + ts0_invert = <0>; interrupts = <0 23 1 0 5 1 0 53 1 @@ -1364,16 +1372,31 @@ "dvr1_irq", "dvrfill0_fill", "dvrfill1_flush"; + pinctrl-names = "s_ts0"; + pinctrl-0 = <&dvb_s_ts0_pins>; clocks = <&clkc CLKID_DEMUX &clkc CLKID_ASYNC_FIFO &clkc CLKID_AHB_ARB0 &clkc CLKID_DOS_PARSER>; clock-names = "demux", "asyncfifo", "ahbarb0", "uparsertop"; }; + + dvbci { + compatible = "amlogic, dvbci"; + dev_name = "dvbci"; + io_type = <2>;//0:iobus,1:spi,2:cimax + cimax { + io_type = <1>;//0:spi,1:usb + usb { + rst-gpios = <&gpio GPIOZ_12 GPIO_ACTIVE_HIGH>; + }; + }; + }; + aml_dtv_demod { compatible = "amlogic, ddemod-txlx"; dev_name = "aml_dtv_demod"; - status = "okay"; + status = "disabled"; //pinctrl-names="dtvdemod_agc"; //pinctrl-0=<&dtvdemod_agc>; @@ -1395,28 +1418,6 @@ cma_mem_size = <8>; memory-region = <&demod_cma_reserved>;//<&demod_reserved>; }; - dvbfe { - compatible = "amlogic, dvbfe"; - dev_name = "dvbfe"; - status = "disabled"; - dtv_demod0 = "AMLDEMOD"; - fe0_dtv_demod = <0>; - fe0_ts = <2>; - fe0_dev = <0>; - dtv_demod0_mem = <0>; - dtv_demod0_spectrum = <1>; - dtv_demod0_cma_flag = <1>; - dtv_demod0_cma_mem_size = <8>; - memory-region = <&demod_cma_reserved>;//<&demod_reserved>; - tuner0 = "si2151_tuner"; - tuner0_i2c_adap_id = <2>; - tuner0_i2c_addr = <0x60>; - //tuner0_reset_value = <0>; - //tuner0_reset_gpio = "GPIOY_10" ; /*GPIOX_8 76*/ - fe0_tuner = <0>; - atv_demod0 = "aml_atv_demod"; - fe0_atv_demod = <0>; - }; thermal-zones { soc_thermal { @@ -1560,7 +1561,7 @@ /*lcd_extern*/ lcd_extern_off_pins:lcd_extern_off_pin { mux { - pins = "GPIOH_2", + groups = "GPIOH_2", "GPIOH_3"; function = "gpio_periphs"; /*output-high;*/ @@ -1572,59 +1573,68 @@ /*backlight*/ bl_pwm_on_pins:bl_pwm_on_pin { mux { - pins = "pwm_b"; + groups = "pwm_b"; function = "pwm_b"; }; }; bl_pwm_vs_on_pins:bl_pwm_vs_on_pin { mux { - pins = "pwm_vs_z6"; + groups = "pwm_vs_z6"; function = "pwm_vs"; }; }; bl_pwm_off_pins:bl_pwm_off_pin { mux { - pins = "GPIOZ_6"; + groups = "GPIOZ_6"; function = "gpio_periphs"; output-low; }; }; bl_pwm_combo_0_on_pins:bl_pwm_combo_0_on_pin { mux { - pins = "pwm_b"; + groups = "pwm_b"; function = "pwm_b"; }; }; bl_pwm_combo_1_on_pins:bl_pwm_combo_1_on_pin { mux { - pins = "pwm_c_z"; + groups = "pwm_c_z"; function = "pwm_c"; }; }; bl_pwm_combo_0_vs_on_pins:bl_pwm_combo_0_vs_on_pin { mux { - pins = "pwm_vs_z6"; + groups = "pwm_vs_z6"; function = "pwm_vs"; }; }; bl_pwm_combo_1_vs_on_pins:bl_pwm_combo_1_vs_on_pin { mux { - pins = "pwm_vs_z7"; + groups = "pwm_vs_z7"; function = "pwm_vs"; }; }; bl_pwm_combo_off_pins:bl_pwm_combo_off_pin { mux { - pins = "GPIOZ_6", + groups = "GPIOZ_6", "GPIOZ_7"; function = "gpio_periphs"; output-low; }; }; + dvb_s_ts0_pins: dvb_s_ts0_pins { + mux { + groups = "tsin_d0_a_dv", + "tsin_clk_a_dv", + "tsin_sop_a_dv", + "tsin_valid_a_dv"; + function = "tsin_a"; + }; + }; }; &uart_A { - status = "okay"; + status = "disabled"; }; &audio_data{ @@ -1649,3 +1659,4 @@ pinctrl-0 = <&spi_a_pins>; cs-gpios = <&gpio GPIOZ_3 0>; }; + diff --git a/arch/arm/configs/meson64_a32_defconfig b/arch/arm/configs/meson64_a32_defconfig index 9cb58f83311c..963dd38cbff3 100644 --- a/arch/arm/configs/meson64_a32_defconfig +++ b/arch/arm/configs/meson64_a32_defconfig @@ -3,6 +3,7 @@ CONFIG_POSIX_MQUEUE=y CONFIG_AUDIT=y CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y +CONFIG_SCHED_WALT=y CONFIG_BSD_PROCESS_ACCT=y CONFIG_TASKSTATS=y CONFIG_TASK_DELAY_ACCT=y @@ -16,9 +17,11 @@ CONFIG_CGROUP_DEBUG=y CONFIG_CGROUP_FREEZER=y CONFIG_CPUSETS=y CONFIG_CGROUP_CPUACCT=y +CONFIG_CGROUP_SCHEDTUNE=y CONFIG_CGROUP_SCHED=y CONFIG_RT_GROUP_SCHED=y CONFIG_CGROUP_BPF=y +CONFIG_SCHED_TUNE=y CONFIG_DEFAULT_USE_ENERGY_AWARE=y CONFIG_BLK_DEV_INITRD=y CONFIG_KALLSYMS_ALL=y @@ -27,7 +30,6 @@ CONFIG_EMBEDDED=y # CONFIG_COMPAT_BRK is not set CONFIG_PROFILING=y CONFIG_JUMP_LABEL=y -CONFIG_CC_STACKPROTECTOR_STRONG=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y CONFIG_MODVERSIONS=y @@ -321,9 +323,11 @@ CONFIG_AMLOGIC_POST_PROCESS_MANAGER_PPSCALER=y CONFIG_AMLOGIC_VIDEOBUF2_ION=y CONFIG_AMLOGIC_IONVIDEO=y CONFIG_AMLOGIC_PIC_DEC=y +CONFIG_AMLOGIC_VIDEOSYNC=y CONFIG_AMLOGIC_MEDIA_ENHANCEMENT=y CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM=y CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION=y +CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_PRIME_SL=y CONFIG_AMLOGIC_MEDIA_GDC=y CONFIG_AMLOGIC_VIDEO_CAPTURE=y CONFIG_AMLOGIC_VM_DISABLE_VIDEOLAYER=y @@ -357,8 +361,11 @@ CONFIG_AMLOGIC_WDT_MESON_V3=y CONFIG_AMLOGIC_ESM=y CONFIG_AMLOGIC_WIFI=y CONFIG_AMLOGIC_BT_DEVICE=y +CONFIG_AMLOGIC_POWER=y CONFIG_AMLOGIC_PCIE=y -CONFIG_AMLOGIC_IRBLASTER=y +CONFIG_AMLOGIC_IRBLASTER_CORE=y +CONFIG_AMLOGIC_IRBLASTER_MESON=y +CONFIG_AMLOGIC_IRBLASTER_PROTOCOL=y CONFIG_AMLOGIC_IIO=y CONFIG_AMLOGIC_SARADC=y CONFIG_AMLOGIC_DDR_TOOL=y @@ -482,10 +489,10 @@ CONFIG_AMLOGIC_SND_CODEC_PCM2BT=y CONFIG_AMLOGIC_SND_CODEC_PDM_DUMMY_CODEC=y CONFIG_AMLOGIC_SND_CODEC_AMLT9015=y CONFIG_AMLOGIC_SND_CODEC_AMLT9015S=y +CONFIG_AMLOGIC_SND_SOC_TAS5805=y CONFIG_AMLOGIC_SND_CODEC_TXLX_ACODEC=y CONFIG_AMLOGIC_SND_CODEC_TL1_ACODEC=y CONFIG_AMLOGIC_SND_SOC_TAS5707=y -CONFIG_AMLOGIC_SND_SOC_TAS5805=y CONFIG_AMLOGIC_SND_SOC_TLV320ADC3101=y CONFIG_AMLOGIC_SND_SOC_PCM186X=y CONFIG_AMLOGIC_SND_SOC_SSM3525=y @@ -590,6 +597,7 @@ CONFIG_SQUASHFS=y CONFIG_PSTORE=y CONFIG_PSTORE_CONSOLE=y CONFIG_PSTORE_PMSG=y +CONFIG_PSTORE_FTRACE=y CONFIG_PSTORE_RAM=y CONFIG_NLS_CODEPAGE_437=y CONFIG_NLS_ISO8859_1=y @@ -618,7 +626,6 @@ CONFIG_LSM_MMAP_MIN_ADDR=0 CONFIG_HARDENED_USERCOPY=y CONFIG_SECURITY_SELINUX=y CONFIG_SECURITY_SMACK=y -CONFIG_CRYPTO_CRYPTD=y CONFIG_CRYPTO_MICHAEL_MIC=y CONFIG_CRYPTO_SHA512=y CONFIG_CRYPTO_TWOFISH=y diff --git a/arch/arm/configs/meson64_a32_smarthome_defconfig b/arch/arm/configs/meson64_a32_smarthome_defconfig index 762fad1e5449..8705513d42aa 100644 --- a/arch/arm/configs/meson64_a32_smarthome_defconfig +++ b/arch/arm/configs/meson64_a32_smarthome_defconfig @@ -294,6 +294,7 @@ CONFIG_AMLOGIC_IONVIDEO=y CONFIG_AMLOGIC_MEDIA_ENHANCEMENT=y CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM=y CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION=y +CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_PRIME_SL=y CONFIG_AMLOGIC_MMC=y CONFIG_AMLOGIC_NAND=y CONFIG_AMLOGIC_VRTC=y @@ -424,6 +425,7 @@ CONFIG_AMLOGIC_SND_CODEC_PCM2BT=y CONFIG_AMLOGIC_SND_CODEC_PDM_DUMMY_CODEC=y CONFIG_AMLOGIC_SND_CODEC_AMLT9015=y CONFIG_AMLOGIC_SND_CODEC_TXLX_ACODEC=y +CONFIG_AMLOGIC_SND_SOC_TAS5782M=y CONFIG_AMLOGIC_SND_SOC_TAS5707=y CONFIG_AMLOGIC_SND_SOC_TLV320ADC3101=y CONFIG_AMLOGIC_SND_SOC_PCM186X=y @@ -553,3 +555,4 @@ CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE=y CONFIG_X509_CERTIFICATE_PARSER=y CONFIG_CRC_T10DIF=y CONFIG_CRC7=y +CONFIG_AMLOGIC_VIDEOSYNC=y diff --git a/arch/arm/include/asm/assembler.h b/arch/arm/include/asm/assembler.h index 7d727506096f..dc53f286905b 100644 --- a/arch/arm/include/asm/assembler.h +++ b/arch/arm/include/asm/assembler.h @@ -208,6 +208,10 @@ THUMB( mov \rd, sp ) THUMB( lsr \rd, \rd, #THREAD_SIZE_ORDER + PAGE_SHIFT ) mov \rd, \rd, lsl #THREAD_SIZE_ORDER + PAGE_SHIFT +#ifdef CONFIG_AMLOGIC_VMAP + add \rd, \rd, #TI_THREAD_SIZE + sub \rd, \rd, #TI_THREAD_INFO_SIZE +#endif .endm /* diff --git a/arch/arm/include/asm/hardirq.h b/arch/arm/include/asm/hardirq.h index f81292dbc46e..3d7351c844aa 100644 --- a/arch/arm/include/asm/hardirq.h +++ b/arch/arm/include/asm/hardirq.h @@ -5,11 +5,7 @@ #include #include -#ifdef CONFIG_AMLOGIC_MODIFY -#define NR_IPI 8 -#else #define NR_IPI 7 -#endif typedef struct { unsigned int __softirq_pending; diff --git a/arch/arm/include/asm/highmem.h b/arch/arm/include/asm/highmem.h index 0a0e2d1784c0..e3ff8a8d2a96 100644 --- a/arch/arm/include/asm/highmem.h +++ b/arch/arm/include/asm/highmem.h @@ -3,7 +3,12 @@ #include +#ifdef CONFIG_AMLOGIC_KASAN32 +#include +#define PKMAP_BASE VMALLOC_END +#else #define PKMAP_BASE (PAGE_OFFSET - PMD_SIZE) +#endif #define LAST_PKMAP PTRS_PER_PTE #define LAST_PKMAP_MASK (LAST_PKMAP - 1) #define PKMAP_NR(virt) (((virt) - PKMAP_BASE) >> PAGE_SHIFT) diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h index 021692c64de3..202cab53d821 100644 --- a/arch/arm/include/asm/io.h +++ b/arch/arm/include/asm/io.h @@ -31,6 +31,9 @@ #include #include +#ifdef CONFIG_AMLOGIC_MODIFY +#include +#endif /* * ISA I/O bus memory addresses are 1:1 with the physical address. */ @@ -73,17 +76,29 @@ void __raw_readsl(const volatile void __iomem *addr, void *data, int longlen); #define __raw_writew __raw_writew static inline void __raw_writew(u16 val, volatile void __iomem *addr) { +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE + pstore_ftrace_io_wr((unsigned long)addr, (unsigned long)val); +#endif asm volatile("strh %1, %0" : : "Q" (*(volatile u16 __force *)addr), "r" (val)); +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE + pstore_ftrace_io_wr_end((unsigned long)addr, (unsigned long)val); +#endif } #define __raw_readw __raw_readw static inline u16 __raw_readw(const volatile void __iomem *addr) { u16 val; +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE + pstore_ftrace_io_rd((unsigned long)addr); +#endif asm volatile("ldrh %0, %1" : "=r" (val) : "Q" (*(volatile u16 __force *)addr)); +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE + pstore_ftrace_io_rd_end((unsigned long)addr); +#endif return val; } #endif @@ -91,24 +106,42 @@ static inline u16 __raw_readw(const volatile void __iomem *addr) #define __raw_writeb __raw_writeb static inline void __raw_writeb(u8 val, volatile void __iomem *addr) { +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE + pstore_ftrace_io_wr((unsigned long)addr, (unsigned long)val); +#endif asm volatile("strb %1, %0" : : "Qo" (*(volatile u8 __force *)addr), "r" (val)); +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE + pstore_ftrace_io_wr_end((unsigned long)addr, (unsigned long)val); +#endif } #define __raw_writel __raw_writel static inline void __raw_writel(u32 val, volatile void __iomem *addr) { +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE + pstore_ftrace_io_wr((unsigned long)addr, (unsigned long)val); +#endif asm volatile("str %1, %0" : : "Qo" (*(volatile u32 __force *)addr), "r" (val)); +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE + pstore_ftrace_io_wr_end((unsigned long)addr, (unsigned long)val); +#endif } #define __raw_readb __raw_readb static inline u8 __raw_readb(const volatile void __iomem *addr) { u8 val; +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE + pstore_ftrace_io_rd((unsigned long)addr); +#endif asm volatile("ldrb %0, %1" : "=r" (val) : "Qo" (*(volatile u8 __force *)addr)); +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE + pstore_ftrace_io_rd_end((unsigned long)addr); +#endif return val; } @@ -116,9 +149,15 @@ static inline u8 __raw_readb(const volatile void __iomem *addr) static inline u32 __raw_readl(const volatile void __iomem *addr) { u32 val; +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE + pstore_ftrace_io_rd((unsigned long)addr); +#endif asm volatile("ldr %0, %1" : "=r" (val) : "Qo" (*(volatile u32 __force *)addr)); +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE + pstore_ftrace_io_rd_end((unsigned long)addr); +#endif return val; } @@ -317,7 +356,13 @@ static inline void memset_io(volatile void __iomem *dst, unsigned c, size_t count) { extern void mmioset(void *, unsigned int, size_t); +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE + pstore_ftrace_io_wr((unsigned long)dst, (unsigned long)count); +#endif mmioset((void __force *)dst, c, count); +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE + pstore_ftrace_io_wr_end((unsigned long)dst, (unsigned long)count); +#endif } #define memset_io(dst,c,count) memset_io(dst,c,count) @@ -325,7 +370,13 @@ static inline void memcpy_fromio(void *to, const volatile void __iomem *from, size_t count) { extern void mmiocpy(void *, const void *, size_t); +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE + pstore_ftrace_io_wr((unsigned long)to, (unsigned long)count); +#endif mmiocpy(to, (const void __force *)from, count); +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE + pstore_ftrace_io_wr_end((unsigned long)to, (unsigned long)count); +#endif } #define memcpy_fromio(to,from,count) memcpy_fromio(to,from,count) @@ -333,7 +384,13 @@ static inline void memcpy_toio(volatile void __iomem *to, const void *from, size_t count) { extern void mmiocpy(void *, const void *, size_t); +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE + pstore_ftrace_io_wr((unsigned long)to, (unsigned long)count); +#endif mmiocpy((void __force *)to, from, count); +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE + pstore_ftrace_io_wr_end((unsigned long)to, (unsigned long)count); +#endif } #define memcpy_toio(to,from,count) memcpy_toio(to,from,count) diff --git a/arch/arm/include/asm/kasan.h b/arch/arm/include/asm/kasan.h new file mode 100644 index 000000000000..7b86cb0096b1 --- /dev/null +++ b/arch/arm/include/asm/kasan.h @@ -0,0 +1,66 @@ +#ifndef __ASM_KASAN_H +#define __ASM_KASAN_H + +#ifndef __ASSEMBLY__ + +#ifdef CONFIG_KASAN + +#include +#include + +#define sym_to_pfn(x) __phys_to_pfn(__pa_symbol(x)) +#define PAGE_KERNEL_RO _MOD_PROT(pgprot_kernel, L_PTE_RDONLY) + +/* + * KASAN_SHADOW_START: beginning of the kernel virtual addresses. + * KASAN_SHADOW_END: KASAN_SHADOW_START + 1/8 of kernel virtual addresses. + * + * For 32bit KASAN, we using a fixed Memory map here + * + * 0x00000000 +--------+ + * | | + * | | + * | | User space memory, 2944MB + * | | + * | | + * 0xb8000000 +--------+ + * | | Kasan shaddow memory, 128MB + * 0xc0000000 +--------+ + * | | Vmalloc address, 240MB + * | | + * 0xCF400000 +--------+ + * 0xCF600000 +--------+ PKmap, for kmap 2MB + * 0xD0000000 +--------+ Module and pkmap, 10MB + * | | + * | | Kernel linear mapped space, 762MB + * 0xFFa00000 +--------+ + * 0xFFFc0000 +--------+ static map, 2MB + * 0xFFF00000 +--------+ Fixed map, for kmap_atomic, 3MB + * 0xFFFF0000 +--------+ High vector, 4KB + * + */ +#define KADDR_SIZE (SZ_1G) +#define KASAN_SHADOW_SIZE (KADDR_SIZE >> 3) +#define KASAN_SHADOW_START (TASK_SIZE) +#define KASAN_SHADOW_END (KASAN_SHADOW_START + KASAN_SHADOW_SIZE) + +/* + * This value is used to map an address to the corresponding shadow + * address by the following formula: + * shadow_addr = (address >> 3) + KASAN_SHADOW_OFFSET; + * + */ +#define KASAN_SHADOW_OFFSET (KASAN_SHADOW_START - (VMALLOC_START >> 3)) +struct map_desc; +void kasan_init(void); +void kasan_copy_shadow(pgd_t *pgdir); +asmlinkage void kasan_early_init(void); +void cpu_v7_set_pte_ext(pte_t *ptep, pte_t pte, unsigned int ext); +void create_mapping(struct map_desc *md); +#else +static inline void kasan_init(void) { } +static inline void kasan_copy_shadow(pgd_t *pgdir) { } +#endif + +#endif +#endif diff --git a/arch/arm/include/asm/memory.h b/arch/arm/include/asm/memory.h index bde40c41c574..f03375912f4e 100644 --- a/arch/arm/include/asm/memory.h +++ b/arch/arm/include/asm/memory.h @@ -33,11 +33,27 @@ #ifdef CONFIG_MMU +#ifdef CONFIG_AMLOGIC_VMAP +/* + * TASK_SIZE - the maximum size of a user space task. + * TASK_UNMAPPED_BASE - the lower boundary of the mmap VM area + */ +#define TASK_SIZE (UL(CONFIG_PAGE_OFFSET) - UL(SZ_64M)) +#elif defined(CONFIG_AMLOGIC_KASAN32) +/* + * reserve 128MB address space for kasan + * for this memory layout implementation, PAGE_OFFSET should be 0xD0000000 + */ +#define VMALLOC_START (UL(CONFIG_PAGE_OFFSET) - UL(SZ_256M)) +#define TASK_SIZE (VMALLOC_START - UL(SZ_128M)) +#define KMEM_END (0xffa00000UL) +#else /* * TASK_SIZE - the maximum size of a user space task. * TASK_UNMAPPED_BASE - the lower boundary of the mmap VM area */ #define TASK_SIZE (UL(CONFIG_PAGE_OFFSET) - UL(SZ_16M)) +#endif /* CONFIG_AMLOGIC_VMAP */ #define TASK_UNMAPPED_BASE ALIGN(TASK_SIZE / 3, SZ_16M) /* @@ -45,16 +61,35 @@ */ #define TASK_SIZE_26 (UL(1) << 26) +#ifdef CONFIG_AMLOGIC_VMAP +#ifndef CONFIG_THUMB2_KERNEL +#define MODULES_VADDR (PAGE_OFFSET - SZ_64M) +#else +#define MODULES_VADDR (PAGE_OFFSET - SZ_8M) +#endif +#else /* CONFIG_AMLOGIC_VMAP */ /* * The module space lives between the addresses given by TASK_SIZE * and PAGE_OFFSET - it must be within 32MB of the kernel text. */ #ifndef CONFIG_THUMB2_KERNEL +#ifdef CONFIG_AMLOGIC_KASAN32 +/* + * to fix module link problem + */ +#define MODULES_VADDR (PAGE_OFFSET - SZ_16M + SZ_4M + SZ_2M) +#else #define MODULES_VADDR (PAGE_OFFSET - SZ_16M) +#endif #else /* smaller range for Thumb-2 symbols relocation (2^24)*/ #define MODULES_VADDR (PAGE_OFFSET - SZ_8M) #endif +#endif /* CONFIG_AMLOGIC_VMAP */ + +#ifdef CONFIG_AMLOGIC_KASAN32 +#define VMALLOC_END (MODULES_VADDR - SZ_2M) +#endif #if TASK_SIZE > MODULES_VADDR #error Top of user space clashes with start of module space @@ -63,11 +98,15 @@ /* * The highmem pkmap virtual space shares the end of the module area. */ +#ifdef CONFIG_AMLOGIC_KASAN32 +#define MODULES_END (PAGE_OFFSET) +#else #ifdef CONFIG_HIGHMEM #define MODULES_END (PAGE_OFFSET - PMD_SIZE) #else #define MODULES_END (PAGE_OFFSET) #endif +#endif /* * The XIP kernel gets mapped at the bottom of the module vm area. diff --git a/arch/arm/include/asm/perf_event.h b/arch/arm/include/asm/perf_event.h index 0142b04a4a0f..6241c4d9de6a 100644 --- a/arch/arm/include/asm/perf_event.h +++ b/arch/arm/include/asm/perf_event.h @@ -31,49 +31,7 @@ extern unsigned long perf_misc_flags(struct pt_regs *regs); } #ifdef CONFIG_AMLOGIC_MODIFY - -extern void armv8pmu_handle_irq_ipi(void); - -struct amlpmu_fixup_cpuinfo { - int irq_num; - - int fix_done; - - unsigned long irq_cnt; - unsigned long empty_irq_cnt; - - unsigned long irq_time; - unsigned long empty_irq_time; - - unsigned long last_irq_cnt; - unsigned long last_empty_irq_cnt; - - unsigned long last_irq_time; - unsigned long last_empty_irq_time; -}; - -struct amlpmu_fixup_context { - struct amlpmu_fixup_cpuinfo __percpu *cpuinfo; - - /* struct arm_pmu */ - void *dev; - - /* sys_cpu_status0 reg */ - unsigned int *sys_cpu_status0; - - /* - * In main pmu irq route wait for other cpu fix done may cause lockup, - * when lockup we disable main irq for a while. - * relax_timer will enable main irq again. - */ - struct hrtimer relax_timer; - - /* dts prop */ - unsigned int sys_cpu_status0_offset; - unsigned int sys_cpu_status0_pmuirq_mask; - unsigned int relax_timer_ns; - unsigned int max_wait_cnt; -}; +void enable_pmuserenr(void); #endif #endif /* __ARM_PERF_EVENT_H__ */ diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h index a8d656d9aec7..b4fe2f6be7d9 100644 --- a/arch/arm/include/asm/pgtable.h +++ b/arch/arm/include/asm/pgtable.h @@ -41,9 +41,11 @@ * The vmalloc() routines leaves a hole of 4kB between each vmalloced * area for the same reason. ;) */ +#ifndef CONFIG_AMLOGIC_KASAN32 #define VMALLOC_OFFSET (8*1024*1024) #define VMALLOC_START (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1)) #define VMALLOC_END 0xff800000UL +#endif /* !CONFIG_AMLOGIC_KASAN32 */ #define LIBRARY_TEXT_START 0x0c000000 diff --git a/arch/arm/include/asm/ptrace.h b/arch/arm/include/asm/ptrace.h index e9c9a117bd25..61bdfc358b75 100644 --- a/arch/arm/include/asm/ptrace.h +++ b/arch/arm/include/asm/ptrace.h @@ -164,9 +164,16 @@ static inline unsigned long user_stack_pointer(struct pt_regs *regs) return regs->ARM_sp; } +#ifdef CONFIG_AMLOGIC_VMAP +#define current_pt_regs(void) ({ (struct pt_regs *) \ + ((current_stack_pointer | (THREAD_SIZE - 1)) - 7 - \ + THREAD_INFO_SIZE) - 1; \ +}) +#else #define current_pt_regs(void) ({ (struct pt_regs *) \ ((current_stack_pointer | (THREAD_SIZE - 1)) - 7) - 1; \ }) +#endif #endif /* __ASSEMBLY__ */ #endif diff --git a/arch/arm/include/asm/string.h b/arch/arm/include/asm/string.h index cf4f3aad0fc1..8b9e9029ab4e 100644 --- a/arch/arm/include/asm/string.h +++ b/arch/arm/include/asm/string.h @@ -26,6 +26,24 @@ extern void * memset(void *, int, __kernel_size_t); extern void __memzero(void *ptr, __kernel_size_t n); +#ifdef CONFIG_AMLOGIC_KASAN32 +/* replace default function to check kasan */ +extern void *__memcpy(void *dst, const void *src, __kernel_size_t size); +extern void *__memmove(void *dst, const void *src, __kernel_size_t size); +extern void *__memset(void *dst, int v, __kernel_size_t size); +#if defined(CONFIG_KASAN) && !defined(__SANITIZE_ADDRESS__) + +/* + * For files that are not instrumented (e.g. mm/slub.c) we + * should use not instrumented version of mem* functions. + */ + +#define memcpy(dst, src, len) __memcpy(dst, src, len) +#define memmove(dst, src, len) __memmove(dst, src, len) +#define memset(s, c, n) __memset(s, c, n) +#endif + +#else #define memset(p,v,n) \ ({ \ void *__p = (p); size_t __n = n; \ @@ -39,3 +57,4 @@ extern void __memzero(void *ptr, __kernel_size_t n); }) #endif +#endif diff --git a/arch/arm/include/asm/thread_info.h b/arch/arm/include/asm/thread_info.h index df8420672c7e..935ec19a5b4d 100644 --- a/arch/arm/include/asm/thread_info.h +++ b/arch/arm/include/asm/thread_info.h @@ -16,9 +16,23 @@ #include #include +#ifdef CONFIG_AMLOGIC_KASAN32 +#define THREAD_SIZE_ORDER 2 +#else #define THREAD_SIZE_ORDER 1 +#endif /* CONFIG_AMLOGIC_KASAN32 */ + #define THREAD_SIZE (PAGE_SIZE << THREAD_SIZE_ORDER) + +#ifdef CONFIG_AMLOGIC_VMAP +#define THREAD_INFO_SIZE (sizeof(struct thread_info)) +#define THREAD_INFO_OFFSET (THREAD_SIZE - THREAD_INFO_SIZE) +#define THREAD_START_SP (THREAD_SIZE - 8 - THREAD_INFO_SIZE) +#define VMAP_RESERVE_SIZE (8 + 4 * 4) +#define VMAP_BACK_SP 12 +#else #define THREAD_START_SP (THREAD_SIZE - 8) +#endif #ifndef __ASSEMBLY__ @@ -88,11 +102,20 @@ register unsigned long current_stack_pointer asm ("sp"); */ static inline struct thread_info *current_thread_info(void) __attribute_const__; +#ifdef CONFIG_AMLOGIC_VMAP +static inline struct thread_info *current_thread_info(void) +{ + return (struct thread_info *) + (((current_stack_pointer & ~(THREAD_SIZE - 1)) + + THREAD_INFO_OFFSET)); +} +#else static inline struct thread_info *current_thread_info(void) { return (struct thread_info *) (current_stack_pointer & ~(THREAD_SIZE - 1)); } +#endif #define thread_saved_pc(tsk) \ ((unsigned long)(task_thread_info(tsk)->cpu_context.pc)) diff --git a/arch/arm/include/asm/uaccess.h b/arch/arm/include/asm/uaccess.h index 0f6c6b873bc5..eec26db9bdd3 100644 --- a/arch/arm/include/asm/uaccess.h +++ b/arch/arm/include/asm/uaccess.h @@ -18,6 +18,9 @@ #include #include #include +#ifdef CONFIG_AMLOGIC_KASAN32 +#include +#endif #ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS #include @@ -581,6 +584,9 @@ __clear_user(void __user *addr, unsigned long n) static inline unsigned long __must_check __copy_from_user(void *to, const void __user *from, unsigned long n) { +#ifdef CONFIG_AMLOGIC_KASAN32 + kasan_check_write(to, n); +#endif check_object_size(to, n, false); return __arch_copy_from_user(to, from, n); } @@ -589,6 +595,9 @@ static inline unsigned long __must_check copy_from_user(void *to, const void __user *from, unsigned long n) { unsigned long res = n; +#ifdef CONFIG_AMLOGIC_KASAN32 + kasan_check_write(to, n); +#endif check_object_size(to, n, false); @@ -602,6 +611,9 @@ copy_from_user(void *to, const void __user *from, unsigned long n) static inline unsigned long __must_check __copy_to_user(void __user *to, const void *from, unsigned long n) { +#ifdef CONFIG_AMLOGIC_KASAN32 + kasan_check_read(from, n); +#endif check_object_size(from, n, true); return __arch_copy_to_user(to, from, n); @@ -610,6 +622,9 @@ __copy_to_user(void __user *to, const void *from, unsigned long n) static inline unsigned long __must_check copy_to_user(void __user *to, const void *from, unsigned long n) { +#ifdef CONFIG_AMLOGIC_KASAN32 + kasan_check_read(from, n); +#endif check_object_size(from, n, true); if (access_ok(VERIFY_WRITE, to, n)) diff --git a/arch/arm/kernel/armksyms.c b/arch/arm/kernel/armksyms.c index 8e8d20cdbce7..dfadaff9f145 100644 --- a/arch/arm/kernel/armksyms.c +++ b/arch/arm/kernel/armksyms.c @@ -181,3 +181,9 @@ EXPORT_SYMBOL(__pv_offset); EXPORT_SYMBOL(__arm_smccc_smc); EXPORT_SYMBOL(__arm_smccc_hvc); #endif + +#ifdef CONFIG_AMLOGIC_KASAN32 +EXPORT_SYMBOL(__memset); +EXPORT_SYMBOL(__memcpy); +EXPORT_SYMBOL(__memmove); +#endif diff --git a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c index 608008229c7d..365842d8a811 100644 --- a/arch/arm/kernel/asm-offsets.c +++ b/arch/arm/kernel/asm-offsets.c @@ -183,5 +183,14 @@ int main(void) #ifdef CONFIG_VDSO DEFINE(VDSO_DATA_SIZE, sizeof(union vdso_data_store)); #endif + +#ifdef CONFIG_AMLOGIC_VMAP + DEFINE(TI_THREAD_START_SP, THREAD_START_SP); + DEFINE(TI_VMAP_BACK_SP, VMAP_BACK_SP); + DEFINE(TI_VMAP_RESERVE_LEN, VMAP_RESERVE_SIZE); + DEFINE(TI_THREAD_SIZE, THREAD_SIZE); + DEFINE(TI_THREAD_INFO_SIZE, sizeof(struct thread_info)); +#endif + return 0; } diff --git a/arch/arm/kernel/cpuidle.c b/arch/arm/kernel/cpuidle.c index a3308ad1a024..b802508813a2 100644 --- a/arch/arm/kernel/cpuidle.c +++ b/arch/arm/kernel/cpuidle.c @@ -13,6 +13,9 @@ #include #include #include +#ifdef CONFIG_AMLOGIC_MODIFY +#include +#endif extern struct of_cpuidle_method __cpuidle_method_of_table[]; @@ -51,9 +54,22 @@ int arm_cpuidle_simple_enter(struct cpuidle_device *dev, */ int arm_cpuidle_suspend(int index) { +#ifdef CONFIG_AMLOGIC_MODIFY + int ret; + int cpu = smp_processor_id(); + + ret = cpuidle_ops[cpu].suspend(index); + + if (index > 0) { + pr_debug("arm_cpuidle_suspend(%d) exit\n", index); + enable_pmuserenr(); + } + return ret; +#else int cpu = smp_processor_id(); return cpuidle_ops[cpu].suspend(index); +#endif } /** @@ -135,7 +151,7 @@ static int __init arm_cpuidle_read_ops(struct device_node *dn, int cpu) * this cpu, * -ENOENT if it fails to find an 'enable-method' property, * -ENXIO if the HW reports a failure or a misconfiguration, - * -ENOMEM if the HW report an memory allocation failure + * -ENOMEM if the HW report an memory allocation failure */ int __init arm_cpuidle_init(int cpu) { diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index 9f157e7c51e7..51c5758fdcea 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S @@ -39,15 +39,28 @@ * Interrupt handling. */ .macro irq_handler +#ifdef CONFIG_AMLOGIC_VMAP + mov r8, sp /* back up sp */ + mov r0, sp + bl irq_stack_entry /* switch IRQ stack */ + mov sp, r0 +#endif #ifdef CONFIG_MULTI_IRQ_HANDLER ldr r1, =handle_arch_irq +#ifdef CONFIG_AMLOGIC_VMAP + mov r0, r8 +#else mov r0, sp +#endif badr lr, 9997f ldr pc, [r1] #else arch_irq_handler_default #endif 9997: +#ifdef CONFIG_AMLOGIC_VMAP + mov sp, r8 /* switch stack back to task stack */ +#endif .endm .macro pabt_helper @@ -149,10 +162,24 @@ ENDPROC(__und_invalid) #define SPFIX(code...) #endif +#ifdef CONFIG_AMLOGIC_VMAP + .macro svc_entry, stack_hole=0, trace=1, uaccess=1, vmap=0 +#else .macro svc_entry, stack_hole=0, trace=1, uaccess=1 +#endif UNWIND(.fnstart ) UNWIND(.save {r0 - pc} ) +#ifdef CONFIG_AMLOGIC_VMAP + .if \vmap + /* keep using stack of abt mode */ + str sp, [r0, #TI_VMAP_BACK_SP] + sub sp, r0, #(SVC_REGS_SIZE + \stack_hole - 4) + .else sub sp, sp, #(SVC_REGS_SIZE + \stack_hole - 4) + .endif +#else /* !CONFIG_AMLOGIC_VMAP */ + sub sp, sp, #(SVC_REGS_SIZE + \stack_hole - 4) +#endif /* CONFIG_AMLOGIC_VMAP */ #ifdef CONFIG_THUMB2_KERNEL SPFIX( str r0, [sp] ) @ temporarily saved SPFIX( mov r0, sp ) @@ -167,7 +194,15 @@ ENDPROC(__und_invalid) ldmia r0, {r3 - r5} add r7, sp, #S_SP - 4 @ here for interlock avoidance mov r6, #-1 @ "" "" "" "" +#ifdef CONFIG_AMLOGIC_VMAP + .if \vmap + ldr r2, [sp, #(TI_VMAP_BACK_SP + SVC_REGS_SIZE - 4)] + .else add r2, sp, #(SVC_REGS_SIZE + \stack_hole - 4) + .endif +#else + add r2, sp, #(SVC_REGS_SIZE + \stack_hole - 4) +#endif SPFIX( addeq r2, r2, #4 ) str r3, [sp, #-4]! @ save the "real" r0 copied @ from the exception stack @@ -185,7 +220,44 @@ ENDPROC(__und_invalid) @ stmia r7, {r2 - r6} +#ifdef CONFIG_AMLOGIC_VMAP + .if \vmap + /* + * get fault task thread info + */ + ldr r0, [sp, #(SVC_REGS_SIZE + TI_VMAP_BACK_SP)] + mrc p15, 0, r1, c6, c0, 0 @ get FAR + bl pmd_check + mov tsk, r0 + mov tsk, tsk, lsr #THREAD_SIZE_ORDER + PAGE_SHIFT + mov tsk, tsk, lsl #THREAD_SIZE_ORDER + PAGE_SHIFT + add tsk, tsk, #TI_THREAD_SIZE + sub tsk, tsk, #TI_THREAD_INFO_SIZE + + /* + * copy some important member of thread_info from current + * task to vmap stack + */ + ldr r0, [tsk, #TI_FLAGS] + ldr r1, [tsk, #TI_PREEMPT] + str r0, [sp, #(SVC_REGS_SIZE + TI_VMAP_RESERVE_LEN + TI_FLAGS)] + str r1, [sp, #(SVC_REGS_SIZE + TI_VMAP_RESERVE_LEN + TI_PREEMPT)] + + ldr r0, [tsk, #TI_ADDR_LIMIT] + ldr r1, [tsk, #TI_TASK] + str r0, [sp, #(SVC_REGS_SIZE + TI_VMAP_RESERVE_LEN + TI_ADDR_LIMIT)] + str r1, [sp, #(SVC_REGS_SIZE + TI_VMAP_RESERVE_LEN + TI_TASK)] + + ldr r0, [tsk, #TI_CPU] + ldr r1, [tsk, #TI_CPU_DOMAIN] + str r0, [sp, #(SVC_REGS_SIZE + TI_VMAP_RESERVE_LEN + TI_CPU)] + str r1, [sp, #(SVC_REGS_SIZE + TI_VMAP_RESERVE_LEN + TI_CPU_DOMAIN)] + .else get_thread_info tsk + .endif +#else + get_thread_info tsk +#endif ldr r0, [tsk, #TI_ADDR_LIMIT] mov r1, #TASK_SIZE str r1, [tsk, #TI_ADDR_LIMIT] @@ -205,7 +277,28 @@ ENDPROC(__und_invalid) .align 5 __dabt_svc: +#ifdef CONFIG_AMLOGIC_VMAP + svc_entry uaccess=0, vmap=1 + mrc p15, 0, r1, c5, c0, 0 @ get FSR + mrc p15, 0, r0, c6, c0, 0 @ get FAR + mov r2, sp + uaccess_disable ip @ disable userspace access + bl handle_vmap_fault + cmp r0, #0 + bne .L__dabt_svc_next + /* handled by vmap fault handler */ + svc_exit r5, vmap=1 @ return from exception +.L__dabt_svc_next: + /* re-build context for normal abort handler */ + ldr r0, [sp, #(SVC_REGS_SIZE + TI_VMAP_BACK_SP)] + sub r0, #SVC_REGS_SIZE + mov r1, sp + mov r2, #SVC_REGS_SIZE + bl memcpy /* copy back sp */ + mov sp, r0 +#else svc_entry uaccess=0 +#endif mov r2, sp dabt_helper THUMB( ldr r5, [sp, #S_PSR] ) @ potentially updated CPSR diff --git a/arch/arm/kernel/entry-header.S b/arch/arm/kernel/entry-header.S index fa7c6e5c17e7..0b692a3da507 100644 --- a/arch/arm/kernel/entry-header.S +++ b/arch/arm/kernel/entry-header.S @@ -197,7 +197,11 @@ .endm +#ifdef CONFIG_AMLOGIC_VMAP + .macro svc_exit, rpsr, irq = 0, vmap = 0 +#else .macro svc_exit, rpsr, irq = 0 +#endif /* CONFIG_AMLOGIC_VMAP */ .if \irq != 0 @ IRQs already off #ifdef CONFIG_TRACE_IRQFLAGS @@ -224,7 +228,16 @@ msr spsr_cxsf, \rpsr #if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_32v6K) @ We must avoid clrex due to Cortex-A15 erratum #830321 +#ifdef CONFIG_AMLOGIC_VMAP + .if \vmap + ldr r0, [sp, #(SVC_REGS_SIZE + TI_VMAP_BACK_SP)] + sub r0, r0, #4 @ uninhabited address + .else sub r0, sp, #4 @ uninhabited address + .endif +#else + sub r0, sp, #4 @ uninhabited address +#endif /* CONFIG_AMLOGIC_VMAP */ strex r1, r2, [r0] @ clear the exclusive monitor #endif ldmia sp, {r0 - pc}^ @ load r0 - pc, cpsr diff --git a/arch/arm/kernel/head-common.S b/arch/arm/kernel/head-common.S index 7e662bdd5cb3..165b95a1b91c 100644 --- a/arch/arm/kernel/head-common.S +++ b/arch/arm/kernel/head-common.S @@ -101,6 +101,9 @@ __mmap_switched: str r2, [r6] @ Save atags pointer cmp r7, #0 strne r0, [r7] @ Save control register values +#ifdef CONFIG_AMLOGIC_KASAN32 + bl kasan_early_init +#endif b start_kernel ENDPROC(__mmap_switched) @@ -119,7 +122,11 @@ __mmap_switched_data: #else .long 0 @ r7 #endif +#ifdef CONFIG_AMLOGIC_VMAP + .long init_thread_union + TI_THREAD_START_SP @ sp +#else .long init_thread_union + THREAD_START_SP @ sp +#endif .size __mmap_switched_data, . - __mmap_switched_data __FINIT diff --git a/arch/arm/kernel/hw_breakpoint.c b/arch/arm/kernel/hw_breakpoint.c index 25538a935874..bc8f9b1b752c 100644 --- a/arch/arm/kernel/hw_breakpoint.c +++ b/arch/arm/kernel/hw_breakpoint.c @@ -102,7 +102,11 @@ static u8 max_watchpoint_len; WRITE_WB_REG_CASE(OP2, 14, VAL); \ WRITE_WB_REG_CASE(OP2, 15, VAL) +#ifdef CONFIG_AMLOGIC_MODIFY +u32 read_wb_reg(int n) +#else static u32 read_wb_reg(int n) +#endif { u32 val = 0; diff --git a/arch/arm/kernel/module.c b/arch/arm/kernel/module.c index 4f14b5ce6535..cb235c9a0b61 100644 --- a/arch/arm/kernel/module.c +++ b/arch/arm/kernel/module.c @@ -25,6 +25,9 @@ #include #include #include +#ifdef CONFIG_AMLOGIC_KASAN32 +#include +#endif #ifdef CONFIG_XIP_KERNEL /* @@ -40,6 +43,20 @@ #ifdef CONFIG_MMU void *module_alloc(unsigned long size) { +#ifdef CONFIG_AMLOGIC_KASAN32 + void *p = __vmalloc_node_range(size, MODULE_ALIGN, MODULES_VADDR, + MODULES_END, GFP_KERNEL, PAGE_KERNEL_EXEC, 0, + NUMA_NO_NODE, __builtin_return_address(0)); + if (!p) + p = __vmalloc_node_range(size, MODULE_ALIGN, VMALLOC_START, + VMALLOC_END, GFP_KERNEL, PAGE_KERNEL_EXEC, 0, + NUMA_NO_NODE, __builtin_return_address(0)); + if (p && (kasan_module_alloc(p, size) < 0)) { + vfree(p); + return NULL; + } + return p; +#else void *p = __vmalloc_node_range(size, 1, MODULES_VADDR, MODULES_END, GFP_KERNEL, PAGE_KERNEL_EXEC, 0, NUMA_NO_NODE, __builtin_return_address(0)); @@ -48,6 +65,7 @@ void *module_alloc(unsigned long size) return __vmalloc_node_range(size, 1, VMALLOC_START, VMALLOC_END, GFP_KERNEL, PAGE_KERNEL_EXEC, 0, NUMA_NO_NODE, __builtin_return_address(0)); +#endif } #endif diff --git a/arch/arm/kernel/perf_event_v7.c b/arch/arm/kernel/perf_event_v7.c index e811beb08e87..2cfc7f030076 100644 --- a/arch/arm/kernel/perf_event_v7.c +++ b/arch/arm/kernel/perf_event_v7.c @@ -18,10 +18,6 @@ #ifdef CONFIG_CPU_V7 -#ifdef CONFIG_AMLOGIC_MODIFY -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -#endif - #include #include #include @@ -33,18 +29,9 @@ #include #ifdef CONFIG_AMLOGIC_MODIFY -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include #endif - /* * Common ARMv7 event types * @@ -963,160 +950,13 @@ static void armv7pmu_disable_event(struct perf_event *event) } #ifdef CONFIG_AMLOGIC_MODIFY -static struct amlpmu_fixup_context amlpmu_fixup_ctx; - -static enum hrtimer_restart amlpmu_relax_timer_func(struct hrtimer *timer) -{ - struct amlpmu_fixup_cpuinfo *ci; - - ci = per_cpu_ptr(amlpmu_fixup_ctx.cpuinfo, 0); - - pr_alert("enable cpu0_irq %d again, irq cnt = %lu\n", - ci->irq_num, - ci->irq_cnt); - enable_irq(ci->irq_num); - - return HRTIMER_NORESTART; -} - - -static void amlpmu_relax_timer_start(int other_cpu) -{ - struct amlpmu_fixup_cpuinfo *ci; - int cpu; - - cpu = smp_processor_id(); - WARN_ON(cpu != 0); - - ci = per_cpu_ptr(amlpmu_fixup_ctx.cpuinfo, 0); - - pr_alert("wait cpu %d fixup done timeout, main cpu irq cnt = %lu\n", - other_cpu, - ci->irq_cnt); - - if (hrtimer_active(&amlpmu_fixup_ctx.relax_timer)) { - pr_alert("relax_timer already active, return!\n"); - return; - } - - disable_irq_nosync(ci->irq_num); - - hrtimer_start(&amlpmu_fixup_ctx.relax_timer, - ns_to_ktime(amlpmu_fixup_ctx.relax_timer_ns), - HRTIMER_MODE_REL); -} +#include static irqreturn_t armv7pmu_handle_irq(int irq_num, void *dev); -void armv8pmu_handle_irq_ipi(void) +void amlpmu_handle_irq_ipi(void *arg) { - int cpu = smp_processor_id(); - - WARN_ON(cpu == 0); - WARN_ON(!amlpmu_fixup_ctx.dev); - - armv7pmu_handle_irq(-1, amlpmu_fixup_ctx.dev); -} - -static int aml_pmu_fix(void) -{ - int i; - int cpu; - int pmuirq_val; - struct amlpmu_fixup_cpuinfo *ci; - - int max_wait_cnt = amlpmu_fixup_ctx.max_wait_cnt; - - pmuirq_val = readl(amlpmu_fixup_ctx.sys_cpu_status0); - pmuirq_val &= amlpmu_fixup_ctx.sys_cpu_status0_pmuirq_mask; - - for (cpu = 0; cpu < num_possible_cpus(); cpu++) { - if (pmuirq_val & (1<fix_done = 0; - - /* aml pmu IPI will set fix_done to 1 */ - mb(); - - smp_send_aml_pmu(cpu); - - for (i = 0; i < max_wait_cnt; i++) { - if (READ_ONCE(ci->fix_done)) - break; - - udelay(1); - } - - if (i == amlpmu_fixup_ctx.max_wait_cnt) - amlpmu_relax_timer_start(cpu); - - return 0; - } - } - } - - return 1; -} - -static void aml_pmu_fix_stat_account(int is_empty_irq) -{ - int freq; - unsigned long time = jiffies; - struct amlpmu_fixup_cpuinfo *ci; - - ci = this_cpu_ptr(amlpmu_fixup_ctx.cpuinfo); - - ci->irq_cnt++; - ci->irq_time = time; - if (!ci->last_irq_cnt) { - ci->last_irq_cnt = ci->irq_cnt; - ci->last_irq_time = ci->irq_time; - } - - if (is_empty_irq) { - ci->empty_irq_cnt++; - ci->empty_irq_time = time; - if (!ci->last_empty_irq_cnt) { - ci->last_empty_irq_cnt = ci->empty_irq_cnt; - ci->last_empty_irq_time = ci->empty_irq_time; - } - } - - if (time_after(ci->irq_time, ci->last_irq_time + HZ)) { - freq = ci->irq_cnt - ci->last_irq_cnt; - freq = freq * HZ / (ci->irq_time - ci->last_irq_time); - pr_debug("irq_cnt = %lu, irq_last_cnt = %lu, freq = %d\n", - ci->irq_cnt, - ci->last_irq_cnt, - freq); - - ci->last_irq_cnt = ci->irq_cnt; - ci->last_irq_time = ci->irq_time; - } - - if (is_empty_irq && - time_after(ci->empty_irq_time, ci->last_empty_irq_time + HZ)) { - - freq = ci->empty_irq_cnt - ci->last_empty_irq_cnt; - freq *= HZ; - freq /= (ci->empty_irq_time - ci->last_empty_irq_time); - pr_debug("empty_irq_cnt = %lu, freq = %d\n", - ci->empty_irq_cnt, - freq); - - ci->last_empty_irq_cnt = ci->empty_irq_cnt; - ci->last_empty_irq_time = ci->empty_irq_time; - } + armv7pmu_handle_irq(-1, amlpmu_ctx.pmu); } #endif @@ -1129,47 +969,25 @@ static irqreturn_t armv7pmu_handle_irq(int irq_num, void *dev) struct pt_regs *regs; int idx; -#ifdef CONFIG_AMLOGIC_MODIFY - int cpu; - int is_empty_irq = 0; - struct amlpmu_fixup_cpuinfo *ci; - - ci = this_cpu_ptr(amlpmu_fixup_ctx.cpuinfo); - ci->irq_num = irq_num; - amlpmu_fixup_ctx.dev = dev; - cpu = smp_processor_id(); -#endif - /* * Get and reset the IRQ flags */ pmnc = armv7_pmnc_getreset_flags(); #ifdef CONFIG_AMLOGIC_MODIFY - ci->fix_done = 1; -#endif - + /* amlpmu have routed the interrupt successfully, return IRQ_HANDLED */ + if (amlpmu_handle_irq(cpu_pmu, + irq_num, + armv7_pmnc_has_overflowed(pmnc))) + return IRQ_HANDLED; +#else /* * Did an overflow occur? */ -#ifdef CONFIG_AMLOGIC_MODIFY - if (!armv7_pmnc_has_overflowed(pmnc)) { - is_empty_irq = 1; - - if (cpu == 0) - is_empty_irq = aml_pmu_fix(); - } - - aml_pmu_fix_stat_account(is_empty_irq); - - /* txlx have some empty pmu irqs, so return IRQ_HANDLED */ - if (is_empty_irq) - return IRQ_HANDLED; -#else if (!armv7_pmnc_has_overflowed(pmnc)) return IRQ_NONE; - #endif + /* * Handle the counter(s) overflow(s) */ @@ -2225,76 +2043,74 @@ static const struct pmu_probe_info armv7_pmu_probe_table[] = { }; #ifdef CONFIG_AMLOGIC_MODIFY -static int amlpmu_fixup_init(struct platform_device *pdev) +#if 0 +static int read_pmuserenr(void) { - int ret; - void __iomem *base; + int val = -1; - amlpmu_fixup_ctx.cpuinfo = __alloc_percpu( - sizeof(struct amlpmu_fixup_cpuinfo), 2 * sizeof(void *)); - if (!amlpmu_fixup_ctx.cpuinfo) { - pr_err("alloc percpu failed\n"); - return -ENOMEM; + asm volatile("mrc p15, 0, %0, c9, c14, 0" : "=r" (val):: "memory"); + return val; +} +#endif + +void enable_pmuserenr(void) +{ + //pr_emerg("enable_pmuserenr() start, val = %d\n", read_pmuserenr()); + asm volatile("mcr p15, 0, %0, c9, c14, 0" : : "r" (1) : "memory"); + //pr_emerg("enable_pmuserenr() end, val = %d\n", read_pmuserenr()); +} + +static void enable_pmuserenr_single(void *info) +{ + enable_pmuserenr(); +} + +static void enable_pmuserenr_all(void) +{ + pr_info("enable_pmuserenr_all() start\n"); + + enable_pmuserenr_single(NULL); + smp_call_function_many(cpu_possible_mask, + enable_pmuserenr_single, + NULL, + 1); + + pr_info("enable_pmuserenr_all() end\n"); +} + +static int pmu_user_callback(struct notifier_block *nfb, + unsigned long action, + void *hcpu) +{ + switch (action) { + case CPU_ONLINE: + case CPU_ONLINE_FROZEN: + pr_debug("cpu online callback\n"); + enable_pmuserenr(); + break; + default: + break; } + return NOTIFY_OK; +} - base = of_iomap(pdev->dev.of_node, 0); - if (IS_ERR(base)) { - pr_err("of_iomap() failed, base = %p\n", base); - return PTR_ERR(base); - } +static struct notifier_block pmu_user_notify = { + &pmu_user_callback, + NULL, + 0 +}; - ret = of_property_read_u32(pdev->dev.of_node, - "sys_cpu_status0_offset", - &amlpmu_fixup_ctx.sys_cpu_status0_offset); - if (ret) { - pr_err("read sys_cpu_status0_offset failed, ret = %d\n", ret); - return 1; - } - pr_debug("sys_cpu_status0_offset = 0x%0x\n", - amlpmu_fixup_ctx.sys_cpu_status0_offset); - - ret = of_property_read_u32(pdev->dev.of_node, - "sys_cpu_status0_pmuirq_mask", - &amlpmu_fixup_ctx.sys_cpu_status0_pmuirq_mask); - if (ret) { - pr_err("read sys_cpu_status0_pmuirq_mask failed, ret = %d\n", - ret); - return 1; - } - pr_debug("sys_cpu_status0_pmuirq_mask = 0x%0x\n", - amlpmu_fixup_ctx.sys_cpu_status0_pmuirq_mask); - - - ret = of_property_read_u32(pdev->dev.of_node, - "relax_timer_ns", - &amlpmu_fixup_ctx.relax_timer_ns); - if (ret) { - pr_err("read prop relax_timer_ns failed, ret = %d\n", ret); - return 1; - } - pr_debug("relax_timer_ns = %u\n", amlpmu_fixup_ctx.relax_timer_ns); - - - ret = of_property_read_u32(pdev->dev.of_node, - "max_wait_cnt", - &amlpmu_fixup_ctx.max_wait_cnt); - if (ret) { - pr_err("read prop max_wait_cnt failed, ret = %d\n", ret); - return 1; - } - pr_debug("max_wait_cnt = %u\n", amlpmu_fixup_ctx.max_wait_cnt); - - - base += (amlpmu_fixup_ctx.sys_cpu_status0_offset << 2); - amlpmu_fixup_ctx.sys_cpu_status0 = base; - pr_debug("sys_cpu_status0 = %p\n", amlpmu_fixup_ctx.sys_cpu_status0); - - - hrtimer_init(&amlpmu_fixup_ctx.relax_timer, - CLOCK_MONOTONIC, - HRTIMER_MODE_REL); - amlpmu_fixup_ctx.relax_timer.function = amlpmu_relax_timer_func; +static int armv7_pmu_resume(struct platform_device *pdev) +{ + pr_debug("armv7_pmu_resume()\n"); + enable_pmuserenr(); + return 0; +} +static int armv7_pmu_suspend(struct platform_device *pdev, + pm_message_t state) +{ + pr_debug("armv7_pmu_suspend()\n"); return 0; } #endif @@ -2302,8 +2118,8 @@ static int amlpmu_fixup_init(struct platform_device *pdev) static int armv7_pmu_device_probe(struct platform_device *pdev) { #ifdef CONFIG_AMLOGIC_MODIFY - if (amlpmu_fixup_init(pdev)) - return 1; + enable_pmuserenr_all(); + __register_cpu_notifier(&pmu_user_notify); #endif return arm_pmu_device_probe(pdev, armv7_pmu_of_device_ids, @@ -2316,6 +2132,10 @@ static struct platform_driver armv7_pmu_driver = { .of_match_table = armv7_pmu_of_device_ids, }, .probe = armv7_pmu_device_probe, +#ifdef CONFIG_AMLOGIC_MODIFY + .suspend = armv7_pmu_suspend, + .resume = armv7_pmu_resume, +#endif }; static int __init register_armv7_pmu_driver(void) diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c index 324b32b2ed67..c0c17304221e 100644 --- a/arch/arm/kernel/process.c +++ b/arch/arm/kernel/process.c @@ -350,6 +350,23 @@ done: pr_cont("%s", name); pr_cont("\n"); } + +static void show_vmalloc_pfn(struct pt_regs *regs) +{ + int i; + struct page *page; + + for (i = 0; i < 16; i++) { + if (is_vmalloc_or_module_addr((void *)regs->uregs[i])) { + page = vmalloc_to_page((void *)regs->uregs[i]); + if (!page) + continue; + pr_info("R%-2d : %08lx, PFN:%5lx\n", + i, regs->uregs[i], page_to_pfn(page)); + } + } + +} #endif /* CONFIG_AMLOGIC_USER_FAULT */ void __show_regs(struct pt_regs *regs) @@ -408,6 +425,10 @@ void __show_regs(struct pt_regs *regs) buf[3] = flags & PSR_V_BIT ? 'V' : 'v'; buf[4] = '\0'; +#ifdef CONFIG_AMLOGIC_USER_FAULT + show_vmalloc_pfn(regs); +#endif + #ifndef CONFIG_CPU_V7M { const char *segment; diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index 6d1b6074dd4d..f318e5a6721a 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c @@ -62,9 +62,15 @@ #include #include #include +#ifdef CONFIG_AMLOGIC_VMAP +#include +#endif #ifdef CONFIG_AMLOGIC_CPU_INFO #include #endif +#ifdef CONFIG_AMLOGIC_KASAN32 +#include +#endif #include "atags.h" @@ -520,6 +526,17 @@ static void __init elf_hwcap_fixup(void) elf_hwcap &= ~HWCAP_SWP; } +#ifdef CONFIG_AMLOGIC_VMAP +static void __init fixup_init_thread_union(void) +{ + void *p; + + p = (void *)((unsigned long)&init_thread_union + THREAD_INFO_OFFSET); + memcpy(p, &init_thread_union, THREAD_INFO_SIZE); + memset(&init_thread_union, 0, THREAD_INFO_SIZE); +} +#endif + /* * cpu_init - initialise one CPU. * @@ -583,6 +600,9 @@ void notrace cpu_init(void) "I" (offsetof(struct stack, fiq[0])), PLC (PSR_F_BIT | PSR_I_BIT | SVC_MODE) : "r14"); +#ifdef CONFIG_AMLOGIC_VMAP + __setup_vmap_stack(cpu); +#endif #endif } @@ -605,6 +625,9 @@ void __init smp_setup_processor_id(void) */ set_my_cpu_offset(0); +#ifdef CONFIG_AMLOGIC_VMAP + fixup_init_thread_union(); +#endif pr_info("Booting Linux on physical CPU 0x%x\n", mpidr); } @@ -1117,6 +1140,9 @@ void __init setup_arch(char **cmdline_p) early_ioremap_reset(); paging_init(mdesc); +#ifdef CONFIG_AMLOGIC_KASAN32 + kasan_init(); +#endif request_standard_resources(mdesc); if (mdesc->restart) diff --git a/arch/arm/kernel/sleep.S b/arch/arm/kernel/sleep.S index 0f6c1000582c..dd52f5c182e4 100644 --- a/arch/arm/kernel/sleep.S +++ b/arch/arm/kernel/sleep.S @@ -136,7 +136,12 @@ ARM_BE8(setend be) @ ensure we are in BE mode safe_svcmode_maskall r1 mov r1, #0 ALT_SMP(mrc p15, 0, r0, c0, c0, 5) + ALT_SMP(and r2, r0, #1<<24) + ALT_SMP(cmp r2, #0) + ALT_SMP(beq 2f) + ALT_SMP(lsr r0, r0, #8) ALT_UP_B(1f) +2: adr r2, mpidr_hash_ptr ldr r3, [r2] add r2, r2, r3 @ r2 = struct mpidr_hash phys address diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index a116c7e981bd..2764133c3e51 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c @@ -51,10 +51,6 @@ #include #include -#ifdef CONFIG_AMLOGIC_MODIFY -#include -#endif - #define CREATE_TRACE_POINTS #include @@ -79,9 +75,6 @@ enum ipi_msg_type { IPI_CPU_STOP, IPI_IRQ_WORK, IPI_COMPLETION, - #ifdef CONFIG_AMLOGIC_MODIFY - IPI_AML_PMU, - #endif IPI_CPU_BACKTRACE, /* * SGI8-15 can be reserved by secure firmware, and thus may @@ -364,11 +357,20 @@ void arch_cpu_idle_dead(void) * cpu initialisation. There's some initialisation which needs * to be repeated to undo the effects of taking the CPU offline. */ +#ifdef CONFIG_AMLOGIC_VMAP + __asm__("mov sp, %0\n" + " mov fp, #0\n" + " b secondary_start_kernel" + : + : "r" (task_stack_page(current) + THREAD_SIZE - 8 - + THREAD_INFO_SIZE)); +#else __asm__("mov sp, %0\n" " mov fp, #0\n" " b secondary_start_kernel" : : "r" (task_stack_page(current) + THREAD_SIZE - 8)); +#endif } #endif /* CONFIG_HOTPLUG_CPU */ @@ -525,9 +527,6 @@ static const char *ipi_types[NR_IPI] __tracepoint_string = { S(IPI_CPU_STOP, "CPU stop interrupts"), S(IPI_IRQ_WORK, "IRQ work interrupts"), S(IPI_COMPLETION, "completion interrupts"), -#ifdef CONFIG_AMLOGIC_MODIFY - S(IPI_AML_PMU, "AML pmu cross interrupts"), -#endif }; static void smp_cross_call(const struct cpumask *target, unsigned int ipinr) @@ -536,13 +535,6 @@ static void smp_cross_call(const struct cpumask *target, unsigned int ipinr) __smp_cross_call(target, ipinr); } -#ifdef CONFIG_AMLOGIC_MODIFY -void smp_send_aml_pmu(int cpu) -{ - smp_cross_call(cpumask_of(cpu), IPI_AML_PMU); -} -#endif - void show_ipi_list(struct seq_file *p, int prec) { unsigned int cpu, i; @@ -706,12 +698,6 @@ void handle_IPI(int ipinr, struct pt_regs *regs) printk_nmi_exit(); break; -#ifdef CONFIG_AMLOGIC_MODIFY - case IPI_AML_PMU: - armv8pmu_handle_irq_ipi(); - break; -#endif - default: pr_crit("CPU%u: Unknown IPI message 0x%x\n", cpu, ipinr); diff --git a/arch/arm/kernel/suspend.c b/arch/arm/kernel/suspend.c index 134f0d432610..d80cb970d9f8 100644 --- a/arch/arm/kernel/suspend.c +++ b/arch/arm/kernel/suspend.c @@ -11,6 +11,10 @@ #include #include +#ifdef CONFIG_AMLOGIC_VMAP +#include +#endif + extern int __cpu_suspend(unsigned long, int (*)(unsigned long), u32 cpuid); extern void cpu_resume_mmu(void); @@ -49,6 +53,27 @@ int cpu_suspend(unsigned long arg, int (*fn)(unsigned long)) #define idmap_pgd NULL #endif +#ifdef CONFIG_AMLOGIC_VMAP +void copy_pgd(void) +{ + unsigned long index; + pgd_t *pgd_c = NULL, *pgd_k, *pgd_i; + unsigned long size; + + /* + * sync pgd of current task and idmap_pgd from init mm + */ + index = pgd_index(TASK_SIZE); + pgd_c = cpu_get_pgd() + index; + pgd_i = idmap_pgd + index; + pgd_k = init_mm.pgd + index; + size = (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t); + pr_debug("pgd:%p, pgd_k:%p, pdg_i:%p\n", + pgd_c, pgd_k, pgd_i); + memcpy(pgd_c, pgd_k, size); + memcpy(pgd_i, pgd_k, size); +} +#endif /* * This is called by __cpu_suspend() to save the state, and do whatever * flushing is required to ensure that when the CPU goes to sleep we have @@ -58,7 +83,21 @@ void __cpu_suspend_save(u32 *ptr, u32 ptrsz, u32 sp, u32 *save_ptr) { u32 *ctx = ptr; +#ifdef CONFIG_AMLOGIC_VMAP + if (likely(is_vmap_addr((unsigned long)ptr))) { + struct page *page = vmalloc_to_page(ptr); + unsigned long offset; + + offset = (unsigned long)ptr & (PAGE_SIZE - 1); + *save_ptr = (page_to_phys(page) + offset); + pr_debug("%s, ptr:%p, page:%lx, save_ptr:%x\n", + __func__, ptr, page_to_pfn(page), *save_ptr); + copy_pgd(); + } else + *save_ptr = virt_to_phys(ptr); +#else *save_ptr = virt_to_phys(ptr); +#endif /* This must correspond to the LDM in cpu_resume() assembly */ *ptr++ = virt_to_phys(idmap_pgd); diff --git a/arch/arm/kernel/unwind.c b/arch/arm/kernel/unwind.c index 314cfb232a63..4682dd2485c0 100644 --- a/arch/arm/kernel/unwind.c +++ b/arch/arm/kernel/unwind.c @@ -44,6 +44,10 @@ #include #include #include +#ifdef CONFIG_AMLOGIC_VMAP +#include +#include +#endif #include #include @@ -93,7 +97,7 @@ extern const struct unwind_idx __start_unwind_idx[]; static const struct unwind_idx *__origin_unwind_idx; extern const struct unwind_idx __stop_unwind_idx[]; -static DEFINE_RAW_SPINLOCK(unwind_lock); +static DEFINE_SPINLOCK(unwind_lock); static LIST_HEAD(unwind_tables); /* Convert a prel31 symbol to an absolute address */ @@ -201,7 +205,7 @@ static const struct unwind_idx *unwind_find_idx(unsigned long addr) /* module unwind tables */ struct unwind_table *table; - raw_spin_lock_irqsave(&unwind_lock, flags); + spin_lock_irqsave(&unwind_lock, flags); list_for_each_entry(table, &unwind_tables, list) { if (addr >= table->begin_addr && addr < table->end_addr) { @@ -213,7 +217,7 @@ static const struct unwind_idx *unwind_find_idx(unsigned long addr) break; } } - raw_spin_unlock_irqrestore(&unwind_lock, flags); + spin_unlock_irqrestore(&unwind_lock, flags); } pr_debug("%s: idx = %p\n", __func__, idx); @@ -242,8 +246,21 @@ static unsigned long unwind_get_byte(struct unwind_ctrl_block *ctrl) } /* Before poping a register check whether it is feasible or not */ +#ifdef CONFIG_AMLOGIC_KASAN32 +/* + * If enabled KASAN and unwind_frame is called under IRQ routine, + * an value-less kasan report will trigger. Because IRQ is using + * thread context and don't initialized shadow memory when irq_svc + * saving irq context. Since it's hard to guess reserved memory for + * shadow in stack by compiler, so we just tell compiler do not + * sanitize for this function + */ +int __no_sanitize_address unwind_pop_register(struct unwind_ctrl_block *ctrl, + unsigned long **vsp, unsigned int reg) +#else static int unwind_pop_register(struct unwind_ctrl_block *ctrl, unsigned long **vsp, unsigned int reg) +#endif { if (unlikely(ctrl->check_each_pop)) if (*vsp >= (unsigned long *)ctrl->sp_high) @@ -403,7 +420,13 @@ int unwind_frame(struct stackframe *frame) idx = unwind_find_idx(frame->pc); if (!idx) { + #ifdef CONFIG_AMLOGIC_KASAN32 + /* avoid FUCKING close source ko print too many here */ + if (frame->pc > PAGE_OFFSET) + pr_warn("unwind: Index not found %08lx\n", frame->pc); + #else pr_warn("unwind: Index not found %08lx\n", frame->pc); + #endif return -URC_FAILURE; } @@ -468,6 +491,20 @@ int unwind_frame(struct stackframe *frame) return URC_OK; } +#ifdef CONFIG_AMLOGIC_VMAP +static void dump_backtrace_entry_fp(unsigned long where, unsigned long fp, + unsigned long sp) +{ + signed long fp_size = 0; + + fp_size = fp - sp + 4; + if (fp_size < 0 || !fp) + fp_size = 0; + pr_info("[%08lx+%4ld][<%08lx>] %pS\n", + fp, fp_size, where, (void *)where); +} +#endif + void unwind_backtrace(struct pt_regs *regs, struct task_struct *tsk) { struct stackframe frame; @@ -504,9 +541,44 @@ void unwind_backtrace(struct pt_regs *regs, struct task_struct *tsk) unsigned long where = frame.pc; urc = unwind_frame(&frame); + #ifdef CONFIG_AMLOGIC_VMAP + if (urc < 0) { + int keep = 0; + int cpu; + unsigned long addr; + struct pt_regs *pt_regs; + + cpu = raw_smp_processor_id(); + /* continue search for irq stack */ + if (on_irq_stack(frame.sp, cpu)) { + unsigned long sp_irq; + + keep = 1; + sp_irq = (unsigned long)irq_stack[cpu]; + addr = *((unsigned long *)(sp_irq + + THREAD_INFO_OFFSET - 8 - + sizeof(addr) - 12)); + pt_regs = (struct pt_regs *)addr; + frame.fp = pt_regs->ARM_fp; + frame.sp = pt_regs->ARM_sp; + frame.lr = pt_regs->ARM_lr; + frame.pc = pt_regs->ARM_pc; + } + if (!keep) + break; + } + where = frame.pc; + /* + * The last "where" may be an invalid one, + * rechecking it + */ + if (kernel_text_address(where)) + dump_backtrace_entry_fp(where, frame.fp, frame.sp); + #else if (urc < 0) break; dump_backtrace_entry(where, frame.pc, frame.sp - 4); + #endif } } @@ -529,9 +601,9 @@ struct unwind_table *unwind_table_add(unsigned long start, unsigned long size, tab->begin_addr = text_addr; tab->end_addr = text_addr + text_size; - raw_spin_lock_irqsave(&unwind_lock, flags); + spin_lock_irqsave(&unwind_lock, flags); list_add_tail(&tab->list, &unwind_tables); - raw_spin_unlock_irqrestore(&unwind_lock, flags); + spin_unlock_irqrestore(&unwind_lock, flags); return tab; } @@ -543,9 +615,9 @@ void unwind_table_del(struct unwind_table *tab) if (!tab) return; - raw_spin_lock_irqsave(&unwind_lock, flags); + spin_lock_irqsave(&unwind_lock, flags); list_del(&tab->list); - raw_spin_unlock_irqrestore(&unwind_lock, flags); + spin_unlock_irqrestore(&unwind_lock, flags); kfree(tab); } diff --git a/arch/arm/lib/memcpy.S b/arch/arm/lib/memcpy.S index 64111bd4440b..044d499eadad 100644 --- a/arch/arm/lib/memcpy.S +++ b/arch/arm/lib/memcpy.S @@ -62,9 +62,17 @@ /* Prototype: void *memcpy(void *dest, const void *src, size_t n); */ ENTRY(mmiocpy) +#ifdef CONFIG_AMLOGIC_KASAN32 +ENTRY(__memcpy) +#else ENTRY(memcpy) +#endif #include "copy_template.S" +#ifdef CONFIG_AMLOGIC_KASAN32 +ENDPROC(__memcpy) +#else ENDPROC(memcpy) +#endif ENDPROC(mmiocpy) diff --git a/arch/arm/lib/memmove.S b/arch/arm/lib/memmove.S index 69a9d47fc5ab..d508fe8ff380 100644 --- a/arch/arm/lib/memmove.S +++ b/arch/arm/lib/memmove.S @@ -27,7 +27,11 @@ * occurring in the opposite direction. */ +#ifdef CONFIG_AMLOGIC_KASAN32 +ENTRY(__memmove) +#else ENTRY(memmove) +#endif UNWIND( .fnstart ) subs ip, r0, r1 @@ -224,4 +228,8 @@ ENTRY(memmove) 18: backward_copy_shift push=24 pull=8 +#ifdef CONFIG_AMLOGIC_KASAN32 +ENDPROC(__memmove) +#else ENDPROC(memmove) +#endif diff --git a/arch/arm/lib/memset.S b/arch/arm/lib/memset.S index 3c65e3bd790f..5d23be8b7fab 100644 --- a/arch/arm/lib/memset.S +++ b/arch/arm/lib/memset.S @@ -17,7 +17,11 @@ .align 5 ENTRY(mmioset) +#ifdef CONFIG_AMLOGIC_KASAN32 +ENTRY(__memset) +#else ENTRY(memset) +#endif UNWIND( .fnstart ) ands r3, r0, #3 @ 1 unaligned? mov ip, r0 @ preserve r0 as return value @@ -133,5 +137,9 @@ UNWIND( .fnstart ) add r2, r2, r3 @ 1 (r2 = r2 - (4 - r3)) b 1b UNWIND( .fnend ) +#ifdef CONFIG_AMLOGIC_KASAN32 +ENDPROC(__memset) +#else ENDPROC(memset) +#endif ENDPROC(mmioset) diff --git a/arch/arm/mach-meson/Kconfig b/arch/arm/mach-meson/Kconfig index 44a995ce3cc4..cda1cc1ee69e 100644 --- a/arch/arm/mach-meson/Kconfig +++ b/arch/arm/mach-meson/Kconfig @@ -12,17 +12,17 @@ if ARCH_MESON config MACH_MESON6 bool "Amlogic Meson6 (8726MX) SoCs support" - default ARCH_MESON + default !ARM64_A32 select MESON6_TIMER config MACH_MESON8 bool "Amlogic Meson8 SoCs support" - default ARCH_MESON + default !ARM64_A32 select MESON6_TIMER config MACH_MESON8B bool "Amlogic Meson8b SoCs support" - default ARCH_MESON + default !ARM64_A32 config ARM64_A32 tristate "ARMV8 Run in A32" diff --git a/arch/arm/mach-meson/hotplug-asm.S b/arch/arm/mach-meson/hotplug-asm.S index 1871afa6df56..cc172d243389 100644 --- a/arch/arm/mach-meson/hotplug-asm.S +++ b/arch/arm/mach-meson/hotplug-asm.S @@ -1,3 +1,20 @@ +/* + * arch/arm/mach-meson/hotplug-asm.S + * + * 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 #include diff --git a/arch/arm/mach-meson/meson-secure.c b/arch/arm/mach-meson/meson-secure.c index d7931ed33f65..b9f03d2cf2c4 100644 --- a/arch/arm/mach-meson/meson-secure.c +++ b/arch/arm/mach-meson/meson-secure.c @@ -155,10 +155,12 @@ uint32_t meson_secure_mem_flash_size(void) int32_t meson_secure_mem_ge2d_access(uint32_t msec) { int ret = -1; + struct cpumask org_cpumask; + cpumask_copy(&org_cpumask, ¤t->cpus_allowed); set_cpus_allowed_ptr(current, cpumask_of(0)); ret = meson_smc_hal_api(TRUSTZONE_HAL_API_MEMCONFIG_GE2D, msec); - set_cpus_allowed_ptr(current, cpu_all_mask); + set_cpus_allowed_ptr(current, &org_cpumask); return ret; } @@ -184,15 +186,17 @@ EXPORT_SYMBOL(meson_secure_jtag_apee); int meson_trustzone_efuse(void *arg) { int ret; + struct cpumask org_cpumask; if (!arg) return -1; + cpumask_copy(&org_cpumask, ¤t->cpus_allowed); set_cpus_allowed_ptr(current, cpumask_of(0)); ret = meson_smc_hal_api(TRUSTZONE_HAL_API_EFUSE, __pa(arg)); - set_cpus_allowed_ptr(current, cpu_all_mask); + set_cpus_allowed_ptr(current, &org_cpumask); return ret; } diff --git a/arch/arm/mm/Makefile b/arch/arm/mm/Makefile index 92d47c8cbbc3..0beabc46eab7 100644 --- a/arch/arm/mm/Makefile +++ b/arch/arm/mm/Makefile @@ -107,3 +107,6 @@ obj-$(CONFIG_CACHE_L2X0_PMU) += cache-l2x0-pmu.o obj-$(CONFIG_CACHE_XSC3L2) += cache-xsc3l2.o obj-$(CONFIG_CACHE_TAUROS2) += cache-tauros2.o obj-$(CONFIG_CACHE_UNIPHIER) += cache-uniphier.o + +obj-$(CONFIG_AMLOGIC_KASAN32) += kasan_init.o +KASAN_SANITIZE_kasan_init.o := n diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c index 1565d6b67163..96b980673501 100644 --- a/arch/arm/mm/init.c +++ b/arch/arm/mm/init.c @@ -36,6 +36,9 @@ #include #include +#ifdef CONFIG_AMLOGIC_KASAN32 +#include +#endif #include "mm.h" @@ -502,6 +505,9 @@ void __init mem_init(void) #define MLK_ROUNDUP(b, t) b, t, DIV_ROUND_UP(((t) - (b)), SZ_1K) pr_notice("Virtual kernel memory layout:\n" +#ifdef CONFIG_AMLOGIC_KASAN32 + " kasan : 0x%08lx - 0x%08lx (%4ld MB)\n" +#endif " vector : 0x%08lx - 0x%08lx (%4ld kB)\n" #ifdef CONFIG_HAVE_TCM " DTCM : 0x%08lx - 0x%08lx (%4ld kB)\n" @@ -520,6 +526,9 @@ void __init mem_init(void) " .init : 0x%p" " - 0x%p" " (%4td kB)\n" " .data : 0x%p" " - 0x%p" " (%4td kB)\n" " .bss : 0x%p" " - 0x%p" " (%4td kB)\n", +#ifdef CONFIG_AMLOGIC_KASAN32 + MLM(KASAN_SHADOW_START, KASAN_SHADOW_END), +#endif MLK(UL(CONFIG_VECTORS_BASE), UL(CONFIG_VECTORS_BASE) + (PAGE_SIZE)), diff --git a/arch/arm/mm/kasan_init.c b/arch/arm/mm/kasan_init.c new file mode 100644 index 000000000000..ac269046dbb9 --- /dev/null +++ b/arch/arm/mm/kasan_init.c @@ -0,0 +1,218 @@ +/* + * This file contains kasan initialization code for ARM64. + * + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * Author: Andrey Ryabinin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#define pr_fmt(fmt) "kasan: " fmt +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PGD_SIZE (PTRS_PER_PGD * sizeof(pgd_t)) + +static pgd_t tmp_pg_dir[PTRS_PER_PGD] __initdata __aligned(PGD_SIZE); + +/* + * The p*d_populate functions call virt_to_phys implicitly so they can't be used + * directly on kernel symbols (bm_p*d). All the early functions are called too + * early to use lm_alias so __p*d_populate functions must be used to populate + * with the physical address from __pa_symbol. + */ + +static void __init kasan_early_pte_populate(pmd_t *pmd, unsigned long addr, + unsigned long end) +{ + pte_t *pte; + unsigned long next; + pgprot_t kernel_pte = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | + L_PTE_SHARED | L_PTE_DIRTY | + L_PTE_MT_WRITEALLOC); + + if (pmd_none(*pmd)) + __pmd_populate(pmd, __pa_symbol(kasan_zero_pte), + _PAGE_KERNEL_TABLE); + + pte = pte_offset_kernel(pmd, addr); + do { + next = addr + PAGE_SIZE; + cpu_v7_set_pte_ext(pte, pfn_pte(sym_to_pfn(kasan_zero_page), + kernel_pte), + 0); + } while (pte++, addr = next, addr != end && pte_none(*pte)); +} + +static void __init kasan_early_pmd_populate(pud_t *pud, + unsigned long addr, + unsigned long end) +{ + pmd_t *pmd; + unsigned long next; + + if (pud_none(*pud)) + pud_populate(pud, __pa_symbol(kasan_zero_pmd), PMD_TYPE_TABLE); + + pmd = pmd_offset(pud, addr); + do { + next = pmd_addr_end(addr, end); + kasan_early_pte_populate(pmd, addr, next); + } while (pmd++, addr = next, addr != end && pmd_none(*pmd)); +} + +static void __init kasan_early_pud_populate(pgd_t *pgd, + unsigned long addr, + unsigned long end) +{ + pud_t *pud; + unsigned long next; + + if (pgd_none(*pgd)) + pgd_populate(pgd, __pa_symbol(kasan_zero_pud), PUD_TYPE_TABLE); + + pud = pud_offset(pgd, addr); + do { + next = pud_addr_end(addr, end); + kasan_early_pmd_populate(pud, addr, next); + } while (pud++, addr = next, addr != end && pud_none(*pud)); +} + +static void __init kasan_map_early_shadow(unsigned long start, + unsigned long end) +{ + unsigned long addr = start; + unsigned long next; + pgd_t *pgd; + + pgd = pgd_offset_k(addr); + do { + next = pgd_addr_end(addr, end); + kasan_early_pud_populate(pgd, addr, next); + } while (pgd++, addr = next, addr != end); +} + +asmlinkage void __init kasan_early_init(void) +{ + BUILD_BUG_ON(!IS_ALIGNED(KASAN_SHADOW_START, PGDIR_SIZE)); + BUILD_BUG_ON(!IS_ALIGNED(KASAN_SHADOW_END, PGDIR_SIZE)); + kasan_map_early_shadow(KASAN_SHADOW_START, KASAN_SHADOW_END); +} + +static inline pmd_t *pmd_off_k(unsigned long virt) +{ + return pmd_offset(pud_offset(pgd_offset_k(virt), virt), virt); +} + +static void __init clear_pmds(unsigned long start, + unsigned long end) +{ + /* + * Remove references to kasan page tables from + * swapper_pg_dir. pmd_clear() can't be used + * here because it's nop on 2,3-level pagetable setups + */ + for (; start < end; start += PGDIR_SIZE) + pmd_clear(pmd_off_k(start)); +} + +static void kasan_alloc_and_map_shadow(unsigned long start, unsigned long end) +{ + struct map_desc desc; + unsigned long size; + phys_addr_t l_shadow; + + size = (end - start) >> KASAN_SHADOW_SCALE_SHIFT; + l_shadow = memblock_alloc(size, SECTION_SIZE); + WARN(!l_shadow, "%s, reserve %ld shadow memory failed", + __func__, size); + + desc.virtual = (unsigned long)kasan_mem_to_shadow((void *)start); + desc.pfn = __phys_to_pfn(l_shadow); + desc.length = size; + desc.type = MT_MEMORY_RW; + create_mapping(&desc); + pr_info("KASAN shadow, virt:[%lx-%lx], phys:%x, size:%lx\n", + start, end, l_shadow, size); +} + +void __init kasan_init(void) +{ + unsigned long start, end; + int i; + + /* + * We are going to perform proper setup of shadow memory. + * At first we should unmap early shadow (clear_pmds() call bellow). + * However, instrumented code couldn't execute without shadow memory. + * tmp_pg_dir used to keep early shadow mapped until full shadow + * setup will be finished. + */ + memcpy(tmp_pg_dir, swapper_pg_dir, sizeof(tmp_pg_dir)); + dsb(ishst); + cpu_switch_mm(tmp_pg_dir, &init_mm); + clear_pmds(KASAN_SHADOW_START, KASAN_SHADOW_END); + + kasan_alloc_and_map_shadow(PAGE_OFFSET, KMEM_END); + kasan_alloc_and_map_shadow(FIXADDR_START, FIXADDR_END); +#ifdef CONFIG_HIGHMEM + kasan_alloc_and_map_shadow(PKMAP_BASE, + PKMAP_BASE + LAST_PKMAP * PAGE_SIZE); +#endif + + /* + * populate zero page for vmalloc area and other gap area + * TODO: + * Need check kasan for vmalloc? + */ + start = (ulong)kasan_mem_to_shadow((void *)MODULES_VADDR); + kasan_map_early_shadow(KASAN_SHADOW_START, start); + + start = (ulong)kasan_mem_to_shadow((void *)KMEM_END); + end = (ulong)kasan_mem_to_shadow((void *)FIXADDR_START); + kasan_map_early_shadow(start, end); + + /* + * KAsan may reuse the contents of kasan_zero_pte directly, so we + * should make sure that it maps the zero page read-only. + */ + for (i = 0; i < PTRS_PER_PTE; i++) + set_pte_ext(&kasan_zero_pte[i], + pfn_pte(sym_to_pfn(kasan_zero_page), + PAGE_KERNEL_RO), 0); + + memset(kasan_zero_page, 0, PAGE_SIZE); + cpu_switch_mm(swapper_pg_dir, &init_mm); + local_flush_tlb_all(); + flush_cache_all(); + + /* clear all shawdow memory before kasan running */ + memset(kasan_mem_to_shadow((void *)PAGE_OFFSET), 0, + (KMEM_END - PAGE_OFFSET) >> KASAN_SHADOW_SCALE_SHIFT); + memset(kasan_mem_to_shadow((void *)FIXADDR_START), 0, + (FIXADDR_END - FIXADDR_START) >> KASAN_SHADOW_SCALE_SHIFT); +#ifdef CONFIG_HIGHMEM + memset(kasan_mem_to_shadow((void *)PKMAP_BASE), 0, + (LAST_PKMAP * PAGE_SIZE) >> KASAN_SHADOW_SCALE_SHIFT); +#endif + + /* At this point kasan is fully initialized. Enable error messages */ + init_task.kasan_depth = 0; + pr_info("KernelAddressSanitizer initialized\n"); +} diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index 4d3da37cb798..c7e41d4e11e7 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c @@ -37,6 +37,9 @@ #include #include #include +#ifdef CONFIG_AMLOGIC_KASAN32 +#include +#endif #include "fault.h" #include "mm.h" @@ -951,7 +954,11 @@ static void __init __create_mapping(struct mm_struct *mm, struct map_desc *md, * offsets, and we take full advantage of sections and * supersections. */ +#ifdef CONFIG_AMLOGIC_KASAN32 +void __init create_mapping(struct map_desc *md) +#else static void __init create_mapping(struct map_desc *md) +#endif { if (md->virtual != vectors_base() && md->virtual < TASK_SIZE) { pr_warn("BUG: not creating mapping for 0x%08llx at 0x%08lx in user region\n", @@ -1121,6 +1128,7 @@ void __init debug_ll_io_init(void) } #endif +#ifndef CONFIG_AMLOGIC_KASAN32 static void * __initdata vmalloc_min = (void *)(VMALLOC_END - (240 << 20) - VMALLOC_OFFSET); @@ -1149,6 +1157,7 @@ static int __init early_vmalloc(char *arg) return 0; } early_param("vmalloc", early_vmalloc); +#endif phys_addr_t arm_lowmem_limit __initdata = 0; @@ -1166,7 +1175,11 @@ void __init adjust_lowmem_bounds(void) * and may itself be outside the valid range for which phys_addr_t * and therefore __pa() is defined. */ +#ifdef CONFIG_AMLOGIC_KASAN32 + vmalloc_limit = (u64)(KMEM_END - PAGE_OFFSET + PHYS_OFFSET); +#else vmalloc_limit = (u64)(uintptr_t)vmalloc_min - PAGE_OFFSET + PHYS_OFFSET; +#endif for_each_memblock(memory, reg) { phys_addr_t block_start = reg->base; @@ -1244,8 +1257,19 @@ static inline void prepare_page_table(void) /* * Clear out all the mappings below the kernel image. */ +#ifdef CONFIG_AMLOGIC_KASAN32 + for (addr = 0; addr < MODULES_VADDR; addr += PMD_SIZE) { + /* + * keep pre-initialized kasan shadow memory MMU before + * kasan really eanbled + */ + if (addr < KASAN_SHADOW_START || addr >= KASAN_SHADOW_END) + pmd_clear(pmd_off_k(addr)); + } +#else for (addr = 0; addr < MODULES_VADDR; addr += PMD_SIZE) pmd_clear(pmd_off_k(addr)); +#endif #ifdef CONFIG_XIP_KERNEL /* The XIP kernel is mapped in the module area -- skip over it */ @@ -1321,8 +1345,16 @@ static void __init devicemaps_init(const struct machine_desc *mdesc) /* * Clear page table except top pmd used by early fixmaps */ +#ifdef CONFIG_AMLOGIC_KASAN32 + /* we have adjusted memory map layout */ + for (addr = VMALLOC_START; + addr < (PAGE_OFFSET & PMD_MASK); + addr += PMD_SIZE) + pmd_clear(pmd_off_k(addr)); +#else for (addr = VMALLOC_START; addr < (FIXADDR_TOP & PMD_MASK); addr += PMD_SIZE) pmd_clear(pmd_off_k(addr)); +#endif /* * Map the kernel if it is XIP. @@ -1645,10 +1677,11 @@ void __init paging_init(const struct machine_desc *mdesc) unsigned long notrace phys_check(phys_addr_t x) { unsigned long addr; - struct page *page; addr = x - PHYS_OFFSET + PAGE_OFFSET; +#ifndef CONFIG_AMLOGIC_KASAN32 if (scheduler_running) { + struct page *page; page = phys_to_page(x); /* @@ -1662,16 +1695,19 @@ unsigned long notrace phys_check(phys_addr_t x) dump_stack(); } } +#endif return addr; } EXPORT_SYMBOL(phys_check); unsigned long notrace virt_check(unsigned long x) { +#ifndef CONFIG_AMLOGIC_KASAN32 if (scheduler_running && (x >= VMALLOC_START || x < PAGE_OFFSET)) { pr_err("bad input of virt:%lx\n", x); dump_stack(); } +#endif return (phys_addr_t)x - PAGE_OFFSET + PHYS_OFFSET; } EXPORT_SYMBOL(virt_check); diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S index 850c22bca19c..955fda65ffb4 100644 --- a/arch/arm/mm/proc-v7.S +++ b/arch/arm/mm/proc-v7.S @@ -79,7 +79,9 @@ ENDPROC(cpu_v7_do_idle) ENTRY(cpu_v7_dcache_clean_area) ALT_SMP(W(nop)) @ MP extensions imply L1 PTW ALT_UP_B(1f) +#ifndef CONFIG_AMLOGIC_MODIFY ret lr +#endif 1: dcache_line_size r2, r3 2: mcr p15, 0, r0, c7, c10, 1 @ clean D entry add r0, r0, r2 diff --git a/arch/arm/vdso/Makefile b/arch/arm/vdso/Makefile index 59a8fa7b8a3b..fa1c45be6d7b 100644 --- a/arch/arm/vdso/Makefile +++ b/arch/arm/vdso/Makefile @@ -20,6 +20,8 @@ obj-$(CONFIG_VDSO) += vdso.o extra-$(CONFIG_VDSO) += vdso.lds CPPFLAGS_vdso.lds += -P -C -U$(ARCH) +KASAN_SANITIZE_vgettimeofday.o := n + CFLAGS_REMOVE_vdso.o = -pg # Force -O2 to avoid libgcc dependencies diff --git a/arch/arm64/boot/dts/amlogic/Makefile b/arch/arm64/boot/dts/amlogic/Makefile index c90e6dbb9653..6057533126f3 100644 --- a/arch/arm64/boot/dts/amlogic/Makefile +++ b/arch/arm64/boot/dts/amlogic/Makefile @@ -8,8 +8,6 @@ dtb-y += g12b_a311d_w400.dtb dtb-y += g12b_a311d_w400_buildroot.dtb endif dtb-$(CONFIG_ARCH_MESON64_ODROIDC3) += meson64_odroidc3.dtb -dtb-$(CONFIG_ARCH_MESON64_ODROIDC3) += meson64_odroidc3_android.dtb dtb-$(CONFIG_ARCH_MESON64_ODROIDN2) += meson64_odroidn2.dtb dtb-$(CONFIG_ARCH_MESON64_ODROIDN2) += meson64_odroidn2_drm.dtb -dtb-$(CONFIG_ARCH_MESON64_ODROIDN2) += meson64_odroidn2_android.dtb dtb-$(CONFIG_ARCH_MESON64_ODROIDN2) += meson64_odroidn2_spibios.dtb diff --git a/arch/arm64/boot/dts/amlogic/atom.dts b/arch/arm64/boot/dts/amlogic/atom.dts index 2fa541ea61b0..4021f1de6300 100644 --- a/arch/arm64/boot/dts/amlogic/atom.dts +++ b/arch/arm64/boot/dts/amlogic/atom.dts @@ -45,7 +45,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x0 0x100000 0x0 0x7ff00000>; + linux,usable-memory = <0x0 0x0 0x0 0x80000000>; }; reserved-memory { @@ -58,8 +58,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { compatible = "shared-dma-pool"; diff --git a/arch/arm64/boot/dts/amlogic/axg_a113d_skt.dts b/arch/arm64/boot/dts/amlogic/axg_a113d_skt.dts index 0a92bca20d2c..3e052619aa8b 100644 --- a/arch/arm64/boot/dts/amlogic/axg_a113d_skt.dts +++ b/arch/arm64/boot/dts/amlogic/axg_a113d_skt.dts @@ -36,7 +36,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x0 0x100000 0x0 0x3ff00000>; + linux,usable-memory = <0x0 0x0 0x0 0x40000000>; }; reserved-memory { @@ -49,9 +49,8 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; -}; + ftrace-size = <0x20000>; + }; secmon_reserved:linux,secmon { compatible = "shared-dma-pool"; diff --git a/arch/arm64/boot/dts/amlogic/axg_a113x_skt.dts b/arch/arm64/boot/dts/amlogic/axg_a113x_skt.dts index d3407d8dd797..65a00e75f37f 100644 --- a/arch/arm64/boot/dts/amlogic/axg_a113x_skt.dts +++ b/arch/arm64/boot/dts/amlogic/axg_a113x_skt.dts @@ -47,8 +47,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm64/boot/dts/amlogic/axg_pxp.dts b/arch/arm64/boot/dts/amlogic/axg_pxp.dts index 37955492625d..b120496f41aa 100644 --- a/arch/arm64/boot/dts/amlogic/axg_pxp.dts +++ b/arch/arm64/boot/dts/amlogic/axg_pxp.dts @@ -32,7 +32,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x0 0x100000 0x0 0x3ff00000>; + linux,usable-memory = <0x0 0x0 0x0 0x40000000>; }; reserved-memory { diff --git a/arch/arm64/boot/dts/amlogic/axg_s400.dts b/arch/arm64/boot/dts/amlogic/axg_s400.dts index 4098f87e1557..58383abc24c8 100644 --- a/arch/arm64/boot/dts/amlogic/axg_s400.dts +++ b/arch/arm64/boot/dts/amlogic/axg_s400.dts @@ -47,8 +47,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm64/boot/dts/amlogic/axg_s400_v03.dts b/arch/arm64/boot/dts/amlogic/axg_s400_v03.dts index 25d394141807..ee09047cbdcb 100644 --- a/arch/arm64/boot/dts/amlogic/axg_s400_v03.dts +++ b/arch/arm64/boot/dts/amlogic/axg_s400_v03.dts @@ -47,8 +47,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm64/boot/dts/amlogic/axg_s400_v03gva.dts b/arch/arm64/boot/dts/amlogic/axg_s400_v03gva.dts index f805271bbd23..63336e786088 100644 --- a/arch/arm64/boot/dts/amlogic/axg_s400_v03gva.dts +++ b/arch/arm64/boot/dts/amlogic/axg_s400_v03gva.dts @@ -47,8 +47,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { @@ -421,14 +420,6 @@ pinctrl-0 = <&b_uart_pins>; }; - meson-irblaster { - compatible = "amlogic, am_irblaster"; - dev_name = "meson-irblaster"; - status = "disable"; - pinctrl-names = "default"; - pinctrl-0 = <&irblaster_pins>; - }; - vpu { compatible = "amlogic, vpu-axg"; dev_name = "vpu"; diff --git a/arch/arm64/boot/dts/amlogic/axg_s400_v03gva_sbr.dts b/arch/arm64/boot/dts/amlogic/axg_s400_v03gva_sbr.dts new file mode 100644 index 000000000000..c91bc36f0861 --- /dev/null +++ b/arch/arm64/boot/dts/amlogic/axg_s400_v03gva_sbr.dts @@ -0,0 +1,1638 @@ +/* + * arch/arm64/boot/dts/amlogic/axg_s400_v03gva_sbr.dts + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +/dts-v1/; + +#include "mesonaxg.dtsi" +/* #include "mesonaxg_s400-panel.dtsi" */ +/ { + model = "Amlogic"; + amlogic-dt-id = "axg_s400_v03gva_sbr"; + compatible = "amlogic, axg"; + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + + aliases { + serial0 = &uart_AO; + serial1 = &uart_A; + }; + + memory@00000000 { + device_type = "memory"; + linux,usable-memory = <0x0 0x000000 0x0 0x40000000>; + }; + + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + /* global autoconfigured region for contiguous allocations */ + ramoops@0x07400000 { + compatible = "ramoops"; + reg = <0x0 0x07400000 0x0 0x00100000>; + record-size = <0x8000>; + console-size = <0x8000>; + ftrace-size = <0x20000>; + }; + + secmon_reserved:linux,secmon { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x400000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x05000000 0x0 0x400000>; + }; + + secos_reserved:linux,secos { + status = "disabled"; + compatible = "amlogic, aml_secos_memory"; + reg = <0x0 0x05300000 0x0 0x2000000>; + no-map; + }; + fb_reserved:linux,meson-fb { + //compatible = "amlogic, fb-memory"; + //reg = <0x0 0x3e000000 0x0 0x1f00000>; + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x2000000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x3e000000 0x0 0x2000000>; + }; + }; + mtd_nand { + compatible = "amlogic, aml_mtd_nand"; + dev_name = "mtdnand"; + status = "okay"; + reg = <0x0 0xFFE07800 0x0 0x200>; + interrupts = < 0 34 1 >; + pinctrl-names = "nand_rb_mod","nand_norb_mod", "nand_cs_only"; + pinctrl-0 = <&all_nand_pins>; + pinctrl-1 = <&all_nand_pins>; + pinctrl-2 = <&nand_cs_pins>; + device_id = <0>; + + /*fip/tpl configurations, must be same + * with uboot if bl_mode was set as 1 + * bl_mode: 0 compact mode; 1 descrete mode + * if bl_mode was set as 1, fip configeration will work + */ + bl_mode = <1>; + /*copy count of fip*/ + fip_copies = <4>; + /*size of each fip copy */ + fip_size = <0x200000>; + nand_clk_ctrl = <0xFFE07000>; + plat-names = "bootloader","nandnormal"; + plat-num = <2>; + plat-part-0 = <&bootloader>; + plat-part-1 = <&nandnormal>; + bootloader: bootloader{ + enable_pad ="ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <1>; + part_num = <0>; + rb_detect = <1>; + }; + nandnormal: nandnormal{ + enable_pad ="ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + plane_mode = "twoplane"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <2>; + part_num = <3>; + partition = <&nand_partitions>; + rb_detect = <1>; + }; + nand_partitions:nand_partition{ + /* + * if bl_mode is 1, tpl size was generate by + * fip_copies * fip_size which + * will not skip bad when calculating + * the partition size; + * + * if bl_mode is 0, + * tpl partition must be comment out. + */ + tpl{ + offset=<0x0 0x0>; + size=<0x0 0x0>; + }; + recovery{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + boot{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + system{ + offset=<0x0 0x0>; + size=<0x0 0x11800000>; + }; + factory{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + data{ + offset=<0xffffffff 0xffffffff>; + size=<0x0 0x0>; + }; + }; + }; + + + ethmac: ethernet@0xff3f0000 { + compatible = "amlogic, gxbb-eth-dwmac"; + reg = <0x0 0xff3f0000 0x0 0x10000 + 0x0 0xff634540 0x0 0x8>; + interrupts = <0 8 1>; + pinctrl-names = "external_eth_pins"; + pinctrl-0 = <&external_eth_pins>; + mc_val_internal_phy = <0x1800>; + mc_val_external_phy = <0x1621>; + interrupt-names = "macirq"; + clocks = <&clkc CLKID_ETH_CORE>; + clock-names = "ethclk81"; + internal_phy=<0>; + }; + + aml_sensor0: aml-sensor@0 { + compatible = "amlogic, aml-thermal"; + device_name = "thermal"; + #thermal-sensor-cells = <1>; + cooling_devices { + cpufreq_cool_cluster0 { + min_state = <1000000>; + dyn_coeff = <140>; + cluster_id = <0>; + node_name = "cpufreq_cool0"; + device_type = "cpufreq"; + }; + cpucore_cool_cluster0 { + min_state = <1>; + dyn_coeff = <0>; + cluster_id = <0>; + node_name = "cpucore_cool0"; + device_type = "cpucore"; + }; + }; + cpufreq_cool0:cpufreq_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + cpucore_cool0:cpucore_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + }; + thermal-zones { + soc_thermal { + polling-delay = <1000>; + polling-delay-passive = <100>; + sustainable-power = <1050>; + + thermal-sensors = <&aml_sensor0 3>; + + trips { + switch_on: trip-point@0 { + temperature = <70000>; + hysteresis = <1000>; + type = "passive"; + }; + control: trip-point@1 { + temperature = <80000>; + hysteresis = <1000>; + type = "passive"; + }; + hot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + critical: trip-point@3 { + temperature = <260000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + + cooling-maps { + cpufreq_cooling_map { + trip = <&control>; + cooling-device = <&cpufreq_cool0 0 4>; + contribution = <1024>; + }; + cpucore_cooling_map { + trip = <&control>; + cooling-device = <&cpucore_cool0 0 3>; + contribution = <1024>; + }; + }; + }; + }; + + dwc3: dwc3@ff500000 { + compatible = "synopsys, dwc3"; + status = "okay"; + reg = <0x0 0xff500000 0x0 0x100000>; + interrupts = <0 30 4>; + usb-phy = <&usb2_phy>, <&usb3_phy>; + cpu-type = "gxl"; + clock-src = "usb3.0"; + clocks = <&clkc CLKID_USB_GENERAL>; + clock-names = "dwc_general"; + }; + + usb2_phy: usb2phy@ffe09000 { + compatible = "amlogic, amlogic-new-usb2"; + status = "okay"; + portnum = <4>; + reg = <0x0 0xffe09000 0x0 0x80 + 0x0 0xffd01008 0x0 0x4>; + }; + + usb3_phy: usb3phy@ffe09080 { + compatible = "amlogic, amlogic-new-usb3"; + status = "okay"; + portnum = <0>; + reg = <0x0 0xffe09080 0x0 0x20>; + interrupts = <0 16 4>; + otg = <1>; + gpio-vbus-power = "GPIOAO_5"; + gpios = <&gpio_ao GPIOAO_5 GPIO_ACTIVE_HIGH>; + }; + + dwc2_a { + compatible = "amlogic, dwc2"; + device_name = "dwc2_a"; + reg = <0x0 0xff400000 0x0 0x40000>; + status = "okay"; + interrupts = <0 31 4>; + pl-periph-id = <0>; /** lm name */ + clock-src = "usb0"; /** clock src */ + port-id = <0>; /** ref to mach/usb.h */ + port-type = <2>; /** 0: otg, 1: host, 2: slave */ + port-speed = <0>; /** 0: default, high, 1: full */ + port-config = <0>; /** 0: default */ + /*0:default,1:single,2:incr,3:incr4,4:incr8,5:incr16,6:disable*/ + port-dma = <0>; + port-id-mode = <0>; /** 0: hardware, 1: sw_host, 2: sw_slave*/ + usb-fifo = <728>; + cpu-type = "gxl"; + /** 0: normal, 1: otg+dwc3 host only, 2: otg+dwc3 device only*/ + controller-type = <3>; + phy-reg = <0xffe09000>; + phy-reg-size = <0xa0>; + clocks = <&clkc CLKID_USB_GENERAL + &clkc CLKID_USB1_TO_DDR + &clkc CLKID_USB1>; + clock-names = "usb_general", + "usb1", + "usb1_to_ddr"; + }; + + pcie_A: pcieA@f9800000 { + compatible = "amlogic, amlogic-pcie", "snps,dw-pcie"; + reg = <0x0 0xf9800000 0x0 0x400000 + 0x0 0xff646000 0x0 0x2000 + 0x0 0xf9f00000 0x0 0x100000 + 0x0 PCIE_PHY_REG 0x0 PCIE_PHY_SIZE + 0x0 PCIE_RESET_REG 0x0 PCIE_RESET_SIZE>; + reg-names = "elbi", "cfg", "config", "phy", "reset"; + reset-gpio = <&gpio GPIOX_19 GPIO_ACTIVE_HIGH>; + interrupts = <0 177 0>; + #interrupt-cells = <1>; + bus-range = <0x0 0xff>; + #address-cells = <3>; + #size-cells = <2>; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &gic GIC_SPI 179 IRQ_TYPE_EDGE_RISING>; + device_type = "pci"; + ranges = <0x82000000 0 0 0x0 0xf9c00000 0 0x00300000>; + /* non-prefetchable memory */ + num-lanes = <1>; + pcie-num = <1>; + + clocks = <&clkc CLKID_USB_GENERAL + &clkc CLKID_PCIE_PLL + &clkc CLKID_MIPI_ENABLE_GATE + &clkc CLKID_MIPI_BANDGAP_GATE + &clkc CLKID_PCIE_A + &clkc CLKID_PCIE_CML_EN0>; + clock-names = "pcie_general", + "pcie_refpll", + "pcie_mipi_enable_gate", + "pcie_mipi_bandgap_gate", + "pcie", + "port"; + /*reset-gpio-type 0:Shared pad(no reset)1:OD pad2:Normal pad*/ + gpio-type = <2>; + status = "disabled"; + }; + + pcie_B: pcieB@fa000000 { + compatible = "amlogic, amlogic-pcie", "snps,dw-pcie"; + reg = <0x0 0xfa000000 0x0 0x400000 + 0x0 0xff648000 0x0 0x2000 + 0x0 0xfa400000 0x0 0x100000 + 0x0 PCIE_PHY_REG 0x0 PCIE_PHY_SIZE + 0x0 PCIE_RESET_REG 0x0 PCIE_RESET_SIZE>; + reg-names = "elbi", "cfg", "config", "phy", "reset"; + reset-gpio = <&gpio GPIOZ_10 GPIO_ACTIVE_HIGH>; + interrupts = <0 167 0>; + #interrupt-cells = <1>; + bus-range = <0x0 0xff>; + #address-cells = <3>; + #size-cells = <2>; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &gic GIC_SPI 169 IRQ_TYPE_EDGE_RISING>; + device_type = "pci"; + ranges = <0x81000000 0 0 0 0xfa500000 0x0 0x10000 + /* downstream I/O */ + 0x82000000 0 0xfa510000 0x0 0xfa510000 0 0x002f0000>; + /* non-prefetchable memory */ + num-lanes = <1>; + pcie-num = <2>; + + clocks = <&clkc CLKID_USB_GENERAL + &clkc CLKID_PCIE_PLL + &clkc CLKID_MIPI_ENABLE_GATE + &clkc CLKID_MIPI_BANDGAP_GATE + &clkc CLKID_PCIE_B + &clkc CLKID_PCIE_CML_EN1>; + clock-names = "pcie_general", + "pcie_refpll", + "pcie_mipi_enable_gate", + "pcie_mipi_bandgap_gate", + "pcie", + "port"; + /*reset-gpio-type 0:Shared pad(no reset)1:OD pad2:Normal pad*/ + gpio-type = <1>; + status = "disabled"; + }; + + + uart_A: serial@ffd24000 { + compatible = "amlogic, meson-uart"; + reg = <0x0 0xffd24000 0x0 0x18>; + interrupts = <0 26 1>; + status = "okay"; + clocks = <&xtal + &clkc CLKID_UART0>; + clock-names = "clk_uart", + "clk_gate"; + fifosize = < 128 >; + pinctrl-names = "default"; + pinctrl-0 = <&a_uart_pins>; + }; + + uart_B: serial@ffd23000 { + compatible = "amlogic, meson-uart"; + reg = <0x0 0xffd23000 0x0 0x18>; + interrupts = <0 75 1>; + status = "disabled"; + clocks = <&xtal + &clkc CLKID_UART1>; + clock-names = "clk_uart", + "clk_gate"; + fifosize = < 64 >; + pinctrl-names = "default"; + pinctrl-0 = <&b_uart_pins>; + }; + + vpu { + compatible = "amlogic, vpu-axg"; + dev_name = "vpu"; + status = "okay"; + clocks = <&clkc CLKID_VAPB_MUX>, + <&clkc CLKID_VPU_INTR>, + <&clkc CLKID_VPU_P0_COMP>, + <&clkc CLKID_VPU_P1_COMP>, + <&clkc CLKID_VPU_MUX>; + clock-names = "vapb_clk", + "vpu_intr_gate", + "vpu_clk0", + "vpu_clk1", + "vpu_clk"; + clk_level = <3>; + /* 0: 100.0M 1: 166.7M 2: 200.0M 3: 250.0M */ + }; + + vout { + compatible = "amlogic, vout"; + dev_name = "vout"; + status = "okay"; + }; + + /* Sound iomap */ + aml_snd_iomap { + compatible = "amlogic, snd-iomap"; + status = "okay"; + #address-cells=<2>; + #size-cells=<2>; + ranges; + pdm_bus { + reg = <0x0 0xFF632000 0x0 0x2000>; + }; + audiobus_base { + reg = <0x0 0xFF642000 0x0 0x2000>; + }; + }; + pdm_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, pdm_dummy_codec"; + status = "okay"; + }; + dummy_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, aml_dummy_codec"; + status = "okay"; + }; + + auge_sound { + compatible = "amlogic, axg-sound-card"; + aml-audio-card,name = "AML-AUGESOUND"; + + aml-audio-card,loopback = <&aml_loopback>; + + aml-audio-card,hp-det-gpio = <&gpio GPIOZ_7 GPIO_ACTIVE_LOW>; + + aml-audio-card,dai-link@0 { + format = "dsp_a"; + mclk-fs = <512>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + //bitclock-master = <&tdmacodec>; + //frame-master = <&tdmacodec>; + tdmacpu: cpu { + sound-dai = <&aml_tdma>; + dai-tdm-slot-tx-mask = + <1>; + dai-tdm-slot-rx-mask = + <1>; + dai-tdm-slot-num = <1>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <512000>; + }; + tdmacodec: codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@1 { + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + + /*A113D tdmb slave for HDMI*/ + bitclock-master = <&tdmbcodec>; + frame-master = <&tdmbcodec>; + + /*A113D tdmb master for LineIn*/ + /* + * bitclock-master = <&aml_tdmb>; + * frame-master = <&aml_tdmb>; + */ + + suffix-name = "alsaPORT-i2sCapture"; + cpu { + sound-dai = <&aml_tdmb>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmbcodec:codec { + /* + * prefix-names = "3101_A", "3101_B", + * "3101_C", "3101_D"; + * sound-dai = <&tlv320adc3101_32 + * &tlv320adc3101_30 + * &tlv320adc3101_34 + * &tlv320adc3101_36>; + */ + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@2 { + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + //bitclock-master = <&aml_tdmc>; + //frame-master = <&aml_tdmc>; + cpu { + sound-dai = <&aml_tdmc>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + codec { + /* + *prefix-names = "5707_A", "5707_B"; + *sound-dai = <&tas5707_36 &tas5707_3a + * &dummy_codec>; + */ + prefix-names = "tas5782m_pu1", "tas5782m_pu2", + "tas5782m_pu3", "tas5782m_pu4", "tas5782m_pu5", + "tas5782m_pu6"; + sound-dai = <&tas5782m_pu1 &tas5782m_pu2 + &tas5782m_pu3 &tas5782m_pu4 &tas5782m_pu5 + &tas5782m_pu6>; + }; + }; + + aml-audio-card,dai-link@3 { + mclk-fs = <256>; + cpu { + sound-dai = <&aml_pdm>; + }; + codec { + /* + *enable external loopback + *and tlv320adc3101 as loopback + */ + /*sound-dai = <&pdm_codec &tlv320adc3101_32>;*/ + /* + * enable internal loopback + * or disable loopback + */ + sound-dai = <&pdm_codec>; + }; + }; + + aml-audio-card,dai-link@4 { + mclk-fs = <128>; + cpu { + sound-dai = <&aml_spdif>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + }; + + bt-dev{ + compatible = "amlogic, bt-dev"; + dev_name = "bt-dev"; + status = "okay"; + gpio_reset = <&gpio GPIOX_21 GPIO_ACTIVE_HIGH>; + }; + + wifi{ + compatible = "amlogic, aml_wifi"; + dev_name = "aml_wifi"; + status = "okay"; + interrupt_pin = <&gpio GPIOX_6 GPIO_ACTIVE_HIGH>; + interrupts = < 0 67 4>; + irq_trigger_type = "GPIO_IRQ_LOW"; + power_on_pin2 = <&gpio GPIOX_16 GPIO_ACTIVE_HIGH>; + power_on_pin = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; + dhd_static_buf; //if use bcm wifi, config dhd_static_buf + pinctrl-names = "default"; + pinctrl-0 = <&wifi_32k_pins>; + pwm_config = <&wifi_pwm_conf>; + }; + + wifi_pwm_conf:wifi_pwm_conf{ + pwm_channel1_conf { + pwms = <&pwm_ab MESON_PWM_0 30541 0>; + duty-cycle = <15270>; + times = <10>; + }; + pwm_channel2_conf { + pwms = <&pwm_ab MESON_PWM_2 30500 0>; + duty-cycle = <15250>; + times = <12>; + }; + }; + + sd_emmc_c: emmc@ffe07000 { + status = "disabled"; + compatible = "amlogic, meson-mmc-axg"; + reg = <0x0 0xffe07000 0x0 0x2000>; + interrupts = <0 218 1>; + pinctrl-names = "emmc_clk_cmd_pins", "emmc_all_pins"; + pinctrl-0 = <&emmc_clk_cmd_pins>; + pinctrl-1 = <&emmc_conf_pull_up &emmc_conf_pull_done>; + clocks = <&clkc CLKID_SD_EMMC_C>, + <&clkc CLKID_SD_EMMC_C_P0_COMP>, + <&clkc CLKID_FCLK_DIV2>, + <&clkc CLKID_FCLK_DIV5>, + <&xtal>; + clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + + bus-width = <8>; + cap-sd-highspeed; + cap-mmc-highspeed; + mmc-ddr-1_8v; + mmc-hs200-1_8v; + + max-frequency = <200000000>; + non-removable; + disable-wp; + emmc { + pinname = "emmc"; + ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ + caps = "MMC_CAP_8_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + "MMC_CAP_1_8V_DDR", + "MMC_CAP_HW_RESET", + "MMC_CAP_ERASE", + "MMC_CAP_CMD23"; + caps2 = "MMC_CAP2_HS200", "MMC_CAP2_HS400"; + f_min = <400000>; + f_max = <200000000>; + max_req_size = <0x20000>; /**128KB*/ + gpio_dat3 = <&gpio BOOT_3 GPIO_ACTIVE_HIGH>; + tx_delay = <4>; + hw_reset = <&gpio BOOT_9 GPIO_ACTIVE_HIGH>; + card_type = <1>; + /* 1:mmc card(include eMMC), + * 2:sd card(include tSD) + */ + }; + }; + + sd_emmc_b:sdio@ffe05000 { + status = "okay"; + compatible = "amlogic, meson-mmc-axg"; + reg = <0x0 0xffe05000 0x0 0x2000>; + interrupts = <0 217 4>; + pinctrl-names = "sdio_clk_cmd_pins", "sdio_all_pins"; + pinctrl-0 = <&sdio_clk_cmd_pins>; + pinctrl-1 = <&sdio_all_pins>; + clocks = <&clkc CLKID_SD_EMMC_B>, + <&clkc CLKID_SD_EMMC_B_P0_COMP>, + <&clkc CLKID_FCLK_DIV2>, + <&clkc CLKID_FCLK_DIV5>, + <&xtal>; + clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + + bus-width = <4>; + cap-sd-highspeed; + cap-mmc-highspeed; + max-frequency = <100000000>; + non-removable; + disable-wp; + sdio { + pinname = "sdio"; + ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + "MMC_CAP_UHS_SDR12", + "MMC_CAP_UHS_SDR25", + "MMC_CAP_UHS_SDR50", + "MMC_CAP_UHS_SDR104", + "MMC_PM_KEEP_POWER", + "MMC_CAP_SDIO_IRQ"; + f_min = <400000>; + f_max = <200000000>; + max_req_size = <0x20000>; /**128KB*/ + card_type = <3>; + /* 3:sdio device(ie:sdio-wifi), + * 4:SD combo (IO+mem) card + */ + }; + }; + + partitions: partitions{ + parts = <11>; + part-0 = <&logo>; + part-1 = <&recovery>; + part-2 = <&rsv>; + part-3 = <&tee>; + part-4 = <&crypt>; + part-5 = <&misc>; + part-6 = <&instaboot>; + part-7 = <&boot>; + part-8 = <&system>; + part-9 = <&cache>; + part-10 = <&data>; + + logo:logo{ + pname = "logo"; + size = <0x0 0x2000000>; + mask = <1>; + }; + recovery:recovery{ + pname = "recovery"; + size = <0x0 0x2000000>; + mask = <1>; + }; + rsv:rsv{ + pname = "rsv"; + size = <0x0 0x800000>; + mask = <1>; + }; + tee:tee{ + pname = "tee"; + size = <0x0 0x800000>; + mask = <1>; + }; + crypt:crypt{ + pname = "crypt"; + size = <0x0 0x2000000>; + mask = <1>; + }; + misc:misc{ + pname = "misc"; + size = <0x0 0x2000000>; + mask = <1>; + }; + instaboot:instaboot{ + pname = "instaboot"; + size = <0x0 0x400000>; + mask = <1>; + }; + boot:boot + { + pname = "boot"; + size = <0x0 0x2000000>; + mask = <1>; + }; + system:system + { + pname = "system"; + size = <0x0 0x80000000>; + mask = <1>; + }; + cache:cache + { + pname = "cache"; + size = <0x0 0x20000000>; + mask = <2>; + }; + data:data + { + pname = "data"; + size = <0xffffffff 0xffffffff>; + mask = <4>; + }; + }; + + meson-fb { + compatible = "amlogic, meson-axg"; + memory-region = <&fb_reserved>; + dev_name = "meson-fb"; + status = "disabled"; + interrupts = <0 3 1 + 0 89 1>; + interrupt-names = "viu-vsync", "rdma"; + mem_size = <0x00300000 0x1800000 0x00000000>; + /* uboot logo,fb0/fb1 memory size */ + display_mode_default = "1080p60hz"; + scale_mode = <0>; + /** 0:VPU free scale 1:OSD free scale 2:OSD super scale */ + display_size_default = <768 1024 768 2048 32>; + /*768*1024*4*2 = 0x600000*/ + mem_alloc = <1>; + logo_addr = "0x3e000000"; + pxp_mode = <0>; /** 0:normal mode 1:pxp mode */ + }; + + ge2d { + compatible = "amlogic, ge2d-axg"; + dev_name = "ge2d"; + status = "disabled"; + interrupts = <0 150 1>; + interrupt-names = "ge2d"; + clocks = <&clkc CLKID_VAPB_MUX>, + <&clkc CLKID_G2D>, + <&clkc CLKID_GE2D_GATE>; + clock-names = "clk_vapb_0", + "clk_ge2d", + "clk_ge2d_gate"; + reg = <0x0 0xff940000 0x0 0x10000>; + }; + + adc_keypad { + compatible = "amlogic, adc_keypad"; + status = "okay"; + key_name = "power", "vol-", "vol+", "wifi", "<<", ">>"; + key_num = <6>; + io-channels = <&saradc SARADC_CH0>; + io-channel-names = "key-chan-0"; + key_chan = ; + key_code = <116 114 115 139 105 106>; + key_val = <0 143 266 389 512 635>; //val=voltage/1800mV*1023 + key_tolerance = <40 40 40 40 40 40>; + }; + + unifykey{ + compatible = "amlogic, unifykey"; + status = "okay"; + + unifykey-num = <6>; + unifykey-index-0 = <&keysn_0>; + unifykey-index-1 = <&keysn_1>; + unifykey-index-2 = <&keysn_2>; + unifykey-index-3 = <&keysn_3>; + unifykey-index-4 = <&keysn_4>; + unifykey-index-5 = <&keysn_5>; + unifykey-index-6 = <&keysn_6>; + + keysn_0: key_0{ + key-name = "usid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_1:key_1{ + key-name = "mac"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_2:key_2{ + key-name = "secure_boot_set"; + key-device = "efuse"; + key-permit = "write"; + }; + keysn_3:key_3{ + key-name = "mac_bt"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_4:key_4{ + key-name = "mac_wifi"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_5:key_5{ + key-name = "deviceid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_6:key_6{ + key-name = "gva_certs"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + };//End unifykey + audio_data: audio_data { + compatible = "amlogic, audio_data"; + query_licence_cmd = <0x82000050>; + status = "okay"; + }; +}; /* end of / */ +&efuse { + status = "ok"; +}; + +&pwm_ab { + status = "okay"; +}; +/* Audio Related start */ +/* for spk board */ +&i2c1 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&b_i2c_master>; + + tlv320adc3101_32: tlv320adc3101_32@32 { + compatible = "ti,tlv320adc3101"; + #sound-dai-cells = <0>; + reg = <0x19>; + differential_pair = <1>; + status = "okay"; + }; + + /*****************************************************************/ + tas5782m_pu1: tas5782m_pu1@48 { + compatible = "ti, tas5782m"; + #sound-dai-cells = <0>; + reg = <0x48>; + reset_pin = <&gpio_ao GPIOAO_4 GPIO_ACTIVE_LOW>; + status = "okay"; + codec_name = "tas5782m"; + work_mode = <0>; /*0: i2s 1:tdm*/ + chip_offset = <1>; /*chip_N [1,2....]*/ + }; + + tas5782m_pu2: tas5782m_pu2@49 { + compatible = "ti, tas5782m"; + #sound-dai-cells = <0>; + reg = <0x49>; + status = "okay"; + codec_name = "tas5782m"; + work_mode = <0>; /*0: i2s 1:tdm*/ + chip_offset = <2>; /*chip_N [1,2....]*/ + }; + + tas5782m_pu3: tas5782m_pu3@4a { + compatible = "ti, tas5782m"; + #sound-dai-cells = <0>; + reg = <0x4a>; + status = "okay"; + codec_name = "tas5782m"; + work_mode = <0>; /*0: i2s 1:tdm*/ + chip_offset = <3>; /*chip_N [1,2....]*/ + }; + + tas5782m_pu4: tas5782m_pu4@4b { + compatible = "ti, tas5782m"; + #sound-dai-cells = <0>; + reg = <0x4b>; + status = "okay"; + codec_name = "tas5782m"; + work_mode = <0>; /*0: i2s 1:tdm*/ + chip_offset = <4>; /*chip_N [1,2....]*/ + }; + /*****************************************************************/ + tas5707_36: tas5707_36@36 { + compatible = "ti, tas5707"; + #sound-dai-cells = <0>; + reg = <0x1b>; + status = "disabled"; + reset_pin = <&gpio_ao GPIOAO_4 0>; + }; + + tas5707_3a: tas5707_3a@3a { + compatible = "ti,tas5707"; + #sound-dai-cells = <0>; + reg = <0x1d>; + status = "disabled"; + }; +}; + +/* for mic board */ +&i2c_AO { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&ao_i2c_master_pin2>; + + /*****************************************************************/ + mcu6350: mcu6350@40 { + reg = <0x40>; + status = "okay"; + }; + + /*****************************************************************/ + tas5782m_pu5: tas5782m_pu5@48 { + compatible = "ti, tas5782m"; + #sound-dai-cells = <0>; + reg = <0x48>; + status = "okay"; + codec_name = "tas5782m"; + work_mode = <0>; /*0: i2s 1:tdm*/ + chip_offset = <5>; /*chip_N [1,2....]*/ + }; + + tas5782m_pu6: tas5782m_pu6@49 { + compatible = "ti, tas5782m"; + #sound-dai-cells = <0>; + reg = <0x49>; + status = "okay"; + codec_name = "tas5782m"; + work_mode = <0>; /*0: i2s 1:tdm*/ + chip_offset = <6>; /*chip_N [1,2....]*/ + }; + /*****************************************************************/ + aml_pca9557: aml_pca9557@0x1f { + compatible = "amlogic,pca9557_keypad"; + reg = <0x1f>; + key_num = <4>; + key_name = "fdr", "hotword", "pause", "mute"; + key_value = <106 105 139 116>; + key_index_mask = <0x4 0x8 0x10 0x20>; + key_input_mask = <0x3C>; + status = "okay"; + }; + + tlv320adc3101_30: tlv320adc3101_30@30 { + compatible = "ti,tlv320adc3101"; + #sound-dai-cells = <0>; + reg = <0x18>; + status = "disable"; + }; + tlv320adc3101_34: tlv320adc3101_34@30 { + compatible = "ti,tlv320adc3101"; + #sound-dai-cells = <0>; + reg = <0x1a>; + status = "disable"; + }; + tlv320adc3101_36: tlv320adc3101_36@30 { + compatible = "ti,tlv320adc3101"; + #sound-dai-cells = <0>; + reg = <0x1b>; + status = "disable"; + }; + + cy8c4014_08: cy8c4014_08@08 { + compatible = "cy8c4014"; + #sound-dai-cells = <0>; + reg = <0x8>; + status = "okay"; + }; + + is31fl3236a: is31f3236a@0x78 { + compatible = "issi,is31fl3236,gva"; + reg = <0x3c>; + status = "okay"; + led1_b { + label="LED1_B"; + reg_offset = <1>; + }; + led1_g { + label="LED1_G"; + reg_offset = <2>; + }; + led1_r { + label="LED1_R"; + reg_offset = <3>; + }; + led2_b { + label="LED2_B"; + reg_offset = <4>; + }; + led2_g { + label="LED2_G"; + reg_offset = <5>; + }; + led2_r { + label="LED2_R"; + reg_offset = <6>; + }; + led3_b { + label="LED3_B"; + reg_offset = <7>; + }; + led3_g { + label="LED3_G"; + reg_offset = <8>; + }; + led3_r { + label="LED3_R"; + reg_offset = <9>; + }; + led4_b { + label="LED4_B"; + reg_offset = <10>; + }; + led4_g { + label="LED4_G"; + reg_offset = <11>; + }; + led4_r { + label="LED4_R"; + reg_offset = <12>; + }; + }; +}; + +&audiobus { + aml_tdma: tdma { + compatible = "amlogic, axg-snd-tdma"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <1 0>; + dai-tdm-lane-slot-mask-out = <0 1>; + dai-tdm-clk-sel = <0>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_A + &clkc CLKID_MPLL0>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmout_a &tdmin_a &tdmout_a_data>; + }; + + aml_tdmb: tdmb { + compatible = "amlogic, axg-snd-tdmb"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <1 1 1 1>; + dai-tdm-lane-slot-mask-out = <0 0 0 0>; + dai-tdm-clk-sel = <1>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_B + &clkc CLKID_MPLL1>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + + /*A113D tdmb slave for HDMI*/ + pinctrl-0 = <&tdmb_mclk &tdmin_b_slv &tdmin_b>; + + /*A113D tdmb master for LineIn*/ + /* + * pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; + */ + }; + + aml_tdmc: tdmc { + compatible = "amlogic, axg-snd-tdmc"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 0 0 0>; + dai-tdm-lane-slot-mask-out = <1 1 1 1>; + dai-tdm-clk-sel = <2>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmc_mclk &tdmout_c>; + }; + + aml_spdif: spdif { + compatible = "amlogic, axg-snd-spdif"; + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 + &clkc CLKID_FCLK_DIV4 + &clkaudio CLKID_AUDIO_SPDIFIN + &clkaudio CLKID_AUDIO_SPDIFOUT + &clkaudio CLKID_AUDIO_SPDIFIN_CTRL + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "sysclk", "fixed_clk", "gate_spdifin", + "gate_spdifout", "clk_spdifin", "clk_spdifout"; + interrupts = + ; + + interrupt-names = "irq_spdifin"; + pinctrl-names = "spdif_pins"; + pinctrl-0 = <&spdifout &spdifin>; + + /* + * whether do asrc for pcm. + * if raw data, asrc is disabled automatically + * 0: "Disable", + * 1: "Enable:32K", + * 2: "Enable:44K", + * 3: "Enable:48K", + * 4: "Enable:88K", + * 5: "Enable:96K", + * 6: "Enable:176K", + * 7: "Enable:192K", + */ + auto_asrc = <3>; + status = "okay"; + }; + aml_pdm: pdm { + compatible = "amlogic, axg-snd-pdm"; + #sound-dai-cells = <0>; + clocks = <&clkaudio CLKID_AUDIO_PDM + &clkc CLKID_FCLK_DIV3 + &clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_PDMIN0 + &clkaudio CLKID_AUDIO_PDMIN1>; + clock-names = "gate", + "sysclk_srcpll", + "dclk_srcpll", + "pdm_dclk", + "pdm_sysclk"; + pinctrl-names = "pdm_pins"; + pinctrl-0 = <&pdmin>; + filter_mode = <1>; /* mode 0~4, defalut:1 */ + status = "okay"; + }; + + aml_loopback: loopback { + compatible = "amlogic, snd-loopback"; + + /* + * external loopback clock config + * enable clk while pdm record data + */ + /*clocks = <&clkc CLKID_MPLL1>;*/ + /*clock-names = "datalb_mpll";*/ + + /* + * 0: out rate = in data rate; + * 1: out rate = loopback data rate; + */ + + lb_mode = <0>; + + /* datain src + * 0: tdmin_a; + * 1: tdmin_b; + * 2: tdmin_c; + * 3: spdifin; + * 4: pdmin; + */ + datain_src = <4>; + datain_chnum = <8>; + datain_chmask = <0x7f>; + + /* tdmin_lb src + * 0: tdmoutA + * 1: tdmoutB + * 2: tdmoutC + * 3: PAD_tdminA + * 4: PAD_tdminB + * 5: PAD_tdminC + */ + + /*if tdmin_lb >= 3, use external loopback*/ + datalb_src = <2>; + datalb_chnum = <2>; + /*config which data pin as loopback*/ + /*datalb-lane-mask-in = <0 0 0 1>;*/ + datalb_chmask = <0x1>; + + status = "okay"; + }; + + audioresample: resample { + compatible = "amlogic, axg-resample"; + clocks = <&clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_MCLK_F + &clkaudio CLKID_AUDIO_RESAMPLE_CTRL>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + /*same with toddr_src + * TDMIN_A, + * TDMIN_B, + * TDMIN_C, + * SPDIFIN, + * PDMIN, + * NONE, + * TDMIN_LB, + * LOOPBACK, + */ + resample_module = <3>; + status = "okay"; + }; +}; /* end of audiobus */ + +&pinctrl_periphs { + tdmout_a: tdmout_a { + mux { + groups = "tdma_sclk", + "tdma_fs"; + function = "tdma_out"; + }; + }; + + tdmout_a_data: tdmout_a_data { + mux { + groups = "tdma_dout1_x15"; + function = "tdma_out"; + }; + }; + + tdmin_a: tdmin_a { + mux { + groups = "tdma_din0"; + function = "tdma_in"; + }; + }; + + tdmb_mclk: tdmb_mclk { + mux { + groups = "mclk_b"; + function = "mclk_b"; + }; + }; + + tdmout_b: tdmout_b { + mux { + groups = "tdmb_sclk", + "tdmb_fs"; + function = "tdmb_out"; + }; + }; + + tdmin_b_slv: tdmin_b_slv{ + mux { + groups = "tdmb_slv_sclk", "tdmb_slv_fs"; + function = "tdmb_in"; + }; + }; + + // tdmin and tdmout are the same pins. can't use at same time + tdmin_b:tdmin_b { + mux { + groups = "tdmb_din0", + "tdmb_din1", + "tdmb_din2_a12", + "tdmb_din3_a13"; + function = "tdmb_in"; + }; + }; + + tdmc_mclk: tdmc_mclk { + mux { + groups = "mclk_a"; + function = "mclk_a"; + }; + }; + + tdmout_c:tdmout_c { + mux { + groups = "tdmc_sclk", + "tdmc_fs", + "tdmc_dout0", + "tdmc_dout1", + "tdmc_dout2_a6", + "tdmc_dout3_a7"; + function = "tdmc_out"; + }; + }; + + + tdmin_c:tdmin_c { + mux { + groups = "tdmc_din1"; + function = "tdmc_in"; + }; + }; + + spdifout: spidfout { + mux { + groups = "spdif_out_a20"; + function = "spdif_out"; + }; + }; + + spdifin: spidfin { + mux { + groups = "spdif_in_a19"; + function = "spdif_in"; + }; + }; + + pdmin: pdmin { + mux { + groups = "pdm_dclk_a14", + "pdm_din0", + "pdm_din1", + "pdm_din2", + "pdm_din3"; + function = "pdm"; + }; + }; + + bl_pwm_on_pins: bl_pwm_on_pin { + mux { + groups = "pwm_b_z"; + function = "pwm_b"; + }; + }; + bl_pwm_off_pins:bl_pwm_off_pin { + mux { + pins = "GPIOZ_4"; + function = "gpio_periphs"; + output-high; + }; + }; +}; /* end of pinctrl_periphs */ +/* Audio Related End */ + +&aobus{ + uart_AO: serial@3000 { + compatible = "amlogic, meson-uart"; + reg = <0x0 0x3000 0x0 0x18>; + interrupts = <0 193 1>; + status = "okay"; + clocks = <&xtal>; + clock-names = "clk_uart"; + xtal_tick_en = <1>; + fifosize = < 64 >; + pinctrl-names = "default"; + pinctrl-0 = <&ao_uart_pins>; + support-sysrq = <0>; /* 0 not support , 1 support */ + }; + + uart_AO_B: serial@4000 { + compatible = "amlogic, meson-uart"; + reg = <0x0 0x4000 0x0 0x18>; + interrupts = <0 197 1>; + status = "disable"; + clocks = <&xtal>; + clock-names = "clk_uart"; + fifosize = < 64 >; + pinctrl-names = "default"; + pinctrl-0 = <&ao_b_uart_pins>; + }; +}; + +&audio_data{ + status = "okay"; +}; + +&custom_maps{ + mapnum = <4>; + map0 = <&map_0>; + map1 = <&map_1>; + map2 = <&map_2>; + map3 = <&map_3>; + map_0: map_0{ + mapname = "amlogic-remote-1"; + customcode = <0xfb04>; + release_delay = <80>; + size = <50>; /*keymap size*/ + keymap = ; + }; + map_1: map_1{ + mapname = "amlogic-remote-2"; + customcode = <0xfe01>; + release_delay = <80>; + size = <53>; + keymap = ; + }; + map_2: map_2{ + mapname = "amlogic-remote-3"; + customcode = <0xbd02>; + release_delay = <80>; + size = <17>; + keymap = ; + }; + map_3: map_3{ + mapname = "amlogic-remote-3"; + customcode = <0xa4e8>; /* Reference Remote Control */ + release_delay = <80>; + size = <45>; + keymap = < + REMOTE_KEY(0xc7, 200) /* power */ + REMOTE_KEY(0x93, 201) /* eject-->input source */ + REMOTE_KEY(0xb2, 202) /* usb */ + REMOTE_KEY(0xb8, 203) /* coaxial */ + REMOTE_KEY(0xb7, 204) /* aux */ + REMOTE_KEY(0x8a, 205) /* scan-->hdmi arc */ + REMOTE_KEY(0x96, 206) /* dimmer */ + REMOTE_KEY(0x90, 207) /* hdmi1 */ + REMOTE_KEY(0xa8, 208) /* hdmi2 */ + REMOTE_KEY(0x85, 209) /* mute */ + REMOTE_KEY(0x80, 210) /* vol+ */ + REMOTE_KEY(0x81, 211) /* vol- */ + REMOTE_KEY(0x61, 212) /* DAP */ + REMOTE_KEY(0x62, 213) /* BM */ + REMOTE_KEY(0x63, 214) /* DRC */ + REMOTE_KEY(0x64, 215) /* POST */ + REMOTE_KEY(0x65, 216) /* UPMIX */ + REMOTE_KEY(0x66, 217) /* VIRT */ + REMOTE_KEY(0x67, 218) /* LEGACY */ + REMOTE_KEY(0x68, 219) /* HFILT */ + REMOTE_KEY(0x69, 220) /* Loundness */ + REMOTE_KEY(0x60, 221) /* Audio_info */ + REMOTE_KEY(0xb1, 222) /* CD */ + REMOTE_KEY(0xb4, 223) /* CD */ + REMOTE_KEY(0xb9, 224) /* CD */ + REMOTE_KEY(0xab, 225) /* CD */ + REMOTE_KEY(0x91, 226) /* CD */ + REMOTE_KEY(0x92, 227) /* CD */ + REMOTE_KEY(0x89, 228) /* CD */ + REMOTE_KEY(0x88, 229) /* CD */ + REMOTE_KEY(0xa5, 230) /* CD */ + REMOTE_KEY(0x84, 231) /* CD */ + REMOTE_KEY(0x72, 232) /* CD */ + REMOTE_KEY(0x73, 233) /* CD */ + REMOTE_KEY(0x9a, 234) /* CD */ + REMOTE_KEY(0x9b, 235) /* CD */ + REMOTE_KEY(0xa0, 236) /* CD */ + REMOTE_KEY(0x71, 237) /* CD */ + REMOTE_KEY(0x74, 238) /* CD */ + REMOTE_KEY(0x75, 239) /* CD */ + REMOTE_KEY(0x7e, 240) /* CD */ + REMOTE_KEY(0x7f, 241) /* CD */ + REMOTE_KEY(0x7a, 242) /* CD */ + REMOTE_KEY(0xa7, 243) /* CD */ + REMOTE_KEY(0xa9, 244) /* CD */ + >; + }; +}; diff --git a/arch/arm64/boot/dts/amlogic/axg_s400_v03sbr.dts b/arch/arm64/boot/dts/amlogic/axg_s400_v03sbr.dts new file mode 100644 index 000000000000..6f86df42574a --- /dev/null +++ b/arch/arm64/boot/dts/amlogic/axg_s400_v03sbr.dts @@ -0,0 +1,1717 @@ +/* + * arch/arm64/boot/dts/amlogic/axg_s400_v03sbr.dts + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +/dts-v1/; + +#include "mesonaxg.dtsi" +/* #include "mesonaxg_s400-panel.dtsi" */ +/ { + model = "Amlogic"; + amlogic-dt-id = "axg_s400_v03sbr"; + compatible = "amlogic, axg"; + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + + aliases { + serial0 = &uart_AO; + serial1 = &uart_A; + }; + + memory@00000000 { + device_type = "memory"; + linux,usable-memory = <0x0 0x000000 0x0 0x40000000>; + }; + + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + /* global autoconfigured region for contiguous allocations */ + ramoops@0x07400000 { + compatible = "ramoops"; + reg = <0x0 0x07400000 0x0 0x00100000>; + record-size = <0x8000>; + console-size = <0x8000>; + ftrace-size = <0x20000>; + }; + + secmon_reserved:linux,secmon { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x400000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x05000000 0x0 0x400000>; + }; + + secos_reserved:linux,secos { + status = "disabled"; + compatible = "amlogic, aml_secos_memory"; + reg = <0x0 0x05300000 0x0 0x2000000>; + no-map; + }; + fb_reserved:linux,meson-fb { + //compatible = "amlogic, fb-memory"; + //reg = <0x0 0x3e000000 0x0 0x1f00000>; + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x2000000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x3e000000 0x0 0x2000000>; + }; + }; + mtd_nand { + compatible = "amlogic, aml_mtd_nand"; + dev_name = "mtdnand"; + status = "okay"; + reg = <0x0 0xFFE07800 0x0 0x200>; + interrupts = < 0 34 1 >; + pinctrl-names = "nand_rb_mod","nand_norb_mod", "nand_cs_only"; + pinctrl-0 = <&all_nand_pins>; + pinctrl-1 = <&all_nand_pins>; + pinctrl-2 = <&nand_cs_pins>; + device_id = <0>; + + /*fip/tpl configurations, must be same + * with uboot if bl_mode was set as 1 + * bl_mode: 0 compact mode; 1 descrete mode + * if bl_mode was set as 1, fip configeration will work + */ + bl_mode = <1>; + /*copy count of fip*/ + fip_copies = <4>; + /*size of each fip copy */ + fip_size = <0x200000>; + nand_clk_ctrl = <0xFFE07000>; + plat-names = "bootloader","nandnormal"; + plat-num = <2>; + plat-part-0 = <&bootloader>; + plat-part-1 = <&nandnormal>; + bootloader: bootloader{ + enable_pad ="ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <1>; + part_num = <0>; + rb_detect = <1>; + }; + nandnormal: nandnormal{ + enable_pad ="ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + plane_mode = "twoplane"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <2>; + part_num = <3>; + partition = <&nand_partitions>; + rb_detect = <1>; + }; + nand_partitions:nand_partition{ + /* + * if bl_mode is 1, tpl size was generate by + * fip_copies * fip_size which + * will not skip bad when calculating + * the partition size; + * + * if bl_mode is 0, + * tpl partition must be comment out. + */ + tpl{ + offset=<0x0 0x0>; + size=<0x0 0x0>; + }; + misc{ + offset=<0x0 0x0>; + size=<0x0 0x200000>; + }; + logo{ + offset=<0x0 0x0>; + size=<0x0 0x200000>; + }; + recovery{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + boot{ + offset=<0x0 0x0>; + size=<0x0 0xF00000>; + }; + system{ + offset=<0x0 0x0>; + size=<0x0 0x11800000>; + }; + data{ + offset=<0xffffffff 0xffffffff>; + size=<0x0 0x0>; + }; + }; + }; + + + ethmac: ethernet@0xff3f0000 { + compatible = "amlogic, gxbb-eth-dwmac"; + reg = <0x0 0xff3f0000 0x0 0x10000 + 0x0 0xff634540 0x0 0x8>; + interrupts = <0 8 1>; + pinctrl-names = "external_eth_pins"; + pinctrl-0 = <&external_eth_pins>; + mc_val_internal_phy = <0x1800>; + mc_val_external_phy = <0x1621>; + interrupt-names = "macirq"; + clocks = <&clkc CLKID_ETH_CORE>; + clock-names = "ethclk81"; + internal_phy=<0>; + }; + + aml_sensor0: aml-sensor@0 { + compatible = "amlogic, aml-thermal"; + device_name = "thermal"; + #thermal-sensor-cells = <1>; + cooling_devices { + cpufreq_cool_cluster0 { + min_state = <1000000>; + dyn_coeff = <140>; + cluster_id = <0>; + node_name = "cpufreq_cool0"; + device_type = "cpufreq"; + }; + cpucore_cool_cluster0 { + min_state = <1>; + dyn_coeff = <0>; + cluster_id = <0>; + node_name = "cpucore_cool0"; + device_type = "cpucore"; + }; + }; + cpufreq_cool0:cpufreq_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + cpucore_cool0:cpucore_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + }; + thermal-zones { + soc_thermal { + polling-delay = <1000>; + polling-delay-passive = <100>; + sustainable-power = <1050>; + + thermal-sensors = <&aml_sensor0 3>; + + trips { + switch_on: trip-point@0 { + temperature = <70000>; + hysteresis = <1000>; + type = "passive"; + }; + control: trip-point@1 { + temperature = <80000>; + hysteresis = <1000>; + type = "passive"; + }; + hot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + critical: trip-point@3 { + temperature = <260000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + + cooling-maps { + cpufreq_cooling_map { + trip = <&control>; + cooling-device = <&cpufreq_cool0 0 4>; + contribution = <1024>; + }; + cpucore_cooling_map { + trip = <&control>; + cooling-device = <&cpucore_cool0 0 3>; + contribution = <1024>; + }; + }; + }; + }; + + dwc3: dwc3@ff500000 { + compatible = "synopsys, dwc3"; + status = "okay"; + reg = <0x0 0xff500000 0x0 0x100000>; + interrupts = <0 30 4>; + usb-phy = <&usb2_phy>, <&usb3_phy>; + cpu-type = "gxl"; + clock-src = "usb3.0"; + clocks = <&clkc CLKID_USB_GENERAL>; + clock-names = "dwc_general"; + }; + + usb2_phy: usb2phy@ffe09000 { + compatible = "amlogic, amlogic-new-usb2"; + status = "okay"; + portnum = <4>; + reg = <0x0 0xffe09000 0x0 0x80 + 0x0 0xffd01008 0x0 0x4>; + }; + + usb3_phy: usb3phy@ffe09080 { + compatible = "amlogic, amlogic-new-usb3"; + status = "okay"; + portnum = <0>; + reg = <0x0 0xffe09080 0x0 0x20>; + interrupts = <0 16 4>; + otg = <1>; + gpio-vbus-power = "GPIOAO_5"; + gpios = <&gpio_ao GPIOAO_5 GPIO_ACTIVE_HIGH>; + }; + + dwc2_a { + compatible = "amlogic, dwc2"; + device_name = "dwc2_a"; + reg = <0x0 0xff400000 0x0 0x40000>; + status = "okay"; + interrupts = <0 31 4>; + pl-periph-id = <0>; /** lm name */ + clock-src = "usb0"; /** clock src */ + port-id = <0>; /** ref to mach/usb.h */ + port-type = <2>; /** 0: otg, 1: host, 2: slave */ + port-speed = <0>; /** 0: default, high, 1: full */ + port-config = <0>; /** 0: default */ + /*0:default,1:single,2:incr,3:incr4,4:incr8,5:incr16,6:disable*/ + port-dma = <0>; + port-id-mode = <0>; /** 0: hardware, 1: sw_host, 2: sw_slave*/ + usb-fifo = <728>; + cpu-type = "gxl"; + /** 0: normal, 1: otg+dwc3 host only, 2: otg+dwc3 device only*/ + controller-type = <3>; + phy-reg = <0xffe09000>; + phy-reg-size = <0xa0>; + clocks = <&clkc CLKID_USB_GENERAL + &clkc CLKID_USB1_TO_DDR + &clkc CLKID_USB1>; + clock-names = "usb_general", + "usb1", + "usb1_to_ddr"; + }; + + pcie_A: pcieA@f9800000 { + compatible = "amlogic, amlogic-pcie", "snps,dw-pcie"; + reg = <0x0 0xf9800000 0x0 0x400000 + 0x0 0xff646000 0x0 0x2000 + 0x0 0xf9f00000 0x0 0x100000 + 0x0 PCIE_PHY_REG 0x0 PCIE_PHY_SIZE + 0x0 PCIE_RESET_REG 0x0 PCIE_RESET_SIZE>; + reg-names = "elbi", "cfg", "config", "phy", "reset"; + reset-gpio = <&gpio GPIOX_19 GPIO_ACTIVE_HIGH>; + interrupts = <0 177 0>; + #interrupt-cells = <1>; + bus-range = <0x0 0xff>; + #address-cells = <3>; + #size-cells = <2>; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &gic GIC_SPI 179 IRQ_TYPE_EDGE_RISING>; + device_type = "pci"; + ranges = <0x82000000 0 0 0x0 0xf9c00000 0 0x00300000>; + /* non-prefetchable memory */ + num-lanes = <1>; + pcie-num = <1>; + + clocks = <&clkc CLKID_USB_GENERAL + &clkc CLKID_PCIE_PLL + &clkc CLKID_MIPI_ENABLE_GATE + &clkc CLKID_MIPI_BANDGAP_GATE + &clkc CLKID_PCIE_A + &clkc CLKID_PCIE_CML_EN0>; + clock-names = "pcie_general", + "pcie_refpll", + "pcie_mipi_enable_gate", + "pcie_mipi_bandgap_gate", + "pcie", + "port"; + /*reset-gpio-type 0:Shared pad(no reset)1:OD pad2:Normal pad*/ + gpio-type = <2>; + status = "disabled"; + }; + + pcie_B: pcieB@fa000000 { + compatible = "amlogic, amlogic-pcie", "snps,dw-pcie"; + reg = <0x0 0xfa000000 0x0 0x400000 + 0x0 0xff648000 0x0 0x2000 + 0x0 0xfa400000 0x0 0x100000 + 0x0 PCIE_PHY_REG 0x0 PCIE_PHY_SIZE + 0x0 PCIE_RESET_REG 0x0 PCIE_RESET_SIZE>; + reg-names = "elbi", "cfg", "config", "phy", "reset"; + reset-gpio = <&gpio GPIOZ_10 GPIO_ACTIVE_HIGH>; + interrupts = <0 167 0>; + #interrupt-cells = <1>; + bus-range = <0x0 0xff>; + #address-cells = <3>; + #size-cells = <2>; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &gic GIC_SPI 169 IRQ_TYPE_EDGE_RISING>; + device_type = "pci"; + ranges = <0x81000000 0 0 0 0xfa500000 0x0 0x10000 + /* downstream I/O */ + 0x82000000 0 0xfa510000 0x0 0xfa510000 0 0x002f0000>; + /* non-prefetchable memory */ + num-lanes = <1>; + pcie-num = <2>; + + clocks = <&clkc CLKID_USB_GENERAL + &clkc CLKID_PCIE_PLL + &clkc CLKID_MIPI_ENABLE_GATE + &clkc CLKID_MIPI_BANDGAP_GATE + &clkc CLKID_PCIE_B + &clkc CLKID_PCIE_CML_EN1>; + clock-names = "pcie_general", + "pcie_refpll", + "pcie_mipi_enable_gate", + "pcie_mipi_bandgap_gate", + "pcie", + "port"; + /*reset-gpio-type 0:Shared pad(no reset)1:OD pad2:Normal pad*/ + gpio-type = <1>; + status = "disabled"; + }; + + + uart_A: serial@ffd24000 { + compatible = "amlogic, meson-uart"; + reg = <0x0 0xffd24000 0x0 0x18>; + interrupts = <0 26 1>; + status = "okay"; + clocks = <&xtal + &clkc CLKID_UART0>; + clock-names = "clk_uart", + "clk_gate"; + fifosize = < 128 >; + pinctrl-names = "default"; + pinctrl-0 = <&a_uart_pins>; + }; + + uart_B: serial@ffd23000 { + compatible = "amlogic, meson-uart"; + reg = <0x0 0xffd23000 0x0 0x18>; + interrupts = <0 75 1>; + status = "disabled"; + clocks = <&xtal + &clkc CLKID_UART1>; + clock-names = "clk_uart", + "clk_gate"; + fifosize = < 64 >; + pinctrl-names = "default"; + pinctrl-0 = <&b_uart_pins>; + }; + + vpu { + compatible = "amlogic, vpu-axg"; + dev_name = "vpu"; + status = "okay"; + clocks = <&clkc CLKID_VAPB_MUX>, + <&clkc CLKID_VPU_INTR>, + <&clkc CLKID_VPU_P0_COMP>, + <&clkc CLKID_VPU_P1_COMP>, + <&clkc CLKID_VPU_MUX>; + clock-names = "vapb_clk", + "vpu_intr_gate", + "vpu_clk0", + "vpu_clk1", + "vpu_clk"; + clk_level = <3>; + /* 0: 100.0M 1: 166.7M 2: 200.0M 3: 250.0M */ + }; + + vout { + compatible = "amlogic, vout"; + dev_name = "vout"; + status = "okay"; + }; + + /* Sound iomap */ + aml_snd_iomap { + compatible = "amlogic, snd-iomap"; + status = "okay"; + #address-cells=<2>; + #size-cells=<2>; + ranges; + pdm_bus { + reg = <0x0 0xFF632000 0x0 0x2000>; + }; + audiobus_base { + reg = <0x0 0xFF642000 0x0 0x2000>; + }; + }; + pdm_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, pdm_dummy_codec"; + status = "okay"; + }; + dummy_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, aml_dummy_codec"; + status = "okay"; + }; + + auge_sound { + compatible = "amlogic, axg-sound-card"; + aml-audio-card,name = "AML-AUGESOUND"; + + aml-audio-card,loopback = <&aml_loopback>; + + aml-audio-card,hp-det-gpio = <&gpio GPIOZ_7 GPIO_ACTIVE_LOW>; + + aml-audio-card,dai-link@0 { + format = "dsp_a"; + mclk-fs = <512>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + //bitclock-master = <&tdmacodec>; + //frame-master = <&tdmacodec>; + tdmacpu: cpu { + sound-dai = <&aml_tdma>; + dai-tdm-slot-tx-mask = + <1>; + dai-tdm-slot-rx-mask = + <1>; + dai-tdm-slot-num = <1>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <512000>; + }; + tdmacodec: codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@1 { + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + + /*A113D tdmb slave for HDMI*/ + bitclock-master = <&tdmbcodec>; + frame-master = <&tdmbcodec>; + + /*A113D tdmb master for LineIn*/ + /* + * bitclock-master = <&aml_tdmb>; + * frame-master = <&aml_tdmb>; + */ + + suffix-name = "alsaPORT-i2sCapture"; + cpu { + sound-dai = <&aml_tdmb>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmbcodec:codec { + /* + * prefix-names = "3101_A", "3101_B", + * "3101_C", "3101_D"; + * sound-dai = <&tlv320adc3101_32 + * &tlv320adc3101_30 + * &tlv320adc3101_34 + * &tlv320adc3101_36>; + */ + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@2 { + format = "i2s"; + mclk-fs = <256>; + continuous-clock; + //bitclock-inversion; + //frame-inversion; + //bitclock-master = <&aml_tdmc>; + //frame-master = <&aml_tdmc>; + cpu { + sound-dai = <&aml_tdmc>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + codec { + /* + *prefix-names = "5707_A", "5707_B"; + *sound-dai = <&tas5707_36 &tas5707_3a + * &dummy_codec>; + */ + prefix-names = "tas5782m_pu1", "tas5782m_pu2", + "tas5782m_pu3", "tas5782m_pu4", "tas5782m_pu5", + "tas5782m_pu6"; + sound-dai = <&tas5782m_pu1 &tas5782m_pu2 + &tas5782m_pu3 &tas5782m_pu4 &tas5782m_pu5 + &tas5782m_pu6>; + }; + }; + + aml-audio-card,dai-link@3 { + mclk-fs = <256>; + cpu { + sound-dai = <&aml_pdm>; + }; + codec { + /* + *enable external loopback + *and tlv320adc3101 as loopback + */ + /*sound-dai = <&pdm_codec &tlv320adc3101_32>;*/ + /* + * enable internal loopback + * or disable loopback + */ + sound-dai = <&pdm_codec>; + }; + }; + + aml-audio-card,dai-link@4 { + mclk-fs = <128>; + cpu { + sound-dai = <&aml_spdif>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + }; + + bt-dev{ + compatible = "amlogic, bt-dev"; + dev_name = "bt-dev"; + status = "okay"; + gpio_reset = <&gpio GPIOX_21 GPIO_ACTIVE_HIGH>; + }; + + wifi{ + compatible = "amlogic, aml_wifi"; + dev_name = "aml_wifi"; + status = "okay"; + interrupt_pin = <&gpio GPIOX_6 GPIO_ACTIVE_HIGH>; + interrupts = < 0 67 4>; + irq_trigger_type = "GPIO_IRQ_LOW"; + power_on_pin2 = <&gpio GPIOX_16 GPIO_ACTIVE_HIGH>; + power_on_pin = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; + dhd_static_buf; //if use bcm wifi, config dhd_static_buf + pinctrl-names = "default"; + pinctrl-0 = <&wifi_32k_pins>; + pwm_config = <&wifi_pwm_conf>; + }; + + wifi_pwm_conf:wifi_pwm_conf{ + pwm_channel1_conf { + pwms = <&pwm_ab MESON_PWM_0 30541 0>; + duty-cycle = <15270>; + times = <10>; + }; + pwm_channel2_conf { + pwms = <&pwm_ab MESON_PWM_2 30500 0>; + duty-cycle = <15250>; + times = <12>; + }; + }; + + sd_emmc_c: emmc@ffe07000 { + status = "disabled"; + compatible = "amlogic, meson-mmc-axg"; + reg = <0x0 0xffe07000 0x0 0x2000>; + interrupts = <0 218 1>; + pinctrl-names = "emmc_clk_cmd_pins", "emmc_all_pins"; + pinctrl-0 = <&emmc_clk_cmd_pins>; + pinctrl-1 = <&emmc_conf_pull_up &emmc_conf_pull_done>; + clocks = <&clkc CLKID_SD_EMMC_C>, + <&clkc CLKID_SD_EMMC_C_P0_COMP>, + <&clkc CLKID_FCLK_DIV2>, + <&clkc CLKID_FCLK_DIV5>, + <&xtal>; + clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + + bus-width = <8>; + cap-sd-highspeed; + cap-mmc-highspeed; + mmc-ddr-1_8v; + mmc-hs200-1_8v; + + max-frequency = <200000000>; + non-removable; + disable-wp; + emmc { + pinname = "emmc"; + ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ + caps = "MMC_CAP_8_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + "MMC_CAP_1_8V_DDR", + "MMC_CAP_HW_RESET", + "MMC_CAP_ERASE", + "MMC_CAP_CMD23"; + caps2 = "MMC_CAP2_HS200", "MMC_CAP2_HS400"; + f_min = <400000>; + f_max = <200000000>; + max_req_size = <0x20000>; /**128KB*/ + gpio_dat3 = <&gpio BOOT_3 GPIO_ACTIVE_HIGH>; + tx_delay = <4>; + hw_reset = <&gpio BOOT_9 GPIO_ACTIVE_HIGH>; + card_type = <1>; + /* 1:mmc card(include eMMC), + * 2:sd card(include tSD) + */ + }; + }; + + sd_emmc_b:sdio@ffe05000 { + status = "okay"; + compatible = "amlogic, meson-mmc-axg"; + reg = <0x0 0xffe05000 0x0 0x2000>; + interrupts = <0 217 4>; + pinctrl-names = "sdio_clk_cmd_pins", "sdio_all_pins"; + pinctrl-0 = <&sdio_clk_cmd_pins>; + pinctrl-1 = <&sdio_all_pins>; + clocks = <&clkc CLKID_SD_EMMC_B>, + <&clkc CLKID_SD_EMMC_B_P0_COMP>, + <&clkc CLKID_FCLK_DIV2>, + <&clkc CLKID_FCLK_DIV5>, + <&xtal>; + clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + + bus-width = <4>; + cap-sd-highspeed; + cap-mmc-highspeed; + max-frequency = <100000000>; + non-removable; + disable-wp; + sdio { + pinname = "sdio"; + ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + "MMC_CAP_UHS_SDR12", + "MMC_CAP_UHS_SDR25", + "MMC_CAP_UHS_SDR50", + "MMC_CAP_UHS_SDR104", + "MMC_PM_KEEP_POWER", + "MMC_CAP_SDIO_IRQ"; + f_min = <400000>; + f_max = <200000000>; + max_req_size = <0x20000>; /**128KB*/ + card_type = <3>; + /* 3:sdio device(ie:sdio-wifi), + * 4:SD combo (IO+mem) card + */ + }; + }; + + partitions: partitions{ + parts = <11>; + part-0 = <&logo>; + part-1 = <&recovery>; + part-2 = <&rsv>; + part-3 = <&tee>; + part-4 = <&crypt>; + part-5 = <&misc>; + part-6 = <&instaboot>; + part-7 = <&boot>; + part-8 = <&system>; + part-9 = <&cache>; + part-10 = <&data>; + + logo:logo{ + pname = "logo"; + size = <0x0 0x2000000>; + mask = <1>; + }; + recovery:recovery{ + pname = "recovery"; + size = <0x0 0x2000000>; + mask = <1>; + }; + rsv:rsv{ + pname = "rsv"; + size = <0x0 0x800000>; + mask = <1>; + }; + tee:tee{ + pname = "tee"; + size = <0x0 0x800000>; + mask = <1>; + }; + crypt:crypt{ + pname = "crypt"; + size = <0x0 0x2000000>; + mask = <1>; + }; + misc:misc{ + pname = "misc"; + size = <0x0 0x2000000>; + mask = <1>; + }; + instaboot:instaboot{ + pname = "instaboot"; + size = <0x0 0x400000>; + mask = <1>; + }; + boot:boot + { + pname = "boot"; + size = <0x0 0x2000000>; + mask = <1>; + }; + system:system + { + pname = "system"; + size = <0x0 0x80000000>; + mask = <1>; + }; + cache:cache + { + pname = "cache"; + size = <0x0 0x20000000>; + mask = <2>; + }; + data:data + { + pname = "data"; + size = <0xffffffff 0xffffffff>; + mask = <4>; + }; + }; + + meson-fb { + compatible = "amlogic, meson-axg"; + memory-region = <&fb_reserved>; + dev_name = "meson-fb"; + status = "disabled"; + interrupts = <0 3 1 + 0 89 1>; + interrupt-names = "viu-vsync", "rdma"; + mem_size = <0x00300000 0x1800000 0x00000000>; + /* uboot logo,fb0/fb1 memory size */ + display_mode_default = "1080p60hz"; + scale_mode = <0>; + /** 0:VPU free scale 1:OSD free scale 2:OSD super scale */ + display_size_default = <768 1024 768 2048 32>; + /*768*1024*4*2 = 0x600000*/ + mem_alloc = <1>; + logo_addr = "0x3e000000"; + pxp_mode = <0>; /** 0:normal mode 1:pxp mode */ + }; + + ge2d { + compatible = "amlogic, ge2d-axg"; + dev_name = "ge2d"; + status = "disabled"; + interrupts = <0 150 1>; + interrupt-names = "ge2d"; + clocks = <&clkc CLKID_VAPB_MUX>, + <&clkc CLKID_G2D>, + <&clkc CLKID_GE2D_GATE>; + clock-names = "clk_vapb_0", + "clk_ge2d", + "clk_ge2d_gate"; + reg = <0x0 0xff940000 0x0 0x10000>; + }; + + adc_keypad { + compatible = "amlogic, adc_keypad"; + status = "okay"; + key_name = "power", "vol-", "sos+", "wifi", "<<", ">>", "vol+"; + key_num = <7>; + io-channels = <&saradc SARADC_CH0>; + io-channel-names = "key-chan-0"; + key_chan = ; + key_code = <116 114 115 139 105 106 107>; + key_val = <0 143 266 389 512 635 840>; //val=voltage/1800mV*1023 + key_tolerance = <40 40 40 40 40 40 40>; + }; + + unifykey{ + compatible = "amlogic, unifykey"; + status = "okay"; + + unifykey-num = <6>; + unifykey-index-0 = <&keysn_0>; + unifykey-index-1 = <&keysn_1>; + unifykey-index-2 = <&keysn_2>; + unifykey-index-3 = <&keysn_3>; + unifykey-index-4 = <&keysn_4>; + unifykey-index-5 = <&keysn_5>; + + keysn_0: key_0{ + key-name = "usid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_1:key_1{ + key-name = "mac"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_2:key_2{ + key-name = "secure_boot_set"; + key-device = "efuse"; + key-permit = "write"; + }; + keysn_3:key_3{ + key-name = "mac_bt"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_4:key_4{ + key-name = "mac_wifi"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_5:key_5{ + key-name = "deviceid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + };//End unifykey + +}; /* end of / */ +&efuse { + status = "ok"; +}; + +&pwm_ab { + status = "okay"; +}; +/* Audio Related start */ +/* for spk board */ +&i2c1 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&b_i2c_master>; + + tlv320adc3101_32: tlv320adc3101_32@32 { + compatible = "ti,tlv320adc3101"; + #sound-dai-cells = <0>; + reg = <0x19>; + differential_pair = <1>; + status = "okay"; + }; + + /*****************************************************************/ + tas5782m_pu1: tas5782m_pu1@48 { + compatible = "ti, tas5782m"; + #sound-dai-cells = <0>; + reg = <0x48>; + reset_pin = <&gpio_ao GPIOAO_4 GPIO_ACTIVE_LOW>; + status = "okay"; + codec_name = "tas5782m"; + work_mode = <0>; /*0: i2s 1:tdm*/ + chip_offset = <1>; /*chip_N [1,2....]*/ + }; + + tas5782m_pu2: tas5782m_pu2@49 { + compatible = "ti, tas5782m"; + #sound-dai-cells = <0>; + reg = <0x49>; + status = "okay"; + codec_name = "tas5782m"; + work_mode = <0>; /*0: i2s 1:tdm*/ + chip_offset = <2>; /*chip_N [1,2....]*/ + }; + + tas5782m_pu3: tas5782m_pu3@4a { + compatible = "ti, tas5782m"; + #sound-dai-cells = <0>; + reg = <0x4a>; + status = "okay"; + codec_name = "tas5782m"; + work_mode = <0>; /*0: i2s 1:tdm*/ + chip_offset = <3>; /*chip_N [1,2....]*/ + }; + + tas5782m_pu4: tas5782m_pu4@4b { + compatible = "ti, tas5782m"; + #sound-dai-cells = <0>; + reg = <0x4b>; + status = "okay"; + codec_name = "tas5782m"; + work_mode = <0>; /*0: i2s 1:tdm*/ + chip_offset = <4>; /*chip_N [1,2....]*/ + }; + /*****************************************************************/ + + tas5707_36: tas5707_36@36 { + compatible = "ti, tas5707"; + #sound-dai-cells = <0>; + reg = <0x1b>; + status = "disabled"; + reset_pin = <&gpio_ao GPIOAO_4 GPIO_ACTIVE_LOW>; + }; + + tas5707_3a: tas5707_3a@3a { + compatible = "ti, tas5707"; + #sound-dai-cells = <0>; + reg = <0x1d>; + status = "disabled"; + }; +}; + +/* for mic board : /dev/i2c-1 */ +&i2c_AO { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&ao_i2c_master_pin2>; + + /*****************************************************************/ + mcu6350: mcu6350@40 { + reg = <0x40>; + status = "okay"; + }; + + /*****************************************************************/ + tas5782m_pu5: tas5782m_pu5@48 { + compatible = "ti, tas5782m"; + #sound-dai-cells = <0>; + reg = <0x48>; + status = "okay"; + codec_name = "tas5782m"; + work_mode = <0>; /*0: i2s 1:tdm*/ + chip_offset = <5>; /*chip_N [1,2....]*/ + }; + + tas5782m_pu6: tas5782m_pu6@49 { + compatible = "ti, tas5782m"; + #sound-dai-cells = <0>; + reg = <0x49>; + status = "okay"; + codec_name = "tas5782m"; + work_mode = <0>; /*0: i2s 1:tdm*/ + chip_offset = <6>; /*chip_N [1,2....]*/ + }; + /*****************************************************************/ + + aml_pca9557: aml_pca9557@0x1f { + compatible = "aml, ledring"; + reg = <0x1f>; + mode = <0>; /*0: 6-led 1: 4key+2led */ + key_num = <4>; + led_dev_name = "aml_ledring"; + key_dev_name = "aml_pca_key"; + key_name = "mute", "pause", "vol+", "vol-"; + key_value = <200 201 202 203>; + status = "okay"; + }; + + tlv320adc3101_30: tlv320adc3101_30@30 { + compatible = "ti,tlv320adc3101"; + #sound-dai-cells = <0>; + reg = <0x18>; + status = "disabled"; + }; + tlv320adc3101_34: tlv320adc3101_34@30 { + compatible = "ti,tlv320adc3101"; + #sound-dai-cells = <0>; + reg = <0x1a>; + status = "disabled"; + }; + tlv320adc3101_36: tlv320adc3101_36@30 { + compatible = "ti,tlv320adc3101"; + #sound-dai-cells = <0>; + reg = <0x1b>; + status = "disabled"; + }; + + es7243_10: es7243_10@10 { + compatible = "MicArray_0"; + #sound-dai-cells = <0>; + reg = <0x10>; + status = "disabled"; + }; + es7243_12: es7243_12@12 { + compatible = "MicArray_1"; + #sound-dai-cells = <0>; + reg = <0x12>; + status = "disabled"; + }; + es7243_13: es7243_13@13 { + compatible = "MicArray_2"; + #sound-dai-cells = <0>; + reg = <0x13>; + status = "disabled"; + }; + is31fl3236a: is31f3236a@0x78 { + compatible = "issi,is31fl3236"; + reg = <0x3c>; + status = "disabled"; + led1_r { + label="LED1_R"; + reg_offset = <24>; + }; + led1_g { + label="LED1_G"; + reg_offset = <23>; + }; + led1_b { + label="LED1_B"; + reg_offset = <22>; + }; + led2_r { + label="LED2_R"; + reg_offset = <21>; + }; + led2_g { + label="LED2_G"; + reg_offset = <20>; + }; + led2_b { + label="LED2_B"; + reg_offset = <19>; + }; + led3_r { + label="LED3_R"; + reg_offset = <18>; + }; + led3_g { + label="LED3_G"; + reg_offset = <17>; + }; + led3_b { + label="LED3_B"; + reg_offset = <16>; + }; + led4_r { + label="LED4_R"; + reg_offset = <15>; + }; + led4_g { + label="LED4_G"; + reg_offset = <14>; + }; + led4_b { + label="LED4_B"; + reg_offset = <13>; + }; + led5_r { + label="LED5_R"; + reg_offset = <36>; + }; + led5_g { + label="LED5_G"; + reg_offset = <35>; + }; + led5_b { + label="LED5_B"; + reg_offset = <34>; + }; + led6_r { + label="LED6_R"; + reg_offset = <33>; + }; + led6_g { + label="LED6_G"; + reg_offset = <32>; + }; + led6_b { + label="LED6_B"; + reg_offset = <31>; + }; + led7_r { + label="LED7_R"; + reg_offset = <30>; + }; + led7_g { + label="LED7_G"; + reg_offset = <29>; + }; + led7_b { + label="LED7_B"; + reg_offset = <28>; + }; + led8_r { + label="LED8_R"; + reg_offset = <27>; + }; + led8_g { + label="LED8_G"; + reg_offset = <26>; + }; + led8_b { + label="LED8_B"; + reg_offset = <25>; + }; + }; +}; + +&audiobus { + aml_tdma: tdma { + compatible = "amlogic, axg-snd-tdma"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <1 0>; + dai-tdm-lane-slot-mask-out = <0 1>; + dai-tdm-clk-sel = <0>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_A + &clkc CLKID_MPLL0>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmout_a &tdmin_a &tdmout_a_data>; + }; + + aml_tdmb: tdmb { + compatible = "amlogic, axg-snd-tdmb"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <1 1 1 1>; + dai-tdm-lane-slot-mask-out = <0 0 0 0>; + dai-tdm-clk-sel = <1>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_B + &clkc CLKID_MPLL1>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + + /*A113D tdmb slave for HDMI*/ + pinctrl-0 = <&tdmb_mclk &tdmin_b_slv &tdmin_b>; + + /*A113D tdmb master for LineIn*/ + /* + * pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; + */ + }; + + aml_tdmc: tdmc { + compatible = "amlogic, axg-snd-tdmc"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 0 0 0>; + dai-tdm-lane-slot-mask-out = <1 1 1 1>; + dai-tdm-clk-sel = <2>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmc_mclk &tdmout_c>; + }; + + aml_spdif: spdif { + compatible = "amlogic, axg-snd-spdif"; + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 + &clkc CLKID_FCLK_DIV4 + &clkaudio CLKID_AUDIO_SPDIFIN + &clkaudio CLKID_AUDIO_SPDIFOUT + &clkaudio CLKID_AUDIO_SPDIFIN_CTRL + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "sysclk", "fixed_clk", "gate_spdifin", + "gate_spdifout", "clk_spdifin", "clk_spdifout"; + interrupts = + ; + + interrupt-names = "irq_spdifin"; + pinctrl-names = "spdif_pins"; + pinctrl-0 = <&spdifout &spdifin>; + + /* + * whether do asrc for pcm. + * if raw data, asrc is disabled automatically + * 0: "Disable", + * 1: "Enable:32K", + * 2: "Enable:44K", + * 3: "Enable:48K", + * 4: "Enable:88K", + * 5: "Enable:96K", + * 6: "Enable:176K", + * 7: "Enable:192K", + */ + auto_asrc = <3>; + status = "okay"; + }; + aml_pdm: pdm { + compatible = "amlogic, axg-snd-pdm"; + #sound-dai-cells = <0>; + clocks = <&clkaudio CLKID_AUDIO_PDM + &clkc CLKID_FCLK_DIV3 + &clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_PDMIN0 + &clkaudio CLKID_AUDIO_PDMIN1>; + clock-names = "gate", + "sysclk_srcpll", + "dclk_srcpll", + "pdm_dclk", + "pdm_sysclk"; + pinctrl-names = "pdm_pins"; + pinctrl-0 = <&pdmin>; + filter_mode = <1>; /* mode 0~4, defalut:1 */ + status = "okay"; + }; + + aml_loopback: loopback { + compatible = "amlogic, snd-loopback"; + + /* + * external loopback clock config + * enable clk while pdm record data + */ + /*clocks = <&clkc CLKID_MPLL1>;*/ + /*clock-names = "datalb_mpll";*/ + + /* + * 0: out rate = in data rate; + * 1: out rate = loopback data rate; + */ + + lb_mode = <0>; + + /* datain src + * 0: tdmin_a; + * 1: tdmin_b; + * 2: tdmin_c; + * 3: spdifin; + * 4: pdmin; + */ + datain_src = <4>; + datain_chnum = <8>; + datain_chmask = <0x7f>; + + /* tdmin_lb src + * 0: tdmoutA + * 1: tdmoutB + * 2: tdmoutC + * 3: PAD_tdminA + * 4: PAD_tdminB + * 5: PAD_tdminC + */ + + /*if tdmin_lb >= 3, use external loopback*/ + datalb_src = <2>; + datalb_chnum = <2>; + /*config which data pin as loopback*/ + /*datalb-lane-mask-in = <0 0 0 1>;*/ + datalb_chmask = <0x1>; + + status = "okay"; + }; + + audioresample: resample { + compatible = "amlogic, axg-resample"; + clocks = <&clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_MCLK_F + &clkaudio CLKID_AUDIO_RESAMPLE_CTRL>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + /*same with toddr_src + * TDMIN_A, + * TDMIN_B, + * TDMIN_C, + * SPDIFIN, + * PDMIN, + * NONE, + * TDMIN_LB, + * LOOPBACK, + */ + resample_module = <3>; + status = "okay"; + }; + aml_pwrdet: pwrdet { + compatible = "amlogic, axg-power-detect"; + + interrupts = ; + interrupt-names = "pwrdet_irq"; + + /* pwrdet source sel + * 7: loopback; + * 6: tdmin_lb; + * 5: reserved; + * 4: pdmin; + * 3: spdifin; + * 2: tdmin_c; + * 1: tdmin_b; + * 0: tdmin_a; + */ + pwrdet_src = <4>; + + hi_th = <0x70000>; + lo_th = <0x16000>; + + status = "disabled"; + }; +}; /* end of audiobus */ + +&pinctrl_periphs { + tdmout_a: tdmout_a { + mux { + groups = "tdma_sclk", + "tdma_fs"; + function = "tdma_out"; + }; + }; + + tdmout_a_data: tdmout_a_data { + mux { + groups = "tdma_dout1_x15"; + function = "tdma_out"; + }; + }; + + tdmin_a: tdmin_a { + mux { + groups = "tdma_din0"; + function = "tdma_in"; + }; + }; + + tdmb_mclk: tdmb_mclk { + mux { + groups = "mclk_b"; + function = "mclk_b"; + }; + }; + + tdmout_b: tdmout_b { + mux { + groups = "tdmb_sclk", + "tdmb_fs"; + function = "tdmb_out"; + }; + }; + + tdmin_b_slv: tdmin_b_slv{ + mux { + groups = "tdmb_slv_sclk", "tdmb_slv_fs"; + function = "tdmb_in"; + }; + }; + + // tdmin and tdmout are the same pins. can't use at same time + tdmin_b:tdmin_b { + mux { + groups = "tdmb_din0", + "tdmb_din1", + "tdmb_din2_a12", + "tdmb_din3_a13"; + function = "tdmb_in"; + }; + }; + + tdmc_mclk: tdmc_mclk { + mux { + groups = "mclk_a"; + function = "mclk_a"; + }; + }; + + tdmout_c:tdmout_c { + mux { + groups = "tdmc_sclk", + "tdmc_fs", + "tdmc_dout0", + "tdmc_dout1", + "tdmc_dout2_a6", + "tdmc_dout3_a7"; + function = "tdmc_out"; + }; + }; + + + tdmin_c:tdmin_c { + mux { + groups = "tdmc_din1"; + function = "tdmc_in"; + }; + }; + + spdifout: spidfout { + mux { + groups = "spdif_out_a20"; + function = "spdif_out"; + }; + }; + + spdifin: spidfin { + mux { + groups = "spdif_in_a19"; + function = "spdif_in"; + }; + }; + + pdmin: pdmin { + mux { + groups = "pdm_dclk_a14", + "pdm_din0", + "pdm_din1", + "pdm_din2", + "pdm_din3"; + function = "pdm"; + }; + }; + + bl_pwm_on_pins: bl_pwm_on_pin { + mux { + groups = "pwm_b_z"; + function = "pwm_b"; + }; + }; + bl_pwm_off_pins:bl_pwm_off_pin { + mux { + pins = "GPIOZ_4"; + function = "gpio_periphs"; + output-high; + }; + }; +}; /* end of pinctrl_periphs */ +/* Audio Related End */ + +&aobus{ + uart_AO: serial@3000 { + compatible = "amlogic, meson-uart"; + reg = <0x0 0x3000 0x0 0x18>; + interrupts = <0 193 1>; + status = "okay"; + clocks = <&xtal>; + clock-names = "clk_uart"; + xtal_tick_en = <1>; + fifosize = < 64 >; + pinctrl-names = "default"; + pinctrl-0 = <&ao_uart_pins>; + support-sysrq = <0>; /* 0 not support , 1 support */ + }; + + uart_AO_B: serial@4000 { + compatible = "amlogic, meson-uart"; + reg = <0x0 0x4000 0x0 0x18>; + interrupts = <0 197 1>; + status = "disable"; + clocks = <&xtal>; + clock-names = "clk_uart"; + fifosize = < 64 >; + pinctrl-names = "default"; + pinctrl-0 = <&ao_b_uart_pins>; + }; +}; + +&audio_data{ + status = "okay"; +}; + +&custom_maps{ + mapnum = <4>; + map0 = <&map_0>; + map1 = <&map_1>; + map2 = <&map_2>; + map3 = <&map_3>; + map_0: map_0{ + mapname = "amlogic-remote-1"; + customcode = <0xfb04>; + release_delay = <80>; + size = <50>; /*keymap size*/ + keymap = ; + }; + map_1: map_1{ + mapname = "amlogic-remote-2"; + customcode = <0xfe01>; + release_delay = <80>; + size = <53>; + keymap = ; + }; + map_2: map_2{ + mapname = "amlogic-remote-3"; + customcode = <0xbd02>; + release_delay = <80>; + size = <17>; + keymap = ; + }; + map_3: map_3{ + mapname = "amlogic-remote-3"; + customcode = <0xa4e8>; /* Reference Remote Control */ + release_delay = <80>; + size = <45>; + keymap = < + REMOTE_KEY(0xc7, 200) /* power */ + REMOTE_KEY(0x93, 201) /* eject-->input source */ + REMOTE_KEY(0xb2, 202) /* usb */ + REMOTE_KEY(0xb8, 203) /* coaxial */ + REMOTE_KEY(0xb7, 204) /* aux */ + REMOTE_KEY(0x8a, 205) /* scan-->hdmi arc */ + REMOTE_KEY(0x96, 206) /* dimmer */ + REMOTE_KEY(0x90, 207) /* hdmi1 */ + REMOTE_KEY(0xa8, 208) /* hdmi2 */ + REMOTE_KEY(0x85, 209) /* mute */ + REMOTE_KEY(0x80, 210) /* vol+ */ + REMOTE_KEY(0x81, 211) /* vol- */ + REMOTE_KEY(0x61, 212) /* DAP */ + REMOTE_KEY(0x62, 213) /* BM */ + REMOTE_KEY(0x63, 214) /* DRC */ + REMOTE_KEY(0x64, 215) /* POST */ + REMOTE_KEY(0x65, 216) /* UPMIX */ + REMOTE_KEY(0x66, 217) /* VIRT */ + REMOTE_KEY(0x67, 218) /* LEGACY */ + REMOTE_KEY(0x68, 219) /* HFILT */ + REMOTE_KEY(0x69, 220) /* Loundness */ + REMOTE_KEY(0x60, 221) /* Audio_info */ + REMOTE_KEY(0xb1, 222) /* CD */ + REMOTE_KEY(0xb4, 223) /* CD */ + REMOTE_KEY(0xb9, 224) /* CD */ + REMOTE_KEY(0xab, 225) /* CD */ + REMOTE_KEY(0x91, 226) /* CD */ + REMOTE_KEY(0x92, 227) /* CD */ + REMOTE_KEY(0x89, 228) /* CD */ + REMOTE_KEY(0x88, 229) /* CD */ + REMOTE_KEY(0xa5, 230) /* CD */ + REMOTE_KEY(0x84, 231) /* CD */ + REMOTE_KEY(0x72, 232) /* CD */ + REMOTE_KEY(0x73, 233) /* CD */ + REMOTE_KEY(0x9a, 234) /* CD */ + REMOTE_KEY(0x9b, 235) /* CD */ + REMOTE_KEY(0xa0, 236) /* CD */ + REMOTE_KEY(0x71, 237) /* CD */ + REMOTE_KEY(0x74, 238) /* CD */ + REMOTE_KEY(0x75, 239) /* CD */ + REMOTE_KEY(0x7e, 240) /* CD */ + REMOTE_KEY(0x7f, 241) /* CD */ + REMOTE_KEY(0x7a, 242) /* CD */ + REMOTE_KEY(0xa7, 243) /* CD */ + REMOTE_KEY(0xa9, 244) /* CD */ + >; + }; + }; diff --git a/arch/arm64/boot/dts/amlogic/axg_s400emmc_512m.dts b/arch/arm64/boot/dts/amlogic/axg_s400emmc_512m.dts index 6b30d540f730..445b84940a96 100644 --- a/arch/arm64/boot/dts/amlogic/axg_s400emmc_512m.dts +++ b/arch/arm64/boot/dts/amlogic/axg_s400emmc_512m.dts @@ -53,8 +53,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm/boot/dts/amlogic/axg_s400emmc_512m.dts b/arch/arm64/boot/dts/amlogic/axg_s410.dts similarity index 77% rename from arch/arm/boot/dts/amlogic/axg_s400emmc_512m.dts rename to arch/arm64/boot/dts/amlogic/axg_s410.dts index da16137a1c10..a1ba6c854777 100644 --- a/arch/arm/boot/dts/amlogic/axg_s400emmc_512m.dts +++ b/arch/arm64/boot/dts/amlogic/axg_s410.dts @@ -1,5 +1,5 @@ /* - * arch/arm/boot/dts/amlogic/axg_s400emmc.dts + * arch/arm64/boot/dts/amlogic/axg_s410.dts * * Copyright (C) 2017 Amlogic, Inc. All rights reserved. * @@ -18,81 +18,61 @@ /dts-v1/; #include "mesonaxg.dtsi" -#include "mesonaxg_s400-panel.dtsi" -#include "partition_mbox_normal.dtsi" +//#include "mesonaxg_s400-panel.dtsi" / { model = "Amlogic"; - amlogic-dt-id = "axg_s400emmc_512m"; + amlogic-dt-id = "axg_s410_1g"; compatible = "amlogic, axg"; interrupt-parent = <&gic>; - #address-cells = <1>; - #size-cells = <1>; + #address-cells = <2>; + #size-cells = <2>; aliases { serial0 = &uart_AO; serial1 = &uart_A; - }; - - ion_dev { - compatible = "amlogic, ion_dev"; - memory-region = <&ion_reserved>; + serial2 = &uart_B; }; memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x000000 0x20000000>; + linux,usable-memory = <0x0 0x000000 0x0 0x8000000>; }; reserved-memory { - #address-cells = <1>; - #size-cells = <1>; + #address-cells = <2>; + #size-cells = <2>; ranges; /* global autoconfigured region for contiguous allocations */ - ramoops@0x07400000 { - compatible = "ramoops"; - reg = <0x07400000 0x00100000>; - record-size = <0x8000>; - console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; - }; secmon_reserved:linux,secmon { compatible = "shared-dma-pool"; reusable; - size = <0x400000>; - alignment = <0x400000>; - alloc-ranges = <0x05000000 0x400000>; + size = <0x0 0x400000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x05000000 0x0 0x400000>; }; secos_reserved:linux,secos { status = "disable"; compatible = "amlogic, aml_secos_memory"; - reg = <0x05300000 0x2000000>; + reg = <0x0 0x05300000 0x0 0x2000000>; no-map; }; fb_reserved:linux,meson-fb { //compatible = "amlogic, fb-memory"; - //reg = <0x3e000000 0x1f00000>; + //reg = <0x0 0x3e000000 0x0 0x1f00000>; compatible = "shared-dma-pool"; reusable; - size = <0x2000000>; - alignment = <0x400000>; - alloc-ranges = <0x3e000000 0x2000000>; - }; - - ion_reserved:linux,ion-dev { - compatible = "shared-dma-pool"; - reusable; - size = <0x2000000>; - alignment = <0x400000>; + size = <0x0 0x2000000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x3e000000 0x0 0x2000000>; }; }; mtd_nand { compatible = "amlogic, aml_mtd_nand"; dev_name = "mtdnand"; - status = "disable"; - reg = <0xFFE07800 0x200>; + status = "okay"; + reg = <0x0 0xFFE07800 0x0 0x200>; interrupts = < 0 34 1 >; pinctrl-names = "nand_rb_mod","nand_norb_mod", "nand_cs_only"; pinctrl-0 = <&all_nand_pins>; @@ -153,7 +133,7 @@ offset=<0x0 0x0>; size=<0x0 0x0>; }; - logo{ + misc{ offset=<0x0 0x0>; size=<0x0 0x200000>; }; @@ -167,7 +147,7 @@ }; system{ offset=<0x0 0x0>; - size=<0x0 0x11800000>; + size=<0x0 0x3C00000>; }; data{ offset=<0xffffffff 0xffffffff>; @@ -179,8 +159,8 @@ ethmac: ethernet@0xff3f0000 { compatible = "amlogic, gxbb-eth-dwmac"; - reg = <0xff3f0000 0x10000 - 0xff634540 0x8>; + reg = <0x0 0xff3f0000 0x0 0x10000 + 0x0 0xff634540 0x0 0x8>; interrupts = <0 8 1>; pinctrl-names = "external_eth_pins"; pinctrl-0 = <&external_eth_pins>; @@ -268,7 +248,7 @@ dwc3: dwc3@ff500000 { compatible = "synopsys, dwc3"; status = "okay"; - reg = <0xff500000 0x100000>; + reg = <0x0 0xff500000 0x0 0x100000>; interrupts = <0 30 4>; usb-phy = <&usb2_phy>, <&usb3_phy>; cpu-type = "gxl"; @@ -281,15 +261,15 @@ compatible = "amlogic, amlogic-new-usb2"; status = "okay"; portnum = <4>; - reg = <0xffe09000 0x80 - 0xffd01008 0x4>; + reg = <0x0 0xffe09000 0x0 0x80 + 0x0 0xffd01008 0x0 0x4>; }; usb3_phy: usb3phy@ffe09080 { compatible = "amlogic, amlogic-new-usb3"; status = "okay"; portnum = <0>; - reg = <0xffe09080 0x20>; + reg = <0x0 0xffe09080 0x0 0x20>; interrupts = <0 16 4>; otg = <1>; gpio-vbus-power = "GPIOAO_5"; @@ -299,13 +279,13 @@ dwc2_a { compatible = "amlogic, dwc2"; device_name = "dwc2_a"; - reg = <0xff400000 0x40000>; + reg = <0x0 0xff400000 0x0 0x40000>; status = "okay"; interrupts = <0 31 4>; pl-periph-id = <0>; /** lm name */ clock-src = "usb0"; /** clock src */ - port-id = <0>; /** ref to mach/usb.h */ - port-type = <2>; /** 0: otg, 1: host, 2: slave */ + port-id = <0>; /** ref to mach/usb.h */ + port-type = <2>; /** 0: otg, 1: host, 2: slave */ port-speed = <0>; /** 0: default, high, 1: full */ port-config = <0>; /** 0: default */ /*0:default,1:single,2:incr,3:incr4,4:incr8,5:incr16,6:disable*/ @@ -327,22 +307,22 @@ pcie_A: pcieA@f9800000 { compatible = "amlogic, amlogic-pcie", "snps,dw-pcie"; - reg = <0xf9800000 0x400000 - 0xff646000 0x2000 - 0xf9f00000 0x100000 - PCIE_PHY_REG PCIE_PHY_SIZE - PCIE_RESET_REG PCIE_RESET_SIZE>; + reg = <0x0 0xf9800000 0x0 0x400000 + 0x0 0xff646000 0x0 0x2000 + 0x0 0xf9f00000 0x0 0x100000 + 0x0 PCIE_PHY_REG 0x0 PCIE_PHY_SIZE + 0x0 PCIE_RESET_REG 0x0 PCIE_RESET_SIZE>; reg-names = "elbi", "cfg", "config", "phy", "reset"; reset-gpio = <&gpio GPIOX_19 GPIO_ACTIVE_HIGH>; interrupts = <0 177 0>; #interrupt-cells = <1>; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &gic GIC_SPI 179 IRQ_TYPE_EDGE_RISING>; bus-range = <0x0 0xff>; #address-cells = <3>; #size-cells = <2>; - interrupt-map-mask = <0 0 0 0>; - interrupt-map = <0 0 0 0 &gic GIC_SPI 179 IRQ_TYPE_EDGE_RISING>; device_type = "pci"; - ranges = <0x82000000 0 0 0xf9c00000 0 0x00300000>; + ranges = <0x82000000 0 0 0x0 0xf9c00000 0 0x00300000>; /* non-prefetchable memory */ num-lanes = <1>; pcie-num = <1>; @@ -361,16 +341,16 @@ "port"; /*reset-gpio-type 0:Shared pad(no reset)1:OD pad2:Normal pad*/ gpio-type = <2>; - status = "okay"; + status = "disable"; }; pcie_B: pcieB@fa000000 { compatible = "amlogic, amlogic-pcie", "snps,dw-pcie"; - reg = <0xfa000000 0x400000 - 0xff648000 0x2000 - 0xfa400000 0x100000 - PCIE_PHY_REG PCIE_PHY_SIZE - PCIE_RESET_REG PCIE_RESET_SIZE>; + reg = <0x0 0xfa000000 0x0 0x400000 + 0x0 0xff648000 0x0 0x2000 + 0x0 0xfa400000 0x0 0x100000 + 0x0 PCIE_PHY_REG 0x0 PCIE_PHY_SIZE + 0x0 PCIE_RESET_REG 0x0 PCIE_RESET_SIZE>; reg-names = "elbi", "cfg", "config", "phy", "reset"; reset-gpio = <&gpio GPIOZ_10 GPIO_ACTIVE_HIGH>; interrupts = <0 167 0>; @@ -381,9 +361,9 @@ interrupt-map-mask = <0 0 0 0>; interrupt-map = <0 0 0 0 &gic GIC_SPI 169 IRQ_TYPE_EDGE_RISING>; device_type = "pci"; - ranges = <0x81000000 0 0 0xfa500000 0x0 0x10000 + ranges = <0x81000000 0 0 0 0xfa500000 0x0 0x10000 /* downstream I/O */ - 0x82000000 0 0xfa510000 0xfa510000 0 0x002f0000>; + 0x82000000 0 0xfa510000 0x0 0xfa510000 0 0x002f0000>; /* non-prefetchable memory */ num-lanes = <1>; pcie-num = <2>; @@ -402,13 +382,13 @@ "port"; /*reset-gpio-type 0:Shared pad(no reset)1:OD pad2:Normal pad*/ gpio-type = <1>; - status = "okay"; + status = "disable"; }; uart_A: serial@ffd24000 { compatible = "amlogic, meson-uart"; - reg = <0xffd24000 0x18>; + reg = <0x0 0xffd24000 0x0 0x18>; interrupts = <0 26 1>; status = "okay"; clocks = <&xtal @@ -422,9 +402,9 @@ uart_B: serial@ffd23000 { compatible = "amlogic, meson-uart"; - reg = <0xffd23000 0x18>; + reg = <0x0 0xffd23000 0x0 0x18>; interrupts = <0 75 1>; - status = "disable"; + status = "okay"; clocks = <&xtal &clkc CLKID_UART1>; clock-names = "clk_uart", @@ -449,27 +429,31 @@ "vpu_clk1", "vpu_clk"; clk_level = <3>; - /* 0: 100.0M 1: 166.7M 2: 200.0M 3: 250.0M */ + /* 0: 100.0M 1: 166.7M 2: 200.0M 3: 250.0M */ }; vout { compatible = "amlogic, vout"; dev_name = "vout"; - status = "okay"; + status = "disable"; }; + /* Audio Related start */ /* Sound iomap */ aml_snd_iomap { compatible = "amlogic, snd-iomap"; status = "okay"; - #address-cells=<1>; - #size-cells=<1>; + #address-cells=<2>; + #size-cells=<2>; ranges; pdm_bus { - reg = <0xFF632000 0x2000>; + reg = <0x0 0xFF632000 0x0 0x2000>; }; audiobus_base { - reg = <0xFF642000 0x2000>; + reg = <0x0 0xFF642000 0x0 0x2000>; + }; + audiolocker_base { + reg = <0x0 0xFF64A000 0x0 0x2000>; }; }; pdm_codec:dummy{ @@ -490,28 +474,23 @@ aml-audio-card,loopback = <&aml_loopback>; aml-audio-card,dai-link@0 { - format = "dsp_a"; - mclk-fs = <512>; + format = "i2s"; + mclk-fs = <256>; //continuous-clock; //bitclock-inversion; //frame-inversion; - //bitclock-master = <&tdmacodec>; - //frame-master = <&tdmacodec>; - /* suffix-name, sync with android audio hal - * what's the dai link used for - */ + bitclock-master = <&aml_tdma>; + frame-master = <&aml_tdma>; suffix-name = "alsaPORT-pcm"; - tdmacpu: cpu { + cpu{ sound-dai = <&aml_tdma>; - dai-tdm-slot-tx-mask = - <1 1 1 1 1 1 1 1>; - dai-tdm-slot-rx-mask = - <1 1 1 1 1 1 1 1>; - dai-tdm-slot-num = <8>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; dai-tdm-slot-width = <32>; - system-clock-frequency = <24576000>; + system-clock-frequency = <12288000>; }; - tdmacodec: codec { + codec { sound-dai = <&dummy_codec &dummy_codec>; }; }; @@ -522,14 +501,9 @@ //continuous-clock; //bitclock-inversion; //frame-inversion; - bitclock-master = <&aml_tdmb>; - frame-master = <&aml_tdmb>; - //bitclock-master = <&tdmbcodec>; - //frame-master = <&tdmbcodec>; - /* suffix-name, sync with android audio hal - * what's the dai link used for - */ - //suffix-name = "alsaPORT-i2s"; + bitclock-master = <&tdmbcodec>; + frame-master = <&tdmbcodec>; + suffix-name = "alsaPORT-i2sCapture"; cpu { sound-dai = <&aml_tdmb>; dai-tdm-slot-tx-mask = <1 1>; @@ -538,7 +512,7 @@ dai-tdm-slot-width = <32>; system-clock-frequency = <12288000>; }; - codec { + tdmbcodec:codec { /* * prefix-names = "3101_A", "3101_B", * "3101_C", "3101_D"; @@ -547,22 +521,19 @@ * &tlv320adc3101_34 * &tlv320adc3101_36>; */ - sound-dai = <&tlv320adc3101_32 &dummy_codec>; + sound-dai = <&dummy_codec>; }; }; aml-audio-card,dai-link@2 { format = "i2s"; mclk-fs = <256>; - continuous-clock; + //continuous-clock; //bitclock-inversion; //frame-inversion; //bitclock-master = <&aml_tdmc>; //frame-master = <&aml_tdmc>; - /* suffix-name, sync with android audio hal - * what's the dai link used for - */ - suffix-name = "alsaPORT-i2s"; + suffix-name = "alsaPORT-i2sPlayback"; cpu { sound-dai = <&aml_tdmc>; dai-tdm-slot-tx-mask = <1 1>; @@ -579,18 +550,14 @@ }; aml-audio-card,dai-link@3 { - mclk-fs = <64>; - /* suffix-name, sync with android audio hal - * what's the dai link used for - */ - suffix-name = "alsaPORT-pdm"; + mclk-fs = <256>; cpu { sound-dai = <&aml_pdm>; }; codec { /* - *enable external loopback - *and tlv320adc3101 as loopback + * enable external loopback + * and tlv320adc3101 as loopback */ /*sound-dai = <&pdm_codec &tlv320adc3101_32>;*/ /* @@ -603,9 +570,6 @@ aml-audio-card,dai-link@4 { mclk-fs = <128>; - /* suffix-name, sync with android audio hal - * what's the dai link used for - */ suffix-name = "alsaPORT-spdif"; cpu { sound-dai = <&aml_spdif>; @@ -616,22 +580,40 @@ }; }; }; + audiolocker: locker { + compatible = "amlogic, audiolocker"; + clocks = <&clkaudio CLKID_AUDIO_LOCKER_OUT + &clkaudio CLKID_AUDIO_LOCKER_IN + &clkaudio CLKID_AUDIO_MCLK_D + &clkaudio CLKID_AUDIO_MCLK_E + &clkc CLKID_MPLL1 + &clkc CLKID_MPLL2>; + clock-names = "lock_out", "lock_in", "out_src", + "in_src", "out_calc", "in_ref"; + interrupts = ; + interrupt-names = "irq"; + frequency = <49000000>; /* pll */ + dividor = <49>; /* locker's parent */ + status = "okay"; + }; + /* Audio Related end */ bt-dev{ compatible = "amlogic, bt-dev"; dev_name = "bt-dev"; - status = "okay"; - gpio_reset = <&gpio GPIOX_21 GPIO_ACTIVE_HIGH>; + status = "disable"; + gpio_reset = <&gpio GPIOX_21 GPIO_ACTIVE_HIGH>; }; wifi{ compatible = "amlogic, aml_wifi"; dev_name = "aml_wifi"; - status = "okay"; - interrupt_pin = <&gpio GPIOX_6 GPIO_ACTIVE_HIGH>; + status = "disable"; + interrupt_pin = <&gpio GPIOX_6 GPIO_ACTIVE_HIGH>; + interrupts = < 0 67 4>; irq_trigger_type = "GPIO_IRQ_LOW"; - power_on_pin2 = <&gpio GPIOX_16 GPIO_ACTIVE_HIGH>; - power_on_pin = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; + power_on_pin2 = <&gpio GPIOX_16 GPIO_ACTIVE_HIGH>; + power_on_pin = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; dhd_static_buf; //if use bcm wifi, config dhd_static_buf pinctrl-names = "default"; pinctrl-0 = <&wifi_32k_pins>; @@ -640,30 +622,30 @@ wifi_pwm_conf:wifi_pwm_conf{ pwm_channel1_conf { - pwms = <&pwm_ab MESON_PWM_0 30541 0>; - duty-cycle = <15270>; + pwms = <&pwm_ab MESON_PWM_0 30040 0>; + duty-cycle = <15020>; times = <10>; }; pwm_channel2_conf { - pwms = <&pwm_ab MESON_PWM_2 30500 0>; - duty-cycle = <15250>; + pwms = <&pwm_ab MESON_PWM_2 30030 0>; + duty-cycle = <15015>; times = <12>; }; }; sd_emmc_c: emmc@ffe07000 { - status = "okay"; + status = "disabled"; compatible = "amlogic, meson-mmc-axg"; - reg = <0xffe07000 0x2000>; + reg = <0x0 0xffe07000 0x0 0x2000>; interrupts = <0 218 1>; pinctrl-names = "emmc_clk_cmd_pins", "emmc_all_pins"; pinctrl-0 = <&emmc_clk_cmd_pins>; pinctrl-1 = <&emmc_conf_pull_up &emmc_conf_pull_done>; clocks = <&clkc CLKID_SD_EMMC_C>, - <&clkc CLKID_SD_EMMC_C_P0_COMP>, - <&clkc CLKID_FCLK_DIV2>, - <&clkc CLKID_FCLK_DIV5>, - <&xtal>; + <&clkc CLKID_SD_EMMC_C_P0_COMP>, + <&clkc CLKID_FCLK_DIV2>, + <&clkc CLKID_FCLK_DIV5>, + <&xtal>; clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; bus-width = <8>; @@ -686,8 +668,9 @@ "MMC_CAP_HW_RESET", "MMC_CAP_ERASE", "MMC_CAP_CMD23"; + caps2 = "MMC_CAP2_HS200", "MMC_CAP2_HS400"; f_min = <400000>; - f_max = <100000000>; + f_max = <200000000>; max_req_size = <0x20000>; /**128KB*/ gpio_dat3 = <&gpio BOOT_3 GPIO_ACTIVE_HIGH>; tx_delay = <8>; @@ -702,16 +685,16 @@ sd_emmc_b:sdio@ffe05000 { status = "okay"; compatible = "amlogic, meson-mmc-axg"; - reg = <0xffe05000 0x2000>; + reg = <0x0 0xffe05000 0x0 0x2000>; interrupts = <0 217 4>; pinctrl-names = "sdio_clk_cmd_pins", "sdio_all_pins"; pinctrl-0 = <&sdio_clk_cmd_pins>; pinctrl-1 = <&sdio_all_pins>; clocks = <&clkc CLKID_SD_EMMC_B>, - <&clkc CLKID_SD_EMMC_B_P0_COMP>, - <&clkc CLKID_FCLK_DIV2>, - <&clkc CLKID_FCLK_DIV5>, - <&xtal>; + <&clkc CLKID_SD_EMMC_B_P0_COMP>, + <&clkc CLKID_FCLK_DIV2>, + <&clkc CLKID_FCLK_DIV5>, + <&xtal>; clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; bus-width = <4>; @@ -744,7 +727,7 @@ }; partitions: partitions{ - parts = <14>; + parts = <11>; part-0 = <&logo>; part-1 = <&recovery>; part-2 = <&rsv>; @@ -753,12 +736,9 @@ part-5 = <&misc>; part-6 = <&instaboot>; part-7 = <&boot>; - part-8 = <&vendor>; - part-9 = <&odm>; - part-10 = <&system>; - part-11 = <&cache>; - part-12 = <&udisk>; - part-13 = <&data>; + part-8 = <&system>; + part-9 = <&cache>; + part-10 = <&data>; logo:logo{ pname = "logo"; @@ -801,22 +781,10 @@ size = <0x0 0x2000000>; mask = <1>; }; - vendor:vendor - { - pname = "vendor"; - size = <0x0 0x10000000>; - mask = <1>; - }; - odm:odm - { - pname = "odm"; - size = <0x0 0x10000000>; - mask = <1>; - }; system:system { pname = "system"; - size = <0x0 0x82000000>; + size = <0x0 0x80000000>; mask = <1>; }; cache:cache @@ -825,12 +793,6 @@ size = <0x0 0x20000000>; mask = <2>; }; - udisk:udisk - { - pname = "udisk"; - size = <0x0 0x20000000>; - mask = <2>; - }; data:data { pname = "data"; @@ -840,42 +802,43 @@ }; meson-fb { - compatible = "amlogic, meson-axg"; + compatible = "amlogic, meson-fb"; memory-region = <&fb_reserved>; dev_name = "meson-fb"; - status = "okay"; + status = "disable"; interrupts = <0 3 1 0 89 1>; interrupt-names = "viu-vsync", "rdma"; mem_size = <0x00300000 0x1800000 0x00000000>; - /* uboot logo,fb0/fb1 memory size,if afbcd fb0=0x0b51000*/ - display_mode_default = "720p60hz"; + /* uboot logo,fb0/fb1 memory size */ + display_mode_default = "1080p60hz"; scale_mode = <0>; - /*1280*720*4*2 = 0xA8C000*/ - display_size_default = <1280 720 1280 1440 32>; + /** 0:VPU free scale 1:OSD free scale 2:OSD super scale */ + display_size_default = <768 1024 768 2048 32>; /*768*1024*4*2 = 0x600000*/ + mem_alloc = <1>; logo_addr = "0x3e000000"; pxp_mode = <0>; /** 0:normal mode 1:pxp mode */ }; ge2d { - compatible = "amlogic, ge2d-axg"; + compatible = "amlogic, ge2d"; dev_name = "ge2d"; - status = "okay"; + status = "disable"; interrupts = <0 150 1>; interrupt-names = "ge2d"; clocks = <&clkc CLKID_VAPB_MUX>, - <&clkc CLKID_G2D>, - <&clkc CLKID_GE2D_GATE>; + <&clkc CLKID_GE2D_GATE>, + <&clkc CLKID_G2D>; clock-names = "clk_vapb_0", "clk_ge2d", "clk_ge2d_gate"; - reg = <0xff940000 0x10000>; + reg = <0x0 0xff940000 0x0 0x10000>; }; adc_keypad { compatible = "amlogic, adc_keypad"; - status = "okay"; + status = "disable"; key_name = "power", "vol-", "vol+", "wifi", "<<", ">>"; key_num = <6>; io-channels = <&saradc SARADC_CH0>; @@ -889,7 +852,7 @@ unifykey{ compatible = "amlogic, unifykey"; - status = "ok"; + status = "disable"; unifykey-num = <6>; unifykey-index-0 = <&keysn_0>; @@ -918,7 +881,7 @@ key-name = "mac_bt"; key-device = "normal"; key-permit = "read","write","del"; - key-type = "mac"; + key-type = "mac"; }; keysn_4:key_4{ key-name = "mac_wifi"; @@ -939,8 +902,9 @@ }; &pwm_ab { - status = "okay"; + status = "disable"; }; + /* Audio Related start */ /* for spk board */ &i2c1 { @@ -978,11 +942,18 @@ pinctrl-names="default"; pinctrl-0=<&ao_i2c_master_pin2>; - pca9557: pca9557@0x1f { - compatible = "nxp,pca9557"; - reg = <0x1f>; - status = "okay"; + aml_pca9557: aml_pca9557@0x1f { + compatible = "aml, ledring"; + reg = <0x1f>; + mode = <0>; /*0: 6-led 1: 4key+2led */ + key_num = <4>; + led_dev_name = "aml_ledring"; + key_dev_name = "aml_pca_key"; + key_name = "mute", "pause", "vol+", "vol-"; + key_value = <200 201 202 203>; + status = "okay"; }; + tlv320adc3101_30: tlv320adc3101_30@30 { compatible = "ti,tlv320adc3101"; #sound-dai-cells = <0>; @@ -1001,46 +972,165 @@ reg = <0x1b>; status = "disable"; }; + es7243_10: es7243_10@10 { + compatible = "MicArray_0"; + #sound-dai-cells = <0>; + reg = <0x10>; + status = "disable"; + }; + es7243_12: es7243_12@12 { + compatible = "MicArray_1"; + #sound-dai-cells = <0>; + reg = <0x12>; + status = "disable"; + }; + es7243_13: es7243_13@13 { + compatible = "MicArray_2"; + #sound-dai-cells = <0>; + reg = <0x13>; + status = "disable"; + }; + is31fl3236a: is31f3236a@0x78 { + compatible = "issi,is31fl3236"; + reg = <0x3c>; + status = "disable"; + led1_r { + label="LED1_R"; + reg_offset = <24>; + }; + led1_g { + label="LED1_G"; + reg_offset = <23>; + }; + led1_b { + label="LED1_B"; + reg_offset = <22>; + }; + led2_r { + label="LED2_R"; + reg_offset = <21>; + }; + led2_g { + label="LED2_G"; + reg_offset = <20>; + }; + led2_b { + label="LED2_B"; + reg_offset = <19>; + }; + led3_r { + label="LED3_R"; + reg_offset = <18>; + }; + led3_g { + label="LED3_G"; + reg_offset = <17>; + }; + led3_b { + label="LED3_B"; + reg_offset = <16>; + }; + led4_r { + label="LED4_R"; + reg_offset = <15>; + }; + led4_g { + label="LED4_G"; + reg_offset = <14>; + }; + led4_b { + label="LED4_B"; + reg_offset = <13>; + }; + led5_r { + label="LED5_R"; + reg_offset = <36>; + }; + led5_g { + label="LED5_G"; + reg_offset = <35>; + }; + led5_b { + label="LED5_B"; + reg_offset = <34>; + }; + led6_r { + label="LED6_R"; + reg_offset = <33>; + }; + led6_g { + label="LED6_G"; + reg_offset = <32>; + }; + led6_b { + label="LED6_B"; + reg_offset = <31>; + }; + led7_r { + label="LED7_R"; + reg_offset = <30>; + }; + led7_g { + label="LED7_G"; + reg_offset = <29>; + }; + led7_b { + label="LED7_B"; + reg_offset = <28>; + }; + led8_r { + label="LED8_R"; + reg_offset = <27>; + }; + led8_g { + label="LED8_G"; + reg_offset = <26>; + }; + led8_b { + label="LED8_B"; + reg_offset = <25>; + }; + }; }; &audiobus { aml_tdma: tdma { compatible = "amlogic, axg-snd-tdma"; #sound-dai-cells = <0>; - dai-tdm-lane-slot-mask-in = <1 0>; - dai-tdm-lane-slot-mask-out = <0 1>; + dai-tdm-lane-slot-mask-in = <1 1>; + dai-tdm-lane-slot-mask-out = <0 0>; dai-tdm-clk-sel = <0>; clocks = <&clkaudio CLKID_AUDIO_MCLK_A &clkc CLKID_MPLL0>; clock-names = "mclk", "clk_srcpll"; pinctrl-names = "tdm_pins"; - pinctrl-0 = <&tdmout_a &tdmin_a &tdmout_a_data>; + pinctrl-0 = <&tdmout_a &tdmin_a>; }; aml_tdmb: tdmb { compatible = "amlogic, axg-snd-tdmb"; #sound-dai-cells = <0>; - /*dai-tdm-lane-slot-mask-in = <1 1 1 1>;*/ - dai-tdm-lane-slot-mask-in = <0 0 0 1>; + dai-tdm-lane-slot-mask-in = <1 1 1 1>; + dai-tdm-lane-slot-mask-out = <0 0 0 0>; dai-tdm-clk-sel = <1>; clocks = <&clkaudio CLKID_AUDIO_MCLK_B &clkc CLKID_MPLL1>; clock-names = "mclk", "clk_srcpll"; pinctrl-names = "tdm_pins"; - pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; + pinctrl-0 = <&tdmin_b>; }; aml_tdmc: tdmc { compatible = "amlogic, axg-snd-tdmc"; #sound-dai-cells = <0>; - dai-tdm-lane-slot-mask-in = <0 1 0 0>; - dai-tdm-lane-slot-mask-out = <0 0 1 1>; + dai-tdm-lane-slot-mask-in = <0 0 0 0>; + dai-tdm-lane-slot-mask-out = <1 1 1 1>; dai-tdm-clk-sel = <2>; clocks = <&clkaudio CLKID_AUDIO_MCLK_C &clkc CLKID_MPLL2>; clock-names = "mclk", "clk_srcpll"; pinctrl-names = "tdm_pins"; - pinctrl-0 = <&tdmc_mclk &tdmout_c &tdmin_c>; + pinctrl-0 = <&tdmc_mclk &tdmout_c>; }; aml_spdif: spdif { @@ -1073,7 +1163,7 @@ * 6: "Enable:176K", * 7: "Enable:192K", */ - auto_asrc = <0>; + auto_asrc = <3>; status = "okay"; }; aml_pdm: pdm { @@ -1097,6 +1187,7 @@ aml_loopback: loopback { compatible = "amlogic, snd-loopback"; + /* * external loopback clock config * enable clk while pdm record data @@ -1129,6 +1220,7 @@ * 4: PAD_tdminB * 5: PAD_tdminC */ + /*if tdmin_lb >= 3, use external loopback*/ datalb_src = <2>; datalb_chnum = <2>; @@ -1136,6 +1228,7 @@ /*datalb-lane-mask-in = <0 0 0 1>;*/ datalb_chmask = <0x1>; + status = "okay"; }; @@ -1223,7 +1316,10 @@ // tdmin and tdmout are the same pins. can't use at same time tdmin_b:tdmin_b { mux { - groups = "tdmb_din0", + groups = + "tdmb_slv_sclk", + "tdmb_slv_fs", + "tdmb_din0", "tdmb_din1", "tdmb_din2_a12", "tdmb_din3_a13"; @@ -1243,6 +1339,7 @@ groups = "tdmc_sclk", "tdmc_fs", "tdmc_dout0", + "tdmc_dout1", "tdmc_dout2_a6", "tdmc_dout3_a7"; function = "tdmc_out"; @@ -1288,20 +1385,13 @@ function = "pwm_b"; }; }; - bl_pwm_off_pins:bl_pwm_off_pin { - mux { - pins = "GPIOZ_4"; - function = "gpio_periphs"; - output-high; - }; - }; }; /* end of pinctrl_periphs */ /* Audio Related End */ &aobus{ uart_AO: serial@3000 { compatible = "amlogic, meson-uart"; - reg = <0x3000 0x18>; + reg = <0x0 0x3000 0x0 0x18>; interrupts = <0 193 1>; status = "okay"; clocks = <&xtal>; @@ -1315,7 +1405,7 @@ uart_AO_B: serial@4000 { compatible = "amlogic, meson-uart"; - reg = <0x4000 0x18>; + reg = <0x0 0x4000 0x0 0x18>; interrupts = <0 197 1>; status = "disable"; clocks = <&xtal>; diff --git a/arch/arm64/boot/dts/amlogic/axg_s420.dts b/arch/arm64/boot/dts/amlogic/axg_s420.dts index ddc988d71ee9..6f1c708d9ea4 100644 --- a/arch/arm64/boot/dts/amlogic/axg_s420.dts +++ b/arch/arm64/boot/dts/amlogic/axg_s420.dts @@ -47,8 +47,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm64/boot/dts/amlogic/axg_s420_v03.dts b/arch/arm64/boot/dts/amlogic/axg_s420_v03.dts index b2ce78745814..6033259c5f37 100644 --- a/arch/arm64/boot/dts/amlogic/axg_s420_v03.dts +++ b/arch/arm64/boot/dts/amlogic/axg_s420_v03.dts @@ -47,8 +47,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm64/boot/dts/amlogic/axg_s420_v03gva.dts b/arch/arm64/boot/dts/amlogic/axg_s420_v03gva.dts index 1b2300f0f4ef..b01bb73f12be 100644 --- a/arch/arm64/boot/dts/amlogic/axg_s420_v03gva.dts +++ b/arch/arm64/boot/dts/amlogic/axg_s420_v03gva.dts @@ -47,8 +47,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { @@ -316,14 +315,6 @@ pinctrl-0 = <&b_uart_pins>; }; - meson-irblaster { - compatible = "amlogic, am_irblaster"; - dev_name = "meson-irblaster"; - status = "disable"; - pinctrl-names = "default"; - pinctrl-0 = <&irblaster_pins>; - }; - /* Sound iomap */ aml_snd_iomap { compatible = "amlogic, snd-iomap"; @@ -441,16 +432,16 @@ }; }; - /*aml-audio-card,dai-link@4 { - * mclk-fs = <128>; - * cpu { - * sound-dai = <&aml_spdif>; - * }; - * codec { - * sound-dai = <&dummy_codec>; - * }; - *}; - */ + aml-audio-card,dai-link@4 { + mclk-fs = <128>; + cpu { + sound-dai = <&aml_spdif>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + }; bt-dev{ diff --git a/arch/arm64/boot/dts/amlogic/firmware_avb_ab.dtsi b/arch/arm64/boot/dts/amlogic/firmware_avb_ab.dtsi index 0ec3f8cf1c82..299febcbb32a 100644 --- a/arch/arm64/boot/dts/amlogic/firmware_avb_ab.dtsi +++ b/arch/arm64/boot/dts/amlogic/firmware_avb_ab.dtsi @@ -39,7 +39,7 @@ firmware { dev = "/dev/block/product"; type = "ext4"; mnt_flags = "ro,barrier=1,inode_readahead_blks=8"; - fsmgr_flags = "wait,slotselect"; + fsmgr_flags = "wait,slotselect,avb"; }; odm { compatible = "android,odm"; diff --git a/arch/arm64/boot/dts/amlogic/g12a_pxp.dts b/arch/arm64/boot/dts/amlogic/g12a_pxp.dts index dc0e5ac104f4..7613b14ac751 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_pxp.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_pxp.dts @@ -37,7 +37,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x0 0x100000 0x0 0x3ff00000>; + linux,usable-memory = <0x0 0x0 0x0 0x40000000>; }; reserved-memory { diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905d2_skt.dts b/arch/arm64/boot/dts/amlogic/g12a_s905d2_skt.dts index 5700547f0188..76eb019352c5 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905d2_skt.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905d2_skt.dts @@ -23,6 +23,7 @@ / { model = "Amlogic"; + amlogic-dt-id = "g12a_skt_2g"; compatible = "amlogic, g12a"; interrupt-parent = <&gic>; #address-cells = <2>; @@ -45,7 +46,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x0 0x100000 0x0 0x7ff00000>; + linux,usable-memory = <0x0 0x0 0x0 0x80000000>; }; reserved-memory { @@ -58,8 +59,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { @@ -226,6 +226,14 @@ }; }; + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + codec_mm { compatible = "amlogic, codec, mm"; memory-region = <&codec_mm_cma &codec_mm_reserved>; @@ -233,6 +241,13 @@ status = "okay"; }; + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + ppmgr { compatible = "amlogic, ppmgr"; memory-region = <&ppmgr_reserved>; @@ -792,8 +807,10 @@ dai-tdm-clk-sel = <1>; clocks = <&clkaudio CLKID_AUDIO_MCLK_B &clkc CLKID_MPLL1 - &clkc CLKID_MPLL0>; - clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; /* @@ -837,8 +854,10 @@ ; interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; pinctrl-0 = <&spdifout &spdifin>; + pinctrl-1 = <&spdifout_a_mute>; status = "okay"; }; aml_spdif_b: spdif_b { @@ -1060,6 +1079,13 @@ function = "spdif_out_ao"; }; }; + + spdifout_a_mute: spdifout_a_mute { + mux { /* gpiao_10 */ + groups = "GPIOAO_10"; + function = "gpio_aobus"; + }; + }; }; /* end of pinctrl_aobus */ &audio_data { diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905d2_skt_buildroot.dts b/arch/arm64/boot/dts/amlogic/g12a_s905d2_skt_buildroot.dts index 5c48f26ba772..8b3e7a30b2a2 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905d2_skt_buildroot.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905d2_skt_buildroot.dts @@ -46,7 +46,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x0 0x100000 0x0 0x7ff00000>; + linux,usable-memory = <0x0 0x0 0x0 0x80000000>; }; reserved-memory { @@ -213,6 +213,14 @@ }; }; + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + codec_mm { compatible = "amlogic, codec, mm"; memory-region = <&codec_mm_cma &codec_mm_reserved>; @@ -220,6 +228,13 @@ status = "okay"; }; + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + ppmgr { compatible = "amlogic, ppmgr"; memory-region = <&ppmgr_reserved>; @@ -784,8 +799,10 @@ ; interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; pinctrl-0 = <&spdifout &spdifin>; + pinctrl-1 = <&spdifout_a_mute>; status = "okay"; }; aml_spdif_b: spdif_b { @@ -1007,6 +1024,13 @@ function = "spdif_out_ao"; }; }; + + spdifout_a_mute: spdifout_a_mute { + mux { /* gpiao_10 */ + groups = "GPIOAO_10"; + function = "gpio_aobus"; + }; + }; }; /* end of pinctrl_aobus */ &audio_data { diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200.dts b/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200.dts index bda0c8a24e39..639e2e62f50c 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200.dts @@ -23,6 +23,7 @@ / { model = "Amlogic"; + amlogic-dt-id = "g12a_u200_2g"; compatible = "amlogic, g12a"; interrupt-parent = <&gic>; #address-cells = <2>; @@ -58,10 +59,10 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; + secmon_reserved:linux,secmon { compatible = "shared-dma-pool"; reusable; @@ -165,8 +166,6 @@ label="sys_led"; gpios=<&gpio_ao GPIOAO_11 GPIO_ACTIVE_HIGH>; default-state ="on"; - retain-state-suspended; - linux,default-trigger="cpu0"; }; }; @@ -245,6 +244,14 @@ }; }; + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + codec_mm { compatible = "amlogic, codec, mm"; memory-region = <&codec_mm_cma &codec_mm_reserved>; @@ -252,6 +259,13 @@ status = "okay"; }; + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + ppmgr { compatible = "amlogic, ppmgr"; memory-region = <&ppmgr_reserved>; @@ -461,6 +475,7 @@ key-device = "secure"; key-permit = "read","write","del"; }; +<<<<<<< HEAD keysn_15:key_15{ key-name = "region_code"; key-device = "normal"; @@ -471,6 +486,8 @@ key-device = "secure"; key-permit = "read","write","del"; }; +======= +>>>>>>> 9b43aa8... dts: add the attestationkeybox of unifykey[1/3] };//End unifykey efusekey:efusekey{ @@ -793,6 +810,122 @@ }; }; + cpu_opp_table1: cpu_opp_table1 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <731000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <731000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <731000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <731000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <731000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <731000>; + }; + opp06 { + opp-hz = /bits/ 64 <1398000000>; + opp-microvolt = <761000>; + }; + opp07 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <791000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <831000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <861000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <981000>; + }; + opp11 { + opp-hz = /bits/ 64 <1908000000>; + opp-microvolt = <991000>; + }; + }; + + cpu_opp_table2: cpu_opp_table2 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <731000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <731000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <731000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <731000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <731000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <731000>; + }; + opp06 { + opp-hz = /bits/ 64 <1398000000>; + opp-microvolt = <761000>; + }; + opp07 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <791000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <831000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <861000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <981000>; + }; + opp11 { + opp-hz = /bits/ 64 <1908000000>; + opp-microvolt = <991000>; + }; + opp12 { + opp-hz = /bits/ 64 <2016000000>; + opp-microvolt = <1011000>; + }; + opp13 { + opp-hz = /bits/ 64 <2100000000>; + opp-microvolt = <1011000>; + }; + }; + cpufreq-meson { compatible = "amlogic, cpufreq-meson"; pinctrl-names = "default"; @@ -802,6 +935,50 @@ }; /* end of / */ +&CPU0 { + /*set differents table cpufreq max*/ + diff_tables_supply; + hispeed_cpufreq_max = <2100>; + medspeed_cpufreq_max = <1908>; + lospeed_cpufreq_max = <1800>; + operating-points-v2 = <&cpu_opp_table0>, + <&cpu_opp_table1>, + <&cpu_opp_table2>; +}; + +&CPU1 { + /*set differents table cpufreq max*/ + diff_tables_supply; + hispeed_cpufreq_max = <2100>; + medspeed_cpufreq_max = <1908>; + lospeed_cpufreq_max = <1800>; + operating-points-v2 = <&cpu_opp_table0>, + <&cpu_opp_table1>, + <&cpu_opp_table2>; +}; + +&CPU2 { + /*set differents table cpufreq max*/ + diff_tables_supply; + hispeed_cpufreq_max = <2100>; + medspeed_cpufreq_max = <1908>; + lospeed_cpufreq_max = <1800>; + operating-points-v2 = <&cpu_opp_table0>, + <&cpu_opp_table1>, + <&cpu_opp_table2>; +}; + +&CPU3 { + /*set differents table cpufreq max*/ + diff_tables_supply; + hispeed_cpufreq_max = <2100>; + medspeed_cpufreq_max = <1908>; + lospeed_cpufreq_max = <1800>; + operating-points-v2 = <&cpu_opp_table0>, + <&cpu_opp_table1>, + <&cpu_opp_table2>; +}; + &meson_fb { status = "okay"; display_size_default = <1920 1080 1920 2160 32>; @@ -909,8 +1086,10 @@ dai-tdm-clk-sel = <1>; clocks = <&clkaudio CLKID_AUDIO_MCLK_B &clkc CLKID_MPLL1 - &clkc CLKID_MPLL0>; - clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; /* @@ -968,8 +1147,10 @@ ; interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; pinctrl-0 = <&spdifout &spdifin>; + pinctrl-1 = <&spdifout_a_mute>; status = "okay"; }; aml_spdif_b: spdif_b { @@ -1218,6 +1399,13 @@ function = "spdif_out_ao"; }; }; + + spdifout_a_mute: spdifout_a_mute { + mux { /* gpiao_10 */ + groups = "GPIOAO_10"; + function = "gpio_aobus"; + }; + }; }; /* end of pinctrl_aobus */ &audio_data { diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_1g.dts b/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_1g.dts index 1fe4278e5257..07b674175fb0 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_1g.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_1g.dts @@ -23,6 +23,7 @@ / { model = "Amlogic"; + amlogic-dt-id = "g12a_u200_1g"; compatible = "amlogic, g12a"; interrupt-parent = <&gic>; #address-cells = <2>; @@ -53,13 +54,12 @@ #size-cells = <2>; ranges; /* global autoconfigured region for contiguous allocations */ - ramoops@0x07400000 { + ramoops@0x07400000 { compatible = "ramoops"; reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { @@ -165,8 +165,6 @@ label="sys_led"; gpios=<&gpio_ao GPIOAO_11 GPIO_ACTIVE_HIGH>; default-state ="on"; - retain-state-suspended; - linux,default-trigger="cpu0"; }; }; @@ -245,6 +243,14 @@ }; }; + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + codec_mm { compatible = "amlogic, codec, mm"; memory-region = <&codec_mm_cma &codec_mm_reserved>; @@ -252,6 +258,13 @@ status = "okay"; }; + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + ppmgr { compatible = "amlogic, ppmgr"; memory-region = <&ppmgr_reserved>; @@ -909,8 +922,10 @@ dai-tdm-clk-sel = <1>; clocks = <&clkaudio CLKID_AUDIO_MCLK_B &clkc CLKID_MPLL1 - &clkc CLKID_MPLL0>; - clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; /* @@ -968,8 +983,10 @@ ; interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; pinctrl-0 = <&spdifout &spdifin>; + pinctrl-1 = <&spdifout_a_mute>; status = "okay"; }; aml_spdif_b: spdif_b { @@ -1218,6 +1235,13 @@ function = "spdif_out_ao"; }; }; + + spdifout_a_mute: spdifout_a_mute { + mux { /* gpiao_10 */ + groups = "GPIOAO_10"; + function = "gpio_aobus"; + }; + }; }; /* end of pinctrl_aobus */ &audio_data { diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_buildroot.dts b/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_buildroot.dts index 1b5bb0f0155b..08970fe41d61 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_buildroot.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_buildroot.dts @@ -19,6 +19,7 @@ #include "mesong12a.dtsi" #include "mesong12a_skt-panel.dtsi" +#include "mesong12a_drm.dtsi" / { model = "Amlogic"; @@ -44,7 +45,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x0 0x100000 0x0 0x7ff00000>; + linux,usable-memory = <0x0 0x0 0x0 0x80000000>; }; reserved-memory { @@ -149,8 +150,6 @@ label="sys_led"; gpios=<&gpio_ao GPIOAO_11 GPIO_ACTIVE_HIGH>; default-state ="on"; - retain-state-suspended; - linux,default-trigger="cpu0"; }; }; @@ -224,6 +223,14 @@ }; }; + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + codec_mm { compatible = "amlogic, codec, mm"; memory-region = <&codec_mm_cma &codec_mm_reserved>; @@ -231,6 +238,13 @@ status = "okay"; }; + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + ppmgr { compatible = "amlogic, ppmgr"; memory-region = <&ppmgr_reserved>; @@ -882,8 +896,10 @@ dai-tdm-clk-sel = <1>; clocks = <&clkaudio CLKID_AUDIO_MCLK_B &clkc CLKID_MPLL1 - &clkc CLKID_MPLL0>; - clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; /* @@ -927,8 +943,10 @@ ; interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; pinctrl-0 = <&spdifout &spdifin>; + pinctrl-1 = <&spdifout_a_mute>; status = "okay"; }; aml_spdif_b: spdif_b { @@ -1151,6 +1169,13 @@ function = "spdif_out_ao"; }; }; + + spdifout_a_mute: spdifout_a_mute { + mux { /* gpiao_10 */ + groups = "GPIOAO_10"; + function = "gpio_aobus"; + }; + }; }; /* end of pinctrl_aobus */ &audio_data { diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_buildroot_vccktest.dts b/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_buildroot_vccktest.dts index bbbbb344343b..e92bf361641b 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_buildroot_vccktest.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_buildroot_vccktest.dts @@ -19,7 +19,7 @@ #include "mesong12a.dtsi" #include "mesong12a_skt-panel.dtsi" - +#include "mesong12a_drm.dtsi" / { model = "Amlogic"; compatible = "amlogic, g12a"; @@ -44,7 +44,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x0 0x100000 0x0 0x7ff00000>; + linux,usable-memory = <0x0 0x0 0x0 0x80000000>; }; reserved-memory { @@ -150,8 +150,6 @@ label="sys_led"; gpios=<&gpio_ao GPIOAO_11 GPIO_ACTIVE_HIGH>; default-state ="on"; - retain-state-suspended; - linux,default-trigger="cpu0"; }; }; @@ -901,8 +899,10 @@ dai-tdm-clk-sel = <1>; clocks = <&clkaudio CLKID_AUDIO_MCLK_B &clkc CLKID_MPLL1 - &clkc CLKID_MPLL0>; - clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; /* @@ -946,8 +946,10 @@ ; interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; pinctrl-0 = <&spdifout &spdifin>; + pinctrl-1 = <&spdifout_a_mute>; status = "okay"; }; aml_spdif_b: spdif_b { @@ -1170,6 +1172,13 @@ function = "spdif_out_ao"; }; }; + + spdifout_a_mute: spdifout_a_mute { + mux { /* gpiao_10 */ + groups = "GPIOAO_10"; + function = "gpio_aobus"; + }; + }; }; /* end of pinctrl_aobus */ &audio_data { diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_drm_buildroot.dts b/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_drm_buildroot.dts index 927ef1bb2e29..9d35b059adf0 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_drm_buildroot.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_drm_buildroot.dts @@ -45,7 +45,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x0 0x100000 0x0 0x7ff00000>; + linux,usable-memory = <0x0 0x0 0x0 0x80000000>; }; reserved-memory { @@ -150,8 +150,6 @@ label="sys_led"; gpios=<&gpio_ao GPIOAO_11 GPIO_ACTIVE_HIGH>; default-state ="on"; - retain-state-suspended; - linux,default-trigger="cpu0"; }; }; @@ -225,6 +223,14 @@ }; }; + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + codec_mm { compatible = "amlogic, codec, mm"; memory-region = <&codec_mm_cma &codec_mm_reserved>; @@ -232,6 +238,13 @@ status = "okay"; }; + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + ppmgr { compatible = "amlogic, ppmgr"; memory-region = <&ppmgr_reserved>; @@ -897,8 +910,10 @@ dai-tdm-clk-sel = <1>; clocks = <&clkaudio CLKID_AUDIO_MCLK_B &clkc CLKID_MPLL1 - &clkc CLKID_MPLL0>; - clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; /* @@ -942,8 +957,10 @@ ; interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; pinctrl-0 = <&spdifout &spdifin>; + pinctrl-1 = <&spdifout_a_mute>; status = "okay"; }; aml_spdif_b: spdif_b { @@ -1166,6 +1183,13 @@ function = "spdif_out_ao"; }; }; + + spdifout_a_mute: spdifout_a_mute { + mux { /* gpiao_10 */ + groups = "GPIOAO_10"; + function = "gpio_aobus"; + }; + }; }; /* end of pinctrl_aobus */ &audio_data { diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211.dts b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211.dts index d45f54b86f3d..08d52a09a004 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211.dts @@ -45,7 +45,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x0 0x100000 0x0 0x7ff00000>; + linux,usable-memory = <0x0 0x0 0x0 0x80000000>; }; reserved-memory { @@ -58,8 +58,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { @@ -188,8 +187,6 @@ label="sys_led"; gpios=<&gpio_ao GPIOAO_11 GPIO_ACTIVE_LOW>; default-state ="on"; - retain-state-suspended; - linux,default-trigger="cpu0"; }; }; @@ -263,6 +260,14 @@ }; }; + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + codec_mm { compatible = "amlogic, codec, mm"; memory-region = <&codec_mm_cma &codec_mm_reserved>; @@ -270,6 +275,13 @@ status = "okay"; }; + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + ppmgr { compatible = "amlogic, ppmgr"; memory-region = <&ppmgr_reserved>; @@ -842,8 +854,10 @@ dai-tdm-clk-sel = <1>; clocks = <&clkaudio CLKID_AUDIO_MCLK_B &clkc CLKID_MPLL1 - &clkc CLKID_MPLL0>; - clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; /* @@ -901,8 +915,10 @@ ; interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; pinctrl-0 = <&spdifout>; + pinctrl-1 = <&spdifout_a_mute>; status = "okay"; }; aml_spdif_b: spdif_b { @@ -1095,6 +1111,13 @@ }; }; + spdifout_a_mute: spdifout_a_mute { + mux { /* GPIOH_4 */ + groups = "GPIOH_4"; + function = "gpio_periphs"; + }; + }; + pdmin: pdmin { mux { /* gpioa_5, gpioa_6, gpioa_7, gpioa_8, gpioa_9*/ groups = "pdm_din0_a", diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211_1g.dts b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211_1g.dts index c463f06ac21a..1dce4d3bf867 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211_1g.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211_1g.dts @@ -45,7 +45,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x0 0x100000 0x0 0x3ff00000>; + linux,usable-memory = <0x0 0x0 0x0 0x40000000>; }; @@ -59,8 +59,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { @@ -189,8 +188,6 @@ label="sys_led"; gpios=<&gpio_ao GPIOAO_11 GPIO_ACTIVE_LOW>; default-state ="on"; - retain-state-suspended; - linux,default-trigger="cpu0"; }; }; @@ -257,6 +254,14 @@ }; }; + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + codec_mm { compatible = "amlogic, codec, mm"; memory-region = <&codec_mm_cma &codec_mm_reserved>; @@ -264,6 +269,13 @@ status = "okay"; }; + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + ppmgr { compatible = "amlogic, ppmgr"; memory-region = <&ppmgr_reserved>; @@ -833,8 +845,10 @@ dai-tdm-clk-sel = <1>; clocks = <&clkaudio CLKID_AUDIO_MCLK_B &clkc CLKID_MPLL1 - &clkc CLKID_MPLL0>; - clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; /* @@ -892,8 +906,10 @@ ; interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; pinctrl-0 = <&spdifout>; + pinctrl-1 = <&spdifout_a_mute>; status = "okay"; }; aml_spdif_b: spdif_b { @@ -1086,6 +1102,13 @@ }; }; + spdifout_a_mute: spdifout_a_mute { + mux { /* GPIOH_4 */ + groups = "GPIOH_4"; + function = "gpio_periphs"; + }; + }; + pdmin: pdmin { mux { /* gpioa_5, gpioa_6, gpioa_7, gpioa_8, gpioa_9*/ groups = "pdm_din0_a", diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211_512m.dts b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211_512m.dts index 88edd7a1e77a..7e8d963e1e41 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211_512m.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211_512m.dts @@ -57,8 +57,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { @@ -177,8 +176,6 @@ label="sys_led"; gpios=<&gpio_ao GPIOAO_11 GPIO_ACTIVE_LOW>; default-state ="on"; - retain-state-suspended; - linux,default-trigger="cpu0"; }; }; @@ -252,6 +249,14 @@ }; }; + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + codec_mm { compatible = "amlogic, codec, mm"; memory-region = <&codec_mm_cma &codec_mm_reserved>; @@ -259,6 +264,13 @@ status = "okay"; }; + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + ppmgr { compatible = "amlogic, ppmgr"; memory-region = <&ppmgr_reserved>; @@ -829,8 +841,10 @@ dai-tdm-clk-sel = <1>; clocks = <&clkaudio CLKID_AUDIO_MCLK_B &clkc CLKID_MPLL1 - &clkc CLKID_MPLL0>; - clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; /* @@ -888,8 +902,10 @@ ; interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; pinctrl-0 = <&spdifout>; + pinctrl-1 = <&spdifout_a_mute>; status = "okay"; }; aml_spdif_b: spdif_b { @@ -1082,6 +1098,13 @@ }; }; + spdifout_a_mute: spdifout_a_mute { + mux { /* GPIOH_4 */ + groups = "GPIOH_4"; + function = "gpio_periphs"; + }; + }; + pdmin: pdmin { mux { /* gpioa_5, gpioa_6, gpioa_7, gpioa_8, gpioa_9*/ groups = "pdm_din0_a", diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211_buildroot.dts b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211_buildroot.dts index c2ac3e54fafe..981f39508346 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211_buildroot.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u211_buildroot.dts @@ -18,9 +18,11 @@ /dts-v1/; #include "mesong12a.dtsi" +#include "mesong12a_drm.dtsi" / { model = "Amlogic"; + amlogic-dt-id = "g12a_u211_2g"; compatible = "amlogic, g12a"; interrupt-parent = <&gic>; #address-cells = <2>; @@ -43,7 +45,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x0 0x100000 0x0 0x7ff00000>; + linux,usable-memory = <0x0 0x0 0x0 0x80000000>; }; reserved-memory { @@ -167,8 +169,6 @@ label="sys_led"; gpios=<&gpio_ao GPIOAO_11 GPIO_ACTIVE_LOW>; default-state ="on"; - retain-state-suspended; - linux,default-trigger="cpu0"; }; }; @@ -236,6 +236,14 @@ }; }; + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + codec_mm { compatible = "amlogic, codec, mm"; memory-region = <&codec_mm_cma &codec_mm_reserved>; @@ -243,6 +251,13 @@ status = "okay"; }; + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + ppmgr { compatible = "amlogic, ppmgr"; memory-region = <&ppmgr_reserved>; @@ -883,8 +898,10 @@ dai-tdm-clk-sel = <1>; clocks = <&clkaudio CLKID_AUDIO_MCLK_B &clkc CLKID_MPLL1 - &clkc CLKID_MPLL0>; - clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; /* @@ -928,8 +945,10 @@ ; interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; pinctrl-0 = <&spdifout>; + pinctrl-1 = <&spdifout_a_mute>; status = "okay"; }; aml_spdif_b: spdif_b { @@ -1122,6 +1141,13 @@ }; }; + spdifout_a_mute: spdifout_a_mute { + mux { /* GPIOH_4 */ + groups = "GPIOH_4"; + function = "gpio_periphs"; + }; + }; + pdmin: pdmin { mux { /* gpioa_5, gpioa_6, gpioa_7, gpioa_8, gpioa_9*/ groups = "pdm_din0_a", diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212.dts b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212.dts index 83da45b4fdb6..23ed588c6b72 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212.dts @@ -22,7 +22,7 @@ / { model = "Amlogic"; - amlogic-dt-id = "g12a_s905x2_u212"; + amlogic-dt-id = "g12a_u212_2g"; compatible = "amlogic, g12a"; interrupt-parent = <&gic>; #address-cells = <2>; @@ -58,8 +58,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { @@ -163,17 +162,17 @@ gpioleds { compatible = "gpio-leds"; - status = "okay"; + status = "disabled"; net_red { label="net_red"; - gpios=<&gpio GPIOA_14 GPIO_ACTIVE_LOW>; + /*gpios=<&gpio GPIOA_14 GPIO_ACTIVE_LOW>;*/ default-state ="on"; }; net_green { label="net_green"; - gpios=<&gpio GPIOA_15 GPIO_ACTIVE_HIGH>; + /*gpios=<&gpio GPIOA_15 GPIO_ACTIVE_HIGH>;*/ default-state ="on"; }; @@ -188,8 +187,6 @@ label="sys_led"; gpios=<&gpio_ao GPIOAO_11 GPIO_ACTIVE_LOW>; default-state ="on"; - retain-state-suspended; - linux,default-trigger="cpu0"; }; }; @@ -263,6 +260,14 @@ }; }; + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + codec_mm { compatible = "amlogic, codec, mm"; memory-region = <&codec_mm_cma &codec_mm_reserved>; @@ -270,6 +275,13 @@ status = "okay"; }; + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + ppmgr { compatible = "amlogic, ppmgr"; memory-region = <&ppmgr_reserved>; @@ -306,43 +318,47 @@ dev_name = "ionvideo"; status = "okay"; }; - /*dvb { - * compatible = "amlogic, dvb"; - * dev_name = "dvb"; - * - * fe0_mode = "external"; - * fe0_demod = "Atbm8881"; - * fe0_i2c_adap_id = <&i2c2>; - * fe0_demod_i2c_addr = <0xc0>; - * fe0_ts = <1>; - * fe0_reset_value = <0>; - * fe0_reset_gpio = <&gpio GPIOZ_1 GPIO_ACTIVE_HIGH>; - * - * ts1 = "parallel"; - * ts1_control = <0>; - * ts1_invert = <0>; - * interrupts = <0 23 1 - * 0 5 1 - * 0 21 1 - * 0 19 1 - * 0 25 1 - * 0 18 1 - * 0 24 1>; - * interrupt-names = "demux0_irq", - * "demux1_irq", - * "demux2_irq", - * "dvr0_irq", - * "dvr1_irq", - * "dvrfill0_fill", - * "dvrfill1_flush"; - * pinctrl-names = "p_ts1"; - * pinctrl-0 = <&dvb_p_ts1_pins>; - * clocks = <&clkc CLKID_DEMUX - * &clkc CLKID_AHB_ARB0 - * &clkc CLKID_DOS_PARSER>; - * clock-names = "demux", "ahbarb0", "parser_top"; - *}; - */ + dvb { + compatible = "amlogic, dvb"; + dev_name = "dvb"; + status = "ok"; + + ts0 = "serial"; + ts0_control = <0x800>; + ts0_invert = <0>; + pinctrl-names = "s_ts0"; + pinctrl-0 = <&dvb_s_ts0_pins>; + + interrupts = <0 23 1 + 0 5 1 + 0 53 1 + 0 19 1 + 0 25 1 + 0 18 1 + 0 24 1>; + interrupt-names = "demux0_irq", + "demux1_irq", + "demux2_irq", + "dvr0_irq", + "dvr1_irq", + "dvrfill0_fill", + "dvrfill1_flush"; + }; + dvbfe { + compatible = "amlogic, dvbfe"; + dev_name = "dvbfe"; + dtv_demod0 = "Avl6762"; + dtv_demod0_i2c_adap = <&i2c3>; + dtv_demod0_i2c_addr = <0x14>; + dtv_demod0_reset_value = <0>; + dtv_demod0_reset_gpio = <&gpio GPIOZ_10 GPIO_ACTIVE_HIGH>; + dtv_demod0_ant_poweron_value = <0>; + dtv_demod0_ant_power_gpio = <&gpio GPIOH_5 GPIO_ACTIVE_HIGH>; + dtv_demod0_tuner_type = <52>; + fe0_dtv_demod = <0>; + fe0_ts = <0>; + fe0_dev = <0>; + }; unifykey{ compatible = "amlogic, unifykey"; status = "ok"; @@ -830,7 +846,7 @@ */ &i2c3 { - status = "disabled"; + status = "ok"; pinctrl-names="default"; pinctrl-0=<&i2c3_master_pins2>; clock-frequency = <100000>; /* default 100k */ @@ -882,8 +898,10 @@ dai-tdm-clk-sel = <1>; clocks = <&clkaudio CLKID_AUDIO_MCLK_B &clkc CLKID_MPLL1 - &clkc CLKID_MPLL0>; - clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; /* @@ -941,8 +959,10 @@ ; interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; pinctrl-0 = <&spdifout>; + pinctrl-1 = <&spdifout_a_mute>; status = "okay"; }; aml_spdif_b: spdif_b { @@ -1135,6 +1155,13 @@ }; }; + spdifout_a_mute: spdifout_a_mute { + mux { /* GPIOH_4 */ + groups = "GPIOH_4"; + function = "gpio_periphs"; + }; + }; + pdmin: pdmin { mux { /* gpioa_5, gpioa_6, gpioa_7, gpioa_8, gpioa_9*/ groups = "pdm_din0_a", @@ -1386,3 +1413,14 @@ status = "okay"; }; +&pinctrl_aobus { + dvb_s_ts0_pins: dvb_s_ts0_pins { + tsin_a { + groups = "tsin_a_sop_ao", + "tsin_a_valid_ao", + "tsin_a_clk_ao", + "tsin_a_din0_ao"; + function = "tsin_a_ao"; + }; + }; +}; diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212_1g.dts b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212_1g.dts index 80821091057e..b742fe8b87a7 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212_1g.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212_1g.dts @@ -22,7 +22,7 @@ / { model = "Amlogic"; - amlogic-dt-id = "g12a_s905x2_u212_1g"; + amlogic-dt-id = "g12a_u212_1g"; compatible = "amlogic, g12a"; interrupt-parent = <&gic>; #address-cells = <2>; @@ -59,8 +59,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { @@ -164,17 +163,17 @@ gpioleds { compatible = "gpio-leds"; - status = "okay"; + status = "disabled"; net_red { label="net_red"; - gpios=<&gpio GPIOA_14 GPIO_ACTIVE_LOW>; + /*gpios=<&gpio GPIOA_14 GPIO_ACTIVE_LOW>;*/ default-state ="on"; }; net_green { label="net_green"; - gpios=<&gpio GPIOA_15 GPIO_ACTIVE_HIGH>; + /*gpios=<&gpio GPIOA_15 GPIO_ACTIVE_HIGH>;*/ default-state ="on"; }; @@ -189,8 +188,6 @@ label="sys_led"; gpios=<&gpio_ao GPIOAO_11 GPIO_ACTIVE_LOW>; default-state ="on"; - retain-state-suspended; - linux,default-trigger="cpu0"; }; }; @@ -257,6 +254,14 @@ }; }; + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + codec_mm { compatible = "amlogic, codec, mm"; memory-region = <&codec_mm_cma &codec_mm_reserved>; @@ -264,6 +269,13 @@ status = "okay"; }; + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + ppmgr { compatible = "amlogic, ppmgr"; memory-region = <&ppmgr_reserved>; @@ -300,43 +312,47 @@ dev_name = "ionvideo"; status = "okay"; }; - /*dvb { - * compatible = "amlogic, dvb"; - * dev_name = "dvb"; - * - * fe0_mode = "external"; - * fe0_demod = "Atbm8881"; - * fe0_i2c_adap_id = <&i2c2>; - * fe0_demod_i2c_addr = <0xc0>; - * fe0_ts = <1>; - * fe0_reset_value = <0>; - * fe0_reset_gpio = <&gpio GPIOZ_1 GPIO_ACTIVE_HIGH>; - * - * ts1 = "parallel"; - * ts1_control = <0>; - * ts1_invert = <0>; - * interrupts = <0 23 1 - * 0 5 1 - * 0 21 1 - * 0 19 1 - * 0 25 1 - * 0 18 1 - * 0 24 1>; - * interrupt-names = "demux0_irq", - * "demux1_irq", - * "demux2_irq", - * "dvr0_irq", - * "dvr1_irq", - * "dvrfill0_fill", - * "dvrfill1_flush"; - * pinctrl-names = "p_ts1"; - * pinctrl-0 = <&dvb_p_ts1_pins>; - * clocks = <&clkc CLKID_DEMUX - * &clkc CLKID_AHB_ARB0 - * &clkc CLKID_DOS_PARSER>; - * clock-names = "demux", "ahbarb0", "parser_top"; - *}; - */ + dvb { + compatible = "amlogic, dvb"; + dev_name = "dvb"; + status = "ok"; + + ts0 = "serial"; + ts0_control = <0x800>; + ts0_invert = <0>; + pinctrl-names = "s_ts0"; + pinctrl-0 = <&dvb_s_ts0_pins>; + + interrupts = <0 23 1 + 0 5 1 + 0 53 1 + 0 19 1 + 0 25 1 + 0 18 1 + 0 24 1>; + interrupt-names = "demux0_irq", + "demux1_irq", + "demux2_irq", + "dvr0_irq", + "dvr1_irq", + "dvrfill0_fill", + "dvrfill1_flush"; + }; + dvbfe { + compatible = "amlogic, dvbfe"; + dev_name = "dvbfe"; + dtv_demod0 = "Avl6762"; + dtv_demod0_i2c_adap = <&i2c3>; + dtv_demod0_i2c_addr = <0x14>; + dtv_demod0_reset_value = <0>; + dtv_demod0_reset_gpio = <&gpio GPIOZ_10 GPIO_ACTIVE_HIGH>; + dtv_demod0_ant_poweron_value = <0>; + dtv_demod0_ant_power_gpio = <&gpio GPIOH_5 GPIO_ACTIVE_HIGH>; + dtv_demod0_tuner_type = <52>; + fe0_dtv_demod = <0>; + fe0_ts = <0>; + fe0_dev = <0>; + }; unifykey{ compatible = "amlogic, unifykey"; status = "ok"; @@ -822,7 +838,7 @@ */ &i2c3 { - status = "disabled"; + status = "okay"; pinctrl-names="default"; pinctrl-0=<&i2c3_master_pins2>; clock-frequency = <100000>; /* default 100k */ @@ -874,8 +890,10 @@ dai-tdm-clk-sel = <1>; clocks = <&clkaudio CLKID_AUDIO_MCLK_B &clkc CLKID_MPLL1 - &clkc CLKID_MPLL0>; - clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; /* @@ -933,8 +951,10 @@ ; interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; pinctrl-0 = <&spdifout>; + pinctrl-1 = <&spdifout_a_mute>; status = "okay"; }; aml_spdif_b: spdif_b { @@ -1127,6 +1147,13 @@ }; }; + spdifout_a_mute: spdifout_a_mute { + mux { /* GPIOH_4 */ + groups = "GPIOH_4"; + function = "gpio_periphs"; + }; + }; + pdmin: pdmin { mux { /* gpioa_5, gpioa_6, gpioa_7, gpioa_8, gpioa_9*/ groups = "pdm_din0_a", @@ -1372,3 +1399,14 @@ &saradc { status = "disabled"; }; +&pinctrl_aobus { + dvb_s_ts0_pins: dvb_s_ts0_pins { + tsin_a { + groups = "tsin_a_sop_ao", + "tsin_a_valid_ao", + "tsin_a_clk_ao", + "tsin_a_din0_ao"; + function = "tsin_a_ao"; + }; + }; +}; diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212_buildroot.dts b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212_buildroot.dts index 0d3a73079a8e..fa91c3874e63 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212_buildroot.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212_buildroot.dts @@ -18,6 +18,7 @@ /dts-v1/; #include "mesong12a.dtsi" +#include "mesong12a_drm.dtsi" / { model = "Amlogic"; @@ -43,7 +44,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x0 0x100000 0x0 0x7ff00000>; + linux,usable-memory = <0x0 0x0 0x0 0x80000000>; }; reserved-memory { @@ -167,8 +168,6 @@ label="sys_led"; gpios=<&gpio_ao GPIOAO_11 GPIO_ACTIVE_LOW>; default-state ="on"; - retain-state-suspended; - linux,default-trigger="cpu0"; }; }; @@ -236,6 +235,14 @@ }; }; + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + codec_mm { compatible = "amlogic, codec, mm"; memory-region = <&codec_mm_cma &codec_mm_reserved>; @@ -243,6 +250,13 @@ status = "okay"; }; + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + ppmgr { compatible = "amlogic, ppmgr"; memory-region = <&ppmgr_reserved>; @@ -883,8 +897,10 @@ dai-tdm-clk-sel = <1>; clocks = <&clkaudio CLKID_AUDIO_MCLK_B &clkc CLKID_MPLL1 - &clkc CLKID_MPLL0>; - clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; /* @@ -928,8 +944,10 @@ ; interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; pinctrl-0 = <&spdifout>; + pinctrl-1 = <&spdifout_a_mute>; status = "okay"; }; aml_spdif_b: spdif_b { @@ -1122,6 +1140,13 @@ }; }; + spdifout_a_mute: spdifout_a_mute { + mux { /* GPIOH_4 */ + groups = "GPIOH_4"; + function = "gpio_periphs"; + }; + }; + pdmin: pdmin { mux { /* gpioa_5, gpioa_6, gpioa_7, gpioa_8, gpioa_9*/ groups = "pdm_din0_a", diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212_drm_buildroot.dts b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212_drm_buildroot.dts new file mode 100644 index 000000000000..dd00ad385edc --- /dev/null +++ b/arch/arm64/boot/dts/amlogic/g12a_s905x2_u212_drm_buildroot.dts @@ -0,0 +1,1393 @@ +/* + * arch/arm64/boot/dts/amlogic/g12a_s905x2_u212_drm_buildroot.dts + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +/dts-v1/; + +#include "mesong12a.dtsi" +#include "mesong12a_drm.dtsi" + +/ { + model = "Amlogic"; + compatible = "amlogic, g12a"; + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + + aliases { + serial0 = &uart_AO; + serial1 = &uart_A; + serial2 = &uart_B; + serial3 = &uart_C; + serial4 = &uart_AO_B; + tsensor0 = &p_tsensor; + tsensor1 = &d_tsensor; + i2c0 = &i2c0; + i2c1 = &i2c1; + i2c2 = &i2c2; + i2c3 = &i2c3; + i2c4 = &i2c_AO; + }; + + memory@00000000 { + device_type = "memory"; + linux,usable-memory = <0x0 0x100000 0x0 0x7ff00000>; + }; + + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + /* global autoconfigured region for contiguous allocations */ + secmon_reserved:linux,secmon { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x400000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x05000000 0x0 0x400000>; + }; + secos_reserved:linux,secos { + status = "disable"; + compatible = "amlogic, aml_secos_memory"; + reg = <0x0 0x05300000 0x0 0x2000000>; + no-map; + }; + logo_reserved:linux,meson-fb { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x800000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x7f800000 0x0 0x800000>; + }; + ion_cma_reserved:linux,ion-dev { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x8000000>; + alignment = <0x0 0x400000>; + }; + //di_reserved:linux,di { + //compatible = "amlogic, di-mem"; + /* buffer_size = 3621952(yuv422 8bit) */ + /* 4179008(yuv422 10bit full pack mode) */ + /** 10x3621952=34.6M(0x23) support 8bit **/ + /** 10x4736064=45.2M(0x2e) support 12bit **/ + /** 10x4179008=40M(0x28) support 10bit **/ + //size = <0x0 0x2800000>; + //no-map; + //}; + /*di CMA pool */ + di_cma_reserved:linux,di_cma { + compatible = "shared-dma-pool"; + reusable; + /* buffer_size = 3621952(yuv422 8bit) + * | 4736064(yuv422 10bit) + * | 4074560(yuv422 10bit full pack mode) + * 10x3621952=34.6M(0x23) support 8bit + * 10x4736064=45.2M(0x2e) support 12bit + * 10x4074560=40M(0x28) support 10bit + */ + size = <0x0 0x02800000>; + alignment = <0x0 0x400000>; + }; + /* POST PROCESS MANAGER */ + ppmgr_reserved:linux,ppmgr { + compatible = "shared-dma-pool"; + size = <0x0 0x0>; + }; + + codec_mm_cma:linux,codec_mm_cma { + compatible = "shared-dma-pool"; + reusable; + /* ion_codec_mm max can alloc size 80M*/ + size = <0x0 0x13400000>; + alignment = <0x0 0x400000>; + linux,contiguous-region; + }; + /* codec shared reserved */ + codec_mm_reserved:linux,codec_mm_reserved { + compatible = "amlogic, codec-mm-reserved"; + size = <0x0 0x0>; + alignment = <0x0 0x100000>; + //no-map; + }; + /* vdin0 CMA pool */ + vdin0_cma_reserved:linux,vdin0_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16+4 M */ + size = <0x0 0x04000000>; + alignment = <0x0 0x400000>; + }; + /* vdin1 CMA pool */ + vdin1_cma_reserved:linux,vdin1_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16 M */ + size = <0x0 0x04000000>; + alignment = <0x0 0x400000>; + }; + }; + + gpioleds { + compatible = "gpio-leds"; + status = "okay"; + + net_red { + label="net_red"; + gpios=<&gpio GPIOA_14 GPIO_ACTIVE_LOW>; + default-state ="on"; + }; + + net_green { + label="net_green"; + gpios=<&gpio GPIOA_15 GPIO_ACTIVE_HIGH>; + default-state ="on"; + }; + + remote_led { + label = "remote_led"; + gpios = <&gpio_ao GPIOAO_10 GPIO_ACTIVE_LOW>; + default-state = "off"; + linux,default-trigger = "rc_feedback"; + }; + + sys_led { + label="sys_led"; + gpios=<&gpio_ao GPIOAO_11 GPIO_ACTIVE_LOW>; + default-state ="on"; + retain-state-suspended; + linux,default-trigger="cpu0"; + }; + }; + + cvbsout { + compatible = "amlogic, cvbsout-g12a"; + dev_name = "cvbsout"; + status = "okay"; + clocks = <&clkc CLKID_VCLK2_ENCI + &clkc CLKID_VCLK2_VENCI0 + &clkc CLKID_VCLK2_VENCI1 + &clkc CLKID_DAC_CLK>; + clock-names = "venci_top_gate", + "venci_0_gate", + "venci_1_gate", + "vdac_clk_gate"; + clk_path = <0>; + + /* performance: reg_address, reg_value */ + /* g12a */ + performance = <0x1bf0 0x9 + 0x1b56 0x343 + 0x1b12 0x0 + 0x1b05 0x9 + 0x1c59 0xfc48 + 0xffff 0x0>; /* ending flag */ + performance_telecom = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x8080 + 0x1b05 0xfd + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + }; + + bt-dev{ + compatible = "amlogic, bt-dev"; + dev_name = "bt-dev"; + status = "okay"; + gpio_reset = <&gpio GPIOX_17 GPIO_ACTIVE_HIGH>; + gpio_hostwake = <&gpio GPIOX_19 GPIO_ACTIVE_HIGH>; + }; + + wifi{ + compatible = "amlogic, aml_wifi"; + dev_name = "aml_wifi"; + status = "okay"; + interrupt_pin = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; + irq_trigger_type = "GPIO_IRQ_LOW"; + power_on_pin = <&gpio GPIOX_6 GPIO_ACTIVE_HIGH>; + dhd_static_buf; //if use bcm wifi, config dhd_static_buf + pinctrl-names = "default"; + pinctrl-0 = <&pwm_e_pins>; + pwm_config = <&wifi_pwm_conf>; + }; + + wifi_pwm_conf:wifi_pwm_conf{ + pwm_channel1_conf { + pwms = <&pwm_ef MESON_PWM_0 30541 0>; + duty-cycle = <15270>; + times = <10>; + }; + pwm_channel2_conf { + pwms = <&pwm_ef MESON_PWM_2 30500 0>; + duty-cycle = <15250>; + times = <12>; + }; + }; + + codec_mm { + compatible = "amlogic, codec, mm"; + memory-region = <&codec_mm_cma &codec_mm_reserved>; + dev_name = "codec_mm"; + status = "okay"; + }; + + ppmgr { + compatible = "amlogic, ppmgr"; + memory-region = <&ppmgr_reserved>; + dev_name = "ppmgr"; + status = "okay"; + }; + + deinterlace { + compatible = "amlogic, deinterlace"; + status = "okay"; + /* 0:use reserved; 1:use cma; 2:use cma as reserved */ + flag_cma = <1>; + //memory-region = <&di_reserved>; + memory-region = <&di_cma_reserved>; + interrupts = <0 46 1 + 0 40 1>; + interrupt-names = "pre_irq", "post_irq"; + clocks = <&clkc CLKID_VPU_CLKB_TMP_COMP>, + <&clkc CLKID_VPU_CLKB_COMP>; + clock-names = "vpu_clkb_tmp_composite", + "vpu_clkb_composite"; + clock-range = <334 667>; + /* buffer-size = <3621952>;(yuv422 8bit) */ + buffer-size = <4074560>;/*yuv422 fullpack*/ + /* reserve-iomap = "true"; */ + /* if enable nr10bit, set nr10bit-support to 1 */ + post-wr-support = <1>; + nr10bit-support = <1>; + nrds-enable = <1>; + pps-enable = <1>; + }; + ionvideo { + compatible = "amlogic, ionvideo"; + dev_name = "ionvideo"; + status = "okay"; + }; + + + partitions: partitions{ + parts = <14>; + part-0 = <&logo>; + part-1 = <&recovery>; + part-2 = <&misc>; + part-3 = <&dto>; + part-4 = <&cri_data>; + part-5 = <¶m>; + part-6 = <&boot>; + part-7 = <&rsv>; + part-8 = <&tee>; + part-9 = <&vendor>; + part-10 = <&odm>; + part-11 = <&system>; + part-12 = <&cache>; + part-13 = <&data>; + + logo:logo{ + pname = "logo"; + size = <0x0 0x800000>; + mask = <1>; + }; + recovery:recovery{ + pname = "recovery"; + size = <0x0 0x1800000>; + mask = <1>; + }; + misc:misc{ + pname = "misc"; + size = <0x0 0x800000>; + mask = <1>; + }; + dto:dto{ + pname = "dto"; + size = <0x0 0x800000>; + mask = <1>; + }; + cri_data:cri_data{ + pname = "cri_data"; + size = <0x0 0x800000>; + mask = <2>; + }; + rsv:rsv{ + pname = "rsv"; + size = <0x0 0x1000000>; + mask = <1>; + }; + param:param{ + pname = "param"; + size = <0x0 0x1000000>; + mask = <2>; + }; + boot:boot{ + pname = "boot"; + size = <0x0 0x1000000>; + mask = <1>; + }; + tee:tee{ + pname = "tee"; + size = <0x0 0x2000000>; + mask = <1>; + }; + vendor:vendor{ + pname = "vendor"; + size = <0x0 0x10000000>; + mask = <1>; + }; + odm:odm{ + pname = "odm"; + size = <0x0 0x10000000>; + mask = <1>; + }; + system:system{ + pname = "system"; + size = <0x0 0x80000000>; + mask = <1>; + }; + cache:cache{ + pname = "cache"; + size = <0x0 0x46000000>; + mask = <2>; + }; + data:data{ + pname = "data"; + size = <0xffffffff 0xffffffff>; + mask = <4>; + }; + }; + unifykey{ + compatible = "amlogic, unifykey"; + status = "ok"; + unifykey-num = <16>; + unifykey-index-0 = <&keysn_0>; + unifykey-index-1 = <&keysn_1>; + unifykey-index-2 = <&keysn_2>; + unifykey-index-3 = <&keysn_3>; + unifykey-index-4 = <&keysn_4>; + unifykey-index-5 = <&keysn_5>; + unifykey-index-6 = <&keysn_6>; + unifykey-index-7 = <&keysn_7>; + unifykey-index-8 = <&keysn_8>; + unifykey-index-9 = <&keysn_9>; + unifykey-index-10= <&keysn_10>; + unifykey-index-11= <&keysn_11>; + unifykey-index-12= <&keysn_12>; + unifykey-index-13= <&keysn_13>; + unifykey-index-14= <&keysn_14>; + unifykey-index-15= <&keysn_15>; + + keysn_0: key_0{ + key-name = "usid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_1:key_1{ + key-name = "mac"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_2:key_2{ + key-name = "hdcp"; + key-device = "secure"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_3:key_3{ + key-name = "secure_boot_set"; + key-device = "efuse"; + key-permit = "write"; + }; + keysn_4:key_4{ + key-name = "mac_bt"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_5:key_5{ + key-name = "mac_wifi"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_6:key_6{ + key-name = "hdcp2_tx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_7:key_7{ + key-name = "hdcp2_rx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_8:key_8{ + key-name = "widevinekeybox"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_9:key_9{ + key-name = "deviceid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_10:key_10{ + key-name = "hdcp22_fw_private"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_11:key_11{ + key-name = "PlayReadykeybox25"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_12:key_12{ + key-name = "prpubkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_13:key_13{ + key-name = "prprivkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_14:key_14{ + key-name = "attestationkeybox";// attestation key + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_15:key_15{ + key-name = "netflix_mgkid"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + };//End unifykey + + efusekey:efusekey{ + keynum = <4>; + key0 = <&key_0>; + key1 = <&key_1>; + key2 = <&key_2>; + key3 = <&key_3>; + key_0:key_0{ + keyname = "mac"; + offset = <0>; + size = <6>; + }; + key_1:key_1{ + keyname = "mac_bt"; + offset = <6>; + size = <6>; + }; + key_2:key_2{ + keyname = "mac_wifi"; + offset = <12>; + size = <6>; + }; + key_3:key_3{ + keyname = "usid"; + offset = <18>; + size = <16>; + }; + };//End efusekey + + amlvecm { + compatible = "amlogic, vecm"; + dev_name = "aml_vecm"; + status = "okay"; + gamma_en = <0>;/*1:enabel ;0:disable*/ + wb_en = <0>;/*1:enabel ;0:disable*/ + cm_en = <0>;/*1:enabel ;0:disable*/ + /*0: 709/601 1: bt2020*/ + tx_op_color_primary = <0>; + }; + + amdolby_vision { + compatible = "amlogic, dolby_vision_g12a"; + dev_name = "aml_amdolby_vision_driver"; + status = "okay"; + tv_mode = <0>;/*1:enabel ;0:disable*/ + }; + + meson-fb { + compatible = "amlogic, meson-g12a"; + /*memory-region = <&logo_reserved>;*/ + dev_name = "meson-fb"; + status = "disable"; + interrupts = <0 3 1 + 0 56 1 + 0 89 1>; + interrupt-names = "viu-vsync", "viu2-vsync", "rdma"; + mem_size = <0x00800000 0x1980000 0x100000 0x100000 0x800000>; + /* uboot logo,fb0/fb1 memory size,if afbcd fb0=0x01851000*/ + display_mode_default = "1080p60hz"; + scale_mode = <1>; + /** 0:VPU free scale 1:OSD free scale 2:OSD super scale */ + display_size_default = <1920 1080 1920 2160 32>; + /*1920*1080*4*3 = 0x17BB000*/ + pxp_mode = <0>; /** 0:normal mode 1:pxp mode */ + mem_alloc = <1>; + logo_addr = "0x3f800000"; + clocks = <&clkc CLKID_VPU_CLKC_MUX>; + clock-names = "vpu_clkc"; + }; + + /* Audio Related start */ + pdm_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, pdm_dummy_codec"; + status = "okay"; + }; + dummy_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, aml_dummy_codec"; + status = "okay"; + }; + amlogic_codec:t9015{ + #sound-dai-cells = <0>; + compatible = "amlogic, aml_codec_T9015"; + reg = <0x0 0xFF632000 0x0 0x2000>; + is_auge_used = <1>; /* meson or auge chipset used */ + tdmout_index = <1>; + status = "okay"; + }; + audio_effect:eqdrc{ + /*eq_enable = <1>;*/ + /*drc_enable = <1>;*/ + /* + * 0:tdmout_a + * 1:tdmout_b + * 2:tdmout_c + * 3:spdifout + * 4:spdifout_b + */ + eqdrc_module = <1>; + /* max 0xf, each bit for one lane, usually one lane */ + lane_mask = <0x1>; + /* max 0xff, each bit for one channel */ + channel_mask = <0x3>; + }; + auge_sound { + compatible = "amlogic, g12a-sound-card"; + aml-audio-card,name = "AML-AUGESOUND"; + + aml-audio-card,loopback = <&aml_loopback>; + aml-audio-card,aux-devs = <&amlogic_codec>; + /*avout mute gpio*/ + avout_mute-gpios = <&gpio_ao GPIOAO_2 GPIO_ACTIVE_HIGH>; + /*for audio effect ,eqdrc */ + aml-audio-card,effect = <&audio_effect>; + + aml-audio-card,dai-link@0 { + format = "dsp_a"; + mclk-fs = <512>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + //bitclock-master = <&tdmacodec>; + //frame-master = <&tdmacodec>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-pcm"; + tdmacpu: cpu { + sound-dai = <&aml_tdma>; + dai-tdm-slot-tx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-rx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-num = <8>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <24576000>; + }; + tdmacodec: codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@1 { + format = "i2s";// "dsp_a"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + bitclock-master = <&aml_tdmb>; + frame-master = <&aml_tdmb>; + //bitclock-master = <&tdmbcodec>; + //frame-master = <&tdmbcodec>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-i2s"; + cpu { + sound-dai = <&aml_tdmb>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + /* + * dai-tdm-slot-tx-mask = + * <1 1 1 1 1 1 1 1>; + * dai-tdm-slot-rx-mask = + * <1 1 1 1 1 1 1 1>; + * dai-tdm-slot-num = <8>; + */ + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmbcodec: codec { + sound-dai = <&dummy_codec &dummy_codec + &amlogic_codec>; + }; + }; + + aml-audio-card,dai-link@2 { + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + bitclock-master = <&aml_tdmc>; + frame-master = <&aml_tdmc>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + //suffix-name = "alsaPORT-tdm"; + cpu { + sound-dai = <&aml_tdmc>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@3 { + mclk-fs = <64>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-pdm"; + cpu { + sound-dai = <&aml_pdm>; + }; + codec { + sound-dai = <&pdm_codec>; + }; + }; + + aml-audio-card,dai-link@4 { + mclk-fs = <128>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-spdif"; + cpu { + sound-dai = <&aml_spdif>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + /* spdif_b to hdmi, only playback */ + aml-audio-card,dai-link@5 { + mclk-fs = <128>; + continuous-clock; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-spdifb2hdmi"; + cpu { + sound-dai = <&aml_spdif_b>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + }; + audiolocker: locker { + compatible = "amlogic, audiolocker"; + clocks = <&clkaudio CLKID_AUDIO_LOCKER_OUT + &clkaudio CLKID_AUDIO_LOCKER_IN + &clkaudio CLKID_AUDIO_MCLK_D + &clkaudio CLKID_AUDIO_MCLK_E + &clkc CLKID_MPLL1 + &clkc CLKID_MPLL2>; + clock-names = "lock_out", "lock_in", "out_src", + "in_src", "out_calc", "in_ref"; + interrupts = ; + interrupt-names = "irq"; + frequency = <49000000>; /* pll */ + dividor = <49>; /* locker's parent */ + status = "okay"; + }; + /* Audio Related end */ + + /*DCDC for SY8120B1ABC*/ + cpu_opp_table0: cpu_opp_table0 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <731000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <731000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <731000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <731000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <731000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <761000>; + }; + opp06 { + opp-hz = /bits/ 64 <1398000000>; + opp-microvolt = <791000>; + }; + opp07 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <831000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <871000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <921000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <981000>; + }; + }; + + cpufreq-meson { + compatible = "amlogic, cpufreq-meson"; + pinctrl-names = "default"; + pinctrl-0 = <&pwm_ao_d_pins3>; + status = "okay"; + }; + +}; /* end of / */ + +&drm_vpu { + status = "okay"; + logo_addr = "0x7f800000"; +}; + +&drm_amhdmitx { + status = "okay"; + hdcp = "disabled"; +}; + +&drm_lcd { + status = "disable"; +}; +&pwm_AO_cd { + status = "okay"; +}; + +&i2c0 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&i2c0_master_pins2>; + clock-frequency = <400000>; + + gt9xx@5d { + compatible = "goodix,gt9xx"; + status = "disabled"; + reg = <0x5d>; + reset-gpio = <&gpio GPIOZ_9 0x00>; + irq-gpio = <&gpio GPIOZ_3 0x00>; + }; + + ftxx@38 { + compatible = "focaltech,fts"; + status = "disabled"; + reg = <0x38>; + reset-gpio = <&gpio GPIOZ_9 0x00>; + irq-gpio = <&gpio GPIOZ_3 0x00>; + x_max = <600>; + y_max = <1024>; + max-touch-number = <10>; + }; +}; + +&i2c3 { + status = "disabled"; + pinctrl-names="default"; + pinctrl-0=<&i2c3_master_pins2>; + clock-frequency = <100000>; /* default 100k */ + + /* for ref board */ + ad82584f_62: ad82584f_62@62 { + compatible = "ESMT, ad82584f"; + #sound-dai-cells = <0>; + reg = <0x31>; + status = "disabled"; + reset_pin = <&gpio GPIOA_5 0>; + }; + + tas5707_36: tas5707_36@36 { + compatible = "ti,tas5707"; + #sound-dai-cells = <0>; + reg = <0x1b>; + status = "disabled"; + reset_pin = <&gpio GPIOA_5 0>; + }; + + bl_extern_i2c { + compatible = "amlogic, bl_extern_i2c"; + status = "disabled"; + reg = <0x2c>; /*reg_address for lp8556*/ + dev_name = "lp8556"; + }; +}; + +&audiobus { + aml_tdma: tdma { + compatible = "amlogic, g12a-snd-tdma"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 1>; + dai-tdm-oe-lane-slot-mask-out = <1 0>; + dai-tdm-clk-sel = <0>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_A + &clkc CLKID_MPLL0>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmout_a &tdmin_a>; + }; + + aml_tdmb: tdmb { + compatible = "amlogic, g12a-snd-tdmb"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 1 0 0>; + dai-tdm-lane-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <1>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_B + &clkc CLKID_MPLL1 + &clkc CLKID_MPLL0>; + clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; + /* + * 0: tdmout_a; + * 1: tdmout_b; + * 2: tdmout_c; + * 3: spdifout; + * 4: spdifout_b; + */ + samesource_sel = <3>; + }; + + aml_tdmc: tdmc { + compatible = "amlogic, g12a-snd-tdmc"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 1 0 0>; + #dai-tdm-lane-slot-mask-out = <1 0 1 1>; + #dai-tdm-lane-oe-slot-mask-in = <0 0 0 0>; + dai-tdm-lane-oe-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <2>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmc_mclk &tdmout_c &tdmin_c>; + }; + + + aml_spdif: spdif { + compatible = "amlogic, g12a-snd-spdif-a"; + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 + &clkc CLKID_FCLK_DIV4 + &clkaudio CLKID_AUDIO_SPDIFIN + &clkaudio CLKID_AUDIO_SPDIFOUT + &clkaudio CLKID_AUDIO_SPDIFIN_CTRL + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "sysclk", "fixed_clk", "gate_spdifin", + "gate_spdifout", "clk_spdifin", "clk_spdifout"; + interrupts = + ; + + interrupt-names = "irq_spdifin"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; + pinctrl-0 = <&spdifout>; + pinctrl-1 = <&spdifout_a_mute>; + status = "okay"; + }; + aml_spdif_b: spdif_b { + compatible = "amlogic, g12a-snd-spdif-b"; + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 /*CLKID_HIFI_PLL*/ + &clkaudio CLKID_AUDIO_SPDIFOUTB + &clkaudio CLKID_AUDIO_SPDIFOUTB_CTRL>; + clock-names = "sysclk", + "gate_spdifout", "clk_spdifout"; + status = "okay"; + }; + aml_pdm: pdm { + compatible = "amlogic, g12a-snd-pdm"; + #sound-dai-cells = <0>; + clocks = <&clkaudio CLKID_AUDIO_PDM + &clkc CLKID_FCLK_DIV3 + &clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_PDMIN0 + &clkaudio CLKID_AUDIO_PDMIN1>; + clock-names = "gate", + "sysclk_srcpll", + "dclk_srcpll", + "pdm_dclk", + "pdm_sysclk"; + pinctrl-names = "pdm_pins"; + pinctrl-0 = <&pdmin>; + filter_mode = <1>; /* mode 0~4, defalut:1 */ + status = "okay"; + }; + aml_loopback: loopback { + compatible = "amlogic, snd-loopback"; + /* + * 0: out rate = in data rate; + * 1: out rate = loopback data rate; + */ + lb_mode = <0>; + + /* datain src + * 0: tdmin_a; + * 1: tdmin_b; + * 2: tdmin_c; + * 3: spdifin; + * 4: pdmin; + */ + datain_src = <4>; + datain_chnum = <8>; + datain_chmask = <0x3f>; + + /* tdmin_lb src + * 0: tdmoutA + * 1: tdmoutB + * 2: tdmoutC + * 3: PAD_tdminA + * 4: PAD_tdminB + * 5: PAD_tdminC + */ + datalb_src = <2>; + datalb_chnum = <8>; + datalb_chmask = <0x3>; + + status = "okay"; + }; + + audioresample: resample { + compatible = "amlogic, g12a-resample"; + clocks = <&clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_MCLK_F + &clkaudio CLKID_AUDIO_RESAMPLE_CTRL>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + /*same with toddr_src + * TDMIN_A, 0 + * TDMIN_B, 1 + * TDMIN_C, 2 + * SPDIFIN, 3 + * PDMIN, 4 + * NONE, + * TDMIN_LB, 6 + * LOOPBACK, 7 + */ + resample_module = <4>; + status = "okay"; + }; + aml_pwrdet: pwrdet { + compatible = "amlogic, g12a-power-detect"; + + interrupts = ; + interrupt-names = "pwrdet_irq"; + + /* pwrdet source sel + * 7: loopback; + * 6: tdmin_lb; + * 5: reserved; + * 4: pdmin; + * 3: spdifin; + * 2: tdmin_c; + * 1: tdmin_b; + * 0: tdmin_a; + */ + pwrdet_src = <4>; + + hi_th = <0x70000>; + lo_th = <0x16000>; + + status = "okay"; + }; +}; /* end of audiobus */ + +&pinctrl_periphs { + tdmout_a: tdmout_a { + mux { /* GPIOX_11, GPIOX_10, GPIOX_9 */ + groups = "tdma_sclk", + "tdma_fs", + "tdma_dout0"; + function = "tdma_out"; + }; + }; + + tdmin_a: tdmin_a { + mux { /* GPIOX_8 */ + groups = "tdma_din1"; + function = "tdma_in"; + }; + }; + + tdmb_mclk: tdmb_mclk { + mux { + groups = "mclk0_a"; + function = "mclk0"; + drive-strength = <2>; + }; + }; + tdmout_b: tdmout_b { + mux { /* GPIOA_1, GPIOA_2, GPIOA_3 */ + groups = "tdmb_sclk", + "tdmb_fs", + "tdmb_dout0"; + function = "tdmb_out"; + drive-strength = <2>; + }; + }; + + tdmin_b:tdmin_b { + mux { /* GPIOA_4 */ + groups = "tdmb_din1" + /*,"tdmb_slv_sclk", "tdmb_slv_fs"*/; + function = "tdmb_in"; + drive-strength = <2>; + }; + }; + + tdmc_mclk: tdmc_mclk { + mux { /* GPIOA_11 */ + groups = "mclk1_a"; + function = "mclk1"; + }; + }; + + tdmout_c:tdmout_c { + mux { /* GPIOA_12, GPIOA_13, GPIOA_10, GPIOA_8, GPIOA_7*/ + groups = "tdmc_sclk_a", + "tdmc_fs_a", + "tdmc_dout0_a" + /*, "tdmc_dout2", + * "tdmc_dout3" + */; + function = "tdmc_out"; + }; + }; + + tdmin_c:tdmin_c { + mux { /* GPIOA_9 */ + groups = "tdmc_din1_a"; + function = "tdmc_in"; + }; + }; + + spdifin: spdifin { + mux {/* GPIOH_5 */ + groups = "spdif_in_h"; + function = "spdif_in"; + }; + }; + + /* GPIOH_4 */ + spdifout: spdifout { + mux { + groups = "spdif_out_h"; + function = "spdif_out"; + }; + }; + + spdifout_a_mute: spdifout_a_mute { + mux { /* GPIOH_4 */ + groups = "GPIOH_4"; + function = "gpio_periphs"; + }; + }; + + pdmin: pdmin { + mux { /* gpioa_5, gpioa_6, gpioa_7, gpioa_8, gpioa_9*/ + groups = "pdm_din0_a", + /*"pdm_din1_a",*/ + "pdm_din2_a", + /*"pdm_din3_a",*/ + "pdm_dclk_a"; + function = "pdm"; + }; + }; + + +}; /* end of pinctrl_periphs */ +&pinctrl_aobus { + /*gpiao_10*/ + /*spdifout: spdifout { */ + /* mux { */ + /* groups = "spdif_out_ao"; */ + /* function = "spdif_out_ao";*/ + /* }; */ + /*}; */ +}; /* end of pinctrl_aobus */ + +&audio_data { + status = "okay"; +}; + +/* Audio Related End */ + +&pwm_ef { + status = "okay"; +}; + +&dwc3 { + status = "okay"; +}; + +&usb2_phy_v2 { + status = "okay"; + portnum = <2>; +}; + +&usb3_phy_v2 { + status = "okay"; + portnum = <1>; + otg = <0>; +}; + +&dwc2_a { + status = "okay"; + /** 0: normal, 1: otg+dwc3 host only, 2: otg+dwc3 device only*/ + controller-type = <1>; +}; +ðmac { + status = "okay"; + pinctrl-names = "internal_eth_pins"; + pinctrl-0 = <&internal_eth_pins>; + mc_val = <0x4be04>; + + internal_phy=<1>; +}; + +&uart_A { + status = "okay"; +}; + +/*if you want to use vdin just modify status to "ok"*/ +&vdin0 { + memory-region = <&vdin0_cma_reserved>; + status = "okay"; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + *bit4:support yuv422 10bit full pack mode (from txl new add) + */ + tv_bit_mode = <0x15>; +}; +&vdin1 { + memory-region = <&vdin1_cma_reserved>; + status = "okay"; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + */ + tv_bit_mode = <1>; +}; + + +&sd_emmc_c { + status = "okay"; + emmc { + caps = "MMC_CAP_8_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + /* "MMC_CAP_1_8V_DDR", */ + "MMC_CAP_HW_RESET", + "MMC_CAP_ERASE", + "MMC_CAP_CMD23"; + caps2 = "MMC_CAP2_HS200"; + /* "MMC_CAP2_HS400";*/ + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&sd_emmc_b1 { + status = "disabled"; + sd { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED"; + f_min = <400000>; + f_max = <50000000>; + }; +}; + +&sd_emmc_b2 { + status = "disabled"; + sd { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED"; + f_min = <400000>; + f_max = <50000000>; + }; + + sdio { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + "MMC_CAP_UHS_SDR12", + "MMC_CAP_UHS_SDR25", + "MMC_CAP_UHS_SDR50", + "MMC_CAP_UHS_SDR104", + "MMC_PM_KEEP_POWER", + "MMC_CAP_SDIO_IRQ"; + + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&sd_emmc_a { + status = "disabled"; + sdio { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + "MMC_CAP_UHS_SDR12", + "MMC_CAP_UHS_SDR25", + "MMC_CAP_UHS_SDR50", + "MMC_CAP_UHS_SDR104", + "MMC_PM_KEEP_POWER", + "MMC_CAP_SDIO_IRQ"; + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&nand { + status = "disabled"; + plat-names = "bootloader","nandnormal"; + plat-num = <2>; + plat-part-0 = <&bootloader>; + plat-part-1 = <&nandnormal>; + bootloader: bootloader{ + enable_pad ="ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <1>; + part_num = <0>; + rb_detect = <1>; + }; + nandnormal: nandnormal{ + enable_pad ="ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + plane_mode = "twoplane"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <2>; + part_num = <3>; + partition = <&nand_partitions>; + rb_detect = <1>; + }; + nand_partitions:nand_partition{ + /* + * if bl_mode is 1, tpl size was generate by + * fip_copies * fip_size which + * will not skip bad when calculating + * the partition size; + * + * if bl_mode is 0, + * tpl partition must be comment out. + */ + tpl{ + offset=<0x0 0x0>; + size=<0x0 0x0>; + }; + logo{ + offset=<0x0 0x0>; + size=<0x0 0x200000>; + }; + recovery{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + boot{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + system{ + offset=<0x0 0x0>; + size=<0x0 0x4000000>; + }; + data{ + offset=<0xffffffff 0xffffffff>; + size=<0x0 0x0>; + }; + }; +}; + +&pcie_A { + reset-gpio = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; + status = "disable"; +}; + +&meson_cooldev { + status = "okay"; +}; + +&defendkey { + status = "okay"; +}; + diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905y2_u220.dts b/arch/arm64/boot/dts/amlogic/g12a_s905y2_u220.dts index 1af01b2b46d7..738792decd23 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905y2_u220.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905y2_u220.dts @@ -44,7 +44,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x0 0x100000 0x0 0x7ff00000>; + linux,usable-memory = <0x0 0x0 0x0 0x80000000>; }; reserved-memory { @@ -57,8 +57,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { @@ -220,6 +219,14 @@ }; }; + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + codec_mm { compatible = "amlogic, codec, mm"; memory-region = <&codec_mm_cma &codec_mm_reserved>; @@ -227,6 +234,13 @@ status = "okay"; }; + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + ppmgr { compatible = "amlogic, ppmgr"; memory-region = <&ppmgr_reserved>; @@ -823,8 +837,10 @@ dai-tdm-clk-sel = <1>; clocks = <&clkaudio CLKID_AUDIO_MCLK_B &clkc CLKID_MPLL1 - &clkc CLKID_MPLL0>; - clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; /* @@ -882,8 +898,10 @@ ; interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; pinctrl-0 = <&spdifout &spdifin>; + pinctrl-1 = <&spdifout_a_mute>; status = "okay"; }; aml_spdif_b: spdif_b { @@ -1098,6 +1116,13 @@ function = "spdif_out_ao"; }; }; + + spdifout_a_mute: spdifout_a_mute { + mux { /* gpiao_10 */ + groups = "GPIOAO_10"; + function = "gpio_aobus"; + }; + }; }; /* end of pinctrl_aobus */ &audio_data { diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905y2_u221.dts b/arch/arm64/boot/dts/amlogic/g12a_s905y2_u221.dts index cec20dd0bf39..2ae7ce426f05 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905y2_u221.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905y2_u221.dts @@ -210,6 +210,14 @@ }; }; + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + codec_mm { compatible = "amlogic, codec, mm"; memory-region = <&codec_mm_cma &codec_mm_reserved>; @@ -217,6 +225,13 @@ status = "okay"; }; + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + ppmgr { compatible = "amlogic, ppmgr"; memory-region = <&ppmgr_reserved>; @@ -667,18 +682,20 @@ opp-hz = /bits/ 64 <1512000000>; opp-microvolt = <831000>; }; - opp08 { - opp-hz = /bits/ 64 <1608000000>; - opp-microvolt = <871000>; - }; - opp09 { - opp-hz = /bits/ 64 <1704000000>; - opp-microvolt = <921000>; - }; - opp10 { - opp-hz = /bits/ 64 <1800000000>; - opp-microvolt = <981000>; - }; +/* + * opp08 { + * opp-hz = /bits/ 64 <1608000000>; + * opp-microvolt = <871000>; + * }; + * opp09 { + * opp-hz = /bits/ 64 <1704000000>; + * opp-microvolt = <921000>; + * }; + * opp10 { + * opp-hz = /bits/ 64 <1800000000>; + * opp-microvolt = <981000>; + * }; + */ }; cpufreq-meson { @@ -782,8 +799,10 @@ dai-tdm-clk-sel = <1>; clocks = <&clkaudio CLKID_AUDIO_MCLK_B &clkc CLKID_MPLL1 - &clkc CLKID_MPLL0>; - clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; /* @@ -841,8 +860,10 @@ ; interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; pinctrl-0 = <&spdifout &spdifin>; + pinctrl-1 = <&spdifout_a_mute>; status = "okay"; }; aml_spdif_b: spdif_b { @@ -1057,6 +1078,13 @@ function = "spdif_out_ao"; }; }; + + spdifout_a_mute: spdifout_a_mute { + mux { /* gpiao_10 */ + groups = "GPIOAO_10"; + function = "gpio_aobus"; + }; + }; }; /* end of pinctrl_aobus */ &audio_data { @@ -1285,3 +1313,13 @@ status = "okay"; }; +&gpu{ + /*max gpu is 500MHz*/ + tbl = <&dvfs285_cfg + &dvfs400_cfg + &dvfs500_cfg>; +}; + +&amhdmitx { + dongle_mode = <1>; +}; diff --git a/arch/arm64/boot/dts/amlogic/g12b-sched-energy-a.dtsi b/arch/arm64/boot/dts/amlogic/g12b-sched-energy-a.dtsi new file mode 100644 index 000000000000..184be9d06b57 --- /dev/null +++ b/arch/arm64/boot/dts/amlogic/g12b-sched-energy-a.dtsi @@ -0,0 +1,87 @@ + +/ { + energy-costs { + CPU_COST_A73: core-cost0 { + busy-cost-data = < + 54 17 + 135 110 + 270 202 + 360 264 + 540 396 + 648 470 + 755 557 + 816 620 + 868 699 + 920 759 + /*1024 1024*/ + >; + idle-cost-data = < + 5 + 0 + 0 + >; + }; + CPU_COST_A53: core-cost1 { + busy-cost-data = < + 33 4 + 83 23 + 166 41 + 221 54 + 332 78 + 399 92 + 465 116 + 503 135 + 535 162 + 567 184 + 599 224 + 631 279 + >; + idle-cost-data = < + 3 + 0 + 0 + >; + }; + CLUSTER_COST_A73: cluster-cost0 { + busy-cost-data = < + 54 17 + 135 20 + 270 25 + 360 27 + 540 35 + 648 40 + 755 49 + 816 57 + 868 54 + 920 64 + /*1024 79*/ + >; + idle-cost-data = < + 10 + 10 + 0 + >; + }; + CLUSTER_COST_A53: cluster-cost1 { + busy-cost-data = < + 33 7 + 83 8 + 166 9 + 221 10 + 332 13 + 399 15 + 465 19 + 503 23 + 535 26 + 567 31 + 599 36 + 631 42 + >; + idle-cost-data = < + 6 + 6 + 0 + >; + }; + }; +}; diff --git a/arch/arm64/boot/dts/amlogic/g12b-sched-energy.dtsi b/arch/arm64/boot/dts/amlogic/g12b-sched-energy.dtsi index 796f592ae9f7..9177949abde1 100644 --- a/arch/arm64/boot/dts/amlogic/g12b-sched-energy.dtsi +++ b/arch/arm64/boot/dts/amlogic/g12b-sched-energy.dtsi @@ -13,7 +13,11 @@ 816 620 868 699 920 759 - /*1024 1024*/ + 972 819 + 1030 887 + 1088 937 + 1134 976 + 1192 1048 >; idle-cost-data = < 5 @@ -33,6 +37,7 @@ 503 135 535 162 567 184 + 599 224 631 279 >; idle-cost-data = < @@ -53,7 +58,11 @@ 816 57 868 54 920 64 - /*1024 79*/ + 972 75 + 1030 86 + 1088 97 + 1134 108 + 1192 110 >; idle-cost-data = < 10 @@ -73,6 +82,7 @@ 503 23 535 26 567 31 + 599 36 631 42 >; idle-cost-data = < diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311d_odroid_n2.dts b/arch/arm64/boot/dts/amlogic/g12b_a311d_odroid_n2.dts new file mode 100644 index 000000000000..00ad63b35cc1 --- /dev/null +++ b/arch/arm64/boot/dts/amlogic/g12b_a311d_odroid_n2.dts @@ -0,0 +1,5 @@ +#include "meson64_odroidn2.dts" + +/{ + coreelec-dt-id = "g12b_a311d_odroid_n2"; +}; diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311d_skt.dts b/arch/arm64/boot/dts/amlogic/g12b_a311d_skt.dts index fa545c35feed..171aec33996d 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_a311d_skt.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_a311d_skt.dts @@ -23,6 +23,7 @@ / { model = "Amlogic"; + amlogic-dt-id = "g12b_skt_b"; compatible = "amlogic, g12b"; interrupt-parent = <&gic>; #address-cells = <2>; @@ -45,7 +46,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x0 0x100000 0x0 0x7ff00000>; + linux,usable-memory = <0x0 0x0 0x0 0x80000000>; }; reserved-memory { @@ -58,8 +59,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { @@ -154,7 +154,7 @@ galcore_reserved:linux,galcore { compatible = "shared-dma-pool"; reusable; - size = <0x0 0x1000000>; + size = <0x0 0x0>; alignment = <0x0 0x400000>; linux,contiguous-region; }; @@ -483,11 +483,11 @@ }; amlogic_codec:t9015{ #sound-dai-cells = <0>; - /*compatible = "amlogic, aml_codec_T9015";*/ + compatible = "amlogic, aml_codec_T9015"; reg = <0x0 0xFF632000 0x0 0x2000>; is_auge_used = <1>; /* meson or auge chipset used */ tdmout_index = <1>; - status = "disabled"; + status = "okay"; }; audio_effect:eqdrc{ /*eq_enable = <1>;*/ @@ -567,7 +567,7 @@ }; tdmbcodec: codec { sound-dai = <&dummy_codec &dummy_codec - &dummy_codec &ad82584f_62>; + &amlogic_codec &ad82584f_62>; }; }; @@ -665,31 +665,31 @@ }; opp04 { opp-hz = /bits/ 64 <1000000000>; - opp-microvolt = <731000>; + opp-microvolt = <761000>; }; opp05 { opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <731000>; + opp-microvolt = <781000>; }; opp06 { opp-hz = /bits/ 64 <1398000000>; - opp-microvolt = <761000>; + opp-microvolt = <811000>; }; opp07 { opp-hz = /bits/ 64 <1512000000>; - opp-microvolt = <791000>; + opp-microvolt = <861000>; }; opp08 { opp-hz = /bits/ 64 <1608000000>; - opp-microvolt = <831000>; + opp-microvolt = <901000>; }; opp09 { opp-hz = /bits/ 64 <1704000000>; - opp-microvolt = <861000>; + opp-microvolt = <951000>; }; opp10 { opp-hz = /bits/ 64 <1800000000>; - opp-microvolt = <981000>; + opp-microvolt = <1001000>; }; }; @@ -699,43 +699,63 @@ opp00 { opp-hz = /bits/ 64 <100000000>; - opp-microvolt = <751000>; + opp-microvolt = <731000>; }; opp01 { opp-hz = /bits/ 64 <250000000>; - opp-microvolt = <751000>; + opp-microvolt = <731000>; }; opp02 { opp-hz = /bits/ 64 <500000000>; - opp-microvolt = <751000>; + opp-microvolt = <731000>; }; opp03 { opp-hz = /bits/ 64 <667000000>; - opp-microvolt = <751000>; + opp-microvolt = <731000>; }; opp04 { opp-hz = /bits/ 64 <1000000000>; - opp-microvolt = <771000>; + opp-microvolt = <731000>; }; opp05 { opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <771000>; + opp-microvolt = <751000>; }; opp06 { opp-hz = /bits/ 64 <1398000000>; - opp-microvolt = <791000>; + opp-microvolt = <771000>; }; opp07 { opp-hz = /bits/ 64 <1512000000>; - opp-microvolt = <821000>; + opp-microvolt = <771000>; }; opp08 { opp-hz = /bits/ 64 <1608000000>; - opp-microvolt = <861000>; + opp-microvolt = <781000>; }; opp09 { opp-hz = /bits/ 64 <1704000000>; - opp-microvolt = <891000>; + opp-microvolt = <791000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <831000>; + }; + opp11 { + opp-hz = /bits/ 64 <1908000000>; + opp-microvolt = <861000>; + }; + opp12 { + opp-hz = /bits/ 64 <2016000000>; + opp-microvolt = <911000>; + }; + opp13 { + opp-hz = /bits/ 64 <2100000000>; + opp-microvolt = <951000>; + }; + opp14 { + opp-hz = /bits/ 64 <2208000000>; + opp-microvolt = <1011000>; }; }; @@ -747,7 +767,7 @@ sensor: sensor { compatible = "soc, sensor"; status = "okay"; - sensor-name = "imx290"; /*imx290;os08a10;imx227*/ + sensor-name = "imx290"; /*imx290;os08a10;imx227;imx307*/ pinctrl-names="default"; pinctrl-0=<&clk12_24_z_pins>; clocks = <&clkc CLKID_24M>; @@ -760,7 +780,7 @@ iq: iq { compatible = "soc, iq"; status = "okay"; - sensor-name = "imx290"; /*imx290;os08a10;imx227*/ + sensor-name = "imx290"; /*imx290;os08a10;imx227;imx307*/ }; }; /* end of / */ &i2c2 { @@ -893,8 +913,10 @@ dai-tdm-clk-sel = <1>; clocks = <&clkaudio CLKID_AUDIO_MCLK_B &clkc CLKID_MPLL1 - &clkc CLKID_MPLL0>; - clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; /* @@ -904,7 +926,7 @@ * 3: spdifout; * 4: spdifout_b; */ - samesource_sel = <4>; + /* samesource_sel = <4>; */ }; aml_tdmc: tdmc { @@ -952,8 +974,10 @@ ; interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; pinctrl-0 = <&spdifout &spdifin>; + pinctrl-1 = <&spdifout_a_mute>; status = "okay"; }; aml_spdif_b: spdif_b { @@ -1184,6 +1208,13 @@ function = "spdif_out_ao"; }; }; + + spdifout_a_mute: spdifout_a_mute { + mux { /* gpiao_10 */ + groups = "GPIOAO_10"; + function = "gpio_aobus"; + }; + }; }; /* end of pinctrl_aobus */ &irblaster { diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311d_skt_a.dts b/arch/arm64/boot/dts/amlogic/g12b_a311d_skt_a.dts new file mode 100644 index 000000000000..f20a7b708125 --- /dev/null +++ b/arch/arm64/boot/dts/amlogic/g12b_a311d_skt_a.dts @@ -0,0 +1,1397 @@ +/* + * arch/arm64/boot/dts/amlogic/g12b_a311d_skt_a.dts + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +/dts-v1/; + +#include "partition_mbox_normal.dtsi" +#include "mesong12b_a.dtsi" +#include "mesong12b_skt-panel.dtsi" + +/ { + model = "Amlogic"; + amlogic-dt-id = "g12b_skt_a"; + compatible = "amlogic, g12b"; + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + + aliases { + serial0 = &uart_AO; + serial1 = &uart_A; + serial2 = &uart_B; + serial3 = &uart_C; + serial4 = &uart_AO_B; + i2c0 = &i2c0; + i2c1 = &i2c1; + i2c2 = &i2c2; + i2c3 = &i2c3; + i2c4 = &i2c_AO; + tsensor0 = &p_tsensor; + tsensor1 = &d_tsensor; + }; + + memory@00000000 { + device_type = "memory"; + linux,usable-memory = <0x0 0x100000 0x0 0x7ff00000>; + }; + + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + /* global autoconfigured region for contiguous allocations */ + ramoops@0x07400000 { + compatible = "ramoops"; + reg = <0x0 0x07400000 0x0 0x00100000>; + record-size = <0x8000>; + console-size = <0x8000>; + ftrace-size = <0x20000>; + }; + + secmon_reserved:linux,secmon { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x400000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x05000000 0x0 0x400000>; + clear-map; + }; + + secos_reserved:linux,secos { + status = "disable"; + compatible = "amlogic, aml_secos_memory"; + reg = <0x0 0x05300000 0x0 0x2000000>; + no-map; + }; + logo_reserved:linux,meson-fb { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x800000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x7f800000 0x0 0x800000>; + }; + ion_cma_reserved:linux,ion-dev { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x8000000>; + alignment = <0x0 0x400000>; + }; + + //di_reserved:linux,di { + //compatible = "amlogic, di-mem"; + /* buffer_size = 3621952(yuv422 8bit) */ + /* 4179008(yuv422 10bit full pack mode) */ + /** 10x3621952=34.6M(0x23) support 8bit **/ + /** 10x4736064=45.2M(0x2e) support 12bit **/ + /** 10x4179008=40M(0x28) support 10bit **/ + //size = <0x0 0x2800000>; + //no-map; + //}; + /*di CMA pool */ + di_cma_reserved:linux,di_cma { + compatible = "shared-dma-pool"; + reusable; + /* buffer_size = 3621952(yuv422 8bit) + * | 4736064(yuv422 10bit) + * | 4074560(yuv422 10bit full pack mode) + * 10x3621952=34.6M(0x23) support 8bit + * 10x4736064=45.2M(0x2e) support 12bit + * 10x4074560=40M(0x28) support 10bit + */ + size = <0x0 0x02800000>; + alignment = <0x0 0x400000>; + }; + /* POST PROCESS MANAGER */ + ppmgr_reserved:linux,ppmgr { + compatible = "shared-dma-pool"; + size = <0x0 0x0>; + }; + codec_mm_cma:linux,codec_mm_cma { + compatible = "shared-dma-pool"; + reusable; + /* ion_codec_mm max can alloc size 80M*/ + size = <0x0 0x13400000>; + alignment = <0x0 0x400000>; + linux,contiguous-region; + }; + /* codec shared reserved */ + codec_mm_reserved:linux,codec_mm_reserved { + compatible = "amlogic, codec-mm-reserved"; + size = <0x0 0x0>; + alignment = <0x0 0x100000>; + //no-map; + }; + /* vdin0 CMA pool */ + vdin0_cma_reserved:linux,vdin0_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16+4 M */ + size = <0x0 0x04000000>; + alignment = <0x0 0x400000>; + }; + /* vdin1 CMA pool */ + vdin1_cma_reserved:linux,vdin1_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16 M */ + size = <0x0 0x04000000>; + alignment = <0x0 0x400000>; + }; + galcore_reserved:linux,galcore { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x0>; + alignment = <0x0 0x400000>; + linux,contiguous-region; + }; + + isp_cma_reserved:linux,isp_cma { + compatible = "shared-dma-pool"; + reusable; + status = "okay"; + size = <0x0 0x10000000>; + alignment = <0x0 0x400000>; + }; + + adapt_cma_reserved:linux,adapt_cma { + compatible = "shared-dma-pool"; + reusable; + status = "okay"; + size = <0x0 0x03000000>; + alignment = <0x0 0x400000>; + }; + gdc_cma_reserved:linux,gdc_cma { + compatible = "shared-dma-pool"; + reusable; + status = "okay"; + size = <0x0 0x04000000>; + alignment = <0x0 0x400000>; + }; + }; + galcore { + status = "okay"; + memory-region = <&galcore_reserved>; + }; + cvbsout { + compatible = "amlogic, cvbsout-g12b"; + dev_name = "cvbsout"; + status = "okay"; + clocks = <&clkc CLKID_VCLK2_ENCI + &clkc CLKID_VCLK2_VENCI0 + &clkc CLKID_VCLK2_VENCI1 + &clkc CLKID_DAC_CLK>; + clock-names = "venci_top_gate", + "venci_0_gate", + "venci_1_gate", + "vdac_clk_gate"; + clk_path = <0>; + + /* performance: reg_address, reg_value */ + /* g12b */ + performance = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x8080 + 0x1b05 0xfd + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + performance_sarft = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x0 + 0x1b05 0x9 + 0x1c59 0xfc48 + 0xffff 0x0>; /* ending flag */ + }; + + bt-dev{ + compatible = "amlogic, bt-dev"; + dev_name = "bt-dev"; + status = "okay"; + gpio_reset = <&gpio GPIOX_17 GPIO_ACTIVE_HIGH>; + gpio_hostwake = <&gpio GPIOX_19 GPIO_ACTIVE_HIGH>; + }; + + wifi{ + compatible = "amlogic, aml_wifi"; + dev_name = "aml_wifi"; + status = "okay"; + interrupt_pin = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; + irq_trigger_type = "GPIO_IRQ_LOW"; + power_on_pin = <&gpio GPIOX_6 GPIO_ACTIVE_HIGH>; + dhd_static_buf; //if use bcm wifi, config dhd_static_buf + pinctrl-names = "default"; + pinctrl-0 = <&pwm_e_pins>; + pwm_config = <&wifi_pwm_conf>; + }; + + wifi_pwm_conf:wifi_pwm_conf{ + pwm_channel1_conf { + pwms = <&pwm_ef MESON_PWM_0 30541 0>; + duty-cycle = <15270>; + times = <10>; + }; + pwm_channel2_conf { + pwms = <&pwm_ef MESON_PWM_2 30500 0>; + duty-cycle = <15250>; + times = <12>; + }; + }; + + codec_mm { + compatible = "amlogic, codec, mm"; + memory-region = <&codec_mm_cma &codec_mm_reserved>; + dev_name = "codec_mm"; + status = "okay"; + }; + + ppmgr { + compatible = "amlogic, ppmgr"; + memory-region = <&ppmgr_reserved>; + dev_name = "ppmgr"; + status = "okay"; + }; + + deinterlace { + compatible = "amlogic, deinterlace"; + status = "okay"; + /* 0:use reserved; 1:use cma; 2:use cma as reserved */ + flag_cma = <1>; + //memory-region = <&di_reserved>; + memory-region = <&di_cma_reserved>; + interrupts = <0 46 1 + 0 40 1>; + interrupt-names = "pre_irq", "post_irq"; + clocks = <&clkc CLKID_VPU_CLKB_TMP_COMP>, + <&clkc CLKID_VPU_CLKB_COMP>; + clock-names = "vpu_clkb_tmp_composite", + "vpu_clkb_composite"; + clock-range = <334 667>; + /* buffer-size = <3621952>;(yuv422 8bit) */ + buffer-size = <4074560>;/*yuv422 fullpack*/ + /* reserve-iomap = "true"; */ + /* if enable nr10bit, set nr10bit-support to 1 */ + post-wr-support = <1>; + nr10bit-support = <1>; + nrds-enable = <1>; + pps-enable = <1>; + }; + ionvideo { + compatible = "amlogic, ionvideo"; + dev_name = "ionvideo"; + status = "okay"; + }; + + gpio_keypad { + compatible = "amlogic, gpio_keypad"; + status = "okay"; + scan_period = <20>; + key_num = <1>; + key_name = "power"; + key_code = <116>; + key-gpios = <&gpio_ao GPIOAO_3 GPIO_ACTIVE_HIGH>; + detect_mode = <0>;/*0:polling mode, 1:irq mode*/ + }; + + adc_keypad { + compatible = "amlogic, adc_keypad"; + status = "okay"; + key_name = "menu", "vol-", "vol+", "esc", "home"; + key_num = <5>; + io-channels = <&saradc SARADC_CH2>; + io-channel-names = "key-chan-2"; + key_chan = ; + key_code = <139 114 115 1 102>; + key_val = <0 143 266 389 512>; //val=voltage/1800mV*1023 + key_tolerance = <40 40 40 40 40>; + }; + + unifykey{ + compatible = "amlogic, unifykey"; + status = "ok"; + unifykey-num = <16>; + unifykey-index-0 = <&keysn_0>; + unifykey-index-1 = <&keysn_1>; + unifykey-index-2 = <&keysn_2>; + unifykey-index-3 = <&keysn_3>; + unifykey-index-4 = <&keysn_4>; + unifykey-index-5 = <&keysn_5>; + unifykey-index-6 = <&keysn_6>; + unifykey-index-7 = <&keysn_7>; + unifykey-index-8 = <&keysn_8>; + unifykey-index-9 = <&keysn_9>; + unifykey-index-10= <&keysn_10>; + unifykey-index-11= <&keysn_11>; + unifykey-index-12= <&keysn_12>; + unifykey-index-13= <&keysn_13>; + unifykey-index-14= <&keysn_14>; + unifykey-index-15= <&keysn_15>; + + + keysn_0: key_0{ + key-name = "usid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_1:key_1{ + key-name = "mac"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_2:key_2{ + key-name = "hdcp"; + key-device = "secure"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_3:key_3{ + key-name = "secure_boot_set"; + key-device = "efuse"; + key-permit = "write"; + }; + keysn_4:key_4{ + key-name = "mac_bt"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_5:key_5{ + key-name = "mac_wifi"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_6:key_6{ + key-name = "hdcp2_tx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_7:key_7{ + key-name = "hdcp2_rx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_8:key_8{ + key-name = "widevinekeybox"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_9:key_9{ + key-name = "deviceid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_10:key_10{ + key-name = "hdcp22_fw_private"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_11:key_11{ + key-name = "PlayReadykeybox25"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_12:key_12{ + key-name = "prpubkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_13:key_13{ + key-name = "prprivkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_14:key_14{ + key-name = "attestationkeybox";// attestation key + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_15:key_15{ + key-name = "netflix_mgkid"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + };//End unifykey + + efusekey:efusekey{ + keynum = <4>; + key0 = <&key_0>; + key1 = <&key_1>; + key2 = <&key_2>; + key3 = <&key_3>; + key_0:key_0{ + keyname = "mac"; + offset = <0>; + size = <6>; + }; + key_1:key_1{ + keyname = "mac_bt"; + offset = <6>; + size = <6>; + }; + key_2:key_2{ + keyname = "mac_wifi"; + offset = <12>; + size = <6>; + }; + key_3:key_3{ + keyname = "usid"; + offset = <18>; + size = <16>; + }; + };//End efusekey + + + amlvecm { + compatible = "amlogic, vecm"; + dev_name = "aml_vecm"; + status = "okay"; + gamma_en = <0>;/*1:enabel ;0:disable*/ + wb_en = <0>;/*1:enabel ;0:disable*/ + cm_en = <0>;/*1:enabel ;0:disable*/ + }; + amdolby_vision { + compatible = "amlogic, dolby_vision_g12a"; + dev_name = "aml_amdolby_vision_driver"; + status = "okay"; + tv_mode = <0>;/*1:enabel ;0:disable*/ + }; + + /* Audio Related start */ + pdm_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, pdm_dummy_codec"; + status = "okay"; + }; + dummy_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, aml_dummy_codec"; + status = "okay"; + }; + amlogic_codec:t9015{ + #sound-dai-cells = <0>; + /*compatible = "amlogic, aml_codec_T9015";*/ + reg = <0x0 0xFF632000 0x0 0x2000>; + is_auge_used = <1>; /* meson or auge chipset used */ + tdmout_index = <1>; + status = "disabled"; + }; + audio_effect:eqdrc{ + /*eq_enable = <1>;*/ + /*drc_enable = <1>;*/ + /* + * 0:tdmout_a + * 1:tdmout_b + * 2:tdmout_c + * 3:spdifout + * 4:spdifout_b + */ + eqdrc_module = <1>; + /* max 0xf, each bit for one lane, usually one lane */ + lane_mask = <0x1>; + /* max 0xff, each bit for one channel */ + channel_mask = <0x3>; + }; + auge_sound { + compatible = "amlogic, g12a-sound-card"; + aml-audio-card,name = "AML-AUGESOUND"; + + //aml-audio-card,loopback = <&aml_loopback>; + //aml-audio-card,aux-devs = <&amlogic_codec>; + /*avout mute gpio*/ + avout_mute-gpios = <&gpio_ao GPIOAO_2 GPIO_ACTIVE_HIGH>; + /*for audio effect ,eqdrc */ + aml-audio-card,effect = <&audio_effect>; + + aml-audio-card,dai-link@0 { + format = "dsp_a"; + mclk-fs = <512>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + //bitclock-master = <&tdmacodec>; + //frame-master = <&tdmacodec>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-pcm"; + tdmacpu: cpu { + sound-dai = <&aml_tdma>; + dai-tdm-slot-tx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-rx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-num = <8>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <24576000>; + }; + tdmacodec: codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@1 { + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + bitclock-master = <&aml_tdmb>; + frame-master = <&aml_tdmb>; + //bitclock-master = <&tdmbcodec>; + //frame-master = <&tdmbcodec>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-i2s"; + cpu { + sound-dai = <&aml_tdmb>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmbcodec: codec { + sound-dai = <&dummy_codec &dummy_codec + &dummy_codec &ad82584f_62>; + }; + }; + + aml-audio-card,dai-link@2 { + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + bitclock-master = <&aml_tdmc>; + frame-master = <&aml_tdmc>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + //suffix-name = "alsaPORT-tdm"; + cpu { + sound-dai = <&aml_tdmc>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@3 { + mclk-fs = <64>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-pdm"; + cpu { + sound-dai = <&aml_pdm>; + }; + codec { + sound-dai = <&pdm_codec>; + }; + }; + + aml-audio-card,dai-link@4 { + mclk-fs = <128>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-spdif"; + cpu { + sound-dai = <&aml_spdif>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + }; + audiolocker: locker { + compatible = "amlogic, audiolocker"; + clocks = <&clkaudio CLKID_AUDIO_LOCKER_OUT + &clkaudio CLKID_AUDIO_LOCKER_IN + &clkaudio CLKID_AUDIO_MCLK_D + &clkaudio CLKID_AUDIO_MCLK_E + &clkc CLKID_MPLL1 + &clkc CLKID_MPLL2>; + clock-names = "lock_out", "lock_in", "out_src", + "in_src", "out_calc", "in_ref"; + interrupts = ; + interrupt-names = "irq"; + frequency = <49000000>; /* pll */ + dividor = <49>; /* locker's parent */ + status = "okay"; + }; + /* Audio Related end */ + + cpu_opp_table0: cpu_opp_table0 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <731000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <731000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <731000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <731000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <731000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <731000>; + }; + opp06 { + opp-hz = /bits/ 64 <1398000000>; + opp-microvolt = <761000>; + }; + opp07 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <791000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <831000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <861000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <981000>; + }; + }; + + cpu_opp_table1: cpu_opp_table1 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <751000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <751000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <751000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <751000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <771000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <771000>; + }; + opp06 { + opp-hz = /bits/ 64 <1398000000>; + opp-microvolt = <791000>; + }; + opp07 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <821000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <861000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <891000>; + }; + }; + + cpufreq-meson { + compatible = "amlogic, cpufreq-meson"; + status = "okay"; + }; + + sensor: sensor { + compatible = "soc, sensor"; + status = "okay"; + sensor-name = "imx290"; /*imx290;os08a10;imx227;imx307*/ + pinctrl-names="default"; + pinctrl-0=<&clk12_24_z_pins>; + clocks = <&clkc CLKID_24M>; + clock-names = "g12a_24m"; + reset = <&gpio GPIOZ_12 GPIO_ACTIVE_HIGH>; + ir_cut_gpio = <&gpio GPIOZ_11 GPIO_ACTIVE_HIGH + &gpio GPIOZ_7 GPIO_ACTIVE_HIGH>; + }; + + iq: iq { + compatible = "soc, iq"; + status = "okay"; + sensor-name = "imx290"; /*imx290;os08a10;imx227;imx307*/ + }; +}; /* end of / */ +&i2c2 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&i2c2_master_pins2>; + clock-frequency = <100000>; /* default 100k */ + sensor-i2c@6c { + compatible = "arm, i2c-sensor"; + reg = <0x6c>; + reg-names = "i2c-sensor"; + slave-addr = <0x6c>; + reg-type = <2>; + reg-data-type = <1>; + link-device = <&phycsi>; + }; + + lcd_extern_i2c0: lcd_extern_i2c@0 { + compatible = "lcd_ext, i2c"; + dev_name = "i2c_LT8912_0"; + reg = <0x48>; + status = "disabled"; + }; + + lcd_extern_i2c1: lcd_extern_i2c@1 { + compatible = "lcd_ext, i2c"; + dev_name = "i2c_LT8912_1"; + reg = <0x49>; + status = "disabled"; + }; +}; + +&isp { + status = "okay"; + memory-region = <&isp_cma_reserved>; +}; + +&adapter { + status = "okay"; + memory-region = <&adapt_cma_reserved>; +}; + +&gdc { + status = "okay"; + memory-region = <&gdc_cma_reserved>; +}; + +&meson_fb { + status = "okay"; + display_size_default = <1920 1080 1920 2160 32>; + mem_size = <0x00800000 0x1980000 0x100000 0x100000 0x800000>; + logo_addr = "0x7f800000"; + mem_alloc = <1>; + pxp_mode = <0>; /** 0:normal mode 1:pxp mode */ +}; + +&pwm_ab { + status = "okay"; + }; + +&pwm_ef { + status = "okay"; + }; + +&pwm_AO_cd { + status = "okay"; + }; + +&i2c0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_master_pins2>; + clock-frequency = <400000>; + + touchscreen@38 { + compatible = "focaltech,fts"; + status = "disabled"; + reg = <0x38>; + reset-gpio = <&gpio GPIOZ_9 GPIO_ACTIVE_HIGH>; + irq-gpio = <&gpio GPIOZ_3 GPIO_ACTIVE_HIGH>; + x_max = <720>; + y_max = <1280>; + max-touch-number = <10>; + }; +}; + +&i2c3 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&i2c3_master_pins2>; + clock-frequency = <100000>; /* default 100k */ + + /* for ref board */ + ad82584f_62: ad82584f_62@62 { + compatible = "ESMT, ad82584f"; + #sound-dai-cells = <0>; + reg = <0x31>; + status = "okay"; + reset_pin = <&gpio GPIOA_5 0>; + }; + + tlv320adc3101_32: tlv320adc3101_32@32 { + compatible = "ti,tlv320adc3101"; + #sound-dai-cells = <0>; + reg = <0x19>; + differential_pair = <1>; + status = "disabled"; + }; +}; + +&audiobus { + aml_tdma: tdma { + compatible = "amlogic, g12a-snd-tdma"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 1>; + dai-tdm-oe-lane-slot-mask-out = <1 0>; + dai-tdm-clk-sel = <0>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_A + &clkc CLKID_MPLL0>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmout_a &tdmin_a>; + }; + + aml_tdmb: tdmb { + compatible = "amlogic, g12a-snd-tdmb"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 1 0 0>; + dai-tdm-lane-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <1>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_B + &clkc CLKID_MPLL1 + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; + /* + * 0: tdmout_a; + * 1: tdmout_b; + * 2: tdmout_c; + * 3: spdifout; + * 4: spdifout_b; + */ + samesource_sel = <4>; + }; + + aml_tdmc: tdmc { + compatible = "amlogic, g12a-snd-tdmc"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <1 0 0 0>; + #dai-tdm-lane-slot-mask-out = <1 0 1 1>; + #dai-tdm-lane-oe-slot-mask-in = <0 0 0 0>; + #dai-tdm-lane-oe-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <2>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmc_mclk &tdmout_c &tdmin_c>; + }; + + /* copy a useless tdm to output for hdmi, no pinmux */ + aml_i2s2hdmi: i2s2hdmi { + compatible = "amlogic, g12a-snd-tdmc"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-out = <1 1 1 1>; + dai-tdm-clk-sel = <2>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + + i2s2hdmi = <1>; + + status = "okay"; + }; + + aml_spdif: spdif { + compatible = "amlogic, g12a-snd-spdif-a"; + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 + &clkc CLKID_FCLK_DIV4 + &clkaudio CLKID_AUDIO_SPDIFIN + &clkaudio CLKID_AUDIO_SPDIFOUT + &clkaudio CLKID_AUDIO_SPDIFIN_CTRL + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "sysclk", "fixed_clk", "gate_spdifin", + "gate_spdifout", "clk_spdifin", "clk_spdifout"; + interrupts = + ; + + interrupt-names = "irq_spdifin"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; + pinctrl-0 = <&spdifout &spdifin>; + pinctrl-1 = <&spdifout_a_mute>; + status = "okay"; + }; + aml_spdif_b: spdif_b { + compatible = "amlogic, g12a-snd-spdif-b"; + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 /*CLKID_HIFI_PLL*/ + &clkaudio CLKID_AUDIO_SPDIFOUTB + &clkaudio CLKID_AUDIO_SPDIFOUTB_CTRL>; + clock-names = "sysclk", + "gate_spdifout", "clk_spdifout"; + status = "disabled"; + }; + aml_pdm: pdm { + compatible = "amlogic, g12a-snd-pdm"; + #sound-dai-cells = <0>; + clocks = <&clkaudio CLKID_AUDIO_PDM + &clkc CLKID_FCLK_DIV3 + &clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_PDMIN0 + &clkaudio CLKID_AUDIO_PDMIN1>; + clock-names = "gate", + "sysclk_srcpll", + "dclk_srcpll", + "pdm_dclk", + "pdm_sysclk"; + pinctrl-names = "pdm_pins"; + pinctrl-0 = <&pdmin>; + filter_mode = <1>; /* mode 0~4, defalut:1 */ + status = "okay"; + }; + aml_loopback: loopback { + compatible = "amlogic, snd-loopback"; + /* + * 0: out rate = in data rate; + * 1: out rate = loopback data rate; + */ + lb_mode = <0>; + + /* datain src + * 0: tdmin_a; + * 1: tdmin_b; + * 2: tdmin_c; + * 3: spdifin; + * 4: pdmin; + */ + datain_src = <4>; + datain_chnum = <8>; + datain_chmask = <0x3f>; + + /* tdmin_lb src + * 0: tdmoutA + * 1: tdmoutB + * 2: tdmoutC + * 3: PAD_tdminA + * 4: PAD_tdminB + * 5: PAD_tdminC + */ + datalb_src = <2>; + datalb_chnum = <8>; + datalb_chmask = <0x3>; + + status = "disabled"; + }; + + audioresample: resample { + compatible = "amlogic, g12a-resample"; + clocks = <&clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_MCLK_F + &clkaudio CLKID_AUDIO_RESAMPLE_CTRL>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + /*same with toddr_src + * TDMIN_A, 0 + * TDMIN_B, 1 + * TDMIN_C, 2 + * SPDIFIN, 3 + * PDMIN, 4 + * NONE, + * TDMIN_LB, 6 + * LOOPBACK, 7 + */ + resample_module = <4>; + status = "disabled"; + }; + aml_pwrdet: pwrdet { + compatible = "amlogic, g12a-power-detect"; + + interrupts = ; + interrupt-names = "pwrdet_irq"; + + /* pwrdet source sel + * 7: loopback; + * 6: tdmin_lb; + * 5: reserved; + * 4: pdmin; + * 3: spdifin; + * 2: tdmin_c; + * 1: tdmin_b; + * 0: tdmin_a; + */ + pwrdet_src = <4>; + + hi_th = <0x70000>; + lo_th = <0x16000>; + + status = "disabled"; + }; +}; /* end of audiobus */ + +&pinctrl_periphs { + tdmout_a: tdmout_a { + mux { /* GPIOX_11, GPIOX_10, GPIOX_9 */ + groups = "tdma_sclk", + "tdma_fs", + "tdma_dout0"; + function = "tdma_out"; + }; + }; + + tdmin_a: tdmin_a { + mux { /* GPIOX_8 */ + groups = "tdma_din1"; + function = "tdma_in"; + }; + }; + + tdmb_mclk: tdmb_mclk { + mux { + groups = "mclk0_a"; + function = "mclk0"; + drive-strength = <2>; + }; + }; + tdmout_b: tdmout_b { + mux { /* GPIOA_1, GPIOA_2, GPIOA_3 */ + groups = "tdmb_sclk", + "tdmb_fs", + "tdmb_dout0"; + function = "tdmb_out"; + drive-strength = <2>; + }; + }; + + tdmin_b:tdmin_b { + mux { /* GPIOA_4 */ + groups = "tdmb_din1" + /*,"tdmb_slv_sclk", "tdmb_slv_fs"*/; + function = "tdmb_in"; + drive-strength = <2>; + }; + }; + + tdmc_mclk: tdmc_mclk { + mux { /* GPIOA_11 */ + groups = "mclk1_a"; + function = "mclk1"; + }; + }; + + clk12_24_z_pins:clk12_24_z_pins { + mux { + groups = "clk12_24_z"; + function = "clk12_24_ee"; + drive-strength = <3>; + }; + }; + + tdmout_c:tdmout_c { + mux { /* GPIOA_12, GPIOA_13, GPIOA_8, GPIOA_7*/ + groups = "tdmc_sclk_a", + "tdmc_fs_a", + "tdmc_dout0_a" + /*, "tdmc_dout2", + * "tdmc_dout3" + */; + function = "tdmc_out"; + }; + }; + + tdmin_c:tdmin_c { + mux { /* GPIOA_10 */ + groups = "tdmc_din0_a"; + function = "tdmc_in"; + }; + }; + + spdifin: spdifin { + mux {/* GPIOH_5 */ + groups = "spdif_in_h"; + function = "spdif_in"; + }; + }; + + /* GPIOH_4 */ + /* + * spdifout: spdifout { + * mux { + * groups = "spdif_out_h"; + * function = "spdif_out"; + * }; + *}; + */ + + pdmin: pdmin { + mux { /* gpioa_5, gpioa_6, gpioa_7, gpioa_8, gpioa_9*/ + groups = "pdm_din0_a", + /*"pdm_din1_a",*/ + "pdm_din2_a", + /*"pdm_din3_a",*/ + "pdm_dclk_a"; + function = "pdm"; + }; + }; + + bl_pwm_off_pins:bl_pwm_off_pin { + mux { + pins = "GPIOH_5"; + function = "gpio_periphs"; + output-high; + }; + }; + +}; /* end of pinctrl_periphs */ + +&pinctrl_aobus { + spdifout: spdifout { + mux { /* gpiao_10 */ + groups = "spdif_out_ao"; + function = "spdif_out_ao"; + }; + }; + + spdifout_a_mute: spdifout_a_mute { + mux { /* gpiao_10 */ + groups = "GPIOAO_10"; + function = "gpio_aobus"; + }; + }; +}; /* end of pinctrl_aobus */ + +&irblaster { + status = "disabled"; +}; + +&audio_data { + status = "okay"; +}; + +/*if you want to use vdin just modify status to "ok"*/ +&vdin0 { + memory-region = <&vdin0_cma_reserved>; + status = "okay"; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + *bit4:support yuv422 10bit full pack mode (from txl new add) + */ + tv_bit_mode = <0x15>; +}; +&vdin1 { + memory-region = <&vdin1_cma_reserved>; + status = "okay"; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + */ + tv_bit_mode = <1>; +}; + +&sd_emmc_c { + status = "okay"; + emmc { + caps = "MMC_CAP_8_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + /* "MMC_CAP_1_8V_DDR", */ + "MMC_CAP_HW_RESET", + "MMC_CAP_ERASE", + "MMC_CAP_CMD23"; + caps2 = "MMC_CAP2_HS200"; + /* "MMC_CAP2_HS400";*/ + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&sd_emmc_b { + status = "okay"; + sd { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED"; + f_min = <400000>; + f_max = <50000000>; + }; +}; + +&sd_emmc_a { + status = "okay"; + sdio { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + "MMC_CAP_UHS_SDR12", + "MMC_CAP_UHS_SDR25", + "MMC_CAP_UHS_SDR50", + "MMC_CAP_UHS_SDR104", + "MMC_PM_KEEP_POWER", + "MMC_CAP_SDIO_IRQ"; + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&nand { + status = "disabled"; + plat-names = "bootloader","nandnormal"; + plat-num = <2>; + plat-part-0 = <&bootloader>; + plat-part-1 = <&nandnormal>; + bootloader: bootloader{ + enable_pad ="ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <1>; + part_num = <0>; + rb_detect = <1>; + }; + nandnormal: nandnormal{ + enable_pad ="ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + plane_mode = "twoplane"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <2>; + part_num = <3>; + partition = <&nand_partitions>; + rb_detect = <1>; + }; + nand_partitions:nand_partition{ + /* + * if bl_mode is 1, tpl size was generate by + * fip_copies * fip_size which + * will not skip bad when calculating + * the partition size; + * + * if bl_mode is 0, + * tpl partition must be comment out. + */ + tpl{ + offset=<0x0 0x0>; + size=<0x0 0x0>; + }; + logo{ + offset=<0x0 0x0>; + size=<0x0 0x200000>; + }; + recovery{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + boot{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + system{ + offset=<0x0 0x0>; + size=<0x0 0x4000000>; + }; + data{ + offset=<0xffffffff 0xffffffff>; + size=<0x0 0x0>; + }; + }; +}; +&dwc3 { + status = "okay"; +}; + +&usb2_phy_v2 { + status = "okay"; + portnum = <2>; +}; + +&usb3_phy_v2 { + status = "okay"; + portnum = <0>; + otg = <1>; + gpio-vbus-power = "GPIOH_6"; + gpios = <&gpio GPIOH_6 GPIO_ACTIVE_HIGH>; +}; + +&dwc2_a { + status = "okay"; + /** 0: normal, 1: otg+dwc3 host only, 2: otg+dwc3 device only*/ + controller-type = <3>; +}; +ðmac { + status = "okay"; +/* //conflict with isp i2c + * pinctrl-names = "internal_eth_pins"; + * pinctrl-0 = <&internal_eth_pins>; + */ + mc_val = <0x4be04>; + + internal_phy=<1>; +}; + +&uart_A { + status = "okay"; +}; + +&pcie_A { + reset-gpio = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; + status = "disabled"; +}; + +&saradc { + status = "okay"; +}; + +&spicc1 { + status = "disabled"; + pinctrl-names = "default"; + pinctrl-0 = <&spicc1_pins>; + cs-gpios = <&gpio GPIOH_6 0>; +}; diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400.dts b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400.dts index 30a09e5013bf..377595fcbffe 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400.dts @@ -23,6 +23,7 @@ / { model = "Amlogic"; + amlogic-dt-id = "g12b_w400_b"; compatible = "amlogic, g12b"; interrupt-parent = <&gic>; #address-cells = <2>; @@ -58,8 +59,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { @@ -147,6 +147,17 @@ size = <0x0 0x04000000>; alignment = <0x0 0x400000>; }; + galcore_reserved:linux,galcore { + compatible = "shared-dma-pool"; + reusable; + size = <0x1000000>; + alignment = <0x400000>; + linux,contiguous-region; + }; + }; + galcore { + status = "okay"; + memory-region = <&galcore_reserved>; }; gpioleds { @@ -228,6 +239,14 @@ }; }; + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + codec_mm { compatible = "amlogic, codec, mm"; memory-region = <&codec_mm_cma &codec_mm_reserved>; @@ -235,6 +254,13 @@ status = "okay"; }; + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + deinterlace { compatible = "amlogic, deinterlace"; status = "okay"; @@ -633,31 +659,31 @@ }; opp04 { opp-hz = /bits/ 64 <1000000000>; - opp-microvolt = <731000>; + opp-microvolt = <761000>; }; opp05 { opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <731000>; + opp-microvolt = <781000>; }; opp06 { opp-hz = /bits/ 64 <1398000000>; - opp-microvolt = <761000>; + opp-microvolt = <811000>; }; opp07 { opp-hz = /bits/ 64 <1512000000>; - opp-microvolt = <791000>; + opp-microvolt = <861000>; }; opp08 { opp-hz = /bits/ 64 <1608000000>; - opp-microvolt = <831000>; + opp-microvolt = <901000>; }; opp09 { opp-hz = /bits/ 64 <1704000000>; - opp-microvolt = <861000>; + opp-microvolt = <951000>; }; opp10 { opp-hz = /bits/ 64 <1800000000>; - opp-microvolt = <981000>; + opp-microvolt = <1001000>; }; }; @@ -667,43 +693,63 @@ opp00 { opp-hz = /bits/ 64 <100000000>; - opp-microvolt = <751000>; + opp-microvolt = <731000>; }; opp01 { opp-hz = /bits/ 64 <250000000>; - opp-microvolt = <751000>; + opp-microvolt = <731000>; }; opp02 { opp-hz = /bits/ 64 <500000000>; - opp-microvolt = <751000>; + opp-microvolt = <731000>; }; opp03 { opp-hz = /bits/ 64 <667000000>; - opp-microvolt = <751000>; + opp-microvolt = <731000>; }; opp04 { opp-hz = /bits/ 64 <1000000000>; - opp-microvolt = <771000>; + opp-microvolt = <731000>; }; opp05 { opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <771000>; + opp-microvolt = <751000>; }; opp06 { opp-hz = /bits/ 64 <1398000000>; - opp-microvolt = <791000>; + opp-microvolt = <771000>; }; opp07 { opp-hz = /bits/ 64 <1512000000>; - opp-microvolt = <821000>; + opp-microvolt = <771000>; }; opp08 { opp-hz = /bits/ 64 <1608000000>; - opp-microvolt = <861000>; + opp-microvolt = <781000>; }; opp09 { opp-hz = /bits/ 64 <1704000000>; - opp-microvolt = <891000>; + opp-microvolt = <791000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <831000>; + }; + opp11 { + opp-hz = /bits/ 64 <1908000000>; + opp-microvolt = <861000>; + }; + opp12 { + opp-hz = /bits/ 64 <2016000000>; + opp-microvolt = <911000>; + }; + opp13 { + opp-hz = /bits/ 64 <2100000000>; + opp-microvolt = <951000>; + }; + opp14 { + opp-hz = /bits/ 64 <2208000000>; + opp-microvolt = <1011000>; }; }; @@ -833,8 +879,10 @@ dai-tdm-clk-sel = <1>; clocks = <&clkaudio CLKID_AUDIO_MCLK_B &clkc CLKID_MPLL1 - &clkc CLKID_MPLL0>; - clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; /* @@ -892,8 +940,10 @@ ; interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; pinctrl-0 = <&spdifout &spdifin>; + pinctrl-1 = <&spdifout_a_mute>; status = "okay"; }; aml_spdif_b: spdif_b { @@ -1116,6 +1166,13 @@ function = "spdif_out_ao"; }; }; + + spdifout_a_mute: spdifout_a_mute { + mux { /* gpiao_10 */ + groups = "GPIOAO_10"; + function = "gpio_aobus"; + }; + }; }; /* end of pinctrl_aobus */ &irblaster { @@ -1161,9 +1218,9 @@ /* "MMC_CAP_1_8V_DDR", */ "MMC_CAP_HW_RESET", "MMC_CAP_ERASE", - "MMC_CAP_CMD23"; - caps2 = "MMC_CAP2_HS200"; - /* "MMC_CAP2_HS400";*/ + "MMC_CAP_CMD23", + "MMC_CAP_DRIVER_TYPE_A"; + caps2 = "MMC_CAP2_HS200", "MMC_CAP2_HS400"; f_min = <400000>; f_max = <200000000>; }; @@ -1275,7 +1332,7 @@ &usb3_phy_v2 { status = "okay"; - portnum = <0>; + portnum = <1>; otg = <1>; gpio-vbus-power = "GPIOH_6"; gpios = <&gpio GPIOH_6 GPIO_ACTIVE_HIGH>; @@ -1301,7 +1358,7 @@ &pcie_A { reset-gpio = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; - status = "okay"; + status = "disable"; }; &saradc { diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_a.dts b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_a.dts new file mode 100644 index 000000000000..7f1418567299 --- /dev/null +++ b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_a.dts @@ -0,0 +1,1347 @@ +/* + * arch/arm64/boot/dts/amlogic/g12b_a311d_w400_a.dts + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +/dts-v1/; + +#include "partition_mbox_normal.dtsi" +#include "mesong12b_a.dtsi" +#include "mesong12b_skt-panel.dtsi" + +/ { + model = "Amlogic"; + amlogic-dt-id = "g12b_w400_a"; + compatible = "amlogic, g12b"; + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + + aliases { + serial0 = &uart_AO; + serial1 = &uart_A; + serial2 = &uart_B; + serial3 = &uart_C; + serial4 = &uart_AO_B; + i2c0 = &i2c0; + i2c1 = &i2c1; + i2c2 = &i2c2; + i2c3 = &i2c3; + i2c4 = &i2c_AO; + tsensor0 = &p_tsensor; + tsensor1 = &d_tsensor; + }; + + memory@00000000 { + device_type = "memory"; + linux,usable-memory = <0x0 0x000000 0x0 0x80000000>; + }; + + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + /* global autoconfigured region for contiguous allocations */ + ramoops@0x07400000 { + compatible = "ramoops"; + reg = <0x0 0x07400000 0x0 0x00100000>; + record-size = <0x8000>; + console-size = <0x8000>; + ftrace-size = <0x20000>; + }; + + secmon_reserved:linux,secmon { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x400000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x05000000 0x0 0x400000>; + clear-map; + }; + + secos_reserved:linux,secos { + status = "disable"; + compatible = "amlogic, aml_secos_memory"; + reg = <0x0 0x05300000 0x0 0x2000000>; + no-map; + }; + logo_reserved:linux,meson-fb { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x800000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x7f800000 0x0 0x800000>; + }; + ion_cma_reserved:linux,ion-dev { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x8000000>; + alignment = <0x0 0x400000>; + }; + + //di_reserved:linux,di { + //compatible = "amlogic, di-mem"; + /* buffer_size = 3621952(yuv422 8bit) */ + /* 4179008(yuv422 10bit full pack mode) */ + /** 10x3621952=34.6M(0x23) support 8bit **/ + /** 10x4736064=45.2M(0x2e) support 12bit **/ + /** 10x4179008=40M(0x28) support 10bit **/ + //size = <0x0 0x2800000>; + //no-map; + //}; + /*di CMA pool */ + di_cma_reserved:linux,di_cma { + compatible = "shared-dma-pool"; + reusable; + /* buffer_size = 3621952(yuv422 8bit) + * | 4736064(yuv422 10bit) + * | 4074560(yuv422 10bit full pack mode) + * 10x3621952=34.6M(0x23) support 8bit + * 10x4736064=45.2M(0x2e) support 12bit + * 10x4074560=40M(0x28) support 10bit + */ + size = <0x0 0x02800000>; + alignment = <0x0 0x400000>; + }; + codec_mm_cma:linux,codec_mm_cma { + compatible = "shared-dma-pool"; + reusable; + /* ion_codec_mm max can alloc size 80M*/ + size = <0x0 0x13400000>; + alignment = <0x0 0x400000>; + linux,contiguous-region; + clear-map; + }; + /* codec shared reserved */ + codec_mm_reserved:linux,codec_mm_reserved { + compatible = "amlogic, codec-mm-reserved"; + size = <0x0 0x0>; + alignment = <0x0 0x100000>; + //no-map; + }; + /* vdin0 CMA pool */ + vdin0_cma_reserved:linux,vdin0_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16+4 M */ + size = <0x0 0x04000000>; + alignment = <0x0 0x400000>; + }; + /* vdin1 CMA pool */ + vdin1_cma_reserved:linux,vdin1_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16 M */ + size = <0x0 0x04000000>; + alignment = <0x0 0x400000>; + }; + galcore_reserved:linux,galcore { + compatible = "shared-dma-pool"; + reusable; + size = <0x1000000>; + alignment = <0x400000>; + linux,contiguous-region; + }; + }; + galcore { + status = "okay"; + memory-region = <&galcore_reserved>; + }; + + gpioleds { + compatible = "gpio-leds"; + status = "okay"; + sys_led { + label="sys_led"; + gpios=<&gpio_ao GPIOAO_11 GPIO_ACTIVE_HIGH>; + default-state ="on"; + }; + }; + + cvbsout { + compatible = "amlogic, cvbsout-g12b"; + dev_name = "cvbsout"; + status = "okay"; + clocks = <&clkc CLKID_VCLK2_ENCI + &clkc CLKID_VCLK2_VENCI0 + &clkc CLKID_VCLK2_VENCI1 + &clkc CLKID_DAC_CLK>; + clock-names = "venci_top_gate", + "venci_0_gate", + "venci_1_gate", + "vdac_clk_gate"; + /* clk path */ + /* 0:vid_pll vid2_clk */ + /* 1:gp0_pll vid2_clk */ + /* 2:vid_pll vid1_clk */ + /* 3:gp0_pll vid1_clk */ + clk_path = <0>; + + /* performance: reg_address, reg_value */ + /* g12b */ + performance = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x8080 + 0x1b05 0xfd + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + performance_sarft = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x0 + 0x1b05 0x9 + 0x1c59 0xfc48 + 0xffff 0x0>; /* ending flag */ + }; + + bt-dev{ + compatible = "amlogic, bt-dev"; + dev_name = "bt-dev"; + status = "okay"; + gpio_reset = <&gpio GPIOX_17 GPIO_ACTIVE_HIGH>; + gpio_hostwake = <&gpio GPIOX_19 GPIO_ACTIVE_HIGH>; + }; + + wifi{ + compatible = "amlogic, aml_wifi"; + dev_name = "aml_wifi"; + status = "okay"; + interrupt_pin = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; + irq_trigger_type = "GPIO_IRQ_LOW"; + power_on_pin = <&gpio GPIOX_6 GPIO_ACTIVE_HIGH>; + dhd_static_buf; //if use bcm wifi, config dhd_static_buf + pinctrl-names = "default"; + pinctrl-0 = <&pwm_e_pins>; + pwm_config = <&wifi_pwm_conf>; + }; + + wifi_pwm_conf:wifi_pwm_conf{ + pwm_channel1_conf { + pwms = <&pwm_ef MESON_PWM_0 30541 0>; + duty-cycle = <15270>; + times = <10>; + }; + pwm_channel2_conf { + pwms = <&pwm_ef MESON_PWM_2 30500 0>; + duty-cycle = <15250>; + times = <12>; + }; + }; + + codec_mm { + compatible = "amlogic, codec, mm"; + memory-region = <&codec_mm_cma &codec_mm_reserved>; + dev_name = "codec_mm"; + status = "okay"; + }; + + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + + deinterlace { + compatible = "amlogic, deinterlace"; + status = "okay"; + /* 0:use reserved; 1:use cma; 2:use cma as reserved */ + flag_cma = <1>; + //memory-region = <&di_reserved>; + memory-region = <&di_cma_reserved>; + interrupts = <0 46 1 + 0 40 1>; + interrupt-names = "pre_irq", "post_irq"; + clocks = <&clkc CLKID_VPU_CLKB_TMP_COMP>, + <&clkc CLKID_VPU_CLKB_COMP>; + clock-names = "vpu_clkb_tmp_composite", + "vpu_clkb_composite"; + clock-range = <334 667>; + /* buffer-size = <3621952>;(yuv422 8bit) */ + buffer-size = <4074560>;/*yuv422 fullpack*/ + /* reserve-iomap = "true"; */ + /* if enable nr10bit, set nr10bit-support to 1 */ + post-wr-support = <1>; + nr10bit-support = <1>; + nrds-enable = <1>; + pps-enable = <1>; + }; + ionvideo { + compatible = "amlogic, ionvideo"; + dev_name = "ionvideo"; + status = "okay"; + }; + + gpio_keypad { + compatible = "amlogic, gpio_keypad"; + status = "okay"; + scan_period = <20>; + key_num = <1>; + key_name = "power"; + key_code = <116>; + key-gpios = <&gpio_ao GPIOAO_3 GPIO_ACTIVE_HIGH>; + detect_mode = <0>;/*0:polling mode, 1:irq mode*/ + }; + + adc_keypad { + compatible = "amlogic, adc_keypad"; + status = "okay"; + key_name = "vol-", "vol+", "enter"; + key_num = <3>; + io-channels = <&saradc SARADC_CH2>; + io-channel-names = "key-chan-2"; + key_chan = ; + key_code = <114 115 28>; + key_val = <143 266 389>; //val=voltage/1800mV*1023 + key_tolerance = <40 40 40>; + }; + + unifykey{ + compatible = "amlogic, unifykey"; + status = "ok"; + unifykey-num = <16>; + unifykey-index-0 = <&keysn_0>; + unifykey-index-1 = <&keysn_1>; + unifykey-index-2 = <&keysn_2>; + unifykey-index-3 = <&keysn_3>; + unifykey-index-4 = <&keysn_4>; + unifykey-index-5 = <&keysn_5>; + unifykey-index-6 = <&keysn_6>; + unifykey-index-7 = <&keysn_7>; + unifykey-index-8 = <&keysn_8>; + unifykey-index-9 = <&keysn_9>; + unifykey-index-10= <&keysn_10>; + unifykey-index-11= <&keysn_11>; + unifykey-index-12= <&keysn_12>; + unifykey-index-13= <&keysn_13>; + unifykey-index-14= <&keysn_14>; + unifykey-index-15= <&keysn_15>; + + keysn_0: key_0{ + key-name = "usid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_1:key_1{ + key-name = "mac"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_2:key_2{ + key-name = "hdcp"; + key-device = "secure"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_3:key_3{ + key-name = "secure_boot_set"; + key-device = "efuse"; + key-permit = "write"; + }; + keysn_4:key_4{ + key-name = "mac_bt"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_5:key_5{ + key-name = "mac_wifi"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_6:key_6{ + key-name = "hdcp2_tx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_7:key_7{ + key-name = "hdcp2_rx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_8:key_8{ + key-name = "widevinekeybox"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_9:key_9{ + key-name = "deviceid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_10:key_10{ + key-name = "hdcp22_fw_private"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_11:key_11{ + key-name = "PlayReadykeybox25"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_12:key_12{ + key-name = "prpubkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_13:key_13{ + key-name = "prprivkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_14:key_14{ + key-name = "attestationkeybox";// attestation key + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_15:key_15{ + key-name = "netflix_mgkid"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + };//End unifykey + + efusekey:efusekey{ + keynum = <4>; + key0 = <&key_0>; + key1 = <&key_1>; + key2 = <&key_2>; + key3 = <&key_3>; + key_0:key_0{ + keyname = "mac"; + offset = <0>; + size = <6>; + }; + key_1:key_1{ + keyname = "mac_bt"; + offset = <6>; + size = <6>; + }; + key_2:key_2{ + keyname = "mac_wifi"; + offset = <12>; + size = <6>; + }; + key_3:key_3{ + keyname = "usid"; + offset = <18>; + size = <16>; + }; + };//End efusekey + + amlvecm { + compatible = "amlogic, vecm"; + dev_name = "aml_vecm"; + status = "okay"; + gamma_en = <0>;/*1:enabel ;0:disable*/ + wb_en = <0>;/*1:enabel ;0:disable*/ + cm_en = <0>;/*1:enabel ;0:disable*/ + }; + amdolby_vision { + compatible = "amlogic, dolby_vision_g12a"; + dev_name = "aml_amdolby_vision_driver"; + status = "okay"; + tv_mode = <0>;/*1:enabel ;0:disable*/ + }; + + /* Audio Related start */ + pdm_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, pdm_dummy_codec"; + status = "okay"; + }; + dummy_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, aml_dummy_codec"; + status = "okay"; + }; + amlogic_codec:t9015{ + #sound-dai-cells = <0>; + compatible = "amlogic, aml_codec_T9015"; + reg = <0x0 0xFF632000 0x0 0x2000>; + is_auge_used = <1>; /* meson or auge chipset used */ + tdmout_index = <1>; + status = "okay"; + }; + audio_effect:eqdrc{ + /*eq_enable = <1>;*/ + /*drc_enable = <1>;*/ + /* + * 0:tdmout_a + * 1:tdmout_b + * 2:tdmout_c + * 3:spdifout + * 4:spdifout_b + */ + eqdrc_module = <1>; + /* max 0xf, each bit for one lane, usually one lane */ + lane_mask = <0x1>; + /* max 0xff, each bit for one channel */ + channel_mask = <0x3>; + }; + auge_sound { + compatible = "amlogic, g12a-sound-card"; + aml-audio-card,name = "AML-AUGESOUND"; + + //aml-audio-card,loopback = <&aml_loopback>; + //aml-audio-card,aux-devs = <&amlogic_codec>; + /*avout mute gpio*/ + avout_mute-gpios = <&gpio_ao GPIOAO_2 GPIO_ACTIVE_HIGH>; + /*for audio effect ,eqdrc */ + aml-audio-card,effect = <&audio_effect>; + + aml-audio-card,dai-link@0 { + format = "dsp_a"; + mclk-fs = <512>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + //bitclock-master = <&tdmacodec>; + //frame-master = <&tdmacodec>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-pcm"; + tdmacpu: cpu { + sound-dai = <&aml_tdma>; + dai-tdm-slot-tx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-rx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-num = <8>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <24576000>; + }; + tdmacodec: codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@1 { + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + bitclock-master = <&aml_tdmb>; + frame-master = <&aml_tdmb>; + //bitclock-master = <&tdmbcodec>; + //frame-master = <&tdmbcodec>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-i2s"; + cpu { + sound-dai = <&aml_tdmb>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmbcodec: codec { + sound-dai = <&dummy_codec &dummy_codec + &amlogic_codec &ad82584f_62>; + }; + }; + + aml-audio-card,dai-link@2 { + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + bitclock-master = <&aml_tdmc>; + frame-master = <&aml_tdmc>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + //suffix-name = "alsaPORT-tdm"; + cpu { + sound-dai = <&aml_tdmc>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@3 { + mclk-fs = <64>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-pdm"; + cpu { + sound-dai = <&aml_pdm>; + }; + codec { + sound-dai = <&pdm_codec>; + }; + }; + + aml-audio-card,dai-link@4 { + mclk-fs = <128>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-spdif"; + cpu { + sound-dai = <&aml_spdif>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + }; + audiolocker: locker { + compatible = "amlogic, audiolocker"; + clocks = <&clkaudio CLKID_AUDIO_LOCKER_OUT + &clkaudio CLKID_AUDIO_LOCKER_IN + &clkaudio CLKID_AUDIO_MCLK_D + &clkaudio CLKID_AUDIO_MCLK_E + &clkc CLKID_MPLL1 + &clkc CLKID_MPLL2>; + clock-names = "lock_out", "lock_in", "out_src", + "in_src", "out_calc", "in_ref"; + interrupts = ; + interrupt-names = "irq"; + frequency = <49000000>; /* pll */ + dividor = <49>; /* locker's parent */ + status = "okay"; + }; + /* Audio Related end */ + + cpu_opp_table0: cpu_opp_table0 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <731000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <731000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <731000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <731000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <731000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <731000>; + }; + opp06 { + opp-hz = /bits/ 64 <1398000000>; + opp-microvolt = <761000>; + }; + opp07 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <791000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <831000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <861000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <981000>; + }; + }; + + cpu_opp_table1: cpu_opp_table1 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <751000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <751000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <751000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <751000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <771000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <771000>; + }; + opp06 { + opp-hz = /bits/ 64 <1398000000>; + opp-microvolt = <791000>; + }; + opp07 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <821000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <861000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <891000>; + }; + }; + + cpufreq-meson { + compatible = "amlogic, cpufreq-meson"; + status = "okay"; + }; + + +}; /* end of / */ + +&meson_fb { + status = "okay"; + display_size_default = <1920 1080 1920 2160 32>; + mem_size = <0x00800000 0x1980000 0x100000 0x100000 0x800000>; + logo_addr = "0x7f800000"; + mem_alloc = <0>; + pxp_mode = <0>; /** 0:normal mode 1:pxp mode */ +}; + +&pwm_ab { + status = "okay"; + }; + +&pwm_ef { + status = "okay"; + }; + +&pwm_AO_cd { + status = "okay"; + }; + +&i2c0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_master_pins2>; + clock-frequency = <400000>; + + touchscreen@5d { + compatible = "goodix,gt9xx"; + status = "disabled"; + reg = <0x5d>; + reset-gpio = <&gpio GPIOZ_9 GPIO_ACTIVE_HIGH>; + irq-gpio = <&gpio GPIOZ_3 GPIO_ACTIVE_HIGH>; + goodix,cfg-group0 = [ + 41 00 04 58 02 05 0C 00 02 54 07 + 0F 50 2D 03 05 00 00 00 00 40 00 + 04 20 10 F3 AA 07 28 0A 2C 2E 7C + 06 00 00 00 C9 03 24 00 01 00 00 + 00 00 FF 5D 66 98 32 28 64 94 C5 + 02 08 00 00 01 91 2C 00 8A 34 00 + 8A 3F 00 7E 4C 00 78 5B 00 78 00 + 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 + 00 00 02 04 06 08 0A 0C 0E 10 12 + 14 FF FF FF FF 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 + 02 04 06 08 0A 0C 1D 1E 1F 20 21 + 22 24 26 FF FF FF FF FF FF FF FF + FF FF FF 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 E3 01]; + }; + + touchscreen@38 { + compatible = "focaltech,fts"; + status = "disabled"; + reg = <0x38>; + reset-gpio = <&gpio GPIOZ_9 GPIO_ACTIVE_HIGH>; + irq-gpio = <&gpio GPIOZ_3 GPIO_ACTIVE_HIGH>; + x_max = <720>; + y_max = <1280>; + max-touch-number = <10>; + }; +}; + +&i2c3 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&i2c3_master_pins2>; + clock-frequency = <100000>; /* default 100k */ + + /* for ref board */ + ad82584f_62: ad82584f_62@62 { + compatible = "ESMT, ad82584f"; + #sound-dai-cells = <0>; + reg = <0x31>; + status = "okay"; + reset_pin = <&gpio GPIOA_5 0>; + }; + + tlv320adc3101_32: tlv320adc3101_32@32 { + compatible = "ti,tlv320adc3101"; + #sound-dai-cells = <0>; + reg = <0x19>; + differential_pair = <1>; + status = "disabled"; + }; + + bl_extern_i2c { + compatible = "bl_extern, i2c"; + dev_name = "lp8556"; + reg = <0x2c>; + status = "disabled"; + }; +}; + +&audiobus { + aml_tdma: tdma { + compatible = "amlogic, g12a-snd-tdma"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 1>; + dai-tdm-oe-lane-slot-mask-out = <1 0>; + dai-tdm-clk-sel = <0>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_A + &clkc CLKID_MPLL0>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmout_a &tdmin_a>; + }; + + aml_tdmb: tdmb { + compatible = "amlogic, g12a-snd-tdmb"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 1 0 0>; + dai-tdm-lane-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <1>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_B + &clkc CLKID_MPLL1 + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; + /* + * 0: tdmout_a; + * 1: tdmout_b; + * 2: tdmout_c; + * 3: spdifout; + * 4: spdifout_b; + */ + samesource_sel = <3>; + }; + + aml_tdmc: tdmc { + compatible = "amlogic, g12a-snd-tdmc"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <1 0 0 0>; + #dai-tdm-lane-slot-mask-out = <1 0 1 1>; + #dai-tdm-lane-oe-slot-mask-in = <0 0 0 0>; + #dai-tdm-lane-oe-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <2>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmc_mclk &tdmout_c &tdmin_c>; + }; + + /* copy a useless tdm to output for hdmi, no pinmux */ + aml_i2s2hdmi: i2s2hdmi { + compatible = "amlogic, g12a-snd-tdmc"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-out = <1 1 1 1>; + dai-tdm-clk-sel = <2>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + + i2s2hdmi = <1>; + + status = "okay"; + }; + + aml_spdif: spdif { + compatible = "amlogic, g12a-snd-spdif-a"; + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 + &clkc CLKID_FCLK_DIV4 + &clkaudio CLKID_AUDIO_SPDIFIN + &clkaudio CLKID_AUDIO_SPDIFOUT + &clkaudio CLKID_AUDIO_SPDIFIN_CTRL + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "sysclk", "fixed_clk", "gate_spdifin", + "gate_spdifout", "clk_spdifin", "clk_spdifout"; + interrupts = + ; + + interrupt-names = "irq_spdifin"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; + pinctrl-0 = <&spdifout &spdifin>; + pinctrl-1 = <&spdifout_a_mute>; + status = "okay"; + }; + aml_spdif_b: spdif_b { + compatible = "amlogic, g12a-snd-spdif-b"; + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 /*CLKID_HIFI_PLL*/ + &clkaudio CLKID_AUDIO_SPDIFOUTB + &clkaudio CLKID_AUDIO_SPDIFOUTB_CTRL>; + clock-names = "sysclk", + "gate_spdifout", "clk_spdifout"; + status = "disabled"; + }; + aml_pdm: pdm { + compatible = "amlogic, g12a-snd-pdm"; + #sound-dai-cells = <0>; + clocks = <&clkaudio CLKID_AUDIO_PDM + &clkc CLKID_FCLK_DIV3 + &clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_PDMIN0 + &clkaudio CLKID_AUDIO_PDMIN1>; + clock-names = "gate", + "sysclk_srcpll", + "dclk_srcpll", + "pdm_dclk", + "pdm_sysclk"; + pinctrl-names = "pdm_pins"; + pinctrl-0 = <&pdmin>; + filter_mode = <1>; /* mode 0~4, defalut:1 */ + status = "okay"; + }; + aml_loopback: loopback { + compatible = "amlogic, snd-loopback"; + /* + * 0: out rate = in data rate; + * 1: out rate = loopback data rate; + */ + lb_mode = <0>; + + /* datain src + * 0: tdmin_a; + * 1: tdmin_b; + * 2: tdmin_c; + * 3: spdifin; + * 4: pdmin; + */ + datain_src = <4>; + datain_chnum = <8>; + datain_chmask = <0x3f>; + + /* tdmin_lb src + * 0: tdmoutA + * 1: tdmoutB + * 2: tdmoutC + * 3: PAD_tdminA + * 4: PAD_tdminB + * 5: PAD_tdminC + */ + datalb_src = <2>; + datalb_chnum = <8>; + datalb_chmask = <0x3>; + + status = "disabled"; + }; + + audioresample: resample { + compatible = "amlogic, g12a-resample"; + clocks = <&clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_MCLK_F + &clkaudio CLKID_AUDIO_RESAMPLE_CTRL>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + /*same with toddr_src + * TDMIN_A, 0 + * TDMIN_B, 1 + * TDMIN_C, 2 + * SPDIFIN, 3 + * PDMIN, 4 + * NONE, + * TDMIN_LB, 6 + * LOOPBACK, 7 + */ + resample_module = <4>; + status = "disabled"; + }; + aml_pwrdet: pwrdet { + compatible = "amlogic, g12a-power-detect"; + + interrupts = ; + interrupt-names = "pwrdet_irq"; + + /* pwrdet source sel + * 7: loopback; + * 6: tdmin_lb; + * 5: reserved; + * 4: pdmin; + * 3: spdifin; + * 2: tdmin_c; + * 1: tdmin_b; + * 0: tdmin_a; + */ + pwrdet_src = <4>; + + hi_th = <0x70000>; + lo_th = <0x16000>; + + status = "disabled"; + }; +}; /* end of audiobus */ + +&pinctrl_periphs { + tdmout_a: tdmout_a { + mux { /* GPIOX_11, GPIOX_10, GPIOX_9 */ + groups = "tdma_sclk", + "tdma_fs", + "tdma_dout0"; + function = "tdma_out"; + }; + }; + + tdmin_a: tdmin_a { + mux { /* GPIOX_8 */ + groups = "tdma_din1"; + function = "tdma_in"; + }; + }; + + tdmb_mclk: tdmb_mclk { + mux { + groups = "mclk0_a"; + function = "mclk0"; + drive-strength = <2>; + }; + }; + tdmout_b: tdmout_b { + mux { /* GPIOA_1, GPIOA_2, GPIOA_3 */ + groups = "tdmb_sclk", + "tdmb_fs", + "tdmb_dout0"; + function = "tdmb_out"; + drive-strength = <2>; + }; + }; + + tdmin_b:tdmin_b { + mux { /* GPIOA_4 */ + groups = "tdmb_din1" + /*,"tdmb_slv_sclk", "tdmb_slv_fs"*/; + function = "tdmb_in"; + drive-strength = <2>; + }; + }; + + tdmc_mclk: tdmc_mclk { + mux { /* GPIOA_11 */ + groups = "mclk1_a"; + function = "mclk1"; + }; + }; + + tdmout_c:tdmout_c { + mux { /* GPIOA_12, GPIOA_13, GPIOA_8, GPIOA_7*/ + groups = "tdmc_sclk_a", + "tdmc_fs_a", + "tdmc_dout0_a" + /*, "tdmc_dout2", + * "tdmc_dout3" + */; + function = "tdmc_out"; + }; + }; + + tdmin_c:tdmin_c { + mux { /* GPIOA_10 */ + groups = "tdmc_din0_a"; + function = "tdmc_in"; + }; + }; + + spdifin: spdifin { + mux {/* GPIOH_5 */ + groups = "spdif_in_h"; + function = "spdif_in"; + }; + }; + + /* GPIOH_4 */ + /* + * spdifout: spdifout { + * mux { + * groups = "spdif_out_h"; + * function = "spdif_out"; + * }; + *}; + */ + + pdmin: pdmin { + mux { /* gpioa_5, gpioa_6, gpioa_7, gpioa_8, gpioa_9*/ + groups = "pdm_din0_a", + /*"pdm_din1_a",*/ + "pdm_din2_a", + /*"pdm_din3_a",*/ + "pdm_dclk_a"; + function = "pdm"; + }; + }; + + bl_pwm_off_pins:bl_pwm_off_pin { + mux { + pins = "GPIOH_5"; + function = "gpio_periphs"; + output-high; + }; + }; + +}; /* end of pinctrl_periphs */ + +&pinctrl_aobus { + spdifout: spdifout { + mux { /* gpiao_10 */ + groups = "spdif_out_ao"; + function = "spdif_out_ao"; + }; + }; + + spdifout_a_mute: spdifout_a_mute { + mux { /* gpiao_10 */ + groups = "GPIOAO_10"; + function = "gpio_aobus"; + }; + }; +}; /* end of pinctrl_aobus */ + +&irblaster { + status = "disabled"; +}; + +&audio_data { + status = "okay"; +}; + +/*if you want to use vdin just modify status to "ok"*/ +&vdin0 { + memory-region = <&vdin0_cma_reserved>; + status = "okay"; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + *bit4:support yuv422 10bit full pack mode (from txl new add) + */ + tv_bit_mode = <0x15>; +}; +&vdin1 { + memory-region = <&vdin1_cma_reserved>; + status = "okay"; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + */ + tv_bit_mode = <1>; +}; + +&sd_emmc_c { + status = "okay"; + emmc { + caps = "MMC_CAP_8_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + /* "MMC_CAP_1_8V_DDR", */ + "MMC_CAP_HW_RESET", + "MMC_CAP_ERASE", + "MMC_CAP_CMD23"; + caps2 = "MMC_CAP2_HS200"; + /* "MMC_CAP2_HS400";*/ + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&sd_emmc_b { + status = "okay"; + sd { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED"; + f_min = <400000>; + f_max = <50000000>; + }; +}; + +&sd_emmc_a { + status = "okay"; + sdio { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + "MMC_CAP_UHS_SDR12", + "MMC_CAP_UHS_SDR25", + "MMC_CAP_UHS_SDR50", + "MMC_CAP_UHS_SDR104", + "MMC_PM_KEEP_POWER", + "MMC_CAP_SDIO_IRQ"; + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&nand { + status = "disabled"; + plat-names = "bootloader","nandnormal"; + plat-num = <2>; + plat-part-0 = <&bootloader>; + plat-part-1 = <&nandnormal>; + bootloader: bootloader{ + enable_pad ="ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <1>; + part_num = <0>; + rb_detect = <1>; + }; + nandnormal: nandnormal{ + enable_pad ="ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + plane_mode = "twoplane"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <2>; + part_num = <3>; + partition = <&nand_partitions>; + rb_detect = <1>; + }; + nand_partitions:nand_partition{ + /* + * if bl_mode is 1, tpl size was generate by + * fip_copies * fip_size which + * will not skip bad when calculating + * the partition size; + * + * if bl_mode is 0, + * tpl partition must be comment out. + */ + tpl{ + offset=<0x0 0x0>; + size=<0x0 0x0>; + }; + logo{ + offset=<0x0 0x0>; + size=<0x0 0x200000>; + }; + recovery{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + boot{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + system{ + offset=<0x0 0x0>; + size=<0x0 0x4000000>; + }; + data{ + offset=<0xffffffff 0xffffffff>; + size=<0x0 0x0>; + }; + }; +}; +&dwc3 { + status = "okay"; +}; + +&usb2_phy_v2 { + status = "okay"; + portnum = <2>; +}; + +&usb3_phy_v2 { + status = "okay"; + portnum = <1>; + otg = <1>; + gpio-vbus-power = "GPIOH_6"; + gpios = <&gpio GPIOH_6 GPIO_ACTIVE_HIGH>; +}; + +&dwc2_a { + status = "okay"; + /** 0: normal, 1: otg+dwc3 host only, 2: otg+dwc3 device only*/ + controller-type = <3>; +}; +ðmac { + status = "okay"; + pinctrl-names = "internal_eth_pins"; + pinctrl-0 = <&internal_eth_pins>; + mc_val = <0x4be04>; + + internal_phy=<1>; +}; + +&uart_A { + status = "okay"; +}; + +&pcie_A { + reset-gpio = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; + status = "disable"; +}; + +&saradc { + status = "okay"; +}; + diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts index 5d81dd3c4217..2ffeeab99849 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts @@ -22,6 +22,7 @@ / { model = "Amlogic"; + amlogic-dt-id = "g12b_w400_b"; compatible = "amlogic, g12b"; interrupt-parent = <&gic>; #address-cells = <2>; @@ -44,7 +45,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x0 0x100000 0x0 0x7ff00000>; + linux,usable-memory = <0x0 0x0 0x0 0x80000000>; }; reserved-memory { @@ -57,8 +58,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { @@ -153,7 +153,7 @@ galcore_reserved:linux,galcore { compatible = "shared-dma-pool"; reusable; - size = <0x0 0x1000000>; + size = <0x0 0x0>; alignment = <0x0 0x400000>; linux,contiguous-region; }; @@ -162,7 +162,7 @@ compatible = "shared-dma-pool"; reusable; status = "okay"; - size = <0x0 0x1f000000>; + size = <0x0 0x10000000>; alignment = <0x0 0x400000>; }; @@ -193,8 +193,6 @@ label="sys_led"; gpios=<&gpio_ao GPIOAO_11 GPIO_ACTIVE_HIGH>; default-state ="on"; - retain-state-suspended; - linux,default-trigger="cpu0"; }; }; @@ -261,6 +259,14 @@ }; }; + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + codec_mm { compatible = "amlogic, codec, mm"; memory-region = <&codec_mm_cma &codec_mm_reserved>; @@ -275,6 +281,13 @@ status = "okay"; }; + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + deinterlace { compatible = "amlogic, deinterlace"; status = "okay"; @@ -729,31 +742,31 @@ }; opp04 { opp-hz = /bits/ 64 <1000000000>; - opp-microvolt = <731000>; + opp-microvolt = <761000>; }; opp05 { opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <731000>; + opp-microvolt = <781000>; }; opp06 { opp-hz = /bits/ 64 <1398000000>; - opp-microvolt = <761000>; + opp-microvolt = <811000>; }; opp07 { opp-hz = /bits/ 64 <1512000000>; - opp-microvolt = <791000>; + opp-microvolt = <861000>; }; opp08 { opp-hz = /bits/ 64 <1608000000>; - opp-microvolt = <831000>; + opp-microvolt = <901000>; }; opp09 { opp-hz = /bits/ 64 <1704000000>; - opp-microvolt = <861000>; + opp-microvolt = <951000>; }; opp10 { opp-hz = /bits/ 64 <1800000000>; - opp-microvolt = <981000>; + opp-microvolt = <1001000>; }; }; @@ -763,43 +776,63 @@ opp00 { opp-hz = /bits/ 64 <100000000>; - opp-microvolt = <751000>; + opp-microvolt = <731000>; }; opp01 { opp-hz = /bits/ 64 <250000000>; - opp-microvolt = <751000>; + opp-microvolt = <731000>; }; opp02 { opp-hz = /bits/ 64 <500000000>; - opp-microvolt = <751000>; + opp-microvolt = <731000>; }; opp03 { opp-hz = /bits/ 64 <667000000>; - opp-microvolt = <751000>; + opp-microvolt = <731000>; }; opp04 { opp-hz = /bits/ 64 <1000000000>; - opp-microvolt = <771000>; + opp-microvolt = <731000>; }; opp05 { opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <771000>; + opp-microvolt = <751000>; }; opp06 { opp-hz = /bits/ 64 <1398000000>; - opp-microvolt = <791000>; + opp-microvolt = <771000>; }; opp07 { opp-hz = /bits/ 64 <1512000000>; - opp-microvolt = <821000>; + opp-microvolt = <771000>; }; opp08 { opp-hz = /bits/ 64 <1608000000>; - opp-microvolt = <861000>; + opp-microvolt = <781000>; }; opp09 { opp-hz = /bits/ 64 <1704000000>; - opp-microvolt = <891000>; + opp-microvolt = <791000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <831000>; + }; + opp11 { + opp-hz = /bits/ 64 <1908000000>; + opp-microvolt = <861000>; + }; + opp12 { + opp-hz = /bits/ 64 <2016000000>; + opp-microvolt = <911000>; + }; + opp13 { + opp-hz = /bits/ 64 <2100000000>; + opp-microvolt = <951000>; + }; + opp14 { + opp-hz = /bits/ 64 <2208000000>; + opp-microvolt = <1011000>; }; }; @@ -811,18 +844,20 @@ sensor: sensor { compatible = "soc, sensor"; status = "okay"; - sensor-name = "imx290"; /*imx290;os08a10;imx227*/ + sensor-name = "imx290"; /*imx290;os08a10;imx227;imx307*/ pinctrl-names="default"; pinctrl-0=<&clk12_24_z_pins>; clocks = <&clkc CLKID_24M>; clock-names = "g12a_24m"; reset = <&gpio GPIOZ_12 GPIO_ACTIVE_HIGH>; + ir_cut_gpio = <&gpio GPIOZ_11 GPIO_ACTIVE_HIGH + &gpio GPIOZ_7 GPIO_ACTIVE_HIGH>; }; iq: iq { compatible = "soc, iq"; status = "okay"; - sensor-name = "imx290"; /*imx290;os08a10;imx227*/ + sensor-name = "imx290"; /*imx290;os08a10;imx227;imx307*/ }; }; /* end of / */ @@ -949,8 +984,10 @@ dai-tdm-clk-sel = <1>; clocks = <&clkaudio CLKID_AUDIO_MCLK_B &clkc CLKID_MPLL1 - &clkc CLKID_MPLL0>; - clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; /* @@ -1008,8 +1045,10 @@ ; interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; pinctrl-0 = <&spdifout &spdifin>; + pinctrl-1 = <&spdifout_a_mute>; status = "okay"; }; aml_spdif_b: spdif_b { @@ -1240,6 +1279,13 @@ function = "spdif_out_ao"; }; }; + + spdifout_a_mute: spdifout_a_mute { + mux { /* gpiao_10 */ + groups = "GPIOAO_10"; + function = "gpio_aobus"; + }; + }; }; /* end of pinctrl_aobus */ &irblaster { diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot_a.dts b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot_a.dts new file mode 100644 index 000000000000..e86e01060d83 --- /dev/null +++ b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot_a.dts @@ -0,0 +1,1455 @@ +/* + * arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot_a.dts + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +/dts-v1/; + +#include "mesong12b_a.dtsi" +#include "mesong12b_skt-panel.dtsi" + +/ { + model = "Amlogic"; + amlogic-dt-id = "g12b_w400_a"; + compatible = "amlogic, g12b"; + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + + aliases { + serial0 = &uart_AO; + serial1 = &uart_A; + serial2 = &uart_B; + serial3 = &uart_C; + serial4 = &uart_AO_B; + i2c0 = &i2c0; + i2c1 = &i2c1; + i2c2 = &i2c2; + i2c3 = &i2c3; + i2c4 = &i2c_AO; + tsensor0 = &p_tsensor; + tsensor1 = &d_tsensor; + }; + + memory@00000000 { + device_type = "memory"; + linux,usable-memory = <0x0 0x100000 0x0 0x7ff00000>; + }; + + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + /* global autoconfigured region for contiguous allocations */ + ramoops@0x07400000 { + compatible = "ramoops"; + reg = <0x0 0x07400000 0x0 0x00100000>; + record-size = <0x8000>; + console-size = <0x8000>; + ftrace-size = <0x20000>; + }; + + secmon_reserved:linux,secmon { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x400000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x05000000 0x0 0x400000>; + clear-map; + }; + + secos_reserved:linux,secos { + status = "disable"; + compatible = "amlogic, aml_secos_memory"; + reg = <0x0 0x05300000 0x0 0x2000000>; + no-map; + }; + logo_reserved:linux,meson-fb { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x800000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x7f800000 0x0 0x800000>; + }; + ion_cma_reserved:linux,ion-dev { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x8000000>; + alignment = <0x0 0x400000>; + }; + + //di_reserved:linux,di { + //compatible = "amlogic, di-mem"; + /* buffer_size = 3621952(yuv422 8bit) */ + /* 4179008(yuv422 10bit full pack mode) */ + /** 10x3621952=34.6M(0x23) support 8bit **/ + /** 10x4736064=45.2M(0x2e) support 12bit **/ + /** 10x4179008=40M(0x28) support 10bit **/ + //size = <0x0 0x2800000>; + //no-map; + //}; + /*di CMA pool */ + di_cma_reserved:linux,di_cma { + compatible = "shared-dma-pool"; + reusable; + /* buffer_size = 3621952(yuv422 8bit) + * | 4736064(yuv422 10bit) + * | 4074560(yuv422 10bit full pack mode) + * 10x3621952=34.6M(0x23) support 8bit + * 10x4736064=45.2M(0x2e) support 12bit + * 10x4074560=40M(0x28) support 10bit + */ + size = <0x0 0x02800000>; + alignment = <0x0 0x400000>; + }; + /* POST PROCESS MANAGER */ + ppmgr_reserved:linux,ppmgr { + compatible = "shared-dma-pool"; + size = <0x0 0x0>; + }; + codec_mm_cma:linux,codec_mm_cma { + compatible = "shared-dma-pool"; + reusable; + /* ion_codec_mm max can alloc size 80M*/ + size = <0x0 0x13400000>; + alignment = <0x0 0x400000>; + linux,contiguous-region; + }; + /* codec shared reserved */ + codec_mm_reserved:linux,codec_mm_reserved { + compatible = "amlogic, codec-mm-reserved"; + size = <0x0 0x0>; + alignment = <0x0 0x100000>; + //no-map; + }; + /* vdin0 CMA pool */ + vdin0_cma_reserved:linux,vdin0_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16+4 M */ + size = <0x0 0x04000000>; + alignment = <0x0 0x400000>; + }; + /* vdin1 CMA pool */ + vdin1_cma_reserved:linux,vdin1_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16 M */ + size = <0x0 0x04000000>; + alignment = <0x0 0x400000>; + }; + galcore_reserved:linux,galcore { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x0>; + alignment = <0x0 0x400000>; + linux,contiguous-region; + }; + + isp_cma_reserved:linux,isp_cma { + compatible = "shared-dma-pool"; + reusable; + status = "okay"; + size = <0x0 0x10000000>; + alignment = <0x0 0x400000>; + }; + + adapt_cma_reserved:linux,adapt_cma { + compatible = "shared-dma-pool"; + reusable; + status = "okay"; + size = <0x0 0x03000000>; + alignment = <0x0 0x400000>; + }; + gdc_cma_reserved:linux,gdc_cma { + compatible = "shared-dma-pool"; + reusable; + status = "okay"; + size = <0x0 0x04000000>; + alignment = <0x0 0x400000>; + }; + }; + galcore { + status = "okay"; + memory-region = <&galcore_reserved>; + }; + gpioleds { + compatible = "gpio-leds"; + status = "okay"; + + sys_led { + label="sys_led"; + gpios=<&gpio_ao GPIOAO_11 GPIO_ACTIVE_HIGH>; + default-state ="on"; + retain-state-suspended; + linux,default-trigger="cpu0"; + }; + }; + + cvbsout { + compatible = "amlogic, cvbsout-g12b"; + dev_name = "cvbsout"; + status = "okay"; + clocks = <&clkc CLKID_VCLK2_ENCI + &clkc CLKID_VCLK2_VENCI0 + &clkc CLKID_VCLK2_VENCI1 + &clkc CLKID_DAC_CLK>; + clock-names = "venci_top_gate", + "venci_0_gate", + "venci_1_gate", + "vdac_clk_gate"; + + /* performance: reg_address, reg_value */ + /* g12b */ + performance = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x8080 + 0x1b05 0xfd + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + performance_sarft = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x0 + 0x1b05 0x9 + 0x1c59 0xfc48 + 0xffff 0x0>; /* ending flag */ + }; + + bt-dev{ + compatible = "amlogic, bt-dev"; + dev_name = "bt-dev"; + status = "okay"; + gpio_reset = <&gpio GPIOX_17 GPIO_ACTIVE_HIGH>; + gpio_hostwake = <&gpio GPIOX_19 GPIO_ACTIVE_HIGH>; + }; + + wifi{ + compatible = "amlogic, aml_wifi"; + dev_name = "aml_wifi"; + status = "okay"; + interrupt_pin = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; + irq_trigger_type = "GPIO_IRQ_LOW"; + power_on_pin = <&gpio GPIOX_6 GPIO_ACTIVE_HIGH>; + dhd_static_buf; //if use bcm wifi, config dhd_static_buf + pinctrl-names = "default"; + pinctrl-0 = <&pwm_e_pins>; + pwm_config = <&wifi_pwm_conf>; + }; + + wifi_pwm_conf:wifi_pwm_conf{ + pwm_channel1_conf { + pwms = <&pwm_ef MESON_PWM_0 30541 0>; + duty-cycle = <15270>; + times = <10>; + }; + pwm_channel2_conf { + pwms = <&pwm_ef MESON_PWM_2 30500 0>; + duty-cycle = <15250>; + times = <12>; + }; + }; + + codec_mm { + compatible = "amlogic, codec, mm"; + memory-region = <&codec_mm_cma &codec_mm_reserved>; + dev_name = "codec_mm"; + status = "okay"; + }; + + ppmgr { + compatible = "amlogic, ppmgr"; + memory-region = <&ppmgr_reserved>; + dev_name = "ppmgr"; + status = "okay"; + }; + + deinterlace { + compatible = "amlogic, deinterlace"; + status = "okay"; + /* 0:use reserved; 1:use cma; 2:use cma as reserved */ + flag_cma = <1>; + //memory-region = <&di_reserved>; + memory-region = <&di_cma_reserved>; + interrupts = <0 46 1 + 0 40 1>; + interrupt-names = "pre_irq", "post_irq"; + clocks = <&clkc CLKID_VPU_CLKB_TMP_COMP>, + <&clkc CLKID_VPU_CLKB_COMP>; + clock-names = "vpu_clkb_tmp_composite", + "vpu_clkb_composite"; + clock-range = <334 667>; + /* buffer-size = <3621952>;(yuv422 8bit) */ + buffer-size = <4074560>;/*yuv422 fullpack*/ + /* reserve-iomap = "true"; */ + /* if enable nr10bit, set nr10bit-support to 1 */ + post-wr-support = <1>; + nr10bit-support = <1>; + nrds-enable = <1>; + pps-enable = <1>; + }; + ionvideo { + compatible = "amlogic, ionvideo"; + dev_name = "ionvideo"; + status = "okay"; + }; + + + partitions: partitions{ + parts = <14>; + part-0 = <&logo>; + part-1 = <&recovery>; + part-2 = <&misc>; + part-3 = <&dto>; + part-4 = <&cri_data>; + part-5 = <¶m>; + part-6 = <&boot>; + part-7 = <&rsv>; + part-8 = <&tee>; + part-9 = <&vendor>; + part-10 = <&odm>; + part-11 = <&system>; + part-12 = <&cache>; + part-13 = <&data>; + + logo:logo{ + pname = "logo"; + size = <0x0 0x800000>; + mask = <1>; + }; + recovery:recovery{ + pname = "recovery"; + size = <0x0 0x1800000>; + mask = <1>; + }; + misc:misc{ + pname = "misc"; + size = <0x0 0x800000>; + mask = <1>; + }; + dto:dto{ + pname = "dto"; + size = <0x0 0x800000>; + mask = <1>; + }; + cri_data:cri_data{ + pname = "cri_data"; + size = <0x0 0x800000>; + mask = <2>; + }; + rsv:rsv{ + pname = "rsv"; + size = <0x0 0x1000000>; + mask = <1>; + }; + param:param{ + pname = "param"; + size = <0x0 0x1000000>; + mask = <2>; + }; + boot:boot{ + pname = "boot"; + size = <0x0 0x1000000>; + mask = <1>; + }; + tee:tee{ + pname = "tee"; + size = <0x0 0x2000000>; + mask = <1>; + }; + vendor:vendor{ + pname = "vendor"; + size = <0x0 0x10000000>; + mask = <1>; + }; + odm:odm{ + pname = "odm"; + size = <0x0 0x10000000>; + mask = <1>; + }; + system:system{ + pname = "system"; + size = <0x0 0x80000000>; + mask = <1>; + }; + cache:cache{ + pname = "cache"; + size = <0x0 0x46000000>; + mask = <2>; + }; + data:data{ + pname = "data"; + size = <0xffffffff 0xffffffff>; + mask = <4>; + }; + }; + + gpio_keypad { + compatible = "amlogic, gpio_keypad"; + status = "okay"; + scan_period = <20>; + key_num = <1>; + key_name = "power"; + key_code = <116>; + key-gpios = <&gpio_ao GPIOAO_3 GPIO_ACTIVE_HIGH>; + detect_mode = <0>;/*0:polling mode, 1:irq mode*/ + }; + + adc_keypad { + compatible = "amlogic, adc_keypad"; + status = "okay"; + key_name = "vol-", "vol+", "enter"; + key_num = <3>; + io-channels = <&saradc SARADC_CH2>; + io-channel-names = "key-chan-2"; + key_chan = ; + key_code = <114 115 28>; + key_val = <143 266 389>; //val=voltage/1800mV*1023 + key_tolerance = <40 40 40>; + }; + + unifykey{ + compatible = "amlogic, unifykey"; + status = "ok"; + unifykey-num = <15>; + unifykey-index-0 = <&keysn_0>; + unifykey-index-1 = <&keysn_1>; + unifykey-index-2 = <&keysn_2>; + unifykey-index-3 = <&keysn_3>; + unifykey-index-4 = <&keysn_4>; + unifykey-index-5 = <&keysn_5>; + unifykey-index-6 = <&keysn_6>; + unifykey-index-7 = <&keysn_7>; + unifykey-index-8 = <&keysn_8>; + unifykey-index-9 = <&keysn_9>; + unifykey-index-10= <&keysn_10>; + unifykey-index-11= <&keysn_11>; + unifykey-index-12= <&keysn_12>; + unifykey-index-13= <&keysn_13>; + unifykey-index-14= <&keysn_14>; + + keysn_0: key_0{ + key-name = "usid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_1:key_1{ + key-name = "mac"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_2:key_2{ + key-name = "hdcp"; + key-device = "secure"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_3:key_3{ + key-name = "secure_boot_set"; + key-device = "efuse"; + key-permit = "write"; + }; + keysn_4:key_4{ + key-name = "mac_bt"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_5:key_5{ + key-name = "mac_wifi"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_6:key_6{ + key-name = "hdcp2_tx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_7:key_7{ + key-name = "hdcp2_rx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_8:key_8{ + key-name = "widevinekeybox"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_9:key_9{ + key-name = "deviceid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_10:key_10{ + key-name = "hdcp22_fw_private"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_11:key_11{ + key-name = "PlayReadykeybox25"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_12:key_12{ + key-name = "prpubkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_13:key_13{ + key-name = "prprivkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_14:key_14{ + key-name = "netflix_mgkid"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + };//End unifykey + + amlvecm { + compatible = "amlogic, vecm"; + dev_name = "aml_vecm"; + status = "okay"; + gamma_en = <0>;/*1:enabel ;0:disable*/ + wb_en = <0>;/*1:enabel ;0:disable*/ + cm_en = <0>;/*1:enabel ;0:disable*/ + }; + amdolby_vision { + compatible = "amlogic, dolby_vision_g12a"; + dev_name = "aml_amdolby_vision_driver"; + status = "okay"; + tv_mode = <0>;/*1:enabel ;0:disable*/ + }; + + /* Audio Related start */ + pdm_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, pdm_dummy_codec"; + status = "okay"; + }; + dummy_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, aml_dummy_codec"; + status = "okay"; + }; + amlogic_codec:t9015{ + #sound-dai-cells = <0>; + compatible = "amlogic, aml_codec_T9015"; + reg = <0x0 0xFF632000 0x0 0x2000>; + is_auge_used = <1>; /* meson or auge chipset used */ + tdmout_index = <1>; + status = "okay"; + }; + audio_effect:eqdrc{ + /*eq_enable = <1>;*/ + /*drc_enable = <1>;*/ + /* + * 0:tdmout_a + * 1:tdmout_b + * 2:tdmout_c + * 3:spdifout + * 4:spdifout_b + */ + eqdrc_module = <1>; + /* max 0xf, each bit for one lane, usually one lane */ + lane_mask = <0x1>; + /* max 0xff, each bit for one channel */ + channel_mask = <0x3>; + }; + auge_sound { + compatible = "amlogic, g12a-sound-card"; + aml-audio-card,name = "AML-AUGESOUND"; + + //aml-audio-card,loopback = <&aml_loopback>; + //aml-audio-card,aux-devs = <&amlogic_codec>; + /*avout mute gpio*/ + avout_mute-gpios = <&gpio_ao GPIOAO_2 GPIO_ACTIVE_HIGH>; + /*for audio effect ,eqdrc */ + aml-audio-card,effect = <&audio_effect>; + + aml-audio-card,dai-link@0 { + format = "dsp_a"; + mclk-fs = <512>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + //bitclock-master = <&tdmacodec>; + //frame-master = <&tdmacodec>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-pcm"; + tdmacpu: cpu { + sound-dai = <&aml_tdma>; + dai-tdm-slot-tx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-rx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-num = <8>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <24576000>; + }; + tdmacodec: codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@1 { + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + bitclock-master = <&aml_tdmb>; + frame-master = <&aml_tdmb>; + //bitclock-master = <&tdmbcodec>; + //frame-master = <&tdmbcodec>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-i2s"; + cpu { + sound-dai = <&aml_tdmb>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmbcodec: codec { + sound-dai = <&dummy_codec &dummy_codec + &amlogic_codec &ad82584f_62>; + }; + }; + + aml-audio-card,dai-link@2 { + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + bitclock-master = <&aml_tdmc>; + frame-master = <&aml_tdmc>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + //suffix-name = "alsaPORT-tdm"; + cpu { + sound-dai = <&aml_tdmc>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@3 { + mclk-fs = <64>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-pdm"; + cpu { + sound-dai = <&aml_pdm>; + }; + codec { + sound-dai = <&pdm_codec>; + }; + }; + + aml-audio-card,dai-link@4 { + mclk-fs = <128>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-spdif"; + cpu { + sound-dai = <&aml_spdif>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + }; + audiolocker: locker { + compatible = "amlogic, audiolocker"; + clocks = <&clkaudio CLKID_AUDIO_LOCKER_OUT + &clkaudio CLKID_AUDIO_LOCKER_IN + &clkaudio CLKID_AUDIO_MCLK_D + &clkaudio CLKID_AUDIO_MCLK_E + &clkc CLKID_MPLL1 + &clkc CLKID_MPLL2>; + clock-names = "lock_out", "lock_in", "out_src", + "in_src", "out_calc", "in_ref"; + interrupts = ; + interrupt-names = "irq"; + frequency = <49000000>; /* pll */ + dividor = <49>; /* locker's parent */ + status = "okay"; + }; + /* Audio Related end */ + + cpu_opp_table0: cpu_opp_table0 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <731000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <731000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <731000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <731000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <731000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <731000>; + }; + opp06 { + opp-hz = /bits/ 64 <1398000000>; + opp-microvolt = <761000>; + }; + opp07 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <791000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <831000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <861000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <981000>; + }; + }; + + cpu_opp_table1: cpu_opp_table1 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <751000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <751000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <751000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <751000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <771000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <771000>; + }; + opp06 { + opp-hz = /bits/ 64 <1398000000>; + opp-microvolt = <791000>; + }; + opp07 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <821000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <861000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <891000>; + }; + }; + + cpufreq-meson { + compatible = "amlogic, cpufreq-meson"; + status = "okay"; + }; + + sensor: sensor { + compatible = "soc, sensor"; + status = "okay"; + sensor-name = "imx290"; /*imx290;os08a10;imx227;imx307*/ + pinctrl-names="default"; + pinctrl-0=<&clk12_24_z_pins>; + clocks = <&clkc CLKID_24M>; + clock-names = "g12a_24m"; + reset = <&gpio GPIOZ_12 GPIO_ACTIVE_HIGH>; + ir_cut_gpio = <&gpio GPIOZ_11 GPIO_ACTIVE_HIGH + &gpio GPIOZ_7 GPIO_ACTIVE_HIGH>; + }; + + iq: iq { + compatible = "soc, iq"; + status = "okay"; + sensor-name = "imx290"; /*imx290;os08a10;imx227;imx307*/ + }; +}; /* end of / */ + +&i2c2 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&i2c2_master_pins2>; + clock-frequency = <100000>; /* default 100k */ + sensor-i2c@6c { + compatible = "arm, i2c-sensor"; + reg = <0x6c>; + reg-names = "i2c-sensor"; + slave-addr = <0x6c>; + reg-type = <2>; + reg-data-type = <1>; + link-device = <&phycsi>; + }; +}; + +&isp { + status = "okay"; + memory-region = <&isp_cma_reserved>; +}; + +&adapter { + status = "okay"; + memory-region = <&adapt_cma_reserved>; +}; + +&gdc { + status = "okay"; + memory-region = <&gdc_cma_reserved>; +}; + +&meson_fb { + status = "okay"; + display_size_default = <1920 1080 1920 2160 32>; + mem_size = <0x00800000 0x1980000 0x100000 0x100000 0x800000>; + logo_addr = "0x7f800000"; + mem_alloc = <1>; + pxp_mode = <0>; /** 0:normal mode 1:pxp mode */ +}; + +&pwm_ab { + status = "okay"; + }; + +&pwm_ef { + status = "okay"; + }; + +&pwm_AO_cd { + status = "okay"; + }; + +&i2c0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_master_pins2>; + clock-frequency = <400000>; + + touchscreen@38 { + compatible = "focaltech,fts"; + status = "disabled"; + reg = <0x38>; + reset-gpio = <&gpio GPIOZ_9 GPIO_ACTIVE_HIGH>; + irq-gpio = <&gpio GPIOZ_3 GPIO_ACTIVE_HIGH>; + x_max = <720>; + y_max = <1280>; + max-touch-number = <10>; + }; +}; + +&i2c3 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&i2c3_master_pins2>; + clock-frequency = <100000>; /* default 100k */ + + /* for ref board */ + ad82584f_62: ad82584f_62@62 { + compatible = "ESMT, ad82584f"; + #sound-dai-cells = <0>; + reg = <0x31>; + status = "okay"; + reset_pin = <&gpio GPIOA_5 0>; + }; + + tlv320adc3101_32: tlv320adc3101_32@32 { + compatible = "ti,tlv320adc3101"; + #sound-dai-cells = <0>; + reg = <0x19>; + differential_pair = <1>; + status = "disabled"; + }; + + bl_extern_i2c { + compatible = "bl_extern, i2c"; + dev_name = "lp8556"; + reg = <0x2c>; + status = "disabled"; + }; +}; + +&audiobus { + aml_tdma: tdma { + compatible = "amlogic, g12a-snd-tdma"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 1>; + dai-tdm-oe-lane-slot-mask-out = <1 0>; + dai-tdm-clk-sel = <0>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_A + &clkc CLKID_MPLL0>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmout_a &tdmin_a>; + }; + + aml_tdmb: tdmb { + compatible = "amlogic, g12a-snd-tdmb"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 1 0 0>; + dai-tdm-lane-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <1>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_B + &clkc CLKID_MPLL1 + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; + /* + * 0: tdmout_a; + * 1: tdmout_b; + * 2: tdmout_c; + * 3: spdifout; + * 4: spdifout_b; + */ + samesource_sel = <3>; + }; + + aml_tdmc: tdmc { + compatible = "amlogic, g12a-snd-tdmc"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <1 0 0 0>; + #dai-tdm-lane-slot-mask-out = <1 0 1 1>; + #dai-tdm-lane-oe-slot-mask-in = <0 0 0 0>; + #dai-tdm-lane-oe-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <2>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmc_mclk &tdmout_c &tdmin_c>; + }; + + /* copy a useless tdm to output for hdmi, no pinmux */ + aml_i2s2hdmi: i2s2hdmi { + compatible = "amlogic, g12a-snd-tdmc"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-out = <1 1 1 1>; + dai-tdm-clk-sel = <2>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + + i2s2hdmi = <1>; + + status = "okay"; + }; + + aml_spdif: spdif { + compatible = "amlogic, g12a-snd-spdif-a"; + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 + &clkc CLKID_FCLK_DIV4 + &clkaudio CLKID_AUDIO_SPDIFIN + &clkaudio CLKID_AUDIO_SPDIFOUT + &clkaudio CLKID_AUDIO_SPDIFIN_CTRL + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "sysclk", "fixed_clk", "gate_spdifin", + "gate_spdifout", "clk_spdifin", "clk_spdifout"; + interrupts = + ; + + interrupt-names = "irq_spdifin"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; + pinctrl-0 = <&spdifout &spdifin>; + pinctrl-1 = <&spdifout_a_mute>; + status = "okay"; + }; + aml_spdif_b: spdif_b { + compatible = "amlogic, g12a-snd-spdif-b"; + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 /*CLKID_HIFI_PLL*/ + &clkaudio CLKID_AUDIO_SPDIFOUTB + &clkaudio CLKID_AUDIO_SPDIFOUTB_CTRL>; + clock-names = "sysclk", + "gate_spdifout", "clk_spdifout"; + status = "disabled"; + }; + aml_pdm: pdm { + compatible = "amlogic, g12a-snd-pdm"; + #sound-dai-cells = <0>; + clocks = <&clkaudio CLKID_AUDIO_PDM + &clkc CLKID_FCLK_DIV3 + &clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_PDMIN0 + &clkaudio CLKID_AUDIO_PDMIN1>; + clock-names = "gate", + "sysclk_srcpll", + "dclk_srcpll", + "pdm_dclk", + "pdm_sysclk"; + pinctrl-names = "pdm_pins"; + pinctrl-0 = <&pdmin>; + filter_mode = <1>; /* mode 0~4, defalut:1 */ + status = "okay"; + }; + aml_loopback: loopback { + compatible = "amlogic, snd-loopback"; + /* + * 0: out rate = in data rate; + * 1: out rate = loopback data rate; + */ + lb_mode = <0>; + + /* datain src + * 0: tdmin_a; + * 1: tdmin_b; + * 2: tdmin_c; + * 3: spdifin; + * 4: pdmin; + */ + datain_src = <4>; + datain_chnum = <8>; + datain_chmask = <0x3f>; + + /* tdmin_lb src + * 0: tdmoutA + * 1: tdmoutB + * 2: tdmoutC + * 3: PAD_tdminA + * 4: PAD_tdminB + * 5: PAD_tdminC + */ + datalb_src = <2>; + datalb_chnum = <8>; + datalb_chmask = <0x3>; + + status = "disabled"; + }; + + audioresample: resample { + compatible = "amlogic, g12a-resample"; + clocks = <&clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_MCLK_F + &clkaudio CLKID_AUDIO_RESAMPLE_CTRL>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + /*same with toddr_src + * TDMIN_A, 0 + * TDMIN_B, 1 + * TDMIN_C, 2 + * SPDIFIN, 3 + * PDMIN, 4 + * NONE, + * TDMIN_LB, 6 + * LOOPBACK, 7 + */ + resample_module = <4>; + status = "disabled"; + }; + aml_pwrdet: pwrdet { + compatible = "amlogic, g12a-power-detect"; + + interrupts = ; + interrupt-names = "pwrdet_irq"; + + /* pwrdet source sel + * 7: loopback; + * 6: tdmin_lb; + * 5: reserved; + * 4: pdmin; + * 3: spdifin; + * 2: tdmin_c; + * 1: tdmin_b; + * 0: tdmin_a; + */ + pwrdet_src = <4>; + + hi_th = <0x70000>; + lo_th = <0x16000>; + + status = "disabled"; + }; +}; /* end of audiobus */ + +&pinctrl_periphs { + tdmout_a: tdmout_a { + mux { /* GPIOX_11, GPIOX_10, GPIOX_9 */ + groups = "tdma_sclk", + "tdma_fs", + "tdma_dout0"; + function = "tdma_out"; + }; + }; + + tdmin_a: tdmin_a { + mux { /* GPIOX_8 */ + groups = "tdma_din1"; + function = "tdma_in"; + }; + }; + + tdmb_mclk: tdmb_mclk { + mux { + groups = "mclk0_a"; + function = "mclk0"; + drive-strength = <2>; + }; + }; + tdmout_b: tdmout_b { + mux { /* GPIOA_1, GPIOA_2, GPIOA_3 */ + groups = "tdmb_sclk", + "tdmb_fs", + "tdmb_dout0"; + function = "tdmb_out"; + drive-strength = <2>; + }; + }; + + tdmin_b:tdmin_b { + mux { /* GPIOA_4 */ + groups = "tdmb_din1" + /*,"tdmb_slv_sclk", "tdmb_slv_fs"*/; + function = "tdmb_in"; + drive-strength = <2>; + }; + }; + + tdmc_mclk: tdmc_mclk { + mux { /* GPIOA_11 */ + groups = "mclk1_a"; + function = "mclk1"; + }; + }; + + clk12_24_z_pins:clk12_24_z_pins { + mux { + groups = "clk12_24_z"; + function = "clk12_24_ee"; + drive-strength = <3>; + }; + }; + + tdmout_c:tdmout_c { + mux { /* GPIOA_12, GPIOA_13, GPIOA_8, GPIOA_7*/ + groups = "tdmc_sclk_a", + "tdmc_fs_a", + "tdmc_dout0_a" + /*, "tdmc_dout2", + * "tdmc_dout3" + */; + function = "tdmc_out"; + }; + }; + + tdmin_c:tdmin_c { + mux { /* GPIOA_10 */ + groups = "tdmc_din0_a"; + function = "tdmc_in"; + }; + }; + + spdifin: spdifin { + mux {/* GPIOH_5 */ + groups = "spdif_in_h"; + function = "spdif_in"; + }; + }; + + /* GPIOH_4 */ + /* + * spdifout: spdifout { + * mux { + * groups = "spdif_out_h"; + * function = "spdif_out"; + * }; + *}; + */ + + pdmin: pdmin { + mux { /* gpioa_5, gpioa_6, gpioa_7, gpioa_8, gpioa_9*/ + groups = "pdm_din0_a", + /*"pdm_din1_a",*/ + "pdm_din2_a", + /*"pdm_din3_a",*/ + "pdm_dclk_a"; + function = "pdm"; + }; + }; + + bl_pwm_off_pins:bl_pwm_off_pin { + mux { + pins = "GPIOH_5"; + function = "gpio_periphs"; + output-high; + }; + }; + +}; /* end of pinctrl_periphs */ + +&pinctrl_aobus { + spdifout: spdifout { + mux { /* gpiao_10 */ + groups = "spdif_out_ao"; + function = "spdif_out_ao"; + }; + }; + + spdifout_a_mute: spdifout_a_mute { + mux { /* gpiao_10 */ + groups = "GPIOAO_10"; + function = "gpio_aobus"; + }; + }; +}; /* end of pinctrl_aobus */ + +&irblaster { + status = "disabled"; +}; + +&audio_data { + status = "okay"; +}; + +/*if you want to use vdin just modify status to "ok"*/ +&vdin0 { + memory-region = <&vdin0_cma_reserved>; + status = "okay"; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + *bit4:support yuv422 10bit full pack mode (from txl new add) + */ + tv_bit_mode = <0x15>; +}; +&vdin1 { + memory-region = <&vdin1_cma_reserved>; + status = "okay"; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + */ + tv_bit_mode = <1>; +}; + +&sd_emmc_c { + status = "okay"; + emmc { + caps = "MMC_CAP_8_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + /* "MMC_CAP_1_8V_DDR", */ + "MMC_CAP_HW_RESET", + "MMC_CAP_ERASE", + "MMC_CAP_CMD23"; + caps2 = "MMC_CAP2_HS200"; + /* "MMC_CAP2_HS400";*/ + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&sd_emmc_b { + status = "okay"; + sd { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED"; + f_min = <400000>; + f_max = <50000000>; + }; +}; + +&sd_emmc_a { + status = "okay"; + sdio { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + "MMC_CAP_UHS_SDR12", + "MMC_CAP_UHS_SDR25", + "MMC_CAP_UHS_SDR50", + "MMC_CAP_UHS_SDR104", + "MMC_PM_KEEP_POWER", + "MMC_CAP_SDIO_IRQ"; + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&nand { + status = "disabled"; + plat-names = "bootloader","nandnormal"; + plat-num = <2>; + plat-part-0 = <&bootloader>; + plat-part-1 = <&nandnormal>; + bootloader: bootloader{ + enable_pad ="ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <1>; + part_num = <0>; + rb_detect = <1>; + }; + nandnormal: nandnormal{ + enable_pad ="ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + plane_mode = "twoplane"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <2>; + part_num = <3>; + partition = <&nand_partitions>; + rb_detect = <1>; + }; + nand_partitions:nand_partition{ + /* + * if bl_mode is 1, tpl size was generate by + * fip_copies * fip_size which + * will not skip bad when calculating + * the partition size; + * + * if bl_mode is 0, + * tpl partition must be comment out. + */ + tpl{ + offset=<0x0 0x0>; + size=<0x0 0x0>; + }; + logo{ + offset=<0x0 0x0>; + size=<0x0 0x200000>; + }; + recovery{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + boot{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + system{ + offset=<0x0 0x0>; + size=<0x0 0x4000000>; + }; + data{ + offset=<0xffffffff 0xffffffff>; + size=<0x0 0x0>; + }; + }; +}; +&dwc3 { + status = "okay"; +}; + +&usb2_phy_v2 { + status = "okay"; + portnum = <2>; +}; + +&usb3_phy_v2 { + status = "okay"; + portnum = <0>; + otg = <1>; + gpio-vbus-power = "GPIOH_6"; + gpios = <&gpio GPIOH_6 GPIO_ACTIVE_HIGH>; +}; + +&dwc2_a { + status = "okay"; + /** 0: normal, 1: otg+dwc3 host only, 2: otg+dwc3 device only*/ + controller-type = <3>; +}; +ðmac { + status = "okay"; +/* //conflict with isp i2c + * pinctrl-names = "internal_eth_pins"; + * pinctrl-0 = <&internal_eth_pins>; + */ + mc_val = <0x4be04>; + + internal_phy=<1>; +}; + +&uart_A { + status = "okay"; +}; + +&pcie_A { + reset-gpio = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; + status = "okay"; +}; + +&saradc { + status = "okay"; +}; + +&spicc1 { + status = "disabled"; + pinctrl-names = "default"; + pinctrl-0 = <&spicc1_pins>; + cs-gpios = <&gpio GPIOH_6 0>; +}; diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest.dts b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest.dts index 6a304e48ccf0..280a07ab75af 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest.dts @@ -22,6 +22,7 @@ / { model = "Amlogic"; + amlogic-dt-id = "g12b_w400_b"; compatible = "amlogic, g12b"; interrupt-parent = <&gic>; #address-cells = <2>; @@ -44,7 +45,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x0 0x100000 0x0 0x7ff00000>; + linux,usable-memory = <0x0 0x0 0x0 0x80000000>; }; reserved-memory { @@ -57,8 +58,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { @@ -159,8 +159,6 @@ label="sys_led"; gpios=<&gpio_ao GPIOAO_11 GPIO_ACTIVE_HIGH>; default-state ="on"; - retain-state-suspended; - linux,default-trigger="cpu0"; }; }; @@ -234,6 +232,21 @@ status = "okay"; }; + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + ppmgr { compatible = "amlogic, ppmgr"; memory-region = <&ppmgr_reserved>; @@ -695,39 +708,31 @@ }; opp04 { opp-hz = /bits/ 64 <1000000000>; - opp-microvolt = <731000>; + opp-microvolt = <761000>; }; opp05 { opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <731000>; + opp-microvolt = <781000>; }; opp06 { opp-hz = /bits/ 64 <1398000000>; - opp-microvolt = <761000>; + opp-microvolt = <811000>; }; opp07 { opp-hz = /bits/ 64 <1512000000>; - opp-microvolt = <791000>; + opp-microvolt = <861000>; }; opp08 { opp-hz = /bits/ 64 <1608000000>; - opp-microvolt = <831000>; + opp-microvolt = <901000>; }; opp09 { opp-hz = /bits/ 64 <1704000000>; - opp-microvolt = <861000>; + opp-microvolt = <951000>; }; opp10 { - opp-hz = /bits/ 64 <1896000000>; - opp-microvolt = <981000>; - }; - opp11 { - opp-hz = /bits/ 64 <2016000000>; - opp-microvolt = <1011000>; - }; - opp12 { - opp-hz = /bits/ 64 <2100000000>; - opp-microvolt = <1011000>; + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <1001000>; }; }; @@ -737,54 +742,62 @@ opp00 { opp-hz = /bits/ 64 <100000000>; - opp-microvolt = <751000>; + opp-microvolt = <731000>; }; opp01 { opp-hz = /bits/ 64 <250000000>; - opp-microvolt = <751000>; + opp-microvolt = <731000>; }; opp02 { opp-hz = /bits/ 64 <500000000>; - opp-microvolt = <751000>; + opp-microvolt = <731000>; }; opp03 { opp-hz = /bits/ 64 <667000000>; - opp-microvolt = <751000>; + opp-microvolt = <731000>; }; opp04 { opp-hz = /bits/ 64 <1000000000>; - opp-microvolt = <771000>; + opp-microvolt = <731000>; }; opp05 { opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <771000>; + opp-microvolt = <751000>; }; opp06 { opp-hz = /bits/ 64 <1398000000>; - opp-microvolt = <791000>; + opp-microvolt = <771000>; }; opp07 { opp-hz = /bits/ 64 <1512000000>; - opp-microvolt = <821000>; + opp-microvolt = <771000>; }; opp08 { opp-hz = /bits/ 64 <1608000000>; - opp-microvolt = <861000>; + opp-microvolt = <781000>; }; opp09 { opp-hz = /bits/ 64 <1704000000>; - opp-microvolt = <891000>; + opp-microvolt = <791000>; }; opp10 { opp-hz = /bits/ 64 <1800000000>; - opp-microvolt = <1011000>; + opp-microvolt = <831000>; }; opp11 { opp-hz = /bits/ 64 <1908000000>; - opp-microvolt = <1011000>; + opp-microvolt = <861000>; }; opp12 { opp-hz = /bits/ 64 <2016000000>; + opp-microvolt = <911000>; + }; + opp13 { + opp-hz = /bits/ 64 <2100000000>; + opp-microvolt = <951000>; + }; + opp14 { + opp-hz = /bits/ 64 <2208000000>; opp-microvolt = <1011000>; }; }; @@ -864,8 +877,10 @@ dai-tdm-clk-sel = <1>; clocks = <&clkaudio CLKID_AUDIO_MCLK_B &clkc CLKID_MPLL1 - &clkc CLKID_MPLL0>; - clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; pinctrl-names = "tdm_pins"; pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; /* @@ -923,8 +938,10 @@ ; interrupt-names = "irq_spdifin"; - pinctrl-names = "spdif_pins"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; pinctrl-0 = <&spdifout &spdifin>; + pinctrl-1 = <&spdifout_a_mute>; status = "okay"; }; aml_spdif_b: spdif_b { @@ -1147,6 +1164,13 @@ function = "spdif_out_ao"; }; }; + + spdifout_a_mute: spdifout_a_mute { + mux { /* gpiao_10 */ + groups = "GPIOAO_10"; + function = "gpio_aobus"; + }; + }; }; /* end of pinctrl_aobus */ &irblaster { diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest_a.dts b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest_a.dts new file mode 100644 index 000000000000..ac5ca3645b64 --- /dev/null +++ b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest_a.dts @@ -0,0 +1,1351 @@ +/* + * arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot_vccktest_a.dts + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +/dts-v1/; + +#include "mesong12b_a.dtsi" +#include "mesong12b_skt-panel.dtsi" + +/ { + model = "Amlogic"; + amlogic-dt-id = "g12b_w400_a"; + compatible = "amlogic, g12b"; + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + + aliases { + serial0 = &uart_AO; + serial1 = &uart_A; + serial2 = &uart_B; + serial3 = &uart_C; + serial4 = &uart_AO_B; + i2c0 = &i2c0; + i2c1 = &i2c1; + i2c2 = &i2c2; + i2c3 = &i2c3; + i2c4 = &i2c_AO; + tsensor0 = &p_tsensor; + tsensor1 = &d_tsensor; + }; + + memory@00000000 { + device_type = "memory"; + linux,usable-memory = <0x0 0x100000 0x0 0x7ff00000>; + }; + + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + /* global autoconfigured region for contiguous allocations */ + ramoops@0x07400000 { + compatible = "ramoops"; + reg = <0x0 0x07400000 0x0 0x00100000>; + record-size = <0x8000>; + console-size = <0x8000>; + ftrace-size = <0x20000>; + }; + + secmon_reserved:linux,secmon { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x400000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x05000000 0x0 0x400000>; + }; + + secos_reserved:linux,secos { + status = "disable"; + compatible = "amlogic, aml_secos_memory"; + reg = <0x0 0x05300000 0x0 0x2000000>; + no-map; + }; + logo_reserved:linux,meson-fb { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x800000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x7f800000 0x0 0x800000>; + }; + ion_cma_reserved:linux,ion-dev { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x8000000>; + alignment = <0x0 0x400000>; + }; + + //di_reserved:linux,di { + //compatible = "amlogic, di-mem"; + /* buffer_size = 3621952(yuv422 8bit) */ + /* 4179008(yuv422 10bit full pack mode) */ + /** 10x3621952=34.6M(0x23) support 8bit **/ + /** 10x4736064=45.2M(0x2e) support 12bit **/ + /** 10x4179008=40M(0x28) support 10bit **/ + //size = <0x0 0x2800000>; + //no-map; + //}; + /*di CMA pool */ + di_cma_reserved:linux,di_cma { + compatible = "shared-dma-pool"; + reusable; + /* buffer_size = 3621952(yuv422 8bit) + * | 4736064(yuv422 10bit) + * | 4074560(yuv422 10bit full pack mode) + * 10x3621952=34.6M(0x23) support 8bit + * 10x4736064=45.2M(0x2e) support 12bit + * 10x4074560=40M(0x28) support 10bit + */ + size = <0x0 0x02800000>; + alignment = <0x0 0x400000>; + }; + /* POST PROCESS MANAGER */ + ppmgr_reserved:linux,ppmgr { + compatible = "shared-dma-pool"; + size = <0x0 0x0>; + }; + codec_mm_cma:linux,codec_mm_cma { + compatible = "shared-dma-pool"; + reusable; + /* ion_codec_mm max can alloc size 80M*/ + size = <0x0 0x13400000>; + alignment = <0x0 0x400000>; + linux,contiguous-region; + }; + /* codec shared reserved */ + codec_mm_reserved:linux,codec_mm_reserved { + compatible = "amlogic, codec-mm-reserved"; + size = <0x0 0x0>; + alignment = <0x0 0x100000>; + //no-map; + }; + /* vdin0 CMA pool */ + vdin0_cma_reserved:linux,vdin0_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16+4 M */ + size = <0x0 0x04000000>; + alignment = <0x0 0x400000>; + }; + /* vdin1 CMA pool */ + vdin1_cma_reserved:linux,vdin1_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16 M */ + size = <0x0 0x04000000>; + alignment = <0x0 0x400000>; + }; + }; + + gpioleds { + compatible = "gpio-leds"; + status = "okay"; + + sys_led { + label="sys_led"; + gpios=<&gpio_ao GPIOAO_11 GPIO_ACTIVE_HIGH>; + default-state ="on"; + retain-state-suspended; + linux,default-trigger="cpu0"; + }; + }; + + cvbsout { + compatible = "amlogic, cvbsout-g12b"; + dev_name = "cvbsout"; + status = "okay"; + clocks = <&clkc CLKID_VCLK2_ENCI + &clkc CLKID_VCLK2_VENCI0 + &clkc CLKID_VCLK2_VENCI1 + &clkc CLKID_DAC_CLK>; + clock-names = "venci_top_gate", + "venci_0_gate", + "venci_1_gate", + "vdac_clk_gate"; + + /* performance: reg_address, reg_value */ + /* g12b */ + performance = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x8080 + 0x1b05 0xfd + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + performance_sarft = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x0 + 0x1b05 0x9 + 0x1c59 0xfc48 + 0xffff 0x0>; /* ending flag */ + }; + + bt-dev{ + compatible = "amlogic, bt-dev"; + dev_name = "bt-dev"; + status = "okay"; + gpio_reset = <&gpio GPIOX_17 GPIO_ACTIVE_HIGH>; + gpio_hostwake = <&gpio GPIOX_19 GPIO_ACTIVE_HIGH>; + }; + + wifi{ + compatible = "amlogic, aml_wifi"; + dev_name = "aml_wifi"; + status = "okay"; + interrupt_pin = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; + irq_trigger_type = "GPIO_IRQ_LOW"; + power_on_pin = <&gpio GPIOX_6 GPIO_ACTIVE_HIGH>; + dhd_static_buf; //if use bcm wifi, config dhd_static_buf + pinctrl-names = "default"; + pinctrl-0 = <&pwm_e_pins>; + pwm_config = <&wifi_pwm_conf>; + }; + + wifi_pwm_conf:wifi_pwm_conf{ + pwm_channel1_conf { + pwms = <&pwm_ef MESON_PWM_0 30541 0>; + duty-cycle = <15270>; + times = <10>; + }; + pwm_channel2_conf { + pwms = <&pwm_ef MESON_PWM_2 30500 0>; + duty-cycle = <15250>; + times = <12>; + }; + }; + + codec_mm { + compatible = "amlogic, codec, mm"; + memory-region = <&codec_mm_cma &codec_mm_reserved>; + dev_name = "codec_mm"; + status = "okay"; + }; + + ppmgr { + compatible = "amlogic, ppmgr"; + memory-region = <&ppmgr_reserved>; + dev_name = "ppmgr"; + status = "okay"; + }; + + deinterlace { + compatible = "amlogic, deinterlace"; + status = "okay"; + /* 0:use reserved; 1:use cma; 2:use cma as reserved */ + flag_cma = <1>; + //memory-region = <&di_reserved>; + memory-region = <&di_cma_reserved>; + interrupts = <0 46 1 + 0 40 1>; + interrupt-names = "pre_irq", "post_irq"; + clocks = <&clkc CLKID_VPU_CLKB_TMP_COMP>, + <&clkc CLKID_VPU_CLKB_COMP>; + clock-names = "vpu_clkb_tmp_composite", + "vpu_clkb_composite"; + clock-range = <334 667>; + /* buffer-size = <3621952>;(yuv422 8bit) */ + buffer-size = <4074560>;/*yuv422 fullpack*/ + /* reserve-iomap = "true"; */ + /* if enable nr10bit, set nr10bit-support to 1 */ + post-wr-support = <1>; + nr10bit-support = <1>; + nrds-enable = <1>; + pps-enable = <1>; + }; + ionvideo { + compatible = "amlogic, ionvideo"; + dev_name = "ionvideo"; + status = "okay"; + }; + + + partitions: partitions{ + parts = <14>; + part-0 = <&logo>; + part-1 = <&recovery>; + part-2 = <&misc>; + part-3 = <&dto>; + part-4 = <&cri_data>; + part-5 = <¶m>; + part-6 = <&boot>; + part-7 = <&rsv>; + part-8 = <&tee>; + part-9 = <&vendor>; + part-10 = <&odm>; + part-11 = <&system>; + part-12 = <&cache>; + part-13 = <&data>; + + logo:logo{ + pname = "logo"; + size = <0x0 0x800000>; + mask = <1>; + }; + recovery:recovery{ + pname = "recovery"; + size = <0x0 0x1800000>; + mask = <1>; + }; + misc:misc{ + pname = "misc"; + size = <0x0 0x800000>; + mask = <1>; + }; + dto:dto{ + pname = "dto"; + size = <0x0 0x800000>; + mask = <1>; + }; + cri_data:cri_data{ + pname = "cri_data"; + size = <0x0 0x800000>; + mask = <2>; + }; + rsv:rsv{ + pname = "rsv"; + size = <0x0 0x1000000>; + mask = <1>; + }; + param:param{ + pname = "param"; + size = <0x0 0x1000000>; + mask = <2>; + }; + boot:boot{ + pname = "boot"; + size = <0x0 0x1000000>; + mask = <1>; + }; + tee:tee{ + pname = "tee"; + size = <0x0 0x2000000>; + mask = <1>; + }; + vendor:vendor{ + pname = "vendor"; + size = <0x0 0x10000000>; + mask = <1>; + }; + odm:odm{ + pname = "odm"; + size = <0x0 0x10000000>; + mask = <1>; + }; + system:system{ + pname = "system"; + size = <0x0 0x80000000>; + mask = <1>; + }; + cache:cache{ + pname = "cache"; + size = <0x0 0x46000000>; + mask = <2>; + }; + data:data{ + pname = "data"; + size = <0xffffffff 0xffffffff>; + mask = <4>; + }; + }; + + gpio_keypad { + compatible = "amlogic, gpio_keypad"; + status = "okay"; + scan_period = <20>; + key_num = <1>; + key_name = "power"; + key_code = <116>; + key-gpios = <&gpio_ao GPIOAO_3 GPIO_ACTIVE_HIGH>; + detect_mode = <0>;/*0:polling mode, 1:irq mode*/ + }; + + adc_keypad { + compatible = "amlogic, adc_keypad"; + status = "okay"; + key_name = "vol-", "vol+", "enter"; + key_num = <3>; + io-channels = <&saradc SARADC_CH2>; + io-channel-names = "key-chan-2"; + key_chan = ; + key_code = <114 115 28>; + key_val = <143 266 389>; //val=voltage/1800mV*1023 + key_tolerance = <40 40 40>; + }; + + unifykey{ + compatible = "amlogic, unifykey"; + status = "ok"; + unifykey-num = <15>; + unifykey-index-0 = <&keysn_0>; + unifykey-index-1 = <&keysn_1>; + unifykey-index-2 = <&keysn_2>; + unifykey-index-3 = <&keysn_3>; + unifykey-index-4 = <&keysn_4>; + unifykey-index-5 = <&keysn_5>; + unifykey-index-6 = <&keysn_6>; + unifykey-index-7 = <&keysn_7>; + unifykey-index-8 = <&keysn_8>; + unifykey-index-9 = <&keysn_9>; + unifykey-index-10= <&keysn_10>; + unifykey-index-11= <&keysn_11>; + unifykey-index-12= <&keysn_12>; + unifykey-index-13= <&keysn_13>; + unifykey-index-14= <&keysn_14>; + + keysn_0: key_0{ + key-name = "usid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_1:key_1{ + key-name = "mac"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_2:key_2{ + key-name = "hdcp"; + key-device = "secure"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_3:key_3{ + key-name = "secure_boot_set"; + key-device = "efuse"; + key-permit = "write"; + }; + keysn_4:key_4{ + key-name = "mac_bt"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_5:key_5{ + key-name = "mac_wifi"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_6:key_6{ + key-name = "hdcp2_tx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_7:key_7{ + key-name = "hdcp2_rx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_8:key_8{ + key-name = "widevinekeybox"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_9:key_9{ + key-name = "deviceid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_10:key_10{ + key-name = "hdcp22_fw_private"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_11:key_11{ + key-name = "PlayReadykeybox25"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_12:key_12{ + key-name = "prpubkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_13:key_13{ + key-name = "prprivkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_14:key_14{ + key-name = "netflix_mgkid"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + };//End unifykey + + amlvecm { + compatible = "amlogic, vecm"; + dev_name = "aml_vecm"; + status = "okay"; + gamma_en = <0>;/*1:enabel ;0:disable*/ + wb_en = <0>;/*1:enabel ;0:disable*/ + cm_en = <0>;/*1:enabel ;0:disable*/ + }; + amdolby_vision { + compatible = "amlogic, dolby_vision_g12a"; + dev_name = "aml_amdolby_vision_driver"; + status = "okay"; + tv_mode = <0>;/*1:enabel ;0:disable*/ + }; + + /* Audio Related start */ + pdm_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, pdm_dummy_codec"; + status = "okay"; + }; + dummy_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, aml_dummy_codec"; + status = "okay"; + }; + amlogic_codec:t9015{ + #sound-dai-cells = <0>; + compatible = "amlogic, aml_codec_T9015"; + reg = <0x0 0xFF632000 0x0 0x2000>; + is_auge_used = <1>; /* meson or auge chipset used */ + tdmout_index = <1>; + status = "okay"; + }; + audio_effect:eqdrc{ + /*eq_enable = <1>;*/ + /*drc_enable = <1>;*/ + /* + * 0:tdmout_a + * 1:tdmout_b + * 2:tdmout_c + * 3:spdifout + * 4:spdifout_b + */ + eqdrc_module = <1>; + /* max 0xf, each bit for one lane, usually one lane */ + lane_mask = <0x1>; + /* max 0xff, each bit for one channel */ + channel_mask = <0x3>; + }; + auge_sound { + compatible = "amlogic, g12a-sound-card"; + aml-audio-card,name = "AML-AUGESOUND"; + + //aml-audio-card,loopback = <&aml_loopback>; + //aml-audio-card,aux-devs = <&amlogic_codec>; + /*avout mute gpio*/ + avout_mute-gpios = <&gpio_ao GPIOAO_2 GPIO_ACTIVE_HIGH>; + /*for audio effect ,eqdrc */ + aml-audio-card,effect = <&audio_effect>; + + aml-audio-card,dai-link@0 { + format = "dsp_a"; + mclk-fs = <512>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + //bitclock-master = <&tdmacodec>; + //frame-master = <&tdmacodec>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-pcm"; + tdmacpu: cpu { + sound-dai = <&aml_tdma>; + dai-tdm-slot-tx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-rx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-num = <8>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <24576000>; + }; + tdmacodec: codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@1 { + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + bitclock-master = <&aml_tdmb>; + frame-master = <&aml_tdmb>; + //bitclock-master = <&tdmbcodec>; + //frame-master = <&tdmbcodec>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-i2s"; + cpu { + sound-dai = <&aml_tdmb>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmbcodec: codec { + sound-dai = <&dummy_codec &dummy_codec + &amlogic_codec &ad82584f_62>; + }; + }; + + aml-audio-card,dai-link@2 { + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + bitclock-master = <&aml_tdmc>; + frame-master = <&aml_tdmc>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + //suffix-name = "alsaPORT-tdm"; + cpu { + sound-dai = <&aml_tdmc>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@3 { + mclk-fs = <64>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-pdm"; + cpu { + sound-dai = <&aml_pdm>; + }; + codec { + sound-dai = <&pdm_codec>; + }; + }; + + aml-audio-card,dai-link@4 { + mclk-fs = <128>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-spdif"; + cpu { + sound-dai = <&aml_spdif>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + }; + audiolocker: locker { + compatible = "amlogic, audiolocker"; + clocks = <&clkaudio CLKID_AUDIO_LOCKER_OUT + &clkaudio CLKID_AUDIO_LOCKER_IN + &clkaudio CLKID_AUDIO_MCLK_D + &clkaudio CLKID_AUDIO_MCLK_E + &clkc CLKID_MPLL1 + &clkc CLKID_MPLL2>; + clock-names = "lock_out", "lock_in", "out_src", + "in_src", "out_calc", "in_ref"; + interrupts = ; + interrupt-names = "irq"; + frequency = <49000000>; /* pll */ + dividor = <49>; /* locker's parent */ + status = "okay"; + }; + /* Audio Related end */ + + cpu_opp_table0: cpu_opp_table0 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <731000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <731000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <731000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <731000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <731000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <731000>; + }; + opp06 { + opp-hz = /bits/ 64 <1398000000>; + opp-microvolt = <761000>; + }; + opp07 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <791000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <831000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <861000>; + }; + opp10 { + opp-hz = /bits/ 64 <1896000000>; + opp-microvolt = <981000>; + }; + opp11 { + opp-hz = /bits/ 64 <2016000000>; + opp-microvolt = <1011000>; + }; + opp12 { + opp-hz = /bits/ 64 <2100000000>; + opp-microvolt = <1011000>; + }; + }; + + cpu_opp_table1: cpu_opp_table1 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <751000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <751000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <751000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <751000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <771000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <771000>; + }; + opp06 { + opp-hz = /bits/ 64 <1398000000>; + opp-microvolt = <791000>; + }; + opp07 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <821000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <861000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <891000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <1011000>; + }; + opp11 { + opp-hz = /bits/ 64 <1908000000>; + opp-microvolt = <1011000>; + }; + opp12 { + opp-hz = /bits/ 64 <2016000000>; + opp-microvolt = <1011000>; + }; + }; + + cpufreq-meson { + compatible = "amlogic, cpufreq-meson"; + status = "okay"; + }; + + +}; /* end of / */ + +&meson_fb { + status = "okay"; + display_size_default = <1920 1080 1920 2160 32>; + mem_size = <0x00800000 0x1980000 0x100000 0x100000 0x800000>; + logo_addr = "0x7f800000"; + mem_alloc = <1>; + pxp_mode = <0>; /** 0:normal mode 1:pxp mode */ +}; + +&pwm_ab { + status = "okay"; + }; + +&pwm_ef { + status = "okay"; + }; + +&pwm_AO_cd { + status = "okay"; + }; + +&i2c3 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&i2c3_master_pins2>; + clock-frequency = <100000>; /* default 100k */ + + /* for ref board */ + ad82584f_62: ad82584f_62@62 { + compatible = "ESMT, ad82584f"; + #sound-dai-cells = <0>; + reg = <0x31>; + status = "okay"; + reset_pin = <&gpio GPIOA_5 0>; + }; + + tlv320adc3101_32: tlv320adc3101_32@32 { + compatible = "ti,tlv320adc3101"; + #sound-dai-cells = <0>; + reg = <0x19>; + differential_pair = <1>; + status = "disabled"; + }; +}; + +&audiobus { + aml_tdma: tdma { + compatible = "amlogic, g12a-snd-tdma"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 1>; + dai-tdm-oe-lane-slot-mask-out = <1 0>; + dai-tdm-clk-sel = <0>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_A + &clkc CLKID_MPLL0>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmout_a &tdmin_a>; + }; + + aml_tdmb: tdmb { + compatible = "amlogic, g12a-snd-tdmb"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 1 0 0>; + dai-tdm-lane-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <1>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_B + &clkc CLKID_MPLL1 + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; + /* + * 0: tdmout_a; + * 1: tdmout_b; + * 2: tdmout_c; + * 3: spdifout; + * 4: spdifout_b; + */ + samesource_sel = <3>; + }; + + aml_tdmc: tdmc { + compatible = "amlogic, g12a-snd-tdmc"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <1 0 0 0>; + #dai-tdm-lane-slot-mask-out = <1 0 1 1>; + #dai-tdm-lane-oe-slot-mask-in = <0 0 0 0>; + #dai-tdm-lane-oe-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <2>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmc_mclk &tdmout_c &tdmin_c>; + }; + + /* copy a useless tdm to output for hdmi, no pinmux */ + aml_i2s2hdmi: i2s2hdmi { + compatible = "amlogic, g12a-snd-tdmc"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-out = <1 1 1 1>; + dai-tdm-clk-sel = <2>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + + i2s2hdmi = <1>; + + status = "okay"; + }; + + aml_spdif: spdif { + compatible = "amlogic, g12a-snd-spdif-a"; + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 + &clkc CLKID_FCLK_DIV4 + &clkaudio CLKID_AUDIO_SPDIFIN + &clkaudio CLKID_AUDIO_SPDIFOUT + &clkaudio CLKID_AUDIO_SPDIFIN_CTRL + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "sysclk", "fixed_clk", "gate_spdifin", + "gate_spdifout", "clk_spdifin", "clk_spdifout"; + interrupts = + ; + + interrupt-names = "irq_spdifin"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; + pinctrl-0 = <&spdifout &spdifin>; + pinctrl-1 = <&spdifout_a_mute>; + status = "okay"; + }; + aml_spdif_b: spdif_b { + compatible = "amlogic, g12a-snd-spdif-b"; + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 /*CLKID_HIFI_PLL*/ + &clkaudio CLKID_AUDIO_SPDIFOUTB + &clkaudio CLKID_AUDIO_SPDIFOUTB_CTRL>; + clock-names = "sysclk", + "gate_spdifout", "clk_spdifout"; + status = "disabled"; + }; + aml_pdm: pdm { + compatible = "amlogic, g12a-snd-pdm"; + #sound-dai-cells = <0>; + clocks = <&clkaudio CLKID_AUDIO_PDM + &clkc CLKID_FCLK_DIV3 + &clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_PDMIN0 + &clkaudio CLKID_AUDIO_PDMIN1>; + clock-names = "gate", + "sysclk_srcpll", + "dclk_srcpll", + "pdm_dclk", + "pdm_sysclk"; + pinctrl-names = "pdm_pins"; + pinctrl-0 = <&pdmin>; + filter_mode = <1>; /* mode 0~4, defalut:1 */ + status = "okay"; + }; + aml_loopback: loopback { + compatible = "amlogic, snd-loopback"; + /* + * 0: out rate = in data rate; + * 1: out rate = loopback data rate; + */ + lb_mode = <0>; + + /* datain src + * 0: tdmin_a; + * 1: tdmin_b; + * 2: tdmin_c; + * 3: spdifin; + * 4: pdmin; + */ + datain_src = <4>; + datain_chnum = <8>; + datain_chmask = <0x3f>; + + /* tdmin_lb src + * 0: tdmoutA + * 1: tdmoutB + * 2: tdmoutC + * 3: PAD_tdminA + * 4: PAD_tdminB + * 5: PAD_tdminC + */ + datalb_src = <2>; + datalb_chnum = <8>; + datalb_chmask = <0x3>; + + status = "disabled"; + }; + + audioresample: resample { + compatible = "amlogic, g12a-resample"; + clocks = <&clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_MCLK_F + &clkaudio CLKID_AUDIO_RESAMPLE_CTRL>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + /*same with toddr_src + * TDMIN_A, 0 + * TDMIN_B, 1 + * TDMIN_C, 2 + * SPDIFIN, 3 + * PDMIN, 4 + * NONE, + * TDMIN_LB, 6 + * LOOPBACK, 7 + */ + resample_module = <4>; + status = "disabled"; + }; + aml_pwrdet: pwrdet { + compatible = "amlogic, g12a-power-detect"; + + interrupts = ; + interrupt-names = "pwrdet_irq"; + + /* pwrdet source sel + * 7: loopback; + * 6: tdmin_lb; + * 5: reserved; + * 4: pdmin; + * 3: spdifin; + * 2: tdmin_c; + * 1: tdmin_b; + * 0: tdmin_a; + */ + pwrdet_src = <4>; + + hi_th = <0x70000>; + lo_th = <0x16000>; + + status = "disabled"; + }; +}; /* end of audiobus */ + +&pinctrl_periphs { + tdmout_a: tdmout_a { + mux { /* GPIOX_11, GPIOX_10, GPIOX_9 */ + groups = "tdma_sclk", + "tdma_fs", + "tdma_dout0"; + function = "tdma_out"; + }; + }; + + tdmin_a: tdmin_a { + mux { /* GPIOX_8 */ + groups = "tdma_din1"; + function = "tdma_in"; + }; + }; + + tdmb_mclk: tdmb_mclk { + mux { + groups = "mclk0_a"; + function = "mclk0"; + drive-strength = <2>; + }; + }; + tdmout_b: tdmout_b { + mux { /* GPIOA_1, GPIOA_2, GPIOA_3 */ + groups = "tdmb_sclk", + "tdmb_fs", + "tdmb_dout0"; + function = "tdmb_out"; + drive-strength = <2>; + }; + }; + + tdmin_b:tdmin_b { + mux { /* GPIOA_4 */ + groups = "tdmb_din1" + /*,"tdmb_slv_sclk", "tdmb_slv_fs"*/; + function = "tdmb_in"; + drive-strength = <2>; + }; + }; + + tdmc_mclk: tdmc_mclk { + mux { /* GPIOA_11 */ + groups = "mclk1_a"; + function = "mclk1"; + }; + }; + + tdmout_c:tdmout_c { + mux { /* GPIOA_12, GPIOA_13, GPIOA_8, GPIOA_7*/ + groups = "tdmc_sclk_a", + "tdmc_fs_a", + "tdmc_dout0_a" + /*, "tdmc_dout2", + * "tdmc_dout3" + */; + function = "tdmc_out"; + }; + }; + + tdmin_c:tdmin_c { + mux { /* GPIOA_10 */ + groups = "tdmc_din0_a"; + function = "tdmc_in"; + }; + }; + + spdifin: spdifin { + mux {/* GPIOH_5 */ + groups = "spdif_in_h"; + function = "spdif_in"; + }; + }; + + /* GPIOH_4 */ + /* + * spdifout: spdifout { + * mux { + * groups = "spdif_out_h"; + * function = "spdif_out"; + * }; + *}; + */ + + pdmin: pdmin { + mux { /* gpioa_5, gpioa_6, gpioa_7, gpioa_8, gpioa_9*/ + groups = "pdm_din0_a", + /*"pdm_din1_a",*/ + "pdm_din2_a", + /*"pdm_din3_a",*/ + "pdm_dclk_a"; + function = "pdm"; + }; + }; + + bl_pwm_off_pins:bl_pwm_off_pin { + mux { + pins = "GPIOH_5"; + function = "gpio_periphs"; + output-high; + }; + }; + +}; /* end of pinctrl_periphs */ + +&pinctrl_aobus { + spdifout: spdifout { + mux { /* gpiao_10 */ + groups = "spdif_out_ao"; + function = "spdif_out_ao"; + }; + }; + + spdifout_a_mute: spdifout_a_mute { + mux { /* gpiao_10 */ + groups = "GPIOAO_10"; + function = "gpio_aobus"; + }; + }; +}; /* end of pinctrl_aobus */ + +&irblaster { + status = "disabled"; +}; + +&audio_data { + status = "okay"; +}; + +/*if you want to use vdin just modify status to "ok"*/ +&vdin0 { + memory-region = <&vdin0_cma_reserved>; + status = "okay"; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + *bit4:support yuv422 10bit full pack mode (from txl new add) + */ + tv_bit_mode = <0x15>; +}; +&vdin1 { + memory-region = <&vdin1_cma_reserved>; + status = "okay"; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + */ + tv_bit_mode = <1>; +}; + +&sd_emmc_c { + status = "okay"; + emmc { + caps = "MMC_CAP_8_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + /* "MMC_CAP_1_8V_DDR", */ + "MMC_CAP_HW_RESET", + "MMC_CAP_ERASE", + "MMC_CAP_CMD23"; + caps2 = "MMC_CAP2_HS200"; + /* "MMC_CAP2_HS400";*/ + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&sd_emmc_b { + status = "okay"; + sd { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED"; + f_min = <400000>; + f_max = <50000000>; + }; +}; + +&sd_emmc_a { + status = "okay"; + sdio { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + "MMC_CAP_UHS_SDR12", + "MMC_CAP_UHS_SDR25", + "MMC_CAP_UHS_SDR50", + "MMC_CAP_UHS_SDR104", + "MMC_PM_KEEP_POWER", + "MMC_CAP_SDIO_IRQ"; + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&nand { + status = "disabled"; + plat-names = "bootloader","nandnormal"; + plat-num = <2>; + plat-part-0 = <&bootloader>; + plat-part-1 = <&nandnormal>; + bootloader: bootloader{ + enable_pad ="ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <1>; + part_num = <0>; + rb_detect = <1>; + }; + nandnormal: nandnormal{ + enable_pad ="ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + plane_mode = "twoplane"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <2>; + part_num = <3>; + partition = <&nand_partitions>; + rb_detect = <1>; + }; + nand_partitions:nand_partition{ + /* + * if bl_mode is 1, tpl size was generate by + * fip_copies * fip_size which + * will not skip bad when calculating + * the partition size; + * + * if bl_mode is 0, + * tpl partition must be comment out. + */ + tpl{ + offset=<0x0 0x0>; + size=<0x0 0x0>; + }; + logo{ + offset=<0x0 0x0>; + size=<0x0 0x200000>; + }; + recovery{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + boot{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + system{ + offset=<0x0 0x0>; + size=<0x0 0x4000000>; + }; + data{ + offset=<0xffffffff 0xffffffff>; + size=<0x0 0x0>; + }; + }; +}; +&dwc3 { + status = "okay"; +}; + +&usb2_phy_v2 { + status = "okay"; + portnum = <2>; +}; + +&usb3_phy_v2 { + status = "okay"; + portnum = <0>; + otg = <1>; + gpio-vbus-power = "GPIOH_6"; + gpios = <&gpio GPIOH_6 GPIO_ACTIVE_HIGH>; +}; + +&dwc2_a { + status = "okay"; + /** 0: normal, 1: otg+dwc3 host only, 2: otg+dwc3 device only*/ + controller-type = <3>; +}; +ðmac { + status = "okay"; + pinctrl-names = "internal_eth_pins"; + pinctrl-0 = <&internal_eth_pins>; + mc_val = <0x4be04>; + + internal_phy=<1>; +}; + +&uart_A { + status = "okay"; +}; + +&pcie_A { + reset-gpio = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; + status = "okay"; +}; + +&saradc { + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_drm_buildroot.dts b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_drm_buildroot.dts new file mode 100644 index 000000000000..f22c04a4c4fa --- /dev/null +++ b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_drm_buildroot.dts @@ -0,0 +1,1471 @@ +/* + * arch/arm64/boot/dts/amlogic/g12b_a311d_w400_buildroot.dts + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +/dts-v1/; + +#include "mesong12b_a.dtsi" +#include "mesong12b_skt-panel.dtsi" +#include "mesong12a_drm.dtsi" + +/ { + model = "Amlogic"; + amlogic-dt-id = "g12b_w400_a"; + compatible = "amlogic, g12b"; + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + + aliases { + serial0 = &uart_AO; + serial1 = &uart_A; + serial2 = &uart_B; + serial3 = &uart_C; + serial4 = &uart_AO_B; + i2c0 = &i2c0; + i2c1 = &i2c1; + i2c2 = &i2c2; + i2c3 = &i2c3; + i2c4 = &i2c_AO; + tsensor0 = &p_tsensor; + tsensor1 = &d_tsensor; + }; + + memory@00000000 { + device_type = "memory"; + linux,usable-memory = <0x0 0x100000 0x0 0x7ff00000>; + }; + + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + /* global autoconfigured region for contiguous allocations */ + ramoops@0x07400000 { + compatible = "ramoops"; + reg = <0x0 0x07400000 0x0 0x00100000>; + record-size = <0x8000>; + console-size = <0x8000>; + ftrace-size = <0x20000>; + }; + + secmon_reserved:linux,secmon { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x400000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x05000000 0x0 0x400000>; + clear-map; + }; + + secos_reserved:linux,secos { + status = "disable"; + compatible = "amlogic, aml_secos_memory"; + reg = <0x0 0x05300000 0x0 0x2000000>; + no-map; + }; + logo_reserved:linux,meson-fb { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x800000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x7f800000 0x0 0x800000>; + }; + ion_cma_reserved:linux,ion-dev { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x8000000>; + alignment = <0x0 0x400000>; + }; + + //di_reserved:linux,di { + //compatible = "amlogic, di-mem"; + /* buffer_size = 3621952(yuv422 8bit) */ + /* 4179008(yuv422 10bit full pack mode) */ + /** 10x3621952=34.6M(0x23) support 8bit **/ + /** 10x4736064=45.2M(0x2e) support 12bit **/ + /** 10x4179008=40M(0x28) support 10bit **/ + //size = <0x0 0x2800000>; + //no-map; + //}; + /*di CMA pool */ + di_cma_reserved:linux,di_cma { + compatible = "shared-dma-pool"; + reusable; + /* buffer_size = 3621952(yuv422 8bit) + * | 4736064(yuv422 10bit) + * | 4074560(yuv422 10bit full pack mode) + * 10x3621952=34.6M(0x23) support 8bit + * 10x4736064=45.2M(0x2e) support 12bit + * 10x4074560=40M(0x28) support 10bit + */ + size = <0x0 0x02800000>; + alignment = <0x0 0x400000>; + }; + /* POST PROCESS MANAGER */ + ppmgr_reserved:linux,ppmgr { + compatible = "shared-dma-pool"; + size = <0x0 0x0>; + }; + codec_mm_cma:linux,codec_mm_cma { + compatible = "shared-dma-pool"; + reusable; + /* ion_codec_mm max can alloc size 80M*/ + size = <0x0 0x13400000>; + alignment = <0x0 0x400000>; + linux,contiguous-region; + }; + /* codec shared reserved */ + codec_mm_reserved:linux,codec_mm_reserved { + compatible = "amlogic, codec-mm-reserved"; + size = <0x0 0x0>; + alignment = <0x0 0x100000>; + //no-map; + }; + /* vdin0 CMA pool */ + vdin0_cma_reserved:linux,vdin0_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16+4 M */ + size = <0x0 0x04000000>; + alignment = <0x0 0x400000>; + }; + /* vdin1 CMA pool */ + vdin1_cma_reserved:linux,vdin1_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16 M */ + size = <0x0 0x04000000>; + alignment = <0x0 0x400000>; + }; + galcore_reserved:linux,galcore { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x0>; + alignment = <0x0 0x400000>; + linux,contiguous-region; + }; + + isp_cma_reserved:linux,isp_cma { + compatible = "shared-dma-pool"; + reusable; + status = "okay"; + size = <0x0 0x10000000>; + alignment = <0x0 0x400000>; + }; + + adapt_cma_reserved:linux,adapt_cma { + compatible = "shared-dma-pool"; + reusable; + status = "okay"; + size = <0x0 0x03000000>; + alignment = <0x0 0x400000>; + }; + gdc_cma_reserved:linux,gdc_cma { + compatible = "shared-dma-pool"; + reusable; + status = "okay"; + size = <0x0 0x04000000>; + alignment = <0x0 0x400000>; + }; + }; + galcore { + status = "okay"; + memory-region = <&galcore_reserved>; + }; + gpioleds { + compatible = "gpio-leds"; + status = "okay"; + + sys_led { + label="sys_led"; + gpios=<&gpio_ao GPIOAO_11 GPIO_ACTIVE_HIGH>; + default-state ="on"; + retain-state-suspended; + linux,default-trigger="cpu0"; + }; + }; + + cvbsout { + compatible = "amlogic, cvbsout-g12b"; + dev_name = "cvbsout"; + status = "okay"; + clocks = <&clkc CLKID_VCLK2_ENCI + &clkc CLKID_VCLK2_VENCI0 + &clkc CLKID_VCLK2_VENCI1 + &clkc CLKID_DAC_CLK>; + clock-names = "venci_top_gate", + "venci_0_gate", + "venci_1_gate", + "vdac_clk_gate"; + + /* performance: reg_address, reg_value */ + /* g12b */ + performance = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x8080 + 0x1b05 0xfd + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + performance_sarft = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x0 + 0x1b05 0x9 + 0x1c59 0xfc48 + 0xffff 0x0>; /* ending flag */ + }; + + bt-dev{ + compatible = "amlogic, bt-dev"; + dev_name = "bt-dev"; + status = "okay"; + gpio_reset = <&gpio GPIOX_17 GPIO_ACTIVE_HIGH>; + gpio_hostwake = <&gpio GPIOX_19 GPIO_ACTIVE_HIGH>; + }; + + wifi{ + compatible = "amlogic, aml_wifi"; + dev_name = "aml_wifi"; + status = "okay"; + interrupt_pin = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; + irq_trigger_type = "GPIO_IRQ_LOW"; + power_on_pin = <&gpio GPIOX_6 GPIO_ACTIVE_HIGH>; + dhd_static_buf; //if use bcm wifi, config dhd_static_buf + pinctrl-names = "default"; + pinctrl-0 = <&pwm_e_pins>; + pwm_config = <&wifi_pwm_conf>; + }; + + wifi_pwm_conf:wifi_pwm_conf{ + pwm_channel1_conf { + pwms = <&pwm_ef MESON_PWM_0 30541 0>; + duty-cycle = <15270>; + times = <10>; + }; + pwm_channel2_conf { + pwms = <&pwm_ef MESON_PWM_2 30500 0>; + duty-cycle = <15250>; + times = <12>; + }; + }; + + codec_mm { + compatible = "amlogic, codec, mm"; + memory-region = <&codec_mm_cma &codec_mm_reserved>; + dev_name = "codec_mm"; + status = "okay"; + }; + + ppmgr { + compatible = "amlogic, ppmgr"; + memory-region = <&ppmgr_reserved>; + dev_name = "ppmgr"; + status = "okay"; + }; + + deinterlace { + compatible = "amlogic, deinterlace"; + status = "okay"; + /* 0:use reserved; 1:use cma; 2:use cma as reserved */ + flag_cma = <1>; + //memory-region = <&di_reserved>; + memory-region = <&di_cma_reserved>; + interrupts = <0 46 1 + 0 40 1>; + interrupt-names = "pre_irq", "post_irq"; + clocks = <&clkc CLKID_VPU_CLKB_TMP_COMP>, + <&clkc CLKID_VPU_CLKB_COMP>; + clock-names = "vpu_clkb_tmp_composite", + "vpu_clkb_composite"; + clock-range = <334 667>; + /* buffer-size = <3621952>;(yuv422 8bit) */ + buffer-size = <4074560>;/*yuv422 fullpack*/ + /* reserve-iomap = "true"; */ + /* if enable nr10bit, set nr10bit-support to 1 */ + post-wr-support = <1>; + nr10bit-support = <1>; + nrds-enable = <1>; + pps-enable = <1>; + }; + ionvideo { + compatible = "amlogic, ionvideo"; + dev_name = "ionvideo"; + status = "okay"; + }; + + + partitions: partitions{ + parts = <14>; + part-0 = <&logo>; + part-1 = <&recovery>; + part-2 = <&misc>; + part-3 = <&dto>; + part-4 = <&cri_data>; + part-5 = <¶m>; + part-6 = <&boot>; + part-7 = <&rsv>; + part-8 = <&tee>; + part-9 = <&vendor>; + part-10 = <&odm>; + part-11 = <&system>; + part-12 = <&cache>; + part-13 = <&data>; + + logo:logo{ + pname = "logo"; + size = <0x0 0x800000>; + mask = <1>; + }; + recovery:recovery{ + pname = "recovery"; + size = <0x0 0x1800000>; + mask = <1>; + }; + misc:misc{ + pname = "misc"; + size = <0x0 0x800000>; + mask = <1>; + }; + dto:dto{ + pname = "dto"; + size = <0x0 0x800000>; + mask = <1>; + }; + cri_data:cri_data{ + pname = "cri_data"; + size = <0x0 0x800000>; + mask = <2>; + }; + rsv:rsv{ + pname = "rsv"; + size = <0x0 0x1000000>; + mask = <1>; + }; + param:param{ + pname = "param"; + size = <0x0 0x1000000>; + mask = <2>; + }; + boot:boot{ + pname = "boot"; + size = <0x0 0x1000000>; + mask = <1>; + }; + tee:tee{ + pname = "tee"; + size = <0x0 0x2000000>; + mask = <1>; + }; + vendor:vendor{ + pname = "vendor"; + size = <0x0 0x10000000>; + mask = <1>; + }; + odm:odm{ + pname = "odm"; + size = <0x0 0x10000000>; + mask = <1>; + }; + system:system{ + pname = "system"; + size = <0x0 0x80000000>; + mask = <1>; + }; + cache:cache{ + pname = "cache"; + size = <0x0 0x46000000>; + mask = <2>; + }; + data:data{ + pname = "data"; + size = <0xffffffff 0xffffffff>; + mask = <4>; + }; + }; + + gpio_keypad { + compatible = "amlogic, gpio_keypad"; + status = "okay"; + scan_period = <20>; + key_num = <1>; + key_name = "power"; + key_code = <116>; + key-gpios = <&gpio_ao GPIOAO_3 GPIO_ACTIVE_HIGH>; + detect_mode = <0>;/*0:polling mode, 1:irq mode*/ + }; + + adc_keypad { + compatible = "amlogic, adc_keypad"; + status = "okay"; + key_name = "vol-", "vol+", "enter"; + key_num = <3>; + io-channels = <&saradc SARADC_CH2>; + io-channel-names = "key-chan-2"; + key_chan = ; + key_code = <114 115 28>; + key_val = <143 266 389>; //val=voltage/1800mV*1023 + key_tolerance = <40 40 40>; + }; + + unifykey{ + compatible = "amlogic, unifykey"; + status = "ok"; + unifykey-num = <15>; + unifykey-index-0 = <&keysn_0>; + unifykey-index-1 = <&keysn_1>; + unifykey-index-2 = <&keysn_2>; + unifykey-index-3 = <&keysn_3>; + unifykey-index-4 = <&keysn_4>; + unifykey-index-5 = <&keysn_5>; + unifykey-index-6 = <&keysn_6>; + unifykey-index-7 = <&keysn_7>; + unifykey-index-8 = <&keysn_8>; + unifykey-index-9 = <&keysn_9>; + unifykey-index-10= <&keysn_10>; + unifykey-index-11= <&keysn_11>; + unifykey-index-12= <&keysn_12>; + unifykey-index-13= <&keysn_13>; + unifykey-index-14= <&keysn_14>; + + keysn_0: key_0{ + key-name = "usid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_1:key_1{ + key-name = "mac"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_2:key_2{ + key-name = "hdcp"; + key-device = "secure"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_3:key_3{ + key-name = "secure_boot_set"; + key-device = "efuse"; + key-permit = "write"; + }; + keysn_4:key_4{ + key-name = "mac_bt"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_5:key_5{ + key-name = "mac_wifi"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_6:key_6{ + key-name = "hdcp2_tx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_7:key_7{ + key-name = "hdcp2_rx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_8:key_8{ + key-name = "widevinekeybox"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_9:key_9{ + key-name = "deviceid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_10:key_10{ + key-name = "hdcp22_fw_private"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_11:key_11{ + key-name = "PlayReadykeybox25"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_12:key_12{ + key-name = "prpubkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_13:key_13{ + key-name = "prprivkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_14:key_14{ + key-name = "netflix_mgkid"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + };//End unifykey + + amlvecm { + compatible = "amlogic, vecm"; + dev_name = "aml_vecm"; + status = "okay"; + gamma_en = <0>;/*1:enabel ;0:disable*/ + wb_en = <0>;/*1:enabel ;0:disable*/ + cm_en = <0>;/*1:enabel ;0:disable*/ + }; + amdolby_vision { + compatible = "amlogic, dolby_vision_g12a"; + dev_name = "aml_amdolby_vision_driver"; + status = "okay"; + tv_mode = <0>;/*1:enabel ;0:disable*/ + }; + + /* Audio Related start */ + pdm_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, pdm_dummy_codec"; + status = "okay"; + }; + dummy_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, aml_dummy_codec"; + status = "okay"; + }; + amlogic_codec:t9015{ + #sound-dai-cells = <0>; + compatible = "amlogic, aml_codec_T9015"; + reg = <0x0 0xFF632000 0x0 0x2000>; + is_auge_used = <1>; /* meson or auge chipset used */ + tdmout_index = <1>; + status = "okay"; + }; + audio_effect:eqdrc{ + /*eq_enable = <1>;*/ + /*drc_enable = <1>;*/ + /* + * 0:tdmout_a + * 1:tdmout_b + * 2:tdmout_c + * 3:spdifout + * 4:spdifout_b + */ + eqdrc_module = <1>; + /* max 0xf, each bit for one lane, usually one lane */ + lane_mask = <0x1>; + /* max 0xff, each bit for one channel */ + channel_mask = <0x3>; + }; + auge_sound { + compatible = "amlogic, g12a-sound-card"; + aml-audio-card,name = "AML-AUGESOUND"; + + //aml-audio-card,loopback = <&aml_loopback>; + //aml-audio-card,aux-devs = <&amlogic_codec>; + /*avout mute gpio*/ + avout_mute-gpios = <&gpio_ao GPIOAO_2 GPIO_ACTIVE_HIGH>; + /*for audio effect ,eqdrc */ + aml-audio-card,effect = <&audio_effect>; + + aml-audio-card,dai-link@0 { + format = "dsp_a"; + mclk-fs = <512>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + //bitclock-master = <&tdmacodec>; + //frame-master = <&tdmacodec>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-pcm"; + tdmacpu: cpu { + sound-dai = <&aml_tdma>; + dai-tdm-slot-tx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-rx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-num = <8>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <24576000>; + }; + tdmacodec: codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@1 { + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + bitclock-master = <&aml_tdmb>; + frame-master = <&aml_tdmb>; + //bitclock-master = <&tdmbcodec>; + //frame-master = <&tdmbcodec>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-i2s"; + cpu { + sound-dai = <&aml_tdmb>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmbcodec: codec { + sound-dai = <&dummy_codec &dummy_codec + &amlogic_codec &ad82584f_62>; + }; + }; + + aml-audio-card,dai-link@2 { + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + bitclock-master = <&aml_tdmc>; + frame-master = <&aml_tdmc>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + //suffix-name = "alsaPORT-tdm"; + cpu { + sound-dai = <&aml_tdmc>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@3 { + mclk-fs = <64>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-pdm"; + cpu { + sound-dai = <&aml_pdm>; + }; + codec { + sound-dai = <&pdm_codec>; + }; + }; + + aml-audio-card,dai-link@4 { + mclk-fs = <128>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-spdif"; + cpu { + sound-dai = <&aml_spdif>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + }; + audiolocker: locker { + compatible = "amlogic, audiolocker"; + clocks = <&clkaudio CLKID_AUDIO_LOCKER_OUT + &clkaudio CLKID_AUDIO_LOCKER_IN + &clkaudio CLKID_AUDIO_MCLK_D + &clkaudio CLKID_AUDIO_MCLK_E + &clkc CLKID_MPLL1 + &clkc CLKID_MPLL2>; + clock-names = "lock_out", "lock_in", "out_src", + "in_src", "out_calc", "in_ref"; + interrupts = ; + interrupt-names = "irq"; + frequency = <49000000>; /* pll */ + dividor = <49>; /* locker's parent */ + status = "okay"; + }; + /* Audio Related end */ + + cpu_opp_table0: cpu_opp_table0 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <731000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <731000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <731000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <731000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <731000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <731000>; + }; + opp06 { + opp-hz = /bits/ 64 <1398000000>; + opp-microvolt = <761000>; + }; + opp07 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <791000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <831000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <861000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <981000>; + }; + }; + + cpu_opp_table1: cpu_opp_table1 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <751000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <751000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <751000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <751000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <771000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <771000>; + }; + opp06 { + opp-hz = /bits/ 64 <1398000000>; + opp-microvolt = <791000>; + }; + opp07 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <821000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <861000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <891000>; + }; + }; + + cpufreq-meson { + compatible = "amlogic, cpufreq-meson"; + status = "okay"; + }; + + sensor: sensor { + compatible = "soc, sensor"; + status = "okay"; + sensor-name = "imx290"; /*imx290;os08a10;imx227*/ + pinctrl-names="default"; + pinctrl-0=<&clk12_24_z_pins>; + clocks = <&clkc CLKID_24M>; + clock-names = "g12a_24m"; + reset = <&gpio GPIOZ_12 GPIO_ACTIVE_HIGH>; + ir_cut_gpio = <&gpio GPIOZ_11 GPIO_ACTIVE_HIGH + &gpio GPIOZ_7 GPIO_ACTIVE_HIGH>; + }; + + iq: iq { + compatible = "soc, iq"; + status = "okay"; + sensor-name = "imx290"; /*imx290;os08a10;imx227*/ + }; +}; /* end of / */ + +&i2c2 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&i2c2_master_pins2>; + clock-frequency = <100000>; /* default 100k */ + sensor-i2c@6c { + compatible = "arm, i2c-sensor"; + reg = <0x6c>; + reg-names = "i2c-sensor"; + slave-addr = <0x6c>; + reg-type = <2>; + reg-data-type = <1>; + link-device = <&phycsi>; + }; +}; + +&isp { + status = "okay"; + memory-region = <&isp_cma_reserved>; +}; + +&adapter { + status = "okay"; + memory-region = <&adapt_cma_reserved>; +}; + +&gdc { + status = "okay"; + memory-region = <&gdc_cma_reserved>; +}; + +&meson_fb { + status = "disable"; + display_size_default = <1920 1080 1920 2160 32>; + mem_size = <0x00800000 0x1980000 0x100000 0x100000 0x800000>; + logo_addr = "0x7f800000"; + mem_alloc = <1>; + pxp_mode = <0>; /** 0:normal mode 1:pxp mode */ +}; + +&drm_vpu { + status = "okay"; + compatible = "amlogic,meson-g12b-vpu"; + logo_addr = "0x7f800000"; +}; + +&drm_amhdmitx { + status = "okay"; + hdcp = "disabled"; +}; + +&drm_lcd { + status = "disable"; +}; + +&pwm_ab { + status = "okay"; + }; + +&pwm_ef { + status = "okay"; + }; + +&pwm_AO_cd { + status = "okay"; + }; + +&i2c0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_master_pins2>; + clock-frequency = <400000>; + + touchscreen@38 { + compatible = "focaltech,fts"; + status = "disabled"; + reg = <0x38>; + reset-gpio = <&gpio GPIOZ_9 GPIO_ACTIVE_HIGH>; + irq-gpio = <&gpio GPIOZ_3 GPIO_ACTIVE_HIGH>; + x_max = <720>; + y_max = <1280>; + max-touch-number = <10>; + }; +}; + +&i2c3 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&i2c3_master_pins2>; + clock-frequency = <100000>; /* default 100k */ + + /* for ref board */ + ad82584f_62: ad82584f_62@62 { + compatible = "ESMT, ad82584f"; + #sound-dai-cells = <0>; + reg = <0x31>; + status = "okay"; + reset_pin = <&gpio GPIOA_5 0>; + }; + + tlv320adc3101_32: tlv320adc3101_32@32 { + compatible = "ti,tlv320adc3101"; + #sound-dai-cells = <0>; + reg = <0x19>; + differential_pair = <1>; + status = "disabled"; + }; + + bl_extern_i2c { + compatible = "bl_extern, i2c"; + dev_name = "lp8556"; + reg = <0x2c>; + status = "disabled"; + }; +}; + +&audiobus { + aml_tdma: tdma { + compatible = "amlogic, g12a-snd-tdma"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 1>; + dai-tdm-oe-lane-slot-mask-out = <1 0>; + dai-tdm-clk-sel = <0>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_A + &clkc CLKID_MPLL0>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmout_a &tdmin_a>; + }; + + aml_tdmb: tdmb { + compatible = "amlogic, g12a-snd-tdmb"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 1 0 0>; + dai-tdm-lane-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <1>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_B + &clkc CLKID_MPLL1 + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; + /* + * 0: tdmout_a; + * 1: tdmout_b; + * 2: tdmout_c; + * 3: spdifout; + * 4: spdifout_b; + */ + samesource_sel = <3>; + }; + + aml_tdmc: tdmc { + compatible = "amlogic, g12a-snd-tdmc"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <1 0 0 0>; + #dai-tdm-lane-slot-mask-out = <1 0 1 1>; + #dai-tdm-lane-oe-slot-mask-in = <0 0 0 0>; + #dai-tdm-lane-oe-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <2>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmc_mclk &tdmout_c &tdmin_c>; + }; + + /* copy a useless tdm to output for hdmi, no pinmux */ + aml_i2s2hdmi: i2s2hdmi { + compatible = "amlogic, g12a-snd-tdmc"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-out = <1 1 1 1>; + dai-tdm-clk-sel = <2>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + + i2s2hdmi = <1>; + + status = "okay"; + }; + + aml_spdif: spdif { + compatible = "amlogic, g12a-snd-spdif-a"; + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 + &clkc CLKID_FCLK_DIV4 + &clkaudio CLKID_AUDIO_SPDIFIN + &clkaudio CLKID_AUDIO_SPDIFOUT + &clkaudio CLKID_AUDIO_SPDIFIN_CTRL + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "sysclk", "fixed_clk", "gate_spdifin", + "gate_spdifout", "clk_spdifin", "clk_spdifout"; + interrupts = + ; + + interrupt-names = "irq_spdifin"; + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; + pinctrl-0 = <&spdifout &spdifin>; + pinctrl-1 = <&spdifout_a_mute>; + status = "okay"; + }; + aml_spdif_b: spdif_b { + compatible = "amlogic, g12a-snd-spdif-b"; + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 /*CLKID_HIFI_PLL*/ + &clkaudio CLKID_AUDIO_SPDIFOUTB + &clkaudio CLKID_AUDIO_SPDIFOUTB_CTRL>; + clock-names = "sysclk", + "gate_spdifout", "clk_spdifout"; + status = "disabled"; + }; + aml_pdm: pdm { + compatible = "amlogic, g12a-snd-pdm"; + #sound-dai-cells = <0>; + clocks = <&clkaudio CLKID_AUDIO_PDM + &clkc CLKID_FCLK_DIV3 + &clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_PDMIN0 + &clkaudio CLKID_AUDIO_PDMIN1>; + clock-names = "gate", + "sysclk_srcpll", + "dclk_srcpll", + "pdm_dclk", + "pdm_sysclk"; + pinctrl-names = "pdm_pins"; + pinctrl-0 = <&pdmin>; + filter_mode = <1>; /* mode 0~4, defalut:1 */ + status = "okay"; + }; + aml_loopback: loopback { + compatible = "amlogic, snd-loopback"; + /* + * 0: out rate = in data rate; + * 1: out rate = loopback data rate; + */ + lb_mode = <0>; + + /* datain src + * 0: tdmin_a; + * 1: tdmin_b; + * 2: tdmin_c; + * 3: spdifin; + * 4: pdmin; + */ + datain_src = <4>; + datain_chnum = <8>; + datain_chmask = <0x3f>; + + /* tdmin_lb src + * 0: tdmoutA + * 1: tdmoutB + * 2: tdmoutC + * 3: PAD_tdminA + * 4: PAD_tdminB + * 5: PAD_tdminC + */ + datalb_src = <2>; + datalb_chnum = <8>; + datalb_chmask = <0x3>; + + status = "disabled"; + }; + + audioresample: resample { + compatible = "amlogic, g12a-resample"; + clocks = <&clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_MCLK_F + &clkaudio CLKID_AUDIO_RESAMPLE_CTRL>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + /*same with toddr_src + * TDMIN_A, 0 + * TDMIN_B, 1 + * TDMIN_C, 2 + * SPDIFIN, 3 + * PDMIN, 4 + * NONE, + * TDMIN_LB, 6 + * LOOPBACK, 7 + */ + resample_module = <4>; + status = "disabled"; + }; + aml_pwrdet: pwrdet { + compatible = "amlogic, g12a-power-detect"; + + interrupts = ; + interrupt-names = "pwrdet_irq"; + + /* pwrdet source sel + * 7: loopback; + * 6: tdmin_lb; + * 5: reserved; + * 4: pdmin; + * 3: spdifin; + * 2: tdmin_c; + * 1: tdmin_b; + * 0: tdmin_a; + */ + pwrdet_src = <4>; + + hi_th = <0x70000>; + lo_th = <0x16000>; + + status = "disabled"; + }; +}; /* end of audiobus */ + +&pinctrl_periphs { + tdmout_a: tdmout_a { + mux { /* GPIOX_11, GPIOX_10, GPIOX_9 */ + groups = "tdma_sclk", + "tdma_fs", + "tdma_dout0"; + function = "tdma_out"; + }; + }; + + tdmin_a: tdmin_a { + mux { /* GPIOX_8 */ + groups = "tdma_din1"; + function = "tdma_in"; + }; + }; + + tdmb_mclk: tdmb_mclk { + mux { + groups = "mclk0_a"; + function = "mclk0"; + drive-strength = <2>; + }; + }; + tdmout_b: tdmout_b { + mux { /* GPIOA_1, GPIOA_2, GPIOA_3 */ + groups = "tdmb_sclk", + "tdmb_fs", + "tdmb_dout0"; + function = "tdmb_out"; + drive-strength = <2>; + }; + }; + + tdmin_b:tdmin_b { + mux { /* GPIOA_4 */ + groups = "tdmb_din1" + /*,"tdmb_slv_sclk", "tdmb_slv_fs"*/; + function = "tdmb_in"; + drive-strength = <2>; + }; + }; + + tdmc_mclk: tdmc_mclk { + mux { /* GPIOA_11 */ + groups = "mclk1_a"; + function = "mclk1"; + }; + }; + + clk12_24_z_pins:clk12_24_z_pins { + mux { + groups = "clk12_24_z"; + function = "clk12_24_ee"; + drive-strength = <3>; + }; + }; + + tdmout_c:tdmout_c { + mux { /* GPIOA_12, GPIOA_13, GPIOA_8, GPIOA_7*/ + groups = "tdmc_sclk_a", + "tdmc_fs_a", + "tdmc_dout0_a" + /*, "tdmc_dout2", + * "tdmc_dout3" + */; + function = "tdmc_out"; + }; + }; + + tdmin_c:tdmin_c { + mux { /* GPIOA_10 */ + groups = "tdmc_din0_a"; + function = "tdmc_in"; + }; + }; + + spdifin: spdifin { + mux {/* GPIOH_5 */ + groups = "spdif_in_h"; + function = "spdif_in"; + }; + }; + + /* GPIOH_4 */ + /* + * spdifout: spdifout { + * mux { + * groups = "spdif_out_h"; + * function = "spdif_out"; + * }; + *}; + */ + + pdmin: pdmin { + mux { /* gpioa_5, gpioa_6, gpioa_7, gpioa_8, gpioa_9*/ + groups = "pdm_din0_a", + /*"pdm_din1_a",*/ + "pdm_din2_a", + /*"pdm_din3_a",*/ + "pdm_dclk_a"; + function = "pdm"; + }; + }; + + bl_pwm_off_pins:bl_pwm_off_pin { + mux { + pins = "GPIOH_5"; + function = "gpio_periphs"; + output-high; + }; + }; + +}; /* end of pinctrl_periphs */ + +&pinctrl_aobus { + spdifout: spdifout { + mux { /* gpiao_10 */ + groups = "spdif_out_ao"; + function = "spdif_out_ao"; + }; + }; + + spdifout_a_mute: spdifout_a_mute { + mux { /* gpiao_10 */ + groups = "GPIOAO_10"; + function = "gpio_aobus"; + }; + }; +}; /* end of pinctrl_aobus */ + +&irblaster { + status = "disabled"; +}; + +&audio_data { + status = "okay"; +}; + +/*if you want to use vdin just modify status to "ok"*/ +&vdin0 { + memory-region = <&vdin0_cma_reserved>; + status = "okay"; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + *bit4:support yuv422 10bit full pack mode (from txl new add) + */ + tv_bit_mode = <0x15>; +}; +&vdin1 { + memory-region = <&vdin1_cma_reserved>; + status = "okay"; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + */ + tv_bit_mode = <1>; +}; + +&sd_emmc_c { + status = "okay"; + emmc { + caps = "MMC_CAP_8_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + /* "MMC_CAP_1_8V_DDR", */ + "MMC_CAP_HW_RESET", + "MMC_CAP_ERASE", + "MMC_CAP_CMD23"; + caps2 = "MMC_CAP2_HS200"; + /* "MMC_CAP2_HS400";*/ + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&sd_emmc_b { + status = "okay"; + sd { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED"; + f_min = <400000>; + f_max = <50000000>; + }; +}; + +&sd_emmc_a { + status = "okay"; + sdio { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + "MMC_CAP_UHS_SDR12", + "MMC_CAP_UHS_SDR25", + "MMC_CAP_UHS_SDR50", + "MMC_CAP_UHS_SDR104", + "MMC_PM_KEEP_POWER", + "MMC_CAP_SDIO_IRQ"; + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&nand { + status = "disabled"; + plat-names = "bootloader","nandnormal"; + plat-num = <2>; + plat-part-0 = <&bootloader>; + plat-part-1 = <&nandnormal>; + bootloader: bootloader{ + enable_pad ="ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <1>; + part_num = <0>; + rb_detect = <1>; + }; + nandnormal: nandnormal{ + enable_pad ="ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + plane_mode = "twoplane"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <2>; + part_num = <3>; + partition = <&nand_partitions>; + rb_detect = <1>; + }; + nand_partitions:nand_partition{ + /* + * if bl_mode is 1, tpl size was generate by + * fip_copies * fip_size which + * will not skip bad when calculating + * the partition size; + * + * if bl_mode is 0, + * tpl partition must be comment out. + */ + tpl{ + offset=<0x0 0x0>; + size=<0x0 0x0>; + }; + logo{ + offset=<0x0 0x0>; + size=<0x0 0x200000>; + }; + recovery{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + boot{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + system{ + offset=<0x0 0x0>; + size=<0x0 0x4000000>; + }; + data{ + offset=<0xffffffff 0xffffffff>; + size=<0x0 0x0>; + }; + }; +}; +&dwc3 { + status = "okay"; +}; + +&usb2_phy_v2 { + status = "okay"; + portnum = <2>; +}; + +&usb3_phy_v2 { + status = "okay"; + portnum = <0>; + otg = <1>; + gpio-vbus-power = "GPIOH_6"; + gpios = <&gpio GPIOH_6 GPIO_ACTIVE_HIGH>; +}; + +&dwc2_a { + status = "okay"; + /** 0: normal, 1: otg+dwc3 host only, 2: otg+dwc3 device only*/ + controller-type = <3>; +}; +ðmac { + status = "okay"; +/* //conflict with isp i2c + * pinctrl-names = "internal_eth_pins"; + * pinctrl-0 = <&internal_eth_pins>; + */ + mc_val = <0x4be04>; + + internal_phy=<1>; +}; + +&uart_A { + status = "okay"; +}; + +&pcie_A { + reset-gpio = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; + status = "okay"; +}; + +&saradc { + status = "okay"; +}; + +&spicc1 { + status = "disabled"; + pinctrl-names = "default"; + pinctrl-0 = <&spicc1_pins>; + cs-gpios = <&gpio GPIOH_6 0>; +}; diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot.dts b/arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot.dts new file mode 100644 index 000000000000..63f6b0d72f9b --- /dev/null +++ b/arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot.dts @@ -0,0 +1,1477 @@ +/* + * arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot.dts + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +/dts-v1/; + +#include "mesong12b.dtsi" + +/ { + model = "Amlogic"; + amlogic-dt-id = "g12b_w411_b"; + compatible = "amlogic, g12b"; + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + + aliases { + serial0 = &uart_AO; + serial1 = &uart_A; + serial2 = &uart_B; + serial3 = &uart_C; + serial4 = &uart_AO_B; + i2c0 = &i2c0; + i2c1 = &i2c1; + i2c2 = &i2c2; + i2c3 = &i2c3; + i2c4 = &i2c_AO; + tsensor0 = &p_tsensor; + tsensor1 = &d_tsensor; + }; + + memory@00000000 { + device_type = "memory"; + linux,usable-memory = <0x0 0x0 0x0 0x40000000>; + }; + + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + /* global autoconfigured region for contiguous allocations */ + ramoops@0x07400000 { + compatible = "ramoops"; + reg = <0x0 0x07400000 0x0 0x00100000>; + record-size = <0x8000>; + console-size = <0x8000>; + ftrace-size = <0x20000>; + }; + + secmon_reserved:linux,secmon { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x400000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x05000000 0x0 0x400000>; + clear-map; + }; + + secos_reserved:linux,secos { + status = "disable"; + compatible = "amlogic, aml_secos_memory"; + reg = <0x0 0x05300000 0x0 0x2000000>; + no-map; + }; + logo_reserved:linux,meson-fb { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x800000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x3f800000 0x0 0x800000>; + }; + ion_cma_reserved:linux,ion-dev { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x8000000>; + alignment = <0x0 0x400000>; + }; + + //di_reserved:linux,di { + //compatible = "amlogic, di-mem"; + /* buffer_size = 3621952(yuv422 8bit) */ + /* 4179008(yuv422 10bit full pack mode) */ + /** 10x3621952=34.6M(0x23) support 8bit **/ + /** 10x4736064=45.2M(0x2e) support 12bit **/ + /** 10x4179008=40M(0x28) support 10bit **/ + //size = <0x0 0x2800000>; + //no-map; + //}; + /*di CMA pool */ + di_cma_reserved:linux,di_cma { + compatible = "shared-dma-pool"; + reusable; + /* buffer_size = 3621952(yuv422 8bit) + * | 4736064(yuv422 10bit) + * | 4074560(yuv422 10bit full pack mode) + * 10x3621952=34.6M(0x23) support 8bit + * 10x4736064=45.2M(0x2e) support 12bit + * 10x4074560=40M(0x28) support 10bit + */ + size = <0x0 0x02800000>; + alignment = <0x0 0x400000>; + }; + /* POST PROCESS MANAGER */ + ppmgr_reserved:linux,ppmgr { + compatible = "shared-dma-pool"; + size = <0x0 0x0>; + }; + codec_mm_cma:linux,codec_mm_cma { + compatible = "shared-dma-pool"; + reusable; + /* ion_codec_mm max can alloc size 80M*/ + size = <0x0 0x5000000>; + alignment = <0x0 0x400000>; + linux,contiguous-region; + }; + /* codec shared reserved */ + codec_mm_reserved:linux,codec_mm_reserved { + compatible = "amlogic, codec-mm-reserved"; + size = <0x0 0x0>; + alignment = <0x0 0x100000>; + //no-map; + }; + /* vdin0 CMA pool */ + // vdin0_cma_reserved:linux,vdin0_cma { + // compatible = "shared-dma-pool"; + // reusable; + /* 1920x1080x2x4 =16+4 M */ + // size = <0x0 0x04000000>; + // alignment = <0x0 0x400000>; + // }; + /* vdin1 CMA pool */ + // vdin1_cma_reserved:linux,vdin1_cma { + // compatible = "shared-dma-pool"; + // reusable; + /* 1920x1080x2x4 =16 M */ + // size = <0x0 0x04000000>; + // alignment = <0x0 0x400000>; + // }; + galcore_reserved:linux,galcore { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x0>; + alignment = <0x0 0x400000>; + linux,contiguous-region; + }; + + isp_cma_reserved:linux,isp_cma { + compatible = "shared-dma-pool"; + reusable; + status = "okay"; + size = <0x0 0x3c00000>; + alignment = <0x0 0x400000>; + }; + + adapt_cma_reserved:linux,adapt_cma { + compatible = "shared-dma-pool"; + reusable; + status = "okay"; + size = <0x0 0x1800000>; + alignment = <0x0 0x400000>; + }; + gdc_cma_reserved:linux,gdc_cma { + compatible = "shared-dma-pool"; + reusable; + status = "okay"; + size = <0x0 0x04000000>; + alignment = <0x0 0x400000>; + }; + }; + galcore { + status = "okay"; + memory-region = <&galcore_reserved>; + }; + gpioleds { + compatible = "gpio-leds"; + status = "okay"; + + sys_led { + label="sys_led"; + gpios=<&gpio_ao GPIOAO_11 GPIO_ACTIVE_HIGH>; + default-state ="on"; + }; + }; + + cvbsout { + compatible = "amlogic, cvbsout-g12b"; + dev_name = "cvbsout"; + status = "okay"; + clocks = <&clkc CLKID_VCLK2_ENCI + &clkc CLKID_VCLK2_VENCI0 + &clkc CLKID_VCLK2_VENCI1 + &clkc CLKID_DAC_CLK>; + clock-names = "venci_top_gate", + "venci_0_gate", + "venci_1_gate", + "vdac_clk_gate"; + + /* performance: reg_address, reg_value */ + /* g12b */ + performance = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x8080 + 0x1b05 0xfd + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + performance_sarft = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x0 + 0x1b05 0x9 + 0x1c59 0xfc48 + 0xffff 0x0>; /* ending flag */ + }; + + bt-dev{ + compatible = "amlogic, bt-dev"; + dev_name = "bt-dev"; + status = "okay"; + gpio_reset = <&gpio GPIOX_17 GPIO_ACTIVE_HIGH>; + gpio_hostwake = <&gpio GPIOX_19 GPIO_ACTIVE_HIGH>; + }; + + wifi{ + compatible = "amlogic, aml_wifi"; + dev_name = "aml_wifi"; + status = "okay"; + interrupt_pin = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; + irq_trigger_type = "GPIO_IRQ_LOW"; + power_on_pin = <&gpio GPIOX_6 GPIO_ACTIVE_HIGH>; + dhd_static_buf; //if use bcm wifi, config dhd_static_buf + pinctrl-names = "default"; + pinctrl-0 = <&pwm_e_pins>; + pwm_config = <&wifi_pwm_conf>; + }; + + wifi_pwm_conf:wifi_pwm_conf{ + pwm_channel1_conf { + pwms = <&pwm_ef MESON_PWM_0 30541 0>; + duty-cycle = <15270>; + times = <10>; + }; + pwm_channel2_conf { + pwms = <&pwm_ef MESON_PWM_2 30500 0>; + duty-cycle = <15250>; + times = <12>; + }; + }; + + codec_mm { + compatible = "amlogic, codec, mm"; + memory-region = <&codec_mm_cma &codec_mm_reserved>; + dev_name = "codec_mm"; + status = "okay"; + }; + + ppmgr { + compatible = "amlogic, ppmgr"; + memory-region = <&ppmgr_reserved>; + dev_name = "ppmgr"; + status = "okay"; + }; + + deinterlace { + compatible = "amlogic, deinterlace"; + status = "okay"; + /* 0:use reserved; 1:use cma; 2:use cma as reserved */ + flag_cma = <1>; + //memory-region = <&di_reserved>; + memory-region = <&di_cma_reserved>; + interrupts = <0 46 1 + 0 40 1>; + interrupt-names = "pre_irq", "post_irq"; + clocks = <&clkc CLKID_VPU_CLKB_TMP_COMP>, + <&clkc CLKID_VPU_CLKB_COMP>; + clock-names = "vpu_clkb_tmp_composite", + "vpu_clkb_composite"; + clock-range = <334 667>; + /* buffer-size = <3621952>;(yuv422 8bit) */ + buffer-size = <4074560>;/*yuv422 fullpack*/ + /* reserve-iomap = "true"; */ + /* if enable nr10bit, set nr10bit-support to 1 */ + post-wr-support = <1>; + nr10bit-support = <1>; + nrds-enable = <1>; + pps-enable = <1>; + }; + ionvideo { + compatible = "amlogic, ionvideo"; + dev_name = "ionvideo"; + status = "okay"; + }; + + + partitions: partitions{ + parts = <14>; + part-0 = <&logo>; + part-1 = <&recovery>; + part-2 = <&misc>; + part-3 = <&dto>; + part-4 = <&cri_data>; + part-5 = <¶m>; + part-6 = <&boot>; + part-7 = <&rsv>; + part-8 = <&tee>; + part-9 = <&vendor>; + part-10 = <&odm>; + part-11 = <&system>; + part-12 = <&cache>; + part-13 = <&data>; + + logo:logo{ + pname = "logo"; + size = <0x0 0x800000>; + mask = <1>; + }; + recovery:recovery{ + pname = "recovery"; + size = <0x0 0x1800000>; + mask = <1>; + }; + misc:misc{ + pname = "misc"; + size = <0x0 0x800000>; + mask = <1>; + }; + dto:dto{ + pname = "dto"; + size = <0x0 0x800000>; + mask = <1>; + }; + cri_data:cri_data{ + pname = "cri_data"; + size = <0x0 0x800000>; + mask = <2>; + }; + rsv:rsv{ + pname = "rsv"; + size = <0x0 0x1000000>; + mask = <1>; + }; + param:param{ + pname = "param"; + size = <0x0 0x1000000>; + mask = <2>; + }; + boot:boot{ + pname = "boot"; + size = <0x0 0x1000000>; + mask = <1>; + }; + tee:tee{ + pname = "tee"; + size = <0x0 0x2000000>; + mask = <1>; + }; + vendor:vendor{ + pname = "vendor"; + size = <0x0 0x10000000>; + mask = <1>; + }; + odm:odm{ + pname = "odm"; + size = <0x0 0x10000000>; + mask = <1>; + }; + system:system{ + pname = "system"; + size = <0x0 0x80000000>; + mask = <1>; + }; + cache:cache{ + pname = "cache"; + size = <0x0 0x46000000>; + mask = <2>; + }; + data:data{ + pname = "data"; + size = <0xffffffff 0xffffffff>; + mask = <4>; + }; + }; + + gpio_keypad { + compatible = "amlogic, gpio_keypad"; + status = "okay"; + scan_period = <20>; + key_num = <1>; + key_name = "wificonfig"; + key_code = <139>; + key-gpios = <&gpio_ao GPIOAO_3 GPIO_ACTIVE_HIGH>; + detect_mode = <0>;/*0:polling mode, 1:irq mode*/ + }; + + adc_keypad { + compatible = "amlogic, adc_keypad"; + status = "disabled"; + key_name = "vol-", "vol+", "enter", "wificonfig"; + key_num = <4>; + io-channels = <&saradc SARADC_CH2>; + io-channel-names = "key-chan-2"; + key_chan = ; + key_code = <114 115 28 139>; + key_val = <143 266 389 0>; //val=voltage/1800mV*1023 + key_tolerance = <40 40 40 40>; + }; + + unifykey{ + compatible = "amlogic, unifykey"; + status = "ok"; + unifykey-num = <14>; + unifykey-index-0 = <&keysn_0>; + unifykey-index-1 = <&keysn_1>; + unifykey-index-2 = <&keysn_2>; + unifykey-index-3 = <&keysn_3>; + unifykey-index-4 = <&keysn_4>; + unifykey-index-5 = <&keysn_5>; + unifykey-index-6 = <&keysn_6>; + unifykey-index-7 = <&keysn_7>; + unifykey-index-8 = <&keysn_8>; + unifykey-index-9 = <&keysn_9>; + unifykey-index-10= <&keysn_10>; + unifykey-index-11= <&keysn_11>; + unifykey-index-12= <&keysn_12>; + unifykey-index-13= <&keysn_13>; + + keysn_0: key_0{ + key-name = "usid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_1:key_1{ + key-name = "mac"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_2:key_2{ + key-name = "hdcp"; + key-device = "secure"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_3:key_3{ + key-name = "secure_boot_set"; + key-device = "efuse"; + key-permit = "write"; + }; + keysn_4:key_4{ + key-name = "mac_bt"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_5:key_5{ + key-name = "mac_wifi"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_6:key_6{ + key-name = "hdcp2_tx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_7:key_7{ + key-name = "hdcp2_rx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_8:key_8{ + key-name = "widevinekeybox"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_9:key_9{ + key-name = "deviceid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_10:key_10{ + key-name = "hdcp22_fw_private"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_11:key_11{ + key-name = "PlayReadykeybox25"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_12:key_12{ + key-name = "prpubkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_13:key_13{ + key-name = "prprivkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + };//End unifykey + + amlvecm { + compatible = "amlogic, vecm"; + dev_name = "aml_vecm"; + status = "okay"; + gamma_en = <0>;/*1:enabel ;0:disable*/ + wb_en = <0>;/*1:enabel ;0:disable*/ + cm_en = <0>;/*1:enabel ;0:disable*/ + }; + amdolby_vision { + compatible = "amlogic, dolby_vision_g12a"; + dev_name = "aml_amdolby_vision_driver"; + status = "okay"; + tv_mode = <0>;/*1:enabel ;0:disable*/ + }; + + /* Audio Related start */ + pdm_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, pdm_dummy_codec"; + status = "okay"; + }; + dummy_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, aml_dummy_codec"; + status = "okay"; + }; + amlogic_codec:t9015{ + #sound-dai-cells = <0>; + compatible = "amlogic, aml_codec_T9015"; + reg = <0x0 0xFF632000 0x0 0x2000>; + is_auge_used = <1>; /* meson or auge chipset used */ + tdmout_index = <1>; + status = "okay"; + }; + audio_effect:eqdrc{ + /*eq_enable = <1>;*/ + /*drc_enable = <1>;*/ + /* + * 0:tdmout_a + * 1:tdmout_b + * 2:tdmout_c + * 3:spdifout + * 4:spdifout_b + */ + eqdrc_module = <1>; + /* max 0xf, each bit for one lane, usually one lane */ + lane_mask = <0x1>; + /* max 0xff, each bit for one channel */ + channel_mask = <0x3>; + }; + auge_sound { + compatible = "amlogic, g12a-sound-card"; + aml-audio-card,name = "AML-AUGESOUND"; + + //aml-audio-card,loopback = <&aml_loopback>; + //aml-audio-card,aux-devs = <&amlogic_codec>; + /*avout mute gpio*/ + avout_mute-gpios = <&gpio_ao GPIOAO_6 GPIO_ACTIVE_HIGH>; + /*for audio effect ,eqdrc */ + aml-audio-card,effect = <&audio_effect>; + + aml-audio-card,dai-link@0 { + format = "dsp_a"; + mclk-fs = <512>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + //bitclock-master = <&tdmacodec>; + //frame-master = <&tdmacodec>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-pcm"; + tdmacpu: cpu { + sound-dai = <&aml_tdma>; + dai-tdm-slot-tx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-rx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-num = <8>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <24576000>; + }; + tdmacodec: codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@1 { + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + bitclock-master = <&aml_tdmb>; + frame-master = <&aml_tdmb>; + //bitclock-master = <&tdmbcodec>; + //frame-master = <&tdmbcodec>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-i2s"; + cpu { + sound-dai = <&aml_tdmb>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmbcodec: codec { + sound-dai = <&dummy_codec &dummy_codec + &amlogic_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@2 { + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + bitclock-master = <&aml_tdmc>; + frame-master = <&aml_tdmc>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + //suffix-name = "alsaPORT-tdm"; + cpu { + sound-dai = <&aml_tdmc>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@3 { + mclk-fs = <64>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-pdm"; + cpu { + sound-dai = <&aml_pdm>; + }; + codec { + sound-dai = <&pdm_codec>; + }; + }; + + aml-audio-card,dai-link@4 { + mclk-fs = <128>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-spdif"; + cpu { + sound-dai = <&aml_spdif>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + }; + audiolocker: locker { + compatible = "amlogic, audiolocker"; + clocks = <&clkaudio CLKID_AUDIO_LOCKER_OUT + &clkaudio CLKID_AUDIO_LOCKER_IN + &clkaudio CLKID_AUDIO_MCLK_D + &clkaudio CLKID_AUDIO_MCLK_E + &clkc CLKID_MPLL1 + &clkc CLKID_MPLL2>; + clock-names = "lock_out", "lock_in", "out_src", + "in_src", "out_calc", "in_ref"; + interrupts = ; + interrupt-names = "irq"; + frequency = <49000000>; /* pll */ + dividor = <49>; /* locker's parent */ + status = "okay"; + }; + /* Audio Related end */ + + cpu_opp_table0: cpu_opp_table0 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <731000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <731000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <731000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <731000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <761000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <781000>; + }; + opp06 { + opp-hz = /bits/ 64 <1398000000>; + opp-microvolt = <811000>; + }; + opp07 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <861000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <901000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <951000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <1001000>; + }; + }; + + cpu_opp_table1: cpu_opp_table1 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <731000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <731000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <731000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <731000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <731000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <751000>; + }; + opp06 { + opp-hz = /bits/ 64 <1398000000>; + opp-microvolt = <771000>; + }; + opp07 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <771000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <781000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <791000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <831000>; + }; + opp11 { + opp-hz = /bits/ 64 <1908000000>; + opp-microvolt = <861000>; + }; + opp12 { + opp-hz = /bits/ 64 <2016000000>; + opp-microvolt = <911000>; + }; + opp13 { + opp-hz = /bits/ 64 <2100000000>; + opp-microvolt = <951000>; + }; + opp14 { + opp-hz = /bits/ 64 <2208000000>; + opp-microvolt = <1011000>; + }; + }; + + cpufreq-meson { + compatible = "amlogic, cpufreq-meson"; + status = "okay"; + }; + + sensor: sensor { + compatible = "soc, sensor"; + status = "okay"; + sensor-name = "imx290"; /*imx290;os08a10;imx227;imx307*/ + pinctrl-names="default"; + pinctrl-0=<&clk12_24_z_pins>; + clocks = <&clkc CLKID_24M>; + clock-names = "g12a_24m"; + reset = <&gpio GPIOZ_12 GPIO_ACTIVE_HIGH>; + ir_cut_gpio = <&gpio GPIOZ_11 GPIO_ACTIVE_HIGH + &gpio GPIOZ_7 GPIO_ACTIVE_HIGH>; + }; + + iq: iq { + compatible = "soc, iq"; + status = "okay"; + sensor-name = "imx290"; /*imx290;os08a10;imx227;imx307*/ + }; + ircut: ircut { + compatible = "amlogic, ircut"; + status = "okay"; + filter1-gpios = <&gpio GPIOH_6 GPIO_ACTIVE_HIGH>; + filter2-gpios = <&gpio GPIOH_7 GPIO_ACTIVE_HIGH>; + light_in-gpios = <&gpio_ao GPIOAO_7 GPIO_ACTIVE_HIGH>; + alarm-gpios = <&gpio_ao GPIOAO_10 GPIO_ACTIVE_HIGH>; + }; + vcodec_dec { + compatible = "amlogic, vcodec-dec"; + dev_name = "aml-vcodec-dec"; + status = "okay"; + }; +}; /* end of / */ +&i2c2 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&i2c2_master_pins2>; + clock-frequency = <100000>; /* default 100k */ + sensor-i2c@6c { + compatible = "arm, i2c-sensor"; + reg = <0x6c>; + reg-names = "i2c-sensor"; + slave-addr = <0x6c>; + reg-type = <2>; + reg-data-type = <1>; + link-device = <&phycsi>; + }; +}; + +&isp { + status = "okay"; + memory-region = <&isp_cma_reserved>; +}; + +&adapter { + status = "okay"; + mem_alloc = <24>; + memory-region = <&adapt_cma_reserved>; +}; + +&gdc { + status = "okay"; + memory-region = <&gdc_cma_reserved>; +}; + +&meson_fb { + status = "okay"; + display_size_default = <1920 1080 1920 2160 32>; + mem_size = <0x00800000 0x1980000 0x100000 0x100000 0x800000>; + logo_addr = "0x3f800000"; + mem_alloc = <1>; + pxp_mode = <0>; /** 0:normal mode 1:pxp mode */ +}; + +&pwm_ab { + status = "okay"; + }; + +&pwm_ef { + status = "okay"; + }; + +&pwm_AO_cd { + status = "okay"; + }; + +&i2c3 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&i2c3_master_pins2>; + clock-frequency = <100000>; /* default 100k */ + + /* for ref board */ + ad82584f_62: ad82584f_62@62 { + compatible = "ESMT, ad82584f"; + #sound-dai-cells = <0>; + reg = <0x31>; + status = "disabled"; + reset_pin = <&gpio GPIOA_5 0>; + }; + + tlv320adc3101_32: tlv320adc3101_32@32 { + compatible = "ti,tlv320adc3101"; + #sound-dai-cells = <0>; + reg = <0x19>; + differential_pair = <1>; + status = "disabled"; + }; + + bl_extern_i2c { + compatible = "bl_extern, i2c"; + dev_name = "lp8556"; + reg = <0x2c>; + status = "disabled"; + }; +}; + +&audiobus { + aml_tdma: tdma { + compatible = "amlogic, g12a-snd-tdma"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 1>; + dai-tdm-oe-lane-slot-mask-out = <1 0>; + dai-tdm-clk-sel = <0>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_A + &clkc CLKID_MPLL0>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmout_a &tdmin_a>; + }; + + aml_tdmb: tdmb { + compatible = "amlogic, g12a-snd-tdmb"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 1 0 0>; + dai-tdm-lane-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <1>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_B + &clkc CLKID_MPLL1 + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; + /* + * 0: tdmout_a; + * 1: tdmout_b; + * 2: tdmout_c; + * 3: spdifout; + * 4: spdifout_b; + */ + samesource_sel = <3>; + }; + + aml_tdmc: tdmc { + compatible = "amlogic, g12a-snd-tdmc"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <1 0 0 0>; + #dai-tdm-lane-slot-mask-out = <1 0 1 1>; + #dai-tdm-lane-oe-slot-mask-in = <0 0 0 0>; + #dai-tdm-lane-oe-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <2>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmc_mclk &tdmout_c &tdmin_c>; + }; + + /* copy a useless tdm to output for hdmi, no pinmux */ + aml_i2s2hdmi: i2s2hdmi { + compatible = "amlogic, g12a-snd-tdmc"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-out = <1 1 1 1>; + dai-tdm-clk-sel = <2>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + + i2s2hdmi = <1>; + + status = "okay"; + }; + + aml_spdif: spdif { + compatible = "amlogic, g12a-snd-spdif-a"; + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 + &clkc CLKID_FCLK_DIV4 + &clkaudio CLKID_AUDIO_SPDIFIN + &clkaudio CLKID_AUDIO_SPDIFOUT + &clkaudio CLKID_AUDIO_SPDIFIN_CTRL + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "sysclk", "fixed_clk", "gate_spdifin", + "gate_spdifout", "clk_spdifin", "clk_spdifout"; + interrupts = + ; + + interrupt-names = "irq_spdifin"; + pinctrl-names = "spdif_pins"; + pinctrl-0 = <&spdifin>; + status = "okay"; + }; + aml_spdif_b: spdif_b { + compatible = "amlogic, g12a-snd-spdif-b"; + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 /*CLKID_HIFI_PLL*/ + &clkaudio CLKID_AUDIO_SPDIFOUTB + &clkaudio CLKID_AUDIO_SPDIFOUTB_CTRL>; + clock-names = "sysclk", + "gate_spdifout", "clk_spdifout"; + status = "disabled"; + }; + aml_pdm: pdm { + compatible = "amlogic, g12a-snd-pdm"; + #sound-dai-cells = <0>; + clocks = <&clkaudio CLKID_AUDIO_PDM + &clkc CLKID_FCLK_DIV3 + &clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_PDMIN0 + &clkaudio CLKID_AUDIO_PDMIN1>; + clock-names = "gate", + "sysclk_srcpll", + "dclk_srcpll", + "pdm_dclk", + "pdm_sysclk"; + pinctrl-names = "pdm_pins"; + pinctrl-0 = <&pdmin>; + lane-mask-in = <0 0 1 0>; + filter_mode = <1>; /* mode 0~4, defalut:1 */ + status = "okay"; + }; + aml_loopback: loopback { + compatible = "amlogic, snd-loopback"; + /* + * 0: out rate = in data rate; + * 1: out rate = loopback data rate; + */ + lb_mode = <0>; + + /* datain src + * 0: tdmin_a; + * 1: tdmin_b; + * 2: tdmin_c; + * 3: spdifin; + * 4: pdmin; + */ + datain_src = <4>; + datain_chnum = <8>; + datain_chmask = <0x3f>; + + /* tdmin_lb src + * 0: tdmoutA + * 1: tdmoutB + * 2: tdmoutC + * 3: PAD_tdminA + * 4: PAD_tdminB + * 5: PAD_tdminC + */ + datalb_src = <2>; + datalb_chnum = <8>; + datalb_chmask = <0x3>; + + status = "disabled"; + }; + + audioresample: resample { + compatible = "amlogic, g12a-resample"; + clocks = <&clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_MCLK_F + &clkaudio CLKID_AUDIO_RESAMPLE_CTRL>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + /*same with toddr_src + * TDMIN_A, 0 + * TDMIN_B, 1 + * TDMIN_C, 2 + * SPDIFIN, 3 + * PDMIN, 4 + * NONE, + * TDMIN_LB, 6 + * LOOPBACK, 7 + */ + resample_module = <4>; + status = "disabled"; + }; + aml_pwrdet: pwrdet { + compatible = "amlogic, g12a-power-detect"; + + interrupts = ; + interrupt-names = "pwrdet_irq"; + + /* pwrdet source sel + * 7: loopback; + * 6: tdmin_lb; + * 5: reserved; + * 4: pdmin; + * 3: spdifin; + * 2: tdmin_c; + * 1: tdmin_b; + * 0: tdmin_a; + */ + pwrdet_src = <4>; + + hi_th = <0x70000>; + lo_th = <0x16000>; + + status = "disabled"; + }; +}; /* end of audiobus */ + +&pinctrl_periphs { + tdmout_a: tdmout_a { + mux { /* GPIOX_11, GPIOX_10, GPIOX_9 */ + groups = "tdma_sclk", + "tdma_fs", + "tdma_dout0"; + function = "tdma_out"; + }; + }; + + tdmin_a: tdmin_a { + mux { /* GPIOX_8 */ + groups = "tdma_din1"; + function = "tdma_in"; + }; + }; + + tdmb_mclk: tdmb_mclk { + mux { + groups = "mclk0_a"; + function = "mclk0"; + drive-strength = <2>; + }; + }; + tdmout_b: tdmout_b { + mux { /* GPIOA_1, GPIOA_2, GPIOA_3 */ + groups = "tdmb_sclk", + "tdmb_fs", + "tdmb_dout0"; + function = "tdmb_out"; + drive-strength = <2>; + }; + }; + + tdmin_b:tdmin_b { + mux { /* GPIOA_4 */ + groups = "tdmb_din1" + /*,"tdmb_slv_sclk", "tdmb_slv_fs"*/; + function = "tdmb_in"; + drive-strength = <2>; + }; + }; + + tdmc_mclk: tdmc_mclk { + mux { /* GPIOA_11 */ + groups = "mclk1_a"; + function = "mclk1"; + }; + }; + + clk12_24_z_pins:clk12_24_z_pins { + mux { + groups = "clk12_24_z"; + function = "clk12_24_ee"; + drive-strength = <3>; + }; + }; + + tdmout_c:tdmout_c { + mux { /* GPIOA_12, GPIOA_13, GPIOA_8, GPIOA_7*/ + groups = "tdmc_sclk_a", + "tdmc_fs_a", + "tdmc_dout0_a" + /*, "tdmc_dout2", + * "tdmc_dout3" + */; + function = "tdmc_out"; + }; + }; + + tdmin_c:tdmin_c { + mux { /* GPIOA_10 */ + groups = "tdmc_din0_a"; + function = "tdmc_in"; + }; + }; + + spdifin: spdifin { + mux {/* GPIOH_5 */ + groups = "spdif_in_h"; + function = "spdif_in"; + }; + }; + + /* GPIOH_4 */ + /* + * spdifout: spdifout { + * mux { + * groups = "spdif_out_h"; + * function = "spdif_out"; + * }; + *}; + */ + + pdmin: pdmin { + mux { /* gpioa_5, gpioa_6, gpioa_7, gpioa_8, gpioa_9*/ + groups = "pdm_din0_a", + /*"pdm_din1_a",*/ + "pdm_din2_a", + /*"pdm_din3_a",*/ + "pdm_dclk_a"; + function = "pdm"; + }; + }; + + bl_pwm_off_pins:bl_pwm_off_pin { + mux { + pins = "GPIOH_5"; + function = "gpio_periphs"; + output-high; + }; + }; + +}; /* end of pinctrl_periphs */ + +&pinctrl_aobus { +// spdifout: spdifout { +// mux { /* gpiao_10 */ +// groups = "spdif_out_ao"; +// function = "spdif_out_ao"; +// }; +//}; + ao_b_uart_pins2:ao_b_uart2 { + mux { + groups = "uart_ao_tx_b_8", + "uart_ao_rx_b_9"; + function = "uart_ao_b"; + }; + }; +}; /* end of pinctrl_aobus */ + +&irblaster { + status = "disabled"; +}; + +&audio_data { + status = "okay"; +}; + +/*if you want to use vdin just modify status to "ok"*/ +&vdin0 { +// memory-region = <&vdin0_cma_reserved>; + status = "disabled"; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + *bit4:support yuv422 10bit full pack mode (from txl new add) + */ + tv_bit_mode = <0x15>; +}; +&vdin1 { +// memory-region = <&vdin1_cma_reserved>; + status = "disabled"; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + */ + tv_bit_mode = <1>; +}; + +&sd_emmc_c { + status = "okay"; + emmc { + caps = "MMC_CAP_8_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + /* "MMC_CAP_1_8V_DDR", */ + "MMC_CAP_HW_RESET", + "MMC_CAP_ERASE", + "MMC_CAP_CMD23"; + caps2 = "MMC_CAP2_HS200"; + /* "MMC_CAP2_HS400";*/ + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&sd_emmc_b { + status = "okay"; + sd { + /*if card have no switch gpio, + * remove all relative to vol_switch + */ + vol_switch = <&gpio_ao GPIOAO_2 GPIO_ACTIVE_HIGH>; + vol_switch_18 = <1>; /* 1 = high, 0 = low */ + vol_switch_delay = <150>; /* Uint: ms*/ + + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_UHS_SDR12", + "MMC_CAP_UHS_SDR25", + "MMC_CAP_UHS_SDR50", + "MMC_CAP_UHS_SDR104"; + + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&sd_emmc_a { + status = "okay"; + sdio { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", +// "MMC_CAP_UHS_SDR12", +// "MMC_CAP_UHS_SDR25", +// "MMC_CAP_UHS_SDR50", +// "MMC_CAP_UHS_SDR104", + "MMC_PM_KEEP_POWER", + "MMC_CAP_SDIO_IRQ"; + f_min = <400000>; + f_max = <50000000>; + }; +}; + +&nand { + status = "disabled"; + plat-names = "bootloader","nandnormal"; + plat-num = <2>; + plat-part-0 = <&bootloader>; + plat-part-1 = <&nandnormal>; + bootloader: bootloader{ + enable_pad ="ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <1>; + part_num = <0>; + rb_detect = <1>; + }; + nandnormal: nandnormal{ + enable_pad ="ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + plane_mode = "twoplane"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <2>; + part_num = <3>; + partition = <&nand_partitions>; + rb_detect = <1>; + }; + nand_partitions:nand_partition{ + /* + * if bl_mode is 1, tpl size was generate by + * fip_copies * fip_size which + * will not skip bad when calculating + * the partition size; + * + * if bl_mode is 0, + * tpl partition must be comment out. + */ + tpl{ + offset=<0x0 0x0>; + size=<0x0 0x0>; + }; + logo{ + offset=<0x0 0x0>; + size=<0x0 0x200000>; + }; + recovery{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + boot{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + system{ + offset=<0x0 0x0>; + size=<0x0 0x4000000>; + }; + data{ + offset=<0xffffffff 0xffffffff>; + size=<0x0 0x0>; + }; + }; +}; +&dwc3 { + status = "okay"; +}; + +&usb2_phy_v2 { + status = "okay"; + portnum = <2>; +}; + +&usb3_phy_v2 { + status = "okay"; + portnum = <0>; + otg = <1>; + //gpio-vbus-power = "GPIOH_6"; + //gpios = <&gpio GPIOH_6 GPIO_ACTIVE_HIGH>; +}; + +&dwc2_a { + status = "okay"; + /** 0: normal, 1: otg+dwc3 host only, 2: otg+dwc3 device only*/ + controller-type = <3>; +}; +ðmac { + status = "okay"; + //conflict with isp i2c + //pinctrl-names = "internal_eth_pins"; + //pinctrl-0 = <&internal_eth_pins>; + + mc_val = <0x4be04>; + + internal_phy=<1>; +}; + +&uart_A { + status = "okay"; +}; +&uart_AO_B { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&ao_b_uart_pins2>; +}; + +&pcie_A { + reset-gpio = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; + status = "disabled"; +}; + +&saradc { + status = "okay"; +}; + +&spicc1 { + status = "disabled"; + pinctrl-names = "default"; + pinctrl-0 = <&spicc1_pins>; + cs-gpios = <&gpio GPIOH_6 0>; +}; diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot_a.dts b/arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot_a.dts new file mode 100644 index 000000000000..a37936e0870b --- /dev/null +++ b/arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot_a.dts @@ -0,0 +1,1446 @@ +/* + * arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot_a.dts + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +/dts-v1/; + +#include "mesong12b_a.dtsi" + +/ { + model = "Amlogic"; + amlogic-dt-id = "g12b_w411_a"; + compatible = "amlogic, g12b"; + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + + aliases { + serial0 = &uart_AO; + serial1 = &uart_A; + serial2 = &uart_B; + serial3 = &uart_C; + serial4 = &uart_AO_B; + i2c0 = &i2c0; + i2c1 = &i2c1; + i2c2 = &i2c2; + i2c3 = &i2c3; + i2c4 = &i2c_AO; + tsensor0 = &p_tsensor; + tsensor1 = &d_tsensor; + }; + + memory@00000000 { + device_type = "memory"; + linux,usable-memory = <0x0 0x100000 0x0 0x3ff00000>; + }; + + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + /* global autoconfigured region for contiguous allocations */ + ramoops@0x07400000 { + compatible = "ramoops"; + reg = <0x0 0x07400000 0x0 0x00100000>; + record-size = <0x8000>; + console-size = <0x8000>; + ftrace-size = <0x20000>; + }; + + secmon_reserved:linux,secmon { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x400000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x05000000 0x0 0x400000>; + clear-map; + }; + + secos_reserved:linux,secos { + status = "disable"; + compatible = "amlogic, aml_secos_memory"; + reg = <0x0 0x05300000 0x0 0x2000000>; + no-map; + }; + logo_reserved:linux,meson-fb { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x800000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x3f800000 0x0 0x800000>; + }; + ion_cma_reserved:linux,ion-dev { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x8000000>; + alignment = <0x0 0x400000>; + }; + + //di_reserved:linux,di { + //compatible = "amlogic, di-mem"; + /* buffer_size = 3621952(yuv422 8bit) */ + /* 4179008(yuv422 10bit full pack mode) */ + /** 10x3621952=34.6M(0x23) support 8bit **/ + /** 10x4736064=45.2M(0x2e) support 12bit **/ + /** 10x4179008=40M(0x28) support 10bit **/ + //size = <0x0 0x2800000>; + //no-map; + //}; + /*di CMA pool */ + di_cma_reserved:linux,di_cma { + compatible = "shared-dma-pool"; + reusable; + /* buffer_size = 3621952(yuv422 8bit) + * | 4736064(yuv422 10bit) + * | 4074560(yuv422 10bit full pack mode) + * 10x3621952=34.6M(0x23) support 8bit + * 10x4736064=45.2M(0x2e) support 12bit + * 10x4074560=40M(0x28) support 10bit + */ + size = <0x0 0x02800000>; + alignment = <0x0 0x400000>; + }; + /* POST PROCESS MANAGER */ + ppmgr_reserved:linux,ppmgr { + compatible = "shared-dma-pool"; + size = <0x0 0x0>; + }; + codec_mm_cma:linux,codec_mm_cma { + compatible = "shared-dma-pool"; + reusable; + /* ion_codec_mm max can alloc size 80M*/ + size = <0x0 0x5000000>; + alignment = <0x0 0x400000>; + linux,contiguous-region; + }; + /* codec shared reserved */ + codec_mm_reserved:linux,codec_mm_reserved { + compatible = "amlogic, codec-mm-reserved"; + size = <0x0 0x0>; + alignment = <0x0 0x100000>; + //no-map; + }; + /* vdin0 CMA pool */ + // vdin0_cma_reserved:linux,vdin0_cma { + // compatible = "shared-dma-pool"; + // reusable; + /* 1920x1080x2x4 =16+4 M */ + // size = <0x0 0x04000000>; + // alignment = <0x0 0x400000>; + // }; + /* vdin1 CMA pool */ + // vdin1_cma_reserved:linux,vdin1_cma { + // compatible = "shared-dma-pool"; + // reusable; + /* 1920x1080x2x4 =16 M */ + // size = <0x0 0x04000000>; + // alignment = <0x0 0x400000>; + // }; + galcore_reserved:linux,galcore { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x0>; + alignment = <0x0 0x400000>; + linux,contiguous-region; + }; + + isp_cma_reserved:linux,isp_cma { + compatible = "shared-dma-pool"; + reusable; + status = "okay"; + size = <0x0 0x3c00000>; + alignment = <0x0 0x400000>; + }; + + adapt_cma_reserved:linux,adapt_cma { + compatible = "shared-dma-pool"; + reusable; + status = "okay"; + size = <0x0 0x1800000>; + alignment = <0x0 0x400000>; + }; + gdc_cma_reserved:linux,gdc_cma { + compatible = "shared-dma-pool"; + reusable; + status = "okay"; + size = <0x0 0x04000000>; + alignment = <0x0 0x400000>; + }; + }; + galcore { + status = "okay"; + memory-region = <&galcore_reserved>; + }; + gpioleds { + compatible = "gpio-leds"; + status = "okay"; + + sys_led { + label="sys_led"; + gpios=<&gpio_ao GPIOAO_11 GPIO_ACTIVE_HIGH>; + default-state ="on"; + retain-state-suspended; + linux,default-trigger="cpu0"; + }; + }; + + cvbsout { + compatible = "amlogic, cvbsout-g12b"; + dev_name = "cvbsout"; + status = "okay"; + clocks = <&clkc CLKID_VCLK2_ENCI + &clkc CLKID_VCLK2_VENCI0 + &clkc CLKID_VCLK2_VENCI1 + &clkc CLKID_DAC_CLK>; + clock-names = "venci_top_gate", + "venci_0_gate", + "venci_1_gate", + "vdac_clk_gate"; + + /* performance: reg_address, reg_value */ + /* g12b */ + performance = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x8080 + 0x1b05 0xfd + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + performance_sarft = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x0 + 0x1b05 0x9 + 0x1c59 0xfc48 + 0xffff 0x0>; /* ending flag */ + }; + + bt-dev{ + compatible = "amlogic, bt-dev"; + dev_name = "bt-dev"; + status = "okay"; + gpio_reset = <&gpio GPIOX_17 GPIO_ACTIVE_HIGH>; + gpio_hostwake = <&gpio GPIOX_19 GPIO_ACTIVE_HIGH>; + }; + + wifi{ + compatible = "amlogic, aml_wifi"; + dev_name = "aml_wifi"; + status = "okay"; + interrupt_pin = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; + irq_trigger_type = "GPIO_IRQ_LOW"; + power_on_pin = <&gpio GPIOX_6 GPIO_ACTIVE_HIGH>; + dhd_static_buf; //if use bcm wifi, config dhd_static_buf + pinctrl-names = "default"; + pinctrl-0 = <&pwm_e_pins>; + pwm_config = <&wifi_pwm_conf>; + }; + + wifi_pwm_conf:wifi_pwm_conf{ + pwm_channel1_conf { + pwms = <&pwm_ef MESON_PWM_0 30541 0>; + duty-cycle = <15270>; + times = <10>; + }; + pwm_channel2_conf { + pwms = <&pwm_ef MESON_PWM_2 30500 0>; + duty-cycle = <15250>; + times = <12>; + }; + }; + + codec_mm { + compatible = "amlogic, codec, mm"; + memory-region = <&codec_mm_cma &codec_mm_reserved>; + dev_name = "codec_mm"; + status = "okay"; + }; + + ppmgr { + compatible = "amlogic, ppmgr"; + memory-region = <&ppmgr_reserved>; + dev_name = "ppmgr"; + status = "okay"; + }; + + deinterlace { + compatible = "amlogic, deinterlace"; + status = "okay"; + /* 0:use reserved; 1:use cma; 2:use cma as reserved */ + flag_cma = <1>; + //memory-region = <&di_reserved>; + memory-region = <&di_cma_reserved>; + interrupts = <0 46 1 + 0 40 1>; + interrupt-names = "pre_irq", "post_irq"; + clocks = <&clkc CLKID_VPU_CLKB_TMP_COMP>, + <&clkc CLKID_VPU_CLKB_COMP>; + clock-names = "vpu_clkb_tmp_composite", + "vpu_clkb_composite"; + clock-range = <334 667>; + /* buffer-size = <3621952>;(yuv422 8bit) */ + buffer-size = <4074560>;/*yuv422 fullpack*/ + /* reserve-iomap = "true"; */ + /* if enable nr10bit, set nr10bit-support to 1 */ + post-wr-support = <1>; + nr10bit-support = <1>; + nrds-enable = <1>; + pps-enable = <1>; + }; + ionvideo { + compatible = "amlogic, ionvideo"; + dev_name = "ionvideo"; + status = "okay"; + }; + + + partitions: partitions{ + parts = <14>; + part-0 = <&logo>; + part-1 = <&recovery>; + part-2 = <&misc>; + part-3 = <&dto>; + part-4 = <&cri_data>; + part-5 = <¶m>; + part-6 = <&boot>; + part-7 = <&rsv>; + part-8 = <&tee>; + part-9 = <&vendor>; + part-10 = <&odm>; + part-11 = <&system>; + part-12 = <&cache>; + part-13 = <&data>; + + logo:logo{ + pname = "logo"; + size = <0x0 0x800000>; + mask = <1>; + }; + recovery:recovery{ + pname = "recovery"; + size = <0x0 0x1800000>; + mask = <1>; + }; + misc:misc{ + pname = "misc"; + size = <0x0 0x800000>; + mask = <1>; + }; + dto:dto{ + pname = "dto"; + size = <0x0 0x800000>; + mask = <1>; + }; + cri_data:cri_data{ + pname = "cri_data"; + size = <0x0 0x800000>; + mask = <2>; + }; + rsv:rsv{ + pname = "rsv"; + size = <0x0 0x1000000>; + mask = <1>; + }; + param:param{ + pname = "param"; + size = <0x0 0x1000000>; + mask = <2>; + }; + boot:boot{ + pname = "boot"; + size = <0x0 0x1000000>; + mask = <1>; + }; + tee:tee{ + pname = "tee"; + size = <0x0 0x2000000>; + mask = <1>; + }; + vendor:vendor{ + pname = "vendor"; + size = <0x0 0x10000000>; + mask = <1>; + }; + odm:odm{ + pname = "odm"; + size = <0x0 0x10000000>; + mask = <1>; + }; + system:system{ + pname = "system"; + size = <0x0 0x80000000>; + mask = <1>; + }; + cache:cache{ + pname = "cache"; + size = <0x0 0x46000000>; + mask = <2>; + }; + data:data{ + pname = "data"; + size = <0xffffffff 0xffffffff>; + mask = <4>; + }; + }; + + gpio_keypad { + compatible = "amlogic, gpio_keypad"; + status = "okay"; + scan_period = <20>; + key_num = <1>; + key_name = "wificonfig"; + key_code = <139>; + key-gpios = <&gpio_ao GPIOAO_3 GPIO_ACTIVE_HIGH>; + detect_mode = <0>;/*0:polling mode, 1:irq mode*/ + }; + + adc_keypad { + compatible = "amlogic, adc_keypad"; + status = "disabled"; + key_name = "vol-", "vol+", "enter", "wificonfig"; + key_num = <4>; + io-channels = <&saradc SARADC_CH2>; + io-channel-names = "key-chan-2"; + key_chan = ; + key_code = <114 115 28 139>; + key_val = <143 266 389 0>; //val=voltage/1800mV*1023 + key_tolerance = <40 40 40 40>; + }; + + unifykey{ + compatible = "amlogic, unifykey"; + status = "ok"; + unifykey-num = <14>; + unifykey-index-0 = <&keysn_0>; + unifykey-index-1 = <&keysn_1>; + unifykey-index-2 = <&keysn_2>; + unifykey-index-3 = <&keysn_3>; + unifykey-index-4 = <&keysn_4>; + unifykey-index-5 = <&keysn_5>; + unifykey-index-6 = <&keysn_6>; + unifykey-index-7 = <&keysn_7>; + unifykey-index-8 = <&keysn_8>; + unifykey-index-9 = <&keysn_9>; + unifykey-index-10= <&keysn_10>; + unifykey-index-11= <&keysn_11>; + unifykey-index-12= <&keysn_12>; + unifykey-index-13= <&keysn_13>; + + keysn_0: key_0{ + key-name = "usid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_1:key_1{ + key-name = "mac"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_2:key_2{ + key-name = "hdcp"; + key-device = "secure"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_3:key_3{ + key-name = "secure_boot_set"; + key-device = "efuse"; + key-permit = "write"; + }; + keysn_4:key_4{ + key-name = "mac_bt"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_5:key_5{ + key-name = "mac_wifi"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_6:key_6{ + key-name = "hdcp2_tx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_7:key_7{ + key-name = "hdcp2_rx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_8:key_8{ + key-name = "widevinekeybox"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_9:key_9{ + key-name = "deviceid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_10:key_10{ + key-name = "hdcp22_fw_private"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_11:key_11{ + key-name = "PlayReadykeybox25"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_12:key_12{ + key-name = "prpubkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_13:key_13{ + key-name = "prprivkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + };//End unifykey + + amlvecm { + compatible = "amlogic, vecm"; + dev_name = "aml_vecm"; + status = "okay"; + gamma_en = <0>;/*1:enabel ;0:disable*/ + wb_en = <0>;/*1:enabel ;0:disable*/ + cm_en = <0>;/*1:enabel ;0:disable*/ + }; + amdolby_vision { + compatible = "amlogic, dolby_vision_g12a"; + dev_name = "aml_amdolby_vision_driver"; + status = "okay"; + tv_mode = <0>;/*1:enabel ;0:disable*/ + }; + + /* Audio Related start */ + pdm_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, pdm_dummy_codec"; + status = "okay"; + }; + dummy_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, aml_dummy_codec"; + status = "okay"; + }; + amlogic_codec:t9015{ + #sound-dai-cells = <0>; + compatible = "amlogic, aml_codec_T9015"; + reg = <0x0 0xFF632000 0x0 0x2000>; + is_auge_used = <1>; /* meson or auge chipset used */ + tdmout_index = <1>; + status = "okay"; + }; + audio_effect:eqdrc{ + /*eq_enable = <1>;*/ + /*drc_enable = <1>;*/ + /* + * 0:tdmout_a + * 1:tdmout_b + * 2:tdmout_c + * 3:spdifout + * 4:spdifout_b + */ + eqdrc_module = <1>; + /* max 0xf, each bit for one lane, usually one lane */ + lane_mask = <0x1>; + /* max 0xff, each bit for one channel */ + channel_mask = <0x3>; + }; + auge_sound { + compatible = "amlogic, g12a-sound-card"; + aml-audio-card,name = "AML-AUGESOUND"; + + //aml-audio-card,loopback = <&aml_loopback>; + //aml-audio-card,aux-devs = <&amlogic_codec>; + /*avout mute gpio*/ + avout_mute-gpios = <&gpio_ao GPIOAO_6 GPIO_ACTIVE_HIGH>; + /*for audio effect ,eqdrc */ + aml-audio-card,effect = <&audio_effect>; + + aml-audio-card,dai-link@0 { + format = "dsp_a"; + mclk-fs = <512>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + //bitclock-master = <&tdmacodec>; + //frame-master = <&tdmacodec>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-pcm"; + tdmacpu: cpu { + sound-dai = <&aml_tdma>; + dai-tdm-slot-tx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-rx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-num = <8>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <24576000>; + }; + tdmacodec: codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@1 { + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + bitclock-master = <&aml_tdmb>; + frame-master = <&aml_tdmb>; + //bitclock-master = <&tdmbcodec>; + //frame-master = <&tdmbcodec>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-i2s"; + cpu { + sound-dai = <&aml_tdmb>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmbcodec: codec { + sound-dai = <&dummy_codec &dummy_codec + &amlogic_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@2 { + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + bitclock-master = <&aml_tdmc>; + frame-master = <&aml_tdmc>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + //suffix-name = "alsaPORT-tdm"; + cpu { + sound-dai = <&aml_tdmc>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@3 { + mclk-fs = <64>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-pdm"; + cpu { + sound-dai = <&aml_pdm>; + }; + codec { + sound-dai = <&pdm_codec>; + }; + }; + + aml-audio-card,dai-link@4 { + mclk-fs = <128>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-spdif"; + cpu { + sound-dai = <&aml_spdif>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + }; + audiolocker: locker { + compatible = "amlogic, audiolocker"; + clocks = <&clkaudio CLKID_AUDIO_LOCKER_OUT + &clkaudio CLKID_AUDIO_LOCKER_IN + &clkaudio CLKID_AUDIO_MCLK_D + &clkaudio CLKID_AUDIO_MCLK_E + &clkc CLKID_MPLL1 + &clkc CLKID_MPLL2>; + clock-names = "lock_out", "lock_in", "out_src", + "in_src", "out_calc", "in_ref"; + interrupts = ; + interrupt-names = "irq"; + frequency = <49000000>; /* pll */ + dividor = <49>; /* locker's parent */ + status = "okay"; + }; + /* Audio Related end */ + + cpu_opp_table0: cpu_opp_table0 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <731000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <731000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <731000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <731000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <731000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <731000>; + }; + opp06 { + opp-hz = /bits/ 64 <1398000000>; + opp-microvolt = <761000>; + }; + opp07 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <791000>; + }; + }; + + cpu_opp_table1: cpu_opp_table1 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <751000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <751000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <751000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <751000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <771000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <771000>; + }; + opp06 { + opp-hz = /bits/ 64 <1398000000>; + opp-microvolt = <791000>; + }; + opp07 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <821000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <861000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <891000>; + }; + }; + + cpufreq-meson { + compatible = "amlogic, cpufreq-meson"; + status = "okay"; + }; + + sensor: sensor { + compatible = "soc, sensor"; + status = "okay"; + sensor-name = "imx290"; /*imx290;os08a10;imx227;imx307*/ + pinctrl-names="default"; + pinctrl-0=<&clk12_24_z_pins>; + clocks = <&clkc CLKID_24M>; + clock-names = "g12a_24m"; + reset = <&gpio GPIOZ_12 GPIO_ACTIVE_HIGH>; + ir_cut_gpio = <&gpio GPIOZ_11 GPIO_ACTIVE_HIGH + &gpio GPIOZ_7 GPIO_ACTIVE_HIGH>; + }; + + iq: iq { + compatible = "soc, iq"; + status = "okay"; + sensor-name = "imx290"; /*imx290;os08a10;imx227;imx307*/ + }; + ircut: ircut { + compatible = "amlogic, ircut"; + status = "okay"; + filter1-gpios = <&gpio GPIOH_6 GPIO_ACTIVE_HIGH>; + filter2-gpios = <&gpio GPIOH_7 GPIO_ACTIVE_HIGH>; + light_in-gpios = <&gpio_ao GPIOAO_7 GPIO_ACTIVE_HIGH>; + alarm-gpios = <&gpio_ao GPIOAO_10 GPIO_ACTIVE_HIGH>; + }; + vcodec_dec { + compatible = "amlogic, vcodec-dec"; + dev_name = "aml-vcodec-dec"; + status = "okay"; + }; +}; /* end of / */ +&i2c2 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&i2c2_master_pins2>; + clock-frequency = <100000>; /* default 100k */ + sensor-i2c@6c { + compatible = "arm, i2c-sensor"; + reg = <0x6c>; + reg-names = "i2c-sensor"; + slave-addr = <0x6c>; + reg-type = <2>; + reg-data-type = <1>; + link-device = <&phycsi>; + }; +}; + +&isp { + status = "okay"; + memory-region = <&isp_cma_reserved>; +}; + +&adapter { + status = "okay"; + memory-region = <&adapt_cma_reserved>; +}; + +&gdc { + status = "okay"; + memory-region = <&gdc_cma_reserved>; +}; + +&meson_fb { + status = "okay"; + display_size_default = <1920 1080 1920 2160 32>; + mem_size = <0x00800000 0x1980000 0x100000 0x100000 0x800000>; + logo_addr = "0x3f800000"; + mem_alloc = <1>; + pxp_mode = <0>; /** 0:normal mode 1:pxp mode */ +}; + +&pwm_ab { + status = "okay"; + }; + +&pwm_ef { + status = "okay"; + }; + +&pwm_AO_cd { + status = "okay"; + }; + +&i2c3 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&i2c3_master_pins2>; + clock-frequency = <100000>; /* default 100k */ + + /* for ref board */ + ad82584f_62: ad82584f_62@62 { + compatible = "ESMT, ad82584f"; + #sound-dai-cells = <0>; + reg = <0x31>; + status = "disabled"; + reset_pin = <&gpio GPIOA_5 0>; + }; + + tlv320adc3101_32: tlv320adc3101_32@32 { + compatible = "ti,tlv320adc3101"; + #sound-dai-cells = <0>; + reg = <0x19>; + differential_pair = <1>; + status = "disabled"; + }; + + bl_extern_i2c { + compatible = "bl_extern, i2c"; + dev_name = "lp8556"; + reg = <0x2c>; + status = "disabled"; + }; +}; + +&audiobus { + aml_tdma: tdma { + compatible = "amlogic, g12a-snd-tdma"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 1>; + dai-tdm-oe-lane-slot-mask-out = <1 0>; + dai-tdm-clk-sel = <0>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_A + &clkc CLKID_MPLL0>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmout_a &tdmin_a>; + }; + + aml_tdmb: tdmb { + compatible = "amlogic, g12a-snd-tdmb"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 1 0 0>; + dai-tdm-lane-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <1>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_B + &clkc CLKID_MPLL1 + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; + /* + * 0: tdmout_a; + * 1: tdmout_b; + * 2: tdmout_c; + * 3: spdifout; + * 4: spdifout_b; + */ + samesource_sel = <3>; + }; + + aml_tdmc: tdmc { + compatible = "amlogic, g12a-snd-tdmc"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <1 0 0 0>; + #dai-tdm-lane-slot-mask-out = <1 0 1 1>; + #dai-tdm-lane-oe-slot-mask-in = <0 0 0 0>; + #dai-tdm-lane-oe-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <2>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmc_mclk &tdmout_c &tdmin_c>; + }; + + /* copy a useless tdm to output for hdmi, no pinmux */ + aml_i2s2hdmi: i2s2hdmi { + compatible = "amlogic, g12a-snd-tdmc"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-out = <1 1 1 1>; + dai-tdm-clk-sel = <2>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + + i2s2hdmi = <1>; + + status = "okay"; + }; + + aml_spdif: spdif { + compatible = "amlogic, g12a-snd-spdif-a"; + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 + &clkc CLKID_FCLK_DIV4 + &clkaudio CLKID_AUDIO_SPDIFIN + &clkaudio CLKID_AUDIO_SPDIFOUT + &clkaudio CLKID_AUDIO_SPDIFIN_CTRL + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "sysclk", "fixed_clk", "gate_spdifin", + "gate_spdifout", "clk_spdifin", "clk_spdifout"; + interrupts = + ; + + interrupt-names = "irq_spdifin"; + pinctrl-names = "spdif_pins"; + pinctrl-0 = <&spdifin>; + status = "okay"; + }; + aml_spdif_b: spdif_b { + compatible = "amlogic, g12a-snd-spdif-b"; + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 /*CLKID_HIFI_PLL*/ + &clkaudio CLKID_AUDIO_SPDIFOUTB + &clkaudio CLKID_AUDIO_SPDIFOUTB_CTRL>; + clock-names = "sysclk", + "gate_spdifout", "clk_spdifout"; + status = "disabled"; + }; + aml_pdm: pdm { + compatible = "amlogic, g12a-snd-pdm"; + #sound-dai-cells = <0>; + clocks = <&clkaudio CLKID_AUDIO_PDM + &clkc CLKID_FCLK_DIV3 + &clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_PDMIN0 + &clkaudio CLKID_AUDIO_PDMIN1>; + clock-names = "gate", + "sysclk_srcpll", + "dclk_srcpll", + "pdm_dclk", + "pdm_sysclk"; + pinctrl-names = "pdm_pins"; + pinctrl-0 = <&pdmin>; + lane-mask-in = <0 0 1 0>; + filter_mode = <1>; /* mode 0~4, defalut:1 */ + status = "okay"; + }; + aml_loopback: loopback { + compatible = "amlogic, snd-loopback"; + /* + * 0: out rate = in data rate; + * 1: out rate = loopback data rate; + */ + lb_mode = <0>; + + /* datain src + * 0: tdmin_a; + * 1: tdmin_b; + * 2: tdmin_c; + * 3: spdifin; + * 4: pdmin; + */ + datain_src = <4>; + datain_chnum = <8>; + datain_chmask = <0x3f>; + + /* tdmin_lb src + * 0: tdmoutA + * 1: tdmoutB + * 2: tdmoutC + * 3: PAD_tdminA + * 4: PAD_tdminB + * 5: PAD_tdminC + */ + datalb_src = <2>; + datalb_chnum = <8>; + datalb_chmask = <0x3>; + + status = "disabled"; + }; + + audioresample: resample { + compatible = "amlogic, g12a-resample"; + clocks = <&clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_MCLK_F + &clkaudio CLKID_AUDIO_RESAMPLE_CTRL>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + /*same with toddr_src + * TDMIN_A, 0 + * TDMIN_B, 1 + * TDMIN_C, 2 + * SPDIFIN, 3 + * PDMIN, 4 + * NONE, + * TDMIN_LB, 6 + * LOOPBACK, 7 + */ + resample_module = <4>; + status = "disabled"; + }; + aml_pwrdet: pwrdet { + compatible = "amlogic, g12a-power-detect"; + + interrupts = ; + interrupt-names = "pwrdet_irq"; + + /* pwrdet source sel + * 7: loopback; + * 6: tdmin_lb; + * 5: reserved; + * 4: pdmin; + * 3: spdifin; + * 2: tdmin_c; + * 1: tdmin_b; + * 0: tdmin_a; + */ + pwrdet_src = <4>; + + hi_th = <0x70000>; + lo_th = <0x16000>; + + status = "disabled"; + }; +}; /* end of audiobus */ + +&pinctrl_periphs { + tdmout_a: tdmout_a { + mux { /* GPIOX_11, GPIOX_10, GPIOX_9 */ + groups = "tdma_sclk", + "tdma_fs", + "tdma_dout0"; + function = "tdma_out"; + }; + }; + + tdmin_a: tdmin_a { + mux { /* GPIOX_8 */ + groups = "tdma_din1"; + function = "tdma_in"; + }; + }; + + tdmb_mclk: tdmb_mclk { + mux { + groups = "mclk0_a"; + function = "mclk0"; + drive-strength = <2>; + }; + }; + tdmout_b: tdmout_b { + mux { /* GPIOA_1, GPIOA_2, GPIOA_3 */ + groups = "tdmb_sclk", + "tdmb_fs", + "tdmb_dout0"; + function = "tdmb_out"; + drive-strength = <2>; + }; + }; + + tdmin_b:tdmin_b { + mux { /* GPIOA_4 */ + groups = "tdmb_din1" + /*,"tdmb_slv_sclk", "tdmb_slv_fs"*/; + function = "tdmb_in"; + drive-strength = <2>; + }; + }; + + tdmc_mclk: tdmc_mclk { + mux { /* GPIOA_11 */ + groups = "mclk1_a"; + function = "mclk1"; + }; + }; + + clk12_24_z_pins:clk12_24_z_pins { + mux { + groups = "clk12_24_z"; + function = "clk12_24_ee"; + drive-strength = <3>; + }; + }; + + tdmout_c:tdmout_c { + mux { /* GPIOA_12, GPIOA_13, GPIOA_8, GPIOA_7*/ + groups = "tdmc_sclk_a", + "tdmc_fs_a", + "tdmc_dout0_a" + /*, "tdmc_dout2", + * "tdmc_dout3" + */; + function = "tdmc_out"; + }; + }; + + tdmin_c:tdmin_c { + mux { /* GPIOA_10 */ + groups = "tdmc_din0_a"; + function = "tdmc_in"; + }; + }; + + spdifin: spdifin { + mux {/* GPIOH_5 */ + groups = "spdif_in_h"; + function = "spdif_in"; + }; + }; + + /* GPIOH_4 */ + /* + * spdifout: spdifout { + * mux { + * groups = "spdif_out_h"; + * function = "spdif_out"; + * }; + *}; + */ + + pdmin: pdmin { + mux { /* gpioa_5, gpioa_6, gpioa_7, gpioa_8, gpioa_9*/ + groups = "pdm_din0_a", + /*"pdm_din1_a",*/ + "pdm_din2_a", + /*"pdm_din3_a",*/ + "pdm_dclk_a"; + function = "pdm"; + }; + }; + + bl_pwm_off_pins:bl_pwm_off_pin { + mux { + pins = "GPIOH_5"; + function = "gpio_periphs"; + output-high; + }; + }; + +}; /* end of pinctrl_periphs */ + +&pinctrl_aobus { +// spdifout: spdifout { +// mux { /* gpiao_10 */ +// groups = "spdif_out_ao"; +// function = "spdif_out_ao"; +// }; +//}; + ao_b_uart_pins2:ao_b_uart2 { + mux { + groups = "uart_ao_tx_b_8", + "uart_ao_rx_b_9"; + function = "uart_ao_b"; + }; + }; +}; /* end of pinctrl_aobus */ + +&irblaster { + status = "disabled"; +}; + +&audio_data { + status = "okay"; +}; + +/*if you want to use vdin just modify status to "ok"*/ +&vdin0 { +// memory-region = <&vdin0_cma_reserved>; + status = "disabled"; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + *bit4:support yuv422 10bit full pack mode (from txl new add) + */ + tv_bit_mode = <0x15>; +}; +&vdin1 { +// memory-region = <&vdin1_cma_reserved>; + status = "disabled"; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + */ + tv_bit_mode = <1>; +}; + +&sd_emmc_c { + status = "okay"; + emmc { + caps = "MMC_CAP_8_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + /* "MMC_CAP_1_8V_DDR", */ + "MMC_CAP_HW_RESET", + "MMC_CAP_ERASE", + "MMC_CAP_CMD23"; + caps2 = "MMC_CAP2_HS200"; + /* "MMC_CAP2_HS400";*/ + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&sd_emmc_b { + status = "okay"; + sd { + /*if card have no switch gpio, + * remove all relative to vol_switch + */ + vol_switch = <&gpio_ao GPIOAO_2 GPIO_ACTIVE_HIGH>; + vol_switch_18 = <1>; /* 1 = high, 0 = low */ + vol_switch_delay = <150>; /* Uint: ms*/ + + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_UHS_SDR12", + "MMC_CAP_UHS_SDR25", + "MMC_CAP_UHS_SDR50", + "MMC_CAP_UHS_SDR104"; + + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&sd_emmc_a { + status = "okay"; + sdio { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", +// "MMC_CAP_UHS_SDR12", +// "MMC_CAP_UHS_SDR25", +// "MMC_CAP_UHS_SDR50", +// "MMC_CAP_UHS_SDR104", + "MMC_PM_KEEP_POWER", + "MMC_CAP_SDIO_IRQ"; + f_min = <400000>; + f_max = <50000000>; + }; +}; + +&nand { + status = "disabled"; + plat-names = "bootloader","nandnormal"; + plat-num = <2>; + plat-part-0 = <&bootloader>; + plat-part-1 = <&nandnormal>; + bootloader: bootloader{ + enable_pad ="ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <1>; + part_num = <0>; + rb_detect = <1>; + }; + nandnormal: nandnormal{ + enable_pad ="ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + plane_mode = "twoplane"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <2>; + part_num = <3>; + partition = <&nand_partitions>; + rb_detect = <1>; + }; + nand_partitions:nand_partition{ + /* + * if bl_mode is 1, tpl size was generate by + * fip_copies * fip_size which + * will not skip bad when calculating + * the partition size; + * + * if bl_mode is 0, + * tpl partition must be comment out. + */ + tpl{ + offset=<0x0 0x0>; + size=<0x0 0x0>; + }; + logo{ + offset=<0x0 0x0>; + size=<0x0 0x200000>; + }; + recovery{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + boot{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + system{ + offset=<0x0 0x0>; + size=<0x0 0x4000000>; + }; + data{ + offset=<0xffffffff 0xffffffff>; + size=<0x0 0x0>; + }; + }; +}; +&dwc3 { + status = "okay"; +}; + +&usb2_phy_v2 { + status = "okay"; + portnum = <2>; +}; + +&usb3_phy_v2 { + status = "okay"; + portnum = <0>; + otg = <1>; + //gpio-vbus-power = "GPIOH_6"; + //gpios = <&gpio GPIOH_6 GPIO_ACTIVE_HIGH>; +}; + +&dwc2_a { + status = "okay"; + /** 0: normal, 1: otg+dwc3 host only, 2: otg+dwc3 device only*/ + controller-type = <3>; +}; +ðmac { + status = "okay"; + //conflict with isp i2c + //pinctrl-names = "internal_eth_pins"; + //pinctrl-0 = <&internal_eth_pins>; + + mc_val = <0x4be04>; + + internal_phy=<1>; +}; + +&uart_A { + status = "okay"; +}; +&uart_AO_B { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&ao_b_uart_pins2>; +}; + +&pcie_A { + reset-gpio = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; + status = "disabled"; +}; + +&saradc { + status = "okay"; +}; + +&spicc1 { + status = "disabled"; + pinctrl-names = "default"; + pinctrl-0 = <&spicc1_pins>; + cs-gpios = <&gpio GPIOH_6 0>; +}; diff --git a/arch/arm64/boot/dts/amlogic/g12b_pxp.dts b/arch/arm64/boot/dts/amlogic/g12b_pxp.dts index 6386b1423b23..36f125968f83 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_pxp.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_pxp.dts @@ -21,6 +21,7 @@ / { model = "Amlogic"; + amlogic-dt-id = "g12b_skt_b"; compatible = "amlogic, g12b"; interrupt-parent = <&gic>; #address-cells = <2>; @@ -37,7 +38,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x0 0x100000 0x0 0x3ff00000>; + linux,usable-memory = <0x0 0x0 0x0 0x40000000>; }; reserved-memory { @@ -366,31 +367,31 @@ }; opp04 { opp-hz = /bits/ 64 <1000000000>; - opp-microvolt = <731000>; + opp-microvolt = <761000>; }; opp05 { opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <731000>; + opp-microvolt = <781000>; }; opp06 { opp-hz = /bits/ 64 <1398000000>; - opp-microvolt = <761000>; + opp-microvolt = <811000>; }; opp07 { opp-hz = /bits/ 64 <1512000000>; - opp-microvolt = <791000>; + opp-microvolt = <861000>; }; opp08 { opp-hz = /bits/ 64 <1608000000>; - opp-microvolt = <831000>; + opp-microvolt = <901000>; }; opp09 { opp-hz = /bits/ 64 <1704000000>; - opp-microvolt = <861000>; + opp-microvolt = <951000>; }; opp10 { opp-hz = /bits/ 64 <1800000000>; - opp-microvolt = <981000>; + opp-microvolt = <1001000>; }; }; @@ -400,43 +401,63 @@ opp00 { opp-hz = /bits/ 64 <100000000>; - opp-microvolt = <751000>; + opp-microvolt = <731000>; }; opp01 { opp-hz = /bits/ 64 <250000000>; - opp-microvolt = <751000>; + opp-microvolt = <731000>; }; opp02 { opp-hz = /bits/ 64 <500000000>; - opp-microvolt = <751000>; + opp-microvolt = <731000>; }; opp03 { opp-hz = /bits/ 64 <667000000>; - opp-microvolt = <751000>; + opp-microvolt = <731000>; }; opp04 { opp-hz = /bits/ 64 <1000000000>; - opp-microvolt = <771000>; + opp-microvolt = <731000>; }; opp05 { opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <771000>; + opp-microvolt = <751000>; }; opp06 { opp-hz = /bits/ 64 <1398000000>; - opp-microvolt = <791000>; + opp-microvolt = <771000>; }; opp07 { opp-hz = /bits/ 64 <1512000000>; - opp-microvolt = <821000>; + opp-microvolt = <771000>; }; opp08 { opp-hz = /bits/ 64 <1608000000>; - opp-microvolt = <861000>; + opp-microvolt = <781000>; }; opp09 { opp-hz = /bits/ 64 <1704000000>; - opp-microvolt = <891000>; + opp-microvolt = <791000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <831000>; + }; + opp11 { + opp-hz = /bits/ 64 <1908000000>; + opp-microvolt = <861000>; + }; + opp12 { + opp-hz = /bits/ 64 <2016000000>; + opp-microvolt = <911000>; + }; + opp13 { + opp-hz = /bits/ 64 <2100000000>; + opp-microvolt = <951000>; + }; + opp14 { + opp-hz = /bits/ 64 <2208000000>; + opp-microvolt = <1011000>; }; }; diff --git a/arch/arm64/boot/dts/amlogic/g12b_pxp_a.dts b/arch/arm64/boot/dts/amlogic/g12b_pxp_a.dts new file mode 100644 index 000000000000..b1e9088a1665 --- /dev/null +++ b/arch/arm64/boot/dts/amlogic/g12b_pxp_a.dts @@ -0,0 +1,736 @@ +/* + * arch/arm64/boot/dts/amlogic/g12b_pxp_a.dts + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +/dts-v1/; + +#include "mesong12b_a.dtsi" + +/ { + model = "Amlogic"; + amlogic-dt-id = "g12b_skt_a"; + compatible = "amlogic, g12b"; + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + + aliases { + serial0 = &uart_AO; + i2c0 = &i2c0; + i2c1 = &i2c1; + i2c2 = &i2c2; + i2c3 = &i2c3; + i2c4 = &i2c_AO; + }; + + memory@00000000 { + device_type = "memory"; + linux,usable-memory = <0x0 0x100000 0x0 0x3ff00000>; + }; + + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + /* global autoconfigured region for contiguous allocations */ + secmon_reserved:linux,secmon { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x400000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x05000000 0x0 0x400000>; + }; + + secos_reserved:linux,secos { + status = "disable"; + compatible = "amlogic, aml_secos_memory"; + reg = <0x0 0x05300000 0x0 0x2000000>; + no-map; + }; + logo_reserved:linux,meson-fb { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x800000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x3f800000 0x0 0x800000>; + }; + ion_cma_reserved:linux,ion-dev { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x8000000>; + alignment = <0x0 0x400000>; + }; + + //di_reserved:linux,di { + //compatible = "amlogic, di-mem"; + /* buffer_size = 3621952(yuv422 8bit) */ + /* 4179008(yuv422 10bit full pack mode) */ + /** 10x3621952=34.6M(0x23) support 8bit **/ + /** 10x4736064=45.2M(0x2e) support 12bit **/ + /** 10x4179008=40M(0x28) support 10bit **/ + //size = <0x0 0x2800000>; + //no-map; + //}; + /*di CMA pool */ + di_cma_reserved:linux,di_cma { + compatible = "shared-dma-pool"; + reusable; + /* buffer_size = 3621952(yuv422 8bit) + * | 4736064(yuv422 10bit) + * | 4074560(yuv422 10bit full pack mode) + * 10x3621952=34.6M(0x23) support 8bit + * 10x4736064=45.2M(0x2e) support 12bit + * 10x4074560=40M(0x28) support 10bit + */ + size = <0x0 0x02800000>; + alignment = <0x0 0x400000>; + }; + codec_mm_cma:linux,codec_mm_cma { + compatible = "shared-dma-pool"; + reusable; + /* ion_codec_mm max can alloc size 80M*/ + size = <0x0 0x13400000>; + alignment = <0x0 0x400000>; + linux,contiguous-region; + }; + /* codec shared reserved */ + codec_mm_reserved:linux,codec_mm_reserved { + compatible = "amlogic, codec-mm-reserved"; + size = <0x0 0x0>; + alignment = <0x0 0x100000>; + //no-map; + }; + /* vdin0 CMA pool */ + vdin0_cma_reserved:linux,vdin0_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16+4 M */ + size = <0x0 0x04000000>; + alignment = <0x0 0x400000>; + }; + /* vdin1 CMA pool */ + vdin1_cma_reserved:linux,vdin1_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16 M */ + size = <0x0 0x04000000>; + alignment = <0x0 0x400000>; + }; + }; + + cvbsout { + compatible = "amlogic, cvbsout-g12b"; + dev_name = "cvbsout"; + status = "okay"; + clocks = <&clkc CLKID_VCLK2_ENCI + &clkc CLKID_VCLK2_VENCI0 + &clkc CLKID_VCLK2_VENCI1 + &clkc CLKID_DAC_CLK>; + clock-names = "venci_top_gate", + "venci_0_gate", + "venci_1_gate", + "vdac_clk_gate"; + clk_path = <0>; + + /* performance: reg_address, reg_value */ + /* g12b */ + performance = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x8080 + 0x1b05 0xfd + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + performance_sarft = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x0 + 0x1b05 0x9 + 0x1c59 0xfc48 + 0xffff 0x0>; /* ending flag */ + }; + + codec_mm { + compatible = "amlogic, codec, mm"; + memory-region = <&codec_mm_cma &codec_mm_reserved>; + dev_name = "codec_mm"; + status = "okay"; + }; + + deinterlace { + compatible = "amlogic, deinterlace"; + status = "disabled"; + /* 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>; + }; + + amlvecm { + compatible = "amlogic, vecm"; + dev_name = "aml_vecm"; + status = "disabled"; + gamma_en = <0>;/*1:enabel ;0:disable*/ + wb_en = <0>;/*1:enabel ;0:disable*/ + cm_en = <0>;/*1:enabel ;0:disable*/ + }; + amdolby_vision { + compatible = "amlogic, dolby_vision_g12a"; + dev_name = "aml_amdolby_vision_driver"; + status = "disabled"; + tv_mode = <0>;/*1:enabel ;0:disable*/ + }; + + /* Audio Related start */ + pdm_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, pdm_dummy_codec"; + status = "disabled"; + }; + dummy_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, aml_dummy_codec"; + status = "disabled"; + }; + amlogic_codec:t9015{ + #sound-dai-cells = <0>; + /*compatible = "amlogic, aml_codec_T9015";*/ + reg = <0x0 0xFF632000 0x0 0x2000>; + is_auge_used = <1>; /* meson or auge chipset used */ + tdmout_index = <0>; + status = "disabled"; + }; + auge_sound { + /*compatible = "amlogic, g12a-sound-card";*/ + aml-audio-card,name = "AML-AUGESOUND"; + + aml-audio-card,dai-link@0 { + format = "dsp_a"; + mclk-fs = <512>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + //bitclock-master = <&tdmacodec>; + //frame-master = <&tdmacodec>; + tdmacpu: cpu { + sound-dai = <&aml_tdma>; + dai-tdm-slot-tx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-rx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-num = <8>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <24576000>; + }; + tdmacodec: codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@1 { + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + bitclock-master = <&aml_tdmb>; + frame-master = <&aml_tdmb>; + cpu { + sound-dai = <&aml_tdmb>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@2 { + format = "i2s"; + mclk-fs = <256>; + continuous-clock; + //bitclock-inversion; + //frame-inversion; + bitclock-master = <&aml_tdmc>; + frame-master = <&aml_tdmc>; + cpu { + sound-dai = <&aml_tdmc>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@3 { + mclk-fs = <64>; + cpu { + sound-dai = <&aml_pdm>; + }; + codec { + sound-dai = <&pdm_codec>; + }; + }; + + aml-audio-card,dai-link@4 { + mclk-fs = <128>; + cpu { + sound-dai = <&aml_spdif>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + aml-audio-card,dai-link@5 { + mclk-fs = <128>; + cpu { + sound-dai = <&aml_spdif_b>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + }; + audiolocker: locker { + compatible = "amlogic, audiolocker"; + clocks = <&clkaudio CLKID_AUDIO_LOCKER_OUT + &clkaudio CLKID_AUDIO_LOCKER_IN + &clkaudio CLKID_AUDIO_MCLK_D + &clkaudio CLKID_AUDIO_MCLK_E + &clkc CLKID_MPLL1 + &clkc CLKID_MPLL2>; + clock-names = "lock_out", "lock_in", "out_src", + "in_src", "out_calc", "in_ref"; + interrupts = ; + interrupt-names = "irq"; + frequency = <49000000>; /* pll */ + dividor = <49>; /* locker's parent */ + status = "disabled"; + }; + /* Audio Related end */ + + cpu_opp_table0: cpu_opp_table0 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <731000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <731000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <731000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <731000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <731000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <731000>; + }; + opp06 { + opp-hz = /bits/ 64 <1398000000>; + opp-microvolt = <761000>; + }; + opp07 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <791000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <831000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <861000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <981000>; + }; + }; + + cpu_opp_table1: cpu_opp_table1 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <751000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <751000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <751000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <751000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <771000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <771000>; + }; + opp06 { + opp-hz = /bits/ 64 <1398000000>; + opp-microvolt = <791000>; + }; + opp07 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <821000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <861000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <891000>; + }; + }; + + cpufreq-meson { + compatible = "amlogic, cpufreq-meson"; + status = "okay"; + }; + + +}; /* end of / */ + +&meson_fb { + status = "okay"; + display_size_default = <1920 1080 1920 2160 32>; + mem_size = <0x00800000 0x1980000 0x100000 0x100000 0x800000>; + logo_addr = "0x3f800000"; + mem_alloc = <1>; + pxp_mode = <1>; /** 0:normal mode 1:pxp mode */ +}; + +&pwm_AO_cd { + status = "okay"; +}; + +&pwm_ab { + status = "okay"; +}; + + +&audiobus { + aml_tdma: tdma { + /*compatible = "amlogic, g12a-snd-tdma";*/ + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <1 0>; + dai-tdm-lane-slot-mask-out = <0 1>; + dai-tdm-clk-sel = <0>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_A + &clkc CLKID_MPLL0>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmout_a &tdmin_a>; + }; + + aml_tdmb: tdmb { + /*compatible = "amlogic, g12a-snd-tdmb";*/ + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <1 1 1 1>; + dai-tdm-clk-sel = <1>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_B + &clkc CLKID_MPLL1>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmb_mclk /*&tdmout_b &tdmin_b*/>; + }; + + aml_tdmc: tdmc { + /*compatible = "amlogic, g12a-snd-tdmc";*/ + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 1 0 0>; + #dai-tdm-lane-slot-mask-out = <1 0 1 1>; + #dai-tdm-lane-oe-slot-mask-in = <0 0 0 0>; + dai-tdm-lane-oe-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <2>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmc_mclk &tdmout_c &tdmin_c>; + }; + + aml_spdif: spdif { + /*compatible = "amlogic, g12a-snd-spdif-a";*/ + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 + &clkc CLKID_FCLK_DIV4 + &clkaudio CLKID_AUDIO_SPDIFIN + &clkaudio CLKID_AUDIO_SPDIFOUT + &clkaudio CLKID_AUDIO_SPDIFIN_CTRL + &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>; + clock-names = "sysclk", "fixed_clk", "gate_spdifin", + "gate_spdifout", "clk_spdifin", "clk_spdifout"; + interrupts = + ; + + interrupt-names = "irq_spdifin"; + pinctrl-names = "spdif_pins"; + pinctrl-0 = <&spdifout &spdifin>; + status = "disabled"; + }; + aml_spdif_b: spdif_b { + /*compatible = "amlogic, g12a-snd-spdif-b";*/ + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 /*CLKID_HIFI_PLL*/ + &clkaudio CLKID_AUDIO_SPDIFOUTB + &clkaudio CLKID_AUDIO_SPDIFOUTB_CTRL>; + clock-names = "sysclk", + "gate_spdifout", "clk_spdifout"; + pinctrl-names = "spdif_pins"; + pinctrl-0 = <&spdifout_b>; + status = "disabled"; + }; + aml_pdm: pdm { + /*compatible = "amlogic, g12a-snd-pdm";*/ + #sound-dai-cells = <0>; + clocks = <&clkaudio CLKID_AUDIO_PDM + &clkc CLKID_FCLK_DIV3 + &clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_PDMIN0 + &clkaudio CLKID_AUDIO_PDMIN1>; + clock-names = "gate", + "sysclk_srcpll", + "dclk_srcpll", + "pdm_dclk", + "pdm_sysclk"; + pinctrl-names = "pdm_pins"; + pinctrl-0 = <&pdmin>; + filter_mode = <1>; /* mode 0~4, defalut:1 */ + status = "disabled"; + }; + aml_pwrdet: pwrdet { + compatible = "amlogic, g12a-power-detect"; + + interrupts = ; + interrupt-names = "pwrdet_irq"; + + /* pwrdet source sel + * 7: loopback; + * 6: tdmin_lb; + * 5: reserved; + * 4: pdmin; + * 3: spdifin; + * 2: tdmin_c; + * 1: tdmin_b; + * 0: tdmin_a; + */ + pwrdet_src = <4>; + + hi_th = <0x70000>; + lo_th = <0x16000>; + + status = "disabled"; + }; +}; /* end of audiobus */ + +&pinctrl_periphs { + tdmout_a: tdmout_a { + mux { /* GPIOX_11, GPIOX_10, GPIOX_8 */ + groups = "tdma_sclk", + "tdma_fs", + "tdma_dout1"; + function = "tdma_out"; + }; + }; + + tdmin_a: tdmin_a { + mux { /* GPIOX_9 */ + groups = "tdma_din0"; + function = "tdma_in"; + }; + }; + + tdmb_mclk: tdmb_mclk { + mux { + groups = "mclk0_a"; + function = "mclk0"; + }; + }; + + tdmc_mclk: tdmc_mclk { + mux { /* GPIOZ_8 */ + groups = "mclk1_z"; + function = "mclk1"; + }; + }; + + tdmout_c:tdmout_c { + mux { /* gpioz_7, gpioz_6, GPIOZ_2, GPIOZ_4, GPIOZ_5*/ + groups = "tdmc_sclk_z", + "tdmc_fs_z", + "tdmc_dout0_z" + /*,"tdmc_dout2_z", + *"tdmc_dout3_z" + */; + function = "tdmc_out"; + }; + }; + + tdmin_c:tdmin_c { + mux { /* GPIOZ_3 */ + groups = "tdmc_din1_z"; + function = "tdmc_in"; + }; + }; + + spdifin: spdifin { + mux {/* gpioa_10 */ + groups = "spdif_in_a10"; + function = "spdif_in"; + }; + }; + + spdifout: spdifout { + mux {/* gpioa_11 */ + groups = "spdif_out_a11"; + function = "spdif_out"; + }; + }; + + spdifout_b: spdifout_b { + mux { /* gpioa_13 */ + groups = "spdif_out_a13"; + function = "spdif_out"; + }; + }; + + pdmin: pdmin { + mux { /* gpioa_5, gpioa_6, gpioa_7, gpioa_8, gpioa_9*/ + groups = "pdm_din0_a", + "pdm_din1_a", + "pdm_din2_a", + "pdm_din3_a", + "pdm_dclk_a"; + function = "pdm"; + }; + }; + +}; /* end of pinctrl_periphs */ + +&pinctrl_aobus { + tdmout_b: tdmout_b { + mux { /* GPIOAO_7, GPIOAO_8, GPIOAO_4 */ + groups = "tdmb_fs_ao", + "tdmb_fs_ao", + "tdmb_dout0_ao"; + function = "tdmb_out_ao"; + }; + }; + + tdmin_b:tdmin_b { + mux { + groups = "tdmb_din2_ao"; + function = "tdmb_in_ao"; + }; + }; +}; /* end of pinctrl_aobus */ +/* Audio Related End */ + +&aobus{ + +}; + +&irblaster { + status = "disabled"; +}; + +/*if you want to use vdin just modify status to "ok"*/ +&vdin0 { + memory-region = <&vdin0_cma_reserved>; + status = "disabled"; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + *bit4:support yuv422 10bit full pack mode (from txl new add) + */ + tv_bit_mode = <0x15>; +}; +&vdin1 { + memory-region = <&vdin1_cma_reserved>; + status = "disabled"; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + */ + tv_bit_mode = <1>; +}; +&sd_emmc_b { + status = "disabled"; + sd { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + "MMC_CAP_UHS_SDR12", + "MMC_CAP_UHS_SDR25", + "MMC_CAP_UHS_SDR50", + "MMC_PM_KEEP_POWER", + "MMC_CAP_NONREMOVABLE"; /**ptm debug */ + f_min = <400000>; + f_max = <200000000>; + }; +}; + diff --git a/arch/arm64/boot/dts/amlogic/gxl_p212_2g.dts b/arch/arm64/boot/dts/amlogic/gxl_p212_2g.dts index df862e17defe..302ea680e67f 100644 --- a/arch/arm64/boot/dts/amlogic/gxl_p212_2g.dts +++ b/arch/arm64/boot/dts/amlogic/gxl_p212_2g.dts @@ -56,8 +56,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { compatible = "shared-dma-pool"; diff --git a/arch/arm64/boot/dts/amlogic/gxl_p230_2g.dts b/arch/arm64/boot/dts/amlogic/gxl_p230_2g.dts index 101ad78b2091..6adc66fb6a92 100644 --- a/arch/arm64/boot/dts/amlogic/gxl_p230_2g.dts +++ b/arch/arm64/boot/dts/amlogic/gxl_p230_2g.dts @@ -56,8 +56,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { compatible = "shared-dma-pool"; diff --git a/arch/arm64/boot/dts/amlogic/gxl_p230_2g_buildroot.dts b/arch/arm64/boot/dts/amlogic/gxl_p230_2g_buildroot.dts index 5c38487443f2..841f7da52be9 100644 --- a/arch/arm64/boot/dts/amlogic/gxl_p230_2g_buildroot.dts +++ b/arch/arm64/boot/dts/amlogic/gxl_p230_2g_buildroot.dts @@ -56,8 +56,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm64/boot/dts/amlogic/gxl_p231_1g.dts b/arch/arm64/boot/dts/amlogic/gxl_p231_1g.dts index 7d8d55ab43b9..a7b5e439da75 100644 --- a/arch/arm64/boot/dts/amlogic/gxl_p231_1g.dts +++ b/arch/arm64/boot/dts/amlogic/gxl_p231_1g.dts @@ -56,8 +56,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { @@ -1111,11 +1110,14 @@ key-device = "secure"; key-permit = "read","write","del"; }; +<<<<<<< HEAD keysn_15:key_15{ key-name = "netflix_mgkid"; key-device = "secure"; key-permit = "read","write","del"; }; +======= +>>>>>>> 9b43aa8... dts: add the attestationkeybox of unifykey[1/3] };//End unifykey }; &efuse { diff --git a/arch/arm64/boot/dts/amlogic/gxl_p231_2g.dts b/arch/arm64/boot/dts/amlogic/gxl_p231_2g.dts index ba85a853779d..db2416922a41 100644 --- a/arch/arm64/boot/dts/amlogic/gxl_p231_2g.dts +++ b/arch/arm64/boot/dts/amlogic/gxl_p231_2g.dts @@ -56,8 +56,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { @@ -1111,11 +1110,14 @@ key-device = "secure"; key-permit = "read","write","del"; }; +<<<<<<< HEAD keysn_15:key_15{ key-name = "netflix_mgkid"; key-device = "secure"; key-permit = "read","write","del"; }; +======= +>>>>>>> 9b43aa8... dts: add the attestationkeybox of unifykey[1/3] };//End unifykey }; &efuse { diff --git a/arch/arm64/boot/dts/amlogic/gxl_p231_2g_buildroot.dts b/arch/arm64/boot/dts/amlogic/gxl_p231_2g_buildroot.dts index 92f6e7d9ceef..b334aca4f65b 100644 --- a/arch/arm64/boot/dts/amlogic/gxl_p231_2g_buildroot.dts +++ b/arch/arm64/boot/dts/amlogic/gxl_p231_2g_buildroot.dts @@ -53,8 +53,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm64/boot/dts/amlogic/gxl_p241_1g.dts b/arch/arm64/boot/dts/amlogic/gxl_p241_1g.dts index dadb59aed48a..66db66c9f860 100644 --- a/arch/arm64/boot/dts/amlogic/gxl_p241_1g.dts +++ b/arch/arm64/boot/dts/amlogic/gxl_p241_1g.dts @@ -55,8 +55,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm64/boot/dts/amlogic/gxl_p241_1g_buildroot.dts b/arch/arm64/boot/dts/amlogic/gxl_p241_1g_buildroot.dts index 2a7245aff17a..854b833d2170 100644 --- a/arch/arm64/boot/dts/amlogic/gxl_p241_1g_buildroot.dts +++ b/arch/arm64/boot/dts/amlogic/gxl_p241_1g_buildroot.dts @@ -55,8 +55,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { @@ -1319,11 +1318,14 @@ key-device = "secure"; key-permit = "read","write","del"; }; +<<<<<<< HEAD keysn_15:key_15{ key-name = "netflix_mgkid"; key-device = "secure"; key-permit = "read","write","del"; }; +======= +>>>>>>> 9b43aa8... dts: add the attestationkeybox of unifykey[1/3] };//End unifykey }; diff --git a/arch/arm64/boot/dts/amlogic/gxl_p241_v2-1g.dts b/arch/arm64/boot/dts/amlogic/gxl_p241_v2-1g.dts index f569d0799fc5..f915038df6cd 100644 --- a/arch/arm64/boot/dts/amlogic/gxl_p241_v2-1g.dts +++ b/arch/arm64/boot/dts/amlogic/gxl_p241_v2-1g.dts @@ -56,8 +56,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm64/boot/dts/amlogic/gxl_p241_v2_1g_buildroot.dts b/arch/arm64/boot/dts/amlogic/gxl_p241_v2_1g_buildroot.dts index 6bfe499fead6..ca8d72a56763 100644 --- a/arch/arm64/boot/dts/amlogic/gxl_p241_v2_1g_buildroot.dts +++ b/arch/arm64/boot/dts/amlogic/gxl_p241_v2_1g_buildroot.dts @@ -55,8 +55,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm64/boot/dts/amlogic/gxl_p400_2g.dts b/arch/arm64/boot/dts/amlogic/gxl_p400_2g.dts index bb6cc479e20c..41ce3a54edcc 100644 --- a/arch/arm64/boot/dts/amlogic/gxl_p400_2g.dts +++ b/arch/arm64/boot/dts/amlogic/gxl_p400_2g.dts @@ -51,8 +51,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm64/boot/dts/amlogic/gxl_p401_2g.dts b/arch/arm64/boot/dts/amlogic/gxl_p401_2g.dts index f316571920da..e8555c961e91 100644 --- a/arch/arm64/boot/dts/amlogic/gxl_p401_2g.dts +++ b/arch/arm64/boot/dts/amlogic/gxl_p401_2g.dts @@ -51,8 +51,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm64/boot/dts/amlogic/gxl_sei210_2g.dts b/arch/arm64/boot/dts/amlogic/gxl_sei210_2g.dts index 5140780d2f7f..cf3440bfd7f8 100644 --- a/arch/arm64/boot/dts/amlogic/gxl_sei210_2g.dts +++ b/arch/arm64/boot/dts/amlogic/gxl_sei210_2g.dts @@ -56,8 +56,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { compatible = "shared-dma-pool"; diff --git a/arch/arm64/boot/dts/amlogic/gxm-sched-energy.dtsi b/arch/arm64/boot/dts/amlogic/gxm-sched-energy.dtsi new file mode 100644 index 000000000000..30fca0951f28 --- /dev/null +++ b/arch/arm64/boot/dts/amlogic/gxm-sched-energy.dtsi @@ -0,0 +1,68 @@ +/ { + energy-costs { + CPU_COST_A53_HS: core-cost0 { + busy-cost-data = < + 33 4 + 83 23 + 166 41 + 221 54 + 332 78 + 399 92 + 503 135 + >; + idle-cost-data = < + 3 + 0 + 0 + >; + }; + + CPU_COST_A53: core-cost1 { + busy-cost-data = < + 33 4 + 83 23 + 166 41 + 221 54 + 332 78 + >; + idle-cost-data = < + 3 + 0 + 0 + >; + }; + + CLUSTER_COST_A53_HS: cluster-cost0 { + busy-cost-data = < + 33 7 + 83 8 + 166 9 + 221 10 + 332 13 + 399 15 + 503 23 + >; + idle-cost-data = < + 6 + 6 + 0 + >; + }; + + CLUSTER_COST_A53: cluster-cost1 { + busy-cost-data = < + 33 7 + 83 8 + 166 9 + 221 10 + 332 13 + >; + idle-cost-data = < + 6 + 6 + 0 + >; + }; + + }; +}; diff --git a/arch/arm64/boot/dts/amlogic/gxm_q200_2g.dts b/arch/arm64/boot/dts/amlogic/gxm_q200_2g.dts index d3bc6cd8c294..6bddb2bcd189 100644 --- a/arch/arm64/boot/dts/amlogic/gxm_q200_2g.dts +++ b/arch/arm64/boot/dts/amlogic/gxm_q200_2g.dts @@ -55,8 +55,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { compatible = "shared-dma-pool"; diff --git a/arch/arm64/boot/dts/amlogic/gxm_q200_2g_buildroot.dts b/arch/arm64/boot/dts/amlogic/gxm_q200_2g_buildroot.dts index e8dcafa47c2e..b5e51bcbd530 100644 --- a/arch/arm64/boot/dts/amlogic/gxm_q200_2g_buildroot.dts +++ b/arch/arm64/boot/dts/amlogic/gxm_q200_2g_buildroot.dts @@ -54,8 +54,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm64/boot/dts/amlogic/gxm_q201_1g.dts b/arch/arm64/boot/dts/amlogic/gxm_q201_1g.dts index a9043e836c4c..0340ebf2682f 100644 --- a/arch/arm64/boot/dts/amlogic/gxm_q201_1g.dts +++ b/arch/arm64/boot/dts/amlogic/gxm_q201_1g.dts @@ -55,9 +55,8 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; -}; + ftrace-size = <0x20000>; + }; secmon_reserved:linux,secmon { compatible = "shared-dma-pool"; @@ -1112,7 +1111,11 @@ compatible = "amlogic, unifykey"; status = "ok"; +<<<<<<< HEAD unifykey-num = <17>; +======= + unifykey-num = <15>; +>>>>>>> 9b43aa8... dts: add the attestationkeybox of unifykey[1/3] unifykey-index-0 = <&keysn_0>; unifykey-index-1 = <&keysn_1>; unifykey-index-2 = <&keysn_2>; @@ -1128,8 +1131,11 @@ unifykey-index-12= <&keysn_12>; unifykey-index-13= <&keysn_13>; unifykey-index-14= <&keysn_14>; +<<<<<<< HEAD unifykey-index-15= <&keysn_15>; unifykey-index-16= <&keysn_16>; +======= +>>>>>>> 9b43aa8... dts: add the attestationkeybox of unifykey[1/3] keysn_0: key_0{ key-name = "usid"; @@ -1209,6 +1215,7 @@ key-device = "secure"; key-permit = "read","write","del"; }; +<<<<<<< HEAD keysn_15:key_15{ key-name = "region_code"; key-device = "normal"; @@ -1219,6 +1226,8 @@ key-device = "secure"; key-permit = "read","write","del"; }; +======= +>>>>>>> 9b43aa8... dts: add the attestationkeybox of unifykey[1/3] };//End unifykey }; &efuse { diff --git a/arch/arm64/boot/dts/amlogic/gxm_q201_2g.dts b/arch/arm64/boot/dts/amlogic/gxm_q201_2g.dts index 0b9e93620866..cde470e1fd8e 100644 --- a/arch/arm64/boot/dts/amlogic/gxm_q201_2g.dts +++ b/arch/arm64/boot/dts/amlogic/gxm_q201_2g.dts @@ -55,8 +55,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { @@ -1115,7 +1114,11 @@ compatible = "amlogic, unifykey"; status = "ok"; +<<<<<<< HEAD unifykey-num = <17>; +======= + unifykey-num = <15>; +>>>>>>> 9b43aa8... dts: add the attestationkeybox of unifykey[1/3] unifykey-index-0 = <&keysn_0>; unifykey-index-1 = <&keysn_1>; unifykey-index-2 = <&keysn_2>; @@ -1131,8 +1134,11 @@ unifykey-index-12= <&keysn_12>; unifykey-index-13= <&keysn_13>; unifykey-index-14= <&keysn_14>; +<<<<<<< HEAD unifykey-index-15= <&keysn_15>; unifykey-index-16= <&keysn_16>; +======= +>>>>>>> 9b43aa8... dts: add the attestationkeybox of unifykey[1/3] keysn_0: key_0{ key-name = "usid"; @@ -1212,6 +1218,7 @@ key-device = "secure"; key-permit = "read","write","del"; }; +<<<<<<< HEAD keysn_15:key_15{ key-name = "region_code"; key-device = "normal"; @@ -1222,6 +1229,8 @@ key-device = "secure"; key-permit = "read","write","del"; }; +======= +>>>>>>> 9b43aa8... dts: add the attestationkeybox of unifykey[1/3] };//End unifykey }; &efuse { diff --git a/arch/arm64/boot/dts/amlogic/gxm_skt.dts b/arch/arm64/boot/dts/amlogic/gxm_skt.dts index 90dde409de72..148290c04da6 100644 --- a/arch/arm64/boot/dts/amlogic/gxm_skt.dts +++ b/arch/arm64/boot/dts/amlogic/gxm_skt.dts @@ -55,8 +55,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { diff --git a/arch/arm64/boot/dts/amlogic/meson64_odroidc3_android.dts b/arch/arm64/boot/dts/amlogic/meson64_odroidc3_android.dts deleted file mode 100644 index 1be53aa9fd87..000000000000 --- a/arch/arm64/boot/dts/amlogic/meson64_odroidc3_android.dts +++ /dev/null @@ -1,78 +0,0 @@ -/* - * arch/arm64/boot/dts/amlogic/meson64_odroidc3_android.dts - * - * Copyright (C) 2018 Hardkernel Co., Ltd. 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 "meson64_odroidc3.dts" - -/ { - firmware { - android { - compatible = "android,firmware"; - vbmeta { - compatible = "android,vbmeta"; - parts = "boot,system,vendor"; - by_name_prefix="/dev/block"; - }; - fstab { - compatible = "android,fstab"; - system { - compatible = "android,system"; - dev = "/dev/block/system"; - type = "ext4"; - mnt_flags = "ro,barrier=1,inode_readahead_blks=8"; - fsmgr_flags = "wait"; - }; - vendor { - compatible = "android,vendor"; - dev = "/dev/block/vendor"; - type = "ext4"; - mnt_flags = "ro,barrier=1,inode_readahead_blks=8"; - fsmgr_flags = "wait"; - }; - odm { - compatible = "android,odm"; - dev = "/dev/block/odm"; - type = "vfat"; - mnt_flags = "rw"; - fsmgr_flags = "wait"; - }; - }; - }; - }; -}; - -&custom_maps { - mapnum = <1>; - map0 = <&map_0>; - map_0: map_0 { - mapname = "hardkernel-remote"; - customcode = <0x4db2>; - release_delay = <80>; - size = <12>; - keymap = ; - }; -}; diff --git a/arch/arm64/boot/dts/amlogic/meson64_odroidn2.dts b/arch/arm64/boot/dts/amlogic/meson64_odroidn2.dts index dce418715d71..4ece5798b1eb 100644 --- a/arch/arm64/boot/dts/amlogic/meson64_odroidn2.dts +++ b/arch/arm64/boot/dts/amlogic/meson64_odroidn2.dts @@ -17,7 +17,7 @@ /dts-v1/; -#include "mesong12b.dtsi" +#include "mesong12b_a.dtsi" #include "mesong12_odroid_common.dtsi" / { @@ -39,8 +39,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { @@ -49,6 +48,7 @@ size = <0x0 0x400000>; alignment = <0x0 0x400000>; alloc-ranges = <0x0 0x05000000 0x0 0x400000>; + clear-map; }; secos_reserved:linux,secos { @@ -57,6 +57,13 @@ reg = <0x0 0x05300000 0x0 0x2000000>; no-map; }; + + /* POST PROCESS MANAGER */ + ppmgr_reserved:linux,ppmgr { + compatible = "shared-dma-pool"; + size = <0x0 0x0>; + }; + logo_reserved:linux,meson-fb { compatible = "shared-dma-pool"; reusable; @@ -95,11 +102,6 @@ size = <0x0 0x02800000>; alignment = <0x0 0x400000>; }; - /* POST PROCESS MANAGER */ - ppmgr_reserved:linux,ppmgr { - compatible = "shared-dma-pool"; - size = <0x0 0x0>; - }; codec_mm_cma:linux,codec_mm_cma { compatible = "shared-dma-pool"; reusable; @@ -107,6 +109,7 @@ size = <0x0 0x13400000>; alignment = <0x0 0x400000>; linux,contiguous-region; + clear-map; }; /* codec shared reserved */ codec_mm_reserved:linux,codec_mm_reserved { @@ -133,6 +136,17 @@ size = <0x0 0x04000000>; alignment = <0x0 0x400000>; }; + galcore_reserved:linux,galcore { + compatible = "shared-dma-pool"; + reusable; + size = <0x1000000>; + alignment = <0x400000>; + linux,contiguous-region; + }; + }; + galcore { + status = "okay"; + memory-region = <&galcore_reserved>; }; cvbsout { diff --git a/arch/arm64/boot/dts/amlogic/meson64_odroidn2_android.dts b/arch/arm64/boot/dts/amlogic/meson64_odroidn2_android.dts deleted file mode 100644 index 74b5c1b77d54..000000000000 --- a/arch/arm64/boot/dts/amlogic/meson64_odroidn2_android.dts +++ /dev/null @@ -1,78 +0,0 @@ -/* - * arch/arm64/boot/dts/amlogic/meson64_odroidc3_android.dts - * - * Copyright (C) 2018 Hardkernel Co., Ltd. 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 "meson64_odroidn2.dts" - -/ { - firmware { - android { - compatible = "android,firmware"; - vbmeta { - compatible = "android,vbmeta"; - parts = "boot,system,vendor"; - by_name_prefix="/dev/block"; - }; - fstab { - compatible = "android,fstab"; - system { - compatible = "android,system"; - dev = "/dev/block/system"; - type = "ext4"; - mnt_flags = "ro,barrier=1,inode_readahead_blks=8"; - fsmgr_flags = "wait"; - }; - vendor { - compatible = "android,vendor"; - dev = "/dev/block/vendor"; - type = "ext4"; - mnt_flags = "ro,barrier=1,inode_readahead_blks=8"; - fsmgr_flags = "wait"; - }; - odm { - compatible = "android,odm"; - dev = "/dev/block/odm"; - type = "vfat"; - mnt_flags = "rw"; - fsmgr_flags = "wait"; - }; - }; - }; - }; -}; - -&custom_maps { - mapnum = <1>; - map0 = <&map_0>; - map_0: map_0 { - mapname = "hardkernel-remote"; - customcode = <0x4db2>; - release_delay = <80>; - size = <12>; - keymap = ; - }; -}; diff --git a/arch/arm64/boot/dts/amlogic/mesonaxg.dtsi b/arch/arm64/boot/dts/amlogic/mesonaxg.dtsi index 14759a6ef0e3..00f49dd1268d 100644 --- a/arch/arm64/boot/dts/amlogic/mesonaxg.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesonaxg.dtsi @@ -119,24 +119,19 @@ bit_mode=<12>; bit_resolution=<0>; }; + arm_pmu { compatible = "arm,armv8-pmuv3"; - interrupts = <0 137 4>; - reg = <0x0 0xff634400 0 0x1000>; - - /* addr = base + offset << 2 */ - sys_cpu_status0_offset = <0xa0>; - - sys_cpu_status0_pmuirq_mask = <0xf>; - + /* clusterb-enabled; */ + interrupts = ; + reg = <0x0 0xff634680 0x0 0x4>; + cpumasks = <0xf>; /* default 10ms */ - relax_timer_ns = <10000000>; - + relax-timer-ns = <10000000>; /* default 10000us */ - max_wait_cnt = <10000>; + max-wait-cnt = <10000>; }; - gic: interrupt-controller@2c001000 { compatible = "arm,cortex-a15-gic", "arm,cortex-a9-gic"; #interrupt-cells = <3>; @@ -152,15 +147,14 @@ method = "smc"; }; - meson_suspend:pm { + aml_pm { compatible = "amlogic, pm"; device_name = "aml_pm"; status = "okay"; - reg = <0x0 0xff8000a8 0x0 0x4>, - <0x0 0xff80023c 0x0 0x4>; + debug_reg = <0xff8000a8>; + exit_reg = <0xff80023c>; }; - secmon { compatible = "amlogic, secmon"; memory-region = <&secmon_reserved>; @@ -285,6 +279,18 @@ ram-dump { compatible = "amlogic, ram_dump"; status = "okay"; + reg = <0x0 0xFF6345E0 0x0 4>; + reg-names = "PREG_STICKY_REG8"; + store_device = "data"; + }; + + jtag { + compatible = "amlogic, jtag"; + status = "okay"; + select = "disable"; /* disable/apao/apee */ + pinctrl-names="jtag_apao_pins", "jtag_apee_pins"; + pinctrl-0=<&jtag_apao_pins>; + pinctrl-1=<&jtag_apee_pins>; }; pinctrl_aobus: pinctrl@ff800014{ @@ -463,6 +469,16 @@ clock-names = "clk_i2c"; clock-frequency = <100000>; }; + + irblaster: meson-irblaster@c0 { + compatible = "amlogic, aml_irblaster"; + reg = <0x0 0xc0 0x0 0xc>, + <0x0 0x40 0x0 0x4>; + #irblaster-cells = <2>; + pinctrl-names = "default"; + pinctrl-0 = <&irblaster_pins>; + status = "disabled"; + }; };/* end of aobus */ periphs: periphs@ff634400 { @@ -738,16 +754,6 @@ }; }; - irblaster: meson-irblaster { - compatible = "amlogic, meson_irblaster"; - reg = <0x0 0xff8000c0 0x0 0x10>, - <0x0 0xff800040 0x0 0x4>; - pinctrl-names = "default"; - pinctrl-0 = <&irblaster_pins>; - interrupts = <0 198 1>; - status = "disabled"; - }; - saradc:saradc { compatible = "amlogic,meson-axg-saradc"; status = "okay"; @@ -820,6 +826,12 @@ cpu_ver_name{ compatible = "amlogic, cpu-major-id-axg"; }; + + openvfd { + compatible = "open,vfd"; + dev_name = "openvfd"; + status = "okay"; + }; };/* end of / */ &pinctrl_aobus { @@ -885,6 +897,15 @@ }; }; + jtag_apao_pins:jtag_apao_pin { + mux { + groups = "jtag_ao_tdi", + "jtag_ao_tdo", + "jtag_ao_clk", + "jtag_ao_tms"; + function = "jtag_ao"; + }; + }; }; /* end of pinctrl_aobus */ &pinctrl_periphs { @@ -1146,5 +1167,14 @@ }; }; + jtag_apee_pins:jtag_apee_pin { + mux { + groups = "jtag_tdo_x", + "jtag_tdi_x", + "jtag_clk_x", + "jtag_tms_x"; + function = "jtag_ee"; + }; + }; }; /* end of pinctrl_periphs */ diff --git a/arch/arm64/boot/dts/amlogic/mesong12_odroid_common.dtsi b/arch/arm64/boot/dts/amlogic/mesong12_odroid_common.dtsi index f6ff8991ad8d..54b4075f9db0 100644 --- a/arch/arm64/boot/dts/amlogic/mesong12_odroid_common.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesong12_odroid_common.dtsi @@ -46,12 +46,12 @@ status = "okay"; }; - ppmgr { - compatible = "amlogic, ppmgr"; - memory-region = <&ppmgr_reserved>; - dev_name = "ppmgr"; - status = "okay"; - }; + ppmgr { + compatible = "amlogic, ppmgr"; + memory-region = <&ppmgr_reserved>; + dev_name = "ppmgr"; + status = "okay"; + }; ionvideo { compatible = "amlogic, ionvideo"; @@ -189,6 +189,8 @@ write_cmd = <0x82000031>; get_max_cmd = <0x82000033>; key = <&efusekey>; + clocks = <&clkc CLKID_EFUSE>; + clock-names = "efuse_clk"; status = "okay"; }; @@ -525,8 +527,8 @@ }; }; spdifout: spdifout { - mux {/* GPIOA_11 */ - groups = "spdif_out_a11"; + mux {/* GPIOA_13 */ + groups = "spdif_out_a13"; function = "spdif_out"; }; }; diff --git a/arch/arm64/boot/dts/amlogic/mesong12a.dtsi b/arch/arm64/boot/dts/amlogic/mesong12a.dtsi index 9d1b4bb7db53..0880f335af5e 100644 --- a/arch/arm64/boot/dts/amlogic/mesong12a.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesong12a.dtsi @@ -155,21 +155,17 @@ bit_mode=<12>; bit_resolution=<0>; }; + arm_pmu { compatible = "arm,armv8-pmuv3"; - interrupts = <0 137 4>; - reg = <0x0 0xff634400 0 0x1000>; - - /* addr = base + offset << 2 */ - sys_cpu_status0_offset = <0xa0>; - - sys_cpu_status0_pmuirq_mask = <0xf>; - + /* clusterb-enabled; */ + interrupts = ; + reg = <0x0 0xff634680 0x0 0x4>; + cpumasks = <0xf>; /* default 10ms */ - relax_timer_ns = <10000000>; - + relax-timer-ns = <10000000>; /* default 10000us */ - max_wait_cnt = <10000>; + max-wait-cnt = <10000>; }; gic: interrupt-controller@2c001000 { @@ -187,12 +183,12 @@ method = "smc"; }; - meson_suspend:pm { + aml_pm { compatible = "amlogic, pm"; status = "okay"; device_name = "aml_pm"; - reg = <0x0 0xff8000a8 0x0 0x4>, - <0x0 0xff80023c 0x0 0x4>; + debug_reg = <0xff8000a8>; + exit_reg = <0xff80023c>; }; secmon { @@ -446,20 +442,18 @@ ram-dump { compatible = "amlogic, ram_dump"; status = "okay"; + reg = <0x0 0xFF6345E0 0x0 4>; + reg-names = "PREG_STICKY_REG8"; + store_device = "data"; }; jtag { compatible = "amlogic, jtag"; status = "okay"; - select = "apao"; /* disable/apao/apee */ - jtagao-gpios = <&gpio_ao GPIOAO_6 0 - &gpio_ao GPIOAO_7 0 - &gpio_ao GPIOAO_8 0 - &gpio_ao GPIOAO_9 0>; - jtagee-gpios = <&gpio GPIOC_0 0 - &gpio GPIOC_1 0 - &gpio GPIOC_4 0 - &gpio GPIOC_5 0>; + select = "disable"; /* disable/apao/apee */ + pinctrl-names="jtag_apao_pins", "jtag_apee_pins"; + pinctrl-0=<&jtag_apao_pins>; + pinctrl-1=<&jtag_apee_pins>; }; saradc:saradc { @@ -763,6 +757,17 @@ pinctrl-names = "default"; pinctrl-0 = <&ao_b_uart_pins>; }; + + irblaster: meson-irblaster@14c { + compatible = "amlogic, meson_irblaster"; + reg = <0x0 0x14c 0x0 0x10>, + <0x0 0x40 0x0 0x4>; + #irblaster-cells = <2>; + pinctrl-names = "default"; + pinctrl-0 = <&irblaster_pins>; + interrupts = ; + status = "disabled"; + }; };/* end of aobus */ periphs: periphs@ff634400 { @@ -1089,6 +1094,7 @@ * 10:G12A */ ic_type = <10>; + dongle_mode = <0>; vend_data: vend_data{ /* Should modified by Customer */ vendor_name = "Amlogic"; /* Max Chars: 8 */ /* standards.ieee.org/develop/regauth/oui/oui.txt */ @@ -1096,6 +1102,12 @@ }; }; + amprime_sl: amprime_sl { + compatible = "amlogic, prime_sl_g12"; + dev_name = "amprime_sl"; + status = "disabled"; + }; + aocec: aocec { compatible = "amlogic, aocec-g12a"; device_name = "aocec"; @@ -1339,15 +1351,6 @@ clocks = <&clkc CLKID_VPU_CLKC_MUX>; clock-names = "vpu_clkc"; }; - irblaster: meson-irblaster { - compatible = "amlogic, meson_irblaster"; - reg = <0x0 0xff80014c 0x0 0x10>, - <0x0 0xff800040 0x0 0x4>; - pinctrl-names = "default"; - pinctrl-0 = <&irblaster_pins>; - interrupts = <0 198 1>; - status = "okay"; - }; sd_emmc_c: emmc@ffe07000 { status = "disabled"; @@ -1382,7 +1385,7 @@ calc_f = <1>; max_req_size = <0x20000>; /**128KB*/ gpio_dat3 = <&gpio BOOT_3 GPIO_ACTIVE_HIGH>; - hw_reset = <&gpio BOOT_9 GPIO_ACTIVE_HIGH>; + hw_reset = <&gpio BOOT_12 GPIO_ACTIVE_HIGH>; card_type = <1>; /* 1:mmc card(include eMMC), * 2:sd card(include tSD) @@ -1759,7 +1762,7 @@ max-duty-cycle = <1250>; /* Voltage Duty-Cycle */ voltage-table = <1022000 0>, - <1011000 3>, + <1011000 3>, <1001000 6>, <991000 10>, <981000 13>, @@ -1830,6 +1833,12 @@ dev_name = "aml_sha_dma"; status = "okay"; }; + + aml_tdes { + compatible = "amlogic,tdes_dma"; + dev_name = "aml_tdes_dma"; + status = "okay"; + }; }; rng { @@ -1855,6 +1864,12 @@ cpu_ver_name { compatible = "amlogic, cpu-major-id-g12a"; }; + + openvfd { + compatible = "open,vfd"; + dev_name = "openvfd"; + status = "okay"; + }; };/* end of / */ &pinctrl_aobus { @@ -1994,6 +2009,16 @@ function = "cec_ao"; }; }; + + jtag_apao_pins:jtag_apao_pin { + mux { + groups = "jtag_a_tdi", + "jtag_a_tdo", + "jtag_a_clk", + "jtag_a_tms"; + function = "jtag_a"; + }; + }; }; &pinctrl_periphs { @@ -2579,6 +2604,16 @@ drive-strength = <3>; }; }; + + jtag_apee_pins:jtag_apee_pin { + mux { + groups = "jtag_b_tdi", + "jtag_b_tdo", + "jtag_b_clk", + "jtag_b_tms"; + function = "jtag_b"; + }; + }; }; &pinctrl_aobus { diff --git a/arch/arm64/boot/dts/amlogic/mesong12a_drm.dtsi b/arch/arm64/boot/dts/amlogic/mesong12a_drm.dtsi index 9708a6296f86..60c3cff86599 100644 --- a/arch/arm64/boot/dts/amlogic/mesong12a_drm.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesong12a_drm.dtsi @@ -107,3 +107,24 @@ }; }; +&gpu{ + /*gpu max freq is 850M*/ + def_clk = <1>; + tbl = <&dvfs285_cfg &dvfs666_cfg &dvfs850_cfg &dvfs850_cfg>; + + dvfs285_cfg:dvfs285_cfg { + keep_count = <2>; + threshold = <100 200>; + }; + + dvfs666_cfg:dvfs666_cfg { + keep_count = <1>; + threshold = <85 200>; + }; + + dvfs850_cfg:dvfs850_cfg { + keep_count = <1>; + threshold = <179 255>; + }; + +}; diff --git a/arch/arm64/boot/dts/amlogic/mesong12b.dtsi b/arch/arm64/boot/dts/amlogic/mesong12b.dtsi index db8954b1bcda..3786fbdfca64 100644 --- a/arch/arm64/boot/dts/amlogic/mesong12b.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesong12b.dtsi @@ -215,9 +215,19 @@ bit_mode=<12>; bit_resolution=<0>; }; + arm_pmu { compatible = "arm,armv8-pmuv3"; - interrupts = <0 137 4>; + clusterb-enabled; + interrupts = , + ; + reg = <0x0 0xff634680 0x0 0x4>, + <0x0 0xff6347c0 0x0 0x04>; + cpumasks = <0x3 0x3C>; + /* default 10ms */ + relax-timer-ns = <10000000>; + /* default 10000us */ + max-wait-cnt = <10000>; }; gic: interrupt-controller@2c001000 { @@ -235,12 +245,12 @@ method = "smc"; }; - meson_suspend:pm { + aml_pm { compatible = "amlogic, pm"; status = "okay"; device_name = "aml_pm"; - reg = <0x0 0xff8000a8 0x0 0x4>, - <0x0 0xff80023c 0x0 0x4>; + debug_reg = <0xff8000a8>; + exit_reg = <0xff80023c>; }; secmon { @@ -311,6 +321,14 @@ #clock-cells = <0>; }; + rtc{ + compatible = "amlogic, aml_vrtc"; + alarm_reg_addr = <0xff8000a8>; + timer_e_addr = <0xffd0f188>; + init_date = "2019/01/01"; + status = "okay"; + }; + cpu_info { compatible = "amlogic, cpuinfo"; status = "okay"; @@ -484,6 +502,15 @@ clocks = <&xtal>; }; + jtag { + compatible = "amlogic, jtag"; + status = "okay"; + select = "disable"; /* disable/apao/apee */ + pinctrl-names="jtag_apao_pins", "jtag_apee_pins"; + pinctrl-0=<&jtag_apao_pins>; + pinctrl-1=<&jtag_apee_pins>; + }; + saradc:saradc { compatible = "amlogic,meson-g12a-saradc"; status = "disabled"; @@ -530,6 +557,14 @@ #thermal-sensor-cells = <1>; }; + ram-dump { + compatible = "amlogic, ram_dump"; + status = "okay"; + reg = <0x0 0xFF6345E0 0x0 4>; + reg-names = "PREG_STICKY_REG8"; + store_device = "data"; + }; + soc { compatible = "simple-bus"; #address-cells = <2>; @@ -786,6 +821,15 @@ pinctrl-names = "default"; pinctrl-0 = <&ao_b_uart_pins>; }; + + irblaster: meson-irblaster@14c { + compatible = "amlogic, meson_irblaster"; + reg = <0x0 0x14c 0x0 0x10>, + <0x0 0x40 0x0 0x4>; + #irblaster-cells = <2>; + interrupts = ; + status = "disabled"; + }; };/* end of aobus */ periphs: periphs@ff634400 { @@ -848,167 +892,44 @@ }; };/* end of audiobus*/ + aml_dma { + compatible = "amlogic,aml_txlx_dma"; + reg = <0x0 0xff63e000 0x0 0x48>; + interrupts = <0 180 1>; + + aml_aes { + compatible = "amlogic,aes_g12a_dma"; + dev_name = "aml_aes_dma"; + status = "okay"; + }; + + aml_sha { + compatible = "amlogic,sha_dma"; + dev_name = "aml_sha_dma"; + status = "okay"; + }; + + aml_tdes { + compatible = "amlogic,tdes_dma"; + dev_name = "aml_tdes_dma"; + status = "okay"; + }; + }; }; /* end of soc*/ - remote:rc@0xff808040 { + meson-remote { compatible = "amlogic, aml_remote"; dev_name = "meson-remote"; reg = <0x0 0xff808040 0x00 0x44>, /*Multi-format IR controller*/ <0x0 0xff808000 0x00 0x20>; /*Legacy IR controller*/ - status = "okay"; + status = "disabled"; protocol = ; interrupts = <0 196 1>; pinctrl-names = "default"; pinctrl-0 = <&remote_pins>; - map = <&custom_maps>; max_frame_time = <200>; /*set software decoder max frame time*/ }; - custom_maps:custom_maps { - mapnum = <3>; - map0 = <&map_0>; - map1 = <&map_1>; - map2 = <&map_2>; - map_0: map_0{ - mapname = "amlogic-remote-1"; - customcode = <0xfb04>; - release_delay = <80>; - size = <50>; /*keymap size*/ - keymap = ; - }; - map_1: map_1{ - mapname = "amlogic-remote-2"; - customcode = <0xfe01>; - release_delay = <80>; - size = <53>; - keymap = ; - }; - map_2: map_2{ - mapname = "amlogic-remote-3"; - customcode = <0xbd02>; - release_delay = <80>; - size = <17>; - keymap = ; - }; - }; - uart_A: serial@ffd24000 { compatible = "amlogic, meson-uart"; reg = <0x0 0xffd24000 0x0 0x18>; @@ -1122,6 +1043,12 @@ }; }; + amprime_sl: amprime_sl { + compatible = "amlogic, prime_sl_g12"; + dev_name = "amprime_sl"; + status = "disabled"; + }; + galcore { compatible = "amlogic, galcore"; dev_name = "galcore"; @@ -1130,7 +1057,7 @@ <&clkc CLKID_VNANOQ_CORE_CLK_COMP>; clock-names = "cts_vipnanoq_axi_clk_composite", "cts_vipnanoq_core_clk_composite"; - interrupts = <0 147 1>; + interrupts = <0 147 4>; interrupt-names = "galcore"; reg = <0x0 0xff100000 0x0 0x800 0x0 0xff000000 0x0 0x400000>; @@ -1318,6 +1245,13 @@ "clk_hevcb_mux"; }; + amvideocap { + compatible = "amlogic, amvideocap"; + dev_name = "amvideocap.0"; + status = "okay"; + max_size = <8>;//8M + }; + vdec { compatible = "amlogic, vdec"; dev_name = "vdec.0"; @@ -1360,7 +1294,7 @@ }; rdma{ - compatible = "amlogic, meson, rdma"; + compatible = "amlogic, meson-g12b, rdma"; dev_name = "amlogic-rdma"; status = "okay"; interrupts = <0 89 1>; @@ -1385,15 +1319,6 @@ clocks = <&clkc CLKID_VPU_CLKC_MUX>; clock-names = "vpu_clkc"; }; - irblaster: meson-irblaster { - compatible = "amlogic, meson_irblaster"; - reg = <0x0 0xff80014c 0x0 0x10>, - <0x0 0xff800040 0x0 0x4>; - pinctrl-names = "default"; - pinctrl-0 = <&irblaster_pins>; - interrupts = <0 198 1>; - status = "disabled"; - }; sd_emmc_c: emmc@ffe07000 { status = "disabled"; @@ -1406,9 +1331,9 @@ clocks = <&clkc CLKID_SD_EMMC_C>, <&clkc CLKID_SD_EMMC_C_P0_COMP>, <&clkc CLKID_FCLK_DIV2>, - <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_FCLK_DIV2P5>, <&xtal>; - clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + clock-names = "core","clkin0","clkin1","clkin2","xtal"; bus-width = <8>; cap-sd-highspeed; @@ -1572,20 +1497,11 @@ node_name = "cpufreq_cool1"; device_type = "cpufreq"; }; - cpucore_cool_cluster0 { + cpucore_cool_cluster { min_state = <1>; dyn_coeff = <0>; - cluster_id = <0>; gpu_pp = <2>; - node_name = "cpucore_cool0"; - device_type = "cpucore"; - }; - cpucore_cool_cluster1 { - min_state = <0>; - dyn_coeff = <0>; - cluster_id = <1>; - gpu_pp = <2>; - node_name = "cpucore_cool1"; + node_name = "cpucore_cool"; device_type = "cpucore"; }; gpufreq_cool { @@ -1611,10 +1527,7 @@ cpufreq_cool1:cpufreq_cool1 { #cooling-cells = <2>; /* min followed by max */ }; - cpucore_cool0:cpucore_cool0 { - #cooling-cells = <2>; /* min followed by max */ - }; - cpucore_cool1:cpucore_cool1 { + cpucore_cool:cpucore_cool { #cooling-cells = <2>; /* min followed by max */ }; gpufreq_cool0:gpufreq_cool0 { @@ -1634,7 +1547,7 @@ thermal-sensors = <&p_tsensor 0>; trips { pswitch_on: trip-point@0 { - temperature = <65000>; + temperature = <60000>; hysteresis = <5000>; type = "passive"; }; @@ -1644,7 +1557,7 @@ type = "passive"; }; phot: trip-point@2 { - temperature = <95000>; + temperature = <85000>; hysteresis = <5000>; type = "hot"; }; @@ -1668,12 +1581,7 @@ }; cpucore_cooling_map0 { trip = <&pcontrol>; - cooling-device = <&cpucore_cool0 0 1>; - contribution = <1024>; - }; - cpucore_cooling_map1 { - trip = <&pcontrol>; - cooling-device = <&cpucore_cool1 0 4>; + cooling-device = <&cpucore_cool 0 5>; contribution = <1024>; }; gpufreq_cooling_map { @@ -1886,6 +1794,7 @@ reg-names = "adapter"; interrupts = <0 179 0>; interrupt-names = "adapter-irq"; + mem_alloc = <48>; }; phycsi: phy-csi@ff650000 { @@ -1918,6 +1827,12 @@ mem_size = <0x0 0x100000>; status = "okay"; }; + + openvfd { + compatible = "open,vfd"; + dev_name = "openvfd"; + status = "okay"; + }; };/* end of / */ &pinctrl_aobus { @@ -2047,6 +1962,16 @@ function = "pwm_a_gpioe"; }; }; + + jtag_apao_pins:jtag_apao_pin { + mux { + groups = "jtag_a_tdi", + "jtag_a_tdo", + "jtag_a_clk", + "jtag_a_tms"; + function = "jtag_a"; + }; + }; }; &pinctrl_periphs { @@ -2565,6 +2490,16 @@ function = "remote_out"; }; }; + + jtag_apee_pins:jtag_apee_pin { + mux { + groups = "jtag_b_tdi", + "jtag_b_tdo", + "jtag_b_clk", + "jtag_b_tms"; + function = "jtag_b"; + }; + }; }; &gpu{ diff --git a/arch/arm64/boot/dts/amlogic/mesong12b_a.dtsi b/arch/arm64/boot/dts/amlogic/mesong12b_a.dtsi new file mode 100644 index 000000000000..03afb23726d4 --- /dev/null +++ b/arch/arm64/boot/dts/amlogic/mesong12b_a.dtsi @@ -0,0 +1,2508 @@ +/* + * arch/arm64/boot/dts/amlogic/mesong12b_a.dtsi + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "mesong12a-bifrost.dtsi" +#include "g12b-sched-energy-a.dtsi" + +/ { + cpus:cpus { + #address-cells = <2>; + #size-cells = <0>; + + cpu-map { + cluster0:cluster0 { + core0 { + cpu = <&CPU0>; + }; + core1 { + cpu = <&CPU1>; + }; + }; + cluster1:cluster1 { + core0 { + cpu = <&CPU2>; + }; + core1 { + cpu = <&CPU3>; + }; + core2 { + cpu = <&CPU4>; + }; + core3 { + cpu = <&CPU5>; + }; + }; + }; + + CPU0:cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a53","arm,armv8"; + reg = <0x0 0x0>; + enable-method = "psci"; + //cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; + sched-energy-costs = <&CPU_COST_A53 &CLUSTER_COST_A53>; + clocks = <&clkc CLKID_CPU_CLK>, + <&clkc CLKID_CPU_FCLK_P>, + <&clkc CLKID_SYS1_PLL>; + clock-names = "core_clk", + "low_freq_clk_parent", + "high_freq_clk_parent"; + operating-points-v2 = <&cpu_opp_table0>; + cpu-supply = <&vddcpu0>; + voltage-tolerance = <0>; + clock-latency = <50000>; + }; + + CPU1:cpu@1 { + device_type = "cpu"; + compatible = "arm,cortex-a53","arm,armv8"; + reg = <0x0 0x1>; + enable-method = "psci"; + sched-energy-costs = <&CPU_COST_A53 &CLUSTER_COST_A53>; + clocks = <&clkc CLKID_CPU_CLK>, + <&clkc CLKID_CPU_FCLK_P>, + <&clkc CLKID_SYS1_PLL>; + clock-names = "core_clk", + "low_freq_clk_parent", + "high_freq_clk_parent"; + operating-points-v2 = <&cpu_opp_table0>; + cpu-supply = <&vddcpu0>; + voltage-tolerance = <0>; + clock-latency = <50000>; + }; + + CPU2:cpu@100 { + device_type = "cpu"; + compatible = "arm,cortex-a73","arm,armv8"; + reg = <0x0 0x100>; + enable-method = "psci"; + //cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; + sched-energy-costs = <&CPU_COST_A73 &CLUSTER_COST_A73>; + clocks = <&clkc CLKID_CPUB_CLK>, + <&clkc CLKID_CPUB_FCLK_P>, + <&clkc CLKID_SYS_PLL>; + clock-names = "core_clk", + "low_freq_clk_parent", + "high_freq_clk_parent"; + operating-points-v2 = <&cpu_opp_table1>; + cpu-supply = <&vddcpu1>; + voltage-tolerance = <0>; + clock-latency = <50000>; + }; + + CPU3:cpu@101 { + device_type = "cpu"; + compatible = "arm,cortex-a73","arm,armv8"; + reg = <0x0 0x101>; + enable-method = "psci"; + //cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; + sched-energy-costs = <&CPU_COST_A73 &CLUSTER_COST_A73>; + clocks = <&clkc CLKID_CPUB_CLK>, + <&clkc CLKID_CPUB_FCLK_P>, + <&clkc CLKID_SYS_PLL>; + clock-names = "core_clk", + "low_freq_clk_parent", + "high_freq_clk_parent"; + operating-points-v2 = <&cpu_opp_table1>; + cpu-supply = <&vddcpu1>; + voltage-tolerance = <0>; + clock-latency = <50000>; + }; + + CPU4:cpu@102 { + device_type = "cpu"; + compatible = "arm,cortex-a73","arm,armv8"; + reg = <0x0 0x102>; + enable-method = "psci"; + //cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; + sched-energy-costs = <&CPU_COST_A73 &CLUSTER_COST_A73>; + clocks = <&clkc CLKID_CPUB_CLK>, + <&clkc CLKID_CPUB_FCLK_P>, + <&clkc CLKID_SYS_PLL>; + clock-names = "core_clk", + "low_freq_clk_parent", + "high_freq_clk_parent"; + operating-points-v2 = <&cpu_opp_table1>; + cpu-supply = <&vddcpu1>; + voltage-tolerance = <0>; + clock-latency = <50000>; + }; + + CPU5:cpu@103 { + device_type = "cpu"; + compatible = "arm,cortex-a73","arm,armv8"; + reg = <0x0 0x103>; + enable-method = "psci"; + //cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; + sched-energy-costs = <&CPU_COST_A73 &CLUSTER_COST_A73>; + clocks = <&clkc CLKID_CPUB_CLK>, + <&clkc CLKID_CPUB_FCLK_P>, + <&clkc CLKID_SYS_PLL>; + clock-names = "core_clk", + "low_freq_clk_parent", + "high_freq_clk_parent"; + operating-points-v2 = <&cpu_opp_table1>; + cpu-supply = <&vddcpu1>; + voltage-tolerance = <0>; + clock-latency = <50000>; + }; + + idle-states { + entry-method = "arm,psci"; + + CPU_SLEEP_0: cpu-sleep-0 { + compatible = "arm,idle-state"; + arm,psci-suspend-param = <0x0010000>; + local-timer-stop; + entry-latency-us = <8000>; + exit-latency-us = <8000>; + min-residency-us = <20000>; + }; + + CLUSTER_SLEEP_0: cluster-sleep-0 { + compatible = "arm,idle-state"; + arm,psci-suspend-param = <0x1010000>; + local-timer-stop; + entry-latency-us = <9000>; + exit-latency-us = <9000>; + min-residency-us = <25000>; + }; + }; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupts = , + , + , + ; + }; + + timer_bc { + compatible = "arm, meson-bc-timer"; + reg= <0x0 0xffd0f190 0x0 0x4 0x0 0xffd0f194 0x0 0x4>; + timer_name = "Meson TimerF"; + clockevent-rating=<300>; + clockevent-shift=<20>; + clockevent-features=<0x23>; + interrupts = <0 60 1>; + bit_enable=<16>; + bit_mode=<12>; + bit_resolution=<0>; + }; + + arm_pmu { + compatible = "arm,armv8-pmuv3"; + clusterb-enabled; + interrupts = , + ; + reg = <0x0 0xff634680 0x0 0x4>, + <0x0 0xff6347c0 0x0 0x04>; + cpumasks = <0x3 0x3C>; + /* default 10ms */ + relax-timer-ns = <10000000>; + /* default 10000us */ + max-wait-cnt = <10000>; + }; + + gic: interrupt-controller@2c001000 { + compatible = "arm,cortex-a15-gic", "arm,cortex-a9-gic"; + #interrupt-cells = <3>; + #address-cells = <0>; + interrupt-controller; + reg = <0x0 0xffc01000 0 0x1000>, + <0x0 0xffc02000 0 0x0100>; + interrupts = ; + }; + + psci { + compatible = "arm,psci-0.2"; + method = "smc"; + }; + + meson_suspend:pm { + compatible = "amlogic, pm"; + status = "okay"; + device_name = "aml_pm"; + debug_reg = <0xff8000a8>; + exit_reg = <0xff80023c>; + }; + + secmon { + compatible = "amlogic, secmon"; + memory-region = <&secmon_reserved>; + in_base_func = <0x82000020>; + out_base_func = <0x82000021>; + reserve_mem_size = <0x00300000>; + clear_range = <0x05100000 0x200000>; + }; + + securitykey { + compatible = "aml, securitykey"; + storage_query = <0x82000060>; + storage_read = <0x82000061>; + storage_write = <0x82000062>; + storage_tell = <0x82000063>; + storage_verify = <0x82000064>; + storage_status = <0x82000065>; + storage_list = <0x82000067>; + storage_remove = <0x82000068>; + storage_in_func = <0x82000023>; + storage_out_func = <0x82000024>; + storage_block_func = <0x82000025>; + storage_size_func = <0x82000027>; + storage_set_enctype = <0x8200006A>; + storage_get_enctype = <0x8200006B>; + storage_version = <0x8200006C>; + }; + + mailbox: mhu@c883c400 { + compatible = "amlogic, meson_mhu"; + reg = <0x0 0xff63c400 0x0 0x4c>, /* MHU registers */ + <0x0 0xfffe7000 0x0 0x800>; /* Payload area */ + interrupts = <0 209 1>, /* low priority interrupt */ + <0 210 1>; /* high priority interrupt */ + #mbox-cells = <1>; + mbox-names = "cpu_to_scp_low", "cpu_to_scp_high"; + mboxes = <&mailbox 0 &mailbox 1>; + }; + + cpu_iomap { + compatible = "amlogic, iomap"; + #address-cells=<2>; + #size-cells=<2>; + ranges; + io_cbus_base { + reg = <0x0 0xffd00000 0x0 0x26000>; + }; + io_apb_base { + reg = <0x0 0xffe01000 0x0 0x7f000>; + }; + io_aobus_base { + reg = <0x0 0xff800000 0x0 0xb000>; + }; + io_vapb_base { + reg = <0x0 0xff900000 0x0 0x50000>; + }; + io_hiu_base { + reg = <0x0 0xff63c000 0x0 0x2000>; + }; + }; + + xtal: xtal-clk { + compatible = "fixed-clock"; + clock-frequency = <24000000>; + clock-output-names = "xtal"; + #clock-cells = <0>; + }; + + cpu_info { + compatible = "amlogic, cpuinfo"; + status = "okay"; + cpuinfo_cmd = <0x82000044>; + }; + + aml_reboot{ + compatible = "aml, reboot"; + sys_reset = <0x84000009>; + sys_poweroff = <0x84000008>; + }; + + vpu { + compatible = "amlogic, vpu-g12b"; + dev_name = "vpu"; + status = "okay"; + clocks = <&clkc CLKID_VAPB_MUX>, + <&clkc CLKID_VPU_INTR>, + <&clkc CLKID_VPU_P0_COMP>, + <&clkc CLKID_VPU_P1_COMP>, + <&clkc CLKID_VPU_MUX>; + clock-names = "vapb_clk", + "vpu_intr_gate", + "vpu_clk0", + "vpu_clk1", + "vpu_clk"; + clk_level = <7>; + /* 0: 100.0M 1: 166.7M 2: 200.0M 3: 250.0M */ + /* 4: 333.3M 5: 400.0M 6: 500.0M 7: 666.7M */ + }; + + ethmac: ethernet@ff3f0000 { + compatible = "amlogic, g12a-eth-dwmac","snps,dwmac"; + reg = <0x0 0xff3f0000 0x0 0x10000 + 0x0 0xff634540 0x0 0x8 + 0x0 0xff64c000 0x0 0xa0>; + reg-names = "eth_base", "eth_cfg", "eth_pll"; + interrupts = <0 8 1>; + interrupt-names = "macirq"; + status = "disabled"; + clocks = <&clkc CLKID_ETH_CORE>; + clock-names = "ethclk81"; + pll_val = <0x9c0040a 0x927e0000 0xac5f49e5>; + analog_val = <0x20200000 0x0000c000 0x00000023>; + }; + + pinctrl_aobus: pinctrl@ff800014{ + compatible = "amlogic,meson-g12a-aobus-pinctrl"; + #address-cells = <2>; + #size-cells = <2>; + ranges; + + gpio_ao: ao-bank@ff800014{ + reg = <0x0 0xff800014 0x0 0x8>, + <0x0 0xff800024 0x0 0x14>, + <0x0 0xff80001c 0x0 0x8>; + reg-names = "mux","gpio", "drive-strength"; + gpio-controller; + #gpio-cells = <2>; + }; + }; + + pinctrl_periphs: pinctrl@ff634480{ + compatible = "amlogic,meson-g12a-periphs-pinctrl"; + #address-cells = <2>; + #size-cells = <2>; + ranges; + + gpio: banks@ff6346c0{ + reg = <0x0 0xff6346c0 0x0 0x40>, + <0x0 0xff6344e8 0x0 0x18>, + <0x0 0xff634520 0x0 0x18>, + <0x0 0xff634440 0x0 0x4c>, + <0x0 0xff634740 0x0 0x1c>; + reg-names = "mux", + "pull", + "pull-enable", + "gpio", + "drive-strength"; + gpio-controller; + #gpio-cells = <2>; + }; + }; + + audio_data: audio_data { + compatible = "amlogic, audio_data"; + query_licence_cmd = <0x82000050>; + status = "disabled"; + }; + + dwc3: dwc3@ff500000 { + compatible = "synopsys, dwc3"; + status = "disabled"; + reg = <0x0 0xff500000 0x0 0x100000>; + interrupts = <0 30 4>; + usb-phy = <&usb2_phy_v2>, <&usb3_phy_v2>; + cpu-type = "gxl"; + clock-src = "usb3.0"; + clocks = <&clkc CLKID_USB_GENERAL>; + clock-names = "dwc_general"; + }; + + usb2_phy_v2: usb2phy@ffe09000 { + compatible = "amlogic, amlogic-new-usb2-v2"; + status = "disabled"; + reg = <0x0 0xffe09000 0x0 0x80 + 0x0 0xffd01008 0x0 0x100 + 0x0 0xff636000 0x0 0x2000 + 0x0 0xff63a000 0x0 0x2000>; + pll-setting-1 = <0x09400414>; + pll-setting-2 = <0x927E0000>; + pll-setting-3 = <0xac5f69e5>; + pll-setting-4 = <0xfe18>; + pll-setting-5 = <0x8000fff>; + pll-setting-6 = <0x78000>; + pll-setting-7 = <0xe0004>; + pll-setting-8 = <0xe000c>; + }; + + usb3_phy_v2: usb3phy@ffe09080 { + compatible = "amlogic, amlogic-new-usb3-v2"; + status = "disabled"; + reg = <0x0 0xffe09080 0x0 0x20>; + phy-reg = <0xff646000>; + phy-reg-size = <0x2000>; + usb2-phy-reg = <0xffe09000>; + usb2-phy-reg-size = <0x80>; + interrupts = <0 16 4>; + clocks = <&clkc CLKID_PCIE_PLL>; + clock-names = "pcie_refpll"; + }; + + dwc2_a: dwc2_a@ff400000 { + compatible = "amlogic, dwc2"; + status = "disabled"; + device_name = "dwc2_a"; + reg = <0x0 0xff400000 0x0 0x40000>; + interrupts = <0 31 4>; + pl-periph-id = <0>; /** lm name */ + clock-src = "usb0"; /** clock src */ + port-id = <0>; /** ref to mach/usb.h */ + port-type = <2>; /** 0: otg, 1: host, 2: slave */ + port-speed = <0>; /** 0: default, high, 1: full */ + port-config = <0>; /** 0: default */ + /*0:default,1:single,2:incr,3:incr4,4:incr8,5:incr16,6:disable*/ + port-dma = <0>; + port-id-mode = <0>; /** 0: hardware, 1: sw_host, 2: sw_slave*/ + usb-fifo = <728>; + cpu-type = "v2"; + phy-reg = <0xffe09000>; + phy-reg-size = <0xa0>; + /** phy-interface: 0x0: amlogic phy, 0x1: synopsys phy **/ + phy-interface = <0x0>; + clocks = <&clkc CLKID_USB_GENERAL + &clkc CLKID_USB1_TO_DDR>; + clock-names = "usb_general", + "usb1"; + }; + + wdt: watchdog@0xffd0f0d0 { + compatible = "amlogic, meson-wdt"; + status = "okay"; + default_timeout=<10>; + reset_watchdog_method=<1>; /* 0:sysfs,1:kernel */ + reset_watchdog_time=<2>; + shutdown_timeout=<10>; + firmware_timeout=<6>; + suspend_timeout=<6>; + reg = <0x0 0xffd0f0d0 0x0 0x10>; + clock-names = "xtal"; + clocks = <&xtal>; + }; + + jtag { + compatible = "amlogic, jtag"; + status = "okay"; + select = "disable"; /* disable/apao/apee */ + pinctrl-names="jtag_apao_pins", "jtag_apee_pins"; + pinctrl-0=<&jtag_apao_pins>; + pinctrl-1=<&jtag_apee_pins>; + }; + + saradc:saradc { + compatible = "amlogic,meson-g12a-saradc"; + status = "disabled"; + #io-channel-cells = <1>; + clocks = <&xtal>, <&clkc CLKID_SARADC_GATE>; + clock-names = "xtal", "saradc_clk"; + interrupts = ; + reg = <0x0 0xff809000 0x0 0x48>; + }; + + p_tsensor: p_tsensor@ff634594 { + compatible = "amlogic, r1p1-tsensor"; + device_name = "meson-pthermal"; + status = "okay"; + reg = <0x0 0xff634800 0x0 0x50>, + <0x0 0xff800268 0x0 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 35 0>; + clocks = <&clkc CLKID_TS_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + d_tsensor: d_tsensor@ff800228 { + compatible = "amlogic, r1p1-tsensor"; + device_name = "meson-dthermal"; + status = "okay"; + reg = <0x0 0xff634c00 0x0 0x50>, + <0x0 0xff800230 0x0 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 36 0>; + clocks = <&clkc CLKID_TS_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + soc { + compatible = "simple-bus"; + #address-cells = <2>; + #size-cells = <2>; + ranges; + + cbus: cbus@ffd00000 { + compatible = "simple-bus"; + reg = <0x0 0xffd00000 0x0 0x26000>; + #address-cells = <2>; + #size-cells = <2>; + ranges = <0x0 0x0 0x0 0xffd00000 0x0 0x26000>; + + gpio_intc: interrupt-controller@f080 { + compatible = "amlogic,meson-gpio-intc", + "amlogic,meson-g12a-gpio-intc"; + reg = <0x0 0xf080 0x0 0x10>; + interrupt-controller; + #interrupt-cells = <2>; + amlogic,channel-interrupts = + <64 65 66 67 68 69 70 71>; + status = "okay"; + }; + + meson_clk_msr { + compatible = "amlogic, gxl_measure"; + reg = <0x0 0x18004 0x0 0x4 + 0x0 0x1800c 0x0 0x4>; + }; + + pwm_ab: pwm@1b000 { + compatible = "amlogic,g12b-ee-pwm"; + reg = <0x0 0x1b000 0x0 0x20>; + #pwm-cells = <3>; + clocks = <&xtal>, + <&xtal>, + <&xtal>, + <&xtal>; + clock-names = "clkin0", + "clkin1", + "clkin2", + "clkin3"; + /* default xtal 24m clkin0-clkin2 and + * clkin1-clkin3 should be set the same + */ + status = "disabled"; + }; + + pwm_cd: pwm@1a000 { + compatible = "amlogic,g12b-ee-pwm"; + reg = <0x0 0x1a000 0x0 0x20>; + #pwm-cells = <3>; + clocks = <&xtal>, + <&xtal>, + <&xtal>, + <&xtal>; + clock-names = "clkin0", + "clkin1", + "clkin2", + "clkin3"; + status = "disabled"; + }; + + pwm_ef: pwm@19000 { + compatible = "amlogic,g12b-ee-pwm"; + reg = <0x0 0x19000 0x0 0x20>; + #pwm-cells = <3>; + clocks = <&xtal>, + <&xtal>, + <&xtal>, + <&xtal>; + clock-names = "clkin0", + "clkin1", + "clkin2", + "clkin3"; + status = "disabled"; + }; + + i2c0: i2c@1f000 { + compatible = "amlogic,meson-g12b-i2c"; + status = "disabled"; + reg = <0x0 0x1f000 0x0 0x20>; + interrupts = , + ; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&clkc CLKID_I2C>; + clock-names = "clk_i2c"; + }; + + i2c1: i2c@1e000 { + compatible = "amlogic,meson-g12b-i2c"; + status = "disabled"; + reg = <0x0 0x1e000 0x0 0x20>; + interrupts = , + ; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&clkc CLKID_I2C>; + clock-names = "clk_i2c"; + }; + + i2c2: i2c@1d000 { + compatible = "amlogic,meson-g12b-i2c"; + status = "disabled"; + reg = <0x0 0x1d000 0x0 0x20>; + interrupts = , + ; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&clkc CLKID_I2C>; + clock-names = "clk_i2c"; + }; + + i2c3: i2c@1c000 { + compatible = "amlogic,meson-g12b-i2c"; + status = "disabled"; + reg = <0x0 0x1c000 0x0 0x20>; + interrupts = , + ; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&clkc CLKID_I2C>; + clock-names = "clk_i2c"; + }; + + spicc0: spi@13000 { + compatible = "amlogic,meson-g12b-spicc", + "amlogic,meson-g12a-spicc"; + reg = <0x0 0x13000 0x0 0x44>; + interrupts = ; + clocks = <&clkc CLKID_SPICC0>, + <&clkc CLKID_SPICC0_COMP>; + clock-names = "core", "comp"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + spifc: spifc@14000 { + status = "disabled"; + compatible = "amlogic,aml-spi-nor"; + reg = <0x0 0x14000 0x0 0x80>; + pinctrl-names = "default"; + pinctrl-0 = <&spifc_all_pins>; + clocks = <&clkc CLKID_CLK81>; + clock-names = "core"; + }; + + spicc1: spi@15000 { + compatible = "amlogic,meson-g12b-spicc", + "amlogic,meson-g12a-spicc"; + reg = <0x0 0x15000 0x0 0x44>; + interrupts = ; + clocks = <&clkc CLKID_SPICC1>, + <&clkc CLKID_SPICC1_COMP>; + clock-names = "core", "comp"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + }; /* end of cbus */ + + aobus: aobus@ff800000 { + compatible = "simple-bus"; + reg = <0x0 0xff800000 0x0 0xb000>; + #address-cells = <2>; + #size-cells = <2>; + ranges = <0x0 0x0 0x0 0xff800000 0x0 0xb000>; + + cpu_version { + reg=<0x0 0x220 0x0 0x4>; + }; + + aoclkc: clock-controller@0 { + compatible = "amlogic,g12b-aoclkc"; + #clock-cells = <1>; + reg = <0x0 0x0 0x0 0x320>; + }; + + pwm_AO_ab: pwm@7000 { + compatible = "amlogic,g12b-ao-pwm"; + reg = <0x0 0x7000 0x0 0x20>; + #pwm-cells = <3>; + clocks = <&xtal>, + <&xtal>, + <&xtal>, + <&xtal>; + clock-names = "clkin0", + "clkin1", + "clkin2", + "clkin3"; + status = "disabled"; + }; + + pwm_AO_cd: pwm@2000 { + compatible = "amlogic,g12b-ao-pwm"; + reg = <0x0 0x2000 0x0 0x20>; + #pwm-cells = <3>; + clocks = <&xtal>, + <&xtal>, + <&xtal>, + <&xtal>; + clock-names = "clkin0", + "clkin1", + "clkin2", + "clkin3"; + status = "disabled"; + }; + + i2c_AO: i2c@5000 { + compatible = "amlogic,meson-g12b-i2c"; + status = "disabled"; + reg = <0x0 0x05000 0x0 0x20>; + interrupts = , + ; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&clkc CLKID_I2C>; + clock-names = "clk_i2c"; + }; + + i2c_AO_slave:i2c_slave@6000 { + compatible = "amlogic, meson-i2c-slave"; + status = "disabled"; + reg = <0x0 0x6000 0x0 0x20>; + interrupts = <0 194 1>; + pinctrl-names="default"; + pinctrl-0=<&ao_i2c_slave_pins>; + }; + + uart_AO: serial@3000 { + compatible = "amlogic, meson-uart"; + reg = <0x0 0x3000 0x0 0x18>; + interrupts = <0 193 1>; + status = "okay"; + clocks = <&xtal>; + clock-names = "clk_uart"; + xtal_tick_en = <2>; + fifosize = < 64 >; + pinctrl-names = "default"; + /*pinctrl-0 = <&ao_uart_pins>;*/ + support-sysrq = <0>; /* 0 not support*/ + }; + + uart_AO_B: serial@4000 { + compatible = "amlogic, meson-uart"; + reg = <0x0 0x4000 0x0 0x18>; + interrupts = <0 197 1>; + status = "disabled"; + clocks = <&xtal>; + clock-names = "clk_uart"; + fifosize = < 64 >; + pinctrl-names = "default"; + pinctrl-0 = <&ao_b_uart_pins>; + }; + };/* end of aobus */ + + periphs: periphs@ff634400 { + compatible = "simple-bus"; + reg = <0x0 0xff634400 0x0 0x400>; + #address-cells = <2>; + #size-cells = <2>; + ranges = <0x0 0x0 0x0 0xff634400 0x0 0x400>; + + };/* end of periphs */ + + hiubus: hiubus@ff63c000 { + compatible = "simple-bus"; + reg = <0x0 0xff63c000 0x0 0x2000>; + #address-cells = <2>; + #size-cells = <2>; + ranges = <0x0 0x0 0x0 0xff63c000 0x0 0x2000>; + + clkc: clock-controller@0 { + compatible = "amlogic,g12b-clkc-1"; + #clock-cells = <1>; + reg = <0x0 0x0 0x0 0x3dc>; + }; + clkc_b: clock-controller@1 { + compatible = "amlogic,g12b-clkc-2"; + #clock-cells = <1>; + reg = <0x0 0x0 0x0 0x3dc>; + }; + };/* end of hiubus*/ + + ion_dev { + compatible = "amlogic, ion_dev"; + memory-region = <&ion_cma_reserved>; + };/* end of ion_dev*/ + + audiobus: audiobus@0xff642000 { + compatible = "amlogic, audio-controller", "simple-bus"; + reg = <0x0 0xff642000 0x0 0x2000>; + #address-cells = <2>; + #size-cells = <2>; + ranges = <0x0 0x0 0x0 0xff642000 0x0 0x2000>; + clkaudio: audio_clocks { + compatible = "amlogic, g12a-audio-clocks"; + #clock-cells = <1>; + reg = <0x0 0x0 0x0 0xb0>; + }; + ddr_manager { + compatible = "amlogic, g12a-audio-ddr-manager"; + interrupts = < + GIC_SPI 148 IRQ_TYPE_EDGE_RISING + GIC_SPI 149 IRQ_TYPE_EDGE_RISING + GIC_SPI 150 IRQ_TYPE_EDGE_RISING + GIC_SPI 152 IRQ_TYPE_EDGE_RISING + GIC_SPI 153 IRQ_TYPE_EDGE_RISING + GIC_SPI 154 IRQ_TYPE_EDGE_RISING + >; + interrupt-names = + "toddr_a", "toddr_b", "toddr_c", + "frddr_a", "frddr_b", "frddr_c"; + }; + };/* end of audiobus*/ + + }; /* end of soc*/ + + meson-remote { + compatible = "amlogic, aml_remote"; + dev_name = "meson-remote"; + reg = <0x0 0xff808040 0x00 0x44>, /*Multi-format IR controller*/ + <0x0 0xff808000 0x00 0x20>; /*Legacy IR controller*/ + status = "disabled"; + protocol = ; + interrupts = <0 196 1>; + pinctrl-names = "default"; + pinctrl-0 = <&remote_pins>; + max_frame_time = <200>; /*set software decoder max frame time*/ + }; + + uart_A: serial@ffd24000 { + compatible = "amlogic, meson-uart"; + reg = <0x0 0xffd24000 0x0 0x18>; + interrupts = <0 26 1>; + status = "disabled"; + clocks = <&xtal + &clkc CLKID_UART0>; + clock-names = "clk_uart", + "clk_gate"; + fifosize = < 128 >; + pinctrl-names = "default"; + pinctrl-0 = <&a_uart_pins>; + }; + + uart_B: serial@ffd23000 { + compatible = "amlogic, meson-uart"; + reg = <0x0 0xffd23000 0x0 0x18>; + interrupts = <0 75 1>; + status = "disabled"; + clocks = <&xtal + &clkc CLKID_UART1>; + clock-names = "clk_uart", + "clk_gate"; + fifosize = < 64 >; + pinctrl-names = "default"; + pinctrl-0 = <&b_uart_pins>; + }; + + uart_C: serial@ffd22000 { + compatible = "amlogic, meson-uart"; + reg = <0x0 0xffd22000 0x0 0x18>; + interrupts = <0 93 1>; + status = "disabled"; + clocks = <&xtal + &clkc CLKID_UART1>; + clock-names = "clk_uart", + "clk_gate"; + fifosize = < 64 >; + pinctrl-names = "default"; + pinctrl-0 = <&c_uart_pins>; + }; + + + pcie_A: pcieA@fc000000 { + compatible = "amlogic, amlogic-pcie-v2", "snps,dw-pcie"; + reg = <0x0 0xfc000000 0x0 0x400000 + 0x0 0xff648000 0x0 0x2000 + 0x0 0xfc400000 0x0 0x200000 + 0x0 0xff646000 0x0 0x2000 + 0x0 0xffd01080 0x0 0x10>; + reg-names = "elbi", "cfg", "config", "phy", "reset"; + interrupts = <0 221 0>; + #interrupt-cells = <1>; + bus-range = <0x0 0xff>; + #address-cells = <3>; + #size-cells = <2>; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &gic GIC_SPI 223 IRQ_TYPE_EDGE_RISING>; + device_type = "pci"; + ranges = <0x81000000 0 0 0 0xfc600000 0x0 0x100000 + /* downstream I/O */ + 0x82000000 0 0xfc700000 0x0 0xfc700000 0 0x1900000>; + /* non-prefetchable memory */ + num-lanes = <1>; + pcie-num = <1>; + + clocks = <&clkc CLKID_PCIE_PLL + &clkc CLKID_PCIE_COMB + &clkc CLKID_PCIE_PHY>; + clock-names = "pcie_refpll", + "pcie", + "pcie_phy"; + /*reset-gpio-type 0:Shared pad(no reset)1:OD pad2:Normal pad*/ + gpio-type = <2>; + pcie-apb-rst-bit = <15>; + pcie-phy-rst-bit = <14>; + pcie-ctrl-a-rst-bit = <12>; + status = "disabled"; + }; + + amhdmitx: amhdmitx{ + compatible = "amlogic, amhdmitx"; + dev_name = "amhdmitx"; + status = "okay"; + vend-data = <&vend_data>; + pinctrl-names="default", "hdmitx_i2c"; + pinctrl-0=<&hdmitx_hpd &hdmitx_ddc>; + pinctrl-1=<&hdmitx_hpd_gpio &i2c3_master_pins1>; + clocks = <&clkc CLKID_VCLK2_ENCI + &clkc CLKID_VCLK2_VENCI0 + &clkc CLKID_VCLK2_VENCI1 + &clkc CLKID_VAPB_MUX + &clkc CLKID_VPU_MUX>; + clock-names = "venci_top_gate", + "venci_0_gate", + "venci_1_gate", + "hdmi_vapb_clk", + "hdmi_vpu_clk"; + /* HPD, 57 + 32 = 89; CEC, 151 + 32 = 183*/ + interrupts = <0 57 1>; + interrupt-names = "hdmitx_hpd"; + /* 0:M8B 1:GXBB 2:GXTVBB 3:GXL 4:GXM + * 5:TXL 6:TXLX 7:AXG 8:GXLX 9:TXHD + * 10:G12A 11:G12B + */ + ic_type = <11>; + vend_data: vend_data{ /* Should modified by Customer */ + vendor_name = "Amlogic"; /* Max Chars: 8 */ + /* standards.ieee.org/develop/regauth/oui/oui.txt */ + vendor_id = <0x000000>; + }; + }; + + galcore { + compatible = "amlogic, galcore"; + dev_name = "galcore"; + status = "disabled"; + clocks = <&clkc CLKID_VNANOQ_AXI_CLK_COMP>, + <&clkc CLKID_VNANOQ_CORE_CLK_COMP>; + clock-names = "cts_vipnanoq_axi_clk_composite", + "cts_vipnanoq_core_clk_composite"; + interrupts = <0 147 4>; + interrupt-names = "galcore"; + reg = <0x0 0xff100000 0x0 0x800 + 0x0 0xff000000 0x0 0x400000>; + }; + + aocec: aocec { + compatible = "amlogic, aocec-g12a"; + device_name = "aocec"; + status = "okay"; + vendor_name = "Amlogic"; /* Max Chars: 8 */ + /* Refer to the following URL at: + * http://standards.ieee.org/develop/regauth/oui/oui.txt + */ + vendor_id = <0x000000>; + product_desc = "G12B"; /* Max Chars: 16 */ + cec_osd_string = "AML_MBOX"; /* Max Chars: 14 */ + port_num = <1>; + ee_cec; + arc_port_mask = <0x2>; + interrupts = <0 203 1 + 0 199 1>; /*0:snps 1:ts*/ + interrupt-names = "hdmi_aocecb","hdmi_aocec"; + pinctrl-names = "default","hdmitx_aocecb","cec_pin_sleep"; + pinctrl-0=<&eecec_a>; + pinctrl-1=<&eecec_b>; + pinctrl-2=<&eecec_b>; + reg = <0x0 0xFF80023c 0x0 0x4 + 0x0 0xFF800000 0x0 0x400 + 0x0 0xFF634400 0x0 0x26>; + reg-names = "ao_exit","ao","periphs"; + }; + + /*if you want to use vdin just modify status to "ok"*/ + vdin0: vdin0 { + compatible = "amlogic, vdin"; + dev_name = "vdin0"; + status = "disabled"; + reserve-iomap = "true"; + flag_cma = <0>;/*1:share with codec_mm;2:cma alone*/ + /*MByte, if 10bit disable: 64M(YUV422), + *if 10bit enable: 64*1.5 = 96M(YUV422) + *if support 4K2K-YUV444-10bit-WR:3840*2160*4*4 ~= 128M + *if support 4K2K-YUV422-10bit-wr:3840*2160*3*4 ~= 96M + *if support 4K2K-YUV422-8BIT-WR:3840*2160*2*4 ~= 64M + *if support 1080p-YUV422-8BIT-WR:1920*1080*2*4 ~= 16M + */ + /*cma_size = <16>;*/ + interrupts = <0 83 1>; + rdma-irq = <2>; + /*clocks = <&clock CLK_FPLL_DIV5>, + * <&clock CLK_VDIN_MEAS_CLK>; + *clock-names = "fclk_div5", "cts_vdin_meas_clk"; + */ + vdin_id = <0>; + }; + vdin1: vdin1 { + compatible = "amlogic, vdin"; + dev_name = "vdin1"; + status = "disabled"; + reserve-iomap = "true"; + flag_cma = <0>;/*1:share with codec_mm;0:cma alone*/ + interrupts = <0 85 1>; + rdma-irq = <4>; + /*clocks = <&clock CLK_FPLL_DIV5>, + * <&clock CLK_VDIN_MEAS_CLK>; + *clock-names = "fclk_div5", "cts_vdin_meas_clk"; + */ + vdin_id = <1>; + }; + + vout { + compatible = "amlogic, vout"; + dev_name = "vout"; + status = "okay"; + }; + + vout2 { + compatible = "amlogic, vout2"; + dev_name = "vout"; + status = "okay"; + clocks = <&clkc CLKID_VPU_CLKC_P0_COMP>, + <&clkc CLKID_VPU_CLKC_MUX>; + clock-names = "vpu_clkc0", + "vpu_clkc"; + }; + + vdac { + compatible = "amlogic, vdac-g12b"; + status = "okay"; + }; + + canvas: canvas{ + compatible = "amlogic, meson, canvas"; + dev_name = "amlogic-canvas"; + status = "okay"; + reg = <0x0 0xff638000 0x0 0x2000>; + }; + + ge2d { + compatible = "amlogic, ge2d-g12a"; + dev_name = "ge2d"; + status = "okay"; + interrupts = <0 146 1>; + interrupt-names = "ge2d"; + clocks = <&clkc CLKID_VAPB_MUX>, + <&clkc CLKID_G2D>, + <&clkc CLKID_GE2D_GATE>; + clock-names = "clk_vapb_0", + "clk_ge2d", + "clk_ge2d_gate"; + reg = <0x0 0xff940000 0x0 0x10000>; + }; + + meson-amvideom { + compatible = "amlogic, amvideom"; + dev_name = "amvideom"; + status = "okay"; + interrupts = <0 3 1>; + interrupt-names = "vsync"; + }; + + codec_io: codec_io { + compatible = "amlogic, codec_io"; + status = "okay"; + #address-cells=<2>; + #size-cells=<2>; + ranges; + io_cbus_base{ + reg = <0x0 0xffd00000 0x0 0x100000>; + }; + io_dos_base{ + reg = <0x0 0xff620000 0x0 0x10000>; + }; + io_hiubus_base{ + reg = <0x0 0xff63c000 0x0 0x2000>; + }; + io_aobus_base{ + reg = <0x0 0xff800000 0x0 0x10000>; + }; + io_vcbus_base{ + reg = <0x0 0xff900000 0x0 0x40000>; + }; + io_dmc_base{ + reg = <0x0 0xff638000 0x0 0x2000>; + }; + io_efuse_base{ + reg = <0x0 0xff630000 0x0 0x2000>; + }; + }; + + gdc:gdc { + #address-cells=<2>; + #size-cells=<2>; + status = "ok"; + compatible = "amlogic, g12b-gdc"; + reg = <0 0xFF950000 0 0x0000100 + 0 0xFF63C16C 0 0x0000004 + 0 0xFF63C100 0 0x0000004>; + interrupts = <0 144 1>; + interrupt-names = "GDC"; + clocks = <&clkc CLKID_GDC_CORE_CLK_COMP + &clkc CLKID_GDC_AXI_CLK_COMP >; + clock-names = "core","axi"; + }; + + mesonstream { + compatible = "amlogic, codec, streambuf"; + dev_name = "mesonstream"; + status = "okay"; + clocks = <&clkc CLKID_DOS_PARSER + &clkc CLKID_DEMUX + &clkc CLKID_AHB_ARB0 + &clkc CLKID_DOS + &clkc CLKID_VDEC_MUX + &clkc CLKID_HCODEC_MUX + &clkc CLKID_HEVC_MUX + &clkc CLKID_HEVCF_MUX>; + clock-names = "parser_top", + "demux", + "ahbarb0", + "vdec", + "clk_vdec_mux", + "clk_hcodec_mux", + "clk_hevc_mux", + "clk_hevcb_mux"; + }; + + amvideocap { + compatible = "amlogic, amvideocap"; + dev_name = "amvideocap.0"; + status = "okay"; + max_size = <8>;//8M + }; + + vdec { + compatible = "amlogic, vdec"; + dev_name = "vdec.0"; + status = "okay"; + interrupts = <0 3 1 + 0 23 1 + 0 32 1 + 0 43 1 + 0 44 1 + 0 45 1>; + interrupt-names = "vsync", + "demux", + "parser", + "mailbox_0", + "mailbox_1", + "mailbox_2"; + }; + + amvenc_avc{ + compatible = "amlogic, amvenc_avc"; + dev_name = "amvenc_avc"; + status = "okay"; + interrupts = <0 45 1>; + interrupt-names = "mailbox_2"; + }; + + hevc_enc{ + compatible = "cnm, HevcEnc"; + //memory-region = <&hevc_enc_reserved>; + dev_name = "HevcEnc"; + status = "okay"; + interrupts = <0 187 1>; + interrupt-names = "wave420l_irq"; + #address-cells=<2>; + #size-cells=<2>; + ranges; + io_reg_base{ + reg = <0x0 0xff610000 0x0 0x4000>; + }; + }; + + rdma{ + compatible = "amlogic, meson, rdma"; + dev_name = "amlogic-rdma"; + status = "okay"; + interrupts = <0 89 1>; + interrupt-names = "rdma"; + }; + + meson_fb: meson-fb { + compatible = "amlogic, meson-g12b"; + memory-region = <&logo_reserved>; + dev_name = "meson-fb"; + status = "disable"; + interrupts = <0 3 1 + 0 56 1 + 0 89 1>; + interrupt-names = "viu-vsync", "viu2-vsync", "rdma"; + /* uboot logo,fb0/fb1 memory size,if afbcd fb0=0x01851000*/ + display_mode_default = "1080p60hz"; + scale_mode = <1>; + /** 0:VPU free scale 1:OSD free scale 2:OSD super scale */ + display_size_default = <1920 1080 1920 2160 32>; + /*1920*1080*4*3 = 0x17BB000*/ + clocks = <&clkc CLKID_VPU_CLKC_MUX>; + clock-names = "vpu_clkc"; + }; + irblaster: meson-irblaster { + compatible = "amlogic, meson_irblaster"; + reg = <0x0 0xff80014c 0x0 0x10>, + <0x0 0xff800040 0x0 0x4>; + pinctrl-names = "default"; + pinctrl-0 = <&irblaster_pins>; + interrupts = <0 198 1>; + status = "disabled"; + }; + + sd_emmc_c: emmc@ffe07000 { + status = "disabled"; + compatible = "amlogic, meson-mmc-g12b-a"; + reg = <0x0 0xffe07000 0x0 0x800>; + interrupts = <0 191 1>; + pinctrl-names = "emmc_clk_cmd_pins", "emmc_all_pins"; + pinctrl-0 = <&emmc_clk_cmd_pins>; + pinctrl-1 = <&emmc_conf_pull_up &emmc_conf_pull_done>; + clocks = <&clkc CLKID_SD_EMMC_C>, + <&clkc CLKID_SD_EMMC_C_P0_COMP>, + <&clkc CLKID_FCLK_DIV2>, + <&clkc CLKID_FCLK_DIV5>, + <&xtal>; + clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + + bus-width = <8>; + cap-sd-highspeed; + cap-mmc-highspeed; + /* mmc-ddr-1_8v; */ + /* mmc-hs200-1_8v; */ + + max-frequency = <200000000>; + non-removable; + disable-wp; + emmc { + pinname = "emmc"; + ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ + /*caps defined in dts*/ + tx_delay = <0>; + max_req_size = <0x20000>; /**128KB*/ + gpio_dat3 = <&gpio BOOT_3 GPIO_ACTIVE_HIGH>; + hw_reset = <&gpio BOOT_9 GPIO_ACTIVE_HIGH>; + card_type = <1>; + /* 1:mmc card(include eMMC), + * 2:sd card(include tSD) + */ + }; + }; + + sd_emmc_b:sd@ffe05000 { + status = "disabled"; + compatible = "amlogic, meson-mmc-g12b"; + reg = <0x0 0xffe05000 0x0 0x800>; + interrupts = <0 190 1>; + + pinctrl-names = "sd_all_pins", + "sd_clk_cmd_pins", + "sd_1bit_pins", + "sd_clk_cmd_uart_pins", + "sd_1bit_uart_pins", + "sd_to_ao_uart_pins", + "ao_to_sd_uart_pins", + "sd_to_ao_jtag_pins", + "ao_to_sd_jtag_pins"; + pinctrl-0 = <&sd_all_pins>; + pinctrl-1 = <&sd_clk_cmd_pins>; + pinctrl-2 = <&sd_1bit_pins>; + pinctrl-3 = <&sd_to_ao_uart_clr_pins + &sd_clk_cmd_pins &ao_to_sd_uart_pins>; + pinctrl-4 = <&sd_to_ao_uart_clr_pins + &sd_1bit_pins &ao_to_sd_uart_pins>; + pinctrl-5 = <&sd_all_pins &sd_to_ao_uart_pins>; + pinctrl-6 = <&sd_to_ao_uart_clr_pins &ao_to_sd_uart_pins>; + pinctrl-7 = <&sd_all_pins &sd_to_ao_uart_pins>; + pinctrl-8 = <&sd_to_ao_uart_clr_pins &ao_to_sd_uart_pins>; + + clocks = <&clkc CLKID_SD_EMMC_B>, + <&clkc CLKID_SD_EMMC_B_P0_COMP>, + <&clkc CLKID_FCLK_DIV2>, + <&clkc CLKID_FCLK_DIV5>, + <&xtal>; + clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + + bus-width = <4>; + cap-sd-highspeed; + cap-mmc-highspeed; + max-frequency = <100000000>; + disable-wp; + sd { + pinname = "sd"; + ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ + max_req_size = <0x20000>; /**128KB*/ + gpio_dat3 = <&gpio GPIOC_3 GPIO_ACTIVE_HIGH>; + jtag_pin = <&gpio GPIOC_0 GPIO_ACTIVE_HIGH>; + gpio_cd = <&gpio GPIOC_6 GPIO_ACTIVE_HIGH>; + card_type = <5>; + /* 3:sdio device(ie:sdio-wifi), + * 4:SD combo (IO+mem) card + */ + }; + }; + + sd_emmc_a:sdio@ffe03000 { + status = "disabled"; + compatible = "amlogic, meson-mmc-g12b"; + reg = <0x0 0xffe03000 0x0 0x800>; + interrupts = <0 189 4>; + + pinctrl-names = "sdio_all_pins", + "sdio_clk_cmd_pins"; + pinctrl-0 = <&sdio_all_pins>; + pinctrl-1 = <&sdio_clk_cmd_pins>; + + clocks = <&clkc CLKID_SD_EMMC_A>, + <&clkc CLKID_SD_EMMC_A_P0_COMP>, + <&clkc CLKID_FCLK_DIV2>, + <&clkc CLKID_FCLK_DIV5>, + <&xtal>; + clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + + bus-width = <4>; + cap-sd-highspeed; + cap-mmc-highspeed; + max-frequency = <100000000>; + disable-wp; + sdio { + pinname = "sdio"; + ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ + max_req_size = <0x20000>; /**128KB*/ + card_type = <3>; + /* 3:sdio device(ie:sdio-wifi), + * 4:SD combo (IO+mem) card + */ + }; + }; + + nand: nfc@0 { + compatible = "amlogic, aml_mtd_nand"; + dev_name = "mtdnand"; + status = "disabled"; + reg = <0x0 0xFFE07800 0x0 0x200>; + interrupts = <0 34 1>; + + pinctrl-names = "nand_rb_mod","nand_norb_mod", "nand_cs_only"; + pinctrl-0 = <&all_nand_pins>; + pinctrl-1 = <&all_nand_pins>; + pinctrl-2 = <&nand_cs_pins>; + clocks = <&clkc CLKID_SD_EMMC_C>, + <&clkc CLKID_SD_EMMC_C_P0_COMP>; + clock-names = "core", "clkin"; + + device_id = <0>; + /*fip/tpl configurations, must be same + * with uboot if bl_mode was set as 1 + * bl_mode: 0 compact mode; 1 descrete mode + * if bl_mode was set as 1, fip configuration will work + */ + bl_mode = <1>; + /*copy count of fip*/ + fip_copies = <4>; + /*size of each fip copy */ + fip_size = <0x200000>; + nand_clk_ctrl = <0xFFE07000>; + /*partions defined in dts */ + }; + + meson_cooldev: meson-cooldev@0 { + status = "okay"; + compatible = "amlogic, meson-cooldev"; + device_name = "mcooldev"; + cooling_devices { + cpufreq_cool_cluster0 { + min_state = <1000000>; + dyn_coeff = <120>; + cluster_id = <0>; + gpu_pp = <2>; + node_name = "cpufreq_cool0"; + device_type = "cpufreq"; + }; + cpufreq_cool_cluster1 { + min_state = <1000000>; + dyn_coeff = <460>; + cluster_id = <1>; + gpu_pp = <2>; + node_name = "cpufreq_cool1"; + device_type = "cpufreq"; + }; + cpucore_cool_cluster { + min_state = <1>; + dyn_coeff = <0>; + gpu_pp = <2>; + node_name = "cpucore_cool"; + device_type = "cpucore"; + }; + gpufreq_cool { + min_state = <400>; + dyn_coeff = <358>; + cluster_id = <0>; + gpu_pp = <2>; + node_name = "gpufreq_cool0"; + device_type = "gpufreq"; + }; + gpucore_cool { + min_state = <1>; + dyn_coeff = <0>; + cluster_id = <0>; + gpu_pp = <2>; + node_name = "gpucore_cool0"; + device_type = "gpucore"; + }; + }; + cpufreq_cool0:cpufreq_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + cpufreq_cool1:cpufreq_cool1 { + #cooling-cells = <2>; /* min followed by max */ + }; + cpucore_cool:cpucore_cool { + #cooling-cells = <2>; /* min followed by max */ + }; + gpufreq_cool0:gpufreq_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + gpucore_cool0:gpucore_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + }; + /*meson cooling devices end*/ + + thermal-zones { + soc_thermal: soc_thermal { + polling-delay = <1000>; + polling-delay-passive = <100>; + sustainable-power = <3550>; + thermal-sensors = <&p_tsensor 0>; + trips { + pswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + pcontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + phot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + pcritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + + cooling-maps { + cpufreq_cooling_map0 { + trip = <&pcontrol>; + cooling-device = <&cpufreq_cool0 0 10>; + contribution = <1024>; + }; + cpufreq_cooling_map1 { + trip = <&pcontrol>; + cooling-device = <&cpufreq_cool1 0 9>; + contribution = <1024>; + }; + cpucore_cooling_map { + trip = <&pcontrol>; + cooling-device = <&cpucore_cool 0 5>; + contribution = <1024>; + }; + gpufreq_cooling_map { + trip = <&pcontrol>; + cooling-device = <&gpufreq_cool0 0 4>; + contribution = <1024>; + }; + gpucore_cooling_map { + trip = <&pcontrol>; + cooling-device = <&gpucore_cool0 0 2>; + contribution = <1024>; + }; + }; + }; + ddr_thermal: ddr_thermal { + polling-delay = <1000>; + polling-delay-passive = <100>; + sustainable-power = <3550>; + thermal-sensors = <&d_tsensor 1>; + trips { + dswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + dcontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + dhot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + dcritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + + }; + }; + /*thermal zone end*/ + + /* Sound iomap */ + aml_snd_iomap { + compatible = "amlogic, snd-iomap"; + status = "okay"; + #address-cells=<2>; + #size-cells=<2>; + ranges; + pdm_bus { + reg = <0x0 0xFF640000 0x0 0x2000>; + }; + audiobus_base { + reg = <0x0 0xFF642000 0x0 0x2000>; + }; + audiolocker_base { + reg = <0x0 0xFF64A000 0x0 0x2000>; + }; + eqdrc_base { + reg = <0x0 0xFF656000 0x0 0x1800>; + }; + reset_base { + reg = <0x0 0xFFD01000 0x0 0x1000>; + }; + }; + + vddcpu0: pwmao_d-regulator { + compatible = "pwm-regulator"; + pinctrl-names = "default"; + pinctrl-0 = <&pwm_ao_d_pins3>; + pwms = <&pwm_AO_cd MESON_PWM_1 1250 0>; + regulator-name = "vddcpu0"; + regulator-min-microvolt = <721000>; + regulator-max-microvolt = <1022000>; + regulator-always-on; + max-duty-cycle = <1250>; + /* Voltage Duty-Cycle */ + voltage-table = <1022000 0>, + <1011000 3>, + <1001000 6>, + <991000 10>, + <981000 13>, + <971000 16>, + <961000 20>, + <951000 23>, + <941000 26>, + <931000 30>, + <921000 33>, + <911000 36>, + <901000 40>, + <891000 43>, + <881000 46>, + <871000 50>, + <861000 53>, + <851000 56>, + <841000 60>, + <831000 63>, + <821000 67>, + <811000 70>, + <801000 73>, + <791000 76>, + <781000 80>, + <771000 83>, + <761000 86>, + <751000 90>, + <741000 93>, + <731000 96>, + <721000 100>; + status = "okay"; + }; + + vddcpu1: pwmab_a-regulator { + compatible = "pwm-regulator"; + pinctrl-names = "default"; + pinctrl-0 = <&pwm_a_e2>; + pwms = <&pwm_ab MESON_PWM_0 1250 0>; + regulator-name = "vddcpu1"; + regulator-min-microvolt = <721000>; + regulator-max-microvolt = <1022000>; + regulator-always-on; + max-duty-cycle = <1250>; + /* Voltage Duty-Cycle */ + voltage-table = <1022000 0>, + <1011000 3>, + <1001000 6>, + <991000 10>, + <981000 13>, + <971000 16>, + <961000 20>, + <951000 23>, + <941000 26>, + <931000 30>, + <921000 33>, + <911000 36>, + <901000 40>, + <891000 43>, + <881000 46>, + <871000 50>, + <861000 53>, + <851000 56>, + <841000 60>, + <831000 63>, + <821000 67>, + <811000 70>, + <801000 73>, + <791000 76>, + <781000 80>, + <771000 83>, + <761000 86>, + <751000 90>, + <741000 93>, + <731000 96>, + <721000 100>; + status = "okay"; + }; + + rng { + compatible = "amlogic,meson-rng"; + status = "okay"; + #address-cells = <2>; + #size-cells = <2>; + reg = <0x0 0xff630218 0x0 0x4>; + quality = /bits/ 16 <1000>; + }; + + ddr_bandwidth { + compatible = "amlogic, ddr-bandwidth"; + status = "okay"; + reg = <0x0 0xff638000 0x0 0x100 + 0x0 0xff638c00 0x0 0x100>; + interrupts = <0 52 1>; + interrupt-names = "ddr_bandwidth"; + }; + dmc_monitor { + compatible = "amlogic, dmc_monitor"; + status = "okay"; + reg_base = <0xff639000>; + interrupts = <0 51 1>; + }; + + isp_sc: isp-sc@ff655400 { + compatible = "amlogic, isp-sc"; + reg = <0x0 0xff655400 0x0 0x00001000>; + reg-names = "isp_sc"; + interrupts = <0 17 0>; + interrupt-names = "isp_sc"; + }; + + isp: isp@ff140000 { + compatible = "arm, isp"; + reg = <0x0 0xff140000 0x0 0x00040000>; + reg-names = "ISP"; + interrupts = <0 142 4>; + interrupt-names = "ISP"; + temper-buf-size = <24>; + clocks = <&clkc CLKID_MIPI_ISP_CLK_COMP>, + <&clkc CLKID_MIPI_CSI_PHY_CLK0_COMP>; + clock-names = "cts_mipi_isp_clk_composite", + "cts_mipi_csi_phy_clk0_composite"; + link-device = <&isp_sc>; + }; + + adapter: isp-adapter@ff650000 { + compatible = "amlogic, isp-adapter"; + reg = <0x0 0xff650000 0x0 0x00006000>; + reg-names = "adapter"; + interrupts = <0 179 0>; + interrupt-names = "adapter-irq"; + }; + + phycsi: phy-csi@ff650000 { + compatible = "amlogic, phy-csi"; + reg = <0x0 0xff650000 0x0 0x00002000>, + <0x0 0xff652000 0x0 0x00002000>, + <0x0 0xff63c300 0x0 0x00000100>, + <0x0 0xff654000 0x0 0x00000100>, + <0x0 0xff654400 0x0 0x00000100>; + reg-names = "csi2_phy0", "csi2_phy1", "aphy_reg", + "csi0_host", "csi1_host"; + interrupts = <0 41 0>, + <0 42 0>, + <0 72 0>, + <0 74 0>, + <0 87 0>, + <0 88 0>; + interrupt-names = "phy0-irq", + "phy1-irq", + "csi-host0-intr2", + "csi-host0-intr1", + "csi-host1-intr2", + "csi-host1-intr1"; + link-device = <&adapter>; + }; + + defendkey: defendkey { + compatible = "amlogic, defendkey"; + reg = <0x0 0xff630218 0x0 0x4>; /*RNG_USR_DATA*/ + mem_size = <0x0 0x100000>; + status = "okay"; + }; + + openvfd { + compatible = "open,vfd"; + dev_name = "openvfd"; + status = "okay"; + }; +};/* end of / */ + +&pinctrl_aobus { + ao_uart_pins:ao_uart { + mux { + groups = "uart_ao_tx_a", + "uart_ao_rx_a"; + function = "uart_ao_a"; + }; + }; + + ao_b_uart_pins:ao_b_uart { + mux { + groups = "uart_ao_tx_b_2", + "uart_ao_rx_b_3"; + function = "uart_ao_b"; + }; + }; + + ao_i2c_master_pins1:ao_i2c_pins1 { + mux { + groups = "i2c_ao_sck", + "i2c_ao_sda"; + function = "i2c_ao"; + bias-pull-up; + drive-strength = <2>; + }; + }; + + ao_i2c_master_pins2:ao_i2c_pins2 { + mux { + groups = "i2c_ao_sck_e", + "i2c_ao_sda_e"; + function = "i2c_ao"; + bias-pull-up; + drive-strength = <2>; + }; + }; + + ao_i2c_slave_pins:ao_i2c_slave_pins { + mux { + groups = "i2c_ao_slave_sck", + "i2c_ao_slave_sda"; + function = "i2c_ao_slave"; + }; + }; + + pwm_ao_a_pins: pwm_ao_a { + mux { + groups = "pwm_ao_a"; + function = "pwm_ao_a"; + }; + }; + + pwm_ao_a_hiz_pins: pwm_ao_a_hiz { + mux { + groups = "pwm_ao_a_hiz"; + function = "pwm_ao_a"; + }; + }; + + pwm_ao_b_pins: pwm_ao_b { + mux { + groups = "pwm_ao_b"; + function = "pwm_ao_b"; + }; + }; + + pwm_ao_c_pins1: pwm_ao_c_pins1 { + mux { + groups = "pwm_ao_c_4"; + function = "pwm_ao_c"; + }; + }; + + pwm_ao_c_pins2: pwm_ao_c_pins2 { + mux { + groups = "pwm_ao_c_6"; + function = "pwm_ao_c"; + }; + }; + + pwm_ao_c_hiz_pins: pwm_ao_c_hiz { + mux { + groups = "pwm_ao_c_hiz_4"; + function = "pwm_ao_c"; + }; + }; + + pwm_ao_d_pins1: pwm_ao_d_pins1 { + mux { + groups = "pwm_ao_d_5"; + function = "pwm_ao_d"; + }; + }; + + pwm_ao_d_pins2: pwm_ao_d_pins2 { + mux { + groups = "pwm_ao_d_10"; + function = "pwm_ao_d"; + }; + }; + + pwm_ao_d_pins3: pwm_ao_d_pins3 { + mux { + groups = "pwm_ao_d_e"; + function = "pwm_ao_d"; + }; + }; + + aocec_a: ao_ceca { + mux { + groups = "cec_ao_a"; + function = "cec_ao"; + }; + }; + + aocec_b: ao_cecb { + mux { + groups = "cec_ao_b"; + function = "cec_ao"; + }; + }; + pwm_a_e2: pwm_a_e2 { + mux { + groups = "pwm_a_e2"; + function = "pwm_a_gpioe"; + }; + }; + + jtag_apao_pins:jtag_apao_pin { + mux { + groups = "jtag_a_tdi", + "jtag_a_tdo", + "jtag_a_clk", + "jtag_a_tms"; + function = "jtag_a"; + }; + }; +}; + +&pinctrl_periphs { + /* sdemmc portC */ + emmc_clk_cmd_pins:emmc_clk_cmd_pins { + mux { + groups = "emmc_clk", + "emmc_cmd"; + function = "emmc"; + input-enable; + bias-pull-up; + drive-strength = <3>; + }; + }; + + emmc_conf_pull_up:emmc_conf_pull_up { + mux { + groups = "emmc_nand_d7", + "emmc_nand_d6", + "emmc_nand_d5", + "emmc_nand_d4", + "emmc_nand_d3", + "emmc_nand_d2", + "emmc_nand_d1", + "emmc_nand_d0", + "emmc_clk", + "emmc_cmd"; + function = "emmc"; + input-enable; + bias-pull-up; + drive-strength = <3>; + }; + }; + + emmc_conf_pull_done:emmc_conf_pull_done { + mux { + groups = "emmc_nand_ds"; + function = "emmc"; + input-enable; + bias-pull-down; + drive-strength = <3>; + }; + }; + + /* sdemmc portB */ + sd_clk_cmd_pins:sd_clk_cmd_pins { + mux { + groups = "sdcard_cmd_c", + "sdcard_clk_c"; + function = "sdcard"; + input-enable; + bias-pull-up; + drive-strength = <3>; + }; + }; + + sd_all_pins:sd_all_pins { + mux { + groups = "sdcard_d0_c", + "sdcard_d1_c", + "sdcard_d2_c", + "sdcard_d3_c", + "sdcard_cmd_c", + "sdcard_clk_c"; + function = "sdcard"; + input-enable; + bias-pull-up; + drive-strength = <3>; + }; + }; + sd_1bit_pins:sd_1bit_pins { + mux { + groups = "sdcard_d0_c", + "sdcard_cmd_c", + "sdcard_clk_c"; + function = "sdcard"; + input-enable; + bias-pull-up; + drive-strength = <3>; + }; + }; + + ao_to_sd_uart_pins:ao_to_sd_uart_pins { + mux { + groups = "uart_ao_tx_a_c3", + "uart_ao_rx_a_c2"; + function = "uart_ao_a_ee"; + bias-pull-up; + input-enable; + }; + }; + /* sdemmc portA */ + sdio_clk_cmd_pins:sdio_clk_cmd_pins { + mux { + groups = "sdio_clk", + "sdio_cmd"; + function = "sdio"; + input-enable; + bias-pull-up; + drive-strength = <3>; + }; + }; + + sdio_all_pins:sdio_all_pins { + mux { + groups = "sdio_d0", + "sdio_d1", + "sdio_d2", + "sdio_d3", + "sdio_clk", + "sdio_cmd"; + function = "sdio"; + input-enable; + bias-pull-up; + drive-strength = <3>; + }; + }; + all_nand_pins: all_nand_pins { + mux { + groups = "emmc_nand_d0", + "emmc_nand_d1", + "emmc_nand_d2", + "emmc_nand_d3", + "emmc_nand_d4", + "emmc_nand_d5", + "emmc_nand_d6", + "emmc_nand_d7", + "nand_ce0", + "nand_ale", + "nand_cle", + "nand_wen_clk", + "nand_ren_wr", + "nand_rb0"; + function = "nand"; + input-enable; + }; + }; + + nand_cs_pins: nand_cs { + mux { + groups = "nand_ce0"; + function = "nand"; + }; + }; + + i2c0_master_pins1:i2c0_pins1 { + mux { + groups = "i2c0_sda_c", + "i2c0_sck_c"; + function = "i2c0"; + bias-pull-up; + drive-strength = <2>; + }; + }; + + i2c0_master_pins2:i2c0_pins2 { + mux { + groups = "i2c0_sda_z0", + "i2c0_sck_z1"; + function = "i2c0"; + bias-pull-up; + drive-strength = <2>; + }; + }; + + i2c0_master_pins3:i2c0_pins3 { + mux { + groups = "i2c0_sda_z7", + "i2c0_sck_z8"; + function = "i2c0"; + bias-pull-up; + drive-strength = <2>; + }; + }; + + i2c1_master_pins1:i2c1_pins1 { + mux { + groups = "i2c1_sda_x", + "i2c1_sck_x"; + function = "i2c1"; + bias-pull-up; + drive-strength = <2>; + }; + }; + + i2c1_master_pins2:i2c1_pins2 { + mux { + groups = "i2c1_sda_h2", + "i2c1_sck_h3"; + function = "i2c1"; + bias-pull-up; + drive-strength = <2>; + }; + }; + + i2c1_master_pins3:i2c1_pins3 { + mux { + groups = "i2c1_sda_h6", + "i2c1_sck_h7"; + function = "i2c1"; + bias-pull-up; + drive-strength = <2>; + }; + }; + + i2c2_master_pins1:i2c2_pins1 { + mux { + groups = "i2c2_sda_x", + "i2c2_sck_x"; + function = "i2c2"; + bias-pull-up; + drive-strength = <2>; + }; + }; + + i2c2_master_pins2:i2c2_pins2 { + mux { + groups = "i2c2_sda_z", + "i2c2_sck_z"; + function = "i2c2"; + bias-pull-up; + drive-strength = <2>; + }; + }; + + i2c3_master_pins1:i2c3_pins1 { + mux { + groups = "i2c3_sda_h", + "i2c3_sck_h"; + function = "i2c3"; + bias-pull-up; + drive-strength = <2>; + }; + }; + + i2c3_master_pins2:i2c3_pins2 { + mux { + groups = "i2c3_sda_a", + "i2c3_sck_a"; + function = "i2c3"; + bias-pull-up; + drive-strength = <2>; + }; + }; + + pwm_a_pins: pwm_a { + mux { + groups = "pwm_a"; + function = "pwm_a"; + }; + }; + + pwm_b_pins1: pwm_b_pins1 { + mux { + groups = "pwm_b_x7"; + function = "pwm_b"; + }; + }; + + pwm_b_pins2: pwm_b_pins2 { + mux { + groups = "pwm_b_x19"; + function = "pwm_b"; + }; + }; + + pwm_b_pins3: pwm_b_pins3 { + mux { + groups = "pwm_b_h"; + function = "pwm_b"; + }; + }; + + pwm_b_pins4: pwm_b_pins4 { + mux { + groups = "pwm_b_z0"; + function = "pwm_b"; + }; + }; + + pwm_b_pins5: pwm_b_pins5 { + mux { + groups = "pwm_b_z13"; + function = "pwm_b"; + }; + }; + + pwm_c_pins1: pwm_c_pins1 { + mux { + groups = "pwm_c_c4"; + function = "pwm_c"; + }; + }; + + pwm_c_pins2: pwm_c_pins2 { + mux { + groups = "pwm_c_x5"; + function = "pwm_c"; + }; + }; + + pwm_c_pins3: pwm_c_pins3 { + mux { + groups = "pwm_c_x8"; + function = "pwm_c"; + }; + }; + + pwm_c_pins4: pwm_c_pins4 { + mux { + groups = "pwm_c_z"; + function = "pwm_c"; + }; + }; + + pwm_d_pins1: pwm_d_pins1 { + mux { + groups = "pwm_d_x3"; + function = "pwm_d"; + }; + }; + + pwm_d_pins2: pwm_d_pins2 { + mux { + groups = "pwm_d_x6"; + function = "pwm_d"; + }; + }; + + pwm_d_pins3: pwm_d_pins3 { + mux { + groups = "pwm_d_z"; + function = "pwm_d"; + }; + }; + + pwm_d_pins4: pwm_d_pins4 { + mux { + groups = "pwm_d_a4"; + function = "pwm_d"; + }; + }; + + pwm_e_pins: pwm_e { + mux { + groups = "pwm_e"; + function = "pwm_e"; + }; + }; + + pwm_f_pins1: pwm_f_pins1 { + mux { + groups = "pwm_f_x"; + function = "pwm_f"; + }; + }; + + pwm_f_pins2: pwm_f_pins2 { + mux { + groups = "pwm_f_h"; + function = "pwm_f"; + }; + }; + + pwm_f_pins3: pwm_f_pins3 { + mux { + groups = "pwm_f_z"; + function = "pwm_f"; + }; + }; + + pwm_f_pins4: pwm_f_pins4 { + mux { + groups = "pwm_f_a11"; + function = "pwm_f"; + }; + }; + + spicc0_pins_x: spicc0_pins_x { + mux { + groups = "spi0_mosi_x", + "spi0_miso_x", + //"spi0_ss0_x", + "spi0_clk_x"; + function = "spi0"; + drive-strength = <1>; + }; + }; + + spifc_all_pins: spifc_all_pins { + mux { + groups = "nor_d", + "nor_q", + "nor_c"; + function = "nor"; + input-enable; + bias-pull-up; + }; + }; + + spicc1_pins: spicc1_pins { + mux { + groups = "spi1_mosi", + "spi1_miso", + //"spi1_ss0", + "spi1_clk"; + function = "spi1"; + drive-strength = <1>; + }; + }; + + a_uart_pins:a_uart { + mux { + groups = "uart_tx_a", + "uart_rx_a", + "uart_cts_a", + "uart_rts_a"; + function = "uart_a"; + }; + }; + + b_uart_pins:b_uart { + mux { + groups = "uart_tx_b", + "uart_rx_b"; + function = "uart_b"; + }; + }; + + c_uart_pins:c_uart { + mux { + groups = "uart_tx_c", + "uart_rx_c"; + function = "uart_c"; + }; + }; + + hdmitx_hpd: hdmitx_hpd { + mux { + groups = "hdmitx_hpd_in"; + function = "hdmitx"; + bias-disable; + }; + }; + + hdmitx_hpd_gpio: hdmitx_hpd_gpio { + mux { + groups = "GPIOH_1"; + function = "gpio_periphs"; + bias-disable; + }; + }; + + hdmitx_ddc: hdmitx_ddc { + mux { + groups = "hdmitx_sda", + "hdmitx_sck"; + function = "hdmitx"; + bias-disable; + }; + }; + + eecec_a: ee_ceca { + mux { + groups = "cec_ao_a_ee"; + function = "cec_ao_ee"; + }; + }; + + eecec_b: ee_cecb { + mux { + groups = "cec_ao_b_ee"; + function = "cec_ao_ee"; + }; + }; + + internal_eth_pins: internal_eth_pins { + mux { + groups = "eth_link_led", + "eth_act_led"; + function = "eth"; + }; + }; + + external_eth_pins: external_eth_pins { + mux { + groups = "eth_mdio", + "eth_mdc", + "eth_rgmii_rx_clk", + "eth_rx_dv", + "eth_rxd0", + "eth_rxd1", + "eth_rxd2_rgmii", + "eth_rxd3_rgmii", + "eth_rgmii_tx_clk", + "eth_txen", + "eth_txd0", + "eth_txd1", + "eth_txd2_rgmii", + "eth_txd3_rgmii"; + function = "eth"; + drive-strength = <3>; + }; + }; + + irblaster_pins2:irblaster_pins2 { + mux { + groups = "remote_out_h"; + function = "remote_out"; + }; + }; + + irblaster_pins3:irblaster_pins3 { + mux { + groups = "remote_out_z"; + function = "remote_out"; + }; + }; + + jtag_apee_pins:jtag_apee_pin { + mux { + groups = "jtag_b_tdi", + "jtag_b_tdo", + "jtag_b_clk", + "jtag_b_tms"; + function = "jtag_b"; + }; + }; +}; + +&gpu{ + system-coherency = <0>; + tbl = <&dvfs285_cfg + &dvfs400_cfg + &dvfs500_cfg + &dvfs666_cfg + &dvfs800_cfg + &dvfs800_cfg>; +}; + +&pinctrl_aobus { + sd_to_ao_uart_clr_pins:sd_to_ao_uart_clr_pins { + mux { + groups = "GPIOAO_0", + "GPIOAO_1"; + function = "gpio_aobus"; + }; + }; + + sd_to_ao_uart_pins:sd_to_ao_uart_pins { + mux { + groups = "uart_ao_tx_a", + "uart_ao_rx_a"; + function = "uart_ao_a"; + bias-pull-up; + input-enable; + }; + }; + + remote_pins:remote_pin { + mux { + groups = "remote_input_ao"; + function = "remote_input_ao"; + }; + }; + + irblaster_pins:irblaster_pin { + mux { + groups = "remote_out_ao"; + function = "remote_out_ao"; + }; + }; + + irblaster_pins1:irblaster_pin1 { + mux { + groups = "remote_out_ao9"; + function = "remote_out_ao"; + }; + }; +}; /* end of pinctrl_aobus */ diff --git a/arch/arm64/boot/dts/amlogic/mesongxl.dtsi b/arch/arm64/boot/dts/amlogic/mesongxl.dtsi index 643a922dd599..7a3c21beb0f2 100644 --- a/arch/arm64/boot/dts/amlogic/mesongxl.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesongxl.dtsi @@ -119,21 +119,17 @@ bit_mode=<12>; bit_resolution=<0>; }; + arm_pmu { compatible = "arm,armv8-pmuv3"; - interrupts = <0 137 4>; - reg = <0x0 0xc8834400 0 0x1000>; - - /* addr = base + offset << 2 */ - sys_cpu_status0_offset = <0xa0>; - - sys_cpu_status0_pmuirq_mask = <0xf>; - + /* clusterb-enabled; */ + interrupts = ; + reg = <0x0 0xc8834680 0x0 0x4>; + cpumasks = <0xf>; /* default 10ms */ - relax_timer_ns = <10000000>; - + relax-timer-ns = <10000000>; /* default 10000us */ - max_wait_cnt = <10000>; + max-wait-cnt = <10000>; }; gic: interrupt-controller@2c001000 { @@ -151,11 +147,12 @@ method = "smc"; }; - meson_suspend:pm{ + aml_pm { compatible = "amlogic, pm"; + status = "okay"; device_name = "aml_pm"; - reg = <0x0 0xc81000a8 0x0 0x4>, - <0x0 0xc810023c 0x0 0x4>; + debug_reg = <0xc81000a8>; + exit_reg = <0xc810023c>; }; secmon { @@ -236,20 +233,21 @@ ram-dump { compatible = "amlogic, ram_dump"; status = "okay"; + reg = <0x0 0xC88345E0 0x0 4>; + reg-names = "PREG_STICKY_REG8"; + store_device = "data"; }; jtag { compatible = "amlogic, jtag"; status = "okay"; - select = "apao"; /* disable/apao/apee */ - jtagao-gpios = <&gpio GPIOH_6 0 - &gpio GPIOH_7 0 - &gpio GPIOH_8 0 - &gpio GPIOH_9 0>; - jtagee-gpios = <&gpio CARD_0 0 - &gpio CARD_1 0 - &gpio CARD_2 0 - &gpio CARD_3 0>; + select = "disable"; /* disable/apao/apee */ + /* both sets of jtags for the GXL platform */ + /* are in the ee domain, this is named apao */ + /* just to match the jtag driver */ + pinctrl-names="jtag_apao_pins", "jtag_apee_pins"; + pinctrl-0=<&jtag_a_pins>; + pinctrl-1=<&jtag_b_pins>; }; mailbox: mhu@c883c400 { @@ -513,6 +511,14 @@ clocks = <&clkc CLKID_I2C>; clock-names = "clk_i2c"; }; + + irblaster: meson-irblaster@c0 { + compatible = "amlogic, aml_irblaster"; + reg = <0x0 0xc0 0x0 0xc>, + <0x0 0x40 0x0 0x4>; + #irblaster-cells = <2>; + status = "disabled"; + }; }; periphs: periphs@c8834000 { @@ -533,6 +539,7 @@ clkc: clock-controller@0 { compatible = "amlogic,gxl-clkc"; #clock-cells = <1>; + #reset-cells = <1>; reg = <0x0 0x0 0x0 0x3db>; }; }; @@ -561,6 +568,12 @@ mem_size = <0x0 0x100000>; status = "okay"; }; + + openvfd { + compatible = "open,vfd"; + dev_name = "openvfd"; + status = "okay"; + }; }; /* end of root */ &pinctrl_aobus { @@ -625,6 +638,20 @@ function = "ee_cec"; }; }; + + irblaster_pins:irblaster_pin { + mux { + groups = "ir_out_ao7"; + function = "ir_out"; + }; + }; + + irblaster_pins1:irblaster_pin1 { + mux { + groups = "ir_out_ao9"; + function = "ir_out"; + }; + }; }; /* end of pinctrl_aobus*/ &pinctrl_periphs { @@ -648,23 +675,23 @@ }; }; - jtag_apao_pins:jtag_apao_pin { + jtag_a_pins:jtag_a_pin { mux { - groups = "jtag_tdi_0", - "jtag_tdo_0", - "jtag_clk_0", - "jtag_tms_0"; - function = "jtag"; + groups = "GPIOH_6", + "GPIOH_7", + "GPIOH_8", + "GPIOH_9"; + function = "gpio_periphs"; }; }; - jtag_apee_pins:jtag_apee_pin { + jtag_b_pins:jtag_b_pin { mux { - groups ="jtag_tdi_1", - "jtag_tdo_1", - "jtag_clk_1", - "jtag_tms_1"; - function = "jtag"; + groups = "CARD_0", + "CARD_1", + "CARD_2", + "CARD_3"; + function = "gpio_periphs"; }; }; diff --git a/arch/arm64/boot/dts/amlogic/mesongxl_sei210.dtsi b/arch/arm64/boot/dts/amlogic/mesongxl_sei210.dtsi index a66605342869..c8dbc57835b7 100644 --- a/arch/arm64/boot/dts/amlogic/mesongxl_sei210.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesongxl_sei210.dtsi @@ -133,12 +133,17 @@ bit_mode=<12>; bit_resolution=<0>; }; + arm_pmu { compatible = "arm,armv8-pmuv3"; - interrupts = <0 137 4>, - <0 138 4>, - <0 153 4>, - <0 154 4>; + /* clusterb-enabled; */ + interrupts = ; + reg = <0x0 0xc8834680 0x0 0x4>; + cpumasks = <0xf>; + /* default 10ms */ + relax-timer-ns = <10000000>; + /* default 10000us */ + max-wait-cnt = <10000>; }; gic: interrupt-controller@2c001000 { @@ -156,11 +161,12 @@ method = "smc"; }; - meson_suspend:pm{ + aml_pm { compatible = "amlogic, pm"; + status = "okay"; device_name = "aml_pm"; - reg = <0x0 0xc81000a8 0x0 0x4 - 0x0 0xc810023c 0x0 0x4>; + debug_reg = <0xc81000a8>; + exit_reg = <0xc810023c>; }; secmon { @@ -235,15 +241,13 @@ jtag { compatible = "amlogic, jtag"; status = "okay"; - select = "apao"; /* disable/apao/apee */ - jtagao-gpios = <&gpio GPIOH_6 0 - &gpio GPIOH_7 0 - &gpio GPIOH_8 0 - &gpio GPIOH_9 0>; - jtagee-gpios = <&gpio CARD_0 0 - &gpio CARD_1 0 - &gpio CARD_2 0 - &gpio CARD_3 0>; + select = "disable"; /* disable/apao/apee */ + /* both sets of jtags for the GXL platform */ + /* are in the ee domain, this is named apao */ + /* just to match the jtag driver */ + pinctrl-names="jtag_apao_pins", "jtag_apee_pins"; + pinctrl-0=<&jtag_a_pins>; + pinctrl-1=<&jtag_b_pins>; }; mailbox: mhu@c883c400 { @@ -551,6 +555,12 @@ mem_size = <0x0 0x100000>; status = "okay"; }; + + openvfd { + compatible = "open,vfd"; + dev_name = "openvfd"; + status = "okay"; + }; }; /* end of root */ &pinctrl_aobus { @@ -638,23 +648,23 @@ }; }; - jtag_apao_pins:jtag_apao_pin { + jtag_a_pins:jtag_a_pin { mux { - groups = "jtag_tdi_0", - "jtag_tdo_0", - "jtag_clk_0", - "jtag_tms_0"; - function = "jtag"; + groups = "GPIOH_6", + "GPIOH_7", + "GPIOH_8", + "GPIOH_9"; + function = "gpio_periphs"; }; }; - jtag_apee_pins:jtag_apee_pin { + jtag_b_pins:jtag_b_pin { mux { - groups ="jtag_tdi_1", - "jtag_tdo_1", - "jtag_clk_1", - "jtag_tms_1"; - function = "jtag"; + groups = "CARD_0", + "CARD_1", + "CARD_2", + "CARD_3"; + function = "gpio_periphs"; }; }; diff --git a/arch/arm64/boot/dts/amlogic/mesongxm.dtsi b/arch/arm64/boot/dts/amlogic/mesongxm.dtsi index 22cbefdd4a4c..f638d7afdba0 100644 --- a/arch/arm64/boot/dts/amlogic/mesongxm.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesongxm.dtsi @@ -26,6 +26,7 @@ #include #include #include "mesongxm-gpu-t82x.dtsi" +#include "gxm-sched-energy.dtsi" / { cpus:cpus { #address-cells = <2>; @@ -69,6 +70,8 @@ clocks = <&scpi_dvfs 0>; clock-names = "cpu-cluster.0"; cpu-idle-states = <&SYSTEM_SLEEP_0>; + sched-energy-costs = <&CPU_COST_A53_HS + &CLUSTER_COST_A53_HS>; /* * cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0 * &SYSTEM_SLEEP_0>; @@ -83,6 +86,8 @@ clocks = <&scpi_dvfs 0>; clock-names = "cpu-cluster.0"; cpu-idle-states = <&SYSTEM_SLEEP_0>; + sched-energy-costs = <&CPU_COST_A53_HS + &CLUSTER_COST_A53_HS>; /* * cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0 * &SYSTEM_SLEEP_0>; @@ -97,6 +102,8 @@ clocks = <&scpi_dvfs 0>; clock-names = "cpu-cluster.0"; cpu-idle-states = <&SYSTEM_SLEEP_0>; + sched-energy-costs = <&CPU_COST_A53_HS + &CLUSTER_COST_A53_HS>; /* * cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0 * &SYSTEM_SLEEP_0>; @@ -111,6 +118,8 @@ clocks = <&scpi_dvfs 0>; clock-names = "cpu-cluster.0"; cpu-idle-states = <&SYSTEM_SLEEP_0>; + sched-energy-costs = <&CPU_COST_A53_HS + &CLUSTER_COST_A53_HS>; /* * cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0 * &SYSTEM_SLEEP_0>; @@ -125,6 +134,8 @@ clocks = <&scpi_dvfs 1>; clock-names = "cpu-cluster.1"; cpu-idle-states = <&SYSTEM_SLEEP_0>; + sched-energy-costs = <&CPU_COST_A53 + &CLUSTER_COST_A53>; /* * cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0 * &SYSTEM_SLEEP_0>; @@ -139,6 +150,8 @@ clocks = <&scpi_dvfs 1>; clock-names = "cpu-cluster.1"; cpu-idle-states = <&SYSTEM_SLEEP_0>; + sched-energy-costs = <&CPU_COST_A53 + &CLUSTER_COST_A53>; /* * cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0 * &SYSTEM_SLEEP_0>; @@ -152,6 +165,8 @@ clocks = <&scpi_dvfs 1>; clock-names = "cpu-cluster.1"; cpu-idle-states = <&SYSTEM_SLEEP_0>; + sched-energy-costs = <&CPU_COST_A53 + &CLUSTER_COST_A53>; /* * cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0 * &SYSTEM_SLEEP_0>; @@ -166,6 +181,8 @@ clocks = <&scpi_dvfs 1>; clock-names = "cpu-cluster.1"; cpu-idle-states = <&SYSTEM_SLEEP_0>; + sched-energy-costs = <&CPU_COST_A53 + &CLUSTER_COST_A53>; /* * cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0 * &SYSTEM_SLEEP_0>; @@ -223,12 +240,17 @@ bit_mode=<12>; bit_resolution=<0>; }; + arm_pmu { compatible = "arm,armv8-pmuv3"; - interrupts = <0 137 4>, - <0 138 4>, - <0 153 4>, - <0 154 4>; + /* clusterb-enabled; */ + interrupts = ; + reg = <0x0 0xc8834680 0x0 0x4>; + cpumasks = <0xf>; + /* default 10ms */ + relax-timer-ns = <10000000>; + /* default 10000us */ + max-wait-cnt = <10000>; }; gic: interrupt-controller@2c001000 { @@ -258,14 +280,21 @@ ram-dump { compatible = "amlogic, ram_dump"; status = "okay"; + reg = <0x0 0xC88345E0 0x0 4>; + reg-names = "PREG_STICKY_REG8"; + store_device = "data"; }; jtag { compatible = "amlogic, jtag"; - status = "disabled"; + status = "okay"; + select = "disable"; /* disable/apao/apee */ + /* both sets of jtags for the GXM platform */ + /* are in the ee domain, this is named apao */ + /* just to match the jtag driver */ pinctrl-names = "jtag_apao_pins", "jtag_apee_pins"; - pinctrl-0 = <&jtag_apao_pins>; - pinctrl-1 = <&jtag_apee_pins>; + pinctrl-0 = <&jtag_a_pins>; + pinctrl-1 = <&jtag_b_pins>; }; psci { @@ -273,11 +302,12 @@ method = "smc"; }; - meson_suspend:pm{ + aml_pm { compatible = "amlogic, pm"; + status = "okay"; device_name = "aml_pm"; - reg = <0x0 0xc81000a8 0x0 0x4>, - <0x0 0xc810023c 0x0 0x4>; + debug_reg = <0xc81000a8>; + exit_reg = <0xc810023c>; }; secmon { @@ -601,6 +631,14 @@ clocks = <&clkc CLKID_I2C>; clock-names = "clk_i2c"; }; + + irblaster: meson-irblaster@c0 { + compatible = "amlogic, aml_irblaster"; + reg = <0x0 0xc0 0x0 0xc>, + <0x0 0x40 0x0 0x4>; + #irblaster-cells = <2>; + status = "disabled"; + }; }; periphs: periphs@c8834000 { @@ -621,6 +659,7 @@ clkc: clock-controller@0 { compatible = "amlogic,gxl-clkc"; #clock-cells = <1>; + #reset-cells = <1>; reg = <0x0 0x0 0x0 0x3db>; }; }; @@ -642,6 +681,12 @@ compatible = "amlogic, vdac-gxm"; status = "okay"; }; + + openvfd { + compatible = "open,vfd"; + dev_name = "openvfd"; + status = "okay"; + }; }; /* end of root */ &pinctrl_aobus { @@ -706,6 +751,20 @@ function = "ee_cec"; }; }; + + irblaster_pins:irblaster_pin { + mux { + groups = "ir_out_ao7"; + function = "ir_out"; + }; + }; + + irblaster_pins1:irblaster_pin1 { + mux { + groups = "ir_out_ao9"; + function = "ir_out"; + }; + }; }; /* end of pinctrl_aobus*/ &pinctrl_periphs { @@ -729,23 +788,23 @@ }; }; - jtag_apao_pins:jtag_apao_pin { + jtag_a_pins:jtag_a_pin { mux { - groups = "jtag_tdi_0", - "jtag_tdo_0", - "jtag_clk_0", - "jtag_tms_0"; - function = "jtag"; + groups = "GPIOH_6", + "GPIOH_7", + "GPIOH_8", + "GPIOH_9"; + function = "gpio_periphs"; }; }; - jtag_apee_pins:jtag_apee_pin { + jtag_b_pins:jtag_b_pin { mux { - groups ="jtag_tdi_1", - "jtag_tdo_1", - "jtag_clk_1", - "jtag_tms_1"; - function = "jtag"; + groups = "CARD_0", + "CARD_1", + "CARD_2", + "CARD_3"; + function = "gpio_periphs"; }; }; diff --git a/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi b/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi new file mode 100644 index 000000000000..23f3e1456fc2 --- /dev/null +++ b/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi @@ -0,0 +1,2414 @@ +/* + * arch/arm64/boot/dts/amlogic/mesonsm1.dtsi + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "mesong12a-bifrost.dtsi" + +/ { + cpus:cpus { + #address-cells = <2>; + #size-cells = <0>; + + cpu-map { + cluster0:cluster0 { + core0 { + cpu = <&CPU0>; + }; + core1 { + cpu = <&CPU1>; + }; + core2 { + cpu = <&CPU2>; + }; + core3 { + cpu = <&CPU3>; + }; + }; + }; + + CPU0:cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a53","arm,armv8"; + reg = <0x0 0x0>; + enable-method = "psci"; + cpu-idle-states = <&CPU_SLEEP_0>; + clocks = <&clkc CLKID_CPU_CLK>, + <&clkc CLKID_CPU_FCLK_P>, + <&clkc CLKID_SYS_PLL>; + clock-names = "core_clk", + "low_freq_clk_parent", + "high_freq_clk_parent"; + operating-points-v2 = <&cpu_opp_table0>; + cpu-supply = <&vddcpu0>; + voltage-tolerance = <0>; + clock-latency = <50000>; + }; + + CPU1:cpu@1 { + device_type = "cpu"; + compatible = "arm,cortex-a53","arm,armv8"; + reg = <0x0 0x1>; + enable-method = "psci"; + cpu-idle-states = <&CPU_SLEEP_0>; + clocks = <&clkc CLKID_CPU_CLK>, + <&clkc CLKID_CPU_FCLK_P>, + <&clkc CLKID_SYS_PLL>; + clock-names = "core_clk", + "low_freq_clk_parent", + "high_freq_clk_parent"; + operating-points-v2 = <&cpu_opp_table0>; + cpu-supply = <&vddcpu0>; + voltage-tolerance = <0>; + clock-latency = <50000>; + }; + + CPU2:cpu@2 { + device_type = "cpu"; + compatible = "arm,cortex-a53","arm,armv8"; + reg = <0x0 0x2>; + enable-method = "psci"; + cpu-idle-states = <&CPU_SLEEP_0>; + clocks = <&clkc CLKID_CPU_CLK>, + <&clkc CLKID_CPU_FCLK_P>, + <&clkc CLKID_SYS_PLL>; + clock-names = "core_clk", + "low_freq_clk_parent", + "high_freq_clk_parent"; + operating-points-v2 = <&cpu_opp_table0>; + cpu-supply = <&vddcpu0>; + voltage-tolerance = <0>; + clock-latency = <50000>; + }; + + CPU3:cpu@3 { + device_type = "cpu"; + compatible = "arm,cortex-a53","arm,armv8"; + reg = <0x0 0x3>; + enable-method = "psci"; + cpu-idle-states = <&CPU_SLEEP_0>; + clocks = <&clkc CLKID_CPU_CLK>, + <&clkc CLKID_CPU_FCLK_P>, + <&clkc CLKID_SYS_PLL>; + clock-names = "core_clk", + "low_freq_clk_parent", + "high_freq_clk_parent"; + operating-points-v2 = <&cpu_opp_table0>; + cpu-supply = <&vddcpu0>; + voltage-tolerance = <0>; + clock-latency = <50000>; + }; + + idle-states { + entry-method = "arm,psci-0.2"; + CPU_SLEEP_0: cpu-sleep-0 { + compatible = "arm,idle-state"; + arm,psci-suspend-param = <0x0010000>; + local-timer-stop; + entry-latency-us = <4000>; + exit-latency-us = <5000>; + min-residency-us = <10000>; + }; + }; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupts = , + , + , + ; + }; + + timer_bc { + compatible = "arm, meson-bc-timer"; + reg= <0x0 0xffd0f190 0x0 0x4 0x0 0xffd0f194 0x0 0x4>; + timer_name = "Meson TimerF"; + clockevent-rating=<300>; + clockevent-shift=<20>; + clockevent-features=<0x23>; + interrupts = <0 60 1>; + bit_enable=<16>; + bit_mode=<12>; + bit_resolution=<0>; + }; + + arm_pmu { + compatible = "arm,armv8-pmuv3"; + /* clusterb-enabled; */ + interrupts = ; + reg = <0x0 0xff634680 0x0 0x4>; + cpumasks = <0xf>; + /* default 10ms */ + relax-timer-ns = <10000000>; + /* default 10000us */ + max-wait-cnt = <10000>; + }; + + gic: interrupt-controller@2c001000 { + compatible = "arm,cortex-a15-gic", "arm,cortex-a9-gic"; + #interrupt-cells = <3>; + #address-cells = <0>; + interrupt-controller; + reg = <0x0 0xffc01000 0 0x1000>, + <0x0 0xffc02000 0 0x0100>; + interrupts = ; + }; + + psci { + compatible = "arm,psci-0.2"; + method = "smc"; + }; + + aml_pm { + compatible = "amlogic, pm"; + status = "okay"; + device_name = "aml_pm"; + debug_reg = <0xff8000a8>; + exit_reg = <0xff80023c>; + }; + + secmon { + compatible = "amlogic, secmon"; + memory-region = <&secmon_reserved>; + in_base_func = <0x82000020>; + out_base_func = <0x82000021>; + reserve_mem_size = <0x00300000>; + }; + + securitykey { + compatible = "aml, securitykey"; + storage_query = <0x82000060>; + storage_read = <0x82000061>; + storage_write = <0x82000062>; + storage_tell = <0x82000063>; + storage_verify = <0x82000064>; + storage_status = <0x82000065>; + storage_list = <0x82000067>; + storage_remove = <0x82000068>; + storage_in_func = <0x82000023>; + storage_out_func = <0x82000024>; + storage_block_func = <0x82000025>; + storage_size_func = <0x82000027>; + storage_set_enctype = <0x8200006A>; + storage_get_enctype = <0x8200006B>; + storage_version = <0x8200006C>; + }; + + mailbox: mhu@c883c400 { + compatible = "amlogic, meson_mhu"; + reg = <0x0 0xff63c400 0x0 0x4c>, /* MHU registers */ + <0x0 0xfffe7000 0x0 0x800>; /* Payload area */ + interrupts = <0 209 1>, /* low priority interrupt */ + <0 210 1>; /* high priority interrupt */ + #mbox-cells = <1>; + mbox-names = "cpu_to_scp_low", "cpu_to_scp_high"; + mboxes = <&mailbox 0 &mailbox 1>; + }; + + cpu_iomap { + compatible = "amlogic, iomap"; + #address-cells=<2>; + #size-cells=<2>; + ranges; + io_cbus_base { + reg = <0x0 0xffd00000 0x0 0x26fff>; + }; + io_apb_base { + reg = <0x0 0xffe01000 0x0 0x7f000>; + }; + io_aobus_base { + reg = <0x0 0xff800000 0x0 0xb000>; + }; + io_vapb_base { + reg = <0x0 0xff900000 0x0 0x50000>; + }; + io_hiu_base { + reg = <0x0 0xff63c000 0x0 0x2000>; + }; + }; + + xtal: xtal-clk { + compatible = "fixed-clock"; + clock-frequency = <24000000>; + clock-output-names = "xtal"; + #clock-cells = <0>; + }; + + rtc{ + compatible = "amlogic, aml_vrtc"; + alarm_reg_addr = <0xff8000a8>; + timer_e_addr = <0xffd0f188>; + init_date = "2015/01/01"; + status = "okay"; + }; + + cpu_info { + compatible = "amlogic, cpuinfo"; + status = "okay"; + cpuinfo_cmd = <0x82000044>; + }; + + aml_reboot{ + compatible = "aml, reboot"; + sys_reset = <0x84000009>; + sys_poweroff = <0x84000008>; + }; + + vpu: vpu { + compatible = "amlogic, vpu-sm1"; + dev_name = "vpu"; + status = "okay"; + clocks = <&clkc CLKID_VAPB_MUX>, + <&clkc CLKID_VPU_INTR>, + <&clkc CLKID_VPU_P0_COMP>, + <&clkc CLKID_VPU_P1_COMP>, + <&clkc CLKID_VPU_MUX>; + clock-names = "vapb_clk", + "vpu_intr_gate", + "vpu_clk0", + "vpu_clk1", + "vpu_clk"; + clk_level = <7>; + /* 0: 100.0M 1: 166.7M 2: 200.0M 3: 250.0M */ + /* 4: 333.3M 5: 400.0M 6: 500.0M 7: 666.7M */ + }; + + ethmac: ethernet@ff3f0000 { + compatible = "amlogic, g12a-eth-dwmac","snps,dwmac"; + reg = <0x0 0xff3f0000 0x0 0x10000 + 0x0 0xff634540 0x0 0x8 + 0x0 0xff64c000 0x0 0xa0>; + reg-names = "eth_base", "eth_cfg", "eth_pll"; + interrupts = <0 8 1>; + interrupt-names = "macirq"; + status = "disabled"; + clocks = <&clkc CLKID_ETH_CORE>; + clock-names = "ethclk81"; + pll_val = <0x9c0040a 0x927e0000 0xac5f49e5>; + analog_val = <0x20200000 0x0000c000 0x00000023>; + }; + + pinctrl_aobus: pinctrl@ff800014{ + compatible = "amlogic,meson-g12a-aobus-pinctrl"; + #address-cells = <2>; + #size-cells = <2>; + ranges; + + gpio_ao: ao-bank@ff800014{ + reg = <0x0 0xff800014 0x0 0x8>, + <0x0 0xff800024 0x0 0x14>, + <0x0 0xff80001c 0x0 0x8>; + reg-names = "mux","gpio", "drive-strength"; + gpio-controller; + #gpio-cells = <2>; + }; + }; + + pinctrl_periphs: pinctrl@ff634480{ + compatible = "amlogic,meson-g12a-periphs-pinctrl"; + #address-cells = <2>; + #size-cells = <2>; + ranges; + + gpio: banks@ff6346c0{ + reg = <0x0 0xff6346c0 0x0 0x40>, + <0x0 0xff6344e8 0x0 0x18>, + <0x0 0xff634520 0x0 0x18>, + <0x0 0xff634440 0x0 0x4c>, + <0x0 0xff634740 0x0 0x1c>; + reg-names = "mux", + "pull", + "pull-enable", + "gpio", + "drive-strength"; + gpio-controller; + #gpio-cells = <2>; + }; + }; + + audio_data: audio_data { + compatible = "amlogic, audio_data"; + query_licence_cmd = <0x82000050>; + status = "disabled"; + }; + + dwc3: dwc3@ff500000 { + compatible = "synopsys, dwc3"; + status = "disable"; + reg = <0x0 0xff500000 0x0 0x100000>; + interrupts = <0 30 4>; + usb-phy = <&usb2_phy_v2>, <&usb3_phy_v2>; + cpu-type = "gxl"; + clock-src = "usb3.0"; + clocks = <&clkc CLKID_USB_GENERAL>; + clock-names = "dwc_general"; + }; + + usb2_phy_v2: usb2phy@ffe09000 { + compatible = "amlogic, amlogic-new-usb2-v2"; + status = "disable"; + reg = <0x0 0xffe09000 0x0 0x80 + 0x0 0xffd01008 0x0 0x100 + 0x0 0xff636000 0x0 0x2000 + 0x0 0xff63a000 0x0 0x2000>; + pll-setting-1 = <0x09400414>; + pll-setting-2 = <0x927E0000>; + pll-setting-3 = <0xac5f69e5>; + pll-setting-4 = <0xfe18>; + pll-setting-5 = <0x8000fff>; + pll-setting-6 = <0x78000>; + pll-setting-7 = <0xe0004>; + pll-setting-8 = <0xe000c>; + version = <2>; + pwr-ctl = <1>; + u2-ctrl-sleep-shift = <17>; + u2-hhi-mem-pd-shift = <30>; + u2-hhi-mem-pd-mask = <0x3>; + u2-ctrl-iso-shift = <17>; + }; + + usb3_phy_v2: usb3phy@ffe09080 { + compatible = "amlogic, amlogic-new-usb3-v2"; + status = "disable"; + reg = <0x0 0xffe09080 0x0 0x20 + 0x0 0xffd01008 0x0 0x100>; + phy-reg = <0xff646000>; + phy-reg-size = <0x2000>; + usb2-phy-reg = <0xffe09000>; + usb2-phy-reg-size = <0x80>; + interrupts = <0 16 4>; + clocks = <&clkc CLKID_PCIE_PLL>; + clock-names = "pcie_refpll"; + pwr-ctl = <1>; + u3-ctrl-sleep-shift = <18>; + u3-hhi-mem-pd-shift = <26>; + u3-hhi-mem-pd-mask = <0xf>; + u3-ctrl-iso-shift = <18>; + }; + + dwc2_a: dwc2_a@ff400000 { + compatible = "amlogic, dwc2"; + status = "disable"; + device_name = "dwc2_a"; + reg = <0x0 0xff400000 0x0 0x40000>; + interrupts = <0 31 4>; + pl-periph-id = <0>; /** lm name */ + clock-src = "usb0"; /** clock src */ + port-id = <0>; /** ref to mach/usb.h */ + port-type = <2>; /** 0: otg, 1: host, 2: slave */ + port-speed = <0>; /** 0: default, high, 1: full */ + port-config = <0>; /** 0: default */ + /*0:default,1:single,2:incr,3:incr4,4:incr8,5:incr16,6:disable*/ + port-dma = <0>; + port-id-mode = <0>; /** 0: hardware, 1: sw_host, 2: sw_slave*/ + usb-fifo = <728>; + cpu-type = "v2"; + phy-reg = <0xffe09000>; + phy-reg-size = <0xa0>; + /** phy-interface: 0x0: amlogic phy, 0x1: synopsys phy **/ + phy-interface = <0x2>; + clocks = <&clkc CLKID_USB_GENERAL + &clkc CLKID_USB1_TO_DDR>; + clock-names = "usb_general", + "usb1"; + }; + + wdt: watchdog@0xffd0f0d0 { + compatible = "amlogic, meson-wdt"; + status = "okay"; + default_timeout=<10>; + reset_watchdog_method=<1>; /* 0:sysfs,1:kernel */ + reset_watchdog_time=<2>; + shutdown_timeout=<10>; + firmware_timeout=<6>; + suspend_timeout=<6>; + reg = <0x0 0xffd0f0d0 0x0 0x10>; + clock-names = "xtal"; + clocks = <&xtal>; + }; + + ram-dump { + compatible = "amlogic, ram_dump"; + status = "okay"; + reg = <0x0 0xFF6345E0 0x0 4>; + reg-names = "PREG_STICKY_REG8"; + store_device = "data"; + }; + + jtag { + compatible = "amlogic, jtag"; + status = "okay"; + select = "disable"; /* disable/apao/apee */ + pinctrl-names="jtag_apao_pins", "jtag_apee_pins"; + pinctrl-0=<&jtag_apao_pins>; + pinctrl-1=<&jtag_apee_pins>; + }; + + saradc:saradc { + compatible = "amlogic,meson-g12a-saradc"; + status = "okay"; + #io-channel-cells = <1>; + clocks = <&xtal>, <&clkc CLKID_SARADC_GATE>; + clock-names = "xtal", "saradc_clk"; + interrupts = ; + reg = <0x0 0xff809000 0x0 0x48>; + }; + + power_ctrl: power_ctrl@ff8000e8 { + compatible = "amlogic, sm1-powerctrl"; + reg = <0x0 0xff8000e8 0x0 0x10>, + <0x0 0xff63c100 0x0 0x10>; + }; + + soc { + compatible = "simple-bus"; + #address-cells = <2>; + #size-cells = <2>; + ranges; + + cbus: cbus@ffd00000 { + compatible = "simple-bus"; + reg = <0x0 0xffd00000 0x0 0x26000>; + #address-cells = <2>; + #size-cells = <2>; + ranges = <0x0 0x0 0x0 0xffd00000 0x0 0x26000>; + + gpio_intc: interrupt-controller@f080 { + compatible = "amlogic,meson-gpio-intc", + "amlogic,meson-sm1-gpio-intc"; + reg = <0x0 0xf080 0x0 0x10>; + interrupt-controller; + #interrupt-cells = <2>; + amlogic,channel-interrupts = + <64 65 66 67 68 69 70 71>; + status = "okay"; + }; + + meson_clk_msr { + compatible = "amlogic, sm1-measure"; + reg = <0x0 0x18004 0x0 0x4 + 0x0 0x1800c 0x0 0x4>; + ringctrl = <0xff6345fc>; + }; + + pwm_ab: pwm@1b000 { + compatible = "amlogic,g12a-ee-pwm"; + reg = <0x0 0x1b000 0x0 0x20>; + #pwm-cells = <3>; + clocks = <&xtal>, + <&xtal>, + <&xtal>, + <&xtal>; + clock-names = "clkin0", + "clkin1", + "clkin2", + "clkin3"; + /* default xtal 24m clkin0-clkin2 and + * clkin1-clkin3 should be set the same + */ + status = "disabled"; + }; + + pwm_cd: pwm@1a000 { + compatible = "amlogic,g12a-ee-pwm"; + reg = <0x0 0x1a000 0x0 0x20>; + #pwm-cells = <3>; + clocks = <&xtal>, + <&xtal>, + <&xtal>, + <&xtal>; + clock-names = "clkin0", + "clkin1", + "clkin2", + "clkin3"; + status = "disabled"; + }; + + pwm_ef: pwm@19000 { + compatible = "amlogic,g12a-ee-pwm"; + reg = <0x0 0x19000 0x0 0x20>; + #pwm-cells = <3>; + clocks = <&xtal>, + <&xtal>, + <&xtal>, + <&xtal>; + clock-names = "clkin0", + "clkin1", + "clkin2", + "clkin3"; + status = "disabled"; + }; + + i2c0: i2c@1f000 { + compatible = "amlogic,meson-g12a-i2c"; + status = "disabled"; + reg = <0x0 0x1f000 0x0 0x20>; + interrupts = , + ; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&clkc CLKID_I2C>; + clock-names = "clk_i2c"; + }; + + i2c1: i2c@1e000 { + compatible = "amlogic,meson-g12a-i2c"; + status = "disabled"; + reg = <0x0 0x1e000 0x0 0x20>; + interrupts = , + ; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&clkc CLKID_I2C>; + clock-names = "clk_i2c"; + }; + + i2c2: i2c@1d000 { + compatible = "amlogic,meson-g12a-i2c"; + status = "disabled"; + reg = <0x0 0x1d000 0x0 0x20>; + interrupts = , + ; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&clkc CLKID_I2C>; + clock-names = "clk_i2c"; + }; + + i2c3: i2c@1c000 { + compatible = "amlogic,meson-g12a-i2c"; + status = "disabled"; + reg = <0x0 0x1c000 0x0 0x20>; + interrupts = , + ; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&clkc CLKID_I2C>; + clock-names = "clk_i2c"; + }; + + spicc0: spi@13000 { + compatible = "amlogic,meson-g12a-spicc"; + reg = <0x0 0x13000 0x0 0x44>; + interrupts = ; + clocks = <&clkc CLKID_SPICC0>, + <&clkc CLKID_SPICC0_COMP>; + clock-names = "core", "comp"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + spicc1: spi@15000 { + compatible = "amlogic,meson-g12a-spicc"; + reg = <0x0 0x15000 0x0 0x44>; + interrupts = ; + clocks = <&clkc CLKID_SPICC1>, + <&clkc CLKID_SPICC1_COMP>; + clock-names = "core", "comp"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + }; /* end of cbus */ + + aobus: aobus@ff800000 { + compatible = "simple-bus"; + reg = <0x0 0xff800000 0x0 0xb000>; + #address-cells = <2>; + #size-cells = <2>; + ranges = <0x0 0x0 0x0 0xff800000 0x0 0xb000>; + + cpu_version { + reg=<0x0 0x220 0x0 0x4>; + }; + + aoclkc: clock-controller@0 { + compatible = "amlogic,sm1-aoclkc"; + #clock-cells = <1>; + reg = <0x0 0x0 0x0 0x3dc>; + }; + + pwm_AO_ab: pwm@7000 { + compatible = "amlogic,g12a-ao-pwm"; + reg = <0x0 0x7000 0x0 0x20>; + #pwm-cells = <3>; + clocks = <&xtal>, + <&xtal>, + <&xtal>, + <&xtal>; + clock-names = "clkin0", + "clkin1", + "clkin2", + "clkin3"; + status = "disabled"; + }; + + pwm_AO_cd: pwm@2000 { + compatible = "amlogic,g12a-ao-pwm"; + reg = <0x0 0x2000 0x0 0x20>; + #pwm-cells = <3>; + clocks = <&xtal>, + <&xtal>, + <&xtal>, + <&xtal>; + clock-names = "clkin0", + "clkin1", + "clkin2", + "clkin3"; + status = "disabled"; + }; + + i2c_AO: i2c@5000 { + compatible = "amlogic,meson-g12a-i2c"; + status = "disabled"; + reg = <0x0 0x05000 0x0 0x20>; + interrupts = , + ; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&clkc CLKID_I2C>; + clock-names = "clk_i2c"; + }; + + i2c_AO_slave:i2c_slave@6000 { + compatible = "amlogic, meson-i2c-slave"; + status = "disabled"; + reg = <0x0 0x6000 0x0 0x20>; + interrupts = <0 194 1>; + pinctrl-names="default"; + pinctrl-0=<&ao_i2c_slave_pins>; + }; + + uart_AO: serial@3000 { + compatible = "amlogic, meson-uart"; + reg = <0x0 0x3000 0x0 0x18>; + interrupts = <0 193 1>; + status = "okay"; + clocks = <&xtal>; + clock-names = "clk_uart"; + xtal_tick_en = <2>; + fifosize = < 64 >; + pinctrl-names = "default"; + /*pinctrl-0 = <&ao_uart_pins>;*/ + support-sysrq = <1>; /* 0 not support*/ + }; + + uart_AO_B: serial@4000 { + compatible = "amlogic, meson-uart"; + reg = <0x0 0x4000 0x0 0x18>; + interrupts = <0 197 1>; + status = "disabled"; + clocks = <&xtal>; + clock-names = "clk_uart"; + fifosize = < 64 >; + pinctrl-names = "default"; + pinctrl-0 = <&ao_b_uart_pins>; + }; + };/* end of aobus */ + + periphs: periphs@ff634400 { + compatible = "simple-bus"; + reg = <0x0 0xff634400 0x0 0x400>; + #address-cells = <2>; + #size-cells = <2>; + ranges = <0x0 0x0 0x0 0xff634400 0x0 0x400>; + + };/* end of periphs */ + + hiubus: hiubus@ff63c000 { + compatible = "simple-bus"; + reg = <0x0 0xff63c000 0x0 0x2000>; + #address-cells = <2>; + #size-cells = <2>; + ranges = <0x0 0x0 0x0 0xff63c000 0x0 0x2000>; + + clkc: clock-controller@0 { + compatible = "amlogic,sm1-clkc-1"; + #clock-cells = <1>; + reg = <0x0 0x0 0x0 0x3dc>; + }; + + clkc_b: clock-controller@1 { + compatible = "amlogic,sm1-clkc-2"; + #clock-cells = <1>; + reg = <0x0 0x0 0x0 0x3dc>; + }; + };/* end of hiubus*/ + + ion_dev { + compatible = "amlogic, ion_dev"; + memory-region = <&ion_cma_reserved>; + };/* end of ion_dev*/ + + audiobus: audiobus@0xFF660000 { + compatible = "amlogic, audio-controller", "simple-bus"; + reg = <0x0 0xFF660000 0x0 0x4000>; + #address-cells = <2>; + #size-cells = <2>; + ranges = <0x0 0x0 0x0 0xFF660000 0x0 0x4000>; + clkaudio: audio_clocks { + compatible = "amlogic, sm1-audio-clocks"; + #clock-cells = <1>; + reg = <0x0 0x0 0x0 0xb0>; + }; + ddr_manager { + compatible = "amlogic, sm1-audio-ddr-manager"; + interrupts = < + GIC_SPI 148 IRQ_TYPE_EDGE_RISING + GIC_SPI 149 IRQ_TYPE_EDGE_RISING + GIC_SPI 150 IRQ_TYPE_EDGE_RISING + GIC_SPI 49 IRQ_TYPE_EDGE_RISING + GIC_SPI 152 IRQ_TYPE_EDGE_RISING + GIC_SPI 153 IRQ_TYPE_EDGE_RISING + GIC_SPI 154 IRQ_TYPE_EDGE_RISING + GIC_SPI 50 IRQ_TYPE_EDGE_RISING + >; + interrupt-names = + "toddr_a", "toddr_b", "toddr_c", + "toddr_d", + "frddr_a", "frddr_b", "frddr_c", + "frddr_d"; + }; + };/* end of audiobus*/ + + }; /* end of soc*/ + + remote:rc@0xff808040 { + compatible = "amlogic, aml_remote"; + dev_name = "meson-remote"; + reg = <0x0 0xff808040 0x00 0x44>, /*Multi-format IR controller*/ + <0x0 0xff808000 0x00 0x20>; /*Legacy IR controller*/ + status = "okay"; + protocol = ; + led_blink = <1>; + led_blink_frq = <100>; + interrupts = <0 196 1>; + pinctrl-names = "default"; + pinctrl-0 = <&remote_pins>; + map = <&custom_maps>; + max_frame_time = <200>; /*set software decoder max frame time*/ + }; + + custom_maps:custom_maps { + mapnum = <3>; + map0 = <&map_0>; + map1 = <&map_1>; + map2 = <&map_2>; + map_0: map_0{ + mapname = "amlogic-remote-1"; + customcode = <0xfb04>; + release_delay = <80>; + size = <50>; /*keymap size*/ + keymap = ; + }; + map_1: map_1{ + mapname = "amlogic-remote-2"; + customcode = <0xfe01>; + release_delay = <80>; + size = <53>; + keymap = ; + }; + map_2: map_2{ + mapname = "amlogic-remote-3"; + customcode = <0xbd02>; + release_delay = <80>; + size = <17>; + keymap = ; + }; + }; + + uart_A: serial@ffd24000 { + compatible = "amlogic, meson-uart"; + reg = <0x0 0xffd24000 0x0 0x18>; + interrupts = <0 26 1>; + status = "disabled"; + clocks = <&xtal + &clkc CLKID_UART0>; + clock-names = "clk_uart", + "clk_gate"; + fifosize = < 128 >; + pinctrl-names = "default"; + pinctrl-0 = <&a_uart_pins>; + }; + + uart_B: serial@ffd23000 { + compatible = "amlogic, meson-uart"; + reg = <0x0 0xffd23000 0x0 0x18>; + interrupts = <0 75 1>; + status = "disabled"; + clocks = <&xtal + &clkc CLKID_UART1>; + clock-names = "clk_uart", + "clk_gate"; + fifosize = < 64 >; + pinctrl-names = "default"; + pinctrl-0 = <&b_uart_pins>; + }; + + uart_C: serial@ffd22000 { + compatible = "amlogic, meson-uart"; + reg = <0x0 0xffd22000 0x0 0x18>; + interrupts = <0 93 1>; + status = "disabled"; + clocks = <&xtal + &clkc CLKID_UART1>; + clock-names = "clk_uart", + "clk_gate"; + fifosize = < 64 >; + pinctrl-names = "default"; + pinctrl-0 = <&c_uart_pins>; + }; + + + pcie_A: pcieA@fc000000 { + compatible = "amlogic, amlogic-pcie-v2", "snps,dw-pcie"; + reg = <0x0 0xfc000000 0x0 0x400000 + 0x0 0xff648000 0x0 0x2000 + 0x0 0xfc400000 0x0 0x200000 + 0x0 0xff646000 0x0 0x2000 + 0x0 0xffd01080 0x0 0x10>; + reg-names = "elbi", "cfg", "config", "phy", "reset"; + interrupts = <0 221 0>; + #interrupt-cells = <1>; + bus-range = <0x0 0xff>; + #address-cells = <3>; + #size-cells = <2>; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &gic GIC_SPI 223 IRQ_TYPE_EDGE_RISING>; + device_type = "pci"; + ranges = <0x81000000 0 0 0 0xfc600000 0x0 0x100000 + /* downstream I/O */ + 0x82000000 0 0xfc700000 0x0 0xfc700000 0 0x1900000>; + /* non-prefetchable memory */ + num-lanes = <1>; + pcie-num = <1>; + + clocks = <&clkc CLKID_PCIE_PLL + &clkc CLKID_PCIE_COMB + &clkc CLKID_PCIE_PHY>; + clock-names = "pcie_refpll", + "pcie", + "pcie_phy"; + /*reset-gpio-type 0:Shared pad(no reset)1:OD pad2:Normal pad*/ + gpio-type = <2>; + pcie-apb-rst-bit = <15>; + pcie-phy-rst-bit = <14>; + pcie-ctrl-a-rst-bit = <12>; + pwr-ctl = <1>; + pcie-ctrl-sleep-shift = <18>; + pcie-hhi-mem-pd-shift = <26>; + pcie-hhi-mem-pd-mask = <0xf>; + pcie-ctrl-iso-shift = <18>; + status = "disabled"; + }; + + amhdmitx: amhdmitx{ + compatible = "amlogic, amhdmitx"; + dev_name = "amhdmitx"; + status = "okay"; + vend-data = <&vend_data>; + pinctrl-names="default", "hdmitx_i2c"; + pinctrl-0=<&hdmitx_hpd &hdmitx_ddc>; + pinctrl-1=<&hdmitx_hpd_gpio &i2c3_master_pins1>; + clocks = <&clkc CLKID_VCLK2_ENCI + &clkc CLKID_VCLK2_VENCI0 + &clkc CLKID_VCLK2_VENCI1 + &clkc CLKID_VAPB_MUX + &clkc CLKID_VPU_MUX>; + clock-names = "venci_top_gate", + "venci_0_gate", + "venci_1_gate", + "hdmi_vapb_clk", + "hdmi_vpu_clk"; + /* HPD, 57 + 32 = 89; CEC, 151 + 32 = 183*/ + interrupts = <0 57 1>; + interrupt-names = "hdmitx_hpd"; + /* 0:M8B 1:GXBB 2:GXTVBB 3:GXL 4:GXM + * 5:TXL 6:TXLX 7:AXG 8:GXLX 9:TXHD + * 10:G12A 11:G12B 12:SM1 + */ + ic_type = <12>; + vend_data: vend_data{ /* Should modified by Customer */ + vendor_name = "Amlogic"; /* Max Chars: 8 */ + /* standards.ieee.org/develop/regauth/oui/oui.txt */ + vendor_id = <0x000000>; + }; + }; + + galcore { + compatible = "amlogic, galcore"; + dev_name = "galcore"; + status = "disabled"; + clocks = <&clkc CLKID_VNANOQ_AXI_CLK_COMP>, + <&clkc CLKID_VNANOQ_CORE_CLK_COMP>; + clock-names = "cts_vipnanoq_axi_clk_composite", + "cts_vipnanoq_core_clk_composite"; + interrupts = <0 186 4>; + interrupt-names = "galcore"; + reg = <0x0 0xff100000 0x0 0x800 + /*reg base value:0xff100000 */ + 0x0 0xff000000 0x0 0x400000 + /*Sram bse value:0xff000000*/ + 0x0 0xff63c118 0x0 0x0 + 0x0 0xff63c11c 0x0 0x0 + /*0xff63c118,0xff63c11c :nanoq mem regs*/ + 0x0 0xffd01088 0x0 0x0 + /*0xffd01088:reset reg*/ + >; + }; + aocec: aocec { + compatible = "amlogic, aocec-sm1"; + device_name = "aocec"; + status = "okay"; + vendor_name = "Amlogic"; /* Max Chars: 8 */ + /* Refer to the following URL at: + * http://standards.ieee.org/develop/regauth/oui/oui.txt + */ + vendor_id = <0x000000>; + product_desc = "SM1"; /* Max Chars: 16 */ + cec_osd_string = "AML_MBOX"; /* Max Chars: 14 */ + cec_version = <5>;/*5:1.4;6:2.0*/ + port_num = <1>; + ee_cec; + arc_port_mask = <0x2>; + interrupts = <0 203 1 + 0 199 1>; /*0:snps 1:ts*/ + interrupt-names = "hdmi_aocecb","hdmi_aocec"; + pinctrl-names = "default","hdmitx_aocecb","cec_pin_sleep"; + pinctrl-0=<&eecec_a>; + pinctrl-1=<&eecec_b>; + pinctrl-2=<&eecec_b>; + reg = <0x0 0xFF80023c 0x0 0x4 + 0x0 0xFF800000 0x0 0x400 + 0x0 0xFF634400 0x0 0x70>; + reg-names = "ao_exit","ao","periphs"; + }; + + /*if you want to use vdin just modify status to "ok"*/ + vdin0: vdin0 { + compatible = "amlogic, vdin"; + dev_name = "vdin0"; + status = "disabled"; + reserve-iomap = "true"; + flag_cma = <0>;/*1:share with codec_mm;2:cma alone*/ + /*MByte, if 10bit disable: 64M(YUV422), + *if 10bit enable: 64*1.5 = 96M(YUV422) + *if support 4K2K-YUV444-10bit-WR:3840*2160*4*4 ~= 128M + *if support 4K2K-YUV422-10bit-wr:3840*2160*3*4 ~= 96M + *if support 4K2K-YUV422-8BIT-WR:3840*2160*2*4 ~= 64M + *if support 1080p-YUV422-8BIT-WR:1920*1080*2*4 ~= 16M + */ + /*cma_size = <16>;*/ + interrupts = <0 83 1>; + rdma-irq = <2>; + /*clocks = <&clock CLK_FPLL_DIV5>, + * <&clock CLK_VDIN_MEAS_CLK>; + *clock-names = "fclk_div5", "cts_vdin_meas_clk"; + */ + vdin_id = <0>; + }; + vdin1: vdin1 { + compatible = "amlogic, vdin"; + dev_name = "vdin1"; + status = "disabled"; + reserve-iomap = "true"; + flag_cma = <0>;/*1:share with codec_mm;0:cma alone*/ + interrupts = <0 85 1>; + rdma-irq = <4>; + /*clocks = <&clock CLK_FPLL_DIV5>, + * <&clock CLK_VDIN_MEAS_CLK>; + *clock-names = "fclk_div5", "cts_vdin_meas_clk"; + */ + vdin_id = <1>; + }; + + vout { + compatible = "amlogic, vout"; + dev_name = "vout"; + status = "okay"; + }; + + vout2 { + compatible = "amlogic, vout2"; + dev_name = "vout"; + status = "okay"; + clocks = <&clkc CLKID_VPU_CLKC_P0_COMP>, + <&clkc CLKID_VPU_CLKC_MUX>; + clock-names = "vpu_clkc0", + "vpu_clkc"; + }; + + vdac { + compatible = "amlogic, vdac-sm1"; + status = "okay"; + }; + + canvas: canvas{ + compatible = "amlogic, meson, canvas"; + dev_name = "amlogic-canvas"; + status = "okay"; + reg = <0x0 0xff638000 0x0 0x2000>; + }; + + ge2d { + compatible = "amlogic, ge2d-sm1"; + dev_name = "ge2d"; + status = "okay"; + interrupts = <0 146 1>; + interrupt-names = "ge2d"; + clocks = <&clkc CLKID_VAPB_MUX>, + <&clkc CLKID_G2D>, + <&clkc CLKID_GE2D_GATE>; + clock-names = "clk_vapb_0", + "clk_ge2d", + "clk_ge2d_gate"; + reg = <0x0 0xff940000 0x0 0x10000>; + }; + + meson-amvideom { + compatible = "amlogic, amvideom"; + dev_name = "amvideom"; + status = "okay"; + interrupts = <0 3 1>; + interrupt-names = "vsync"; + }; + + codec_io: codec_io { + compatible = "amlogic, codec_io"; + status = "okay"; + #address-cells=<2>; + #size-cells=<2>; + ranges; + io_cbus_base{ + reg = <0x0 0xffd00000 0x0 0x100000>; + }; + io_dos_base{ + reg = <0x0 0xff620000 0x0 0x10000>; + }; + io_hiubus_base{ + reg = <0x0 0xff63c000 0x0 0x2000>; + }; + io_aobus_base{ + reg = <0x0 0xff800000 0x0 0x10000>; + }; + io_vcbus_base{ + reg = <0x0 0xff900000 0x0 0x40000>; + }; + io_dmc_base{ + reg = <0x0 0xff638000 0x0 0x2000>; + }; + io_efuse_base{ + reg = <0x0 0xff630000 0x0 0x2000>; + }; + }; + + mesonstream { + compatible = "amlogic, codec, streambuf"; + dev_name = "mesonstream"; + status = "okay"; + clocks = <&clkc CLKID_DOS_PARSER + &clkc CLKID_DEMUX + &clkc CLKID_AHB_ARB0 + &clkc CLKID_DOS + &clkc CLKID_CLK81 + &clkc CLKID_VDEC_MUX + &clkc CLKID_HCODEC_MUX + &clkc CLKID_HEVC_MUX + &clkc CLKID_HEVCF_MUX>; + clock-names = "parser_top", + "demux", + "ahbarb0", + "vdec", + "clk_81", + "clk_vdec_mux", + "clk_hcodec_mux", + "clk_hevc_mux", + "clk_hevcb_mux"; + }; + + vdec { + compatible = "amlogic, vdec"; + dev_name = "vdec.0"; + status = "okay"; + interrupts = <0 3 1 + 0 23 1 + 0 32 1 + 0 43 1 + 0 44 1 + 0 45 1 + 0 72 1>; + interrupt-names = "vsync", + "demux", + "parser", + "mailbox_0", + "mailbox_1", + "mailbox_2", + "parser_b"; + }; + + vcodec_dec { + compatible = "amlogic, vcodec-dec"; + dev_name = "aml-vcodec-dec"; + status = "okay"; + }; + + amvenc_avc{ + compatible = "amlogic, amvenc_avc"; + dev_name = "amvenc_avc"; + status = "okay"; + interrupts = <0 45 1>; + interrupt-names = "mailbox_2"; + }; + + hevc_enc{ + compatible = "cnm, HevcEnc"; + //memory-region = <&hevc_enc_reserved>; + dev_name = "HevcEnc"; + status = "okay"; + interrupts = <0 187 1>; + interrupt-names = "wave420l_irq"; + #address-cells=<2>; + #size-cells=<2>; + ranges; + io_reg_base{ + reg = <0x0 0xff610000 0x0 0x4000>; + }; + }; + + rdma{ + compatible = "amlogic, meson, rdma"; + dev_name = "amlogic-rdma"; + status = "okay"; + interrupts = <0 89 1>; + interrupt-names = "rdma"; + }; + + meson_fb: fb { + compatible = "amlogic, meson-sm1"; + memory-region = <&logo_reserved>; + dev_name = "meson-fb"; + status = "disable"; + interrupts = <0 3 1 + 0 56 1 + 0 89 1>; + interrupt-names = "viu-vsync", "viu2-vsync", "rdma"; + /* uboot logo,fb0/fb1 memory size,if afbcd fb0=0x01851000*/ + display_mode_default = "1080p60hz"; + scale_mode = <1>; + /** 0:VPU free scale 1:OSD free scale 2:OSD super scale */ + display_size_default = <1920 1080 1920 2160 32>; + /*1920*1080*4*3 = 0x17BB000*/ + clocks = <&clkc CLKID_VPU_CLKC_MUX>; + clock-names = "vpu_clkc"; + }; + irblaster: meson-irblaster { + compatible = "amlogic, meson_irblaster"; + reg = <0x0 0xff80014c 0x0 0x10>, + <0x0 0xff800040 0x0 0x4>; + pinctrl-names = "default"; + pinctrl-0 = <&irblaster_pins>; + interrupts = <0 198 1>; + status = "okay"; + }; + + sd_emmc_c: emmc@ffe07000 { + status = "disabled"; + compatible = "amlogic, meson-mmc-sm1"; + reg = <0x0 0xffe07000 0x0 0x800>; + interrupts = <0 191 1>; + pinctrl-names = "emmc_clk_cmd_pins", "emmc_all_pins"; + pinctrl-0 = <&emmc_clk_cmd_pins>; + pinctrl-1 = <&emmc_conf_pull_up &emmc_conf_pull_done>; + clocks = <&clkc CLKID_SD_EMMC_C>, + <&clkc CLKID_SD_EMMC_C_P0_COMP>, + <&clkc CLKID_FCLK_DIV2>, + <&clkc CLKID_FCLK_DIV5>, + <&xtal>; + clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + + bus-width = <8>; + cap-sd-highspeed; + cap-mmc-highspeed; + /* mmc-ddr-1_8v; */ + /* mmc-hs200-1_8v; */ + + max-frequency = <200000000>; + non-removable; + disable-wp; + emmc { + pinname = "emmc"; + ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ + /*caps defined in dts*/ + tx_delay = <0>; + co_phase = <3>; + max_req_size = <0x20000>; /**128KB*/ + gpio_dat3 = <&gpio BOOT_3 GPIO_ACTIVE_HIGH>; + hw_reset = <&gpio BOOT_12 GPIO_ACTIVE_HIGH>; + card_type = <1>; + /* 1:mmc card(include eMMC), + * 2:sd card(include tSD) + */ + }; + }; + + sd_emmc_b:sd@ffe05000 { + status = "disabled"; + compatible = "amlogic, meson-mmc-sm1"; + reg = <0x0 0xffe05000 0x0 0x800>; + interrupts = <0 190 1>; + + pinctrl-names = "sd_all_pins", + "sd_clk_cmd_pins", + "sd_1bit_pins", + "sd_clk_cmd_uart_pins", + "sd_1bit_uart_pins", + "sd_to_ao_uart_pins", + "ao_to_sd_uart_pins", + "sd_to_ao_jtag_pins", + "ao_to_sd_jtag_pins"; + + pinctrl-0 = <&sd_all_pins>; + pinctrl-1 = <&sd_clk_cmd_pins>; + pinctrl-2 = <&sd_1bit_pins>; + pinctrl-3 = <&sd_to_ao_uart_clr_pins + &sd_clk_cmd_pins &ao_to_sd_uart_pins>; + pinctrl-4 = <&sd_to_ao_uart_clr_pins + &sd_1bit_pins &ao_to_sd_uart_pins>; + pinctrl-5 = <&sd_all_pins &sd_to_ao_uart_pins>; + pinctrl-6 = <&sd_to_ao_uart_clr_pins + &ao_to_sd_uart_pins>; + pinctrl-7 = <&sd_all_pins &sd_to_ao_uart_pins>; + pinctrl-8 = <&sd_to_ao_uart_clr_pins + &ao_to_sd_uart_pins>; + + clocks = <&clkc CLKID_SD_EMMC_B>, + <&clkc CLKID_SD_EMMC_B_P0_COMP>, + <&clkc CLKID_FCLK_DIV2>, + <&clkc CLKID_FCLK_DIV5>, + <&xtal>; + clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + + bus-width = <4>; + cap-sd-highspeed; + cap-mmc-highspeed; + max-frequency = <100000000>; + disable-wp; + sd { + pinname = "sd"; + ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ + max_req_size = <0x20000>; /**128KB*/ + gpio_dat3 = <&gpio GPIOC_3 GPIO_ACTIVE_HIGH>; + jtag_pin = <&gpio GPIOC_0 GPIO_ACTIVE_HIGH>; + gpio_cd = <&gpio GPIOC_6 GPIO_ACTIVE_HIGH>; + card_type = <5>; + /* 3:sdio device(ie:sdio-wifi), + * 4:SD combo (IO+mem) card + */ + }; + }; + + + sd_emmc_a:sdio@ffe03000 { + status = "disabled"; + compatible = "amlogic, meson-mmc-sm1"; + reg = <0x0 0xffe03000 0x0 0x800>; + interrupts = <0 189 4>; + + pinctrl-names = "sdio_all_pins", + "sdio_clk_cmd_pins"; + pinctrl-0 = <&sdio_all_pins>; + pinctrl-1 = <&sdio_clk_cmd_pins>; + + clocks = <&clkc CLKID_SD_EMMC_A>, + <&clkc CLKID_SD_EMMC_A_P0_COMP>, + <&clkc CLKID_FCLK_DIV2>, + <&clkc CLKID_FCLK_DIV5>, + <&xtal>; + clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + + bus-width = <4>; + cap-sd-highspeed; + cap-mmc-highspeed; + max-frequency = <100000000>; + disable-wp; + sdio { + pinname = "sdio"; + ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ + max_req_size = <0x20000>; /**128KB*/ + card_type = <3>; + /* 3:sdio device(ie:sdio-wifi), + * 4:SD combo (IO+mem) card + */ + }; + }; + + nand: nfc@0 { + compatible = "amlogic, aml_mtd_nand"; + dev_name = "mtdnand"; + status = "disabled"; + reg = <0x0 0xFFE07800 0x0 0x200>; + interrupts = <0 34 1>; + + pinctrl-names = "nand_rb_mod","nand_norb_mod", "nand_cs_only"; + pinctrl-0 = <&all_nand_pins>; + pinctrl-1 = <&all_nand_pins>; + pinctrl-2 = <&nand_cs_pins>; + clocks = <&clkc CLKID_SD_EMMC_C>, + <&clkc CLKID_SD_EMMC_C_P0_COMP>; + clock-names = "core", "clkin"; + + device_id = <0>; + /*fip/tpl configurations, must be same + * with uboot if bl_mode was set as 1 + * bl_mode: 0 compact mode; 1 descrete mode + * if bl_mode was set as 1, fip configuration will work + */ + bl_mode = <1>; + /*copy count of fip*/ + fip_copies = <4>; + /*size of each fip copy */ + fip_size = <0x200000>; + nand_clk_ctrl = <0xFFE07000>; + /*partions defined in dts */ + }; + + /* Sound iomap */ + aml_snd_iomap { + compatible = "amlogic, snd-iomap"; + status = "okay"; + #address-cells=<2>; + #size-cells=<2>; + ranges; + pdm_bus { + reg = <0x0 0xFF661000 0x0 0x400>; + }; + audiobus_base { + reg = <0x0 0xFF660000 0x0 0x1000>; + }; + audiolocker_base { + reg = <0x0 0xFF661400 0x0 0x400>; + }; + eqdrc_base { + reg = <0x0 0xFF662000 0x0 0x1000>; + }; + reset_base { + reg = <0x0 0xFFD01000 0x0 0x1000>; + }; + vad_base { + reg = <0x0 0xFF661800 0x0 0x400>; + }; + earcrx_cdmc_base { + reg = <0x0 0xFF663800 0x0 0x30>; + }; + earcrx_dmac_base { + reg = <0x0 0xFF663C00 0x0 0x20>; + }; + earcrx_top_base { + reg = <0x0 0xFF663E00 0x0 0x10>; + }; + }; + + vddcpu0: pwmao_d-regulator { + compatible = "pwm-regulator"; + pwms = <&pwm_AO_cd MESON_PWM_1 1500 0>; + regulator-name = "vddcpu0"; + regulator-min-microvolt = <690000>; + regulator-max-microvolt = <1050000>; + regulator-always-on; + max-duty-cycle = <1500>; + /* Voltage Duty-Cycle */ + voltage-table = <1050000 0>, + <1040000 3>, + <1030000 6>, + <1020000 8>, + <1010000 11>, + <1000000 14>, + <990000 17>, + <980000 20>, + <970000 23>, + <960000 26>, + <950000 29>, + <940000 31>, + <930000 34>, + <920000 37>, + <910000 40>, + <900000 43>, + <890000 45>, + <880000 48>, + <870000 51>, + <860000 54>, + <850000 56>, + <840000 59>, + <830000 62>, + <820000 65>, + <810000 68>, + <800000 70>, + <790000 73>, + <780000 76>, + <770000 79>, + <760000 81>, + <750000 84>, + <740000 87>, + <730000 89>, + <720000 92>, + <710000 95>, + <700000 98>, + <690000 100>; + status = "okay"; + }; + + ddr_bandwidth { + compatible = "amlogic, ddr-bandwidth"; + status = "okay"; + reg = <0x0 0xff638000 0x0 0x100 + 0x0 0xff638c00 0x0 0x100>; + interrupts = <0 52 1>; + interrupt-names = "ddr_bandwidth"; + }; + dmc_monitor { + compatible = "amlogic, dmc_monitor"; + status = "okay"; + reg_base = <0xff639000>; + interrupts = <0 51 1>; + }; + + defendkey: defendkey { + compatible = "amlogic, defendkey"; + reg = <0x0 0xff630218 0x0 0x4>; /*RNG_USR_DATA*/ + mem_size = <0x0 0x100000>; + status = "okay"; + }; + + aml_dma { + compatible = "amlogic,aml_txlx_dma"; + reg = <0x0 0xff63e000 0x0 0x48>; + interrupts = <0 180 1>; + + aml_aes { + compatible = "amlogic,aes_g12a_dma"; + dev_name = "aml_aes_dma"; + status = "okay"; + }; + + aml_sha { + compatible = "amlogic,sha_dma"; + dev_name = "aml_sha_dma"; + status = "okay"; + }; + }; + + rng { + compatible = "amlogic,meson-rng"; + status = "okay"; + #address-cells = <2>; + #size-cells = <2>; + reg = <0x0 0xff630218 0x0 0x4>; + quality = /bits/ 16 <1000>; + }; + + efuse: efuse{ + compatible = "amlogic, efuse"; + read_cmd = <0x82000030>; + write_cmd = <0x82000031>; + get_max_cmd = <0x82000033>; + key = <&efusekey>; + clocks = <&clkc CLKID_EFUSE>; + clock-names = "efuse_clk"; + status = "disabled"; + }; + + cpu_ver_name { + compatible = "amlogic, cpu-major-id-sm1"; + }; +};/* end of / */ + +&pinctrl_aobus { + sd_to_ao_uart_clr_pins:sd_to_ao_uart_clr_pins { + mux { + groups = "GPIOAO_0", + "GPIOAO_1"; + function = "gpio_aobus"; + }; + }; + + sd_to_ao_uart_pins:sd_to_ao_uart_pins { + mux { + groups = "uart_ao_tx_a", + "uart_ao_rx_a"; + function = "uart_ao_a"; + bias-pull-up; + input-enable; + }; + }; + + ao_uart_pins:ao_uart { + mux { + groups = "uart_ao_tx_a", + "uart_ao_rx_a"; + function = "uart_ao_a"; + }; + }; + + ao_b_uart_pins:ao_b_uart { + mux { + groups = "uart_ao_tx_b_2", + "uart_ao_rx_b_3"; + function = "uart_ao_b"; + }; + }; + + ao_i2c_master_pins1:ao_i2c_pins1 { + mux { + groups = "i2c_ao_sck", + "i2c_ao_sda"; + function = "i2c_ao"; + drive-strength = <2>; + }; + }; + + ao_i2c_master_pins2:ao_i2c_pins2 { + mux { + groups = "i2c_ao_sck_e", + "i2c_ao_sda_e"; + function = "i2c_ao"; + drive-strength = <2>; + }; + }; + + ao_i2c_slave_pins:ao_i2c_slave_pins { + mux { + groups = "i2c_ao_slave_sck", + "i2c_ao_slave_sda"; + function = "i2c_ao_slave"; + }; + }; + + pwm_ao_a_pins: pwm_ao_a { + mux { + groups = "pwm_ao_a"; + function = "pwm_ao_a"; + }; + }; + + pwm_ao_a_hiz_pins: pwm_ao_a_hiz { + mux { + groups = "pwm_ao_a_hiz"; + function = "pwm_ao_a"; + }; + }; + + pwm_ao_b_pins: pwm_ao_b { + mux { + groups = "pwm_ao_b"; + function = "pwm_ao_b"; + }; + }; + + pwm_ao_c_pins1: pwm_ao_c_pins1 { + mux { + groups = "pwm_ao_c_4"; + function = "pwm_ao_c"; + }; + }; + + pwm_ao_c_pins2: pwm_ao_c_pins2 { + mux { + groups = "pwm_ao_c_6"; + function = "pwm_ao_c"; + }; + }; + + pwm_ao_c_hiz_pins: pwm_ao_c_hiz { + mux { + groups = "pwm_ao_c_hiz_4"; + function = "pwm_ao_c"; + }; + }; + + pwm_ao_d_pins1: pwm_ao_d_pins1 { + mux { + groups = "pwm_ao_d_5"; + function = "pwm_ao_d"; + }; + }; + + pwm_ao_d_pins2: pwm_ao_d_pins2 { + mux { + groups = "pwm_ao_d_10"; + function = "pwm_ao_d"; + }; + }; + + pwm_ao_d_pins3: pwm_ao_d_pins3 { + mux { + groups = "pwm_ao_d_e"; + function = "pwm_ao_d"; + }; + }; + + aocec_a: ao_ceca { + mux { + groups = "cec_ao_a"; + function = "cec_ao"; + }; + }; + + aocec_b: ao_cecb { + mux { + groups = "cec_ao_b"; + function = "cec_ao"; + }; + }; + + jtag_apao_pins:jtag_apao_pin { + mux { + groups = "jtag_a_tdi", + "jtag_a_tdo", + "jtag_a_clk", + "jtag_a_tms"; + function = "jtag_a"; + }; + }; +}; + +&pinctrl_periphs { + /* sdemmc portC */ + emmc_clk_cmd_pins:emmc_clk_cmd_pins { + mux { + groups = "emmc_clk", + "emmc_cmd"; + function = "emmc"; + input-enable; + bias-pull-up; + }; + }; + + emmc_conf_pull_up:emmc_conf_pull_up { + mux { + groups = "emmc_nand_d7", + "emmc_nand_d6", + "emmc_nand_d5", + "emmc_nand_d4", + "emmc_nand_d3", + "emmc_nand_d2", + "emmc_nand_d1", + "emmc_nand_d0", + "emmc_clk", + "emmc_cmd"; + function = "emmc"; + input-enable; + bias-pull-up; + }; + }; + + emmc_conf_pull_done:emmc_conf_pull_done { + mux { + groups = "emmc_nand_ds"; + function = "emmc"; + input-enable; + bias-pull-down; + }; + }; + + /* sdemmc portB */ + sd_clk_cmd_pins:sd_clk_cmd_pins { + mux { + groups = "sdcard_cmd_c"; + function = "sdcard"; + input-enable; + bias-pull-up; + drive-strength = <3>; + }; + mux1 { + groups = "sdcard_clk_c"; + function = "sdcard"; + bias-pull-up; + output-high; + drive-strength = <3>; + }; + }; + + sd_all_pins:sd_all_pins { + mux { + groups = "sdcard_d0_c", + "sdcard_d1_c", + "sdcard_d2_c", + "sdcard_d3_c", + "sdcard_cmd_c"; + function = "sdcard"; + input-enable; + bias-pull-up; + drive-strength = <3>; + }; + mux1 { + groups = "sdcard_clk_c"; + function = "sdcard"; + bias-pull-up; + output-high; + drive-strength = <3>; + }; + }; + + sd_1bit_pins:sd_1bit_pins { + mux { + groups = "sdcard_d0_c", + "sdcard_cmd_c"; + function = "sdcard"; + input-enable; + bias-pull-up; + drive-strength = <3>; + }; + mux1 { + groups = "sdcard_clk_c"; + function = "sdcard"; + bias-pull-up; + output-high; + drive-strength = <3>; + }; + }; + + sd_clr_all_pins:sd_clr_all_pins { + mux { + groups = "GPIOC_0", + "GPIOC_1", + "GPIOC_2", + "GPIOC_3", + "GPIOC_5"; + function = "gpio_periphs"; + output-high; + }; + mux1 { + groups = "GPIOC_4"; + function = "gpio_periphs"; + output-low; + }; + }; + + sd_clr_noall_pins:sd_clr_noall_pins { + mux { + groups = "GPIOC_0", + "GPIOC_1", + "GPIOC_4", + "GPIOC_5"; + function = "gpio_periphs"; + output-high; + }; + }; + + ao_to_sd_uart_pins:ao_to_sd_uart_pins { + mux { + groups = "uart_ao_tx_a_c3", + "uart_ao_rx_a_c2"; + function = "uart_ao_a_ee"; + bias-pull-up; + input-enable; + }; + }; + + /* sdemmc portA */ + sdio_clk_cmd_pins:sdio_clk_cmd_pins { + mux { + groups = "sdio_clk", + "sdio_cmd"; + function = "sdio"; + input-enable; + bias-pull-up; + drive-strength = <3>; + }; + }; + + sdio_all_pins:sdio_all_pins { + mux { + groups = "sdio_d0", + "sdio_d1", + "sdio_d2", + "sdio_d3", + "sdio_clk", + "sdio_cmd"; + function = "sdio"; + input-enable; + bias-pull-up; + drive-strength = <3>; + }; + }; + + sdio_x_clk_cmd_pins:sdio_x_clk_cmd_pins { + mux { + groups = "GPIOX_5"; + function = "gpio_periphs"; + input-enable; + bias-pull-up; + drive-strength = <3>; + }; + mux1 { + groups = "GPIOX_4"; + function = "gpio_periphs"; + bias-pull-up; + output-high; + drive-strength = <3>; + }; + }; + + sdio_x_all_pins:sdio_x_all_pins { + mux { + groups = "GPIOX_0", + "GPIOX_1", + "GPIOX_2", + "GPIOX_3", + "GPIOX_5"; + function = "gpio_periphs"; + input-enable; + bias-pull-up; + drive-strength = <3>; + }; + mux1 { + groups = "GPIOX_4"; + function = "gpio_periphs"; + bias-pull-up; + output-high; + drive-strength = <3>; + }; + }; + + sdio_x_en_pins:sdio_x_en_pins { + mux { + groups = "sdio_dummy"; + function = "sdio"; + bias-pull-up; + output-high; + }; + }; + + sdio_x_clr_pins:sdio_x_clr_pins { + mux { + groups = "GPIOV_0"; + function = "gpio_periphs"; + bias-pull-up; + output-low; + }; + mux1 { + groups = "GPIOX_4"; + function = "gpio_periphs"; + output-low; + }; + }; + + all_nand_pins: all_nand_pins { + mux { + groups = "emmc_nand_d0", + "emmc_nand_d1", + "emmc_nand_d2", + "emmc_nand_d3", + "emmc_nand_d4", + "emmc_nand_d5", + "emmc_nand_d6", + "emmc_nand_d7", + "nand_ce0", + "nand_ale", + "nand_cle", + "nand_wen_clk", + "nand_ren_wr", + "nand_rb0"; + function = "nand"; + input-enable; + }; + }; + + nand_cs_pins: nand_cs { + mux { + groups = "nand_ce0"; + function = "nand"; + }; + }; + + i2c0_master_pins1:i2c0_pins1 { + mux { + groups = "i2c0_sda_c", + "i2c0_sck_c"; + function = "i2c0"; + drive-strength = <2>; + }; + }; + + i2c0_master_pins2:i2c0_pins2 { + mux { + groups = "i2c0_sda_z0", + "i2c0_sck_z1"; + function = "i2c0"; + drive-strength = <2>; + }; + }; + + i2c0_master_pins3:i2c0_pins3 { + mux { + groups = "i2c0_sda_z7", + "i2c0_sck_z8"; + function = "i2c0"; + drive-strength = <2>; + }; + }; + + i2c1_master_pins1:i2c1_pins1 { + mux { + groups = "i2c1_sda_x", + "i2c1_sck_x"; + function = "i2c1"; + drive-strength = <2>; + }; + }; + + i2c1_master_pins2:i2c1_pins2 { + mux { + groups = "i2c1_sda_h2", + "i2c1_sck_h3"; + function = "i2c1"; + drive-strength = <2>; + }; + }; + + i2c1_master_pins3:i2c1_pins3 { + mux { + groups = "i2c1_sda_h6", + "i2c1_sck_h7"; + function = "i2c1"; + drive-strength = <2>; + }; + }; + + i2c2_master_pins1:i2c2_pins1 { + mux { + groups = "i2c2_sda_x", + "i2c2_sck_x"; + function = "i2c2"; + drive-strength = <2>; + }; + }; + + i2c2_master_pins2:i2c2_pins2 { + mux { + groups = "i2c2_sda_z", + "i2c2_sck_z"; + function = "i2c2"; + drive-strength = <2>; + }; + }; + + i2c3_master_pins1:i2c3_pins1 { + mux { + groups = "i2c3_sda_h", + "i2c3_sck_h"; + function = "i2c3"; + drive-strength = <2>; + }; + }; + + i2c3_master_pins2:i2c3_pins2 { + mux { + groups = "i2c3_sda_a", + "i2c3_sck_a"; + function = "i2c3"; + drive-strength = <2>; + }; + }; + + /*dvb_p_ts1_pins: dvb_p_ts1_pins { + * tsin_b { + * groups = "tsin_b_sop_z", + * "tsin_b_valid_z", + * "tsin_b_clk_z", + * "tsin_b_din0_z", + * "tsin_b_din1", + * "tsin_b_din2", + * "tsin_b_din3", + * "tsin_b_din4", + * "tsin_b_din5", + * "tsin_b_din6", + * "tsin_b_din7"; + * function = "tsin_b"; + * }; + *}; + */ + + pwm_a_pins: pwm_a { + mux { + groups = "pwm_a"; + function = "pwm_a"; + }; + }; + + pwm_b_pins1: pwm_b_pins1 { + mux { + groups = "pwm_b_x7"; + function = "pwm_b"; + }; + }; + + pwm_b_pins2: pwm_b_pins2 { + mux { + groups = "pwm_b_x19"; + function = "pwm_b"; + }; + }; + + pwm_c_pins1: pwm_c_pins1 { + mux { + groups = "pwm_c_c4"; + function = "pwm_c"; + }; + }; + + pwm_c_pins2: pwm_c_pins2 { + mux { + groups = "pwm_c_x5"; + function = "pwm_c"; + }; + }; + + pwm_c_pins3: pwm_c_pins3 { + mux { + groups = "pwm_c_x8"; + function = "pwm_c"; + }; + }; + + pwm_d_pins1: pwm_d_pins1 { + mux { + groups = "pwm_d_x3"; + function = "pwm_d"; + }; + }; + + pwm_d_pins2: pwm_d_pins2 { + mux { + groups = "pwm_d_x6"; + function = "pwm_d"; + }; + }; + + pwm_e_pins: pwm_e { + mux { + groups = "pwm_e"; + function = "pwm_e"; + }; + }; + + pwm_f_pins1: pwm_f_pins1 { + mux { + groups = "pwm_f_x"; + function = "pwm_f"; + }; + }; + + pwm_f_pins2: pwm_f_pins2 { + mux { + groups = "pwm_f_h"; + function = "pwm_f"; + }; + }; + + spicc0_pins_x: spicc0_pins_x { + mux { + groups = "spi0_mosi_x", + "spi0_miso_x", + //"spi0_ss0_x", + "spi0_clk_x"; + function = "spi0"; + drive-strength = <1>; + }; + }; + + spicc0_pins_c: spicc0_pins_c { + mux { + groups = "spi0_mosi_c", + "spi0_miso_c", + "spi0_ss0_c", + "spi0_clk_c"; + function = "spi0"; + drive-strength = <1>; + }; + }; + + spicc1_pins: spicc1_pins { + mux { + groups = "spi1_mosi", + "spi1_miso", + //"spi1_ss0", + "spi1_clk"; + function = "spi1"; + drive-strength = <1>; + }; + }; + + a_uart_pins:a_uart { + mux { + groups = "uart_tx_a", + "uart_rx_a", + "uart_cts_a", + "uart_rts_a"; + function = "uart_a"; + }; + }; + + b_uart_pins:b_uart { + mux { + groups = "uart_tx_b", + "uart_rx_b"; + function = "uart_b"; + }; + }; + + c_uart_pins:c_uart { + mux { + groups = "uart_tx_c", + "uart_rx_c"; + function = "uart_c"; + }; + }; + + hdmitx_hpd: hdmitx_hpd { + mux { + groups = "hdmitx_hpd_in"; + function = "hdmitx"; + bias-disable; + }; + }; + + hdmitx_hpd_gpio: hdmitx_hpd_gpio { + mux { + groups = "GPIOH_1"; + function = "gpio_periphs"; + bias-disable; + }; + }; + + hdmitx_ddc: hdmitx_ddc { + mux { + groups = "hdmitx_sda", + "hdmitx_sck"; + function = "hdmitx"; + bias-disable; + drive-strength = <3>; + }; + }; + + eecec_a: ee_ceca { + mux { + groups = "cec_ao_a_ee"; + function = "cec_ao_ee"; + }; + }; + + eecec_b: ee_cecb { + mux { + groups = "cec_ao_b_ee"; + function = "cec_ao_ee"; + }; + }; + + internal_eth_pins: internal_eth_pins { + mux { + groups = "eth_link_led", + "eth_act_led"; + function = "eth"; + }; + }; + + internal_gpio_pins: internal_gpio_pins { + mux { + groups = "GPIOZ_14", + "GPIOZ_15"; + function = "gpio_periphs"; + bias-disable; + input-enable; + }; + }; + + external_eth_pins: external_eth_pins { + mux { + groups = "eth_mdio", + "eth_mdc", + "eth_rgmii_rx_clk", + "eth_rx_dv", + "eth_rxd0", + "eth_rxd1", + "eth_rxd2_rgmii", + "eth_rxd3_rgmii", + "eth_rgmii_tx_clk", + "eth_txen", + "eth_txd0", + "eth_txd1", + "eth_txd2_rgmii", + "eth_txd3_rgmii"; + function = "eth"; + drive-strength = <3>; + }; + }; + + jtag_apee_pins:jtag_apee_pin { + mux { + groups = "jtag_b_tdi", + "jtag_b_tdo", + "jtag_b_clk", + "jtag_b_tms"; + function = "jtag_b"; + }; + }; +}; + +&pinctrl_aobus { + remote_pins:remote_pin { + mux { + groups = "remote_input_ao"; + function = "remote_input_ao"; + }; + }; + + irblaster_pins:irblaster_pin { + mux { + groups = "remote_out_ao"; + function = "remote_out_ao"; + }; + }; +}; /* end of pinctrl_aobus */ diff --git a/arch/arm64/boot/dts/amlogic/mesonsm1_skt-panel.dtsi b/arch/arm64/boot/dts/amlogic/mesonsm1_skt-panel.dtsi new file mode 100644 index 000000000000..e12ca025ebc0 --- /dev/null +++ b/arch/arm64/boot/dts/amlogic/mesonsm1_skt-panel.dtsi @@ -0,0 +1,488 @@ +/* + * + * Copyright (C) 2019 Amlogic, Inc. All rights reserved. + * + */ + +/ { + lcd{ + compatible = "amlogic, lcd-sm1"; + mode = "tablet"; + status = "okay"; + key_valid = <0>; + clocks = <&clkc CLKID_MIPI_DSI_HOST + &clkc CLKID_MIPI_DSI_PHY + &clkc CLKID_DSI_MEAS_COMP + &clkc CLKID_VCLK2_ENCL + &clkc CLKID_VCLK2_VENCL + &clkc CLKID_GP0_PLL>; + clock-names = "dsi_host_gate", + "dsi_phy_gate", + "dsi_meas", + "encl_top_gate", + "encl_int_gate", + "gp0_pll"; + reg = <0x0 0xffd07000 0x0 0x400 /* dsi_host */ + 0x0 0xff644000 0x0 0x200>; /* dsi_phy */ + interrupts = <0 3 1 + 0 56 1>; + interrupt-names = "vsync","vsync2"; + pinctrl_version = <2>; /* for uboot */ + + /* power type: + * (0=cpu_gpio, 1=pmu_gpio, 2=signal,3=extern, 0xff=ending) + * power index: + * (point gpios_index, or extern_index,0xff=invalid) + * power value:(0=output low, 1=output high, 2=input) + * power delay:(unit in ms) + */ + lcd_cpu-gpios = <&gpio GPIOZ_9 GPIO_ACTIVE_HIGH + &gpio GPIOZ_8 GPIO_ACTIVE_HIGH>; + lcd_cpu_gpio_names = "GPIOZ_9","GPIOZ_8"; + + lcd_0{ + model_name = "B080XAN01"; + interface = "mipi"; + basic_setting = <768 1024 /*h_active, v_active*/ + 948 1140 /*h_period, v_period*/ + 8 /*lcd_bits*/ + 119 159>; /*screen_widht, screen_height*/ + lcd_timing = <64 56 0 /*hs_width, hs_bp, hs_pol*/ + 50 30 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = <0 /*fr_adj_type(0=clk, 1=htotal, 2=vtotal)*/ + 0 /*clk_ss_level */ + 1 /*clk_auto_generate*/ + 64843200>; /*pixel_clk(unit in Hz)*/ + mipi_attr = <4 /*lane_num*/ + 550 /*bit_rate_max(MHz)*/ + 0 /*factor(*100, default 0 for auto)*/ + 1 /*operation_mode_init(0=video, 1=command)*/ + 0 /*operation_mode_display(0=video, 1=command)*/ + 2 /* + *video_mode_type + *(0=sync_pulse,1=sync_event,2=burst) + */ + 1 /*clk_always_hs(0=disable,1=enable)*/ + 0>; /*phy_switch(0=auto,1=standard,2=slow)*/ + + /* dsi_init: data_type, num, data... */ + dsi_init_on = <0x05 1 0x11 + 0xfd 1 20 /*delay(ms)*/ + 0x05 1 0x29 + 0xfd 1 20 /*delay(ms)*/ + 0xff 0>; /*ending*/ + dsi_init_off = <0x05 1 0x28 + 0xfd 1 10 /*delay(ms)*/ + 0x05 1 0x10 + 0xfd 1 10 /*delay(ms)*/ + 0xff 0>; /*ending*/ + extern_init = <0xff>; /*0xff for invalid*/ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 1 0 100 + 0 0 0 10 + 0 0 1 20 + 2 0 0 0 + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 50 + 0 0 0 10 + 0 1 1 100 + 0xff 0 0 0>; /*ending*/ + backlight_index = <0>; + }; + + lcd_1{ + model_name = "P070ACB_FT"; + interface = "mipi"; + basic_setting = <600 1024 /*h_active, v_active*/ + 770 1070 /*h_period, v_period*/ + 8 /*lcd_bits*/ + 3 5>; /*screen_widht, screen_height*/ + lcd_timing = <10 80 0 /*hs_width,hs_bp,hs_pol*/ + 6 20 0>; /*vs_width,vs_bp,vs_pol*/ + clk_attr = <0 /*fr_adj_type(0=clock,1=htotal,2=vtotal)*/ + 0 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 49434000>; /*pixel_clk(unit in Hz)*/ + mipi_attr = <4 /*lane_num*/ + 400 /*bit_rate_max(MHz)*/ + 0 /*factor(*100, default 0 for auto)*/ + 1 /*operation_mode_init(0=video, 1=command)*/ + 0 /*operation_mode_display(0=video, 1=command)*/ + 2 /* + *video_mode_type + *(0=sync_pulse,1=sync_event,2=burst) + */ + 0 /*clk_always_hs(0=disable,1=enable)*/ + 0>; /*phy_switch(0=auto,1=standard,2=slow)*/ + /* dsi_init: data_type, num, data... */ + dsi_init_on = < + 0xff 10 + 0xf0 3 0 1 30 /* reset high, delay 30ms */ + 0xf0 3 0 0 10 /* reset low, delay 10ms */ + 0xf0 3 0 1 30 /* reset high, delay 30ms */ + 0xfc 2 0x04 3 /* check_reg, check_cnt */ + 0xff 0>; /* ending flag */ + dsi_init_off = <0xff 0>; /* ending flag */ + /* extern_init: 0xff for invalid */ + extern_init = <5>; + /* power step: type,index,value,delay(ms) */ + power_on_step = < + 0 1 0 200 /* panel power on */ + 2 0 0 0 + 0xff 0 0 0>; + power_off_step = < + 2 0 0 0 + 0 0 0 20 /* reset low */ + 0 1 1 100 /* panel power off */ + 0xff 0 0 0>; + backlight_index = <0>; + }; + }; + + lcd_extern{ + compatible = "amlogic, lcd_extern"; + status = "okay"; + i2c_bus = "i2c_bus_0"; + key_valid = <0>; + + extern_0{ + index = <0>; + extern_name = "mipi_default";/*default*/ + status = "okay"; + type = <2>; /* 0=i2c, 1=spi, 2=mipi */ + cmd_size = <0xff>; + init_on = < + 0xfd 1 10 + 0x05 1 0x11 + 0xfd 1 120 /* delay 120ms */ + 0x05 1 0x29 + 0xff 0>; /*ending*/ + init_off = < + 0x05 1 0x28 /* display off */ + 0xfd 1 10 /* delay 10ms */ + 0x05 1 0x10 /* sleep in */ + 0xfd 1 150 /* delay 150ms */ + 0xff 0>; /*ending*/ + }; + + extern_1{ + index = <1>; + extern_name = "mipi_default";/*P070ACB_FT*/ + status = "okay"; + type = <2>; /* 0=i2c, 1=spi, 2=mipi */ + cmd_size = <0xff>; + init_on = < + 0x23 2 0xE0 0x00 /* Page 0 */ + 0x23 2 0xE1 0x93 /* PASSWORD */ + 0x23 2 0xE2 0x65 + 0x23 2 0xE3 0xF8 + 0x23 2 0x80 0x03 + 0x23 2 0xE0 0x01 /* Page 01 */ + 0x23 2 0x0C 0x74 /* Set PWRIC */ + 0x23 2 0x17 0x00 /* Set Gamma Power */ + 0x23 2 0x18 0xEF /* VGMP=5.1V */ + 0x23 2 0x19 0x00 + 0x23 2 0x1A 0x00 + 0x23 2 0x1B 0xEF /* VGMN=-5.1V */ + 0x23 2 0x1C 0x00 + 0x23 2 0x1F 0x70 /* Set Gate Power */ + 0x23 2 0x20 0x2D + 0x23 2 0x21 0x2D + 0x23 2 0x22 0x7E + 0x23 2 0x26 0xF3 /* VDDD from IOVCC */ + 0x23 2 0x37 0x09 /* SetPanel */ + 0x23 2 0x38 0x04 /* SET RGBCYC */ + 0x23 2 0x39 0x00 + 0x23 2 0x3A 0x01 + 0x23 2 0x3C 0x90 + 0x23 2 0x3D 0xFF + 0x23 2 0x3E 0xFF + 0x23 2 0x3F 0xFF + 0x23 2 0x40 0x02 /* Set TCON */ + 0x23 2 0x41 0x80 + 0x23 2 0x42 0x99 + 0x23 2 0x43 0x14 + 0x23 2 0x44 0x19 + 0x23 2 0x45 0x5A + 0x23 2 0x4B 0x04 + 0x23 2 0x55 0x02 /* power voltage */ + 0x23 2 0x56 0x01 + 0x23 2 0x57 0x69 + 0x23 2 0x58 0x0A + 0x23 2 0x59 0x0A + 0x23 2 0x5A 0x2E /* VGH = 16.2V */ + 0x23 2 0x5B 0x19 /* VGL = -12V */ + 0x23 2 0x5C 0x15 + 0x23 2 0x5D 0x77 /* Gamma */ + 0x23 2 0x5E 0x56 + 0x23 2 0x5F 0x45 + 0x23 2 0x60 0x38 + 0x23 2 0x61 0x35 + 0x23 2 0x62 0x27 + 0x23 2 0x63 0x2D + 0x23 2 0x64 0x18 + 0x23 2 0x65 0x33 + 0x23 2 0x66 0x34 + 0x23 2 0x67 0x35 + 0x23 2 0x68 0x56 + 0x23 2 0x69 0x45 + 0x23 2 0x6A 0x4F + 0x23 2 0x6B 0x42 + 0x23 2 0x6C 0x40 + 0x23 2 0x6D 0x34 + 0x23 2 0x6E 0x25 + 0x23 2 0x6F 0x02 + 0x23 2 0x70 0x77 + 0x23 2 0x71 0x56 + 0x23 2 0x72 0x45 + 0x23 2 0x73 0x38 + 0x23 2 0x74 0x35 + 0x23 2 0x75 0x27 + 0x23 2 0x76 0x2D + 0x23 2 0x77 0x18 + 0x23 2 0x78 0x33 + 0x23 2 0x79 0x34 + 0x23 2 0x7A 0x35 + 0x23 2 0x7B 0x56 + 0x23 2 0x7C 0x45 + 0x23 2 0x7D 0x4F + 0x23 2 0x7E 0x42 + 0x23 2 0x7F 0x40 + 0x23 2 0x80 0x34 + 0x23 2 0x81 0x25 + 0x23 2 0x82 0x02 + 0x23 2 0xE0 0x02 /* Page2 */ + 0x23 2 0x00 0x53 + /* GIP_L Pin mapping RESET_EVEN */ + 0x23 2 0x01 0x55 /* VSSG_EVEN */ + 0x23 2 0x02 0x55 /* VSSA_EVEN */ + 0x23 2 0x03 0x51 /* STV2_EVEN */ + 0x23 2 0x04 0x77 /* VDD2_EVEN */ + 0x23 2 0x05 0x57 /* VDD1_EVEN */ + 0x23 2 0x06 0x1F + 0x23 2 0x07 0x4F /* CK12 */ + 0x23 2 0x08 0x4D /* CK10 */ + 0x23 2 0x09 0x1F + 0x23 2 0x0A 0x4B /* CK8 */ + 0x23 2 0x0B 0x49 /* CK6 */ + 0x23 2 0x0C 0x1F + 0x23 2 0x0D 0x47 /* CK4 */ + 0x23 2 0x0E 0x45 /* CK2 */ + 0x23 2 0x0F 0x41 /* STV1_EVEN */ + 0x23 2 0x10 0x1F + 0x23 2 0x11 0x1F + 0x23 2 0x12 0x1F + 0x23 2 0x13 0x55 /* VGG */ + 0x23 2 0x14 0x1F + 0x23 2 0x15 0x1F + 0x23 2 0x16 0x52 + /* GIP_R Pin mapping RESET_ODD */ + 0x23 2 0x17 0x55 /* VSSG_ODD */ + 0x23 2 0x18 0x55 /* VSSA_ODD */ + 0x23 2 0x19 0x50 /* STV2_ODD */ + 0x23 2 0x1A 0x77 /* VDD2_ODD */ + 0x23 2 0x1B 0x57 /* VDD1_ODD */ + 0x23 2 0x1C 0x1F + 0x23 2 0x1D 0x4E /* CK11 */ + 0x23 2 0x1E 0x4C /* CK9 */ + 0x23 2 0x1F 0x1F + 0x23 2 0x20 0x4A /* CK7 */ + 0x23 2 0x21 0x48 /* CK5 */ + 0x23 2 0x22 0x1F + 0x23 2 0x23 0x46 /* CK3 */ + 0x23 2 0x24 0x44 /* CK1 */ + 0x23 2 0x25 0x40 /* STV1_ODD */ + 0x23 2 0x26 0x1F + 0x23 2 0x27 0x1F + 0x23 2 0x28 0x1F + 0x23 2 0x29 0x1F + 0x23 2 0x2A 0x1F + 0x23 2 0x2B 0x55 /* VGG */ + 0x23 2 0x2C 0x12 /* GIP_L_GS Pin mapping */ + 0x23 2 0x2D 0x15 + 0x23 2 0x2E 0x15 + 0x23 2 0x2F 0x00 + 0x23 2 0x30 0x37 + 0x23 2 0x31 0x17 + 0x23 2 0x32 0x1F + 0x23 2 0x33 0x08 + 0x23 2 0x34 0x0A + 0x23 2 0x35 0x1F + 0x23 2 0x36 0x0C + 0x23 2 0x37 0x0E + 0x23 2 0x38 0x1F + 0x23 2 0x39 0x04 + 0x23 2 0x3A 0x06 + 0x23 2 0x3B 0x10 + 0x23 2 0x3C 0x1F + 0x23 2 0x3D 0x1F + 0x23 2 0x3E 0x1F + 0x23 2 0x3F 0x15 + 0x23 2 0x40 0x1F + 0x23 2 0x41 0x1F + 0x23 2 0x42 0x13 /* GIP_R_GS Pin mapping */ + 0x23 2 0x43 0x15 + 0x23 2 0x44 0x15 + 0x23 2 0x45 0x01 + 0x23 2 0x46 0x37 + 0x23 2 0x47 0x17 + 0x23 2 0x48 0x1F + 0x23 2 0x49 0x09 + 0x23 2 0x4A 0x0B + 0x23 2 0x4B 0x1F + 0x23 2 0x4C 0x0D + 0x23 2 0x4D 0x0F + 0x23 2 0x4E 0x1F + 0x23 2 0x4F 0x05 + 0x23 2 0x50 0x07 + 0x23 2 0x51 0x11 + 0x23 2 0x52 0x1F + 0x23 2 0x53 0x1F + 0x23 2 0x54 0x1F + 0x23 2 0x55 0x1F + 0x23 2 0x56 0x1F + 0x23 2 0x57 0x15 + 0x23 2 0x58 0x40 /* GIP Timing */ + 0x23 2 0x59 0x00 + 0x23 2 0x5A 0x00 + 0x23 2 0x5B 0x10 + 0x23 2 0x5C 0x14 + 0x23 2 0x5D 0x40 + 0x23 2 0x5E 0x01 + 0x23 2 0x5F 0x02 + 0x23 2 0x60 0x40 + 0x23 2 0x61 0x03 + 0x23 2 0x62 0x04 + 0x23 2 0x63 0x7A + 0x23 2 0x64 0x7A + 0x23 2 0x65 0x74 + 0x23 2 0x66 0x16 + 0x23 2 0x67 0xB4 + 0x23 2 0x68 0x16 + 0x23 2 0x69 0x7A + 0x23 2 0x6A 0x7A + 0x23 2 0x6B 0x0C + 0x23 2 0x6C 0x00 + 0x23 2 0x6D 0x04 + 0x23 2 0x6E 0x04 + 0x23 2 0x6F 0x88 + 0x23 2 0x70 0x00 + 0x23 2 0x71 0x00 + 0x23 2 0x72 0x06 + 0x23 2 0x73 0x7B + 0x23 2 0x74 0x00 + 0x23 2 0x75 0xBC + 0x23 2 0x76 0x00 + 0x23 2 0x77 0x04 + 0x23 2 0x78 0x2C + 0x23 2 0x79 0x00 + 0x23 2 0x7A 0x00 + 0x23 2 0x7B 0x00 + 0x23 2 0x7C 0x00 + 0x23 2 0x7D 0x03 + 0x23 2 0x7E 0x7B + 0x23 2 0xE0 0x04 /* Page4 */ + 0x23 2 0x09 0x11 /* Set RGBCYC2 */ + 0x23 2 0x0E 0x48 + 0x23 2 0x2B 0x2B /* ESD Protect */ + 0x23 2 0x2E 0x44 + 0x23 2 0xE0 0x00 /* Page0 */ + 0x23 2 0xE6 0x02 /* Watch dog */ + 0x23 2 0xE7 0x0C + 0x05 1 0x11 /* sleep out */ + 0xfd 1 120 + 0x05 1 0x29 /* display on */ + 0x05 1 0x35 + 0xfd 1 20 /* delay(ms) */ + 0xFF 0>; /*ending*/ + init_off = < + 0x05 1 0x28 /* display off */ + 0xfd 1 10 /* delay 10ms */ + 0x05 1 0x10 /* sleep in */ + 0xfd 1 150 /* delay 150ms */ + 0xff 0>; /*ending*/ + }; + }; + + backlight{ + compatible = "amlogic, backlight-sm1"; + status = "okay"; + key_valid = <0>; + pinctrl-names = "pwm_on","pwm_off"; + pinctrl-0 = <&pwm_f_pins2>; + pinctrl-1 = <&bl_pwm_off_pins>; + pinctrl_version = <2>; /* for uboot */ + bl_pwm_config = <&bl_pwm_conf>; + bl-gpios = <&gpio GPIOH_4 GPIO_ACTIVE_HIGH + &gpio GPIOH_5 GPIO_ACTIVE_HIGH>; + bl_gpio_names = "GPIOH_4","GPIOH_5"; + + /* pwm port: PWM_A, PWM_B, PWM_C, PWM_D, PWM_E, PWM_F, PWM_VS*/ + /* power index:(point gpios_index, 0xff=invalid) + * power value:(0=output low, 1=output high, 2=input) + * power delay:(unit in ms) + */ + + backlight_0{ + index = <0>; + bl_name = "backlight_pwm"; + bl_level_default_uboot_kernel = <100 100>; + bl_level_attr = <255 10 /*max, min*/ + 128 128>; /*mid, mid_mapping*/ + bl_ctrl_method = <1>; /* 1=pwm, 2=pwm_combo, 4=extern */ + bl_power_attr = <0 /*en_gpio_index*/ + 1 0 /*on_value, off_value*/ + 200 200>; /*on_delay(ms), off_delay(ms)*/ + bl_pwm_port = "PWM_F"; + bl_pwm_attr = <0 /*pwm_method*/ + 180 /*pwm_freq(pwm:Hz, pwm_vs:multiple of vs)*/ + 100 25>; /*duty_max(%), duty_min(%)*/ + bl_pwm_power = <1 1 /*pwm_gpio_index, pwm_gpio_off*/ + 10 10>; /*pwm_on_delay(ms), pwm_off_delay(ms)*/ + bl_pwm_en_sequence_reverse = <0>; /* 1 for reverse */ + }; + backlight_1{ + index = <1>; + bl_name = "bl_extern"; + bl_level_default_uboot_kernel = <100 100>; + bl_level_attr = <255 10 /*max, min*/ + 128 128>; /*mid, mid_mapping*/ + bl_ctrl_method = <4>; /*1=pwm, 2=pwm_combo, 4=extern*/ + bl_power_attr = <1 /*en_gpio_index*/ + 1 0 /*on_value, off_value*/ + 200 200>; /*on_delay(ms), off_delay(ms)*/ + bl_extern_index = <0>; + }; + }; + bl_pwm_conf:bl_pwm_conf{ + pwm_channel_0 { + pwm_port_index = <5>; + pwms = <&pwm_ef MESON_PWM_1 30040 0>; + }; + }; + + bl_extern{ + compatible = "amlogic, bl_extern"; + status = "disabled"; + i2c_bus = "i2c_bus_3"; + + extern_0{ + index = <0>; + extern_name = "i2c_lp8556"; + type = <0>; /*0=i2c, 1=spi, 2=mipi*/ + i2c_address = <0x2c>; /*7bit i2c address*/ + dim_max_min = <255 10>; + }; + + extern_1{ + index = <1>; + extern_name = "mipi_lt070me05"; + type = <2>; /*0=i2c, 1=spi, 2=mipi*/ + dim_max_min = <255 10>; + }; + }; +};/* end of panel */ + diff --git a/arch/arm64/boot/dts/amlogic/mesontl1_t309-panel.dtsi b/arch/arm64/boot/dts/amlogic/mesontl1_t309-panel.dtsi new file mode 100644 index 000000000000..7831799e1bda --- /dev/null +++ b/arch/arm64/boot/dts/amlogic/mesontl1_t309-panel.dtsi @@ -0,0 +1,1059 @@ +/* + * arch/arm64/boot/dts/amlogic/mesontl1_t309-panel.dtsi + * + * Copyright (C) 2018 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. + * + */ + +/ { + lcd { + compatible = "amlogic, lcd-tl1"; + status = "okay"; + mode = "tv"; + fr_auto_policy = <1>; /* 0=disable, 1=60/50hz, 2=60/50/48hz */ + key_valid = <1>; + clocks = <&clkc CLKID_VCLK2_ENCL + &clkc CLKID_VCLK2_VENCL + &clkc CLKID_TCON + &clkc CLKID_FCLK_DIV5 + &clkc CLKID_TCON_PLL_COMP>; + clock-names = "encl_top_gate", + "encl_int_gate", + "tcon_gate", + "fclk_div5", + "clk_tcon"; + reg = <0x0 0xff660000 0x0 0x8100 + 0x0 0xff634400 0x0 0x300>; + interrupts = <0 3 1 + 0 78 1 + 0 88 1>; + interrupt-names = "vsync","vbyone","tcon"; + pinctrl-names = "vbyone","vbyone_off","tcon","tcon_off"; + pinctrl-0 = <&lcd_vbyone_pins>; + pinctrl-1 = <&lcd_vbyone_off_pins>; + pinctrl-2 = <&lcd_tcon_pins>; + pinctrl-3 = <&lcd_tcon_off_pins>; + pinctrl_version = <2>; /* for uboot */ + memory-region = <&lcd_tcon_reserved>; + + /* power type:(0=cpu_gpio, 2=signal, 3=extern, 0xff=ending) */ + /* power index:(gpios_index, or extern_index, 0xff=invalid) */ + /* power value:(0=output low, 1=output high, 2=input) */ + /* power delay:(unit in ms) */ + lcd_cpu-gpios = <&gpio_ao GPIOAO_4 GPIO_ACTIVE_HIGH + &gpio GPIOH_2 GPIO_ACTIVE_HIGH + &gpio GPIOH_3 GPIO_ACTIVE_HIGH + &gpio GPIOH_8 GPIO_ACTIVE_HIGH + &gpio GPIOH_14 GPIO_ACTIVE_HIGH>; + lcd_cpu_gpio_names = "GPIOAO_4","GPIOH_2","GPIOH_3", + "GPIOH_8","GPIOH_14"; + + lvds_0{ + model_name = "1080p-vfreq"; + interface = "lvds"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 1920 1080 /*h_active, v_active*/ + 2200 1125 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 2060 2650 /*h_period_min,max*/ + 1100 1480 /*v_period_min,max*/ + 120000000 160000000>; /*pclk_min,max*/ + lcd_timing = < + 44 148 0 /*hs_width, hs_bp, hs_pol*/ + 5 30 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 15 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + lvds_attr = < + 1 /*lvds_repack*/ + 1 /*dual_port*/ + 0 /*pn_swap*/ + 0 /*port_swap*/ + 0>; /*lane_reverse*/ + phy_attr=<0xf 0>; /*vswing_level, preem_level*/ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 0 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0>; + }; + + lvds_1{ + model_name = "1080p-hfreq_hdmi"; + interface = "lvds"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 1920 1080 /*h_active, v_active*/ + 2200 1125 /*h_period, v_period*/ + 8 /*lcd_bits*/ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 2080 2720 /*h_period min, max*/ + 1100 1380 /*v_period min, max*/ + 133940000 156000000>; /*pclk_min, max*/ + lcd_timing = < + 44 148 0 /*hs_width, hs_bp, hs_pol*/ + 5 30 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 4 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 0 /*clk_ss_level */ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + lvds_attr = < + 1 /*lvds_repack*/ + 1 /*dual_port*/ + 0 /*pn_swap*/ + 0 /*port_swap*/ + 0>; /*lane_reverse*/ + phy_attr=<0xf 0>; /*vswing_level, preem_level*/ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 0 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0>; + }; + lvds_2{ + model_name = "768p-vfreq"; + interface = "lvds"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 1366 768 /*h_active, v_active*/ + 1560 806 /*h_period, v_period*/ + 8 /*lcd_bits*/ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 1460 2000 /*h_period_min, max */ + 784 1015 /*v_period_min, max */ + 50000000 85000000>; /*pclk_min, max*/ + lcd_timing = < + 56 64 0 /*hs_width, hs_bp, hs_pol*/ + 3 28 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 15 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + lvds_attr = < + 1 /*lvds_repack*/ + 0 /*dual_port*/ + 0 /*pn_swap*/ + 0 /*port_swap*/ + 0>; /*lane_reverse*/ + phy_attr=<0xf 0>; /*vswing_level, preem_level*/ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 0 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0>; + }; + vbyone_0{ + model_name = "public_2region"; + interface = "vbyone"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 10 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 4800 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 33 477 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + vbyone_attr = < + 8 /*lane_count*/ + 2 /*region_num*/ + 4 /*byte_mode*/ + 4>; /*color_fmt*/ + vbyone_intr_enable = < + 1 /*vbyone_intr_enable */ + 3>; /*vbyone_vsync_intr_enable*/ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = <0 0 1 50 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = <2 0 0 10 /*signal disable*/ + 0 0 0 200 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <2>; + }; + vbyone_1{ + model_name = "public_1region"; + interface = "vbyone"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 10 /*lcd_bits*/ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 4800 /*h_period_min, max*/ + 2200 2790 /*v_period_min, max*/ + 552000000 632000000>; /*pclk_min,max*/ + lcd_timing = < + 33 477 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + vbyone_attr = < + 8 /*lane_count*/ + 1 /*region_num*/ + 4 /*byte_mode*/ + 4>; /*color_fmt*/ + vbyone_intr_enable = < + 1 /*vbyone_intr_enable*/ + 3>; /*vbyone_vsync_intr_enable*/ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 50 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 200 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <2>; + }; + vbyone_2{ + model_name = "public_2region_hdmi"; + interface = "vbyone"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 10 /*lcd_bits*/ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 4800 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*v_period_min, max*/ + lcd_timing = < + 33 477 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 4 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 0 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + vbyone_attr = < + 8 /*lane_count*/ + 2 /*region_num*/ + 4 /*byte_mode*/ + 4>; /*color_fmt*/ + vbyone_intr_enable = < + 1 /*vbyone_intr_enable*/ + 3>; /*vbyone_vsync_intr_enable*/ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 50 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 200 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <2>; + }; + vbyone_3{ + model_name = "BOE_HV550QU2"; + interface = "vbyone"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 10 /*lcd_bits*/ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 4800 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 560000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 33 477 1 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + vbyone_attr = < + 8 /*lane_count*/ + 2 /*region_num*/ + 4 /*byte_mode*/ + 4>; /*color_fmt*/ + vbyone_intr_enable = < + 1 /*vbyone_intr_enable*/ + 3>; /*vbyone_vsync_intr_enable*/ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 0 3 0 10 /*3d_disable*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 3 2 0 /*3d_disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <2>; + }; + vbyone_4{ + model_name = "BOE_HV550QU2_1region"; + interface = "vbyone"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 10 /*lcd_bits*/ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 4800 /*h_period_min,max*/ + 2200 2760 /*v_period_min,max*/ + 560000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 33 477 1 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + vbyone_attr = < + 8 /*lane_count*/ + 1 /*region_num*/ + 4 /*byte_mode*/ + 4>; /*color_fmt*/ + vbyone_intr_enable = < + 1 /*vbyone_intr_enable*/ + 3>; /*vbyone_vsync_intr_enable*/ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 0 3 0 10 /*3d_disable*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 3 2 0 /*3d_disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <2>; + }; + p2p_0{ + model_name = "p2p_ceds"; + interface = "p2p"; /*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 5000 2250 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 5100 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 16 29 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + p2p_attr = < + 0 /* teyp: 0=ceds, 1=cmpi, 2=isp, 3=epi, + * 10=chpi, 11=cspi, 12=usit + */ + 12 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 3 2 0 200 /* extern init voltage */ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + p2p_1{ + model_name = "p2p_ceds"; + interface = "p2p"; /*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 5000 2250 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 5100 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 16 29 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + p2p_attr = < + 0 /* teyp: 0=ceds, 1=cmpi, 2=isp, 3=epi, + * 10=chpi, 11=cspi, 12=usit + */ + 6 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + p2p_2{ + model_name = "p2p_chpi"; + interface = "p2p"; /*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 5100 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 16 29 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + p2p_attr = < + 10 /* teyp: 0=ceds, 1=cmpi, 2=isp, 3=epi, + * 10=chpi, 11=cspi, 12=usit + */ + 6 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + p2p_3{ + model_name = "p2p_chpi"; + interface = "p2p"; /*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 5100 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 16 29 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + p2p_attr = < + 10 /* teyp: 0=ceds, 1=cmpi, 2=isp, 3=epi, + * 10=chpi, 11=cspi, 12=usit + */ + 12 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + mlvds_0{ + model_name = "mlvds_1080p"; + interface = "minilvds"; /*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 1920 1080 /*h_active, v_active*/ + 2200 1125 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 2080 2720 /*h_period_min, max*/ + 2200 1125 /*v_period_min, max*/ + 133940000 156000000>; /*pclk_min, max*/ + lcd_timing = < + 44 148 0 /*hs_width, hs_bp, hs_pol*/ + 5 30 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + minilvds_attr = < + 6 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0x660 /* clk_phase */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 0>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + mlvds_1{ + model_name = "mlvds_768p"; + interface = "minilvds";/*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 1366 768 /*h_active, v_active*/ + 1560 806 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 1460 2000 /*h_period_min, max*/ + 784 1015 /*v_period_min, max*/ + 50000000 85000000>; /*pclk_min, max*/ + lcd_timing = < + 56 64 0 /*hs_width, hs_bp, hs_pol*/ + 3 28 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + minilvds_attr = < + 6 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0x660 /* clk_phase */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 0>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + }; + + lcd_extern{ + compatible = "amlogic, lcd_extern"; + status = "okay"; + key_valid = <1>; + i2c_bus = "i2c_bus_1"; + + extern_0{ + index = <0>; + extern_name = "ext_default"; + status = "disabled"; + type = <0>; /*0=i2c, 1=spi, 2=mipi*/ + i2c_address = <0x1c>; /*7bit i2c_addr*/ + i2c_address2 = <0xff>; + cmd_size = <0xff>; /*dynamic cmd_size*/ + + /* init on/off: + * fixed cmd_size: (type, value...); + * cmd_size include all data. + * dynamic cmd_size: (type, cmd_size, value...); + * cmd_size include value. + */ + /* type: 0x00=cmd with delay(bit[3:0]=1 for address2), + * 0xc0=cmd(bit[3:0]=1 for address2), + * 0xf0=gpio, + * 0xfd=delay, + * 0xff=ending + */ + /* value: i2c or spi cmd, or gpio index & level */ + /* delay: unit ms */ + init_on = < + 0xc0 7 0x20 0x01 0x02 0x00 0x40 0xFF 0x00 + 0xc0 7 0x80 0x02 0x00 0x40 0x62 0x51 0x73 + 0xc0 7 0x61 0x06 0x00 0x00 0x00 0x00 0x00 + 0xc0 7 0xC1 0x05 0x0F 0x00 0x08 0x70 0x00 + 0xc0 7 0x13 0x01 0x00 0x00 0x00 0x00 0x00 + 0xc0 7 0x3D 0x02 0x01 0x00 0x00 0x00 0x00 + 0xc0 7 0xED 0x0D 0x01 0x00 0x00 0x00 0x00 + 0xc0 7 0x23 0x02 0x00 0x00 0x00 0x00 0x00 + 0xfd 1 10 /* delay 10ms */ + 0xff 0>; /*ending*/ + init_off = <0xff 0>; /*ending*/ + }; + extern_1{ + index = <1>; + extern_name = "i2c_T5800Q"; + status = "disabled"; + type = <0>; /* 0=i2c, 1=spi, 2=mipi */ + i2c_address = <0x1c>; /* 7bit i2c address */ + }; + extern_2{ + index = <2>; + extern_name = "i2c_ANX6862_7911"; + status = "okay"; + type = <0>; /* 0=i2c, 1=spi, 2=mipi */ + i2c_address = <0x20>; /* 7bit i2c address */ + i2c_address2 = <0x74>; /* 7bit i2c address */ + cmd_size = <0xff>; + + init_on = < + 0xc0 2 0x01 0x2b + 0xc0 2 0x02 0x05 + 0xc0 2 0x03 0x00 + 0xc0 2 0x04 0x00 + 0xc0 2 0x05 0x0c + 0xc0 2 0x06 0x04 + 0xc0 2 0x07 0x21 + 0xc0 2 0x08 0x0f + 0xc0 2 0x09 0x04 + 0xc0 2 0x0a 0x00 + 0xc0 2 0x0b 0x04 + 0xc0 2 0xff 0x00 + 0xfd 1 100 /* delay 100ms */ + + 0xc1 2 0x01 0xca + 0xc1 2 0x02 0x3b + 0xc1 2 0x03 0x33 + 0xc1 2 0x04 0x05 + 0xc1 2 0x05 0x2c + 0xc1 2 0x06 0xf2 + 0xc1 2 0x07 0x9c + 0xc1 2 0x08 0x1b + 0xc1 2 0x09 0x82 + 0xc1 2 0x0a 0x3d + 0xc1 2 0x0b 0x20 + 0xc1 2 0x0c 0x11 + 0xc1 2 0x0d 0xc4 + 0xc1 2 0x0e 0x1a + 0xc1 2 0x0f 0x31 + 0xc1 2 0x10 0x4c + 0xc1 2 0x11 0x12 + 0xc1 2 0x12 0x90 + 0xc1 2 0x13 0xf7 + 0xc1 2 0x14 0x0c + 0xc1 2 0x15 0x20 + 0xc1 2 0x16 0x13 + 0xff 0>; /*ending*/ + init_off = <0xff 0>; /*ending*/ + }; + }; + + backlight{ + compatible = "amlogic, backlight-tl1"; + status = "okay"; + key_valid = <1>; + pinctrl-names = "pwm_on","pwm_vs_on", + "pwm_combo_0_1_on", + "pwm_combo_0_vs_1_on", + "pwm_combo_0_1_vs_on", + "pwm_off", + "pwm_combo_off"; + pinctrl-0 = <&pwm_c_pins3>; + pinctrl-1 = <&bl_pwm_vs_on_pins>; + pinctrl-2 = <&pwm_c_pins3 &pwm_d_pins2>; + pinctrl-3 = <&bl_pwm_combo_0_vs_on_pins &pwm_d_pins2>; + pinctrl-4 = <&pwm_c_pins3 &bl_pwm_combo_1_vs_on_pins>; + pinctrl-5 = <&bl_pwm_off_pins>; + pinctrl-6 = <&bl_pwm_combo_off_pins>; + pinctrl_version = <2>; /* for uboot */ + interrupts = <0 3 1>; + interrupt-names = "ldim_vsync"; + bl_pwm_config = <&bl_pwm_conf>; + + /* pwm port: PWM_A, PWM_B, PWM_C, PWM_D, PWM_E, PWM_F, PWM_VS*/ + /* power index:(point gpios_index, 0xff=invalid) */ + /* power value:(0=output low, 1=output high, 2=input) */ + /* power delay:(unit in ms) */ + bl-gpios = <&gpio_ao GPIOAO_11 GPIO_ACTIVE_HIGH + &gpio GPIOZ_5 GPIO_ACTIVE_HIGH + &gpio GPIOZ_6 GPIO_ACTIVE_HIGH>; + bl_gpio_names = "GPIOAO_11","GPIOZ_5","GPIOZ_6"; + + backlight_0{ + index = <0>; + bl_name = "backlight_pwm"; + bl_level_default_uboot_kernel = <100 100>; + bl_level_attr = <255 10 /*max, min*/ + 128 128>; /*mid, mid_mapping*/ + bl_ctrl_method = <1>; /*1=pwm,2=pwm_combo,3=ldim*/ + bl_power_attr = <0 /*en_gpio_index*/ + 1 0 /*on_value, off_value*/ + 200 200>; /*on_delay(ms), off_delay(ms)*/ + bl_pwm_port = "PWM_C"; + bl_pwm_attr = <1 /*pwm_method(0=negative, 1=positvie)*/ + 180 /*pwm_freq(pwm:Hz, pwm_vs:multiple of vs)*/ + 100 25>; /*duty_max(%), duty_min(%)*/ + bl_pwm_power = <1 0 /*pwm_gpio_index, pwm_gpio_off*/ + 10 10>; /*pwm_on_delay(ms), pwm_off_delay(ms)*/ + bl_pwm_en_sequence_reverse = <0>; /* 1 for reverse */ + }; + backlight_1{ + index = <1>; + bl_name = "backlight_pwm_vs"; + bl_level_default_uboot_kernel = <100 100>; + bl_level_attr = <255 10 /*max, min*/ + 128 128>; /*mid, mid_mapping*/ + bl_ctrl_method = <1>; /*1=pwm,2=pwm_combo,3=ldim*/ + bl_power_attr = <0 /*en_gpio_index*/ + 1 0 /*on_value, off_value*/ + 200 200>; /* on_delay(ms), off_delay(ms)*/ + bl_pwm_port = "PWM_VS"; + bl_pwm_attr = <1 /*pwm_method(0=negative, 1=positvie)*/ + 2 /*pwm_freq(pwm:Hz, pwm_vs:multiple of vs)*/ + 100 25>; /*duty_max(%), duty_min(%)*/ + bl_pwm_power = <1 0 /*pwm_gpio_index, pwm_gpio_off*/ + 10 10>; /*pwm_on_delay(ms), pwm_off_delay(ms)*/ + bl_pwm_en_sequence_reverse = <0>; /* 1 for reverse */ + }; + backlight_2{ + index = <2>; + bl_name = "backlight_pwm_combo"; + bl_level_default_uboot_kernel = <31 100>; + bl_level_attr = <255 10 /*max, min*/ + 128 128>; /*mid, mid_mapping*/ + bl_ctrl_method = <2>; /*1=pwm,2=pwm_combo,3=ldim*/ + bl_power_attr = <0 /*en_gpio_index*/ + 1 0 /*on_value, off_value*/ + 410 110>; /*on_delay(ms), off_delay(ms)*/ + bl_pwm_combo_level_mapping = <255 10 /*pwm_0 range*/ + 0 0>; /*pwm_1 range*/ + bl_pwm_combo_port = "PWM_C","PWM_D"; + bl_pwm_combo_attr = <1 /*pwm0 method*/ + 180 /*pwm0 freq(pwm:Hz, pwm_vs:multiple of vs)*/ + 100 25 /*pwm0 duty_max(%), duty_min(%)*/ + 1 /*pwm1 method*/ + 18000 /*pwm1 freq(pwm:Hz, pwm_vs:multi of vs)*/ + 80 80>; /*pwm1 duty_max(%), duty_min(%)*/ + bl_pwm_combo_power = <1 0 /*pwm0 gpio_index, gpio_off*/ + 2 0 /*pwm1 gpio_index, gpio_off*/ + 10 10>; /*pwm_on_delay(ms), pwm_off_delay(ms)*/ + }; + backlight_3{ + index = <3>; + bl_name = "pwm_combo_ldim_test"; + bl_level_default_uboot_kernel = <31 100>; + bl_level_attr = <255 10 /*max, min*/ + 128 128>; /*mid, mid_mapping*/ + bl_ctrl_method = <2>; /*1=pwm,2=pwm_combo,3=ldim*/ + bl_power_attr = <0 /*en_gpio_index*/ + 1 0 /*on_value, off_value*/ + 410 110>; /*on_delay(ms), off_delay(ms)*/ + bl_pwm_combo_level_mapping = <255 10 /*pwm_0 range*/ + 0 0>; /*pwm_1 range*/ + bl_pwm_combo_port = "PWM_C","PWM_D"; + bl_pwm_combo_attr = <1 /*pwm0 method*/ + 180 /*pwm0 freq(pwm:Hz, pwm_vs:multiple of vs)*/ + 100 25 /*pwm0 duty_max(%), duty_min(%)*/ + 1 /*pwm1 method*/ + 18000 /*pwm1 freq(pwm:Hz, pwm_vs:multi of vs)*/ + 80 80>; /*pwm1 duty_max(%), duty_min(%)*/ + bl_pwm_combo_power = <1 0 /*pwm0 gpio_index, gpio_off*/ + 2 0 /*pwm1 gpio_index, gpio_off*/ + 10 10>; /*pwm_on_delay(ms), pwm_off_delay(ms)*/ + bl_ldim_region_row_col = <2 10>; + }; + backlight_4{ + index = <4>; + bl_name = "ldim_global"; + bl_level_default_uboot_kernel = <100 100>; + bl_level_attr = <255 10 /*max, min*/ + 128 128>; /*mid, mid_mapping*/ + bl_ctrl_method = <3>; /*1=pwm,2=pwm_combo,3=ldim*/ + bl_power_attr = <0xff /*en_gpio_index*/ + 1 0 /*on_value, off_value*/ + 200 200>; /*on_delay(ms), off_delay(ms)*/ + bl_ldim_region_row_col = <1 1>; + bl_ldim_mode = <1>; /*0=left/right side + *1=top/bottom side + *2=direct + */ + ldim_dev_index = <1>; + }; + backlight_5{ + index = <5>; + bl_name = "ldim_iw7027"; + bl_level_default_uboot_kernel = <100 100>; + bl_level_attr = <255 10 /*max, min*/ + 128 128>; /*mid, mid_mapping*/ + bl_ctrl_method = <3>; /*1=pwm,2=pwm_combo,3=ldim*/ + bl_power_attr = <0 /*en_gpio_index*/ + 1 0 /*on_value, off_value*/ + 200 200>; /*on_delay(ms), off_delay(ms)*/ + bl_ldim_region_row_col = <1 10>; + bl_ldim_mode = <1>; /*0=left/right side + *1=top/bottom side + *2=direct + */ + ldim_dev_index = <2>; + }; + }; + + bl_pwm_conf:bl_pwm_conf{ + pwm_channel_0 { + pwm_port_index = <2>; + pwms = <&pwm_cd MESON_PWM_0 30040 0>; + }; + pwm_channel_1 { + pwm_port_index = <3>; + pwms = <&pwm_cd MESON_PWM_1 30040 0>; + }; + }; + + local_dimming_device { + compatible = "amlogic, ldim_dev"; + status = "okay"; + pinctrl-names = "ldim_pwm", + "ldim_pwm_vs", + "ldim_pwm_combo", + "ldim_pwm_vs_combo", + "ldim_pwm_off", + "ldim_pwm_combo_off"; + pinctrl-0 = <&pwm_c_pins3>; + pinctrl-1 = <&bl_pwm_vs_on_pins>; + pinctrl-2 = <&pwm_c_pins3 &pwm_d_pins2>; + pinctrl-3 = <&bl_pwm_vs_on_pins &pwm_d_pins2>; + pinctrl-4 = <&bl_pwm_off_pins>; + pinctrl-5 = <&bl_pwm_combo_off_pins>; + pinctrl_version = <1>; /* for uboot */ + ldim_pwm_config = <&bl_pwm_conf>; + + /* pwm port: PWM_A, PWM_B, PWM_C, PWM_D, PWM_E, PWM_F, PWM_VS*/ + ldim_dev-gpios = <&gpio_ao GPIOAO_11 GPIO_ACTIVE_HIGH + &gpio GPIOZ_5 GPIO_ACTIVE_HIGH + &gpio GPIOZ_6 GPIO_ACTIVE_HIGH>; + ldim_dev_gpio_names = "GPIOAO_11","GPIOZ_5","GPIOZ_6"; + + ldim_dev_0 { + index = <0>; + type = <0>; /*0=normal, 1=spi, 2=i2c*/ + ldim_dev_name = "ob3350"; + ldim_pwm_port = "PWM_C"; + ldim_pwm_attr = <0 /* pol */ + 200 /*freq(pwm:Hz, pwm_vs:multiple of vs)*/ + 50>;/*default duty(%)*/ + en_gpio_on_off = <0 /*ldim_dev-gpios index*/ + 1 0>; /*on_level, off_level*/ + dim_max_min = <100 20>; /*dim_max, dim_min*/ + }; + ldim_dev_1 { + index = <1>; + type = <0>; /*0=normal, 1=spi, 2=i2c*/ + ldim_dev_name = "global"; + ldim_pwm_port = "PWM_C"; + ldim_pwm_attr = <1 /* pol */ + 180 /*freq(pwm:Hz, pwm_vs:multiple of vs)*/ + 50>;/*default duty(%)*/ + analog_pwm_port = "PWM_D"; + analog_pwm_attr = <1 /*pol(0=negative, 1=positvie)*/ + 18000 /*freq(pwm:Hz)*/ + 100 25 /*duty_max(%), duty_min(%)*/ + 80>; /*default duty(%)*/ + en_gpio_on_off = <0 /*ldim_dev-gpios index*/ + 1 0>; /*on_level, off_level*/ + dim_max_min = <100 20>; /*dim_max, dim_min*/ + }; + + ldim_dev_2 { + index = <2>; + type = <1>; /* 0=normal,1=spi,2=i2c */ + ldim_dev_name = "iw7027"; + ldim_pwm_port = "PWM_VS"; + ldim_pwm_attr = <1 /* pol */ + 2 /*freq(pwm:Hz, pwm_vs:multiple of vs)*/ + 50>;/*default duty(%)*/ + spi_bus_num = <0>; + spi_chip_select = <0>; + spi_max_frequency = <1000000>; /* unit: hz */ + spi_mode = <0>; /* mode: 0, 1, 2, 3 */ + spi_cs_delay = <10 /* hold_high_delay */ + 100>; /* clk_cs_delay (unit: us) */ + en_gpio_on_off = <0 /* ldim_dev-gpios index */ + 1 /* on_level */ + 0>; /* off_level */ + lamp_err_gpio = <0xff>; + /* ldim_dev-gpios index, 0xff=invalid */ + spi_write_check = <0>; /* 0=disable, 1=enable */ + + dim_max_min = <0xfff 0x7f>; /* dim_max, dim_min */ + ldim_region_mapping = <0 1 2 3 4 5 6 7 8 9>; + + cmd_size = <0xff>; + /* init: (type, data...) */ + /* type: 0x00=cmd with delay, + * 0xc0=cmd, + * 0xfd=delay, + * 0xff=ending + */ + /* data: spi data, fill 0x0 for no use */ + /* delay: unit ms */ + init_on = < + 0xc0 2 0x23 0x03 + 0xc0 2 0x24 0xff + 0xc0 2 0x25 0x00 + 0xc0 2 0x26 0x00 + 0xc0 2 0x27 0x60 + 0xc0 2 0x29 0x00 + 0xc0 2 0x2a 0x00 + 0xc0 2 0x2b 0x00 + 0xc0 2 0x2c 0x73 + 0xc0 2 0x2d 0x37 + 0xc0 2 0x31 0x93 + 0xc0 2 0x32 0x0f + 0xc0 2 0x33 0xff + 0xc0 2 0x34 0xc8 + 0xc0 2 0x35 0xbf + 0xff 0>; + init_off = <0xff 0>; + }; + }; +}; /* end of / */ diff --git a/arch/arm64/boot/dts/amlogic/mesontl1_x301-panel.dtsi b/arch/arm64/boot/dts/amlogic/mesontl1_x301-panel.dtsi new file mode 100644 index 000000000000..31be33cef753 --- /dev/null +++ b/arch/arm64/boot/dts/amlogic/mesontl1_x301-panel.dtsi @@ -0,0 +1,1062 @@ +/* + * arch/arm64/boot/dts/amlogic/mesontl1_x301-panel.dtsi + * + * Copyright (C) 2018 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. + * + */ + +/ { + lcd { + compatible = "amlogic, lcd-tl1"; + status = "okay"; + mode = "tv"; + fr_auto_policy = <1>; /* 0=disable, 1=60/50hz, 2=60/50/48hz */ + key_valid = <1>; + clocks = <&clkc CLKID_VCLK2_ENCL + &clkc CLKID_VCLK2_VENCL + &clkc CLKID_TCON + &clkc CLKID_FCLK_DIV5 + &clkc CLKID_TCON_PLL_COMP>; + clock-names = "encl_top_gate", + "encl_int_gate", + "tcon_gate", + "fclk_div5", + "clk_tcon"; + reg = <0x0 0xff660000 0x0 0x8100 + 0x0 0xff634400 0x0 0x300>; + interrupts = <0 3 1 + 0 78 1 + 0 88 1>; + interrupt-names = "vsync","vbyone","tcon"; + pinctrl-names = "vbyone","vbyone_off","tcon","tcon_off"; + pinctrl-0 = <&lcd_vbyone_pins>; + pinctrl-1 = <&lcd_vbyone_off_pins>; + pinctrl-2 = <&lcd_tcon_pins>; + pinctrl-3 = <&lcd_tcon_off_pins>; + pinctrl_version = <2>; /* for uboot */ + memory-region = <&lcd_tcon_reserved>; + + /* power type:(0=cpu_gpio, 2=signal, 3=extern, 0xff=ending) */ + /* power index:(gpios_index, or extern_index, 0xff=invalid) */ + /* power value:(0=output low, 1=output high, 2=input) */ + /* power delay:(unit in ms) */ + lcd_cpu-gpios = <&gpio_ao GPIOAO_4 GPIO_ACTIVE_HIGH + &gpio GPIOH_2 GPIO_ACTIVE_HIGH + &gpio GPIOH_3 GPIO_ACTIVE_HIGH + &gpio GPIOH_12 GPIO_ACTIVE_HIGH + &gpio GPIOH_8 GPIO_ACTIVE_HIGH + &gpio GPIOH_10 GPIO_ACTIVE_HIGH + &gpio GPIOH_11 GPIO_ACTIVE_HIGH + &gpio GPIOH_14 GPIO_ACTIVE_HIGH>; + lcd_cpu_gpio_names = "GPIOAO_4","GPIOH_2","GPIOH_3","GPIOH_12", + "GPIOH_8","GPIOH_10","GPIOH_11","GPIOH_14"; + + lvds_0{ + model_name = "1080p-vfreq"; + interface = "lvds"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 1920 1080 /*h_active, v_active*/ + 2200 1125 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 2060 2650 /*h_period_min,max*/ + 1100 1480 /*v_period_min,max*/ + 120000000 160000000>; /*pclk_min,max*/ + lcd_timing = < + 44 148 0 /*hs_width, hs_bp, hs_pol*/ + 5 30 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 15 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + lvds_attr = < + 1 /*lvds_repack*/ + 1 /*dual_port*/ + 0 /*pn_swap*/ + 0 /*port_swap*/ + 0>; /*lane_reverse*/ + phy_attr=<0xf 0>; /*vswing_level, preem_level*/ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 0 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0>; + }; + + lvds_1{ + model_name = "1080p-hfreq_hdmi"; + interface = "lvds"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 1920 1080 /*h_active, v_active*/ + 2200 1125 /*h_period, v_period*/ + 8 /*lcd_bits*/ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 2080 2720 /*h_period min, max*/ + 1100 1380 /*v_period min, max*/ + 133940000 156000000>; /*pclk_min, max*/ + lcd_timing = < + 44 148 0 /*hs_width, hs_bp, hs_pol*/ + 5 30 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 4 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 0 /*clk_ss_level */ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + lvds_attr = < + 1 /*lvds_repack*/ + 1 /*dual_port*/ + 0 /*pn_swap*/ + 0 /*port_swap*/ + 0>; /*lane_reverse*/ + phy_attr=<0xf 0>; /*vswing_level, preem_level*/ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 0 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0>; + }; + lvds_2{ + model_name = "768p-vfreq"; + interface = "lvds"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 1366 768 /*h_active, v_active*/ + 1560 806 /*h_period, v_period*/ + 8 /*lcd_bits*/ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 1460 2000 /*h_period_min, max */ + 784 1015 /*v_period_min, max */ + 50000000 85000000>; /*pclk_min, max*/ + lcd_timing = < + 56 64 0 /*hs_width, hs_bp, hs_pol*/ + 3 28 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 15 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + lvds_attr = < + 1 /*lvds_repack*/ + 0 /*dual_port*/ + 0 /*pn_swap*/ + 0 /*port_swap*/ + 0>; /*lane_reverse*/ + phy_attr=<0xf 0>; /*vswing_level, preem_level*/ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 0 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0>; + }; + vbyone_0{ + model_name = "public_2region"; + interface = "vbyone"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 10 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 4800 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 33 477 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + vbyone_attr = < + 8 /*lane_count*/ + 2 /*region_num*/ + 4 /*byte_mode*/ + 4>; /*color_fmt*/ + vbyone_intr_enable = < + 1 /*vbyone_intr_enable */ + 3>; /*vbyone_vsync_intr_enable*/ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = <0 0 1 50 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = <2 0 0 10 /*signal disable*/ + 0 0 0 200 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <2>; + }; + vbyone_1{ + model_name = "public_1region"; + interface = "vbyone"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 10 /*lcd_bits*/ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 4800 /*h_period_min, max*/ + 2200 2790 /*v_period_min, max*/ + 552000000 632000000>; /*pclk_min,max*/ + lcd_timing = < + 33 477 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + vbyone_attr = < + 8 /*lane_count*/ + 1 /*region_num*/ + 4 /*byte_mode*/ + 4>; /*color_fmt*/ + vbyone_intr_enable = < + 1 /*vbyone_intr_enable*/ + 3>; /*vbyone_vsync_intr_enable*/ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 50 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 200 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <2>; + }; + vbyone_2{ + model_name = "public_2region_hdmi"; + interface = "vbyone"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 10 /*lcd_bits*/ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 4800 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*v_period_min, max*/ + lcd_timing = < + 33 477 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 4 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 0 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + vbyone_attr = < + 8 /*lane_count*/ + 2 /*region_num*/ + 4 /*byte_mode*/ + 4>; /*color_fmt*/ + vbyone_intr_enable = < + 1 /*vbyone_intr_enable*/ + 3>; /*vbyone_vsync_intr_enable*/ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 50 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 200 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <2>; + }; + vbyone_3{ + model_name = "BOE_HV550QU2"; + interface = "vbyone"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 10 /*lcd_bits*/ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 4800 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 560000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 33 477 1 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + vbyone_attr = < + 8 /*lane_count*/ + 2 /*region_num*/ + 4 /*byte_mode*/ + 4>; /*color_fmt*/ + vbyone_intr_enable = < + 1 /*vbyone_intr_enable*/ + 3>; /*vbyone_vsync_intr_enable*/ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 0 3 0 10 /*3d_disable*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 3 2 0 /*3d_disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <2>; + }; + vbyone_4{ + model_name = "BOE_HV550QU2_1region"; + interface = "vbyone"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 10 /*lcd_bits*/ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 4800 /*h_period_min,max*/ + 2200 2760 /*v_period_min,max*/ + 560000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 33 477 1 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + vbyone_attr = < + 8 /*lane_count*/ + 1 /*region_num*/ + 4 /*byte_mode*/ + 4>; /*color_fmt*/ + vbyone_intr_enable = < + 1 /*vbyone_intr_enable*/ + 3>; /*vbyone_vsync_intr_enable*/ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 0 3 0 10 /*3d_disable*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 3 2 0 /*3d_disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <2>; + }; + p2p_0{ + model_name = "p2p_ceds"; + interface = "p2p"; /*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 5000 2250 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 5100 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 16 29 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + p2p_attr = < + 0 /* teyp: 0=ceds, 1=cmpi, 2=isp, 3=epi, + * 10=chpi, 11=cspi, 12=usit + */ + 12 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 3 2 0 200 /* extern init voltage */ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + p2p_1{ + model_name = "p2p_ceds"; + interface = "p2p"; /*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 5000 2250 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 5100 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 16 29 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + p2p_attr = < + 0 /* teyp: 0=ceds, 1=cmpi, 2=isp, 3=epi, + * 10=chpi, 11=cspi, 12=usit + */ + 6 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + p2p_2{ + model_name = "p2p_chpi"; + interface = "p2p"; /*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 5100 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 16 29 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + p2p_attr = < + 10 /* teyp: 0=ceds, 1=cmpi, 2=isp, 3=epi, + * 10=chpi, 11=cspi, 12=usit + */ + 6 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + p2p_3{ + model_name = "p2p_chpi"; + interface = "p2p"; /*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 5100 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 16 29 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + p2p_attr = < + 10 /* teyp: 0=ceds, 1=cmpi, 2=isp, 3=epi, + * 10=chpi, 11=cspi, 12=usit + */ + 12 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + mlvds_0{ + model_name = "mlvds_1080p"; + interface = "minilvds"; /*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 1920 1080 /*h_active, v_active*/ + 2200 1125 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 2080 2720 /*h_period_min, max*/ + 2200 1125 /*v_period_min, max*/ + 133940000 156000000>; /*pclk_min, max*/ + lcd_timing = < + 44 148 0 /*hs_width, hs_bp, hs_pol*/ + 5 30 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + minilvds_attr = < + 6 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0x660 /* clk_phase */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 0>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + mlvds_1{ + model_name = "mlvds_768p"; + interface = "minilvds";/*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 1366 768 /*h_active, v_active*/ + 1560 806 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 1460 2000 /*h_period_min, max*/ + 784 1015 /*v_period_min, max*/ + 50000000 85000000>; /*pclk_min, max*/ + lcd_timing = < + 56 64 0 /*hs_width, hs_bp, hs_pol*/ + 3 28 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + minilvds_attr = < + 6 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0x660 /* clk_phase */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 0>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + }; + + lcd_extern{ + compatible = "amlogic, lcd_extern"; + status = "okay"; + key_valid = <1>; + i2c_bus = "i2c_bus_1"; + + extern_0{ + index = <0>; + extern_name = "ext_default"; + status = "disabled"; + type = <0>; /*0=i2c, 1=spi, 2=mipi*/ + i2c_address = <0x1c>; /*7bit i2c_addr*/ + i2c_address2 = <0xff>; + cmd_size = <0xff>; /*dynamic cmd_size*/ + + /* init on/off: + * fixed cmd_size: (type, value...); + * cmd_size include all data. + * dynamic cmd_size: (type, cmd_size, value...); + * cmd_size include value. + */ + /* type: 0x00=cmd with delay(bit[3:0]=1 for address2), + * 0xc0=cmd(bit[3:0]=1 for address2), + * 0xf0=gpio, + * 0xfd=delay, + * 0xff=ending + */ + /* value: i2c or spi cmd, or gpio index & level */ + /* delay: unit ms */ + init_on = < + 0xc0 7 0x20 0x01 0x02 0x00 0x40 0xFF 0x00 + 0xc0 7 0x80 0x02 0x00 0x40 0x62 0x51 0x73 + 0xc0 7 0x61 0x06 0x00 0x00 0x00 0x00 0x00 + 0xc0 7 0xC1 0x05 0x0F 0x00 0x08 0x70 0x00 + 0xc0 7 0x13 0x01 0x00 0x00 0x00 0x00 0x00 + 0xc0 7 0x3D 0x02 0x01 0x00 0x00 0x00 0x00 + 0xc0 7 0xED 0x0D 0x01 0x00 0x00 0x00 0x00 + 0xc0 7 0x23 0x02 0x00 0x00 0x00 0x00 0x00 + 0xfd 1 10 /* delay 10ms */ + 0xff 0>; /*ending*/ + init_off = <0xff 0>; /*ending*/ + }; + extern_1{ + index = <1>; + extern_name = "i2c_T5800Q"; + status = "disabled"; + type = <0>; /* 0=i2c, 1=spi, 2=mipi */ + i2c_address = <0x1c>; /* 7bit i2c address */ + }; + extern_2{ + index = <2>; + extern_name = "i2c_ANX6862_7911"; + status = "okay"; + type = <0>; /* 0=i2c, 1=spi, 2=mipi */ + i2c_address = <0x20>; /* 7bit i2c address */ + i2c_address2 = <0x74>; /* 7bit i2c address */ + cmd_size = <0xff>; + + init_on = < + 0xc0 2 0x01 0x2b + 0xc0 2 0x02 0x05 + 0xc0 2 0x03 0x00 + 0xc0 2 0x04 0x00 + 0xc0 2 0x05 0x0c + 0xc0 2 0x06 0x04 + 0xc0 2 0x07 0x21 + 0xc0 2 0x08 0x0f + 0xc0 2 0x09 0x04 + 0xc0 2 0x0a 0x00 + 0xc0 2 0x0b 0x04 + 0xc0 2 0xff 0x00 + 0xfd 1 100 /* delay 100ms */ + + 0xc1 2 0x01 0xca + 0xc1 2 0x02 0x3b + 0xc1 2 0x03 0x33 + 0xc1 2 0x04 0x05 + 0xc1 2 0x05 0x2c + 0xc1 2 0x06 0xf2 + 0xc1 2 0x07 0x9c + 0xc1 2 0x08 0x1b + 0xc1 2 0x09 0x82 + 0xc1 2 0x0a 0x3d + 0xc1 2 0x0b 0x20 + 0xc1 2 0x0c 0x11 + 0xc1 2 0x0d 0xc4 + 0xc1 2 0x0e 0x1a + 0xc1 2 0x0f 0x31 + 0xc1 2 0x10 0x4c + 0xc1 2 0x11 0x12 + 0xc1 2 0x12 0x90 + 0xc1 2 0x13 0xf7 + 0xc1 2 0x14 0x0c + 0xc1 2 0x15 0x20 + 0xc1 2 0x16 0x13 + 0xff 0>; /*ending*/ + init_off = <0xff 0>; /*ending*/ + }; + }; + + backlight{ + compatible = "amlogic, backlight-tl1"; + status = "okay"; + key_valid = <1>; + pinctrl-names = "pwm_on","pwm_vs_on", + "pwm_combo_0_1_on", + "pwm_combo_0_vs_1_on", + "pwm_combo_0_1_vs_on", + "pwm_off", + "pwm_combo_off"; + pinctrl-0 = <&pwm_c_pins3>; + pinctrl-1 = <&bl_pwm_vs_on_pins>; + pinctrl-2 = <&pwm_c_pins3 &pwm_d_pins2>; + pinctrl-3 = <&bl_pwm_combo_0_vs_on_pins &pwm_d_pins2>; + pinctrl-4 = <&pwm_c_pins3 &bl_pwm_combo_1_vs_on_pins>; + pinctrl-5 = <&bl_pwm_off_pins>; + pinctrl-6 = <&bl_pwm_combo_off_pins>; + pinctrl_version = <2>; /* for uboot */ + interrupts = <0 3 1>; + interrupt-names = "ldim_vsync"; + bl_pwm_config = <&bl_pwm_conf>; + + /* pwm port: PWM_A, PWM_B, PWM_C, PWM_D, PWM_E, PWM_F, PWM_VS*/ + /* power index:(point gpios_index, 0xff=invalid) */ + /* power value:(0=output low, 1=output high, 2=input) */ + /* power delay:(unit in ms) */ + bl-gpios = <&gpio_ao GPIOAO_11 GPIO_ACTIVE_HIGH + &gpio GPIOZ_5 GPIO_ACTIVE_HIGH + &gpio GPIOZ_6 GPIO_ACTIVE_HIGH>; + bl_gpio_names = "GPIOAO_11","GPIOZ_5","GPIOZ_6"; + + backlight_0{ + index = <0>; + bl_name = "backlight_pwm"; + bl_level_default_uboot_kernel = <100 100>; + bl_level_attr = <255 10 /*max, min*/ + 128 128>; /*mid, mid_mapping*/ + bl_ctrl_method = <1>; /*1=pwm,2=pwm_combo,3=ldim*/ + bl_power_attr = <0 /*en_gpio_index*/ + 1 0 /*on_value, off_value*/ + 200 200>; /*on_delay(ms), off_delay(ms)*/ + bl_pwm_port = "PWM_C"; + bl_pwm_attr = <1 /*pwm_method(0=negative, 1=positvie)*/ + 180 /*pwm_freq(pwm:Hz, pwm_vs:multiple of vs)*/ + 100 25>; /*duty_max(%), duty_min(%)*/ + bl_pwm_power = <1 0 /*pwm_gpio_index, pwm_gpio_off*/ + 10 10>; /*pwm_on_delay(ms), pwm_off_delay(ms)*/ + bl_pwm_en_sequence_reverse = <0>; /* 1 for reverse */ + }; + backlight_1{ + index = <1>; + bl_name = "backlight_pwm_vs"; + bl_level_default_uboot_kernel = <100 100>; + bl_level_attr = <255 10 /*max, min*/ + 128 128>; /*mid, mid_mapping*/ + bl_ctrl_method = <1>; /*1=pwm,2=pwm_combo,3=ldim*/ + bl_power_attr = <0 /*en_gpio_index*/ + 1 0 /*on_value, off_value*/ + 200 200>; /* on_delay(ms), off_delay(ms)*/ + bl_pwm_port = "PWM_VS"; + bl_pwm_attr = <1 /*pwm_method(0=negative, 1=positvie)*/ + 2 /*pwm_freq(pwm:Hz, pwm_vs:multiple of vs)*/ + 100 25>; /*duty_max(%), duty_min(%)*/ + bl_pwm_power = <1 0 /*pwm_gpio_index, pwm_gpio_off*/ + 10 10>; /*pwm_on_delay(ms), pwm_off_delay(ms)*/ + bl_pwm_en_sequence_reverse = <0>; /* 1 for reverse */ + }; + backlight_2{ + index = <2>; + bl_name = "backlight_pwm_combo"; + bl_level_default_uboot_kernel = <31 100>; + bl_level_attr = <255 10 /*max, min*/ + 128 128>; /*mid, mid_mapping*/ + bl_ctrl_method = <2>; /*1=pwm,2=pwm_combo,3=ldim*/ + bl_power_attr = <0 /*en_gpio_index*/ + 1 0 /*on_value, off_value*/ + 410 110>; /*on_delay(ms), off_delay(ms)*/ + bl_pwm_combo_level_mapping = <255 10 /*pwm_0 range*/ + 0 0>; /*pwm_1 range*/ + bl_pwm_combo_port = "PWM_C","PWM_D"; + bl_pwm_combo_attr = <1 /*pwm0 method*/ + 180 /*pwm0 freq(pwm:Hz, pwm_vs:multiple of vs)*/ + 100 25 /*pwm0 duty_max(%), duty_min(%)*/ + 1 /*pwm1 method*/ + 18000 /*pwm1 freq(pwm:Hz, pwm_vs:multi of vs)*/ + 80 80>; /*pwm1 duty_max(%), duty_min(%)*/ + bl_pwm_combo_power = <1 0 /*pwm0 gpio_index, gpio_off*/ + 2 0 /*pwm1 gpio_index, gpio_off*/ + 10 10>; /*pwm_on_delay(ms), pwm_off_delay(ms)*/ + }; + backlight_3{ + index = <3>; + bl_name = "pwm_combo_ldim_test"; + bl_level_default_uboot_kernel = <31 100>; + bl_level_attr = <255 10 /*max, min*/ + 128 128>; /*mid, mid_mapping*/ + bl_ctrl_method = <2>; /*1=pwm,2=pwm_combo,3=ldim*/ + bl_power_attr = <0 /*en_gpio_index*/ + 1 0 /*on_value, off_value*/ + 410 110>; /*on_delay(ms), off_delay(ms)*/ + bl_pwm_combo_level_mapping = <255 10 /*pwm_0 range*/ + 0 0>; /*pwm_1 range*/ + bl_pwm_combo_port = "PWM_C","PWM_D"; + bl_pwm_combo_attr = <1 /*pwm0 method*/ + 180 /*pwm0 freq(pwm:Hz, pwm_vs:multiple of vs)*/ + 100 25 /*pwm0 duty_max(%), duty_min(%)*/ + 1 /*pwm1 method*/ + 18000 /*pwm1 freq(pwm:Hz, pwm_vs:multi of vs)*/ + 80 80>; /*pwm1 duty_max(%), duty_min(%)*/ + bl_pwm_combo_power = <1 0 /*pwm0 gpio_index, gpio_off*/ + 2 0 /*pwm1 gpio_index, gpio_off*/ + 10 10>; /*pwm_on_delay(ms), pwm_off_delay(ms)*/ + bl_ldim_region_row_col = <2 10>; + }; + backlight_4{ + index = <4>; + bl_name = "ldim_global"; + bl_level_default_uboot_kernel = <100 100>; + bl_level_attr = <255 10 /*max, min*/ + 128 128>; /*mid, mid_mapping*/ + bl_ctrl_method = <3>; /*1=pwm,2=pwm_combo,3=ldim*/ + bl_power_attr = <0xff /*en_gpio_index*/ + 1 0 /*on_value, off_value*/ + 200 200>; /*on_delay(ms), off_delay(ms)*/ + bl_ldim_region_row_col = <1 1>; + bl_ldim_mode = <1>; /*0=left/right side + *1=top/bottom side + *2=direct + */ + ldim_dev_index = <1>; + }; + backlight_5{ + index = <5>; + bl_name = "ldim_iw7027"; + bl_level_default_uboot_kernel = <100 100>; + bl_level_attr = <255 10 /*max, min*/ + 128 128>; /*mid, mid_mapping*/ + bl_ctrl_method = <3>; /*1=pwm,2=pwm_combo,3=ldim*/ + bl_power_attr = <0 /*en_gpio_index*/ + 1 0 /*on_value, off_value*/ + 200 200>; /*on_delay(ms), off_delay(ms)*/ + bl_ldim_region_row_col = <1 10>; + bl_ldim_mode = <1>; /*0=left/right side + *1=top/bottom side + *2=direct + */ + ldim_dev_index = <2>; + }; + }; + + bl_pwm_conf:bl_pwm_conf{ + pwm_channel_0 { + pwm_port_index = <2>; + pwms = <&pwm_cd MESON_PWM_0 30040 0>; + }; + pwm_channel_1 { + pwm_port_index = <3>; + pwms = <&pwm_cd MESON_PWM_1 30040 0>; + }; + }; + + local_dimming_device { + compatible = "amlogic, ldim_dev"; + status = "okay"; + pinctrl-names = "ldim_pwm", + "ldim_pwm_vs", + "ldim_pwm_combo", + "ldim_pwm_vs_combo", + "ldim_pwm_off", + "ldim_pwm_combo_off"; + pinctrl-0 = <&pwm_c_pins3>; + pinctrl-1 = <&bl_pwm_vs_on_pins>; + pinctrl-2 = <&pwm_c_pins3 &pwm_d_pins2>; + pinctrl-3 = <&bl_pwm_vs_on_pins &pwm_d_pins2>; + pinctrl-4 = <&bl_pwm_off_pins>; + pinctrl-5 = <&bl_pwm_combo_off_pins>; + pinctrl_version = <1>; /* for uboot */ + ldim_pwm_config = <&bl_pwm_conf>; + + /* pwm port: PWM_A, PWM_B, PWM_C, PWM_D, PWM_E, PWM_F, PWM_VS*/ + ldim_dev-gpios = <&gpio_ao GPIOAO_11 GPIO_ACTIVE_HIGH + &gpio GPIOZ_5 GPIO_ACTIVE_HIGH + &gpio GPIOZ_6 GPIO_ACTIVE_HIGH>; + ldim_dev_gpio_names = "GPIOAO_11","GPIOZ_5","GPIOZ_6"; + + ldim_dev_0 { + index = <0>; + type = <0>; /*0=normal, 1=spi, 2=i2c*/ + ldim_dev_name = "ob3350"; + ldim_pwm_port = "PWM_C"; + ldim_pwm_attr = <0 /* pol */ + 200 /*freq(pwm:Hz, pwm_vs:multiple of vs)*/ + 50>;/*default duty(%)*/ + en_gpio_on_off = <0 /*ldim_dev-gpios index*/ + 1 0>; /*on_level, off_level*/ + dim_max_min = <100 20>; /*dim_max, dim_min*/ + }; + ldim_dev_1 { + index = <1>; + type = <0>; /*0=normal, 1=spi, 2=i2c*/ + ldim_dev_name = "global"; + ldim_pwm_port = "PWM_C"; + ldim_pwm_attr = <1 /* pol */ + 180 /*freq(pwm:Hz, pwm_vs:multiple of vs)*/ + 50>;/*default duty(%)*/ + analog_pwm_port = "PWM_D"; + analog_pwm_attr = <1 /*pol(0=negative, 1=positvie)*/ + 18000 /*freq(pwm:Hz)*/ + 100 25 /*duty_max(%), duty_min(%)*/ + 80>; /*default duty(%)*/ + en_gpio_on_off = <0 /*ldim_dev-gpios index*/ + 1 0>; /*on_level, off_level*/ + dim_max_min = <100 20>; /*dim_max, dim_min*/ + }; + + ldim_dev_2 { + index = <2>; + type = <1>; /* 0=normal,1=spi,2=i2c */ + ldim_dev_name = "iw7027"; + ldim_pwm_port = "PWM_VS"; + ldim_pwm_attr = <1 /* pol */ + 2 /*freq(pwm:Hz, pwm_vs:multiple of vs)*/ + 50>;/*default duty(%)*/ + spi_bus_num = <0>; + spi_chip_select = <0>; + spi_max_frequency = <1000000>; /* unit: hz */ + spi_mode = <0>; /* mode: 0, 1, 2, 3 */ + spi_cs_delay = <10 /* hold_high_delay */ + 100>; /* clk_cs_delay (unit: us) */ + en_gpio_on_off = <0 /* ldim_dev-gpios index */ + 1 /* on_level */ + 0>; /* off_level */ + lamp_err_gpio = <0xff>; + /* ldim_dev-gpios index, 0xff=invalid */ + spi_write_check = <0>; /* 0=disable, 1=enable */ + + dim_max_min = <0xfff 0x7f>; /* dim_max, dim_min */ + ldim_region_mapping = <0 1 2 3 4 5 6 7 8 9>; + + cmd_size = <0xff>; + /* init: (type, data...) */ + /* type: 0x00=cmd with delay, + * 0xc0=cmd, + * 0xfd=delay, + * 0xff=ending + */ + /* data: spi data, fill 0x0 for no use */ + /* delay: unit ms */ + init_on = < + 0xc0 2 0x23 0x03 + 0xc0 2 0x24 0xff + 0xc0 2 0x25 0x00 + 0xc0 2 0x26 0x00 + 0xc0 2 0x27 0x60 + 0xc0 2 0x29 0x00 + 0xc0 2 0x2a 0x00 + 0xc0 2 0x2b 0x00 + 0xc0 2 0x2c 0x73 + 0xc0 2 0x2d 0x37 + 0xc0 2 0x31 0x93 + 0xc0 2 0x32 0x0f + 0xc0 2 0x33 0xff + 0xc0 2 0x34 0xc8 + 0xc0 2 0x35 0xbf + 0xff 0>; + init_off = <0xff 0>; + }; + }; +}; /* end of / */ diff --git a/arch/arm64/boot/dts/amlogic/mesontm2.dtsi b/arch/arm64/boot/dts/amlogic/mesontm2.dtsi new file mode 100644 index 000000000000..8cf08ee2768a --- /dev/null +++ b/arch/arm64/boot/dts/amlogic/mesontm2.dtsi @@ -0,0 +1,2270 @@ +/* + * arch/arm64/boot/dts/amlogic/mesontm2.dtsi + * + * Copyright (C) 2018 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "mesong12a-bifrost.dtsi" +#include +/ { + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + + cpus:cpus { + #address-cells = <2>; + #size-cells = <0>; + #cooling-cells = <2>;/* min followed by max */ + CPU0:cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a53","arm,armv8"; + reg = <0x0 0x0>; + //timer=<&timer_a>; + enable-method = "psci"; + clocks = <&clkc CLKID_CPU_CLK>, + <&clkc CLKID_CPU_FCLK_P>, + <&clkc CLKID_SYS_PLL>; + clock-names = "core_clk", + "low_freq_clk_parent", + "high_freq_clk_parent"; + operating-points-v2 = <&cpu_opp_table0>; + cpu-supply = <&vddcpu0>; + //cpu-idle-states = <&SYSTEM_SLEEP_0>; + voltage-tolerance = <0>; + clock-latency = <50000>; + }; + + CPU1:cpu@1 { + device_type = "cpu"; + compatible = "arm,cortex-a53","arm,armv8"; + reg = <0x0 0x1>; + //timer=<&timer_b>; + enable-method = "psci"; + clocks = <&clkc CLKID_CPU_CLK>, + <&clkc CLKID_CPU_FCLK_P>, + <&clkc CLKID_SYS_PLL>; + clock-names = "core_clk", + "low_freq_clk_parent", + "high_freq_clk_parent"; + operating-points-v2 = <&cpu_opp_table0>; + cpu-supply = <&vddcpu0>; + //cpu-idle-states = <&SYSTEM_SLEEP_0>; + voltage-tolerance = <0>; + clock-latency = <50000>; + }; + + CPU2:cpu@2 { + device_type = "cpu"; + compatible = "arm,cortex-a53","arm,armv8"; + reg = <0x0 0x2>; + //timer=<&timer_c>; + enable-method = "psci"; + clocks = <&clkc CLKID_CPU_CLK>, + <&clkc CLKID_CPU_FCLK_P>, + <&clkc CLKID_SYS_PLL>; + clock-names = "core_clk", + "low_freq_clk_parent", + "high_freq_clk_parent"; + operating-points-v2 = <&cpu_opp_table0>; + cpu-supply = <&vddcpu0>; + //cpu-idle-states = <&SYSTEM_SLEEP_0>; + voltage-tolerance = <0>; + clock-latency = <50000>; + }; + + CPU3:cpu@3 { + device_type = "cpu"; + compatible = "arm,cortex-a53","arm,armv8"; + reg = <0x0 0x3>; + //timer=<&timer_d>; + enable-method = "psci"; + clocks = <&clkc CLKID_CPU_CLK>, + <&clkc CLKID_CPU_FCLK_P>, + <&clkc CLKID_SYS_PLL>; + clock-names = "core_clk", + "low_freq_clk_parent", + "high_freq_clk_parent"; + operating-points-v2 = <&cpu_opp_table0>; + cpu-supply = <&vddcpu0>; + //cpu-idle-states = <&SYSTEM_SLEEP_0>; + voltage-tolerance = <0>; + clock-latency = <50000>; + }; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupts = , + , + , + ; + }; + + timer_bc { + compatible = "arm, meson-bc-timer"; + reg = <0x0 0xffd0f190 0x0 0x4 0x0 0xffd0f194 0x0 0x4>; + timer_name = "Meson TimerF"; + clockevent-rating =<300>; + clockevent-shift =<20>; + clockevent-features =<0x23>; + interrupts = <0 60 1>; + bit_enable =<16>; + bit_mode =<12>; + bit_resolution =<0>; + }; + + arm_pmu { + compatible = "arm,armv8-pmuv3"; + /* clusterb-enabled; */ + interrupts = ; + reg = <0x0 0xff634680 0x0 0x4>; + cpumasks = <0xf>; + /* default 10ms */ + relax-timer-ns = <10000000>; + /* default 10000us */ + max-wait-cnt = <10000>; + }; + + gic: interrupt-controller@2c001000 { + compatible = "arm,cortex-a15-gic", "arm,cortex-a9-gic"; + #interrupt-cells = <3>; + #address-cells = <2>; + interrupt-controller; + reg = <0x0 0xffc01000 0x0 0x1000>, + <0x0 0xffc02000 0x0 0x0100>; + interrupts = ; + }; + + psci { + compatible = "arm,psci-0.2"; + method = "smc"; + }; + + secmon { + compatible = "amlogic, secmon"; + memory-region = <&secmon_reserved>; + in_base_func = <0x82000020>; + out_base_func = <0x82000021>; + reserve_mem_size = <0x00300000>; + }; + + securitykey { + compatible = "amlogic, securitykey"; + status = "okay"; + storage_query = <0x82000060>; + storage_read = <0x82000061>; + storage_write = <0x82000062>; + storage_tell = <0x82000063>; + storage_verify = <0x82000064>; + storage_status = <0x82000065>; + storage_list = <0x82000067>; + storage_remove = <0x82000068>; + storage_in_func = <0x82000023>; + storage_out_func = <0x82000024>; + storage_block_func = <0x82000025>; + storage_size_func = <0x82000027>; + storage_set_enctype = <0x8200006A>; + storage_get_enctype = <0x8200006B>; + storage_version = <0x8200006C>; + }; + + mailbox: mhu@ff63c400 { + status = "okay"; + compatible = "amlogic, meson_mhu"; + reg = <0x0 0xff63c400 0x0 0x4c>, /* MHU registers */ + <0x0 0xfffdf000 0x0 0x800>; /* Payload area */ + interrupts = <0 209 1>, /* low priority interrupt */ + <0 210 1>; /* high priority interrupt */ + #mbox-cells = <1>; + mbox-names = "cpu_to_scp_low", "cpu_to_scp_high"; + mboxes = <&mailbox 0 &mailbox 1>; + }; + + cpu_iomap { + compatible = "amlogic, iomap"; + #address-cells = <2>; + #size-cells = <2>; + ranges; + + io_cbus_base { + reg = <0x0 0xffd00000 0x0 0x101000>; + }; + io_apb_base { + reg = <0x0 0xffe01000 0x0 0x19f000>; + }; + io_aobus_base { + reg = <0x0 0xff800000 0x0 0x100000>; + }; + io_vapb_base { + reg = <0x0 0xff900000 0x0 0x200000>; + }; + io_hiu_base { + reg = <0x0 0xff63c000 0x0 0x2000>; + }; + }; + + xtal: xtal-clk { + compatible = "fixed-clock"; + clock-frequency = <24000000>; + clock-output-names = "xtal"; + #clock-cells = <0>; + }; + + aml_pm { + compatible = "amlogic, pm"; + status = "okay"; + device_name = "aml_pm"; + debug_reg = <0xff8000a8>; + exit_reg = <0xff80023c>; + }; + + cpuinfo { + compatible = "amlogic, cpuinfo"; + status = "okay"; + cpuinfo_cmd = <0x82000044>; + }; + + reboot { + compatible = "amlogic,reboot"; + sys_reset = <0x84000009>; + sys_poweroff = <0x84000008>; + }; + + ram-dump { + compatible = "amlogic, ram_dump"; + status = "okay"; + reg = <0x0 0xFF6345E0 0x0 4>; + reg-names = "PREG_STICKY_REG8"; + store_device = "data"; + }; + + vpu { + compatible = "amlogic, vpu-tm2"; + status = "okay"; + clocks = <&clkc CLKID_VAPB_MUX>, + <&clkc CLKID_VPU_INTR>, + <&clkc CLKID_VPU_P0_COMP>, + <&clkc CLKID_VPU_P1_COMP>, + <&clkc CLKID_VPU_MUX>; + clock-names = "vapb_clk", + "vpu_intr_gate", + "vpu_clk0", + "vpu_clk1", + "vpu_clk"; + clk_level = <7>; + /* 0: 100.0M 1: 166.7M 2: 200.0M 3: 250.0M */ + /* 4: 333.3M 5: 400.0M 6: 500.0M 7: 666.7M */ + }; + + ethmac: ethernet@ff3f0000 { + compatible = "amlogic, g12a-eth-dwmac","snps,dwmac"; + reg = <0x0 0xff3f0000 0x0 0x10000 + 0x0 0xff634540 0x0 0x8 + 0x0 0xff64c000 0x0 0xa0>; + reg-names = "eth_base", "eth_cfg", "eth_pll"; + interrupts = <0 8 1>; + interrupt-names = "macirq"; + status = "disabled"; + clocks = <&clkc CLKID_ETH_CORE>; + clock-names = "ethclk81"; + pll_val = <0x9c0040a 0x927e0000 0xac5f49e5>; + analog_val = <0x20200000 0x0000c000 0x00000023>; + }; + + pinctrl_aobus: pinctrl@ff800014 { + compatible = "amlogic,meson-tl1-aobus-pinctrl"; + #address-cells = <2>; + #size-cells = <2>; + ranges; + + gpio_ao: ao-bank@ff800014 { + reg = <0x0 0xff800014 0x0 0x8>, + <0x0 0xff800024 0x0 0x14>, + <0x0 0xff80001c 0x0 0x8>; + reg-names = "mux", "gpio", "drive-strength"; + gpio-controller; + #gpio-cells = <2>; + }; + + aoceca_mux:aoceca_mux { + mux { + groups = "cec_ao_a"; + function = "cec_ao"; + }; + }; + + aocecb_mux:aocecb_mux { + mux { + groups = "cec_ao_b"; + function = "cec_ao"; + }; + }; + }; + + pinctrl_periphs: pinctrl@ff6346c0 { + compatible = "amlogic,meson-tl1-periphs-pinctrl"; + #address-cells = <2>; + #size-cells = <2>; + ranges; + + gpio: banks@ff6346c0 { + reg = <0x0 0xff6346c0 0x0 0x40>, + <0x0 0xff6344e8 0x0 0x18>, + <0x0 0xff634520 0x0 0x18>, + <0x0 0xff634440 0x0 0x4c>, + <0x0 0xff634740 0x0 0x1c>; + reg-names = "mux", + "pull", + "pull-enable", + "gpio", + "drive-strength"; + gpio-controller; + #gpio-cells = <2>; + }; + + + hdmirx_a_mux:hdmirx_a_mux { + mux { + groups = "hdmirx_a_hpd", "hdmirx_a_det", + "hdmirx_a_sda", "hdmirx_a_sck"; + function = "hdmirx_a"; + }; + }; + + hdmirx_b_mux:hdmirx_b_mux { + mux { + groups = "hdmirx_b_hpd", "hdmirx_b_det", + "hdmirx_b_sda", "hdmirx_b_sck"; + function = "hdmirx_b"; + }; + }; + + hdmirx_c_mux:hdmirx_c_mux { + mux { + groups = "hdmirx_c_hpd", "hdmirx_c_det", + "hdmirx_c_sda", "hdmirx_c_sck"; + function = "hdmirx_c"; + }; + }; + + }; + + dwc3: dwc3@ff500000 { + compatible = "synopsys, dwc3"; + status = "disabled"; + reg = <0x0 0xff500000 0x0 0x100000>; + interrupts = <0 30 4>; + usb-phy = <&usb2_phy_v2>, <&usb3_phy_v2>; + cpu-type = "gxl"; + clock-src = "usb3.0"; + clocks = <&clkc CLKID_USB_GENERAL>; + clock-names = "dwc_general"; + snps,quirk-frame-length-adjustment = <0x20>; + }; + + usb2_phy_v2: usb2phy@ffe09000 { + compatible = "amlogic, amlogic-new-usb2-v2"; + status = "disabled"; + reg = <0x0 0xffe09000 0x0 0x80 + 0x0 0xffd01008 0x0 0x100 + 0x0 0xff636000 0x0 0x2000 + 0x0 0xff63a000 0x0 0x2000 + 0x0 0xff658000 0x0 0x2000>; + pll-setting-1 = <0x09400414>; + pll-setting-2 = <0x927E0000>; + pll-setting-3 = <0xac5f69e5>; + pll-setting-4 = <0xfe18>; + pll-setting-5 = <0x8000fff>; + pll-setting-6 = <0x78000>; + pll-setting-7 = <0xe0004>; + pll-setting-8 = <0xe000c>; + version = <2>; + pwr-ctl = <1>; + u2-ctrl-sleep-shift = <17>; + u2-hhi-mem-pd-shift = <30>; + u2-hhi-mem-pd-mask = <0x3>; + u2-ctrl-iso-shift = <17>; + }; + + usb3_phy_v2: usb3phy@ffe09080 { + compatible = "amlogic, amlogic-new-usb3-v3"; + status = "disable"; + reg = <0x0 0xffe09080 0x0 0x20>; + phy0-reg = <0xff646000>; + phy0-reg-size = <0x2000>; + phy1-reg = <0xff65c000>; + phy1-reg-size = <0x2000>; + reset-reg = <0xffd01008>; + reset-reg-size = <0x100>; + clocks = <&clkc CLKID_PCIE0_GATE + &clkc CLKID_PCIE_PLL + &clkc CLKID_PCIE1_GATE>; + clock-names = "pcie0_gate", + "pcie_refpll", + "pcie1_gate"; + pwr-ctl = <1>; + u30-ctrl-sleep-shift = <18>; + u30-hhi-mem-pd-shift = <26>; + u30-hhi-mem-pd-mask = <0xf>; + u30-ctrl-iso-shift = <18>; + usb30-ctrl-a-rst-bit = <12>; + u31-ctrl-sleep-shift = <20>; + u31-hhi-mem-pd-shift = <4>; + u31-hhi-mem-pd-mask = <0xf>; + u31-ctrl-iso-shift = <20>; + usb31-ctrl-a-rst-bit = <28>; + }; + + usb_otg: usbotg@ffe09080 { + compatible = "amlogic, amlogic-new-otg"; + status = "disabled"; + usb2-phy-reg = <0xffe09000>; + usb2-phy-reg-size = <0x100>; + interrupts = <0 16 4>; + }; + + + dwc2_a: dwc2_a@ff400000 { + compatible = "amlogic, dwc2"; + status = "disabled"; + device_name = "dwc2_a"; + reg = <0x0 0xff400000 0x0 0x40000>; + interrupts = <0 31 4>; + pl-periph-id = <0>; /** lm name */ + clock-src = "usb0"; /** clock src */ + port-id = <0>; /** ref to mach/usb.h */ + port-type = <2>; /** 0: otg, 1: host, 2: slave */ + port-speed = <0>; /** 0: default, high, 1: full */ + port-config = <0>; /** 0: default */ + /*0:default,1:single,2:incr,3:incr4,4:incr8,5:incr16,6:disable*/ + port-dma = <0>; + port-id-mode = <0>; /** 0: hardware, 1: sw_host, 2: sw_slave*/ + usb-fifo = <728>; + cpu-type = "v2"; + phy-reg = <0xffe09000>; + phy-reg-size = <0xa0>; + /** phy-interface: 0x0: amlogic-v1 phy, 0x1: synopsys phy **/ + /** 0x2: amlogic-v2 phy **/ + phy-interface = <0x2>; + phy-otg = <0x1>; + clocks = <&clkc CLKID_USB_GENERAL + &clkc CLKID_USB1_TO_DDR>; + clock-names = "usb_general", + "usb1"; + }; + + wdt: watchdog@0xffd0f0d0 { + compatible = "amlogic, meson-wdt"; + status = "disabled"; + default_timeout=<10>; + reset_watchdog_method=<1>; /* 0:sysfs,1:kernel */ + reset_watchdog_time=<2>; + shutdown_timeout=<10>; + firmware_timeout=<6>; + suspend_timeout=<6>; + reg = <0x0 0xffd0f0d0 0x0 0x10>; + clock-names = "xtal"; + clocks = <&xtal>; + }; + + jtag { + compatible = "amlogic, jtag"; + status = "okay"; + select = "disable"; /* disable/apao */ + pinctrl-names="jtag_apao_pins"; + pinctrl-0=<&jtag_apao_pins>; + }; + + saradc:saradc { + compatible = "amlogic,meson-g12a-saradc"; + status = "disabled"; + #io-channel-cells = <1>; + clocks = <&xtal>, <&clkc CLKID_SARADC_GATE>; + clock-names = "xtal", "saradc_clk"; + interrupts = ; + reg = <0x0 0xff809000 0x0 0x48>; + }; + + vddcpu0: pwmao_d-regulator { + compatible = "pwm-regulator"; + pwms = <&pwm_AO_cd MESON_PWM_1 1500 0>; + regulator-name = "vddcpu0"; + regulator-min-microvolt = <690000>; + regulator-max-microvolt = <1050000>; + regulator-always-on; + max-duty-cycle = <1500>; + /* Voltage Duty-Cycle */ + voltage-table = <1050000 0>, + <1040000 3>, + <1030000 6>, + <1020000 8>, + <1010000 11>, + <1000000 14>, + <990000 17>, + <980000 20>, + <970000 23>, + <960000 26>, + <950000 29>, + <940000 31>, + <930000 34>, + <920000 37>, + <910000 40>, + <900000 43>, + <890000 45>, + <880000 48>, + <870000 51>, + <860000 54>, + <850000 56>, + <840000 59>, + <830000 62>, + <820000 65>, + <810000 68>, + <800000 70>, + <790000 73>, + <780000 76>, + <770000 79>, + <760000 81>, + <750000 84>, + <740000 87>, + <730000 89>, + <720000 92>, + <710000 95>, + <700000 98>, + <690000 100>; + status = "okay"; + }; + + aml_dma { + compatible = "amlogic,aml_txlx_dma"; + reg = <0x0 0xff63e000 0x0 0x48>; + interrupts = <0 180 1>; + + aml_aes { + compatible = "amlogic,aes_g12a_dma"; + dev_name = "aml_aes_dma"; + status = "okay"; + }; + + aml_sha { + compatible = "amlogic,sha_dma"; + dev_name = "aml_sha_dma"; + status = "okay"; + }; + }; + + rng { + compatible = "amlogic,meson-rng"; + status = "okay"; + #address-cells = <2>; + #size-cells = <2>; + reg = <0x0 0xff630218 0x0 0x4>; + quality = /bits/ 16 <1000>; + }; + + power_ctrl: power_ctrl@ff8000e8 { + compatible = "amlogic, sm1-powerctrl"; + reg = <0x0 0xff8000e8 0x0 0x10>, + <0x0 0xff63c100 0x0 0x10>; + }; + + soc { + compatible = "simple-bus"; + #address-cells = <2>; + #size-cells = <2>; + ranges; + + hiubus: hiubus@ff63c000 { + compatible = "simple-bus"; + reg = <0x0 0xff63c000 0x0 0x2000>; + #address-cells = <2>; + #size-cells = <2>; + ranges = <0x0 0x0 0x0 0xff63c000 0x0 0x2000>; + + clkc: clock-controller@0 { + compatible = "amlogic,tl1-clkc"; + #clock-cells = <1>; + reg = <0x0 0x0 0x0 0x3fc>; + }; + };/* end of hiubus*/ + + audiobus: audiobus@0xff600000 { + compatible = "amlogic, audio-controller", "simple-bus"; + #address-cells = <2>; + #size-cells = <2>; + reg = <0x0 0xff600000 0x0 0x10000>; + ranges = <0x0 0x0 0x0 0xff600000 0x0 0x10000>; + + clkaudio:audio_clocks { + compatible = "amlogic, tm2-audio-clocks"; + #clock-cells = <1>; + reg = <0x0 0x0 0x0 0xb0>; + }; + + ddr_manager { + compatible = "amlogic, tl1-audio-ddr-manager"; + interrupts = < + GIC_SPI 148 IRQ_TYPE_EDGE_RISING + GIC_SPI 149 IRQ_TYPE_EDGE_RISING + GIC_SPI 150 IRQ_TYPE_EDGE_RISING + GIC_SPI 48 IRQ_TYPE_EDGE_RISING + GIC_SPI 152 IRQ_TYPE_EDGE_RISING + GIC_SPI 153 IRQ_TYPE_EDGE_RISING + GIC_SPI 154 IRQ_TYPE_EDGE_RISING + GIC_SPI 49 IRQ_TYPE_EDGE_RISING + >; + interrupt-names = + "toddr_a", "toddr_b", "toddr_c", + "toddr_d", + "frddr_a", "frddr_b", "frddr_c", + "frddr_d"; + }; + };/* end of audiobus*/ + + /* Sound iomap */ + aml_snd_iomap { + compatible = "amlogic, snd-iomap"; + status = "okay"; + #address-cells=<2>; + #size-cells=<2>; + ranges; + pdm_bus { + reg = <0x0 0xFF601000 0x0 0x400>; + }; + audiobus_base { + reg = <0x0 0xFF600000 0x0 0x1000>; + }; + audiolocker_base { + reg = <0x0 0xFF601400 0x0 0x400>; + }; + eqdrc_base { + reg = <0x0 0xFF602000 0x0 0x1000>; + }; + reset_base { + reg = <0x0 0xFFD01000 0x0 0x1000>; + }; + vad_base { + reg = <0x0 0xFF601800 0x0 0x400>; + }; + earcrx_cdmc_base { + reg = <0x0 0xFF603800 0x0 0x30>; + }; + earcrx_dmac_base { + reg = <0x0 0xFF603C00 0x0 0x20>; + }; + earcrx_top_base { + reg = <0x0 0xFF603E00 0x0 0x10>; + }; + }; + + cbus: cbus@ffd00000 { + compatible = "simple-bus"; + reg = <0x0 0xffd00000 0x0 0x27000>; + #address-cells = <2>; + #size-cells = <2>; + ranges = <0x0 0x0 0x0 0xffd00000 0x0 0x27000>; + + clk-measure@18004 { + compatible = "amlogic,tl1-measure"; + reg = <0x0 0x18004 0x0 0x4 0x0 0x1800c 0x0 0x4>; + ringctrl = <0xff6345fc>; + }; + + i2c0: i2c@1f000 { + compatible = "amlogic,meson-i2c"; + status = "disabled"; + reg = <0x0 0x1f000 0x0 0x20>; + interrupts = , + ; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&clkc CLKID_I2C>; + clock-frequency = <100000>; + }; + + i2c1: i2c@1e000 { + compatible = "amlogic,meson-i2c"; + status = "disabled"; + reg = <0x0 0x1e000 0x0 0x20>; + interrupts = , + ; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&clkc CLKID_I2C>; + clock-frequency = <100000>; + }; + + i2c2: i2c@1d000 { + compatible = "amlogic,meson-i2c"; + status = "disabled"; + reg = <0x0 0x1d000 0x0 0x20>; + interrupts = , + ; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&clkc CLKID_I2C>; + clock-frequency = <100000>; + }; + + i2c3: i2c@1c000 { + compatible = "amlogic,meson-i2c"; + status = "disabled"; + reg = <0x0 0x1c000 0x0 0x20>; + interrupts = , + ; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&clkc CLKID_I2C>; + clock-frequency = <100000>; + }; + + gpio_intc: interrupt-controller@f080 { + compatible = "amlogic,meson-gpio-intc", + "amlogic,meson-tm2-gpio-intc"; + reg = <0x0 0xf080 0x0 0x10>; + interrupt-controller; + #interrupt-cells = <2>; + amlogic,channel-interrupts = + <64 65 66 67 68 69 70 71>; + status = "okay"; + }; + + pwm_ab: pwm@1b000 { + compatible = "amlogic,tl1-ee-pwm"; + reg = <0x0 0x1b000 0x0 0x20>; + #pwm-cells = <3>; + clocks = <&xtal>, + <&xtal>, + <&xtal>, + <&xtal>; + clock-names = "clkin0", + "clkin1", + "clkin2", + "clkin3"; + /* default xtal 24m clkin0-clkin2 and + * clkin1-clkin3 should be set the same + */ + status = "disabled"; + }; + + pwm_cd: pwm@1a000 { + compatible = "amlogic,tl1-ee-pwm"; + reg = <0x0 0x1a000 0x0 0x20>; + #pwm-cells = <3>; + clocks = <&xtal>, + <&xtal>, + <&xtal>, + <&xtal>; + clock-names = "clkin0", + "clkin1", + "clkin2", + "clkin3"; + status = "disabled"; + }; + + pwm_ef: pwm@19000 { + compatible = "amlogic,tl1-ee-pwm"; + reg = <0x0 0x19000 0x0 0x20>; + #pwm-cells = <3>; + clocks = <&xtal>, + <&xtal>, + <&xtal>, + <&xtal>; + clock-names = "clkin0", + "clkin1", + "clkin2", + "clkin3"; + status = "disabled"; + }; + + spicc0: spi@13000 { + compatible = "amlogic,meson-tl1-spicc", + "amlogic,meson-g12a-spicc"; + reg = <0x0 0x13000 0x0 0x44>; + interrupts = ; + clocks = <&clkc CLKID_SPICC0>, + <&clkc CLKID_SPICC0_COMP>; + clock-names = "core", "comp"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + spicc1: spi@15000 { + compatible = "amlogic,meson-tl1-spicc", + "amlogic,meson-g12a-spicc"; + reg = <0x0 0x15000 0x0 0x44>; + interrupts = ; + clocks = <&clkc CLKID_SPICC1>, + <&clkc CLKID_SPICC1_COMP>; + clock-names = "core", "comp"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + }; + + aobus: aobus@ff800000 { + compatible = "simple-bus"; + reg = <0x0 0xff800000 0x0 0xb000>; + #address-cells = <2>; + #size-cells = <2>; + ranges = <0x0 0x0 0x0 0xff800000 0x0 0xb000>; + + cpu_version { + reg = <0x0 0x220 0x0 0x4>; + }; + + aoclkc: clock-controller@0 { + compatible = "amlogic,tl1-aoclkc"; + #clock-cells = <1>; + reg = <0x0 0x0 0x0 0x1000>; + }; + + pwm_AO_ab: pwm@7000 { + compatible = "amlogic,tl1-ao-pwm"; + reg = <0x0 0x7000 0x0 0x20>; + #pwm-cells = <3>; + clocks = <&xtal>, + <&xtal>, + <&xtal>, + <&xtal>; + clock-names = "clkin0", + "clkin1", + "clkin2", + "clkin3"; + status = "disabled"; + }; + + pwm_AO_cd: pwm@2000 { + compatible = "amlogic,tl1-ao-pwm"; + reg = <0x0 0x2000 0x0 0x20>; + #pwm-cells = <3>; + clocks = <&xtal>, + <&xtal>, + <&xtal>, + <&xtal>; + clock-names = "clkin0", + "clkin1", + "clkin2", + "clkin3"; + status = "disabled"; + }; + + uart_AO: serial@3000 { + compatible = "amlogic, meson-uart"; + reg = <0x0 0x3000 0x0 0x18>; + interrupts = <0 193 1>; + status = "okay"; + clocks = <&xtal>; + clock-names = "clk_uart"; + xtal_tick_en = <2>; + fifosize = < 64 >; + //pinctrl-names = "default"; + //pinctrl-0 = <&ao_a_uart_pins>; + /* 0 not support; 1 support */ + support-sysrq = <0>; + }; + + uart_AO_B: serial@4000 { + compatible = "amlogic, meson-uart"; + reg = <0x0 0x4000 0x0 0x18>; + interrupts = <0 197 1>; + status = "disabled"; + clocks = <&xtal>; + clock-names = "clk_uart"; + fifosize = < 64 >; + pinctrl-names = "default"; + pinctrl-0 = <&ao_b_uart_pins1>; + }; + remote: rc@8040 { + compatible = "amlogic, aml_remote"; + reg = <0x0 0x8040 0x0 0x44>, + <0x0 0x8000 0x0 0x20>; + status = "okay"; + protocol = ; + interrupts = ; + pinctrl-names = "default"; + pinctrl-0 = <&remote_pins>; + map = <&custom_maps>; + max_frame_time = <200>; + }; + + irblaster: meson-irblaster@14c { + compatible = "amlogic, meson_irblaster"; + reg = <0x0 0x14c 0x0 0x10>, + <0x0 0x40 0x0 0x4>; + #irblaster-cells = <2>; + interrupts = ; + status = "disabled"; + }; + + i2c_AO: i2c@5000 { + compatible = "amlogic,meson-i2c"; + status = "disabled"; + reg = <0x0 0x05000 0x0 0x20>; + interrupts = , + ; + #address-cells = <2>; + #size-cells = <2>; + clocks = <&clkc CLKID_I2C>; + clock-frequency = <100000>; + }; + + i2c_AO_slave:i2c_slave@6000 { + compatible = "amlogic, meson-i2c-slave"; + status = "disabled"; + reg = <0x0 0x6000 0x0 0x20>; + interrupts = ; + pinctrl-names="default"; + pinctrl-0=<&i2c_ao_slave_pins>; + }; + };/* end of aobus */ + + ion_dev { + compatible = "amlogic, ion_dev"; + status = "okay"; + memory-region = <&ion_cma_reserved>; + };/* end of ion_dev*/ + }; /* end of soc*/ + + custom_maps: custom_maps { + mapnum = <3>; + map0 = <&map_0>; + map1 = <&map_1>; + map2 = <&map_2>; + map_0: map_0{ + mapname = "amlogic-remote-1"; + customcode = <0xfb04>; + release_delay = <80>; + size = <44>; /*keymap size*/ + keymap = ; + }; + + map_1: map_1{ + mapname = "amlogic-remote-2"; + customcode = <0xfe01>; + release_delay = <80>; + size = <53>; + keymap = ; + }; + + map_2: map_2{ + mapname = "amlogic-remote-3"; + customcode = <0xbd02>; + release_delay = <80>; + size = <17>; + keymap = ; + }; + }; + + uart_A: serial@ffd24000 { + compatible = "amlogic, meson-uart"; + reg = <0x0 0xffd24000 0x0 0x18>; + interrupts = <0 26 1>; + status = "disabled"; + clocks = <&xtal + &clkc CLKID_UART0>; + clock-names = "clk_uart", + "clk_gate"; + fifosize = < 128 >; + pinctrl-names = "default"; + pinctrl-0 = <&a_uart_pins>; + }; + + uart_B: serial@ffd23000 { + compatible = "amlogic, meson-uart"; + reg = <0x0 0xffd23000 0x0 0x18>; + interrupts = <0 75 1>; + status = "disabled"; + clocks = <&xtal + &clkc CLKID_UART1>; + clock-names = "clk_uart", + "clk_gate"; + fifosize = < 64 >; + pinctrl-names = "default"; + pinctrl-0 = <&b_uart_pins>; + }; + + uart_C: serial@ffd22000 { + compatible = "amlogic, meson-uart"; + reg = <0x0 0xffd22000 0x0 0x18>; + interrupts = <0 93 1>; + status = "disabled"; + clocks = <&xtal + &clkc CLKID_UART1>; + clock-names = "clk_uart", + "clk_gate"; + fifosize = < 64 >; + pinctrl-names = "default"; + pinctrl-0 = <&c_uart_pins>; + }; + + + pcie_A: pcieA@fc000000 { + compatible = "amlogic, amlogic-pcie-v2", "snps,dw-pcie"; + reg = <0x0 0xfc000000 0x0 0x400000 + 0x0 0xff648000 0x0 0x2000 + 0x0 0xfc400000 0x0 0x200000 + 0x0 0xff646000 0x0 0x2000 + 0x0 0xffd01080 0x0 0x10>; + reg-names = "elbi", "cfg", "config", "phy", "reset"; + interrupts = <0 221 0>; + #interrupt-cells = <1>; + bus-range = <0x0 0xff>; + #address-cells = <3>; + #size-cells = <2>; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &gic GIC_SPI 223 IRQ_TYPE_EDGE_RISING>; + device_type = "pci"; + ranges = <0x81000000 0 0 0 0xfc600000 0x0 0x100000 + /* downstream I/O */ + 0x82000000 0 0xfc700000 0x0 0xfc700000 0 0x1900000>; + /* non-prefetchable memory */ + num-lanes = <1>; + pcie-num = <1>; + + clocks = <&clkc CLKID_PCIE0_GATE + &clkc CLKID_PCIE1 + &clkc CLKID_PCIE0PHY>; + clock-names = "pcie_refpll", + "pcie", + "pcie_phy"; + /*reset-gpio-type 0:Shared pad(no reset)1:OD pad2:Normal pad*/ + gpio-type = <2>; + pcie-apb-rst-bit = <15>; + pcie-phy-rst-bit = <14>; + pcie-ctrl-a-rst-bit = <12>; + pwr-ctl = <1>; + pcie-ctrl-sleep-shift = <18>; + pcie-hhi-mem-pd-shift = <26>; + pcie-hhi-mem-pd-mask = <0xf>; + pcie-ctrl-iso-shift = <18>; + status = "disabled"; + }; + + pcie_B: pcieB@fc000000 { + compatible = "amlogic, amlogic-pcie-v2", "snps,dw-pcie"; + reg = <0x0 0xfA000000 0x0 0x400000 + 0x0 0xff65E000 0x0 0x2000 + 0x0 0xfA400000 0x0 0x200000 + 0x0 0xff65C000 0x0 0x2000 + 0x0 0xffd01080 0x0 0x10>; + reg-names = "elbi", "cfg", "config", "phy", + "reset"; + interrupts = <0 229 0>; + #interrupt-cells = <1>; + bus-range = <0x0 0xff>; + #address-cells = <3>; + #size-cells = <2>; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &gic GIC_SPI 231 IRQ_TYPE_EDGE_RISING>; + device_type = "pci"; + ranges = <0x81000000 0 0 0 0xfA600000 0x0 0x100000 + /* downstream I/O */ + 0x82000000 0 0xfA700000 0x0 0xfA700000 0 0x1900000>; + /* non-prefetchable memory */ + num-lanes = <1>; + pcie-num = <1>; + + clocks = <&clkc CLKID_PCIE1_GATE + &clkc CLKID_PCIE1 + &clkc CLKID_PCIE1PHY>; + clock-names = "pcie_refpll", + "pcie", + "pcie_phy"; + /*reset-gpio-type 0:Shared pad(no reset)1:OD pad2:Normal pad*/ + gpio-type = <2>; + pcie-apb-rst-bit = <30>; + pcie-phy-rst-bit = <29>; + pcie-ctrl-a-rst-bit = <28>; + pwr-ctl = <1>; + pcie-ctrl-sleep-shift = <20>; + pcie-hhi-mem-pd-shift = <4>; + pcie-hhi-mem-pd-mask = <0xf>; + pcie-ctrl-iso-shift = <20>; + status = "disabled"; + }; + galcore { + compatible = "amlogic, galcore"; + dev_name = "galcore"; + status = "disabled"; + interrupts = <0 147 4>; + interrupt-names = "galcore"; + reg = <0x0 0xff100000 0x0 0x800 + /*reg base value:0xff100000 */ + 0x0 0xff000000 0x0 0x400000 + /*Sram bse value:0xff000000*/ + 0x0 0xff63c118 0x0 0x0 + 0x0 0xff63c11c 0x0 0x0 + /*0xff63c118,0xff63c11c :nanoq mem regs*/ + 0x0 0xffd01088 0x0 0x0 + /*0xffd01088:reset reg*/ + >; + }; + sd_emmc_c: emmc@ffe07000 { + status = "disabled"; + compatible = "amlogic, meson-mmc-tm2"; + reg = <0x0 0xffe07000 0x0 0x800>; + interrupts = <0 191 1>; + pinctrl-names = "emmc_clk_cmd_pins", "emmc_all_pins"; + pinctrl-0 = <&emmc_clk_cmd_pins>; + pinctrl-1 = <&emmc_conf_pull_up &emmc_conf_pull_done>; + clocks = <&clkc CLKID_SD_EMMC_C>, + <&clkc CLKID_SD_EMMC_C_P0_COMP>, + <&clkc CLKID_FCLK_DIV2>, + <&clkc CLKID_FCLK_DIV2P5>, + <&xtal>; + clock-names = "core","clkin0","clkin1","clkin2","xtal"; + + bus-width = <8>; + cap-sd-highspeed; + cap-mmc-highspeed; + /* mmc-ddr-1_8v; */ + /* mmc-hs200-1_8v; */ + + max-frequency = <200000000>; + non-removable; + disable-wp; + emmc { + pinname = "emmc"; + ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ + /*caps defined in dts*/ + tx_delay = <0>; + max_req_size = <0x20000>; /**128KB*/ + gpio_dat3 = <&gpio BOOT_3 GPIO_ACTIVE_HIGH>; + hw_reset = <&gpio BOOT_12 GPIO_ACTIVE_HIGH>; + card_type = <1>; + /* 1:mmc card(include eMMC), + * 2:sd card(include tSD) + */ + }; + }; + + + spifc: spifc@ffd14000 { + compatible = "amlogic,aml-spi-nor"; + status = "disabled"; + + reg = <0x0 0xffd14000 0x0 0x80>; + pinctrl-names = "default"; + pinctrl-0 = <&spifc_all_pins>; + clock-names = "core"; + clocks = <&clkc CLKID_CLK81>; + + spi-nor@0 { + compatible = "jedec,spi-nor"; + spifc-frequency = <40000000>; + read-capability = <4>;/* dual read 1_1_2 */ + spifc-io-width = <4>; + }; + }; + + slc_nand: nand-controller@0xFFE07800 { + compatible = "amlogic, aml_mtd_nand"; + status = "disabled"; + reg = <0x0 0xFFE07800 0x0 0x200>; + interrupts = <0 34 1>; + + pinctrl-names = "nand_rb_mod", "nand_norb_mod", "nand_cs_only"; + pinctrl-0 = <&all_nand_pins>; + pinctrl-1 = <&all_nand_pins>; + pinctrl-2 = <&nand_cs_pins>; + clocks = <&clkc CLKID_SD_EMMC_C>, + <&clkc CLKID_SD_EMMC_C_P0_COMP>; + clock-names = "core", "clkin"; + + device_id = <0>; + /*fip/tpl configurations, must be same + *with uboot if bl_mode was set as 1 + *bl_mode: 0 compact mode;1 descrete mode + *if bl_mode was set as 1,fip configuration will work + */ + bl_mode = <1>; + /*copy count of fip*/ + fip_copies = <4>; + /*size of each fip copy*/ + fip_size = <0x200000>; + nand_clk_ctrl = <0xFFE07000>; + /*partions defined in dts*/ + }; + + mesonstream { + compatible = "amlogic, codec, streambuf"; + status = "okay"; + clocks = <&clkc CLKID_U_PARSER + &clkc CLKID_DEMUX + &clkc CLKID_AHB_ARB0 + &clkc CLKID_CLK81 + &clkc CLKID_DOS + &clkc CLKID_VDEC_MUX + &clkc CLKID_HCODEC_MUX + &clkc CLKID_HEVC_MUX + &clkc CLKID_HEVCF_MUX>; + clock-names = "parser_top", + "demux", + "ahbarb0", + "clk_81", + "vdec", + "clk_vdec_mux", + "clk_hcodec_mux", + "clk_hevc_mux", + "clk_hevcb_mux"; + }; + + vcodec-dec { + compatible = "amlogic, vcodec-dec"; + status = "okay"; + }; + + vdec { + compatible = "amlogic, vdec"; + status = "okay"; + interrupts = <0 3 1 + 0 23 1 + 0 32 1 + 0 43 1 + 0 44 1 + 0 45 1 + 0 74 1>; + interrupt-names = "vsync", + "demux", + "parser", + "mailbox_0", + "mailbox_1", + "mailbox_2", + "parser_b"; + }; + + amvenc_avc{ + compatible = "amlogic, amvenc_avc"; + dev_name = "amvenc_avc"; + status = "okay"; + interrupts = <0 45 1>; + interrupt-names = "mailbox_2"; + }; + + canvas: canvas { + compatible = "amlogic, meson, canvas"; + status = "okay"; + reg = <0x0 0xff638000 0x0 0x2000>; + }; + + codec_io: codec_io { + compatible = "amlogic, codec_io"; + status = "okay"; + #address-cells=<2>; + #size-cells=<2>; + ranges; + io_cbus_base{ + reg = <0x0 0xffd00000 0x0 0x100000>; + }; + io_dos_base{ + reg = <0x0 0xff620000 0x0 0x10000>; + }; + io_hiubus_base{ + reg = <0x0 0xff63c000 0x0 0x2000>; + }; + io_aobus_base{ + reg = <0x0 0xff800000 0x0 0x10000>; + }; + io_vcbus_base{ + reg = <0x0 0xff900000 0x0 0x40000>; + }; + io_dmc_base{ + reg = <0x0 0xff638000 0x0 0x2000>; + }; + io_efuse_base{ + reg = <0x0 0xff630000 0x0 0x2000>; + }; + }; + + rdma { + compatible = "amlogic, meson-tl1, rdma"; + status = "okay"; + interrupts = <0 89 1>; + interrupt-names = "rdma"; + }; + + meson_fb: fb { + compatible = "amlogic, meson-tm2"; + memory-region = <&logo_reserved>; + status = "disabled"; + interrupts = <0 3 1 + 0 56 1 + 0 89 1>; + interrupt-names = "viu-vsync", "viu2-vsync", "rdma"; + /* uboot logo,fb0/fb1 memory size,if afbcd fb0=0x01851000*/ + display_mode_default = "1080p60hz"; + scale_mode = <1>; + /** 0:VPU free scale 1:OSD free scale 2:OSD super scale */ + display_size_default = <1920 1080 1920 2160 32>; + /*1920*1080*4*3 = 0x17BB000*/ + clocks = <&clkc CLKID_VPU_CLKC_MUX>; + clock-names = "vpu_clkc"; + }; + + ge2d { + compatible = "amlogic, ge2d-sm1"; + status = "okay"; + interrupts = <0 146 1>; + interrupt-names = "ge2d"; + clocks = <&clkc CLKID_VAPB_MUX>, + <&clkc CLKID_G2D>, + <&clkc CLKID_GE2D_GATE>; + clock-names = "clk_vapb_0", + "clk_ge2d", + "clk_ge2d_gate"; + reg = <0x0 0xff940000 0x0 0x10000>; + }; + + meson-amvideom { + compatible = "amlogic, amvideom"; + status = "okay"; + interrupts = <0 3 1>; + interrupt-names = "vsync"; + }; + + ionvideo { + compatible = "amlogic, ionvideo"; + status = "okay"; + }; + + amlvideo { + compatible = "amlogic, amlvideo"; + status = "okay"; + }; + + vdac { + compatible = "amlogic, vdac-tl1"; + status = "okay"; + }; + + ddr_bandwidth { + compatible = "amlogic, ddr-bandwidth"; + status = "disabled"; + reg = <0x0 0xff638000 0x0 0x100 + 0x0 0xff638c00 0x0 0x100>; + interrupts = <0 52 1>; + interrupt-names = "ddr_bandwidth"; + }; + + dmc_monitor { + compatible = "amlogic, dmc_monitor"; + status = "disabled"; + reg_base = <0xff638800>; + interrupts = ; + }; + + efuse: efuse{ + compatible = "amlogic, efuse"; + read_cmd = <0x82000030>; + write_cmd = <0x82000031>; + get_max_cmd = <0x82000033>; + key = <&efusekey>; + clocks = <&clkc CLKID_EFUSE>; + clock-names = "efuse_clk"; + status = "disabled"; + }; + + efusekey:efusekey{ + keynum = <4>; + key0 = <&key_0>; + key1 = <&key_1>; + key2 = <&key_2>; + key3 = <&key_3>; + key_0:key_0{ + keyname = "mac"; + offset = <0>; + size = <6>; + }; + key_1:key_1{ + keyname = "mac_bt"; + offset = <6>; + size = <6>; + }; + key_2:key_2{ + keyname = "mac_wifi"; + offset = <12>; + size = <6>; + }; + key_3:key_3{ + keyname = "usid"; + offset = <18>; + size = <16>; + }; + }; + + audio_data: audio_data { + compatible = "amlogic, audio_data"; + query_licence_cmd = <0x82000050>; + status = "disabled"; + }; + + defendkey: defendkey { + compatible = "amlogic, defendkey"; + mem_size = <0 0x100000>; + status = "okay"; + }; + cpu_ver_name { + compatible = "amlogic, cpu-major-id-tm2"; + }; +}; /* end of / */ + +&pinctrl_aobus { + sd_to_ao_uart_clr_pins: sd_to_ao_uart_clr_pins { + mux { + groups = "GPIOAO_0", + "GPIOAO_1", + "GPIOAO_2", + "GPIOAO_3", + "GPIOAO_4", + "GPIOAO_5", + "GPIOAO_6", + "GPIOAO_7", + "GPIOAO_8", + "GPIOAO_9", + "GPIOAO_10", + "GPIOAO_11", + "GPIOE_0", + "GPIOE_1", + "GPIOE_2", + "GPIO_TEST_N"; + function = "gpio_aobus"; + }; + }; + + sd_to_ao_uart_pins: sd_to_ao_uart_pins { + mux { + groups = "uart_ao_a_tx", + "uart_ao_a_rx", + "uart_ao_a_cts", + "uart_ao_a_rts"; + function = "uart_ao_a"; + bias-pull-up; + input-enable; + }; + }; + + remote_pins:remote_pin { + mux { + groups = "remote_input_ao"; + function = "remote_input_ao"; + }; + }; + + pwm_ao_a_pins: pwm_ao_a { + mux { + groups = "pwm_ao_a"; + function = "pwm_ao_a"; + }; + }; + + pwm_ao_a_hiz_pins: pwm_ao_a_hiz { + mux { + groups = "pwm_ao_a_hiz"; + function = "pwm_ao_a"; + }; + }; + + pwm_ao_b_pins: pwm_ao_b { + mux { + groups = "pwm_ao_b"; + function = "pwm_ao_b"; + }; + }; + + pwm_ao_c_pins1: pwm_ao_c_pins1 { + mux { + groups = "pwm_ao_c_4"; + function = "pwm_ao_c"; + }; + }; + + pwm_ao_c_pins2: pwm_ao_c_pins2 { + mux { + groups = "pwm_ao_c_6"; + function = "pwm_ao_c"; + }; + }; + + pwm_ao_c_hiz_pins1: pwm_ao_c_hiz1 { + mux { + groups = "pwm_ao_c_hiz_4"; + function = "pwm_ao_c"; + }; + }; + + pwm_ao_c_hiz_pins2: pwm_ao_c_hiz2 { + mux { + groups = "pwm_ao_c_hiz_7"; + function = "pwm_ao_c"; + }; + }; + + pwm_ao_d_pins1: pwm_ao_d_pins1 { + mux { + groups = "pwm_ao_d_5"; + function = "pwm_ao_d"; + }; + }; + + pwm_ao_d_pins2: pwm_ao_d_pins2 { + mux { + groups = "pwm_ao_d_10"; + function = "pwm_ao_d"; + }; + }; + + pwm_ao_d_pins3: pwm_ao_d_pins3 { + mux { + groups = "pwm_ao_d_e"; + function = "pwm_ao_d"; + }; + }; + + pwm_a_e2: pwm_a_e2 { + mux { + groups = "pwm_a_e2"; + function = "pwm_a_e2"; + }; + }; + + i2c_ao_2_pins:i2c_ao_2 { + mux { + groups = "i2c_ao_sck_2", + "i2c_ao_sda_3"; + function = "i2c_ao"; + bias-pull-up; + drive-strength = <3>; + }; + }; + + i2c_ao_e_pins:i2c_ao_e { + mux { + groups = "i2c_ao_sck_e", + "i2c_ao_sda_e"; + function = "i2c_ao"; + bias-pull-up; + drive-strength = <3>; + }; + }; + + i2c_ao_slave_pins:i2c_ao_slave { + mux { + groups = "i2c_ao_slave_sck", + "i2c_ao_slave_sda"; + function = "i2c_ao_slave"; + }; + }; + + ao_uart_pins:ao_uart { + mux { + groups = "uart_ao_a_rx", + "uart_ao_a_tx"; + function = "uart_ao_a"; + }; + }; + + ao_b_uart_pins1:ao_b_uart1 { + mux { + groups = "uart_ao_b_tx_2", + "uart_ao_b_rx_3"; + function = "uart_ao_b"; + }; + }; + + ao_b_uart_pins2:ao_b_uart2 { + mux { + groups = "uart_ao_b_tx_8", + "uart_ao_b_rx_9"; + function = "uart_ao_b"; + }; + }; + + irblaster_pins:irblaster_pin { + mux { + groups = "remote_out_ao"; + function = "remote_out_ao"; + }; + }; + + irblaster_pins1:irblaster_pin1 { + mux { + groups = "remote_out_ao9"; + function = "remote_out_ao"; + }; + }; + + jtag_apao_pins:jtag_apao_pin { + mux { + groups = "jtag_a_tdi", + "jtag_a_tdo", + "jtag_a_clk", + "jtag_a_tms"; + function = "jtag_a"; + }; + }; +}; + +&pinctrl_periphs { + /* sdemmc portC */ + emmc_clk_cmd_pins: emmc_clk_cmd_pins { + mux { + groups = "emmc_clk", + "emmc_cmd"; + function = "emmc"; + input-enable; + bias-pull-up; + drive-strength = <2>; + }; + }; + + emmc_conf_pull_up: emmc_conf_pull_up { + mux { + groups = "emmc_nand_d7", + "emmc_nand_d6", + "emmc_nand_d5", + "emmc_nand_d4", + "emmc_nand_d3", + "emmc_nand_d2", + "emmc_nand_d1", + "emmc_nand_d0", + "emmc_clk", + "emmc_cmd"; + function = "emmc"; + input-enable; + bias-pull-up; + drive-strength = <2>; + }; + }; + + emmc_conf_pull_done: emmc_conf_pull_done { + mux { + groups = "emmc_nand_ds"; + function = "emmc"; + input-enable; + bias-pull-down; + drive-strength = <2>; + }; + }; + + /* sdemmc portB */ + sd_clk_cmd_pins: sd_clk_cmd_pins { + mux { + groups = "sdcard_cmd", + "sdcard_clk"; + function = "sdcard"; + input-enable; + bias-pull-up; + drive-strength = <3>; + }; + }; + + sd_all_pins: sd_all_pins { + mux { + groups = "sdcard_d0", + "sdcard_d1", + "sdcard_d2", + "sdcard_d3", + "sdcard_cmd", + "sdcard_clk"; + function = "sdcard"; + input-enable; + bias-pull-up; + drive-strength = <3>; + }; + }; + + sd_1bit_pins: sd_1bit_pins { + mux { + groups = "sdcard_d0", + "sdcard_cmd", + "sdcard_clk"; + function = "sdcard"; + input-enable; + bias-pull-up; + drive-strength = <3>; + }; + }; + + ao_to_sd_uart_pins: ao_to_sd_uart_pins { + mux { + groups ="uart_ao_a_rx_w3", + "uart_ao_a_tx_w2", + "uart_ao_a_rx_w7", + "uart_ao_a_tx_w6", + "uart_ao_a_rx_w11", + "uart_ao_a_tx_w10"; + function = "uart_ao_a_ee"; + bias-pull-up; + input-enable; + }; + }; + + all_nand_pins: all_nand_pins { + mux { + groups = "emmc_nand_d0", + "emmc_nand_d1", + "emmc_nand_d2", + "emmc_nand_d3", + "emmc_nand_d4", + "emmc_nand_d5", + "emmc_nand_d6", + "emmc_nand_d7", + "nand_ce0", + "nand_ale", + "nand_cle", + "nand_wen_clk", + "nand_ren_wr"; + function = "nand"; + input-enable; + drive-strength = <3>; + }; + }; + + nand_cs_pins:nand_cs { + mux { + groups = "nand_ce0"; + function = "nand"; + drive-strength = <3>; + }; + }; + + /* sdemmc port */ + sdio_clk_cmd_pins: sdio_clk_cmd_pins { + mux { + groups = "sdcard_clk", + "sdcard_cmd"; + function = "sdcard"; + input-enable; + bias-pull-up; + drive-strength = <3>; + }; + }; + + sdio_all_pins: sdio_all_pins { + mux { + groups = "sdcard_d0", + "sdcard_d1", + "sdcard_d2", + "sdcard_d3", + "sdcard_clk", + "sdcard_cmd"; + function = "sdcard"; + input-enable; + bias-pull-up; + drive-strength = <3>; + }; + }; + + spifc_cs_pin:spifc_cs_pin { + mux { + groups = "nor_cs"; + function = "nor"; + bias-pull-up; + }; + }; + + spifc_pulldown: spifc_pulldown { + mux { + groups = "nor_d", + "nor_q", + "nor_c"; + function = "nor"; + bias-pull-down; + }; + }; + + spifc_pullup: spifc_pullup { + mux { + groups = "nor_cs"; + function = "nor"; + bias-pull-up; + }; + }; + + spifc_all_pins: spifc_all_pins { + mux { + groups = "nor_d", + "nor_q", + "nor_c", + "nor_hold", + "nor_wp"; + function = "nor"; + input-enable; + bias-pull-down; + }; + }; + + pwm_a_pins: pwm_a { + mux { + groups = "pwm_a"; + function = "pwm_a"; + }; + }; + + pwm_b_pins1: pwm_b_pins1 { + mux { + groups = "pwm_b_c"; + function = "pwm_b"; + }; + }; + + pwm_b_pins2: pwm_b_pins2 { + mux { + groups = "pwm_b_z"; + function = "pwm_b"; + }; + }; + + pwm_c_pins1: pwm_c_pins1 { + mux { + groups = "pwm_c_dv"; + function = "pwm_c"; + }; + }; + + pwm_c_pins2: pwm_c_pins2 { + mux { + groups = "pwm_c_h"; + function = "pwm_c"; + }; + }; + + pwm_c_pins3: pwm_c_pins3 { + mux { + groups = "pwm_c_z"; + function = "pwm_c"; + }; + }; + + pwm_d_pins1: pwm_d_pins1 { + mux { + groups = "pwm_d_dv"; + function = "pwm_d"; + }; + }; + + pwm_d_pins2: pwm_d_pins2 { + mux { + groups = "pwm_d_z"; + function = "pwm_d"; + }; + }; + + pwm_e_pins1: pwm_e1 { + mux { + groups = "pwm_e_dv"; + function = "pwm_e"; + }; + }; + + pwm_e_pins2: pwm_e2 { + mux { + groups = "pwm_e_z"; + function = "pwm_e"; + }; + }; + + pwm_f_pins1: pwm_f_pins1 { + mux { + groups = "pwm_f_dv"; + function = "pwm_f"; + }; + }; + + pwm_f_pins2: pwm_f_pins2 { + mux { + groups = "pwm_f_z"; + function = "pwm_f"; + }; + }; + + i2c0_c_pins:i2c0_c { + mux { + groups = "i2c0_sda_c", + "i2c0_sck_c"; + function = "i2c0"; + bias-pull-up; + drive-strength = <3>; + }; + }; + + i2c0_dv_pins:i2c0_dv { + mux { + groups = "i2c0_sda_dv", + "i2c0_sck_dv"; + function = "i2c0"; + bias-pull-up; + drive-strength = <3>; + }; + }; + + i2c1_z_pins:i2c1_z { + mux { + groups = "i2c1_sda_z", + "i2c1_sck_z"; + function = "i2c1"; + bias-pull-up; + drive-strength = <3>; + }; + }; + + i2c1_h_pins:i2c1_h { + mux { + groups = "i2c1_sda_h", + "i2c1_sck_h"; + function = "i2c1"; + bias-pull-up; + drive-strength = <3>; + }; + }; + + i2c2_h_pins:i2c2_h { + mux { + groups = "i2c2_sda_h", + "i2c2_sck_h"; + function = "i2c2"; + bias-pull-up; + drive-strength = <3>; + }; + }; + + i2c2_z_pins:i2c2_z { + mux { + groups = "i2c2_sda_z", + "i2c2_sck_z"; + function = "i2c2"; + bias-pull-up; + drive-strength = <3>; + }; + }; + + i2c3_h1_pins:i2c3_h1 { + mux { + groups = "i2c3_sda_h1", + "i2c3_sck_h0"; + function = "i2c3"; + bias-pull-up; + drive-strength = <3>; + }; + }; + + i2c3_h20_pins:i2c3_h3 { + mux { + groups = "i2c3_sda_h20", + "i2c3_sck_h19"; + function = "i2c3"; + bias-pull-up; + drive-strength = <3>; + }; + }; + + i2c3_dv_pins:i2c3_dv { + mux { + groups = "i2c3_sda_dv", + "i2c3_sck_dv"; + function = "i2c3"; + bias-pull-up; + drive-strength = <3>; + }; + }; + + i2c3_c_pins:i2c3_c { + mux { + groups = "i2c3_sda_c", + "i2c3_sck_c"; + function = "i2c3"; + bias-pull-up; + drive-strength = <3>; + }; + }; + + spicc0_pins_h: spicc0_pins_h { + mux { + groups = "spi0_mosi_h", + "spi0_miso_h", + "spi0_clk_h"; + function = "spi0"; + drive-strength = <1>; + }; + }; + + spicc1_pins_dv: spicc1_pins_dv { + mux { + groups = "spi1_mosi_dv", + "spi1_miso_dv", + "spi1_clk_dv"; + function = "spi1"; + drive-strength = <1>; + }; + }; + + internal_eth_pins: internal_eth_pins { + mux { + groups = "eth_link_led", + "eth_act_led"; + function = "eth"; + }; + }; + + internal_gpio_pins: internal_gpio_pins { + mux { + groups = "GPIOZ_14", + "GPIOZ_15"; + function = "gpio_periphs"; + bias-disable; + input-enable; + }; + }; + + external_eth_pins: external_eth_pins { + mux { + groups = "eth_mdio", + "eth_mdc", + "eth_rgmii_rx_clk", + "eth_rx_dv", + "eth_rxd0", + "eth_rxd1", + "eth_rxd2_rgmii", + "eth_rxd3_rgmii", + "eth_rgmii_tx_clk", + "eth_txen", + "eth_txd0", + "eth_txd1", + "eth_txd2_rgmii", + "eth_txd3_rgmii"; + function = "eth"; + drive-strength = <3>; + }; + }; + + a_uart_pins:a_uart { + mux { + groups = "uart_a_tx", + "uart_a_rx", + "uart_a_cts", + "uart_a_rts"; + function = "uart_a"; + }; + }; + + b_uart_pins:b_uart { + mux { + groups = "uart_b_tx", + "uart_b_rx"; + function = "uart_b"; + }; + }; + + c_uart_pins:c_uart { + mux { + groups = "uart_c_tx", + "uart_c_rx"; + function = "uart_c"; + }; + }; + + atvdemod_agc_pins: atvdemod_agc_pins { + mux { + groups = "atv_if_agc_dv"; + function = "atv"; + }; + }; + + dtvdemod_agc_pins: dtvdemod_agc_pins { + mux { + groups = "dtv_if_agc_dv2"; + function = "dtv"; + }; + }; + + lcd_vbyone_pins: lcd_vbyone_pin { + mux { + groups = "vx1_lockn","vx1_htpdn"; + function = "vx1"; + }; + }; + lcd_vbyone_off_pins: lcd_vbyone_off_pin { + mux { + groups = "GPIOH_15","GPIOH_16"; + function = "gpio_periphs"; + input-enable; + }; + }; + + lcd_tcon_pins: lcd_tcon_pin { + mux { + groups = "tcon_0","tcon_1","tcon_2","tcon_3", + "tcon_4","tcon_5","tcon_6","tcon_7", + "tcon_8","tcon_9","tcon_10","tcon_11", + "tcon_12","tcon_13","tcon_14","tcon_15", + "tcon_lock","tcon_spi_mo","tcon_spi_mi", + "tcon_spi_clk","tcon_spi_ss"; + function = "tcon"; + }; + }; + lcd_tcon_off_pins: lcd_tcon_off_pin { + mux { + groups = "GPIOH_0","GPIOH_1","GPIOH_2","GPIOH_3", + "GPIOH_4","GPIOH_5","GPIOH_6","GPIOH_7", + "GPIOH_8","GPIOH_9","GPIOH_10","GPIOH_11", + "GPIOH_12","GPIOH_13","GPIOH_14","GPIOH_15", + "GPIOH_16","GPIOH_17","GPIOH_18","GPIOH_19", + "GPIOH_20"; + function = "gpio_periphs"; + input-enable; + }; + }; +}; + +&gpu{ + tbl = <&dvfs285_cfg + &dvfs400_cfg + &dvfs500_cfg + &dvfs666_cfg + &dvfs800_cfg + &dvfs800_cfg>; +}; diff --git a/arch/arm64/boot/dts/amlogic/mesontm2_t962x3_ab301-panel.dtsi b/arch/arm64/boot/dts/amlogic/mesontm2_t962x3_ab301-panel.dtsi new file mode 100644 index 000000000000..e0c2c99489ba --- /dev/null +++ b/arch/arm64/boot/dts/amlogic/mesontm2_t962x3_ab301-panel.dtsi @@ -0,0 +1,1066 @@ +/* + * arch/arm64/boot/dts/amlogic/mesontm2_t962x3_ab301-panel.dtsi + * + * Copyright (C) 2018 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. + * + */ + +/ { + lcd { + compatible = "amlogic, lcd-tm2"; + status = "okay"; + mode = "tv"; + fr_auto_policy = <1>; /* 0=disable, 1=60/50hz, 2=60/50/48hz */ + key_valid = <0>; + clocks = <&clkc CLKID_VCLK2_ENCL + &clkc CLKID_VCLK2_VENCL + &clkc CLKID_TCON + &clkc CLKID_FCLK_DIV5 + &clkc CLKID_TCON_PLL_COMP>; + clock-names = "encl_top_gate", + "encl_int_gate", + "tcon_gate", + "fclk_div5", + "clk_tcon"; + reg = <0x0 0xff660000 0x0 0x8100 + 0x0 0xff634400 0x0 0x300>; + interrupts = <0 3 1 + 0 78 1 + 0 88 1>; + interrupt-names = "vsync","vbyone","tcon"; + pinctrl-names = "vbyone","vbyone_off","tcon","tcon_off"; + pinctrl-0 = <&lcd_vbyone_pins>; + pinctrl-1 = <&lcd_vbyone_off_pins>; + pinctrl-2 = <&lcd_tcon_pins>; + pinctrl-3 = <&lcd_tcon_off_pins>; + pinctrl_version = <2>; /* for uboot */ + memory-region = <&lcd_tcon_reserved>; + + /* power type:(0=cpu_gpio, 2=signal, 3=extern, 0xff=ending) */ + /* power index:(gpios_index, or extern_index, 0xff=invalid) */ + /* power value:(0=output low, 1=output high, 2=input) */ + /* power delay:(unit in ms) */ + lcd_cpu-gpios = <&gpio_ao GPIOAO_4 GPIO_ACTIVE_HIGH + &gpio GPIOH_2 GPIO_ACTIVE_HIGH + &gpio GPIOH_3 GPIO_ACTIVE_HIGH + &gpio GPIOH_12 GPIO_ACTIVE_HIGH + &gpio GPIOH_8 GPIO_ACTIVE_HIGH + &gpio GPIOH_10 GPIO_ACTIVE_HIGH + &gpio GPIOH_11 GPIO_ACTIVE_HIGH + &gpio GPIOH_14 GPIO_ACTIVE_HIGH>; + lcd_cpu_gpio_names = "GPIOAO_4","GPIOH_2","GPIOH_3","GPIOH_12", + "GPIOH_8","GPIOH_10","GPIOH_11","GPIOH_14"; + + lvds_0{ + model_name = "1080p-vfreq"; + interface = "lvds"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 1920 1080 /*h_active, v_active*/ + 2200 1125 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 2060 2650 /*h_period_min,max*/ + 1100 1480 /*v_period_min,max*/ + 120000000 160000000>; /*pclk_min,max*/ + lcd_timing = < + 44 148 0 /*hs_width, hs_bp, hs_pol*/ + 5 30 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 15 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + lvds_attr = < + 1 /*lvds_repack*/ + 1 /*dual_port*/ + 0 /*pn_swap*/ + 0 /*port_swap*/ + 0>; /*lane_reverse*/ + phy_attr=<0xf 0>; /*vswing_level, preem_level*/ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 0 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0>; + }; + + lvds_1{ + model_name = "1080p-hfreq_hdmi"; + interface = "lvds"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 1920 1080 /*h_active, v_active*/ + 2200 1125 /*h_period, v_period*/ + 8 /*lcd_bits*/ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 2080 2720 /*h_period min, max*/ + 1100 1380 /*v_period min, max*/ + 133940000 156000000>; /*pclk_min, max*/ + lcd_timing = < + 44 148 0 /*hs_width, hs_bp, hs_pol*/ + 5 30 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 4 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 0 /*clk_ss_level */ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + lvds_attr = < + 1 /*lvds_repack*/ + 1 /*dual_port*/ + 0 /*pn_swap*/ + 0 /*port_swap*/ + 0>; /*lane_reverse*/ + phy_attr=<0xf 0>; /*vswing_level, preem_level*/ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 0 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0>; + }; + lvds_2{ + model_name = "768p-vfreq"; + interface = "lvds"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 1366 768 /*h_active, v_active*/ + 1560 806 /*h_period, v_period*/ + 8 /*lcd_bits*/ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 1460 2000 /*h_period_min, max */ + 784 1015 /*v_period_min, max */ + 50000000 85000000>; /*pclk_min, max*/ + lcd_timing = < + 56 64 0 /*hs_width, hs_bp, hs_pol*/ + 3 28 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 15 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + lvds_attr = < + 1 /*lvds_repack*/ + 0 /*dual_port*/ + 0 /*pn_swap*/ + 0 /*port_swap*/ + 0>; /*lane_reverse*/ + phy_attr=<0xf 0>; /*vswing_level, preem_level*/ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 0 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0>; + }; + vbyone_0{ + model_name = "public_2region"; + interface = "vbyone"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 10 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 4800 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 33 477 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + vbyone_attr = < + 8 /*lane_count*/ + 2 /*region_num*/ + 4 /*byte_mode*/ + 4>; /*color_fmt*/ + vbyone_intr_enable = < + 1 /*vbyone_intr_enable */ + 3>; /*vbyone_vsync_intr_enable*/ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = <0 0 1 50 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = <2 0 0 10 /*signal disable*/ + 0 0 0 200 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <2>; + }; + vbyone_1{ + model_name = "public_1region"; + interface = "vbyone"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 10 /*lcd_bits*/ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 4800 /*h_period_min, max*/ + 2200 2790 /*v_period_min, max*/ + 552000000 632000000>; /*pclk_min,max*/ + lcd_timing = < + 33 477 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + vbyone_attr = < + 8 /*lane_count*/ + 1 /*region_num*/ + 4 /*byte_mode*/ + 4>; /*color_fmt*/ + vbyone_intr_enable = < + 1 /*vbyone_intr_enable*/ + 3>; /*vbyone_vsync_intr_enable*/ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 50 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 200 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <2>; + }; + vbyone_2{ + model_name = "public_2region_hdmi"; + interface = "vbyone"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 10 /*lcd_bits*/ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 4800 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*v_period_min, max*/ + lcd_timing = < + 33 477 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 4 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 0 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + vbyone_attr = < + 8 /*lane_count*/ + 2 /*region_num*/ + 4 /*byte_mode*/ + 4>; /*color_fmt*/ + vbyone_intr_enable = < + 1 /*vbyone_intr_enable*/ + 3>; /*vbyone_vsync_intr_enable*/ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 50 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 200 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <2>; + }; + vbyone_3{ + model_name = "BOE_HV550QU2"; + interface = "vbyone"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 10 /*lcd_bits*/ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 4800 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 560000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 33 477 1 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + vbyone_attr = < + 8 /*lane_count*/ + 2 /*region_num*/ + 4 /*byte_mode*/ + 4>; /*color_fmt*/ + vbyone_intr_enable = < + 1 /*vbyone_intr_enable*/ + 3>; /*vbyone_vsync_intr_enable*/ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 0 3 0 10 /*3d_disable*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 3 2 0 /*3d_disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <2>; + }; + vbyone_4{ + model_name = "BOE_HV550QU2_1region"; + interface = "vbyone"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 10 /*lcd_bits*/ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 4800 /*h_period_min,max*/ + 2200 2760 /*v_period_min,max*/ + 560000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 33 477 1 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + vbyone_attr = < + 8 /*lane_count*/ + 1 /*region_num*/ + 4 /*byte_mode*/ + 4>; /*color_fmt*/ + vbyone_intr_enable = < + 1 /*vbyone_intr_enable*/ + 3>; /*vbyone_vsync_intr_enable*/ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 0 3 0 10 /*3d_disable*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 3 2 0 /*3d_disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <2>; + }; + p2p_0{ + model_name = "p2p_ceds"; + interface = "p2p"; /*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 5000 2250 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 5100 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 16 29 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + p2p_attr = < + 0x0 /* p2p_teyp: + * 0x0=ceds, 0x1=cmpi, 0x2=isp, 0x3=epi, + * 0x10=chpi, 0x11=cspi, 0x12=usit + */ + 12 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 3 2 0 200 /* extern init voltage */ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + p2p_1{ + model_name = "p2p_ceds"; + interface = "p2p"; /*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 5000 2250 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 5100 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 16 29 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + p2p_attr = < + 0x0 /* p2p_teyp: + * 0x0=ceds, 0x1=cmpi, 0x2=isp, 0x3=epi, + * 0x10=chpi, 0x11=cspi, 0x12=usit + */ + 6 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + p2p_2{ + model_name = "p2p_chpi"; + interface = "p2p"; /*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 5100 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 16 29 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + p2p_attr = < + 0x10 /* p2p_teyp: + * 0x0=ceds, 0x1=cmpi, 0x2=isp, 0x3=epi, + * 0x10=chpi, 0x11=cspi, 0x12=usit + */ + 6 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + p2p_3{ + model_name = "p2p_chpi"; + interface = "p2p"; /*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 5100 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 16 29 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + p2p_attr = < + 0x10 /* p2p_teyp: + * 0x0=ceds, 0x1=cmpi, 0x2=isp, 0x3=epi, + * 0x10=chpi, 0x11=cspi, 0x12=usit + */ + 12 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + mlvds_0{ + model_name = "mlvds_1080p"; + interface = "minilvds"; /*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 1920 1080 /*h_active, v_active*/ + 2200 1125 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 2080 2720 /*h_period_min, max*/ + 2200 1125 /*v_period_min, max*/ + 133940000 156000000>; /*pclk_min, max*/ + lcd_timing = < + 44 148 0 /*hs_width, hs_bp, hs_pol*/ + 5 30 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + minilvds_attr = < + 6 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0x660 /* clk_phase */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 0>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + mlvds_1{ + model_name = "mlvds_768p"; + interface = "minilvds";/*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 1366 768 /*h_active, v_active*/ + 1560 806 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 1460 2000 /*h_period_min, max*/ + 784 1015 /*v_period_min, max*/ + 50000000 85000000>; /*pclk_min, max*/ + lcd_timing = < + 56 64 0 /*hs_width, hs_bp, hs_pol*/ + 3 28 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 3 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + minilvds_attr = < + 6 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0x660 /* clk_phase */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 0>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 0 0 1 20 /*panel power on*/ + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0 0 0 100 /*panel power off*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + }; + + lcd_extern{ + compatible = "amlogic, lcd_extern"; + status = "okay"; + key_valid = <0>; + i2c_bus = "i2c_bus_1"; + + extern_0{ + index = <0>; + extern_name = "ext_default"; + status = "disabled"; + type = <0>; /*0=i2c, 1=spi, 2=mipi*/ + i2c_address = <0x1c>; /*7bit i2c_addr*/ + i2c_address2 = <0xff>; + cmd_size = <0xff>; /*dynamic cmd_size*/ + + /* init on/off: + * fixed cmd_size: (type, value...); + * cmd_size include all data. + * dynamic cmd_size: (type, cmd_size, value...); + * cmd_size include value. + */ + /* type: 0x00=cmd with delay(bit[3:0]=1 for address2), + * 0xc0=cmd(bit[3:0]=1 for address2), + * 0xf0=gpio, + * 0xfd=delay, + * 0xff=ending + */ + /* value: i2c or spi cmd, or gpio index & level */ + /* delay: unit ms */ + init_on = < + 0xc0 7 0x20 0x01 0x02 0x00 0x40 0xFF 0x00 + 0xc0 7 0x80 0x02 0x00 0x40 0x62 0x51 0x73 + 0xc0 7 0x61 0x06 0x00 0x00 0x00 0x00 0x00 + 0xc0 7 0xC1 0x05 0x0F 0x00 0x08 0x70 0x00 + 0xc0 7 0x13 0x01 0x00 0x00 0x00 0x00 0x00 + 0xc0 7 0x3D 0x02 0x01 0x00 0x00 0x00 0x00 + 0xc0 7 0xED 0x0D 0x01 0x00 0x00 0x00 0x00 + 0xc0 7 0x23 0x02 0x00 0x00 0x00 0x00 0x00 + 0xfd 1 10 /* delay 10ms */ + 0xff 0>; /*ending*/ + init_off = <0xff 0>; /*ending*/ + }; + extern_1{ + index = <1>; + extern_name = "i2c_T5800Q"; + status = "disabled"; + type = <0>; /* 0=i2c, 1=spi, 2=mipi */ + i2c_address = <0x1c>; /* 7bit i2c address */ + }; + extern_2{ + index = <2>; + extern_name = "i2c_ANX6862_7911"; + status = "okay"; + type = <0>; /* 0=i2c, 1=spi, 2=mipi */ + i2c_address = <0x20>; /* 7bit i2c address */ + i2c_address2 = <0x74>; /* 7bit i2c address */ + cmd_size = <0xff>; + + init_on = < + 0xc0 2 0x01 0x2b + 0xc0 2 0x02 0x05 + 0xc0 2 0x03 0x00 + 0xc0 2 0x04 0x00 + 0xc0 2 0x05 0x0c + 0xc0 2 0x06 0x04 + 0xc0 2 0x07 0x21 + 0xc0 2 0x08 0x0f + 0xc0 2 0x09 0x04 + 0xc0 2 0x0a 0x00 + 0xc0 2 0x0b 0x04 + 0xc0 2 0xff 0x00 + 0xfd 1 100 /* delay 100ms */ + + 0xc1 2 0x01 0xca + 0xc1 2 0x02 0x3b + 0xc1 2 0x03 0x33 + 0xc1 2 0x04 0x05 + 0xc1 2 0x05 0x2c + 0xc1 2 0x06 0xf2 + 0xc1 2 0x07 0x9c + 0xc1 2 0x08 0x1b + 0xc1 2 0x09 0x82 + 0xc1 2 0x0a 0x3d + 0xc1 2 0x0b 0x20 + 0xc1 2 0x0c 0x11 + 0xc1 2 0x0d 0xc4 + 0xc1 2 0x0e 0x1a + 0xc1 2 0x0f 0x31 + 0xc1 2 0x10 0x4c + 0xc1 2 0x11 0x12 + 0xc1 2 0x12 0x90 + 0xc1 2 0x13 0xf7 + 0xc1 2 0x14 0x0c + 0xc1 2 0x15 0x20 + 0xc1 2 0x16 0x13 + 0xff 0>; /*ending*/ + init_off = <0xff 0>; /*ending*/ + }; + }; + + backlight{ + compatible = "amlogic, backlight-tm2"; + status = "okay"; + key_valid = <0>; + pinctrl-names = "pwm_on","pwm_vs_on", + "pwm_combo_0_1_on", + "pwm_combo_0_vs_1_on", + "pwm_combo_0_1_vs_on", + "pwm_off", + "pwm_combo_off"; + pinctrl-0 = <&pwm_c_pins3>; + pinctrl-1 = <&bl_pwm_vs_on_pins>; + pinctrl-2 = <&pwm_c_pins3 &pwm_d_pins2>; + pinctrl-3 = <&bl_pwm_combo_0_vs_on_pins &pwm_d_pins2>; + pinctrl-4 = <&pwm_c_pins3 &bl_pwm_combo_1_vs_on_pins>; + pinctrl-5 = <&bl_pwm_off_pins>; + pinctrl-6 = <&bl_pwm_combo_off_pins>; + pinctrl_version = <2>; /* for uboot */ + interrupts = <0 3 1>; + interrupt-names = "ldim_vsync"; + bl_pwm_config = <&bl_pwm_conf>; + + /* pwm port: PWM_A, PWM_B, PWM_C, PWM_D, PWM_E, PWM_F, PWM_VS*/ + /* power index:(point gpios_index, 0xff=invalid) */ + /* power value:(0=output low, 1=output high, 2=input) */ + /* power delay:(unit in ms) */ + bl-gpios = <&gpio_ao GPIOAO_11 GPIO_ACTIVE_HIGH + &gpio GPIOZ_5 GPIO_ACTIVE_HIGH + &gpio GPIOZ_6 GPIO_ACTIVE_HIGH>; + bl_gpio_names = "GPIOAO_11","GPIOZ_5","GPIOZ_6"; + + backlight_0{ + index = <0>; + bl_name = "backlight_pwm"; + bl_level_default_uboot_kernel = <100 100>; + bl_level_attr = <255 10 /*max, min*/ + 128 128>; /*mid, mid_mapping*/ + bl_ctrl_method = <1>; /*1=pwm,2=pwm_combo,3=ldim*/ + bl_power_attr = <0 /*en_gpio_index*/ + 1 0 /*on_value, off_value*/ + 200 200>; /*on_delay(ms), off_delay(ms)*/ + bl_pwm_port = "PWM_C"; + bl_pwm_attr = <1 /*pwm_method(0=negative, 1=positvie)*/ + 180 /*pwm_freq(pwm:Hz, pwm_vs:multiple of vs)*/ + 100 25>; /*duty_max(%), duty_min(%)*/ + bl_pwm_power = <1 0 /*pwm_gpio_index, pwm_gpio_off*/ + 10 10>; /*pwm_on_delay(ms), pwm_off_delay(ms)*/ + bl_pwm_en_sequence_reverse = <0>; /* 1 for reverse */ + }; + backlight_1{ + index = <1>; + bl_name = "backlight_pwm_vs"; + bl_level_default_uboot_kernel = <100 100>; + bl_level_attr = <255 10 /*max, min*/ + 128 128>; /*mid, mid_mapping*/ + bl_ctrl_method = <1>; /*1=pwm,2=pwm_combo,3=ldim*/ + bl_power_attr = <0 /*en_gpio_index*/ + 1 0 /*on_value, off_value*/ + 200 200>; /* on_delay(ms), off_delay(ms)*/ + bl_pwm_port = "PWM_VS"; + bl_pwm_attr = <1 /*pwm_method(0=negative, 1=positvie)*/ + 2 /*pwm_freq(pwm:Hz, pwm_vs:multiple of vs)*/ + 100 25>; /*duty_max(%), duty_min(%)*/ + bl_pwm_power = <1 0 /*pwm_gpio_index, pwm_gpio_off*/ + 10 10>; /*pwm_on_delay(ms), pwm_off_delay(ms)*/ + bl_pwm_en_sequence_reverse = <0>; /* 1 for reverse */ + }; + backlight_2{ + index = <2>; + bl_name = "backlight_pwm_combo"; + bl_level_default_uboot_kernel = <31 100>; + bl_level_attr = <255 10 /*max, min*/ + 128 128>; /*mid, mid_mapping*/ + bl_ctrl_method = <2>; /*1=pwm,2=pwm_combo,3=ldim*/ + bl_power_attr = <0 /*en_gpio_index*/ + 1 0 /*on_value, off_value*/ + 410 110>; /*on_delay(ms), off_delay(ms)*/ + bl_pwm_combo_level_mapping = <255 10 /*pwm_0 range*/ + 0 0>; /*pwm_1 range*/ + bl_pwm_combo_port = "PWM_C","PWM_D"; + bl_pwm_combo_attr = <1 /*pwm0 method*/ + 180 /*pwm0 freq(pwm:Hz, pwm_vs:multiple of vs)*/ + 100 25 /*pwm0 duty_max(%), duty_min(%)*/ + 1 /*pwm1 method*/ + 18000 /*pwm1 freq(pwm:Hz, pwm_vs:multi of vs)*/ + 80 80>; /*pwm1 duty_max(%), duty_min(%)*/ + bl_pwm_combo_power = <1 0 /*pwm0 gpio_index, gpio_off*/ + 2 0 /*pwm1 gpio_index, gpio_off*/ + 10 10>; /*pwm_on_delay(ms), pwm_off_delay(ms)*/ + }; + backlight_3{ + index = <3>; + bl_name = "pwm_combo_ldim_test"; + bl_level_default_uboot_kernel = <31 100>; + bl_level_attr = <255 10 /*max, min*/ + 128 128>; /*mid, mid_mapping*/ + bl_ctrl_method = <2>; /*1=pwm,2=pwm_combo,3=ldim*/ + bl_power_attr = <0 /*en_gpio_index*/ + 1 0 /*on_value, off_value*/ + 410 110>; /*on_delay(ms), off_delay(ms)*/ + bl_pwm_combo_level_mapping = <255 10 /*pwm_0 range*/ + 0 0>; /*pwm_1 range*/ + bl_pwm_combo_port = "PWM_C","PWM_D"; + bl_pwm_combo_attr = <1 /*pwm0 method*/ + 180 /*pwm0 freq(pwm:Hz, pwm_vs:multiple of vs)*/ + 100 25 /*pwm0 duty_max(%), duty_min(%)*/ + 1 /*pwm1 method*/ + 18000 /*pwm1 freq(pwm:Hz, pwm_vs:multi of vs)*/ + 80 80>; /*pwm1 duty_max(%), duty_min(%)*/ + bl_pwm_combo_power = <1 0 /*pwm0 gpio_index, gpio_off*/ + 2 0 /*pwm1 gpio_index, gpio_off*/ + 10 10>; /*pwm_on_delay(ms), pwm_off_delay(ms)*/ + bl_ldim_region_row_col = <2 10>; + }; + backlight_4{ + index = <4>; + bl_name = "ldim_global"; + bl_level_default_uboot_kernel = <100 100>; + bl_level_attr = <255 10 /*max, min*/ + 128 128>; /*mid, mid_mapping*/ + bl_ctrl_method = <3>; /*1=pwm,2=pwm_combo,3=ldim*/ + bl_power_attr = <0xff /*en_gpio_index*/ + 1 0 /*on_value, off_value*/ + 200 200>; /*on_delay(ms), off_delay(ms)*/ + bl_ldim_region_row_col = <1 1>; + bl_ldim_mode = <1>; /*0=left/right side + *1=top/bottom side + *2=direct + */ + ldim_dev_index = <1>; + }; + backlight_5{ + index = <5>; + bl_name = "ldim_iw7027"; + bl_level_default_uboot_kernel = <100 100>; + bl_level_attr = <255 10 /*max, min*/ + 128 128>; /*mid, mid_mapping*/ + bl_ctrl_method = <3>; /*1=pwm,2=pwm_combo,3=ldim*/ + bl_power_attr = <0 /*en_gpio_index*/ + 1 0 /*on_value, off_value*/ + 200 200>; /*on_delay(ms), off_delay(ms)*/ + bl_ldim_region_row_col = <1 10>; + bl_ldim_mode = <1>; /*0=left/right side + *1=top/bottom side + *2=direct + */ + ldim_dev_index = <2>; + }; + }; + + bl_pwm_conf:bl_pwm_conf{ + pwm_channel_0 { + pwm_port_index = <2>; + pwms = <&pwm_cd MESON_PWM_0 30040 0>; + }; + pwm_channel_1 { + pwm_port_index = <3>; + pwms = <&pwm_cd MESON_PWM_1 30040 0>; + }; + }; + + local_dimming_device { + compatible = "amlogic, ldim_dev"; + status = "okay"; + pinctrl-names = "ldim_pwm", + "ldim_pwm_vs", + "ldim_pwm_combo", + "ldim_pwm_vs_combo", + "ldim_pwm_off", + "ldim_pwm_combo_off"; + pinctrl-0 = <&pwm_c_pins3>; + pinctrl-1 = <&bl_pwm_vs_on_pins>; + pinctrl-2 = <&pwm_c_pins3 &pwm_d_pins2>; + pinctrl-3 = <&bl_pwm_vs_on_pins &pwm_d_pins2>; + pinctrl-4 = <&bl_pwm_off_pins>; + pinctrl-5 = <&bl_pwm_combo_off_pins>; + pinctrl_version = <1>; /* for uboot */ + ldim_pwm_config = <&bl_pwm_conf>; + + /* pwm port: PWM_A, PWM_B, PWM_C, PWM_D, PWM_E, PWM_F, PWM_VS*/ + ldim_dev-gpios = <&gpio_ao GPIOAO_11 GPIO_ACTIVE_HIGH + &gpio GPIOZ_5 GPIO_ACTIVE_HIGH + &gpio GPIOZ_6 GPIO_ACTIVE_HIGH>; + ldim_dev_gpio_names = "GPIOAO_11","GPIOZ_5","GPIOZ_6"; + + ldim_dev_0 { + index = <0>; + type = <0>; /*0=normal, 1=spi, 2=i2c*/ + ldim_dev_name = "ob3350"; + ldim_pwm_port = "PWM_C"; + ldim_pwm_attr = <0 /* pol */ + 200 /*freq(pwm:Hz, pwm_vs:multiple of vs)*/ + 50>;/*default duty(%)*/ + en_gpio_on_off = <0 /*ldim_dev-gpios index*/ + 1 0>; /*on_level, off_level*/ + dim_max_min = <100 20>; /*dim_max, dim_min*/ + }; + ldim_dev_1 { + index = <1>; + type = <0>; /*0=normal, 1=spi, 2=i2c*/ + ldim_dev_name = "global"; + ldim_pwm_port = "PWM_C"; + ldim_pwm_attr = <1 /* pol */ + 180 /*freq(pwm:Hz, pwm_vs:multiple of vs)*/ + 50>;/*default duty(%)*/ + analog_pwm_port = "PWM_D"; + analog_pwm_attr = <1 /*pol(0=negative, 1=positvie)*/ + 18000 /*freq(pwm:Hz)*/ + 100 25 /*duty_max(%), duty_min(%)*/ + 80>; /*default duty(%)*/ + en_gpio_on_off = <0 /*ldim_dev-gpios index*/ + 1 0>; /*on_level, off_level*/ + dim_max_min = <100 20>; /*dim_max, dim_min*/ + }; + + ldim_dev_2 { + index = <2>; + type = <1>; /* 0=normal,1=spi,2=i2c */ + ldim_dev_name = "iw7027"; + ldim_pwm_port = "PWM_VS"; + ldim_pwm_attr = <1 /* pol */ + 2 /*freq(pwm:Hz, pwm_vs:multiple of vs)*/ + 50>;/*default duty(%)*/ + spi_bus_num = <0>; + spi_chip_select = <0>; + spi_max_frequency = <1000000>; /* unit: hz */ + spi_mode = <0>; /* mode: 0, 1, 2, 3 */ + spi_cs_delay = <10 /* hold_high_delay */ + 100>; /* clk_cs_delay (unit: us) */ + en_gpio_on_off = <0 /* ldim_dev-gpios index */ + 1 /* on_level */ + 0>; /* off_level */ + lamp_err_gpio = <0xff>; + /* ldim_dev-gpios index, 0xff=invalid */ + spi_write_check = <0>; /* 0=disable, 1=enable */ + + dim_max_min = <0xfff 0x7f>; /* dim_max, dim_min */ + ldim_region_mapping = <0 1 2 3 4 5 6 7 8 9>; + + cmd_size = <0xff>; + /* init: (type, data...) */ + /* type: 0x00=cmd with delay, + * 0xc0=cmd, + * 0xfd=delay, + * 0xff=ending + */ + /* data: spi data, fill 0x0 for no use */ + /* delay: unit ms */ + init_on = < + 0xc0 2 0x23 0x03 + 0xc0 2 0x24 0xff + 0xc0 2 0x25 0x00 + 0xc0 2 0x26 0x00 + 0xc0 2 0x27 0x60 + 0xc0 2 0x29 0x00 + 0xc0 2 0x2a 0x00 + 0xc0 2 0x2b 0x00 + 0xc0 2 0x2c 0x73 + 0xc0 2 0x2d 0x37 + 0xc0 2 0x31 0x93 + 0xc0 2 0x32 0x0f + 0xc0 2 0x33 0xff + 0xc0 2 0x34 0xc8 + 0xc0 2 0x35 0xbf + 0xff 0>; + init_off = <0xff 0>; + }; + }; +}; /* end of / */ diff --git a/arch/arm64/boot/dts/amlogic/mesontm2_t962x3_ab309-panel.dtsi b/arch/arm64/boot/dts/amlogic/mesontm2_t962x3_ab309-panel.dtsi new file mode 100644 index 000000000000..6f74572fb3b0 --- /dev/null +++ b/arch/arm64/boot/dts/amlogic/mesontm2_t962x3_ab309-panel.dtsi @@ -0,0 +1,585 @@ +/* + * arch/arm64/boot/dts/amlogic/mesontm2_t962x3_ab309-panel.dtsi + * + * Copyright (C) 2018 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. + * + */ + +/ { + lcd { + compatible = "amlogic, lcd-tm2"; + status = "okay"; + mode = "tv"; + fr_auto_policy = <0>; /* 0=disable, 1=60/50hz, 2=60/50/48hz */ + key_valid = <0>; + clocks = <&clkc CLKID_VCLK2_ENCL + &clkc CLKID_VCLK2_VENCL + &clkc CLKID_TCON + &clkc CLKID_FCLK_DIV5 + &clkc CLKID_TCON_PLL_COMP>; + clock-names = "encl_top_gate", + "encl_int_gate", + "tcon_gate", + "fclk_div5", + "clk_tcon"; + reg = <0x0 0xff660000 0x0 0x8100 + 0x0 0xff634400 0x0 0x300>; + interrupts = <0 3 1 + 0 78 1 + 0 88 1>; + interrupt-names = "vsync","vbyone","tcon"; + pinctrl-names = "vbyone","vbyone_off","tcon","tcon_off"; + pinctrl-0 = <&lcd_vbyone_pins>; + pinctrl-1 = <&lcd_vbyone_off_pins>; + pinctrl-2 = <&lcd_tcon_pins>; + pinctrl-3 = <&lcd_tcon_off_pins>; + pinctrl_version = <2>; /* for uboot */ + + /* power type:(0=cpu_gpio, 2=signal, 3=extern, 0xff=ending) */ + /* power index:(gpios_index, or extern_index, 0xff=invalid) */ + /* power value:(0=output low, 1=output high, 2=input) */ + /* power delay:(unit in ms) */ + + lvds_0{ + model_name = "1080p-vfreq"; + interface = "lvds"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 1920 1080 /*h_active, v_active*/ + 2200 1125 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 2060 2650 /*h_period_min,max*/ + 1100 1480 /*v_period_min,max*/ + 120000000 160000000>; /*pclk_min,max*/ + lcd_timing = < + 44 148 0 /*hs_width, hs_bp, hs_pol*/ + 5 30 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 0 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + lvds_attr = < + 1 /*lvds_repack*/ + 1 /*dual_port*/ + 0 /*pn_swap*/ + 0 /*port_swap*/ + 0>; /*lane_reverse*/ + phy_attr=<0xf 0>; /*vswing_level, preem_level*/ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 2 0 0 0 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + lvds_1{ + model_name = "1080p-hfreq_hdmi"; + interface = "lvds"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 1920 1080 /*h_active, v_active*/ + 2200 1125 /*h_period, v_period*/ + 8 /*lcd_bits*/ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 2080 2720 /*h_period min, max*/ + 1100 1380 /*v_period min, max*/ + 133940000 156000000>; /*pclk_min, max*/ + lcd_timing = < + 44 148 0 /*hs_width, hs_bp, hs_pol*/ + 5 30 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 4 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 0 /*clk_ss_level */ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + lvds_attr = < + 1 /*lvds_repack*/ + 1 /*dual_port*/ + 0 /*pn_swap*/ + 0 /*port_swap*/ + 0>; /*lane_reverse*/ + phy_attr=<0xf 0>; /*vswing_level, preem_level*/ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 2 0 0 0 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + vbyone_0{ + model_name = "public_2region"; + interface = "vbyone"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 10 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 4800 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 33 477 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 0 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + vbyone_attr = < + 8 /*lane_count*/ + 2 /*region_num*/ + 4 /*byte_mode*/ + 4>; /*color_fmt*/ + vbyone_intr_enable = < + 1 /*vbyone_intr_enable */ + 3>; /*vbyone_vsync_intr_enable*/ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + vbyone_1{ + model_name = "public_1region"; + interface = "vbyone"; /*lcd_interface(lvds, vbyone)*/ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 10 /*lcd_bits*/ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 4800 /*h_period_min, max*/ + 2200 2790 /*v_period_min, max*/ + 552000000 632000000>; /*pclk_min,max*/ + lcd_timing = < + 33 477 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 0 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + vbyone_attr = < + 8 /*lane_count*/ + 1 /*region_num*/ + 4 /*byte_mode*/ + 4>; /*color_fmt*/ + vbyone_intr_enable = < + 1 /*vbyone_intr_enable*/ + 3>; /*vbyone_vsync_intr_enable*/ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + p2p_0{ + model_name = "p2p_ceds"; + interface = "p2p"; /*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 5000 2250 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 5100 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 16 29 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 0 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + p2p_attr = < + 0 /* teyp: 0=ceds, 1=cmpi, 2=isp, 3=epi, + * 10=chpi, 11=cspi, 12=usit + */ + 12 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + p2p_1{ + model_name = "p2p_ceds"; + interface = "p2p"; /*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 5000 2250 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 5100 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 16 29 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 0 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + p2p_attr = < + 0 /* teyp: 0=ceds, 1=cmpi, 2=isp, 3=epi, + * 10=chpi, 11=cspi, 12=usit + */ + 6 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + p2p_2{ + model_name = "p2p_chpi"; + interface = "p2p"; /*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 5100 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 16 29 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 0 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + p2p_attr = < + 10 /* teyp: 0=ceds, 1=cmpi, 2=isp, 3=epi, + * 10=chpi, 11=cspi, 12=usit + */ + 6 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + p2p_3{ + model_name = "p2p_chpi"; + interface = "p2p"; /*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 3840 2160 /*h_active, v_active*/ + 4400 2250 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 4240 5100 /*h_period_min, max*/ + 2200 2760 /*v_period_min, max*/ + 480000000 624000000>; /*pclk_min, max*/ + lcd_timing = < + 16 29 0 /*hs_width, hs_bp, hs_pol*/ + 6 65 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 0 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + p2p_attr = < + 10 /* teyp: 0=ceds, 1=cmpi, 2=isp, 3=epi, + * 10=chpi, 11=cspi, 12=usit + */ + 12 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 1>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + mlvds_0{ + model_name = "mlvds_1080p"; + interface = "minilvds"; /*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 1920 1080 /*h_active, v_active*/ + 2200 1125 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 2080 2720 /*h_period_min, max*/ + 2200 1125 /*v_period_min, max*/ + 133940000 156000000>; /*pclk_min, max*/ + lcd_timing = < + 44 148 0 /*hs_width, hs_bp, hs_pol*/ + 5 30 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 0 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + minilvds_attr = < + 6 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0x660 /* clk_phase */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 0>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + mlvds_1{ + model_name = "mlvds_768p"; + interface = "minilvds"; /*lcd_interface + *(lvds, vbyone, minilvds, p2p) + */ + basic_setting = < + 1366 768 /*h_active, v_active*/ + 1560 806 /*h_period, v_period*/ + 8 /*lcd_bits */ + 16 9>; /*screen_widht, screen_height*/ + range_setting = < + 1460 2000 /*h_period_min, max*/ + 784 1015 /*v_period_min, max*/ + 50000000 85000000>; /*pclk_min, max*/ + lcd_timing = < + 56 64 0 /*hs_width, hs_bp, hs_pol*/ + 3 28 0>; /*vs_width, vs_bp, vs_pol*/ + clk_attr = < + 2 /*fr_adj_type + *(0=clk, 1=htotal, 2=vtotal, 3=auto_range, + * 4=hdmi_mode) + */ + 0 /*clk_ss_level*/ + 1 /*clk_auto_generate*/ + 0>; /*pixel_clk(unit in Hz)*/ + minilvds_attr = < + 6 /* channel_num */ + 0x76543210 /* channel_sel0 */ + 0xba98 /* channel_sel1 */ + 0x660 /* clk_phase */ + 0 /* pn_swap */ + 0>; /* bit_swap */ + phy_attr=<0xf 0>; /* vswing_level, preem_level */ + + /* power step: type, index, value, delay(ms) */ + power_on_step = < + 2 0 0 10 /*signal enable*/ + 0xff 0 0 0>; /*ending*/ + power_off_step = < + 2 0 0 10 /*signal disable*/ + 0xff 0 0 0>; /*ending*/ + backlight_index = <0xff>; + }; + }; + + lcd_extern{ + compatible = "amlogic, lcd_extern"; + status = "okay"; + key_valid = <0>; + i2c_bus = "i2c_bus_1"; + + extern_0{ + index = <0>; + extern_name = "ext_default"; + status = "disabled"; + type = <0>; /*0=i2c, 1=spi, 2=mipi*/ + i2c_address = <0x1c>; /*7bit i2c_addr*/ + i2c_address2 = <0xff>; + cmd_size = <0xff>; /*dynamic cmd_size*/ + + /* init on/off: + * fixed cmd_size: (type, value...); + * cmd_size include all data. + * dynamic cmd_size: (type, cmd_size, value...); + * cmd_size include value. + */ + /* type: 0x00=cmd with delay(bit[3:0]=1 for address2), + * 0xc0=cmd(bit[3:0]=1 for address2), + * 0xf0=gpio, + * 0xfd=delay, + * 0xff=ending + */ + /* value: i2c or spi cmd, or gpio index & level */ + /* delay: unit ms */ + init_on = < + 0xc0 7 0x20 0x01 0x02 0x00 0x40 0xFF 0x00 + 0xc0 7 0x80 0x02 0x00 0x40 0x62 0x51 0x73 + 0xc0 7 0x61 0x06 0x00 0x00 0x00 0x00 0x00 + 0xc0 7 0xC1 0x05 0x0F 0x00 0x08 0x70 0x00 + 0xc0 7 0x13 0x01 0x00 0x00 0x00 0x00 0x00 + 0xc0 7 0x3D 0x02 0x01 0x00 0x00 0x00 0x00 + 0xc0 7 0xED 0x0D 0x01 0x00 0x00 0x00 0x00 + 0xc0 7 0x23 0x02 0x00 0x00 0x00 0x00 0x00 + 0xfd 1 10 /* delay 10ms */ + 0xff 0>; /*ending*/ + init_off = <0xff 0>; /*ending*/ + }; + extern_1{ + index = <1>; + extern_name = "i2c_T5800Q"; + status = "disabled"; + type = <0>; /* 0=i2c, 1=spi, 2=mipi */ + i2c_address = <0x1c>; /* 7bit i2c address */ + }; + extern_2{ + index = <2>; + extern_name = "i2c_ANX6862_7911"; + status = "okay"; + type = <0>; /* 0=i2c, 1=spi, 2=mipi */ + i2c_address = <0x20>; /* 7bit i2c address */ + i2c_address2 = <0x74>; /* 7bit i2c address */ + cmd_size = <0xff>; + + init_on = < + 0xc0 2 0x01 0x2b + 0xc0 2 0x02 0x05 + 0xc0 2 0x03 0x00 + 0xc0 2 0x04 0x00 + 0xc0 2 0x05 0x0c + 0xc0 2 0x06 0x04 + 0xc0 2 0x07 0x21 + 0xc0 2 0x08 0x0f + 0xc0 2 0x09 0x04 + 0xc0 2 0x0a 0x00 + 0xc0 2 0x0b 0x04 + 0xc0 2 0xff 0x00 + 0xfd 1 100 /* delay 100ms */ + + 0xc1 2 0x01 0xca + 0xc1 2 0x02 0x3b + 0xc1 2 0x03 0x33 + 0xc1 2 0x04 0x05 + 0xc1 2 0x05 0x2c + 0xc1 2 0x06 0xf2 + 0xc1 2 0x07 0x9c + 0xc1 2 0x08 0x1b + 0xc1 2 0x09 0x82 + 0xc1 2 0x0a 0x3d + 0xc1 2 0x0b 0x20 + 0xc1 2 0x0c 0x11 + 0xc1 2 0x0d 0xc4 + 0xc1 2 0x0e 0x1a + 0xc1 2 0x0f 0x31 + 0xc1 2 0x10 0x4c + 0xc1 2 0x11 0x12 + 0xc1 2 0x12 0x90 + 0xc1 2 0x13 0xf7 + 0xc1 2 0x14 0x0c + 0xc1 2 0x15 0x20 + 0xc1 2 0x16 0x13 + 0xff 0>; /*ending*/ + init_off = <0xff 0>; /*ending*/ + }; + }; + +}; /* end of / */ diff --git a/arch/arm64/boot/dts/amlogic/mesontxl.dtsi b/arch/arm64/boot/dts/amlogic/mesontxl.dtsi index 10332dfbbe35..daabcef056a7 100644 --- a/arch/arm64/boot/dts/amlogic/mesontxl.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesontxl.dtsi @@ -1068,6 +1068,12 @@ compatible = "amlogic, vdac-txl"; status = "okay"; }; + + openvfd { + compatible = "open,vfd"; + dev_name = "openvfd"; + status = "okay"; + }; }; /* end of / */ &gpu{ @@ -1533,4 +1539,9 @@ function = "spi_a"; }; }; + openvfd { + compatible = "open,vfd"; + dev_name = "openvfd"; + status = "okay"; + }; }; diff --git a/arch/arm64/boot/dts/amlogic/mesontxlx.dtsi b/arch/arm64/boot/dts/amlogic/mesontxlx.dtsi index 11424d09e16d..85431f530ea5 100644 --- a/arch/arm64/boot/dts/amlogic/mesontxlx.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesontxlx.dtsi @@ -134,19 +134,14 @@ arm_pmu { compatible = "arm,armv8-pmuv3"; - interrupts = <0 137 4>; - reg = <0x0 0xff634400 0 0x1000>; - - /* addr = base + offset << 2 */ - sys_cpu_status0_offset = <0xa0>; - - sys_cpu_status0_pmuirq_mask = <0xf>; - + /* clusterb-enabled; */ + interrupts = ; + reg = <0x0 0xff634680 0x0 0x4>; + cpumasks = <0xf>; /* default 10ms */ - relax_timer_ns = <10000000>; - + relax-timer-ns = <10000000>; /* default 10000us */ - max_wait_cnt = <10000>; + max-wait-cnt = <10000>; }; gic: interrupt-controller@2c001000 { @@ -164,13 +159,12 @@ method = "smc"; }; - meson_suspend:pm { + aml_pm { compatible = "amlogic, pm"; - device_name = "aml_pm"; - /*gxbaby-suspend;*/ status = "okay"; - reg = <0x0 0xff8000a8 0x0 0x4>, - <0x0 0xff80023c 0x0 0x4>; + device_name = "aml_pm"; + debug_reg = <0xff8000a8>; + exit_reg = <0xff80023c>; }; secmon { @@ -288,11 +282,18 @@ ram-dump { compatible = "amlogic, ram_dump"; status = "okay"; + reg = <0x0 0xFF6345E0 0x0 4>; + reg-names = "PREG_STICKY_REG8"; + store_device = "data"; }; - amlogic-jtag { + jtag { compatible = "amlogic, jtag"; status = "okay"; + select = "disable"; /* disable/apao/apee */ + pinctrl-names="jtag_apao_pins", "jtag_apee_pins"; + pinctrl-0=<&jtag_apao_pins>; + pinctrl-1=<&jtag_apee_pins>; }; vpu { @@ -839,15 +840,14 @@ status = "disabled"; }; - meson-irblaster { - compatible = "amlogic, am_irblaster"; - dev_name = "meson-irblaster"; - status = "disable"; - pinctrl-names = "default"; - pinctrl-0 = <&irblaster_pins>; + irblaster: meson-irblaster@c0 { + compatible = "amlogic, aml_irblaster"; + reg = <0x0 0xc0 0x0 0xc>, + <0x0 0x40 0x0 0x4>; + #irblaster-cells = <2>; + status = "disabled"; }; - remote: rc@8040 { compatible = "amlogic, aml_remote"; dev_name = "meson-remote"; @@ -943,6 +943,17 @@ compatible = "amlogic, vdac-txlx"; status = "okay"; }; + + defendkey: defendkey { + compatible = "amlogic, defendkey"; + reg = <0x0 0xff634500 0x0 0x4>; /*RNG_USR_DATA*/ + mem_size = <0x0 0x100000>; + }; + openvfd { + compatible = "open,vfd"; + dev_name = "openvfd"; + status = "okay"; + }; }; /* end of / */ &pinctrl_aobus { @@ -1022,6 +1033,13 @@ }; }; + irblaster_pins1:irblaster_pin1 { + mux { + groups = "remote_out_ao6"; + function = "ir_out"; + }; + }; + pwmleds_pins:pwmleds { mux { @@ -1045,6 +1063,16 @@ function = "i2c_ao"; }; }; + + jtag_apao_pins:jtag_apao_pin { + mux { + groups = "GPIOAO_3", + "GPIOAO_4", + "GPIOAO_5", + "GPIOAO_7"; + function = "gpio_aobus"; + }; + }; }; &pinctrl_periphs { @@ -1385,6 +1413,16 @@ function = "pwm_d"; }; }; + + jtag_apee_pins:jtag_apee_pin { + mux { + groups = "GPIOC_0", + "GPIOC_1", + "GPIOC_2", + "GPIOC_3"; + function = "gpio_periphs"; + }; + }; }; &gpu{ diff --git a/arch/arm64/boot/dts/amlogic/mesontxlx_r311-panel.dtsi b/arch/arm64/boot/dts/amlogic/mesontxlx_r311-panel.dtsi index 99c8c93e14ab..610a57d10ec6 100644 --- a/arch/arm64/boot/dts/amlogic/mesontxlx_r311-panel.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesontxlx_r311-panel.dtsi @@ -678,6 +678,23 @@ }; backlight_4{ index = <4>; + bl_name = "ldim_global"; + bl_level_default_uboot_kernel = <100 100>; + bl_level_attr = <255 10 /*max, min*/ + 128 128>; /*mid, mid_mapping*/ + bl_ctrl_method = <3>; /*1=pwm,2=pwm_combo,3=ldim*/ + bl_power_attr = <0xff /*en_gpio_index*/ + 1 0 /*on_value, off_value*/ + 200 200>; /* on_delay(ms), off_delay(ms)*/ + bl_ldim_region_row_col = <1 1>; + bl_ldim_mode = <1>; /*0=left/right side + *1=top/bottom side + *2=direct + */ + ldim_dev_index = <1>; + }; + backlight_5{ + index = <5>; bl_name = "ldim_iw7027"; bl_level_default_uboot_kernel = <100 100>; bl_level_attr = <255 10 /*max, min*/ @@ -693,23 +710,6 @@ */ ldim_dev_index = <2>; }; - backlight_5{ - index = <5>; - bl_name = "ldim_global"; - bl_level_default_uboot_kernel = <100 100>; - bl_level_attr = <255 10 /*max, min*/ - 128 128>; /*mid, mid_mapping*/ - bl_ctrl_method = <3>; /*1=pwm,2=pwm_combo,3=ldim*/ - bl_power_attr = <0 /*en_gpio_index*/ - 1 0 /*on_value, off_value*/ - 200 200>; /* on_delay(ms), off_delay(ms)*/ - bl_ldim_region_row_col = <1 1>; - bl_ldim_mode = <1>; /*0=left/right side - *1=top/bottom side - *2=direct - */ - ldim_dev_index = <1>; - }; }; bl_pwm_conf:bl_pwm_conf{ @@ -728,54 +728,63 @@ status = "okay"; pinctrl-names = "ldim_pwm", "ldim_pwm_vs", - "ldim_pwm_off"; + "ldim_pwm_combo", + "ldim_pwm_vs_combo", + "ldim_pwm_off", + "ldim_pwm_combo_off"; pinctrl-0 = <&bl_pwm_on_pins>; pinctrl-1 = <&bl_pwm_vs_on_pins>; - pinctrl-2 = <&bl_pwm_off_pins>; + pinctrl-2 = <&bl_pwm_on_pins &bl_pwm_combo_1_on_pins>; + pinctrl-3 = <&bl_pwm_vs_on_pins &bl_pwm_combo_1_on_pins>; + pinctrl-4 = <&bl_pwm_off_pins>; + pinctrl-5 = <&bl_pwm_combo_off_pins>; pinctrl_version = <1>; /* for uboot */ ldim_pwm_config = <&bl_pwm_conf>; /* pwm port: PWM_A, PWM_B, PWM_C, PWM_D, PWM_E, PWM_F, PWM_VS*/ ldim_dev-gpios = <&gpio GPIOZ_12 GPIO_ACTIVE_HIGH &gpio GPIOZ_6 GPIO_ACTIVE_HIGH - &gpio GPIOZ_7 GPIO_ACTIVE_HIGH>; - ldim_dev_gpio_names = "GPIOZ_12","GPIOZ_6","GPIOZ_7"; + &gpio GPIOZ_7 GPIO_ACTIVE_HIGH + &gpio GPIOZ_4 GPIO_ACTIVE_HIGH>; + ldim_dev_gpio_names = "GPIOZ_12","GPIOZ_6","GPIOZ_7","GPIOZ_4"; ldim_dev_0 { index = <0>; type = <0>; /*0=normal, 1=spi, 2=i2c*/ ldim_dev_name = "ob3350"; - ldim_pwm_pinmux_sel = "ldim_pwm"; ldim_pwm_port = "PWM_B"; ldim_pwm_attr = <0 /* pol */ 200 /*freq(pwm:Hz, pwm_vs:multiple of vs)*/ - 50>;/*duty(%)*/ - dim_max_min = <100 20>; /*dim_max, dim_min*/ + 50>;/*default duty(%)*/ en_gpio_on_off = <0 /*ldim_dev-gpios index*/ 1 0>; /*on_level, off_level*/ + dim_max_min = <100 20>; /*dim_max, dim_min*/ }; ldim_dev_1 { index = <1>; type = <0>; /*0=normal, 1=spi, 2=i2c*/ ldim_dev_name = "global"; - ldim_pwm_pinmux_sel = "ldim_pwm"; ldim_pwm_port = "PWM_B"; ldim_pwm_attr = <1 /* pol */ 180 /*freq(pwm:Hz, pwm_vs:multiple of vs)*/ - 50>;/*duty(%)*/ - dim_max_min = <100 20>; /*dim_max, dim_min*/ - en_gpio_on_off = <2 /*ldim_dev-gpios index*/ + 50>;/*default duty(%)*/ + analog_pwm_port = "PWM_C"; + analog_pwm_attr = <1 /*pol(0=negative, 1=positvie)*/ + 18000 /*freq(pwm:Hz)*/ + 100 25 /*duty_max(%), duty_min(%)*/ + 80>; /*default duty(%)*/ + en_gpio_on_off = <3 /*ldim_dev-gpios index*/ 1 0>; /*on_level, off_level*/ + dim_max_min = <100 20>; /*dim_max, dim_min*/ }; ldim_dev_2 { index = <2>; type = <1>; /* 0=normal,1=spi,2=i2c */ ldim_dev_name = "iw7027"; - ldim_pwm_pinmux_sel = "ldim_pwm_vs"; ldim_pwm_port = "PWM_VS"; ldim_pwm_attr = <1 /* pol */ 2 /*freq(pwm:Hz, pwm_vs:multiple of vs)*/ - 50>;/*duty(%)*/ + 50>;/*default duty(%)*/ spi_bus_num = <0>; spi_chip_select = <0>; spi_max_frequency = <1000000>; /* unit: hz */ @@ -818,6 +827,7 @@ 0xc0 2 0x34 0xc8 0xc0 2 0x35 0xbf 0xff 0>; + init_off = <0xff 0>; }; }; diff --git a/arch/arm64/boot/dts/amlogic/partition_mbox_ab.dtsi b/arch/arm64/boot/dts/amlogic/partition_mbox_ab.dtsi index a78cd67fdc23..d917b8fa3f70 100644 --- a/arch/arm64/boot/dts/amlogic/partition_mbox_ab.dtsi +++ b/arch/arm64/boot/dts/amlogic/partition_mbox_ab.dtsi @@ -88,13 +88,13 @@ vendor_a:vendor_a { pname = "vendor_a"; - size = <0x0 0x10000000>; + size = <0x0 0x14000000>; mask = <1>; }; vendor_b:vendor_b { pname = "vendor_b"; - size = <0x0 0x10000000>; + size = <0x0 0x14000000>; mask = <1>; }; odm_a:odm_a diff --git a/arch/arm64/boot/dts/amlogic/partition_mbox_ab_P_32.dtsi b/arch/arm64/boot/dts/amlogic/partition_mbox_ab_P_32.dtsi index fc5a9b7490f6..8998e7ea6ebe 100644 --- a/arch/arm64/boot/dts/amlogic/partition_mbox_ab_P_32.dtsi +++ b/arch/arm64/boot/dts/amlogic/partition_mbox_ab_P_32.dtsi @@ -120,13 +120,13 @@ vendor_a:vendor_a { pname = "vendor_a"; - size = <0x0 0x10000000>; + size = <0x0 0x14000000>; mask = <1>; }; vendor_b:vendor_b { pname = "vendor_b"; - size = <0x0 0x10000000>; + size = <0x0 0x14000000>; mask = <1>; }; odm_a:odm_a diff --git a/arch/arm64/boot/dts/amlogic/partition_mbox_ab_avb.dtsi b/arch/arm64/boot/dts/amlogic/partition_mbox_ab_avb.dtsi index c64a54e27c17..83409beb1e53 100644 --- a/arch/arm64/boot/dts/amlogic/partition_mbox_ab_avb.dtsi +++ b/arch/arm64/boot/dts/amlogic/partition_mbox_ab_avb.dtsi @@ -88,13 +88,13 @@ vendor_a:vendor_a { pname = "vendor_a"; - size = <0x0 0x10000000>; + size = <0x0 0x14000000>; mask = <1>; }; vendor_b:vendor_b { pname = "vendor_b"; - size = <0x0 0x10000000>; + size = <0x0 0x14000000>; mask = <1>; }; odm_a:odm_a diff --git a/arch/arm64/boot/dts/amlogic/partition_mbox_normal_P_32.dtsi b/arch/arm64/boot/dts/amlogic/partition_mbox_normal_P_32.dtsi index f2c574203d53..6cbedc415e4f 100644 --- a/arch/arm64/boot/dts/amlogic/partition_mbox_normal_P_32.dtsi +++ b/arch/arm64/boot/dts/amlogic/partition_mbox_normal_P_32.dtsi @@ -90,7 +90,7 @@ vendor:vendor { pname = "vendor"; - size = <0x0 0x10000000>; + size = <0x0 0x14000000>; mask = <1>; }; odm:odm diff --git a/arch/arm64/boot/dts/amlogic/partition_mbox_normal_P_64.dtsi b/arch/arm64/boot/dts/amlogic/partition_mbox_normal_P_64.dtsi index 2b8e7304cac6..13e510e4e931 100644 --- a/arch/arm64/boot/dts/amlogic/partition_mbox_normal_P_64.dtsi +++ b/arch/arm64/boot/dts/amlogic/partition_mbox_normal_P_64.dtsi @@ -90,7 +90,7 @@ vendor:vendor { pname = "vendor"; - size = <0x0 0x10000000>; + size = <0x0 0x14000000>; mask = <1>; }; odm:odm diff --git a/arch/arm64/boot/dts/amlogic/partition_mbox_p241_P.dtsi b/arch/arm64/boot/dts/amlogic/partition_mbox_p241_P.dtsi index aeb1dee501f9..3b0796a9cf21 100644 --- a/arch/arm64/boot/dts/amlogic/partition_mbox_p241_P.dtsi +++ b/arch/arm64/boot/dts/amlogic/partition_mbox_p241_P.dtsi @@ -90,7 +90,7 @@ vendor:vendor { pname = "vendor"; - size = <0x0 0x10000000>; + size = <0x0 0x14000000>; mask = <1>; }; odm:odm diff --git a/arch/arm64/boot/dts/amlogic/sm1_pxp.dts b/arch/arm64/boot/dts/amlogic/sm1_pxp.dts new file mode 100644 index 000000000000..e0fdc85ab210 --- /dev/null +++ b/arch/arm64/boot/dts/amlogic/sm1_pxp.dts @@ -0,0 +1,742 @@ +/* + * arch/arm64/boot/dts/amlogic/sm1_pxp.dts + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +/dts-v1/; + +#include "mesonsm1.dtsi" +#include "partition_mbox_normal.dtsi" + +/ { + model = "Amlogic"; + compatible = "amlogic, g12a"; + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + + aliases { + serial0 = &uart_AO; + i2c0 = &i2c0; + i2c1 = &i2c1; + i2c2 = &i2c2; + i2c3 = &i2c3; + i2c4 = &i2c_AO; + }; + + memory@00000000 { + device_type = "memory"; + linux,usable-memory = <0x0 0x0 0x0 0x40000000>; + }; + + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + /* global autoconfigured region for contiguous allocations */ + secmon_reserved:linux,secmon { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x400000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x05000000 0x0 0x400000>; + }; + + secos_reserved:linux,secos { + status = "disable"; + compatible = "amlogic, aml_secos_memory"; + reg = <0x0 0x05300000 0x0 0x2000000>; + no-map; + }; + logo_reserved:linux,meson-fb { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x800000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x3f800000 0x0 0x800000>; + }; + ion_cma_reserved:linux,ion-dev { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x8000000>; + alignment = <0x0 0x400000>; + }; + + //di_reserved:linux,di { + //compatible = "amlogic, di-mem"; + /* buffer_size = 3621952(yuv422 8bit) */ + /* 4179008(yuv422 10bit full pack mode) */ + /** 10x3621952=34.6M(0x23) support 8bit **/ + /** 10x4736064=45.2M(0x2e) support 12bit **/ + /** 10x4179008=40M(0x28) support 10bit **/ + //size = <0x0 0x2800000>; + //no-map; + //}; + /*di CMA pool */ + di_cma_reserved:linux,di_cma { + compatible = "shared-dma-pool"; + reusable; + /* buffer_size = 3621952(yuv422 8bit) + * | 4736064(yuv422 10bit) + * | 4074560(yuv422 10bit full pack mode) + * 10x3621952=34.6M(0x23) support 8bit + * 10x4736064=45.2M(0x2e) support 12bit + * 10x4074560=40M(0x28) support 10bit + */ + size = <0x0 0x02800000>; + alignment = <0x0 0x400000>; + }; + codec_mm_cma:linux,codec_mm_cma { + compatible = "shared-dma-pool"; + reusable; + /* ion_codec_mm max can alloc size 80M*/ + size = <0x0 0x13400000>; + alignment = <0x0 0x400000>; + linux,contiguous-region; + }; + /* codec shared reserved */ + codec_mm_reserved:linux,codec_mm_reserved { + compatible = "amlogic, codec-mm-reserved"; + size = <0x0 0x0>; + alignment = <0x0 0x100000>; + //no-map; + }; + /* vdin0 CMA pool */ + vdin0_cma_reserved:linux,vdin0_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16+4 M */ + size = <0x0 0x04000000>; + alignment = <0x0 0x400000>; + }; + /* vdin1 CMA pool */ + vdin1_cma_reserved:linux,vdin1_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16 M */ + size = <0x0 0x04000000>; + alignment = <0x0 0x400000>; + }; + }; + + cvbsout { + compatible = "amlogic, cvbsout-sm1"; + dev_name = "cvbsout"; + status = "okay"; + clocks = <&clkc CLKID_VCLK2_ENCI + &clkc CLKID_VCLK2_VENCI0 + &clkc CLKID_VCLK2_VENCI1 + &clkc CLKID_DAC_CLK>; + clock-names = "venci_top_gate", + "venci_0_gate", + "venci_1_gate", + "vdac_clk_gate"; + clk_path = <0>; + + /* performance: reg_address, reg_value */ + /* sm1 */ + performance = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x8080 + 0x1b05 0xfd + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + performance_sarft = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x0 + 0x1b05 0x9 + 0x1c59 0xfc48 + 0xffff 0x0>; /* ending flag */ + performance_revB_telecom = <0x1bf0 0x9 + 0x1b56 0x546 + 0x1b12 0x8080 + 0x1b05 0x9 + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + }; + + codec_mm { + compatible = "amlogic, codec, mm"; + memory-region = <&codec_mm_cma &codec_mm_reserved>; + dev_name = "codec_mm"; + status = "okay"; + }; + + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + + deinterlace { + compatible = "amlogic, deinterlace"; + status = "okay"; + /* 0:use reserved; 1:use cma; 2:use cma as reserved */ + flag_cma = <1>; + //memory-region = <&di_reserved>; + memory-region = <&di_cma_reserved>; + interrupts = <0 46 1 + 0 40 1>; + interrupt-names = "pre_irq", "post_irq"; + clocks = <&clkc CLKID_VPU_CLKB_TMP_COMP>, + <&clkc CLKID_VPU_CLKB_COMP>; + clock-names = "vpu_clkb_tmp_composite", + "vpu_clkb_composite"; + clock-range = <334 667>; + /* buffer-size = <3621952>;(yuv422 8bit) */ + buffer-size = <4074560>;/*yuv422 fullpack*/ + /* reserve-iomap = "true"; */ + /* if enable nr10bit, set nr10bit-support to 1 */ + post-wr-support = <1>; + nr10bit-support = <1>; + nrds-enable = <1>; + pps-enable = <1>; + }; + + efusekey:efusekey{ + keynum = <4>; + key0 = <&key_0>; + key1 = <&key_1>; + key2 = <&key_2>; + key3 = <&key_3>; + key_0:key_0{ + keyname = "mac"; + offset = <0>; + size = <6>; + }; + key_1:key_1{ + keyname = "mac_bt"; + offset = <6>; + size = <6>; + }; + key_2:key_2{ + keyname = "mac_wifi"; + offset = <12>; + size = <6>; + }; + key_3:key_3{ + keyname = "usid"; + offset = <18>; + size = <16>; + }; + };//End efusekey + + amlvecm { + compatible = "amlogic, vecm"; + dev_name = "aml_vecm"; + status = "okay"; + gamma_en = <0>;/*1:enabel ;0:disable*/ + wb_en = <0>;/*1:enabel ;0:disable*/ + cm_en = <0>;/*1:enabel ;0:disable*/ + /*0: 709/601 1: bt2020*/ + tx_op_color_primary = <0>; + }; + amdolby_vision { + compatible = "amlogic, dolby_vision_sm1"; + dev_name = "aml_amdolby_vision_driver"; + status = "okay"; + tv_mode = <0>;/*1:enabel ;0:disable*/ + }; + + /* Audio Related start */ + + pdm_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, pdm_dummy_codec"; + status = "okay"; + }; + dummy_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, aml_dummy_codec"; + status = "okay"; + }; + amlogic_codec:t9015{ + #sound-dai-cells = <0>; + compatible = "amlogic, aml_codec_T9015"; + reg = <0x0 0xFF632000 0x0 0x2000>; + is_auge_used = <1>; /* meson or auge chipset used */ + tdmout_index = <0>; + status = "disabled"; + }; + auge_sound { + compatible = "amlogic, g12a-sound-card"; + aml-audio-card,name = "AML-AUGESOUND"; + + aml-audio-card,dai-link@0 { + format = "dsp_a"; + mclk-fs = <512>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdma>; + frame-master = <&tdma>; + /* slave mode */ + /* + * bitclock-master = <&tdmacodec>; + * frame-master = <&tdmacodec>; + */ + tdmacpu: cpu { + sound-dai = <&tdma>; + dai-tdm-slot-tx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-rx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-num = <8>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <24576000>; + }; + tdmacodec: codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@1 { + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdmb>; + frame-master = <&tdmb>; + /* slave mode */ + //bitclock-master = <&tdmbcodec>; + //frame-master = <&tdmbcodec>; + cpu { + sound-dai = <&tdmb>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmbcodec: codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@2 { + format = "i2s"; + mclk-fs = <256>; + continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdmc>; + frame-master = <&tdmc>; + /* slave mode */ + //bitclock-master = <&tdmccodec>; + //frame-master = <&tdmccodec>; + cpu { + sound-dai = <&tdmc>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmccodec: codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@3 { + mclk-fs = <64>; + cpu { + sound-dai = <&pdm>; + }; + codec { + sound-dai = <&pdm_codec>; + }; + }; + + aml-audio-card,dai-link@4 { + mclk-fs = <128>; + cpu { + sound-dai = <&spdifa>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + aml-audio-card,dai-link@5 { + mclk-fs = <128>; + cpu { + sound-dai = <&spdifb>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + }; + audiolocker: locker { + compatible = "amlogic, audiolocker"; + clocks = <&clkaudio CLKID_AUDIO_LOCKER_OUT + &clkaudio CLKID_AUDIO_LOCKER_IN + &clkaudio CLKID_AUDIO_MCLK_D + &clkaudio CLKID_AUDIO_MCLK_E + &clkc CLKID_MPLL1 + &clkc CLKID_MPLL2>; + clock-names = "lock_out", "lock_in", "out_src", + "in_src", "out_calc", "in_ref"; + interrupts = ; + interrupt-names = "irq"; + frequency = <49000000>; /* pll */ + dividor = <49>; /* locker's parent */ + status = "disabled"; + }; + /* Audio Related end */ + + cpu_opp_table0: cpu_opp_table0 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <730000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <730000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <730000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <750000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <770000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <780000>; + }; + opp06 { + opp-hz = /bits/ 64 <1404000000>; + opp-microvolt = <790000>; + }; + opp07 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <800000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <810000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <850000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <900000>; + }; + opp11 { + opp-hz = /bits/ 64 <1908000000>; + opp-microvolt = <950000>; + }; + }; + + cpufreq-meson { + compatible = "amlogic, cpufreq-meson"; + pinctrl-names = "default"; + pinctrl-0 = <&pwm_ao_d_pins3>; + status = "disabled"; + }; + + +}; /* end of / */ + +&meson_fb { + status = "okay"; + display_size_default = <1920 1080 1920 2160 32>; + mem_size = <0x00800000 0x1980000 0x100000 0x100000 0x800000>; + logo_addr = "0x7f800000"; + mem_alloc = <1>; + pxp_mode = <1>; /** 0:normal mode 1:pxp mode */ +}; + +&pwm_AO_cd { + status = "okay"; + }; + +&audiobus { + tdma: tdm@0 { + compatible = "amlogic, sm1-snd-tdma"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <1 0>; + dai-tdm-lane-slot-mask-out = <0 1>; + dai-tdm-clk-sel = <0>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_A + &clkc CLKID_MPLL0>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmout_a &tdmin_a>; + + status = "okay"; + }; + + tdmb: tdm@1 { + compatible = "amlogic, sm1-snd-tdmb"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <1 1 1 1>; + dai-tdm-clk-sel = <1>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_B + &clkc CLKID_MPLL1>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmb_mclk /*&tdmout_b &tdmin_b*/>; + }; + + tdmc: tdm@2 { + compatible = "amlogic, sm1-snd-tdmc"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 1 0 0>; + #dai-tdm-lane-slot-mask-out = <1 0 1 1>; + #dai-tdm-lane-oe-slot-mask-in = <0 0 0 0>; + dai-tdm-lane-oe-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <2>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmc_mclk &tdmout_c &tdmin_c>; + + status = "okay"; + }; + + spdifa: spdif@0 { + compatible = "amlogic, sm1-snd-spdif-a"; + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 + &clkc CLKID_FCLK_DIV4 + &clkaudio CLKID_AUDIO_GATE_SPDIFIN + &clkaudio CLKID_AUDIO_GATE_SPDIFOUT_A + &clkaudio CLKID_AUDIO_SPDIFIN + &clkaudio CLKID_AUDIO_SPDIFOUT_A>; + clock-names = "sysclk", "fixed_clk", "gate_spdifin", + "gate_spdifout", "clk_spdifin", "clk_spdifout"; + interrupts = + ; + + interrupt-names = "irq_spdifin"; + pinctrl-names = "spdif_pins"; + pinctrl-0 = <&spdifout &spdifin>; + + status = "okay"; + }; + spdifb: spdif@1 { + compatible = "amlogic, sm1-snd-spdif-b"; + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 /*CLKID_HIFI_PLL*/ + &clkaudio CLKID_AUDIO_GATE_SPDIFOUT_B + &clkaudio CLKID_AUDIO_SPDIFOUT_B>; + clock-names = "sysclk", + "gate_spdifout", "clk_spdifout"; + + status = "okay"; + }; + pdm: pdm { + compatible = "amlogic, sm1-snd-pdm"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_PDM + &clkc CLKID_FCLK_DIV3 + &clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_PDMIN0 + &clkaudio CLKID_AUDIO_PDMIN1>; + clock-names = "gate", + "sysclk_srcpll", + "dclk_srcpll", + "pdm_dclk", + "pdm_sysclk"; + + pinctrl-names = "pdm_pins"; + pinctrl-0 = <&pdmin>; + + /* mode 0~4, defalut:1 */ + filter_mode = <1>; + + status = "okay"; + }; +}; /* end of audiobus */ + +&pinctrl_periphs { + tdmout_a: tdmout_a { + mux { /* GPIOX_11, GPIOX_10, GPIOX_8 */ + groups = "tdma_sclk", + "tdma_fs", + "tdma_dout1"; + function = "tdma_out"; + }; + }; + + tdmin_a: tdmin_a { + mux { /* GPIOX_9 */ + groups = "tdma_din0"; + function = "tdma_in"; + }; + }; + + tdmb_mclk: tdmb_mclk { + mux { + groups = "mclk0_a"; + function = "mclk0"; + }; + }; + + tdmc_mclk: tdmc_mclk { + mux { /* GPIOZ_8 */ + groups = "mclk1_z"; + function = "mclk1"; + }; + }; + + tdmout_c:tdmout_c { + mux { /* gpioz_7, gpioz_6, GPIOZ_2, GPIOZ_4, GPIOZ_5*/ + groups = "tdmc_sclk_z", + "tdmc_fs_z", + "tdmc_dout0_z" + /*,"tdmc_dout2_z", + *"tdmc_dout3_z" + */; + function = "tdmc_out"; + }; + }; + + tdmin_c:tdmin_c { + mux { /* GPIOZ_3 */ + groups = "tdmc_din1_z"; + function = "tdmc_in"; + }; + }; + + spdifin: spdifin { + mux {/* gpioa_10 */ + groups = "spdif_in_a10"; + function = "spdif_in"; + }; + }; + + spdifout: spdifout { + mux {/* gpioa_11 */ + groups = "spdif_out_a11"; + function = "spdif_out"; + }; + }; + + spdifout_b: spdifout_b { + mux { /* gpioa_13 */ + groups = "spdif_out_a13"; + function = "spdif_out"; + }; + }; + + pdmin: pdmin { + mux { /* gpioa_5, gpioa_6, gpioa_7, gpioa_8, gpioa_9*/ + groups = "pdm_din0_a", + "pdm_din1_a", + "pdm_din2_a", + "pdm_din3_a", + "pdm_dclk_a"; + function = "pdm"; + }; + }; + +}; /* end of pinctrl_periphs */ + +&pinctrl_aobus { + tdmout_b: tdmout_b { + mux { /* GPIOAO_7, GPIOAO_8, GPIOAO_4 */ + groups = "tdmb_fs_ao", + "tdmb_fs_ao", + "tdmb_dout0_ao"; + function = "tdmb_out_ao"; + }; + }; + + tdmin_b:tdmin_b { + mux { + groups = "tdmb_din2_ao"; + function = "tdmb_in_ao"; + }; + }; +}; /* end of pinctrl_aobus */ +/* Audio Related End */ + +&aobus{ + +}; + +&irblaster { + status = "disabled"; +}; + +/*if you want to use vdin just modify status to "ok"*/ +&vdin0 { + memory-region = <&vdin0_cma_reserved>; + status = "okay"; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + *bit4:support yuv422 10bit full pack mode (from txl new add) + */ + tv_bit_mode = <0x15>; +}; +&vdin1 { + memory-region = <&vdin1_cma_reserved>; + status = "okay"; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + */ + tv_bit_mode = <1>; +}; + +&sd_emmc_b { + status = "okay"; + sd { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED"; + f_min = <400000>; + f_max = <50000000>; + }; +}; + +&defendkey { + status = "okay"; +}; + diff --git a/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts b/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts new file mode 100644 index 000000000000..0709022cd4ec --- /dev/null +++ b/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts @@ -0,0 +1,1628 @@ +/* + * arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +/dts-v1/; + +#include "mesonsm1.dtsi" +#include "partition_mbox_normal.dtsi" +#include "mesonsm1_skt-panel.dtsi" + +/ { + model = "Amlogic"; + amlogic-dt-id = "sm1_ac200_2g"; + compatible = "amlogic, g12a"; + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + + aliases { + serial0 = &uart_AO; + serial1 = &uart_A; + serial2 = &uart_B; + serial3 = &uart_C; + serial4 = &uart_AO_B; + tsensor0 = &p_tsensor; + tsensor1 = &d_tsensor; + i2c0 = &i2c0; + i2c1 = &i2c1; + i2c2 = &i2c2; + i2c3 = &i2c3; + i2c4 = &i2c_AO; + }; + + memory@00000000 { + device_type = "memory"; + linux,usable-memory = <0x0 0x000000 0x0 0x80000000>; + }; + + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + /* global autoconfigured region for contiguous allocations */ + ramoops@0x07400000 { + compatible = "ramoops"; + reg = <0x0 0x07400000 0x0 0x00100000>; + record-size = <0x8000>; + console-size = <0x8000>; + ftrace-size = <0x20000>; + }; + + secmon_reserved:linux,secmon { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x400000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x05000000 0x0 0x400000>; + }; + secos_reserved:linux,secos { + status = "disable"; + compatible = "amlogic, aml_secos_memory"; + reg = <0x0 0x05300000 0x0 0x2000000>; + no-map; + }; + logo_reserved:linux,meson-fb { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x800000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x7f800000 0x0 0x800000>; + }; + ion_cma_reserved:linux,ion-dev { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x8000000>; + alignment = <0x0 0x400000>; + }; + //di_reserved:linux,di { + //compatible = "amlogic, di-mem"; + /* buffer_size = 3621952(yuv422 8bit) */ + /* 4179008(yuv422 10bit full pack mode) */ + /** 10x3621952=34.6M(0x23) support 8bit **/ + /** 10x4736064=45.2M(0x2e) support 12bit **/ + /** 10x4179008=40M(0x28) support 10bit **/ + //size = <0x0 0x2800000>; + //no-map; + //}; + /*di CMA pool */ + di_cma_reserved:linux,di_cma { + compatible = "shared-dma-pool"; + reusable; + /* buffer_size = 3621952(yuv422 8bit) + * | 4736064(yuv422 10bit) + * | 4074560(yuv422 10bit full pack mode) + * 10x3621952=34.6M(0x23) support 8bit + * 10x4736064=45.2M(0x2e) support 12bit + * 10x4074560=40M(0x28) support 10bit + */ + size = <0x0 0x02800000>; + alignment = <0x0 0x400000>; + }; + /* POST PROCESS MANAGER */ + ppmgr_reserved:linux,ppmgr { + compatible = "shared-dma-pool"; + size = <0x0 0x0>; + }; + + codec_mm_cma:linux,codec_mm_cma { + compatible = "shared-dma-pool"; + reusable; + /* ion_codec_mm max can alloc size 80M*/ + size = <0x0 0x13400000>; + alignment = <0x0 0x400000>; + linux,contiguous-region; + }; + /* codec shared reserved */ + codec_mm_reserved:linux,codec_mm_reserved { + compatible = "amlogic, codec-mm-reserved"; + size = <0x0 0x0>; + alignment = <0x0 0x100000>; + //no-map; + }; + /* vdin0 CMA pool */ + vdin0_cma_reserved:linux,vdin0_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16+4 M */ + size = <0x0 0x04000000>; + alignment = <0x0 0x400000>; + }; + /* vdin1 CMA pool */ + vdin1_cma_reserved:linux,vdin1_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16 M */ + size = <0x0 0x04000000>; + alignment = <0x0 0x400000>; + }; + vm0_cma_reserved:linux,vm0_cma { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x2000000>; + alignment = <0x0 0x400000>; + }; + }; + + galcore { + status = "okay"; + }; + gpioleds { + compatible = "gpio-leds"; + status = "okay"; + + sys_led { + label="sys_led"; + gpios=<&gpio_ao GPIOAO_11 GPIO_ACTIVE_HIGH>; + default-state ="on"; + }; + }; + + cvbsout { + compatible = "amlogic, cvbsout-sm1"; + dev_name = "cvbsout"; + status = "okay"; + clocks = <&clkc CLKID_VCLK2_ENCI + &clkc CLKID_VCLK2_VENCI0 + &clkc CLKID_VCLK2_VENCI1 + &clkc CLKID_DAC_CLK>; + clock-names = "venci_top_gate", + "venci_0_gate", + "venci_1_gate", + "vdac_clk_gate"; + /* clk path */ + /* 0:vid_pll vid2_clk */ + /* 1:gp0_pll vid2_clk */ + /* 2:vid_pll vid1_clk */ + /* 3:gp0_pll vid1_clk */ + clk_path = <0>; + + /* performance: reg_address, reg_value */ + /* sm1 */ + performance = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x8080 + 0x1b05 0xfd + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + performance_sarft = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x0 + 0x1b05 0x9 + 0x1c59 0xfc48 + 0xffff 0x0>; /* ending flag */ + performance_revB_telecom = <0x1bf0 0x9 + 0x1b56 0x546 + 0x1b12 0x8080 + 0x1b05 0x9 + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + }; + + bt-dev{ + compatible = "amlogic, bt-dev"; + dev_name = "bt-dev"; + status = "okay"; + gpio_reset = <&gpio GPIOX_17 GPIO_ACTIVE_HIGH>; + gpio_hostwake = <&gpio GPIOX_19 GPIO_ACTIVE_HIGH>; + }; + + wifi{ + compatible = "amlogic, aml_wifi"; + dev_name = "aml_wifi"; + status = "okay"; + interrupt_pin = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; + irq_trigger_type = "GPIO_IRQ_LOW"; + power_on_pin = <&gpio GPIOX_6 GPIO_ACTIVE_HIGH>; + dhd_static_buf; //if use bcm wifi, config dhd_static_buf + pinctrl-names = "default"; + pinctrl-0 = <&pwm_e_pins>; + pwm_config = <&wifi_pwm_conf>; + }; + + wifi_pwm_conf:wifi_pwm_conf{ + pwm_channel1_conf { + pwms = <&pwm_ef MESON_PWM_0 30541 0>; + duty-cycle = <15270>; + times = <10>; + }; + pwm_channel2_conf { + pwms = <&pwm_ef MESON_PWM_2 30500 0>; + duty-cycle = <15250>; + times = <12>; + }; + }; + + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + + codec_mm { + compatible = "amlogic, codec, mm"; + memory-region = <&codec_mm_cma &codec_mm_reserved>; + dev_name = "codec_mm"; + status = "okay"; + }; + + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + + ppmgr { + compatible = "amlogic, ppmgr"; + memory-region = <&ppmgr_reserved>; + dev_name = "ppmgr"; + status = "okay"; + }; + + deinterlace { + compatible = "amlogic, deinterlace"; + status = "okay"; + /* 0:use reserved; 1:use cma; 2:use cma as reserved */ + flag_cma = <1>; + //memory-region = <&di_reserved>; + memory-region = <&di_cma_reserved>; + interrupts = <0 46 1 + 0 40 1>; + interrupt-names = "pre_irq", "post_irq"; + clocks = <&clkc CLKID_VPU_CLKB_TMP_COMP>, + <&clkc CLKID_VPU_CLKB_COMP>; + clock-names = "vpu_clkb_tmp_composite", + "vpu_clkb_composite"; + clock-range = <334 667>; + /* buffer-size = <3621952>;(yuv422 8bit) */ + buffer-size = <4074560>;/*yuv422 fullpack*/ + /* reserve-iomap = "true"; */ + /* if enable nr10bit, set nr10bit-support to 1 */ + post-wr-support = <1>; + nr10bit-support = <1>; + nrds-enable = <1>; + pps-enable = <1>; + }; + ionvideo { + compatible = "amlogic, ionvideo"; + dev_name = "ionvideo"; + status = "okay"; + }; + vm0 { + compatible = "amlogic, vm"; + memory-region = <&vm0_cma_reserved>; + dev_name = "vm0"; + status = "disabled"; + vm_id = <0>; + }; + + amvdec_656in { + /*bt656 gpio conflict with i2c0*/ + compatible = "amlogic, amvdec_656in"; + dev_name = "amvdec_656in"; + status = "disabled"; + reg = <0x0 0xffe02000 0x0 0x7c>; + clocks = <&clkc CLKID_BT656_COMP>, + <&clkc CLKID_BT656>; + clock-names = "cts_bt656_clk1", + "clk_gate_bt656"; + /* bt656in1, bt656in2 */ + bt656in1 { + bt656_id = <1>; + status = "disabled"; + }; + }; + + aml_cams { + compatible = "amlogic, cams_prober"; + status = "disabled"; + pinctrl-names="default"; + pinctrl-0=<&cam_dvp_pins &gen_clk_ee_z>; + clocks = <&clkc CLKID_GEN_CLK>; + clock-names = "g12a_24m"; + cam_0{ + cam_name = "gc2145"; + front_back = <0>; + /*u200 i2c2 gpio conflict with ethmac*/ + camera-i2c-bus = <&i2c2>; + gpio_pwdn-gpios = <&gpio GPIOZ_2 GPIO_ACTIVE_HIGH>; + gpio_rst-gpios = <&gpio GPIOZ_12 GPIO_ACTIVE_HIGH>; + mirror_flip = <1>; + vertical_flip = <1>; + spread_spectrum = <0>; + bt_path = "gpio"; + bt_path_count = <1>; + vdin_path = <0>; + status = "okay"; + }; + }; + + gpio_keypad{ + compatible = "amlogic, gpio_keypad"; + status = "okay"; + scan_period = <20>; + key_num = <1>; + key_name = "power"; + key_code = <116>; + key-gpios = <&gpio_ao GPIOAO_3 GPIO_ACTIVE_HIGH>; + detect_mode = <0>;/*0:polling mode, 1:irq mode*/ + }; + + adc_keypad { + compatible = "amlogic, adc_keypad"; + status = "okay"; + key_name = "vol-", "vol+", "enter"; + key_num = <3>; + io-channels = <&saradc SARADC_CH2>; + io-channel-names = "key-chan-2"; + key_chan = ; + key_code = <114 115 97>; + key_val = <143 266 389>; //val=voltage/1800mV*1023 + key_tolerance = <40 40 40>; + }; + + unifykey{ + compatible = "amlogic, unifykey"; + status = "ok"; + unifykey-num = <17>; + unifykey-index-0 = <&keysn_0>; + unifykey-index-1 = <&keysn_1>; + unifykey-index-2 = <&keysn_2>; + unifykey-index-3 = <&keysn_3>; + unifykey-index-4 = <&keysn_4>; + unifykey-index-5 = <&keysn_5>; + unifykey-index-6 = <&keysn_6>; + unifykey-index-7 = <&keysn_7>; + unifykey-index-8 = <&keysn_8>; + unifykey-index-9 = <&keysn_9>; + unifykey-index-10= <&keysn_10>; + unifykey-index-11= <&keysn_11>; + unifykey-index-12= <&keysn_12>; + unifykey-index-13= <&keysn_13>; + unifykey-index-14= <&keysn_14>; + unifykey-index-15= <&keysn_15>; + unifykey-index-16= <&keysn_16>; + + keysn_0: key_0{ + key-name = "usid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_1:key_1{ + key-name = "mac"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_2:key_2{ + key-name = "hdcp"; + key-device = "secure"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_3:key_3{ + key-name = "secure_boot_set"; + key-device = "efuse"; + key-permit = "write"; + }; + keysn_4:key_4{ + key-name = "mac_bt"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_5:key_5{ + key-name = "mac_wifi"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_6:key_6{ + key-name = "hdcp2_tx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_7:key_7{ + key-name = "hdcp2_rx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_8:key_8{ + key-name = "widevinekeybox"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_9:key_9{ + key-name = "deviceid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_10:key_10{ + key-name = "hdcp22_fw_private"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_11:key_11{ + key-name = "PlayReadykeybox25"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_12:key_12{ + key-name = "prpubkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_13:key_13{ + key-name = "prprivkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_14:key_14{ + key-name = "attestationkeybox";// attestation key + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_15:key_15{ + key-name = "region_code"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_16:key_16{ + key-name = "netflix_mgkid"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + };//End unifykey + + efusekey:efusekey{ + keynum = <4>; + key0 = <&key_0>; + key1 = <&key_1>; + key2 = <&key_2>; + key3 = <&key_3>; + key_0:key_0{ + keyname = "mac"; + offset = <0>; + size = <6>; + }; + key_1:key_1{ + keyname = "mac_bt"; + offset = <6>; + size = <6>; + }; + key_2:key_2{ + keyname = "mac_wifi"; + offset = <12>; + size = <6>; + }; + key_3:key_3{ + keyname = "usid"; + offset = <18>; + size = <16>; + }; + };//End efusekey + + amlvecm { + compatible = "amlogic, vecm"; + dev_name = "aml_vecm"; + status = "okay"; + gamma_en = <0>;/*1:enabel ;0:disable*/ + wb_en = <0>;/*1:enabel ;0:disable*/ + cm_en = <0>;/*1:enabel ;0:disable*/ + /*0: 709/601 1: bt2020*/ + tx_op_color_primary = <0>; + }; + + amdolby_vision { + compatible = "amlogic, dolby_vision_sm1"; + dev_name = "aml_amdolby_vision_driver"; + status = "okay"; + tv_mode = <0>;/*1:enabel ;0:disable*/ + }; + + /* Audio Related start */ + pdm_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, pdm_dummy_codec"; + status = "okay"; + }; + dummy_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, aml_dummy_codec"; + status = "okay"; + }; + amlogic_codec:t9015{ + #sound-dai-cells = <0>; + compatible = "amlogic, aml_codec_T9015"; + reg = <0x0 0xFF632000 0x0 0x2000>; + is_auge_used = <1>; /* meson or auge chipset used */ + tocodec_inout = <1>; + tdmout_index = <1>; + ch0_sel = <0>; + ch1_sel = <1>; + + status = "okay"; + }; + + auge_sound { + compatible = "amlogic, g12a-sound-card"; + aml-audio-card,name = "AML-AUGESOUND"; + + /*avout mute gpio*/ + avout_mute-gpios = <&gpio_ao GPIOAO_2 GPIO_ACTIVE_HIGH>; + + aml-audio-card,dai-link@0 { + format = "dsp_a"; + mclk-fs = <512>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdma>; + frame-master = <&tdma>; + /* slave mode */ + /* + * bitclock-master = <&tdmacodec>; + * frame-master = <&tdmacodec>; + */ + suffix-name = "alsaPORT-pcm"; + tdmacpu: cpu { + sound-dai = <&tdma>; + dai-tdm-slot-tx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-rx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-num = <8>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <24576000>; + }; + tdmacodec: codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@1 { + format = "i2s";// "dsp_a"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdmb>; + frame-master = <&tdmb>; + /* slave mode */ + //bitclock-master = <&tdmbcodec>; + //frame-master = <&tdmbcodec>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-i2s"; + cpu { + sound-dai = <&tdmb>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + /* + * dai-tdm-slot-tx-mask = + * <1 1 1 1 1 1 1 1>; + * dai-tdm-slot-rx-mask = + * <1 1 1 1 1 1 1 1>; + * dai-tdm-slot-num = <8>; + */ + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmbcodec: codec { + sound-dai = <&dummy_codec &dummy_codec + &amlogic_codec &ad82584f_62>; + }; + }; + + aml-audio-card,dai-link@2 { + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdmc>; + frame-master = <&tdmc>; + /* slave mode */ + //bitclock-master = <&tdmccodec>; + //frame-master = <&tdmccodec>; + /* suffix-name, sync with android audio hal used for */ + //suffix-name = "alsaPORT-tdm"; + cpu { + sound-dai = <&tdmc>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmccodec: codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@3 { + mclk-fs = <64>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-pdm"; + cpu { + sound-dai = <&pdm>; + }; + codec { + sound-dai = <&pdm_codec>; + }; + }; + + aml-audio-card,dai-link@4 { + mclk-fs = <128>; + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-spdif"; + cpu { + sound-dai = <&spdifa>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@5 { + mclk-fs = <128>; + continuous-clock; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-spdifb"; + cpu { + sound-dai = <&spdifb>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + aml-audio-card,dai-link@6 { + mclk-fs = <256>; + suffix-name = "alsaPORT-earc"; + cpu { + sound-dai = <&earc>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + }; + audiolocker: locker { + compatible = "amlogic, audiolocker"; + clocks = <&clkaudio CLKID_AUDIO_LOCKER_OUT + &clkaudio CLKID_AUDIO_LOCKER_IN + &clkaudio CLKID_AUDIO_MCLK_D + &clkaudio CLKID_AUDIO_MCLK_E + &clkc CLKID_MPLL1 + &clkc CLKID_MPLL2>; + clock-names = "lock_out", "lock_in", "out_src", + "in_src", "out_calc", "in_ref"; + interrupts = ; + interrupt-names = "irq"; + frequency = <49000000>; /* pll */ + dividor = <49>; /* locker's parent */ + status = "disabled"; + }; + /* Audio Related end */ + dvb { + compatible = "amlogic, dvb"; + dev_name = "dvb"; + status = "okay"; +// fe0_mode = "internal"; +// fe0_tuner = <&tuner>; + /*"parallel","serial","disable"*/ +// ts2 = "parallel"; +// ts2_control = <0>; +// ts2_invert = <0>; + interrupts = <0 23 1 + 0 5 1 + 0 53 1 + 0 19 1 + 0 25 1 + 0 18 1 + 0 24 1>; + interrupt-names = "demux0_irq", + "demux1_irq", + "demux2_irq", + "dvr0_irq", + "dvr1_irq", + "dvrfill0_fill", + "dvrfill1_flush"; + clocks = <&clkc CLKID_DEMUX + &clkc CLKID_AHB_ARB0 + &clkc CLKID_DOS_PARSER>; + clock-names = "demux", "ahbarb0", "uparsertop"; + }; + tuner: tuner { + compatible = "amlogic, tuner"; + status = "okay"; + tuner_name = "mxl661_tuner"; + tuner_i2c_adap = <&i2c1>; + tuner_i2c_addr = <0x60>; + tuner_xtal = <0>; /* 0: 16MHz, 1: 24MHz */ + tuner_xtal_mode = <0>; + /* NO_SHARE_XTAL(0) + * SLAVE_XTAL_SHARE(1) + */ + tuner_xtal_cap = <30>; /* when tuner_xtal_mode = 1, set 25 */ + }; + + + p_tsensor: p_tsensor@ff634800 { + compatible = "amlogic, r1p1-tsensor"; + device_name = "meson-pthermal"; + status = "okay"; + reg = <0x0 0xff634800 0x0 0x50>, + <0x0 0xff800268 0x0 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 35 0>; + clocks = <&clkc CLKID_TS_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + d_tsensor: d_tsensor@ff634c00 { + compatible = "amlogic, r1p1-tsensor"; + device_name = "meson-dthermal"; + status = "okay"; + reg = <0x0 0xff634c00 0x0 0x50>, + <0x0 0xff800230 0x0 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 36 0>; + clocks = <&clkc CLKID_TS_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + meson_cooldev: meson-cooldev@0 { + status = "okay"; + compatible = "amlogic, meson-cooldev"; + device_name = "mcooldev"; + cooling_devices { + cpufreq_cool_cluster0 { + min_state = <1000000>; + dyn_coeff = <125>; + cluster_id = <0>; + node_name = "cpufreq_cool0"; + device_type = "cpufreq"; + }; + cpucore_cool_cluster0 { + min_state = <1>; + dyn_coeff = <0>; + cluster_id = <0>; + node_name = "cpucore_cool0"; + device_type = "cpucore"; + }; + gpufreq_cool { + min_state = <400>; + dyn_coeff = <215>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "gpufreq_cool0"; + device_type = "gpufreq"; + }; + gpucore_cool { + min_state = <1>; + dyn_coeff = <0>; + cluster_id = <0>; + node_name = "gpucore_cool0"; + device_type = "gpucore"; + }; + }; + cpufreq_cool0:cpufreq_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + cpucore_cool0:cpucore_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + gpufreq_cool0:gpufreq_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + gpucore_cool0:gpucore_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + }; + /*meson cooling devices end*/ + + thermal-zones { + soc_thermal: soc_thermal { + polling-delay = <1000>; + polling-delay-passive = <100>; + sustainable-power = <1410>; + thermal-sensors = <&p_tsensor 0>; + trips { + pswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + pcontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + phot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + pcritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + + cooling-maps { + cpufreq_cooling_map { + trip = <&pcontrol>; + cooling-device = <&cpufreq_cool0 0 4>; + contribution = <1024>; + }; + cpucore_cooling_map { + trip = <&pcontrol>; + cooling-device = <&cpucore_cool0 0 3>; + contribution = <1024>; + }; + gpufreq_cooling_map { + trip = <&pcontrol>; + cooling-device = <&gpufreq_cool0 0 4>; + contribution = <1024>; + }; + gpucore_cooling_map { + trip = <&pcontrol>; + cooling-device = <&gpucore_cool0 0 2>; + contribution = <1024>; + }; + }; + }; + ddr_thermal: ddr_thermal { + polling-delay = <2000>; + polling-delay-passive = <1000>; + sustainable-power = <1410>; + thermal-sensors = <&d_tsensor 1>; + trips { + dswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + dcontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + dhot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + dcritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + + }; + }; + /*thermal zone end*/ + + cpu_opp_table0: cpu_opp_table0 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <730000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <730000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <730000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <750000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <770000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <780000>; + }; + opp06 { + opp-hz = /bits/ 64 <1404000000>; + opp-microvolt = <790000>; + }; + opp07 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <800000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <810000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <850000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <900000>; + }; + opp11 { + opp-hz = /bits/ 64 <1908000000>; + opp-microvolt = <950000>; + }; + }; + + cpufreq-meson { + compatible = "amlogic, cpufreq-meson"; + pinctrl-names = "default"; + pinctrl-0 = <&pwm_ao_d_pins3>; + status = "okay"; + }; + +}; /* end of / */ + +&meson_fb { + status = "okay"; + display_size_default = <1920 1080 1920 2160 32>; + mem_size = <0x00800000 0x1980000 0x100000 0x100000 0x800000>; + logo_addr = "0x7f800000"; + mem_alloc = <0>; + pxp_mode = <0>; /** 0:normal mode 1:pxp mode */ +}; + +&pwm_AO_cd { + status = "okay"; +}; + +&i2c0 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&i2c0_master_pins2>; + clock-frequency = <400000>; + + gt9xx@5d { + compatible = "goodix,gt9xx"; + status = "disabled"; + reg = <0x5d>; + reset-gpio = <&gpio GPIOZ_9 0x00>; + irq-gpio = <&gpio GPIOZ_3 0x00>; + }; + + ftxx@38 { + compatible = "focaltech,fts"; + status = "disabled"; + reg = <0x38>; + reset-gpio = <&gpio GPIOZ_9 0x00>; + irq-gpio = <&gpio GPIOZ_3 0x00>; + x_max = <600>; + y_max = <1024>; + max-touch-number = <10>; + }; +}; + +&i2c2 { + status = "disabled"; + pinctrl-names="default"; + pinctrl-0=<&i2c2_master_pins2>; + clock-frequency = <100000>; +}; + +&i2c3 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&i2c3_master_pins2>; + clock-frequency = <100000>; /* default 100k */ + + /* for ref board */ + ad82584f_62: ad82584f_62@62 { + compatible = "ESMT, ad82584f"; + #sound-dai-cells = <0>; + reg = <0x31>; + status = "okay"; + reset_pin = <&gpio GPIOA_5 0>; + no_mclk; + }; + + bl_extern_i2c { + compatible = "bl_extern, i2c"; + dev_name = "lp8556"; + reg = <0x2c>; + status = "disabled"; + }; +}; + +&audiobus { + tdma: tdm@0 { + compatible = "amlogic, sm1-snd-tdma"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 1>; + dai-tdm-oe-lane-slot-mask-out = <1 0>; + dai-tdm-clk-sel = <0>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_A + &clkc CLKID_MPLL0>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmout_a &tdmin_a>; + + status = "okay"; + }; + + tdmb: tdm@1 { + compatible = "amlogic, sm1-snd-tdmb"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 1 0 0>; + dai-tdm-lane-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <1>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_B + &clkc CLKID_MPLL1 + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_A>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; + + mclk_pad = <0>; /* 0: mclk_0; 1: mclk_1 */ + + /* + * 0: tdmout_a; + * 1: tdmout_b; + * 2: tdmout_c; + * 3: spdifout; + * 4: spdifout_b; + */ + samesource_sel = <3>; + + status = "okay"; + }; + + tdmc: tdm@2 { + compatible = "amlogic, sm1-snd-tdmc"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <1 0 0 0>; + #dai-tdm-lane-slot-mask-out = <1 0 1 1>; + #dai-tdm-lane-oe-slot-mask-in = <0 0 0 0>; + #dai-tdm-lane-oe-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <2>; + + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmc_mclk &tdmout_c &tdmin_c>; + mclk_pad = <0>; /* 0: mclk_0; 1: mclk_1 */ + + status = "okay"; + }; + + spdifa: spdif@0 { + compatible = "amlogic, sm1-snd-spdif-a"; + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 + &clkc CLKID_FCLK_DIV4 + &clkaudio CLKID_AUDIO_GATE_SPDIFIN + &clkaudio CLKID_AUDIO_GATE_SPDIFOUT_A + &clkaudio CLKID_AUDIO_SPDIFIN + &clkaudio CLKID_AUDIO_SPDIFOUT_A>; + clock-names = "sysclk", "fixed_clk", "gate_spdifin", + "gate_spdifout", "clk_spdifin", "clk_spdifout"; + interrupts = + ; + + interrupt-names = "irq_spdifin"; + pinctrl-names = "spdif_pins"; + pinctrl-0 = <&spdifout /* &spdifin */>; + + status = "okay"; + }; + spdifb: spdif@1 { + compatible = "amlogic, sm1-snd-spdif-b"; + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 /*CLKID_HIFI_PLL*/ + &clkaudio CLKID_AUDIO_GATE_SPDIFOUT_B + &clkaudio CLKID_AUDIO_SPDIFOUT_B>; + clock-names = "sysclk", + "gate_spdifout", "clk_spdifout"; + + status = "okay"; + }; + pdm: pdm { + compatible = "amlogic, sm1-snd-pdm"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_PDM + &clkc CLKID_FCLK_DIV3 + &clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_PDMIN0 + &clkaudio CLKID_AUDIO_PDMIN1>; + clock-names = "gate", + "sysclk_srcpll", + "dclk_srcpll", + "pdm_dclk", + "pdm_sysclk"; + + pinctrl-names = "pdm_pins"; + pinctrl-0 = <&pdmin>; + + /* mode 0~4, defalut:1 */ + filter_mode = <1>; + + status = "okay"; + }; + + earc:earc { + compatible = "amlogic, sm1-snd-earc"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_EARCRX + &clkaudio CLKID_EARCRX_CMDC + &clkaudio CLKID_EARCRX_DMAC + &clkc CLKID_FCLK_DIV5 + &clkc CLKID_FCLK_DIV3 + >; + clock-names = "rx_gate", + "rx_cmdc", + "rx_dmac", + "rx_cmdc_srcpll", + "rx_dmac_srcpll"; + + interrupts = < + GIC_SPI 88 IRQ_TYPE_EDGE_RISING + GIC_SPI 87 IRQ_TYPE_EDGE_RISING + >; + interrupt-names = "rx_cmdc", "rx_dmac"; + + status = "okay"; + }; + + asrca: resample@0 { + compatible = "amlogic, sm1-resample"; + clocks = <&clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_MCLK_F + &clkaudio CLKID_AUDIO_RESAMPLE_A>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + /*same with toddr_src + * TDMIN_A, 0 + * TDMIN_B, 1 + * TDMIN_C, 2 + * SPDIFIN, 3 + * PDMIN, 4 + * NONE, + * TDMIN_LB, 6 + * LOOPBACK, 7 + */ + resample_module = <4>; + status = "disabled"; + }; + + vad:vad { + compatible = "amlogic, snd-vad"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_TOVAD + &clkc CLKID_FCLK_DIV5 + &clkaudio CLKID_AUDIO_VAD>; + clock-names = "gate", "pll", "clk"; + + interrupts = ; + interrupt-names = "irq_wakeup", "irq_frame_sync"; + + /* + * Data src sel: + * 0: tdmin_a; + * 1: tdmin_b; + * 2: tdmin_c; + * 3: spdifin; + * 4: pdmin; + * 5: loopback_b; + * 6: tdmin_lb; + * 7: loopback_a; + */ + src = <4>; + + /* + * deal with hot word in user space or kernel space + * 0: in user space + * 1: in kernel space + */ + level = <1>; + + status = "okay"; + }; +}; /* end of audiobus */ + +&pinctrl_periphs { + tdmout_a: tdmout_a { + mux { /* GPIOX_11, GPIOX_10, GPIOX_9 */ + groups = "tdma_sclk", + "tdma_fs", + "tdma_dout0"; + function = "tdma_out"; + }; + }; + + tdmin_a: tdmin_a { + mux { /* GPIOX_8 */ + groups = "tdma_din1"; + function = "tdma_in"; + }; + }; + + tdmb_mclk: tdmb_mclk { + mux { + groups = "mclk0_a"; + function = "mclk0"; + drive-strength = <2>; + }; + }; + tdmout_b: tdmout_b { + mux { /* GPIOA_1, GPIOA_2, GPIOA_3 */ + groups = "tdmb_sclk", + "tdmb_fs", + "tdmb_dout0"; + function = "tdmb_out"; + drive-strength = <2>; + }; + }; + + tdmin_b:tdmin_b { + mux { /* GPIOA_4 */ + groups = "tdmb_din1" + /*,"tdmb_slv_sclk", "tdmb_slv_fs"*/; + function = "tdmb_in"; + drive-strength = <2>; + }; + }; + + tdmc_mclk: tdmc_mclk { + mux { /* GPIOA_11 */ + groups = "mclk1_a"; + function = "mclk1"; + }; + }; + + tdmout_c:tdmout_c { + mux { /* GPIOA_12, GPIOA_13 */ + groups = "tdmc_sclk_a", + "tdmc_fs_a" + /*, "tdmc_dout0_a" + *, "tdmc_dout2" + *, "tdmc_dout3" + */; + function = "tdmc_out"; + }; + }; + + tdmin_c:tdmin_c { + mux { /* GPIOA_10 */ + groups = "tdmc_din0_a"; + function = "tdmc_in"; + }; + }; + + spdifin: spdifin { + mux {/* GPIOH_5 */ + groups = "spdif_in_h"; + function = "spdif_in"; + }; + }; + + pdmin: pdmin { + mux { /* GPIOA_5, GPIOA_6, GPIOA_8, GPIOA_9, GPIOA_7 */ + groups = "pdm_din0_a", + "pdm_din1_a", + "pdm_din2_a", + /*"pdm_din3_a",*/ + "pdm_dclk_a"; + function = "pdm"; + }; + }; + + bl_pwm_off_pins:bl_pwm_off_pin { + mux { + pins = "GPIOH_5"; + function = "gpio_periphs"; + output-high; + }; + }; + + clk12_24_z_pins:clk12_24_z_pins { + mux { + groups = "clk12_24_z"; + function = "clk12_24_ee"; + drive-strength = <3>; + }; + }; + + gen_clk_ee_z: gen_clk_ee_z { + mux { + groups="gen_clk_ee_z"; + function="gen_clk_ee"; + drive-strength = <3>; + }; + }; + + cam_dvp_pins:cam_dvp_pins { + mux { + groups = "bt656_a_vs", "bt656_a_hs", "bt656_a_clk", + "bt656_a_din0", "bt656_a_din1", "bt656_a_din2", + "bt656_a_din3", "bt656_a_din4", "bt656_a_din5", + "bt656_a_din6", "bt656_a_din7"; + function = "bt656"; + }; + }; + + +}; /* end of pinctrl_periphs */ + +&pinctrl_aobus { + spdifout: spdifout { + mux { /* GPIOAO_10 */ + groups = "spdif_out_ao"; + function = "spdif_out_ao"; + }; + }; +}; /* end of pinctrl_aobus */ + +&audio_data { + status = "okay"; +}; + +/* Audio Related End */ + +&pwm_ef { + status = "okay"; +}; + +&dwc3 { + status = "okay"; +}; + +&usb2_phy_v2 { + status = "okay"; + portnum = <2>; +}; + +&usb3_phy_v2 { + status = "okay"; + portnum = <1>; + otg = <1>; + gpio-vbus-power = "GPIOH_6"; + gpios = <&gpio GPIOH_6 GPIO_ACTIVE_HIGH>; +}; + +&dwc2_a { + status = "okay"; + /** 0: normal, 1: otg+dwc3 host only, 2: otg+dwc3 device only*/ + controller-type = <3>; +}; +ðmac { + status = "okay"; + pinctrl-names = "internal_eth_pins"; + pinctrl-0 = <&internal_eth_pins>; + mc_val = <0x4be04>; + + internal_phy=<1>; +}; + +&uart_A { + status = "okay"; +}; + +/*if you want to use vdin just modify status to "ok"*/ +&vdin0 { + memory-region = <&vdin0_cma_reserved>; + status = "okay"; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + *bit4:support yuv422 10bit full pack mode (from txl new add) + */ + tv_bit_mode = <0x15>; +}; +&vdin1 { + memory-region = <&vdin1_cma_reserved>; + status = "okay"; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + */ + tv_bit_mode = <1>; +}; + + +&sd_emmc_c { + status = "okay"; + emmc { + caps = "MMC_CAP_8_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + /* "MMC_CAP_1_8V_DDR", */ + "MMC_CAP_HW_RESET", + "MMC_CAP_ERASE", + "MMC_CAP_CMD23"; + caps2 = "MMC_CAP2_HS200"; + /* "MMC_CAP2_HS400";*/ + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&sd_emmc_b { + status = "okay"; + sd { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED"; + f_min = <400000>; + f_max = <50000000>; + }; +}; + + +&sd_emmc_a { + status = "okay"; + sdio { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + "MMC_CAP_UHS_SDR12", + "MMC_CAP_UHS_SDR25", + "MMC_CAP_UHS_SDR50", + "MMC_CAP_UHS_SDR104", + "MMC_PM_KEEP_POWER", + "MMC_CAP_SDIO_IRQ"; + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&nand { + status = "disabled"; + plat-names = "bootloader","nandnormal"; + plat-num = <2>; + plat-part-0 = <&bootloader>; + plat-part-1 = <&nandnormal>; + bootloader: bootloader{ + enable_pad ="ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <1>; + part_num = <0>; + rb_detect = <1>; + }; + nandnormal: nandnormal{ + enable_pad ="ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + plane_mode = "twoplane"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <2>; + part_num = <3>; + partition = <&nand_partitions>; + rb_detect = <1>; + }; + nand_partitions:nand_partition{ + /* + * if bl_mode is 1, tpl size was generate by + * fip_copies * fip_size which + * will not skip bad when calculating + * the partition size; + * + * if bl_mode is 0, + * tpl partition must be comment out. + */ + tpl{ + offset=<0x0 0x0>; + size=<0x0 0x0>; + }; + logo{ + offset=<0x0 0x0>; + size=<0x0 0x200000>; + }; + recovery{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + boot{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + system{ + offset=<0x0 0x0>; + size=<0x0 0x4000000>; + }; + data{ + offset=<0xffffffff 0xffffffff>; + size=<0x0 0x0>; + }; + }; +}; + +&pcie_A { + reset-gpio = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; + status = "disable"; +}; + +&meson_cooldev { + status = "okay"; +}; + +&defendkey { + status = "okay"; +}; + diff --git a/arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts b/arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts new file mode 100644 index 000000000000..12b669b1fe7f --- /dev/null +++ b/arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts @@ -0,0 +1,1627 @@ +/* + * arch/arm64/boot/dts/amlogic/sm1_s905d3_skt.dts + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +/dts-v1/; + +#include "mesonsm1.dtsi" +#include "partition_mbox_normal.dtsi" +#include "mesonsm1_skt-panel.dtsi" + +/ { + model = "Amlogic"; + amlogic-dt-id = "sm1_skt_2g"; + compatible = "amlogic, g12a"; + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + + aliases { + serial0 = &uart_AO; + serial1 = &uart_A; + serial2 = &uart_B; + serial3 = &uart_C; + serial4 = &uart_AO_B; + tsensor0 = &p_tsensor; + tsensor1 = &d_tsensor; + i2c0 = &i2c0; + i2c1 = &i2c1; + i2c2 = &i2c2; + i2c3 = &i2c3; + i2c4 = &i2c_AO; + }; + + memory@00000000 { + device_type = "memory"; + linux,usable-memory = <0x0 0x000000 0x0 0x80000000>; + }; + + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + /* global autoconfigured region for contiguous allocations */ + ramoops@0x07400000 { + compatible = "ramoops"; + reg = <0x0 0x07400000 0x0 0x00100000>; + record-size = <0x8000>; + console-size = <0x8000>; + ftrace-size = <0x20000>; + }; + + secmon_reserved:linux,secmon { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x400000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x05000000 0x0 0x400000>; + }; + secos_reserved:linux,secos { + status = "disable"; + compatible = "amlogic, aml_secos_memory"; + reg = <0x0 0x05300000 0x0 0x2000000>; + no-map; + }; + logo_reserved:linux,meson-fb { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x800000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x7f800000 0x0 0x800000>; + }; + ion_cma_reserved:linux,ion-dev { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x8000000>; + alignment = <0x0 0x400000>; + }; + //di_reserved:linux,di { + //compatible = "amlogic, di-mem"; + /* buffer_size = 3621952(yuv422 8bit) */ + /* 4179008(yuv422 10bit full pack mode) */ + /** 10x3621952=34.6M(0x23) support 8bit **/ + /** 10x4736064=45.2M(0x2e) support 12bit **/ + /** 10x4179008=40M(0x28) support 10bit **/ + //size = <0x0 0x2800000>; + //no-map; + //}; + /*di CMA pool */ + di_cma_reserved:linux,di_cma { + compatible = "shared-dma-pool"; + reusable; + /* buffer_size = 3621952(yuv422 8bit) + * | 4736064(yuv422 10bit) + * | 4074560(yuv422 10bit full pack mode) + * 10x3621952=34.6M(0x23) support 8bit + * 10x4736064=45.2M(0x2e) support 12bit + * 10x4074560=40M(0x28) support 10bit + */ + size = <0x0 0x02800000>; + alignment = <0x0 0x400000>; + }; + /* POST PROCESS MANAGER */ + ppmgr_reserved:linux,ppmgr { + compatible = "shared-dma-pool"; + size = <0x0 0x0>; + }; + + codec_mm_cma:linux,codec_mm_cma { + compatible = "shared-dma-pool"; + reusable; + /* ion_codec_mm max can alloc size 80M*/ + size = <0x0 0x13400000>; + alignment = <0x0 0x400000>; + linux,contiguous-region; + }; + /* codec shared reserved */ + codec_mm_reserved:linux,codec_mm_reserved { + compatible = "amlogic, codec-mm-reserved"; + size = <0x0 0x0>; + alignment = <0x0 0x100000>; + //no-map; + }; + /* vdin0 CMA pool */ + vdin0_cma_reserved:linux,vdin0_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16+4 M */ + size = <0x0 0x04000000>; + alignment = <0x0 0x400000>; + }; + /* vdin1 CMA pool */ + vdin1_cma_reserved:linux,vdin1_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16 M */ + size = <0x0 0x04000000>; + alignment = <0x0 0x400000>; + }; + vm0_cma_reserved:linux,vm0_cma { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x2000000>; + alignment = <0x0 0x400000>; + }; + }; + + galcore { + status = "okay"; + }; + gpioleds { + compatible = "gpio-leds"; + status = "okay"; + + sys_led { + label="sys_led"; + gpios=<&gpio_ao GPIOAO_11 GPIO_ACTIVE_HIGH>; + default-state ="on"; + }; + }; + + cvbsout { + compatible = "amlogic, cvbsout-sm1"; + dev_name = "cvbsout"; + status = "okay"; + clocks = <&clkc CLKID_VCLK2_ENCI + &clkc CLKID_VCLK2_VENCI0 + &clkc CLKID_VCLK2_VENCI1 + &clkc CLKID_DAC_CLK>; + clock-names = "venci_top_gate", + "venci_0_gate", + "venci_1_gate", + "vdac_clk_gate"; + /* clk path */ + /* 0:vid_pll vid2_clk */ + /* 1:gp0_pll vid2_clk */ + /* 2:vid_pll vid1_clk */ + /* 3:gp0_pll vid1_clk */ + clk_path = <0>; + + /* performance: reg_address, reg_value */ + /* sm1 */ + performance = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x8080 + 0x1b05 0xfd + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + performance_sarft = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x0 + 0x1b05 0x9 + 0x1c59 0xfc48 + 0xffff 0x0>; /* ending flag */ + performance_revB_telecom = <0x1bf0 0x9 + 0x1b56 0x546 + 0x1b12 0x8080 + 0x1b05 0x9 + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + }; + + bt-dev{ + compatible = "amlogic, bt-dev"; + dev_name = "bt-dev"; + status = "okay"; + gpio_reset = <&gpio GPIOX_17 GPIO_ACTIVE_HIGH>; + gpio_hostwake = <&gpio GPIOX_19 GPIO_ACTIVE_HIGH>; + }; + + wifi{ + compatible = "amlogic, aml_wifi"; + dev_name = "aml_wifi"; + status = "okay"; + interrupt_pin = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; + irq_trigger_type = "GPIO_IRQ_LOW"; + power_on_pin = <&gpio GPIOX_6 GPIO_ACTIVE_HIGH>; + dhd_static_buf; //if use bcm wifi, config dhd_static_buf + pinctrl-names = "default"; + pinctrl-0 = <&pwm_e_pins>; + pwm_config = <&wifi_pwm_conf>; + }; + + wifi_pwm_conf:wifi_pwm_conf{ + pwm_channel1_conf { + pwms = <&pwm_ef MESON_PWM_0 30541 0>; + duty-cycle = <15270>; + times = <10>; + }; + pwm_channel2_conf { + pwms = <&pwm_ef MESON_PWM_2 30500 0>; + duty-cycle = <15250>; + times = <12>; + }; + }; + + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + + codec_mm { + compatible = "amlogic, codec, mm"; + memory-region = <&codec_mm_cma &codec_mm_reserved>; + dev_name = "codec_mm"; + status = "okay"; + }; + + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + + ppmgr { + compatible = "amlogic, ppmgr"; + memory-region = <&ppmgr_reserved>; + dev_name = "ppmgr"; + status = "okay"; + }; + + deinterlace { + compatible = "amlogic, deinterlace"; + status = "okay"; + /* 0:use reserved; 1:use cma; 2:use cma as reserved */ + flag_cma = <1>; + //memory-region = <&di_reserved>; + memory-region = <&di_cma_reserved>; + interrupts = <0 46 1 + 0 40 1>; + interrupt-names = "pre_irq", "post_irq"; + clocks = <&clkc CLKID_VPU_CLKB_TMP_COMP>, + <&clkc CLKID_VPU_CLKB_COMP>; + clock-names = "vpu_clkb_tmp_composite", + "vpu_clkb_composite"; + clock-range = <334 667>; + /* buffer-size = <3621952>;(yuv422 8bit) */ + buffer-size = <4074560>;/*yuv422 fullpack*/ + /* reserve-iomap = "true"; */ + /* if enable nr10bit, set nr10bit-support to 1 */ + post-wr-support = <1>; + nr10bit-support = <1>; + nrds-enable = <1>; + pps-enable = <1>; + }; + ionvideo { + compatible = "amlogic, ionvideo"; + dev_name = "ionvideo"; + status = "okay"; + }; + vm0 { + compatible = "amlogic, vm"; + memory-region = <&vm0_cma_reserved>; + dev_name = "vm0"; + status = "disabled"; + vm_id = <0>; + }; + + amvdec_656in { + /*bt656 gpio conflict with i2c0*/ + compatible = "amlogic, amvdec_656in"; + dev_name = "amvdec_656in"; + status = "disabled"; + reg = <0x0 0xffe02000 0x0 0x7c>; + clocks = <&clkc CLKID_BT656_COMP>, + <&clkc CLKID_BT656>; + clock-names = "cts_bt656_clk1", + "clk_gate_bt656"; + /* bt656in1, bt656in2 */ + bt656in1 { + bt656_id = <1>; + status = "disabled"; + }; + }; + + aml_cams { + compatible = "amlogic, cams_prober"; + status = "disabled"; + pinctrl-names="default"; + pinctrl-0=<&cam_dvp_pins &gen_clk_ee_z>; + clocks = <&clkc CLKID_GEN_CLK>; + clock-names = "g12a_24m"; + cam_0{ + cam_name = "gc2145"; + front_back = <0>; + /*u200 i2c2 gpio conflict with ethmac*/ + camera-i2c-bus = <&i2c2>; + gpio_pwdn-gpios = <&gpio GPIOZ_2 GPIO_ACTIVE_HIGH>; + gpio_rst-gpios = <&gpio GPIOZ_12 GPIO_ACTIVE_HIGH>; + mirror_flip = <1>; + vertical_flip = <1>; + spread_spectrum = <0>; + bt_path = "gpio"; + bt_path_count = <1>; + vdin_path = <0>; + status = "okay"; + }; + }; + + gpio_keypad{ + compatible = "amlogic, gpio_keypad"; + status = "okay"; + scan_period = <20>; + key_num = <1>; + key_name = "power"; + key_code = <116>; + key-gpios = <&gpio_ao GPIOAO_3 GPIO_ACTIVE_HIGH>; + detect_mode = <0>;/*0:polling mode, 1:irq mode*/ + }; + + adc_keypad { + compatible = "amlogic, adc_keypad"; + status = "okay"; + key_name = "vol-", "vol+", "enter"; + key_num = <3>; + io-channels = <&saradc SARADC_CH2>; + io-channel-names = "key-chan-2"; + key_chan = ; + key_code = <114 115 28>; + key_val = <143 266 389>; //val=voltage/1800mV*1023 + key_tolerance = <40 40 40>; + }; + + unifykey{ + compatible = "amlogic, unifykey"; + status = "ok"; + unifykey-num = <17>; + unifykey-index-0 = <&keysn_0>; + unifykey-index-1 = <&keysn_1>; + unifykey-index-2 = <&keysn_2>; + unifykey-index-3 = <&keysn_3>; + unifykey-index-4 = <&keysn_4>; + unifykey-index-5 = <&keysn_5>; + unifykey-index-6 = <&keysn_6>; + unifykey-index-7 = <&keysn_7>; + unifykey-index-8 = <&keysn_8>; + unifykey-index-9 = <&keysn_9>; + unifykey-index-10= <&keysn_10>; + unifykey-index-11= <&keysn_11>; + unifykey-index-12= <&keysn_12>; + unifykey-index-13= <&keysn_13>; + unifykey-index-14= <&keysn_14>; + unifykey-index-15= <&keysn_15>; + unifykey-index-16= <&keysn_16>; + + keysn_0: key_0{ + key-name = "usid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_1:key_1{ + key-name = "mac"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_2:key_2{ + key-name = "hdcp"; + key-device = "secure"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_3:key_3{ + key-name = "secure_boot_set"; + key-device = "efuse"; + key-permit = "write"; + }; + keysn_4:key_4{ + key-name = "mac_bt"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_5:key_5{ + key-name = "mac_wifi"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_6:key_6{ + key-name = "hdcp2_tx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_7:key_7{ + key-name = "hdcp2_rx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_8:key_8{ + key-name = "widevinekeybox"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_9:key_9{ + key-name = "deviceid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_10:key_10{ + key-name = "hdcp22_fw_private"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_11:key_11{ + key-name = "PlayReadykeybox25"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_12:key_12{ + key-name = "prpubkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_13:key_13{ + key-name = "prprivkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_14:key_14{ + key-name = "attestationkeybox";// attestation key + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_15:key_15{ + key-name = "region_code"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_16:key_16{ + key-name = "netflix_mgkid"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + };//End unifykey + + efusekey:efusekey{ + keynum = <4>; + key0 = <&key_0>; + key1 = <&key_1>; + key2 = <&key_2>; + key3 = <&key_3>; + key_0:key_0{ + keyname = "mac"; + offset = <0>; + size = <6>; + }; + key_1:key_1{ + keyname = "mac_bt"; + offset = <6>; + size = <6>; + }; + key_2:key_2{ + keyname = "mac_wifi"; + offset = <12>; + size = <6>; + }; + key_3:key_3{ + keyname = "usid"; + offset = <18>; + size = <16>; + }; + };//End efusekey + + amlvecm { + compatible = "amlogic, vecm"; + dev_name = "aml_vecm"; + status = "okay"; + gamma_en = <0>;/*1:enabel ;0:disable*/ + wb_en = <0>;/*1:enabel ;0:disable*/ + cm_en = <0>;/*1:enabel ;0:disable*/ + /*0: 709/601 1: bt2020*/ + tx_op_color_primary = <0>; + }; + + amdolby_vision { + compatible = "amlogic, dolby_vision_sm1"; + dev_name = "aml_amdolby_vision_driver"; + status = "okay"; + tv_mode = <0>;/*1:enabel ;0:disable*/ + }; + + /* Audio Related start */ + pdm_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, pdm_dummy_codec"; + status = "okay"; + }; + dummy_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, aml_dummy_codec"; + status = "okay"; + }; + amlogic_codec:t9015{ + #sound-dai-cells = <0>; + compatible = "amlogic, aml_codec_T9015"; + reg = <0x0 0xFF632000 0x0 0x2000>; + is_auge_used = <1>; /* meson or auge chipset used */ + tocodec_inout = <1>; + tdmout_index = <1>; + ch0_sel = <0>; + ch1_sel = <1>; + + status = "okay"; + }; + + auge_sound { + compatible = "amlogic, g12a-sound-card"; + aml-audio-card,name = "AML-AUGESOUND"; + + /*avout mute gpio*/ + avout_mute-gpios = <&gpio_ao GPIOAO_2 GPIO_ACTIVE_HIGH>; + + aml-audio-card,dai-link@0 { + format = "dsp_a"; + mclk-fs = <512>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdma>; + frame-master = <&tdma>; + /* slave mode */ + /* + * bitclock-master = <&tdmacodec>; + * frame-master = <&tdmacodec>; + */ + suffix-name = "alsaPORT-pcm"; + tdmacpu: cpu { + sound-dai = <&tdma>; + dai-tdm-slot-tx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-rx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-num = <8>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <24576000>; + }; + tdmacodec: codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@1 { + format = "i2s";// "dsp_a"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdmb>; + frame-master = <&tdmb>; + /* slave mode */ + //bitclock-master = <&tdmbcodec>; + //frame-master = <&tdmbcodec>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-i2s"; + cpu { + sound-dai = <&tdmb>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + /* + * dai-tdm-slot-tx-mask = + * <1 1 1 1 1 1 1 1>; + * dai-tdm-slot-rx-mask = + * <1 1 1 1 1 1 1 1>; + * dai-tdm-slot-num = <8>; + */ + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmbcodec: codec { + sound-dai = <&dummy_codec &dummy_codec + &amlogic_codec &ad82584f_62>; + }; + }; + + aml-audio-card,dai-link@2 { + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdmc>; + frame-master = <&tdmc>; + /* slave mode */ + //bitclock-master = <&tdmccodec>; + //frame-master = <&tdmccodec>; + /* suffix-name, sync with android audio hal used for */ + //suffix-name = "alsaPORT-tdm"; + cpu { + sound-dai = <&tdmc>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmccodec: codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@3 { + mclk-fs = <64>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-pdm"; + cpu { + sound-dai = <&pdm>; + }; + codec { + sound-dai = <&pdm_codec>; + }; + }; + + aml-audio-card,dai-link@4 { + mclk-fs = <128>; + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-spdif"; + cpu { + sound-dai = <&spdifa>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@5 { + mclk-fs = <128>; + continuous-clock; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-spdifb"; + cpu { + sound-dai = <&spdifb>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + aml-audio-card,dai-link@6 { + mclk-fs = <256>; + suffix-name = "alsaPORT-earc"; + cpu { + sound-dai = <&earc>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + }; + audiolocker: locker { + compatible = "amlogic, audiolocker"; + clocks = <&clkaudio CLKID_AUDIO_LOCKER_OUT + &clkaudio CLKID_AUDIO_LOCKER_IN + &clkaudio CLKID_AUDIO_MCLK_D + &clkaudio CLKID_AUDIO_MCLK_E + &clkc CLKID_MPLL1 + &clkc CLKID_MPLL2>; + clock-names = "lock_out", "lock_in", "out_src", + "in_src", "out_calc", "in_ref"; + interrupts = ; + interrupt-names = "irq"; + frequency = <49000000>; /* pll */ + dividor = <49>; /* locker's parent */ + status = "disabled"; + }; + /* Audio Related end */ + dvb { + compatible = "amlogic, dvb"; + dev_name = "dvb"; + status = "okay"; +// fe0_mode = "internal"; +// fe0_tuner = <&tuner>; + /*"parallel","serial","disable"*/ +// ts2 = "parallel"; +// ts2_control = <0>; +// ts2_invert = <0>; + interrupts = <0 23 1 + 0 5 1 + 0 53 1 + 0 19 1 + 0 25 1 + 0 18 1 + 0 24 1>; + interrupt-names = "demux0_irq", + "demux1_irq", + "demux2_irq", + "dvr0_irq", + "dvr1_irq", + "dvrfill0_fill", + "dvrfill1_flush"; + clocks = <&clkc CLKID_DEMUX + &clkc CLKID_AHB_ARB0 + &clkc CLKID_DOS_PARSER>; + clock-names = "demux", "ahbarb0", "uparsertop"; + }; + tuner: tuner { + compatible = "amlogic, tuner"; + status = "okay"; + tuner_name = "mxl661_tuner"; + tuner_i2c_adap = <&i2c1>; + tuner_i2c_addr = <0x60>; + tuner_xtal = <0>; /* 0: 16MHz, 1: 24MHz */ + tuner_xtal_mode = <0>; + /* NO_SHARE_XTAL(0) + * SLAVE_XTAL_SHARE(1) + */ + tuner_xtal_cap = <30>; /* when tuner_xtal_mode = 1, set 25 */ + }; + + p_tsensor: p_tsensor@ff634800 { + compatible = "amlogic, r1p1-tsensor"; + device_name = "meson-pthermal"; + status = "okay"; + reg = <0x0 0xff634800 0x0 0x50>, + <0x0 0xff800268 0x0 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 35 0>; + clocks = <&clkc CLKID_TS_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + d_tsensor: d_tsensor@ff634c00 { + compatible = "amlogic, r1p1-tsensor"; + device_name = "meson-dthermal"; + status = "okay"; + reg = <0x0 0xff634c00 0x0 0x50>, + <0x0 0xff800230 0x0 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 36 0>; + clocks = <&clkc CLKID_TS_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + meson_cooldev: meson-cooldev@0 { + status = "okay"; + compatible = "amlogic, meson-cooldev"; + device_name = "mcooldev"; + cooling_devices { + cpufreq_cool_cluster0 { + min_state = <1000000>; + dyn_coeff = <125>; + cluster_id = <0>; + node_name = "cpufreq_cool0"; + device_type = "cpufreq"; + }; + cpucore_cool_cluster0 { + min_state = <1>; + dyn_coeff = <0>; + cluster_id = <0>; + node_name = "cpucore_cool0"; + device_type = "cpucore"; + }; + gpufreq_cool { + min_state = <400>; + dyn_coeff = <215>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "gpufreq_cool0"; + device_type = "gpufreq"; + }; + gpucore_cool { + min_state = <1>; + dyn_coeff = <0>; + cluster_id = <0>; + node_name = "gpucore_cool0"; + device_type = "gpucore"; + }; + }; + cpufreq_cool0:cpufreq_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + cpucore_cool0:cpucore_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + gpufreq_cool0:gpufreq_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + gpucore_cool0:gpucore_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + }; + /*meson cooling devices end*/ + + thermal-zones { + soc_thermal: soc_thermal { + polling-delay = <1000>; + polling-delay-passive = <100>; + sustainable-power = <1410>; + thermal-sensors = <&p_tsensor 0>; + trips { + pswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + pcontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + phot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + pcritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + + cooling-maps { + cpufreq_cooling_map { + trip = <&pcontrol>; + cooling-device = <&cpufreq_cool0 0 4>; + contribution = <1024>; + }; + cpucore_cooling_map { + trip = <&pcontrol>; + cooling-device = <&cpucore_cool0 0 3>; + contribution = <1024>; + }; + gpufreq_cooling_map { + trip = <&pcontrol>; + cooling-device = <&gpufreq_cool0 0 4>; + contribution = <1024>; + }; + gpucore_cooling_map { + trip = <&pcontrol>; + cooling-device = <&gpucore_cool0 0 2>; + contribution = <1024>; + }; + }; + }; + ddr_thermal: ddr_thermal { + polling-delay = <2000>; + polling-delay-passive = <1000>; + sustainable-power = <1410>; + thermal-sensors = <&d_tsensor 1>; + trips { + dswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + dcontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + dhot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + dcritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + + }; + }; + /*thermal zone end*/ + + cpu_opp_table0: cpu_opp_table0 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <730000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <730000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <730000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <750000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <770000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <780000>; + }; + opp06 { + opp-hz = /bits/ 64 <1404000000>; + opp-microvolt = <790000>; + }; + opp07 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <800000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <810000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <850000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <900000>; + }; + opp11 { + opp-hz = /bits/ 64 <1908000000>; + opp-microvolt = <950000>; + }; + }; + + cpufreq-meson { + compatible = "amlogic, cpufreq-meson"; + pinctrl-names = "default"; + pinctrl-0 = <&pwm_ao_d_pins3>; + status = "okay"; + }; + +}; /* end of / */ + +&meson_fb { + status = "okay"; + display_size_default = <1920 1080 1920 2160 32>; + mem_size = <0x00800000 0x1980000 0x100000 0x100000 0x800000>; + logo_addr = "0x7f800000"; + mem_alloc = <0>; + pxp_mode = <0>; /** 0:normal mode 1:pxp mode */ +}; + +&pwm_AO_cd { + status = "okay"; +}; + +&i2c0 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&i2c0_master_pins2>; + clock-frequency = <400000>; + + gt9xx@5d { + compatible = "goodix,gt9xx"; + status = "disabled"; + reg = <0x5d>; + reset-gpio = <&gpio GPIOZ_9 0x00>; + irq-gpio = <&gpio GPIOZ_3 0x00>; + }; + + ftxx@38 { + compatible = "focaltech,fts"; + status = "disabled"; + reg = <0x38>; + reset-gpio = <&gpio GPIOZ_9 0x00>; + irq-gpio = <&gpio GPIOZ_3 0x00>; + x_max = <600>; + y_max = <1024>; + max-touch-number = <10>; + }; +}; + +&i2c2 { + status = "disabled"; + pinctrl-names="default"; + pinctrl-0=<&i2c2_master_pins2>; + clock-frequency = <100000>; +}; + +&i2c3 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&i2c3_master_pins2>; + clock-frequency = <100000>; /* default 100k */ + + /* for ref board */ + ad82584f_62: ad82584f_62@62 { + compatible = "ESMT, ad82584f"; + #sound-dai-cells = <0>; + reg = <0x31>; + status = "okay"; + reset_pin = <&gpio GPIOA_5 0>; + no_mclk; + }; + + bl_extern_i2c { + compatible = "bl_extern, i2c"; + dev_name = "lp8556"; + reg = <0x2c>; + status = "disabled"; + }; +}; + +&audiobus { + tdma: tdm@0 { + compatible = "amlogic, sm1-snd-tdma"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 1>; + dai-tdm-oe-lane-slot-mask-out = <1 0>; + dai-tdm-clk-sel = <0>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_A + &clkc CLKID_MPLL0>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmout_a &tdmin_a>; + + status = "okay"; + }; + + tdmb: tdm@1 { + compatible = "amlogic, sm1-snd-tdmb"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 1 0 0>; + dai-tdm-lane-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <1>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_B + &clkc CLKID_MPLL1 + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_A>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; + + mclk_pad = <0>; /* 0: mclk_0; 1: mclk_1 */ + + /* + * 0: tdmout_a; + * 1: tdmout_b; + * 2: tdmout_c; + * 3: spdifout; + * 4: spdifout_b; + */ + samesource_sel = <3>; + + status = "okay"; + }; + + tdmc: tdm@2 { + compatible = "amlogic, sm1-snd-tdmc"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <1 0 0 0>; + #dai-tdm-lane-slot-mask-out = <1 0 1 1>; + #dai-tdm-lane-oe-slot-mask-in = <0 0 0 0>; + #dai-tdm-lane-oe-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <2>; + + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmc_mclk &tdmout_c &tdmin_c>; + mclk_pad = <0>; /* 0: mclk_0; 1: mclk_1 */ + + status = "okay"; + }; + + spdifa: spdif@0 { + compatible = "amlogic, sm1-snd-spdif-a"; + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 + &clkc CLKID_FCLK_DIV4 + &clkaudio CLKID_AUDIO_GATE_SPDIFIN + &clkaudio CLKID_AUDIO_GATE_SPDIFOUT_A + &clkaudio CLKID_AUDIO_SPDIFIN + &clkaudio CLKID_AUDIO_SPDIFOUT_A>; + clock-names = "sysclk", "fixed_clk", "gate_spdifin", + "gate_spdifout", "clk_spdifin", "clk_spdifout"; + interrupts = + ; + + interrupt-names = "irq_spdifin"; + pinctrl-names = "spdif_pins"; + pinctrl-0 = <&spdifout &spdifin>; + + status = "okay"; + }; + spdifb: spdif@1 { + compatible = "amlogic, sm1-snd-spdif-b"; + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 /*CLKID_HIFI_PLL*/ + &clkaudio CLKID_AUDIO_GATE_SPDIFOUT_B + &clkaudio CLKID_AUDIO_SPDIFOUT_B>; + clock-names = "sysclk", + "gate_spdifout", "clk_spdifout"; + + status = "okay"; + }; + pdm: pdm { + compatible = "amlogic, sm1-snd-pdm"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_PDM + &clkc CLKID_FCLK_DIV3 + &clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_PDMIN0 + &clkaudio CLKID_AUDIO_PDMIN1>; + clock-names = "gate", + "sysclk_srcpll", + "dclk_srcpll", + "pdm_dclk", + "pdm_sysclk"; + + pinctrl-names = "pdm_pins"; + pinctrl-0 = <&pdmin>; + + /* mode 0~4, defalut:1 */ + filter_mode = <1>; + + status = "okay"; + }; + + earc:earc { + compatible = "amlogic, sm1-snd-earc"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_EARCRX + &clkaudio CLKID_EARCRX_CMDC + &clkaudio CLKID_EARCRX_DMAC + &clkc CLKID_FCLK_DIV5 + &clkc CLKID_FCLK_DIV3 + >; + clock-names = "rx_gate", + "rx_cmdc", + "rx_dmac", + "rx_cmdc_srcpll", + "rx_dmac_srcpll"; + + interrupts = < + GIC_SPI 88 IRQ_TYPE_EDGE_RISING + GIC_SPI 87 IRQ_TYPE_EDGE_RISING + >; + interrupt-names = "rx_cmdc", "rx_dmac"; + + status = "okay"; + }; + + asrca: resample@0 { + compatible = "amlogic, sm1-resample"; + clocks = <&clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_MCLK_F + &clkaudio CLKID_AUDIO_RESAMPLE_A>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + /*same with toddr_src + * TDMIN_A, 0 + * TDMIN_B, 1 + * TDMIN_C, 2 + * SPDIFIN, 3 + * PDMIN, 4 + * NONE, + * TDMIN_LB, 6 + * LOOPBACK, 7 + */ + resample_module = <4>; + status = "disabled"; + }; + + vad:vad { + compatible = "amlogic, snd-vad"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_TOVAD + &clkc CLKID_FCLK_DIV5 + &clkaudio CLKID_AUDIO_VAD>; + clock-names = "gate", "pll", "clk"; + + interrupts = ; + interrupt-names = "irq_wakeup", "irq_frame_sync"; + + /* + * Data src sel: + * 0: tdmin_a; + * 1: tdmin_b; + * 2: tdmin_c; + * 3: spdifin; + * 4: pdmin; + * 5: loopback_b; + * 6: tdmin_lb; + * 7: loopback_a; + */ + src = <4>; + + /* + * deal with hot word in user space or kernel space + * 0: in user space + * 1: in kernel space + */ + level = <1>; + + status = "okay"; + }; +}; /* end of audiobus */ + +&pinctrl_periphs { + tdmout_a: tdmout_a { + mux { /* GPIOX_11, GPIOX_10, GPIOX_9 */ + groups = "tdma_sclk", + "tdma_fs", + "tdma_dout0"; + function = "tdma_out"; + }; + }; + + tdmin_a: tdmin_a { + mux { /* GPIOX_8 */ + groups = "tdma_din1"; + function = "tdma_in"; + }; + }; + + tdmb_mclk: tdmb_mclk { + mux { + groups = "mclk0_a"; + function = "mclk0"; + drive-strength = <2>; + }; + }; + tdmout_b: tdmout_b { + mux { /* GPIOA_1, GPIOA_2, GPIOA_3 */ + groups = "tdmb_sclk", + "tdmb_fs", + "tdmb_dout0"; + function = "tdmb_out"; + drive-strength = <2>; + }; + }; + + tdmin_b:tdmin_b { + mux { /* GPIOA_4 */ + groups = "tdmb_din1" + /*,"tdmb_slv_sclk", "tdmb_slv_fs"*/; + function = "tdmb_in"; + drive-strength = <2>; + }; + }; + + tdmc_mclk: tdmc_mclk { + mux { /* GPIOA_11 */ + groups = "mclk1_a"; + function = "mclk1"; + }; + }; + + tdmout_c:tdmout_c { + mux { /* GPIOA_12, GPIOA_13, GPIOA_8, GPIOA_7*/ + groups = "tdmc_sclk_a", + "tdmc_fs_a", + "tdmc_dout0_a" + /*, "tdmc_dout2", + * "tdmc_dout3" + */; + function = "tdmc_out"; + }; + }; + + tdmin_c:tdmin_c { + mux { /* GPIOA_10 */ + groups = "tdmc_din0_a"; + function = "tdmc_in"; + }; + }; + + spdifin: spdifin { + mux {/* GPIOH_5 */ + groups = "spdif_in_h"; + function = "spdif_in"; + }; + }; + + pdmin: pdmin { + mux { /* GPIOA_5, GPIOA_6, GPIOA_8, GPIOA_9, GPIOA_7 */ + groups = "pdm_din0_a", + /*"pdm_din1_a",*/ + "pdm_din2_a", + /*"pdm_din3_a",*/ + "pdm_dclk_a"; + function = "pdm"; + }; + }; + + bl_pwm_off_pins:bl_pwm_off_pin { + mux { + pins = "GPIOH_5"; + function = "gpio_periphs"; + output-high; + }; + }; + + clk12_24_z_pins:clk12_24_z_pins { + mux { + groups = "clk12_24_z"; + function = "clk12_24_ee"; + drive-strength = <3>; + }; + }; + + gen_clk_ee_z: gen_clk_ee_z { + mux { + groups="gen_clk_ee_z"; + function="gen_clk_ee"; + drive-strength = <3>; + }; + }; + + cam_dvp_pins:cam_dvp_pins { + mux { + groups = "bt656_a_vs", "bt656_a_hs", "bt656_a_clk", + "bt656_a_din0", "bt656_a_din1", "bt656_a_din2", + "bt656_a_din3", "bt656_a_din4", "bt656_a_din5", + "bt656_a_din6", "bt656_a_din7"; + function = "bt656"; + }; + }; + + +}; /* end of pinctrl_periphs */ + +&pinctrl_aobus { + spdifout: spdifout { + mux { /* GPIOAO_10 */ + groups = "spdif_out_ao"; + function = "spdif_out_ao"; + }; + }; +}; /* end of pinctrl_aobus */ + +&audio_data { + status = "okay"; +}; + +/* Audio Related End */ + +&pwm_ef { + status = "okay"; +}; + +&dwc3 { + status = "okay"; +}; + +&usb2_phy_v2 { + status = "okay"; + portnum = <2>; +}; + +&usb3_phy_v2 { + status = "okay"; + portnum = <0>; + otg = <1>; + gpio-vbus-power = "GPIOH_6"; + gpios = <&gpio GPIOH_6 GPIO_ACTIVE_HIGH>; +}; + +&dwc2_a { + status = "okay"; + /** 0: normal, 1: otg+dwc3 host only, 2: otg+dwc3 device only*/ + controller-type = <3>; +}; +ðmac { + status = "okay"; + pinctrl-names = "internal_eth_pins"; + pinctrl-0 = <&internal_eth_pins>; + mc_val = <0x4be04>; + + internal_phy=<1>; +}; + +&uart_A { + status = "okay"; +}; + +/*if you want to use vdin just modify status to "ok"*/ +&vdin0 { + memory-region = <&vdin0_cma_reserved>; + status = "okay"; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + *bit4:support yuv422 10bit full pack mode (from txl new add) + */ + tv_bit_mode = <0x15>; +}; +&vdin1 { + memory-region = <&vdin1_cma_reserved>; + status = "okay"; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + */ + tv_bit_mode = <1>; +}; + + +&sd_emmc_c { + status = "okay"; + emmc { + caps = "MMC_CAP_8_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + /* "MMC_CAP_1_8V_DDR", */ + "MMC_CAP_HW_RESET", + "MMC_CAP_ERASE", + "MMC_CAP_CMD23"; + caps2 = "MMC_CAP2_HS200"; + /* "MMC_CAP2_HS400";*/ + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&sd_emmc_b { + status = "okay"; + sd { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED"; + f_min = <400000>; + f_max = <50000000>; + }; +}; + + +&sd_emmc_a { + status = "okay"; + sdio { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + "MMC_CAP_UHS_SDR12", + "MMC_CAP_UHS_SDR25", + "MMC_CAP_UHS_SDR50", + "MMC_CAP_UHS_SDR104", + "MMC_PM_KEEP_POWER", + "MMC_CAP_SDIO_IRQ"; + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&nand { + status = "disabled"; + plat-names = "bootloader","nandnormal"; + plat-num = <2>; + plat-part-0 = <&bootloader>; + plat-part-1 = <&nandnormal>; + bootloader: bootloader{ + enable_pad ="ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <1>; + part_num = <0>; + rb_detect = <1>; + }; + nandnormal: nandnormal{ + enable_pad ="ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + plane_mode = "twoplane"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <2>; + part_num = <3>; + partition = <&nand_partitions>; + rb_detect = <1>; + }; + nand_partitions:nand_partition{ + /* + * if bl_mode is 1, tpl size was generate by + * fip_copies * fip_size which + * will not skip bad when calculating + * the partition size; + * + * if bl_mode is 0, + * tpl partition must be comment out. + */ + tpl{ + offset=<0x0 0x0>; + size=<0x0 0x0>; + }; + logo{ + offset=<0x0 0x0>; + size=<0x0 0x200000>; + }; + recovery{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + boot{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + system{ + offset=<0x0 0x0>; + size=<0x0 0x4000000>; + }; + data{ + offset=<0xffffffff 0xffffffff>; + size=<0x0 0x0>; + }; + }; +}; + +&pcie_A { + reset-gpio = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; + status = "okay"; +}; + +&meson_cooldev { + status = "okay"; +}; + +&defendkey { + status = "okay"; +}; + diff --git a/arch/arm64/boot/dts/amlogic/sm1_s905x3_ac213.dts b/arch/arm64/boot/dts/amlogic/sm1_s905x3_ac213.dts new file mode 100644 index 000000000000..8c22a555aa35 --- /dev/null +++ b/arch/arm64/boot/dts/amlogic/sm1_s905x3_ac213.dts @@ -0,0 +1,1669 @@ +/* + * arch/arm64/boot/dts/amlogic/sm1_s905x3_ac213.dts + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +/dts-v1/; + +#include "mesonsm1.dtsi" +#include "partition_mbox_normal.dtsi" +#include "mesonsm1_skt-panel.dtsi" + +/ { + model = "Amlogic"; + amlogic-dt-id = "sm1_ac213_2g"; + compatible = "amlogic, g12a"; + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + + aliases { + serial0 = &uart_AO; + serial1 = &uart_A; + serial2 = &uart_B; + serial3 = &uart_C; + serial4 = &uart_AO_B; + tsensor0 = &p_tsensor; + tsensor1 = &d_tsensor; + i2c0 = &i2c0; + i2c1 = &i2c1; + i2c2 = &i2c2; + i2c3 = &i2c3; + i2c4 = &i2c_AO; + }; + + memory@00000000 { + device_type = "memory"; + linux,usable-memory = <0x0 0x000000 0x0 0x80000000>; + }; + + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + /* global autoconfigured region for contiguous allocations */ + ramoops@0x07400000 { + compatible = "ramoops"; + reg = <0x0 0x07400000 0x0 0x00100000>; + record-size = <0x8000>; + console-size = <0x8000>; + ftrace-size = <0x20000>; + }; + + secmon_reserved:linux,secmon { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x400000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x05000000 0x0 0x400000>; + }; + secos_reserved:linux,secos { + status = "disable"; + compatible = "amlogic, aml_secos_memory"; + reg = <0x0 0x05300000 0x0 0x2000000>; + no-map; + }; + logo_reserved:linux,meson-fb { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x800000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x7f800000 0x0 0x800000>; + }; + ion_cma_reserved:linux,ion-dev { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x8000000>; + alignment = <0x0 0x400000>; + }; + //di_reserved:linux,di { + //compatible = "amlogic, di-mem"; + /* buffer_size = 3621952(yuv422 8bit) */ + /* 4179008(yuv422 10bit full pack mode) */ + /** 10x3621952=34.6M(0x23) support 8bit **/ + /** 10x4736064=45.2M(0x2e) support 12bit **/ + /** 10x4179008=40M(0x28) support 10bit **/ + //size = <0x0 0x2800000>; + //no-map; + //}; + /*di CMA pool */ + di_cma_reserved:linux,di_cma { + compatible = "shared-dma-pool"; + reusable; + /* buffer_size = 3621952(yuv422 8bit) + * | 4736064(yuv422 10bit) + * | 4074560(yuv422 10bit full pack mode) + * 10x3621952=34.6M(0x23) support 8bit + * 10x4736064=45.2M(0x2e) support 12bit + * 10x4074560=40M(0x28) support 10bit + */ + size = <0x0 0x02800000>; + alignment = <0x0 0x400000>; + }; + /* POST PROCESS MANAGER */ + ppmgr_reserved:linux,ppmgr { + compatible = "shared-dma-pool"; + size = <0x0 0x0>; + }; + + codec_mm_cma:linux,codec_mm_cma { + compatible = "shared-dma-pool"; + reusable; + /* ion_codec_mm max can alloc size 80M*/ + size = <0x0 0x13400000>; + alignment = <0x0 0x400000>; + linux,contiguous-region; + }; + /* codec shared reserved */ + codec_mm_reserved:linux,codec_mm_reserved { + compatible = "amlogic, codec-mm-reserved"; + size = <0x0 0x0>; + alignment = <0x0 0x100000>; + //no-map; + }; + /* vdin0 CMA pool */ + vdin0_cma_reserved:linux,vdin0_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16+4 M */ + size = <0x0 0x04000000>; + alignment = <0x0 0x400000>; + }; + /* vdin1 CMA pool */ + vdin1_cma_reserved:linux,vdin1_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16 M */ + size = <0x0 0x04000000>; + alignment = <0x0 0x400000>; + }; + vm0_cma_reserved:linux,vm0_cma { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x2000000>; + alignment = <0x0 0x400000>; + }; + }; + + amlogic_battery:dummy-battery { + compatible = "amlogic, dummy-battery"; + status = "disabled"; + }; + + amlogic_charger:dummy-charger { + compatible = "amlogic, dummy-charger"; + status = "disabled"; + }; + + gpioleds { + compatible = "gpio-leds"; + status = "disabled"; + + net_red { + label="net_red"; + /*gpios=<&gpio GPIOA_14 GPIO_ACTIVE_LOW>;*/ + default-state ="on"; + }; + + net_green { + label="net_green"; + /*gpios=<&gpio GPIOA_15 GPIO_ACTIVE_HIGH>;*/ + default-state ="on"; + }; + + remote_led { + label = "remote_led"; + gpios = <&gpio_ao GPIOAO_10 GPIO_ACTIVE_LOW>; + default-state = "off"; + linux,default-trigger = "rc_feedback"; + }; + + sys_led { + label="sys_led"; + gpios=<&gpio_ao GPIOAO_11 GPIO_ACTIVE_LOW>; + default-state ="on"; + }; + }; + + cvbsout { + compatible = "amlogic, cvbsout-sm1"; + dev_name = "cvbsout"; + status = "okay"; + clocks = <&clkc CLKID_VCLK2_ENCI + &clkc CLKID_VCLK2_VENCI0 + &clkc CLKID_VCLK2_VENCI1 + &clkc CLKID_DAC_CLK>; + clock-names = "venci_top_gate", + "venci_0_gate", + "venci_1_gate", + "vdac_clk_gate"; + /* clk path */ + /* 0:vid_pll vid2_clk */ + /* 1:gp0_pll vid2_clk */ + /* 2:vid_pll vid1_clk */ + /* 3:gp0_pll vid1_clk */ + clk_path = <0>; + + /* performance: reg_address, reg_value */ + /* sm1 */ + performance = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x8080 + 0x1b05 0xfd + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + performance_sarft = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x0 + 0x1b05 0x9 + 0x1c59 0xfc48 + 0xffff 0x0>; /* ending flag */ + performance_revB_telecom = <0x1bf0 0x9 + 0x1b56 0x546 + 0x1b12 0x8080 + 0x1b05 0x9 + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + }; + + bt-dev{ + compatible = "amlogic, bt-dev"; + dev_name = "bt-dev"; + status = "okay"; + gpio_reset = <&gpio GPIOX_17 GPIO_ACTIVE_HIGH>; + gpio_hostwake = <&gpio GPIOX_19 GPIO_ACTIVE_HIGH>; + }; + + wifi{ + compatible = "amlogic, aml_wifi"; + dev_name = "aml_wifi"; + status = "okay"; + interrupt_pin = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; + irq_trigger_type = "GPIO_IRQ_LOW"; + power_on_pin = <&gpio GPIOX_6 GPIO_ACTIVE_HIGH>; + dhd_static_buf; //if use bcm wifi, config dhd_static_buf + pinctrl-names = "default"; + pinctrl-0 = <&pwm_e_pins>; + pwm_config = <&wifi_pwm_conf>; + }; + + wifi_pwm_conf:wifi_pwm_conf{ + pwm_channel1_conf { + pwms = <&pwm_ef MESON_PWM_0 30541 0>; + duty-cycle = <15270>; + times = <10>; + }; + pwm_channel2_conf { + pwms = <&pwm_ef MESON_PWM_2 30500 0>; + duty-cycle = <15250>; + times = <12>; + }; + }; + + codec_mm { + compatible = "amlogic, codec, mm"; + memory-region = <&codec_mm_cma &codec_mm_reserved>; + dev_name = "codec_mm"; + status = "okay"; + }; + + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0>; + alignment = <0x0>; + linux,contiguous-region; + }; + + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + + ppmgr { + compatible = "amlogic, ppmgr"; + memory-region = <&ppmgr_reserved>; + dev_name = "ppmgr"; + status = "okay"; + }; + + deinterlace { + compatible = "amlogic, deinterlace"; + status = "okay"; + /* 0:use reserved; 1:use cma; 2:use cma as reserved */ + flag_cma = <1>; + //memory-region = <&di_reserved>; + memory-region = <&di_cma_reserved>; + interrupts = <0 46 1 + 0 40 1>; + interrupt-names = "pre_irq", "post_irq"; + clocks = <&clkc CLKID_VPU_CLKB_TMP_COMP>, + <&clkc CLKID_VPU_CLKB_COMP>; + clock-names = "vpu_clkb_tmp_composite", + "vpu_clkb_composite"; + clock-range = <334 667>; + /* buffer-size = <3621952>;(yuv422 8bit) */ + buffer-size = <4074560>;/*yuv422 fullpack*/ + /* reserve-iomap = "true"; */ + /* if enable nr10bit, set nr10bit-support to 1 */ + post-wr-support = <1>; + nr10bit-support = <1>; + nrds-enable = <1>; + pps-enable = <1>; + }; + dvb { + compatible = "amlogic, dvb"; + dev_name = "dvb"; + status = "ok"; + + ts0 = "serial"; + ts0_control = <0x800>; + ts0_invert = <0>; + pinctrl-names = "s_ts0"; + pinctrl-0 = <&dvb_s_ts0_pins>; + + interrupts = <0 23 1 + 0 5 1 + 0 53 1 + 0 19 1 + 0 25 1 + 0 18 1 + 0 24 1>; + interrupt-names = "demux0_irq", + "demux1_irq", + "demux2_irq", + "dvr0_irq", + "dvr1_irq", + "dvrfill0_fill", + "dvrfill1_flush"; + }; + dvbfe { + compatible = "amlogic, dvbfe"; + dev_name = "dvbfe"; + dtv_demod0 = "Avl6762"; + dtv_demod0_i2c_adap = <&i2c3>; + dtv_demod0_i2c_addr = <0x14>; + dtv_demod0_reset_value = <0>; + dtv_demod0_reset_gpio = <&gpio GPIOZ_10 GPIO_ACTIVE_HIGH>; + dtv_demod0_ant_poweron_value = <0>; + dtv_demod0_ant_power_gpio = <&gpio GPIOH_5 GPIO_ACTIVE_HIGH>; + dtv_demod0_tuner_type = <52>; + fe0_dtv_demod = <0>; + fe0_ts = <0>; + fe0_dev = <0>; + }; + ionvideo { + compatible = "amlogic, ionvideo"; + dev_name = "ionvideo"; + status = "okay"; + }; + vm0 { + compatible = "amlogic, vm"; + memory-region = <&vm0_cma_reserved>; + dev_name = "vm0"; + status = "disabled"; + vm_id = <0>; + }; + + amvdec_656in { + /*bt656 gpio conflict with i2c0*/ + compatible = "amlogic, amvdec_656in"; + dev_name = "amvdec_656in"; + status = "disabled"; + reg = <0x0 0xffe02000 0x0 0x7c>; + clocks = <&clkc CLKID_BT656_COMP>, + <&clkc CLKID_BT656>; + clock-names = "cts_bt656_clk1", + "clk_gate_bt656"; + /* bt656in1, bt656in2 */ + bt656in1 { + bt656_id = <1>; + status = "disabled"; + }; + }; + + aml_cams { + compatible = "amlogic, cams_prober"; + status = "disabled"; + pinctrl-names="default"; + pinctrl-0=<&cam_dvp_pins &gen_clk_ee_z>; + clocks = <&clkc CLKID_GEN_CLK>; + clock-names = "g12a_24m"; + cam_0{ + cam_name = "gc2145"; + front_back = <0>; + /*u200 i2c2 gpio conflict with ethmac*/ + camera-i2c-bus = <&i2c2>; + gpio_pwdn-gpios = <&gpio GPIOZ_2 GPIO_ACTIVE_HIGH>; + gpio_rst-gpios = <&gpio GPIOZ_12 GPIO_ACTIVE_HIGH>; + mirror_flip = <1>; + vertical_flip = <1>; + spread_spectrum = <0>; + bt_path = "gpio"; + bt_path_count = <1>; + vdin_path = <0>; + status = "okay"; + }; + }; + + gpio_keypad{ + compatible = "amlogic, gpio_keypad"; + status = "okay"; + scan_period = <20>; + key_num = <1>; + key_name = "power"; + key_code = <116>; + key-gpios = <&gpio_ao GPIOAO_3 GPIO_ACTIVE_HIGH>; + detect_mode = <0>;/*0:polling mode, 1:irq mode*/ + }; + + adc_keypad { + compatible = "amlogic, adc_keypad"; + status = "okay"; + key_name = "vol-", "vol+", "enter"; + key_num = <3>; + io-channels = <&saradc SARADC_CH2>; + io-channel-names = "key-chan-2"; + key_chan = ; + key_code = <114 115 28>; + key_val = <143 266 389>; //val=voltage/1800mV*1023 + key_tolerance = <40 40 40>; + }; + + unifykey{ + compatible = "amlogic, unifykey"; + status = "ok"; + unifykey-num = <17>; + unifykey-index-0 = <&keysn_0>; + unifykey-index-1 = <&keysn_1>; + unifykey-index-2 = <&keysn_2>; + unifykey-index-3 = <&keysn_3>; + unifykey-index-4 = <&keysn_4>; + unifykey-index-5 = <&keysn_5>; + unifykey-index-6 = <&keysn_6>; + unifykey-index-7 = <&keysn_7>; + unifykey-index-8 = <&keysn_8>; + unifykey-index-9 = <&keysn_9>; + unifykey-index-10= <&keysn_10>; + unifykey-index-11= <&keysn_11>; + unifykey-index-12= <&keysn_12>; + unifykey-index-13= <&keysn_13>; + unifykey-index-14= <&keysn_14>; + unifykey-index-15= <&keysn_15>; + unifykey-index-16= <&keysn_16>; + + keysn_0: key_0{ + key-name = "usid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_1:key_1{ + key-name = "mac"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_2:key_2{ + key-name = "hdcp"; + key-device = "secure"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_3:key_3{ + key-name = "secure_boot_set"; + key-device = "efuse"; + key-permit = "write"; + }; + keysn_4:key_4{ + key-name = "mac_bt"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_5:key_5{ + key-name = "mac_wifi"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_6:key_6{ + key-name = "hdcp2_tx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_7:key_7{ + key-name = "hdcp2_rx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_8:key_8{ + key-name = "widevinekeybox"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_9:key_9{ + key-name = "deviceid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_10:key_10{ + key-name = "hdcp22_fw_private"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_11:key_11{ + key-name = "PlayReadykeybox25"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_12:key_12{ + key-name = "prpubkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_13:key_13{ + key-name = "prprivkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_14:key_14{ + key-name = "attestationkeybox";// attestation key + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_15:key_15{ + key-name = "region_code"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_16:key_16{ + key-name = "netflix_mgkid"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + };//End unifykey + + efusekey:efusekey{ + keynum = <4>; + key0 = <&key_0>; + key1 = <&key_1>; + key2 = <&key_2>; + key3 = <&key_3>; + key_0:key_0{ + keyname = "mac"; + offset = <0>; + size = <6>; + }; + key_1:key_1{ + keyname = "mac_bt"; + offset = <6>; + size = <6>; + }; + key_2:key_2{ + keyname = "mac_wifi"; + offset = <12>; + size = <6>; + }; + key_3:key_3{ + keyname = "usid"; + offset = <18>; + size = <16>; + }; + };//End efusekey + + amlvecm { + compatible = "amlogic, vecm"; + dev_name = "aml_vecm"; + status = "okay"; + gamma_en = <0>;/*1:enabel ;0:disable*/ + wb_en = <0>;/*1:enabel ;0:disable*/ + cm_en = <0>;/*1:enabel ;0:disable*/ + /*0: 709/601 1: bt2020*/ + tx_op_color_primary = <0>; + }; + + amdolby_vision { + compatible = "amlogic, dolby_vision_sm1"; + dev_name = "aml_amdolby_vision_driver"; + status = "okay"; + tv_mode = <0>;/*1:enabel ;0:disable*/ + }; + + /* Audio Related start */ + pdm_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, pdm_dummy_codec"; + status = "okay"; + }; + dummy_codec:dummy{ + #sound-dai-cells = <0>; + compatible = "amlogic, aml_dummy_codec"; + status = "okay"; + }; + amlogic_codec:t9015{ + #sound-dai-cells = <0>; + compatible = "amlogic, aml_codec_T9015"; + reg = <0x0 0xFF632000 0x0 0x2000>; + is_auge_used = <1>; /* meson or auge chipset used */ + tocodec_inout = <1>; + tdmout_index = <1>; + ch0_sel = <0>; + ch1_sel = <1>; + + status = "okay"; + }; + audio_effect:eqdrc{ + /*eq_enable = <1>;*/ + /*drc_enable = <1>;*/ + /* + * 0:tdmout_a + * 1:tdmout_b + * 2:tdmout_c + * 3:spdifout + * 4:spdifout_b + */ + eqdrc_module = <1>; + /* max 0xf, each bit for one lane, usually one lane */ + lane_mask = <0x1>; + /* max 0xff, each bit for one channel */ + channel_mask = <0x3>; + }; + auge_sound { + compatible = "amlogic, g12a-sound-card"; + aml-audio-card,name = "AML-AUGESOUND"; + + /*avout mute gpio*/ + avout_mute-gpios = <&gpio_ao GPIOAO_2 GPIO_ACTIVE_HIGH>; + + aml-audio-card,dai-link@0 { + format = "dsp_a"; + mclk-fs = <512>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdma>; + frame-master = <&tdma>; + /* slave mode */ + /* + * bitclock-master = <&tdmacodec>; + * frame-master = <&tdmacodec>; + */ + suffix-name = "alsaPORT-pcm"; + tdmacpu: cpu { + sound-dai = <&tdma>; + dai-tdm-slot-tx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-rx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-num = <8>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <24576000>; + }; + tdmacodec: codec { + sound-dai = <&dummy_codec &dummy_codec>; + }; + }; + + aml-audio-card,dai-link@1 { + format = "i2s";// "dsp_a"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdmb>; + frame-master = <&tdmb>; + /* slave mode */ + //bitclock-master = <&tdmbcodec>; + //frame-master = <&tdmbcodec>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-i2s"; + cpu { + sound-dai = <&tdmb>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + /* + * dai-tdm-slot-tx-mask = + * <1 1 1 1 1 1 1 1>; + * dai-tdm-slot-rx-mask = + * <1 1 1 1 1 1 1 1>; + * dai-tdm-slot-num = <8>; + */ + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmbcodec: codec { + sound-dai = <&dummy_codec &dummy_codec + &amlogic_codec /*&ad82584f_62*/>; + }; + }; + + aml-audio-card,dai-link@2 { + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdmc>; + frame-master = <&tdmc>; + /* slave mode */ + //bitclock-master = <&tdmccodec>; + //frame-master = <&tdmccodec>; + /* suffix-name, sync with android audio hal used for */ + //suffix-name = "alsaPORT-tdm"; + cpu { + sound-dai = <&tdmc>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmccodec: codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@3 { + mclk-fs = <64>; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-pdm"; + cpu { + sound-dai = <&pdm>; + }; + codec { + sound-dai = <&pdm_codec>; + }; + }; + + aml-audio-card,dai-link@4 { + mclk-fs = <128>; + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-spdif"; + cpu { + sound-dai = <&spdifa>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + /* spdif_b to hdmi, only playback */ + aml-audio-card,dai-link@5 { + mclk-fs = <128>; + continuous-clock; + /* suffix-name, sync with android audio hal + * what's the dai link used for + */ + suffix-name = "alsaPORT-spdifb"; + cpu { + sound-dai = <&spdifb>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + aml-audio-card,dai-link@6 { + mclk-fs = <256>; + suffix-name = "alsaPORT-earc"; + cpu { + sound-dai = <&earc>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + }; + audiolocker: locker { + compatible = "amlogic, audiolocker"; + clocks = <&clkaudio CLKID_AUDIO_LOCKER_OUT + &clkaudio CLKID_AUDIO_LOCKER_IN + &clkaudio CLKID_AUDIO_MCLK_D + &clkaudio CLKID_AUDIO_MCLK_E + &clkc CLKID_MPLL1 + &clkc CLKID_MPLL2>; + clock-names = "lock_out", "lock_in", "out_src", + "in_src", "out_calc", "in_ref"; + interrupts = ; + interrupt-names = "irq"; + frequency = <49000000>; /* pll */ + dividor = <49>; /* locker's parent */ + status = "disabled"; + }; + /* Audio Related end */ + p_tsensor: p_tsensor@ff634594 { + compatible = "amlogic, r1p1-tsensor"; + device_name = "meson-pthermal"; + status = "okay"; + reg = <0x0 0xff634800 0x0 0x50>, + <0x0 0xff800268 0x0 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 35 0>; + clocks = <&clkc CLKID_TS_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + d_tsensor: d_tsensor@ff800228 { + compatible = "amlogic, r1p1-tsensor"; + device_name = "meson-dthermal"; + status = "okay"; + reg = <0x0 0xff634c00 0x0 0x50>, + <0x0 0xff800230 0x0 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 36 0>; + clocks = <&clkc CLKID_TS_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + meson_cooldev: meson-cooldev@0 { + status = "okay"; + compatible = "amlogic, meson-cooldev"; + device_name = "mcooldev"; + cooling_devices { + cpufreq_cool_cluster0 { + min_state = <1000000>; + dyn_coeff = <125>; + cluster_id = <0>; + node_name = "cpufreq_cool0"; + device_type = "cpufreq"; + }; + cpucore_cool_cluster0 { + min_state = <1>; + dyn_coeff = <0>; + cluster_id = <0>; + node_name = "cpucore_cool0"; + device_type = "cpucore"; + }; + gpufreq_cool { + min_state = <400>; + dyn_coeff = <215>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "gpufreq_cool0"; + device_type = "gpufreq"; + }; + gpucore_cool { + min_state = <1>; + dyn_coeff = <0>; + cluster_id = <0>; + node_name = "gpucore_cool0"; + device_type = "gpucore"; + }; + }; + cpufreq_cool0:cpufreq_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + cpucore_cool0:cpucore_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + gpufreq_cool0:gpufreq_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + gpucore_cool0:gpucore_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + }; + /*meson cooling devices end*/ + + thermal-zones { + soc_thermal: soc_thermal { + polling-delay = <1000>; + polling-delay-passive = <100>; + sustainable-power = <1410>; + thermal-sensors = <&p_tsensor 0>; + trips { + pswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + pcontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + phot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + pcritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + + cooling-maps { + cpufreq_cooling_map { + trip = <&pcontrol>; + cooling-device = <&cpufreq_cool0 0 4>; + contribution = <1024>; + }; + cpucore_cooling_map { + trip = <&pcontrol>; + cooling-device = <&cpucore_cool0 0 3>; + contribution = <1024>; + }; + gpufreq_cooling_map { + trip = <&pcontrol>; + cooling-device = <&gpufreq_cool0 0 4>; + contribution = <1024>; + }; + gpucore_cooling_map { + trip = <&pcontrol>; + cooling-device = <&gpucore_cool0 0 2>; + contribution = <1024>; + }; + }; + }; + ddr_thermal: ddr_thermal { + polling-delay = <2000>; + polling-delay-passive = <1000>; + sustainable-power = <1410>; + thermal-sensors = <&d_tsensor 1>; + trips { + dswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + dcontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + dhot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + dcritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + + }; + }; + /*thermal zone end*/ + + cpu_opp_table0: cpu_opp_table0 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <730000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <730000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <730000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <750000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <770000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <780000>; + }; + opp06 { + opp-hz = /bits/ 64 <1404000000>; + opp-microvolt = <790000>; + }; + opp07 { + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <800000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <810000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <850000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <900000>; + }; + opp11 { + opp-hz = /bits/ 64 <1908000000>; + opp-microvolt = <950000>; + }; + }; + + cpufreq-meson { + compatible = "amlogic, cpufreq-meson"; + pinctrl-names = "default"; + pinctrl-0 = <&pwm_ao_d_pins3>; + status = "okay"; + }; + +}; /* end of / */ + +&meson_fb { + status = "okay"; + display_size_default = <1920 1080 1920 2160 32>; + mem_size = <0x00800000 0x1980000 0x100000 0x100000 0x800000>; + logo_addr = "0x7f800000"; + mem_alloc = <0>; + pxp_mode = <0>; /** 0:normal mode 1:pxp mode */ +}; + +&pwm_AO_cd { + status = "okay"; +}; + +&i2c0 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&i2c0_master_pins2>; + clock-frequency = <400000>; + + gt9xx@5d { + compatible = "goodix,gt9xx"; + status = "disabled"; + reg = <0x5d>; + reset-gpio = <&gpio GPIOZ_9 0x00>; + irq-gpio = <&gpio GPIOZ_3 0x00>; + }; + + ftxx@38 { + compatible = "focaltech,fts"; + status = "disabled"; + reg = <0x38>; + reset-gpio = <&gpio GPIOZ_9 0x00>; + irq-gpio = <&gpio GPIOZ_3 0x00>; + x_max = <600>; + y_max = <1024>; + max-touch-number = <10>; + }; +}; + +/*&i2c2 { + * status = "okay"; + * pinctrl-names="default"; + * pinctrl-0=<&i2c2_master_pins2>; + * clock-frequency = <300000>; + *}; + */ + +&i2c3 { + status = "ok"; + pinctrl-names="default"; + pinctrl-0=<&i2c3_master_pins2>; + clock-frequency = <100000>; /* default 100k */ + + /* for ref board */ + ad82584f_62: ad82584f_62@62 { + compatible = "ESMT, ad82584f"; + #sound-dai-cells = <0>; + reg = <0x31>; + status = "disabled"; + reset_pin = <&gpio GPIOA_5 0>; + no_mclk; + }; + + bl_extern_i2c { + compatible = "bl_extern, i2c"; + dev_name = "lp8556"; + reg = <0x2c>; + status = "disabled"; + }; +}; + +&audiobus { + tdma: tdm@0 { + compatible = "amlogic, sm1-snd-tdma"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 1>; + dai-tdm-oe-lane-slot-mask-out = <1 0>; + dai-tdm-clk-sel = <0>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_A + &clkc CLKID_MPLL0>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmout_a &tdmin_a>; + + status = "okay"; + }; + + tdmb: tdm@1 { + compatible = "amlogic, sm1-snd-tdmb"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <0 1 0 0>; + dai-tdm-lane-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <1>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_B + &clkc CLKID_MPLL1 + &clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_SPDIFOUT_A>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>; + + mclk_pad = <0>; /* 0: mclk_0; 1: mclk_1 */ + + /* + * 0: tdmout_a; + * 1: tdmout_b; + * 2: tdmout_c; + * 3: spdifout; + * 4: spdifout_b; + */ + samesource_sel = <3>; + + status = "okay"; + }; + + tdmc: tdm@2 { + compatible = "amlogic, sm1-snd-tdmc"; + #sound-dai-cells = <0>; + dai-tdm-lane-slot-mask-in = <1 0 0 0>; + #dai-tdm-lane-slot-mask-out = <1 0 1 1>; + #dai-tdm-lane-oe-slot-mask-in = <0 0 0 0>; + #dai-tdm-lane-oe-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <2>; + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmc_mclk &tdmout_c &tdmin_c>; + mclk_pad = <0>; /* 0: mclk_0; 1: mclk_1 */ + status = "okay"; + }; + + spdifa: spdif@0 { + compatible = "amlogic, sm1-snd-spdif-a"; + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 + &clkc CLKID_FCLK_DIV4 + &clkaudio CLKID_AUDIO_GATE_SPDIFIN + &clkaudio CLKID_AUDIO_GATE_SPDIFOUT_A + &clkaudio CLKID_AUDIO_SPDIFIN + &clkaudio CLKID_AUDIO_SPDIFOUT_A>; + clock-names = "sysclk", "fixed_clk", "gate_spdifin", + "gate_spdifout", "clk_spdifin", "clk_spdifout"; + interrupts = + ; + + interrupt-names = "irq_spdifin"; + pinctrl-names = "spdif_pins"; + pinctrl-0 = <&spdifout &spdifin>; + + status = "okay"; + }; + spdifb: spdif@1 { + compatible = "amlogic, sm1-snd-spdif-b"; + #sound-dai-cells = <0>; + clocks = <&clkc CLKID_MPLL0 /*CLKID_HIFI_PLL*/ + &clkaudio CLKID_AUDIO_GATE_SPDIFOUT_B + &clkaudio CLKID_AUDIO_SPDIFOUT_B>; + clock-names = "sysclk", + "gate_spdifout", "clk_spdifout"; + + status = "okay"; + }; + pdm: pdm { + compatible = "amlogic, sm1-snd-pdm"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_PDM + &clkc CLKID_FCLK_DIV3 + &clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_PDMIN0 + &clkaudio CLKID_AUDIO_PDMIN1>; + clock-names = "gate", + "sysclk_srcpll", + "dclk_srcpll", + "pdm_dclk", + "pdm_sysclk"; + + pinctrl-names = "pdm_pins"; + pinctrl-0 = <&pdmin>; + + /* mode 0~4, defalut:1 */ + filter_mode = <1>; + + status = "okay"; + }; + + earc:earc { + compatible = "amlogic, sm1-snd-earc"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_EARCRX + &clkaudio CLKID_EARCRX_CMDC + &clkaudio CLKID_EARCRX_DMAC + &clkc CLKID_FCLK_DIV5 + &clkc CLKID_FCLK_DIV3 + >; + clock-names = "rx_gate", + "rx_cmdc", + "rx_dmac", + "rx_cmdc_srcpll", + "rx_dmac_srcpll"; + + interrupts = < + GIC_SPI 88 IRQ_TYPE_EDGE_RISING + GIC_SPI 87 IRQ_TYPE_EDGE_RISING + >; + interrupt-names = "rx_cmdc", "rx_dmac"; + + status = "okay"; + }; + + asrca: resample@0 { + compatible = "amlogic, sm1-resample"; + clocks = <&clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_MCLK_F + &clkaudio CLKID_AUDIO_RESAMPLE_A>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + /*same with toddr_src + * TDMIN_A, 0 + * TDMIN_B, 1 + * TDMIN_C, 2 + * SPDIFIN, 3 + * PDMIN, 4 + * NONE, + * TDMIN_LB, 6 + * LOOPBACK, 7 + */ + resample_module = <4>; + status = "disabled"; + }; + + vad:vad { + compatible = "amlogic, snd-vad"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_TOVAD + &clkc CLKID_FCLK_DIV5 + &clkaudio CLKID_AUDIO_VAD>; + clock-names = "gate", "pll", "clk"; + + interrupts = ; + interrupt-names = "irq_wakeup", "irq_frame_sync"; + + /* + * Data src sel: + * 0: tdmin_a; + * 1: tdmin_b; + * 2: tdmin_c; + * 3: spdifin; + * 4: pdmin; + * 5: loopback_b; + * 6: tdmin_lb; + * 7: loopback_a; + */ + src = <4>; + + /* + * deal with hot word in user space or kernel space + * 0: in user space + * 1: in kernel space + */ + level = <1>; + + status = "okay"; + }; +}; /* end of audiobus */ + +&pinctrl_periphs { + tdmout_a: tdmout_a { + mux { /* GPIOX_11, GPIOX_10, GPIOX_9 */ + groups = "tdma_sclk", + "tdma_fs", + "tdma_dout0"; + function = "tdma_out"; + }; + }; + + tdmin_a: tdmin_a { + mux { /* GPIOX_8 */ + groups = "tdma_din1"; + function = "tdma_in"; + }; + }; + + tdmb_mclk: tdmb_mclk { + mux { + groups = "mclk0_a"; + function = "mclk0"; + drive-strength = <2>; + }; + }; + tdmout_b: tdmout_b { + mux { /* GPIOA_1, GPIOA_2, GPIOA_3 */ + groups = "tdmb_sclk", + "tdmb_fs", + "tdmb_dout0"; + function = "tdmb_out"; + drive-strength = <2>; + }; + }; + + tdmin_b:tdmin_b { + mux { /* GPIOA_4 */ + groups = "tdmb_din1" + /*,"tdmb_slv_sclk", "tdmb_slv_fs"*/; + function = "tdmb_in"; + drive-strength = <2>; + }; + }; + + tdmc_mclk: tdmc_mclk { + mux { /* GPIOA_11 */ + groups = "mclk1_a"; + function = "mclk1"; + }; + }; + + tdmout_c:tdmout_c { + mux { /* GPIOA_12, GPIOA_13 */ + groups = "tdmc_sclk_a", + "tdmc_fs_a" + /*, "tdmc_dout0_a" + *, "tdmc_dout2" + *, "tdmc_dout3" + */; + function = "tdmc_out"; + }; + }; + + tdmin_c:tdmin_c { + mux { /* GPIOA_10 */ + groups = "tdmc_din0_a"; + function = "tdmc_in"; + }; + }; + + spdifin: spdifin { + mux {/* GPIOH_5 */ + groups = "spdif_in_h"; + function = "spdif_in"; + }; + }; + + pdmin: pdmin { + mux { /* GPIOA_5, GPIOA_6, GPIOA_8, GPIOA_9, GPIOA_7 */ + groups = "pdm_din0_a", + "pdm_din1_a", + "pdm_din2_a", + /*"pdm_din3_a",*/ + "pdm_dclk_a"; + function = "pdm"; + }; + }; + + bl_pwm_off_pins:bl_pwm_off_pin { + mux { + pins = "GPIOH_5"; + function = "gpio_periphs"; + output-high; + }; + }; + + clk12_24_z_pins:clk12_24_z_pins { + mux { + groups = "clk12_24_z"; + function = "clk12_24_ee"; + drive-strength = <3>; + }; + }; + + gen_clk_ee_z: gen_clk_ee_z { + mux { + groups="gen_clk_ee_z"; + function="gen_clk_ee"; + drive-strength = <3>; + }; + }; + + cam_dvp_pins:cam_dvp_pins { + mux { + groups = "bt656_a_vs", "bt656_a_hs", "bt656_a_clk", + "bt656_a_din0", "bt656_a_din1", "bt656_a_din2", + "bt656_a_din3", "bt656_a_din4", "bt656_a_din5", + "bt656_a_din6", "bt656_a_din7"; + function = "bt656"; + }; + }; + + spdifout: spdifout { + mux { /* GPIOH_4 */ + groups = "spdif_out_h"; + function = "spdif_out"; + }; + }; + +}; /* end of pinctrl_periphs */ + +//&pinctrl_aobus { +// spdifout: spdifout { +// mux { /* gpiao_10 */ +// groups = "spdif_out_ao"; +// function = "spdif_out_ao"; +// }; +// }; +//}; /* end of pinctrl_aobus */ + +&audio_data { + status = "okay"; +}; + +/* Audio Related End */ + +&pwm_ef { + status = "okay"; +}; + +&dwc3 { + status = "okay"; +}; + +&usb2_phy_v2 { + status = "okay"; + portnum = <2>; +}; + +&usb3_phy_v2 { + status = "okay"; + portnum = <1>; + otg = <0>; +}; + +&dwc2_a { + status = "okay"; + /** 0: normal, 1: otg+dwc3 host only, 2: otg+dwc3 device only*/ + controller-type = <1>; +}; +ðmac { + status = "okay"; + pinctrl-names = "internal_eth_pins"; + pinctrl-0 = <&internal_eth_pins>; + mc_val = <0x4be04>; + + internal_phy=<1>; +}; + +&uart_A { + status = "okay"; +}; + +/*if you want to use vdin just modify status to "ok"*/ +&vdin0 { + memory-region = <&vdin0_cma_reserved>; + status = "okay"; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + *bit4:support yuv422 10bit full pack mode (from txl new add) + */ + tv_bit_mode = <0x15>; +}; +&vdin1 { + memory-region = <&vdin1_cma_reserved>; + status = "okay"; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + */ + tv_bit_mode = <1>; +}; + + +&sd_emmc_c { + status = "okay"; + emmc { + caps = "MMC_CAP_8_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + /* "MMC_CAP_1_8V_DDR", */ + "MMC_CAP_HW_RESET", + "MMC_CAP_ERASE", + "MMC_CAP_CMD23"; + caps2 = "MMC_CAP2_HS200"; + /* "MMC_CAP2_HS400";*/ + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&sd_emmc_b { + status = "okay"; + sd { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED"; + f_min = <400000>; + f_max = <50000000>; + }; +}; + + +&sd_emmc_a { + status = "okay"; + sdio { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + "MMC_CAP_UHS_SDR12", + "MMC_CAP_UHS_SDR25", + "MMC_CAP_UHS_SDR50", + "MMC_CAP_UHS_SDR104", + "MMC_PM_KEEP_POWER", + "MMC_CAP_SDIO_IRQ"; + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&nand { + status = "disabled"; + plat-names = "bootloader","nandnormal"; + plat-num = <2>; + plat-part-0 = <&bootloader>; + plat-part-1 = <&nandnormal>; + bootloader: bootloader{ + enable_pad ="ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <1>; + part_num = <0>; + rb_detect = <1>; + }; + nandnormal: nandnormal{ + enable_pad ="ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + plane_mode = "twoplane"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <2>; + part_num = <3>; + partition = <&nand_partitions>; + rb_detect = <1>; + }; + nand_partitions:nand_partition{ + /* + * if bl_mode is 1, tpl size was generate by + * fip_copies * fip_size which + * will not skip bad when calculating + * the partition size; + * + * if bl_mode is 0, + * tpl partition must be comment out. + */ + tpl{ + offset=<0x0 0x0>; + size=<0x0 0x0>; + }; + logo{ + offset=<0x0 0x0>; + size=<0x0 0x200000>; + }; + recovery{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + boot{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + system{ + offset=<0x0 0x0>; + size=<0x0 0x4000000>; + }; + data{ + offset=<0xffffffff 0xffffffff>; + size=<0x0 0x0>; + }; + }; +}; + +&pcie_A { + reset-gpio = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>; + status = "disable"; +}; + +&meson_cooldev { + status = "okay"; +}; + +&saradc { + status = "disabled"; +}; + +&defendkey { + status = "okay"; +}; + +&pinctrl_aobus { + dvb_s_ts0_pins: dvb_s_ts0_pins { + tsin_a { + groups = "tsin_a_sop_ao", + "tsin_a_valid_ao", + "tsin_a_clk_ao", + "tsin_a_din0_ao"; + function = "tsin_a_ao"; + }; + }; +}; diff --git a/arch/arm64/boot/dts/amlogic/tl1_t962x2_t309.dts b/arch/arm64/boot/dts/amlogic/tl1_t962x2_t309.dts new file mode 100644 index 000000000000..0c8977295e6e --- /dev/null +++ b/arch/arm64/boot/dts/amlogic/tl1_t962x2_t309.dts @@ -0,0 +1,1819 @@ +/* + * arch/arm64/boot/dts/amlogic/tl1_t962x2_t309.dts + * + * Copyright (C) 2018 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +/dts-v1/; + +#include "mesontl1.dtsi" +#include "partition_mbox_normal.dtsi" +#include "mesontl1_t309-panel.dtsi" + +/ { + model = "Amlogic TL1 T962X2 T309"; + amlogic-dt-id = "tl1_t962x2_t309"; + compatible = "amlogic, tl1_t962x2_t309"; + + aliases { + serial0 = &uart_AO; + serial1 = &uart_A; + serial2 = &uart_B; + serial3 = &uart_C; + serial4 = &uart_AO_B; + tsensor0 = &p_tsensor; + tsensor1 = &d_tsensor; + tsensor2 = &s_tsensor; + i2c0 = &i2c0; + i2c1 = &i2c1; + i2c2 = &i2c2; + i2c3 = &i2c3; + i2c4 = &i2c_AO; + }; + + memory@00000000 { + device_type = "memory"; + linux,usable-memory = <0x0 0x0 0x0 0x80000000>; + }; + + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + /* global autoconfigured region for contiguous allocations */ + ramoops@0x07400000 { + compatible = "ramoops"; + reg = <0x0 0x07400000 0x0 0x00100000>; + record-size = <0x8000>; + console-size = <0x8000>; + ftrace-size = <0x20000>; + }; + + secmon_reserved: linux,secmon { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x400000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x05000000 0x0 0x400000>; + }; + + logo_reserved:linux,meson-fb { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x800000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x7f800000 0x0 0x800000>; + }; + + lcd_tcon_reserved:linux,lcd_tcon { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0xc00000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x7ec00000 0x0 0xc00000>; + }; + + codec_mm_cma:linux,codec_mm_cma { + compatible = "shared-dma-pool"; + reusable; + /* ion_codec_mm max can alloc size 80M*/ + size = <0x0 0x13400000>; + alignment = <0x0 0x400000>; + linux,contiguous-region; + }; + + /* codec shared reserved */ + codec_mm_reserved:linux,codec_mm_reserved { + compatible = "amlogic, codec-mm-reserved"; + size = <0x0 0x0>; + alignment = <0x0 0x100000>; + //no-map; + }; + + ion_cma_reserved:linux,ion-dev { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x2000000>; + alignment = <0x0 0x400000>; + }; + + /* vdin0 CMA pool */ + //vdin0_cma_reserved:linux,vdin0_cma { + // compatible = "shared-dma-pool"; + // reusable; + /* 3840x2160x4x4 ~=128 M */ + // size = <0x0 0xc400000>; + // alignment = <0x0 0x400000>; + //}; + + /* vdin1 CMA pool */ + vdin1_cma_reserved:linux,vdin1_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16 M */ + size = <0x0 0x1400000>; + alignment = <0x0 0x400000>; + }; + + /*demod_reserved:linux,demod { + * compatible = "amlogic, demod-mem"; + * size = <0x0 0x800000>; //8M //100m 0x6400000 + * alloc-ranges = <0x0 0x0 0x0 0x30000000>; + * //multi-use; + * //no-map; + *}; + */ + + demod_cma_reserved:linux,demod_cma { + compatible = "shared-dma-pool"; + reusable; + /* 8M */ + size = <0x0 0x0800000>; + alignment = <0x0 0x400000>; + }; + + /*di CMA pool */ + di_cma_reserved:linux,di_cma { + compatible = "shared-dma-pool"; + reusable; + /* buffer_size = 3621952(yuv422 8bit) + * | 4736064(yuv422 10bit) + * | 4074560(yuv422 10bit full pack mode) + * 10x3621952=34.6M(0x23) support 8bit + * 10x4736064=45.2M(0x2e) support 12bit + * 10x4074560=40M(0x28) support 10bit + */ + size = <0x0 0x02800000>; + alignment = <0x0 0x400000>; + }; + + /* for hdmi rx emp use */ + hdmirx_emp_cma_reserved:linux,emp_cma { + compatible = "shared-dma-pool"; + /*linux,phandle = <5>;*/ + reusable; + /* 4M for emp to ddr */ + /* 32M for tmds to ddr */ + size = <0x0 0x2000000>; + alignment = <0x0 0x400000>; + }; + + /* POST PROCESS MANAGER */ + ppmgr_reserved:linux,ppmgr { + compatible = "amlogic, ppmgr_memory"; + size = <0x0 0x0>; + }; + + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x0>; + alignment = <0x0 0x0>; + linux,contiguous-region; + }; + }; /* end of reserved-memory */ + + codec_mm { + compatible = "amlogic, codec, mm"; + status = "okay"; + memory-region = <&codec_mm_cma &codec_mm_reserved>; + }; + + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + + ppmgr { + compatible = "amlogic, ppmgr"; + memory-region = <&ppmgr_reserved>; + status = "okay"; + }; + + deinterlace { + compatible = "amlogic, deinterlace"; + status = "okay"; + /* 0:use reserved; 1:use cma; 2:use cma as reserved */ + flag_cma = <1>; + //memory-region = <&di_reserved>; + memory-region = <&di_cma_reserved>; + interrupts = <0 46 1 + 0 40 1>; + interrupt-names = "pre_irq", "post_irq"; + clocks = <&clkc CLKID_VPU_CLKB_TMP_COMP>, + <&clkc CLKID_VPU_CLKB_COMP>; + clock-names = "vpu_clkb_tmp_composite", + "vpu_clkb_composite"; + clock-range = <334 667>; + /* buffer-size = <3621952>;(yuv422 8bit) */ + buffer-size = <4074560>;/*yuv422 fullpack*/ + /* reserve-iomap = "true"; */ + /* if enable nr10bit, set nr10bit-support to 1 */ + post-wr-support = <1>; + nr10bit-support = <1>; + nrds-enable = <1>; + pps-enable = <1>; + }; + + vout { + compatible = "amlogic, vout"; + status = "okay"; + fr_auto_policy = <0>; + }; + + /* Audio Related start */ + pdm_codec:dummy { + #sound-dai-cells = <0>; + compatible = "amlogic, pdm_dummy_codec"; + status = "okay"; + }; + + dummy_codec:dummy { + #sound-dai-cells = <0>; + compatible = "amlogic, aml_dummy_codec"; + status = "okay"; + }; + + tl1_codec:codec { + #sound-dai-cells = <0>; + compatible = "amlogic, tl1_acodec"; + status = "okay"; + reg = <0x0 0xff632000 0x0 0x1c>; + tdmout_index = <0>; + tdmin_index = <0>; + dat1_ch_sel = <1>; + }; + + aml_dtv_demod { + compatible = "amlogic, ddemod-tl1"; + dev_name = "aml_dtv_demod"; + status = "okay"; + + pinctrl-names="dtvdemod_agc_pins"; + pinctrl-0=<&dtvdemod_agc_pins>; + + clocks = <&clkc CLKID_DAC_CLK>; + clock-names = "vdac_clk_gate"; + + reg = <0x0 0xff650000 0x0 0x4000 /*dtv demod base*/ + 0x0 0xff63c000 0x0 0x2000 /*hiu reg base*/ + 0x0 0xff800000 0x0 0x1000 /*io_aobus_base*/ + 0x0 0xffd01000 0x0 0x1000 /*reset*/ + >; + + dtv_demod0_mem = <0>; // need move to aml_dtv_demod ? + spectrum = <1>; + cma_flag = <1>; + cma_mem_size = <8>; + memory-region = <&demod_cma_reserved>;//<&demod_reserved>; + }; + + auge_sound { + compatible = "amlogic, tl1-sound-card"; + aml-audio-card,name = "AML-AUGESOUND"; + + avout_mute-gpios = <&gpio GPIODV_3 GPIO_ACTIVE_HIGH>; + + aml-audio-card,dai-link@0 { + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdma>; + frame-master = <&tdma>; + /* slave mode */ + /* + * bitclock-master = <&tdmacodec>; + * frame-master = <&tdmacodec>; + */ + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-i2s"; + tdmacpu: cpu { + sound-dai = <&tdma>; + dai-tdm-slot-tx-mask = + <1 1>; + dai-tdm-slot-rx-mask = + <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmacodec: codec { + //sound-dai = <&dummy_codec>; + prefix-names = "AMP"; + sound-dai = <&ad82584f &tl1_codec>; + }; + }; + + aml-audio-card,dai-link@1 { + status = "disabled"; + + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdmb>; + frame-master = <&tdmb>; + /* slave mode */ + //bitclock-master = <&tdmbcodec>; + //frame-master = <&tdmbcodec>; + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-pcm"; + cpu { + sound-dai = <&tdmb>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + /* + * dai-tdm-slot-tx-mask = + * <1 1 1 1 1 1 1 1>; + * dai-tdm-slot-rx-mask = + * <1 1 1 1 1 1 1 1>; + * dai-tdm-slot-num = <8>; + */ + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmbcodec: codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@2 { + status = "disabled"; + + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdmc>; + frame-master = <&tdmc>; + /* slave mode */ + //bitclock-master = <&tdmccodec>; + //frame-master = <&tdmccodec>; + /* suffix-name, sync with android audio hal used for */ + //suffix-name = "alsaPORT-tdm"; + cpu { + sound-dai = <&tdmc>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmccodec: codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@3 { + mclk-fs = <64>; + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-pdm"; + cpu { + sound-dai = <&pdm>; + }; + codec { + sound-dai = <&pdm_codec>; + }; + }; + + aml-audio-card,dai-link@4 { + mclk-fs = <128>; + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-spdif"; + cpu { + sound-dai = <&spdifa>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@5 { + mclk-fs = <128>; + cpu { + sound-dai = <&spdifb>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@6 { + mclk-fs = <256>; + suffix-name = "alsaPORT-tv"; + cpu { + sound-dai = <&extn>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + + }; + /* Audio Related end */ + + dvb { + compatible = "amlogic, dvb"; + status = "okay"; + fe0_mode = "internal"; + fe0_tuner = <&tuner>; + + /*"parallel","serial","disable"*/ + ts2 = "parallel"; + ts2_control = <0>; + ts2_invert = <0>; + interrupts = <0 23 1 + 0 5 1 + 0 53 1 + 0 19 1 + 0 25 1 + 0 17 1>; + interrupt-names = "demux0_irq", + "demux1_irq", + "demux2_irq", + "dvr0_irq", + "dvr1_irq", + "dvr2_irq"; + clocks = <&clkc CLKID_DEMUX + &clkc CLKID_ASYNC_FIFO + &clkc CLKID_AHB_ARB0 +/* &clkc CLKID_DOS_PARSER>;*/ + &clkc CLKID_U_PARSER>; + clock-names = "demux", "asyncfifo", "ahbarb0", "uparsertop"; + }; + + tvafe_avin_detect { + compatible = "amlogic, tl1_tvafe_avin_detect"; + status = "okay"; + device_mask = <1>;/*bit0:ch1;bit1:ch2*/ + interrupts = <0 12 1>, + <0 13 1>; + }; + + amlvecm { + compatible = "amlogic, vecm"; + dev_name = "aml_vecm"; + status = "okay"; + gamma_en = <1>;/*1:enabel ;0:disable*/ + wb_en = <1>;/*1:enabel ;0:disable*/ + cm_en = <1>;/*1:enabel ;0:disable*/ + wb_sel = <1>;/*1:mtx ;0:gainoff*/ + vlock_en = <1>;/*1:enable;0:disable*/ + vlock_mode = <0x4>; + /* vlock work mode: + *bit0:auto ENC + *bit1:auto PLL + *bit2:manual PLL + *bit3:manual ENC + *bit4:manual soft ENC + *bit5:manual MIX PLL ENC + */ + vlock_pll_m_limit = <1>; + vlock_line_limit = <3>; + }; + + vdin@0 { + compatible = "amlogic, vdin"; + /*memory-region = <&vdin0_cma_reserved>;*/ + status = "okay"; + /*bit0:(1:share with codec_mm;0:cma alone) + *bit8:(1:alloc in discontinus way;0:alone in continuous way) + */ + flag_cma = <0x101>; + /*MByte, if 10bit disable: 64M(YUV422), + *if 10bit enable: 64*1.5 = 96M(YUV422) + *if support 4K2K-YUV444-10bit-WR:3840*2160*4*4 ~= 128M + *if support 4K2K-YUV422-10bit-wr:3840*2160*3*4 ~= 96M + *if support 4K2K-YUV422-8BIT-WR:3840*2160*2*4 ~= 64M + *if support 1080p-YUV422-8BIT-WR:1920*1080*2*4 ~= 16M + */ + cma_size = <160>; + interrupts = <0 83 1>; + rdma-irq = <2>; + clocks = <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_VDIN_MEAS_COMP>; + clock-names = "fclk_div5", "cts_vdin_meas_clk"; + vdin_id = <0>; + /*vdin write mem color depth support: + * bit0:support 8bit + * bit1:support 9bit + * bit2:support 10bit + * bit3:support 12bit + * bit4:support yuv422 10bit full pack mode (from txl new add) + * bit8:use 8bit at 4k_50/60hz_10bit + * bit9:use 10bit at 4k_50/60hz_10bit + */ + tv_bit_mode = <0x215>; + /* afbce_bit_mode: (amlogic frame buff compression encoder) + * bit 0~3: + * 0 -- normal mode, not use afbce + * 1 -- use afbce non-mmu mode + * 2 -- use afbce mmu mode + * bit 4: + * 0 -- afbce compression-lossy disable + * 1 -- afbce compression-lossy enable + */ + afbce_bit_mode = <0>; + }; + + vdin@1 { + compatible = "amlogic, vdin"; + memory-region = <&vdin1_cma_reserved>; + status = "okay"; + /*bit0:(1:share with codec_mm;0:cma alone) + *bit8:(1:alloc in discontinus way;0:alone in continuous way) + */ + flag_cma = <0>; + interrupts = <0 85 1>; + rdma-irq = <4>; + clocks = <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_VDIN_MEAS_COMP>; + clock-names = "fclk_div5", "cts_vdin_meas_clk"; + vdin_id = <1>; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + */ + tv_bit_mode = <0x15>; + }; + + tvafe { + compatible = "amlogic, tvafe-tl1"; + /*memory-region = <&tvafe_cma_reserved>;*/ + status = "okay"; + flag_cma = <1>;/*1:share with codec_mm;0:cma alone*/ + cma_size = <5>;/*MByte*/ + reg = <0x0 0xff654000 0x0 0x2000>;/*tvafe reg base*/ + reserve-iomap = "true"; + tvafe_id = <0>; + //pinctrl-names = "default"; + /*!!particular sequence, no more and no less!!!*/ + tvafe_pin_mux = < + 3 /* TVAFE_CVBS_IN2, CVBS_IN0 = 0 */ + 1 /* TVAFE_CVBS_IN0, CVBS_IN1 */ + 2 /* TVAFE_CVBS_IN1, CVBS_IN2 */ + 4 /* TVAFE_CVBS_IN3, CVBS_IN3 */ + >; + clocks = <&clkc CLKID_DAC_CLK>; + clock-names = "vdac_clk_gate"; + }; + + vbi { + compatible = "amlogic, vbi"; + status = "okay"; + interrupts = <0 83 1>; + }; + + cvbsout { + compatible = "amlogic, cvbsout-tl1"; + status = "disabled"; + clocks = <&clkc CLKID_VCLK2_ENCI + &clkc CLKID_VCLK2_VENCI0 + &clkc CLKID_VCLK2_VENCI1 + &clkc CLKID_DAC_CLK>; + clock-names = "venci_top_gate", + "venci_0_gate", + "venci_1_gate", + "vdac_clk_gate"; + /* clk path */ + /* 0:vid_pll vid2_clk */ + /* 1:gp0_pll vid2_clk */ + /* 2:vid_pll vid1_clk */ + /* 3:gp0_pll vid1_clk */ + clk_path = <0>; + + /* performance: reg_address, reg_value */ + /* tl1 */ + performance = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x8080 + 0x1b05 0xfd + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + performance_sarft = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x0 + 0x1b05 0x9 + 0x1c59 0xfc48 + 0xffff 0x0>; /* ending flag */ + performance_revB_telecom = <0x1bf0 0x9 + 0x1b56 0x546 + 0x1b12 0x8080 + 0x1b05 0x9 + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + }; + + /* for external keypad */ + adc_keypad { + compatible = "amlogic, adc_keypad"; + status = "okay"; + key_name = "power","up","down","enter","left","right","home"; + key_num = <7>; + io-channels = <&saradc SARADC_CH2>,<&saradc SARADC_CH3>; + io-channel-names = "key-chan-2", "key-chan-3"; + key_chan = ; + key_code = <116 103 108 28 105 106 102>; + key_val = <0 143 266 389 512 143 266>; //val=voltage/1800mV*1023 + key_tolerance = <40 40 40 40 40 40 40>; +}; + + unifykey { + compatible = "amlogic, unifykey"; + status = "okay"; + + unifykey-num = <21>; + unifykey-index-0 = <&keysn_0>; + unifykey-index-1 = <&keysn_1>; + unifykey-index-2 = <&keysn_2>; + unifykey-index-3 = <&keysn_3>; + unifykey-index-4 = <&keysn_4>; + unifykey-index-5 = <&keysn_5>; + unifykey-index-6 = <&keysn_6>; + unifykey-index-7 = <&keysn_7>; + unifykey-index-8 = <&keysn_8>; + unifykey-index-9 = <&keysn_9>; + unifykey-index-10= <&keysn_10>; + unifykey-index-11 = <&keysn_11>; + unifykey-index-12 = <&keysn_12>; + unifykey-index-13 = <&keysn_13>; + unifykey-index-14 = <&keysn_14>; + unifykey-index-15 = <&keysn_15>; + unifykey-index-16 = <&keysn_16>; + unifykey-index-17 = <&keysn_17>; + unifykey-index-18 = <&keysn_18>; + unifykey-index-19 = <&keysn_19>; + unifykey-index-20 = <&keysn_20>; + + keysn_0: key_0{ + key-name = "usid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_1:key_1{ + key-name = "mac"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_2:key_2{ + key-name = "hdcp"; + key-device = "secure"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_3:key_3{ + key-name = "secure_boot_set"; + key-device = "efuse"; + key-permit = "write"; + }; + keysn_4:key_4{ + key-name = "mac_bt"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_5:key_5{ + key-name = "mac_wifi"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_6:key_6{ + key-name = "hdcp2_tx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_7:key_7{ + key-name = "hdcp2_rx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_8:key_8{ + key-name = "widevinekeybox"; + key-device = "secure"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_9:key_9{ + key-name = "deviceid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_10:key_10{ + key-name = "hdcp22_fw_private"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_11:key_11{ + key-name = "hdcp22_rx_private"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_12:key_12{ + key-name = "hdcp22_rx_fw"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_13:key_13{ + key-name = "hdcp14_rx"; + key-device = "normal"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_14:key_14{ + key-name = "prpubkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_15:key_15{ + key-name = "prprivkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_16:key_16{ + key-name = "lcd"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_17:key_17{ + key-name = "lcd_extern"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_18:key_18{ + key-name = "backlight"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_19:key_19{ + key-name = "lcd_tcon"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_20:key_20{ + key-name = "attestationkeybox";// attestation key + key-device = "secure"; + key-permit = "read","write","del"; + }; + }; /* End unifykey */ + + hdmirx { + compatible = "amlogic, hdmirx_tl1"; + #address-cells=<1>; + #size-cells=<1>; + memory-region = <&hdmirx_emp_cma_reserved>; + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&hdmirx_a_mux &hdmirx_b_mux + &hdmirx_c_mux>; + repeat = <0>; + interrupts = <0 41 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clkc CLKID_HDMIRX_MODET_COMP>, + <&clkc CLKID_HDMIRX_CFG_COMP>, + <&clkc CLKID_HDMIRX_ACR_COMP>, + <&clkc CLKID_HDMIRX_METER_COMP>, + <&clkc CLKID_HDMIRX_AXI_COMP>, + <&xtal>, + <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_FCLK_DIV7>, + <&clkc CLKID_HDCP22_SKP_COMP>, + <&clkc CLKID_HDCP22_ESM_COMP>; + // <&clkc CLK_AUD_PLL2FS>, + // <&clkc CLK_AUD_PLL4FS>, + // <&clkc CLK_AUD_OUT>; + clock-names = "hdmirx_modet_clk", + "hdmirx_cfg_clk", + "hdmirx_acr_ref_clk", + "cts_hdmirx_meter_clk", + "cts_hdmi_axi_clk", + "xtal", + "fclk_div5", + "fclk_div7", + "hdcp_rx22_skp", + "hdcp_rx22_esm"; + // "hdmirx_aud_pll2fs", + // "hdmirx_aud_pll4f", + // "clk_aud_out"; + hdmirx_id = <0>; + en_4k_2_2k = <0>; + hpd_low_cec_off = <1>; + /* bit4: enable feature, bit3~0: port number */ + disable_port = <0x0>; + /* MAP_ADDR_MODULE_CBUS */ + /* MAP_ADDR_MODULE_HIU */ + /* MAP_ADDR_MODULE_HDMIRX_CAPB3 */ + /* MAP_ADDR_MODULE_SEC_AHB */ + /* MAP_ADDR_MODULE_SEC_AHB2 */ + /* MAP_ADDR_MODULE_APB4 */ + /* MAP_ADDR_MODULE_TOP */ + reg = < 0x0 0x0 0x0 0x0 + 0x0 0xff63C000 0x0 0x2000 + 0x0 0xffe0d000 0x0 0x2000 + 0x0 0x0 0x0 0x0 + 0x0 0x0 0x0 0x0 + 0x0 0x0 0x0 0x0 + 0x0 0xff610000 0x0 0xa000>; + }; + + aocec: aocec { + compatible = "amlogic, aocec-tl1"; + /*device_name = "aocec";*/ + status = "okay"; + vendor_name = "Amlogic"; /* Max Chars: 8 */ + /* Refer to the following URL at: + * http://standards.ieee.org/develop/regauth/oui/oui.txt + */ + vendor_id = <0x000000>; + product_desc = "TL1"; /* Max Chars: 16 */ + cec_osd_string = "AML_TV"; /* Max Chars: 14 */ + port_num = <3>; + ee_cec; + arc_port_mask = <0x2>; + interrupts = <0 205 1 + 0 199 1>; + interrupt-names = "hdmi_aocecb","hdmi_aocec"; + pinctrl-names = "default","hdmitx_aocecb","cec_pin_sleep"; + pinctrl-0=<&aoceca_mux>; + pinctrl-1=<&aocecb_mux>; + pinctrl-2=<&aoceca_mux>; + reg = <0x0 0xFF80023c 0x0 0x4 + 0x0 0xFF800000 0x0 0x400>; + reg-names = "ao_exit","ao"; + }; + + p_tsensor: p_tsensor@ff634800 { + compatible = "amlogic, r1p1-tsensor"; + status = "okay"; + reg = <0x0 0xff634800 0x0 0x50>, + <0x0 0xff800268 0x0 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 35 0>; + clocks = <&clkc CLKID_TS_CLK_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + d_tsensor: d_tsensor@ff634c00 { + compatible = "amlogic, r1p1-tsensor"; + status = "okay"; + reg = <0x0 0xff634c00 0x0 0x50>, + <0x0 0xff800230 0x0 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 36 0>; + clocks = <&clkc CLKID_TS_CLK_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + s_tsensor: s_tsensor@ff635000 { + compatible = "amlogic, r1p1-tsensor"; + status = "okay"; + reg = <0x0 0xff635000 0x0 0x50>, + <0x0 0xff80026c 0x0 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 38 0>; + clocks = <&clkc CLKID_TS_CLK_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + meson_cooldev: meson-cooldev@0 { + status = "okay"; + compatible = "amlogic, meson-cooldev"; + cooling_devices { + cpufreq_cool_cluster0 { + min_state = <1000000>; + dyn_coeff = <140>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "cpufreq_cool0"; + device_type = "cpufreq"; + }; + cpucore_cool_cluster0 { + min_state = <1>; + dyn_coeff = <0>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "cpucore_cool0"; + device_type = "cpucore"; + }; + gpufreq_cool { + min_state = <400>; + dyn_coeff = <140>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "gpufreq_cool0"; + device_type = "gpufreq"; + }; + gpucore_cool { + min_state = <1>; + dyn_coeff = <0>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "gpucore_cool0"; + device_type = "gpucore"; + }; + }; + cpufreq_cool0:cpufreq_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + cpucore_cool0:cpucore_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + gpufreq_cool0:gpufreq_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + gpucore_cool0:gpucore_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + };/*meson cooling devices end*/ + + thermal-zones { + pll_thermal: pll_thermal { + polling-delay = <1000>; + polling-delay-passive = <100>; + sustainable-power = <1322>; + thermal-sensors = <&p_tsensor 0>; + trips { + pswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + pcontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + phot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + pcritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + cooling-maps { + cpufreq_cooling_map { + trip = <&pcontrol>; + cooling-device = <&cpufreq_cool0 0 11>; + contribution = <1024>; + }; + cpucore_cooling_map { + trip = <&pcontrol>; + cooling-device = <&cpucore_cool0 0 4>; + contribution = <1024>; + }; + gpufreq_cooling_map { + trip = <&pcontrol>; + cooling-device = <&gpufreq_cool0 0 4>; + contribution = <1024>; + }; + }; + }; + ddr_thermal: ddr_thermal { + polling-delay = <2000>; + polling-delay-passive = <1000>; + sustainable-power = <1322>; + thermal-sensors = <&d_tsensor 1>; + trips { + dswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + dcontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + dhot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + dcritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + }; + sar_thermal: sar_thermal { + polling-delay = <2000>; + polling-delay-passive = <1000>; + sustainable-power = <1322>; + thermal-sensors = <&s_tsensor 2>; + trips { + sswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + scontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + shot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + scritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + }; + }; /*thermal zone end*/ + + /*DCDC for MP8756GD*/ + cpu_opp_table0: cpu_opp_table0 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <729000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <729000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <729000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <749000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <769000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <779000>; + }; + opp06 { + opp-hz = /bits/ 64 <1404000000>; + opp-microvolt = <789000>; + }; + opp07 { + opp-hz = /bits/ 64 <1500000000>; + opp-microvolt = <799000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <809000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <849000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <899000>; + }; + opp11 { + opp-hz = /bits/ 64 <1908000000>; + opp-microvolt = <949000>; + }; + }; + + cpufreq-meson { + compatible = "amlogic, cpufreq-meson"; + pinctrl-names = "default"; + pinctrl-0 = <&pwm_ao_d_pins3>; + status = "okay"; + }; + + tuner: tuner { + compatible = "amlogic, tuner"; + status = "okay"; + tuner_cur = <0>; /* default use tuner */ + tuner_num = <1>; /* tuner number, multi tuner support */ + tuner_name_0 = "r842_tuner"; + tuner_i2c_adap_0 = <&i2c0>; + tuner_i2c_addr_0 = <0xf6>; + tuner_xtal_0 = <1>; /* 0: 16MHz, 1: 24MHz */ + tuner_xtal_mode_0 = <0>; + /* NO_SHARE_XTAL(0) + * MASTER_TO_SLAVE_XTAL_IN(1) + * MASTER_TO_SLAVE_XTAL_OUT(2) + * SLAVE_XTAL_OUT(3) + */ + tuner_xtal_cap_0 = <38>; /* when tuner_xtal_mode = 3, set 25 */ + }; + + atv-demod { + compatible = "amlogic, atv-demod"; + status = "okay"; + tuner = <&tuner>; + btsc_sap_mode = <1>; + pinctrl-names="atvdemod_agc_pins"; + pinctrl-0=<&atvdemod_agc_pins>; + reg = <0x0 0xff656000 0x0 0x2000 /* demod reg */ + 0x0 0xff63c000 0x0 0x2000 /* hiu reg */ + 0x0 0xff634000 0x0 0x2000 /* periphs reg */ + 0x0 0xff64a000 0x0 0x2000>; /* audio reg */ + reg_23cf = <0x88188832>; + /*default:0x88188832;r840 on haier:0x48188832*/ + }; + + bt-dev{ + compatible = "amlogic, bt-dev"; + status = "okay"; + gpio_reset = <&gpio GPIOC_13 GPIO_ACTIVE_HIGH>; + }; + + wifi{ + compatible = "amlogic, aml_wifi"; + status = "okay"; + interrupt_pin = <&gpio GPIOC_12 GPIO_ACTIVE_HIGH>; + irq_trigger_type = "GPIO_IRQ_LOW"; + dhd_static_buf; //dhd_static_buf support + power_on_pin = <&gpio GPIOC_11 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&pwm_b_pins1>; + pwm_config = <&wifi_pwm_conf>; + }; + + wifi_pwm_conf:wifi_pwm_conf{ + pwm_channel1_conf { + pwms = <&pwm_ab MESON_PWM_1 30541 0>; + duty-cycle = <15270>; + times = <8>; + }; + pwm_channel2_conf { + pwms = <&pwm_ab MESON_PWM_3 30500 0>; + duty-cycle = <15250>; + times = <12>; + }; + }; + + sd_emmc_b: sdio@ffe05000 { + status = "okay"; + compatible = "amlogic, meson-mmc-tl1"; + reg = <0x0 0xffe05000 0x0 0x800>; + interrupts = <0 190 4>; + + pinctrl-names = "sdio_all_pins", + "sdio_clk_cmd_pins"; + pinctrl-0 = <&sdio_all_pins>; + pinctrl-1 = <&sdio_clk_cmd_pins>; + + clocks = <&clkc CLKID_SD_EMMC_B>, + <&clkc CLKID_SD_EMMC_B_P0_COMP>, + <&clkc CLKID_FCLK_DIV2>, + <&clkc CLKID_FCLK_DIV5>, + <&xtal>; + clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + + bus-width = <4>; + cap-sd-highspeed; + cap-mmc-highspeed; + max-frequency = <100000000>; + disable-wp; + sdio { + pinname = "sdio"; + ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", /**ptm debug */ + "MMC_CAP_UHS_SDR12", + "MMC_CAP_UHS_SDR25", + "MMC_CAP_UHS_SDR50", + "MMC_CAP_UHS_SDR104", + "MMC_PM_KEEP_POWER", + "MMC_CAP_SDIO_IRQ"; + f_min = <400000>; + f_max = <200000000>; + max_req_size = <0x20000>; /**128KB*/ + card_type = <3>; + /* 3:sdio device(ie:sdio-wifi), + * 4:SD combo (IO+mem) card + */ + }; + }; +}; /* end of / */ + +&i2c0 { + status = "okay"; + clock-frequency = <300000>; + pinctrl-names="default"; + pinctrl-0=<&i2c0_dv_pins>; +}; + +&audiobus { + tdma:tdm@0 { + compatible = "amlogic, tl1-snd-tdma"; + #sound-dai-cells = <0>; + + dai-tdm-lane-slot-mask-in = <1 0>; + dai-tdm-lane-slot-mask-out = <1 1 1 1>; + dai-tdm-clk-sel = <0>; + + clocks = <&clkaudio CLKID_AUDIO_MCLK_A + &clkc CLKID_MPLL0 + &clkc CLKID_MPLL1 + &clkaudio CLKID_AUDIO_SPDIFOUT_A>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; + + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdma_mclk &tdmout_a>; + + /* + * 0: tdmout_a; + * 1: tdmout_b; + * 2: tdmout_c; + * 3: spdifout; + * 4: spdifout_b; + */ + samesource_sel = <3>; + + /* In for ACODEC_ADC */ + acodec_adc = <1>; + + status = "okay"; + + /* !!!For --TV platform-- ONLY */ + Channel_Mask { + /*i2s has 4 pins, 8channel, mux output*/ + Spdif_samesource_Channel_Mask = "i2s_2/3"; + }; + }; + + tdmb:tdm@1 { + compatible = "amlogic, tl1-snd-tdmb"; + #sound-dai-cells = <0>; + + dai-tdm-lane-slot-mask-in = <1 0 0 0>; + dai-tdm-lane-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <1>; + + clocks = <&clkaudio CLKID_AUDIO_MCLK_B + &clkc CLKID_MPLL1>; + clock-names = "mclk", "clk_srcpll"; + + status = "okay"; + }; + + tdmc:tdm@2 { + compatible = "amlogic, tl1-snd-tdmc"; + #sound-dai-cells = <0>; + + dai-tdm-lane-slot-mask-in = <1 0 0 0>; + dai-tdm-lane-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <2>; + + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmout_c &tdmin_c>; + + status = "okay"; + }; + + spdifa:spdif@0 { + compatible = "amlogic, tl1-snd-spdif-a"; + #sound-dai-cells = <0>; + + clocks = <&clkc CLKID_MPLL1 + &clkc CLKID_FCLK_DIV4 + &clkaudio CLKID_AUDIO_GATE_SPDIFIN + &clkaudio CLKID_AUDIO_GATE_SPDIFOUT_A + &clkaudio CLKID_AUDIO_SPDIFIN + &clkaudio CLKID_AUDIO_SPDIFOUT_A>; + clock-names = "sysclk", "fixed_clk", "gate_spdifin", + "gate_spdifout", "clk_spdifin", "clk_spdifout"; + + interrupts = + ; + interrupt-names = "irq_spdifin"; + + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; + pinctrl-0 = <&spdifout_a>; + pinctrl-1 = <&spdifout_a_mute>; + + /* + * whether do asrc for pcm and resample a or b + * if raw data, asrc is disabled automatically + * 0: "Disable", + * 1: "Enable:32K", + * 2: "Enable:44K", + * 3: "Enable:48K", + * 4: "Enable:88K", + * 5: "Enable:96K", + * 6: "Enable:176K", + * 7: "Enable:192K", + */ + asrc_id = <0>; + auto_asrc = <3>; + + status = "okay"; + }; + + spdifb:spdif@1 { + compatible = "amlogic, tl1-snd-spdif-b"; + #sound-dai-cells = <0>; + + clocks = <&clkc CLKID_MPLL0 /*CLKID_HIFI_PLL*/ + &clkaudio CLKID_AUDIO_GATE_SPDIFOUT_B + &clkaudio CLKID_AUDIO_SPDIFOUT_B>; + clock-names = "sysclk", + "gate_spdifout", "clk_spdifout"; + + status = "okay"; + }; + + pdm:pdm { + compatible = "amlogic, tl1-snd-pdm"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_PDM + &clkc CLKID_FCLK_DIV3 + &clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_PDMIN0 + &clkaudio CLKID_AUDIO_PDMIN1>; + clock-names = "gate", + "sysclk_srcpll", + "dclk_srcpll", + "pdm_dclk", + "pdm_sysclk"; + + pinctrl-names = "pdm_pins"; + pinctrl-0 = <&pdmin>; + + /* mode 0~4, defalut:1 */ + filter_mode = <1>; + + status = "okay"; + }; + + extn:extn { + compatible = "amlogic, snd-extn"; + #sound-dai-cells = <0>; + + interrupts = + ; + interrupt-names = "irq_frhdmirx"; + + status = "okay"; + }; + + aed:effect { + compatible = "amlogic, snd-effect-v2"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_EQDRC + &clkc CLKID_FCLK_DIV5 + &clkaudio CLKID_AUDIO_EQDRC>; + clock-names = "gate", "srcpll", "eqdrc"; + + /* + * 0:tdmout_a + * 1:tdmout_b + * 2:tdmout_c + * 3:spdifout + * 4:spdifout_b + */ + eqdrc_module = <0>; + /* max 0xf, each bit for one lane, usually one lane */ + lane_mask = <0x1>; + /* max 0xff, each bit for one channel */ + channel_mask = <0xff>; + + status = "okay"; + }; + + asrca: resample@0 { + compatible = "amlogic, tl1-resample-a"; + clocks = <&clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_MCLK_A + &clkaudio CLKID_AUDIO_RESAMPLE_A>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + /*same with toddr_src + * TDMIN_A, 0 + * TDMIN_B, 1 + * TDMIN_C, 2 + * SPDIFIN, 3 + * PDMIN, 4 + * NONE, + * TDMIN_LB, 6 + * LOOPBACK, 7 + * FRHDMIRX, 8 + */ + resample_module = <8>; + + status = "okay"; + }; + + asrcb: resample@1 { + compatible = "amlogic, tl1-resample-b"; + + clocks = <&clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_MCLK_F + &clkaudio CLKID_AUDIO_RESAMPLE_B>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + + /*same with toddr_src + * TDMIN_A, 0 + * TDMIN_B, 1 + * TDMIN_C, 2 + * SPDIFIN, 3 + * PDMIN, 4 + * NONE, + * TDMIN_LB, 6 + * LOOPBACK, 7 + */ + resample_module = <3>; + + status = "disabled"; + }; + +}; /* end of audiobus */ + +&pinctrl_periphs { + /* audio pin mux */ + + tdma_mclk: tdma_mclk { + mux { /* GPIOZ_0 */ + groups = "mclk0_z"; + function = "mclk0"; + }; + }; + + tdmout_a: tdmout_a { + mux { /* GPIOZ_1, GPIOZ_2, GPIOZ_3 */ + groups = "tdma_sclk_z", + "tdma_fs_z", + "tdma_dout0_z"; + function = "tdma_out"; + bias-pull-down; + }; + }; + + tdmin_a: tdmin_a { + mux { /* GPIOZ_9 */ + groups = "tdma_din2_z"; + function = "tdma_in"; + }; + }; + + tdmout_c: tdmout_c { + mux { /* GPIODV_7, GPIODV_8, GPIODV_9 */ + groups = "tdmc_sclk", + "tdmc_fs", + "tdmc_dout0"; + function = "tdmc_out"; + }; + }; + + tdmin_c: tdmin_c { + mux { /* GPIODV_10 */ + groups = "tdmc_din1"; + function = "tdmc_in"; + }; + }; + + spdifin_a: spdifin_a { + mux { /* GPIODV_5 */ + groups = "spdif_in"; + function = "spdif_in"; + }; + }; + + spdifout_a: spdifout_a { + mux { /* GPIODV_4 */ + groups = "spdif_out_dv4"; + function = "spdif_out"; + }; + }; + + spdifout_a_mute: spdifout_a_mute { + mux { /* GPIODV_4 */ + groups = "GPIODV_4"; + function = "gpio_periphs"; + }; + }; + + pdmin: pdmin { + mux { /* GPIOZ_7, GPIOZ_8, pdm_din2_z4 */ + groups = "pdm_dclk_z", + "pdm_din0_z", + "pdm_din2_z4"; + function = "pdm"; + }; + }; + + /*backlight*/ + bl_pwm_vs_on_pins:bl_pwm_vs_on_pin { + mux { + groups = "pwm_vs_z5"; + function = "pwm_vs"; + }; + }; + bl_pwm_off_pins:bl_pwm_off_pin { + mux { + groups = "GPIOZ_5"; + function = "gpio_periphs"; + output-low; + }; + }; + bl_pwm_combo_0_vs_on_pins:bl_pwm_combo_0_vs_on_pin { + mux { + groups = "pwm_vs_z5"; + function = "pwm_vs"; + }; + }; + bl_pwm_combo_1_vs_on_pins:bl_pwm_combo_1_vs_on_pin { + mux { + groups = "pwm_vs_z6"; + function = "pwm_vs"; + }; + }; + bl_pwm_combo_off_pins:bl_pwm_combo_off_pin { + mux { + groups = "GPIOZ_5", + "GPIOZ_6"; + function = "gpio_periphs"; + output-low; + }; + }; + +}; /* end of pinctrl_periphs */ + +&audio_data{ + status = "okay"; +}; + +&i2c2 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&i2c2_z_pins>; + clock-frequency = <400000>; + + tas5805: tas5805@36 { + compatible = "ti,tas5805"; + #sound-dai-cells = <0>; + codec_name = "tas5805"; + reg = <0x0 0x2d>; + status = "disable"; + }; + + ad82584f: ad82584f@62 { + compatible = "ESMT, ad82584f"; + #sound-dai-cells = <0>; + reg = <0x0 0x31>; + status = "okay"; + reset_pin = <&gpio_ao GPIOAO_6 0>; + }; + +}; + +&sd_emmc_c { + status = "okay"; + emmc { + caps = "MMC_CAP_8_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + "MMC_CAP_1_8V_DDR", + "MMC_CAP_HW_RESET", + "MMC_CAP_ERASE", + "MMC_CAP_CMD23", + "MMC_CAP_DRIVER_TYPE_D"; + caps2 = "MMC_CAP2_HS200"; + /* "MMC_CAP2_HS400";*/ + f_min = <400000>; + f_max = <198000000>; + }; +}; + + + +&spifc { + status = "disabled"; + spi-nor@0 { + cs_gpios = <&gpio BOOT_13 GPIO_ACTIVE_HIGH>; + }; +}; + +&slc_nand { + status = "disabled"; + plat-names = "bootloader", "nandnormal"; + plat-num = <2>; + plat-part-0 = <&bootloader>; + plat-part-1 = <&nandnormal>; + bootloader: bootloader{ + enable_pad = "ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <1>; + part_num = <0>; + rb_detect = <1>; + }; + nandnormal: nandnormal{ + enable_pad = "ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + plane_mode = "twoplane"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <2>; + part_num = <3>; + partition = <&nand_partitions>; + rb_detect = <1>; + }; + nand_partitions:nand_partition{ + /* + * if bl_mode is 1, tpl size was generate by + * fip_copies * fip_size which + * will not skip bad when calculating + * the partition size; + * + * if bl_mode is 0, + * tpl partition must be comment out. + */ + tpl{ + offset=<0x0 0x0>; + size=<0x0 0x0>; + }; + logo{ + offset=<0x0 0x0>; + size=<0x0 0x200000>; + }; + recovery{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + boot{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + system{ + offset=<0x0 0x0>; + size=<0x0 0x4000000>; + }; + data{ + offset=<0xffffffff 0xffffffff>; + size=<0x0 0x0>; + }; + }; +}; + +ðmac { + status = "okay"; + pinctrl-names = "internal_eth_pins"; + pinctrl-0 = <&internal_eth_pins>; + mc_val = <0x4be04>; + + internal_phy=<1>; +}; + +&uart_A { + status = "okay"; +}; + +&dwc3 { + status = "okay"; +}; + +&usb2_phy_v2 { + status = "okay"; + portnum = <3>; +}; + +&usb3_phy_v2 { + status = "okay"; + portnum = <0>; + otg = <0>; +}; + +&dwc2_a { + status = "okay"; + /** 0: normal, 1: otg+dwc3 host only, 2: otg+dwc3 device only*/ + controller-type = <1>; +}; + +&spicc0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&spicc0_pins_h>; + cs-gpios = <&gpio GPIOH_20 0>; +}; + +&meson_fb { + status = "okay"; + display_size_default = <1920 1080 1920 2160 32>; + mem_size = <0x00800000 0x1980000 0x100000 0x800000>; + logo_addr = "0x7f800000"; + mem_alloc = <0>; + pxp_mode = <0>; /** 0:normal mode 1:pxp mode */ +}; + +&pwm_AO_cd { + status = "okay"; +}; + +&saradc { + status = "okay"; +}; + +&i2c1 { + status = "okay"; + clock-frequency = <300000>; + pinctrl-names="default"; + pinctrl-0=<&i2c1_h_pins>; + + lcd_extern_i2c0: lcd_extern_i2c@0 { + compatible = "lcd_ext, i2c"; + dev_name = "i2c_T5800Q"; + reg = <0x0 0x1c>; + status = "okay"; + }; + + lcd_extern_i2c1: lcd_extern_i2c@1 { + compatible = "lcd_ext, i2c"; + dev_name = "i2c_ANX6862"; + reg = <0x0 0x20>; + status = "okay"; + }; + + lcd_extern_i2c2: lcd_extern_i2c@2 { + compatible = "lcd_ext, i2c"; + dev_name = "i2c_ANX7911"; + reg = <0x0 0x74>; + status = "okay"; + }; +}; + +&pwm_ab { + status = "okay"; +}; + +&pwm_cd { + status = "okay"; +}; + +&efuse { + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/amlogic/tl1_t962x2_x301_1g.dts b/arch/arm64/boot/dts/amlogic/tl1_t962x2_x301_1g.dts new file mode 100644 index 000000000000..93566583937c --- /dev/null +++ b/arch/arm64/boot/dts/amlogic/tl1_t962x2_x301_1g.dts @@ -0,0 +1,1880 @@ +/* + * arch/arm64/boot/dts/amlogic/tl1_t962x2_x301_1g.dts + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +/dts-v1/; + +#include "mesontl1.dtsi" +#include "partition_mbox_normal_P_32.dtsi" +#include "mesontl1_x301-panel.dtsi" + +/ { + model = "Amlogic TL1 T962X2 X301"; + amlogic-dt-id = "tl1_t962x2_x301-1g"; + compatible = "amlogic, tl1_t962x2_x301"; + + aliases { + serial0 = &uart_AO; + serial1 = &uart_A; + serial2 = &uart_B; + serial3 = &uart_C; + serial4 = &uart_AO_B; + tsensor0 = &p_tsensor; + tsensor1 = &d_tsensor; + tsensor2 = &s_tsensor; + i2c0 = &i2c0; + i2c1 = &i2c1; + i2c2 = &i2c2; + i2c3 = &i2c3; + i2c4 = &i2c_AO; + }; + + memory@00000000 { + device_type = "memory"; + linux,usable-memory = <0x0 0x0 0x0 0x40000000>; + }; + + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + /* global autoconfigured region for contiguous allocations */ + ramoops@0x07400000 { + compatible = "ramoops"; + reg = <0x0 0x07400000 0x0 0x00100000>; + record-size = <0x8000>; + console-size = <0x8000>; + ftrace-size = <0x20000>; + }; + + secmon_reserved: linux,secmon { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x400000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x05000000 0x0 0x400000>; + }; + + logo_reserved:linux,meson-fb { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x800000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x3f800000 0x0 0x800000>; + }; + + lcd_tcon_reserved:linux,lcd_tcon { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0xc00000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x3ec00000 0x0 0xc00000>; + }; + + codec_mm_cma:linux,codec_mm_cma { + compatible = "shared-dma-pool"; + reusable; + /* ion_codec_mm max can alloc size 80M*/ + size = <0x0 0xd000000>; + alignment = <0x0 0x400000>; + linux,contiguous-region; + alloc-ranges = <0x0 0x30000000 0x0 0x10000000>; + }; + + /* codec shared reserved */ + codec_mm_reserved:linux,codec_mm_reserved { + compatible = "amlogic, codec-mm-reserved"; + size = <0x0 0x0>; + alignment = <0x0 0x100000>; + //no-map; + }; + + ion_cma_reserved:linux,ion-dev { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x2000000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x00000000 0x0 0x30000000>; + }; + + /* vdin0 CMA pool */ + //vdin0_cma_reserved:linux,vdin0_cma { + // compatible = "shared-dma-pool"; + // reusable; + /* 3840x2160x4x4 ~=128 M */ + // size = <0x0 0xc400000>; + // alignment = <0x0 0x400000>; + //}; + + /* vdin1 CMA pool */ + vdin1_cma_reserved:linux,vdin1_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16 M */ + size = <0x0 0x1400000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x30000000 0x0 0x10000000>; + }; + + /*demod_reserved:linux,demod { + * compatible = "amlogic, demod-mem"; + * size = <0x0 0x800000>; //8M //100m 0x6400000 + * alloc-ranges = <0x0 0x0 0x0 0x30000000>; + * //multi-use; + * //no-map; + *}; + */ + + demod_cma_reserved:linux,demod_cma { + compatible = "shared-dma-pool"; + reusable; + /* 8M */ + size = <0x0 0x0800000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x30000000 0x0 0x10000000>; + }; + + /*di CMA pool */ + di_cma_reserved:linux,di_cma { + compatible = "shared-dma-pool"; + reusable; + /* buffer_size = 3621952(yuv422 8bit) + * | 4736064(yuv422 10bit) + * | 4074560(yuv422 10bit full pack mode) + * 10x3621952=34.6M(0x23) support 8bit + * 10x4736064=45.2M(0x2e) support 12bit + * 10x4074560=40M(0x28) support 10bit + */ + size = <0x0 0x02800000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x00000000 0x0 0x30000000>; + }; + + /* for hdmi rx emp use */ + hdmirx_emp_cma_reserved:linux,emp_cma { + compatible = "shared-dma-pool"; + /*linux,phandle = <5>;*/ + reusable; + /* 4M for emp to ddr */ + /* 32M for tmds to ddr */ + size = <0x0 0x2000000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x00000000 0x0 0x30000000>; + }; + + /* POST PROCESS MANAGER */ + ppmgr_reserved:linux,ppmgr { + compatible = "amlogic, ppmgr_memory"; + size = <0x0 0x0>; + }; + + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x0>; + alignment = <0x0 0x0>; + linux,contiguous-region; + }; + }; /* end of reserved-memory */ + + codec_mm { + compatible = "amlogic, codec, mm"; + status = "okay"; + memory-region = <&codec_mm_cma &codec_mm_reserved>; + }; + + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + + ppmgr { + compatible = "amlogic, ppmgr"; + memory-region = <&ppmgr_reserved>; + status = "okay"; + }; + + deinterlace { + compatible = "amlogic, deinterlace"; + status = "okay"; + /* 0:use reserved; 1:use cma; 2:use cma as reserved */ + flag_cma = <1>; + //memory-region = <&di_reserved>; + memory-region = <&di_cma_reserved>; + interrupts = <0 46 1 + 0 40 1>; + interrupt-names = "pre_irq", "post_irq"; + clocks = <&clkc CLKID_VPU_CLKB_TMP_COMP>, + <&clkc CLKID_VPU_CLKB_COMP>; + clock-names = "vpu_clkb_tmp_composite", + "vpu_clkb_composite"; + clock-range = <334 667>; + /* buffer-size = <3621952>;(yuv422 8bit) */ + buffer-size = <4074560>;/*yuv422 fullpack*/ + /* reserve-iomap = "true"; */ + /* if enable nr10bit, set nr10bit-support to 1 */ + post-wr-support = <1>; + nr10bit-support = <1>; + nrds-enable = <1>; + pps-enable = <1>; + }; + + vout { + compatible = "amlogic, vout"; + status = "okay"; + fr_auto_policy = <0>; + }; + + /* Audio Related start */ + pdm_codec:dummy { + #sound-dai-cells = <0>; + compatible = "amlogic, pdm_dummy_codec"; + status = "okay"; + }; + + dummy_codec:dummy { + #sound-dai-cells = <0>; + compatible = "amlogic, aml_dummy_codec"; + status = "okay"; + }; + + tl1_codec:codec { + #sound-dai-cells = <0>; + compatible = "amlogic, tl1_acodec"; + status = "okay"; + reg = <0x0 0xff632000 0x0 0x1c>; + tdmout_index = <0>; + tdmin_index = <0>; + dat1_ch_sel = <1>; + }; + + aml_dtv_demod { + compatible = "amlogic, ddemod-tl1"; + dev_name = "aml_dtv_demod"; + status = "okay"; + + //pinctrl-names="dtvdemod_agc"; + //pinctrl-0=<&dtvdemod_agc>; + + clocks = <&clkc CLKID_DAC_CLK>; + clock-names = "vdac_clk_gate"; + + reg = <0x0 0xff650000 0x0 0x4000 /*dtv demod base*/ + 0x0 0xff63c000 0x0 0x2000 /*hiu reg base*/ + 0x0 0xff800000 0x0 0x1000 /*io_aobus_base*/ + 0x0 0xffd01000 0x0 0x1000 /*reset*/ + >; + + dtv_demod0_mem = <0>; // need move to aml_dtv_demod ? + spectrum = <1>; + cma_flag = <1>; + cma_mem_size = <8>; + memory-region = <&demod_cma_reserved>;//<&demod_reserved>; + }; + + auge_sound { + compatible = "amlogic, tl1-sound-card"; + aml-audio-card,name = "AML-AUGESOUND"; + + avout_mute-gpios = <&gpio GPIODV_3 GPIO_ACTIVE_HIGH>; + + aml-audio-card,dai-link@0 { + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdma>; + frame-master = <&tdma>; + /* slave mode */ + /* + * bitclock-master = <&tdmacodec>; + * frame-master = <&tdmacodec>; + */ + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-i2s"; + tdmacpu: cpu { + sound-dai = <&tdma>; + dai-tdm-slot-tx-mask = + <1 1>; + dai-tdm-slot-rx-mask = + <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmacodec: codec { + //sound-dai = <&dummy_codec>; + prefix-names = "AMP"; + sound-dai = <&ad82584f &tl1_codec>; + }; + }; + + aml-audio-card,dai-link@1 { + status = "disabled"; + + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdmb>; + frame-master = <&tdmb>; + /* slave mode */ + //bitclock-master = <&tdmbcodec>; + //frame-master = <&tdmbcodec>; + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-pcm"; + cpu { + sound-dai = <&tdmb>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + /* + * dai-tdm-slot-tx-mask = + * <1 1 1 1 1 1 1 1>; + * dai-tdm-slot-rx-mask = + * <1 1 1 1 1 1 1 1>; + * dai-tdm-slot-num = <8>; + */ + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmbcodec: codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@2 { + status = "disabled"; + + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdmc>; + frame-master = <&tdmc>; + /* slave mode */ + //bitclock-master = <&tdmccodec>; + //frame-master = <&tdmccodec>; + /* suffix-name, sync with android audio hal used for */ + //suffix-name = "alsaPORT-tdm"; + cpu { + sound-dai = <&tdmc>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmccodec: codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@3 { + mclk-fs = <64>; + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-pdm"; + cpu { + sound-dai = <&pdm>; + }; + codec { + sound-dai = <&pdm_codec>; + }; + }; + + aml-audio-card,dai-link@4 { + mclk-fs = <128>; + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-spdif"; + cpu { + sound-dai = <&spdifa>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@5 { + mclk-fs = <128>; + cpu { + sound-dai = <&spdifb>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@6 { + mclk-fs = <256>; + suffix-name = "alsaPORT-tv"; + cpu { + sound-dai = <&extn>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + + }; + /* Audio Related end */ + + dvb { + compatible = "amlogic, dvb"; + status = "okay"; + fe0_mode = "internal"; + fe0_tuner = <&tuner>; + + /*"parallel","serial","disable"*/ + ts2 = "parallel"; + ts2_control = <0>; + ts2_invert = <0>; + interrupts = <0 23 1 + 0 5 1 + 0 53 1 + 0 19 1 + 0 25 1 + 0 17 1>; + interrupt-names = "demux0_irq", + "demux1_irq", + "demux2_irq", + "dvr0_irq", + "dvr1_irq", + "dvr2_irq"; + clocks = <&clkc CLKID_DEMUX + &clkc CLKID_ASYNC_FIFO + &clkc CLKID_AHB_ARB0 +/* &clkc CLKID_DOS_PARSER>;*/ + &clkc CLKID_U_PARSER>; + clock-names = "demux", "asyncfifo", "ahbarb0", "uparsertop"; + }; + + tvafe_avin_detect { + compatible = "amlogic, tl1_tvafe_avin_detect"; + status = "okay"; + device_mask = <1>;/*bit0:ch1;bit1:ch2*/ + interrupts = <0 12 1>, + <0 13 1>; + }; + + amlvecm { + compatible = "amlogic, vecm"; + dev_name = "aml_vecm"; + status = "okay"; + gamma_en = <1>;/*1:enabel ;0:disable*/ + wb_en = <1>;/*1:enabel ;0:disable*/ + cm_en = <1>;/*1:enabel ;0:disable*/ + wb_sel = <1>;/*1:mtx ;0:gainoff*/ + vlock_en = <1>;/*1:enable;0:disable*/ + vlock_mode = <0x4>; + /* vlock work mode: + *bit0:auto ENC + *bit1:auto PLL + *bit2:manual PLL + *bit3:manual ENC + *bit4:manual soft ENC + *bit5:manual MIX PLL ENC + */ + vlock_pll_m_limit = <1>; + vlock_line_limit = <3>; + }; + + vdin@0 { + compatible = "amlogic, vdin"; + /*memory-region = <&vdin0_cma_reserved>;*/ + status = "okay"; + /*bit0:(1:share with codec_mm;0:cma alone) + *bit8:(1:alloc in discontinus way;0:alone in continuous way) + */ + flag_cma = <0x101>; + /*MByte, if 10bit disable: 64M(YUV422), + *if 10bit enable: 64*1.5 = 96M(YUV422) + *if support 4K2K-YUV444-10bit-WR:3840*2160*4*4 ~= 128M + *if support 4K2K-YUV422-10bit-wr:3840*2160*3*4 ~= 96M + *if support 4K2K-YUV422-8BIT-WR:3840*2160*2*4 ~= 64M + *if support 1080p-YUV422-8BIT-WR:1920*1080*2*4 ~= 16M + */ + cma_size = <160>; + interrupts = <0 83 1>; + rdma-irq = <2>; + clocks = <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_VDIN_MEAS_COMP>; + clock-names = "fclk_div5", "cts_vdin_meas_clk"; + vdin_id = <0>; + /*vdin write mem color depth support: + * bit0:support 8bit + * bit1:support 9bit + * bit2:support 10bit + * bit3:support 12bit + * bit4:support yuv422 10bit full pack mode (from txl new add) + * bit8:use 8bit at 4k_50/60hz_10bit + * bit9:use 10bit at 4k_50/60hz_10bit + */ + tv_bit_mode = <0x215>; + /* afbce_bit_mode: (amlogic frame buff compression encoder) + * bit 0~3: + * 0 -- normal mode, not use afbce + * 1 -- use afbce non-mmu mode + * 2 -- use afbce mmu mode + * bit 4: + * 0 -- afbce compression-lossy disable + * 1 -- afbce compression-lossy enable + */ + afbce_bit_mode = <0x1>; + }; + + vdin@1 { + compatible = "amlogic, vdin"; + memory-region = <&vdin1_cma_reserved>; + status = "okay"; + /*bit0:(1:share with codec_mm;0:cma alone) + *bit8:(1:alloc in discontinus way;0:alone in continuous way) + */ + flag_cma = <0>; + interrupts = <0 85 1>; + rdma-irq = <4>; + clocks = <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_VDIN_MEAS_COMP>; + clock-names = "fclk_div5", "cts_vdin_meas_clk"; + vdin_id = <1>; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + */ + tv_bit_mode = <0x15>; + }; + + tvafe { + compatible = "amlogic, tvafe-tl1"; + /*memory-region = <&tvafe_cma_reserved>;*/ + status = "okay"; + flag_cma = <1>;/*1:share with codec_mm;0:cma alone*/ + cma_size = <5>;/*MByte*/ + reg = <0x0 0xff654000 0x0 0x2000>;/*tvafe reg base*/ + reserve-iomap = "true"; + tvafe_id = <0>; + //pinctrl-names = "default"; + /*!!particular sequence, no more and no less!!!*/ + tvafe_pin_mux = < + 3 /* TVAFE_CVBS_IN2, CVBS_IN0 = 0 */ + 1 /* TVAFE_CVBS_IN0, CVBS_IN1 */ + 2 /* TVAFE_CVBS_IN1, CVBS_IN2 */ + 4 /* TVAFE_CVBS_IN3, CVBS_IN3 */ + >; + clocks = <&clkc CLKID_DAC_CLK>; + clock-names = "vdac_clk_gate"; + }; + + vbi { + compatible = "amlogic, vbi"; + status = "okay"; + interrupts = <0 83 1>; + }; + + cvbsout { + compatible = "amlogic, cvbsout-tl1"; + status = "disabled"; + clocks = <&clkc CLKID_VCLK2_ENCI + &clkc CLKID_VCLK2_VENCI0 + &clkc CLKID_VCLK2_VENCI1 + &clkc CLKID_DAC_CLK>; + clock-names = "venci_top_gate", + "venci_0_gate", + "venci_1_gate", + "vdac_clk_gate"; + /* clk path */ + /* 0:vid_pll vid2_clk */ + /* 1:gp0_pll vid2_clk */ + /* 2:vid_pll vid1_clk */ + /* 3:gp0_pll vid1_clk */ + clk_path = <0>; + + /* performance: reg_address, reg_value */ + /* tl1 */ + performance = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x8080 + 0x1b05 0xfd + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + performance_sarft = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x0 + 0x1b05 0x9 + 0x1c59 0xfc48 + 0xffff 0x0>; /* ending flag */ + performance_revB_telecom = <0x1bf0 0x9 + 0x1b56 0x546 + 0x1b12 0x8080 + 0x1b05 0x9 + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + }; + + /* for external keypad */ + adc_keypad { + compatible = "amlogic, adc_keypad"; + status = "okay"; + key_name = "power","up","down","enter","left","right","home"; + key_num = <7>; + io-channels = <&saradc SARADC_CH2>,<&saradc SARADC_CH3>; + io-channel-names = "key-chan-2", "key-chan-3"; + key_chan = ; + key_code = <116 103 108 28 105 106 102>; + key_val = <0 143 266 389 512 143 266>; //val=voltage/1800mV*1023 + key_tolerance = <40 40 40 40 40 40 40>; +}; + + unifykey { + compatible = "amlogic, unifykey"; + status = "okay"; + + unifykey-num = <21>; + unifykey-index-0 = <&keysn_0>; + unifykey-index-1 = <&keysn_1>; + unifykey-index-2 = <&keysn_2>; + unifykey-index-3 = <&keysn_3>; + unifykey-index-4 = <&keysn_4>; + unifykey-index-5 = <&keysn_5>; + unifykey-index-6 = <&keysn_6>; + unifykey-index-7 = <&keysn_7>; + unifykey-index-8 = <&keysn_8>; + unifykey-index-9 = <&keysn_9>; + unifykey-index-10= <&keysn_10>; + unifykey-index-11 = <&keysn_11>; + unifykey-index-12 = <&keysn_12>; + unifykey-index-13 = <&keysn_13>; + unifykey-index-14 = <&keysn_14>; + unifykey-index-15 = <&keysn_15>; + unifykey-index-16 = <&keysn_16>; + unifykey-index-17 = <&keysn_17>; + unifykey-index-18 = <&keysn_18>; + unifykey-index-19 = <&keysn_19>; + unifykey-index-20 = <&keysn_20>; + + keysn_0: key_0{ + key-name = "usid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_1:key_1{ + key-name = "mac"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_2:key_2{ + key-name = "hdcp"; + key-device = "secure"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_3:key_3{ + key-name = "secure_boot_set"; + key-device = "efuse"; + key-permit = "write"; + }; + keysn_4:key_4{ + key-name = "mac_bt"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_5:key_5{ + key-name = "mac_wifi"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_6:key_6{ + key-name = "hdcp2_tx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_7:key_7{ + key-name = "hdcp2_rx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_8:key_8{ + key-name = "widevinekeybox"; + key-device = "secure"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_9:key_9{ + key-name = "deviceid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_10:key_10{ + key-name = "hdcp22_fw_private"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_11:key_11{ + key-name = "hdcp22_rx_private"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_12:key_12{ + key-name = "hdcp22_rx_fw"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_13:key_13{ + key-name = "hdcp14_rx"; + key-device = "normal"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_14:key_14{ + key-name = "prpubkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_15:key_15{ + key-name = "prprivkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_16:key_16{ + key-name = "lcd"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_17:key_17{ + key-name = "lcd_extern"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_18:key_18{ + key-name = "backlight"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_19:key_19{ + key-name = "lcd_tcon"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_20:key_20{ + key-name = "attestationkeybox";// attestation key + key-device = "secure"; + key-permit = "read","write","del"; + }; + }; /* End unifykey */ + + amlvideo2_0 { + compatible = "amlogic, amlvideo2"; + dev_name = "amlvideo2"; + status = "okay"; + amlvideo2_id = <0>; + cma_mode = <1>; + }; + + amlvideo2_1 { + compatible = "amlogic, amlvideo2"; + dev_name = "amlvideo2"; + status = "okay"; + amlvideo2_id = <1>; + cma_mode = <1>; + }; + + hdmirx { + compatible = "amlogic, hdmirx_tl1"; + #address-cells=<1>; + #size-cells=<1>; + memory-region = <&hdmirx_emp_cma_reserved>; + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&hdmirx_a_mux &hdmirx_b_mux + &hdmirx_c_mux>; + repeat = <0>; + interrupts = <0 41 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clkc CLKID_HDMIRX_MODET_COMP>, + <&clkc CLKID_HDMIRX_CFG_COMP>, + <&clkc CLKID_HDMIRX_ACR_COMP>, + <&clkc CLKID_HDMIRX_METER_COMP>, + <&clkc CLKID_HDMIRX_AXI_COMP>, + <&xtal>, + <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_FCLK_DIV7>, + <&clkc CLKID_HDCP22_SKP_COMP>, + <&clkc CLKID_HDCP22_ESM_COMP>; + // <&clkc CLK_AUD_PLL2FS>, + // <&clkc CLK_AUD_PLL4FS>, + // <&clkc CLK_AUD_OUT>; + clock-names = "hdmirx_modet_clk", + "hdmirx_cfg_clk", + "hdmirx_acr_ref_clk", + "cts_hdmirx_meter_clk", + "cts_hdmi_axi_clk", + "xtal", + "fclk_div5", + "fclk_div7", + "hdcp_rx22_skp", + "hdcp_rx22_esm"; + // "hdmirx_aud_pll2fs", + // "hdmirx_aud_pll4f", + // "clk_aud_out"; + hdmirx_id = <0>; + en_4k_2_2k = <0>; + hpd_low_cec_off = <1>; + /* bit4: enable feature, bit3~0: port number */ + disable_port = <0x0>; + /* MAP_ADDR_MODULE_CBUS */ + /* MAP_ADDR_MODULE_HIU */ + /* MAP_ADDR_MODULE_HDMIRX_CAPB3 */ + /* MAP_ADDR_MODULE_SEC_AHB */ + /* MAP_ADDR_MODULE_SEC_AHB2 */ + /* MAP_ADDR_MODULE_APB4 */ + /* MAP_ADDR_MODULE_TOP */ + reg = < 0x0 0x0 0x0 0x0 + 0x0 0xff63C000 0x0 0x2000 + 0x0 0xffe0d000 0x0 0x2000 + 0x0 0x0 0x0 0x0 + 0x0 0x0 0x0 0x0 + 0x0 0x0 0x0 0x0 + 0x0 0xff610000 0x0 0xa000>; + }; + + aocec: aocec { + compatible = "amlogic, aocec-tl1"; + /*device_name = "aocec";*/ + status = "okay"; + vendor_name = "Amlogic"; /* Max Chars: 8 */ + /* Refer to the following URL at: + * http://standards.ieee.org/develop/regauth/oui/oui.txt + */ + vendor_id = <0x000000>; + product_desc = "TL1"; /* Max Chars: 16 */ + cec_osd_string = "AML_TV"; /* Max Chars: 14 */ + port_num = <3>; + ee_cec; + arc_port_mask = <0x2>; + interrupts = <0 205 1 + 0 199 1>; + interrupt-names = "hdmi_aocecb","hdmi_aocec"; + pinctrl-names = "default","hdmitx_aocecb","cec_pin_sleep"; + pinctrl-0=<&aoceca_mux>; + pinctrl-1=<&aocecb_mux>; + pinctrl-2=<&aoceca_mux>; + reg = <0x0 0xFF80023c 0x0 0x4 + 0x0 0xFF800000 0x0 0x400>; + reg-names = "ao_exit","ao"; + }; + + p_tsensor: p_tsensor@ff634800 { + compatible = "amlogic, r1p1-tsensor"; + status = "okay"; + reg = <0x0 0xff634800 0x0 0x50>, + <0x0 0xff800268 0x0 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 35 0>; + clocks = <&clkc CLKID_TS_CLK_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + d_tsensor: d_tsensor@ff634c00 { + compatible = "amlogic, r1p1-tsensor"; + status = "okay"; + reg = <0x0 0xff634c00 0x0 0x50>, + <0x0 0xff800230 0x0 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 36 0>; + clocks = <&clkc CLKID_TS_CLK_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + s_tsensor: s_tsensor@ff635000 { + compatible = "amlogic, r1p1-tsensor"; + status = "okay"; + reg = <0x0 0xff635000 0x0 0x50>, + <0x0 0xff80026c 0x0 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 38 0>; + clocks = <&clkc CLKID_TS_CLK_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + meson_cooldev: meson-cooldev@0 { + status = "okay"; + compatible = "amlogic, meson-cooldev"; + cooling_devices { + cpufreq_cool_cluster0 { + min_state = <1000000>; + dyn_coeff = <140>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "cpufreq_cool0"; + device_type = "cpufreq"; + }; + cpucore_cool_cluster0 { + min_state = <1>; + dyn_coeff = <0>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "cpucore_cool0"; + device_type = "cpucore"; + }; + gpufreq_cool { + min_state = <400>; + dyn_coeff = <140>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "gpufreq_cool0"; + device_type = "gpufreq"; + }; + gpucore_cool { + min_state = <1>; + dyn_coeff = <0>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "gpucore_cool0"; + device_type = "gpucore"; + }; + }; + cpufreq_cool0:cpufreq_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + cpucore_cool0:cpucore_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + gpufreq_cool0:gpufreq_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + gpucore_cool0:gpucore_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + };/*meson cooling devices end*/ + + thermal-zones { + pll_thermal: pll_thermal { + polling-delay = <1000>; + polling-delay-passive = <100>; + sustainable-power = <1322>; + thermal-sensors = <&p_tsensor 0>; + trips { + pswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + pcontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + phot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + pcritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + cooling-maps { + cpufreq_cooling_map { + trip = <&pcontrol>; + cooling-device = <&cpufreq_cool0 0 11>; + contribution = <1024>; + }; + cpucore_cooling_map { + trip = <&pcontrol>; + cooling-device = <&cpucore_cool0 0 4>; + contribution = <1024>; + }; + gpufreq_cooling_map { + trip = <&pcontrol>; + cooling-device = <&gpufreq_cool0 0 4>; + contribution = <1024>; + }; + }; + }; + ddr_thermal: ddr_thermal { + polling-delay = <2000>; + polling-delay-passive = <1000>; + sustainable-power = <1322>; + thermal-sensors = <&d_tsensor 1>; + trips { + dswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + dcontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + dhot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + dcritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + }; + sar_thermal: sar_thermal { + polling-delay = <2000>; + polling-delay-passive = <1000>; + sustainable-power = <1322>; + thermal-sensors = <&s_tsensor 2>; + trips { + sswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + scontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + shot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + scritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + }; + }; /*thermal zone end*/ + + /*DCDC for MP8756GD*/ + cpu_opp_table0: cpu_opp_table0 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <729000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <729000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <729000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <749000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <769000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <779000>; + }; + opp06 { + opp-hz = /bits/ 64 <1404000000>; + opp-microvolt = <789000>; + }; + opp07 { + opp-hz = /bits/ 64 <1500000000>; + opp-microvolt = <799000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <809000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <849000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <899000>; + }; + opp11 { + opp-hz = /bits/ 64 <1908000000>; + opp-microvolt = <949000>; + }; + }; + + cpufreq-meson { + compatible = "amlogic, cpufreq-meson"; + pinctrl-names = "default"; + pinctrl-0 = <&pwm_ao_d_pins3>; + status = "okay"; + }; + + tuner: tuner { + compatible = "amlogic, tuner"; + status = "okay"; + tuner_cur = <0>; /* default use tuner */ + tuner_num = <1>; /* tuner number, multi tuner support */ + tuner_name_0 = "mxl661_tuner"; + tuner_i2c_adap_0 = <&i2c0>; + tuner_i2c_addr_0 = <0x60>; + tuner_xtal_0 = <1>; /* 0: 16MHz, 1: 24MHz */ + tuner_xtal_mode_0 = <3>; + /* NO_SHARE_XTAL(0) + * SLAVE_XTAL_SHARE(3) + */ + tuner_xtal_cap_0 = <25>; /* when tuner_xtal_mode = 3, set 25 */ + }; + + atv-demod { + compatible = "amlogic, atv-demod"; + status = "okay"; + tuner = <&tuner>; + btsc_sap_mode = <1>; + /* pinctrl-names="atvdemod_agc_pins"; */ + /* pinctrl-0=<&atvdemod_agc_pins>; */ + reg = <0x0 0xff656000 0x0 0x2000 /* demod reg */ + 0x0 0xff63c000 0x0 0x2000 /* hiu reg */ + 0x0 0xff634000 0x0 0x2000 /* periphs reg */ + 0x0 0xff64a000 0x0 0x2000>; /* audio reg */ + reg_23cf = <0x88188832>; + /*default:0x88188832;r840 on haier:0x48188832*/ + }; + + bt-dev{ + compatible = "amlogic, bt-dev"; + status = "okay"; + gpio_reset = <&gpio GPIOC_13 GPIO_ACTIVE_HIGH>; + }; + + wifi{ + compatible = "amlogic, aml_wifi"; + status = "okay"; + interrupt_pin = <&gpio GPIOC_12 GPIO_ACTIVE_HIGH>; + irq_trigger_type = "GPIO_IRQ_LOW"; + dhd_static_buf; //dhd_static_buf support + power_on_pin = <&gpio GPIOC_11 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&pwm_b_pins1>; + pwm_config = <&wifi_pwm_conf>; + }; + + wifi_pwm_conf:wifi_pwm_conf{ + pwm_channel1_conf { + pwms = <&pwm_ab MESON_PWM_1 30541 0>; + duty-cycle = <15270>; + times = <8>; + }; + pwm_channel2_conf { + pwms = <&pwm_ab MESON_PWM_3 30500 0>; + duty-cycle = <15250>; + times = <12>; + }; + }; + + sd_emmc_b: sdio@ffe05000 { + status = "okay"; + compatible = "amlogic, meson-mmc-tl1"; + reg = <0x0 0xffe05000 0x0 0x800>; + interrupts = <0 190 4>; + + pinctrl-names = "sdio_all_pins", + "sdio_clk_cmd_pins"; + pinctrl-0 = <&sdio_all_pins>; + pinctrl-1 = <&sdio_clk_cmd_pins>; + + clocks = <&clkc CLKID_SD_EMMC_B>, + <&clkc CLKID_SD_EMMC_B_P0_COMP>, + <&clkc CLKID_FCLK_DIV2>, + <&clkc CLKID_FCLK_DIV5>, + <&xtal>; + clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + + bus-width = <4>; + cap-sd-highspeed; + cap-mmc-highspeed; + max-frequency = <100000000>; + disable-wp; + sdio { + pinname = "sdio"; + ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", /**ptm debug */ + "MMC_CAP_UHS_SDR12", + "MMC_CAP_UHS_SDR25", + "MMC_CAP_UHS_SDR50", + "MMC_CAP_UHS_SDR104", + "MMC_PM_KEEP_POWER", + "MMC_CAP_SDIO_IRQ"; + f_min = <400000>; + f_max = <200000000>; + max_req_size = <0x20000>; /**128KB*/ + card_type = <3>; + /* 3:sdio device(ie:sdio-wifi), + * 4:SD combo (IO+mem) card + */ + }; + }; +/* sd_emmc_b: sd@ffe05000 { + * status = "okay"; + * compatible = "amlogic, meson-mmc-tl1"; + * reg = <0xffe05000 0x800>; + * interrupts = <0 190 1>; + * + * pinctrl-names = "sd_all_pins", + * "sd_clk_cmd_pins", + * "sd_1bit_pins"; + * pinctrl-0 = <&sd_all_pins>; + * pinctrl-1 = <&sd_clk_cmd_pins>; + * pinctrl-2 = <&sd_1bit_pins>; + * + * clocks = <&clkc CLKID_SD_EMMC_B>, + * <&clkc CLKID_SD_EMMC_B_P0_COMP>, + * <&clkc CLKID_FCLK_DIV2>, + * <&clkc CLKID_FCLK_DIV5>, + * <&xtal>; + * clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + * + * bus-width = <4>; + * cap-sd-highspeed; + * cap-mmc-highspeed; + * max-frequency = <100000000>; + * disable-wp; + * sd { + * pinname = "sd"; + * ocr_avail = <0x200080>; + * caps = "MMC_CAP_4_BIT_DATA", + * "MMC_CAP_MMC_HIGHSPEED", + * "MMC_CAP_SD_HIGHSPEED"; + * f_min = <400000>; + * f_max = <200000000>; + * max_req_size = <0x20000>; + * no_sduart = <1>; + * gpio_dat3 = <&gpio GPIOC_3 GPIO_ACTIVE_HIGH>; + * jtag_pin = <&gpio GPIOC_0 GPIO_ACTIVE_HIGH>; + * gpio_cd = <&gpio GPIOC_10 GPIO_ACTIVE_HIGH>; + * card_type = <5>; + * }; + * }; + */ + +}; /* end of / */ + +&i2c0 { + status = "okay"; + clock-frequency = <300000>; + pinctrl-names="default"; + pinctrl-0=<&i2c0_dv_pins>; +}; + +&audiobus { + tdma:tdm@0 { + compatible = "amlogic, tl1-snd-tdma"; + #sound-dai-cells = <0>; + + dai-tdm-lane-slot-mask-in = <1 0>; + dai-tdm-lane-slot-mask-out = <1 1 1 1>; + dai-tdm-clk-sel = <0>; + + clocks = <&clkaudio CLKID_AUDIO_MCLK_A + &clkc CLKID_MPLL0 + &clkc CLKID_MPLL1 + &clkaudio CLKID_AUDIO_SPDIFOUT_A>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; + + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdma_mclk &tdmout_a>; + + /* + * 0: tdmout_a; + * 1: tdmout_b; + * 2: tdmout_c; + * 3: spdifout; + * 4: spdifout_b; + */ + samesource_sel = <3>; + + /* In for ACODEC_ADC */ + acodec_adc = <1>; + + status = "okay"; + + /* !!!For --TV platform-- ONLY */ + Channel_Mask { + /*i2s has 4 pins, 8channel, mux output*/ + Spdif_samesource_Channel_Mask = "i2s_2/3"; + }; + }; + + tdmb:tdm@1 { + compatible = "amlogic, tl1-snd-tdmb"; + #sound-dai-cells = <0>; + + dai-tdm-lane-slot-mask-in = <1 0 0 0>; + dai-tdm-lane-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <1>; + + clocks = <&clkaudio CLKID_AUDIO_MCLK_B + &clkc CLKID_MPLL1>; + clock-names = "mclk", "clk_srcpll"; + + status = "okay"; + }; + + tdmc:tdm@2 { + compatible = "amlogic, tl1-snd-tdmc"; + #sound-dai-cells = <0>; + + dai-tdm-lane-slot-mask-in = <1 0 0 0>; + dai-tdm-lane-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <2>; + + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmout_c &tdmin_c>; + + status = "okay"; + }; + + spdifa:spdif@0 { + compatible = "amlogic, tl1-snd-spdif-a"; + #sound-dai-cells = <0>; + + clocks = <&clkc CLKID_MPLL1 + &clkc CLKID_FCLK_DIV4 + &clkaudio CLKID_AUDIO_GATE_SPDIFIN + &clkaudio CLKID_AUDIO_GATE_SPDIFOUT_A + &clkaudio CLKID_AUDIO_SPDIFIN + &clkaudio CLKID_AUDIO_SPDIFOUT_A>; + clock-names = "sysclk", "fixed_clk", "gate_spdifin", + "gate_spdifout", "clk_spdifin", "clk_spdifout"; + + interrupts = + ; + interrupt-names = "irq_spdifin"; + + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; + pinctrl-0 = <&spdifout_a>; + pinctrl-1 = <&spdifout_a_mute>; + + /* + * whether do asrc for pcm and resample a or b + * if raw data, asrc is disabled automatically + * 0: "Disable", + * 1: "Enable:32K", + * 2: "Enable:44K", + * 3: "Enable:48K", + * 4: "Enable:88K", + * 5: "Enable:96K", + * 6: "Enable:176K", + * 7: "Enable:192K", + */ + asrc_id = <0>; + auto_asrc = <3>; + + status = "okay"; + }; + + spdifb:spdif@1 { + compatible = "amlogic, tl1-snd-spdif-b"; + #sound-dai-cells = <0>; + + clocks = <&clkc CLKID_MPLL0 /*CLKID_HIFI_PLL*/ + &clkaudio CLKID_AUDIO_GATE_SPDIFOUT_B + &clkaudio CLKID_AUDIO_SPDIFOUT_B>; + clock-names = "sysclk", + "gate_spdifout", "clk_spdifout"; + + status = "okay"; + }; + + pdm:pdm { + compatible = "amlogic, tl1-snd-pdm"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_PDM + &clkc CLKID_FCLK_DIV3 + &clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_PDMIN0 + &clkaudio CLKID_AUDIO_PDMIN1>; + clock-names = "gate", + "sysclk_srcpll", + "dclk_srcpll", + "pdm_dclk", + "pdm_sysclk"; + + pinctrl-names = "pdm_pins"; + pinctrl-0 = <&pdmin>; + + /* mode 0~4, defalut:1 */ + filter_mode = <1>; + + status = "okay"; + }; + + extn:extn { + compatible = "amlogic, snd-extn"; + #sound-dai-cells = <0>; + + interrupts = + ; + interrupt-names = "irq_frhdmirx"; + + status = "okay"; + }; + + aed:effect { + compatible = "amlogic, snd-effect-v2"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_EQDRC + &clkc CLKID_FCLK_DIV5 + &clkaudio CLKID_AUDIO_EQDRC>; + clock-names = "gate", "srcpll", "eqdrc"; + + /* + * 0:tdmout_a + * 1:tdmout_b + * 2:tdmout_c + * 3:spdifout + * 4:spdifout_b + */ + eqdrc_module = <0>; + /* max 0xf, each bit for one lane, usually one lane */ + lane_mask = <0x1>; + /* max 0xff, each bit for one channel */ + channel_mask = <0xff>; + + status = "okay"; + }; + + asrca: resample@0 { + compatible = "amlogic, tl1-resample-a"; + clocks = <&clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_MCLK_A + &clkaudio CLKID_AUDIO_RESAMPLE_A>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + /*same with toddr_src + * TDMIN_A, 0 + * TDMIN_B, 1 + * TDMIN_C, 2 + * SPDIFIN, 3 + * PDMIN, 4 + * NONE, + * TDMIN_LB, 6 + * LOOPBACK, 7 + */ + resample_module = <3>; + + status = "okay"; + }; + + asrcb: resample@1 { + compatible = "amlogic, tl1-resample-b"; + + clocks = <&clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_MCLK_F + &clkaudio CLKID_AUDIO_RESAMPLE_B>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + + /*same with toddr_src + * TDMIN_A, 0 + * TDMIN_B, 1 + * TDMIN_C, 2 + * SPDIFIN, 3 + * PDMIN, 4 + * NONE, + * TDMIN_LB, 6 + * LOOPBACK, 7 + */ + resample_module = <3>; + + status = "disabled"; + }; + +}; /* end of audiobus */ + +&pinctrl_periphs { + /* audio pin mux */ + + tdma_mclk: tdma_mclk { + mux { /* GPIOZ_0 */ + groups = "mclk0_z"; + function = "mclk0"; + }; + }; + + tdmout_a: tdmout_a { + mux { /* GPIOZ_1, GPIOZ_2, GPIOZ_3 */ + groups = "tdma_sclk_z", + "tdma_fs_z", + "tdma_dout0_z"; + function = "tdma_out"; + bias-pull-down; + }; + }; + + tdmin_a: tdmin_a { + mux { /* GPIOZ_9 */ + groups = "tdma_din2_z"; + function = "tdma_in"; + }; + }; + + tdmout_c: tdmout_c { + mux { /* GPIODV_7, GPIODV_8, GPIODV_9 */ + groups = "tdmc_sclk", + "tdmc_fs", + "tdmc_dout0"; + function = "tdmc_out"; + }; + }; + + tdmin_c: tdmin_c { + mux { /* GPIODV_10 */ + groups = "tdmc_din1"; + function = "tdmc_in"; + }; + }; + + spdifin_a: spdifin_a { + mux { /* GPIODV_5 */ + groups = "spdif_in"; + function = "spdif_in"; + }; + }; + + spdifout_a: spdifout_a { + mux { /* GPIODV_4 */ + groups = "spdif_out_dv4"; + function = "spdif_out"; + }; + }; + + spdifout_a_mute: spdifout_a_mute { + mux { /* GPIODV_4 */ + groups = "GPIODV_4"; + function = "gpio_periphs"; + }; + }; + + pdmin: pdmin { + mux { /* GPIOZ_7, GPIOZ_8, pdm_din2_z4 */ + groups = "pdm_dclk_z", + "pdm_din0_z", + "pdm_din2_z4"; + function = "pdm"; + }; + }; + + /*backlight*/ + bl_pwm_vs_on_pins:bl_pwm_vs_on_pin { + mux { + groups = "pwm_vs_z5"; + function = "pwm_vs"; + }; + }; + bl_pwm_off_pins:bl_pwm_off_pin { + mux { + groups = "GPIOZ_5"; + function = "gpio_periphs"; + output-low; + }; + }; + bl_pwm_combo_0_vs_on_pins:bl_pwm_combo_0_vs_on_pin { + mux { + groups = "pwm_vs_z5"; + function = "pwm_vs"; + }; + }; + bl_pwm_combo_1_vs_on_pins:bl_pwm_combo_1_vs_on_pin { + mux { + groups = "pwm_vs_z6"; + function = "pwm_vs"; + }; + }; + bl_pwm_combo_off_pins:bl_pwm_combo_off_pin { + mux { + groups = "GPIOZ_5", + "GPIOZ_6"; + function = "gpio_periphs"; + output-low; + }; + }; + +}; /* end of pinctrl_periphs */ + +&audio_data{ + status = "okay"; +}; + +&i2c2 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&i2c2_z_pins>; + clock-frequency = <400000>; + + tas5805: tas5805@36 { + compatible = "ti,tas5805"; + #sound-dai-cells = <0>; + codec_name = "tas5805"; + reg = <0x2d>; + status = "disable"; + }; + + ad82584f: ad82584f@62 { + compatible = "ESMT, ad82584f"; + #sound-dai-cells = <0>; + reg = <0x31>; + status = "okay"; + reset_pin = <&gpio_ao GPIOAO_6 0>; + }; + +}; + +&sd_emmc_c { + status = "okay"; + emmc { + caps = "MMC_CAP_8_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + "MMC_CAP_1_8V_DDR", + "MMC_CAP_HW_RESET", + "MMC_CAP_ERASE", + "MMC_CAP_CMD23", + "MMC_CAP_DRIVER_TYPE_D"; + caps2 = "MMC_CAP2_HS200", "MMC_CAP2_HS400"; + f_min = <400000>; + f_max = <198000000>; + }; +}; + + + +&spifc { + status = "disabled"; + spi-nor@0 { + cs_gpios = <&gpio BOOT_13 GPIO_ACTIVE_HIGH>; + }; +}; + +&slc_nand { + status = "disabled"; + plat-names = "bootloader", "nandnormal"; + plat-num = <2>; + plat-part-0 = <&bootloader>; + plat-part-1 = <&nandnormal>; + bootloader: bootloader{ + enable_pad = "ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <1>; + part_num = <0>; + rb_detect = <1>; + }; + nandnormal: nandnormal{ + enable_pad = "ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + plane_mode = "twoplane"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <2>; + part_num = <3>; + partition = <&nand_partitions>; + rb_detect = <1>; + }; + nand_partitions:nand_partition{ + /* + * if bl_mode is 1, tpl size was generate by + * fip_copies * fip_size which + * will not skip bad when calculating + * the partition size; + * + * if bl_mode is 0, + * tpl partition must be comment out. + */ + tpl{ + offset=<0x0 0x0>; + size=<0x0 0x0>; + }; + logo{ + offset=<0x0 0x0>; + size=<0x0 0x200000>; + }; + recovery{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + boot{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + system{ + offset=<0x0 0x0>; + size=<0x0 0x4000000>; + }; + data{ + offset=<0xffffffff 0xffffffff>; + size=<0x0 0x0>; + }; + }; +}; + +ðmac { + status = "okay"; + pinctrl-names = "internal_eth_pins"; + pinctrl-0 = <&internal_eth_pins>; + mc_val = <0x4be04>; + + internal_phy=<1>; +}; + +&uart_A { + status = "okay"; +}; + +&dwc3 { + status = "okay"; +}; + +&usb2_phy_v2 { + status = "okay"; + portnum = <3>; +}; + +&usb3_phy_v2 { + status = "okay"; + portnum = <0>; + otg = <0>; +}; + +&dwc2_a { + status = "okay"; + /** 0: normal, 1: otg+dwc3 host only, 2: otg+dwc3 device only*/ + controller-type = <1>; +}; + +&spicc0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&spicc0_pins_h>; + cs-gpios = <&gpio GPIOH_20 0>; +}; + +&meson_fb { + status = "okay"; + display_size_default = <1920 1080 1920 2160 32>; + mem_size = <0x00800000 0x1980000 0x100000 0x800000>; + logo_addr = "0x3f800000"; + mem_alloc = <0>; + pxp_mode = <0>; /** 0:normal mode 1:pxp mode */ +}; + +&pwm_AO_cd { + status = "okay"; +}; + +&saradc { + status = "okay"; +}; + +&i2c1 { + status = "okay"; + clock-frequency = <300000>; + pinctrl-names="default"; + pinctrl-0=<&i2c1_h_pins>; + + lcd_extern_i2c0: lcd_extern_i2c@0 { + compatible = "lcd_ext, i2c"; + dev_name = "i2c_T5800Q"; + reg = <0x1c>; + status = "okay"; + }; + + lcd_extern_i2c1: lcd_extern_i2c@1 { + compatible = "lcd_ext, i2c"; + dev_name = "i2c_ANX6862"; + reg = <0x20>; + status = "okay"; + }; + + lcd_extern_i2c2: lcd_extern_i2c@2 { + compatible = "lcd_ext, i2c"; + dev_name = "i2c_ANX7911"; + reg = <0x74>; + status = "okay"; + }; +}; + +&pwm_ab { + status = "okay"; +}; + +&pwm_cd { + status = "okay"; +}; + +&efuse { + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/amlogic/tl1_t962x2_x301_2g.dts b/arch/arm64/boot/dts/amlogic/tl1_t962x2_x301_2g.dts new file mode 100644 index 000000000000..17b68c35d97e --- /dev/null +++ b/arch/arm64/boot/dts/amlogic/tl1_t962x2_x301_2g.dts @@ -0,0 +1,1875 @@ +/* + * arch/arm64/boot/dts/amlogic/tl1_t962x2_x301_2g.dts + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +/dts-v1/; + +#include "mesontl1.dtsi" +#include "partition_mbox_normal_P_32.dtsi" +#include "mesontl1_x301-panel.dtsi" + +/ { + model = "Amlogic TL1 T962X2 X301"; + amlogic-dt-id = "tl1_t962x2_x301-2g"; + compatible = "amlogic, tl1_t962x2_x301"; + + aliases { + serial0 = &uart_AO; + serial1 = &uart_A; + serial2 = &uart_B; + serial3 = &uart_C; + serial4 = &uart_AO_B; + tsensor0 = &p_tsensor; + tsensor1 = &d_tsensor; + tsensor2 = &s_tsensor; + i2c0 = &i2c0; + i2c1 = &i2c1; + i2c2 = &i2c2; + i2c3 = &i2c3; + i2c4 = &i2c_AO; + }; + + memory@00000000 { + device_type = "memory"; + linux,usable-memory = <0x0 0x0 0x0 0x80000000>; + }; + + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + /* global autoconfigured region for contiguous allocations */ + ramoops@0x07400000 { + compatible = "ramoops"; + reg = <0x0 0x07400000 0x0 0x00100000>; + record-size = <0x8000>; + console-size = <0x8000>; + ftrace-size = <0x20000>; + }; + + secmon_reserved: linux,secmon { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x400000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x05000000 0x0 0x400000>; + }; + + logo_reserved:linux,meson-fb { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x800000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x7f800000 0x0 0x800000>; + }; + + lcd_tcon_reserved:linux,lcd_tcon { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0xc00000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x7ec00000 0x0 0xc00000>; + }; + + codec_mm_cma:linux,codec_mm_cma { + compatible = "shared-dma-pool"; + reusable; + /* ion_codec_mm max can alloc size 80M*/ + size = <0x0 0x13400000>; + alignment = <0x0 0x400000>; + linux,contiguous-region; + }; + + /* codec shared reserved */ + codec_mm_reserved:linux,codec_mm_reserved { + compatible = "amlogic, codec-mm-reserved"; + size = <0x0 0x0>; + alignment = <0x0 0x100000>; + //no-map; + }; + + ion_cma_reserved:linux,ion-dev { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x2000000>; + alignment = <0x0 0x400000>; + }; + + /* vdin0 CMA pool */ + //vdin0_cma_reserved:linux,vdin0_cma { + // compatible = "shared-dma-pool"; + // reusable; + /* 3840x2160x4x4 ~=128 M */ + // size = <0x0 0xc400000>; + // alignment = <0x0 0x400000>; + //}; + + /* vdin1 CMA pool */ + vdin1_cma_reserved:linux,vdin1_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16 M */ + size = <0x0 0x1400000>; + alignment = <0x0 0x400000>; + }; + + /*demod_reserved:linux,demod { + * compatible = "amlogic, demod-mem"; + * size = <0x0 0x800000>; //8M //100m 0x6400000 + * alloc-ranges = <0x0 0x0 0x0 0x30000000>; + * //multi-use; + * //no-map; + *}; + */ + + demod_cma_reserved:linux,demod_cma { + compatible = "shared-dma-pool"; + reusable; + /* 8M */ + size = <0x0 0x0800000>; + alignment = <0x0 0x400000>; + }; + + /*di CMA pool */ + di_cma_reserved:linux,di_cma { + compatible = "shared-dma-pool"; + reusable; + /* buffer_size = 3621952(yuv422 8bit) + * | 4736064(yuv422 10bit) + * | 4074560(yuv422 10bit full pack mode) + * 10x3621952=34.6M(0x23) support 8bit + * 10x4736064=45.2M(0x2e) support 12bit + * 10x4074560=40M(0x28) support 10bit + */ + size = <0x0 0x02800000>; + alignment = <0x0 0x400000>; + }; + + /* for hdmi rx emp use */ + hdmirx_emp_cma_reserved:linux,emp_cma { + compatible = "shared-dma-pool"; + /*linux,phandle = <5>;*/ + reusable; + /* 4M for emp to ddr */ + /* 32M for tmds to ddr */ + size = <0x0 0x2000000>; + alignment = <0x0 0x400000>; + }; + + /* POST PROCESS MANAGER */ + ppmgr_reserved:linux,ppmgr { + compatible = "amlogic, ppmgr_memory"; + size = <0x0 0x0>; + }; + + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x0>; + alignment = <0x0 0x0>; + linux,contiguous-region; + }; + }; /* end of reserved-memory */ + + codec_mm { + compatible = "amlogic, codec, mm"; + status = "okay"; + memory-region = <&codec_mm_cma &codec_mm_reserved>; + }; + + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + + ppmgr { + compatible = "amlogic, ppmgr"; + memory-region = <&ppmgr_reserved>; + status = "okay"; + }; + + deinterlace { + compatible = "amlogic, deinterlace"; + status = "okay"; + /* 0:use reserved; 1:use cma; 2:use cma as reserved */ + flag_cma = <1>; + //memory-region = <&di_reserved>; + memory-region = <&di_cma_reserved>; + interrupts = <0 46 1 + 0 40 1>; + interrupt-names = "pre_irq", "post_irq"; + clocks = <&clkc CLKID_VPU_CLKB_TMP_COMP>, + <&clkc CLKID_VPU_CLKB_COMP>; + clock-names = "vpu_clkb_tmp_composite", + "vpu_clkb_composite"; + clock-range = <334 667>; + /* buffer-size = <3621952>;(yuv422 8bit) */ + buffer-size = <4074560>;/*yuv422 fullpack*/ + /* reserve-iomap = "true"; */ + /* if enable nr10bit, set nr10bit-support to 1 */ + post-wr-support = <1>; + nr10bit-support = <1>; + nrds-enable = <1>; + pps-enable = <1>; + }; + + vout { + compatible = "amlogic, vout"; + status = "okay"; + fr_auto_policy = <0>; + }; + + /* Audio Related start */ + pdm_codec:dummy { + #sound-dai-cells = <0>; + compatible = "amlogic, pdm_dummy_codec"; + status = "okay"; + }; + + dummy_codec:dummy { + #sound-dai-cells = <0>; + compatible = "amlogic, aml_dummy_codec"; + status = "okay"; + }; + + tl1_codec:codec { + #sound-dai-cells = <0>; + compatible = "amlogic, tl1_acodec"; + status = "okay"; + reg = <0x0 0xff632000 0x0 0x1c>; + tdmout_index = <0>; + tdmin_index = <0>; + dat1_ch_sel = <1>; + }; + + aml_dtv_demod { + compatible = "amlogic, ddemod-tl1"; + dev_name = "aml_dtv_demod"; + status = "okay"; + + //pinctrl-names="dtvdemod_agc"; + //pinctrl-0=<&dtvdemod_agc>; + + clocks = <&clkc CLKID_DAC_CLK>; + clock-names = "vdac_clk_gate"; + + reg = <0x0 0xff650000 0x0 0x4000 /*dtv demod base*/ + 0x0 0xff63c000 0x0 0x2000 /*hiu reg base*/ + 0x0 0xff800000 0x0 0x1000 /*io_aobus_base*/ + 0x0 0xffd01000 0x0 0x1000 /*reset*/ + >; + + dtv_demod0_mem = <0>; // need move to aml_dtv_demod ? + spectrum = <1>; + cma_flag = <1>; + cma_mem_size = <8>; + memory-region = <&demod_cma_reserved>;//<&demod_reserved>; + }; + + auge_sound { + compatible = "amlogic, tl1-sound-card"; + aml-audio-card,name = "AML-AUGESOUND"; + + avout_mute-gpios = <&gpio GPIODV_3 GPIO_ACTIVE_HIGH>; + + aml-audio-card,dai-link@0 { + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdma>; + frame-master = <&tdma>; + /* slave mode */ + /* + * bitclock-master = <&tdmacodec>; + * frame-master = <&tdmacodec>; + */ + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-i2s"; + tdmacpu: cpu { + sound-dai = <&tdma>; + dai-tdm-slot-tx-mask = + <1 1>; + dai-tdm-slot-rx-mask = + <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmacodec: codec { + //sound-dai = <&dummy_codec>; + prefix-names = "AMP"; + sound-dai = <&ad82584f &tl1_codec>; + }; + }; + + aml-audio-card,dai-link@1 { + status = "disabled"; + + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdmb>; + frame-master = <&tdmb>; + /* slave mode */ + //bitclock-master = <&tdmbcodec>; + //frame-master = <&tdmbcodec>; + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-pcm"; + cpu { + sound-dai = <&tdmb>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + /* + * dai-tdm-slot-tx-mask = + * <1 1 1 1 1 1 1 1>; + * dai-tdm-slot-rx-mask = + * <1 1 1 1 1 1 1 1>; + * dai-tdm-slot-num = <8>; + */ + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmbcodec: codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@2 { + status = "disabled"; + + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdmc>; + frame-master = <&tdmc>; + /* slave mode */ + //bitclock-master = <&tdmccodec>; + //frame-master = <&tdmccodec>; + /* suffix-name, sync with android audio hal used for */ + //suffix-name = "alsaPORT-tdm"; + cpu { + sound-dai = <&tdmc>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmccodec: codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@3 { + mclk-fs = <64>; + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-pdm"; + cpu { + sound-dai = <&pdm>; + }; + codec { + sound-dai = <&pdm_codec>; + }; + }; + + aml-audio-card,dai-link@4 { + mclk-fs = <128>; + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-spdif"; + cpu { + sound-dai = <&spdifa>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@5 { + mclk-fs = <128>; + cpu { + sound-dai = <&spdifb>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@6 { + mclk-fs = <256>; + suffix-name = "alsaPORT-tv"; + cpu { + sound-dai = <&extn>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + + }; + /* Audio Related end */ + + dvb { + compatible = "amlogic, dvb"; + status = "okay"; + fe0_mode = "internal"; + fe0_tuner = <&tuner>; + + /*"parallel","serial","disable"*/ + ts2 = "parallel"; + ts2_control = <0>; + ts2_invert = <0>; + interrupts = <0 23 1 + 0 5 1 + 0 53 1 + 0 19 1 + 0 25 1 + 0 17 1>; + interrupt-names = "demux0_irq", + "demux1_irq", + "demux2_irq", + "dvr0_irq", + "dvr1_irq", + "dvr2_irq"; + clocks = <&clkc CLKID_DEMUX + &clkc CLKID_ASYNC_FIFO + &clkc CLKID_AHB_ARB0 +/* &clkc CLKID_DOS_PARSER>;*/ + &clkc CLKID_U_PARSER>; + clock-names = "demux", "asyncfifo", "ahbarb0", "uparsertop"; + }; + + tvafe_avin_detect { + compatible = "amlogic, tl1_tvafe_avin_detect"; + status = "okay"; + device_mask = <1>;/*bit0:ch1;bit1:ch2*/ + interrupts = <0 12 1>, + <0 13 1>; + }; + + amlvecm { + compatible = "amlogic, vecm"; + dev_name = "aml_vecm"; + status = "okay"; + gamma_en = <1>;/*1:enabel ;0:disable*/ + wb_en = <1>;/*1:enabel ;0:disable*/ + cm_en = <1>;/*1:enabel ;0:disable*/ + wb_sel = <1>;/*1:mtx ;0:gainoff*/ + vlock_en = <1>;/*1:enable;0:disable*/ + vlock_mode = <0x4>; + /* vlock work mode: + *bit0:auto ENC + *bit1:auto PLL + *bit2:manual PLL + *bit3:manual ENC + *bit4:manual soft ENC + *bit5:manual MIX PLL ENC + */ + vlock_pll_m_limit = <1>; + vlock_line_limit = <3>; + }; + + vdin@0 { + compatible = "amlogic, vdin"; + /*memory-region = <&vdin0_cma_reserved>;*/ + status = "okay"; + /*bit0:(1:share with codec_mm;0:cma alone) + *bit8:(1:alloc in discontinus way;0:alone in continuous way) + */ + flag_cma = <0x101>; + /*MByte, if 10bit disable: 64M(YUV422), + *if 10bit enable: 64*1.5 = 96M(YUV422) + *if support 4K2K-YUV444-10bit-WR:3840*2160*4*4 ~= 128M + *if support 4K2K-YUV422-10bit-wr:3840*2160*3*4 ~= 96M + *if support 4K2K-YUV422-8BIT-WR:3840*2160*2*4 ~= 64M + *if support 1080p-YUV422-8BIT-WR:1920*1080*2*4 ~= 16M + */ + cma_size = <160>; + interrupts = <0 83 1>; + rdma-irq = <2>; + clocks = <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_VDIN_MEAS_COMP>; + clock-names = "fclk_div5", "cts_vdin_meas_clk"; + vdin_id = <0>; + /*vdin write mem color depth support: + * bit0:support 8bit + * bit1:support 9bit + * bit2:support 10bit + * bit3:support 12bit + * bit4:support yuv422 10bit full pack mode (from txl new add) + * bit8:use 8bit at 4k_50/60hz_10bit + * bit9:use 10bit at 4k_50/60hz_10bit + */ + tv_bit_mode = <0x215>; + /* afbce_bit_mode: (amlogic frame buff compression encoder) + * bit 0~3: + * 0 -- normal mode, not use afbce + * 1 -- use afbce non-mmu mode + * 2 -- use afbce mmu mode + * bit 4: + * 0 -- afbce compression-lossy disable + * 1 -- afbce compression-lossy enable + */ + afbce_bit_mode = <0x1>; + }; + + vdin@1 { + compatible = "amlogic, vdin"; + memory-region = <&vdin1_cma_reserved>; + status = "okay"; + /*bit0:(1:share with codec_mm;0:cma alone) + *bit8:(1:alloc in discontinus way;0:alone in continuous way) + */ + flag_cma = <0>; + interrupts = <0 85 1>; + rdma-irq = <4>; + clocks = <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_VDIN_MEAS_COMP>; + clock-names = "fclk_div5", "cts_vdin_meas_clk"; + vdin_id = <1>; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + */ + tv_bit_mode = <0x15>; + }; + + tvafe { + compatible = "amlogic, tvafe-tl1"; + /*memory-region = <&tvafe_cma_reserved>;*/ + status = "okay"; + flag_cma = <1>;/*1:share with codec_mm;0:cma alone*/ + cma_size = <5>;/*MByte*/ + reg = <0x0 0xff654000 0x0 0x2000>;/*tvafe reg base*/ + reserve-iomap = "true"; + tvafe_id = <0>; + //pinctrl-names = "default"; + /*!!particular sequence, no more and no less!!!*/ + tvafe_pin_mux = < + 3 /* TVAFE_CVBS_IN2, CVBS_IN0 = 0 */ + 1 /* TVAFE_CVBS_IN0, CVBS_IN1 */ + 2 /* TVAFE_CVBS_IN1, CVBS_IN2 */ + 4 /* TVAFE_CVBS_IN3, CVBS_IN3 */ + >; + clocks = <&clkc CLKID_DAC_CLK>; + clock-names = "vdac_clk_gate"; + }; + + vbi { + compatible = "amlogic, vbi"; + status = "okay"; + interrupts = <0 83 1>; + }; + + cvbsout { + compatible = "amlogic, cvbsout-tl1"; + status = "disabled"; + clocks = <&clkc CLKID_VCLK2_ENCI + &clkc CLKID_VCLK2_VENCI0 + &clkc CLKID_VCLK2_VENCI1 + &clkc CLKID_DAC_CLK>; + clock-names = "venci_top_gate", + "venci_0_gate", + "venci_1_gate", + "vdac_clk_gate"; + /* clk path */ + /* 0:vid_pll vid2_clk */ + /* 1:gp0_pll vid2_clk */ + /* 2:vid_pll vid1_clk */ + /* 3:gp0_pll vid1_clk */ + clk_path = <0>; + + /* performance: reg_address, reg_value */ + /* tl1 */ + performance = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x8080 + 0x1b05 0xfd + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + performance_sarft = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x0 + 0x1b05 0x9 + 0x1c59 0xfc48 + 0xffff 0x0>; /* ending flag */ + performance_revB_telecom = <0x1bf0 0x9 + 0x1b56 0x546 + 0x1b12 0x8080 + 0x1b05 0x9 + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + }; + + /* for external keypad */ + adc_keypad { + compatible = "amlogic, adc_keypad"; + status = "okay"; + key_name = "power","up","down","enter","left","right","home"; + key_num = <7>; + io-channels = <&saradc SARADC_CH2>,<&saradc SARADC_CH3>; + io-channel-names = "key-chan-2", "key-chan-3"; + key_chan = ; + key_code = <116 103 108 28 105 106 102>; + key_val = <0 143 266 389 512 143 266>; //val=voltage/1800mV*1023 + key_tolerance = <40 40 40 40 40 40 40>; +}; + + unifykey { + compatible = "amlogic, unifykey"; + status = "okay"; + + unifykey-num = <21>; + unifykey-index-0 = <&keysn_0>; + unifykey-index-1 = <&keysn_1>; + unifykey-index-2 = <&keysn_2>; + unifykey-index-3 = <&keysn_3>; + unifykey-index-4 = <&keysn_4>; + unifykey-index-5 = <&keysn_5>; + unifykey-index-6 = <&keysn_6>; + unifykey-index-7 = <&keysn_7>; + unifykey-index-8 = <&keysn_8>; + unifykey-index-9 = <&keysn_9>; + unifykey-index-10= <&keysn_10>; + unifykey-index-11 = <&keysn_11>; + unifykey-index-12 = <&keysn_12>; + unifykey-index-13 = <&keysn_13>; + unifykey-index-14 = <&keysn_14>; + unifykey-index-15 = <&keysn_15>; + unifykey-index-16 = <&keysn_16>; + unifykey-index-17 = <&keysn_17>; + unifykey-index-18 = <&keysn_18>; + unifykey-index-19 = <&keysn_19>; + unifykey-index-20 = <&keysn_20>; + + keysn_0: key_0{ + key-name = "usid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_1:key_1{ + key-name = "mac"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_2:key_2{ + key-name = "hdcp"; + key-device = "secure"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_3:key_3{ + key-name = "secure_boot_set"; + key-device = "efuse"; + key-permit = "write"; + }; + keysn_4:key_4{ + key-name = "mac_bt"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_5:key_5{ + key-name = "mac_wifi"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_6:key_6{ + key-name = "hdcp2_tx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_7:key_7{ + key-name = "hdcp2_rx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_8:key_8{ + key-name = "widevinekeybox"; + key-device = "secure"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_9:key_9{ + key-name = "deviceid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_10:key_10{ + key-name = "hdcp22_fw_private"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_11:key_11{ + key-name = "hdcp22_rx_private"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_12:key_12{ + key-name = "hdcp22_rx_fw"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_13:key_13{ + key-name = "hdcp14_rx"; + key-device = "normal"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_14:key_14{ + key-name = "prpubkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_15:key_15{ + key-name = "prprivkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_16:key_16{ + key-name = "lcd"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_17:key_17{ + key-name = "lcd_extern"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_18:key_18{ + key-name = "backlight"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_19:key_19{ + key-name = "lcd_tcon"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_20:key_20{ + key-name = "attestationkeybox";// attestation key + key-device = "secure"; + key-permit = "read","write","del"; + }; + }; /* End unifykey */ + + amlvideo2_0 { + compatible = "amlogic, amlvideo2"; + dev_name = "amlvideo2"; + status = "okay"; + amlvideo2_id = <0>; + cma_mode = <1>; + }; + + amlvideo2_1 { + compatible = "amlogic, amlvideo2"; + dev_name = "amlvideo2"; + status = "okay"; + amlvideo2_id = <1>; + cma_mode = <1>; + }; + + hdmirx { + compatible = "amlogic, hdmirx_tl1"; + #address-cells=<1>; + #size-cells=<1>; + memory-region = <&hdmirx_emp_cma_reserved>; + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&hdmirx_a_mux &hdmirx_b_mux + &hdmirx_c_mux>; + repeat = <0>; + interrupts = <0 41 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clkc CLKID_HDMIRX_MODET_COMP>, + <&clkc CLKID_HDMIRX_CFG_COMP>, + <&clkc CLKID_HDMIRX_ACR_COMP>, + <&clkc CLKID_HDMIRX_METER_COMP>, + <&clkc CLKID_HDMIRX_AXI_COMP>, + <&xtal>, + <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_FCLK_DIV7>, + <&clkc CLKID_HDCP22_SKP_COMP>, + <&clkc CLKID_HDCP22_ESM_COMP>; + // <&clkc CLK_AUD_PLL2FS>, + // <&clkc CLK_AUD_PLL4FS>, + // <&clkc CLK_AUD_OUT>; + clock-names = "hdmirx_modet_clk", + "hdmirx_cfg_clk", + "hdmirx_acr_ref_clk", + "cts_hdmirx_meter_clk", + "cts_hdmi_axi_clk", + "xtal", + "fclk_div5", + "fclk_div7", + "hdcp_rx22_skp", + "hdcp_rx22_esm"; + // "hdmirx_aud_pll2fs", + // "hdmirx_aud_pll4f", + // "clk_aud_out"; + hdmirx_id = <0>; + en_4k_2_2k = <0>; + hpd_low_cec_off = <1>; + /* bit4: enable feature, bit3~0: port number */ + disable_port = <0x0>; + /* MAP_ADDR_MODULE_CBUS */ + /* MAP_ADDR_MODULE_HIU */ + /* MAP_ADDR_MODULE_HDMIRX_CAPB3 */ + /* MAP_ADDR_MODULE_SEC_AHB */ + /* MAP_ADDR_MODULE_SEC_AHB2 */ + /* MAP_ADDR_MODULE_APB4 */ + /* MAP_ADDR_MODULE_TOP */ + reg = < 0x0 0x0 0x0 0x0 + 0x0 0xff63C000 0x0 0x2000 + 0x0 0xffe0d000 0x0 0x2000 + 0x0 0x0 0x0 0x0 + 0x0 0x0 0x0 0x0 + 0x0 0x0 0x0 0x0 + 0x0 0xff610000 0x0 0xa000>; + }; + + aocec: aocec { + compatible = "amlogic, aocec-tl1"; + /*device_name = "aocec";*/ + status = "okay"; + vendor_name = "Amlogic"; /* Max Chars: 8 */ + /* Refer to the following URL at: + * http://standards.ieee.org/develop/regauth/oui/oui.txt + */ + vendor_id = <0x000000>; + product_desc = "TL1"; /* Max Chars: 16 */ + cec_osd_string = "AML_TV"; /* Max Chars: 14 */ + port_num = <3>; + ee_cec; + arc_port_mask = <0x2>; + interrupts = <0 205 1 + 0 199 1>; + interrupt-names = "hdmi_aocecb","hdmi_aocec"; + pinctrl-names = "default","hdmitx_aocecb","cec_pin_sleep"; + pinctrl-0=<&aoceca_mux>; + pinctrl-1=<&aocecb_mux>; + pinctrl-2=<&aoceca_mux>; + reg = <0x0 0xFF80023c 0x0 0x4 + 0x0 0xFF800000 0x0 0x400>; + reg-names = "ao_exit","ao"; + }; + + p_tsensor: p_tsensor@ff634800 { + compatible = "amlogic, r1p1-tsensor"; + status = "okay"; + reg = <0x0 0xff634800 0x0 0x50>, + <0x0 0xff800268 0x0 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 35 0>; + clocks = <&clkc CLKID_TS_CLK_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + d_tsensor: d_tsensor@ff634c00 { + compatible = "amlogic, r1p1-tsensor"; + status = "okay"; + reg = <0x0 0xff634c00 0x0 0x50>, + <0x0 0xff800230 0x0 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 36 0>; + clocks = <&clkc CLKID_TS_CLK_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + s_tsensor: s_tsensor@ff635000 { + compatible = "amlogic, r1p1-tsensor"; + status = "okay"; + reg = <0x0 0xff635000 0x0 0x50>, + <0x0 0xff80026c 0x0 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 38 0>; + clocks = <&clkc CLKID_TS_CLK_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + meson_cooldev: meson-cooldev@0 { + status = "okay"; + compatible = "amlogic, meson-cooldev"; + cooling_devices { + cpufreq_cool_cluster0 { + min_state = <1000000>; + dyn_coeff = <140>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "cpufreq_cool0"; + device_type = "cpufreq"; + }; + cpucore_cool_cluster0 { + min_state = <1>; + dyn_coeff = <0>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "cpucore_cool0"; + device_type = "cpucore"; + }; + gpufreq_cool { + min_state = <400>; + dyn_coeff = <140>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "gpufreq_cool0"; + device_type = "gpufreq"; + }; + gpucore_cool { + min_state = <1>; + dyn_coeff = <0>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "gpucore_cool0"; + device_type = "gpucore"; + }; + }; + cpufreq_cool0:cpufreq_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + cpucore_cool0:cpucore_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + gpufreq_cool0:gpufreq_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + gpucore_cool0:gpucore_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + };/*meson cooling devices end*/ + + thermal-zones { + pll_thermal: pll_thermal { + polling-delay = <1000>; + polling-delay-passive = <100>; + sustainable-power = <1322>; + thermal-sensors = <&p_tsensor 0>; + trips { + pswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + pcontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + phot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + pcritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + cooling-maps { + cpufreq_cooling_map { + trip = <&pcontrol>; + cooling-device = <&cpufreq_cool0 0 11>; + contribution = <1024>; + }; + cpucore_cooling_map { + trip = <&pcontrol>; + cooling-device = <&cpucore_cool0 0 4>; + contribution = <1024>; + }; + gpufreq_cooling_map { + trip = <&pcontrol>; + cooling-device = <&gpufreq_cool0 0 4>; + contribution = <1024>; + }; + }; + }; + ddr_thermal: ddr_thermal { + polling-delay = <2000>; + polling-delay-passive = <1000>; + sustainable-power = <1322>; + thermal-sensors = <&d_tsensor 1>; + trips { + dswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + dcontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + dhot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + dcritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + }; + sar_thermal: sar_thermal { + polling-delay = <2000>; + polling-delay-passive = <1000>; + sustainable-power = <1322>; + thermal-sensors = <&s_tsensor 2>; + trips { + sswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + scontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + shot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + scritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + }; + }; /*thermal zone end*/ + + /*DCDC for MP8756GD*/ + cpu_opp_table0: cpu_opp_table0 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <729000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <729000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <729000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <749000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <769000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <779000>; + }; + opp06 { + opp-hz = /bits/ 64 <1404000000>; + opp-microvolt = <789000>; + }; + opp07 { + opp-hz = /bits/ 64 <1500000000>; + opp-microvolt = <799000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <809000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <849000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <899000>; + }; + opp11 { + opp-hz = /bits/ 64 <1908000000>; + opp-microvolt = <949000>; + }; + }; + + cpufreq-meson { + compatible = "amlogic, cpufreq-meson"; + pinctrl-names = "default"; + pinctrl-0 = <&pwm_ao_d_pins3>; + status = "okay"; + }; + + tuner: tuner { + compatible = "amlogic, tuner"; + status = "okay"; + tuner_cur = <0>; /* default use tuner */ + tuner_num = <1>; /* tuner number, multi tuner support */ + tuner_name_0 = "mxl661_tuner"; + tuner_i2c_adap_0 = <&i2c0>; + tuner_i2c_addr_0 = <0x60>; + tuner_xtal_0 = <1>; /* 0: 16MHz, 1: 24MHz */ + tuner_xtal_mode_0 = <3>; + /* NO_SHARE_XTAL(0) + * SLAVE_XTAL_SHARE(3) + */ + tuner_xtal_cap_0 = <25>; /* when tuner_xtal_mode = 3, set 25 */ + }; + + atv-demod { + compatible = "amlogic, atv-demod"; + status = "okay"; + tuner = <&tuner>; + btsc_sap_mode = <1>; + /* pinctrl-names="atvdemod_agc_pins"; */ + /* pinctrl-0=<&atvdemod_agc_pins>; */ + reg = <0x0 0xff656000 0x0 0x2000 /* demod reg */ + 0x0 0xff63c000 0x0 0x2000 /* hiu reg */ + 0x0 0xff634000 0x0 0x2000 /* periphs reg */ + 0x0 0xff64a000 0x0 0x2000>; /* audio reg */ + reg_23cf = <0x88188832>; + /*default:0x88188832;r840 on haier:0x48188832*/ + }; + + bt-dev{ + compatible = "amlogic, bt-dev"; + status = "okay"; + gpio_reset = <&gpio GPIOC_13 GPIO_ACTIVE_HIGH>; + }; + + wifi{ + compatible = "amlogic, aml_wifi"; + status = "okay"; + interrupt_pin = <&gpio GPIOC_12 GPIO_ACTIVE_HIGH>; + irq_trigger_type = "GPIO_IRQ_LOW"; + dhd_static_buf; //dhd_static_buf support + power_on_pin = <&gpio GPIOC_11 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&pwm_b_pins1>; + pwm_config = <&wifi_pwm_conf>; + }; + + wifi_pwm_conf:wifi_pwm_conf{ + pwm_channel1_conf { + pwms = <&pwm_ab MESON_PWM_1 30541 0>; + duty-cycle = <15270>; + times = <8>; + }; + pwm_channel2_conf { + pwms = <&pwm_ab MESON_PWM_3 30500 0>; + duty-cycle = <15250>; + times = <12>; + }; + }; + + sd_emmc_b: sdio@ffe05000 { + status = "okay"; + compatible = "amlogic, meson-mmc-tl1"; + reg = <0x0 0xffe05000 0x0 0x800>; + interrupts = <0 190 4>; + + pinctrl-names = "sdio_all_pins", + "sdio_clk_cmd_pins"; + pinctrl-0 = <&sdio_all_pins>; + pinctrl-1 = <&sdio_clk_cmd_pins>; + + clocks = <&clkc CLKID_SD_EMMC_B>, + <&clkc CLKID_SD_EMMC_B_P0_COMP>, + <&clkc CLKID_FCLK_DIV2>, + <&clkc CLKID_FCLK_DIV5>, + <&xtal>; + clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + + bus-width = <4>; + cap-sd-highspeed; + cap-mmc-highspeed; + max-frequency = <100000000>; + disable-wp; + sdio { + pinname = "sdio"; + ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", /**ptm debug */ + "MMC_CAP_UHS_SDR12", + "MMC_CAP_UHS_SDR25", + "MMC_CAP_UHS_SDR50", + "MMC_CAP_UHS_SDR104", + "MMC_PM_KEEP_POWER", + "MMC_CAP_SDIO_IRQ"; + f_min = <400000>; + f_max = <200000000>; + max_req_size = <0x20000>; /**128KB*/ + card_type = <3>; + /* 3:sdio device(ie:sdio-wifi), + * 4:SD combo (IO+mem) card + */ + }; + }; +/* sd_emmc_b: sd@ffe05000 { + * status = "okay"; + * compatible = "amlogic, meson-mmc-tl1"; + * reg = <0xffe05000 0x800>; + * interrupts = <0 190 1>; + * + * pinctrl-names = "sd_all_pins", + * "sd_clk_cmd_pins", + * "sd_1bit_pins"; + * pinctrl-0 = <&sd_all_pins>; + * pinctrl-1 = <&sd_clk_cmd_pins>; + * pinctrl-2 = <&sd_1bit_pins>; + * + * clocks = <&clkc CLKID_SD_EMMC_B>, + * <&clkc CLKID_SD_EMMC_B_P0_COMP>, + * <&clkc CLKID_FCLK_DIV2>, + * <&clkc CLKID_FCLK_DIV5>, + * <&xtal>; + * clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + * + * bus-width = <4>; + * cap-sd-highspeed; + * cap-mmc-highspeed; + * max-frequency = <100000000>; + * disable-wp; + * sd { + * pinname = "sd"; + * ocr_avail = <0x200080>; + * caps = "MMC_CAP_4_BIT_DATA", + * "MMC_CAP_MMC_HIGHSPEED", + * "MMC_CAP_SD_HIGHSPEED"; + * f_min = <400000>; + * f_max = <200000000>; + * max_req_size = <0x20000>; + * no_sduart = <1>; + * gpio_dat3 = <&gpio GPIOC_3 GPIO_ACTIVE_HIGH>; + * jtag_pin = <&gpio GPIOC_0 GPIO_ACTIVE_HIGH>; + * gpio_cd = <&gpio GPIOC_10 GPIO_ACTIVE_HIGH>; + * card_type = <5>; + * }; + * }; + */ + +}; /* end of / */ + +&i2c0 { + status = "okay"; + clock-frequency = <300000>; + pinctrl-names="default"; + pinctrl-0=<&i2c0_dv_pins>; +}; + +&audiobus { + tdma:tdm@0 { + compatible = "amlogic, tl1-snd-tdma"; + #sound-dai-cells = <0>; + + dai-tdm-lane-slot-mask-in = <1 0>; + dai-tdm-lane-slot-mask-out = <1 1 1 1>; + dai-tdm-clk-sel = <0>; + + clocks = <&clkaudio CLKID_AUDIO_MCLK_A + &clkc CLKID_MPLL0 + &clkc CLKID_MPLL1 + &clkaudio CLKID_AUDIO_SPDIFOUT_A>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; + + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdma_mclk &tdmout_a>; + + /* + * 0: tdmout_a; + * 1: tdmout_b; + * 2: tdmout_c; + * 3: spdifout; + * 4: spdifout_b; + */ + samesource_sel = <3>; + + /* In for ACODEC_ADC */ + acodec_adc = <1>; + + status = "okay"; + + /* !!!For --TV platform-- ONLY */ + Channel_Mask { + /*i2s has 4 pins, 8channel, mux output*/ + Spdif_samesource_Channel_Mask = "i2s_2/3"; + }; + }; + + tdmb:tdm@1 { + compatible = "amlogic, tl1-snd-tdmb"; + #sound-dai-cells = <0>; + + dai-tdm-lane-slot-mask-in = <1 0 0 0>; + dai-tdm-lane-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <1>; + + clocks = <&clkaudio CLKID_AUDIO_MCLK_B + &clkc CLKID_MPLL1>; + clock-names = "mclk", "clk_srcpll"; + + status = "okay"; + }; + + tdmc:tdm@2 { + compatible = "amlogic, tl1-snd-tdmc"; + #sound-dai-cells = <0>; + + dai-tdm-lane-slot-mask-in = <1 0 0 0>; + dai-tdm-lane-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <2>; + + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmout_c &tdmin_c>; + + status = "okay"; + }; + + spdifa:spdif@0 { + compatible = "amlogic, tl1-snd-spdif-a"; + #sound-dai-cells = <0>; + + clocks = <&clkc CLKID_MPLL1 + &clkc CLKID_FCLK_DIV4 + &clkaudio CLKID_AUDIO_GATE_SPDIFIN + &clkaudio CLKID_AUDIO_GATE_SPDIFOUT_A + &clkaudio CLKID_AUDIO_SPDIFIN + &clkaudio CLKID_AUDIO_SPDIFOUT_A>; + clock-names = "sysclk", "fixed_clk", "gate_spdifin", + "gate_spdifout", "clk_spdifin", "clk_spdifout"; + + interrupts = + ; + interrupt-names = "irq_spdifin"; + + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; + pinctrl-0 = <&spdifout_a>; + pinctrl-1 = <&spdifout_a_mute>; + + /* + * whether do asrc for pcm and resample a or b + * if raw data, asrc is disabled automatically + * 0: "Disable", + * 1: "Enable:32K", + * 2: "Enable:44K", + * 3: "Enable:48K", + * 4: "Enable:88K", + * 5: "Enable:96K", + * 6: "Enable:176K", + * 7: "Enable:192K", + */ + asrc_id = <0>; + auto_asrc = <3>; + + status = "okay"; + }; + + spdifb:spdif@1 { + compatible = "amlogic, tl1-snd-spdif-b"; + #sound-dai-cells = <0>; + + clocks = <&clkc CLKID_MPLL0 /*CLKID_HIFI_PLL*/ + &clkaudio CLKID_AUDIO_GATE_SPDIFOUT_B + &clkaudio CLKID_AUDIO_SPDIFOUT_B>; + clock-names = "sysclk", + "gate_spdifout", "clk_spdifout"; + + status = "okay"; + }; + + pdm:pdm { + compatible = "amlogic, tl1-snd-pdm"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_PDM + &clkc CLKID_FCLK_DIV3 + &clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_PDMIN0 + &clkaudio CLKID_AUDIO_PDMIN1>; + clock-names = "gate", + "sysclk_srcpll", + "dclk_srcpll", + "pdm_dclk", + "pdm_sysclk"; + + pinctrl-names = "pdm_pins"; + pinctrl-0 = <&pdmin>; + + /* mode 0~4, defalut:1 */ + filter_mode = <1>; + + status = "okay"; + }; + + extn:extn { + compatible = "amlogic, snd-extn"; + #sound-dai-cells = <0>; + + interrupts = + ; + interrupt-names = "irq_frhdmirx"; + + status = "okay"; + }; + + aed:effect { + compatible = "amlogic, snd-effect-v2"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_EQDRC + &clkc CLKID_FCLK_DIV5 + &clkaudio CLKID_AUDIO_EQDRC>; + clock-names = "gate", "srcpll", "eqdrc"; + + /* + * 0:tdmout_a + * 1:tdmout_b + * 2:tdmout_c + * 3:spdifout + * 4:spdifout_b + */ + eqdrc_module = <0>; + /* max 0xf, each bit for one lane, usually one lane */ + lane_mask = <0x1>; + /* max 0xff, each bit for one channel */ + channel_mask = <0xff>; + + status = "okay"; + }; + + asrca: resample@0 { + compatible = "amlogic, tl1-resample-a"; + clocks = <&clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_MCLK_A + &clkaudio CLKID_AUDIO_RESAMPLE_A>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + /*same with toddr_src + * TDMIN_A, 0 + * TDMIN_B, 1 + * TDMIN_C, 2 + * SPDIFIN, 3 + * PDMIN, 4 + * NONE, + * TDMIN_LB, 6 + * LOOPBACK, 7 + * FRHDMIRX, 8 + */ + resample_module = <8>; + + status = "okay"; + }; + + asrcb: resample@1 { + compatible = "amlogic, tl1-resample-b"; + + clocks = <&clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_MCLK_F + &clkaudio CLKID_AUDIO_RESAMPLE_B>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + + /*same with toddr_src + * TDMIN_A, 0 + * TDMIN_B, 1 + * TDMIN_C, 2 + * SPDIFIN, 3 + * PDMIN, 4 + * NONE, + * TDMIN_LB, 6 + * LOOPBACK, 7 + */ + resample_module = <3>; + + status = "disabled"; + }; + +}; /* end of audiobus */ + +&pinctrl_periphs { + /* audio pin mux */ + + tdma_mclk: tdma_mclk { + mux { /* GPIOZ_0 */ + groups = "mclk0_z"; + function = "mclk0"; + }; + }; + + tdmout_a: tdmout_a { + mux { /* GPIOZ_1, GPIOZ_2, GPIOZ_3 */ + groups = "tdma_sclk_z", + "tdma_fs_z", + "tdma_dout0_z"; + function = "tdma_out"; + bias-pull-down; + }; + }; + + tdmin_a: tdmin_a { + mux { /* GPIOZ_9 */ + groups = "tdma_din2_z"; + function = "tdma_in"; + }; + }; + + tdmout_c: tdmout_c { + mux { /* GPIODV_7, GPIODV_8, GPIODV_9 */ + groups = "tdmc_sclk", + "tdmc_fs", + "tdmc_dout0"; + function = "tdmc_out"; + }; + }; + + tdmin_c: tdmin_c { + mux { /* GPIODV_10 */ + groups = "tdmc_din1"; + function = "tdmc_in"; + }; + }; + + spdifin_a: spdifin_a { + mux { /* GPIODV_5 */ + groups = "spdif_in"; + function = "spdif_in"; + }; + }; + + spdifout_a: spdifout_a { + mux { /* GPIODV_4 */ + groups = "spdif_out_dv4"; + function = "spdif_out"; + }; + }; + + spdifout_a_mute: spdifout_a_mute { + mux { /* GPIODV_4 */ + groups = "GPIODV_4"; + function = "gpio_periphs"; + }; + }; + + pdmin: pdmin { + mux { /* GPIOZ_7, GPIOZ_8, pdm_din2_z4 */ + groups = "pdm_dclk_z", + "pdm_din0_z", + "pdm_din2_z4"; + function = "pdm"; + }; + }; + + /*backlight*/ + bl_pwm_vs_on_pins:bl_pwm_vs_on_pin { + mux { + groups = "pwm_vs_z5"; + function = "pwm_vs"; + }; + }; + bl_pwm_off_pins:bl_pwm_off_pin { + mux { + groups = "GPIOZ_5"; + function = "gpio_periphs"; + output-low; + }; + }; + bl_pwm_combo_0_vs_on_pins:bl_pwm_combo_0_vs_on_pin { + mux { + groups = "pwm_vs_z5"; + function = "pwm_vs"; + }; + }; + bl_pwm_combo_1_vs_on_pins:bl_pwm_combo_1_vs_on_pin { + mux { + groups = "pwm_vs_z6"; + function = "pwm_vs"; + }; + }; + bl_pwm_combo_off_pins:bl_pwm_combo_off_pin { + mux { + groups = "GPIOZ_5", + "GPIOZ_6"; + function = "gpio_periphs"; + output-low; + }; + }; + +}; /* end of pinctrl_periphs */ + +&audio_data{ + status = "okay"; +}; + +&i2c2 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&i2c2_z_pins>; + clock-frequency = <400000>; + + tas5805: tas5805@36 { + compatible = "ti,tas5805"; + #sound-dai-cells = <0>; + codec_name = "tas5805"; + reg = <0x2d>; + status = "disable"; + }; + + ad82584f: ad82584f@62 { + compatible = "ESMT, ad82584f"; + #sound-dai-cells = <0>; + reg = <0x31>; + status = "okay"; + reset_pin = <&gpio_ao GPIOAO_6 0>; + }; + +}; + +&sd_emmc_c { + status = "okay"; + emmc { + caps = "MMC_CAP_8_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + "MMC_CAP_1_8V_DDR", + "MMC_CAP_HW_RESET", + "MMC_CAP_ERASE", + "MMC_CAP_CMD23", + "MMC_CAP_DRIVER_TYPE_D"; + caps2 = "MMC_CAP2_HS200", "MMC_CAP2_HS400"; + f_min = <400000>; + f_max = <198000000>; + }; +}; + + + +&spifc { + status = "disabled"; + spi-nor@0 { + cs_gpios = <&gpio BOOT_13 GPIO_ACTIVE_HIGH>; + }; +}; + +&slc_nand { + status = "disabled"; + plat-names = "bootloader", "nandnormal"; + plat-num = <2>; + plat-part-0 = <&bootloader>; + plat-part-1 = <&nandnormal>; + bootloader: bootloader{ + enable_pad = "ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <1>; + part_num = <0>; + rb_detect = <1>; + }; + nandnormal: nandnormal{ + enable_pad = "ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + plane_mode = "twoplane"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <2>; + part_num = <3>; + partition = <&nand_partitions>; + rb_detect = <1>; + }; + nand_partitions:nand_partition{ + /* + * if bl_mode is 1, tpl size was generate by + * fip_copies * fip_size which + * will not skip bad when calculating + * the partition size; + * + * if bl_mode is 0, + * tpl partition must be comment out. + */ + tpl{ + offset=<0x0 0x0>; + size=<0x0 0x0>; + }; + logo{ + offset=<0x0 0x0>; + size=<0x0 0x200000>; + }; + recovery{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + boot{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + system{ + offset=<0x0 0x0>; + size=<0x0 0x4000000>; + }; + data{ + offset=<0xffffffff 0xffffffff>; + size=<0x0 0x0>; + }; + }; +}; + +ðmac { + status = "okay"; + pinctrl-names = "internal_eth_pins"; + pinctrl-0 = <&internal_eth_pins>; + mc_val = <0x4be04>; + + internal_phy=<1>; +}; + +&uart_A { + status = "okay"; +}; + +&dwc3 { + status = "okay"; +}; + +&usb2_phy_v2 { + status = "okay"; + portnum = <3>; +}; + +&usb3_phy_v2 { + status = "okay"; + portnum = <0>; + otg = <0>; +}; + +&dwc2_a { + status = "okay"; + /** 0: normal, 1: otg+dwc3 host only, 2: otg+dwc3 device only*/ + controller-type = <1>; +}; + +&spicc0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&spicc0_pins_h>; + cs-gpios = <&gpio GPIOH_20 0>; +}; + +&meson_fb { + status = "okay"; + display_size_default = <1920 1080 1920 2160 32>; + mem_size = <0x00800000 0x1980000 0x100000 0x800000>; + logo_addr = "0x7f800000"; + mem_alloc = <0>; + pxp_mode = <0>; /** 0:normal mode 1:pxp mode */ +}; + +&pwm_AO_cd { + status = "okay"; +}; + +&saradc { + status = "okay"; +}; + +&i2c1 { + status = "okay"; + clock-frequency = <300000>; + pinctrl-names="default"; + pinctrl-0=<&i2c1_h_pins>; + + lcd_extern_i2c0: lcd_extern_i2c@0 { + compatible = "lcd_ext, i2c"; + dev_name = "i2c_T5800Q"; + reg = <0x1c>; + status = "okay"; + }; + + lcd_extern_i2c1: lcd_extern_i2c@1 { + compatible = "lcd_ext, i2c"; + dev_name = "i2c_ANX6862"; + reg = <0x20>; + status = "okay"; + }; + + lcd_extern_i2c2: lcd_extern_i2c@2 { + compatible = "lcd_ext, i2c"; + dev_name = "i2c_ANX7911"; + reg = <0x74>; + status = "okay"; + }; +}; + +&pwm_ab { + status = "okay"; +}; + +&pwm_cd { + status = "okay"; +}; + +&efuse { + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/amlogic/tm2_pxp.dts b/arch/arm64/boot/dts/amlogic/tm2_pxp.dts new file mode 100644 index 000000000000..defa536fe773 --- /dev/null +++ b/arch/arm64/boot/dts/amlogic/tm2_pxp.dts @@ -0,0 +1,1137 @@ +/* + * arch/arm/boot/dts/amlogic/tl1_pxp.dts + * + * Copyright (C) 2018 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +/dts-v1/; + +#include "mesontm2.dtsi" +#include "partition_mbox_normal_P_32.dtsi" +/*#include "mesontl1_skt-panel.dtsi"*/ + +/ { + model = "Amlogic TL1 PXP"; + amlogic-dt-id = "tl1_pxp"; + compatible = "amlogic, tl1_pxp"; + + aliases { + serial0 = &uart_AO; + i2c0 = &i2c0; + i2c1 = &i2c1; + i2c2 = &i2c2; + i2c3 = &i2c3; + i2c4 = &i2c_AO; + }; + + memory@00000000 { + device_type = "memory"; + linux,usable-memory = <0x0 0x0 0x0 0x80000000>; + }; + + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + /* global autoconfigured region for contiguous allocations */ + secmon_reserved: linux,secmon { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x400000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x05000000 0x0 0x400000>; + }; + + logo_reserved:linux,meson-fb { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x800000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x7f800000 0x0 0x800000>; + }; + + codec_mm_cma:linux,codec_mm_cma { + compatible = "shared-dma-pool"; + reusable; + /* ion_codec_mm max can alloc size 80M*/ + size = <0x0 0x13400000>; + alignment = <0x0 0x400000>; + linux,contiguous-region; + }; + + /* codec shared reserved */ + codec_mm_reserved:linux,codec_mm_reserved { + compatible = "amlogic, codec-mm-reserved"; + size = <0x0 0x0>; + alignment = <0x0 0x100000>; + //no-map; + }; + + ion_cma_reserved:linux,ion-dev { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x8000000>; + alignment = <0x0 0x400000>; + }; + + /* vdin0 CMA pool */ + //vdin0_cma_reserved:linux,vdin0_cma { + // compatible = "shared-dma-pool"; + // reusable; + /* 3840x2160x4x4 ~=128 M */ + // size = <0xc400000>; + // alignment = <0x400000>; + //}; + + /* vdin1 CMA pool */ + vdin1_cma_reserved:linux,vdin1_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16 M */ + size = <0x0 0x1400000>; + alignment = <0x0 0x400000>; + }; + + /*di CMA pool */ + di_cma_reserved:linux,di_cma { + compatible = "shared-dma-pool"; + reusable; + /* buffer_size = 3621952(yuv422 8bit) + * | 4736064(yuv422 10bit) + * | 4074560(yuv422 10bit full pack mode) + * 10x3621952=34.6M(0x23) support 8bit + * 10x4736064=45.2M(0x2e) support 12bit + * 10x4074560=40M(0x28) support 10bit + */ + size = <0x0 0x02800000>; + alignment = <0x0 0x400000>; + }; + + /* for hdmi rx emp use */ + hdmirx_emp_cma_reserved:linux,emp_cma { + compatible = "shared-dma-pool"; + /*linux,phandle = <5>;*/ + reusable; + /* 4M for emp to ddr */ + /* 32M for tmds to ddr */ + size = <0x0 0x2000000>; + alignment = <0x0 0x400000>; + /* alloc-ranges = <0x400000 0x2000000>; */ + }; + + /* POST PROCESS MANAGER */ + ppmgr_reserved:linux,ppmgr { + compatible = "amlogic, ppmgr_memory"; + size = <0x0 0x0>; + }; + + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x0>; + alignment = <0x0 0x0>; + linux,contiguous-region; + }; + }; /* end of reserved-memory */ + + codec_mm { + status = "disabled"; + compatible = "amlogic, codec, mm"; + memory-region = <&codec_mm_cma &codec_mm_reserved>; + }; + + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "disabled"; + }; + + ppmgr { + status = "disabled"; + compatible = "amlogic, ppmgr"; + memory-region = <&ppmgr_reserved>; + }; + + deinterlace { + compatible = "amlogic, deinterlace"; + + status = "disabled"; + /* 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>; + }; + + vout { + compatible = "amlogic, vout"; + status = "okay"; + fr_auto_policy = <0>; + }; + + pdm_codec:dummy { + #sound-dai-cells = <0>; + compatible = "amlogic, pdm_dummy_codec"; + status = "okay"; + }; + + dummy_codec:dummy { + #sound-dai-cells = <0>; + compatible = "amlogic, aml_dummy_codec"; + status = "okay"; + }; + + tl1_codec:codec { + #sound-dai-cells = <0>; + compatible = "amlogic, tl1_acodec"; + status = "disabled"; + reg = <0xff632000 0x1c>; + tdmout_index = <1>; + tdmin_index = <1>; + }; + + aml_dtv_demod { + compatible = "amlogic, ddemod-tl1"; + dev_name = "aml_dtv_demod"; + status = "okay"; + + //pinctrl-names="dtvdemod_agc"; + //pinctrl-0=<&dtvdemod_agc>; + + clocks = <&clkc CLKID_DAC_CLK>; + clock-names = "vdac_clk_gate"; + + reg = <0xff650000 0x4000 /*dtv demod base*/ + 0xff63c000 0x2000 /*hiu reg base*/ + 0xff800000 0x1000 /*io_aobus_base*/ + 0xffd01000 0x1000 /*reset*/ + >; + + /*move from dvbfe*/ + dtv_demod0_mem = <0>; // need move to aml_dtv_demod ? + spectrum = <1>; + cma_flag = <1>; + cma_mem_size = <8>; + //memory-region = <&demod_cma_reserved>;//<&demod_reserved>; + }; + + auge_sound { + compatible = "amlogic, tl1-sound-card"; + aml-audio-card,name = "AML-AUGESOUND"; + + aml-audio-card,dai-link@0 { + format = "dsp_a"; + mclk-fs = <512>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdma>; + frame-master = <&tdma>; + /* slave mode */ + /* + * bitclock-master = <&tdmacodec>; + * frame-master = <&tdmacodec>; + */ + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-pcm"; + tdmacpu: cpu { + sound-dai = <&tdma>; + dai-tdm-slot-tx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-rx-mask = + <1 1 1 1 1 1 1 1>; + dai-tdm-slot-num = <8>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <24576000>; + }; + tdmacodec: codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@1 { + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdmb>; + frame-master = <&tdmb>; + /* slave mode */ + //bitclock-master = <&tdmbcodec>; + //frame-master = <&tdmbcodec>; + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-i2s"; + cpu { + sound-dai = <&tdmb>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + /* + * dai-tdm-slot-tx-mask = + * <1 1 1 1 1 1 1 1>; + * dai-tdm-slot-rx-mask = + * <1 1 1 1 1 1 1 1>; + * dai-tdm-slot-num = <8>; + */ + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmbcodec: codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@2 { + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdmc>; + frame-master = <&tdmc>; + /* slave mode */ + //bitclock-master = <&tdmccodec>; + //frame-master = <&tdmccodec>; + /* suffix-name, sync with android audio hal used for */ + //suffix-name = "alsaPORT-tdm"; + cpu { + sound-dai = <&tdmc>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmccodec: codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@3 { + mclk-fs = <64>; + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-pdm"; + cpu { + sound-dai = <&pdm>; + }; + codec { + sound-dai = <&pdm_codec>; + }; + }; + + aml-audio-card,dai-link@4 { + mclk-fs = <128>; + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-spdif"; + cpu { + sound-dai = <&spdifa>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@5 { + mclk-fs = <128>; + cpu { + sound-dai = <&spdifb>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@6 { + mclk-fs = <256>; + cpu { + sound-dai = <&extn>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + + }; + /* Audio Related end */ + + tvafe_avin_detect { + compatible = "amlogic, tl1_tvafe_avin_detect"; + status = "okay"; + device_mask = <1>;/*bit0:ch1;bit1:ch2*/ + interrupts = <0 12 1>, + <0 13 1>; + }; + + + amlvecm { + compatible = "amlogic, vecm"; + dev_name = "aml_vecm"; + status = "okay"; + gamma_en = <1>;/*1:enabel ;0:disable*/ + wb_en = <1>;/*1:enabel ;0:disable*/ + cm_en = <1>;/*1:enabel ;0:disable*/ + wb_sel = <1>;/*1:mtx ;0:gainoff*/ + vlock_en = <1>;/*1:enable;0:disable*/ + vlock_mode = <0x4>; + /* vlock work mode: + *bit0:auto ENC + *bit1:auto PLL + *bit2:manual PLL + *bit3:manual ENC + *bit4:manual soft ENC + *bit5:manual MIX PLL ENC + */ + vlock_pll_m_limit = <1>; + vlock_line_limit = <3>; + }; + + amdolby_vision { + compatible = "amlogic, dolby_vision_tm2"; + dev_name = "aml_amdolby_vision_driver"; + status = "okay"; + tv_mode = <0>;/*1:enabel ;0:disable*/ + }; + + vdin@0 { + compatible = "amlogic, vdin"; + /*memory-region = <&vdin0_cma_reserved>;*/ + status = "disabled"; + /*bit0:(1:share with codec_mm;0:cma alone) + *bit8:(1:alloc in discontinus way;0:alone in continuous way) + */ + flag_cma = <0x101>; + /*MByte, if 10bit disable: 64M(YUV422), + *if 10bit enable: 64*1.5 = 96M(YUV422) + *if support 4K2K-YUV444-10bit-WR:3840*2160*4*4 ~= 128M + *if support 4K2K-YUV422-10bit-wr:3840*2160*3*4 ~= 96M + *if support 4K2K-YUV422-8BIT-WR:3840*2160*2*4 ~= 64M + *if support 1080p-YUV422-8BIT-WR:1920*1080*2*4 ~= 16M + */ + cma_size = <190>; + interrupts = <0 83 1>; + rdma-irq = <2>; + clocks = <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_VDIN_MEAS_COMP>; + clock-names = "fclk_div5", "cts_vdin_meas_clk"; + vdin_id = <0>; + /*vdin write mem color depth support: + * bit0:support 8bit + * bit1:support 9bit + * bit2:support 10bit + * bit3:support 12bit + * bit4:support yuv422 10bit full pack mode (from txl new add) + * bit8:use 8bit at 4k_50/60hz_10bit + * bit9:use 10bit at 4k_50/60hz_10bit + */ + tv_bit_mode = <0x215>; + /* afbce_bit_mode: (amlogic frame buff compression encoder) + * 0: normal mode, not use afbce + * 1: use afbce non-mmu mode + * 2: use afbce mmu mode + */ + afbce_bit_mode = <0>; + }; + + vdin@1 { + compatible = "amlogic, vdin"; + memory-region = <&vdin1_cma_reserved>; + status = "disabled"; + /*bit0:(1:share with codec_mm;0:cma alone) + *bit8:(1:alloc in discontinus way;0:alone in continuous way) + */ + flag_cma = <0>; + interrupts = <0 85 1>; + rdma-irq = <4>; + clocks = <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_VDIN_MEAS_COMP>; + clock-names = "fclk_div5", "cts_vdin_meas_clk"; + vdin_id = <1>; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + */ + tv_bit_mode = <0x15>; + }; + + hdmirx { + compatible = "amlogic, hdmirx_tl1"; + #address-cells=<1>; + #size-cells=<1>; + memory-region = <&hdmirx_emp_cma_reserved>; + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&hdmirx_a_mux &hdmirx_b_mux + &hdmirx_c_mux>; + repeat = <0>; + interrupts = <0 41 1>; + clocks = <&clkc CLKID_HDMIRX_MODET_COMP>, + <&clkc CLKID_HDMIRX_CFG_COMP>, + <&clkc CLKID_HDMIRX_ACR_COMP>, + <&clkc CLKID_HDMIRX_METER_COMP>, + <&clkc CLKID_HDMIRX_AXI_COMP>, + <&xtal>, + <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_FCLK_DIV7>, + <&clkc CLKID_HDCP22_SKP_COMP>, + <&clkc CLKID_HDCP22_ESM_COMP>; + // <&clkc CLK_AUD_PLL2FS>, + // <&clkc CLK_AUD_PLL4FS>, + // <&clkc CLK_AUD_OUT>; + clock-names = "hdmirx_modet_clk", + "hdmirx_cfg_clk", + "hdmirx_acr_ref_clk", + "cts_hdmirx_meter_clk", + "cts_hdmi_axi_clk", + "xtal", + "fclk_div5", + "fclk_div7", + "hdcp_rx22_skp", + "hdcp_rx22_esm"; + // "hdmirx_aud_pll2fs", + // "hdmirx_aud_pll4f", + // "clk_aud_out"; + hdmirx_id = <0>; + en_4k_2_2k = <0>; + hpd_low_cec_off = <1>; + /* bit4: enable feature, bit3~0: port number */ + disable_port = <0x0>; + /* MAP_ADDR_MODULE_CBUS */ + /* MAP_ADDR_MODULE_HIU */ + /* MAP_ADDR_MODULE_HDMIRX_CAPB3 */ + /* MAP_ADDR_MODULE_SEC_AHB */ + /* MAP_ADDR_MODULE_SEC_AHB2 */ + /* MAP_ADDR_MODULE_APB4 */ + /* MAP_ADDR_MODULE_TOP */ + reg = < 0x0 0x0 0x0 0x0 0x0 0xff63C000 0x0 0x2000 + 0x0 0xffe0d000 0x0 0x2000 + 0x0 0x0 0x0 0x0 + 0x0 0x0 0x0 0x0 + 0x0 0x0 0x0 0x0 + 0x0 0xff610000 0x0 0xa000>; + }; + + aocec: aocec { + compatible = "amlogic, aocec-tm2"; + /*device_name = "aocec";*/ + status = "okay"; + vendor_name = "Amlogic"; /* Max Chars: 8 */ + /* Refer to the following URL at: + * http://standards.ieee.org/develop/regauth/oui/oui.txt + */ + vendor_id = <0x000000>; + product_desc = "TM2"; /* Max Chars: 16 */ + cec_osd_string = "AML_TV"; /* Max Chars: 14 */ + port_num = <3>; + ee_cec; + /*cec_sel = <2>;*/ + output = <1>; /*output port number*/ + arc_port_mask = <0x2>; + interrupts = <0 205 1 + 0 199 1>; + interrupt-names = "hdmi_aocecb","hdmi_aocec"; + pinctrl-names = "default","hdmitx_aocecb","cec_pin_sleep"; + pinctrl-0=<&aoceca_mux>; + pinctrl-1=<&aocecb_mux>; + pinctrl-2=<&aoceca_mux>; + reg = <0x0 0xFF80023c 0x0 0x4 + 0x0 0xFF800000 0x0 0x400>; + reg-names = "ao_exit","ao"; + }; + + cpu_opp_table0: cpu_opp_table0 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <730000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <730000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <730000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <750000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <770000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <780000>; + }; + opp06 { + opp-hz = /bits/ 64 <1404000000>; + opp-microvolt = <790000>; + }; + opp07 { + opp-hz = /bits/ 64 <1500000000>; + opp-microvolt = <800000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <810000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <850000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <900000>; + }; + opp11 { + opp-hz = /bits/ 64 <1908000000>; + opp-microvolt = <950000>; + }; + }; + + cpufreq-meson { + compatible = "amlogic, cpufreq-meson"; + pinctrl-names = "default"; + pinctrl-0 = <&pwm_ao_d_pins3>; + status = "okay"; + }; + + tuner: tuner { + compatible = "amlogic, tuner"; + status = "okay"; + tuner_name = "mxl661_tuner"; + tuner_i2c_adap = <&i2c0>; + tuner_i2c_addr = <0x60>; + tuner_xtal = <1>; /* 0: 16MHz, 1: 24MHz */ + tuner_xtal_mode = <3>; + /* NO_SHARE_XTAL(0) + * SLAVE_XTAL_SHARE(3) + */ + tuner_xtal_cap = <25>; /* when tuner_xtal_mode = 3, set 25 */ + }; + + atv-demod { + compatible = "amlogic, atv-demod"; + status = "okay"; + tuner = <&tuner>; + btsc_sap_mode = <1>; + /* pinctrl-names="atvdemod_agc_pins"; */ + /* pinctrl-0=<&atvdemod_agc_pins>; */ + reg = <0xff656000 0x2000 /* demod reg */ + 0xff63c000 0x2000 /* hiu reg */ + 0xff634000 0x2000 /* periphs reg */ + 0xff64a000 0x2000>; /* audio reg */ + reg_23cf = <0x88188832>; + /*default:0x88188832;r840 on haier:0x48188832*/ + }; + + sd_emmc_b: sd@ffe05000 { + status = "disabled"; + compatible = "amlogic, meson-mmc-tl1"; + reg = <0x0 0xffe05000 0x0 0x800>; + interrupts = <0 190 1>; + + pinctrl-names = "sd_all_pins", + "sd_clk_cmd_pins", + "sd_1bit_pins"; + pinctrl-0 = <&sd_all_pins>; + pinctrl-1 = <&sd_clk_cmd_pins>; + pinctrl-2 = <&sd_1bit_pins>; + + clocks = <&clkc CLKID_SD_EMMC_B>, + <&clkc CLKID_SD_EMMC_B_P0_COMP>, + <&clkc CLKID_FCLK_DIV2>, + <&clkc CLKID_FCLK_DIV5>, + <&xtal>; + clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + + bus-width = <4>; + cap-sd-highspeed; + cap-mmc-highspeed; + max-frequency = <100000000>; + disable-wp; + sd { + pinname = "sd"; + ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE"; /**ptm debug */ + f_min = <400000>; + f_max = <200000000>; + max_req_size = <0x20000>; /**128KB*/ + no_sduart = <1>; + gpio_dat3 = <&gpio GPIOC_3 GPIO_ACTIVE_HIGH>; + jtag_pin = <&gpio GPIOC_0 GPIO_ACTIVE_HIGH>; + gpio_cd = <&gpio GPIOC_10 GPIO_ACTIVE_HIGH>; + card_type = <5>; + }; + }; +};/* end of / */ + + +&i2c0 { + status = "okay"; + clock-frequency = <300000>; + pinctrl-names="default"; + pinctrl-0=<&i2c0_dv_pins>; +}; + +&audiobus { + tdma:tdm@0 { + compatible = "amlogic, tl1-snd-tdma"; + #sound-dai-cells = <0>; + + dai-tdm-lane-slot-mask-in = <1 0>; + dai-tdm-lane-slot-mask-out = <1 0>; + dai-tdm-clk-sel = <0>; + + clocks = <&clkaudio CLKID_AUDIO_MCLK_A + &clkc CLKID_MPLL0>; + clock-names = "mclk", "clk_srcpll"; + + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdma_mclk &tdmout_a &tdmin_a>; + + status = "okay"; + }; + + tdmb:tdm@1 { + compatible = "amlogic, tl1-snd-tdmb"; + #sound-dai-cells = <0>; + + dai-tdm-lane-slot-mask-in = <1 0 0 0>; + dai-tdm-lane-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <1>; + + clocks = <&clkaudio CLKID_AUDIO_MCLK_B + &clkc CLKID_MPLL1>; + clock-names = "mclk", "clk_srcpll"; + + status = "okay"; + }; + + tdmc:tdm@2 { + compatible = "amlogic, tl1-snd-tdmc"; + #sound-dai-cells = <0>; + + dai-tdm-lane-slot-mask-in = <1 0 0 0>; + dai-tdm-lane-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <2>; + + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmout_c &tdmin_c>; + + status = "okay"; + }; + + spdifa:spdif@0 { + compatible = "amlogic, tl1-snd-spdif-a"; + #sound-dai-cells = <0>; + + clocks = <&clkc CLKID_MPLL0 + &clkc CLKID_FCLK_DIV4 + &clkaudio CLKID_AUDIO_GATE_SPDIFIN + &clkaudio CLKID_AUDIO_GATE_SPDIFOUT_A + &clkaudio CLKID_AUDIO_SPDIFIN + &clkaudio CLKID_AUDIO_SPDIFOUT_A>; + clock-names = "sysclk", "fixed_clk", "gate_spdifin", + "gate_spdifout", "clk_spdifin", "clk_spdifout"; + + interrupts = + ; + interrupt-names = "irq_spdifin"; + + pinctrl-names = "spdif_pins"; + pinctrl-0 = <&spdifout_a &spdifin_a>; + + /* + * whether do asrc for pcm and resample a or b + * if raw data, asrc is disabled automatically + * 0: "Disable", + * 1: "Enable:32K", + * 2: "Enable:44K", + * 3: "Enable:48K", + * 4: "Enable:88K", + * 5: "Enable:96K", + * 6: "Enable:176K", + * 7: "Enable:192K", + */ + asrc_id = <0>; + auto_asrc = <0>; + + status = "okay"; + }; + + spdifb:spdif@1 { + compatible = "amlogic, tl1-snd-spdif-b"; + #sound-dai-cells = <0>; + + clocks = <&clkc CLKID_MPLL0 /*CLKID_HIFI_PLL*/ + &clkaudio CLKID_AUDIO_GATE_SPDIFOUT_B + &clkaudio CLKID_AUDIO_SPDIFOUT_B>; + clock-names = "sysclk", + "gate_spdifout", "clk_spdifout"; + + status = "okay"; + }; + + pdm:pdm { + compatible = "amlogic, tl1-snd-pdm"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_PDM + &clkc CLKID_FCLK_DIV3 + &clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_PDMIN0 + &clkaudio CLKID_AUDIO_PDMIN1>; + clock-names = "gate", + "sysclk_srcpll", + "dclk_srcpll", + "pdm_dclk", + "pdm_sysclk"; + + pinctrl-names = "pdm_pins"; + pinctrl-0 = <&pdmin>; + + /* mode 0~4, defalut:1 */ + filter_mode = <1>; + + status = "okay"; + }; + + extn:extn { + compatible = "amlogic, snd-extn"; + #sound-dai-cells = <0>; + + interrupts = + ; + interrupt-names = "irq_frhdmirx"; + + status = "okay"; + }; + + aed:effect { + compatible = "amlogic, snd-effect-v2"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_EQDRC + &clkc CLKID_FCLK_DIV5 + &clkaudio CLKID_AUDIO_EQDRC>; + clock-names = "gate", "clk_srcpll", "eqdrc"; + + eq_enable = <1>; + multiband_drc_enable = <0>; + fullband_drc_enable = <0>; + /* + * 0:tdmout_a + * 1:tdmout_b + * 2:tdmout_c + * 3:spdifout + * 4:spdifout_b + */ + eqdrc_module = <1>; + /* max 0xf, each bit for one lane, usually one lane */ + lane_mask = <0x1>; + /* max 0xff, each bit for one channel */ + channel_mask = <0x3>; + + status = "disabled"; + }; + + asrca: resample@0 { + compatible = "amlogic, tl1-resample-a"; + clocks = <&clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_MCLK_F + &clkaudio CLKID_AUDIO_RESAMPLE_A>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + /*same with toddr_src + * TDMIN_A, 0 + * TDMIN_B, 1 + * TDMIN_C, 2 + * SPDIFIN, 3 + * PDMIN, 4 + * NONE, + * TDMIN_LB, 6 + * LOOPBACK, 7 + */ + resample_module = <3>; + + status = "disabled"; + }; + + asrcb: resample@1 { + compatible = "amlogic, tl1-resample-b"; + + clocks = <&clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_MCLK_F + &clkaudio CLKID_AUDIO_RESAMPLE_B>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + + /*same with toddr_src + * TDMIN_A, 0 + * TDMIN_B, 1 + * TDMIN_C, 2 + * SPDIFIN, 3 + * PDMIN, 4 + * NONE, + * TDMIN_LB, 6 + * LOOPBACK, 7 + */ + resample_module = <3>; + + status = "disabled"; + }; + +}; /* end of audiobus */ +&pinctrl_periphs { + /* audio pin mux */ + + tdma_mclk: tdma_mclk { + mux { /* GPIOZ_0 */ + groups = "mclk0_z"; + function = "mclk0"; + }; + }; + + tdmout_a: tdmout_a { + mux { /* GPIOZ_1, GPIOZ_2, GPIOZ_3, GPIOZ_5, GPIOZ_6 */ + groups = "tdma_sclk_z", + "tdma_fs_z", + "tdma_dout0_z", + "tdma_dout2_z", + "tdma_dout3_z"; + function = "tdma_out"; + }; + }; + + tdmin_a: tdmin_a { + mux { /* GPIOZ_9 */ + groups = "tdma_din2_z"; + function = "tdma_in"; + }; + }; + + tdmout_c: tdmout_c { + mux { /* GPIODV_7, GPIODV_8, GPIODV_9 */ + groups = "tdmc_sclk", + "tdmc_fs", + "tdmc_dout0"; + function = "tdmc_out"; + }; + }; + + tdmin_c: tdmin_c { + mux { /* GPIODV_10 */ + groups = "tdmc_din1"; + function = "tdmc_in"; + }; + }; + + spdifin_a: spdifin_a { + mux { /* GPIODV_5 */ + groups = "spdif_in"; + function = "spdif_in"; + }; + }; + + spdifout_a: spdifout_a { + mux { /* GPIODV_4 */ + groups = "spdif_out_dv4"; + function = "spdif_out"; + }; + }; + + pdmin: pdmin { + mux { /* GPIOZ_7, GPIOZ_8*/ + groups = "pdm_dclk_z", + "pdm_din0_z"; + function = "pdm"; + }; + }; + + +}; /* end of pinctrl_periphs */ + +&pinctrl_aobus { + spdifout: spdifout { + mux { /* gpiao_10 */ + groups = "spdif_out_ao"; + function = "spdif_out_ao"; + }; + }; +}; /* end of pinctrl_aobus */ + +&sd_emmc_b { + status = "okay"; + sd { + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE"; /**ptm debug */ + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&spifc { + status = "disabled"; + spi-nor@0 { + cs_gpios = <&gpio BOOT_13 GPIO_ACTIVE_HIGH>; + }; +}; + +&slc_nand { + status = "disabled"; + plat-names = "bootloader", "nandnormal"; + plat-num = <2>; + plat-part-0 = <&bootloader>; + plat-part-1 = <&nandnormal>; + bootloader: bootloader{ + enable_pad = "ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <1>; + part_num = <0>; + rb_detect = <1>; + }; + nandnormal: nandnormal{ + enable_pad = "ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + plane_mode = "twoplane"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <2>; + part_num = <3>; + partition = <&nand_partitions>; + rb_detect = <1>; + }; + nand_partitions:nand_partition{ + /* + * if bl_mode is 1, tpl size was generate by + * fip_copies * fip_size which + * will not skip bad when calculating + * the partition size; + * + * if bl_mode is 0, + * tpl partition must be comment out. + */ + tpl{ + offset=<0x0 0x0>; + size=<0x0 0x0>; + }; + logo{ + offset=<0x0 0x0>; + size=<0x0 0x200000>; + }; + recovery{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + boot{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + system{ + offset=<0x0 0x0>; + size=<0x0 0x4000000>; + }; + data{ + offset=<0xffffffff 0xffffffff>; + size=<0x0 0x0>; + }; + }; +}; + +&dwc3 { + status = "disabled"; +}; + +&usb2_phy_v2 { + status = "disabled"; + portnum = <3>; +}; + +&usb3_phy_v2 { + status = "disabled"; + portnum = <0>; + otg = <0>; +}; + +&dwc2_a { + status = "disabled"; + /** 0: normal, 1: otg+dwc3 host only, 2: otg+dwc3 device only*/ + controller-type = <1>; +}; + +&spicc0 { + status = "disabled"; + pinctrl-names = "default"; + pinctrl-0 = <&spicc0_pins_h>; + cs-gpios = <&gpio GPIOH_20 0>; +}; + +&meson_fb { + status = "okay"; + display_size_default = <1920 1080 1920 2160 32>; + mem_size = <0x00800000 0x1980000 0x100000 0x100000 0x800000>; + logo_addr = "0x7f800000"; + mem_alloc = <1>; + pxp_mode = <1>; /** 0:normal mode 1:pxp mode */ +}; + +&pwm_AO_cd { + status = "disabled"; +}; + +&efuse { + status = "disabled"; +}; diff --git a/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts b/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts new file mode 100644 index 000000000000..105cc544cf9d --- /dev/null +++ b/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts @@ -0,0 +1,1984 @@ +/* + * arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +/dts-v1/; + +#include "mesontm2.dtsi" +#include "partition_mbox_normal.dtsi" + +/ { + model = "Amlogic TM2 T962E2 AB311"; + amlogic-dt-id = "tm2_t962E2_ab311"; + compatible = "amlogic, tm2_t962e2_ab311"; + + aliases { + serial0 = &uart_AO; + serial1 = &uart_A; + serial2 = &uart_B; + serial3 = &uart_C; + serial4 = &uart_AO_B; + tsensor0 = &p_tsensor; + tsensor1 = &d_tsensor; + tsensor2 = &s_tsensor; + i2c0 = &i2c0; + i2c1 = &i2c1; + i2c2 = &i2c2; + i2c3 = &i2c3; + i2c4 = &i2c_AO; + }; + + memory@00000000 { + device_type = "memory"; + linux,usable-memory = <0x0 0x0 0x0 0x80000000>; + }; + + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + /* global autoconfigured region for contiguous allocations */ + ramoops@0x07400000 { + compatible = "ramoops"; + reg = <0x0 0x07400000 0x0 0x00100000>; + record-size = <0x8000>; + console-size = <0x8000>; + ftrace-size = <0x20000>; + }; + + secmon_reserved: linux,secmon { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x400000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x05000000 0x0 0x400000>; + }; + + logo_reserved:linux,meson-fb { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x800000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x7f800000 0x0 0x800000>; + }; + + lcd_tcon_reserved:linux,lcd_tcon { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0xc00000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x7ec00000 0x0 0xc00000>; + }; + + codec_mm_cma:linux,codec_mm_cma { + compatible = "shared-dma-pool"; + reusable; + /* ion_codec_mm max can alloc size 80M*/ + size = <0x0 0x13400000>; + alignment = <0x0 0x400000>; + linux,contiguous-region; + }; + + /* codec shared reserved */ + codec_mm_reserved:linux,codec_mm_reserved { + compatible = "amlogic, codec-mm-reserved"; + size = <0x0 0x0>; + alignment = <0x0 0x100000>; + //no-map; + }; + + ion_cma_reserved:linux,ion-dev { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x2000000>; + alignment = <0x0 0x400000>; + }; + + /* vdin0 CMA pool */ + //vdin0_cma_reserved:linux,vdin0_cma { + // compatible = "shared-dma-pool"; + // reusable; + /* 3840x2160x4x4 ~=128 M */ + // size = <0x0 0xc400000>; + // alignment = <0x0 0x400000>; + //}; + + /* vdin1 CMA pool */ + vdin1_cma_reserved:linux,vdin1_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16 M */ + size = <0x0 0x1400000>; + alignment = <0x0 0x400000>; + }; + + /*demod_reserved:linux,demod { + * compatible = "amlogic, demod-mem"; + * size = <0x0 0x800000>; //8M //100m 0x6400000 + * alloc-ranges = <0x0 0x0 0x0 0x30000000>; + * //multi-use; + * //no-map; + *}; + */ + + demod_cma_reserved:linux,demod_cma { + compatible = "shared-dma-pool"; + reusable; + /* 8M */ + size = <0x0 0x0800000>; + alignment = <0x0 0x400000>; + }; + + /*di CMA pool */ + di_cma_reserved:linux,di_cma { + compatible = "shared-dma-pool"; + reusable; + /* buffer_size = 3621952(yuv422 8bit) + * | 4736064(yuv422 10bit) + * | 4074560(yuv422 10bit full pack mode) + * 10x3621952=34.6M(0x23) support 8bit + * 10x4736064=45.2M(0x2e) support 12bit + * 10x4074560=40M(0x28) support 10bit + */ + size = <0x0 0x02800000>; + alignment = <0x0 0x400000>; + }; + + /* for hdmi rx emp use */ + hdmirx_emp_cma_reserved:linux,emp_cma { + compatible = "shared-dma-pool"; + /*linux,phandle = <5>;*/ + reusable; + /* 4M for emp to ddr */ + /* 32M for tmds to ddr */ + size = <0x0 0x2000000>; + alignment = <0x0 0x400000>; + }; + + /* POST PROCESS MANAGER */ + ppmgr_reserved:linux,ppmgr { + compatible = "amlogic, ppmgr_memory"; + size = <0x0 0x0>; + }; + + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x0>; + alignment = <0x0 0x0>; + linux,contiguous-region; + }; + }; /* end of reserved-memory */ + galcore { + status = "okay"; + }; + codec_mm { + compatible = "amlogic, codec, mm"; + status = "okay"; + memory-region = <&codec_mm_cma &codec_mm_reserved>; + }; + + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + + ppmgr { + compatible = "amlogic, ppmgr"; + memory-region = <&ppmgr_reserved>; + status = "okay"; + }; + + deinterlace { + compatible = "amlogic, deinterlace"; + status = "okay"; + /* 0:use reserved; 1:use cma; 2:use cma as reserved */ + flag_cma = <1>; + //memory-region = <&di_reserved>; + memory-region = <&di_cma_reserved>; + interrupts = <0 46 1 + 0 40 1>; + interrupt-names = "pre_irq", "post_irq"; + clocks = <&clkc CLKID_VPU_CLKB_TMP_COMP>, + <&clkc CLKID_VPU_CLKB_COMP>; + clock-names = "vpu_clkb_tmp_composite", + "vpu_clkb_composite"; + clock-range = <334 667>; + /* buffer-size = <3621952>;(yuv422 8bit) */ + buffer-size = <4074560>;/*yuv422 fullpack*/ + /* reserve-iomap = "true"; */ + /* if enable nr10bit, set nr10bit-support to 1 */ + post-wr-support = <1>; + nr10bit-support = <1>; + nrds-enable = <1>; + pps-enable = <1>; + }; + + vout { + compatible = "amlogic, vout"; + status = "okay"; + fr_auto_policy = <0>; + }; + + /* Audio Related start */ + pdm_codec:dummy { + #sound-dai-cells = <0>; + compatible = "amlogic, pdm_dummy_codec"; + status = "okay"; + }; + + dummy_codec:dummy { + #sound-dai-cells = <0>; + compatible = "amlogic, aml_dummy_codec"; + status = "okay"; + }; + + tl1_codec:codec { + #sound-dai-cells = <0>; + compatible = "amlogic, tl1_acodec"; + status = "okay"; + reg = <0x0 0xff632000 0x0 0x1c>; + tdmout_index = <0>; + tdmin_index = <0>; + dat1_ch_sel = <1>; + }; + + aml_dtv_demod { + compatible = "amlogic, ddemod-tl1"; + dev_name = "aml_dtv_demod"; + status = "okay"; + + //pinctrl-names="dtvdemod_agc"; + //pinctrl-0=<&dtvdemod_agc>; + + clocks = <&clkc CLKID_DAC_CLK>; + clock-names = "vdac_clk_gate"; + + reg = <0x0 0xff650000 0x0 0x4000 /*dtv demod base*/ + 0x0 0xff63c000 0x0 0x2000 /*hiu reg base*/ + 0x0 0xff800000 0x0 0x1000 /*io_aobus_base*/ + 0x0 0xffd01000 0x0 0x1000 /*reset*/ + >; + + dtv_demod0_mem = <0>; // need move to aml_dtv_demod ? + spectrum = <1>; + cma_flag = <1>; + cma_mem_size = <8>; + memory-region = <&demod_cma_reserved>;//<&demod_reserved>; + }; + + auge_sound { + compatible = "amlogic, tm2-sound-card"; + aml-audio-card,name = "AML-AUGESOUND"; + + avout_mute-gpios = <&gpio GPIODV_3 GPIO_ACTIVE_HIGH>; + + aml-audio-card,dai-link@0 { + format = "i2s"; + mclk-fs = <256>; + continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdma>; + frame-master = <&tdma>; + /* slave mode */ + /* + * bitclock-master = <&tdmacodec>; + * frame-master = <&tdmacodec>; + */ + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-i2s"; + tdmacpu: cpu { + sound-dai = <&tdma>; + dai-tdm-slot-tx-mask = + <1 1>; + dai-tdm-slot-rx-mask = + <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmacodec: codec { + //sound-dai = <&dummy_codec>; + prefix-names = "AMP", "AMP1"; + sound-dai = <&ad82584f &ad82584f1 &tl1_codec>; + }; + }; + + aml-audio-card,dai-link@1 { + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdmb>; + frame-master = <&tdmb>; + /* slave mode */ + //bitclock-master = <&tdmbcodec>; + //frame-master = <&tdmbcodec>; + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-pcm"; + cpu { + sound-dai = <&tdmb>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + /* + * dai-tdm-slot-tx-mask = + * <1 1 1 1 1 1 1 1>; + * dai-tdm-slot-rx-mask = + * <1 1 1 1 1 1 1 1>; + * dai-tdm-slot-num = <8>; + */ + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmbcodec: codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@2 { + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdmc>; + frame-master = <&tdmc>; + /* slave mode */ + //bitclock-master = <&tdmccodec>; + //frame-master = <&tdmccodec>; + /* suffix-name, sync with android audio hal used for */ + //suffix-name = "alsaPORT-tdm"; + cpu { + sound-dai = <&tdmc>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmccodec: codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@3 { + mclk-fs = <64>; + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-pdm"; + cpu { + sound-dai = <&pdm>; + }; + codec { + sound-dai = <&pdm_codec>; + }; + }; + + aml-audio-card,dai-link@4 { + mclk-fs = <128>; + continuous-clock; + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-spdif"; + cpu { + sound-dai = <&spdifa>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@5 { + mclk-fs = <128>; + suffix-name = "alsaPORT-spdifb"; + cpu { + sound-dai = <&spdifb>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@6 { + mclk-fs = <256>; + suffix-name = "alsaPORT-tv"; + cpu { + sound-dai = <&extn>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@7 { + mclk-fs = <256>; + suffix-name = "alsaPORT-earc"; + cpu { + sound-dai = <&earc>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + }; + /* Audio Related end */ + + dvb { + compatible = "amlogic, dvb"; + status = "okay"; + fe0_mode = "internal"; + fe0_tuner = <&tuner>; + + /*"parallel","serial","disable"*/ + ts2 = "parallel"; + ts2_control = <0>; + ts2_invert = <0>; + interrupts = <0 23 1 + 0 5 1 + 0 53 1 + 0 19 1 + 0 25 1 + 0 17 1>; + interrupt-names = "demux0_irq", + "demux1_irq", + "demux2_irq", + "dvr0_irq", + "dvr1_irq", + "dvr2_irq"; + clocks = <&clkc CLKID_DEMUX + &clkc CLKID_ASYNC_FIFO + &clkc CLKID_AHB_ARB0 +/* &clkc CLKID_DOS_PARSER>;*/ + &clkc CLKID_U_PARSER>; + clock-names = "demux", "asyncfifo", "ahbarb0", "uparsertop"; + }; + + tvafe_avin_detect { + compatible = "amlogic, tl1_tvafe_avin_detect"; + status = "okay"; + device_mask = <1>;/*bit0:ch1;bit1:ch2*/ + interrupts = <0 12 1>, + <0 13 1>; + }; + + amlvecm { + compatible = "amlogic, vecm"; + dev_name = "aml_vecm"; + status = "okay"; + gamma_en = <1>;/*1:enabel ;0:disable*/ + wb_en = <1>;/*1:enabel ;0:disable*/ + cm_en = <0>;/*1:enabel ;0:disable*/ + wb_sel = <1>;/*1:mtx ;0:gainoff*/ + vlock_en = <1>;/*1:enable;0:disable*/ + vlock_mode = <0x4>; + /* vlock work mode: + *bit0:auto ENC + *bit1:auto PLL + *bit2:manual PLL + *bit3:manual ENC + *bit4:manual soft ENC + *bit5:manual MIX PLL ENC + */ + vlock_pll_m_limit = <1>; + vlock_line_limit = <3>; + }; + + amdolby_vision { + compatible = "amlogic, dolby_vision_tm2"; + dev_name = "aml_amdolby_vision_driver"; + status = "okay"; + tv_mode = <0>;/*1:enabel ;0:disable*/ + }; + + vdin@0 { + compatible = "amlogic, vdin"; + /*memory-region = <&vdin0_cma_reserved>;*/ + status = "okay"; + /*bit0:(1:share with codec_mm;0:cma alone) + *bit8:(1:alloc in discontinus way;0:alone in continuous way) + */ + flag_cma = <0x101>; + /*MByte, if 10bit disable: 64M(YUV422), + *if 10bit enable: 64*1.5 = 96M(YUV422) + *if support 4K2K-YUV444-10bit-WR:3840*2160*4*4 ~= 128M + *if support 4K2K-YUV422-10bit-wr:3840*2160*3*4 ~= 96M + *if support 4K2K-YUV422-8BIT-WR:3840*2160*2*4 ~= 64M + *if support 1080p-YUV422-8BIT-WR:1920*1080*2*4 ~= 16M + */ + cma_size = <160>; + interrupts = <0 83 1>; + rdma-irq = <2>; + clocks = <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_VDIN_MEAS_COMP>; + clock-names = "fclk_div5", "cts_vdin_meas_clk"; + vdin_id = <0>; + /*vdin write mem color depth support: + * bit0:support 8bit + * bit1:support 9bit + * bit2:support 10bit + * bit3:support 12bit + * bit4:support yuv422 10bit full pack mode (from txl new add) + * bit8:use 8bit at 4k_50/60hz_10bit + * bit9:use 10bit at 4k_50/60hz_10bit + */ + tv_bit_mode = <0x215>; + /* afbce_bit_mode: (amlogic frame buff compression encoder) + * bit 0~3: + * 0 -- normal mode, not use afbce + * 1 -- use afbce non-mmu mode + * 2 -- use afbce mmu mode + * bit 4: + * 0 -- afbce compression-lossy disable + * 1 -- afbce compression-lossy enable + */ + afbce_bit_mode = <0x0>; + }; + + vdin@1 { + compatible = "amlogic, vdin"; + memory-region = <&vdin1_cma_reserved>; + status = "okay"; + /*bit0:(1:share with codec_mm;0:cma alone) + *bit8:(1:alloc in discontinus way;0:alone in continuous way) + */ + flag_cma = <0>; + interrupts = <0 85 1>; + rdma-irq = <4>; + clocks = <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_VDIN_MEAS_COMP>; + clock-names = "fclk_div5", "cts_vdin_meas_clk"; + vdin_id = <1>; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + */ + tv_bit_mode = <0x15>; + }; + + tvafe { + compatible = "amlogic, tvafe-tl1"; + /*memory-region = <&tvafe_cma_reserved>;*/ + status = "okay"; + flag_cma = <1>;/*1:share with codec_mm;0:cma alone*/ + cma_size = <5>;/*MByte*/ + reg = <0x0 0xff654000 0x0 0x2000>;/*tvafe reg base*/ + reserve-iomap = "true"; + tvafe_id = <0>; + //pinctrl-names = "default"; + /*!!particular sequence, no more and no less!!!*/ + tvafe_pin_mux = < + 3 /* TVAFE_CVBS_IN2, CVBS_IN0 = 0 */ + 1 /* TVAFE_CVBS_IN0, CVBS_IN1 */ + 2 /* TVAFE_CVBS_IN1, CVBS_IN2 */ + 4 /* TVAFE_CVBS_IN3, CVBS_IN3 */ + >; + clocks = <&clkc CLKID_DAC_CLK>; + clock-names = "vdac_clk_gate"; + }; + + vbi { + compatible = "amlogic, vbi"; + status = "okay"; + interrupts = <0 83 1>; + }; + + cvbsout { + compatible = "amlogic, cvbsout-tl1"; + status = "disabled"; + clocks = <&clkc CLKID_VCLK2_ENCI + &clkc CLKID_VCLK2_VENCI0 + &clkc CLKID_VCLK2_VENCI1 + &clkc CLKID_DAC_CLK>; + clock-names = "venci_top_gate", + "venci_0_gate", + "venci_1_gate", + "vdac_clk_gate"; + /* clk path */ + /* 0:vid_pll vid2_clk */ + /* 1:gp0_pll vid2_clk */ + /* 2:vid_pll vid1_clk */ + /* 3:gp0_pll vid1_clk */ + clk_path = <0>; + + /* performance: reg_address, reg_value */ + /* tl1 */ + performance = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x8080 + 0x1b05 0xfd + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + performance_sarft = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x0 + 0x1b05 0x9 + 0x1c59 0xfc48 + 0xffff 0x0>; /* ending flag */ + performance_revB_telecom = <0x1bf0 0x9 + 0x1b56 0x546 + 0x1b12 0x8080 + 0x1b05 0x9 + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + }; + + /* for external keypad */ + adc_keypad { + compatible = "amlogic, adc_keypad"; + status = "okay"; + key_name = "power","up","down","enter","left","right","home"; + key_num = <7>; + io-channels = <&saradc SARADC_CH2>,<&saradc SARADC_CH3>; + io-channel-names = "key-chan-2", "key-chan-3"; + key_chan = ; + key_code = <116 103 108 28 105 106 102>; + key_val = <0 143 266 389 512 143 266>; //val=voltage/1800mV*1023 + key_tolerance = <40 40 40 40 40 40 40>; +}; + + unifykey { + compatible = "amlogic, unifykey"; + status = "okay"; + + unifykey-num = <21>; + unifykey-index-0 = <&keysn_0>; + unifykey-index-1 = <&keysn_1>; + unifykey-index-2 = <&keysn_2>; + unifykey-index-3 = <&keysn_3>; + unifykey-index-4 = <&keysn_4>; + unifykey-index-5 = <&keysn_5>; + unifykey-index-6 = <&keysn_6>; + unifykey-index-7 = <&keysn_7>; + unifykey-index-8 = <&keysn_8>; + unifykey-index-9 = <&keysn_9>; + unifykey-index-10= <&keysn_10>; + unifykey-index-11 = <&keysn_11>; + unifykey-index-12 = <&keysn_12>; + unifykey-index-13 = <&keysn_13>; + unifykey-index-14 = <&keysn_14>; + unifykey-index-15 = <&keysn_15>; + unifykey-index-16 = <&keysn_16>; + unifykey-index-17 = <&keysn_17>; + unifykey-index-18 = <&keysn_18>; + unifykey-index-19 = <&keysn_19>; + unifykey-index-20 = <&keysn_20>; + + keysn_0: key_0{ + key-name = "usid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_1:key_1{ + key-name = "mac"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_2:key_2{ + key-name = "hdcp"; + key-device = "secure"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_3:key_3{ + key-name = "secure_boot_set"; + key-device = "efuse"; + key-permit = "write"; + }; + keysn_4:key_4{ + key-name = "mac_bt"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_5:key_5{ + key-name = "mac_wifi"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_6:key_6{ + key-name = "hdcp2_tx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_7:key_7{ + key-name = "hdcp2_rx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_8:key_8{ + key-name = "widevinekeybox"; + key-device = "secure"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_9:key_9{ + key-name = "deviceid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_10:key_10{ + key-name = "hdcp22_fw_private"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_11:key_11{ + key-name = "hdcp22_rx_private"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_12:key_12{ + key-name = "hdcp22_rx_fw"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_13:key_13{ + key-name = "hdcp14_rx"; + key-device = "normal"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_14:key_14{ + key-name = "prpubkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_15:key_15{ + key-name = "prprivkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_16:key_16{ + key-name = "lcd"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_17:key_17{ + key-name = "lcd_extern"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_18:key_18{ + key-name = "backlight"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_19:key_19{ + key-name = "lcd_tcon"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_20:key_20{ + key-name = "attestationkeybox";// attestation key + key-device = "secure"; + key-permit = "read","write","del"; + }; + }; /* End unifykey */ + + amlvideo2_0 { + compatible = "amlogic, amlvideo2"; + dev_name = "amlvideo2"; + status = "okay"; + amlvideo2_id = <0>; + cma_mode = <1>; + }; + + amlvideo2_1 { + compatible = "amlogic, amlvideo2"; + dev_name = "amlvideo2"; + status = "okay"; + amlvideo2_id = <1>; + cma_mode = <1>; + }; + + hdmirx { + compatible = "amlogic, hdmirx_tl1"; + #address-cells=<1>; + #size-cells=<1>; + memory-region = <&hdmirx_emp_cma_reserved>; + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&hdmirx_a_mux &hdmirx_b_mux + &hdmirx_c_mux>; + repeat = <0>; + interrupts = <0 41 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clkc CLKID_HDMIRX_MODET_COMP>, + <&clkc CLKID_HDMIRX_CFG_COMP>, + <&clkc CLKID_HDMIRX_ACR_COMP>, + <&clkc CLKID_HDMIRX_METER_COMP>, + <&clkc CLKID_HDMIRX_AXI_COMP>, + <&xtal>, + <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_FCLK_DIV7>, + <&clkc CLKID_HDCP22_SKP_COMP>, + <&clkc CLKID_HDCP22_ESM_COMP>; + // <&clkc CLK_AUD_PLL2FS>, + // <&clkc CLK_AUD_PLL4FS>, + // <&clkc CLK_AUD_OUT>; + clock-names = "hdmirx_modet_clk", + "hdmirx_cfg_clk", + "hdmirx_acr_ref_clk", + "cts_hdmirx_meter_clk", + "cts_hdmi_axi_clk", + "xtal", + "fclk_div5", + "fclk_div7", + "hdcp_rx22_skp", + "hdcp_rx22_esm"; + // "hdmirx_aud_pll2fs", + // "hdmirx_aud_pll4f", + // "clk_aud_out"; + hdmirx_id = <0>; + en_4k_2_2k = <0>; + hpd_low_cec_off = <1>; + /* bit4: enable feature, bit3~0: port number */ + disable_port = <0x0>; + /* MAP_ADDR_MODULE_CBUS */ + /* MAP_ADDR_MODULE_HIU */ + /* MAP_ADDR_MODULE_HDMIRX_CAPB3 */ + /* MAP_ADDR_MODULE_SEC_AHB */ + /* MAP_ADDR_MODULE_SEC_AHB2 */ + /* MAP_ADDR_MODULE_APB4 */ + /* MAP_ADDR_MODULE_TOP */ + reg = < 0x0 0x0 0x0 0x0 + 0x0 0xff63C000 0x0 0x2000 + 0x0 0xffe0d000 0x0 0x2000 + 0x0 0x0 0x0 0x0 + 0x0 0x0 0x0 0x0 + 0x0 0x0 0x0 0x0 + 0x0 0xff610000 0x0 0xa000>; + }; + + aocec: aocec { + compatible = "amlogic, aocec-tm2"; + /*device_name = "aocec";*/ + status = "okay"; + vendor_name = "Amlogic"; /* Max Chars: 8 */ + /* Refer to the following URL at: + * http://standards.ieee.org/develop/regauth/oui/oui.txt + */ + vendor_id = <0x000000>; + product_desc = "TM2"; /* Max Chars: 16 */ + cec_osd_string = "AML_TV"; /* Max Chars: 14 */ + port_num = <3>; + ee_cec; + /*cec_sel = <2>;*/ + output = <1>; /*output port number*/ + arc_port_mask = <0x2>; + interrupts = <0 205 1 + 0 199 1>; + interrupt-names = "hdmi_aocecb","hdmi_aocec"; + pinctrl-names = "default","hdmitx_aocecb","cec_pin_sleep"; + pinctrl-0=<&aoceca_mux>; + pinctrl-1=<&aocecb_mux>; + pinctrl-2=<&aoceca_mux>; + reg = <0x0 0xFF80023c 0x0 0x4 + 0x0 0xFF800000 0x0 0x400>; + reg-names = "ao_exit","ao"; + }; + + p_tsensor: p_tsensor@ff634800 { + compatible = "amlogic, r1p1-tsensor"; + status = "okay"; + reg = <0x0 0xff634800 0x0 0x50>, + <0x0 0xff800268 0x0 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 35 0>; + clocks = <&clkc CLKID_TS_CLK_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + d_tsensor: d_tsensor@ff634c00 { + compatible = "amlogic, r1p1-tsensor"; + status = "okay"; + reg = <0x0 0xff634c00 0x0 0x50>, + <0x0 0xff800230 0x0 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 36 0>; + clocks = <&clkc CLKID_TS_CLK_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + s_tsensor: s_tsensor@ff635000 { + compatible = "amlogic, r1p1-tsensor"; + status = "okay"; + reg = <0x0 0xff635000 0x0 0x50>, + <0x0 0xff80026c 0x0 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 38 0>; + clocks = <&clkc CLKID_TS_CLK_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + meson_cooldev: meson-cooldev@0 { + status = "okay"; + compatible = "amlogic, meson-cooldev"; + cooling_devices { + cpufreq_cool_cluster0 { + min_state = <1000000>; + dyn_coeff = <140>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "cpufreq_cool0"; + device_type = "cpufreq"; + }; + cpucore_cool_cluster0 { + min_state = <1>; + dyn_coeff = <0>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "cpucore_cool0"; + device_type = "cpucore"; + }; + gpufreq_cool { + min_state = <400>; + dyn_coeff = <140>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "gpufreq_cool0"; + device_type = "gpufreq"; + }; + gpucore_cool { + min_state = <1>; + dyn_coeff = <0>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "gpucore_cool0"; + device_type = "gpucore"; + }; + }; + cpufreq_cool0:cpufreq_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + cpucore_cool0:cpucore_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + gpufreq_cool0:gpufreq_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + gpucore_cool0:gpucore_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + };/*meson cooling devices end*/ + + thermal-zones { + pll_thermal: pll_thermal { + polling-delay = <1000>; + polling-delay-passive = <100>; + sustainable-power = <1322>; + thermal-sensors = <&p_tsensor 0>; + trips { + pswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + pcontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + phot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + pcritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + cooling-maps { + cpufreq_cooling_map { + trip = <&pcontrol>; + cooling-device = <&cpufreq_cool0 0 11>; + contribution = <1024>; + }; + cpucore_cooling_map { + trip = <&pcontrol>; + cooling-device = <&cpucore_cool0 0 4>; + contribution = <1024>; + }; + gpufreq_cooling_map { + trip = <&pcontrol>; + cooling-device = <&gpufreq_cool0 0 4>; + contribution = <1024>; + }; + }; + }; + ddr_thermal: ddr_thermal { + polling-delay = <2000>; + polling-delay-passive = <1000>; + sustainable-power = <1322>; + thermal-sensors = <&d_tsensor 1>; + trips { + dswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + dcontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + dhot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + dcritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + }; + sar_thermal: sar_thermal { + polling-delay = <2000>; + polling-delay-passive = <1000>; + sustainable-power = <1322>; + thermal-sensors = <&s_tsensor 2>; + trips { + sswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + scontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + shot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + scritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + }; + }; /*thermal zone end*/ + + cpu_opp_table0: cpu_opp_table0 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <730000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <730000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <730000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <750000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <770000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <780000>; + }; + opp06 { + opp-hz = /bits/ 64 <1404000000>; + opp-microvolt = <790000>; + }; + opp07 { + opp-hz = /bits/ 64 <1500000000>; + opp-microvolt = <800000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <810000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <850000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <900000>; + }; + opp11 { + opp-hz = /bits/ 64 <1908000000>; + opp-microvolt = <950000>; + }; + }; + + cpufreq-meson { + compatible = "amlogic, cpufreq-meson"; + pinctrl-names = "default"; + pinctrl-0 = <&pwm_ao_d_pins3>; + status = "okay"; + }; + + tuner: tuner { + compatible = "amlogic, tuner"; + status = "okay"; + tuner_cur = <0>; /* default use tuner */ + tuner_num = <1>; /* tuner number, multi tuner support */ + tuner_name_0 = "si2151_tuner"; + tuner_i2c_adap_0 = <&i2c0>; + tuner_i2c_addr_0 = <0x60>; + /* tuner_xtal_0 = <0>; */ /* unuse for si2151 */ + /* tuner_xtal_mode_0 = <0>; */ + /* tuner_xtal_cap_0 = <0>; */ + }; + + atv-demod { + compatible = "amlogic, atv-demod"; + status = "okay"; + tuner = <&tuner>; + btsc_sap_mode = <1>; + /* pinctrl-names="atvdemod_agc_pins"; */ + /* pinctrl-0=<&atvdemod_agc_pins>; */ + reg = <0x0 0xff656000 0x0 0x2000 /* demod reg */ + 0x0 0xff63c000 0x0 0x2000 /* hiu reg */ + 0x0 0xff634000 0x0 0x2000 /* periphs reg */ + 0x0 0xff64a000 0x0 0x2000>; /* audio reg */ + reg_23cf = <0x88188832>; + /*default:0x88188832;r840 on haier:0x48188832*/ + }; + + bt-dev{ + compatible = "amlogic, bt-dev"; + status = "okay"; + gpio_reset = <&gpio GPIOC_13 GPIO_ACTIVE_HIGH>; + }; + + wifi{ + compatible = "amlogic, aml_wifi"; + status = "okay"; + interrupt_pin = <&gpio GPIOC_12 GPIO_ACTIVE_HIGH>; + irq_trigger_type = "GPIO_IRQ_LOW"; + dhd_static_buf; //dhd_static_buf support + power_on_pin = <&gpio GPIOC_11 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&pwm_b_pins1>; + pwm_config = <&wifi_pwm_conf>; + }; + + wifi_pwm_conf:wifi_pwm_conf{ + pwm_channel1_conf { + pwms = <&pwm_ab MESON_PWM_1 30541 0>; + duty-cycle = <15270>; + times = <8>; + }; + pwm_channel2_conf { + pwms = <&pwm_ab MESON_PWM_3 30500 0>; + duty-cycle = <15250>; + times = <12>; + }; + }; + + sd_emmc_b: sdio@ffe05000 { + status = "okay"; + compatible = "amlogic, meson-mmc-tm2"; + reg = <0x0 0xffe05000 0x0 0x800>; + interrupts = <0 190 4>; + + pinctrl-names = "sdio_all_pins", + "sdio_clk_cmd_pins"; + pinctrl-0 = <&sdio_all_pins>; + pinctrl-1 = <&sdio_clk_cmd_pins>; + + clocks = <&clkc CLKID_SD_EMMC_B>, + <&clkc CLKID_SD_EMMC_B_P0_COMP>, + <&clkc CLKID_FCLK_DIV2>, + <&clkc CLKID_FCLK_DIV5>, + <&xtal>; + clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + + bus-width = <4>; + cap-sd-highspeed; + cap-mmc-highspeed; + max-frequency = <100000000>; + disable-wp; + sdio { + pinname = "sdio"; + ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", /**ptm debug */ + "MMC_CAP_UHS_SDR12", + "MMC_CAP_UHS_SDR25", + "MMC_CAP_UHS_SDR50", + "MMC_CAP_UHS_SDR104", + "MMC_PM_KEEP_POWER", + "MMC_CAP_SDIO_IRQ"; + f_min = <400000>; + f_max = <200000000>; + max_req_size = <0x20000>; /**128KB*/ + card_type = <3>; + /* 3:sdio device(ie:sdio-wifi), + * 4:SD combo (IO+mem) card + */ + }; + }; +/* sd_emmc_b: sd@ffe05000 { + * status = "okay"; + * compatible = "amlogic, meson-mmc-tm2"; + * reg = <0xffe05000 0x800>; + * interrupts = <0 190 1>; + * + * pinctrl-names = "sd_all_pins", + * "sd_clk_cmd_pins", + * "sd_1bit_pins"; + * pinctrl-0 = <&sd_all_pins>; + * pinctrl-1 = <&sd_clk_cmd_pins>; + * pinctrl-2 = <&sd_1bit_pins>; + * + * clocks = <&clkc CLKID_SD_EMMC_B>, + * <&clkc CLKID_SD_EMMC_B_P0_COMP>, + * <&clkc CLKID_FCLK_DIV2>, + * <&clkc CLKID_FCLK_DIV5>, + * <&xtal>; + * clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + * + * bus-width = <4>; + * cap-sd-highspeed; + * cap-mmc-highspeed; + * max-frequency = <100000000>; + * disable-wp; + * sd { + * pinname = "sd"; + * ocr_avail = <0x200080>; + * caps = "MMC_CAP_4_BIT_DATA", + * "MMC_CAP_MMC_HIGHSPEED", + * "MMC_CAP_SD_HIGHSPEED"; + * f_min = <400000>; + * f_max = <200000000>; + * max_req_size = <0x20000>; + * no_sduart = <1>; + * gpio_dat3 = <&gpio GPIOC_3 GPIO_ACTIVE_HIGH>; + * jtag_pin = <&gpio GPIOC_0 GPIO_ACTIVE_HIGH>; + * gpio_cd = <&gpio GPIOC_10 GPIO_ACTIVE_HIGH>; + * card_type = <5>; + * }; + * }; + */ + +}; /* end of / */ + +&i2c0 { + status = "okay"; + clock-frequency = <300000>; + pinctrl-names="default"; + pinctrl-0=<&i2c0_dv_pins>; +}; + +&audiobus { + tdma:tdm@0 { + compatible = "amlogic, tm2-snd-tdma"; + #sound-dai-cells = <0>; + + dai-tdm-lane-slot-mask-in = <1 0>; + dai-tdm-lane-slot-mask-out = <1 1 1 1>; + dai-tdm-clk-sel = <0>; + + clocks = <&clkaudio CLKID_AUDIO_MCLK_A + &clkc CLKID_MPLL0 + &clkc CLKID_MPLL0>; + clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdma_mclk &tdmout_a>; + + /* + * 0: tdmout_a; + * 1: tdmout_b; + * 2: tdmout_c; + * 3: spdifout; + * 4: spdifout_b; + */ + samesource_sel = <3>; + + /* In for ACODEC_ADC */ + acodec_adc = <1>; + + status = "okay"; + + /* !!!For --TV platform-- ONLY */ + Channel_Mask { + /*i2s has 4 pins, 8channel, mux output*/ + Spdif_samesource_Channel_Mask = "i2s_2/3"; + }; + }; + + tdmb:tdm@1 { + compatible = "amlogic, tm2-snd-tdmb"; + #sound-dai-cells = <0>; + + dai-tdm-lane-slot-mask-in = <1 0 0 0>; + dai-tdm-lane-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <1>; + + clocks = <&clkaudio CLKID_AUDIO_MCLK_B + &clkc CLKID_MPLL1>; + clock-names = "mclk", "clk_srcpll"; + + status = "okay"; + }; + + tdmc:tdm@2 { + compatible = "amlogic, tm2-snd-tdmc"; + #sound-dai-cells = <0>; + + dai-tdm-lane-slot-mask-in = <1 0 0 0>; + dai-tdm-lane-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <2>; + + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmout_c &tdmin_c>; + + status = "okay"; + }; + + pdm:pdm { + compatible = "amlogic, tm2-snd-pdm"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_PDM + &clkc CLKID_FCLK_DIV3 + &clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_PDMIN0 + &clkaudio CLKID_AUDIO_PDMIN1>; + clock-names = "gate", + "sysclk_srcpll", + "dclk_srcpll", + "pdm_dclk", + "pdm_sysclk"; + + pinctrl-names = "pdm_pins"; + pinctrl-0 = <&pdmin>; + + /* mode 0~4, defalut:1 */ + filter_mode = <1>; + + status = "okay"; + }; + + spdifa:spdif@0 { + compatible = "amlogic, tm2-snd-spdif-a"; + #sound-dai-cells = <0>; + + clocks = <&clkc CLKID_MPLL1 + &clkc CLKID_FCLK_DIV4 + &clkaudio CLKID_AUDIO_GATE_SPDIFIN + &clkaudio CLKID_AUDIO_GATE_SPDIFOUT_A + &clkaudio CLKID_AUDIO_SPDIFIN + &clkaudio CLKID_AUDIO_SPDIFOUT_A>; + clock-names = "sysclk", "fixed_clk", "gate_spdifin", + "gate_spdifout", "clk_spdifin", "clk_spdifout"; + + interrupts = + ; + interrupt-names = "irq_spdifin"; + + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; + pinctrl-0 = <&spdifin_a>; + //pinctrl-1 = <&spdifout_a_mute>; + + /* + * whether do asrc for pcm and resample a or b + * if raw data, asrc is disabled automatically + * 0: "Disable", + * 1: "Enable:32K", + * 2: "Enable:44K", + * 3: "Enable:48K", + * 4: "Enable:88K", + * 5: "Enable:96K", + * 6: "Enable:176K", + * 7: "Enable:192K", + */ + asrc_id = <0>; + auto_asrc = <3>; + + status = "okay"; + }; + + spdifb:spdif@1 { + compatible = "amlogic, tm2-snd-spdif-b"; + #sound-dai-cells = <0>; + + clocks = <&clkc CLKID_MPLL0 /*CLKID_HIFI_PLL*/ + &clkaudio CLKID_AUDIO_GATE_SPDIFOUT_B + &clkaudio CLKID_AUDIO_SPDIFOUT_B>; + clock-names = "sysclk", + "gate_spdifout", "clk_spdifout"; + + status = "okay"; + }; + + extn:extn { + compatible = "amlogic, snd-extn"; + #sound-dai-cells = <0>; + + interrupts = + ; + interrupt-names = "irq_frhdmirx"; + + status = "okay"; + }; + + earc:earc { + compatible = "amlogic, tm2-snd-earc"; + #sound-dai-cells = <0>; + + clocks = < &clkaudio CLKID_EARCRX_CMDC + &clkaudio CLKID_EARCRX_DMAC + &clkc CLKID_FCLK_DIV5 + &clkc CLKID_FCLK_DIV3 + &clkaudio CLKID_EARCTX_CMDC + &clkaudio CLKID_EARCTX_DMAC + &clkc CLKID_FCLK_DIV5 + &clkc CLKID_FCLK_DIV3 + >; + clock-names = + "rx_cmdc", + "rx_dmac", + "rx_cmdc_srcpll", + "rx_dmac_srcpll", + "tx_cmdc", + "tx_dmac", + "tx_cmdc_srcpll", + "tx_dmac_srcpll"; + + interrupts = < + GIC_SPI 88 IRQ_TYPE_EDGE_RISING + GIC_SPI 87 IRQ_TYPE_EDGE_RISING + >; + interrupt-names = "rx_cmdc", "rx_dmac"; + + status = "okay"; + }; + + aed:effect { + compatible = "amlogic, snd-effect-v2"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_EQDRC + &clkc CLKID_FCLK_DIV5 + &clkaudio CLKID_AUDIO_EQDRC>; + clock-names = "gate", "srcpll", "eqdrc"; + + /* + * 0:tdmout_a + * 1:tdmout_b + * 2:tdmout_c + * 3:spdifout + * 4:spdifout_b + */ + eqdrc_module = <0>; + /* max 0xf, each bit for one lane, usually one lane */ + lane_mask = <0x1>; + /* max 0xff, each bit for one channel */ + channel_mask = <0xff>; + + status = "disable"; + }; + + asrca: resample@0 { + compatible = "amlogic, tl1-resample-a"; + clocks = <&clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_MCLK_A + &clkaudio CLKID_AUDIO_RESAMPLE_A>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + /*same with toddr_src + * TDMIN_A, 0 + * TDMIN_B, 1 + * TDMIN_C, 2 + * SPDIFIN, 3 + * PDMIN, 4 + * NONE, + * TDMIN_LB, 6 + * LOOPBACK, 7 + * FRHDMIRX, 8 + */ + resample_module = <8>; + + status = "disabled"; + }; + + asrcb: resample@1 { + compatible = "amlogic, tl1-resample-b"; + + clocks = <&clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_MCLK_F + &clkaudio CLKID_AUDIO_RESAMPLE_B>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + + /*same with toddr_src + * TDMIN_A, 0 + * TDMIN_B, 1 + * TDMIN_C, 2 + * SPDIFIN, 3 + * PDMIN, 4 + * NONE, + * TDMIN_LB, 6 + * LOOPBACK, 7 + */ + resample_module = <3>; + + status = "disabled"; + }; + + vad:vad { + compatible = "amlogic, snd-vad"; + #sound-dai-cells = <0>; + clocks = <&clkaudio CLKID_AUDIO_GATE_TOVAD + &clkc CLKID_FCLK_DIV5 + &clkaudio CLKID_AUDIO_VAD>; + clock-names = "gate", "pll", "clk"; + interrupts = ; + interrupt-names = "irq_wakeup", "irq_frame_sync"; + /* + * Data src sel: + * 0: tdmin_a; + * 1: tdmin_b; + * 2: tdmin_c; + * 3: spdifin; + * 4: pdmin; + * 5: loopback_b; + * 6: tdmin_lb; + * 7: loopback_a; + */ + src = <4>; + /* + * deal with hot word in user space or kernel space + * 0: in user space + * 1: in kernel space + */ + level = <1>; + status = "disabled"; + }; +}; /* end of audiobus */ + +&pinctrl_periphs { + /* audio pin mux */ + + tdma_mclk: tdma_mclk { + mux { /* GPIOH_4 */ + groups = "mclk0_h"; + function = "mclk0"; + }; + }; + + tdmout_a: tdmout_a { + mux { /* GPIOH_5, GPIOH_6, GPIOH_7, GPIOH_8*/ + groups = "tdma_fs_h", + "tdma_sclk_h", + "tdma_dout0_h", + "tdma_dout1_h"; + function = "tdma_out"; + bias-pull-down; + }; + }; + + tdmin_a: tdmin_a { + mux { /* GPIOH_11, GPIOH_12 */ + groups = "tdma_din0_h", + "tdma_din1_h"; + function = "tdma_in"; + }; + }; + + tdmout_c: tdmout_c { + mux { /* GPIODV_7, GPIODV_8, GPIODV_9 */ + groups = "tdmc_sclk", + "tdmc_fs", + "tdmc_dout0"; + function = "tdmc_out"; + }; + }; + + tdmin_c: tdmin_c { + mux { /* GPIODV_10 */ + groups = "tdmc_din1"; + function = "tdmc_in"; + }; + }; + + spdifin_a: spdifin_a { + mux { /* GPIODV_5 */ + groups = "spdif_in"; + function = "spdif_in"; + }; + }; + + spdifout_a: spdifout_a { + mux { /* GPIODV_4 */ + groups = "spdif_out_dv4"; + function = "spdif_out"; + }; + }; + + spdifout_a_mute: spdifout_a_mute { + mux { /* GPIODV_4 */ + groups = "GPIODV_4"; + function = "gpio_periphs"; + }; + }; + + pdmin: pdmin { + mux { /* GPIOZ_7, GPIOZ_8, pdm_din2_z4 */ + groups = "pdm_dclk_z", + "pdm_din0_z", + "pdm_din2_z4"; + function = "pdm"; + }; + }; + + /*backlight*/ + bl_pwm_vs_on_pins:bl_pwm_vs_on_pin { + mux { + groups = "pwm_vs_z5"; + function = "pwm_vs"; + }; + }; + bl_pwm_off_pins:bl_pwm_off_pin { + mux { + groups = "GPIOZ_5"; + function = "gpio_periphs"; + output-low; + }; + }; + bl_pwm_combo_0_vs_on_pins:bl_pwm_combo_0_vs_on_pin { + mux { + groups = "pwm_vs_z5"; + function = "pwm_vs"; + }; + }; + bl_pwm_combo_1_vs_on_pins:bl_pwm_combo_1_vs_on_pin { + mux { + groups = "pwm_vs_z6"; + function = "pwm_vs"; + }; + }; + bl_pwm_combo_off_pins:bl_pwm_combo_off_pin { + mux { + groups = "GPIOZ_5", + "GPIOZ_6"; + function = "gpio_periphs"; + output-low; + }; + }; + +}; /* end of pinctrl_periphs */ + +&audio_data{ + status = "okay"; +}; + +&i2c2 { + status = "disabled"; + pinctrl-names="default"; + pinctrl-0=<&i2c2_z_pins>; + clock-frequency = <400000>; + + tas5805: tas5805@36 { + compatible = "ti,tas5805"; + #sound-dai-cells = <0>; + codec_name = "tas5805"; + reg = <0x2d>; + status = "disable"; + }; +}; + +&i2c3 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&i2c3_h1_pins>; + clock-frequency = <400000>; + + ad82584f: ad82584f@60 { + compatible = "ESMT, ad82584f"; + #sound-dai-cells = <0>; + reg = <0x30>; + status = "okay"; + reset_pin = <&gpio GPIOH_13 0>; + no_mclk; + }; + + ad82584f1: ad82584f@62 { + compatible = "ESMT, ad82584f"; + #sound-dai-cells = <0>; + reg = <0x31>; + status = "okay"; + no_mclk; + }; +}; + + +&sd_emmc_c { + status = "okay"; + emmc { + caps = "MMC_CAP_8_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + "MMC_CAP_1_8V_DDR", + "MMC_CAP_HW_RESET", + "MMC_CAP_ERASE", + "MMC_CAP_CMD23"; + caps2 = "MMC_CAP2_HS200"; + /* "MMC_CAP2_HS400";*/ + f_min = <400000>; + f_max = <200000000>; + }; +}; + + + +&spifc { + status = "disabled"; + spi-nor@0 { + cs_gpios = <&gpio BOOT_13 GPIO_ACTIVE_HIGH>; + }; +}; + +&slc_nand { + status = "disabled"; + plat-names = "bootloader", "nandnormal"; + plat-num = <2>; + plat-part-0 = <&bootloader>; + plat-part-1 = <&nandnormal>; + bootloader: bootloader{ + enable_pad = "ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <1>; + part_num = <0>; + rb_detect = <1>; + }; + nandnormal: nandnormal{ + enable_pad = "ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + plane_mode = "twoplane"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <2>; + part_num = <3>; + partition = <&nand_partitions>; + rb_detect = <1>; + }; + nand_partitions:nand_partition{ + /* + * if bl_mode is 1, tpl size was generate by + * fip_copies * fip_size which + * will not skip bad when calculating + * the partition size; + * + * if bl_mode is 0, + * tpl partition must be comment out. + */ + tpl{ + offset=<0x0 0x0>; + size=<0x0 0x0>; + }; + logo{ + offset=<0x0 0x0>; + size=<0x0 0x200000>; + }; + recovery{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + boot{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + system{ + offset=<0x0 0x0>; + size=<0x0 0x4000000>; + }; + data{ + offset=<0xffffffff 0xffffffff>; + size=<0x0 0x0>; + }; + }; +}; + +ðmac { + status = "okay"; + //pinctrl-names = "internal_eth_pins"; + //pinctrl-0 = <&internal_eth_pins>; + mc_val = <0x4be04>; + + internal_phy=<1>; +}; + +&uart_A { + status = "okay"; +}; + +&dwc3 { + status = "okay"; +}; + +&usb2_phy_v2 { + status = "okay"; + portnum = <3>; +}; + +&usb3_phy_v2 { + status = "okay"; + portnum = <2>; + portconfig-30 = <1>; + portconfig-31 = <1>; +}; + +&usb_otg { + status = "okay"; + otg = <0>; +}; + +&dwc2_a { + status = "okay"; + /** 0: normal, 1: otg+dwc3 host only, 2: otg+dwc3 device only*/ + controller-type = <1>; +}; + +&pcie_A { + reset-gpio = <&gpio_ao GPIOAO_4 GPIO_ACTIVE_HIGH>; + status = "disable"; +}; + +&pcie_B { + /* ab311 only pcie a, no pcie b */ + status = "disable"; +}; + +&spicc0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&spicc0_pins_h>; + cs-gpios = <&gpio GPIOH_20 0>; +}; + +&meson_fb { + status = "okay"; + display_size_default = <1920 1080 1920 2160 32>; + mem_size = <0x00800000 0x1980000 0x100000 0x100000 0x800000>; + logo_addr = "0x7f800000"; + mem_alloc = <0>; + pxp_mode = <0>; /** 0:normal mode 1:pxp mode */ +}; + +&pwm_AO_cd { + status = "okay"; +}; + +&saradc { + status = "okay"; +}; + +&i2c1 { + status = "okay"; + clock-frequency = <300000>; + pinctrl-names="default"; + pinctrl-0=<&i2c1_h_pins>; + + lcd_extern_i2c0: lcd_extern_i2c@0 { + compatible = "lcd_ext, i2c"; + dev_name = "i2c_T5800Q"; + reg = <0x1c>; + status = "okay"; + }; + + lcd_extern_i2c1: lcd_extern_i2c@1 { + compatible = "lcd_ext, i2c"; + dev_name = "i2c_ANX6862"; + reg = <0x20>; + status = "okay"; + }; + + lcd_extern_i2c2: lcd_extern_i2c@2 { + compatible = "lcd_ext, i2c"; + dev_name = "i2c_ANX7911"; + reg = <0x74>; + status = "okay"; + }; +}; + +&pwm_ab { + status = "okay"; +}; + +&pwm_cd { + status = "okay"; +}; + +&efuse { + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab319.dts b/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab319.dts new file mode 100644 index 000000000000..44146fe78453 --- /dev/null +++ b/arch/arm64/boot/dts/amlogic/tm2_t962e2_ab319.dts @@ -0,0 +1,1851 @@ +/* + * arch/arm64/boot/dts/amlogic/tm2_t962e2_ab319.dts + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +/dts-v1/; + +#include "mesontm2.dtsi" +#include "partition_mbox_normal_P_32.dtsi" + +/ { + model = "Amlogic TM2 T962E2 AB319"; + amlogic-dt-id = "tm2_t962e2_ab319"; + compatible = "amlogic, tm2_t962e2_ab319"; + + aliases { + serial0 = &uart_AO; + serial1 = &uart_A; + serial2 = &uart_B; + serial3 = &uart_C; + serial4 = &uart_AO_B; + tsensor0 = &p_tsensor; + tsensor1 = &d_tsensor; + tsensor2 = &s_tsensor; + i2c0 = &i2c0; + i2c1 = &i2c1; + i2c2 = &i2c2; + i2c3 = &i2c3; + i2c4 = &i2c_AO; + }; + + memory@00000000 { + device_type = "memory"; + linux,usable-memory = <0x0 0x0 0x0 0x80000000>; + }; + + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + /* global autoconfigured region for contiguous allocations */ + ramoops@0x07400000 { + compatible = "ramoops"; + reg = <0x0 0x07400000 0x0 0x00100000>; + record-size = <0x8000>; + console-size = <0x8000>; + ftrace-size = <0x20000>; + }; + + secmon_reserved: linux,secmon { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x400000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x05000000 0x0 0x400000>; + }; + + logo_reserved:linux,meson-fb { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x800000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x7f800000 0x0 0x800000>; + }; + + lcd_tcon_reserved:linux,lcd_tcon { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0xc00000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x7ec00000 0x0 0xc00000>; + }; + + codec_mm_cma:linux,codec_mm_cma { + compatible = "shared-dma-pool"; + reusable; + /* ion_codec_mm max can alloc size 80M*/ + size = <0x0 0x13400000>; + alignment = <0x0 0x400000>; + linux,contiguous-region; + }; + + /* codec shared reserved */ + codec_mm_reserved:linux,codec_mm_reserved { + compatible = "amlogic, codec-mm-reserved"; + size = <0x0 0x0>; + alignment = <0x0 0x100000>; + //no-map; + }; + + ion_cma_reserved:linux,ion-dev { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x8000000>; + alignment = <0x0 0x400000>; + }; + + /* vdin0 CMA pool */ + //vdin0_cma_reserved:linux,vdin0_cma { + // compatible = "shared-dma-pool"; + // reusable; + /* 3840x2160x4x4 ~=128 M */ + // size = <0x0 0xc400000>; + // alignment = <0x0 0x400000>; + //}; + + /* vdin1 CMA pool */ + vdin1_cma_reserved:linux,vdin1_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16 M */ + size = <0x0 0x1400000>; + alignment = <0x0 0x400000>; + }; + + /*demod_reserved:linux,demod { + * compatible = "amlogic, demod-mem"; + * size = <0x0 0x800000>; //8M //100m 0x6400000 + * alloc-ranges = <0x0 0x0 0x0 0x30000000>; + * //multi-use; + * //no-map; + *}; + */ + + demod_cma_reserved:linux,demod_cma { + compatible = "shared-dma-pool"; + reusable; + /* 8M */ + size = <0x0 0x0800000>; + alignment = <0x0 0x400000>; + }; + + /*di CMA pool */ + di_cma_reserved:linux,di_cma { + compatible = "shared-dma-pool"; + reusable; + /* buffer_size = 3621952(yuv422 8bit) + * | 4736064(yuv422 10bit) + * | 4074560(yuv422 10bit full pack mode) + * 10x3621952=34.6M(0x23) support 8bit + * 10x4736064=45.2M(0x2e) support 12bit + * 10x4074560=40M(0x28) support 10bit + */ + size = <0x0 0x02800000>; + alignment = <0x0 0x400000>; + }; + + /* for hdmi rx emp use */ + hdmirx_emp_cma_reserved:linux,emp_cma { + compatible = "shared-dma-pool"; + /*linux,phandle = <5>;*/ + reusable; + /* 4M for emp to ddr */ + /* 32M for tmds to ddr */ + size = <0x0 0x400000>; + alignment = <0x0 0x400000>; + /* alloc-ranges = <0x400000 0x2000000>; */ + }; + + /* POST PROCESS MANAGER */ + ppmgr_reserved:linux,ppmgr { + compatible = "amlogic, ppmgr_memory"; + size = <0x0 0x0>; + }; + + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x0>; + alignment = <0x0 0x0>; + linux,contiguous-region; + }; + }; /* end of reserved-memory */ + galcore { + status = "okay"; + }; + codec_mm { + compatible = "amlogic, codec, mm"; + status = "okay"; + memory-region = <&codec_mm_cma &codec_mm_reserved>; + }; + + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + + ppmgr { + compatible = "amlogic, ppmgr"; + memory-region = <&ppmgr_reserved>; + status = "okay"; + }; + + deinterlace { + compatible = "amlogic, deinterlace"; + status = "okay"; + /* 0:use reserved; 1:use cma; 2:use cma as reserved */ + flag_cma = <1>; + //memory-region = <&di_reserved>; + memory-region = <&di_cma_reserved>; + interrupts = <0 46 1 + 0 40 1>; + interrupt-names = "pre_irq", "post_irq"; + clocks = <&clkc CLKID_VPU_CLKB_TMP_COMP>, + <&clkc CLKID_VPU_CLKB_COMP>; + clock-names = "vpu_clkb_tmp_composite", + "vpu_clkb_composite"; + clock-range = <334 667>; + /* buffer-size = <3621952>;(yuv422 8bit) */ + buffer-size = <4074560>;/*yuv422 fullpack*/ + /* reserve-iomap = "true"; */ + /* if enable nr10bit, set nr10bit-support to 1 */ + post-wr-support = <1>; + nr10bit-support = <1>; + nrds-enable = <1>; + pps-enable = <1>; + }; + + vout { + compatible = "amlogic, vout"; + status = "okay"; + fr_auto_policy = <0>; + }; + + /* Audio Related start */ + pdm_codec:dummy { + #sound-dai-cells = <0>; + compatible = "amlogic, pdm_dummy_codec"; + status = "okay"; + }; + + dummy_codec:dummy { + #sound-dai-cells = <0>; + compatible = "amlogic, aml_dummy_codec"; + status = "okay"; + }; + + tl1_codec:codec { + #sound-dai-cells = <0>; + compatible = "amlogic, tl1_acodec"; + status = "okay"; + reg = <0x0 0xff632000 0x0 0x1c>; + tdmout_index = <0>; + tdmin_index = <0>; + dat1_ch_sel = <1>; + }; + + aml_dtv_demod { + compatible = "amlogic, ddemod-tl1"; + dev_name = "aml_dtv_demod"; + status = "okay"; + + //pinctrl-names="dtvdemod_agc"; + //pinctrl-0=<&dtvdemod_agc>; + + clocks = <&clkc CLKID_DAC_CLK>; + clock-names = "vdac_clk_gate"; + + reg = <0x0 0xff650000 0x0 0x4000 /*dtv demod base*/ + 0x0 0xff63c000 0x0 0x2000 /*hiu reg base*/ + 0x0 0xff800000 0x0 0x1000 /*io_aobus_base*/ + 0x0 0xffd01000 0x0 0x1000 /*reset*/ + >; + + dtv_demod0_mem = <0>; // need move to aml_dtv_demod ? + spectrum = <1>; + cma_flag = <1>; + cma_mem_size = <8>; + memory-region = <&demod_cma_reserved>;//<&demod_reserved>; + }; + + auge_sound { + compatible = "amlogic, tm2-sound-card"; + aml-audio-card,name = "AML-AUGESOUND"; + + avout_mute-gpios = <&gpio GPIODV_3 GPIO_ACTIVE_HIGH>; + + aml-audio-card,dai-link@0 { + format = "i2s"; + mclk-fs = <256>; + continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdma>; + frame-master = <&tdma>; + /* slave mode */ + /* + * bitclock-master = <&tdmacodec>; + * frame-master = <&tdmacodec>; + */ + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-i2s"; + tdmacpu: cpu { + sound-dai = <&tdma>; + dai-tdm-slot-tx-mask = + <1 1>; + dai-tdm-slot-rx-mask = + <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmacodec: codec { + //sound-dai = <&dummy_codec>; + sound-dai = ; + }; + }; + + aml-audio-card,dai-link@1 { + + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdmb>; + frame-master = <&tdmb>; + /* slave mode */ + //bitclock-master = <&tdmbcodec>; + //frame-master = <&tdmbcodec>; + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-pcm"; + cpu { + sound-dai = <&tdmb>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + /* + * dai-tdm-slot-tx-mask = + * <1 1 1 1 1 1 1 1>; + * dai-tdm-slot-rx-mask = + * <1 1 1 1 1 1 1 1>; + * dai-tdm-slot-num = <8>; + */ + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmbcodec: codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@2 { + + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdmc>; + frame-master = <&tdmc>; + /* slave mode */ + //bitclock-master = <&tdmccodec>; + //frame-master = <&tdmccodec>; + /* suffix-name, sync with android audio hal used for */ + //suffix-name = "alsaPORT-tdm"; + cpu { + sound-dai = <&tdmc>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmccodec: codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@3 { + mclk-fs = <64>; + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-pdm"; + cpu { + sound-dai = <&pdm>; + }; + codec { + sound-dai = <&pdm_codec>; + }; + }; + + aml-audio-card,dai-link@4 { + mclk-fs = <128>; + continuous-clock; + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-spdif"; + cpu { + sound-dai = <&spdifa>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@5 { + mclk-fs = <128>; + suffix-name = "alsaPORT-spdifb"; + cpu { + sound-dai = <&spdifb>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@6 { + mclk-fs = <256>; + suffix-name = "alsaPORT-tv"; + cpu { + sound-dai = <&extn>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + aml-audio-card,dai-link@7 { + mclk-fs = <256>; + suffix-name = "alsaPORT-earc"; + cpu { + sound-dai = <&earc>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + }; + /* Audio Related end */ + + dvb { + compatible = "amlogic, dvb"; + status = "okay"; + fe0_mode = "internal"; + fe0_tuner = <&tuner>; + + /*"parallel","serial","disable"*/ + ts2 = "parallel"; + ts2_control = <0>; + ts2_invert = <0>; + interrupts = <0 23 1 + 0 5 1 + 0 53 1 + 0 19 1 + 0 25 1 + 0 17 1>; + interrupt-names = "demux0_irq", + "demux1_irq", + "demux2_irq", + "dvr0_irq", + "dvr1_irq", + "dvr2_irq"; + clocks = <&clkc CLKID_DEMUX + &clkc CLKID_ASYNC_FIFO + &clkc CLKID_AHB_ARB0 + /*&clkc CLKID_DOS_PARSER>;*/ + &clkc CLKID_U_PARSER>; + clock-names = "demux", "asyncfifo", "ahbarb0", "uparsertop"; + }; + + tvafe_avin_detect { + compatible = "amlogic, tl1_tvafe_avin_detect"; + status = "okay"; + device_mask = <1>;/*bit0:ch1;bit1:ch2*/ + interrupts = <0 12 1>, + <0 13 1>; + }; + + amlvecm { + compatible = "amlogic, vecm-tl1"; + dev_name = "aml_vecm"; + status = "okay"; + gamma_en = <1>;/*1:enabel ;0:disable*/ + wb_en = <1>;/*1:enabel ;0:disable*/ + cm_en = <0>;/*1:enabel ;0:disable*/ + wb_sel = <1>;/*1:mtx ;0:gainoff*/ + vlock_en = <1>;/*1:enable;0:disable*/ + vlock_mode = <0x4>; + /* vlock work mode: + *bit0:auto ENC + *bit1:auto PLL + *bit2:manual PLL + *bit3:manual ENC + *bit4:manual soft ENC + *bit5:manual MIX PLL ENC + */ + vlock_pll_m_limit = <1>; + vlock_line_limit = <3>; + }; + + amdolby_vision { + compatible = "amlogic, dolby_vision_tm2"; + dev_name = "aml_amdolby_vision_driver"; + status = "okay"; + tv_mode = <0>;/*1:enabel ;0:disable*/ + }; + + vdin@0 { + compatible = "amlogic, vdin"; + /*memory-region = <&vdin0_cma_reserved>;*/ + status = "okay"; + /*bit0:(1:share with codec_mm;0:cma alone) + *bit8:(1:alloc in discontinus way;0:alone in continuous way) + */ + flag_cma = <0x101>; + /*MByte, if 10bit disable: 64M(YUV422), + *if 10bit enable: 64*1.5 = 96M(YUV422) + *if support 4K2K-YUV444-10bit-WR:3840*2160*4*4 ~= 128M + *if support 4K2K-YUV422-10bit-wr:3840*2160*3*4 ~= 96M + *if support 4K2K-YUV422-8BIT-WR:3840*2160*2*4 ~= 64M + *if support 1080p-YUV422-8BIT-WR:1920*1080*2*4 ~= 16M + */ + cma_size = <190>; + interrupts = <0 83 1>; + rdma-irq = <2>; + clocks = <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_VDIN_MEAS_COMP>; + clock-names = "fclk_div5", "cts_vdin_meas_clk"; + vdin_id = <0>; + /*vdin write mem color depth support: + * bit0:support 8bit + * bit1:support 9bit + * bit2:support 10bit + * bit3:support 12bit + * bit4:support yuv422 10bit full pack mode (from txl new add) + * bit8:use 8bit at 4k_50/60hz_10bit + * bit9:use 10bit at 4k_50/60hz_10bit + */ + tv_bit_mode = <0x215>; + /* afbce_bit_mode: (amlogic frame buff compression encoder) + * bit 0~3: + * 0 -- normal mode, not use afbce + * 1 -- use afbce non-mmu mode + * 2 -- use afbce mmu mode + * bit 4: + * 0 -- afbce compression-lossy disable + * 1 -- afbce compression-lossy enable + */ + afbce_bit_mode = <0>; + }; + + vdin@1 { + compatible = "amlogic, vdin"; + memory-region = <&vdin1_cma_reserved>; + status = "okay"; + /*bit0:(1:share with codec_mm;0:cma alone) + *bit8:(1:alloc in discontinus way;0:alone in continuous way) + */ + flag_cma = <0>; + interrupts = <0 85 1>; + rdma-irq = <4>; + clocks = <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_VDIN_MEAS_COMP>; + clock-names = "fclk_div5", "cts_vdin_meas_clk"; + vdin_id = <1>; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + */ + tv_bit_mode = <0x15>; + }; + + tvafe { + compatible = "amlogic, tvafe-tl1"; + /*memory-region = <&tvafe_cma_reserved>;*/ + status = "okay"; + flag_cma = <1>;/*1:share with codec_mm;0:cma alone*/ + cma_size = <5>;/*MByte*/ + reg = <0x0 0xff654000 0x0 0x2000>;/*tvafe reg base*/ + reserve-iomap = "true"; + tvafe_id = <0>; + //pinctrl-names = "default"; + /*!!particular sequence, no more and no less!!!*/ + tvafe_pin_mux = < + 3 /* TVAFE_CVBS_IN2, CVBS_IN0 = 0 */ + 1 /* TVAFE_CVBS_IN0, CVBS_IN1 */ + 2 /* TVAFE_CVBS_IN1, CVBS_IN2 */ + 4 /* TVAFE_CVBS_IN3, CVBS_IN3 */ + >; + clocks = <&clkc CLKID_DAC_CLK>; + clock-names = "vdac_clk_gate"; + }; + + vbi { + compatible = "amlogic, vbi"; + status = "okay"; + interrupts = <0 83 1>; + }; + + cvbsout { + compatible = "amlogic, cvbsout-tl1"; + status = "disabled"; + clocks = <&clkc CLKID_VCLK2_ENCI + &clkc CLKID_VCLK2_VENCI0 + &clkc CLKID_VCLK2_VENCI1 + &clkc CLKID_DAC_CLK>; + clock-names = "venci_top_gate", + "venci_0_gate", + "venci_1_gate", + "vdac_clk_gate"; + /* clk path */ + /* 0:vid_pll vid2_clk */ + /* 1:gp0_pll vid2_clk */ + /* 2:vid_pll vid1_clk */ + /* 3:gp0_pll vid1_clk */ + clk_path = <0>; + + /* performance: reg_address, reg_value */ + /* tl1 */ + performance = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x8080 + 0x1b05 0xfd + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + performance_sarft = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x0 + 0x1b05 0x9 + 0x1c59 0xfc48 + 0xffff 0x0>; /* ending flag */ + performance_revB_telecom = <0x1bf0 0x9 + 0x1b56 0x546 + 0x1b12 0x8080 + 0x1b05 0x9 + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + }; + + adc_keypad { + compatible = "amlogic, adc_keypad"; + status = "okay"; + key_name = "vol-", "vol+", "ch+", "ch-", + "menu", "source", "exit"; + key_num = <7>; + io-channels = <&saradc SARADC_CH2 &saradc SARADC_CH3>; + io-channel-names = "key-chan-2", "key-chan-3"; + key_chan = ; + key_code = <114 115 192 193 139 466 174>; + key_val = <0 143 266 389 0 143 266>; //val=voltage/1800mV*1023 + key_tolerance = <40 40 40 40 40 40 40>; + }; + + unifykey { + compatible = "amlogic, unifykey"; + status = "okay"; + + unifykey-num = <21>; + unifykey-index-0 = <&keysn_0>; + unifykey-index-1 = <&keysn_1>; + unifykey-index-2 = <&keysn_2>; + unifykey-index-3 = <&keysn_3>; + unifykey-index-4 = <&keysn_4>; + unifykey-index-5 = <&keysn_5>; + unifykey-index-6 = <&keysn_6>; + unifykey-index-7 = <&keysn_7>; + unifykey-index-8 = <&keysn_8>; + unifykey-index-9 = <&keysn_9>; + unifykey-index-10= <&keysn_10>; + unifykey-index-11 = <&keysn_11>; + unifykey-index-12 = <&keysn_12>; + unifykey-index-13 = <&keysn_13>; + unifykey-index-14 = <&keysn_14>; + unifykey-index-15 = <&keysn_15>; + unifykey-index-16 = <&keysn_16>; + unifykey-index-17 = <&keysn_17>; + unifykey-index-18 = <&keysn_18>; + unifykey-index-19 = <&keysn_19>; + unifykey-index-20 = <&keysn_20>; + + keysn_0: key_0{ + key-name = "usid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_1:key_1{ + key-name = "mac"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_2:key_2{ + key-name = "hdcp"; + key-device = "secure"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_3:key_3{ + key-name = "secure_boot_set"; + key-device = "efuse"; + key-permit = "write"; + }; + keysn_4:key_4{ + key-name = "mac_bt"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_5:key_5{ + key-name = "mac_wifi"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_6:key_6{ + key-name = "hdcp2_tx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_7:key_7{ + key-name = "hdcp2_rx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_8:key_8{ + key-name = "widevinekeybox"; + key-device = "secure"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_9:key_9{ + key-name = "deviceid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_10:key_10{ + key-name = "hdcp22_fw_private"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_11:key_11{ + key-name = "hdcp22_rx_private"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_12:key_12{ + key-name = "hdcp22_rx_fw"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_13:key_13{ + key-name = "hdcp14_rx"; + key-device = "normal"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_14:key_14{ + key-name = "prpubkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_15:key_15{ + key-name = "prprivkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_16:key_16{ + key-name = "lcd"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_17:key_17{ + key-name = "lcd_extern"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_18:key_18{ + key-name = "backlight"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_19:key_19{ + key-name = "lcd_tcon"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_20:key_20{ + key-name = "attestationkeybox";// attestation key + key-device = "secure"; + key-permit = "read","write","del"; + }; + }; /* End unifykey */ + + hdmirx { + compatible = "amlogic, hdmirx_tl1"; + #address-cells=<1>; + #size-cells=<1>; + memory-region = <&hdmirx_emp_cma_reserved>; + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&hdmirx_a_mux &hdmirx_b_mux + &hdmirx_c_mux>; + repeat = <0>; + interrupts = <0 41 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clkc CLKID_HDMIRX_MODET_COMP>, + <&clkc CLKID_HDMIRX_CFG_COMP>, + <&clkc CLKID_HDMIRX_ACR_COMP>, + <&clkc CLKID_HDMIRX_METER_COMP>, + <&clkc CLKID_HDMIRX_AXI_COMP>, + <&xtal>, + <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_FCLK_DIV7>, + <&clkc CLKID_HDCP22_SKP_COMP>, + <&clkc CLKID_HDCP22_ESM_COMP>; + // <&clkc CLK_AUD_PLL2FS>, + // <&clkc CLK_AUD_PLL4FS>, + // <&clkc CLK_AUD_OUT>; + clock-names = "hdmirx_modet_clk", + "hdmirx_cfg_clk", + "hdmirx_acr_ref_clk", + "cts_hdmirx_meter_clk", + "cts_hdmi_axi_clk", + "xtal", + "fclk_div5", + "fclk_div7", + "hdcp_rx22_skp", + "hdcp_rx22_esm"; + // "hdmirx_aud_pll2fs", + // "hdmirx_aud_pll4f", + // "clk_aud_out"; + hdmirx_id = <0>; + en_4k_2_2k = <0>; + hpd_low_cec_off = <1>; + /* bit4: enable feature, bit3~0: port number */ + disable_port = <0x0>; + /* MAP_ADDR_MODULE_CBUS */ + /* MAP_ADDR_MODULE_HIU */ + /* MAP_ADDR_MODULE_HDMIRX_CAPB3 */ + /* MAP_ADDR_MODULE_SEC_AHB */ + /* MAP_ADDR_MODULE_SEC_AHB2 */ + /* MAP_ADDR_MODULE_APB4 */ + /* MAP_ADDR_MODULE_TOP */ + reg = < 0x0 0x0 0x0 0x0 + 0x0 0xff63C000 0x0 0x2000 + 0x0 0xffe0d000 0x0 0x2000 + 0x0 0x0 0x0 0x0 + 0x0 0x0 0x0 0x0 + 0x0 0x0 0x0 0x0 + 0x0 0xff610000 0x0 0xa000>; + }; + + aocec: aocec { + compatible = "amlogic, aocec-tm2"; + /*device_name = "aocec";*/ + status = "okay"; + vendor_name = "Amlogic"; /* Max Chars: 8 */ + /* Refer to the following URL at: + * http://standards.ieee.org/develop/regauth/oui/oui.txt + */ + vendor_id = <0x000000>; + product_desc = "TM2"; /* Max Chars: 16 */ + cec_osd_string = "AML_TV"; /* Max Chars: 14 */ + port_num = <3>; + ee_cec; + /*cec_sel = <2>;*/ + output = <1>; /*output port number*/ + arc_port_mask = <0x2>; + interrupts = <0 205 1 + 0 199 1>; + interrupt-names = "hdmi_aocecb","hdmi_aocec"; + pinctrl-names = "default","hdmitx_aocecb","cec_pin_sleep"; + pinctrl-0=<&aoceca_mux>; + pinctrl-1=<&aocecb_mux>; + pinctrl-2=<&aoceca_mux>; + reg = <0x0 0xFF80023c 0x0 0x4 + 0x0 0xFF800000 0x0 0x400>; + reg-names = "ao_exit","ao"; + }; + + p_tsensor: p_tsensor@ff634800 { + compatible = "amlogic, r1p1-tsensor"; + status = "okay"; + reg = <0x0 0xff634800 0x0 0x50>, + <0x0 0xff800268 0x0 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 35 0>; + clocks = <&clkc CLKID_TS_CLK_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + d_tsensor: d_tsensor@ff634c00 { + compatible = "amlogic, r1p1-tsensor"; + status = "okay"; + reg = <0x0 0xff634c00 0x0 0x50>, + <0x0 0xff800230 0x0 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 36 0>; + clocks = <&clkc CLKID_TS_CLK_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + s_tsensor: s_tsensor@ff635000 { + compatible = "amlogic, r1p1-tsensor"; + status = "okay"; + reg = <0x0 0xff635000 0x0 0x50>, + <0x0 0xff80026c 0x0 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 38 0>; + clocks = <&clkc CLKID_TS_CLK_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + meson_cooldev: meson-cooldev@0 { + status = "okay"; + compatible = "amlogic, meson-cooldev"; + cooling_devices { + cpufreq_cool_cluster0 { + min_state = <1000000>; + dyn_coeff = <140>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "cpufreq_cool0"; + device_type = "cpufreq"; + }; + cpucore_cool_cluster0 { + min_state = <1>; + dyn_coeff = <0>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "cpucore_cool0"; + device_type = "cpucore"; + }; + gpufreq_cool { + min_state = <400>; + dyn_coeff = <140>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "gpufreq_cool0"; + device_type = "gpufreq"; + }; + gpucore_cool { + min_state = <1>; + dyn_coeff = <0>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "gpucore_cool0"; + device_type = "gpucore"; + }; + }; + cpufreq_cool0:cpufreq_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + cpucore_cool0:cpucore_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + gpufreq_cool0:gpufreq_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + gpucore_cool0:gpucore_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + };/*meson cooling devices end*/ + + thermal-zones { + pll_thermal: pll_thermal { + polling-delay = <1000>; + polling-delay-passive = <100>; + sustainable-power = <1322>; + thermal-sensors = <&p_tsensor 0>; + trips { + pswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + pcontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + phot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + pcritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + cooling-maps { + cpufreq_cooling_map { + trip = <&pcontrol>; + cooling-device = <&cpufreq_cool0 0 11>; + contribution = <1024>; + }; + cpucore_cooling_map { + trip = <&pcontrol>; + cooling-device = <&cpucore_cool0 0 4>; + contribution = <1024>; + }; + gpufreq_cooling_map { + trip = <&pcontrol>; + cooling-device = <&gpufreq_cool0 0 4>; + contribution = <1024>; + }; + }; + }; + ddr_thermal: ddr_thermal { + polling-delay = <2000>; + polling-delay-passive = <1000>; + sustainable-power = <1322>; + thermal-sensors = <&d_tsensor 1>; + trips { + dswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + dcontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + dhot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + dcritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + }; + sar_thermal: sar_thermal { + polling-delay = <2000>; + polling-delay-passive = <1000>; + sustainable-power = <1322>; + thermal-sensors = <&s_tsensor 2>; + trips { + sswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + scontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + shot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + scritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + }; + };/*thermal zone end*/ + + cpu_opp_table0: cpu_opp_table0 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <730000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <730000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <730000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <750000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <770000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <780000>; + }; + opp06 { + opp-hz = /bits/ 64 <1404000000>; + opp-microvolt = <790000>; + }; + opp07 { + opp-hz = /bits/ 64 <1500000000>; + opp-microvolt = <800000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <810000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <850000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <900000>; + }; + opp11 { + opp-hz = /bits/ 64 <1908000000>; + opp-microvolt = <950000>; + }; + }; + + cpufreq-meson { + compatible = "amlogic, cpufreq-meson"; + pinctrl-names = "default"; + pinctrl-0 = <&pwm_ao_d_pins3>; + status = "okay"; + }; + + tuner: tuner { + compatible = "amlogic, tuner"; + status = "okay"; + tuner_cur = <0>; /* default use tuner */ + tuner_num = <1>; /* tuner number, multi tuner support */ + tuner_name_0 = "mxl661_tuner"; + tuner_i2c_adap_0 = <&i2c0>; + tuner_i2c_addr_0 = <0x60>; + tuner_xtal_0 = <0>; /* 0: 16MHz, 1: 24MHz */ + tuner_xtal_mode_0 = <0>; + /* NO_SHARE_XTAL(0) + * SLAVE_XTAL_SHARE(3) + */ + tuner_xtal_cap_0 = <25>; /* when tuner_xtal_mode = 3, set 25 */ + }; + + atv-demod { + compatible = "amlogic, atv-demod"; + status = "okay"; + tuner = <&tuner>; + btsc_sap_mode = <1>; + /* pinctrl-names="atvdemod_agc_pins"; */ + /* pinctrl-0=<&atvdemod_agc_pins>; */ + reg = <0x0 0xff656000 0x0 0x2000 /* demod reg */ + 0x0 0xff63c000 0x0 0x2000 /* hiu reg */ + 0x0 0xff634000 0x0 0x2000 /* periphs reg */ + 0x0 0xff64a000 0x0 0x2000>; /* audio reg */ + reg_23cf = <0x88188832>; + /*default:0x88188832;r840 on haier:0x48188832*/ + }; + + sd_emmc_b: sd@ffe05000 { + status = "okay"; + compatible = "amlogic, meson-mmc-tm2"; + reg = <0x0 0xffe05000 0x0 0x800>; + interrupts = <0 190 1>; + + pinctrl-names = "sd_all_pins", + "sd_clk_cmd_pins", + "sd_1bit_pins"; + pinctrl-0 = <&sd_all_pins>; + pinctrl-1 = <&sd_clk_cmd_pins>; + pinctrl-2 = <&sd_1bit_pins>; + + clocks = <&clkc CLKID_SD_EMMC_B>, + <&clkc CLKID_SD_EMMC_B_P0_COMP>, + <&clkc CLKID_FCLK_DIV2>, + <&clkc CLKID_FCLK_DIV5>, + <&xtal>; + clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + + bus-width = <4>; + cap-sd-highspeed; + cap-mmc-highspeed; + max-frequency = <100000000>; + disable-wp; + sd { + pinname = "sd"; + ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED"; + //"MMC_CAP_NONREMOVABLE"; /**ptm debug */ + f_min = <400000>; + f_max = <200000000>; + max_req_size = <0x20000>; /**128KB*/ + no_sduart = <1>; + gpio_dat3 = <&gpio GPIOC_3 GPIO_ACTIVE_HIGH>; + jtag_pin = <&gpio GPIOC_0 GPIO_ACTIVE_HIGH>; + gpio_cd = <&gpio GPIOC_10 GPIO_ACTIVE_HIGH>; + card_type = <5>; + /* 3:sdio device(ie:sdio-wifi), + * 4:SD combo (IO+mem) card + */ + }; + }; + +}; /* end of / */ + +&i2c0 { + status = "okay"; + clock-frequency = <300000>; + pinctrl-names="default"; + pinctrl-0=<&i2c0_dv_pins>; +}; + +&audiobus { + tdma:tdm@0 { + compatible = "amlogic, tm2-snd-tdma"; + #sound-dai-cells = <0>; + + dai-tdm-lane-slot-mask-in = <1 0>; + dai-tdm-lane-slot-mask-out = <1 1 1 1>; + dai-tdm-clk-sel = <0>; + + clocks = <&clkaudio CLKID_AUDIO_MCLK_A + &clkc CLKID_MPLL0 + &clkc CLKID_MPLL1 + &clkaudio CLKID_AUDIO_SPDIFOUT_A>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; + + pinctrl-names = "tdm_pins"; + pinctrl-0 = ; + + /* + * 0: tdmout_a; + * 1: tdmout_b; + * 2: tdmout_c; + * 3: spdifout; + * 4: spdifout_b; + */ + samesource_sel = <3>; + + /* In for ACODEC_ADC */ + acodec_adc = <1>; + + status = "okay"; + + /* !!!For --TV platform-- ONLY */ + Channel_Mask { + /*i2s has 4 pins, 8channel, mux output*/ + Spdif_samesource_Channel_Mask = "i2s_2/3"; + }; + }; + + tdmb:tdm@1 { + compatible = "amlogic, tm2-snd-tdmb"; + #sound-dai-cells = <0>; + + dai-tdm-lane-slot-mask-in = <1 0 0 0>; + dai-tdm-lane-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <1>; + + clocks = <&clkaudio CLKID_AUDIO_MCLK_B + &clkc CLKID_MPLL1>; + clock-names = "mclk", "clk_srcpll"; + + status = "okay"; + }; + + tdmc:tdm@2 { + compatible = "amlogic, tm2-snd-tdmc"; + #sound-dai-cells = <0>; + + dai-tdm-lane-slot-mask-in = <1 0 0 0>; + dai-tdm-lane-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <2>; + + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + + pinctrl-names = "tdm_pins"; + pinctrl-0 = ; + + status = "okay"; + }; + + pdm:pdm { + compatible = "amlogic, tm2-snd-pdm"; + #sound-dai-cells = <0>; + clocks = <&clkaudio CLKID_AUDIO_GATE_PDM + &clkc CLKID_FCLK_DIV3 + &clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_PDMIN0 + &clkaudio CLKID_AUDIO_PDMIN1>; + clock-names = "gate", + "sysclk_srcpll", + "dclk_srcpll", + "pdm_dclk", + "pdm_sysclk"; + pinctrl-names = "pdm_pins"; + pinctrl-0 = <&pdmin>; + /* mode 0~4, defalut:1 */ + filter_mode = <1>; + status = "okay"; + }; + spdifa:spdif@0 { + compatible = "amlogic, tm2-snd-spdif-a"; + #sound-dai-cells = <0>; + + clocks = <&clkc CLKID_MPLL1 + &clkc CLKID_FCLK_DIV4 + &clkaudio CLKID_AUDIO_GATE_SPDIFIN + &clkaudio CLKID_AUDIO_GATE_SPDIFOUT_A + &clkaudio CLKID_AUDIO_SPDIFIN + &clkaudio CLKID_AUDIO_SPDIFOUT_A>; + clock-names = "sysclk", "fixed_clk", "gate_spdifin", + "gate_spdifout", "clk_spdifin", "clk_spdifout"; + + interrupts = + ; + interrupt-names = "irq_spdifin"; + + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; + + pinctrl-0 = <&spdifout_a &spdifin_a>; + pinctrl-1 = <&spdifout_a_mute>; + + /* + * whether do asrc for pcm and resample a or b + * if raw data, asrc is disabled automatically + * 0: "Disable", + * 1: "Enable:32K", + * 2: "Enable:44K", + * 3: "Enable:48K", + * 4: "Enable:88K", + * 5: "Enable:96K", + * 6: "Enable:176K", + * 7: "Enable:192K", + */ + asrc_id = <0>; + auto_asrc = <3>; + + status = "okay"; + }; + + spdifb:spdif@1 { + compatible = "amlogic, tm2-snd-spdif-b"; + #sound-dai-cells = <0>; + + clocks = <&clkc CLKID_MPLL0 /*CLKID_HIFI_PLL*/ + &clkaudio CLKID_AUDIO_GATE_SPDIFOUT_B + &clkaudio CLKID_AUDIO_SPDIFOUT_B>; + clock-names = "sysclk", + "gate_spdifout", "clk_spdifout"; + + status = "okay"; + }; + + extn:extn { + compatible = "amlogic, snd-extn"; + #sound-dai-cells = <0>; + + + interrupts = + ; + interrupt-names = "irq_frhdmirx"; + + status = "okay"; + }; + + earc:earc { + compatible = "amlogic, tm2-snd-earc"; + #sound-dai-cells = <0>; + + clocks = < &clkaudio CLKID_EARCRX_CMDC + &clkaudio CLKID_EARCRX_DMAC + &clkc CLKID_FCLK_DIV5 + &clkc CLKID_FCLK_DIV3 + &clkaudio CLKID_EARCTX_CMDC + &clkaudio CLKID_EARCTX_DMAC + &clkc CLKID_FCLK_DIV5 + &clkc CLKID_FCLK_DIV3 + >; + clock-names = + "rx_cmdc", + "rx_dmac", + "rx_cmdc_srcpll", + "rx_dmac_srcpll", + "tx_cmdc", + "tx_dmac", + "tx_cmdc_srcpll", + "tx_dmac_srcpll"; + interrupts = < + GIC_SPI 88 IRQ_TYPE_EDGE_RISING + GIC_SPI 87 IRQ_TYPE_EDGE_RISING + >; + interrupt-names = "rx_cmdc", "rx_dmac"; + + status = "okay"; + }; + + aed:effect { + compatible = "amlogic, snd-effect-v2"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_EQDRC + &clkc CLKID_FCLK_DIV5 + &clkaudio CLKID_AUDIO_EQDRC>; + clock-names = "gate", "srcpll", "eqdrc"; + + /* + * 0:tdmout_a + * 1:tdmout_b + * 2:tdmout_c + * 3:spdifout + * 4:spdifout_b + */ + eqdrc_module = <0>; + /* max 0xf, each bit for one lane, usually one lane */ + lane_mask = <0x1>; + /* max 0xff, each bit for one channel */ + channel_mask = <0xff>; + + status = "disable"; + }; + + asrca: resample@0 { + compatible = "amlogic, tl1-resample-a"; + clocks = <&clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_MCLK_A + &clkaudio CLKID_AUDIO_RESAMPLE_A>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + /*same with toddr_src + * TDMIN_A, 0 + * TDMIN_B, 1 + * TDMIN_C, 2 + * SPDIFIN, 3 + * PDMIN, 4 + * NONE, + * TDMIN_LB, 6 + * LOOPBACK, 7 + */ + resample_module = <3>; + + status = "disabled"; + }; + + asrcb: resample@1 { + compatible = "amlogic, tl1-resample-b"; + + clocks = <&clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_MCLK_F + &clkaudio CLKID_AUDIO_RESAMPLE_B>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + + /*same with toddr_src + * TDMIN_A, 0 + * TDMIN_B, 1 + * TDMIN_C, 2 + * SPDIFIN, 3 + * PDMIN, 4 + * NONE, + * TDMIN_LB, 6 + * LOOPBACK, 7 + */ + resample_module = <3>; + + status = "disabled"; + }; + + vad:vad { + compatible = "amlogic, snd-vad"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_TOVAD + &clkc CLKID_FCLK_DIV5 + &clkaudio CLKID_AUDIO_VAD>; + clock-names = "gate", "pll", "clk"; + + interrupts = ; + interrupt-names = "irq_wakeup", "irq_frame_sync"; + + /* + * Data src sel: + * 0: tdmin_a; + * 1: tdmin_b; + * 2: tdmin_c; + * 3: spdifin; + * 4: pdmin; + * 5: loopback_b; + * 6: tdmin_lb; + * 7: loopback_a; + */ + src = <4>; + + /* + * deal with hot word in user space or kernel space + * 0: in user space + * 1: in kernel space + */ + level = <1>; + + status = "disabled"; + }; +}; /* end of audiobus */ + +&pinctrl_periphs { + /* audio pin mux */ + + tdma_mclk: tdma_mclk { + mux { /* GPIOH_4 */ + groups = "mclk0_h"; + function = "mclk0"; + }; + }; + + tdmout_a: tdmout_a { + mux { /* GPIOH_5, GPIOH_6, GPIOH_7, GPIOH_8*/ + groups = "tdma_fs_h", + "tdma_sclk_h", + "tdma_dout0_h", + "tdma_dout1_h"; + function = "tdma_out"; + bias-pull-down; + }; + }; + + tdmin_a: tdmin_a { + mux { /* GPIOH_11, GPIOH_12 */ + groups = "tdma_din0_h", + "tdma_din1_h"; + function = "tdma_in"; + }; + }; + + tdmout_c: tdmout_c { + mux { /* GPIODV_7, GPIODV_8, GPIODV_9 */ + groups = "tdmc_sclk", + "tdmc_fs", + "tdmc_dout0"; + function = "tdmc_out"; + }; + }; + + tdmin_c: tdmin_c { + mux { /* GPIODV_10 */ + groups = "tdmc_din1"; + function = "tdmc_in"; + }; + }; + + spdifin_a: spdifin_a { + mux { /* GPIODV_5 */ + groups = "spdif_in"; + function = "spdif_in"; + }; + }; + + spdifout_a: spdifout_a { + mux { /* GPIODV_4 */ + groups = "spdif_out_dv4"; + function = "spdif_out"; + }; + }; + + spdifout_a_mute: spdifout_a_mute { + mux { /* GPIODV_4 */ + groups = "GPIODV_4"; + function = "gpio_periphs"; + }; + }; + + pdmin: pdmin { + mux { /* GPIOZ_7, GPIOZ_8, pdm_din2_z4 */ + groups = "pdm_dclk_z", + "pdm_din0_z", + "pdm_din2_z4"; + function = "pdm"; + }; + }; + + +}; /* end of pinctrl_periphs */ + +&pinctrl_aobus { + spdifout: spdifout { + mux { /* gpiao_10 */ + groups = "spdif_out_ao"; + function = "spdif_out_ao"; + }; + }; +}; /* end of pinctrl_aobus */ + +&audio_data{ + status = "okay"; +}; + +&i2c2 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&i2c2_z_pins>; + clock-frequency = <400000>; + + tas5805: tas5805@36 { + compatible = "ti,tas5805"; + #sound-dai-cells = <0>; + codec_name = "tas5805"; + reg = <0x0 0x2d>; + status = "disable"; + }; + + ad82584f: ad82584f@62 { + compatible = "ESMT, ad82584f"; + #sound-dai-cells = <0>; + reg = <0x0 0x31>; + status = "disabled"; + reset_pin = <&gpio_ao GPIOAO_6 0>; + }; + +}; + +&sd_emmc_c { + status = "okay"; + emmc { + caps = "MMC_CAP_8_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + "MMC_CAP_1_8V_DDR", + "MMC_CAP_HW_RESET", + "MMC_CAP_ERASE", + "MMC_CAP_CMD23"; + caps2 = "MMC_CAP2_HS200"; + /* "MMC_CAP2_HS400";*/ + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&spifc { + status = "disabled"; + spi-nor@0 { + cs_gpios = <&gpio BOOT_13 GPIO_ACTIVE_HIGH>; + }; +}; + +&slc_nand { + status = "disabled"; + plat-names = "bootloader", "nandnormal"; + plat-num = <2>; + plat-part-0 = <&bootloader>; + plat-part-1 = <&nandnormal>; + bootloader: bootloader{ + enable_pad = "ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <1>; + part_num = <0>; + rb_detect = <1>; + }; + nandnormal: nandnormal{ + enable_pad = "ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + plane_mode = "twoplane"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <2>; + part_num = <3>; + partition = <&nand_partitions>; + rb_detect = <1>; + }; + nand_partitions:nand_partition{ + /* + * if bl_mode is 1, tpl size was generate by + * fip_copies * fip_size which + * will not skip bad when calculating + * the partition size; + * + * if bl_mode is 0, + * tpl partition must be comment out. + */ + tpl{ + offset=<0x0 0x0>; + size=<0x0 0x0>; + }; + logo{ + offset=<0x0 0x0>; + size=<0x0 0x200000>; + }; + recovery{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + boot{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + system{ + offset=<0x0 0x0>; + size=<0x0 0x4000000>; + }; + data{ + offset=<0xffffffff 0xffffffff>; + size=<0x0 0x0>; + }; + }; +}; + +ðmac { + status = "okay"; + pinctrl-names = "internal_eth_pins"; + pinctrl-0 = <&internal_eth_pins>; + mc_val = <0x4be04>; + + internal_phy=<1>; +}; + +&uart_A { + status = "okay"; +}; + +&dwc3 { + status = "okay"; +}; + +&usb2_phy_v2 { + status = "okay"; + portnum = <3>; +}; + +&usb3_phy_v2 { + status = "okay"; + portnum = <2>; + portconfig-30 = <1>; + portconfig-31 = <1>; +}; + +&usb_otg { + status = "okay"; + otg = <0>; +}; + +&dwc2_a { + status = "okay"; + /** 0: normal, 1: otg+dwc3 host only, 2: otg+dwc3 device only*/ + controller-type = <1>; +}; + +&pcie_A { + reset-gpio = <&gpio_ao GPIOAO_11 GPIO_ACTIVE_HIGH>; + status = "disable"; +}; + +&pcie_B { + /* pcie b reset gpio is the oe pad, must be changed */ + reset-gpio = <&gpio GPIOH_22 GPIO_ACTIVE_HIGH>; + status = "disable"; +}; + +&spicc0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&spicc0_pins_h>; + cs-gpios = <&gpio GPIOH_20 0>; +}; + +&meson_fb { + status = "okay"; + display_size_default = <1920 1080 1920 2160 32>; + mem_size = <0x00800000 0x1980000 0x100000 0x100000 0x800000>; + logo_addr = "0x7f800000"; + mem_alloc = <0>; + pxp_mode = <0>; /** 0:normal mode 1:pxp mode */ +}; + +&pwm_AO_cd { + status = "okay"; +}; + +&saradc { + status = "okay"; +}; + +&i2c1 { + status = "okay"; + clock-frequency = <300000>; + pinctrl-names="default"; + pinctrl-0=<&i2c1_h_pins>; + + lcd_extern_i2c0: lcd_extern_i2c@0 { + compatible = "lcd_ext, i2c"; + dev_name = "i2c_T5800Q"; + reg = <0x0 0x1c>; + status = "okay"; + }; + + lcd_extern_i2c1: lcd_extern_i2c@1 { + compatible = "lcd_ext, i2c"; + dev_name = "i2c_ANX6862"; + reg = <0x0 0x20>; + status = "okay"; + }; + + lcd_extern_i2c2: lcd_extern_i2c@2 { + compatible = "lcd_ext, i2c"; + dev_name = "i2c_ANX7911"; + reg = <0x0 0x74>; + status = "okay"; + }; +}; + +&efuse { + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab301.dts b/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab301.dts new file mode 100644 index 000000000000..735d303f8cf7 --- /dev/null +++ b/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab301.dts @@ -0,0 +1,1996 @@ +/* + * arch/arm64/boot/dts/amlogic/tm2_t962e2_ab301.dts + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +/dts-v1/; + +#include "mesontm2.dtsi" +#include "partition_mbox_normal.dtsi" +#include "mesontm2_t962x3_ab301-panel.dtsi" + +/ { + model = "Amlogic TM2 T962E2 AB301"; + amlogic-dt-id = "tm2_t962E2_ab301"; + compatible = "amlogic, tm2_t962e2_ab301"; + + aliases { + serial0 = &uart_AO; + serial1 = &uart_A; + serial2 = &uart_B; + serial3 = &uart_C; + serial4 = &uart_AO_B; + tsensor0 = &p_tsensor; + tsensor1 = &d_tsensor; + tsensor2 = &s_tsensor; + i2c0 = &i2c0; + i2c1 = &i2c1; + i2c2 = &i2c2; + i2c3 = &i2c3; + i2c4 = &i2c_AO; + }; + + memory@00000000 { + device_type = "memory"; + linux,usable-memory = <0x0 0x0 0x0 0x80000000>; + }; + + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + /* global autoconfigured region for contiguous allocations */ + ramoops@0x07400000 { + compatible = "ramoops"; + reg = <0x0 0x07400000 0x0 0x00100000>; + record-size = <0x8000>; + console-size = <0x8000>; + ftrace-size = <0x20000>; + }; + + secmon_reserved: linux,secmon { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x400000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x05000000 0x0 0x400000>; + }; + + logo_reserved:linux,meson-fb { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x800000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x7f800000 0x0 0x800000>; + }; + + lcd_tcon_reserved:linux,lcd_tcon { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0xc00000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x7ec00000 0x0 0xc00000>; + }; + + codec_mm_cma:linux,codec_mm_cma { + compatible = "shared-dma-pool"; + reusable; + /* ion_codec_mm max can alloc size 80M*/ + size = <0x0 0x13400000>; + alignment = <0x0 0x400000>; + linux,contiguous-region; + }; + + lcd_tcon_reserved:linux,lcd_tcon { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0xc00000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x7ec00000 0x0 0xc00000>; + }; + + /* codec shared reserved */ + codec_mm_reserved:linux,codec_mm_reserved { + compatible = "amlogic, codec-mm-reserved"; + size = <0x0 0x0>; + alignment = <0x0 0x100000>; + //no-map; + }; + + ion_cma_reserved:linux,ion-dev { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x2000000>; + alignment = <0x0 0x400000>; + }; + + /* vdin0 CMA pool */ + //vdin0_cma_reserved:linux,vdin0_cma { + // compatible = "shared-dma-pool"; + // reusable; + /* 3840x2160x4x4 ~=128 M */ + // size = <0x0 0xc400000>; + // alignment = <0x0 0x400000>; + //}; + + /* vdin1 CMA pool */ + vdin1_cma_reserved:linux,vdin1_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16 M */ + size = <0x0 0x1400000>; + alignment = <0x0 0x400000>; + }; + + /*demod_reserved:linux,demod { + * compatible = "amlogic, demod-mem"; + * size = <0x0 0x800000>; //8M //100m 0x6400000 + * alloc-ranges = <0x0 0x0 0x0 0x30000000>; + * //multi-use; + * //no-map; + *}; + */ + + demod_cma_reserved:linux,demod_cma { + compatible = "shared-dma-pool"; + reusable; + /* 8M */ + size = <0x0 0x0800000>; + alignment = <0x0 0x400000>; + }; + + /*di CMA pool */ + di_cma_reserved:linux,di_cma { + compatible = "shared-dma-pool"; + reusable; + /* buffer_size = 3621952(yuv422 8bit) + * | 4736064(yuv422 10bit) + * | 4074560(yuv422 10bit full pack mode) + * 10x3621952=34.6M(0x23) support 8bit + * 10x4736064=45.2M(0x2e) support 12bit + * 10x4074560=40M(0x28) support 10bit + */ + size = <0x0 0x02800000>; + alignment = <0x0 0x400000>; + }; + + /* for hdmi rx emp use */ + hdmirx_emp_cma_reserved:linux,emp_cma { + compatible = "shared-dma-pool"; + /*linux,phandle = <5>;*/ + reusable; + /* 4M for emp to ddr */ + /* 32M for tmds to ddr */ + size = <0x0 0x2000000>; + alignment = <0x0 0x400000>; + }; + + /* POST PROCESS MANAGER */ + ppmgr_reserved:linux,ppmgr { + compatible = "amlogic, ppmgr_memory"; + size = <0x0 0x0>; + }; + + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x0>; + alignment = <0x0 0x0>; + linux,contiguous-region; + }; + }; /* end of reserved-memory */ + galcore { + status = "okay"; + }; + codec_mm { + compatible = "amlogic, codec, mm"; + status = "okay"; + memory-region = <&codec_mm_cma &codec_mm_reserved>; + }; + + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + + ppmgr { + compatible = "amlogic, ppmgr"; + memory-region = <&ppmgr_reserved>; + status = "okay"; + }; + + deinterlace { + compatible = "amlogic, deinterlace"; + status = "okay"; + /* 0:use reserved; 1:use cma; 2:use cma as reserved */ + flag_cma = <1>; + //memory-region = <&di_reserved>; + memory-region = <&di_cma_reserved>; + interrupts = <0 46 1 + 0 40 1>; + interrupt-names = "pre_irq", "post_irq"; + clocks = <&clkc CLKID_VPU_CLKB_TMP_COMP>, + <&clkc CLKID_VPU_CLKB_COMP>; + clock-names = "vpu_clkb_tmp_composite", + "vpu_clkb_composite"; + clock-range = <334 667>; + /* buffer-size = <3621952>;(yuv422 8bit) */ + buffer-size = <4074560>;/*yuv422 fullpack*/ + /* reserve-iomap = "true"; */ + /* if enable nr10bit, set nr10bit-support to 1 */ + post-wr-support = <1>; + nr10bit-support = <1>; + nrds-enable = <1>; + pps-enable = <1>; + }; + + vout { + compatible = "amlogic, vout"; + status = "okay"; + fr_auto_policy = <0>; + }; + + /* Audio Related start */ + pdm_codec:dummy { + #sound-dai-cells = <0>; + compatible = "amlogic, pdm_dummy_codec"; + status = "okay"; + }; + + dummy_codec:dummy { + #sound-dai-cells = <0>; + compatible = "amlogic, aml_dummy_codec"; + status = "okay"; + }; + + tl1_codec:codec { + #sound-dai-cells = <0>; + compatible = "amlogic, tl1_acodec"; + status = "okay"; + reg = <0x0 0xff632000 0x0 0x1c>; + tdmout_index = <0>; + tdmin_index = <0>; + dat1_ch_sel = <1>; + }; + + aml_dtv_demod { + compatible = "amlogic, ddemod-tl1"; + dev_name = "aml_dtv_demod"; + status = "okay"; + + //pinctrl-names="dtvdemod_agc"; + //pinctrl-0=<&dtvdemod_agc>; + + clocks = <&clkc CLKID_DAC_CLK>; + clock-names = "vdac_clk_gate"; + + reg = <0x0 0xff650000 0x0 0x4000 /*dtv demod base*/ + 0x0 0xff63c000 0x0 0x2000 /*hiu reg base*/ + 0x0 0xff800000 0x0 0x1000 /*io_aobus_base*/ + 0x0 0xffd01000 0x0 0x1000 /*reset*/ + >; + + dtv_demod0_mem = <0>; // need move to aml_dtv_demod ? + spectrum = <1>; + cma_flag = <1>; + cma_mem_size = <8>; + memory-region = <&demod_cma_reserved>;//<&demod_reserved>; + }; + + auge_sound { + compatible = "amlogic, tm2-sound-card"; + aml-audio-card,name = "AML-AUGESOUND"; + + avout_mute-gpios = <&gpio GPIODV_3 GPIO_ACTIVE_HIGH>; + + aml-audio-card,dai-link@0 { + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdma>; + frame-master = <&tdma>; + /* slave mode */ + /* + * bitclock-master = <&tdmacodec>; + * frame-master = <&tdmacodec>; + */ + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-i2s"; + tdmacpu: cpu { + sound-dai = <&tdma>; + dai-tdm-slot-tx-mask = + <1 1>; + dai-tdm-slot-rx-mask = + <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmacodec: codec { + //sound-dai = <&dummy_codec>; + prefix-names = "AMP"; + sound-dai = <&tas5805 &tl1_codec>; + }; + }; + + aml-audio-card,dai-link@1 { + + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdmb>; + frame-master = <&tdmb>; + /* slave mode */ + //bitclock-master = <&tdmbcodec>; + //frame-master = <&tdmbcodec>; + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-pcm"; + cpu { + sound-dai = <&tdmb>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + /* + * dai-tdm-slot-tx-mask = + * <1 1 1 1 1 1 1 1>; + * dai-tdm-slot-rx-mask = + * <1 1 1 1 1 1 1 1>; + * dai-tdm-slot-num = <8>; + */ + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmbcodec: codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@2 { + + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdmc>; + frame-master = <&tdmc>; + /* slave mode */ + //bitclock-master = <&tdmccodec>; + //frame-master = <&tdmccodec>; + /* suffix-name, sync with android audio hal used for */ + //suffix-name = "alsaPORT-tdm"; + cpu { + sound-dai = <&tdmc>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmccodec: codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@3 { + mclk-fs = <64>; + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-pdm"; + cpu { + sound-dai = <&pdm>; + }; + codec { + sound-dai = <&pdm_codec>; + }; + }; + + aml-audio-card,dai-link@4 { + mclk-fs = <128>; + continuous-clock; + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-spdif"; + cpu { + sound-dai = <&spdifa>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@5 { + mclk-fs = <128>; + suffix-name = "alsaPORT-spdifb"; + cpu { + sound-dai = <&spdifb>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@6 { + mclk-fs = <256>; + suffix-name = "alsaPORT-tv"; + cpu { + sound-dai = <&extn>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@7 { + mclk-fs = <256>; + suffix-name = "alsaPORT-earc"; + cpu { + sound-dai = <&earc>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + }; + /* Audio Related end */ + + dvb { + compatible = "amlogic, dvb"; + status = "okay"; + fe0_mode = "internal"; + fe0_tuner = <&tuner>; + + /*"parallel","serial","disable"*/ + ts2 = "parallel"; + ts2_control = <0>; + ts2_invert = <0>; + interrupts = <0 23 1 + 0 5 1 + 0 53 1 + 0 19 1 + 0 25 1 + 0 17 1>; + interrupt-names = "demux0_irq", + "demux1_irq", + "demux2_irq", + "dvr0_irq", + "dvr1_irq", + "dvr2_irq"; + clocks = <&clkc CLKID_DEMUX + &clkc CLKID_ASYNC_FIFO + &clkc CLKID_AHB_ARB0 +/* &clkc CLKID_DOS_PARSER>;*/ + &clkc CLKID_U_PARSER>; + clock-names = "demux", "asyncfifo", "ahbarb0", "uparsertop"; + }; + + tvafe_avin_detect { + compatible = "amlogic, tl1_tvafe_avin_detect"; + status = "okay"; + device_mask = <1>;/*bit0:ch1;bit1:ch2*/ + interrupts = <0 12 1>, + <0 13 1>; + }; + + amlvecm { + compatible = "amlogic, vecm"; + dev_name = "aml_vecm"; + status = "okay"; + gamma_en = <1>;/*1:enabel ;0:disable*/ + wb_en = <1>;/*1:enabel ;0:disable*/ + cm_en = <0>;/*1:enabel ;0:disable*/ + wb_sel = <1>;/*1:mtx ;0:gainoff*/ + vlock_en = <1>;/*1:enable;0:disable*/ + vlock_mode = <0x4>; + /* vlock work mode: + *bit0:auto ENC + *bit1:auto PLL + *bit2:manual PLL + *bit3:manual ENC + *bit4:manual soft ENC + *bit5:manual MIX PLL ENC + */ + vlock_pll_m_limit = <1>; + vlock_line_limit = <3>; + }; + + amdolby_vision { + compatible = "amlogic, dolby_vision_tm2"; + dev_name = "aml_amdolby_vision_driver"; + status = "okay"; + tv_mode = <1>;/*1:enabel ;0:disable*/ + }; + + vdin@0 { + compatible = "amlogic, vdin"; + /*memory-region = <&vdin0_cma_reserved>;*/ + status = "okay"; + /*bit0:(1:share with codec_mm;0:cma alone) + *bit8:(1:alloc in discontinus way;0:alone in continuous way) + */ + flag_cma = <0x101>; + /*MByte, if 10bit disable: 64M(YUV422), + *if 10bit enable: 64*1.5 = 96M(YUV422) + *if support 4K2K-YUV444-10bit-WR:3840*2160*4*4 ~= 128M + *if support 4K2K-YUV422-10bit-wr:3840*2160*3*4 ~= 96M + *if support 4K2K-YUV422-8BIT-WR:3840*2160*2*4 ~= 64M + *if support 1080p-YUV422-8BIT-WR:1920*1080*2*4 ~= 16M + */ + cma_size = <160>; + interrupts = <0 83 1>; + rdma-irq = <2>; + clocks = <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_VDIN_MEAS_COMP>; + clock-names = "fclk_div5", "cts_vdin_meas_clk"; + vdin_id = <0>; + /*vdin write mem color depth support: + * bit0:support 8bit + * bit1:support 9bit + * bit2:support 10bit + * bit3:support 12bit + * bit4:support yuv422 10bit full pack mode (from txl new add) + * bit8:use 8bit at 4k_50/60hz_10bit + * bit9:use 10bit at 4k_50/60hz_10bit + */ + tv_bit_mode = <0x215>; + /* afbce_bit_mode: (amlogic frame buff compression encoder) + * bit 0~3: + * 0 -- normal mode, not use afbce + * 1 -- use afbce non-mmu mode + * 2 -- use afbce mmu mode + * bit 4: + * 0 -- afbce compression-lossy disable + * 1 -- afbce compression-lossy enable + */ + afbce_bit_mode = <0x1>; + }; + + vdin@1 { + compatible = "amlogic, vdin"; + memory-region = <&vdin1_cma_reserved>; + status = "okay"; + /*bit0:(1:share with codec_mm;0:cma alone) + *bit8:(1:alloc in discontinus way;0:alone in continuous way) + */ + flag_cma = <0>; + interrupts = <0 85 1>; + rdma-irq = <4>; + clocks = <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_VDIN_MEAS_COMP>; + clock-names = "fclk_div5", "cts_vdin_meas_clk"; + vdin_id = <1>; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + */ + tv_bit_mode = <0x15>; + }; + + tvafe { + compatible = "amlogic, tvafe-tl1"; + /*memory-region = <&tvafe_cma_reserved>;*/ + status = "okay"; + flag_cma = <1>;/*1:share with codec_mm;0:cma alone*/ + cma_size = <5>;/*MByte*/ + reg = <0x0 0xff654000 0x0 0x2000>;/*tvafe reg base*/ + reserve-iomap = "true"; + tvafe_id = <0>; + //pinctrl-names = "default"; + /*!!particular sequence, no more and no less!!!*/ + tvafe_pin_mux = < + 3 /* TVAFE_CVBS_IN2, CVBS_IN0 = 0 */ + 1 /* TVAFE_CVBS_IN0, CVBS_IN1 */ + 2 /* TVAFE_CVBS_IN1, CVBS_IN2 */ + 4 /* TVAFE_CVBS_IN3, CVBS_IN3 */ + >; + clocks = <&clkc CLKID_DAC_CLK>; + clock-names = "vdac_clk_gate"; + }; + + vbi { + compatible = "amlogic, vbi"; + status = "okay"; + interrupts = <0 83 1>; + }; + + cvbsout { + compatible = "amlogic, cvbsout-tl1"; + status = "disabled"; + clocks = <&clkc CLKID_VCLK2_ENCI + &clkc CLKID_VCLK2_VENCI0 + &clkc CLKID_VCLK2_VENCI1 + &clkc CLKID_DAC_CLK>; + clock-names = "venci_top_gate", + "venci_0_gate", + "venci_1_gate", + "vdac_clk_gate"; + /* clk path */ + /* 0:vid_pll vid2_clk */ + /* 1:gp0_pll vid2_clk */ + /* 2:vid_pll vid1_clk */ + /* 3:gp0_pll vid1_clk */ + clk_path = <0>; + + /* performance: reg_address, reg_value */ + /* tl1 */ + performance = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x8080 + 0x1b05 0xfd + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + performance_sarft = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x0 + 0x1b05 0x9 + 0x1c59 0xfc48 + 0xffff 0x0>; /* ending flag */ + performance_revB_telecom = <0x1bf0 0x9 + 0x1b56 0x546 + 0x1b12 0x8080 + 0x1b05 0x9 + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + }; + + /* for external keypad */ + adc_keypad { + compatible = "amlogic, adc_keypad"; + status = "okay"; + key_name = "power","up","down","enter","left","right","home"; + key_num = <7>; + io-channels = <&saradc SARADC_CH2>,<&saradc SARADC_CH3>; + io-channel-names = "key-chan-2", "key-chan-3"; + key_chan = ; + key_code = <116 103 108 28 105 106 102>; + key_val = <0 143 266 389 512 143 266>; //val=voltage/1800mV*1023 + key_tolerance = <40 40 40 40 40 40 40>; +}; + + unifykey { + compatible = "amlogic, unifykey"; + status = "okay"; + + unifykey-num = <21>; + unifykey-index-0 = <&keysn_0>; + unifykey-index-1 = <&keysn_1>; + unifykey-index-2 = <&keysn_2>; + unifykey-index-3 = <&keysn_3>; + unifykey-index-4 = <&keysn_4>; + unifykey-index-5 = <&keysn_5>; + unifykey-index-6 = <&keysn_6>; + unifykey-index-7 = <&keysn_7>; + unifykey-index-8 = <&keysn_8>; + unifykey-index-9 = <&keysn_9>; + unifykey-index-10= <&keysn_10>; + unifykey-index-11 = <&keysn_11>; + unifykey-index-12 = <&keysn_12>; + unifykey-index-13 = <&keysn_13>; + unifykey-index-14 = <&keysn_14>; + unifykey-index-15 = <&keysn_15>; + unifykey-index-16 = <&keysn_16>; + unifykey-index-17 = <&keysn_17>; + unifykey-index-18 = <&keysn_18>; + unifykey-index-19 = <&keysn_19>; + unifykey-index-20 = <&keysn_20>; + + keysn_0: key_0{ + key-name = "usid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_1:key_1{ + key-name = "mac"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_2:key_2{ + key-name = "hdcp"; + key-device = "secure"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_3:key_3{ + key-name = "secure_boot_set"; + key-device = "efuse"; + key-permit = "write"; + }; + keysn_4:key_4{ + key-name = "mac_bt"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_5:key_5{ + key-name = "mac_wifi"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_6:key_6{ + key-name = "hdcp2_tx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_7:key_7{ + key-name = "hdcp2_rx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_8:key_8{ + key-name = "widevinekeybox"; + key-device = "secure"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_9:key_9{ + key-name = "deviceid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_10:key_10{ + key-name = "hdcp22_fw_private"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_11:key_11{ + key-name = "hdcp22_rx_private"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_12:key_12{ + key-name = "hdcp22_rx_fw"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_13:key_13{ + key-name = "hdcp14_rx"; + key-device = "normal"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_14:key_14{ + key-name = "prpubkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_15:key_15{ + key-name = "prprivkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_16:key_16{ + key-name = "lcd"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_17:key_17{ + key-name = "lcd_extern"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_18:key_18{ + key-name = "backlight"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_19:key_19{ + key-name = "lcd_tcon"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_20:key_20{ + key-name = "attestationkeybox";// attestation key + key-device = "secure"; + key-permit = "read","write","del"; + }; + }; /* End unifykey */ + + amlvideo2_0 { + compatible = "amlogic, amlvideo2"; + dev_name = "amlvideo2"; + status = "okay"; + amlvideo2_id = <0>; + cma_mode = <1>; + }; + + amlvideo2_1 { + compatible = "amlogic, amlvideo2"; + dev_name = "amlvideo2"; + status = "okay"; + amlvideo2_id = <1>; + cma_mode = <1>; + }; + + hdmirx { + compatible = "amlogic, hdmirx_tl1"; + #address-cells=<1>; + #size-cells=<1>; + memory-region = <&hdmirx_emp_cma_reserved>; + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&hdmirx_a_mux &hdmirx_b_mux + &hdmirx_c_mux>; + repeat = <0>; + interrupts = <0 41 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clkc CLKID_HDMIRX_MODET_COMP>, + <&clkc CLKID_HDMIRX_CFG_COMP>, + <&clkc CLKID_HDMIRX_ACR_COMP>, + <&clkc CLKID_HDMIRX_METER_COMP>, + <&clkc CLKID_HDMIRX_AXI_COMP>, + <&xtal>, + <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_FCLK_DIV7>, + <&clkc CLKID_HDCP22_SKP_COMP>, + <&clkc CLKID_HDCP22_ESM_COMP>; + // <&clkc CLK_AUD_PLL2FS>, + // <&clkc CLK_AUD_PLL4FS>, + // <&clkc CLK_AUD_OUT>; + clock-names = "hdmirx_modet_clk", + "hdmirx_cfg_clk", + "hdmirx_acr_ref_clk", + "cts_hdmirx_meter_clk", + "cts_hdmi_axi_clk", + "xtal", + "fclk_div5", + "fclk_div7", + "hdcp_rx22_skp", + "hdcp_rx22_esm"; + // "hdmirx_aud_pll2fs", + // "hdmirx_aud_pll4f", + // "clk_aud_out"; + hdmirx_id = <0>; + en_4k_2_2k = <0>; + hpd_low_cec_off = <1>; + /* bit4: enable feature, bit3~0: port number */ + disable_port = <0x0>; + /* MAP_ADDR_MODULE_CBUS */ + /* MAP_ADDR_MODULE_HIU */ + /* MAP_ADDR_MODULE_HDMIRX_CAPB3 */ + /* MAP_ADDR_MODULE_SEC_AHB */ + /* MAP_ADDR_MODULE_SEC_AHB2 */ + /* MAP_ADDR_MODULE_APB4 */ + /* MAP_ADDR_MODULE_TOP */ + reg = < 0x0 0x0 0x0 0x0 + 0x0 0xff63C000 0x0 0x2000 + 0x0 0xffe0d000 0x0 0x2000 + 0x0 0x0 0x0 0x0 + 0x0 0x0 0x0 0x0 + 0x0 0x0 0x0 0x0 + 0x0 0xff610000 0x0 0xa000>; + }; + + aocec: aocec { + compatible = "amlogic, aocec-tm2"; + /*device_name = "aocec";*/ + status = "okay"; + vendor_name = "Amlogic"; /* Max Chars: 8 */ + /* Refer to the following URL at: + * http://standards.ieee.org/develop/regauth/oui/oui.txt + */ + vendor_id = <0x000000>; + product_desc = "TM2"; /* Max Chars: 16 */ + cec_osd_string = "AML_TV"; /* Max Chars: 14 */ + port_num = <3>; + ee_cec; + /*cec_sel = <2>;*/ + output = <1>; /*output port number*/ + arc_port_mask = <0x2>; + interrupts = <0 205 1 + 0 199 1>; + interrupt-names = "hdmi_aocecb","hdmi_aocec"; + pinctrl-names = "default","hdmitx_aocecb","cec_pin_sleep"; + pinctrl-0=<&aoceca_mux>; + pinctrl-1=<&aocecb_mux>; + pinctrl-2=<&aoceca_mux>; + reg = <0x0 0xFF80023c 0x0 0x4 + 0x0 0xFF800000 0x0 0x400>; + reg-names = "ao_exit","ao"; + }; + + p_tsensor: p_tsensor@ff634800 { + compatible = "amlogic, r1p1-tsensor"; + status = "okay"; + reg = <0x0 0xff634800 0x0 0x50>, + <0x0 0xff800268 0x0 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 35 0>; + clocks = <&clkc CLKID_TS_CLK_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + d_tsensor: d_tsensor@ff634c00 { + compatible = "amlogic, r1p1-tsensor"; + status = "okay"; + reg = <0x0 0xff634c00 0x0 0x50>, + <0x0 0xff800230 0x0 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 36 0>; + clocks = <&clkc CLKID_TS_CLK_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + s_tsensor: s_tsensor@ff635000 { + compatible = "amlogic, r1p1-tsensor"; + status = "okay"; + reg = <0x0 0xff635000 0x0 0x50>, + <0x0 0xff80026c 0x0 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 38 0>; + clocks = <&clkc CLKID_TS_CLK_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + meson_cooldev: meson-cooldev@0 { + status = "okay"; + compatible = "amlogic, meson-cooldev"; + cooling_devices { + cpufreq_cool_cluster0 { + min_state = <1000000>; + dyn_coeff = <140>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "cpufreq_cool0"; + device_type = "cpufreq"; + }; + cpucore_cool_cluster0 { + min_state = <1>; + dyn_coeff = <0>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "cpucore_cool0"; + device_type = "cpucore"; + }; + gpufreq_cool { + min_state = <400>; + dyn_coeff = <140>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "gpufreq_cool0"; + device_type = "gpufreq"; + }; + gpucore_cool { + min_state = <1>; + dyn_coeff = <0>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "gpucore_cool0"; + device_type = "gpucore"; + }; + }; + cpufreq_cool0:cpufreq_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + cpucore_cool0:cpucore_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + gpufreq_cool0:gpufreq_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + gpucore_cool0:gpucore_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + };/*meson cooling devices end*/ + + thermal-zones { + pll_thermal: pll_thermal { + polling-delay = <1000>; + polling-delay-passive = <100>; + sustainable-power = <1322>; + thermal-sensors = <&p_tsensor 0>; + trips { + pswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + pcontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + phot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + pcritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + cooling-maps { + cpufreq_cooling_map { + trip = <&pcontrol>; + cooling-device = <&cpufreq_cool0 0 11>; + contribution = <1024>; + }; + cpucore_cooling_map { + trip = <&pcontrol>; + cooling-device = <&cpucore_cool0 0 4>; + contribution = <1024>; + }; + gpufreq_cooling_map { + trip = <&pcontrol>; + cooling-device = <&gpufreq_cool0 0 4>; + contribution = <1024>; + }; + }; + }; + ddr_thermal: ddr_thermal { + polling-delay = <2000>; + polling-delay-passive = <1000>; + sustainable-power = <1322>; + thermal-sensors = <&d_tsensor 1>; + trips { + dswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + dcontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + dhot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + dcritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + }; + sar_thermal: sar_thermal { + polling-delay = <2000>; + polling-delay-passive = <1000>; + sustainable-power = <1322>; + thermal-sensors = <&s_tsensor 2>; + trips { + sswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + scontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + shot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + scritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + }; + }; /*thermal zone end*/ + + cpu_opp_table0: cpu_opp_table0 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <730000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <730000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <730000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <750000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <770000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <780000>; + }; + opp06 { + opp-hz = /bits/ 64 <1404000000>; + opp-microvolt = <790000>; + }; + opp07 { + opp-hz = /bits/ 64 <1500000000>; + opp-microvolt = <800000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <810000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <850000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <900000>; + }; + opp11 { + opp-hz = /bits/ 64 <1908000000>; + opp-microvolt = <950000>; + }; + }; + + cpufreq-meson { + compatible = "amlogic, cpufreq-meson"; + pinctrl-names = "default"; + pinctrl-0 = <&pwm_ao_d_pins3>; + status = "okay"; + }; + + tuner: tuner { + compatible = "amlogic, tuner"; + status = "okay"; + tuner_cur = <0>; /* default use tuner */ + tuner_num = <1>; /* tuner number, multi tuner support */ + tuner_name_0 = "mxl661_tuner"; + tuner_i2c_adap_0 = <&i2c0>; + tuner_i2c_addr_0 = <0x60>; + tuner_xtal_0 = <1>; /* 0: 16MHz, 1: 24MHz */ + tuner_xtal_mode_0 = <3>; + /* NO_SHARE_XTAL(0) + * SLAVE_XTAL_SHARE(3) + */ + tuner_xtal_cap_0 = <25>; /* when tuner_xtal_mode = 3, set 25 */ + }; + + atv-demod { + compatible = "amlogic, atv-demod"; + status = "okay"; + tuner = <&tuner>; + btsc_sap_mode = <1>; + /* pinctrl-names="atvdemod_agc_pins"; */ + /* pinctrl-0=<&atvdemod_agc_pins>; */ + reg = <0x0 0xff656000 0x0 0x2000 /* demod reg */ + 0x0 0xff63c000 0x0 0x2000 /* hiu reg */ + 0x0 0xff634000 0x0 0x2000 /* periphs reg */ + 0x0 0xff64a000 0x0 0x2000>; /* audio reg */ + reg_23cf = <0x88188832>; + /*default:0x88188832;r840 on haier:0x48188832*/ + }; + + bt-dev{ + compatible = "amlogic, bt-dev"; + status = "okay"; + gpio_reset = <&gpio GPIOC_13 GPIO_ACTIVE_HIGH>; + }; + + wifi{ + compatible = "amlogic, aml_wifi"; + status = "okay"; + interrupt_pin = <&gpio GPIOC_12 GPIO_ACTIVE_HIGH>; + irq_trigger_type = "GPIO_IRQ_LOW"; + dhd_static_buf; //dhd_static_buf support + power_on_pin = <&gpio GPIOC_11 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&pwm_b_pins1>; + pwm_config = <&wifi_pwm_conf>; + }; + + wifi_pwm_conf:wifi_pwm_conf{ + pwm_channel1_conf { + pwms = <&pwm_ab MESON_PWM_1 30541 0>; + duty-cycle = <15270>; + times = <8>; + }; + pwm_channel2_conf { + pwms = <&pwm_ab MESON_PWM_3 30500 0>; + duty-cycle = <15250>; + times = <12>; + }; + }; + + sd_emmc_b: sdio@ffe05000 { + status = "okay"; + compatible = "amlogic, meson-mmc-tm2"; + reg = <0x0 0xffe05000 0x0 0x800>; + interrupts = <0 190 4>; + + pinctrl-names = "sdio_all_pins", + "sdio_clk_cmd_pins"; + pinctrl-0 = <&sdio_all_pins>; + pinctrl-1 = <&sdio_clk_cmd_pins>; + + clocks = <&clkc CLKID_SD_EMMC_B>, + <&clkc CLKID_SD_EMMC_B_P0_COMP>, + <&clkc CLKID_FCLK_DIV2>, + <&clkc CLKID_FCLK_DIV5>, + <&xtal>; + clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + + bus-width = <4>; + cap-sd-highspeed; + cap-mmc-highspeed; + max-frequency = <100000000>; + disable-wp; + sdio { + pinname = "sdio"; + ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", /**ptm debug */ + "MMC_CAP_UHS_SDR12", + "MMC_CAP_UHS_SDR25", + "MMC_CAP_UHS_SDR50", + "MMC_CAP_UHS_SDR104", + "MMC_PM_KEEP_POWER", + "MMC_CAP_SDIO_IRQ"; + f_min = <400000>; + f_max = <200000000>; + max_req_size = <0x20000>; /**128KB*/ + card_type = <3>; + /* 3:sdio device(ie:sdio-wifi), + * 4:SD combo (IO+mem) card + */ + }; + }; +/* sd_emmc_b: sd@ffe05000 { + * status = "okay"; + * compatible = "amlogic, meson-mmc-tm2"; + * reg = <0xffe05000 0x800>; + * interrupts = <0 190 1>; + * + * pinctrl-names = "sd_all_pins", + * "sd_clk_cmd_pins", + * "sd_1bit_pins"; + * pinctrl-0 = <&sd_all_pins>; + * pinctrl-1 = <&sd_clk_cmd_pins>; + * pinctrl-2 = <&sd_1bit_pins>; + * + * clocks = <&clkc CLKID_SD_EMMC_B>, + * <&clkc CLKID_SD_EMMC_B_P0_COMP>, + * <&clkc CLKID_FCLK_DIV2>, + * <&clkc CLKID_FCLK_DIV5>, + * <&xtal>; + * clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + * + * bus-width = <4>; + * cap-sd-highspeed; + * cap-mmc-highspeed; + * max-frequency = <100000000>; + * disable-wp; + * sd { + * pinname = "sd"; + * ocr_avail = <0x200080>; + * caps = "MMC_CAP_4_BIT_DATA", + * "MMC_CAP_MMC_HIGHSPEED", + * "MMC_CAP_SD_HIGHSPEED"; + * f_min = <400000>; + * f_max = <200000000>; + * max_req_size = <0x20000>; + * no_sduart = <1>; + * gpio_dat3 = <&gpio GPIOC_3 GPIO_ACTIVE_HIGH>; + * jtag_pin = <&gpio GPIOC_0 GPIO_ACTIVE_HIGH>; + * gpio_cd = <&gpio GPIOC_10 GPIO_ACTIVE_HIGH>; + * card_type = <5>; + * }; + * }; + */ + +}; /* end of / */ + +&i2c0 { + status = "okay"; + clock-frequency = <300000>; + pinctrl-names="default"; + pinctrl-0=<&i2c0_dv_pins>; +}; + +&audiobus { + tdma:tdm@0 { + compatible = "amlogic, tm2-snd-tdma"; + #sound-dai-cells = <0>; + + dai-tdm-lane-slot-mask-in = <1 0>; + dai-tdm-lane-slot-mask-out = <1 1 1 1>; + dai-tdm-clk-sel = <0>; + + clocks = <&clkaudio CLKID_AUDIO_MCLK_A + &clkc CLKID_MPLL0 + &clkc CLKID_MPLL0>; + clock-names = "mclk", "clk_srcpll", "samesource_sysclk"; + + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdma_mclk &tdmout_a>; + + /* + * 0: tdmout_a; + * 1: tdmout_b; + * 2: tdmout_c; + * 3: spdifout; + * 4: spdifout_b; + */ + samesource_sel = <3>; + + /* In for ACODEC_ADC */ + acodec_adc = <1>; + + status = "okay"; + + /* !!!For --TV platform-- ONLY */ + Channel_Mask { + /*i2s has 4 pins, 8channel, mux output*/ + Spdif_samesource_Channel_Mask = "i2s_2/3"; + }; + }; + + tdmb:tdm@1 { + compatible = "amlogic, tm2-snd-tdmb"; + #sound-dai-cells = <0>; + + dai-tdm-lane-slot-mask-in = <1 0 0 0>; + dai-tdm-lane-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <1>; + + clocks = <&clkaudio CLKID_AUDIO_MCLK_B + &clkc CLKID_MPLL1>; + clock-names = "mclk", "clk_srcpll"; + + status = "okay"; + }; + + tdmc:tdm@2 { + compatible = "amlogic, tm2-snd-tdmc"; + #sound-dai-cells = <0>; + + dai-tdm-lane-slot-mask-in = <1 0 0 0>; + dai-tdm-lane-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <2>; + + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + + pinctrl-names = "tdm_pins"; + pinctrl-0 = <&tdmout_c &tdmin_c>; + + status = "okay"; + }; + + pdm:pdm { + compatible = "amlogic, tm2-snd-pdm"; + #sound-dai-cells = <0>; + clocks = <&clkaudio CLKID_AUDIO_GATE_PDM + &clkc CLKID_FCLK_DIV3 + &clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_PDMIN0 + &clkaudio CLKID_AUDIO_PDMIN1>; + clock-names = "gate", + "sysclk_srcpll", + "dclk_srcpll", + "pdm_dclk", + "pdm_sysclk"; + pinctrl-names = "pdm_pins"; + pinctrl-0 = <&pdmin>; + /* mode 0~4, defalut:1 */ + filter_mode = <1>; + status = "okay"; + }; + spdifa:spdif@0 { + compatible = "amlogic, tm2-snd-spdif-a"; + #sound-dai-cells = <0>; + + clocks = <&clkc CLKID_MPLL1 + &clkc CLKID_FCLK_DIV4 + &clkaudio CLKID_AUDIO_GATE_SPDIFIN + &clkaudio CLKID_AUDIO_GATE_SPDIFOUT_A + &clkaudio CLKID_AUDIO_SPDIFIN + &clkaudio CLKID_AUDIO_SPDIFOUT_A>; + clock-names = "sysclk", "fixed_clk", "gate_spdifin", + "gate_spdifout", "clk_spdifin", "clk_spdifout"; + + interrupts = + ; + interrupt-names = "irq_spdifin"; + + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; + + pinctrl-0 = <&spdifout_a>; + pinctrl-1 = <&spdifout_a_mute>; + + /* + * whether do asrc for pcm and resample a or b + * if raw data, asrc is disabled automatically + * 0: "Disable", + * 1: "Enable:32K", + * 2: "Enable:44K", + * 3: "Enable:48K", + * 4: "Enable:88K", + * 5: "Enable:96K", + * 6: "Enable:176K", + * 7: "Enable:192K", + */ + asrc_id = <0>; + auto_asrc = <3>; + + status = "okay"; + }; + + spdifb:spdif@1 { + compatible = "amlogic, tm2-snd-spdif-b"; + #sound-dai-cells = <0>; + + clocks = <&clkc CLKID_MPLL0 /*CLKID_HIFI_PLL*/ + &clkaudio CLKID_AUDIO_GATE_SPDIFOUT_B + &clkaudio CLKID_AUDIO_SPDIFOUT_B>; + clock-names = "sysclk", + "gate_spdifout", "clk_spdifout"; + + status = "okay"; + }; + + extn:extn { + compatible = "amlogic, snd-extn"; + #sound-dai-cells = <0>; + + + interrupts = + ; + interrupt-names = "irq_frhdmirx"; + + status = "okay"; + }; + + earc:earc { + compatible = "amlogic, tm2-snd-earc"; + #sound-dai-cells = <0>; + + clocks = < &clkaudio CLKID_EARCRX_CMDC + &clkaudio CLKID_EARCRX_DMAC + &clkc CLKID_FCLK_DIV5 + &clkc CLKID_FCLK_DIV3 + &clkaudio CLKID_EARCTX_CMDC + &clkaudio CLKID_EARCTX_DMAC + &clkc CLKID_FCLK_DIV5 + &clkc CLKID_FCLK_DIV3 + >; + clock-names = + "rx_cmdc", + "rx_dmac", + "rx_cmdc_srcpll", + "rx_dmac_srcpll", + "tx_cmdc", + "tx_dmac", + "tx_cmdc_srcpll", + "tx_dmac_srcpll"; + interrupts = < + GIC_SPI 88 IRQ_TYPE_EDGE_RISING + GIC_SPI 87 IRQ_TYPE_EDGE_RISING + >; + interrupt-names = "rx_cmdc", "rx_dmac"; + + status = "okay"; + }; + + aed:effect { + compatible = "amlogic, snd-effect-v2"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_EQDRC + &clkc CLKID_FCLK_DIV5 + &clkaudio CLKID_AUDIO_EQDRC>; + clock-names = "gate", "srcpll", "eqdrc"; + + /* + * 0:tdmout_a + * 1:tdmout_b + * 2:tdmout_c + * 3:spdifout + * 4:spdifout_b + */ + eqdrc_module = <0>; + /* max 0xf, each bit for one lane, usually one lane */ + lane_mask = <0x1>; + /* max 0xff, each bit for one channel */ + channel_mask = <0xff>; + + status = "disable"; + }; + + asrca: resample@0 { + compatible = "amlogic, tl1-resample-a"; + clocks = <&clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_MCLK_A + &clkaudio CLKID_AUDIO_RESAMPLE_A>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + /*same with toddr_src + * TDMIN_A, 0 + * TDMIN_B, 1 + * TDMIN_C, 2 + * SPDIFIN, 3 + * PDMIN, 4 + * NONE, + * TDMIN_LB, 6 + * LOOPBACK, 7 + * FRHDMIRX, 8 + */ + resample_module = <8>; + + status = "disabled"; + }; + + asrcb: resample@1 { + compatible = "amlogic, tl1-resample-b"; + + clocks = <&clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_MCLK_F + &clkaudio CLKID_AUDIO_RESAMPLE_B>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + + /*same with toddr_src + * TDMIN_A, 0 + * TDMIN_B, 1 + * TDMIN_C, 2 + * SPDIFIN, 3 + * PDMIN, 4 + * NONE, + * TDMIN_LB, 6 + * LOOPBACK, 7 + */ + resample_module = <3>; + + status = "disabled"; + }; + + vad:vad { + compatible = "amlogic, snd-vad"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_TOVAD + &clkc CLKID_FCLK_DIV5 + &clkaudio CLKID_AUDIO_VAD>; + clock-names = "gate", "pll", "clk"; + + interrupts = ; + interrupt-names = "irq_wakeup", "irq_frame_sync"; + + /* + * Data src sel: + * 0: tdmin_a; + * 1: tdmin_b; + * 2: tdmin_c; + * 3: spdifin; + * 4: pdmin; + * 5: loopback_b; + * 6: tdmin_lb; + * 7: loopback_a; + */ + src = <4>; + + /* + * deal with hot word in user space or kernel space + * 0: in user space + * 1: in kernel space + */ + level = <1>; + + status = "disabled"; + }; +}; /* end of audiobus */ + +&pinctrl_periphs { + /* audio pin mux */ + + tdma_mclk: tdma_mclk { + mux { /* GPIOZ_0 */ + groups = "mclk0_z"; + function = "mclk0"; + }; + }; + + tdmout_a: tdmout_a { + mux { /* GPIOZ_1, GPIOZ_2, GPIOZ_3*/ + groups = "tdma_sclk_z", + "tdma_fs_z", + "tdma_dout0_z"; + function = "tdma_out"; + bias-pull-down; + }; + }; + + tdmin_a: tdmin_a { + mux { /* GPIOH_11, GPIOH_12 */ + groups = "tdma_din0_h", + "tdma_din1_h"; + function = "tdma_in"; + }; + }; + + tdmout_c: tdmout_c { + mux { /* GPIODV_7, GPIODV_8, GPIODV_9 */ + groups = "tdmc_sclk", + "tdmc_fs", + "tdmc_dout0"; + function = "tdmc_out"; + }; + }; + + tdmin_c: tdmin_c { + mux { /* GPIODV_10 */ + groups = "tdmc_din1"; + function = "tdmc_in"; + }; + }; + + spdifin_a: spdifin_a { + mux { /* GPIODV_5 */ + groups = "spdif_in"; + function = "spdif_in"; + }; + }; + + spdifout_a: spdifout_a { + mux { /* GPIODV_4 */ + groups = "spdif_out_dv4"; + function = "spdif_out"; + }; + }; + + spdifout_a_mute: spdifout_a_mute { + mux { /* GPIODV_4 */ + groups = "GPIODV_4"; + function = "gpio_periphs"; + }; + }; + + pdmin: pdmin { + mux { /* GPIOZ_7, GPIOZ_8, pdm_din2_z4 */ + groups = "pdm_dclk_z", + "pdm_din0_z", + "pdm_din2_z4"; + function = "pdm"; + }; + }; + + /*backlight*/ + bl_pwm_vs_on_pins:bl_pwm_vs_on_pin { + mux { + groups = "pwm_vs_z5"; + function = "pwm_vs"; + }; + }; + bl_pwm_off_pins:bl_pwm_off_pin { + mux { + groups = "GPIOZ_5"; + function = "gpio_periphs"; + output-low; + }; + }; + bl_pwm_combo_0_vs_on_pins:bl_pwm_combo_0_vs_on_pin { + mux { + groups = "pwm_vs_z5"; + function = "pwm_vs"; + }; + }; + bl_pwm_combo_1_vs_on_pins:bl_pwm_combo_1_vs_on_pin { + mux { + groups = "pwm_vs_z6"; + function = "pwm_vs"; + }; + }; + bl_pwm_combo_off_pins:bl_pwm_combo_off_pin { + mux { + groups = "GPIOZ_5", + "GPIOZ_6"; + function = "gpio_periphs"; + output-low; + }; + }; +}; /* end of pinctrl_periphs */ + +&pinctrl_aobus { + spdifout: spdifout { + mux { /* gpiao_10 */ + groups = "spdif_out_ao"; + function = "spdif_out_ao"; + }; + }; + +}; /* end of pinctrl_periphs */ + +&audio_data{ + status = "okay"; +}; + +&i2c2 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&i2c2_z_pins>; + clock-frequency = <400000>; + + tas5805: tas5805@5c { + compatible = "ti,tas5805"; + #sound-dai-cells = <0>; + codec_name = "tas5805"; + reg = <0x2e>; + reset_pin = <&gpio_ao GPIOAO_6 GPIO_ACTIVE_HIGH>; + status = "okay"; + }; + + ad82584f: ad82584f@62 { + compatible = "ESMT, ad82584f"; + #sound-dai-cells = <0>; + reg = <0x31>; + status = "disabled"; + reset_pin = <&gpio_ao GPIOAO_6 0>; + }; + +}; + +&sd_emmc_c { + status = "okay"; + emmc { + caps = "MMC_CAP_8_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + "MMC_CAP_1_8V_DDR", + "MMC_CAP_HW_RESET", + "MMC_CAP_ERASE", + "MMC_CAP_CMD23", + "MMC_CAP_DRIVER_TYPE_D"; + caps2 = "MMC_CAP2_HS200", "MMC_CAP2_HS400"; + f_min = <400000>; + f_max = <198000000>; + }; +}; + + + +&spifc { + status = "disabled"; + spi-nor@0 { + cs_gpios = <&gpio BOOT_13 GPIO_ACTIVE_HIGH>; + }; +}; + +&slc_nand { + status = "disabled"; + plat-names = "bootloader", "nandnormal"; + plat-num = <2>; + plat-part-0 = <&bootloader>; + plat-part-1 = <&nandnormal>; + bootloader: bootloader{ + enable_pad = "ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <1>; + part_num = <0>; + rb_detect = <1>; + }; + nandnormal: nandnormal{ + enable_pad = "ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + plane_mode = "twoplane"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <2>; + part_num = <3>; + partition = <&nand_partitions>; + rb_detect = <1>; + }; + nand_partitions:nand_partition{ + /* + * if bl_mode is 1, tpl size was generate by + * fip_copies * fip_size which + * will not skip bad when calculating + * the partition size; + * + * if bl_mode is 0, + * tpl partition must be comment out. + */ + tpl{ + offset=<0x0 0x0>; + size=<0x0 0x0>; + }; + logo{ + offset=<0x0 0x0>; + size=<0x0 0x200000>; + }; + recovery{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + boot{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + system{ + offset=<0x0 0x0>; + size=<0x0 0x4000000>; + }; + data{ + offset=<0xffffffff 0xffffffff>; + size=<0x0 0x0>; + }; + }; +}; + +ðmac { + status = "okay"; + pinctrl-names = "internal_eth_pins"; + pinctrl-0 = <&internal_eth_pins>; + mc_val = <0x4be04>; + + internal_phy=<1>; +}; + +&uart_A { + status = "okay"; +}; + +&dwc3 { + status = "okay"; +}; + +&usb2_phy_v2 { + status = "okay"; + portnum = <3>; +}; + +&usb3_phy_v2 { + status = "okay"; + portnum = <2>; + portconfig-30 = <1>; + portconfig-31 = <1>; +}; + +&usb_otg { + status = "okay"; + otg = <0>; +}; + +&dwc2_a { + status = "okay"; + /** 0: normal, 1: otg+dwc3 host only, 2: otg+dwc3 device only*/ + controller-type = <1>; +}; + +&pcie_A { + reset-gpio = <&gpio_ao GPIOAO_4 GPIO_ACTIVE_HIGH>; + status = "disable"; +}; + +&pcie_B { + /* ab311 only pcie a, no pcie b */ + status = "disable"; +}; + +&spicc0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&spicc0_pins_h>; + cs-gpios = <&gpio GPIOH_20 0>; +}; + +&meson_fb { + status = "okay"; + display_size_default = <1920 1080 1920 2160 32>; + mem_size = <0x00800000 0x1980000 0x100000 0x100000 0x800000>; + logo_addr = "0x7f800000"; + mem_alloc = <0>; + pxp_mode = <0>; /** 0:normal mode 1:pxp mode */ +}; + +&pwm_AO_cd { + status = "okay"; +}; + +&pwm_cd { + status = "okay"; +}; + +&saradc { + status = "okay"; +}; + +&i2c1 { + status = "okay"; + clock-frequency = <300000>; + pinctrl-names="default"; + pinctrl-0=<&i2c1_h_pins>; + + lcd_extern_i2c0: lcd_extern_i2c@0 { + compatible = "lcd_ext, i2c"; + dev_name = "i2c_T5800Q"; + reg = <0x1c>; + status = "okay"; + }; + + lcd_extern_i2c1: lcd_extern_i2c@1 { + compatible = "lcd_ext, i2c"; + dev_name = "i2c_ANX6862"; + reg = <0x20>; + status = "okay"; + }; + + lcd_extern_i2c2: lcd_extern_i2c@2 { + compatible = "lcd_ext, i2c"; + dev_name = "i2c_ANX7911"; + reg = <0x74>; + status = "okay"; + }; +}; + +&pwm_ab { + status = "okay"; +}; + +&pwm_cd { + status = "okay"; +}; + +&efuse { + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab309.dts b/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab309.dts new file mode 100644 index 000000000000..15662fe68e95 --- /dev/null +++ b/arch/arm64/boot/dts/amlogic/tm2_t962x3_ab309.dts @@ -0,0 +1,1853 @@ +/* + * arch/arm64/boot/dts/amlogic/tm2_t962x3_ab309.dts + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +/dts-v1/; + +#include "mesontm2.dtsi" +#include "partition_mbox_normal.dtsi" +#include "mesontm2_t962x3_ab309-panel.dtsi" + +/ { + model = "Amlogic TM2 T962X3 AB309"; + amlogic-dt-id = "tm2_t962x3_ab309"; + compatible = "amlogic, tm2_t962x3_ab309"; + + aliases { + serial0 = &uart_AO; + serial1 = &uart_A; + serial2 = &uart_B; + serial3 = &uart_C; + serial4 = &uart_AO_B; + tsensor0 = &p_tsensor; + tsensor1 = &d_tsensor; + tsensor2 = &s_tsensor; + i2c0 = &i2c0; + i2c1 = &i2c1; + i2c2 = &i2c2; + i2c3 = &i2c3; + i2c4 = &i2c_AO; + }; + + memory@00000000 { + device_type = "memory"; + linux,usable-memory = <0x0 0x0 0x0 0x80000000>; + }; + + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + /* global autoconfigured region for contiguous allocations */ + ramoops@0x07400000 { + compatible = "ramoops"; + reg = <0x0 0x07400000 0x0 0x00100000>; + record-size = <0x8000>; + console-size = <0x8000>; + ftrace-size = <0x20000>; + }; + + secmon_reserved: linux,secmon { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x400000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x05000000 0x0 0x400000>; + }; + + logo_reserved:linux,meson-fb { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x800000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x7f800000 0x0 0x800000>; + }; + + lcd_tcon_reserved:linux,lcd_tcon { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0xc00000>; + alignment = <0x0 0x400000>; + alloc-ranges = <0x0 0x7ec00000 0x0 0xc00000>; + }; + + codec_mm_cma:linux,codec_mm_cma { + compatible = "shared-dma-pool"; + reusable; + /* ion_codec_mm max can alloc size 80M*/ + size = <0x0 0x13400000>; + alignment = <0x0 0x400000>; + linux,contiguous-region; + }; + + /* codec shared reserved */ + codec_mm_reserved:linux,codec_mm_reserved { + compatible = "amlogic, codec-mm-reserved"; + size = <0x0 0x0>; + alignment = <0x0 0x100000>; + //no-map; + }; + + ion_cma_reserved:linux,ion-dev { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x8000000>; + alignment = <0x0 0x400000>; + }; + + /* vdin0 CMA pool */ + //vdin0_cma_reserved:linux,vdin0_cma { + // compatible = "shared-dma-pool"; + // reusable; + /* 3840x2160x4x4 ~=128 M */ + // size = <0x0 0xc400000>; + // alignment = <0x0 0x400000>; + //}; + + /* vdin1 CMA pool */ + vdin1_cma_reserved:linux,vdin1_cma { + compatible = "shared-dma-pool"; + reusable; + /* 1920x1080x2x4 =16 M */ + size = <0x0 0x1400000>; + alignment = <0x0 0x400000>; + }; + + /*demod_reserved:linux,demod { + * compatible = "amlogic, demod-mem"; + * size = <0x0 0x800000>; //8M //100m 0x6400000 + * alloc-ranges = <0x0 0x0 0x0 0x30000000>; + * //multi-use; + * //no-map; + *}; + */ + + demod_cma_reserved:linux,demod_cma { + compatible = "shared-dma-pool"; + reusable; + /* 8M */ + size = <0x0 0x0800000>; + alignment = <0x0 0x400000>; + }; + + /*di CMA pool */ + di_cma_reserved:linux,di_cma { + compatible = "shared-dma-pool"; + reusable; + /* buffer_size = 3621952(yuv422 8bit) + * | 4736064(yuv422 10bit) + * | 4074560(yuv422 10bit full pack mode) + * 10x3621952=34.6M(0x23) support 8bit + * 10x4736064=45.2M(0x2e) support 12bit + * 10x4074560=40M(0x28) support 10bit + */ + size = <0x0 0x02800000>; + alignment = <0x0 0x400000>; + }; + + /* for hdmi rx emp use */ + hdmirx_emp_cma_reserved:linux,emp_cma { + compatible = "shared-dma-pool"; + /*linux,phandle = <5>;*/ + reusable; + /* 4M for emp to ddr */ + /* 32M for tmds to ddr */ + size = <0x0 0x400000>; + alignment = <0x0 0x400000>; + /* alloc-ranges = <0x400000 0x2000000>; */ + }; + + /* POST PROCESS MANAGER */ + ppmgr_reserved:linux,ppmgr { + compatible = "amlogic, ppmgr_memory"; + size = <0x0 0x0>; + }; + + picdec_cma_reserved:linux,picdec { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x0>; + alignment = <0x0 0x0>; + linux,contiguous-region; + }; + }; /* end of reserved-memory */ + galcore { + status = "okay"; + }; + codec_mm { + compatible = "amlogic, codec, mm"; + status = "okay"; + memory-region = <&codec_mm_cma &codec_mm_reserved>; + }; + + picdec { + compatible = "amlogic, picdec"; + memory-region = <&picdec_cma_reserved>; + dev_name = "picdec"; + status = "okay"; + }; + + ppmgr { + compatible = "amlogic, ppmgr"; + memory-region = <&ppmgr_reserved>; + status = "okay"; + }; + + deinterlace { + compatible = "amlogic, deinterlace"; + status = "okay"; + /* 0:use reserved; 1:use cma; 2:use cma as reserved */ + flag_cma = <1>; + //memory-region = <&di_reserved>; + memory-region = <&di_cma_reserved>; + interrupts = <0 46 1 + 0 40 1>; + interrupt-names = "pre_irq", "post_irq"; + clocks = <&clkc CLKID_VPU_CLKB_TMP_COMP>, + <&clkc CLKID_VPU_CLKB_COMP>; + clock-names = "vpu_clkb_tmp_composite", + "vpu_clkb_composite"; + clock-range = <334 667>; + /* buffer-size = <3621952>;(yuv422 8bit) */ + buffer-size = <4074560>;/*yuv422 fullpack*/ + /* reserve-iomap = "true"; */ + /* if enable nr10bit, set nr10bit-support to 1 */ + post-wr-support = <1>; + nr10bit-support = <1>; + nrds-enable = <1>; + pps-enable = <1>; + }; + + vout { + compatible = "amlogic, vout"; + status = "okay"; + fr_auto_policy = <0>; + }; + + /* Audio Related start */ + pdm_codec:dummy { + #sound-dai-cells = <0>; + compatible = "amlogic, pdm_dummy_codec"; + status = "okay"; + }; + + dummy_codec:dummy { + #sound-dai-cells = <0>; + compatible = "amlogic, aml_dummy_codec"; + status = "okay"; + }; + + tl1_codec:codec { + #sound-dai-cells = <0>; + compatible = "amlogic, tl1_acodec"; + status = "okay"; + reg = <0x0 0xff632000 0x0 0x1c>; + tdmout_index = <0>; + tdmin_index = <0>; + dat1_ch_sel = <1>; + }; + + aml_dtv_demod { + compatible = "amlogic, ddemod-tl1"; + dev_name = "aml_dtv_demod"; + status = "okay"; + + //pinctrl-names="dtvdemod_agc"; + //pinctrl-0=<&dtvdemod_agc>; + + clocks = <&clkc CLKID_DAC_CLK>; + clock-names = "vdac_clk_gate"; + + reg = <0x0 0xff650000 0x0 0x4000 /*dtv demod base*/ + 0x0 0xff63c000 0x0 0x2000 /*hiu reg base*/ + 0x0 0xff800000 0x0 0x1000 /*io_aobus_base*/ + 0x0 0xffd01000 0x0 0x1000 /*reset*/ + >; + + dtv_demod0_mem = <0>; // need move to aml_dtv_demod ? + spectrum = <1>; + cma_flag = <1>; + cma_mem_size = <8>; + memory-region = <&demod_cma_reserved>;//<&demod_reserved>; + }; + + auge_sound { + compatible = "amlogic, tm2-sound-card"; + aml-audio-card,name = "AML-AUGESOUND"; + + avout_mute-gpios = <&gpio GPIODV_3 GPIO_ACTIVE_HIGH>; + + aml-audio-card,dai-link@0 { + format = "i2s"; + mclk-fs = <256>; + continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdma>; + frame-master = <&tdma>; + /* slave mode */ + /* + * bitclock-master = <&tdmacodec>; + * frame-master = <&tdmacodec>; + */ + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-i2s"; + tdmacpu: cpu { + sound-dai = <&tdma>; + dai-tdm-slot-tx-mask = + <1 1>; + dai-tdm-slot-rx-mask = + <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmacodec: codec { + //sound-dai = <&dummy_codec>; + sound-dai = ; + }; + }; + + aml-audio-card,dai-link@1 { + + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdmb>; + frame-master = <&tdmb>; + /* slave mode */ + //bitclock-master = <&tdmbcodec>; + //frame-master = <&tdmbcodec>; + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-pcm"; + cpu { + sound-dai = <&tdmb>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + /* + * dai-tdm-slot-tx-mask = + * <1 1 1 1 1 1 1 1>; + * dai-tdm-slot-rx-mask = + * <1 1 1 1 1 1 1 1>; + * dai-tdm-slot-num = <8>; + */ + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmbcodec: codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@2 { + + format = "i2s"; + mclk-fs = <256>; + //continuous-clock; + //bitclock-inversion; + //frame-inversion; + /* master mode */ + bitclock-master = <&tdmc>; + frame-master = <&tdmc>; + /* slave mode */ + //bitclock-master = <&tdmccodec>; + //frame-master = <&tdmccodec>; + /* suffix-name, sync with android audio hal used for */ + //suffix-name = "alsaPORT-tdm"; + cpu { + sound-dai = <&tdmc>; + dai-tdm-slot-tx-mask = <1 1>; + dai-tdm-slot-rx-mask = <1 1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; + }; + tdmccodec: codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@3 { + mclk-fs = <64>; + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-pdm"; + cpu { + sound-dai = <&pdm>; + }; + codec { + sound-dai = <&pdm_codec>; + }; + }; + + aml-audio-card,dai-link@4 { + mclk-fs = <128>; + continuous-clock; + /* suffix-name, sync with android audio hal used for */ + suffix-name = "alsaPORT-spdif"; + cpu { + sound-dai = <&spdifa>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@5 { + mclk-fs = <128>; + suffix-name = "alsaPORT-spdifb"; + cpu { + sound-dai = <&spdifb>; + system-clock-frequency = <6144000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + + aml-audio-card,dai-link@6 { + mclk-fs = <256>; + suffix-name = "alsaPORT-tv"; + cpu { + sound-dai = <&extn>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + aml-audio-card,dai-link@7 { + mclk-fs = <256>; + suffix-name = "alsaPORT-earc"; + cpu { + sound-dai = <&earc>; + system-clock-frequency = <12288000>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + }; + + /* Audio Related end */ + dvb { + compatible = "amlogic, dvb"; + status = "okay"; + fe0_mode = "internal"; + fe0_tuner = <&tuner>; + + /*"parallel","serial","disable"*/ + ts2 = "parallel"; + ts2_control = <0>; + ts2_invert = <0>; + interrupts = <0 23 1 + 0 5 1 + 0 53 1 + 0 19 1 + 0 25 1 + 0 17 1>; + interrupt-names = "demux0_irq", + "demux1_irq", + "demux2_irq", + "dvr0_irq", + "dvr1_irq", + "dvr2_irq"; + clocks = <&clkc CLKID_DEMUX + &clkc CLKID_ASYNC_FIFO + &clkc CLKID_AHB_ARB0 + /*&clkc CLKID_DOS_PARSER>;*/ + &clkc CLKID_U_PARSER>; + clock-names = "demux", "asyncfifo", "ahbarb0", "uparsertop"; + }; + + tvafe_avin_detect { + compatible = "amlogic, tl1_tvafe_avin_detect"; + status = "okay"; + device_mask = <1>;/*bit0:ch1;bit1:ch2*/ + interrupts = <0 12 1>, + <0 13 1>; + }; + + amlvecm { + compatible = "amlogic, vecm-tl1"; + dev_name = "aml_vecm"; + status = "okay"; + gamma_en = <1>;/*1:enabel ;0:disable*/ + wb_en = <1>;/*1:enabel ;0:disable*/ + cm_en = <0>;/*1:enabel ;0:disable*/ + wb_sel = <1>;/*1:mtx ;0:gainoff*/ + vlock_en = <1>;/*1:enable;0:disable*/ + vlock_mode = <0x4>; + /* vlock work mode: + *bit0:auto ENC + *bit1:auto PLL + *bit2:manual PLL + *bit3:manual ENC + *bit4:manual soft ENC + *bit5:manual MIX PLL ENC + */ + vlock_pll_m_limit = <1>; + vlock_line_limit = <3>; + }; + + amdolby_vision { + compatible = "amlogic, dolby_vision_tm2"; + dev_name = "aml_amdolby_vision_driver"; + status = "okay"; + tv_mode = <1>;/*1:enabel ;0:disable*/ + }; + + vdin@0 { + compatible = "amlogic, vdin"; + /*memory-region = <&vdin0_cma_reserved>;*/ + status = "okay"; + /*bit0:(1:share with codec_mm;0:cma alone) + *bit8:(1:alloc in discontinus way;0:alone in continuous way) + */ + flag_cma = <0x101>; + /*MByte, if 10bit disable: 64M(YUV422), + *if 10bit enable: 64*1.5 = 96M(YUV422) + *if support 4K2K-YUV444-10bit-WR:3840*2160*4*4 ~= 128M + *if support 4K2K-YUV422-10bit-wr:3840*2160*3*4 ~= 96M + *if support 4K2K-YUV422-8BIT-WR:3840*2160*2*4 ~= 64M + *if support 1080p-YUV422-8BIT-WR:1920*1080*2*4 ~= 16M + */ + cma_size = <190>; + interrupts = <0 83 1>; + rdma-irq = <2>; + clocks = <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_VDIN_MEAS_COMP>; + clock-names = "fclk_div5", "cts_vdin_meas_clk"; + vdin_id = <0>; + /*vdin write mem color depth support: + * bit0:support 8bit + * bit1:support 9bit + * bit2:support 10bit + * bit3:support 12bit + * bit4:support yuv422 10bit full pack mode (from txl new add) + * bit8:use 8bit at 4k_50/60hz_10bit + * bit9:use 10bit at 4k_50/60hz_10bit + */ + tv_bit_mode = <0x215>; + /* afbce_bit_mode: (amlogic frame buff compression encoder) + * bit 0~3: + * 0 -- normal mode, not use afbce + * 1 -- use afbce non-mmu mode + * 2 -- use afbce mmu mode + * bit 4: + * 0 -- afbce compression-lossy disable + * 1 -- afbce compression-lossy enable + */ + afbce_bit_mode = <0>; + }; + + vdin@1 { + compatible = "amlogic, vdin"; + memory-region = <&vdin1_cma_reserved>; + status = "okay"; + /*bit0:(1:share with codec_mm;0:cma alone) + *bit8:(1:alloc in discontinus way;0:alone in continuous way) + */ + flag_cma = <0>; + interrupts = <0 85 1>; + rdma-irq = <4>; + clocks = <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_VDIN_MEAS_COMP>; + clock-names = "fclk_div5", "cts_vdin_meas_clk"; + vdin_id = <1>; + /*vdin write mem color depth support: + *bit0:support 8bit + *bit1:support 9bit + *bit2:support 10bit + *bit3:support 12bit + */ + tv_bit_mode = <0x15>; + }; + + tvafe { + compatible = "amlogic, tvafe-tl1"; + /*memory-region = <&tvafe_cma_reserved>;*/ + status = "okay"; + flag_cma = <1>;/*1:share with codec_mm;0:cma alone*/ + cma_size = <5>;/*MByte*/ + reg = <0x0 0xff654000 0x0 0x2000>;/*tvafe reg base*/ + reserve-iomap = "true"; + tvafe_id = <0>; + //pinctrl-names = "default"; + /*!!particular sequence, no more and no less!!!*/ + tvafe_pin_mux = < + 3 /* TVAFE_CVBS_IN2, CVBS_IN0 = 0 */ + 1 /* TVAFE_CVBS_IN0, CVBS_IN1 */ + 2 /* TVAFE_CVBS_IN1, CVBS_IN2 */ + 4 /* TVAFE_CVBS_IN3, CVBS_IN3 */ + >; + clocks = <&clkc CLKID_DAC_CLK>; + clock-names = "vdac_clk_gate"; + }; + + vbi { + compatible = "amlogic, vbi"; + status = "okay"; + interrupts = <0 83 1>; + }; + + cvbsout { + compatible = "amlogic, cvbsout-tl1"; + status = "disabled"; + clocks = <&clkc CLKID_VCLK2_ENCI + &clkc CLKID_VCLK2_VENCI0 + &clkc CLKID_VCLK2_VENCI1 + &clkc CLKID_DAC_CLK>; + clock-names = "venci_top_gate", + "venci_0_gate", + "venci_1_gate", + "vdac_clk_gate"; + /* clk path */ + /* 0:vid_pll vid2_clk */ + /* 1:gp0_pll vid2_clk */ + /* 2:vid_pll vid1_clk */ + /* 3:gp0_pll vid1_clk */ + clk_path = <0>; + + /* performance: reg_address, reg_value */ + /* tl1 */ + performance = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x8080 + 0x1b05 0xfd + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + performance_sarft = <0x1bf0 0x9 + 0x1b56 0x333 + 0x1b12 0x0 + 0x1b05 0x9 + 0x1c59 0xfc48 + 0xffff 0x0>; /* ending flag */ + performance_revB_telecom = <0x1bf0 0x9 + 0x1b56 0x546 + 0x1b12 0x8080 + 0x1b05 0x9 + 0x1c59 0xf850 + 0xffff 0x0>; /* ending flag */ + }; + + adc_keypad { + compatible = "amlogic, adc_keypad"; + status = "okay"; + key_name = "vol-", "vol+", "ch+", "ch-", + "menu", "source", "exit"; + key_num = <7>; + io-channels = <&saradc SARADC_CH2 &saradc SARADC_CH3>; + io-channel-names = "key-chan-2", "key-chan-3"; + key_chan = ; + key_code = <114 115 192 193 139 466 174>; + key_val = <0 143 266 389 0 143 266>; //val=voltage/1800mV*1023 + key_tolerance = <40 40 40 40 40 40 40>; + }; + + unifykey { + compatible = "amlogic, unifykey"; + status = "okay"; + + unifykey-num = <21>; + unifykey-index-0 = <&keysn_0>; + unifykey-index-1 = <&keysn_1>; + unifykey-index-2 = <&keysn_2>; + unifykey-index-3 = <&keysn_3>; + unifykey-index-4 = <&keysn_4>; + unifykey-index-5 = <&keysn_5>; + unifykey-index-6 = <&keysn_6>; + unifykey-index-7 = <&keysn_7>; + unifykey-index-8 = <&keysn_8>; + unifykey-index-9 = <&keysn_9>; + unifykey-index-10= <&keysn_10>; + unifykey-index-11 = <&keysn_11>; + unifykey-index-12 = <&keysn_12>; + unifykey-index-13 = <&keysn_13>; + unifykey-index-14 = <&keysn_14>; + unifykey-index-15 = <&keysn_15>; + unifykey-index-16 = <&keysn_16>; + unifykey-index-17 = <&keysn_17>; + unifykey-index-18 = <&keysn_18>; + unifykey-index-19 = <&keysn_19>; + unifykey-index-20 = <&keysn_20>; + + keysn_0: key_0{ + key-name = "usid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_1:key_1{ + key-name = "mac"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_2:key_2{ + key-name = "hdcp"; + key-device = "secure"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_3:key_3{ + key-name = "secure_boot_set"; + key-device = "efuse"; + key-permit = "write"; + }; + keysn_4:key_4{ + key-name = "mac_bt"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_5:key_5{ + key-name = "mac_wifi"; + key-device = "normal"; + key-permit = "read","write","del"; + key-type = "mac"; + }; + keysn_6:key_6{ + key-name = "hdcp2_tx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_7:key_7{ + key-name = "hdcp2_rx"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_8:key_8{ + key-name = "widevinekeybox"; + key-device = "secure"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_9:key_9{ + key-name = "deviceid"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_10:key_10{ + key-name = "hdcp22_fw_private"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_11:key_11{ + key-name = "hdcp22_rx_private"; + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_12:key_12{ + key-name = "hdcp22_rx_fw"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_13:key_13{ + key-name = "hdcp14_rx"; + key-device = "normal"; + key-type = "sha1"; + key-permit = "read","write","del"; + }; + keysn_14:key_14{ + key-name = "prpubkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_15:key_15{ + key-name = "prprivkeybox";// PlayReady + key-device = "secure"; + key-permit = "read","write","del"; + }; + keysn_16:key_16{ + key-name = "lcd"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_17:key_17{ + key-name = "lcd_extern"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_18:key_18{ + key-name = "backlight"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_19:key_19{ + key-name = "lcd_tcon"; + key-device = "normal"; + key-permit = "read","write","del"; + }; + keysn_20:key_20{ + key-name = "attestationkeybox";// attestation key + key-device = "secure"; + key-permit = "read","write","del"; + }; + }; /* End unifykey */ + + hdmirx { + compatible = "amlogic, hdmirx_tl1"; + #address-cells=<1>; + #size-cells=<1>; + memory-region = <&hdmirx_emp_cma_reserved>; + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&hdmirx_a_mux &hdmirx_b_mux + &hdmirx_c_mux>; + repeat = <0>; + interrupts = <0 41 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clkc CLKID_HDMIRX_MODET_COMP>, + <&clkc CLKID_HDMIRX_CFG_COMP>, + <&clkc CLKID_HDMIRX_ACR_COMP>, + <&clkc CLKID_HDMIRX_METER_COMP>, + <&clkc CLKID_HDMIRX_AXI_COMP>, + <&xtal>, + <&clkc CLKID_FCLK_DIV5>, + <&clkc CLKID_FCLK_DIV7>, + <&clkc CLKID_HDCP22_SKP_COMP>, + <&clkc CLKID_HDCP22_ESM_COMP>; + // <&clkc CLK_AUD_PLL2FS>, + // <&clkc CLK_AUD_PLL4FS>, + // <&clkc CLK_AUD_OUT>; + clock-names = "hdmirx_modet_clk", + "hdmirx_cfg_clk", + "hdmirx_acr_ref_clk", + "cts_hdmirx_meter_clk", + "cts_hdmi_axi_clk", + "xtal", + "fclk_div5", + "fclk_div7", + "hdcp_rx22_skp", + "hdcp_rx22_esm"; + // "hdmirx_aud_pll2fs", + // "hdmirx_aud_pll4f", + // "clk_aud_out"; + hdmirx_id = <0>; + en_4k_2_2k = <0>; + hpd_low_cec_off = <1>; + /* bit4: enable feature, bit3~0: port number */ + disable_port = <0x0>; + /* MAP_ADDR_MODULE_CBUS */ + /* MAP_ADDR_MODULE_HIU */ + /* MAP_ADDR_MODULE_HDMIRX_CAPB3 */ + /* MAP_ADDR_MODULE_SEC_AHB */ + /* MAP_ADDR_MODULE_SEC_AHB2 */ + /* MAP_ADDR_MODULE_APB4 */ + /* MAP_ADDR_MODULE_TOP */ + reg = < 0x0 0x0 0x0 0x0 + 0x0 0xff63C000 0x0 0x2000 + 0x0 0xffe0d000 0x0 0x2000 + 0x0 0x0 0x0 0x0 + 0x0 0x0 0x0 0x0 + 0x0 0x0 0x0 0x0 + 0x0 0xff610000 0x0 0xa000>; + }; + + aocec: aocec { + compatible = "amlogic, aocec-tm2"; + /*device_name = "aocec";*/ + status = "okay"; + vendor_name = "Amlogic"; /* Max Chars: 8 */ + /* Refer to the following URL at: + * http://standards.ieee.org/develop/regauth/oui/oui.txt + */ + vendor_id = <0x000000>; + product_desc = "TM2"; /* Max Chars: 16 */ + cec_osd_string = "AML_TV"; /* Max Chars: 14 */ + port_num = <3>; + ee_cec; + /*cec_sel = <2>;*/ + arc_port_mask = <0x2>; + output = <1>; /*output port number*/ + interrupts = <0 205 1 + 0 199 1>; + interrupt-names = "hdmi_aocecb","hdmi_aocec"; + pinctrl-names = "default","hdmitx_aocecb","cec_pin_sleep"; + pinctrl-0=<&aoceca_mux>; + pinctrl-1=<&aocecb_mux>; + pinctrl-2=<&aoceca_mux>; + reg = <0x0 0xFF80023c 0x0 0x4 + 0x0 0xFF800000 0x0 0x400>; + reg-names = "ao_exit","ao"; + }; + + p_tsensor: p_tsensor@ff634800 { + compatible = "amlogic, r1p1-tsensor"; + status = "okay"; + reg = <0x0 0xff634800 0x0 0x50>, + <0x0 0xff800268 0x0 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 35 0>; + clocks = <&clkc CLKID_TS_CLK_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + d_tsensor: d_tsensor@ff634c00 { + compatible = "amlogic, r1p1-tsensor"; + status = "okay"; + reg = <0x0 0xff634c00 0x0 0x50>, + <0x0 0xff800230 0x0 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 36 0>; + clocks = <&clkc CLKID_TS_CLK_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + s_tsensor: s_tsensor@ff635000 { + compatible = "amlogic, r1p1-tsensor"; + status = "okay"; + reg = <0x0 0xff635000 0x0 0x50>, + <0x0 0xff80026c 0x0 0x4>; + cal_type = <0x1>; + cal_a = <324>; + cal_b = <424>; + cal_c = <3159>; + cal_d = <9411>; + rtemp = <115000>; + interrupts = <0 38 0>; + clocks = <&clkc CLKID_TS_CLK_COMP>; /* CLKID_TS_COMP>;*/ + clock-names = "ts_comp"; + #thermal-sensor-cells = <1>; + }; + + meson_cooldev: meson-cooldev@0 { + status = "okay"; + compatible = "amlogic, meson-cooldev"; + cooling_devices { + cpufreq_cool_cluster0 { + min_state = <1000000>; + dyn_coeff = <140>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "cpufreq_cool0"; + device_type = "cpufreq"; + }; + cpucore_cool_cluster0 { + min_state = <1>; + dyn_coeff = <0>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "cpucore_cool0"; + device_type = "cpucore"; + }; + gpufreq_cool { + min_state = <400>; + dyn_coeff = <140>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "gpufreq_cool0"; + device_type = "gpufreq"; + }; + gpucore_cool { + min_state = <1>; + dyn_coeff = <0>; + gpu_pp = <2>; + cluster_id = <0>; + node_name = "gpucore_cool0"; + device_type = "gpucore"; + }; + }; + cpufreq_cool0:cpufreq_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + cpucore_cool0:cpucore_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + gpufreq_cool0:gpufreq_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + gpucore_cool0:gpucore_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + };/*meson cooling devices end*/ + + thermal-zones { + pll_thermal: pll_thermal { + polling-delay = <1000>; + polling-delay-passive = <100>; + sustainable-power = <1322>; + thermal-sensors = <&p_tsensor 0>; + trips { + pswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + pcontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + phot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + pcritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + cooling-maps { + cpufreq_cooling_map { + trip = <&pcontrol>; + cooling-device = <&cpufreq_cool0 0 11>; + contribution = <1024>; + }; + cpucore_cooling_map { + trip = <&pcontrol>; + cooling-device = <&cpucore_cool0 0 4>; + contribution = <1024>; + }; + gpufreq_cooling_map { + trip = <&pcontrol>; + cooling-device = <&gpufreq_cool0 0 4>; + contribution = <1024>; + }; + }; + }; + ddr_thermal: ddr_thermal { + polling-delay = <2000>; + polling-delay-passive = <1000>; + sustainable-power = <1322>; + thermal-sensors = <&d_tsensor 1>; + trips { + dswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + dcontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + dhot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + dcritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + }; + sar_thermal: sar_thermal { + polling-delay = <2000>; + polling-delay-passive = <1000>; + sustainable-power = <1322>; + thermal-sensors = <&s_tsensor 2>; + trips { + sswitch_on: trip-point@0 { + temperature = <60000>; + hysteresis = <5000>; + type = "passive"; + }; + scontrol: trip-point@1 { + temperature = <75000>; + hysteresis = <5000>; + type = "passive"; + }; + shot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + scritical: trip-point@3 { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + }; + };/*thermal zone end*/ + + cpu_opp_table0: cpu_opp_table0 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <730000>; + }; + opp01 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <730000>; + }; + opp02 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <730000>; + }; + opp03 { + opp-hz = /bits/ 64 <667000000>; + opp-microvolt = <750000>; + }; + opp04 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <770000>; + }; + opp05 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <780000>; + }; + opp06 { + opp-hz = /bits/ 64 <1404000000>; + opp-microvolt = <790000>; + }; + opp07 { + opp-hz = /bits/ 64 <1500000000>; + opp-microvolt = <800000>; + }; + opp08 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <810000>; + }; + opp09 { + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <850000>; + }; + opp10 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <900000>; + }; + opp11 { + opp-hz = /bits/ 64 <1908000000>; + opp-microvolt = <950000>; + }; + }; + + cpufreq-meson { + compatible = "amlogic, cpufreq-meson"; + pinctrl-names = "default"; + pinctrl-0 = <&pwm_ao_d_pins3>; + status = "okay"; + }; + + tuner: tuner { + compatible = "amlogic, tuner"; + status = "okay"; + tuner_cur = <0>; /* default use tuner */ + tuner_num = <1>; /* tuner number, multi tuner support */ + tuner_name_0 = "mxl661_tuner"; + tuner_i2c_adap_0 = <&i2c0>; + tuner_i2c_addr_0 = <0x60>; + tuner_xtal_0 = <0>; /* 0: 16MHz, 1: 24MHz */ + tuner_xtal_mode_0 = <0>; + /* NO_SHARE_XTAL(0) + * SLAVE_XTAL_SHARE(3) + */ + tuner_xtal_cap_0 = <25>; /* when tuner_xtal_mode = 3, set 25 */ + }; + + atv-demod { + compatible = "amlogic, atv-demod"; + status = "okay"; + tuner = <&tuner>; + btsc_sap_mode = <1>; + /* pinctrl-names="atvdemod_agc_pins"; */ + /* pinctrl-0=<&atvdemod_agc_pins>; */ + reg = <0x0 0xff656000 0x0 0x2000 /* demod reg */ + 0x0 0xff63c000 0x0 0x2000 /* hiu reg */ + 0x0 0xff634000 0x0 0x2000 /* periphs reg */ + 0x0 0xff64a000 0x0 0x2000>; /* audio reg */ + reg_23cf = <0x88188832>; + /*default:0x88188832;r840 on haier:0x48188832*/ + }; + + sd_emmc_b: sd@ffe05000 { + status = "okay"; + compatible = "amlogic, meson-mmc-tm2"; + reg = <0x0 0xffe05000 0x0 0x800>; + interrupts = <0 190 1>; + + pinctrl-names = "sd_all_pins", + "sd_clk_cmd_pins", + "sd_1bit_pins"; + pinctrl-0 = <&sd_all_pins>; + pinctrl-1 = <&sd_clk_cmd_pins>; + pinctrl-2 = <&sd_1bit_pins>; + + clocks = <&clkc CLKID_SD_EMMC_B>, + <&clkc CLKID_SD_EMMC_B_P0_COMP>, + <&clkc CLKID_FCLK_DIV2>, + <&clkc CLKID_FCLK_DIV5>, + <&xtal>; + clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal"; + + bus-width = <4>; + cap-sd-highspeed; + cap-mmc-highspeed; + max-frequency = <100000000>; + disable-wp; + sd { + pinname = "sd"; + ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */ + caps = "MMC_CAP_4_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED"; + //"MMC_CAP_NONREMOVABLE"; /**ptm debug */ + f_min = <400000>; + f_max = <200000000>; + max_req_size = <0x20000>; /**128KB*/ + no_sduart = <1>; + gpio_dat3 = <&gpio GPIOC_3 GPIO_ACTIVE_HIGH>; + jtag_pin = <&gpio GPIOC_0 GPIO_ACTIVE_HIGH>; + gpio_cd = <&gpio GPIOC_10 GPIO_ACTIVE_HIGH>; + card_type = <5>; + /* 3:sdio device(ie:sdio-wifi), + * 4:SD combo (IO+mem) card + */ + }; + }; + +}; /* end of / */ + +&i2c0 { + status = "okay"; + clock-frequency = <300000>; + pinctrl-names="default"; + pinctrl-0=<&i2c0_dv_pins>; +}; + +&audiobus { + tdma:tdm@0 { + compatible = "amlogic, tm2-snd-tdma"; + #sound-dai-cells = <0>; + + dai-tdm-lane-slot-mask-in = <1 0>; + dai-tdm-lane-slot-mask-out = <1 1 1 1>; + dai-tdm-clk-sel = <0>; + + clocks = <&clkaudio CLKID_AUDIO_MCLK_A + &clkc CLKID_MPLL0 + &clkc CLKID_MPLL1 + &clkaudio CLKID_AUDIO_SPDIFOUT_A>; + clock-names = "mclk", "clk_srcpll", + "samesource_srcpll", "samesource_clk"; + + pinctrl-names = "tdm_pins"; + pinctrl-0 = ; + + /* + * 0: tdmout_a; + * 1: tdmout_b; + * 2: tdmout_c; + * 3: spdifout; + * 4: spdifout_b; + */ + samesource_sel = <3>; + + /* In for ACODEC_ADC */ + acodec_adc = <1>; + + status = "okay"; + + /* !!!For --TV platform-- ONLY */ + Channel_Mask { + /*i2s has 4 pins, 8channel, mux output*/ + Spdif_samesource_Channel_Mask = "i2s_2/3"; + }; + }; + + tdmb:tdm@1 { + compatible = "amlogic, tm2-snd-tdmb"; + #sound-dai-cells = <0>; + + dai-tdm-lane-slot-mask-in = <1 0 0 0>; + dai-tdm-lane-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <1>; + + clocks = <&clkaudio CLKID_AUDIO_MCLK_B + &clkc CLKID_MPLL1>; + clock-names = "mclk", "clk_srcpll"; + + status = "okay"; + }; + + tdmc:tdm@2 { + compatible = "amlogic, tm2-snd-tdmc"; + #sound-dai-cells = <0>; + + dai-tdm-lane-slot-mask-in = <1 0 0 0>; + dai-tdm-lane-slot-mask-out = <1 0 0 0>; + dai-tdm-clk-sel = <2>; + + clocks = <&clkaudio CLKID_AUDIO_MCLK_C + &clkc CLKID_MPLL2>; + clock-names = "mclk", "clk_srcpll"; + + pinctrl-names = "tdm_pins"; + pinctrl-0 = ; + + status = "okay"; + }; + + pdm:pdm { + compatible = "amlogic, tm2-snd-pdm"; + #sound-dai-cells = <0>; + clocks = <&clkaudio CLKID_AUDIO_GATE_PDM + &clkc CLKID_FCLK_DIV3 + &clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_PDMIN0 + &clkaudio CLKID_AUDIO_PDMIN1>; + clock-names = "gate", + "sysclk_srcpll", + "dclk_srcpll", + "pdm_dclk", + "pdm_sysclk"; + pinctrl-names = "pdm_pins"; + pinctrl-0 = <&pdmin>; + /* mode 0~4, defalut:1 */ + filter_mode = <1>; + status = "okay"; + }; + spdifa:spdif@0 { + compatible = "amlogic, tm2-snd-spdif-a"; + #sound-dai-cells = <0>; + + clocks = <&clkc CLKID_MPLL1 + &clkc CLKID_FCLK_DIV4 + &clkaudio CLKID_AUDIO_GATE_SPDIFIN + &clkaudio CLKID_AUDIO_GATE_SPDIFOUT_A + &clkaudio CLKID_AUDIO_SPDIFIN + &clkaudio CLKID_AUDIO_SPDIFOUT_A>; + clock-names = "sysclk", "fixed_clk", "gate_spdifin", + "gate_spdifout", "clk_spdifin", "clk_spdifout"; + + interrupts = + ; + interrupt-names = "irq_spdifin"; + + pinctrl-names = "spdif_pins", + "spdif_pins_mute"; + + pinctrl-0 = <&spdifout_a &spdifin_a>; + pinctrl-1 = <&spdifout_a_mute>; + + /* + * whether do asrc for pcm and resample a or b + * if raw data, asrc is disabled automatically + * 0: "Disable", + * 1: "Enable:32K", + * 2: "Enable:44K", + * 3: "Enable:48K", + * 4: "Enable:88K", + * 5: "Enable:96K", + * 6: "Enable:176K", + * 7: "Enable:192K", + */ + asrc_id = <0>; + auto_asrc = <3>; + + status = "okay"; + }; + + spdifb:spdif@1 { + compatible = "amlogic, tm2-snd-spdif-b"; + #sound-dai-cells = <0>; + + clocks = <&clkc CLKID_MPLL0 /*CLKID_HIFI_PLL*/ + &clkaudio CLKID_AUDIO_GATE_SPDIFOUT_B + &clkaudio CLKID_AUDIO_SPDIFOUT_B>; + clock-names = "sysclk", + "gate_spdifout", "clk_spdifout"; + + status = "okay"; + }; + + extn:extn { + compatible = "amlogic, snd-extn"; + #sound-dai-cells = <0>; + + + interrupts = + ; + interrupt-names = "irq_frhdmirx"; + + status = "okay"; + }; + + earc:earc { + compatible = "amlogic, tm2-snd-earc"; + #sound-dai-cells = <0>; + + clocks = < &clkaudio CLKID_EARCRX_CMDC + &clkaudio CLKID_EARCRX_DMAC + &clkc CLKID_FCLK_DIV5 + &clkc CLKID_FCLK_DIV3 + &clkaudio CLKID_EARCTX_CMDC + &clkaudio CLKID_EARCTX_DMAC + &clkc CLKID_FCLK_DIV5 + &clkc CLKID_FCLK_DIV3 + >; + clock-names = + "rx_cmdc", + "rx_dmac", + "rx_cmdc_srcpll", + "rx_dmac_srcpll", + "tx_cmdc", + "tx_dmac", + "tx_cmdc_srcpll", + "tx_dmac_srcpll"; + interrupts = < + GIC_SPI 88 IRQ_TYPE_EDGE_RISING + GIC_SPI 87 IRQ_TYPE_EDGE_RISING + >; + interrupt-names = "rx_cmdc", "rx_dmac"; + + status = "okay"; + }; + + aed:effect { + compatible = "amlogic, snd-effect-v2"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_EQDRC + &clkc CLKID_FCLK_DIV5 + &clkaudio CLKID_AUDIO_EQDRC>; + clock-names = "gate", "srcpll", "eqdrc"; + + /* + * 0:tdmout_a + * 1:tdmout_b + * 2:tdmout_c + * 3:spdifout + * 4:spdifout_b + */ + eqdrc_module = <0>; + /* max 0xf, each bit for one lane, usually one lane */ + lane_mask = <0x1>; + /* max 0xff, each bit for one channel */ + channel_mask = <0xff>; + + status = "disable"; + }; + + asrca: resample@0 { + compatible = "amlogic, tl1-resample-a"; + clocks = <&clkc CLKID_MPLL0 + &clkaudio CLKID_AUDIO_MCLK_A + &clkaudio CLKID_AUDIO_RESAMPLE_A>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + /*same with toddr_src + * TDMIN_A, 0 + * TDMIN_B, 1 + * TDMIN_C, 2 + * SPDIFIN, 3 + * PDMIN, 4 + * NONE, + * TDMIN_LB, 6 + * LOOPBACK, 7 + */ + resample_module = <3>; + + status = "disabled"; + }; + + asrcb: resample@1 { + compatible = "amlogic, tl1-resample-b"; + + clocks = <&clkc CLKID_MPLL3 + &clkaudio CLKID_AUDIO_MCLK_F + &clkaudio CLKID_AUDIO_RESAMPLE_B>; + clock-names = "resample_pll", "resample_src", "resample_clk"; + + /*same with toddr_src + * TDMIN_A, 0 + * TDMIN_B, 1 + * TDMIN_C, 2 + * SPDIFIN, 3 + * PDMIN, 4 + * NONE, + * TDMIN_LB, 6 + * LOOPBACK, 7 + */ + resample_module = <3>; + + status = "disabled"; + }; + + vad:vad { + compatible = "amlogic, snd-vad"; + #sound-dai-cells = <0>; + + clocks = <&clkaudio CLKID_AUDIO_GATE_TOVAD + &clkc CLKID_FCLK_DIV5 + &clkaudio CLKID_AUDIO_VAD>; + clock-names = "gate", "pll", "clk"; + + interrupts = ; + interrupt-names = "irq_wakeup", "irq_frame_sync"; + + /* + * Data src sel: + * 0: tdmin_a; + * 1: tdmin_b; + * 2: tdmin_c; + * 3: spdifin; + * 4: pdmin; + * 5: loopback_b; + * 6: tdmin_lb; + * 7: loopback_a; + */ + src = <4>; + + /* + * deal with hot word in user space or kernel space + * 0: in user space + * 1: in kernel space + */ + level = <1>; + + status = "disabled"; + }; +}; /* end of audiobus */ + +&pinctrl_periphs { + /* audio pin mux */ + + tdma_mclk: tdma_mclk { + mux { /* GPIOH_4 */ + groups = "mclk0_h"; + function = "mclk0"; + }; + }; + + tdmout_a: tdmout_a { + mux { /* GPIOH_5, GPIOH_6, GPIOH_7, GPIOH_8*/ + groups = "tdma_fs_h", + "tdma_sclk_h", + "tdma_dout0_h", + "tdma_dout1_h"; + function = "tdma_out"; + bias-pull-down; + }; + }; + + tdmin_a: tdmin_a { + mux { /* GPIOH_11, GPIOH_12 */ + groups = "tdma_din0_h", + "tdma_din1_h"; + function = "tdma_in"; + }; + }; + + tdmout_c: tdmout_c { + mux { /* GPIODV_7, GPIODV_8, GPIODV_9 */ + groups = "tdmc_sclk", + "tdmc_fs", + "tdmc_dout0"; + function = "tdmc_out"; + }; + }; + + tdmin_c: tdmin_c { + mux { /* GPIODV_10 */ + groups = "tdmc_din1"; + function = "tdmc_in"; + }; + }; + + spdifin_a: spdifin_a { + mux { /* GPIODV_5 */ + groups = "spdif_in"; + function = "spdif_in"; + }; + }; + + spdifout_a: spdifout_a { + mux { /* GPIODV_4 */ + groups = "spdif_out_dv4"; + function = "spdif_out"; + }; + }; + + spdifout_a_mute: spdifout_a_mute { + mux { /* GPIODV_4 */ + groups = "GPIODV_4"; + function = "gpio_periphs"; + }; + }; + + pdmin: pdmin { + mux { /* GPIOZ_7, GPIOZ_8, pdm_din2_z4 */ + groups = "pdm_dclk_z", + "pdm_din0_z", + "pdm_din2_z4"; + function = "pdm"; + }; + }; + + +}; /* end of pinctrl_periphs */ + +&pinctrl_aobus { + spdifout: spdifout { + mux { /* gpiao_10 */ + groups = "spdif_out_ao"; + function = "spdif_out_ao"; + }; + }; +}; /* end of pinctrl_aobus */ + +&audio_data{ + status = "okay"; +}; + +&i2c2 { + status = "okay"; + pinctrl-names="default"; + pinctrl-0=<&i2c2_z_pins>; + clock-frequency = <400000>; + + tas5805: tas5805@36 { + compatible = "ti,tas5805"; + #sound-dai-cells = <0>; + codec_name = "tas5805"; + reg = <0x0 0x2d>; + status = "disable"; + }; + + ad82584f: ad82584f@62 { + compatible = "ESMT, ad82584f"; + #sound-dai-cells = <0>; + reg = <0x0 0x31>; + status = "disabled"; + reset_pin = <&gpio_ao GPIOAO_6 0>; + }; + +}; + +&sd_emmc_c { + status = "okay"; + emmc { + caps = "MMC_CAP_8_BIT_DATA", + "MMC_CAP_MMC_HIGHSPEED", + "MMC_CAP_SD_HIGHSPEED", + "MMC_CAP_NONREMOVABLE", + "MMC_CAP_1_8V_DDR", + "MMC_CAP_HW_RESET", + "MMC_CAP_ERASE", + "MMC_CAP_CMD23"; + caps2 = "MMC_CAP2_HS200"; + /* "MMC_CAP2_HS400";*/ + f_min = <400000>; + f_max = <200000000>; + }; +}; + +&spifc { + status = "disabled"; + spi-nor@0 { + cs_gpios = <&gpio BOOT_13 GPIO_ACTIVE_HIGH>; + }; +}; + +&slc_nand { + status = "disabled"; + plat-names = "bootloader", "nandnormal"; + plat-num = <2>; + plat-part-0 = <&bootloader>; + plat-part-1 = <&nandnormal>; + bootloader: bootloader{ + enable_pad = "ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <1>; + part_num = <0>; + rb_detect = <1>; + }; + nandnormal: nandnormal{ + enable_pad = "ce0"; + busy_pad = "rb0"; + timming_mode = "mode5"; + bch_mode = "bch8_1k"; + plane_mode = "twoplane"; + t_rea = <20>; + t_rhoh = <15>; + chip_num = <2>; + part_num = <3>; + partition = <&nand_partitions>; + rb_detect = <1>; + }; + nand_partitions:nand_partition{ + /* + * if bl_mode is 1, tpl size was generate by + * fip_copies * fip_size which + * will not skip bad when calculating + * the partition size; + * + * if bl_mode is 0, + * tpl partition must be comment out. + */ + tpl{ + offset=<0x0 0x0>; + size=<0x0 0x0>; + }; + logo{ + offset=<0x0 0x0>; + size=<0x0 0x200000>; + }; + recovery{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + boot{ + offset=<0x0 0x0>; + size=<0x0 0x1000000>; + }; + system{ + offset=<0x0 0x0>; + size=<0x0 0x4000000>; + }; + data{ + offset=<0xffffffff 0xffffffff>; + size=<0x0 0x0>; + }; + }; +}; + +ðmac { + status = "okay"; + pinctrl-names = "internal_eth_pins"; + pinctrl-0 = <&internal_eth_pins>; + mc_val = <0x4be04>; + + internal_phy=<1>; +}; + +&uart_A { + status = "okay"; +}; + +&dwc3 { + status = "okay"; +}; + +&usb2_phy_v2 { + status = "okay"; + portnum = <3>; +}; + +&usb3_phy_v2 { + status = "okay"; + portnum = <2>; + portconfig-30 = <1>; + portconfig-31 = <1>; +}; + +&usb_otg { + status = "okay"; + otg = <0>; +}; + +&dwc2_a { + status = "okay"; + /** 0: normal, 1: otg+dwc3 host only, 2: otg+dwc3 device only*/ + controller-type = <1>; +}; + +&pcie_A { + /* pcie a reset gpio must be updated */ + reset-gpio = <&gpio_ao GPIOAO_11 GPIO_ACTIVE_HIGH>; + status = "disable"; +}; + +&pcie_B { + /* pcie b reset gpio must be updated */ + reset-gpio = <&gpio GPIOH_22 GPIO_ACTIVE_HIGH>; + status = "disable"; +}; + +&spicc0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&spicc0_pins_h>; + cs-gpios = <&gpio GPIOH_20 0>; +}; + +&meson_fb { + status = "okay"; + display_size_default = <1920 1080 1920 2160 32>; + mem_size = <0x00800000 0x1980000 0x100000 0x100000 0x800000>; + logo_addr = "0x7f800000"; + mem_alloc = <0>; + pxp_mode = <0>; /** 0:normal mode 1:pxp mode */ +}; + +&pwm_AO_cd { + status = "okay"; +}; + +&saradc { + status = "okay"; +}; + +&i2c1 { + status = "okay"; + clock-frequency = <300000>; + pinctrl-names="default"; + pinctrl-0=<&i2c1_h_pins>; + + lcd_extern_i2c0: lcd_extern_i2c@0 { + compatible = "lcd_ext, i2c"; + dev_name = "i2c_T5800Q"; + reg = <0x0 0x1c>; + status = "okay"; + }; + + lcd_extern_i2c1: lcd_extern_i2c@1 { + compatible = "lcd_ext, i2c"; + dev_name = "i2c_ANX6862"; + reg = <0x0 0x20>; + status = "okay"; + }; + + lcd_extern_i2c2: lcd_extern_i2c@2 { + compatible = "lcd_ext, i2c"; + dev_name = "i2c_ANX7911"; + reg = <0x0 0x74>; + status = "okay"; + }; +}; + +&efuse { + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/amlogic/txl_t950_p341.dts b/arch/arm64/boot/dts/amlogic/txl_t950_p341.dts index c3ad02ce19b3..2dcf8572fd33 100644 --- a/arch/arm64/boot/dts/amlogic/txl_t950_p341.dts +++ b/arch/arm64/boot/dts/amlogic/txl_t950_p341.dts @@ -436,18 +436,21 @@ }; tuner: tuner { + compatible = "amlogic, tuner"; status = "okay"; - tuner_name = "r842_tuner"; - tuner_i2c_adap = <&i2c1>; - tuner_i2c_addr = <0xf6>; - tuner_xtal = <1>; /* 0: 16MHz, 1: 24MHz, 3: 27MHz */ - tuner_xtal_mode = <3>; + tuner_cur = <0>; /* default use tuner */ + tuner_num = <1>; /* tuner number, multi tuner support */ + tuner_name_0 = "r842_tuner"; + tuner_i2c_adap_0 = <&i2c1>; + tuner_i2c_addr_0 = <0xf6>; + tuner_xtal_0 = <1>; /* 0: 16MHz, 1: 24MHz, 3: 27MHz */ + tuner_xtal_mode_0 = <3>; /* NO_SHARE_XTAL(0) * MASTER_TO_SLAVE_XTAL_IN(1) * MASTER_TO_SLAVE_XTAL_OUT(2) * SLAVE_XTAL_OUT(3) */ - tuner_xtal_cap = <0>; /* 0 ~ 41 (pf) */ + tuner_xtal_cap_0 = <0>; /* 0 ~ 41 (pf) */ }; atv-demod { diff --git a/arch/arm64/boot/dts/amlogic/txl_t960_p346.dts b/arch/arm64/boot/dts/amlogic/txl_t960_p346.dts index 1d3a079c0a09..8731df171276 100644 --- a/arch/arm64/boot/dts/amlogic/txl_t960_p346.dts +++ b/arch/arm64/boot/dts/amlogic/txl_t960_p346.dts @@ -436,18 +436,21 @@ }; tuner: tuner { + compatible = "amlogic, tuner"; status = "okay"; - tuner_name = "r842_tuner"; - tuner_i2c_adap = <&i2c1>; - tuner_i2c_addr = <0xf6>; - tuner_xtal = <1>; /* 0: 16MHz, 1: 24MHz, 3: 27MHz */ - tuner_xtal_mode = <3>; + tuner_cur = <0>; /* default use tuner */ + tuner_num = <1>; /* tuner number, multi tuner support */ + tuner_name_0 = "r842_tuner"; + tuner_i2c_adap_0 = <&i2c1>; + tuner_i2c_addr_0 = <0xf6>; + tuner_xtal_0 = <1>; /* 0: 16MHz, 1: 24MHz, 3: 27MHz */ + tuner_xtal_mode_0 = <3>; /* NO_SHARE_XTAL(0) * MASTER_TO_SLAVE_XTAL_IN(1) * MASTER_TO_SLAVE_XTAL_OUT(2) * SLAVE_XTAL_OUT(3) */ - tuner_xtal_cap = <0>; /* 0 ~ 41 (pf) */ + tuner_xtal_cap_0 = <0>; /* 0 ~ 41 (pf) */ }; atv-demod { diff --git a/arch/arm64/boot/dts/amlogic/txl_t962_p320.dts b/arch/arm64/boot/dts/amlogic/txl_t962_p320.dts index b87e7e04187d..374583ed929f 100644 --- a/arch/arm64/boot/dts/amlogic/txl_t962_p320.dts +++ b/arch/arm64/boot/dts/amlogic/txl_t962_p320.dts @@ -427,13 +427,16 @@ }; tuner: tuner { + compatible = "amlogic, tuner"; status = "okay"; - tuner_name = "si2151_tuner"; - tuner_i2c_adap = <&i2c1>; - tuner_i2c_addr = <0x60>; - /* tuner_xtal = <0>; */ /* unuse for si2151 */ - /* tuner_xtal_mode = <0>; */ - /* tuner_xtal_cap = <0>; */ + tuner_cur = <0>; /* default use tuner */ + tuner_num = <1>; /* tuner number, multi tuner support */ + tuner_name_0 = "si2151_tuner"; + tuner_i2c_adap_0 = <&i2c1>; + tuner_i2c_addr_0 = <0x60>; + /* tuner_xtal_0 = <0>; */ /* unuse for si2151 */ + /* tuner_xtal_mode_0 = <0>; */ + /* tuner_xtal_cap_0 = <0>; */ }; atv-demod { diff --git a/arch/arm64/boot/dts/amlogic/txl_t962_p321.dts b/arch/arm64/boot/dts/amlogic/txl_t962_p321.dts index 446bf37091e4..c52c595488a4 100644 --- a/arch/arm64/boot/dts/amlogic/txl_t962_p321.dts +++ b/arch/arm64/boot/dts/amlogic/txl_t962_p321.dts @@ -272,6 +272,22 @@ status = "okay"; }; + amlvideo2_0 { + compatible = "amlogic, amlvideo2"; + dev_name = "amlvideo2"; + status = "okay"; + amlvideo2_id = <0>; + cma_mode = <1>; + }; + + amlvideo2_1 { + compatible = "amlogic, amlvideo2"; + dev_name = "amlvideo2"; + status = "okay"; + amlvideo2_id = <1>; + cma_mode = <1>; + }; + hdmirx { compatible = "amlogic, hdmirx-txl"; status = "okay"; @@ -424,18 +440,21 @@ }; tuner: tuner { + compatible = "amlogic, tuner"; status = "okay"; - tuner_name = "r842_tuner"; - tuner_i2c_adap = <&i2c1>; - tuner_i2c_addr = <0xf6>; - tuner_xtal = <1>; /* 0: 16MHz, 1: 24MHz, 3: 27MHz */ - tuner_xtal_mode = <0>; + tuner_cur = <0>; /* default use tuner */ + tuner_num = <1>; /* tuner number, multi tuner support */ + tuner_name_0 = "r842_tuner"; + tuner_i2c_adap_0 = <&i2c1>; + tuner_i2c_addr_0 = <0xf6>; + tuner_xtal_0 = <1>; /* 0: 16MHz, 1: 24MHz, 3: 27MHz */ + tuner_xtal_mode_0 = <0>; /* NO_SHARE_XTAL(0) * MASTER_TO_SLAVE_XTAL_IN(1) * MASTER_TO_SLAVE_XTAL_OUT(2) * SLAVE_XTAL_OUT(3) */ - tuner_xtal_cap = <38>; /* 0 ~ 41 (pf) */ + tuner_xtal_cap_0 = <38>; /* 0 ~ 41 (pf) */ }; atv-demod { diff --git a/arch/arm64/boot/dts/amlogic/txl_t962_p321_720p.dts b/arch/arm64/boot/dts/amlogic/txl_t962_p321_720p.dts index ce7bea90cd69..89f0f7f7476b 100644 --- a/arch/arm64/boot/dts/amlogic/txl_t962_p321_720p.dts +++ b/arch/arm64/boot/dts/amlogic/txl_t962_p321_720p.dts @@ -272,6 +272,22 @@ status = "okay"; }; + amlvideo2_0 { + compatible = "amlogic, amlvideo2"; + dev_name = "amlvideo2"; + status = "okay"; + amlvideo2_id = <0>; + cma_mode = <1>; + }; + + amlvideo2_1 { + compatible = "amlogic, amlvideo2"; + dev_name = "amlvideo2"; + status = "okay"; + amlvideo2_id = <1>; + cma_mode = <1>; + }; + hdmirx { compatible = "amlogic, hdmirx-txl"; status = "okay"; @@ -424,18 +440,21 @@ }; tuner: tuner { + compatible = "amlogic, tuner"; status = "okay"; - tuner_name = "r842_tuner"; - tuner_i2c_adap = <&i2c1>; - tuner_i2c_addr = <0xf6>; - tuner_xtal = <1>; /* 0: 16MHz, 1: 24MHz, 3: 27MHz */ - tuner_xtal_mode = <0>; + tuner_cur = <0>; /* default use tuner */ + tuner_num = <1>; /* tuner number, multi tuner support */ + tuner_name_0 = "r842_tuner"; + tuner_i2c_adap_0 = <&i2c1>; + tuner_i2c_addr_0 = <0xf6>; + tuner_xtal_0 = <1>; /* 0: 16MHz, 1: 24MHz, 3: 27MHz */ + tuner_xtal_mode_0 = <0>; /* NO_SHARE_XTAL(0) * MASTER_TO_SLAVE_XTAL_IN(1) * MASTER_TO_SLAVE_XTAL_OUT(2) * SLAVE_XTAL_OUT(3) */ - tuner_xtal_cap = <38>; /* 0 ~ 41 (pf) */ + tuner_xtal_cap_0 = <38>; /* 0 ~ 41 (pf) */ }; atv-demod { diff --git a/arch/arm64/boot/dts/amlogic/txlx_t962e_r321.dts b/arch/arm64/boot/dts/amlogic/txlx_t962e_r321.dts index abf3c56be82f..d281ce3b80c0 100644 --- a/arch/arm64/boot/dts/amlogic/txlx_t962e_r321.dts +++ b/arch/arm64/boot/dts/amlogic/txlx_t962e_r321.dts @@ -45,7 +45,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x0 0x100000 0x0 0x7ff00000>; + linux,usable-memory = <0x0 0x0 0x0 0x80000000>; }; reserved-memory { @@ -58,8 +58,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { compatible = "shared-dma-pool"; @@ -161,12 +160,6 @@ size = <0x0 0x01400000>; alignment = <0x0 0x400000>; }; - - /*vbi reserved mem*/ - vbi_reserved:linux,vbi { - compatible = "amlogic, vbi-mem"; - size = <0x0 0x100000>; - }; }; /* for external keypad */ @@ -567,11 +560,9 @@ vbi { compatible = "amlogic, vbi"; - memory-region = <&vbi_reserved>; dev_name = "vbi"; status = "okay"; interrupts = <0 83 1>; - reserve-iomap = "true"; }; tvafe_avin_detect { @@ -625,13 +616,16 @@ }; tuner: tuner { + compatible = "amlogic, tuner"; status = "okay"; - tuner_name = "si2151_tuner"; - tuner_i2c_adap = <&i2c1>; - tuner_i2c_addr = <0x60>; - /* tuner_xtal = <0>; */ /* unuse for si2151 */ - /* tuner_xtal_mode = <0>; */ - /* tuner_xtal_cap = <0>; */ + tuner_cur = <0>; /* default use tuner */ + tuner_num = <1>; /* tuner number, multi tuner support */ + tuner_name_0 = "si2151_tuner"; + tuner_i2c_adap_0 = <&i2c1>; + tuner_i2c_addr_0 = <0x60>; + /* tuner_xtal_0 = <0>; */ /* unuse for si2151 */ + /* tuner_xtal_mode_0 = <0>; */ + /* tuner_xtal_cap_0 = <0>; */ }; atv-demod { diff --git a/arch/arm64/boot/dts/amlogic/txlx_t962e_r321_buildroot.dts b/arch/arm64/boot/dts/amlogic/txlx_t962e_r321_buildroot.dts index 71ae1696fa1c..c3030551b899 100644 --- a/arch/arm64/boot/dts/amlogic/txlx_t962e_r321_buildroot.dts +++ b/arch/arm64/boot/dts/amlogic/txlx_t962e_r321_buildroot.dts @@ -44,7 +44,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x0 0x100000 0x0 0x7ff00000>; + linux,usable-memory = <0x0 0x0 0x0 0x80000000>; }; reserved-memory { @@ -57,8 +57,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { @@ -152,12 +151,6 @@ size = <0x0 0x01400000>; alignment = <0x0 0x400000>; }; - - /*vbi reserved mem*/ - vbi_reserved:linux,vbi { - compatible = "amlogic, vbi-mem"; - size = <0x0 0x100000>; - }; }; /* for external keypad */ @@ -610,11 +603,9 @@ vbi { compatible = "amlogic, vbi"; - memory-region = <&vbi_reserved>; dev_name = "vbi"; status = "okay"; interrupts = <0 83 1>; - reserve-iomap = "true"; }; tvafe_avin_detect { @@ -669,13 +660,16 @@ }; tuner: tuner { + compatible = "amlogic, tuner"; status = "okay"; - tuner_name = "si2151_tuner"; - tuner_i2c_adap = <&i2c1>; - tuner_i2c_addr = <0x60>; - /* tuner_xtal = <0>; */ /* unuse for si2151 */ - /* tuner_xtal_mode = <0>; */ - /* tuner_xtal_cap = <0>; */ + tuner_cur = <0>; /* default use tuner */ + tuner_num = <1>; /* tuner number, multi tuner support */ + tuner_name_0 = "si2151_tuner"; + tuner_i2c_adap_0 = <&i2c1>; + tuner_i2c_addr_0 = <0x60>; + /* tuner_xtal_0 = <0>; */ /* unuse for si2151 */ + /* tuner_xtal_mode_0 = <0>; */ + /* tuner_xtal_cap_0 = <0>; */ }; atv-demod { diff --git a/arch/arm64/boot/dts/amlogic/txlx_t962x_r311_1g.dts b/arch/arm64/boot/dts/amlogic/txlx_t962x_r311_1g.dts index fbe808f93aef..df6523b6500c 100644 --- a/arch/arm64/boot/dts/amlogic/txlx_t962x_r311_1g.dts +++ b/arch/arm64/boot/dts/amlogic/txlx_t962x_r311_1g.dts @@ -48,7 +48,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x0 0x100000 0x0 0x3ff00000>; + linux,usable-memory = <0x0 0x0 0x0 0x40000000>; }; reserved-memory { @@ -61,8 +61,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { compatible = "shared-dma-pool"; @@ -164,12 +163,6 @@ size = <0x0 0x01400000>; alignment = <0x0 0x400000>; }; - - /*vbi reserved mem*/ - vbi_reserved:linux,vbi { - compatible = "amlogic, vbi-mem"; - size = <0x0 0x100000>; - }; }; amlogic_battery:dummy-battery { @@ -572,11 +565,9 @@ vbi { compatible = "amlogic, vbi"; - memory-region = <&vbi_reserved>; dev_name = "vbi"; status = "okay"; interrupts = <0 83 1>; - reserve-iomap = "true"; }; tvafe_avin_detect { @@ -626,16 +617,19 @@ }; tuner: tuner { + compatible = "amlogic, tuner"; status = "okay"; - tuner_name = "mxl661_tuner"; - tuner_i2c_adap = <&i2c1>; - tuner_i2c_addr = <0x60>; - tuner_xtal = <0>; /* 0: 16MHz, 1: 24MHz */ - tuner_xtal_mode = <0>; + tuner_cur = <0>; /* default use tuner */ + tuner_num = <1>; /* tuner number, multi tuner support */ + tuner_name_0 = "mxl661_tuner"; + tuner_i2c_adap_0 = <&i2c1>; + tuner_i2c_addr_0 = <0x60>; + tuner_xtal_0 = <0>; /* 0: 16MHz, 1: 24MHz */ + tuner_xtal_mode_0 = <0>; /* NO_SHARE_XTAL(0) * SLAVE_XTAL_SHARE(1) */ - tuner_xtal_cap = <30>; /* when tuner_xtal_mode = 1, set 25 */ + tuner_xtal_cap_0 = <30>; /* when tuner_xtal_mode = 1, set 25 */ }; atv-demod { @@ -1554,7 +1548,7 @@ /*lcd_extern*/ lcd_extern_off_pins:lcd_extern_off_pin { mux { - pins = "GPIOH_2", + groups = "GPIOH_2", "GPIOH_3"; function = "gpio_periphs"; /*output-high;*/ @@ -1566,50 +1560,50 @@ /*backlight*/ bl_pwm_on_pins:bl_pwm_on_pin { mux { - pins = "pwm_b"; + groups = "pwm_b"; function = "pwm_b"; }; }; bl_pwm_vs_on_pins:bl_pwm_vs_on_pin { mux { - pins = "pwm_vs_z6"; + groups = "pwm_vs_z6"; function = "pwm_vs"; }; }; bl_pwm_off_pins:bl_pwm_off_pin { mux { - pins = "GPIOZ_6"; + groups = "GPIOZ_6"; function = "gpio_periphs"; output-low; }; }; bl_pwm_combo_0_on_pins:bl_pwm_combo_0_on_pin { mux { - pins = "pwm_b"; + groups = "pwm_b"; function = "pwm_b"; }; }; bl_pwm_combo_1_on_pins:bl_pwm_combo_1_on_pin { mux { - pins = "pwm_c_z"; + groups = "pwm_c_z"; function = "pwm_c"; }; }; bl_pwm_combo_0_vs_on_pins:bl_pwm_combo_0_vs_on_pin { mux { - pins = "pwm_vs_z6"; + groups = "pwm_vs_z6"; function = "pwm_vs"; }; }; bl_pwm_combo_1_vs_on_pins:bl_pwm_combo_1_vs_on_pin { mux { - pins = "pwm_vs_z7"; + groups = "pwm_vs_z7"; function = "pwm_vs"; }; }; bl_pwm_combo_off_pins:bl_pwm_combo_off_pin { mux { - pins = "GPIOZ_6", + groups = "GPIOZ_6", "GPIOZ_7"; function = "gpio_periphs"; output-low; diff --git a/arch/arm64/boot/dts/amlogic/txlx_t962x_r311_2g.dts b/arch/arm64/boot/dts/amlogic/txlx_t962x_r311_2g.dts index b3b9a8acf7b4..95975254a527 100644 --- a/arch/arm64/boot/dts/amlogic/txlx_t962x_r311_2g.dts +++ b/arch/arm64/boot/dts/amlogic/txlx_t962x_r311_2g.dts @@ -48,7 +48,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x0 0x100000 0x0 0x7ff00000>; + linux,usable-memory = <0x0 0x0 0x0 0x80000000>; }; reserved-memory { @@ -61,8 +61,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { compatible = "shared-dma-pool"; @@ -164,12 +163,6 @@ size = <0x0 0x01400000>; alignment = <0x0 0x400000>; }; - - /*vbi reserved mem*/ - vbi_reserved:linux,vbi { - compatible = "amlogic, vbi-mem"; - size = <0x0 0x100000>; - }; }; amlogic_battery:dummy-battery { @@ -572,11 +565,9 @@ vbi { compatible = "amlogic, vbi"; - memory-region = <&vbi_reserved>; dev_name = "vbi"; status = "okay"; interrupts = <0 83 1>; - reserve-iomap = "true"; }; tvafe_avin_detect { @@ -626,16 +617,19 @@ }; tuner: tuner { + compatible = "amlogic, tuner"; status = "okay"; - tuner_name = "mxl661_tuner"; - tuner_i2c_adap = <&i2c1>; - tuner_i2c_addr = <0x60>; - tuner_xtal = <0>; /* 0: 16MHz, 1: 24MHz */ - tuner_xtal_mode = <0>; + tuner_cur = <0>; /* default use tuner */ + tuner_num = <1>; /* tuner number, multi tuner support */ + tuner_name_0 = "mxl661_tuner"; + tuner_i2c_adap_0 = <&i2c1>; + tuner_i2c_addr_0 = <0x60>; + tuner_xtal_0 = <0>; /* 0: 16MHz, 1: 24MHz */ + tuner_xtal_mode_0 = <0>; /* NO_SHARE_XTAL(0) * SLAVE_XTAL_SHARE(1) */ - tuner_xtal_cap = <30>; /* when tuner_xtal_mode = 1, set 25 */ + tuner_xtal_cap_0 = <30>; /* when tuner_xtal_mode = 1, set 25 */ }; atv-demod { @@ -1560,7 +1554,7 @@ /*lcd_extern*/ lcd_extern_off_pins:lcd_extern_off_pin { mux { - pins = "GPIOH_2", + groups = "GPIOH_2", "GPIOH_3"; function = "gpio_periphs"; /*output-high;*/ @@ -1572,50 +1566,50 @@ /*backlight*/ bl_pwm_on_pins:bl_pwm_on_pin { mux { - pins = "pwm_b"; + groups = "pwm_b"; function = "pwm_b"; }; }; bl_pwm_vs_on_pins:bl_pwm_vs_on_pin { mux { - pins = "pwm_vs_z6"; + groups = "pwm_vs_z6"; function = "pwm_vs"; }; }; bl_pwm_off_pins:bl_pwm_off_pin { mux { - pins = "GPIOZ_6"; + groups = "GPIOZ_6"; function = "gpio_periphs"; output-low; }; }; bl_pwm_combo_0_on_pins:bl_pwm_combo_0_on_pin { mux { - pins = "pwm_b"; + groups = "pwm_b"; function = "pwm_b"; }; }; bl_pwm_combo_1_on_pins:bl_pwm_combo_1_on_pin { mux { - pins = "pwm_c_z"; + groups = "pwm_c_z"; function = "pwm_c"; }; }; bl_pwm_combo_0_vs_on_pins:bl_pwm_combo_0_vs_on_pin { mux { - pins = "pwm_vs_z6"; + groups = "pwm_vs_z6"; function = "pwm_vs"; }; }; bl_pwm_combo_1_vs_on_pins:bl_pwm_combo_1_vs_on_pin { mux { - pins = "pwm_vs_z7"; + groups = "pwm_vs_z7"; function = "pwm_vs"; }; }; bl_pwm_combo_off_pins:bl_pwm_combo_off_pin { mux { - pins = "GPIOZ_6", + groups = "GPIOZ_6", "GPIOZ_7"; function = "gpio_periphs"; output-low; diff --git a/arch/arm64/boot/dts/amlogic/txlx_t962x_r311_720p.dts b/arch/arm64/boot/dts/amlogic/txlx_t962x_r311_720p.dts index b838d0966d7b..70d11b2dba28 100644 --- a/arch/arm64/boot/dts/amlogic/txlx_t962x_r311_720p.dts +++ b/arch/arm64/boot/dts/amlogic/txlx_t962x_r311_720p.dts @@ -48,7 +48,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x0 0x100000 0x0 0x3ff00000>; + linux,usable-memory = <0x0 0x0 0x0 0x40000000>; }; reserved-memory { @@ -61,8 +61,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { compatible = "shared-dma-pool"; @@ -164,12 +163,6 @@ size = <0x0 0x01400000>; alignment = <0x0 0x400000>; }; - - /*vbi reserved mem*/ - vbi_reserved:linux,vbi { - compatible = "amlogic, vbi-mem"; - size = <0x0 0x100000>; - }; }; amlogic_battery:dummy-battery { @@ -571,11 +564,9 @@ vbi { compatible = "amlogic, vbi"; - memory-region = <&vbi_reserved>; dev_name = "vbi"; status = "okay"; interrupts = <0 83 1>; - reserve-iomap = "true"; }; tvafe_avin_detect { @@ -625,16 +616,19 @@ }; tuner: tuner { + compatible = "amlogic, tuner"; status = "okay"; - tuner_name = "mxl661_tuner"; - tuner_i2c_adap = <&i2c1>; - tuner_i2c_addr = <0x60>; - tuner_xtal = <0>; /* 0: 16MHz, 1: 24MHz */ - tuner_xtal_mode = <0>; + tuner_cur = <0>; /* default use tuner */ + tuner_num = <1>; /* tuner number, multi tuner support */ + tuner_name_0 = "mxl661_tuner"; + tuner_i2c_adap_0 = <&i2c1>; + tuner_i2c_addr_0 = <0x60>; + tuner_xtal_0 = <0>; /* 0: 16MHz, 1: 24MHz */ + tuner_xtal_mode_0 = <0>; /* NO_SHARE_XTAL(0) * SLAVE_XTAL_SHARE(1) */ - tuner_xtal_cap = <30>; /* when tuner_xtal_mode = 1, set 25 */ + tuner_xtal_cap_0 = <30>; /* when tuner_xtal_mode = 1, set 25 */ }; atv-demod { @@ -1552,7 +1546,7 @@ /*lcd_extern*/ lcd_extern_off_pins:lcd_extern_off_pin { mux { - pins = "GPIOH_2", + groups = "GPIOH_2", "GPIOH_3"; function = "gpio_periphs"; /*output-high;*/ @@ -1564,50 +1558,50 @@ /*backlight*/ bl_pwm_on_pins:bl_pwm_on_pin { mux { - pins = "pwm_b"; + groups = "pwm_b"; function = "pwm_b"; }; }; bl_pwm_vs_on_pins:bl_pwm_vs_on_pin { mux { - pins = "pwm_vs_z6"; + groups = "pwm_vs_z6"; function = "pwm_vs"; }; }; bl_pwm_off_pins:bl_pwm_off_pin { mux { - pins = "GPIOZ_6"; + groups = "GPIOZ_6"; function = "gpio_periphs"; output-low; }; }; bl_pwm_combo_0_on_pins:bl_pwm_combo_0_on_pin { mux { - pins = "pwm_b"; + groups = "pwm_b"; function = "pwm_b"; }; }; bl_pwm_combo_1_on_pins:bl_pwm_combo_1_on_pin { mux { - pins = "pwm_c_z"; + groups = "pwm_c_z"; function = "pwm_c"; }; }; bl_pwm_combo_0_vs_on_pins:bl_pwm_combo_0_vs_on_pin { mux { - pins = "pwm_vs_z6"; + groups = "pwm_vs_z6"; function = "pwm_vs"; }; }; bl_pwm_combo_1_vs_on_pins:bl_pwm_combo_1_vs_on_pin { mux { - pins = "pwm_vs_z7"; + groups = "pwm_vs_z7"; function = "pwm_vs"; }; }; bl_pwm_combo_off_pins:bl_pwm_combo_off_pin { mux { - pins = "GPIOZ_6", + groups = "GPIOZ_6", "GPIOZ_7"; function = "gpio_periphs"; output-low; diff --git a/arch/arm64/boot/dts/amlogic/txlx_t962x_r314.dts b/arch/arm64/boot/dts/amlogic/txlx_t962x_r314.dts index 8cc857ebfb41..3b1058718814 100644 --- a/arch/arm64/boot/dts/amlogic/txlx_t962x_r314.dts +++ b/arch/arm64/boot/dts/amlogic/txlx_t962x_r314.dts @@ -48,7 +48,7 @@ memory@00000000 { device_type = "memory"; - linux,usable-memory = <0x0 0x100000 0x0 0x5ff00000>; + linux,usable-memory = <0x0 0x0 0x0 0x60000000>; }; reserved-memory { @@ -61,8 +61,7 @@ reg = <0x0 0x07400000 0x0 0x00100000>; record-size = <0x8000>; console-size = <0x8000>; - ftrace-size = <0x0>; - pmsg-size = <0x8000>; + ftrace-size = <0x20000>; }; secmon_reserved:linux,secmon { compatible = "shared-dma-pool"; @@ -165,12 +164,6 @@ size = <0x0 0x01400000>; alignment = <0x0 0x400000>; }; - - /*vbi reserved mem*/ - vbi_reserved:linux,vbi { - compatible = "amlogic, vbi-mem"; - size = <0x0 0x100000>; - }; }; amlogic_battery:dummy-battery { @@ -573,11 +566,9 @@ vbi { compatible = "amlogic, vbi"; - memory-region = <&vbi_reserved>; dev_name = "vbi"; status = "okay"; interrupts = <0 83 1>; - reserve-iomap = "true"; }; tvafe_avin_detect { @@ -627,21 +618,24 @@ }; tuner: tuner { - status = "okay"; - tuner_name = "mxl661_tuner"; - tuner_i2c_adap = <&i2c1>; - tuner_i2c_addr = <0x60>; - tuner_xtal = <0>; /* 0: 16MHz, 1: 24MHz */ - tuner_xtal_mode = <0>; + compatible = "amlogic, tuner"; + status = "disabled"; + tuner_cur = <0>; /* default use tuner */ + tuner_num = <1>; /* tuner number, multi tuner support */ + tuner_name_0 = "mxl661_tuner"; + tuner_i2c_adap_0 = <&i2c1>; + tuner_i2c_addr_0 = <0x60>; + tuner_xtal_0 = <0>; /* 0: 16MHz, 1: 24MHz */ + tuner_xtal_mode_0 = <0>; /* NO_SHARE_XTAL(0) * SLAVE_XTAL_SHARE(1) */ - tuner_xtal_cap = <30>; /* when tuner_xtal_mode = 1, set 25 */ + tuner_xtal_cap_0 = <30>; /* when tuner_xtal_mode = 1, set 25 */ }; atv-demod { compatible = "amlogic, atv-demod"; - status = "okay"; + status = "disabled"; tuner = <&tuner>; btsc_sap_mode = <1>; /* pinctrl-names="atvdemod_agc_pins"; */ @@ -1211,8 +1205,9 @@ #sound-dai-cells = <0>; compatible = "amlogic, aml-spdif-codec"; pinctrl-names = "audio_spdif_out", "audio_spdif_out_mute"; - pinctrl-0 = <&audio_spdif_out_pins>; - pinctrl-1 = <&audio_spdif_out_mute_pins>; + /* disable spdif pin mux temporary, enable it if necessary */ + /*pinctrl-0 = <&audio_spdif_out_pins>;*/ + /*pinctrl-1 = <&audio_spdif_out_mute_pins>;*/ }; pcm_codec: pcm_codec{ @@ -1339,12 +1334,17 @@ compatible = "amlogic, dvb"; dev_name = "dvb"; status = "okay"; - fe0_mode = "internal"; - fe0_tuner = <&tuner>; - /*"parallel","serial","disable"*/ - ts2 = "parallel"; - ts2_control = <0>; - ts2_invert = <0>; + fe0_mode = "external"; + fe0_demod = "Si2168"; + fe0_i2c_adap_id = <&i2c1>; + fe0_demod_i2c_addr = <0x64>; + fe0_ts = <0>; + fe0_reset_value = <0>; + fe0_reset_gpio = <&gpio GPIODV_6 GPIO_ACTIVE_HIGH>; + + ts0 = "serial"; + ts0_control = <0x800>; + ts0_invert = <0>; interrupts = <0 23 1 0 5 1 0 53 1 @@ -1359,16 +1359,31 @@ "dvr1_irq", "dvrfill0_fill", "dvrfill1_flush"; + pinctrl-names = "s_ts0"; + pinctrl-0 = <&dvb_s_ts0_pins>; clocks = <&clkc CLKID_DEMUX &clkc CLKID_ASYNC_FIFO &clkc CLKID_AHB_ARB0 &clkc CLKID_DOS_PARSER>; clock-names = "demux", "asyncfifo", "ahbarb0", "uparsertop"; }; + + dvbci { + compatible = "amlogic, dvbci"; + dev_name = "dvbci"; + io_type = <2>;//0:iobus,1:spi,2:cimax + cimax { + io_type = <1>;//0:spi,1:usb + usb { + rst-gpios = <&gpio GPIOZ_12 GPIO_ACTIVE_HIGH>; + }; + }; + }; + aml_dtv_demod { compatible = "amlogic, ddemod-txlx"; dev_name = "aml_dtv_demod"; - status = "okay"; + status = "disabled"; //pinctrl-names="dtvdemod_agc"; //pinctrl-0=<&dtvdemod_agc>; @@ -1390,28 +1405,6 @@ cma_mem_size = <8>; memory-region = <&demod_cma_reserved>;//<&demod_reserved>; }; - dvbfe { - compatible = "amlogic, dvbfe"; - dev_name = "dvbfe"; - status = "disabled"; - dtv_demod0 = "AMLDEMOD"; - fe0_dtv_demod = <0>; - fe0_ts = <2>; - fe0_dev = <0>; - dtv_demod0_mem = <0>; - dtv_demod0_spectrum = <1>; - dtv_demod0_cma_flag = <1>; - dtv_demod0_cma_mem_size = <8>; - memory-region = <&demod_cma_reserved>;//<&demod_reserved>; - tuner0 = "si2151_tuner"; - tuner0_i2c_adap_id = <2>; - tuner0_i2c_addr = <0x60>; - //tuner0_reset_value = <0>; - //tuner0_reset_gpio = "GPIOY_10" ; /*GPIOX_8 76*/ - fe0_tuner = <0>; - atv_demod0 = "aml_atv_demod"; - fe0_atv_demod = <0>; - }; thermal-zones { soc_thermal { @@ -1555,7 +1548,7 @@ /*lcd_extern*/ lcd_extern_off_pins:lcd_extern_off_pin { mux { - pins = "GPIOH_2", + groups = "GPIOH_2", "GPIOH_3"; function = "gpio_periphs"; /*output-high;*/ @@ -1567,59 +1560,68 @@ /*backlight*/ bl_pwm_on_pins:bl_pwm_on_pin { mux { - pins = "pwm_b"; + groups = "pwm_b"; function = "pwm_b"; }; }; bl_pwm_vs_on_pins:bl_pwm_vs_on_pin { mux { - pins = "pwm_vs_z6"; + groups = "pwm_vs_z6"; function = "pwm_vs"; }; }; bl_pwm_off_pins:bl_pwm_off_pin { mux { - pins = "GPIOZ_6"; + groups = "GPIOZ_6"; function = "gpio_periphs"; output-low; }; }; bl_pwm_combo_0_on_pins:bl_pwm_combo_0_on_pin { mux { - pins = "pwm_b"; + groups = "pwm_b"; function = "pwm_b"; }; }; bl_pwm_combo_1_on_pins:bl_pwm_combo_1_on_pin { mux { - pins = "pwm_c_z"; + groups = "pwm_c_z"; function = "pwm_c"; }; }; bl_pwm_combo_0_vs_on_pins:bl_pwm_combo_0_vs_on_pin { mux { - pins = "pwm_vs_z6"; + groups = "pwm_vs_z6"; function = "pwm_vs"; }; }; bl_pwm_combo_1_vs_on_pins:bl_pwm_combo_1_vs_on_pin { mux { - pins = "pwm_vs_z7"; + groups = "pwm_vs_z7"; function = "pwm_vs"; }; }; bl_pwm_combo_off_pins:bl_pwm_combo_off_pin { mux { - pins = "GPIOZ_6", + groups = "GPIOZ_6", "GPIOZ_7"; function = "gpio_periphs"; output-low; }; }; + dvb_s_ts0_pins: dvb_s_ts0_pins { + mux { + groups = "tsin_d0_a_dv", + "tsin_clk_a_dv", + "tsin_sop_a_dv", + "tsin_valid_a_dv"; + function = "tsin_a"; + }; + }; }; &uart_A { - status = "okay"; + status = "disabled"; }; &audio_data{ diff --git a/arch/arm64/configs/meson64_defconfig b/arch/arm64/configs/meson64_defconfig index 2391a66e7af7..ddc21eb7bc80 100644 --- a/arch/arm64/configs/meson64_defconfig +++ b/arch/arm64/configs/meson64_defconfig @@ -30,6 +30,7 @@ CONFIG_EMBEDDED=y # CONFIG_COMPAT_BRK is not set CONFIG_PROFILING=y CONFIG_JUMP_LABEL=y +CONFIG_CC_STACKPROTECTOR_STRONG=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y CONFIG_MODVERSIONS=y @@ -317,9 +318,11 @@ CONFIG_AMLOGIC_POST_PROCESS_MANAGER_PPSCALER=y CONFIG_AMLOGIC_VIDEOBUF2_ION=y CONFIG_AMLOGIC_IONVIDEO=y CONFIG_AMLOGIC_PIC_DEC=y +CONFIG_AMLOGIC_VIDEOSYNC=y CONFIG_AMLOGIC_MEDIA_ENHANCEMENT=y CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM=y CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION=y +CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_PRIME_SL=y CONFIG_AMLOGIC_MEDIA_GDC=y CONFIG_AMLOGIC_VIDEO_CAPTURE=y CONFIG_AMLOGIC_VM_DISABLE_VIDEOLAYER=y @@ -353,8 +356,11 @@ CONFIG_AMLOGIC_WDT_MESON_V3=y CONFIG_AMLOGIC_ESM=y CONFIG_AMLOGIC_WIFI=y CONFIG_AMLOGIC_BT_DEVICE=y +CONFIG_AMLOGIC_POWER=y CONFIG_AMLOGIC_PCIE=y -CONFIG_AMLOGIC_IRBLASTER=y +CONFIG_AMLOGIC_IRBLASTER_CORE=y +CONFIG_AMLOGIC_IRBLASTER_MESON=y +CONFIG_AMLOGIC_IRBLASTER_PROTOCOL=y CONFIG_AMLOGIC_IIO=y CONFIG_AMLOGIC_SARADC=y CONFIG_AMLOGIC_DDR_TOOL=y @@ -582,6 +588,7 @@ CONFIG_SQUASHFS=y CONFIG_PSTORE=y CONFIG_PSTORE_CONSOLE=y CONFIG_PSTORE_PMSG=y +CONFIG_PSTORE_FTRACE=y CONFIG_PSTORE_RAM=y CONFIG_NLS_CODEPAGE_437=y CONFIG_NLS_ISO8859_1=y diff --git a/arch/arm64/configs/meson64_smarthome_defconfig b/arch/arm64/configs/meson64_smarthome_defconfig index 4493f96cc2b9..a82fb252a5ea 100644 --- a/arch/arm64/configs/meson64_smarthome_defconfig +++ b/arch/arm64/configs/meson64_smarthome_defconfig @@ -280,9 +280,11 @@ CONFIG_AMLOGIC_POST_PROCESS_MANAGER=y CONFIG_AMLOGIC_POST_PROCESS_MANAGER_PPSCALER=y CONFIG_AMLOGIC_VIDEOBUF2_ION=y CONFIG_AMLOGIC_IONVIDEO=y +CONFIG_AMLOGIC_VIDEOSYNC=y CONFIG_AMLOGIC_MEDIA_ENHANCEMENT=y CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM=y CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION=y +CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_PRIME_SL=y CONFIG_AMLOGIC_MMC=y CONFIG_AMLOGIC_NAND=y CONFIG_AMLOGIC_VRTC=y @@ -415,6 +417,7 @@ CONFIG_AMLOGIC_SND_CODEC_PDM_DUMMY_CODEC=y CONFIG_AMLOGIC_SND_CODEC_AMLT9015=y CONFIG_AMLOGIC_SND_CODEC_AMLT9015S=y CONFIG_AMLOGIC_SND_CODEC_TXLX_ACODEC=y +CONFIG_AMLOGIC_SND_SOC_TAS5782M=y CONFIG_AMLOGIC_SND_SOC_TAS5707=y CONFIG_AMLOGIC_SND_SOC_TLV320ADC3101=y CONFIG_AMLOGIC_SND_SOC_PCM186X=y diff --git a/arch/arm64/configs/odroidn2_defconfig b/arch/arm64/configs/odroidn2_defconfig index 7dac169ecef7..85c30b4d6f75 100644 --- a/arch/arm64/configs/odroidn2_defconfig +++ b/arch/arm64/configs/odroidn2_defconfig @@ -246,10 +246,11 @@ CONFIG_SECCOMP_FILTER=y CONFIG_HAVE_GCC_PLUGINS=y # CONFIG_GCC_PLUGINS is not set CONFIG_HAVE_CC_STACKPROTECTOR=y -CONFIG_CC_STACKPROTECTOR=y +# CONFIG_CC_STACKPROTECTOR is not set # CONFIG_CC_STACKPROTECTOR_NONE is not set # CONFIG_CC_STACKPROTECTOR_REGULAR is not set CONFIG_CC_STACKPROTECTOR_STRONG=y +# CONFIG_CC_STACKPROTECTOR_STRONG_AMLOGIC is not set # CONFIG_LTO is not set CONFIG_ARCH_SUPPORTS_LTO_CLANG=y CONFIG_LTO_NONE=y @@ -1413,6 +1414,7 @@ CONFIG_AMLOGIC_SERIAL_MESON_CONSOLE=y # CONFIG_AMLOGIC_PRINTK_NOBLOCK_MODE is not set CONFIG_AMLOGIC_IOMAP=y CONFIG_AMLOGIC_PINCTRL=y +# CONFIG_AMLOGIC_PINCTRL_MESON_GXBB is not set CONFIG_AMLOGIC_PINCTRL_MESON_GXL=y CONFIG_AMLOGIC_PINCTRL_MESON_AXG=y CONFIG_AMLOGIC_PINCTRL_MESON_TXLX=y @@ -1659,6 +1661,11 @@ CONFIG_AMLOGIC_IONVIDEO=y # CONFIG_AMLOGIC_PIC_DEC=y +# +# Amlogic videosync support +# +CONFIG_AMLOGIC_VIDEOSYNC=y + # # Amlogic Enhancement drivers # @@ -1681,6 +1688,15 @@ CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM=y # Amlogic amdolby_vision Driver # # CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION is not set + +# +# Amlogic amprime_sl Drivers +# + +# +# Amlogic amprime_sl Driver +# +# CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_PRIME_SL is not set CONFIG_AMLOGIC_MEDIA_GDC=y # @@ -1782,11 +1798,12 @@ CONFIG_AMLOGIC_ESM=y # # DVB COMPAT support # +# CONFIG_AMLOGIC_POWER is not set # # Multimedia Card support # -CONFIG_AMLOGIC_IRBLASTER=y +# CONFIG_AMLOGIC_IRBLASTER_CORE is not set CONFIG_AMLOGIC_IIO=y # @@ -1806,14 +1823,16 @@ CONFIG_AMLOGIC_MEMORY_EXTEND=y CONFIG_AMLOGIC_RAMDUMP=y CONFIG_AMLOGIC_CMA=y # CONFIG_AMLOGIC_VMAP is not set +# CONFIG_AMLOGIC_WATCHPOINT is not set CONFIG_AMLOGIC_GPIO_IRQ=y # # Amlogic ATV driver # -CONFIG_AMLOGIC_ATV_DEMOD=y +# CONFIG_AMLOGIC_ATV_DEMOD is not set CONFIG_AMLOGIC_DEBUG=y CONFIG_AMLOGIC_DEBUG_LOCKUP=y +# CONFIG_AMLOGIC_DEBUG_ATRACE is not set # # Amlogic defend img file update support @@ -3388,6 +3407,7 @@ CONFIG_DVB_MAX_ADAPTERS=8 CONFIG_RC_CORE=y CONFIG_RC_MAP=y CONFIG_RC_DECODERS=y +CONFIG_IR_IRMP_DECODER=y CONFIG_LIRC=m CONFIG_IR_LIRC_CODEC=m CONFIG_IR_NEC_DECODER=m @@ -4139,6 +4159,7 @@ CONFIG_AMLOGIC_SND_CODEC_AMLT9015=y # CONFIG_AMLOGIC_SND_SOC_TAS5805 is not set CONFIG_AMLOGIC_SND_CODEC_TXLX_ACODEC=y # CONFIG_AMLOGIC_SND_CODEC_TL1_ACODEC is not set +# CONFIG_AMLOGIC_SND_SOC_TAS5782M is not set CONFIG_AMLOGIC_SND_SOC_TAS5707=y CONFIG_AMLOGIC_SND_SOC_TLV320ADC3101=y CONFIG_AMLOGIC_SND_SOC_PCM186X=y diff --git a/arch/arm64/configs/odroidn2_drm_defconfig b/arch/arm64/configs/odroidn2_drm_defconfig index c8210722d1af..dcad9c8eb840 100644 --- a/arch/arm64/configs/odroidn2_drm_defconfig +++ b/arch/arm64/configs/odroidn2_drm_defconfig @@ -1,6 +1,6 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/arm64 4.9.177 Kernel Configuration +# Linux/arm64 4.9.185 Kernel Configuration # CONFIG_ARM64=y CONFIG_64BIT=y @@ -249,7 +249,8 @@ CONFIG_HAVE_CC_STACKPROTECTOR=y CONFIG_CC_STACKPROTECTOR=y # CONFIG_CC_STACKPROTECTOR_NONE is not set # CONFIG_CC_STACKPROTECTOR_REGULAR is not set -CONFIG_CC_STACKPROTECTOR_STRONG=y +# CONFIG_CC_STACKPROTECTOR_STRONG is not set +CONFIG_CC_STACKPROTECTOR_STRONG_AMLOGIC=y # CONFIG_LTO is not set CONFIG_ARCH_SUPPORTS_LTO_CLANG=y CONFIG_LTO_NONE=y @@ -1413,6 +1414,7 @@ CONFIG_AMLOGIC_SERIAL_MESON_CONSOLE=y # CONFIG_AMLOGIC_PRINTK_NOBLOCK_MODE is not set CONFIG_AMLOGIC_IOMAP=y CONFIG_AMLOGIC_PINCTRL=y +# CONFIG_AMLOGIC_PINCTRL_MESON_GXBB is not set CONFIG_AMLOGIC_PINCTRL_MESON_GXL=y CONFIG_AMLOGIC_PINCTRL_MESON_AXG=y CONFIG_AMLOGIC_PINCTRL_MESON_TXLX=y @@ -1659,6 +1661,11 @@ CONFIG_AMLOGIC_IONVIDEO=y # CONFIG_AMLOGIC_PIC_DEC=y +# +# Amlogic videosync support +# +CONFIG_AMLOGIC_VIDEOSYNC=y + # # Amlogic Enhancement drivers # @@ -1681,6 +1688,15 @@ CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM=y # Amlogic amdolby_vision Driver # # CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION is not set + +# +# Amlogic amprime_sl Drivers +# + +# +# Amlogic amprime_sl Driver +# +# CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_PRIME_SL is not set CONFIG_AMLOGIC_MEDIA_GDC=y # @@ -1782,11 +1798,12 @@ CONFIG_AMLOGIC_ESM=y # # DVB COMPAT support # +# CONFIG_AMLOGIC_POWER is not set # # Multimedia Card support # -CONFIG_AMLOGIC_IRBLASTER=y +# CONFIG_AMLOGIC_IRBLASTER_CORE is not set CONFIG_AMLOGIC_IIO=y # @@ -1811,14 +1828,16 @@ CONFIG_AMLOGIC_MEMORY_EXTEND=y CONFIG_AMLOGIC_RAMDUMP=y CONFIG_AMLOGIC_CMA=y # CONFIG_AMLOGIC_VMAP is not set +CONFIG_AMLOGIC_WATCHPOINT=y CONFIG_AMLOGIC_GPIO_IRQ=y # # Amlogic ATV driver # -CONFIG_AMLOGIC_ATV_DEMOD=y +# CONFIG_AMLOGIC_ATV_DEMOD is not set CONFIG_AMLOGIC_DEBUG=y CONFIG_AMLOGIC_DEBUG_LOCKUP=y +CONFIG_AMLOGIC_DEBUG_ATRACE=y # # Amlogic defend img file update support @@ -3389,6 +3408,7 @@ CONFIG_DVB_MAX_ADAPTERS=8 CONFIG_RC_CORE=y CONFIG_RC_MAP=y CONFIG_RC_DECODERS=y +CONFIG_IR_IRMP_DECODER=y CONFIG_LIRC=m CONFIG_IR_LIRC_CODEC=m CONFIG_IR_NEC_DECODER=m @@ -4149,6 +4169,7 @@ CONFIG_AMLOGIC_SND_CODEC_AMLT9015=y # CONFIG_AMLOGIC_SND_SOC_TAS5805 is not set CONFIG_AMLOGIC_SND_CODEC_TXLX_ACODEC=y # CONFIG_AMLOGIC_SND_CODEC_TL1_ACODEC is not set +# CONFIG_AMLOGIC_SND_SOC_TAS5782M is not set CONFIG_AMLOGIC_SND_SOC_TAS5707=y CONFIG_AMLOGIC_SND_SOC_TLV320ADC3101=y CONFIG_AMLOGIC_SND_SOC_PCM186X=y diff --git a/arch/arm64/include/asm/hardirq.h b/arch/arm64/include/asm/hardirq.h index 9745a1d52418..8740297dac77 100644 --- a/arch/arm64/include/asm/hardirq.h +++ b/arch/arm64/include/asm/hardirq.h @@ -20,11 +20,7 @@ #include #include -#ifdef CONFIG_AMLOGIC_MODIFY -#define NR_IPI 7 -#else #define NR_IPI 6 -#endif typedef struct { unsigned int __softirq_pending; diff --git a/arch/arm64/include/asm/hw_breakpoint.h b/arch/arm64/include/asm/hw_breakpoint.h index b6b167ac082b..9b5a831601e0 100644 --- a/arch/arm64/include/asm/hw_breakpoint.h +++ b/arch/arm64/include/asm/hw_breakpoint.h @@ -159,9 +159,15 @@ static inline int get_num_brps(void) static inline int get_num_wrps(void) { u64 dfr0 = read_system_reg(SYS_ID_AA64DFR0_EL1); +#ifdef CONFIG_AMLOGIC_VMAP + return (1 + + cpuid_feature_extract_unsigned_field(dfr0, + ID_AA64DFR0_WRPS_SHIFT)) - 2; +#else return 1 + cpuid_feature_extract_unsigned_field(dfr0, ID_AA64DFR0_WRPS_SHIFT); +#endif } #endif /* __KERNEL__ */ diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h index 0bba427bb4c2..931f49b560bd 100644 --- a/arch/arm64/include/asm/io.h +++ b/arch/arm64/include/asm/io.h @@ -33,42 +33,74 @@ #include #include - +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE +#include +#endif /* * Generic IO read/write. These perform native-endian accesses. */ #define __raw_writeb __raw_writeb static inline void __raw_writeb(u8 val, volatile void __iomem *addr) { +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE + pstore_ftrace_io_wr((unsigned long)addr, (unsigned long)val); +#endif asm volatile("strb %w0, [%1]" : : "rZ" (val), "r" (addr)); +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE + pstore_ftrace_io_wr_end((unsigned long)addr, (unsigned long)val); +#endif } #define __raw_writew __raw_writew static inline void __raw_writew(u16 val, volatile void __iomem *addr) { +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE + pstore_ftrace_io_wr((unsigned long)addr, (unsigned long)val); +#endif asm volatile("strh %w0, [%1]" : : "rZ" (val), "r" (addr)); +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE + pstore_ftrace_io_wr_end((unsigned long)addr, (unsigned long)val); +#endif } #define __raw_writel __raw_writel static inline void __raw_writel(u32 val, volatile void __iomem *addr) { +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE + pstore_ftrace_io_wr((unsigned long)addr, (unsigned long)val); +#endif asm volatile("str %w0, [%1]" : : "rZ" (val), "r" (addr)); +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE + pstore_ftrace_io_wr_end((unsigned long)addr, (unsigned long)val); +#endif } #define __raw_writeq __raw_writeq static inline void __raw_writeq(u64 val, volatile void __iomem *addr) { +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE + pstore_ftrace_io_wr((unsigned long)addr, (unsigned long)val); +#endif asm volatile("str %x0, [%1]" : : "rZ" (val), "r" (addr)); +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE + pstore_ftrace_io_wr_end((unsigned long)addr, (unsigned long)val); +#endif } #define __raw_readb __raw_readb static inline u8 __raw_readb(const volatile void __iomem *addr) { u8 val; +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE + pstore_ftrace_io_rd((unsigned long)addr); +#endif asm volatile(ALTERNATIVE("ldrb %w0, [%1]", "ldarb %w0, [%1]", ARM64_WORKAROUND_DEVICE_LOAD_ACQUIRE) : "=r" (val) : "r" (addr)); +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE + pstore_ftrace_io_rd_end((unsigned long)addr); +#endif return val; } @@ -77,10 +109,16 @@ static inline u16 __raw_readw(const volatile void __iomem *addr) { u16 val; +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE + pstore_ftrace_io_rd((unsigned long)addr); +#endif asm volatile(ALTERNATIVE("ldrh %w0, [%1]", "ldarh %w0, [%1]", ARM64_WORKAROUND_DEVICE_LOAD_ACQUIRE) : "=r" (val) : "r" (addr)); +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE + pstore_ftrace_io_rd_end((unsigned long)addr); +#endif return val; } @@ -88,10 +126,16 @@ static inline u16 __raw_readw(const volatile void __iomem *addr) static inline u32 __raw_readl(const volatile void __iomem *addr) { u32 val; +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE + pstore_ftrace_io_rd((unsigned long)addr); +#endif asm volatile(ALTERNATIVE("ldr %w0, [%1]", "ldar %w0, [%1]", ARM64_WORKAROUND_DEVICE_LOAD_ACQUIRE) : "=r" (val) : "r" (addr)); +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE + pstore_ftrace_io_rd_end((unsigned long)addr); +#endif return val; } @@ -99,10 +143,16 @@ static inline u32 __raw_readl(const volatile void __iomem *addr) static inline u64 __raw_readq(const volatile void __iomem *addr) { u64 val; +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE + pstore_ftrace_io_rd((unsigned long)addr); +#endif asm volatile(ALTERNATIVE("ldr %0, [%1]", "ldar %0, [%1]", ARM64_WORKAROUND_DEVICE_LOAD_ACQUIRE) : "=r" (val) : "r" (addr)); +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE + pstore_ftrace_io_rd_end((unsigned long)addr); +#endif return val; } diff --git a/arch/arm64/include/asm/perf_event.h b/arch/arm64/include/asm/perf_event.h index 11185b42b060..b963c3bbd437 100644 --- a/arch/arm64/include/asm/perf_event.h +++ b/arch/arm64/include/asm/perf_event.h @@ -92,50 +92,6 @@ extern unsigned long perf_misc_flags(struct pt_regs *regs); } -#ifdef CONFIG_AMLOGIC_MODIFY -extern void armv8pmu_handle_irq_ipi(void); - -struct amlpmu_fixup_cpuinfo { - int irq_num; - - int fix_done; - - unsigned long irq_cnt; - unsigned long empty_irq_cnt; - - unsigned long irq_time; - unsigned long empty_irq_time; - - unsigned long last_irq_cnt; - unsigned long last_empty_irq_cnt; - - unsigned long last_irq_time; - unsigned long last_empty_irq_time; -}; - -struct amlpmu_fixup_context { - struct amlpmu_fixup_cpuinfo __percpu *cpuinfo; - - /* struct arm_pmu */ - void *dev; - - /* sys_cpu_status0 reg */ - unsigned int *sys_cpu_status0; - - /* - * In main pmu irq route wait for other cpu fix done may cause lockup, - * when lockup we disable main irq for a while. - * relax_timer will enable main irq again. - */ - struct hrtimer relax_timer; - - /* dts prop */ - unsigned int sys_cpu_status0_offset; - unsigned int sys_cpu_status0_pmuirq_mask; - unsigned int relax_timer_ns; - unsigned int max_wait_cnt; -}; -#endif #endif diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S index a2ccd33d5aee..3530d705ae05 100644 --- a/arch/arm64/kernel/entry.S +++ b/arch/arm64/kernel/entry.S @@ -359,10 +359,8 @@ alternative_insn eret, nop, ARM64_UNMAP_KERNEL_AT_EL0 * Add a dummy stack frame, this non-standard format is fixed up * by unwind_frame() */ -#ifndef CONFIG_AMLOGIC_VMAP /* we need get right stack of el1_preempt */ stp x29, x19, [sp, #-16]! mov x29, sp -#endif /* !CONFIG_AMLOGIC_VMAP */ 9998: .endm diff --git a/arch/arm64/kernel/hw_breakpoint.c b/arch/arm64/kernel/hw_breakpoint.c index 0798abd4d692..97e9b4d5999b 100644 --- a/arch/arm64/kernel/hw_breakpoint.c +++ b/arch/arm64/kernel/hw_breakpoint.c @@ -114,7 +114,11 @@ int hw_breakpoint_slots(int type) WRITE_WB_REG_CASE(OFF, 14, REG, VAL); \ WRITE_WB_REG_CASE(OFF, 15, REG, VAL) +#ifdef CONFIG_AMLOGIC_MODIFY +u64 read_wb_reg(int reg, int n) +#else static u64 read_wb_reg(int reg, int n) +#endif { u64 val = 0; @@ -129,14 +133,18 @@ static u64 read_wb_reg(int reg, int n) return val; } +#ifndef CONFIG_AMLOGIC_MODIFY NOKPROBE_SYMBOL(read_wb_reg); +#endif static void write_wb_reg(int reg, int n, u64 val) { #ifdef CONFIG_AMLOGIC_VMAP /* avoid write DBGWVR since we use it for special purpose */ - if (reg >= AARCH64_DBG_REG_WVR && reg < AARCH64_DBG_REG_WCR) + if ((reg + n) >= (AARCH64_DBG_REG_WVR + 2) && + (reg + n) < AARCH64_DBG_REG_WCR) { return; + } #endif switch (reg + n) { GEN_WRITE_WB_REG_CASES(AARCH64_DBG_REG_BVR, AARCH64_DBG_REG_NAME_BVR, val); diff --git a/arch/arm64/kernel/io.c b/arch/arm64/kernel/io.c index 79b17384effa..b90a1613e051 100644 --- a/arch/arm64/kernel/io.c +++ b/arch/arm64/kernel/io.c @@ -18,13 +18,21 @@ #include #include +#define SKIP_IO_TRACE #include +#undef SKIP_IO_TRACE +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE +#include +#endif /* * Copy data from IO memory space to "real" memory space. */ void __memcpy_fromio(void *to, const volatile void __iomem *from, size_t count) { +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE + pstore_ftrace_io_rd((unsigned long)addr); +#endif while (count && !IS_ALIGNED((unsigned long)from, 8)) { *(u8 *)to = __raw_readb(from); from++; @@ -45,6 +53,9 @@ void __memcpy_fromio(void *to, const volatile void __iomem *from, size_t count) to++; count--; } +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE + pstore_ftrace_io_rd_end((unsigned long)addr); +#endif } EXPORT_SYMBOL(__memcpy_fromio); @@ -53,6 +64,9 @@ EXPORT_SYMBOL(__memcpy_fromio); */ void __memcpy_toio(volatile void __iomem *to, const void *from, size_t count) { +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE + pstore_ftrace_io_wr((unsigned long)addr, 0x1234); +#endif while (count && !IS_ALIGNED((unsigned long)to, 8)) { __raw_writeb(*(u8 *)from, to); from++; @@ -73,6 +87,9 @@ void __memcpy_toio(volatile void __iomem *to, const void *from, size_t count) to++; count--; } +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE + pstore_ftrace_io_wr_end((unsigned long)addr, 0x1234); +#endif } EXPORT_SYMBOL(__memcpy_toio); @@ -83,6 +100,9 @@ void __memset_io(volatile void __iomem *dst, int c, size_t count) { u64 qc = (u8)c; +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE + pstore_ftrace_io_wr((unsigned long)addr, 0xabcd); +#endif qc |= qc << 8; qc |= qc << 16; qc |= qc << 32; @@ -104,5 +124,8 @@ void __memset_io(volatile void __iomem *dst, int c, size_t count) dst++; count--; } +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE + pstore_ftrace_io_wr_end((unsigned long)addr, 0xabcd); +#endif } EXPORT_SYMBOL(__memset_io); diff --git a/arch/arm64/kernel/perf_event.c b/arch/arm64/kernel/perf_event.c index 30ba8cf00977..9c49326793ef 100644 --- a/arch/arm64/kernel/perf_event.c +++ b/arch/arm64/kernel/perf_event.c @@ -19,10 +19,6 @@ * along with this program. If not, see . */ -#ifdef CONFIG_AMLOGIC_MODIFY -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -#endif - #include #include #include @@ -34,18 +30,6 @@ #include -#ifdef CONFIG_AMLOGIC_MODIFY -#include -#include -#include -#include -#include -#include -#include -#include -#include -#endif - /* * ARMv8 PMUv3 Performance Events handling code. * Common event types (some are defined in asm/perf_event.h). @@ -766,161 +750,13 @@ static void armv8pmu_disable_event(struct perf_event *event) } #ifdef CONFIG_AMLOGIC_MODIFY - -static struct amlpmu_fixup_context amlpmu_fixup_ctx; - -static enum hrtimer_restart amlpmu_relax_timer_func(struct hrtimer *timer) -{ - struct amlpmu_fixup_cpuinfo *ci; - - ci = per_cpu_ptr(amlpmu_fixup_ctx.cpuinfo, 0); - - pr_alert("enable cpu0_irq %d again, irq cnt = %lu\n", - ci->irq_num, - ci->irq_cnt); - enable_irq(ci->irq_num); - - return HRTIMER_NORESTART; -} - - -static void amlpmu_relax_timer_start(int other_cpu) -{ - struct amlpmu_fixup_cpuinfo *ci; - int cpu; - - cpu = smp_processor_id(); - WARN_ON(cpu != 0); - - ci = per_cpu_ptr(amlpmu_fixup_ctx.cpuinfo, 0); - - pr_alert("wait cpu %d fixup done timeout, main cpu irq cnt = %lu\n", - other_cpu, - ci->irq_cnt); - - if (hrtimer_active(&amlpmu_fixup_ctx.relax_timer)) { - pr_alert("relax_timer already active, return!\n"); - return; - } - - disable_irq_nosync(ci->irq_num); - - hrtimer_start(&amlpmu_fixup_ctx.relax_timer, - ns_to_ktime(amlpmu_fixup_ctx.relax_timer_ns), - HRTIMER_MODE_REL); -} +#include static irqreturn_t armv8pmu_handle_irq(int irq_num, void *dev); -void armv8pmu_handle_irq_ipi(void) +void amlpmu_handle_irq_ipi(void *arg) { - int cpu = smp_processor_id(); - - WARN_ON(cpu == 0); - WARN_ON(!amlpmu_fixup_ctx.dev); - - armv8pmu_handle_irq(-1, amlpmu_fixup_ctx.dev); -} - -static int aml_pmu_fix(void) -{ - int i; - int cpu; - int pmuirq_val; - struct amlpmu_fixup_cpuinfo *ci; - - int max_wait_cnt = amlpmu_fixup_ctx.max_wait_cnt; - - pmuirq_val = readl(amlpmu_fixup_ctx.sys_cpu_status0); - pmuirq_val &= amlpmu_fixup_ctx.sys_cpu_status0_pmuirq_mask; - - for (cpu = 0; cpu < num_possible_cpus(); cpu++) { - if (pmuirq_val & (1<fix_done = 0; - - /* aml pmu IPI will set fix_done to 1 */ - mb(); - - smp_send_aml_pmu(cpu); - - for (i = 0; i < max_wait_cnt; i++) { - if (READ_ONCE(ci->fix_done)) - break; - - udelay(1); - } - - if (i == amlpmu_fixup_ctx.max_wait_cnt) - amlpmu_relax_timer_start(cpu); - - return 0; - } - } - } - - return 1; -} - -static void aml_pmu_fix_stat_account(int is_empty_irq) -{ - int freq; - unsigned long time = jiffies; - struct amlpmu_fixup_cpuinfo *ci; - - ci = this_cpu_ptr(amlpmu_fixup_ctx.cpuinfo); - - ci->irq_cnt++; - ci->irq_time = time; - if (!ci->last_irq_cnt) { - ci->last_irq_cnt = ci->irq_cnt; - ci->last_irq_time = ci->irq_time; - } - - if (is_empty_irq) { - ci->empty_irq_cnt++; - ci->empty_irq_time = time; - if (!ci->last_empty_irq_cnt) { - ci->last_empty_irq_cnt = ci->empty_irq_cnt; - ci->last_empty_irq_time = ci->empty_irq_time; - } - } - - if (time_after(ci->irq_time, ci->last_irq_time + HZ)) { - freq = ci->irq_cnt - ci->last_irq_cnt; - freq = freq * HZ / (ci->irq_time - ci->last_irq_time); - pr_debug("irq_cnt = %lu, irq_last_cnt = %lu, freq = %d\n", - ci->irq_cnt, - ci->last_irq_cnt, - freq); - - ci->last_irq_cnt = ci->irq_cnt; - ci->last_irq_time = ci->irq_time; - } - - if (is_empty_irq && - time_after(ci->empty_irq_time, ci->last_empty_irq_time + HZ)) { - - freq = ci->empty_irq_cnt - ci->last_empty_irq_cnt; - freq *= HZ; - freq /= (ci->empty_irq_time - ci->last_empty_irq_time); - pr_debug("empty_irq_cnt = %lu, freq = %d\n", - ci->empty_irq_cnt, - freq); - - ci->last_empty_irq_cnt = ci->empty_irq_cnt; - ci->last_empty_irq_time = ci->empty_irq_time; - } + armv8pmu_handle_irq(-1, amlpmu_ctx.pmu); } #endif @@ -933,42 +769,21 @@ static irqreturn_t armv8pmu_handle_irq(int irq_num, void *dev) struct pt_regs *regs; int idx; -#ifdef CONFIG_AMLOGIC_MODIFY - int cpu; - int is_empty_irq = 0; - struct amlpmu_fixup_cpuinfo *ci; - - ci = this_cpu_ptr(amlpmu_fixup_ctx.cpuinfo); - ci->irq_num = irq_num; - amlpmu_fixup_ctx.dev = dev; - cpu = smp_processor_id(); -#endif - /* * Get and reset the IRQ flags */ pmovsr = armv8pmu_getreset_flags(); #ifdef CONFIG_AMLOGIC_MODIFY - ci->fix_done = 1; -#endif + /* amlpmu have routed the interrupt already, so return IRQ_HANDLED */ + if (amlpmu_handle_irq(cpu_pmu, + irq_num, + armv8pmu_has_overflowed(pmovsr))) + return IRQ_HANDLED; +#else /* * Did an overflow occur? */ -#ifdef CONFIG_AMLOGIC_MODIFY - if (!armv8pmu_has_overflowed(pmovsr)) { - is_empty_irq = 1; - - if (cpu == 0) - is_empty_irq = aml_pmu_fix(); - } - - aml_pmu_fix_stat_account(is_empty_irq); - - /* txlx have some empty pmu irqs, so return IRQ_HANDLED */ - if (is_empty_irq) - return IRQ_HANDLED; -#else if (!armv8pmu_has_overflowed(pmovsr)) return IRQ_NONE; #endif @@ -1014,9 +829,6 @@ static irqreturn_t armv8pmu_handle_irq(int irq_num, void *dev) return IRQ_HANDLED; } - - - static void armv8pmu_start(struct arm_pmu *cpu_pmu) { unsigned long flags; @@ -1308,87 +1120,8 @@ static const struct pmu_probe_info armv8_pmu_probe_table[] = { }; -#ifdef CONFIG_AMLOGIC_MODIFY -static int amlpmu_fixup_init(struct platform_device *pdev) -{ - int ret; - void __iomem *base; - - amlpmu_fixup_ctx.cpuinfo = __alloc_percpu( - sizeof(struct amlpmu_fixup_cpuinfo), 2 * sizeof(void *)); - if (!amlpmu_fixup_ctx.cpuinfo) { - pr_err("alloc percpu failed\n"); - return -ENOMEM; - } - - base = of_iomap(pdev->dev.of_node, 0); - if (IS_ERR(base)) { - pr_err("of_iomap() failed, base = %p\n", base); - return PTR_ERR(base); - } - - ret = of_property_read_u32(pdev->dev.of_node, - "sys_cpu_status0_offset", - &amlpmu_fixup_ctx.sys_cpu_status0_offset); - if (ret) { - pr_err("read sys_cpu_status0_offset failed, ret = %d\n", ret); - return 1; - } - pr_debug("sys_cpu_status0_offset = 0x%0x\n", - amlpmu_fixup_ctx.sys_cpu_status0_offset); - - ret = of_property_read_u32(pdev->dev.of_node, - "sys_cpu_status0_pmuirq_mask", - &amlpmu_fixup_ctx.sys_cpu_status0_pmuirq_mask); - if (ret) { - pr_err("read sys_cpu_status0_pmuirq_mask failed, ret = %d\n", - ret); - return 1; - } - pr_debug("sys_cpu_status0_pmuirq_mask = 0x%0x\n", - amlpmu_fixup_ctx.sys_cpu_status0_pmuirq_mask); - - - ret = of_property_read_u32(pdev->dev.of_node, - "relax_timer_ns", - &amlpmu_fixup_ctx.relax_timer_ns); - if (ret) { - pr_err("read prop relax_timer_ns failed, ret = %d\n", ret); - return 1; - } - pr_debug("relax_timer_ns = %u\n", amlpmu_fixup_ctx.relax_timer_ns); - - - ret = of_property_read_u32(pdev->dev.of_node, - "max_wait_cnt", - &amlpmu_fixup_ctx.max_wait_cnt); - if (ret) { - pr_err("read prop max_wait_cnt failed, ret = %d\n", ret); - return 1; - } - pr_debug("max_wait_cnt = %u\n", amlpmu_fixup_ctx.max_wait_cnt); - - - base += (amlpmu_fixup_ctx.sys_cpu_status0_offset << 2); - amlpmu_fixup_ctx.sys_cpu_status0 = base; - pr_debug("sys_cpu_status0 = %p\n", amlpmu_fixup_ctx.sys_cpu_status0); - - - hrtimer_init(&amlpmu_fixup_ctx.relax_timer, - CLOCK_MONOTONIC, - HRTIMER_MODE_REL); - amlpmu_fixup_ctx.relax_timer.function = amlpmu_relax_timer_func; - - return 0; -} -#endif - static int armv8_pmu_device_probe(struct platform_device *pdev) { -#ifdef CONFIG_AMLOGIC_MODIFY - if (amlpmu_fixup_init(pdev)) - return 1; -#endif if (acpi_disabled) return arm_pmu_device_probe(pdev, armv8_pmu_of_device_ids, NULL); diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c index 6084d01e99b5..7f377c10e433 100644 --- a/arch/arm64/kernel/process.c +++ b/arch/arm64/kernel/process.c @@ -268,6 +268,23 @@ static void show_user_data(unsigned long addr, int nbytes, const char *name) pr_cont("\n"); } } + +static void show_vmalloc_pfn(struct pt_regs *regs) +{ + int i; + struct page *page; + + for (i = 0; i < 16; i++) { + if (is_vmalloc_or_module_addr((void *)regs->regs[i])) { + page = vmalloc_to_page((void *)regs->regs[i]); + if (!page) + continue; + pr_info("R%-2d : %016llx, PFN:%5lx\n", + i, regs->regs[i], page_to_pfn(page)); + } + } + +} #endif /* CONFIG_AMLOGIC_USER_FAULT */ static void show_extra_register_data(struct pt_regs *regs, int nbytes) @@ -443,6 +460,7 @@ void __show_regs(struct pt_regs *regs) show_vma(current->mm, instruction_pointer(regs)); show_vma(current->mm, lr); } + show_vmalloc_pfn(regs); #endif /* CONFIG_AMLOGIC_USER_FAULT */ printk("pc : [<%016llx>] lr : [<%016llx>] pstate: %08llx\n", regs->pc, lr, regs->pstate); diff --git a/arch/arm64/kernel/sleep.S b/arch/arm64/kernel/sleep.S index 5a4fbcc744d2..32a9754a884d 100644 --- a/arch/arm64/kernel/sleep.S +++ b/arch/arm64/kernel/sleep.S @@ -75,6 +75,10 @@ ENTRY(__cpu_suspend_enter) /* find the mpidr_hash */ ldr_l x1, sleep_save_stash mrs x7, mpidr_el1 + ubfx x2, x7, #24, 1 + cbz x2, __cpu_suspend_enter_cont + lsr x7, x7, #8 +__cpu_suspend_enter_cont: adr_l x9, mpidr_hash ldr x10, [x9, #MPIDR_HASH_MASK] /* @@ -109,6 +113,10 @@ ENDPROC(cpu_resume) ENTRY(_cpu_resume) mrs x1, mpidr_el1 + ubfx x2, x1, #24, 1 + cbz x2, _cpu_resume_cont + lsr x1, x1, #8 +_cpu_resume_cont: adr_l x8, mpidr_hash // x8 = struct mpidr_hash virt address /* retrieve mpidr_hash members to compute the hash */ diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c index f30ec481fa7a..9edc7228a870 100644 --- a/arch/arm64/kernel/smp.c +++ b/arch/arm64/kernel/smp.c @@ -55,10 +55,6 @@ #include #include -#ifdef CONFIG_AMLOGIC_MODIFY -#include -#endif - #ifdef CONFIG_AMLOGIC_VMAP #include #endif @@ -84,12 +80,7 @@ enum ipi_msg_type { IPI_CPU_STOP, IPI_TIMER, IPI_IRQ_WORK, -#ifdef CONFIG_AMLOGIC_MODIFY - IPI_WAKEUP, - IPI_AML_PMU -#else IPI_WAKEUP -#endif }; #ifdef CONFIG_ARM64_VHE @@ -775,9 +766,6 @@ static const char *ipi_types[NR_IPI] __tracepoint_string = { S(IPI_TIMER, "Timer broadcast interrupts"), S(IPI_IRQ_WORK, "IRQ work interrupts"), S(IPI_WAKEUP, "CPU wake-up interrupts"), -#ifdef CONFIG_AMLOGIC_MODIFY - S(IPI_AML_PMU, "AML pmu cross interrupts"), -#endif }; static void smp_cross_call(const struct cpumask *target, unsigned int ipinr) @@ -786,13 +774,6 @@ static void smp_cross_call(const struct cpumask *target, unsigned int ipinr) __smp_cross_call(target, ipinr); } -#ifdef CONFIG_AMLOGIC_MODIFY -void smp_send_aml_pmu(int cpu) -{ - smp_cross_call(cpumask_of(cpu), IPI_AML_PMU); -} -#endif - void show_ipi_list(struct seq_file *p, int prec) { unsigned int cpu, i; @@ -911,12 +892,6 @@ void handle_IPI(int ipinr, struct pt_regs *regs) break; #endif -#ifdef CONFIG_AMLOGIC_MODIFY - case IPI_AML_PMU: - armv8pmu_handle_irq_ipi(); - break; -#endif - default: pr_crit("CPU%u: Unknown IPI message 0x%x\n", cpu, ipinr); break; diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c index 6b66b228a41a..872369b8c212 100644 --- a/arch/arm64/mm/fault.c +++ b/arch/arm64/mm/fault.c @@ -316,7 +316,7 @@ static void __do_user_fault(struct task_struct *tsk, unsigned long addr, pr_info("%s[%d]: unhandled %s (%d) at 0x%08lx, esr 0x%03x\n", tsk->comm, task_pid_nr(tsk), inf->name, sig, addr, esr); - show_pte(regs); + show_pte(addr); #ifdef CONFIG_AMLOGIC_USER_FAULT show_all_pfn(tsk, regs); #endif /* CONFIG_AMLOGIC_USER_FAULT */ diff --git a/drivers/amlogic/.gitignore b/drivers/amlogic/.gitignore new file mode 100644 index 000000000000..c9423b3761ed --- /dev/null +++ b/drivers/amlogic/.gitignore @@ -0,0 +1,101 @@ +# +# NOTE! Don't add files that are generated in specific +# subdirectories here. Add them in the ".gitignore" file +# in that subdirectory instead. +# +# NOTE! Please use 'git ls-files -i --exclude-standard' +# command after changing this file, to see if there are +# any tracked files which get ignored after the change. +# +# Normal rules +# +.* +*.o +*.o.* +*.a +*.s +*.ko +*.so +*.so.dbg +*.mod.c +*.i +*.lst +*.symtypes +*.order +modules.builtin +*.elf +#*.bin +*.gz +*.bz2 +*.lzma +*.xz +*.lz4 +*.lzo +*.patch +*.gcno + +# +# Top-level generic files +# +/tags +/TAGS +/linux +/vmlinux +/vmlinuz +/System.map +/Module.markers +Module.symvers + +# +# Debian directory (make deb-pkg) +# +/debian/ + +# +# git files that we don't want to ignore even it they are dot-files +# +!.gitignore +!.mailmap + +# +# Generated include files +# +include/config +include/generated +arch/*/include/generated + +# stgit generated dirs +patches-* + +# quilt's files +patches +series + +# cscope files +cscope.* +ncscope.* + +# gnu global files +GPATH +GRTAGS +GSYMS +GTAGS + +*.orig +*~ +\#*# + +# +# Leavings from module signing +# +extra_certificates +signing_key.priv +signing_key.x509 +x509.genkey + +# Kconfig presets +all.config + +# customer folder +customer + diff --git a/drivers/amlogic/Makefile b/drivers/amlogic/Makefile index 4ef2059bbd30..69d054f2b64b 100644 --- a/drivers/amlogic/Makefile +++ b/drivers/amlogic/Makefile @@ -101,7 +101,7 @@ obj-$(CONFIG_AMLOGIC_POWER) += power/ obj-$(CONFIG_AMLOGIC_PCIE) += pci/ -obj-$(CONFIG_AMLOGIC_IRBLASTER) += irblaster/ +obj-$(CONFIG_AMLOGIC_IRBLASTER_CORE) += irblaster/ obj-$(CONFIG_AMLOGIC_IIO) += iio/ diff --git a/drivers/amlogic/Media.mk b/drivers/amlogic/Media.mk new file mode 100644 index 000000000000..eba1e1ed3612 --- /dev/null +++ b/drivers/amlogic/Media.mk @@ -0,0 +1,112 @@ +ifeq ($(KERNEL_A32_SUPPORT), true) +KERNEL_ARCH := arm +else +KERNEL_ARCH := arm64 +endif + +CONFIGS := CONFIG_AMLOGIC_MEDIA_VDEC_MPEG12=m \ + CONFIG_AMLOGIC_MEDIA_VDEC_MPEG2_MULTI=m \ + CONFIG_AMLOGIC_MEDIA_VDEC_MPEG4=m \ + CONFIG_AMLOGIC_MEDIA_VDEC_MPEG4_MULTI=m \ + CONFIG_AMLOGIC_MEDIA_VDEC_VC1=m \ + CONFIG_AMLOGIC_MEDIA_VDEC_H264=m \ + CONFIG_AMLOGIC_MEDIA_VDEC_H264_MULTI=m \ + CONFIG_AMLOGIC_MEDIA_VDEC_H264_MVC=m \ + CONFIG_AMLOGIC_MEDIA_VDEC_H265=m \ + CONFIG_AMLOGIC_MEDIA_VDEC_VP9=m \ + CONFIG_AMLOGIC_MEDIA_VDEC_MJPEG=m \ + CONFIG_AMLOGIC_MEDIA_VDEC_MJPEG_MULTI=m \ + CONFIG_AMLOGIC_MEDIA_VDEC_REAL=m \ + CONFIG_AMLOGIC_MEDIA_VDEC_AVS=m \ + CONFIG_AMLOGIC_MEDIA_VDEC_AVS2=m \ + CONFIG_AMLOGIC_MEDIA_VENC_H264=m \ + CONFIG_AMLOGIC_MEDIA_VENC_H265=m \ + CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION=y + CONFIG_AMLOGIC_MEDIA_GE2D=y + +define copy-media-modules +$(foreach m, $(shell find $(strip $(1)) -name "*.ko"),\ + $(shell cp $(m) $(strip $(2)) -rfa)) +endef + +ifneq (,$(TOP)) +KDIR := $(shell pwd)/$(PRODUCT_OUT)/obj/KERNEL_OBJ/ + +MEDIA_DRIVERS := $(TOP)/hardware/amlogic/media_modules/drivers +ifeq (,$(wildcard $(MEDIA_DRIVERS))) +$(error No find the dir of drivers.) +endif + +INCLUDE := $(MEDIA_DRIVERS)/include +ifeq (,$(wildcard $(INCLUDE))) +$(error No find the dir of include.) +endif + +MEDIA_MODULES := $(shell pwd)/$(PRODUCT_OUT)/obj/media_modules +ifeq (,$(wildcard $(MEDIA_MODULES))) +$(shell mkdir $(MEDIA_MODULES) -p) +endif + +MODS_OUT := $(shell pwd)/$(PRODUCT_OUT)/obj/lib_vendor +ifeq (,$(wildcard $(MODS_OUT))) +$(shell mkdir $(MODS_OUT) -p) +endif + +UCODE_OUT := $(shell pwd)/$(PRODUCT_OUT)/$(TARGET_COPY_OUT_VENDOR)/lib/firmware/video +ifeq (,$(wildcard $(UCODE_OUT))) +$(shell mkdir $(UCODE_OUT) -p) +endif + +$(shell cp $(MEDIA_DRIVERS)/../firmware/* $(UCODE_OUT) -rfa) +$(shell cp $(MEDIA_DRIVERS)/* $(MEDIA_MODULES) -rfa) + +define media-modules + @$(MAKE) -C $(KDIR) M=$(MEDIA_MODULES) ARCH=$(KERNEL_ARCH) \ + CROSS_COMPILE=$(PREFIX_CROSS_COMPILE) $(CONFIGS) \ + EXTRA_CFLAGS+=-I$(INCLUDE) modules; \ + find $(MEDIA_MODULES) -name "*.ko" | xargs -i cp {} $(MODS_OUT) +endef + +else +KDIR := $(PWD)/kernel +ifeq (,$(wildcard $(KDIR))) +$(error No find the dir of kernel.) +endif + +MEDIA_DRIVERS := $(PWD)/media_modules/drivers +ifeq (,$(wildcard $(MEDIA_DRIVERS))) +$(error No find the dir of drivers.) +endif + +INCLUDE := $(MEDIA_DRIVERS)/include +ifeq (,$(wildcard $(INCLUDE))) +$(error No find the dir of include.) +endif + +MODS_OUT ?= $(MEDIA_DRIVERS)/../modules +ifeq (,$(wildcard $(MODS_OUT))) +$(shell mkdir $(MODS_OUT) -p) +endif + +ifeq ($(KERNEL_A32_SUPPORT), true) +TOOLS := /opt/gcc-linaro-6.3.1-2017.02-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf- +else +TOOLS := /opt/gcc-linaro-5.3-2016.02-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu- +endif + +modules: + @$(MAKE) -C $(KDIR) M=$(MEDIA_DRIVERS) ARCH=$(KERNEL_ARCH) \ + CROSS_COMPILE=$(TOOLS) $(CONFIGS) \ + EXTRA_CFLAGS+=-I$(INCLUDE) -j64 + +copy-modules: + @echo "start copying media modules." + mkdir -p $(MODS_OUT) + $(call copy-media-modules, $(MEDIA_DRIVERS), $(MODS_OUT)) + +all: modules copy-modules + +clean: + $(MAKE) -C $(KDIR) M=$(MEDIA_DRIVERS) ARCH=$(KERNEL_ARCH) clean + +endif diff --git a/drivers/amlogic/atv_demod/atv_demod_access.c b/drivers/amlogic/atv_demod/atv_demod_access.c index 390c5d02cf91..9f08b56d9dbe 100644 --- a/drivers/amlogic/atv_demod/atv_demod_access.c +++ b/drivers/amlogic/atv_demod/atv_demod_access.c @@ -82,9 +82,9 @@ int atvaudiodem_reg_read(unsigned int reg, unsigned int *val) return 0; } } - - if (amlatvdemod_devp->audio_reg_base) - *val = readl(amlatvdemod_devp->audio_reg_base + reg); +#endif + if (amlatvdemod_devp->audiodemod_reg_base) + *val = readl(amlatvdemod_devp->audiodemod_reg_base + reg); return 0; } @@ -101,8 +101,40 @@ int atvaudiodem_reg_write(unsigned int reg, unsigned int val) } } + if (amlatvdemod_devp->audiodemod_reg_base) + writel(val, (amlatvdemod_devp->audiodemod_reg_base + reg)); + + return 0; +} + +int atvaudio_ctrl_read(unsigned int *val) +{ + /* only [0xffd0d340](others)/[0xff60074c](tl1) write */ + /* others: */ + /* bit0: I2s select in_src, 0 = atv_demod, 1 = adec */ + /* bit1: Din5, 0 = atv_demod, 1 = adec */ + /* bit2: L/R swap for adec audio data */ + /* TL1: */ + /* bit19: L/R swap for adec audio data */ + /* bit20: I2s select in_src, 0 = atv_demod, 1 = adec */ if (amlatvdemod_devp->audio_reg_base) - writel(val, (amlatvdemod_devp->audio_reg_base + reg)); + *val = readl(amlatvdemod_devp->audio_reg_base); + + return 0; +} + +int atvaudio_ctrl_write(unsigned int val) +{ + /* only 0xffd0d340(others)/0xff60074c(tl1) write */ + /* others: */ + /* bit0: I2s select in_src, 0 = atv_demod, 1 = adec */ + /* bit1: Din5, 0 = atv_demod, 1 = adec */ + /* bit2: L/R swap for adec audio data */ + /* TL1: */ + /* bit19: L/R swap for adec audio data */ + /* bit20: I2s select in_src, 0 = atv_demod, 1 = adec */ + if (amlatvdemod_devp->audio_reg_base) + writel(val, amlatvdemod_devp->audio_reg_base); return 0; } @@ -152,10 +184,10 @@ void atv_dmd_wr_reg(unsigned char block, unsigned char reg, unsigned long data) unsigned long atv_dmd_rd_reg(unsigned char block, unsigned char reg) { - unsigned long data = 0; + unsigned int data = 0; unsigned int reg_addr = (block << 8) + reg * 4; - amlatvdemod_reg_read(reg_addr, (unsigned int *)&data); + amlatvdemod_reg_read(reg_addr, &data); return data; } diff --git a/drivers/amlogic/atv_demod/atv_demod_access.h b/drivers/amlogic/atv_demod/atv_demod_access.h index 51b21821b46a..85c579c58b65 100644 --- a/drivers/amlogic/atv_demod/atv_demod_access.h +++ b/drivers/amlogic/atv_demod/atv_demod_access.h @@ -25,6 +25,8 @@ extern int amlatvdemod_reg_read(unsigned int reg, unsigned int *val); extern int amlatvdemod_reg_write(unsigned int reg, unsigned int val); extern int atvaudiodem_reg_read(unsigned int reg, unsigned int *val); extern int atvaudiodem_reg_write(unsigned int reg, unsigned int val); +extern int atvaudio_ctrl_read(unsigned int *val); +extern int atvaudio_ctrl_write(unsigned int val); extern int amlatvdemod_hiu_reg_read(unsigned int reg, unsigned int *val); extern int amlatvdemod_hiu_reg_write(unsigned int reg, unsigned int val); extern int amlatvdemod_periphs_reg_read(unsigned int reg, unsigned int *val); diff --git a/drivers/amlogic/atv_demod/atv_demod_afc.c b/drivers/amlogic/atv_demod/atv_demod_afc.c index 04edf2009df6..3cf5d956c8fa 100644 --- a/drivers/amlogic/atv_demod/atv_demod_afc.c +++ b/drivers/amlogic/atv_demod/atv_demod_afc.c @@ -107,7 +107,6 @@ void atv_demod_afc_do_work(struct work_struct *work) int freq_offset = 100; int tmp = 0; int field_lock = 0; - static int audio_overmodul; if (afc->state == false) return; @@ -125,13 +124,6 @@ void atv_demod_afc_do_work(struct work_struct *work) afc->pre_step = 0; - if (afc->lock) { - if (0 == ((audio_overmodul++) % 10)) { - aml_audio_overmodulation(1); - audio_overmodul = 0; - } - } - retrieve_frequency_offset(&freq_offset); if (++(afc->wave_cnt) <= afc_wave_cnt) {/*40ms*/ @@ -158,7 +150,8 @@ void atv_demod_afc_do_work(struct work_struct *work) return; } - if (!afc->lock || (afc->lock && !field_lock)) { + /* add "(lock && !field_lock)", horizontal synchronization test NG */ + if (!afc->lock/* || (afc->lock && !field_lock)*/) { afc->status = AFC_LOCK_STATUS_POST_UNLOCK; afc->pre_lock_cnt = 0; param->frequency -= afc->offset * 1000; @@ -263,6 +256,7 @@ static void atv_demod_afc_enable(struct atv_demod_afc *afc) afc->offset = 0; afc->no_sig_cnt = 0; afc->pre_step = 0; + afc->timer_delay_cnt = 20; afc->status = AFC_LOCK_STATUS_NULL; add_timer(&afc->timer); afc->state = true; diff --git a/drivers/amlogic/atv_demod/atv_demod_debug.c b/drivers/amlogic/atv_demod/atv_demod_debug.c index d85343cae3a7..284eeb838218 100644 --- a/drivers/amlogic/atv_demod/atv_demod_debug.c +++ b/drivers/amlogic/atv_demod/atv_demod_debug.c @@ -52,9 +52,12 @@ DEBUGFS_CREATE_NODE(aud_std, 0640, dentry, u32)\ DEBUGFS_CREATE_NODE(aud_mode, 0640, dentry, u32)\ DEBUGFS_CREATE_NODE(aud_auto, 0640, dentry, u32)\ + DEBUGFS_CREATE_NODE(aud_reinit, 0640, dentry, u32)\ + DEBUGFS_CREATE_NODE(aud_mono_only, 0640, dentry, u32)\ DEBUGFS_CREATE_NODE(over_threshold, 0640, dentry, u64)\ DEBUGFS_CREATE_NODE(input_amplitude, 0640, dentry, u64)\ DEBUGFS_CREATE_NODE(atvaudio_det_outputmode_en, 0640, dentry, bool)\ + DEBUGFS_CREATE_NODE(audio_carrier_offset_det_en, 0640, dentry, bool)\ DEBUGFS_CREATE_NODE(audio_det_en, 0640, dentry, bool)\ DEBUGFS_CREATE_NODE(non_std_en, 0640, dentry, u32)\ DEBUGFS_CREATE_NODE(atvdemod_det_nonstd_en, 0640, dentry, bool)\ @@ -84,6 +87,7 @@ DEBUGFS_CREATE_NODE(atvdemod_timer_delay2, 0640, dentry, u32)\ DEBUGFS_CREATE_NODE(atvdemod_mixer_tune_en, 0640, dentry, bool)\ DEBUGFS_CREATE_NODE(atvdemod_overmodulated_en, 0640, dentry, bool)\ + DEBUGFS_CREATE_NODE(atv_audio_overmodulated_en, 0640, dentry, bool)\ DEBUGFS_CREATE_NODE(audio_thd_en, 0640, dentry, bool)\ DEBUGFS_CREATE_NODE(pwm_kp, 0640, dentry, u32)\ DEBUGFS_CREATE_NODE(audio_gain_val, 0640, dentry, u32)\ @@ -92,8 +96,11 @@ DEBUGFS_CREATE_NODE(audio_nicam_delay, 0640, dentry, u32)\ DEBUGFS_CREATE_NODE(audio_a2_auto, 0640, dentry, u32)\ DEBUGFS_CREATE_NODE(audio_a2_power_threshold, 0640, dentry, u32)\ + DEBUGFS_CREATE_NODE(audio_a2_carrier_report, 0640, dentry, u32)\ DEBUGFS_CREATE_NODE(audio_gain_shift, 0640, dentry, u32)\ DEBUGFS_CREATE_NODE(audio_gain_lpr, 0640, dentry, u32)\ + DEBUGFS_CREATE_NODE(audio_atv_ov, 0640, dentry, u32)\ + DEBUGFS_CREATE_NODE(audio_atv_ov_flag, 0640, dentry, u32)\ } @@ -110,6 +117,7 @@ DEBUGFS_CREATE_FILE(sum2_thd_h, 0640, dentry, fops, int)\ DEBUGFS_CREATE_FILE(sum2_thd_l, 0640, dentry, fops, int)\ DEBUGFS_CREATE_FILE(afc_default, 0640, dentry, fops, int)\ + DEBUGFS_CREATE_FILE(snr_threshold, 0640, dentry, fops, int)\ } @@ -125,6 +133,7 @@ DEBUGFS_DENTRY_DEFINE(sum1_thd_l); DEBUGFS_DENTRY_DEFINE(sum2_thd_h); DEBUGFS_DENTRY_DEFINE(sum2_thd_l); DEBUGFS_DENTRY_DEFINE(afc_default); +DEBUGFS_DENTRY_DEFINE(snr_threshold); struct dentry_value *debugfs_dentry[] = { DEBUGFS_DENTRY_VALUE(non_std_thld_4c_h), @@ -136,6 +145,7 @@ struct dentry_value *debugfs_dentry[] = { DEBUGFS_DENTRY_VALUE(sum2_thd_h), DEBUGFS_DENTRY_VALUE(sum2_thd_l), DEBUGFS_DENTRY_VALUE(afc_default), + DEBUGFS_DENTRY_VALUE(snr_threshold), }; static int debugfs_open(struct inode *node, struct file *file) @@ -176,12 +186,11 @@ static ssize_t debugfs_write(struct file *file, const char __user *userbuf, char buf[20] = { 0 }; int len = ARRAY_SIZE(debugfs_dentry); + memset(buf, 0, sizeof(buf)); count = min_t(size_t, count, (sizeof(buf) - 1)); if (copy_from_user(buf, userbuf, count)) return -EFAULT; - buf[count] = 0; - /*i = sscanf(buf, "%d", &val);*/ i = kstrtoint(buf, 0, &val); if (i == 0) { diff --git a/drivers/amlogic/atv_demod/atv_demod_driver.c b/drivers/amlogic/atv_demod/atv_demod_driver.c index ceb4f299f0a0..93bb20530d09 100644 --- a/drivers/amlogic/atv_demod/atv_demod_driver.c +++ b/drivers/amlogic/atv_demod/atv_demod_driver.c @@ -45,7 +45,7 @@ #include "atvauddemod_func.h" -#define AMLATVDEMOD_VER "V2.04" +#define AMLATVDEMOD_VER "V2.09" struct aml_atvdemod_device *amlatvdemod_devp; @@ -66,7 +66,7 @@ static ssize_t aml_atvdemod_store(struct class *class, unsigned long tmp = 0, data = 0; struct aml_atvdemod_device *dev = container_of(class, struct aml_atvdemod_device, cls); - struct atv_demod_priv *priv = dev->v4l2_fe.fe.analog_demod_priv; + /*struct atv_demod_priv *priv = dev->v4l2_fe.fe.analog_demod_priv;*/ buf_orig = kstrdup(buf, GFP_KERNEL); ps = buf_orig; @@ -82,11 +82,12 @@ static ssize_t aml_atvdemod_store(struct class *class, if (parm[0] == NULL) goto EXIT; - +#if 0 if (priv->state != ATVDEMOD_STATE_WORK) { pr_info("atvdemod_state not work ....\n"); goto EXIT; } +#endif if (!strncmp(parm[0], "init", 4)) { ret = atv_demod_enter_mode(&dev->v4l2_fe.fe); @@ -271,6 +272,7 @@ static ssize_t aml_atvdemod_store(struct class *class, struct analog_parameters params; struct v4l2_analog_parameters *p = NULL; unsigned int std = 0; + unsigned int freq = 0; fe = &dev->v4l2_fe.fe; p = &dev->v4l2_fe.params; @@ -280,7 +282,12 @@ static ssize_t aml_atvdemod_store(struct class *class, else std = p->std; - params.frequency = p->frequency; + if (parm[2] && kstrtoul(parm[2], 0, &tmp) == 0) + freq = tmp; + else + freq = p->frequency; + + params.frequency = freq; params.mode = p->afc_range; params.audmode = p->audmode; params.std = std; @@ -310,11 +317,40 @@ static ssize_t aml_atvdemod_store(struct class *class, v4l2_std_to_str((0xffffff & dev->std))); pr_info("[atvdemod] audmode: 0x%x\n", dev->audmode); pr_info("[atvdemod] flag: %d\n", p->flag); - pr_info("[atvdemod] tuner_id: %d\n", dev->tuner_id); + pr_info("[atvdemod] tuner_cur: %d\n", dev->tuner_cur); + pr_info("[atvdemod] tuner_id: %d\n", + dev->tuners[dev->tuner_cur].cfg.id); pr_info("[atvdemod] if_freq: %d\n", dev->if_freq); pr_info("[atvdemod] if_inv: %d\n", dev->if_inv); pr_info("[atvdemod] fre_offset: %d\n", dev->fre_offset); pr_info("[atvdemod] version: %s.\n", AMLATVDEMOD_VER); + } else if (!strncmp(parm[0], "attach_tuner", 12)) { + int tuner_id = 0; + + if (parm[1] && kstrtoul(parm[1], 10, &tmp) == 0) { + val = tmp; + + for (i = 0; i < dev->tuner_num; ++i) { + if (dev->tuners[i].cfg.id == val) { + tuner_id = dev->tuners[i].cfg.id; + break; + } + } + + if (tuner_id == 0 || dev->tuner_cur == i) { + pr_err("%s: set nonsupport or the same tuner %d.\n", + __func__, val); + goto EXIT; + } + + dev->tuner_cur = i; + + ret = aml_attach_tuner(dev); + if (ret) + pr_info("attach_tuner error.\n"); + else + pr_info("attach_tuner %d done.\n", tuner_id); + } } else pr_dbg("invalid command\n"); @@ -350,7 +386,9 @@ static void aml_atvdemod_dt_parse(struct aml_atvdemod_device *pdev) struct device_node *node_i2c = NULL; unsigned int val = 0; const char *str = NULL; + char buf[20] = { 0 }; int ret = 0; + int i = 0; node = pdev->dev->of_node; if (node == NULL) { @@ -382,8 +420,7 @@ static void aml_atvdemod_dt_parse(struct aml_atvdemod_device *pdev) pdev->agc_pin = NULL; pr_err("can't find agc pinmux.\n"); } else { - pr_err("atvdemod agc pinmux name: %s\n", - pdev->pin_name); + pr_err("atvdemod agc pinmux name: %s\n", pdev->pin_name); } ret = of_property_read_u32(node, "btsc_sap_mode", &val); @@ -394,119 +431,176 @@ static void aml_atvdemod_dt_parse(struct aml_atvdemod_device *pdev) /* get tuner config node */ node_tuner = of_parse_phandle(node, "tuner", 0); - if (node_tuner) { - ret = of_property_read_string(node_tuner, "tuner_name", &str); - if (ret) - pr_err("can't find tuner.\n"); - else { - if (!strncmp(str, "mxl661_tuner", 12)) - pdev->tuner_id = AM_TUNER_MXL661; - else if (!strncmp(str, "si2151_tuner", 12)) - pdev->tuner_id = AM_TUNER_SI2151; - else if (!strncmp(str, "si2159_tuner", 12)) - pdev->tuner_id = AM_TUNER_SI2159; - else if (!strncmp(str, "r840_tuner", 10)) - pdev->tuner_id = AM_TUNER_R840; - else if (!strncmp(str, "r842_tuner", 10)) - pdev->tuner_id = AM_TUNER_R842; - else - pr_err("nonsupport tuner: %s.\n", str); + if (!node_tuner) { + pr_err("can't find tuner node.\n"); + return; + } + + ret = of_property_read_u32(node_tuner, "tuner_num", &val); + if (ret == 0) + pdev->tuner_num = val; + else { + pr_err("can't find tuner_num.\n"); + return; + } + + pdev->tuners = kcalloc(pdev->tuner_num, sizeof(struct aml_tuner), + GFP_KERNEL); + if (!pdev->tuners) { + /* pr_err("can't kcalloc for tuners.\n"); */ + return; + } + + ret = of_property_read_u32(node_tuner, "tuner_cur", &val); + if (ret) { + pr_err("can't find tuner_cur, use default 0.\n"); + pdev->tuner_cur = -1; + } else + pdev->tuner_cur = val; + + for (i = 0; i < pdev->tuner_num; ++i) { + snprintf(buf, sizeof(buf), "tuner_name_%d", i); + ret = of_property_read_string(node_tuner, buf, &str); + if (ret) { + pr_err("can't find tuner %d.\n", i); + continue; } - node_i2c = of_parse_phandle(node_tuner, "tuner_i2c_adap", 0); + if (!strncmp(str, "mxl661_tuner", 12)) + pdev->tuners[i].cfg.id = AM_TUNER_MXL661; + else if (!strncmp(str, "si2151_tuner", 12)) + pdev->tuners[i].cfg.id = AM_TUNER_SI2151; + else if (!strncmp(str, "si2159_tuner", 12)) + pdev->tuners[i].cfg.id = AM_TUNER_SI2159; + else if (!strncmp(str, "r840_tuner", 10)) + pdev->tuners[i].cfg.id = AM_TUNER_R840; + else if (!strncmp(str, "r842_tuner", 10)) + pdev->tuners[i].cfg.id = AM_TUNER_R842; + else { + pr_err("can't support tuner: %s.\n", str); + pdev->tuners[i].cfg.id = AM_TUNER_NONE; + } + + snprintf(buf, sizeof(buf), "tuner_i2c_adap_%d", i); + node_i2c = of_parse_phandle(node_tuner, buf, 0); if (node_i2c) { - pdev->i2c_adp = of_find_i2c_adapter_by_node(node_i2c); + pdev->tuners[i].i2c_adp = + of_find_i2c_adapter_by_node(node_i2c); of_node_put(node_i2c); - if (!pdev->i2c_adp) + if (!pdev->tuners[i].i2c_adp) pr_err("can't find tuner_i2c_adap.\n"); } - ret = of_property_read_u32(node_tuner, "tuner_i2c_addr", &val); + snprintf(buf, sizeof(buf), "tuner_i2c_addr_%d", i); + ret = of_property_read_u32(node_tuner, buf, &val); if (ret) pr_err("can't find tuner_i2c_addr.\n"); else - pdev->i2c_addr = val; + pdev->tuners[i].cfg.i2c_addr = val; - ret = of_property_read_u32(node_tuner, "tuner_xtal", &val); + snprintf(buf, sizeof(buf), "tuner_xtal_%d", i); + ret = of_property_read_u32(node_tuner, buf, &val); if (ret) pr_err("can't find tuner_xtal.\n"); else - pdev->tuner_xtal = val; + pdev->tuners[i].cfg.xtal = val; - ret = of_property_read_u32(node_tuner, "tuner_xtal_mode", &val); + snprintf(buf, sizeof(buf), "tuner_xtal_mode_%d", i); + ret = of_property_read_u32(node_tuner, buf, &val); if (ret) pr_err("can't find tuner_xtal_mode.\n"); else - pdev->tuner_xtal_mode = val; + pdev->tuners[i].cfg.xtal_mode = val; - ret = of_property_read_u32(node_tuner, "tuner_xtal_cap", &val); + snprintf(buf, sizeof(buf), "tuner_xtal_cap_%d", i); + ret = of_property_read_u32(node_tuner, buf, &val); if (ret) pr_err("can't find tuner_xtal_cap.\n"); else - pdev->tuner_xtal_cap = val; + pdev->tuners[i].cfg.xtal_cap = val; - of_node_put(node_tuner); + pr_err("find tuner %d.\n", i); } + + of_node_put(node_tuner); } -int aml_attach_demod_tuner(struct aml_atvdemod_device *dev) +int aml_attach_demod(struct aml_atvdemod_device *dev) { void *p = NULL; struct v4l2_frontend *v4l2_fe = &dev->v4l2_fe; struct dvb_frontend *fe = &v4l2_fe->fe; - struct tuner_config cfg = { 0 }; - if (!dev->analog_attached) { - p = v4l2_attach(aml_atvdemod_attach, fe, v4l2_fe, - dev->i2c_adp, dev->i2c_addr, dev->tuner_id); - if (p != NULL) - dev->analog_attached = true; - else { - pr_err("%s: attach demod error.\n", __func__); - return -1; - } + if (dev->tuner_cur < 0) { + pr_err("%s: dev->tuner_cur [%d] error.\n", + __func__, dev->tuner_cur); + return -1; } - p = NULL; + p = v4l2_attach(aml_atvdemod_attach, fe, v4l2_fe, + dev->tuners[dev->tuner_cur].i2c_adp, + dev->tuners[dev->tuner_cur].cfg.i2c_addr, + dev->tuners[dev->tuner_cur].cfg.id); + if (p != NULL) + dev->analog_attached = true; + else { + pr_err("%s: attach demod error.\n", __func__); + return -1; + } - cfg.id = dev->tuner_id; - cfg.i2c_addr = dev->i2c_addr; - cfg.xtal = dev->tuner_xtal; - cfg.xtal_mode = dev->tuner_xtal_mode; - cfg.xtal_cap = dev->tuner_xtal_cap; + return 0; +} - if (!dev->tuner_attached) { - switch (dev->tuner_id) { - case AM_TUNER_R840: - p = v4l2_attach(r840_attach, fe, - dev->i2c_adp, &cfg); - break; - case AM_TUNER_R842: - p = v4l2_attach(r842_attach, fe, - dev->i2c_adp, &cfg); - break; - case AM_TUNER_SI2151: - p = v4l2_attach(si2151_attach, fe, - dev->i2c_adp, &cfg); - break; - case AM_TUNER_SI2159: - p = v4l2_attach(si2159_attach, fe, - dev->i2c_adp, &cfg); - break; - case AM_TUNER_MXL661: - p = v4l2_attach(mxl661_attach, fe, - dev->i2c_adp, &cfg); - break; - } +int aml_attach_tuner(struct aml_atvdemod_device *dev) +{ + void *p = NULL; + struct v4l2_frontend *v4l2_fe = &dev->v4l2_fe; + struct dvb_frontend *fe = &v4l2_fe->fe; + struct tuner_config *cfg = NULL; - if (p != NULL) - dev->tuner_attached = true; - else { - pr_err("%s: attach tuner [%d] error.\n", - __func__, dev->tuner_id); - return -1; - } + if (dev->tuner_cur < 0) { + pr_err("%s: dev->tuner_cur [%d] error.\n", + __func__, dev->tuner_cur); + return -1; + } + + cfg = &dev->tuners[dev->tuner_cur].cfg; + + switch (cfg->id) { + case AM_TUNER_R840: + p = v4l2_attach(r840_attach, fe, + dev->tuners[dev->tuner_cur].i2c_adp, cfg); + break; + case AM_TUNER_R842: + p = v4l2_attach(r842_attach, fe, + dev->tuners[dev->tuner_cur].i2c_adp, cfg); + break; + case AM_TUNER_SI2151: + p = v4l2_attach(si2151_attach, fe, + dev->tuners[dev->tuner_cur].i2c_adp, cfg); + break; + case AM_TUNER_SI2159: + p = v4l2_attach(si2159_attach, fe, + dev->tuners[dev->tuner_cur].i2c_adp, cfg); + break; + case AM_TUNER_MXL661: + p = v4l2_attach(mxl661_attach, fe, + dev->tuners[dev->tuner_cur].i2c_adp, cfg); + break; + default: + pr_err("%s: Nonsupport tuner [%d].\n", __func__, cfg->id); + break; + } + + if (p != NULL) { + dev->tuner_attached = true; + v4l2_fe->tuner_id = cfg->id; + v4l2_fe->i2c.addr = cfg->i2c_addr; + v4l2_fe->i2c.adapter = dev->tuners[dev->tuner_cur].i2c_adp; + } else { + pr_err("%s: attach tuner [%d] error.\n", __func__, cfg->id); + return -1; } return 0; @@ -548,7 +642,7 @@ static int aml_atvdemod_probe(struct platform_device *pdev) res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { - pr_err("get demod memory resource fail.\n"); + pr_err("no demod memory resource.\n"); goto fail_get_resource; } @@ -566,7 +660,7 @@ static int aml_atvdemod_probe(struct platform_device *pdev) res = platform_get_resource(pdev, IORESOURCE_MEM, 1); if (!res) { - pr_err("no hiu demod memory resource.\n"); + pr_err("no hiu memory resource.\n"); dev->hiu_reg_base = NULL; } else { size_io_reg = resource_size(res); @@ -584,7 +678,7 @@ static int aml_atvdemod_probe(struct platform_device *pdev) res = platform_get_resource(pdev, IORESOURCE_MEM, 2); if (!res) { - pr_err("no periphs demod memory resource.\n"); + pr_err("no periphs memory resource.\n"); dev->periphs_reg_base = NULL; } else { size_io_reg = resource_size(res); @@ -602,39 +696,40 @@ static int aml_atvdemod_probe(struct platform_device *pdev) res = platform_get_resource(pdev, IORESOURCE_MEM, 3); if (!res) { - pr_err("no audio demod memory resource.\n"); - dev->audio_reg_base = NULL; + pr_err("no audiodemod memory resource.\n"); + dev->audiodemod_reg_base = NULL; } else { size_io_reg = resource_size(res); - dev->audio_reg_base = devm_ioremap_nocache( + dev->audiodemod_reg_base = devm_ioremap_nocache( &pdev->dev, res->start, size_io_reg); - if (!dev->audio_reg_base) { - pr_err("audio ioremap failed.\n"); + if (!dev->audiodemod_reg_base) { + pr_err("audiodemod ioremap failed.\n"); goto fail_get_resource; } - pr_info("audio start = 0x%p, size = 0x%x, base = 0x%p.\n", + pr_info("audiodemod start = 0x%p, size = 0x%x, base = 0x%p.\n", (void *) res->start, size_io_reg, - dev->audio_reg_base); + dev->audiodemod_reg_base); } + /* add for audio system control */ if (is_meson_txlx_cpu() || is_meson_txhd_cpu()) { - /* add for audio system control */ - dev->audio_demod_reg_base = ioremap( - round_down(0xffd0d340, 0x3), 4); + dev->audio_reg_base = ioremap(round_down(0xffd0d340, 0x3), 4); - pr_info("audio_demod_reg_base = 0x%p.\n", - dev->audio_demod_reg_base); + pr_info("audio_reg_base = 0x%p.\n", dev->audio_reg_base); + } else if (is_meson_tl1_cpu()) { + dev->audio_reg_base = ioremap(round_down(0xff60074c, 0x3), 4); + + pr_info("audio_reg_base = 0x%p.\n", dev->audio_reg_base); } aml_atvdemod_dt_parse(dev); - aml_attach_demod_tuner(dev); + aml_attach_demod(dev); + aml_attach_tuner(dev); dev->v4l2_fe.dev = dev->dev; - dev->v4l2_fe.tuner_id = dev->tuner_id; - dev->v4l2_fe.i2c.addr = dev->i2c_addr; - dev->v4l2_fe.i2c.adapter = dev->i2c_adp; + ret = v4l2_resister_frontend(&dev->v4l2_fe); if (ret < 0) { pr_err("resister v4l2 fail.\n"); @@ -653,6 +748,7 @@ fail_register_v4l2: fail_get_resource: class_unregister(&dev->cls); fail_class_register: + kfree(dev->tuners); kfree(dev); pr_info("%s: fail.\n", __func__); @@ -674,6 +770,7 @@ static int aml_atvdemod_remove(struct platform_device *pdev) amlatvdemod_devp = NULL; + kfree(dev->tuners); kfree(dev); pr_info("%s: OK.\n", __func__); diff --git a/drivers/amlogic/atv_demod/atv_demod_driver.h b/drivers/amlogic/atv_demod/atv_demod_driver.h index 55d67a5eddc7..60a368543603 100644 --- a/drivers/amlogic/atv_demod/atv_demod_driver.h +++ b/drivers/amlogic/atv_demod/atv_demod_driver.h @@ -38,18 +38,20 @@ struct aml_atvdemod_parameters { unsigned int reserved; }; +struct aml_tuner { + struct tuner_config cfg; + unsigned int i2c_adapter_id; + struct i2c_adapter *i2c_adp; +}; + struct aml_atvdemod_device { char *name; struct class cls; struct device *dev; - unsigned int tuner_id; - unsigned int tuner_xtal; - unsigned int tuner_xtal_mode; - unsigned int tuner_xtal_cap; - unsigned int i2c_addr; - unsigned int i2c_adapter_id; - struct i2c_adapter *i2c_adp; + unsigned int tuner_num; + int tuner_cur; + struct aml_tuner *tuners; unsigned int if_freq; unsigned int if_inv; @@ -66,10 +68,10 @@ struct aml_atvdemod_device { bool tuner_attached; void __iomem *demod_reg_base; - void __iomem *audio_reg_base; + void __iomem *audiodemod_reg_base; void __iomem *hiu_reg_base; void __iomem *periphs_reg_base; - void __iomem *audio_demod_reg_base; + void __iomem *audio_reg_base; unsigned int reg_23cf; /* IIR filter */ int btsc_sap_mode; /*0: off 1:monitor 2:auto */ @@ -94,6 +96,7 @@ struct aml_atvdemod_device { extern struct aml_atvdemod_device *amlatvdemod_devp; -extern int aml_attach_demod_tuner(struct aml_atvdemod_device *dev); +extern int aml_attach_demod(struct aml_atvdemod_device *dev); +extern int aml_attach_tuner(struct aml_atvdemod_device *dev); #endif /* __ATV_DEMOD_DRIVER_H__ */ diff --git a/drivers/amlogic/atv_demod/atv_demod_monitor.c b/drivers/amlogic/atv_demod/atv_demod_monitor.c index 86cd6fcb16bb..726b019a45f3 100644 --- a/drivers/amlogic/atv_demod/atv_demod_monitor.c +++ b/drivers/amlogic/atv_demod/atv_demod_monitor.c @@ -29,11 +29,13 @@ static DEFINE_MUTEX(monitor_mutex); bool atvdemod_mixer_tune_en; bool atvdemod_overmodulated_en; +bool atv_audio_overmodulated_en; bool audio_det_en; bool atvdemod_det_snr_en = true; -bool audio_thd_en = true; +bool audio_thd_en; bool atvdemod_det_nonstd_en; bool atvaudio_det_outputmode_en = true; +bool audio_carrier_offset_det_en; unsigned int atvdemod_timer_delay = 100; /* 1s */ unsigned int atvdemod_timer_delay2 = 10; /* 100ms */ @@ -43,28 +45,45 @@ bool atvdemod_timer_en = true; static void atv_demod_monitor_do_work(struct work_struct *work) { + int vpll_lock = 0, line_lock = 0; struct atv_demod_monitor *monitor = container_of(work, struct atv_demod_monitor, work); if (!monitor->state) return; + retrieve_vpll_carrier_lock(&vpll_lock); + retrieve_vpll_carrier_line_lock(&line_lock); + if ((vpll_lock != 0) || (line_lock != 0)) { + monitor->lock_cnt = 0; + return; + } + + monitor->lock_cnt++; + if (atvdemod_mixer_tune_en) atvdemod_mixer_tune(); if (atvdemod_overmodulated_en) atvdemod_video_overmodulated(); + if (atv_audio_overmodulated_en) { + if (monitor->lock_cnt % 10 == 0) + aml_audio_overmodulation(1); + } + if (atvdemod_det_snr_en) atvdemod_det_snr_serice(); if (audio_thd_en) audio_thd_det(); - if (atvaudio_det_outputmode_en && - (is_meson_txlx_cpu() || is_meson_txhd_cpu())) + if (atvaudio_det_outputmode_en) atvauddemod_set_outputmode(); + if (audio_carrier_offset_det_en) + audio_carrier_offset_det(); + if (atvdemod_det_nonstd_en) atv_dmd_non_std_set(true); } @@ -103,6 +122,7 @@ static void atv_demod_monitor_enable(struct atv_demod_monitor *monitor) ATVDEMOD_INTERVAL * atvdemod_timer_delay; add_timer(&monitor->timer); monitor->state = true; + monitor->lock_cnt = 0; } mutex_unlock(&monitor->mtx); @@ -134,6 +154,7 @@ void atv_demod_monitor_init(struct atv_demod_monitor *monitor) monitor->state = false; monitor->lock = false; + monitor->lock_cnt = 0; monitor->disable = atv_demod_monitor_disable; monitor->enable = atv_demod_monitor_enable; diff --git a/drivers/amlogic/atv_demod/atv_demod_monitor.h b/drivers/amlogic/atv_demod/atv_demod_monitor.h index b9c1e6ad3b88..95c5a2b59b31 100644 --- a/drivers/amlogic/atv_demod/atv_demod_monitor.h +++ b/drivers/amlogic/atv_demod/atv_demod_monitor.h @@ -34,6 +34,8 @@ struct atv_demod_monitor { bool state; bool lock; + unsigned int lock_cnt; + void (*disable)(struct atv_demod_monitor *monitor); void (*enable)(struct atv_demod_monitor *monitor); }; diff --git a/drivers/amlogic/atv_demod/atv_demod_ops.c b/drivers/amlogic/atv_demod/atv_demod_ops.c index 029d65229e3a..f980075a51d3 100644 --- a/drivers/amlogic/atv_demod/atv_demod_ops.c +++ b/drivers/amlogic/atv_demod/atv_demod_ops.c @@ -73,8 +73,7 @@ void aml_fe_get_atvaudio_state(int *state) /* scan mode need mute */ if (priv->state == ATVDEMOD_STATE_WORK && !priv->scanning - && !priv->standby - && av_status) { + && !priv->standby) { retrieve_vpll_carrier_lock(&vpll_lock); retrieve_vpll_carrier_line_lock(&line_lock); if ((vpll_lock == 0) && (line_lock == 0)) { @@ -87,9 +86,9 @@ void aml_fe_get_atvaudio_state(int *state) } } else { *state = 0; - pr_audio("ATV state[%d], scan[%d], standby[%d], av[%d].\n", - priv->state, priv->scanning, - priv->standby, av_status); + pr_audio("%s, ATV in state[%d], scanning[%d], standby[%d].\n", + __func__, priv->state, + priv->scanning, priv->standby); } /* If the atv signal is locked, it means there is audio data, @@ -173,7 +172,6 @@ int atv_demod_leave_mode(struct dvb_frontend *fe) struct atv_demod_priv *priv = fe->analog_demod_priv; priv->state = ATVDEMOD_STATE_IDEL; - priv->standby = true; if (priv->afc.disable) priv->afc.disable(&priv->afc); @@ -243,27 +241,26 @@ static void atv_demod_set_params(struct dvb_frontend *fe, (p->tuner_id == AM_TUNER_SI2151) || (p->tuner_id == AM_TUNER_SI2159) || (p->tuner_id == AM_TUNER_MXL661)) - reconfig = true; + reconfig = false; /* In general, demod does not need to be reconfigured * if parameters such as STD remain unchanged, * but when the input signal frequency offset -0.25MHz, * demod will be unlocked. That's very strange. */ - if (reconfig || amlatvdemod_devp->std != p->param.std || + if (reconfig || !priv->scanning || + amlatvdemod_devp->std != p->param.std || amlatvdemod_devp->audmode != p->param.audmode || amlatvdemod_devp->if_freq != p->if_freq || - amlatvdemod_devp->if_inv != p->if_inv || - amlatvdemod_devp->tuner_id != p->tuner_id) { + amlatvdemod_devp->if_inv != p->if_inv) { amlatvdemod_devp->std = p->param.std; amlatvdemod_devp->audmode = p->param.audmode; amlatvdemod_devp->if_freq = p->if_freq; amlatvdemod_devp->if_inv = p->if_inv; - amlatvdemod_devp->tuner_id = p->tuner_id; atv_dmd_set_std(); - + atvdemod_init(!priv->scanning); } else atv_dmd_soft_reset(); @@ -284,6 +281,8 @@ static void atv_demod_set_params(struct dvb_frontend *fe, /* for searching mute audio */ priv->standby = false; } + + priv->standby = false; } static int atv_demod_has_signal(struct dvb_frontend *fe, u16 *signal) @@ -302,7 +301,7 @@ static int atv_demod_has_signal(struct dvb_frontend *fe, u16 *signal) __func__, vpll_lock, line_lock); } else { *signal = V4L2_TIMEDOUT; - pr_info("%s unlocked [vpll_lock: 0x%x, line_lock:0x%x]\n", + pr_dbg("%s unlocked [vpll_lock: 0x%x, line_lock:0x%x]\n", __func__, vpll_lock, line_lock); } @@ -433,7 +432,7 @@ static struct analog_demod_ops atvdemod_ops = { }; -unsigned int tuner_status_cnt = 8; /* 4-->16 test on sky mxl661 */ +unsigned int tuner_status_cnt = 4; /* 4-->16 test on sky mxl661 */ bool slow_mode; @@ -530,7 +529,7 @@ static v4l2_std_id atvdemod_fe_tvin_fmt_to_v4l2_std(int fmt) static void atvdemod_fe_try_analog_format(struct v4l2_frontend *v4l2_fe, int auto_search_std, v4l2_std_id *video_fmt, - unsigned int *audio_fmt) + unsigned int *audio_fmt, unsigned int *soundsys) { struct dvb_frontend *fe = &v4l2_fe->fe; struct v4l2_analog_parameters *p = &v4l2_fe->params; @@ -538,6 +537,7 @@ static void atvdemod_fe_try_analog_format(struct v4l2_frontend *v4l2_fe, int i = 0; int try_vfmt_cnt = 300; int varify_cnt = 0; + int cvbs_std = 0; v4l2_std_id std_bk = 0; unsigned int broad_std = 0; unsigned int audio = 0; @@ -549,12 +549,12 @@ static void atvdemod_fe_try_analog_format(struct v4l2_frontend *v4l2_fe, __func__); break; } - std_bk = aml_fe_hook_get_fmt(); - if (std_bk) { + cvbs_std = aml_fe_hook_get_fmt(); + if (cvbs_std) { varify_cnt++; - pr_dbg("get varify_cnt:%d, cnt:%d, std_bk:0x%x\n", + pr_dbg("get cvbs_std varify_cnt:%d, cnt:%d, cvbs_std:0x%x\n", varify_cnt, i, - (unsigned int) std_bk); + (unsigned int) cvbs_std); if (((v4l2_fe->tuner_id == AM_TUNER_R840 || v4l2_fe->tuner_id == AM_TUNER_R842) && varify_cnt > 0) @@ -591,13 +591,13 @@ static void atvdemod_fe_try_analog_format(struct v4l2_frontend *v4l2_fe, usleep_range(30 * 1000, 30 * 1000 + 100); } - pr_dbg("get std_bk cnt:%d, std_bk: 0x%x\n", - i, (unsigned int) std_bk); + pr_dbg("get cvbs_std cnt:%d, cvbs_std: 0x%x\n", + i, (unsigned int) cvbs_std); - if (std_bk == 0) { + if (cvbs_std == 0) { pr_err("%s: failed to get video fmt, assume PAL.\n", __func__); - std_bk = TVIN_SIG_FMT_CVBS_PAL_I; + cvbs_std = TVIN_SIG_FMT_CVBS_PAL_I; p->std = V4L2_COLOR_STD_PAL | V4L2_STD_PAL_DK; p->frequency += 1; p->audmode = V4L2_STD_PAL_DK; @@ -612,7 +612,7 @@ static void atvdemod_fe_try_analog_format(struct v4l2_frontend *v4l2_fe, usleep_range(20 * 1000, 20 * 1000 + 100); } - std_bk = atvdemod_fe_tvin_fmt_to_v4l2_std(std_bk); + std_bk = atvdemod_fe_tvin_fmt_to_v4l2_std(cvbs_std); } else { /* Only search std by user setting, * so no need tvafe identify signal. @@ -629,9 +629,14 @@ static void atvdemod_fe_try_analog_format(struct v4l2_frontend *v4l2_fe, if (std_bk & V4L2_COLOR_STD_NTSC) { #if 1 /* For TV Signal Generator(TG39) test, NTSC need support other audio.*/ - amlatvdemod_set_std(AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_DK); - broad_std = aml_audiomode_autodet(v4l2_fe); - audio = atvdemod_fmt_2_v4l2_std(broad_std); + if (cvbs_std == TVIN_SIG_FMT_CVBS_NTSC_M) { + broad_std = AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_M; + audio = V4L2_STD_NTSC_M; + } else { + amlatvdemod_set_std(AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC); + broad_std = aml_audiomode_autodet(v4l2_fe); + audio = atvdemod_fmt_2_v4l2_std(broad_std); + } #if 0 /* I don't know what's going on here */ if (audio == V4L2_STD_PAL_M) audio = V4L2_STD_NTSC_M; @@ -651,9 +656,15 @@ static void atvdemod_fe_try_analog_format(struct v4l2_frontend *v4l2_fe, #endif } else { /* V4L2_COLOR_STD_PAL */ - amlatvdemod_set_std(AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_DK); - broad_std = aml_audiomode_autodet(v4l2_fe); - audio = atvdemod_fmt_2_v4l2_std(broad_std); + if (cvbs_std == TVIN_SIG_FMT_CVBS_PAL_M) { + broad_std = AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_M; + audio = V4L2_STD_PAL_M; + } else { + amlatvdemod_set_std( + AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_DK); + broad_std = aml_audiomode_autodet(v4l2_fe); + audio = atvdemod_fmt_2_v4l2_std(broad_std); + } #if 0 /* Why do this to me? We need support PAL_M.*/ if (audio == V4L2_STD_PAL_M) { audio = atvdemod_fmt_2_v4l2_std(broad_std_except_pal_m); @@ -662,10 +673,17 @@ static void atvdemod_fe_try_analog_format(struct v4l2_frontend *v4l2_fe, #endif } - pr_info("autodet audio mode %d, [%s][0x%x]\n", - broad_std, v4l2_std_to_str(audio), audio); - *audio_fmt = audio; + + /* for audio standard detection */ + if (is_meson_txlx_cpu() || is_meson_txhd_cpu() || is_meson_tl1_cpu()) { + *soundsys = amlfmt_aud_standard(broad_std); + *soundsys = (*soundsys << 16) | 0x00FFFF; + } else + *soundsys = 0xFFFFFF; + + pr_info("autodet audio broad_std %d, [%s][0x%x] soundsys[0x%x]\n", + broad_std, v4l2_std_to_str(audio), audio, *soundsys); } static int atvdemod_fe_afc_closer(struct v4l2_frontend *v4l2_fe, int minafcfreq, @@ -795,6 +813,26 @@ static int atvdemod_fe_afc_closer(struct v4l2_frontend *v4l2_fe, int minafcfreq, } } + /* After correcting the frequency offset success, + * need to set up tuner. + */ + if (fe->ops.tuner_ops.set_analog_params) { + params.frequency = p->frequency; + params.mode = p->afc_range; + params.audmode = p->audmode; + params.std = p->std; + fe->ops.tuner_ops.set_analog_params(fe, + ¶ms); + + if (tuner_id == AM_TUNER_SI2151 || + tuner_id == AM_TUNER_SI2159 || + tuner_id == AM_TUNER_R840 || + tuner_id == AM_TUNER_R842) + usleep_range(10 * 1000, 10 * 1000 + 100); + else if (tuner_id == AM_TUNER_MXL661) + usleep_range(30 * 1000, 30 * 1000 + 100); + } + freq_success = p->frequency; ktime_get_ts(&success_time); pr_dbg("[%s] get afc %d khz done, freq %u.\n", @@ -807,8 +845,9 @@ static int atvdemod_fe_afc_closer(struct v4l2_frontend *v4l2_fe, int minafcfreq, static int atvdemod_fe_set_property(struct v4l2_frontend *v4l2_fe, struct v4l2_property *tvp) { - struct dvb_frontend *fe = &amlatvdemod_devp->v4l2_fe.fe; + struct dvb_frontend *fe = &v4l2_fe->fe; struct atv_demod_priv *priv = fe->analog_demod_priv; + struct v4l2_analog_parameters *params = &v4l2_fe->params; pr_dbg("%s: cmd = 0x%x.\n", __func__, tvp->cmd); @@ -816,13 +855,19 @@ static int atvdemod_fe_set_property(struct v4l2_frontend *v4l2_fe, case V4L2_SOUND_SYS: /* aud_mode = tvp->data & 0xFF; */ amlatvdemod_devp->soundsys = tvp->data & 0xFF; - if (amlatvdemod_devp->soundsys != 0xFF) + if (amlatvdemod_devp->soundsys != 0xFF) { aud_mode = amlatvdemod_devp->soundsys; + params->soundsys = aud_mode; + } priv->sound_sys.output_mode = tvp->data & 0xFF; break; case V4L2_SLOW_SEARCH_MODE: - tvp->data = slow_mode; + slow_mode = tvp->data; + break; + + case V4L2_SIF_OVER_MODULATION: + priv->sound_sys.sif_over_modulation = tvp->data; break; default: @@ -847,7 +892,7 @@ static int atvdemod_fe_get_property(struct v4l2_frontend *v4l2_fe, break; case V4L2_SLOW_SEARCH_MODE: - slow_mode = tvp->data; + tvp->data = slow_mode; break; default: @@ -875,6 +920,7 @@ static enum v4l2_search atvdemod_fe_search(struct v4l2_frontend *v4l2_fe) int tuner_status_cnt_local = tuner_status_cnt; v4l2_std_id std_bk = 0; unsigned int audio = 0; + unsigned int soundsys = 0; int double_check_cnt = 1; int auto_search_std = 0; int search_count = 0; @@ -916,6 +962,7 @@ static enum v4l2_search atvdemod_fe_search(struct v4l2_frontend *v4l2_fe) */ if (p->std == 0) { p->std = V4L2_COLOR_STD_NTSC | V4L2_STD_NTSC_M; + /* p->std = V4L2_COLOR_STD_PAL | V4L2_STD_DK; */ auto_search_std = 0x01; pr_dbg("[%s] user std is 0, so set it to NTSC | M.\n", __func__); @@ -954,7 +1001,7 @@ static enum v4l2_search atvdemod_fe_search(struct v4l2_frontend *v4l2_fe) pr_dbg("[%s] slow mode to search the channel\n", __func__); afc_step = ATV_AFC_1_0MHZ; } else if (!slow_mode) { - afc_step = ATV_AFC_2_0MHZ; + afc_step = p->afc_range/* ATV_AFC_2_0MHZ */; } else { pr_dbg("[%s] slow mode to search the channel\n", __func__); afc_step = ATV_AFC_1_0MHZ; @@ -1059,23 +1106,15 @@ static enum v4l2_search atvdemod_fe_search(struct v4l2_frontend *v4l2_fe) pr_dbg("[%s] freq: [%d] pll lock success\n", __func__, p->frequency); -#if 0 /* In get_pll_status has line_lock check.*/ - if (fee->tuner->drv->id == AM_TUNER_MXL661) { - fe->ops.analog_ops.get_atv_status(fe, - &atv_status); - if (atv_status.atv_lock) - usleep_range(30 * 1000, - 30 * 1000 + 100); - } -#endif + ret = atvdemod_fe_afc_closer(v4l2_fe, minafcfreq, maxafcfreq + ATV_AFC_500KHZ, 1); if (ret == 0) { atvdemod_fe_try_analog_format(v4l2_fe, auto_search_std, - &std_bk, &audio); + &std_bk, &audio, &soundsys); - pr_dbg("[%s] freq:%d, std_bk:0x%x, audmode:0x%x, search OK.\n", + pr_info("[%s] freq:%d, std_bk:0x%x, audmode:0x%x, search OK.\n", __func__, p->frequency, (unsigned int) std_bk, audio); @@ -1084,6 +1123,7 @@ static enum v4l2_search atvdemod_fe_search(struct v4l2_frontend *v4l2_fe) p->std = std_bk; /*avoid std unenable */ p->frequency -= 1; + p->soundsys = soundsys; std_bk = 0; audio = 0; } @@ -1096,21 +1136,6 @@ static enum v4l2_search atvdemod_fe_search(struct v4l2_frontend *v4l2_fe) } } - /*avoid sound format is not match after search over */ - if (std_bk != 0 && audio != 0) { - p->std = std_bk; - p->audmode = audio; - - params.frequency = p->frequency; - params.mode = p->afc_range; - params.audmode = p->audmode; - params.std = p->std; - - fe->ops.analog_ops.set_params(fe, ¶ms); - std_bk = 0; - audio = 0; - } - pr_dbg("[%s] freq[analog.std:0x%08x] is[%d] unlock\n", __func__, (uint32_t) p->std, p->frequency); diff --git a/drivers/amlogic/atv_demod/atv_demod_ops.h b/drivers/amlogic/atv_demod/atv_demod_ops.h index 775c5ecf686b..8417722acdf9 100644 --- a/drivers/amlogic/atv_demod/atv_demod_ops.h +++ b/drivers/amlogic/atv_demod/atv_demod_ops.h @@ -49,6 +49,7 @@ struct atv_demod_sound_system { unsigned int audio_std; unsigned int input_mode; unsigned int output_mode; + int sif_over_modulation; }; struct atv_demod_priv { diff --git a/drivers/amlogic/atv_demod/atv_demod_v4l2.c b/drivers/amlogic/atv_demod/atv_demod_v4l2.c index beaad44f9670..7e4fb017c422 100644 --- a/drivers/amlogic/atv_demod/atv_demod_v4l2.c +++ b/drivers/amlogic/atv_demod/atv_demod_v4l2.c @@ -456,12 +456,11 @@ static int v4l2_frontend_read_status(struct v4l2_frontend *v4l2_fe, if (!status) return -1; -#if 0 - if (analog_ops->tuner_status) - analog_ops->tuner_status(&v4l2_fe->fe, status); + + if (analog_ops->has_signal) + analog_ops->has_signal(&v4l2_fe->fe, (u16 *) status); else if (tuner_ops->get_status) - tuner_ops->get_status(&v4l2_fe->fe, status); -#endif + tuner_ops->get_status(&v4l2_fe->fe, (u32 *) status); return ret; } @@ -494,7 +493,7 @@ static unsigned int v4l2_frontend_poll(struct file *filp, poll_wait(filp, &fepriv->events.wait_queue, pts); if (fepriv->events.eventw != fepriv->events.eventr) { - pr_dbg("%s: POLLIN | POLLRDNORM | POLLPRI.\n", __func__); + pr_dbg("%s: POLLIN | POLLRDNORM | POLLPRI.\n", __func__); return (POLLIN | POLLRDNORM | POLLPRI); } @@ -538,14 +537,21 @@ static int v4l2_property_process_set(struct v4l2_frontend *v4l2_fe, struct v4l2_property *tvp, struct file *file) { int r = 0; +#if 0 + int i = 0; + int id = 0; +#endif + struct v4l2_analog_parameters *params = &v4l2_fe->params; v4l2_property_dump(v4l2_fe, true, tvp); switch (tvp->cmd) { case V4L2_TUNE: + v4l2_set_frontend(v4l2_fe, params); break; case V4L2_SOUND_SYS: case V4L2_SLOW_SEARCH_MODE: + case V4L2_SIF_OVER_MODULATION: /* Allow the frontend to override outgoing properties */ if (v4l2_fe->ops.set_property) { r = v4l2_fe->ops.set_property(v4l2_fe, tvp); @@ -553,6 +559,59 @@ static int v4l2_property_process_set(struct v4l2_frontend *v4l2_fe, return r; } break; + case V4L2_FREQUENCY: + params->frequency = tvp->data; + break; + case V4L2_STD: + /* std & 0xFF000000: color std */ + /* std & 0x00FFFFFF: audio std */ + if (tvp->data & 0xFF000000) + params->std = (tvp->data & 0xFF000000); + if (tvp->data & 0x00FFFFFF) { + params->audmode = params->std & 0xFFFFFF; + params->std = (tvp->data & 0xFF000000) + | (params->audmode); + } + break; + case V4L2_FINE_TUNE: + params->frequency += tvp->data; + break; + case V4L2_TUNER_TYPE: +#if 0 /* This supports dynamically setting the tuner type */ + for (i = 0; i < amlatvdemod_devp->tuner_num; ++i) { + if (amlatvdemod_devp->tuners[i].cfg.id == tvp->data) { + id = amlatvdemod_devp->tuners[i].cfg.id; + break; + } + } + + if (id == 0) { + pr_err("%s: nonsupport tuner %d.\n", + __func__, tvp->data); + return -EINVAL; + } + + if (amlatvdemod_devp->tuner_cur == i) { + pr_err("%s: the same tuner %d.\n", + __func__, i); + break; + } + + if (amlatvdemod_devp->tuner_attached) { + if (v4l2_fe->fe.ops.tuner_ops.release) + v4l2_fe->fe.ops.tuner_ops.release(&v4l2_fe->fe); + } + + v4l2_fe->tuner_id = id; + if (aml_attach_tuner(amlatvdemod_devp) < 0) { + pr_err("%s: attach tuner %d error.\n", + __func__, id); + return -EINVAL; + } +#endif + break; + case V4L2_TUNER_IF_FREQ: + break; default: return -EINVAL; } @@ -564,6 +623,8 @@ static int v4l2_property_process_get(struct v4l2_frontend *v4l2_fe, struct v4l2_property *tvp, struct file *file) { int r = 0; + int i = 0; + struct v4l2_analog_parameters *params = &v4l2_fe->params; switch (tvp->cmd) { case V4L2_SOUND_SYS: @@ -575,7 +636,26 @@ static int v4l2_property_process_get(struct v4l2_frontend *v4l2_fe, return r; } break; - + case V4L2_FREQUENCY: + tvp->data = params->frequency; + break; + case V4L2_STD: + /* std & 0xFF000000: color std */ + /* std & 0x00FFFFFF: audio std */ + tvp->data = params->std; + break; + case V4L2_TUNER_TYPE: + i = amlatvdemod_devp->tuner_cur; + if (i < 0) { + pr_err("%s: Has not been set tuner type.\n", __func__); + tvp->data = 0; + return -EINVAL; + } + tvp->data = amlatvdemod_devp->tuners[i].cfg.id; + break; + case V4L2_TUNER_IF_FREQ: + tvp->data = amlatvdemod_devp->if_freq; + break; default: pr_dbg("%s: V4L2 property %d doesn't exist\n", __func__, tvp->cmd); @@ -587,7 +667,7 @@ static int v4l2_property_process_get(struct v4l2_frontend *v4l2_fe, return 0; } -static int v4l2_frontend_ioctl_properties(struct file *filp, +static long v4l2_frontend_ioctl_properties(struct file *filp, unsigned int cmd, void *parg) { struct v4l2_frontend *v4l2_fe = video_get_drvdata(video_devdata(filp)); @@ -740,11 +820,19 @@ static int v4l2_frontend_open(struct file *filp) struct v4l2_frontend_private *fepriv = v4l2_fe->frontend_priv; /* Because tuner ko insmod after demod, so need check */ - if (!amlatvdemod_devp->tuner_attached - || !amlatvdemod_devp->analog_attached) { - ret = aml_attach_demod_tuner(amlatvdemod_devp); + if (!amlatvdemod_devp->analog_attached) { + ret = aml_attach_demod(amlatvdemod_devp); if (ret < 0) { - pr_err("%s: attach demod or tuner %d error.\n", + pr_err("%s: attach demod %d error.\n", + __func__, v4l2_fe->tuner_id); + return -EBUSY; + } + } + + if (!amlatvdemod_devp->tuner_attached) { + ret = aml_attach_tuner(amlatvdemod_devp); + if (ret < 0) { + pr_err("%s: attach tuner %d error.\n", __func__, v4l2_fe->tuner_id); return -EBUSY; } diff --git a/drivers/amlogic/atv_demod/atv_demod_v4l2.h b/drivers/amlogic/atv_demod/atv_demod_v4l2.h index 0683c94878ec..6fc3078090e4 100644 --- a/drivers/amlogic/atv_demod/atv_demod_v4l2.h +++ b/drivers/amlogic/atv_demod/atv_demod_v4l2.h @@ -92,7 +92,12 @@ #define V4L2_TUNE 1 #define V4L2_SOUND_SYS 2 #define V4L2_SLOW_SEARCH_MODE 3 - +#define V4L2_FREQUENCY 4 +#define V4L2_STD 5 +#define V4L2_FINE_TUNE 6 +#define V4L2_SIF_OVER_MODULATION 7 +#define V4L2_TUNER_TYPE 8 +#define V4L2_TUNER_IF_FREQ 9 struct v4l2_frontend; diff --git a/drivers/amlogic/atv_demod/atvauddemod_func.c b/drivers/amlogic/atv_demod/atvauddemod_func.c index b787edccbbe5..889fc4469609 100644 --- a/drivers/amlogic/atv_demod/atvauddemod_func.c +++ b/drivers/amlogic/atv_demod/atvauddemod_func.c @@ -48,11 +48,24 @@ unsigned int audio_thd_threshold2 = 0xf00; unsigned int audio_a2_auto = 1; unsigned int audio_a2_power_threshold = 0x1800; +unsigned int audio_a2_carrier_report = 0xc00; + +static int last_nicam_lock = -1; +static int last_nicam_mono_flag = -1; +static int last_stereo_flag = -1; +static int last_dual_flag = -1; +static int last_sap_flag = -1; +static int last_mode = -1; #undef pr_info #define pr_info(args...)\ do {\ - if (ademod_debug_en)\ + if (ademod_debug_en & 0x1)\ + printk(args);\ + } while (0) +#define pr_carr(args...)\ + do {\ + if (ademod_debug_en & 0x2)\ printk(args);\ } while (0) #undef pr_dbg @@ -379,7 +392,9 @@ void set_a2k(void) adec_wr_reg(ADDR_LPR_GAIN_ADJ, 0x3e0); adec_wr_reg(ADDR_LPR_COMP_CTRL, 0x010); - adec_wr_reg(ADDR_IIR_SPEED_CTRL, 0xd65d7f7f); + adec_wr_reg(ADDR_IIR_SPEED_CTRL, 0xff5d7f7f/*0xd65d7f7f*/); + adec_wr_reg(STEREO_DET_THD, 0x4000); + adec_wr_reg(DUAL_DET_THD, 0x4000); adec_wr_reg((ADDR_SEL_CTRL), 0x1000); } @@ -415,7 +430,9 @@ void set_a2g(void) adec_wr_reg(ADDR_LPR_GAIN_ADJ, 0x3e0); adec_wr_reg(ADDR_LPR_COMP_CTRL, 0x010); - adec_wr_reg(ADDR_IIR_SPEED_CTRL, 0xd65d7f7f); + adec_wr_reg(ADDR_IIR_SPEED_CTRL, 0xff5d7f7f/*0xd65d7f7f*/); + adec_wr_reg(STEREO_DET_THD, 0x4000); + adec_wr_reg(DUAL_DET_THD, 0x4000); } void set_a2bg(void) @@ -449,7 +466,9 @@ void set_a2bg(void) adec_wr_reg(ADDR_LPR_GAIN_ADJ, 0x3e0); adec_wr_reg(ADDR_LPR_COMP_CTRL, 0x010); - adec_wr_reg(ADDR_IIR_SPEED_CTRL, 0xd65d7f7f); + adec_wr_reg(ADDR_IIR_SPEED_CTRL, 0xff5d7f7f/*0xd65d7f7f*/); + adec_wr_reg(STEREO_DET_THD, 0x4000); + adec_wr_reg(DUAL_DET_THD, 0x4000); } void set_a2dk1(void) @@ -483,7 +502,9 @@ void set_a2dk1(void) adec_wr_reg(ADDR_LPR_GAIN_ADJ, 0x3e0); adec_wr_reg(ADDR_LPR_COMP_CTRL, 0x010); - adec_wr_reg(ADDR_IIR_SPEED_CTRL, 0xd65d7f7f); + adec_wr_reg(ADDR_IIR_SPEED_CTRL, 0xff5d7f7f/*0xd65d7f7f*/); + adec_wr_reg(STEREO_DET_THD, 0x4000); + adec_wr_reg(DUAL_DET_THD, 0x4000); } void set_a2dk2(void) @@ -517,7 +538,9 @@ void set_a2dk2(void) adec_wr_reg(ADDR_LPR_GAIN_ADJ, 0x3e0); adec_wr_reg(ADDR_LPR_COMP_CTRL, 0x010); - adec_wr_reg(ADDR_IIR_SPEED_CTRL, 0xd65d7f7f); + adec_wr_reg(ADDR_IIR_SPEED_CTRL, 0xff5d7f7f/*0xd65d7f7f*/); + adec_wr_reg(STEREO_DET_THD, 0x4000); + adec_wr_reg(DUAL_DET_THD, 0x4000); } void set_a2dk3(void) @@ -551,7 +574,9 @@ void set_a2dk3(void) adec_wr_reg(ADDR_LPR_GAIN_ADJ, 0x3e0); adec_wr_reg(ADDR_LPR_COMP_CTRL, 0x010); - adec_wr_reg(ADDR_IIR_SPEED_CTRL, 0xd65d7f7f); + adec_wr_reg(ADDR_IIR_SPEED_CTRL, 0xff5d7f7f/*0xd65d7f7f*/); + adec_wr_reg(STEREO_DET_THD, 0x4000); + adec_wr_reg(DUAL_DET_THD, 0x4000); } void set_eiaj(void) @@ -710,6 +735,101 @@ void set_nicam_l(void) aa = (int)((FCLK-5.85e6)/FCLK*1024.0*1024.0*16.0); adec_wr_reg(0x110, aa); } + +void set_mono_m(void) +{ + int aa; + + adec_wr_reg(ADDR_ADEC_CTRL, 0x2); + + set_filter(filter_50k, ADDR_DDC_FIR0_COEF, 65); + set_filter(filter_50k, ADDR_DDC_FIR1_COEF, 65); + + aa = (int)(4.5e6/FCLK*1024.0*1024.0*8.0); + adec_wr_reg(ADDR_DDC_FREQ0, aa); + + set_lpf15k(); + set_deem(0); + + adec_wr_reg(ADDR_DEMOD_GAIN, 0x12); + + adec_wr_reg(ADDR_LPR_GAIN_ADJ, 0x200); + + adec_wr_reg((ADDR_SEL_CTRL), 0x1000); + + set_lpf15k(); + set_deem(0); +} + +void set_mono_dk(void) +{ + int aa; + + adec_wr_reg(ADDR_ADEC_CTRL, 0xa); + + set_filter(filter_100k, ADDR_DDC_FIR0_COEF, 65); + set_filter(filter_100k, ADDR_DDC_FIR1_COEF, 65); + + aa = (int)(6.5e6/FCLK*1024.0*1024.0*8.0); + adec_wr_reg(ADDR_DDC_FREQ0, aa); + + adec_wr_reg(ADDR_LPR_GAIN_ADJ, 0x200); + + set_deem(1); + set_lpf15k(); +} + +void set_mono_i(void) +{ + int aa; + + adec_wr_reg(ADDR_ADEC_CTRL, 0x7); + + set_filter(filter_100k, ADDR_DDC_FIR0_COEF, 65); + set_filter(filter_100k, ADDR_DDC_FIR1_COEF, 65); + + aa = (int)(6.0e6/FCLK*1024.0*1024.0*8.0); + adec_wr_reg(ADDR_DDC_FREQ0, aa); + adec_wr_reg(ADDR_LPR_GAIN_ADJ, 0x200); + + set_deem(1); + set_lpf15k(); +} + +void set_mono_bg(void) +{ + int aa; + + adec_wr_reg(ADDR_ADEC_CTRL, 0x8); + + set_filter(filter_100k, ADDR_DDC_FIR0_COEF, 65); + set_filter(filter_100k, ADDR_DDC_FIR1_COEF, 65); + + aa = (int)(5.5e6/FCLK*1024.0*1024.0*8.0); + adec_wr_reg(ADDR_DDC_FREQ0, aa); + adec_wr_reg(ADDR_LPR_GAIN_ADJ, 0x200); + + set_deem(1); + set_lpf15k(); +} + +void set_mono_l(void) +{ + int aa; + + adec_wr_reg(ADDR_ADEC_CTRL, 0x9); + + set_filter(filter_100k, ADDR_DDC_FIR0_COEF, 65); + set_filter(filter_100k, ADDR_DDC_FIR1_COEF, 65); + + aa = (int)(6.5e6/FCLK*1024.0*1024.0*8.0); + adec_wr_reg(ADDR_DDC_FREQ0, aa); + adec_wr_reg(ADDR_LPR_GAIN_ADJ, 0x200); + + set_deem(1); + set_lpf15k(); +} + static void set_standard(uint32_t standard) { pr_info("\n<<<<<<<<<<<<<<< start configure register\n"); @@ -759,6 +879,26 @@ static void set_standard(uint32_t standard) pr_info("<<<<<<<<<<<<<<< Set NICAM L and Test\n"); set_nicam_l(); break; + case AUDIO_STANDARD_MONO_M: + pr_info("<<<<<<<<<<<<<<< Set mono M and Test\n"); + set_mono_m(); + break; + case AUDIO_STANDARD_MONO_DK: + pr_info("<<<<<<<<<<<<<<< Set mono DK and Test\n"); + set_mono_dk(); + break; + case AUDIO_STANDARD_MONO_I: + pr_info("<<<<<<<<<<<<<<< Set mono I and Test\n"); + set_mono_i(); + break; + case AUDIO_STANDARD_MONO_BG: + pr_info("<<<<<<<<<<<<<<< Set mono BG and Test\n"); + set_mono_bg(); + break; + case AUDIO_STANDARD_MONO_L: + pr_info("<<<<<<<<<<<<<<< Set mono L and Test\n"); + set_mono_l(); + break; } pr_info("\n<<<<<<<<<<<<<<< configure register finished\n"); @@ -775,14 +915,16 @@ void update_car_power_measure(int *sc1_power, int *sc2_power) void update_a2_eiaj_mode(int auto_en, int *stereo_flag, int *dual_flag) { - uint32_t reg_value; - uint32_t stereo_power, dual_power; + uint32_t reg_value = 0; + uint32_t stereo_power = 0, dual_power = 0; msleep(a2_detect_delay); if (auto_en) { reg_value = adec_rd_reg(CARRIER_MAG_REPORT); - if (((reg_value >> 16) & 0xffff) < 0x400) { + pr_info("%s CARRIER_MAG_REPORT: 0x%x [threshold: 0x%x].\n", + __func__, reg_value, audio_a2_carrier_report); + if (((reg_value >> 16) & 0xffff) < audio_a2_carrier_report) { *stereo_flag = 0; *dual_flag = 0; } else { @@ -792,6 +934,8 @@ void update_a2_eiaj_mode(int auto_en, int *stereo_flag, int *dual_flag) } } else { reg_value = adec_rd_reg(POWER_REPORT); + pr_info("%s POWER_REPORT: 0x%x [threshold: 0x%x].\n", + __func__, reg_value, audio_a2_power_threshold); stereo_power = reg_value & 0xffff; dual_power = (reg_value >> 16) & 0xffff; @@ -885,7 +1029,7 @@ void set_btsc_outputmode(uint32_t outmode) uint32_t reg_value = 0; uint32_t tmp_value = 0, tmp_value1 = 0; int stereo_flag = 0, sap_flag = 0; - static int last_stereo_flag = -1, last_sap_flag = -1, last_mode = -1; + /*static int last_stereo_flag = -1,last_sap_flag = -1,last_mode = -1;*/ update_btsc_mode(1, &stereo_flag, &sap_flag); @@ -996,7 +1140,7 @@ void set_a2_eiaj_outputmode(uint32_t outmode) uint32_t reg_value = 0; uint32_t tmp_value = 0; int stereo_flag = 0, dual_flag = 0; - static int last_stereo_flag = -1, last_dual_flag = -1, last_mode = -1; + /*static int last_stereo_flag = -1,last_dual_flag = -1, last_mode=-1;*/ update_a2_eiaj_mode(audio_a2_auto, &stereo_flag, &dual_flag); @@ -1089,8 +1233,8 @@ void set_nicam_outputmode(uint32_t outmode) uint32_t tmp_value = 0; int nicam_mono_flag = 0, nicam_stereo_flag = 0, nicam_dual_flag = 0; int nicam_lock = 0; - static int last_nicam_lock = -1, last_nicam_mono_flag = -1; - static int last_stereo_flag = -1, last_dual_flag = -1, last_mode = -1; + /*static int last_nicam_lock = -1, last_nicam_mono_flag = -1;*/ + /*static int last_stereo_flag = -1,last_dual_flag = -1, last_mode=-1;*/ update_nicam_mode(&nicam_lock, &nicam_mono_flag, &nicam_stereo_flag, &nicam_dual_flag); @@ -1106,11 +1250,6 @@ void set_nicam_outputmode(uint32_t outmode) */ reg_value = adec_rd_reg(ADDR_ADEC_CTRL); - pr_info("# pll lock: 0x%lx.\n", - atv_dmd_rd_byte(APB_BLOCK_ADDR_CARR_RCVY, 0x43)&0x01); - pr_info("# line lock: 0x%lx.\n", - atv_dmd_rd_byte(APB_BLOCK_ADDR_VDAGC, 0x4f)&0x10); - pr_info("%s nicam_lock:%d, regval:0x%x, signal_mode:%d, outmode:%d\n", __func__, nicam_lock, reg_value, signal_audmode, outmode); @@ -1351,18 +1490,62 @@ void audio_thd_det(void) } } +void audio_carrier_offset_det(void) +{ + unsigned int carrier_freq = 0, report = 0; + int threshold = 0; + + report = adec_rd_reg(DC_REPORT); + carrier_freq = adec_rd_reg(ADDR_DDC_FREQ0); + + pr_carr("\n\nreport: 0x%x.\n", report); + pr_carr("read carrier_freq: 0x%x.\n", carrier_freq); + report = report & 0xFFFF; + + if (report > (1 << 15)) + threshold = report - (1 << 16); + else + threshold = report; + + threshold = threshold >> 8; + pr_carr("threshold: %d.\n", threshold); + + if (threshold > 30) { + carrier_freq = carrier_freq - 0x100; + adec_wr_reg(ADDR_DDC_FREQ0, carrier_freq); + } else if (threshold < -30) { + carrier_freq = carrier_freq + 0x100; + adec_wr_reg(ADDR_DDC_FREQ0, carrier_freq); + } + + pr_carr("write carrier_freq: 0x%x.\n", carrier_freq); +} + +void set_outputmode_status_init(void) +{ + last_nicam_lock = -1; + last_nicam_mono_flag = -1; + last_stereo_flag = -1; + last_dual_flag = -1; + last_sap_flag = -1; + last_mode = -1; +} + void set_output_left_right_exchange(unsigned int ch) { unsigned int read = 0; - if (amlatvdemod_devp->audio_demod_reg_base == NULL) - return; + atvaudio_ctrl_read(&read); - read = readl(amlatvdemod_devp->audio_demod_reg_base); - - if ((read & (1 << 2)) != ((ch & 0x01) << 2)) - writel((read & ~(1 << 2)) | ((ch & 0x01) << 2), - amlatvdemod_devp->audio_demod_reg_base); + if (is_meson_tl1_cpu()) { /* bit[19] */ + if ((read & (1 << 19)) != ((ch & 0x01) << 19)) + atvaudio_ctrl_write((read & ~(1 << 19)) | + ((ch & 0x01) << 19)); + } else { /* bit[2] */ + if ((read & (1 << 2)) != ((ch & 0x01) << 2)) + atvaudio_ctrl_write((read & ~(1 << 2)) | + ((ch & 0x01) << 2)); + } } #endif /* __ATVAUDDEMOD_FUN_H */ diff --git a/drivers/amlogic/atv_demod/atvauddemod_func.h b/drivers/amlogic/atv_demod/atvauddemod_func.h index fcdb246b7f2d..c71037ffd6cd 100644 --- a/drivers/amlogic/atv_demod/atvauddemod_func.h +++ b/drivers/amlogic/atv_demod/atvauddemod_func.h @@ -32,6 +32,7 @@ void configure_adec(int Audio_mode); void adec_soft_reset(void); void audio_thd_init(void); void audio_thd_det(void); +void audio_carrier_offset_det(void); void set_nicam_outputmode(uint32_t outmode); void set_a2_eiaj_outputmode(uint32_t outmode); void set_btsc_outputmode(uint32_t outmode); @@ -39,6 +40,7 @@ void update_nicam_mode(int *nicam_flag, int *nicam_mono_flag, int *nicam_stereo_flag, int *nicam_dual_flag); void update_btsc_mode(int auto_en, int *stereo_flag, int *sap_flag); void update_a2_eiaj_mode(int auto_en, int *stereo_flag, int *dual_flag); +void set_outputmode_status_init(void); void set_output_left_right_exchange(unsigned int ch); diff --git a/drivers/amlogic/atv_demod/atvdemod_func.c b/drivers/amlogic/atv_demod/atvdemod_func.c index 286c16185e54..c22a63b4c423 100644 --- a/drivers/amlogic/atv_demod/atvdemod_func.c +++ b/drivers/amlogic/atv_demod/atvdemod_func.c @@ -40,6 +40,8 @@ unsigned int broad_std = AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC; unsigned int aud_std = AUDIO_STANDARD_NICAM_DK; unsigned int aud_mode = AUDIO_OUTMODE_STEREO; bool aud_auto = true; +bool aud_reinit; +bool aud_mono_only; unsigned long over_threshold = 0xffff; unsigned long input_amplitude = 0xffff; @@ -57,13 +59,14 @@ int sum2_thd_h; int sum2_thd_l = 0x7fffffff; unsigned int atv_video_gain; -unsigned int carrier_amplif_val = 0xc030901; +unsigned int carrier_amplif_val = 0xc010301;/*0xc030901;*/ unsigned int extra_input_fil_val = 0x1030501; bool aud_dmd_jilinTV; unsigned int if_freq = 4250000; /*PAL-DK:3250000;NTSC-M:4250000*/ unsigned int if_inv; int afc_default = CARR_AFC_DEFAULT_VAL; +int snr_threshold = 30; /* @@ -96,6 +99,9 @@ unsigned int audio_a2_threshold = 0x800; unsigned int audio_a2_delay = 10; unsigned int audio_nicam_delay = 100; +unsigned int audio_atv_ov; +unsigned int audio_atv_ov_flag; + enum AUDIO_SCAN_ID { ID_PAL_I = 0, ID_PAL_M, @@ -182,6 +188,8 @@ void power_on_receiver(void) void atv_dmd_misc(void) { + unsigned int reg = 0; + if (broad_std == AML_ATV_DEMOD_VIDEO_MODE_PROP_SECAM_L) { pr_info("broad_std is SECAM_L, no need config misc\n"); return; @@ -190,12 +198,15 @@ void atv_dmd_misc(void) atv_dmd_wr_byte(APB_BLOCK_ADDR_AGC_PWM, 0x08, 0x38); /*zhuangwei*/ /*cpu.write_byte(8'h1A,8'h0E,8'h06);//zhuangwei*/ /*cpu.write_byte(8'h19,8'h01,8'h7f);//zhuangwei*/ - atv_dmd_wr_byte(0x0f, 0x45, 0x90); /*zhuangwei*/ + atv_dmd_wr_byte(APB_BLOCK_ADDR_VDAGC, 0x45, 0x90); /*zhuangwei*/ - atv_dmd_wr_long(0x0f, 0x44, 0x5c8808c1);/*zhuangwei*/ - if (amlatvdemod_devp->tuner_id == AM_TUNER_R840 || - amlatvdemod_devp->tuner_id == AM_TUNER_R842) { - atv_dmd_wr_long(0x0f, 0x3c, reg_23cf);/*zhuangwei*/ + atv_dmd_wr_long(APB_BLOCK_ADDR_VDAGC, 0x44, 0x5c8808c1);/*zhuangwei*/ + if (amlatvdemod_devp->tuners[amlatvdemod_devp->tuner_cur].cfg.id + == AM_TUNER_R840 || + amlatvdemod_devp->tuners[amlatvdemod_devp->tuner_cur].cfg.id + == AM_TUNER_R842) { + /*zhuangwei*/ + atv_dmd_wr_long(APB_BLOCK_ADDR_VDAGC, 0x3c, reg_23cf); /*guanzhong@20150804a*/ atv_dmd_wr_byte(APB_BLOCK_ADDR_SIF_STG_2, 0x00, 0x1); if (is_meson_txhd_cpu()) { @@ -216,51 +227,114 @@ void atv_dmd_misc(void) /*dezhi@20150610a 0x1a maybe better?!*/ /* atv_dmd_wr_byte(APB_BLOCK_ADDR_AGC_PWM, 0x09, 0x19); */ } else { - atv_dmd_wr_long(0x0f, 0x3c, 0x88188832);/*zhuangwei*/ + /*zhuangwei*/ + atv_dmd_wr_long(APB_BLOCK_ADDR_VDAGC, 0x3c, 0x88188832); atv_dmd_wr_long(APB_BLOCK_ADDR_AGC_PWM, 0x08, 0x46170200); } - if (amlatvdemod_devp->tuner_id == AM_TUNER_MXL661) { - atv_dmd_wr_long(0x0c, 0x04, 0xbffa0000) ;/*test in sky*/ - atv_dmd_wr_long(0x0c, 0x00, 0x6f4000);/*test in sky*/ + if (amlatvdemod_devp->tuners[amlatvdemod_devp->tuner_cur].cfg.id + == AM_TUNER_MXL661) { + /*test in sky*/ + atv_dmd_wr_long(APB_BLOCK_ADDR_DAC_UPS, 0x04, 0xbffa0000); + atv_dmd_wr_long(APB_BLOCK_ADDR_DAC_UPS, 0x00, 0x6f4000); /*guanzhong@20151013 fix nonstd def is:0x0c010301;0x0c020601*/ - atv_dmd_wr_long(APB_BLOCK_ADDR_CARR_RCVY, 0x24, 0x0c030901); + atv_dmd_wr_long(APB_BLOCK_ADDR_CARR_RCVY, 0x24, 0xc030901); } else { /*zhuangwei 0xdafa0000*/ - atv_dmd_wr_long(0x0c, 0x04, 0xc8fa0000); - atv_dmd_wr_long(0x0c, 0x00, 0x554000);/*zhuangwei*/ + atv_dmd_wr_long(APB_BLOCK_ADDR_DAC_UPS, 0x04, 0xc8fa0000); + atv_dmd_wr_long(APB_BLOCK_ADDR_DAC_UPS, 0x00, 0x554000); } - atv_dmd_wr_long(0x19, 0x04, 0xdafa0000);/*zhuangwei*/ - atv_dmd_wr_long(0x19, 0x00, 0x4a4000);/*zhuangwei*/ - /*atv_dmd_wr_byte(0x0c,0x01,0x28);//pwd-out gain*/ - /*atv_dmd_wr_byte(0x0c,0x04,0xc0);//pwd-out offset*/ + /*zhuangwei*/ + atv_dmd_wr_long(APB_BLOCK_ADDR_DAC_UPS_24M, 0x04, 0xdafa0000); + atv_dmd_wr_long(APB_BLOCK_ADDR_DAC_UPS_24M, 0x00, 0x4a4000); + /*atv_dmd_wr_byte(APB_BLOCK_ADDR_DAC_UPS, 0x01, 0x28);//pwd-out gain*/ + /*atv_dmd_wr_byte(APB_BLOCK_ADDR_DAC_UPS, 0x04, 0xc0);//pwd-out offset*/ aml_audio_valume_gain_set(audio_gain_val); /* 20160121 fix audio demodulation over */ - atv_dmd_wr_long(0x09, 0x00, 0x1030501); - atv_dmd_wr_long(0x09, 0x04, 0x1900000); + atv_dmd_wr_long(APB_BLOCK_ADDR_SIF_STG_2, 0x00, 0x1030501); + atv_dmd_wr_long(APB_BLOCK_ADDR_SIF_STG_2, 0x04, 0x1900000); + atv_dmd_wr_long(APB_BLOCK_ADDR_VDAGC, 0x0c, 0x367C0831); if (aud_dmd_jilinTV) - atv_dmd_wr_long(0x09, 0x00, 0x2030503); + atv_dmd_wr_long(APB_BLOCK_ADDR_SIF_STG_2, 0x00, 0x2030503); if (non_std_en == 1) { - atv_dmd_wr_long(0x09, 0x00, 0x2030503); - atv_dmd_wr_long(0x0f, 0x44, 0x7c8808c1); - atv_dmd_wr_long(APB_BLOCK_ADDR_CARR_RCVY, 0x24, 0x0c010801); + atv_dmd_wr_long(APB_BLOCK_ADDR_SIF_STG_2, 0x00, 0x2030503); + atv_dmd_wr_long(APB_BLOCK_ADDR_VDAGC, 0x44, 0x7c8808c1); + atv_dmd_wr_long(APB_BLOCK_ADDR_CARR_RCVY, 0x24, 0xc010801); } else if (non_std_en == 2) { /* fix vsync signal is too weak */ - atv_dmd_wr_long(0x09, 0x00, 0x1030501); - atv_dmd_wr_long(0x0f, 0x44, 0x8c0808c1); - atv_dmd_wr_long(0x0f, 0x0c, 0x387c0831); + atv_dmd_wr_long(APB_BLOCK_ADDR_SIF_STG_2, 0x00, 0x1030501); + atv_dmd_wr_long(APB_BLOCK_ADDR_VDAGC, 0x44, 0x8c0808c1); + atv_dmd_wr_long(APB_BLOCK_ADDR_VDAGC, 0x0c, 0x387c0831); atv_dmd_wr_long(APB_BLOCK_ADDR_CARR_RCVY, 0x24, 0xc030901); + } else if (non_std_en == 3) { /* for Hisence */ + atv_dmd_wr_long(APB_BLOCK_ADDR_SIF_STG_2, 0x00, 0x1030501); + atv_dmd_wr_long(APB_BLOCK_ADDR_VDAGC, 0x44, 0x8c0808c1); + atv_dmd_wr_long(APB_BLOCK_ADDR_VDAGC, 0x0c, 0x387c0831); + atv_dmd_wr_long(APB_BLOCK_ADDR_CARR_RCVY, 0x24, 0xc020901); } else { - atv_dmd_wr_long(0x09, 0x00, extra_input_fil_val); + atv_dmd_wr_long(APB_BLOCK_ADDR_SIF_STG_2, 0x00, + extra_input_fil_val); if (atv_video_gain) - atv_dmd_wr_long(0x0f, 0x44, atv_video_gain); + atv_dmd_wr_long(APB_BLOCK_ADDR_VDAGC, 0x44, + atv_video_gain); else - atv_dmd_wr_long(0x0f, 0x44, 0xfc0808c1); + atv_dmd_wr_long(APB_BLOCK_ADDR_VDAGC, 0x44, 0xfc0808c1); atv_dmd_wr_long(APB_BLOCK_ADDR_CARR_RCVY, 0x24, carrier_amplif_val); } + if (audio_atv_ov) { + atv_dmd_wr_long(APB_BLOCK_ADDR_SIF_STG_2, + 0x14, 0x8000015); + atv_dmd_wr_long(APB_BLOCK_ADDR_SIF_STG_2, + 0x18, 0x7ffff); + atv_dmd_wr_long(APB_BLOCK_ADDR_SIF_STG_2, + 0x1c, 0x0f000); + atvaudio_ctrl_read(®); + if (is_meson_tl1_cpu()) + atvaudio_ctrl_write(reg & (~0x100000));/* bit20 */ + else + atvaudio_ctrl_write(reg & (~0x3));/* bit[1-0] */ + audio_atv_ov_flag = 1; + } else { + atv_dmd_wr_long(APB_BLOCK_ADDR_SIF_STG_2, + 0x14, 0xf400000); + atv_dmd_wr_long(APB_BLOCK_ADDR_SIF_STG_2, + 0x18, 0xc000); + atv_dmd_wr_long(APB_BLOCK_ADDR_SIF_STG_2, + 0x1c, 0x1f000); + atvaudio_ctrl_read(®); + if (is_meson_tl1_cpu()) + atvaudio_ctrl_write(reg | 0x100000);/* bit20 */ + else + atvaudio_ctrl_write(reg | 0x3);/* bit[1-0] */ + audio_atv_ov_flag = 0; + } +} + +void atv_dmd_ring_filter(bool on) +{ + if (!is_meson_tl1_cpu()) + return; + + if (on) { + atv_dmd_wr_long(APB_BLOCK_ADDR_GDE_EQUAL, 0x10, 0x8274bf); + atv_dmd_wr_long(APB_BLOCK_ADDR_GDE_EQUAL, 0x14, 0x1d175c); + atv_dmd_wr_long(APB_BLOCK_ADDR_GDE_EQUAL, 0x18, 0x2aa526); + atv_dmd_wr_long(APB_BLOCK_ADDR_GDE_EQUAL, 0x1c, 0x1d175c); + atv_dmd_wr_long(APB_BLOCK_ADDR_GDE_EQUAL, 0x20, 0x2d19e4); + atv_dmd_wr_long(APB_BLOCK_ADDR_GDE_EQUAL, 0x24, 0x8274bf); + atv_dmd_wr_long(APB_BLOCK_ADDR_GDE_EQUAL, 0x28, 0x1d175c); + atv_dmd_wr_long(APB_BLOCK_ADDR_GDE_EQUAL, 0x2c, 0x2aa526); + atv_dmd_wr_long(APB_BLOCK_ADDR_GDE_EQUAL, 0x30, 0x1d175c); + atv_dmd_wr_long(APB_BLOCK_ADDR_GDE_EQUAL, 0x34, 0x2d19e4); + + atv_dmd_wr_long(APB_BLOCK_ADDR_GDE_EQUAL, 0x4c, 0x1); + } else + atv_dmd_wr_long(APB_BLOCK_ADDR_GDE_EQUAL, 0x4c, 0x0); + + pr_dbg("%s do atv_dmd_ring_filter %d ...\n", __func__, on); } void atv_dmd_non_std_set(bool enable) @@ -484,14 +558,15 @@ void configure_receiver(int Broadcast_Standard, unsigned int Tuner_IF_Frequency, int gd_coeff[6] = { 0 }; int gd_bypass = 0; - pr_info("ATV-DMD configure receiver register\n"); + pr_dbg("ATV-DMD configure receiver register\n"); if ((Broadcast_Standard == AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC) || (Broadcast_Standard == AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC_J) || (Broadcast_Standard == AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_M) || (Broadcast_Standard == AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC_DK) || (Broadcast_Standard == AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC_BG) || - (Broadcast_Standard == AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC_I)) { + (Broadcast_Standard == AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC_I) || + (Broadcast_Standard == AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC_M)) { gp_coeff_1[0] = 0x57777; gp_coeff_1[1] = 0xdd777; gp_coeff_1[2] = 0x7d777; @@ -900,7 +975,7 @@ void configure_receiver(int Broadcast_Standard, unsigned int Tuner_IF_Frequency, } sif_fm_gain -= 2; /*avoid sound overflow@guanzhong*/ /*FE PATH*/ - pr_info("ATV-DMD configure mixer\n"); + pr_dbg("ATV-DMD configure mixer\n"); if (Broadcast_Standard == AML_ATV_DEMOD_VIDEO_MODE_PROP_DTV) { tmp_int = (Tuner_IF_Frequency/125000); if (Tuner_Input_IF_inverted == 0x0) @@ -912,19 +987,19 @@ void configure_receiver(int Broadcast_Standard, unsigned int Tuner_IF_Frequency, mixer3_bypass = 0; } else { tmp_int = (Tuner_IF_Frequency/125000); - pr_info("ATV-DMD configure mixer 1\n"); + pr_dbg("ATV-DMD configure mixer 1\n"); if (Tuner_Input_IF_inverted == 0x0) mixer1 = 0xe8 - tmp_int; else mixer1 = tmp_int - 0x18; - pr_info("ATV-DMD configure mixer 2\n"); + pr_dbg("ATV-DMD configure mixer 2\n"); mixer3 = 0x30; mixer3_bypass = 0x1; } - pr_info("ATV-DMD configure mixer 3\n"); + pr_dbg("ATV-DMD configure mixer 3\n"); atv_dmd_wr_byte(APB_BLOCK_ADDR_MIXER_1, 0x0, mixer1); atv_dmd_wr_word(APB_BLOCK_ADDR_MIXER_3, 0x0, (((mixer3 & 0xff) << 8) | (mixer3_bypass & 0xff))); @@ -933,14 +1008,16 @@ void configure_receiver(int Broadcast_Standard, unsigned int Tuner_IF_Frequency, atv_dmd_wr_long(APB_BLOCK_ADDR_ADC_SE, 0x0, 0x03180e0f); else atv_dmd_wr_long(APB_BLOCK_ADDR_ADC_SE, 0x0, 0x03150e0f); - if (amlatvdemod_devp->tuner_id == AM_TUNER_R840 || - amlatvdemod_devp->tuner_id == AM_TUNER_R842) { + if (amlatvdemod_devp->tuners[amlatvdemod_devp->tuner_cur].cfg.id + == AM_TUNER_R840 || + amlatvdemod_devp->tuners[amlatvdemod_devp->tuner_cur].cfg.id + == AM_TUNER_R842) { /*config pwm for tuner r840*/ atv_dmd_wr_byte(APB_BLOCK_ADDR_ADC_SE, 1, 0xf); } /*GP Filter*/ - pr_info("ATV-DMD configure GP_filter\n"); + pr_dbg("ATV-DMD configure GP_filter\n"); if (Broadcast_Standard == AML_ATV_DEMOD_VIDEO_MODE_PROP_DTV) { cv = gp_cv_g1; atv_dmd_wr_long(APB_BLOCK_ADDR_GP_VD_FLT, 0x0, @@ -1051,7 +1128,7 @@ void configure_receiver(int Broadcast_Standard, unsigned int Tuner_IF_Frequency, } /*CRVY*/ - pr_info("ATV-DMD configure CRVY\n"); + pr_dbg("ATV-DMD configure CRVY\n"); if (Broadcast_Standard == AML_ATV_DEMOD_VIDEO_MODE_PROP_DTV) { crvy_reg_1 = 0xFF; crvy_reg_2 = 0x00; @@ -1061,12 +1138,12 @@ void configure_receiver(int Broadcast_Standard, unsigned int Tuner_IF_Frequency, } atv_dmd_wr_byte(APB_BLOCK_ADDR_CARR_RCVY, 0x29, crvy_reg_1); - pr_info("ATV-DMD configure rcvy 2\n"); - pr_info("ATV-DMD configure rcvy, crvy_reg_2 = %x\n", crvy_reg_2); + pr_dbg("ATV-DMD configure rcvy 2\n"); + pr_dbg("ATV-DMD configure rcvy, crvy_reg_2 = %x\n", crvy_reg_2); atv_dmd_wr_byte(APB_BLOCK_ADDR_CARR_RCVY, 0x20, crvy_reg_2); /*SOUND SUPPRESS*/ - pr_info("ATV-DMD configure sound suppress\n"); + pr_dbg("ATV-DMD configure sound suppress\n"); if ((Broadcast_Standard == AML_ATV_DEMOD_VIDEO_MODE_PROP_DTV) || (sound_format == 0)) @@ -1075,7 +1152,7 @@ void configure_receiver(int Broadcast_Standard, unsigned int Tuner_IF_Frequency, atv_dmd_wr_byte(APB_BLOCK_ADDR_SIF_VD_IF, 0x02, 0x00); /*SIF*/ - pr_info("ATV-DMD configure sif\n"); + pr_dbg("ATV-DMD configure sif\n"); if (!(Broadcast_Standard == AML_ATV_DEMOD_VIDEO_MODE_PROP_DTV)) { atv_dmd_wr_byte(APB_BLOCK_ADDR_SIF_IC_STD, 0x03, sif_ic_bw); atv_dmd_wr_byte(APB_BLOCK_ADDR_SIF_IC_STD, 0x01, sif_fi_mx); @@ -1119,7 +1196,7 @@ void configure_receiver(int Broadcast_Standard, unsigned int Tuner_IF_Frequency, } /*VAGC*/ - pr_info("ATV-DMD configure vagc\n"); + pr_dbg("ATV-DMD configure vagc\n"); atv_dmd_wr_long(APB_BLOCK_ADDR_VDAGC, 0x48, 0x9B6F2C00); /*bw select mode*/ atv_dmd_wr_byte(APB_BLOCK_ADDR_VDAGC, 0x37, 0x1C); @@ -1149,7 +1226,7 @@ void configure_receiver(int Broadcast_Standard, unsigned int Tuner_IF_Frequency, atv_dmd_wr_byte(APB_BLOCK_ADDR_VDAGC, 0x12, (freq_hz_cvrt & 0xff)); /*OUTPUT STAGE*/ - pr_info("ATV-DMD configure output stage\n"); + pr_dbg("ATV-DMD configure output stage\n"); if (Broadcast_Standard != AML_ATV_DEMOD_VIDEO_MODE_PROP_DTV) { atv_dmd_wr_byte(APB_BLOCK_ADDR_DAC_UPS, 0x0, 0x00); atv_dmd_wr_byte(APB_BLOCK_ADDR_DAC_UPS, 0x1, 0x40); @@ -1159,7 +1236,7 @@ void configure_receiver(int Broadcast_Standard, unsigned int Tuner_IF_Frequency, } /*GDE FILTER*/ - pr_info("ATV-DMD configure gde filter\n"); + pr_dbg("ATV-DMD configure gde filter\n"); if (GDE_Curve == 0) { gd_coeff[0] = 0x020; /*12'sd32;*/ gd_coeff[1] = 0xf5f; /*-12'sd161;*/ @@ -1206,13 +1283,15 @@ void configure_receiver(int Broadcast_Standard, unsigned int Tuner_IF_Frequency, } /*PWM*/ - pr_info("ATV-DMD configure pwm\n"); + pr_dbg("ATV-DMD configure pwm\n"); atv_dmd_wr_long(APB_BLOCK_ADDR_AGC_PWM, 0x00, 0x1f40); /*4KHz*/ atv_dmd_wr_long(APB_BLOCK_ADDR_AGC_PWM, 0x04, 0xc8); /*26 dB dynamic range*/ atv_dmd_wr_byte(APB_BLOCK_ADDR_AGC_PWM, 0x09, 0xa); - if (amlatvdemod_devp->tuner_id == AM_TUNER_R840 || - amlatvdemod_devp->tuner_id == AM_TUNER_R842) { + if (amlatvdemod_devp->tuners[amlatvdemod_devp->tuner_cur].cfg.id + == AM_TUNER_R840 || + amlatvdemod_devp->tuners[amlatvdemod_devp->tuner_cur].cfg.id + == AM_TUNER_R842) { /*config pwm for tuner r840*/ atv_dmd_wr_long(APB_BLOCK_ADDR_AGC_PWM, 0, 0xc80); /* guanzhong for Tuner AGC shock */ @@ -1290,7 +1369,7 @@ int retrieve_vpll_carrier_afc(void) if ((pll_lock == 1) || (line_lock == 0x10)) { /*if pll unlock, afc is invalid*/ - pr_info("[afc invalid] pll: %d, line: %d, line_strong: %d, field: %d.\n", + pr_dbg("[afc invalid] pll: %d, line: %d, line_strong: %d, field: %d.\n", pll_lock, line_lock, line_lock_strong, field_lock); @@ -1601,18 +1680,31 @@ int amlfmt_aud_standard(int broad_std) int std = 0; int nicam_lock = 0; uint32_t reg_value = 0; + int vpll_lock = 0, line_lock = 0; switch (broad_std) { case AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_M: case AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC: + if (aud_mono_only) { + std = AUDIO_STANDARD_MONO_M; + aud_mode = AUDIO_OUTMODE_MONO; + configure_adec(std); + adec_soft_reset(); + break; + } + std = AUDIO_STANDARD_A2_K; configure_adec(std); adec_soft_reset(); msleep(audio_a2_delay); + retrieve_vpll_carrier_lock(&vpll_lock); + retrieve_vpll_carrier_line_lock(&line_lock); + /* maybe need wait */ reg_value = adec_rd_reg(CARRIER_MAG_REPORT); - pr_info("\n%s 0x%x\n", __func__, (reg_value>>16)&0xffff); + pr_info("\n%s CARRIER_MAG_REPORT: 0x%x\n", + __func__, (reg_value >> 16) & 0xffff); if (((reg_value>>16)&0xffff) > audio_a2_threshold) { std = AUDIO_STANDARD_A2_K; if (amlatvdemod_devp->soundsys == 0xFF) @@ -1630,23 +1722,40 @@ int amlfmt_aud_standard(int broad_std) } break; case AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC_J: + if (aud_mono_only) { + std = AUDIO_STANDARD_MONO_M; + aud_mode = AUDIO_OUTMODE_MONO; + configure_adec(std); + adec_soft_reset(); + break; + } + std = AUDIO_STANDARD_EIAJ; configure_adec(std); adec_soft_reset(); break; case AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_BG: + if (aud_mono_only) { + std = AUDIO_STANDARD_MONO_BG; + aud_mode = AUDIO_OUTMODE_MONO; + configure_adec(std); + adec_soft_reset(); + break; + } + std = AUDIO_STANDARD_NICAM_BG; configure_adec(std); adec_soft_reset(); msleep(audio_nicam_delay); /* need wait */ - pr_info("pll lock: 0x%lx.\n", - atv_dmd_rd_byte(0x06, 0x43) & 0x01); - pr_info("line lock: 0x%lx.\n", - atv_dmd_rd_byte(0x0f, 0x4f) & 0x10); + + retrieve_vpll_carrier_lock(&vpll_lock); + retrieve_vpll_carrier_line_lock(&line_lock); + reg_value = adec_rd_reg(NICAM_LEVEL_REPORT); - nicam_lock = (reg_value>>28)&1; - pr_info("\n%s 0x%x\n", __func__, reg_value); + nicam_lock = (reg_value >> 28) & 1; + pr_info("\n%s NICAM_LEVEL_REPORT: 0x%x\n", + __func__, reg_value); if (nicam_lock) { std = AUDIO_STANDARD_NICAM_BG; if (amlatvdemod_devp->soundsys == 0xFF) @@ -1664,18 +1773,27 @@ int amlfmt_aud_standard(int broad_std) } break; case AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_DK: + if (aud_mono_only) { + std = AUDIO_STANDARD_MONO_DK; + aud_mode = AUDIO_OUTMODE_MONO; + configure_adec(std); + adec_soft_reset(); + break; + } + std = AUDIO_STANDARD_NICAM_DK; configure_adec(std); adec_soft_reset(); mdelay(audio_nicam_delay); /* need wait */ - pr_info("pll lock: 0x%lx.\n", - atv_dmd_rd_byte(0x06, 0x43) & 0x01); - pr_info("line lock: 0x%lx.\n", - atv_dmd_rd_byte(0x0f, 0x4f) & 0x10); + + retrieve_vpll_carrier_lock(&vpll_lock); + retrieve_vpll_carrier_line_lock(&line_lock); + reg_value = adec_rd_reg(NICAM_LEVEL_REPORT); - nicam_lock = (reg_value>>28)&1; - pr_info("\n%s 0x%x\n", __func__, reg_value); + nicam_lock = (reg_value >> 28) & 1; + pr_info("\n%s NICAM_LEVEL_REPORT: 0x%x\n", + __func__, reg_value); if (nicam_lock) { std = AUDIO_STANDARD_NICAM_DK; if (amlatvdemod_devp->soundsys == 0xFF) @@ -1693,17 +1811,87 @@ int amlfmt_aud_standard(int broad_std) } break; case AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_I: + if (aud_mono_only) { + std = AUDIO_STANDARD_MONO_I; + aud_mode = AUDIO_OUTMODE_MONO; + configure_adec(std); + adec_soft_reset(); + break; + } + std = AUDIO_STANDARD_NICAM_I; configure_adec(std); adec_soft_reset(); + msleep(audio_nicam_delay); + /* need wait */ + + retrieve_vpll_carrier_lock(&vpll_lock); + retrieve_vpll_carrier_line_lock(&line_lock); + + reg_value = adec_rd_reg(NICAM_LEVEL_REPORT); + nicam_lock = (reg_value >> 28) & 1; + pr_info("\n%s NICAM_LEVEL_REPORT: 0x%x\n", + __func__, reg_value); + if (nicam_lock) { + std = AUDIO_STANDARD_NICAM_I; + if (amlatvdemod_devp->soundsys == 0xFF) + aud_mode = AUDIO_OUTMODE_NICAM_STEREO; + else + aud_mode = amlatvdemod_devp->soundsys; + } else { + std = AUDIO_STANDARD_MONO_I; + aud_mode = AUDIO_OUTMODE_MONO; + configure_adec(std); + adec_soft_reset(); + } break; case AML_ATV_DEMOD_VIDEO_MODE_PROP_SECAM_L: + if (aud_mono_only) { + std = AUDIO_STANDARD_MONO_L; + aud_mode = AUDIO_OUTMODE_MONO; + configure_adec(std); + adec_soft_reset(); + break; + } + std = AUDIO_STANDARD_NICAM_L; configure_adec(std); adec_soft_reset(); + msleep(audio_nicam_delay); + /* need wait */ + + retrieve_vpll_carrier_lock(&vpll_lock); + retrieve_vpll_carrier_line_lock(&line_lock); + + reg_value = adec_rd_reg(NICAM_LEVEL_REPORT); + nicam_lock = (reg_value >> 28) & 1; + pr_info("\n%s NICAM_LEVEL_REPORT: 0x%x\n", + __func__, reg_value); + if (nicam_lock) { + std = AUDIO_STANDARD_NICAM_L; + if (amlatvdemod_devp->soundsys == 0xFF) + aud_mode = AUDIO_OUTMODE_NICAM_STEREO; + else + aud_mode = amlatvdemod_devp->soundsys; + } else { + std = AUDIO_STANDARD_MONO_L; + aud_mode = AUDIO_OUTMODE_MONO; + configure_adec(std); + adec_soft_reset(); + } break; } - pr_err("%s detect aud std:%d\n", __func__, std); + + if ((vpll_lock == 0) && (line_lock == 0)) { + aud_reinit = false; + } else { + aud_reinit = true; + pr_err("pll lock: 0x%x, line lock: 0x%x.\n", + vpll_lock, line_lock); + } + + pr_err("%s detect aud std:%d, aud_reinit:%d.\n", __func__, + std, aud_reinit); return std; } @@ -1715,8 +1903,11 @@ int atvauddemod_init(void) if (aud_auto) aud_std = amlfmt_aud_standard(broad_std); - /* configure_adec(aud_std); */ - /* adec_soft_reset(); */ + else { + configure_adec(aud_std); + adec_soft_reset(); + } + set_outputmode_status_init(); set_outputmode(aud_std, aud_mode); } else { /* for non support adec */ @@ -1729,21 +1920,33 @@ int atvauddemod_init(void) void atvauddemod_set_outputmode(void) { - set_outputmode(aud_std, aud_mode); + if (is_meson_txlx_cpu() || is_meson_txhd_cpu() || is_meson_tl1_cpu()) { + if (aud_reinit) { + /* before maybe need check afc status */ + atvauddemod_init(); + } else + set_outputmode(aud_std, aud_mode); + } } -int atvdemod_init(void) +int atvdemod_init(bool on) { /* 1.set system clock when atv enter*/ - pr_err("%s do configure_receiver ...\n", __func__); - if (is_meson_txlx_cpu() || is_meson_txhd_cpu()) + pr_dbg("%s do configure_receiver ...\n", __func__); + if (is_meson_txlx_cpu() || is_meson_txhd_cpu() || is_meson_tl1_cpu()) sound_format = 1; configure_receiver(broad_std, if_freq, if_inv, gde_curve, sound_format); - pr_err("%s do atv_dmd_misc ...\n", __func__); + pr_dbg("%s do atv_dmd_misc ...\n", __func__); atv_dmd_misc(); - pr_err("%s do atv_dmd_soft_reset ...\n", __func__); + if (on && (broad_std == AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC_M || + broad_std == AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC)) + atv_dmd_ring_filter(true); + else + atv_dmd_ring_filter(false); + + pr_dbg("%s do atv_dmd_soft_reset ...\n", __func__); /*4.software reset*/ atv_dmd_soft_reset(); @@ -1759,7 +1962,7 @@ int atvdemod_init(void) mix1_freq = atv_dmd_rd_byte(APB_BLOCK_ADDR_MIXER_1, 0x0); - pr_err("%s done\n", __func__); + pr_info("%s done\n", __func__); return 0; } @@ -1776,6 +1979,8 @@ void atvdemod_uninit(void) void atv_dmd_set_std(void) { v4l2_std_id ptstd = amlatvdemod_devp->std; + int tuner_index = amlatvdemod_devp->tuner_cur; + int tuner_id = amlatvdemod_devp->tuners[tuner_index].cfg.id; /* set broad standard of tuner*/ if (((ptstd & V4L2_COLOR_STD_PAL) @@ -1798,7 +2003,8 @@ void atv_dmd_set_std(void) gde_curve = 3; } else if (((ptstd & V4L2_COLOR_STD_PAL) || (ptstd & V4L2_COLOR_STD_SECAM)) - && (ptstd & V4L2_STD_PAL_M)) { + && ((ptstd & V4L2_STD_PAL_M) + || (ptstd & V4L2_STD_NTSC_M))) { amlatvdemod_devp->fre_offset = 2250000; freq_hz_cvrt = AML_ATV_DEMOD_FREQ_60HZ_VERT; broad_std = AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_M; @@ -1852,30 +2058,27 @@ void atv_dmd_set_std(void) } /* Tuner returns the if and signal inverted states */ - if ((amlatvdemod_devp->tuner_id == AM_TUNER_R840) || - (amlatvdemod_devp->tuner_id == AM_TUNER_R842) || - (amlatvdemod_devp->tuner_id == AM_TUNER_SI2151) || - (amlatvdemod_devp->tuner_id == AM_TUNER_SI2159) || - (amlatvdemod_devp->tuner_id == AM_TUNER_MXL661)) { + if ((tuner_id == AM_TUNER_R840) || + (tuner_id == AM_TUNER_R842) || + (tuner_id == AM_TUNER_SI2151) || + (tuner_id == AM_TUNER_SI2159) || + (tuner_id == AM_TUNER_MXL661)) { if_freq = amlatvdemod_devp->if_freq; if_inv = amlatvdemod_devp->if_inv; } - pr_info("[%s] set broad_std %d, hz_cvrt 0x%x, offset %d.\n", + pr_dbg("[%s] set broad_std %d, hz_cvrt 0x%x, offset %d.\n", __func__, broad_std, freq_hz_cvrt, amlatvdemod_devp->fre_offset); - pr_info("[%s] set std color %s, audio type %s.\n", + pr_dbg("[%s] set std color %s, audio type %s.\n", __func__, v4l2_std_to_str((0xff000000 & amlatvdemod_devp->std)), v4l2_std_to_str((0xffffff & amlatvdemod_devp->std))); - pr_info("[%s] set if_freq %d, if_inv %d.\n", + pr_dbg("[%s] set if_freq %d, if_inv %d.\n", __func__, amlatvdemod_devp->if_freq, amlatvdemod_devp->if_inv); - - if (atvdemod_init()) - pr_info("[%s]: atv restart error.\n", __func__); } int aml_audiomode_autodet(struct v4l2_frontend *v4l2_fe) @@ -1889,19 +2092,15 @@ int aml_audiomode_autodet(struct v4l2_frontend *v4l2_fe) unsigned long carrier_power_average_max = 0; unsigned long carrier_power_average[4] = {0}; unsigned long temp_data = 0; - int carrier_lock_count = 0; - int lock = 0; + int lock = 0, line_lock = 0; int broad_std_final = 0; int num = 0, i = 0, final_id = 0; int delay_ms = 10, delay_ms_default = 10; int cur_std = ID_PAL_DK; bool secam_signal = false; - -#if 0 - temp_data = atv_dmd_rd_reg(APB_BLOCK_ADDR_SIF_STG_2, 0x02); - temp_data = temp_data | 0x80;/* 0x40 */ - atv_dmd_wr_reg(APB_BLOCK_ADDR_SIF_STG_2, 0x02, temp_data); -#endif + bool ntsc_signal = false; + bool pal_signal = false; + bool has_audio = false; switch (broad_std) { case AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_DK: @@ -1909,21 +2108,16 @@ int aml_audiomode_autodet(struct v4l2_frontend *v4l2_fe) case AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_BG: case AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_M: broad_std = AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_M; + pal_signal = true; break; case AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC_DK: case AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC_I: case AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC_BG: case AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC_M: case AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC: - - broad_std = AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC_M; - atvdemod_init(); - temp_data = atv_dmd_rd_reg(APB_BLOCK_ADDR_SIF_STG_2, 0x02); - temp_data = temp_data & (~0x80); /* 0xbf; */ - atv_dmd_wr_reg(APB_BLOCK_ADDR_SIF_STG_2, 0x02, temp_data); - /* pr_err("%s, SECAM ,audio set SECAM_L\n", __func__); */ - return broad_std; - + ntsc_signal = true; + broad_std = AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_M; + break; case AML_ATV_DEMOD_VIDEO_MODE_PROP_SECAM_L: case AML_ATV_DEMOD_VIDEO_MODE_PROP_SECAM_DK2: case AML_ATV_DEMOD_VIDEO_MODE_PROP_SECAM_DK3: @@ -1933,7 +2127,7 @@ int aml_audiomode_autodet(struct v4l2_frontend *v4l2_fe) broad_std = AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_M; } else { broad_std = AML_ATV_DEMOD_VIDEO_MODE_PROP_SECAM_L; - atvdemod_init(); + atvdemod_init(false); temp_data = atv_dmd_rd_reg(APB_BLOCK_ADDR_SIF_STG_2, 0x02); @@ -2008,7 +2202,8 @@ int aml_audiomode_autodet(struct v4l2_frontend *v4l2_fe) } } - if (broad_std == AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_M) { + if (broad_std == AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_M + && pal_signal) { /*the max except palm*/ carrier_power_average[final_id] = 0; final_id = 0; @@ -2036,6 +2231,12 @@ int aml_audiomode_autodet(struct v4l2_frontend *v4l2_fe) AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_DK; break; } + /* pal signal and pal-m power max, + * so set to second max std. + */ + broad_std = broad_std_except_pal_m; + pr_err("%s:pal signal and pal-m power max, set broad_std:%d\n", + __func__, broad_std); } p->std = V4L2_COLOR_STD_PAL; @@ -2097,9 +2298,15 @@ int aml_audiomode_autodet(struct v4l2_frontend *v4l2_fe) broad_std = AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_M; cur_std = ID_PAL_M; - p->std = V4L2_COLOR_STD_PAL | V4L2_STD_PAL_M; - p->frequency += 1; - p->audmode = V4L2_STD_PAL_M; + if (!ntsc_signal) { + p->std = V4L2_COLOR_STD_PAL | V4L2_STD_PAL_M; + p->frequency += 1; + p->audmode = V4L2_STD_PAL_M; + } else { + p->std = V4L2_COLOR_STD_NTSC | V4L2_STD_NTSC_M; + p->frequency += 1; + p->audmode = V4L2_STD_NTSC_M; + } delay_ms = delay_ms_default; break; @@ -2127,32 +2334,37 @@ int aml_audiomode_autodet(struct v4l2_frontend *v4l2_fe) /* enable audio detect function */ temp_data = atv_dmd_rd_reg(APB_BLOCK_ADDR_SIF_STG_2, 0x02); - temp_data = temp_data | 0x80;/* 0x40 */ + temp_data = temp_data | 0x87;/* 0x40 */ atv_dmd_wr_reg(APB_BLOCK_ADDR_SIF_STG_2, 0x02, temp_data); usleep_range(delay_ms * 1000, delay_ms * 1000 + 100); - carrier_lock_count = 0; + /* ----------------judgment signal state--------------------- */ i = 4; + has_audio = false; while (i--) { retrieve_vpll_carrier_lock(&lock); - if (lock == 0) + line_lock = atv_dmd_rd_byte(APB_BLOCK_ADDR_VDAGC, 0x4f); + if (lock == 0 && (line_lock & 0x10) == 0) { + has_audio = true; break; - carrier_lock_count++; - if (carrier_lock_count >= 20) { - pr_err("%s step2, retrieve_vpll_carrier_lock failed\n", - __func__); - /* return broad_std; */ } + usleep_range(6000, 9000); } /* ----------------read carrier_power--------------------- */ - for (i = 0; i < 100; i++) { - carrier_power = - atv_dmd_rd_reg(APB_BLOCK_ADDR_SIF_STG_2, 0x03); - carrier_power_max += carrier_power; + if (has_audio) { + for (i = 0; i < 100; i++) { + carrier_power = atv_dmd_rd_reg( + APB_BLOCK_ADDR_SIF_STG_2, 0x03); + carrier_power_max += carrier_power; + } + carrier_power = carrier_power_max/i; + } else { + carrier_power = 0; + pr_err("[%s] pll and line unlock.\n", __func__); } - carrier_power = carrier_power_max/i; + carrier_power_max = 0; pr_err("[%s] [num:%d] [broad_std:%d] audio carrier power: %lu. @@@@@@@@@@\n", __func__, num, broad_std, carrier_power); @@ -2165,7 +2377,7 @@ int aml_audiomode_autodet(struct v4l2_frontend *v4l2_fe) void aml_audio_valume_gain_set(unsigned int audio_gain) { - unsigned long audio_gain_data, temp_data; + unsigned long audio_gain_data = 0, temp_data = 0; if (audio_gain > 0xfff) { pr_err("Error: atv in gain max 7.998, min 0.002! gain = value/512\n"); @@ -2180,7 +2392,7 @@ void aml_audio_valume_gain_set(unsigned int audio_gain) unsigned int aml_audio_valume_gain_get(void) { - unsigned long audio_gain_data; + unsigned long audio_gain_data = 0; audio_gain_data = atv_dmd_rd_word(APB_BLOCK_ADDR_MONO_PROC, 0x52); audio_gain_data = audio_gain_data & 0xfff; @@ -2189,7 +2401,7 @@ unsigned int aml_audio_valume_gain_get(void) void aml_fix_PWM_adjust(int enable) { - unsigned long temp_data; + unsigned long temp_data = 0; /* * temp_data = atv_dmd_rd_byte(APB_BLOCK_ADDR_AGC_PWM, 0x08); * temp_data = temp_data | 0x01; @@ -2210,16 +2422,20 @@ void aml_fix_PWM_adjust(int enable) void aml_audio_overmodulation(int enable) { - static int ov_flag; - unsigned long tmp_v; - unsigned long tmp_v1; + unsigned long tmp_v = 0; + unsigned long tmp_v1 = 0; + unsigned int reg = 0; u32 Broadcast_Standard = broad_std; + /* False entry on weak signal */ + if (atvdemod_get_snr() < snr_threshold) + return; + if (enable && Broadcast_Standard == AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_DK) { tmp_v = atv_dmd_rd_long(APB_BLOCK_ADDR_SIF_STG_2, 0x28); tmp_v = tmp_v&0xffff; - if (tmp_v >= 0x10 && ov_flag == 0) { + if (tmp_v > 0x10 && audio_atv_ov_flag == 0) { tmp_v1 = atv_dmd_rd_long(APB_BLOCK_ADDR_SIF_STG_2, 0); tmp_v1 = (tmp_v1&0xffffff)|(1<<24); @@ -2227,19 +2443,18 @@ void aml_audio_overmodulation(int enable) atv_dmd_wr_long(APB_BLOCK_ADDR_SIF_STG_2, 0x14, 0x8000015); atv_dmd_wr_long(APB_BLOCK_ADDR_SIF_STG_2, - 0x1c, 0x0f000); - } else if (tmp_v >= 0x2500 && ov_flag == 0) { - tmp_v1 = atv_dmd_rd_long(APB_BLOCK_ADDR_SIF_STG_2, 0); - tmp_v1 = (tmp_v1&0xffffff)|(1<<24); - atv_dmd_wr_long(APB_BLOCK_ADDR_SIF_STG_2, 0, tmp_v1); - atv_dmd_wr_long(APB_BLOCK_ADDR_SIF_STG_2, - 0x14, 0xf400015); - atv_dmd_wr_long(APB_BLOCK_ADDR_SIF_STG_2, - 0x18, 0xc000); + 0x18, 0x7ffff); atv_dmd_wr_long(APB_BLOCK_ADDR_SIF_STG_2, 0x1c, 0x0f000); - ov_flag = 1; - } else if (tmp_v <= 0x10 && ov_flag == 1) { + atvaudio_ctrl_read(®); + if (is_meson_tl1_cpu()) /* bit20 */ + atvaudio_ctrl_write(reg & (~0x100000)); + else + atvaudio_ctrl_write(reg & (~0x3));/* bit[1-0] */ + /* audio_atv_ov_flag = 1;*/ /* Enter and hold */ + pr_info("tmp_v[0x%lx] > 0x10 && audio_atv_ov_flag == 0.\n", + tmp_v); + } else if (tmp_v <= 0x10 && audio_atv_ov_flag == 1) { tmp_v1 = atv_dmd_rd_long(APB_BLOCK_ADDR_SIF_STG_2, 0); tmp_v1 = (tmp_v1&0xffffff)|(0<<24); atv_dmd_wr_long(APB_BLOCK_ADDR_SIF_STG_2, 0, tmp_v1); @@ -2249,7 +2464,14 @@ void aml_audio_overmodulation(int enable) 0x18, 0xc000); atv_dmd_wr_long(APB_BLOCK_ADDR_SIF_STG_2, 0x1c, 0x1f000); - ov_flag = 0; + atvaudio_ctrl_read(®); + if (is_meson_tl1_cpu()) /* bit20 */ + atvaudio_ctrl_write(reg | 0x100000); + else + atvaudio_ctrl_write(reg | 0x3);/* bit[1-0] */ + audio_atv_ov_flag = 0; + pr_info("tmp_v[0x%lx] <= 0x10 && audio_atv_ov_flag == 1.\n", + tmp_v); } } } diff --git a/drivers/amlogic/atv_demod/atvdemod_func.h b/drivers/amlogic/atv_demod/atvdemod_func.h index 530982c45cda..57149c934722 100644 --- a/drivers/amlogic/atv_demod/atvdemod_func.h +++ b/drivers/amlogic/atv_demod/atvdemod_func.h @@ -64,12 +64,13 @@ extern void read_version_register(void); extern void check_communication_interface(void); extern void power_on_receiver(void); extern void atv_dmd_misc(void); +extern void atv_dmd_ring_filter(bool on); extern void configure_receiver(int Broadcast_Standard, unsigned int Tuner_IF_Frequency, int Tuner_Input_IF_inverted, int GDE_Curve, int sound_format); extern int atvdemod_clk_init(void); -extern int atvdemod_init(void); +extern int atvdemod_init(bool on); extern void atvdemod_uninit(void); extern void atv_dmd_set_std(void); extern void retrieve_adc_power(int *adc_level); @@ -203,6 +204,7 @@ extern void retrieve_frequency_offset(int *freq_offset); extern void retrieve_field_lock(int *lock); extern void set_atvdemod_scan_mode(int val); extern int atvauddemod_init(void); +extern int amlfmt_aud_standard(int broad_std); extern void atvauddemod_set_outputmode(void); /*from amldemod/amlfrontend.c*/ diff --git a/drivers/amlogic/atv_demod/aud_demod_reg.h b/drivers/amlogic/atv_demod/aud_demod_reg.h index cacc8ca00962..4f9547ee1635 100644 --- a/drivers/amlogic/atv_demod/aud_demod_reg.h +++ b/drivers/amlogic/atv_demod/aud_demod_reg.h @@ -318,6 +318,11 @@ #define AUDIO_STANDARD_INDIAN 0x0F #define AUDIO_STANDARD_BTSC_SA 0x10 #define AUDIO_STANDARD_MONO_ONLY 0x11 +#define AUDIO_STANDARD_MONO_BG 0x12 +#define AUDIO_STANDARD_MONO_DK 0x13 +#define AUDIO_STANDARD_MONO_I 0x14 +#define AUDIO_STANDARD_MONO_M 0x15 +#define AUDIO_STANDARD_MONO_L 0x16 #define AUDIO_OUTMODE_MONO 0 #define AUDIO_OUTMODE_STEREO 1 diff --git a/drivers/amlogic/audioinfo/audio_data.c b/drivers/amlogic/audioinfo/audio_data.c index f5494c3eb2ce..f41136863eb7 100644 --- a/drivers/amlogic/audioinfo/audio_data.c +++ b/drivers/amlogic/audioinfo/audio_data.c @@ -101,12 +101,14 @@ int meson_efuse_fn_smc_query_audioinfo(struct efuse_hal_api_arg *arg) int meson_trustzone_audio_info_get(struct efuse_hal_api_arg *arg) { int ret; + struct cpumask org_cpumask; if (!arg) return -1; + cpumask_copy(&org_cpumask, ¤t->cpus_allowed); set_cpus_allowed_ptr(current, cpumask_of(0)); ret = meson_efuse_fn_smc_query_audioinfo(arg); - set_cpus_allowed_ptr(current, cpu_all_mask); + set_cpus_allowed_ptr(current, &org_cpumask); return ret; } diff --git a/drivers/amlogic/bluetooth/bt_device.c b/drivers/amlogic/bluetooth/bt_device.c index c926f13f7f6f..3d7afc4e687c 100644 --- a/drivers/amlogic/bluetooth/bt_device.c +++ b/drivers/amlogic/bluetooth/bt_device.c @@ -32,6 +32,7 @@ #include #include #include +#include #ifdef CONFIG_AM_WIFI_SD_MMC #include #endif @@ -44,6 +45,48 @@ static struct early_suspend bt_early_suspend; #define BT_RFKILL "bt_rfkill" +char bt_addr[18] = ""; +static struct class *bt_addr_class; +static ssize_t bt_addr_show(struct class *cls, + struct class_attribute *attr, char *_buf) +{ + char local_addr[6]; + + if (!_buf) + return -EINVAL; + + if (strlen(bt_addr) == 0) { + local_addr[0] = 0x22; + local_addr[1] = 0x22; + local_addr[2] = prandom_u32(); + local_addr[3] = prandom_u32(); + local_addr[4] = prandom_u32(); + local_addr[5] = prandom_u32(); + sprintf(bt_addr, "%02x:%02x:%02x:%02x:%02x:%02x", + local_addr[0], local_addr[1], local_addr[2], + local_addr[3], local_addr[4], local_addr[5]); + } + + return sprintf(_buf, "%s\n", bt_addr); +} +static ssize_t bt_addr_store(struct class *cls, + struct class_attribute *attr, const char __user *buf, size_t count) +{ + int ret = -EINVAL; + + if (!buf) + return ret; + + snprintf(bt_addr, sizeof(bt_addr), "%s", buf); + + if (bt_addr[strlen(bt_addr)-1] == '\n') + bt_addr[strlen(bt_addr)-1] = '\0'; + + pr_info("bt_addr=%s\n", bt_addr); + return count; +} +static CLASS_ATTR(value, 0644, bt_addr_show, bt_addr_store); + struct bt_dev_runtime_data { struct rfkill *bt_rfk; struct bt_dev_data *pdata; @@ -281,6 +324,9 @@ static int bt_probe(struct platform_device *pdev) #else pdata = (struct bt_dev_data *)(pdev->dev.platform_data); #endif + bt_addr_class = class_create(THIS_MODULE, "bt_addr"); + ret = class_create_file(bt_addr_class, &class_attr_value); + bt_device_init(pdata); if (pdata->power_down_disable == 1) { pdata->power_down_disable = 0; @@ -402,3 +448,21 @@ module_exit(bt_exit); MODULE_DESCRIPTION("bt rfkill"); MODULE_AUTHOR(""); MODULE_LICENSE("GPL"); + +/**************** bt mac *****************/ + +static int __init mac_addr_set(char *line) +{ + + if (line) { + pr_info("try to read bt mac from emmc key!\n"); + strncpy(bt_addr, line, sizeof(bt_addr)-1); + bt_addr[sizeof(bt_addr)-1] = '\0'; + } + + return 1; +} + +__setup("mac_bt=", mac_addr_set); + + diff --git a/drivers/amlogic/cec/hdmi_ao_cec.c b/drivers/amlogic/cec/hdmi_ao_cec.c index c2f5c688db18..215918e784b3 100644 --- a/drivers/amlogic/cec/hdmi_ao_cec.c +++ b/drivers/amlogic/cec/hdmi_ao_cec.c @@ -82,6 +82,7 @@ struct cec_platform_data_s { bool ee_to_ao;/*ee cec hw module mv to ao;ao cec delete*/ bool ceca_sts_reg;/*add new internal status register*/ enum cecbver cecb_ver;/* detail discription ref enum cecbver */ + enum cecaver ceca_ver; }; @@ -93,6 +94,7 @@ struct cec_wakeup_t { /* global struct for tx and rx */ struct ao_cec_dev { + bool proble_finish; unsigned long dev_type; struct device_node *node; unsigned int port_num; /*total input hdmi port number*/ @@ -145,8 +147,10 @@ static int phy_addr_test; enum { HDMI_OPTION_WAKEUP = 1, HDMI_OPTION_ENABLE_CEC = 2, + /*frame work pw on, 1:pw on 0:suspend*/ HDMI_OPTION_SYSTEM_CEC_CONTROL = 3, HDMI_OPTION_SET_LANG = 5, + /*have cec framework*/ HDMI_OPTION_SERVICE_FLAG = 16, }; @@ -159,7 +163,7 @@ static struct hrtimer start_bit_check; static unsigned char rx_msg[MAX_MSG]; static unsigned char rx_len; static unsigned int new_msg; -static bool wake_ok = 1; +/*static bool wake_ok = 1;*/ static bool ee_cec; static bool pin_status; static unsigned int cec_msg_dbg_en; @@ -181,17 +185,72 @@ static unsigned int cec_msg_dbg_en; static unsigned char msg_log_buf[128] = { 0 }; +static const char * const cec_reg_name1[] = { + "CEC_TX_MSG_LENGTH", + "CEC_TX_MSG_CMD", + "CEC_TX_WRITE_BUF", + "CEC_TX_CLEAR_BUF", + "CEC_RX_MSG_CMD", + "CEC_RX_CLEAR_BUF", + "CEC_LOGICAL_ADDR0", + "CEC_LOGICAL_ADDR1", + "CEC_LOGICAL_ADDR2", + "CEC_LOGICAL_ADDR3", + "CEC_LOGICAL_ADDR4", + "CEC_CLOCK_DIV_H", + "CEC_CLOCK_DIV_L" +}; + +static const char * const cec_reg_name2[] = { + "CEC_RX_MSG_LENGTH", + "CEC_RX_MSG_STATUS", + "CEC_RX_NUM_MSG", + "CEC_TX_MSG_STATUS", + "CEC_TX_NUM_MSG" +}; + +static const char * const ceca_reg_name3[] = { + "STAT_0_0", + "STAT_0_1", + "STAT_0_2", + "STAT_0_3", + "STAT_1_0", + "STAT_1_1", + "STAT_1_2" +}; + +#if 1 +unsigned int waiting_aocec_free(unsigned int r) +{ + unsigned int cnt = 0; + int ret = true; + + while (readl(cec_dev->cec_reg + r) & (1<<23)) { + if (cnt++ >= 3500) { + pr_info("waiting aocec %x free time out %d\n", r, cnt); + if (cec_dev->proble_finish) + cec_hw_reset(CEC_A); + ret = false; + break; + } + } + + return ret; +} +#else #define waiting_aocec_free(r) \ do {\ unsigned long cnt = 0;\ while (readl(cec_dev->cec_reg + r) & (1<<23)) {\ if (cnt++ == 3500) { \ pr_info("waiting aocec %x free time out\n", r);\ - cec_hw_reset(CEC_A);\ + if (cec_dev->proble_finish) \ + cec_hw_reset(CEC_A);\ break;\ } \ } \ } while (0) +#endif static void cec_set_reg_bits(unsigned int addr, unsigned int value, unsigned int offset, unsigned int len) @@ -210,14 +269,20 @@ unsigned int aocec_rd_reg(unsigned long addr) unsigned long flags; spin_lock_irqsave(&cec_dev->cec_reg_lock, flags); - waiting_aocec_free(AO_CEC_RW_REG); + if (!waiting_aocec_free(AO_CEC_RW_REG)) { + spin_unlock_irqrestore(&cec_dev->cec_reg_lock, flags); + return 0; + } data32 = 0; data32 |= 0 << 16; /* [16] cec_reg_wr */ data32 |= 0 << 8; /* [15:8] cec_reg_wrdata */ data32 |= addr << 0; /* [7:0] cec_reg_addr */ writel(data32, cec_dev->cec_reg + AO_CEC_RW_REG); - waiting_aocec_free(AO_CEC_RW_REG); + if (!waiting_aocec_free(AO_CEC_RW_REG)) { + spin_unlock_irqrestore(&cec_dev->cec_reg_lock, flags); + return 0; + } data32 = ((readl(cec_dev->cec_reg + AO_CEC_RW_REG)) >> 24) & 0xff; spin_unlock_irqrestore(&cec_dev->cec_reg_lock, flags); return data32; @@ -229,7 +294,10 @@ void aocec_wr_reg(unsigned long addr, unsigned long data) unsigned long flags; spin_lock_irqsave(&cec_dev->cec_reg_lock, flags); - waiting_aocec_free(AO_CEC_RW_REG); + if (!waiting_aocec_free(AO_CEC_RW_REG)) { + spin_unlock_irqrestore(&cec_dev->cec_reg_lock, flags); + return; + } data32 = 0; data32 |= 1 << 16; /* [16] cec_reg_wr */ data32 |= data << 8; /* [15:8] cec_reg_wrdata */ @@ -416,6 +484,49 @@ static inline void cecrx_clear_irq(unsigned int flags) writel(flags, cec_dev->cec_reg + AO_CECB_INTR_CLR); } +/* max length = 14+1 */ +#define OSD_NAME_DEV 1 +const uint8_t dev_osd_name[1][16] = { + {1, 0x43, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x63, 0x61, 0x73, 0x74}, +}; + +const uint8_t dev_vendor_id[1][3] = { + {0, 0, 0}, +}; + +static bool cec_message_op(unsigned char *msg, unsigned char len) +{ + int i, j; + + if (((msg[0] & 0xf0) >> 4) == cec_dev->cec_info.log_addr) { + CEC_ERR("bad iniator with self:%s", msg_log_buf); + return false; + } + switch (msg[1]) { + case 0x47: + /* OSD name */ + if (len > 16) + break; + for (j = 0; j < OSD_NAME_DEV; j++) { + for (i = 2; i < len; i++) { + if (msg[i] != dev_osd_name[j][i-1]) + break; + } + if (i == len) { + cec_set_dev_info(dev_osd_name[j][0]); + CEC_INFO("specific dev:%d", dev_osd_name[j][0]); + } + } + break; + case 0x87: + /* verdor ID */ + break; + default: + break; + } + return true; +} + static int cecb_pick_msg(unsigned char *msg, unsigned char *out_len) { int i, size; @@ -432,11 +543,10 @@ static int cecb_pick_msg(unsigned char *msg, unsigned char *out_len) /* clr CEC lock bit */ hdmirx_cec_write(DWC_CEC_LOCK, 0); CEC_INFO("%s", msg_log_buf); - if (((msg[0] & 0xf0) >> 4) == cec_dev->cec_info.log_addr) { - *out_len = 0; - CEC_ERR("bad iniator with self:%s", msg_log_buf); - } else + if (cec_message_op(msg, len)) *out_len = len; + else + *out_len = 0; pin_status = 1; return 0; } @@ -453,6 +563,8 @@ void cecb_irq_handle(void) /* clear irq */ if (intr_cec != 0) cecrx_clear_irq(intr_cec); + else + CEC_INFO_L(L_1, "err cec intsts:0\n"); if (cec_dev->plat_data->ee_to_ao) shift = 16; @@ -661,74 +773,156 @@ int cecrx_hw_init(void) return 0; } */ -static int dump_cecrx_reg(char *b) + +int dump_cecrx_reg(char *b) { int i = 0, s = 0; unsigned char reg; unsigned int reg32; + unsigned int chiptype; - if (!cec_dev->plat_data->ee_to_ao) { - reg32 = readl(cec_dev->hhi_reg + HHI_32K_CLK_CNTL); - s += sprintf(b + s, "HHI_32K_CLK_CNTL: 0x%08x\n", reg32); - reg32 = hdmirx_rd_top(TOP_EDID_ADDR_CEC); - s += sprintf(b + s, "TOP_EDID_ADDR_CEC: 0x%08x\n", reg32); - reg32 = hdmirx_rd_top(TOP_EDID_GEN_CNTL); - s += sprintf(b + s, "TOP_EDID_GEN_CNTL: 0x%08x\n", reg32); - reg32 = hdmirx_cec_read(DWC_AUD_CEC_IEN); - s += sprintf(b + s, "DWC_AUD_CEC_IEN: 0x%08x\n", reg32); - reg32 = hdmirx_cec_read(DWC_AUD_CEC_ISTS); - s += sprintf(b + s, "DWC_AUD_CEC_ISTS: 0x%08x\n", reg32); - reg32 = hdmirx_cec_read(DWC_DMI_DISABLE_IF); - s += sprintf(b + s, "DWC_DMI_DISABLE_IF: 0x%08x\n", reg32); - reg32 = hdmirx_rd_top(TOP_CLK_CNTL); - s += sprintf(b + s, "TOP_CLK_CNTL: 0x%08x\n", reg32); + chiptype = get_meson_cpu_version(MESON_CPU_VERSION_LVL_MAJOR); + if ((ee_cec == CEC_A) && (chiptype >= MESON_CPU_MAJOR_ID_GXBB)) { + if (cec_dev->plat_data->ee_to_ao) { + reg32 = readl(cec_dev->cec_reg + AO_CEC_CLK_CNTL_REG0); + s += sprintf(b + s, "AO_CEC_CLK_CNTL_REG0:0x%08x\n", + reg32); + reg32 = readl(cec_dev->cec_reg + AO_CEC_CLK_CNTL_REG1); + s += sprintf(b + s, "AO_CEC_CLK_CNTL_REG1:0x%08x\n", + reg32); + } else { + reg32 = readl(cec_dev->cec_reg + AO_RTC_ALT_CLK_CNTL0); + s += sprintf(b + s, "AO_RTC_ALT_CLK_CNTL0:0x%08x\n", + reg32); + reg32 = readl(cec_dev->cec_reg + AO_RTC_ALT_CLK_CNTL1); + s += sprintf(b + s, "AO_RTC_ALT_CLK_CNTL1:0x%08x\n", + reg32); + reg32 = readl(cec_dev->cec_reg + AO_CRT_CLK_CNTL1); + s += sprintf(b + s, "AO_CRT_CLK_CNTL1:0x%08x\n", + reg32); + } + } + reg32 = readl(cec_dev->cec_reg + AO_RTI_PWR_CNTL_REG0); + s += sprintf(b + s, "AO_RTI_PWR_CNTL_REG0: 0x%08x\n", + reg32); + reg32 = readl(cec_dev->cec_reg + AO_CEC_GEN_CNTL); + s += sprintf(b + s, "AO_CEC_GEN_CNTL: 0x%08x\n", + reg32); + + if (ee_cec == CEC_B) { + if (!cec_dev->plat_data->ee_to_ao) { + reg32 = readl(cec_dev->hhi_reg + HHI_32K_CLK_CNTL); + s += sprintf(b + s, "HHI_32K_CLK_CNTL: 0x%08x\n", + reg32); + reg32 = hdmirx_rd_top(TOP_EDID_ADDR_CEC); + s += sprintf(b + s, "TOP_EDID_ADDR_CEC: 0x%08x\n", + reg32); + reg32 = hdmirx_rd_top(TOP_EDID_GEN_CNTL); + s += sprintf(b + s, "TOP_EDID_GEN_CNTL: 0x%08x\n", + reg32); + reg32 = hdmirx_cec_read(DWC_AUD_CEC_IEN); + s += sprintf(b + s, "DWC_AUD_CEC_IEN: 0x%08x\n", + reg32); + reg32 = hdmirx_cec_read(DWC_AUD_CEC_ISTS); + s += sprintf(b + s, "DWC_AUD_CEC_ISTS: 0x%08x\n", + reg32); + reg32 = hdmirx_cec_read(DWC_DMI_DISABLE_IF); + s += sprintf(b + s, "DWC_DMI_DISABLE_IF: 0x%08x\n", + reg32); + reg32 = hdmirx_rd_top(TOP_CLK_CNTL); + s += sprintf(b + s, "TOP_CLK_CNTL: 0x%08x\n", + reg32); + } else { + reg32 = readl(cec_dev->cec_reg + AO_CECB_CLK_CNTL_REG0); + s += sprintf(b + s, "AO_CECB_CLK_CNTL_REG0: 0x%08x\n", + reg32); + reg32 = readl(cec_dev->cec_reg + AO_CECB_CLK_CNTL_REG1); + s += sprintf(b + s, "AO_CECB_CLK_CNTL_REG1: 0x%08x\n", + reg32); + reg32 = readl(cec_dev->cec_reg + AO_CECB_GEN_CNTL); + s += sprintf(b + s, "AO_CECB_GEN_CNTL: 0x%08x\n", + reg32); + reg32 = readl(cec_dev->cec_reg + AO_CECB_RW_REG); + s += sprintf(b + s, "AO_CECB_RW_REG: 0x%08x\n", + reg32); + reg32 = readl(cec_dev->cec_reg + AO_CECB_INTR_MASKN); + s += sprintf(b + s, "AO_CECB_INTR_MASKN:0x%08x\n", + reg32); + reg32 = readl(cec_dev->cec_reg + AO_CECB_INTR_STAT); + s += sprintf(b + s, "AO_CECB_INTR_STAT: 0x%08x\n", + reg32); + } + + s += sprintf(b + s, "CEC MODULE REGS:\n"); + s += sprintf(b + s, "CEC_CTRL = 0x%02x\n", + hdmirx_cec_read(0x1f00)); + if (cec_dev->plat_data->cecb_ver >= CECB_VER_2) + s += sprintf(b + s, "CEC_CTRL2 = 0x%02x\n", + hdmirx_cec_read(0x1f04)); + s += sprintf(b + s, "CEC_MASK = 0x%02x\n", + hdmirx_cec_read(0x1f08)); + s += sprintf(b + s, "CEC_ADDR_L = 0x%02x\n", + hdmirx_cec_read(0x1f14)); + s += sprintf(b + s, "CEC_ADDR_H = 0x%02x\n", + hdmirx_cec_read(0x1f18)); + s += sprintf(b + s, "CEC_TX_CNT = 0x%02x\n", + hdmirx_cec_read(0x1f1c)); + s += sprintf(b + s, "CEC_RX_CNT = 0x%02x\n", + hdmirx_cec_read(0x1f20)); + if (cec_dev->plat_data->cecb_ver >= CECB_VER_2) + s += sprintf(b + s, "CEC_STAT0 = 0x%02x\n", + hdmirx_cec_read(0x1f24)); + s += sprintf(b + s, "CEC_LOCK = 0x%02x\n", + hdmirx_cec_read(0x1fc0)); + s += sprintf(b + s, "CEC_WKUPCTRL = 0x%02x\n", + hdmirx_cec_read(0x1fc4)); + + s += sprintf(b + s, "%s", "RX buffer:"); + for (i = 0; i < 16; i++) { + reg = (hdmirx_cec_read(0x1f80 + i * 4) & 0xff); + s += sprintf(b + s, " %02x", reg); + } + s += sprintf(b + s, "\n"); + + s += sprintf(b + s, "%s", "TX buffer:"); + for (i = 0; i < 16; i++) { + reg = (hdmirx_cec_read(0x1f40 + i * 4) & 0xff); + s += sprintf(b + s, " %02x", reg); + } + s += sprintf(b + s, "\n"); } else { - reg32 = readl(cec_dev->cec_reg + AO_CECB_CLK_CNTL_REG0); - s += sprintf(b + s, "AO_CECB_CLK_CNTL_REG0: 0x%08x\n", reg32); - reg32 = readl(cec_dev->cec_reg + AO_CECB_CLK_CNTL_REG1); - s += sprintf(b + s, "AO_CECB_CLK_CNTL_REG1: 0x%08x\n", reg32); - reg32 = readl(cec_dev->cec_reg + AO_CECB_GEN_CNTL); - s += sprintf(b + s, "AO_CECB_GEN_CNTL: 0x%08x\n", reg32); - reg32 = readl(cec_dev->cec_reg + AO_CECB_RW_REG); - s += sprintf(b + s, "AO_CECB_RW_REG: 0x%08x\n", reg32); - reg32 = readl(cec_dev->cec_reg + AO_CECB_INTR_MASKN); - s += sprintf(b + s, "AO_CECB_INTR_MASKN: 0x%08x\n", reg32); - reg32 = readl(cec_dev->cec_reg + AO_CECB_INTR_STAT); - s += sprintf(b + s, "AO_CECB_INTR_STAT: 0x%08x\n", reg32); + s += sprintf(b + s, "TX buffer:\n"); + for (i = 0; i <= CEC_TX_MSG_F_OP14; i++) + s += sprintf(b + s, "%2d:%2x\n", i, + aocec_rd_reg(i)); + + for (i = 0; i < ARRAY_SIZE(cec_reg_name1); i++) { + s += sprintf(b + s, "%s:%2x\n", + cec_reg_name1[i], aocec_rd_reg(i + 0x10)); + } + + s += sprintf(b + s, "RX buffer:\n"); + for (i = 0; i <= CEC_TX_MSG_F_OP14; i++) + s += sprintf(b + s, "%2d:%2x\n", i, + aocec_rd_reg(i + 0x80)); + + for (i = 0; i < ARRAY_SIZE(cec_reg_name2); i++) { + s += sprintf(b + s, "%s:%2x\n", + cec_reg_name2[i], aocec_rd_reg(i + 0x90)); + } + + if (cec_dev->plat_data->ceca_sts_reg) { + for (i = 0; i < ARRAY_SIZE(ceca_reg_name3); i++) { + s += sprintf(b + s, "%s:%2x\n", + ceca_reg_name3[i], aocec_rd_reg(i + 0xA0)); + } + } } - s += sprintf(b + s, "CEC MODULE REGS:\n"); - s += sprintf(b + s, "CEC_CTRL = 0x%02x\n", hdmirx_cec_read(0x1f00)); - if (cec_dev->plat_data->cecb_ver >= CECB_VER_2) - s += sprintf(b + s, "CEC_CTRL2 = 0x%02x\n", - hdmirx_cec_read(0x1f04)); - s += sprintf(b + s, "CEC_MASK = 0x%02x\n", hdmirx_cec_read(0x1f08)); - s += sprintf(b + s, "CEC_ADDR_L = 0x%02x\n", hdmirx_cec_read(0x1f14)); - s += sprintf(b + s, "CEC_ADDR_H = 0x%02x\n", hdmirx_cec_read(0x1f18)); - s += sprintf(b + s, "CEC_TX_CNT = 0x%02x\n", hdmirx_cec_read(0x1f1c)); - s += sprintf(b + s, "CEC_RX_CNT = 0x%02x\n", hdmirx_cec_read(0x1f20)); - if (cec_dev->plat_data->cecb_ver >= CECB_VER_2) - s += sprintf(b + s, "CEC_STAT0 = 0x%02x\n", - hdmirx_cec_read(0x1f24)); - s += sprintf(b + s, "CEC_LOCK = 0x%02x\n", hdmirx_cec_read(0x1fc0)); - s += sprintf(b + s, "CEC_WKUPCTRL = 0x%02x\n", hdmirx_cec_read(0x1fc4)); - - s += sprintf(b + s, "%s", "RX buffer:"); - for (i = 0; i < 16; i++) { - reg = (hdmirx_cec_read(0x1f80 + i * 4) & 0xff); - s += sprintf(b + s, " %02x", reg); - } - s += sprintf(b + s, "\n"); - - s += sprintf(b + s, "%s", "TX buffer:"); - for (i = 0; i < 16; i++) { - reg = (hdmirx_cec_read(0x1f40 + i * 4) & 0xff); - s += sprintf(b + s, " %02x", reg); - } - s += sprintf(b + s, "\n"); return s; } + /*--------------------- END of EE CEC --------------------*/ void aocec_irq_enable(bool enable) @@ -988,6 +1182,13 @@ void cec_enable_arc_pin(bool enable) { unsigned int data; + if (is_meson_sm1_cpu() || + cpu_after_eq(MESON_CPU_MAJOR_ID_TM2)) { + /*sm1 and tm2 later, audio module handle this*/ + + return; + } + if (cec_dev->plat_data->cecb_ver >= CECB_VER_2) { data = rd_reg_hhi(HHI_HDMIRX_ARC_CNTL); /* enable bit 1:1 bit 0: 0*/ @@ -1374,6 +1575,11 @@ static void ao_ceca_init(void) udelay(200); reg |= (1 << 30); writel(reg, cec_dev->cec_reg + AO_CEC_CLK_CNTL_REG0); + + reg = readl(cec_dev->cec_reg + AO_RTI_PWR_CNTL_REG0); + reg |= (0x01 << 14);/* enable the crystal clock*/ + writel(reg, cec_dev->cec_reg + AO_RTI_PWR_CNTL_REG0); + } else { reg = (0 << 31) | (0 << 30) | @@ -1385,22 +1591,16 @@ static void ao_ceca_init(void) ((11-1) << 12) | ((8-1) << 0); writel(reg, cec_dev->cec_reg + AO_RTC_ALT_CLK_CNTL1); - + udelay(100); /*enable clk in*/ reg = readl(cec_dev->cec_reg + AO_RTC_ALT_CLK_CNTL0); reg |= (1 << 31); writel(reg, cec_dev->cec_reg + AO_RTC_ALT_CLK_CNTL0); /*enable clk out*/ - udelay(200); + udelay(100); reg |= (1 << 30); writel(reg, cec_dev->cec_reg + AO_RTC_ALT_CLK_CNTL0); - } - if (cec_dev->plat_data->ee_to_ao) { - reg = readl(cec_dev->cec_reg + AO_RTI_PWR_CNTL_REG0); - reg |= (0x01 << 14);/* enable the crystal clock*/ - writel(reg, cec_dev->cec_reg + AO_RTI_PWR_CNTL_REG0); - } else { reg = readl(cec_dev->cec_reg + AO_CRT_CLK_CNTL1); reg |= (0x800 << 16);/* select cts_rtc_oscin_clk */ writel(reg, cec_dev->cec_reg + AO_CRT_CLK_CNTL1); @@ -1553,13 +1753,14 @@ void cec_keep_reset(void) */ static void cec_pre_init(void) { + #if 0 unsigned int reg = readl(cec_dev->cec_reg + AO_RTI_STATUS_REG1); reg &= 0xfffff; if ((reg & 0xffff) == 0xffff) wake_ok = 0; pr_info("cec: wake up flag:%x\n", reg); - + #endif if (cec_dev->cec_num > 1) { ao_ceca_init(); ao_cecb_init(); @@ -1570,6 +1771,8 @@ static void cec_pre_init(void) ao_ceca_init(); } + cec_config(cec_dev->tx_dev->cec_func_config, 1); + //need restore all logical address if (cec_dev->cec_num > 1) cec_restore_logical_addr(CEC_B, cec_dev->cec_info.addr_enable); @@ -1784,12 +1987,13 @@ static void cec_rx_process(void) opcode = msg[1]; switch (opcode) { case CEC_OC_ACTIVE_SOURCE: - if (wake_ok == 0) { + /*if (wake_ok == 0) */ + { int phy_addr = msg[2] << 8 | msg[3]; if (phy_addr == 0xffff) break; - wake_ok = 1; + /*wake_ok = 1;*/ phy_addr |= (initiator << 16); writel(phy_addr, cec_dev->cec_reg + AO_RTI_STATUS_REG1); CEC_INFO("found wake up source:%x", phy_addr); @@ -1879,9 +2083,8 @@ static void cec_rx_process(void) break; default: - CEC_ERR("unsupported command:%x\n", opcode); - CEC_ERR("wake_ok=%d,hal_flag=0x%x\n", - wake_ok, cec_dev->hal_flag); + CEC_ERR("cec unsupported cmd:0x%x, halflg:0x%x\n", + opcode, cec_dev->hal_flag); break; } new_msg = 0; @@ -1890,10 +2093,12 @@ static void cec_rx_process(void) static bool cec_service_suspended(void) { /* service is not enabled */ - if (!(cec_dev->hal_flag & (1 << HDMI_OPTION_SERVICE_FLAG))) - return false; + /*if (!(cec_dev->hal_flag & (1 << HDMI_OPTION_SERVICE_FLAG)))*/ + /* return false;*/ + if (!(cec_dev->hal_flag & (1 << HDMI_OPTION_SYSTEM_CEC_CONTROL))) return true; + return false; } @@ -1905,7 +2110,7 @@ static void cec_task(struct work_struct *work) cec_cfg = cec_config(0, 0); if (cec_cfg & CEC_FUNC_CFG_CEC_ON) { /*cec module on*/ - if (cec_dev && (!wake_ok || cec_service_suspended()) + if (cec_dev && (/*!wake_ok || */cec_service_suspended()) && !(cec_dev->hal_flag & (1 << HDMI_OPTION_SYSTEM_CEC_CONTROL))) cec_rx_process(); @@ -2019,75 +2224,10 @@ static ssize_t port_num_show(struct class *cla, return sprintf(buf, "%d\n", cec_dev->port_num); } -static const char * const cec_reg_name1[] = { - "CEC_TX_MSG_LENGTH", - "CEC_TX_MSG_CMD", - "CEC_TX_WRITE_BUF", - "CEC_TX_CLEAR_BUF", - "CEC_RX_MSG_CMD", - "CEC_RX_CLEAR_BUF", - "CEC_LOGICAL_ADDR0", - "CEC_LOGICAL_ADDR1", - "CEC_LOGICAL_ADDR2", - "CEC_LOGICAL_ADDR3", - "CEC_LOGICAL_ADDR4", - "CEC_CLOCK_DIV_H", - "CEC_CLOCK_DIV_L" -}; - -static const char * const cec_reg_name2[] = { - "CEC_RX_MSG_LENGTH", - "CEC_RX_MSG_STATUS", - "CEC_RX_NUM_MSG", - "CEC_TX_MSG_STATUS", - "CEC_TX_NUM_MSG" -}; - -static const char * const ceca_reg_name3[] = { - "STAT_0_0", - "STAT_0_1", - "STAT_0_2", - "STAT_0_3", - "STAT_1_0", - "STAT_1_1", - "STAT_1_2" -}; - - static ssize_t dump_reg_show(struct class *cla, struct class_attribute *attr, char *b) { - int i, s = 0; - - if (ee_cec == CEC_B) - return dump_cecrx_reg(b); - - s += sprintf(b + s, "TX buffer:\n"); - for (i = 0; i <= CEC_TX_MSG_F_OP14; i++) - s += sprintf(b + s, "%2d:%2x\n", i, aocec_rd_reg(i)); - - for (i = 0; i < ARRAY_SIZE(cec_reg_name1); i++) { - s += sprintf(b + s, "%s:%2x\n", - cec_reg_name1[i], aocec_rd_reg(i + 0x10)); - } - - s += sprintf(b + s, "RX buffer:\n"); - for (i = 0; i <= CEC_TX_MSG_F_OP14; i++) - s += sprintf(b + s, "%2d:%2x\n", i, aocec_rd_reg(i + 0x80)); - - for (i = 0; i < ARRAY_SIZE(cec_reg_name2); i++) { - s += sprintf(b + s, "%s:%2x\n", - cec_reg_name2[i], aocec_rd_reg(i + 0x90)); - } - - if (cec_dev->plat_data->ceca_sts_reg) { - for (i = 0; i < ARRAY_SIZE(ceca_reg_name3); i++) { - s += sprintf(b + s, "%s:%2x\n", - ceca_reg_name3[i], aocec_rd_reg(i + 0xA0)); - } - } - - return s; + return dump_cecrx_reg(b); } static ssize_t arc_port_show(struct class *cla, @@ -2368,7 +2508,10 @@ static ssize_t dbg_store(struct class *cla, struct class_attribute *attr, CEC_ERR("wb cecb reg:0x%x val:0x%x\n", addr, val); hdmirx_cec_write(addr, val); } else if (token && strncmp(token, "dump", 4) == 0) { - dump_reg(); + token = kmalloc(2048, GFP_KERNEL); + dump_cecrx_reg(token); + CEC_ERR("%s\n", token); + kfree(token); } else if (token && strncmp(token, "status", 6) == 0) { cec_dump_info(); } else if (token && strncmp(token, "rao", 3) == 0) { @@ -2531,13 +2674,12 @@ static ssize_t hdmitx_cec_write(struct file *f, const char __user *buf, if (cec_cfg & CEC_FUNC_CFG_CEC_ON) { /*cec module on*/ ret = cec_ll_tx(tempbuf, size); - if (ret == CEC_FAIL_NACK) { - return -1; - } else { - return size; - } + } + + if (ret == CEC_FAIL_NACK) { + return -1; } else { - CEC_ERR("err:cec module disabled\n"); + return size; } return ret; @@ -2622,6 +2764,8 @@ void cec_dump_info(void) struct hdmi_port_info *port; CEC_ERR("driver date:%s\n", CEC_DRIVER_VERSION); + CEC_ERR("chip type:0x%x\n", + get_meson_cpu_version(MESON_CPU_VERSION_LVL_MAJOR)); CEC_ERR("cec sel:%d\n", ee_cec); CEC_ERR("cec_num:%d\n", cec_dev->cec_num); CEC_ERR("dev_type:%d\n", (unsigned int)cec_dev->dev_type); @@ -2826,7 +2970,7 @@ static long hdmitx_cec_ioctl(struct file *f, if (((cec_dev->port_seq >> i*4) & 0xF) == a) break; } - CEC_INFO("phy port:%d, ui port:%d\n", i, a); + CEC_INFO_L(L_2, "phy port:%d, ui port:%d\n", i, a); if ((tmp & (1 << i)) && (a != 0xF)) tmp = 1; @@ -2979,6 +3123,7 @@ static const struct cec_platform_data_s cec_g12a_data = { .line_bit = 3, .ee_to_ao = 1, .ceca_sts_reg = 0, + .ceca_ver = CECA_VER_0, .cecb_ver = CECB_VER_1, }; @@ -2987,6 +3132,7 @@ static const struct cec_platform_data_s cec_txl_data = { .line_bit = 7, .ee_to_ao = 0, .ceca_sts_reg = 0, + .ceca_ver = CECA_VER_0, .cecb_ver = CECB_VER_0, }; @@ -2995,9 +3141,27 @@ static const struct cec_platform_data_s cec_tl1_data = { .line_bit = 10, .ee_to_ao = 1, .ceca_sts_reg = 1, + .ceca_ver = CECA_VER_0, .cecb_ver = CECB_VER_2, }; +static const struct cec_platform_data_s cec_sm1_data = { + .line_reg = 1, + .line_bit = 3, + .ee_to_ao = 1, + .ceca_sts_reg = 1, + .ceca_ver = CECA_VER_1, + .cecb_ver = CECB_VER_2, +}; + +static const struct cec_platform_data_s cec_tm2_data = { + .line_reg = 0, + .line_bit = 3, + .ee_to_ao = 1, + .ceca_sts_reg = 1, + .ceca_ver = CECA_VER_1, + .cecb_ver = CECB_VER_2, +}; static const struct of_device_id aml_cec_dt_match[] = { { @@ -3020,6 +3184,14 @@ static const struct of_device_id aml_cec_dt_match[] = { .compatible = "amlogic, aocec-tl1", .data = &cec_tl1_data, }, + { + .compatible = "amlogic, aocec-sm1", + .data = &cec_sm1_data, + }, + { + .compatible = "amlogic, aocec-tm2", + .data = &cec_tm2_data, + }, {} }; #endif @@ -3062,6 +3234,7 @@ static int aml_cec_probe(struct platform_device *pdev) cec_dev->tx_dev = get_hdmitx_device(); cec_dev->cpu_type = get_cpu_type(); cec_dev->node = pdev->dev.of_node; + cec_dev->proble_finish = false; phy_addr_test = 0; CEC_ERR("cec driver date:%s\n", CEC_DRIVER_VERSION); cec_dbg_init(); @@ -3093,9 +3266,14 @@ static int aml_cec_probe(struct platform_device *pdev) /*get compatible matched device, to get chip related data*/ of_id = of_match_device(aml_cec_dt_match, &pdev->dev); - if (of_id != NULL) + if (of_id != NULL) { cec_dev->plat_data = (struct cec_platform_data_s *)of_id->data; - else + CEC_ERR("compatible:%s\n", of_id->compatible); + CEC_ERR("cecb_ver:0x%x\n", cec_dev->plat_data->cecb_ver); + CEC_ERR("line_reg:0x%x\n", cec_dev->plat_data->line_reg); + CEC_ERR("line_bit:0x%x\n", cec_dev->plat_data->line_bit); + CEC_ERR("ee_to_ao:0x%x\n", cec_dev->plat_data->ee_to_ao); + } else CEC_ERR("unable to get matched device\n"); cec_node_val_init(); @@ -3284,8 +3462,6 @@ static int aml_cec_probe(struct platform_device *pdev) /* irq set */ cec_irq_enable(false); - /* default enable all function*/ - cec_config(CEC_FUNC_CFG_ALL, 1); /* for init */ cec_pre_init(); /* cec hw module reset */ @@ -3373,6 +3549,7 @@ static int aml_cec_probe(struct platform_device *pdev) cec_irq_enable(true); CEC_ERR("%s success end\n", __func__); + cec_dev->proble_finish = true; return 0; tag_cec_msg_alloc_err: diff --git a/drivers/amlogic/cec/hdmi_ao_cec.h b/drivers/amlogic/cec/hdmi_ao_cec.h index 779d58c3f984..454ec2a3e0ef 100644 --- a/drivers/amlogic/cec/hdmi_ao_cec.h +++ b/drivers/amlogic/cec/hdmi_ao_cec.h @@ -19,7 +19,8 @@ #define __AO_CEC_H__ -#define CEC_DRIVER_VERSION "Ver 2019/1/7\n" + +#define CEC_DRIVER_VERSION "Ver 2019/3/25\n" #define CEC_FRAME_DELAY msecs_to_jiffies(400) #define CEC_DEV_NAME "aocec" @@ -29,6 +30,14 @@ #define CEC_PHY_PORT_NUM 4 #define HR_DELAY(n) (ktime_set(0, n * 1000 * 1000)) +enum cecaver { + /*first version*/ + CECA_VER_0 = 0, + + /*support multi logical address*/ + CECA_VER_1 = 1, +}; + enum cecbver { /*first version*/ CECB_VER_0 = 0, @@ -485,7 +494,8 @@ extern uint32_t hdmirx_rd_dwc(uint16_t addr); extern void hdmirx_wr_dwc(uint16_t addr, uint32_t data); extern unsigned int rd_reg_hhi(unsigned int offset); extern void wr_reg_hhi(unsigned int offset, unsigned int val); - +extern int cec_set_dev_info(uint8_t dev_idx); +int __attribute__((weak))cec_set_dev_info(uint8_t dev_idx); #else static inline unsigned long hdmirx_rd_top(unsigned long addr) { @@ -538,4 +548,6 @@ extern void cec_restore_logical_addr(unsigned int cec_sel, unsigned int addr_en); extern void cec_logicaddr_add(unsigned int cec_sel, unsigned int l_add); extern void cec_clear_all_logical_addr(unsigned int cec_sel); +extern int dump_cecrx_reg(char *b); + #endif /* __AO_CEC_H__ */ diff --git a/drivers/amlogic/clk/Makefile b/drivers/amlogic/clk/Makefile index 77fdb66e5b07..95486a70024a 100644 --- a/drivers/amlogic/clk/Makefile +++ b/drivers/amlogic/clk/Makefile @@ -18,5 +18,6 @@ obj-$(CONFIG_AMLOGIC_GX_CLK) += txl/ obj-$(CONFIG_AMLOGIC_GX_CLK) += g12a/ obj-$(CONFIG_AMLOGIC_GX_CLK) += g12b/ obj-$(CONFIG_AMLOGIC_GX_CLK) += tl1/ +obj-$(CONFIG_AMLOGIC_GX_CLK) += sm1/ obj-$(CONFIG_AMLOGIC_M8B_CLK) += m8b/ diff --git a/drivers/amlogic/clk/clk_measure.c b/drivers/amlogic/clk/clk_measure.c index ce5b13dda679..8473964233e4 100644 --- a/drivers/amlogic/clk/clk_measure.c +++ b/drivers/amlogic/clk/clk_measure.c @@ -50,10 +50,6 @@ static DEFINE_SPINLOCK(clk_measure_lock); #define CLKMSR_DEVICE_NAME "clkmsr" unsigned int clk_msr_index = 0xff; -#define AUDIO_FLAG BIT(16) -#define HHI_GEN_CLK_CNTL 0x8a -#define AO_RTI_PIN_MUX_REG1 0x18 -unsigned int audio_index; struct meson_clkmsr_data { const char * const *clk_table; @@ -164,36 +160,6 @@ static unsigned int meson_clk_util_ring_msr(unsigned int clk_mux) } -static unsigned int axg_clk_util_clk_msr(unsigned int clk_mux) -{ - unsigned int clk_val; - - if (clk_mux&AUDIO_FLAG) { - /*for audio*/ - /*set gen_clk_out: cts_msr_clk*/ - aml_write_hiubus(HHI_GEN_CLK_CNTL, 0xc800); - /*msr_clk_mux_sel*/ - writel_relaxed(((clk_mux&0xff)<<20)|(1<<19), msr_clk_reg0); - /*pinmux for GEN_CLK_EE*/ - aml_write_aobus(AO_RTI_PIN_MUX_REG1, 0x402230); - audio_index = clk_mux; - } else { - /*clear gen_clk_out: cts_msr_clk*/ - aml_write_hiubus(HHI_GEN_CLK_CNTL, 0x0); - /*measure clk*/ - clk_val = gxbb_clk_util_clk_msr(clk_mux); - /*for audio*/ - /*set gen_clk_out: cts_msr_clk*/ - aml_write_hiubus(HHI_GEN_CLK_CNTL, 0xc800); - /*msr_clk_mux_sel*/ - writel_relaxed(((audio_index&0xff)<<20)|(1<<19), msr_clk_reg0); - /*pinmux for GEN_CLK_EE*/ - aml_write_aobus(AO_RTI_PIN_MUX_REG1, 0x402230); - return clk_val; - } - return 0; -} - int m8b_clk_measure(struct seq_file *s, void *what, unsigned int index) { static const char * const clk_table[] = { @@ -603,11 +569,11 @@ int axg_clk_measure(struct seq_file *s, void *what, unsigned int index) if (index == 0xff) { for (i = 0; i < len; i++) seq_printf(s, "[%2d][%10d]%s\n", - i, axg_clk_util_clk_msr(i), + i, gxbb_clk_util_clk_msr(i), clk_table[i]); return 0; } - seq_printf(s, "[%10d]%s\n", axg_clk_util_clk_msr(index), + seq_printf(s, "[%10d]%s\n", gxbb_clk_util_clk_msr(index), clk_table[index]); clk_msr_index = 0xff; return 0; @@ -1218,10 +1184,8 @@ int meson_clk_measure(unsigned int clk_mux) case MESON_CPU_MAJOR_ID_TXLX: case MESON_CPU_MAJOR_ID_G12A: case MESON_CPU_MAJOR_ID_G12B: - clk_val = gxbb_clk_util_clk_msr(clk_mux); - break; case MESON_CPU_MAJOR_ID_AXG: - clk_val = axg_clk_util_clk_msr(clk_mux); + clk_val = gxbb_clk_util_clk_msr(clk_mux); break; default: pr_info("Unsupported chip clk measure\n"); @@ -1528,10 +1492,148 @@ static const struct meson_clkmsr_data tl1_data = { .clk_msr_function = gxbb_clk_util_clk_msr, }; +static const char * const sm1_table[] = { + [127] = "clk_csi2_data ", + [126] = "csi_phy0_clk_out ", + [125] = "earcrx_pll_test_clk ", + [124] = "earcx_pll_(dmac)_clk ", + [123] = "audio_resampled_clk ", + [122] = "mod_audio_pdm_dclk_o ", + [121] = "audio_spdifin_mst_clk ", + [120] = "audio_spdifout_mst_clk ", + [119] = "audio_spdifout_b_mst_clk ", + [118] = "audio_pdm_sysclk ", + [117] = "audio_resampleA_clk ", + [116] = "audio_tdmin_a_sclk ", + [115] = "audio_tdmin_b_sclk ", + [114] = "audio_tdmin_c_sclk ", + [113] = "audio_tdmin_lb_sclk ", + [112] = "audio_tdmout_a_sclk ", + [111] = "audio_tdmout_b_sclk ", + [110] = "audio_tdmout_c_sclk ", + [109] = "c_alocker_out_clk ", + [108] = "c_alocker_in_clk ", + [107] = "au_dac_clk_g128x ", + [106] = "ephy_test_clk ", + [105] = "arm_ring_osc_clk_out[16] ", + [104] = "arm_ring_osc_clk_out[15] ", + [103] = "arm_ring_osc_clk_out[14] ", + [102] = "arm_ring_osc_clk_out[13] ", + [101] = "arm_ring_osc_clk_out[12] ", + [100] = "arm_ring_osc_clk_out[11] ", + [99] = "arm_ring_osc_clk_out[10] ", + [98] = "cts_ts_clk ", + [97] = "cts_vpu_clkb_tmp ", + [96] = "cts_vpu_clkb ", + [95] = "eth_phy_plltxclk ", + [94] = "eth_phy_rxclk ", + [93] = "vad_clk ", + [92] = "nna_axi_clk ", + [91] = "nna_core_clk ", + [90] = "cts_hdmitx_sys_clk ", + [89] = "HDMI_CLK_TODIG ", + [88] = "csi2_adapt_clk ", + [87] = "mipi_csi_phy_clk ", + [86] = "arm_ring_osc_clk_out[9] ", + [85] = "arm_ring_osc_clk_out[8] ", + [84] = "co_tx_clk ", + [83] = "co_rx_clk ", + [82] = "cts_ge2d_clk ", + [81] = "cts_vapbclk ", + [80] = "rng_ring_osc_clk[3] ", + [79] = "rng_ring_osc_clk[2] ", + [78] = "rng_ring_osc_clk[1] ", + [77] = "rng_ring_osc_clk[0] ", + [76] = "arm_ring_osc_clk_out[7] ", + [75] = "cts_hevcf_clk ", + [74] = "arm_ring_osc_clk_out[6] ", + [73] = "cts_pwm_C_clk ", + [72] = "cts_pwm_D_clk ", + [71] = "cts_pwm_E_clk ", + [70] = "cts_pwm_F_clk ", + [69] = "cts_hdcp22_skpclk ", + [68] = "cts_hdcp22_esmclk ", + [67] = "cts_dsi_phy_clk ", + [66] = "cts_vid_lock_clk ", + [65] = "cts_spicc_0_clk ", + [64] = "cts_spicc_1_clk ", + [63] = "cts_dsi_meas_clk ", + [62] = "cts_hevcb_clk ", + [61] = "gpio_clk_msr ", + [60] = "arm_ring_osc_clk_out[5] ", + [59] = "cts_hcodec_clk ", + [58] = "cts_wave420l_bclk ", + [57] = "cts_wave420l_cclk ", + [56] = "cts_wave420l_aclk ", + [55] = "vid_pll_div_clk_out ", + [54] = "cts_vpu_clkc ", + [53] = "cts_sd_emmc_clk_A ", + [52] = "cts_sd_emmc_clk_B ", + [51] = "cts_sd_emmc_clk_C ", + [50] = "mp3_clk_out ", + [49] = "mp2_clk_out ", + [48] = "mp1_clk_out ", + [47] = "ddr_dpll_pt_clk ", + [46] = "cts_vpu_clk ", + [45] = "cts_pwm_A_clk ", + [44] = "cts_pwm_B_clk ", + [43] = "fclk_div5 ", + [42] = "mp0_clk_out ", + [41] = "mac_eth_rx_clk_rmii ", + [40] = "arm_ring_osc_clk_out[4] ", + [39] = "cts_bt656_clk0 ", + [38] = "cts_vdin_meas_clk ", + [37] = "cts_cdac_clk_c ", + [36] = "cts_hdmi_tx_pixel_clk ", + [35] = "cts_mali_clk ", + [34] = "eth_mppll_50m_ckout ", + [33] = "1'b0 ", + [32] = "cts_vdec_clk ", + [31] = "mpll_clk_test_out ", + [30] = "pcie_clk_inn ", + [29] = "pcie_clk_inp ", + [28] = "cts_sar_adc_clk ", + [27] = "co_clkin_to_mac ", + [26] = "sc_clk_int ", + [25] = "cts_eth_clk_rmii ", + [24] = "cts_eth_clk125Mhz ", + [23] = "mpll_clk_50m ", + [22] = "mac_eth_phy_ref_clk ", + [21] = "lcd_an_clk_ph3 ", + [20] = "rtc_osc_clk_out ", + [19] = "lcd_an_clk_ph2 ", + [18] = "sys_cpu_clk_div16 ", + [17] = "sys_pll_div16 ", + [16] = "cts_FEC_CLK_2 ", + [15] = "cts_FEC_CLK_1 ", + [14] = "cts_FEC_CLK_0 ", + [13] = "mod_tcon_clko ", + [12] = "hifi_pll_clk ", + [11] = "mac_eth_tx_clk ", + [10] = "cts_vdac_clk ", + [9] = "cts_encl_clk ", + [8] = "cts_encp_clk ", + [7] = "clk81 ", + [6] = "cts_enci_clk ", + [5] = "gp1_pll_clk ", + [4] = "gp0_pll_clk ", + [3] = "am_ring_osc_clk_out_ee[3]", + [2] = "am_ring_osc_clk_out_ee[2]", + [1] = "am_ring_osc_clk_out_ee[1]", + [0] = "am_ring_osc_clk_out_ee[0]", +}; + +static const struct meson_clkmsr_data sm1_data = { + .clk_table = sm1_table, + .table_size = ARRAY_SIZE(sm1_table), + .clk_msr_function = gxbb_clk_util_clk_msr, +}; + static const struct of_device_id meson_clkmsr_dt_match[] = { { .compatible = "amlogic, gxl_measure",}, { .compatible = "amlogic, m8b_measure",}, { .compatible = "amlogic,tl1-measure", .data = &tl1_data }, + { .compatible = "amlogic, sm1-measure", .data = &sm1_data }, {}, }; diff --git a/drivers/amlogic/clk/g12a/g12a.c b/drivers/amlogic/clk/g12a/g12a.c index 9cf950f9f241..c9c8f3295fe2 100644 --- a/drivers/amlogic/clk/g12a/g12a.c +++ b/drivers/amlogic/clk/g12a/g12a.c @@ -175,8 +175,8 @@ static struct meson_clk_pll g12a_hifi_pll = { .shift = 16, .width = 2, }, - .rate_table = g12a_pll_rate_table, - .rate_count = ARRAY_SIZE(g12a_pll_rate_table), + .rate_table = g12a_hifi_pll_rate_table, + .rate_count = ARRAY_SIZE(g12a_hifi_pll_rate_table), .lock = &clk_lock, .hw.init = &(struct clk_init_data){ .name = "hifi_pll", @@ -970,6 +970,20 @@ static void __init g12a_clkc_init(struct device_node *np) __func__); goto iounmap; } + + if (of_property_read_bool(np, "own-dsu-clk")) { + if (clks[CLKID_DSU_CLK]) { + clk_set_parent(clks[CLKID_DSU_CLK], + clks[CLKID_CPU_CLK]); + /* set sm1_dsu_pre_clk to 1.5G, gp1 pll is 1.5G */ + clk_set_rate(clks[CLKID_DSU_PRE_CLK], 1500000000); + clk_prepare_enable(clks[CLKID_DSU_PRE_CLK]); + /* set sm1_dsu_pre_clk as dsu_pre's parent */ + clk_set_parent(clks[CLKID_DSU_CLK], + clks[CLKID_DSU_PRE_CLK]); + } + } + pr_debug("%s: cpu clk register notifier ok!", __func__); ret = of_clk_add_provider(np, of_clk_src_onecell_get, @@ -988,4 +1002,5 @@ iounmap: CLK_OF_DECLARE(g12a, "amlogic,g12a-clkc", g12a_clkc_init); CLK_OF_DECLARE(g12b, "amlogic,g12b-clkc-1", g12a_clkc_init); +CLK_OF_DECLARE(sm1, "amlogic,sm1-clkc-1", g12a_clkc_init); diff --git a/drivers/amlogic/clk/g12a/g12a.h b/drivers/amlogic/clk/g12a/g12a.h index 40b9174e5a13..7c787a141498 100644 --- a/drivers/amlogic/clk/g12a/g12a.h +++ b/drivers/amlogic/clk/g12a/g12a.h @@ -117,7 +117,7 @@ #define HHI_SYS1_PLL_CNTL5 0x394 /* 0xe5 offset in data sheet */ #define HHI_SYS1_PLL_CNTL6 0x398 /* 0xe6 offset in data sheet */ /*****************/ - +#define HHI_BT656_CLK_CNTL 0x3d4 /* 0xf5 offset in data sheet */ #define HHI_SPICC_CLK_CNTL 0x3dc /* 0xf7 offset in data sheet */ /* AO registers*/ #define AO_RTI_PWR_CNTL_REG0 0x10 /* 0x4 offset in data sheet */ @@ -143,8 +143,11 @@ static const struct pll_rate_table g12a_pll_rate_table[] = { PLL_RATE(1104000000ULL, 184, 1, 2), /*DCO=4416M*/ PLL_RATE(1200000000ULL, 200, 1, 2), /*DCO=4800M*/ PLL_RATE(1296000000ULL, 216, 1, 2), /*DCO=5184M*/ + PLL_RATE(1302000000ULL, 217, 1, 2), /*DCO=5208M*/ PLL_RATE(1398000000ULL, 233, 1, 2), /*DCO=5592M*/ + PLL_RATE(1404000000ULL, 234, 1, 2), /*DCO=5616M*/ PLL_RATE(1494000000ULL, 249, 1, 2), /*DCO=5976M*/ + PLL_RATE(1500000000ULL, 125, 1, 1), /*DCO=3000M*/ PLL_RATE(1512000000ULL, 126, 1, 1), /*DCO=3024M*/ PLL_RATE(1608000000ULL, 134, 1, 1), /*DCO=3216M*/ PLL_RATE(1704000000ULL, 142, 1, 1), /*DCO=3408M*/ @@ -153,17 +156,14 @@ static const struct pll_rate_table g12a_pll_rate_table[] = { PLL_RATE(1896000000ULL, 158, 1, 1), /*DCO=3792M*/ PLL_RATE(1908000000ULL, 159, 1, 1), /*DCO=3816M*/ PLL_RATE(1920000000ULL, 160, 1, 1), /*DCO=3840M*/ - PLL_RATE(1932000000ULL, 161, 1, 1), /*DCO=3864M*/ - PLL_RATE(1944000000ULL, 162, 1, 1), /*DCO=3888M*/ - PLL_RATE(1956000000ULL, 163, 1, 1), /*DCO=3912M*/ - PLL_RATE(1968000000ULL, 164, 1, 1), /*DCO=3936M*/ - PLL_RATE(1980000000ULL, 165, 1, 1), /*DCO=3960M*/ PLL_RATE(1992000000ULL, 166, 1, 1), /*DCO=3984M*/ PLL_RATE(2004000000ULL, 167, 1, 1), /*DCO=4008M*/ PLL_RATE(2016000000ULL, 168, 1, 1), /*DCO=4032M*/ PLL_RATE(2100000000ULL, 175, 1, 1), /*DCO=4200M*/ PLL_RATE(2196000000ULL, 183, 1, 1), /*DCO=4392M*/ + PLL_RATE(2208000000ULL, 184, 1, 1), /*DCO=4416M*/ PLL_RATE(2292000000ULL, 191, 1, 1), /*DCO=4584M*/ + PLL_RATE(2304000000ULL, 192, 1, 1), /*DCO=4608M*/ PLL_RATE(2400000000ULL, 200, 1, 1), /*DCO=4800M*/ PLL_RATE(2496000000ULL, 208, 1, 1), /*DCO=4992M*/ PLL_RATE(2592000000ULL, 216, 1, 1), /*DCO=5184M*/ @@ -223,4 +223,8 @@ static const struct pll_rate_table g12a_pcie_pll_rate_table[] = { PLL_RATE(100000000, 150, 0, 9), { /* sentinel */ }, }; + +static const struct pll_rate_table g12a_hifi_pll_rate_table[] = { + PLL_RATE(666000000ULL, 222, 1, 3), /*DCO=5328M*/ +}; #endif /* __G12A_H */ diff --git a/drivers/amlogic/clk/g12a/g12a_ao.c b/drivers/amlogic/clk/g12a/g12a_ao.c index 6ea40b9d4be8..40319856b59e 100644 --- a/drivers/amlogic/clk/g12a/g12a_ao.c +++ b/drivers/amlogic/clk/g12a/g12a_ao.c @@ -145,5 +145,6 @@ static void __init g12a_aoclkc_init(struct device_node *np) CLK_OF_DECLARE(g12a, "amlogic,g12a-aoclkc", g12a_aoclkc_init); CLK_OF_DECLARE(g12b, "amlogic,g12b-aoclkc", g12a_aoclkc_init); +CLK_OF_DECLARE(sm1, "amlogic,sm1-aoclkc", g12a_aoclkc_init); diff --git a/drivers/amlogic/clk/g12a/g12a_clk-pll.c b/drivers/amlogic/clk/g12a/g12a_clk-pll.c index 858a088f4daf..f82d5938127e 100644 --- a/drivers/amlogic/clk/g12a/g12a_clk-pll.c +++ b/drivers/amlogic/clk/g12a/g12a_clk-pll.c @@ -51,10 +51,10 @@ /* G12A */ //#define G12A_PCIE_PLL_CNTL 0x400106c8 -#define G12A_PCIE_PLL_CNTL0_0 0x20090496 -#define G12A_PCIE_PLL_CNTL0_1 0x30090496 -#define G12A_PCIE_PLL_CNTL0_2 0x34090496 -#define G12A_PCIE_PLL_CNTL0_3 0x14090496 +#define G12A_PCIE_PLL_CNTL0_0 0x28060464 +#define G12A_PCIE_PLL_CNTL0_1 0x38060464 +#define G12A_PCIE_PLL_CNTL0_2 0x3c060464 +#define G12A_PCIE_PLL_CNTL0_3 0x1c060464 #define G12A_PCIE_PLL_CNTL1 0x00000000 #define G12A_PCIE_PLL_CNTL2 0x00001100 #define G12A_PCIE_PLL_CNTL2_ 0x00001000 @@ -64,19 +64,6 @@ #define G12A_PCIE_PLL_CNTL5 0x68000048 #define G12A_PCIE_PLL_CNTL5_ 0x68000068 -#define G12B_PCIE_PLL_CNTL0_0 0x200c04c8 -#define G12B_PCIE_PLL_CNTL0_1 0x300c04c8 -#define G12B_PCIE_PLL_CNTL0_2 0x340c04c8 -#define G12B_PCIE_PLL_CNTL0_3 0x140c04c8 -#define G12B_PCIE_PLL_CNTL1 0x00000000 -#define G12B_PCIE_PLL_CNTL2 0x00001100 -#define G12B_PCIE_PLL_CNTL2_ 0x00001000 -#define G12B_PCIE_PLL_CNTL3 0x10058e00 -#define G12B_PCIE_PLL_CNTL4 0x000100c0 -#define G12B_PCIE_PLL_CNTL4_ 0x008100c0 -#define G12B_PCIE_PLL_CNTL5 0x68000048 -#define G12B_PCIE_PLL_CNTL5_ 0x68000068 - #define G12A_SYS_PLL_CNTL1 0x00000000 #define G12A_SYS_PLL_CNTL2 0x00000000 #define G12A_SYS_PLL_CNTL3 0x48681c00 @@ -89,7 +76,7 @@ #define G12A_SYS1_PLL_CNTL4 0x88770290 #define G12A_SYS1_PLL_CNTL5 0x39272000 -#define G12A_GP0_PLL_CNTL1 0x00000000 +#define G12A_GP0_PLL_CNTL1 0x00007800 #define G12A_GP0_PLL_CNTL2 0x00000000 #define G12A_GP0_PLL_CNTL3 0x48681c00 #define G12A_GP0_PLL_CNTL4 0x33771290 @@ -179,14 +166,23 @@ static long meson_g12a_pll_round_rate(struct clk_hw *hw, unsigned long rate, struct meson_clk_pll *pll = to_meson_clk_pll(hw); const struct pll_rate_table *rate_table = pll->rate_table; int i; + u64 ret_rate = 0; for (i = 0; i < pll->rate_count; i++) { - if (rate <= rate_table[i].rate) - return rate_table[i].rate; + if (rate <= rate_table[i].rate) { + ret_rate = rate_table[i].rate; + if (!strcmp(clk_hw_get_name(hw), "sys_pll") + || !strcmp(clk_hw_get_name(hw), "sys1_pll")) + do_div(ret_rate, 1000); + return ret_rate; + } } /* else return the smallest value */ - return rate_table[0].rate; + ret_rate = rate_table[0].rate; + if (!strcmp(clk_hw_get_name(hw), "sys_pll")) + do_div(ret_rate, 1000); + return ret_rate; } static const struct pll_rate_table *meson_g12a_get_pll_settings @@ -233,6 +229,9 @@ static int meson_g12a_pll_set_rate(struct clk_hw *hw, unsigned long rate, if (parent_rate == 0 || rate == 0) return -EINVAL; + if (!strcmp(clk_hw_get_name(hw), "sys_pll") + || !strcmp(clk_hw_get_name(hw), "sys1_pll")) + rate *= 1000; old_rate = rate; @@ -259,65 +258,34 @@ static int meson_g12a_pll_set_rate(struct clk_hw *hw, unsigned long rate, cntlbase = pll->base + p->reg_off; if (!strcmp(clk_hw_get_name(hw), "pcie_pll")) { - if (get_cpu_type() == MESON_CPU_MAJOR_ID_G12A) { - writel(G12A_PCIE_PLL_CNTL0_0, - cntlbase + (unsigned long)(0*4)); - writel(G12A_PCIE_PLL_CNTL0_1, - cntlbase + (unsigned long)(0*4)); - writel(G12A_PCIE_PLL_CNTL1, - cntlbase + (unsigned long)(1*4)); - writel(G12A_PCIE_PLL_CNTL2, - cntlbase + (unsigned long)(2*4)); - writel(G12A_PCIE_PLL_CNTL3, - cntlbase + (unsigned long)(3*4)); - writel(G12A_PCIE_PLL_CNTL4, - cntlbase + (unsigned long)(4*4)); - writel(G12A_PCIE_PLL_CNTL5, - cntlbase + (unsigned long)(5*4)); - writel(G12A_PCIE_PLL_CNTL5_, - cntlbase + (unsigned long)(5*4)); - udelay(20); - writel(G12A_PCIE_PLL_CNTL4_, - cntlbase + (unsigned long)(4*4)); - udelay(10); - /*set pcie_apll_afc_start bit*/ - writel(G12A_PCIE_PLL_CNTL0_2, - cntlbase + (unsigned long)(0*4)); - writel(G12A_PCIE_PLL_CNTL0_3, - cntlbase + (unsigned long)(0*4)); - udelay(10); - writel(G12A_PCIE_PLL_CNTL2_, - cntlbase + (unsigned long)(2*4)); - } else if (get_cpu_type() == MESON_CPU_MAJOR_ID_G12B) { - writel(G12B_PCIE_PLL_CNTL0_0, - cntlbase + (unsigned long)(0*4)); - writel(G12B_PCIE_PLL_CNTL0_1, - cntlbase + (unsigned long)(0*4)); - writel(G12B_PCIE_PLL_CNTL1, - cntlbase + (unsigned long)(1*4)); - writel(G12B_PCIE_PLL_CNTL2, - cntlbase + (unsigned long)(2*4)); - writel(G12B_PCIE_PLL_CNTL3, - cntlbase + (unsigned long)(3*4)); - writel(G12B_PCIE_PLL_CNTL4, - cntlbase + (unsigned long)(4*4)); - writel(G12B_PCIE_PLL_CNTL5, - cntlbase + (unsigned long)(5*4)); - writel(G12B_PCIE_PLL_CNTL5_, - cntlbase + (unsigned long)(5*4)); - udelay(20); - writel(G12B_PCIE_PLL_CNTL4_, - cntlbase + (unsigned long)(4*4)); - udelay(10); - /*set pcie_apll_afc_start bit*/ - writel(G12B_PCIE_PLL_CNTL0_2, - cntlbase + (unsigned long)(0*4)); - writel(G12B_PCIE_PLL_CNTL0_3, - cntlbase + (unsigned long)(0*4)); - udelay(10); - writel(G12B_PCIE_PLL_CNTL2_, - cntlbase + (unsigned long)(2*4)); - } + writel(G12A_PCIE_PLL_CNTL0_0, + cntlbase + (unsigned long)(0*4)); + writel(G12A_PCIE_PLL_CNTL0_1, + cntlbase + (unsigned long)(0*4)); + writel(G12A_PCIE_PLL_CNTL1, + cntlbase + (unsigned long)(1*4)); + writel(G12A_PCIE_PLL_CNTL2, + cntlbase + (unsigned long)(2*4)); + writel(G12A_PCIE_PLL_CNTL3, + cntlbase + (unsigned long)(3*4)); + writel(G12A_PCIE_PLL_CNTL4, + cntlbase + (unsigned long)(4*4)); + writel(G12A_PCIE_PLL_CNTL5, + cntlbase + (unsigned long)(5*4)); + writel(G12A_PCIE_PLL_CNTL5_, + cntlbase + (unsigned long)(5*4)); + udelay(20); + writel(G12A_PCIE_PLL_CNTL4_, + cntlbase + (unsigned long)(4*4)); + udelay(10); + /*set pcie_apll_afc_start bit*/ + writel(G12A_PCIE_PLL_CNTL0_2, + cntlbase + (unsigned long)(0*4)); + writel(G12A_PCIE_PLL_CNTL0_3, + cntlbase + (unsigned long)(0*4)); + udelay(10); + writel(G12A_PCIE_PLL_CNTL2_, + cntlbase + (unsigned long)(2*4)); goto OUT; } else if (!strcmp(clk_hw_get_name(hw), "sys_pll")) { writel((readl(cntlbase) | MESON_PLL_RESET) @@ -351,7 +319,8 @@ static int meson_g12a_pll_set_rate(struct clk_hw *hw, unsigned long rate, writel(G12A_PLL_CNTL6, cntlbase + (unsigned long)(6*4)); udelay(10); - } else if (!strcmp(clk_hw_get_name(hw), "gp0_pll")) { + } else if (!strcmp(clk_hw_get_name(hw), "gp0_pll") + || !strcmp(clk_hw_get_name(hw), "gp1_pll")) { writel((readl(cntlbase) | MESON_PLL_RESET) & (~MESON_PLL_ENABLE), cntlbase); writel(G12A_GP0_PLL_CNTL1, @@ -370,15 +339,15 @@ static int meson_g12a_pll_set_rate(struct clk_hw *hw, unsigned long rate, } else if (!strcmp(clk_hw_get_name(hw), "hifi_pll")) { writel((readl(cntlbase) | MESON_PLL_RESET) & (~MESON_PLL_ENABLE), cntlbase); - writel(G12A_GP0_PLL_CNTL1, + writel(G12A_HIFI_PLL_CNTL1, cntlbase + (unsigned long)(1*4)); - writel(G12A_GP0_PLL_CNTL2, + writel(G12A_HIFI_PLL_CNTL2, cntlbase + (unsigned long)(2*4)); - writel(G12A_GP0_PLL_CNTL3, + writel(G12A_HIFI_PLL_CNTL3, cntlbase + (unsigned long)(3*4)); - writel(G12A_GP0_PLL_CNTL4, + writel(G12A_HIFI_PLL_CNTL4, cntlbase + (unsigned long)(4*4)); - writel(G12A_GP0_PLL_CNTL5, + writel(G12A_HIFI_PLL_CNTL5, cntlbase + (unsigned long)(5*4)); writel(G12A_PLL_CNTL6, cntlbase + (unsigned long)(6*4)); @@ -475,6 +444,7 @@ static int meson_g12a_pll_enable(struct clk_hw *hw) } if (!strcmp(clk_hw_get_name(hw), "gp0_pll") + || !strcmp(clk_hw_get_name(hw), "gp1_pll") || !strcmp(clk_hw_get_name(hw), "hifi_pll") || !strcmp(clk_hw_get_name(hw), "pcie_pll") || !strcmp(clk_hw_get_name(hw), "sys_pll") @@ -524,6 +494,11 @@ static void meson_g12a_pll_disable(struct clk_hw *hw) writel(readl(pll->base + p->reg_off) & (~MESON_PLL_ENABLE), pll->base + p->reg_off); + if (!strcmp(clk_hw_get_name(hw), "pcie_pll")) { + writel(0x20000060, + pll->base + p->reg_off + 0x14); + } + if (pll->lock) spin_unlock_irqrestore(pll->lock, flags); } diff --git a/drivers/amlogic/clk/g12a/g12a_clk_media.c b/drivers/amlogic/clk/g12a/g12a_clk_media.c index a4371eb41711..c7377060d304 100644 --- a/drivers/amlogic/clk/g12a/g12a_clk_media.c +++ b/drivers/amlogic/clk/g12a/g12a_clk_media.c @@ -734,13 +734,13 @@ static struct clk_mux vapb_mux = { }; static struct clk_hw *vapb_clk_hws[] = { - [CLKID_VPU_P0_MUX - CLKID_VPU_P0_MUX] = &vapb_p0_mux.hw, - [CLKID_VPU_P0_DIV - CLKID_VPU_P0_MUX] = &vapb_p0_div.hw, - [CLKID_VPU_P0_GATE - CLKID_VPU_P0_MUX] = &vapb_p0_gate.hw, - [CLKID_VPU_P1_MUX - CLKID_VPU_P0_MUX] = &vapb_p1_mux.hw, - [CLKID_VPU_P1_DIV - CLKID_VPU_P0_MUX] = &vapb_p1_div.hw, - [CLKID_VPU_P1_GATE - CLKID_VPU_P0_MUX] = &vapb_p1_gate.hw, - [CLKID_VPU_MUX - CLKID_VPU_P0_MUX] = &vapb_mux.hw, + [CLKID_VAPB_P0_MUX - CLKID_VAPB_P0_MUX] = &vapb_p0_mux.hw, + [CLKID_VAPB_P0_DIV - CLKID_VAPB_P0_MUX] = &vapb_p0_div.hw, + [CLKID_VAPB_P0_GATE - CLKID_VAPB_P0_MUX] = &vapb_p0_gate.hw, + [CLKID_VAPB_P1_MUX - CLKID_VAPB_P0_MUX] = &vapb_p1_mux.hw, + [CLKID_VAPB_P1_DIV - CLKID_VAPB_P0_MUX] = &vapb_p1_div.hw, + [CLKID_VAPB_P1_GATE - CLKID_VAPB_P0_MUX] = &vapb_p1_gate.hw, + [CLKID_VAPB_MUX - CLKID_VAPB_P0_MUX] = &vapb_mux.hw, }; static struct clk_gate ge2d_gate = { @@ -768,7 +768,7 @@ static struct clk_mux vpu_clkb_tmp_mux = { .name = "vpu_clkb_tmp_mux", .ops = &clk_mux_ops, .parent_names = vpu_clkb_tmp_parent_names, - .num_parents = 8, + .num_parents = ARRAY_SIZE(vpu_clkb_tmp_parent_names), .flags = CLK_GET_RATE_NOCACHE, }, }; @@ -822,7 +822,7 @@ static struct clk_gate vpu_clkb_gate = { .bit_idx = 8, .lock = &clk_lock, .hw.init = &(struct clk_init_data) { - .name = "vpu_clkb_tmp_gate", + .name = "vpu_clkb_gate", .ops = &clk_gate_ops, .parent_names = (const char *[]){ "vpu_clkb_div" }, .num_parents = 1, @@ -943,6 +943,56 @@ static struct clk_hw *vpu_clkc_hws[] = { [CLKID_VPU_CLKC_MUX - CLKID_VPU_CLKC_P0_MUX] = &vpu_clkc_mux.hw, }; +/* cts_bt656 */ +static const char * const bt656_parent_names[] = { "fclk_div2", +"fclk_div3", "fclk_div5", "fclk_div7" }; + +static struct clk_mux bt656_mux = { + .reg = (void *)HHI_BT656_CLK_CNTL, + .mask = 0x3, + .shift = 9, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "bt656_mux", + .ops = &clk_mux_ops, + .parent_names = bt656_parent_names, + .num_parents = ARRAY_SIZE(bt656_parent_names), + .flags = CLK_GET_RATE_NOCACHE, + }, +}; + +static struct clk_divider bt656_div = { + .reg = (void *)HHI_BT656_CLK_CNTL, + .shift = 0, + .width = 7, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "bt656_div", + .ops = &clk_divider_ops, + .parent_names = (const char *[]){ "bt656_mux" }, + .num_parents = 1, + .flags = CLK_GET_RATE_NOCACHE, + }, +}; + +static struct clk_gate bt656_gate = { + .reg = (void *)HHI_BT656_CLK_CNTL, + .bit_idx = 7, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data) { + .name = "bt656_gate", + .ops = &clk_gate_ops, + .parent_names = (const char *[]){ "bt656_div" }, + .num_parents = 1, + .flags = CLK_GET_RATE_NOCACHE, + }, +}; + +static struct clk_hw *bt656_clk_hws[] = { + [0] = &bt656_mux.hw, + [1] = &bt656_div.hw, + [2] = &bt656_gate.hw, +}; void meson_g12a_media_init(void) { @@ -1024,6 +1074,22 @@ void meson_g12a_media_init(void) vpu_clkc_p1_gate.reg = clk_base + (unsigned long)(vpu_clkc_p1_gate.reg); vpu_clkc_mux.reg = clk_base + (unsigned long)(vpu_clkc_mux.reg); + /* bt656 clk */ + bt656_mux.reg = clk_base + (unsigned long)(bt656_mux.reg); + bt656_div.reg = clk_base + (unsigned long)(bt656_div.reg); + bt656_gate.reg = clk_base + (unsigned long)(bt656_gate.reg); + + clks[CLKID_BT656_COMP] = clk_register_composite(NULL, + "bt656_composite", + bt656_parent_names, ARRAY_SIZE(bt656_parent_names), + bt656_clk_hws[0], &clk_mux_ops, + bt656_clk_hws[1], &clk_divider_ops, + bt656_clk_hws[2], &clk_gate_ops, 0); + if (IS_ERR(clks[CLKID_BT656_COMP])) + panic("%s: %d clk_register_composite bt656_composite error\n", + __func__, __LINE__); + + clks[CLKID_DSI_MEAS_COMP] = clk_register_composite(NULL, "dsi_meas_composite", g12a_meas_parent_names, 8, diff --git a/drivers/amlogic/clk/g12a/g12a_clk_sdemmc.c b/drivers/amlogic/clk/g12a/g12a_clk_sdemmc.c index 6ee8f916ee55..091278958054 100644 --- a/drivers/amlogic/clk/g12a/g12a_clk_sdemmc.c +++ b/drivers/amlogic/clk/g12a/g12a_clk_sdemmc.c @@ -27,7 +27,7 @@ #include "g12a.h" static const char * const sd_emmc_parent_names[] = { "xtal", "fclk_div2", - "fclk_div3", "fclk_div5", "fclk_div7", "mpll2", "mpll3", "gp0_pll" }; + "fclk_div3", "fclk_div5", "fclk_div2p5", "mpll2", "mpll3", "gp0_pll" }; static struct clk_mux sd_emmc_p0_mux_A = { .reg = (void *)HHI_SD_EMMC_CLK_CNTL, diff --git a/drivers/amlogic/clk/sm1/Makefile b/drivers/amlogic/clk/sm1/Makefile new file mode 100644 index 000000000000..e36dd8e5ef2d --- /dev/null +++ b/drivers/amlogic/clk/sm1/Makefile @@ -0,0 +1,5 @@ +# +# Makefile for Meson SM1 clk +# + +obj-$(CONFIG_AMLOGIC_GX_CLK) += sm1.o diff --git a/drivers/amlogic/clk/sm1/sm1.c b/drivers/amlogic/clk/sm1/sm1.c new file mode 100644 index 000000000000..9b985abdc917 --- /dev/null +++ b/drivers/amlogic/clk/sm1/sm1.c @@ -0,0 +1,449 @@ +/* + * drivers/amlogic/clk/sm1/sm1.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 +#include +#include +#include +#include +#include +#include + +#include "../clkc.h" +#include "../g12a/g12a.h" +#include "sm1.h" + +static struct meson_clk_pll sm1_gp1_pll = { + .m = { + .reg_off = HHI_GP1_PLL_CNTL0, + .shift = 0, + .width = 9, + }, + .n = { + .reg_off = HHI_GP1_PLL_CNTL0, + .shift = 10, + .width = 5, + }, + .od = { + .reg_off = HHI_GP1_PLL_CNTL0, + .shift = 16, + .width = 3, + }, + .rate_table = g12a_pll_rate_table, + .rate_count = ARRAY_SIZE(g12a_pll_rate_table), + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "gp1_pll", + .ops = &meson_g12a_pll_ops, + .parent_names = (const char *[]){ "xtal" }, + .num_parents = 1, + .flags = CLK_GET_RATE_NOCACHE, + }, +}; + +static const char * const media_parent_names[] = { "xtal", + "gp0_pll", "hifi_pll", "fclk_div2p5", "fclk_div3", "fclk_div4", + "fclk_div5", "fclk_div7"}; + +static struct clk_mux cts_vipnanoq_core_clk_mux = { + .reg = (void *)HHI_VIPNANOQ_CLK_CNTL, + .mask = 0x7, + .shift = 9, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "cts_vipnanoq_core_clk_mux", + .ops = &clk_mux_ops, + .parent_names = media_parent_names, + .num_parents = 8, + .flags = CLK_GET_RATE_NOCACHE, + }, +}; + +static struct clk_divider cts_vipnanoq_core_clk_div = { + .reg = (void *)HHI_VIPNANOQ_CLK_CNTL, + .shift = 0, + .width = 7, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "cts_vipnanoq_core_clk_div", + .ops = &clk_divider_ops, + .parent_names = (const char *[]){ "cts_vipnanoq_core_clk_mux" }, + .num_parents = 1, + .flags = CLK_GET_RATE_NOCACHE, + }, +}; + +static struct clk_gate cts_vipnanoq_core_clk_gate = { + .reg = (void *)HHI_VIPNANOQ_CLK_CNTL, + .bit_idx = 8, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data) { + .name = "cts_vipnanoq_core_clk_gate", + .ops = &clk_gate_ops, + .parent_names = (const char *[]){ "cts_vipnanoq_core_clk_div" }, + .num_parents = 1, + .flags = CLK_GET_RATE_NOCACHE, + }, +}; + +static struct clk_mux cts_vipnanoq_axi_clk_mux = { + .reg = (void *)HHI_VIPNANOQ_CLK_CNTL, + .mask = 0x7, + .shift = 25, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "cts_vipnanoq_axi_clk_mux", + .ops = &clk_mux_ops, + .parent_names = media_parent_names, + .num_parents = 8, + .flags = CLK_GET_RATE_NOCACHE, + }, +}; + +static struct clk_divider cts_vipnanoq_axi_clk_div = { + .reg = (void *)HHI_VIPNANOQ_CLK_CNTL, + .shift = 16, + .width = 7, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "cts_vipnanoq_axi_clk_div", + .ops = &clk_divider_ops, + .parent_names = (const char *[]){ "cts_vipnanoq_axi_clk_mux" }, + .num_parents = 1, + .flags = CLK_GET_RATE_NOCACHE, + }, +}; + +static struct clk_gate cts_vipnanoq_axi_clk_gate = { + .reg = (void *)HHI_VIPNANOQ_CLK_CNTL, + .bit_idx = 24, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data) { + .name = "cts_vipnanoq_axi_clk_gate", + .ops = &clk_gate_ops, + .parent_names = (const char *[]){ "cts_vipnanoq_axi_clk_div" }, + .num_parents = 1, + .flags = CLK_GET_RATE_NOCACHE, + }, +}; +static struct clk_mux sm1_dsu_pre_src_clk_mux0 = { + .reg = (void *)HHI_SYS_CPU_CLK_CNTL5, + .mask = 0x3, + .shift = 0, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "dsu_pre_src0", + .ops = &clk_mux_ops, + .parent_names = (const char *[]){ "xtal", "fclk_div2", + "fclk_div3", "gp1_pll" }, + .num_parents = 4, + .flags = CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, + }, +}; + +static struct clk_mux sm1_dsu_pre_src_clk_mux1 = { + .reg = (void *)HHI_SYS_CPU_CLK_CNTL5, + .mask = 0x3, + .shift = 16, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "dsu_pre_src1", + .ops = &clk_mux_ops, + .parent_names = (const char *[]){ "xtal", "fclk_div2", + "fclk_div3", "gp1_pll" }, + .num_parents = 4, + .flags = CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, + }, +}; + +static struct clk_divider sm1_dsu_clk_div0 = { + .reg = (void *)HHI_SYS_CPU_CLK_CNTL5, + .shift = 4, + .width = 5, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "dsu_clk_div0", + .ops = &clk_divider_ops, + .parent_names = (const char *[]){ "dsu_pre_src0" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_divider sm1_dsu_clk_div1 = { + .reg = (void *)HHI_SYS_CPU_CLK_CNTL5, + .shift = 20, + .width = 5, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "dsu_clk_div1", + .ops = &clk_divider_ops, + .parent_names = (const char *[]){ "dsu_pre_src1" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_mux sm1_dsu_pre_clk_mux0 = { + .reg = (void *)HHI_SYS_CPU_CLK_CNTL5, + .mask = 0x1, + .shift = 2, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "dsu_pre0", + .ops = &clk_mux_ops, + .parent_names = (const char *[]){ "dsu_pre_src0", + "dsu_clk_div0",}, + .num_parents = 2, + .flags = CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, + }, +}; + +static struct clk_mux sm1_dsu_pre_clk_mux1 = { + .reg = (void *)HHI_SYS_CPU_CLK_CNTL5, + .mask = 0x1, + .shift = 18, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "dsu_pre1", + .ops = &clk_mux_ops, + .parent_names = (const char *[]){ "dsu_pre_src1", + "dsu_clk_div1",}, + .num_parents = 2, + .flags = CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, + }, +}; + +static struct clk_mux sm1_dsu_pre_post_clk_mux = { + .reg = (void *)HHI_SYS_CPU_CLK_CNTL5, + .mask = 0x1, + .shift = 10, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "dsu_pre_post", + .ops = &clk_mux_ops, + .parent_names = (const char *[]){ "dsu_pre0", + "dsu_pre1",}, + .num_parents = 2, + .flags = CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, + }, +}; + +static struct clk_mux sm1_dsu_pre_clk = { + .reg = (void *)HHI_SYS_CPU_CLK_CNTL5, + .mask = 0x1, + .shift = 11, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "dsu_pre_clk", + .ops = &clk_mux_ops, + .parent_names = (const char *[]){ "dsu_pre_post", + "sys_pll",}, + .num_parents = 2, + .flags = CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, + }, +}; + +static struct clk_mux sm1_dsu_clk = { + .reg = (void *)HHI_SYS_CPU_CLK_CNTL6, + .mask = 0x1, + .shift = 27, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "dsu_clk", + .ops = &clk_mux_ops, + .parent_names = (const char *[]){ "cpu_clk", + "dsu_pre_clk",}, + .num_parents = 2, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct meson_clk_pll *const sm1_clk_plls[] = { + &sm1_gp1_pll, +}; + +static MESON_GATE(sm1_csi_dig, HHI_GCLK_MPEG1, 18); +static MESON_GATE(sm1_nna, HHI_GCLK_MPEG1, 19); +static MESON_GATE(sm1_parser1, HHI_GCLK_MPEG1, 28); +static MESON_GATE(sm1_csi_host, HHI_GCLK_MPEG2, 16); +static MESON_GATE(sm1_csi_adpat, HHI_GCLK_MPEG2, 17); +static MESON_GATE(sm1_temp_sensor, HHI_GCLK_MPEG2, 22); +static MESON_GATE(sm1_csi_phy, HHI_GCLK_MPEG2, 29); + +static struct clk_gate *sm1_clk_gates[] = { + &sm1_csi_dig, + &sm1_nna, + &sm1_parser1, + &sm1_csi_host, + &sm1_csi_adpat, + &sm1_temp_sensor, + &sm1_csi_phy, +}; + +static struct clk_hw *sm1_clk_hws[] = { + [CLKID_GP1_PLL - CLKID_SM1_ADD_BASE] = &sm1_gp1_pll.hw, + [CLKID_DSU_PRE_SRC0 - CLKID_SM1_ADD_BASE] = + &sm1_dsu_pre_src_clk_mux0.hw, + [CLKID_DSU_PRE_SRC1 - CLKID_SM1_ADD_BASE] = + &sm1_dsu_pre_src_clk_mux1.hw, + [CLKID_DSU_CLK_DIV0 - CLKID_SM1_ADD_BASE] = + &sm1_dsu_clk_div0.hw, + [CLKID_DSU_CLK_DIV1 - CLKID_SM1_ADD_BASE] = + &sm1_dsu_clk_div1.hw, + [CLKID_DSU_PRE_MUX0 - CLKID_SM1_ADD_BASE] = + &sm1_dsu_pre_clk_mux0.hw, + [CLKID_DSU_PRE_MUX1 - CLKID_SM1_ADD_BASE] = + &sm1_dsu_pre_clk_mux1.hw, + [CLKID_DSU_PRE_POST_MUX - CLKID_SM1_ADD_BASE] = + &sm1_dsu_pre_post_clk_mux.hw, + [CLKID_DSU_PRE_CLK - CLKID_SM1_ADD_BASE] = + &sm1_dsu_pre_clk.hw, + [CLKID_DSU_CLK - CLKID_SM1_ADD_BASE] = &sm1_dsu_clk.hw, + [CLKID_CSI_DIG_CLK - CLKID_SM1_ADD_BASE] = + &sm1_csi_dig.hw, + [CLKID_NNA_CLK - CLKID_SM1_ADD_BASE] = + &sm1_nna.hw, + [CLKID_PARSER1_CLK - CLKID_SM1_ADD_BASE] = + &sm1_parser1.hw, + [CLKID_CSI_HOST_CLK - CLKID_SM1_ADD_BASE] = + &sm1_csi_host.hw, + [CLKID_CSI_ADPAT_CLK - CLKID_SM1_ADD_BASE] = + &sm1_csi_adpat.hw, + [CLKID_TEMP_SENSOR_CLK - CLKID_SM1_ADD_BASE] = + &sm1_temp_sensor.hw, + [CLKID_CSI_PHY_CLK - CLKID_SM1_ADD_BASE] = + &sm1_csi_phy.hw, +}; + +static void __init sm1_clkc_init(struct device_node *np) +{ + int ret = 0, clkid, i; + + if (!clk_base) + clk_base = of_iomap(np, 0); + if (!clk_base) { + pr_err("%s: Unable to map clk base\n", __func__); + return; + } + for (i = 0; i < ARRAY_SIZE(sm1_clk_plls); i++) + sm1_clk_plls[i]->base = clk_base; + + sm1_dsu_pre_src_clk_mux0.reg = clk_base + + (unsigned long)sm1_dsu_pre_src_clk_mux0.reg; + sm1_dsu_pre_src_clk_mux1.reg = clk_base + + (unsigned long)sm1_dsu_pre_src_clk_mux1.reg; + sm1_dsu_clk_div0.reg = clk_base + + (unsigned long)sm1_dsu_clk_div0.reg; + sm1_dsu_clk_div1.reg = clk_base + + (unsigned long)sm1_dsu_clk_div1.reg; + sm1_dsu_pre_clk_mux0.reg = clk_base + + (unsigned long)sm1_dsu_pre_clk_mux0.reg; + sm1_dsu_pre_clk_mux1.reg = clk_base + + (unsigned long)sm1_dsu_pre_clk_mux1.reg; + sm1_dsu_pre_post_clk_mux.reg = clk_base + + (unsigned long)sm1_dsu_pre_post_clk_mux.reg; + sm1_dsu_pre_clk.reg = clk_base + + (unsigned long)sm1_dsu_pre_clk.reg; + sm1_dsu_clk.reg = clk_base + + (unsigned long)sm1_dsu_clk.reg; + cts_vipnanoq_core_clk_mux.reg = clk_base + + (unsigned long)(cts_vipnanoq_core_clk_mux.reg); + cts_vipnanoq_core_clk_gate.reg = clk_base + + (unsigned long)(cts_vipnanoq_core_clk_gate.reg); + cts_vipnanoq_core_clk_div.reg = clk_base + + (unsigned long)(cts_vipnanoq_core_clk_div.reg); + cts_vipnanoq_axi_clk_mux.reg = clk_base + + (unsigned long)(cts_vipnanoq_axi_clk_mux.reg); + cts_vipnanoq_axi_clk_gate.reg = clk_base + + (unsigned long)(cts_vipnanoq_axi_clk_gate.reg); + cts_vipnanoq_axi_clk_div.reg = clk_base + + (unsigned long)(cts_vipnanoq_axi_clk_div.reg); + /* Populate base address for gates */ + for (i = 0; i < ARRAY_SIZE(sm1_clk_gates); i++) + sm1_clk_gates[i]->reg = clk_base + + (unsigned long)sm1_clk_gates[i]->reg; + if (!clks) { + clks = kzalloc(NR_CLKS*sizeof(struct clk *), GFP_KERNEL); + if (!clks) { + pr_err("%s: alloc clks fail!", __func__); + return; + } + clk_numbers = NR_CLKS; + } + + /* + * register all clks + */ + + for (clkid = 0; clkid < ARRAY_SIZE(sm1_clk_hws); clkid++) { + if (sm1_clk_hws[clkid]) { + clks[clkid + CLKID_SM1_ADD_BASE] + = clk_register(NULL, sm1_clk_hws[clkid]); + if (IS_ERR(clks[clkid + CLKID_SM1_ADD_BASE])) { + pr_err("%s: failed to register %s\n", __func__, + clk_hw_get_name(sm1_clk_hws[clkid])); + goto iounmap; + } + } + } + clks[CLKID_VNANOQ_CORE_CLK_COMP] = clk_register_composite(NULL, + "cts_vipnanoq_core_clk_composite", + media_parent_names, 8, + &cts_vipnanoq_core_clk_mux.hw, + &clk_mux_ops, + &cts_vipnanoq_core_clk_div.hw, + &clk_divider_ops, + &cts_vipnanoq_core_clk_gate.hw, + &clk_gate_ops, 0); + if (IS_ERR(clks[CLKID_VNANOQ_CORE_CLK_COMP])) + panic("%s: %d register cts_vipnanoq_core_clk_composite error\n", + __func__, __LINE__); + + clks[CLKID_VNANOQ_AXI_CLK_COMP] = clk_register_composite(NULL, + "cts_vipnanoq_axi_clk_composite", + media_parent_names, 8, + &cts_vipnanoq_axi_clk_mux.hw, + &clk_mux_ops, + &cts_vipnanoq_axi_clk_div.hw, + &clk_divider_ops, + &cts_vipnanoq_axi_clk_gate.hw, + &clk_gate_ops, 0); + if (IS_ERR(clks[CLKID_VNANOQ_AXI_CLK_COMP])) + panic("%s: %d register cts_vipnanoq_axi_clk_composite error\n", + __func__, __LINE__); + if (clks[CLKID_CPU_CLK]) { + if (!of_property_read_bool(np, "own-dsu-clk")) + return; + /* set cpu clk as dsu_clk's parent*/ + clk_set_parent(sm1_dsu_clk.hw.clk, clks[CLKID_CPU_CLK]); + /* set sm1_dsu_pre_clk to 1.5G, gp1 pll is 1.5G */ + clk_set_rate(sm1_dsu_pre_clk.hw.clk, 1500000000); + clk_prepare_enable(sm1_dsu_pre_clk.hw.clk); + /* set sm1_dsu_pre_clk as dsu_clk's parent */ + clk_set_parent(sm1_dsu_clk.hw.clk, sm1_dsu_pre_clk.hw.clk); + } + return; + +iounmap: + iounmap(clk_base); + pr_info("%s: %d: ret: %d\n", __func__, __LINE__, ret); +} + +CLK_OF_DECLARE(sm1, "amlogic,sm1-clkc-2", sm1_clkc_init); + + diff --git a/drivers/amlogic/clk/sm1/sm1.h b/drivers/amlogic/clk/sm1/sm1.h new file mode 100644 index 000000000000..d937329277bd --- /dev/null +++ b/drivers/amlogic/clk/sm1/sm1.h @@ -0,0 +1,33 @@ +/* + * drivers/amlogic/clk/sm1/sm1.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 __SM1_H +#define __SM1_H + +/* + * Clock controller register offsets + * + * Register offsets from the data sheet are listed in comment blocks below. + * Those offsets must be multiplied by 4 before adding them to the base address + * to get the right value + */ + +#define HHI_GP1_PLL_CNTL0 0x60 /* 0x18 offset in data sheet */ +#define HHI_SYS_CPU_CLK_CNTL5 0x21C /* 0x87 offset in data sheet */ +#define HHI_SYS_CPU_CLK_CNTL6 0x220 /* 0x88 offset in data sheet */ + +#endif /* __SM1_H */ diff --git a/drivers/amlogic/clk/tl1/tl1.h b/drivers/amlogic/clk/tl1/tl1.h index 92d899658554..e3a7b56dbdc3 100644 --- a/drivers/amlogic/clk/tl1/tl1.h +++ b/drivers/amlogic/clk/tl1/tl1.h @@ -158,6 +158,7 @@ static const struct pll_rate_table tl1_pll_rate_table[] = { PLL_RATE(1104000000ULL, 184, 1, 2), /*DCO=4416M*/ PLL_RATE(1200000000ULL, 200, 1, 2), /*DCO=4800M*/ PLL_RATE(1296000000ULL, 216, 1, 2), /*DCO=5184M*/ + PLL_RATE(1302000000ULL, 217, 1, 2), /*DCO=5208M*/ PLL_RATE(1398000000ULL, 233, 1, 2), /*DCO=5592M*/ PLL_RATE(1494000000ULL, 249, 1, 2), /*DCO=5976M*/ PLL_RATE(1512000000ULL, 126, 1, 1), /*DCO=3024M*/ @@ -167,10 +168,13 @@ static const struct pll_rate_table tl1_pll_rate_table[] = { PLL_RATE(1896000000ULL, 158, 1, 1), /*DCO=3792M*/ PLL_RATE(1908000000ULL, 159, 1, 1), /*DCO=3816M*/ PLL_RATE(1920000000ULL, 160, 1, 1), /*DCO=3840M*/ + PLL_RATE(2004000000ULL, 167, 1, 1), /*DCO=4008M*/ PLL_RATE(2016000000ULL, 168, 1, 1), /*DCO=4032M*/ PLL_RATE(2100000000ULL, 175, 1, 1), /*DCO=4200M*/ PLL_RATE(2196000000ULL, 183, 1, 1), /*DCO=4392M*/ + PLL_RATE(2208000000ULL, 184, 1, 1), /*DCO=4416M*/ PLL_RATE(2292000000ULL, 191, 1, 1), /*DCO=4584M*/ + PLL_RATE(2304000000ULL, 192, 1, 1), /*DCO=4608M*/ PLL_RATE(2400000000ULL, 200, 1, 1), /*DCO=4800M*/ PLL_RATE(2496000000ULL, 208, 1, 1), /*DCO=4992M*/ PLL_RATE(2592000000ULL, 216, 1, 1), /*DCO=5184M*/ diff --git a/drivers/amlogic/clk/tl1/tl1_clk_sdemmc.c b/drivers/amlogic/clk/tl1/tl1_clk_sdemmc.c index 37c37402f025..8ee3df8cc4f2 100644 --- a/drivers/amlogic/clk/tl1/tl1_clk_sdemmc.c +++ b/drivers/amlogic/clk/tl1/tl1_clk_sdemmc.c @@ -27,7 +27,7 @@ #include "tl1.h" PNAME(sd_emmc_parent_names) = { "xtal", "fclk_div2", - "fclk_div3", "fclk_div5", "fclk_div7", "mpll2", "mpll3", "gp0" }; + "fclk_div3", "fclk_div5", "fclk_div2p5", "mpll2", "mpll3", "gp0_pll" }; /*sd_emmc B*/ static MUX(sd_emmc_p0_mux_B, HHI_SD_EMMC_CLK_CNTL, 0x7, 25, sd_emmc_parent_names, CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED); diff --git a/drivers/amlogic/clk/txl/txl.c b/drivers/amlogic/clk/txl/txl.c index c0bc2234bb6d..79941f30ff41 100644 --- a/drivers/amlogic/clk/txl/txl.c +++ b/drivers/amlogic/clk/txl/txl.c @@ -945,7 +945,6 @@ static void __init txl_clkc_init(struct device_node *np) pr_err("%s: Unable to map clk base\n", __func__); return; } - /* Populate base address for PLLs */ for (i = 0; i < ARRAY_SIZE(txl_clk_plls); i++) txl_clk_plls[i]->base = clk_base; @@ -994,6 +993,7 @@ static void __init txl_clkc_init(struct device_node *np) clk_data.clks = clks; clk_data.clk_num = NR_CLKS; + clk_numbers = NR_CLKS; /*register all clks*/ for (clkid = 0; clkid < CLOCK_GATE; clkid++) { @@ -1005,7 +1005,7 @@ static void __init txl_clkc_init(struct device_node *np) meson_txl_sdemmc_init(); meson_txl_media_init(); - meson_init_gpu(); + meson_txl_gpu_init(); parent_hw = clk_hw_get_parent(&txl_cpu_clk.mux.hw); parent_clk = parent_hw->clk; diff --git a/drivers/amlogic/cpu_hotplug/cpu_hotplug.c b/drivers/amlogic/cpu_hotplug/cpu_hotplug.c index 7c260c91e7ca..adf996eef981 100644 --- a/drivers/amlogic/cpu_hotplug/cpu_hotplug.c +++ b/drivers/amlogic/cpu_hotplug/cpu_hotplug.c @@ -97,7 +97,7 @@ void cpu_hotplug_set_max(unsigned int num, int clustr) { unsigned int cpu_online; - if (!num || clustr > hpg.clusters) { + if (clustr > hpg.clusters) { dev_err(NULL, " %s <:%d %d>\n", __func__, num, clustr); return; } @@ -177,7 +177,7 @@ static int __ref cpu_hotplug_thread(void *data) } } else if (flg == CPU_HOTPLUG_UNPLUG) { cnt = 0; - while ((online = cpu_num_online(clustr)) > 1) { + while ((online = cpu_num_online(clustr)) > 0) { if (online <= hpg.gov_num[clustr] && online <= hpg.max_num[clustr]) break; @@ -200,7 +200,8 @@ static int __ref cpu_hotplug_thread(void *data) goto clear_cpu; } if (!cpu_online(target) || - cpumask_first(hpg.cpumask) == target) + (cpumask_first(hpg.cpumask) == target && + clustr == 0)) goto clear_cpu; device_offline(get_cpu_device(target)); clear_cpu: @@ -250,8 +251,7 @@ static ssize_t store_hotplug_max_cpus(struct kobject *kobj, for (c = 0; c < hpg.clusters; c++) { max = input & 0xff; - if (max) - cpu_hotplug_set_max(max, c); + cpu_hotplug_set_max(max, c); input = input >> 8; } return count; diff --git a/drivers/amlogic/cpufreq/meson-cpufreq.c b/drivers/amlogic/cpufreq/meson-cpufreq.c index ce9b432f9f5e..8905b994f392 100644 --- a/drivers/amlogic/cpufreq/meson-cpufreq.c +++ b/drivers/amlogic/cpufreq/meson-cpufreq.c @@ -30,46 +30,18 @@ #include #include #include -#include #include #include #include #include #include #include +#include #include "../../regulator/internal.h" +#include #include "../../base/power/opp/opp.h" -/* Currently we support only two clusters */ -#define MAX_CLUSTERS 2 - -/*core power supply*/ -#define CORE_SUPPLY "cpu" - -/* Core Clocks */ -#define CORE_CLK "core_clk" -#define LOW_FREQ_CLK_PARENT "low_freq_clk_parent" -#define HIGH_FREQ_CLK_PARENT "high_freq_clk_parent" - -static struct thermal_cooling_device *cdev[MAX_CLUSTERS]; -static struct clk *clk[MAX_CLUSTERS]; -static struct cpufreq_frequency_table *freq_table[MAX_CLUSTERS]; - -/* Default voltage_tolerance */ -#define DEF_VOLT_TOL 0 - -/*mid rate for set parent,Khz*/ -static unsigned int mid_rate = (1000*1000); -static unsigned int gap_rate = (10*1000*1000); - -struct meson_cpufreq_driver_data { - struct device *cpu_dev; - struct regulator *reg; - /* voltage tolerance in percentage */ - unsigned int volt_tol; - struct clk *high_freq_clk_p; - struct clk *low_freq_clk_p; -}; +#include "meson-cpufreq.h" #ifdef CONFIG_ARCH_MESON64_ODROIDN2 #define OF_NODE_CPU_OPP_0 "/cpu_opp_table0/" /* Core A53 */ @@ -81,10 +53,6 @@ static unsigned long max_freq[2] = { }; #endif -static DEFINE_PER_CPU(unsigned int, physical_cluster); - -static struct mutex cluster_lock[MAX_CLUSTERS]; - static unsigned int meson_cpufreq_get_rate(unsigned int cpu) { @@ -303,7 +271,10 @@ static int meson_cpufreq_set_target(struct cpufreq_policy *policy, } } + freqs.old = freq_old / 1000; + freqs.new = freq_new / 1000; /*scale clock frequency*/ + cpufreq_freq_transition_begin(policy, &freqs); ret = meson_cpufreq_set_rate(policy, cur_cluster, freq_new / 1000); if (ret) { @@ -316,6 +287,7 @@ static int meson_cpufreq_set_target(struct cpufreq_policy *policy, } return ret; } + cpufreq_freq_transition_end(policy, &freqs, ret); /*cpufreq down,change voltage after frequency*/ if (freq_new < freq_old) { ret = meson_regulator_set_volate(cpu_reg, volt_old, @@ -323,8 +295,12 @@ static int meson_cpufreq_set_target(struct cpufreq_policy *policy, if (ret) { pr_err("failed to scale volt %u %u down: %d\n", volt_new, volt_tol, ret); - meson_cpufreq_set_rate(policy, cur_cluster, + freqs.old = freq_new / 1000; + freqs.new = freq_old / 1000; + cpufreq_freq_transition_begin(policy, &freqs); + ret = meson_cpufreq_set_rate(policy, cur_cluster, freq_old / 1000); + cpufreq_freq_transition_end(policy, &freqs, ret); } } @@ -346,6 +322,133 @@ static inline u32 get_table_max(struct cpufreq_frequency_table *table) return max_freq; } +int get_cpufreq_tables_efuse(u32 cur_cluster) +{ + int ret, efuse_info; + u32 freq, vol; + + efuse_info = scpi_get_cpuinfo(cur_cluster, &freq, &vol); + if (efuse_info) + pr_err("%s,get invalid efuse_info = %d by mailbox!\n", + __func__, efuse_info); + + pr_info("%s:efuse info for cpufreq = %u\n", __func__, freq); + WARN_ON(freq && freq < EFUSE_CPUFREQ_MIN); + freq = DIV_ROUND_UP(freq, CLK_DIV) * CLK_DIV; + pr_info("%s:efuse adjust cpufreq = %u\n", __func__, freq); + if (freq >= hispeed_cpufreq_max) + ret = HISPEED_INDEX; + else if (freq >= medspeed_cpufreq_max && freq < hispeed_cpufreq_max) + ret = MEDSPEED_INDEX; + else + ret = LOSPEED_INDEX; + + return ret; +} + +int choose_cpufreq_tables_index(const struct device_node *np, u32 cur_cluster) +{ + int ret = 0; + + cpufreq_tables_supply = of_property_read_bool(np, "diff_tables_supply"); + if (cpufreq_tables_supply) { + /*choose appropriate cpufreq tables according efuse info*/ + if (of_property_read_u32(np, "hispeed_cpufreq_max", + &hispeed_cpufreq_max)) { + pr_err("%s:don't find the node \n", + __func__); + hispeed_cpufreq_max = 0; + return ret; + } + + if (of_property_read_u32(np, "medspeed_cpufreq_max", + &medspeed_cpufreq_max)) { + pr_err("%s:don't find the node \n", + __func__); + medspeed_cpufreq_max = 0; + return ret; + } + + if (of_property_read_u32(np, "lospeed_cpufreq_max", + &lospeed_cpufreq_max)) { + pr_err("%s:don't find the node \n", + __func__); + lospeed_cpufreq_max = 0; + return ret; + } + + ret = get_cpufreq_tables_efuse(cur_cluster); + pr_info("%s:hispeed_max %u,medspeed_max %u,lospeed_max %u,tables_index %u\n", + __func__, hispeed_cpufreq_max, + medspeed_cpufreq_max, lospeed_cpufreq_max, ret); + + } + + return ret; +} + +static int meson_cpufreq_transition_notifier(struct notifier_block *nb, + unsigned long val, void *data) +{ + struct cpufreq_freqs *freq = data; + struct meson_cpufreq_driver_data *cpufreq_data = + to_meson_dvfs_cpu_nb(nb); + struct cpufreq_policy *policy = cpufreq_data->policy; + struct clk *dsu_clk = cpufreq_data->clk_dsu; + struct clk *dsu_cpu_parent = policy->clk; + struct clk *dsu_pre_parent = cpufreq_data->clk_dsu_pre; + int ret = 0; + static bool first_set = true; + + if (!dsu_clk || !dsu_cpu_parent || !dsu_pre_parent) + return 0; + + pr_debug("%s,event %ld,freq->old_rate =%u,freq->new_rate =%u!\n", + __func__, val, freq->old, freq->new); + switch (val) { + case CPUFREQ_PRECHANGE: + if (freq->new > MID_RATE) { + pr_debug("%s,dsu clk switch parent to dsu pre!\n", + __func__); + if (first_set) { + clk_set_rate(dsu_pre_parent, MID_RATE * 1000); + first_set = false; + pr_info("first set gp1 pll to 1.5G!\n"); + } + if (__clk_get_enable_count(dsu_pre_parent) == 0) { + ret = clk_prepare_enable(dsu_pre_parent); + if (ret) { + pr_err("%s: CPU%d gp1 pll enable failed\n", + __func__, policy->cpu); + return ret; + } + } + + ret = clk_set_parent(dsu_clk, dsu_pre_parent); + } + + return ret; + case CPUFREQ_POSTCHANGE: + if (freq->new <= MID_RATE) { + pr_debug("%s,dsu clk switch parent to cpu!\n", + __func__); + ret = clk_set_parent(dsu_clk, dsu_cpu_parent); + if (__clk_get_enable_count(dsu_pre_parent) >= 1) + clk_disable_unprepare(dsu_pre_parent); + + } + + return ret; + default: + return 0; + } + return 0; +} + +static struct notifier_block meson_cpufreq_notifier_block = { + .notifier_call = meson_cpufreq_transition_notifier, +}; + /* CPU initialization */ static int meson_cpufreq_init(struct cpufreq_policy *policy) { @@ -355,11 +458,11 @@ static int meson_cpufreq_init(struct cpufreq_policy *policy) struct regulator *cpu_reg = NULL; struct meson_cpufreq_driver_data *cpufreq_data; struct clk *low_freq_clk_p, *high_freq_clk_p = NULL; + struct clk *dsu_clk, *dsu_pre_parent; unsigned int transition_latency = CPUFREQ_ETERNAL; unsigned int volt_tol = 0; unsigned long freq_hz = 0; - int cpu = 0; - int ret = 0; + int cpu = 0, ret = 0, tables_index; #ifdef CONFIG_ARCH_MESON64_ODROIDN2 int i = 0; #endif @@ -407,6 +510,14 @@ static int meson_cpufreq_init(struct cpufreq_policy *policy) goto free_clk; } + /*setting low_freq_clk_p to 1G,default 24M*/ + ret = clk_set_rate(low_freq_clk_p, mid_rate * 1000); + if (ret) { + pr_err("%s: error in setting low_freq_clk_p rate!\n", + __func__); + goto free_clk; + } + high_freq_clk_p = of_clk_get_by_name(np, HIGH_FREQ_CLK_PARENT); if (IS_ERR(high_freq_clk_p)) { pr_err("%s: Failed to get high parent for cpu: %d,cluster: %d\n", @@ -415,6 +526,18 @@ static int meson_cpufreq_init(struct cpufreq_policy *policy) goto free_clk; } + dsu_clk = of_clk_get_by_name(np, DSU_CLK); + if (IS_ERR(dsu_clk)) { + dsu_clk = NULL; + pr_debug("%s: ignor dsu clk!\n", __func__); + } + + dsu_pre_parent = of_clk_get_by_name(np, DSU_PRE_PARENT); + if (IS_ERR(dsu_pre_parent)) { + dsu_pre_parent = NULL; + pr_debug("%s: ignor dsu pre parent clk!\n", __func__); + } + cpu_reg = devm_regulator_get(cpu_dev, CORE_SUPPLY); if (IS_ERR(cpu_reg)) { pr_err("%s:failed to get regulator, %ld\n", __func__, @@ -427,15 +550,12 @@ static int meson_cpufreq_init(struct cpufreq_policy *policy) volt_tol = DEF_VOLT_TOL; pr_info("value of voltage_tolerance %u\n", volt_tol); - if (cur_cluster < MAX_CLUSTERS) { - int cpu; - + if (cur_cluster < MAX_CLUSTERS) cpumask_copy(policy->cpus, topology_core_cpumask(policy->cpu)); - for_each_cpu(cpu, policy->cpus) - per_cpu(physical_cluster, cpu) = cur_cluster; - } - ret = dev_pm_opp_of_cpumask_add_table(policy->cpus); + tables_index = choose_cpufreq_tables_index(np, cur_cluster); + ret = dev_pm_opp_of_cpumask_add_table_indexed(policy->cpus, + tables_index); if (ret) { pr_err("%s: init_opp_table failed, cpu: %d, cluster: %d, err: %d\n", __func__, cpu_dev->id, cur_cluster, ret); @@ -472,11 +592,24 @@ static int meson_cpufreq_init(struct cpufreq_policy *policy) if (of_property_read_u32(np, "clock-latency", &transition_latency)) policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; + if (dsu_clk && dsu_pre_parent) { + cpufreq_data->freq_transition = meson_cpufreq_notifier_block; + ret = cpufreq_register_notifier(&cpufreq_data->freq_transition, + CPUFREQ_TRANSITION_NOTIFIER); + if (ret) { + dev_err(cpu_dev, "failed to register cpufreq notifier!\n"); + goto fail_cpufreq_unregister; + } + } + cpufreq_data->cpu_dev = cpu_dev; cpufreq_data->low_freq_clk_p = low_freq_clk_p; cpufreq_data->high_freq_clk_p = high_freq_clk_p; + cpufreq_data->clk_dsu = dsu_clk; + cpufreq_data->clk_dsu_pre = dsu_pre_parent; cpufreq_data->reg = cpu_reg; cpufreq_data->volt_tol = volt_tol; + cpufreq_data->policy = policy; policy->driver_data = cpufreq_data; policy->clk = clk[cur_cluster]; policy->cpuinfo.transition_latency = transition_latency; @@ -497,6 +630,11 @@ static int meson_cpufreq_init(struct cpufreq_policy *policy) dev_info(cpu_dev, "%s: CPU %d initialized\n", __func__, policy->cpu); return ret; +fail_cpufreq_unregister: + if (dsu_clk && dsu_pre_parent) { + cpufreq_unregister_notifier(&cpufreq_data->freq_transition, + CPUFREQ_TRANSITION_NOTIFIER); + } free_opp_table: if (policy->freq_table != NULL) { dev_pm_opp_free_cpufreq_table(cpu_dev, @@ -574,18 +712,13 @@ __setup("max_freq_a73=", get_max_freq_a73); static int meson_cpufreq_exit(struct cpufreq_policy *policy) { struct device *cpu_dev; - struct sprd_cpufreq_driver_data *cpufreq_data; + struct meson_cpufreq_driver_data *cpufreq_data; int cur_cluster = topology_physical_package_id(policy->cpu); cpufreq_data = policy->driver_data; if (cpufreq_data == NULL) return 0; - if (cur_cluster < MAX_CLUSTERS) { - cpufreq_cooling_unregister(cdev[cur_cluster]); - cdev[cur_cluster] = NULL; - } - cpu_dev = get_cpu_device(policy->cpu); if (!cpu_dev) { pr_err("%s: failed to get cpu%d device\n", __func__, @@ -620,7 +753,8 @@ static struct cpufreq_driver meson_cpufreq_driver = { .name = "arm-big-little", .flags = CPUFREQ_STICKY | CPUFREQ_HAVE_GOVERNOR_PER_POLICY | - CPUFREQ_NEED_INITIAL_FREQ_CHECK, + CPUFREQ_NEED_INITIAL_FREQ_CHECK | + CPUFREQ_ASYNC_NOTIFICATION, .verify = cpufreq_generic_frequency_table_verify, .target_index = meson_cpufreq_set_target, .get = meson_cpufreq_get_rate, @@ -631,8 +765,6 @@ static struct cpufreq_driver meson_cpufreq_driver = { .resume = meson_cpufreq_resume, }; -static int meson_cpufreq_register_notifier(void) { return 0; } -static int meson_cpufreq_unregister_notifier(void) { return 0; } static int meson_cpufreq_probe(struct platform_device *pdev) { struct device *cpu_dev; @@ -670,14 +802,6 @@ static int meson_cpufreq_probe(struct platform_device *pdev) if (ret) { pr_err("%s: Failed registering platform driver, err: %d\n", __func__, ret); - } else { - ret = meson_cpufreq_register_notifier(); - if (ret) { - cpufreq_unregister_driver(&meson_cpufreq_driver); - } else { - pr_err("%s: Registered platform drive\n", - __func__); - } } return ret; @@ -685,8 +809,6 @@ static int meson_cpufreq_probe(struct platform_device *pdev) static int meson_cpufreq_remove(struct platform_device *pdev) { - meson_cpufreq_unregister_notifier(); - return cpufreq_unregister_driver(&meson_cpufreq_driver); } diff --git a/drivers/amlogic/cpufreq/meson-cpufreq.h b/drivers/amlogic/cpufreq/meson-cpufreq.h new file mode 100644 index 000000000000..d5508c5a3f37 --- /dev/null +++ b/drivers/amlogic/cpufreq/meson-cpufreq.h @@ -0,0 +1,80 @@ +/* + * drivers/amlogic/cpufreq/meson-cpufreq.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#ifndef __MESON_CPUFREQ_H +#define __MESON_CPUFREQ_H +/* Currently we support only two clusters */ +#define MAX_CLUSTERS 2 + +/*core power supply*/ +#define CORE_SUPPLY "cpu" + +/* Core Clocks */ +#define CORE_CLK "core_clk" +#define LOW_FREQ_CLK_PARENT "low_freq_clk_parent" +#define HIGH_FREQ_CLK_PARENT "high_freq_clk_parent" +#define DSU_CLK "dsu_clk" +#define DSU_PRE_PARENT "dsu_pre_parent" +#define to_meson_dvfs_cpu_nb(_nb) container_of(_nb, \ + struct meson_cpufreq_driver_data, freq_transition) + +static struct clk *clk[MAX_CLUSTERS]; +static struct cpufreq_frequency_table *freq_table[MAX_CLUSTERS]; + +/* Default voltage_tolerance */ +#define DEF_VOLT_TOL 0 +#define CLK_DIV 12 +#define EFUSE_CPUFREQ_MIN 1500 +/*mid rate for set parent,Khz*/ +static unsigned int mid_rate = (1000 * 1000); +static unsigned int gap_rate = (10 * 1000 * 1000); +static struct cpufreq_freqs freqs; +#define MID_RATE (1500 * 1000) + +/*whether use different tables or not*/ +bool cpufreq_tables_supply; +static unsigned int hispeed_cpufreq_max; +static unsigned int medspeed_cpufreq_max; +static unsigned int lospeed_cpufreq_max; +enum cpufreq_index { + LOSPEED_INDEX, + MEDSPEED_INDEX, + HISPEED_INDEX +}; + +struct meson_cpufreq_driver_data { + struct device *cpu_dev; + struct regulator *reg; + struct cpufreq_policy *policy; + /* voltage tolerance in percentage */ + unsigned int volt_tol; + struct clk *high_freq_clk_p; + struct clk *low_freq_clk_p; + struct clk *clk_dsu; + struct clk *clk_dsu_pre; + struct notifier_block freq_transition; +}; + +static struct mutex cluster_lock[MAX_CLUSTERS]; +static unsigned int meson_cpufreq_get_rate(unsigned int cpu); +static unsigned int meson_cpufreq_set_rate(struct cpufreq_policy *policy, + u32 cur_cluster, u32 rate); +static int meson_regulator_set_volate(struct regulator *regulator, int old_uv, + int new_uv, int tol_uv); +int get_cpufreq_tables_efuse(u32 cur_cluster); +int choose_cpufreq_tables_index(const struct device_node *np, u32 cur_cluster); +#endif /* __MESON_CPUFREQ_H */ diff --git a/drivers/amlogic/crypto/aml-aes-dma.c b/drivers/amlogic/crypto/aml-aes-dma.c index b7ff8056ea37..6182b619f891 100644 --- a/drivers/amlogic/crypto/aml-aes-dma.c +++ b/drivers/amlogic/crypto/aml-aes-dma.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -39,7 +40,6 @@ #include #include #include -#include #include #include #include "aml-crypto-dma.h" @@ -135,14 +135,18 @@ static struct aml_aes_drv aml_aes = { static int set_aes_key_iv(struct aml_aes_dev *dd, u32 *key, uint32_t keylen, u32 *iv, uint8_t swap) { + struct device *dev = dd->dev; struct dma_dsc *dsc = dd->descriptor; - uint32_t key_iv[12]; + uint32_t *key_iv = kzalloc(DMA_KEY_IV_BUF_SIZE, GFP_ATOMIC); uint32_t *piv = key_iv + 8; int32_t len = keylen; dma_addr_t dma_addr_key = 0; uint32_t i = 0; - memset(key_iv, 0, sizeof(key_iv)); + if (!key_iv) { + dev_err(dev, "error allocating key_iv buffer\n"); + return -EINVAL; + } memcpy(key_iv, key, keylen); if (iv) { if (swap) { @@ -153,17 +157,16 @@ static int set_aes_key_iv(struct aml_aes_dev *dd, u32 *key, } else { memcpy(piv, iv, 16); } - len = 48; /* full key storage */ } - if (!len) - return -EPERM; + len = DMA_KEY_IV_BUF_SIZE; /* full key storage */ dma_addr_key = dma_map_single(dd->dev, key_iv, - sizeof(key_iv), DMA_TO_DEVICE); + DMA_KEY_IV_BUF_SIZE, DMA_TO_DEVICE); if (dma_mapping_error(dd->dev, dma_addr_key)) { - dev_err(dd->dev, "error mapping dma_addr_key\n"); + dev_err(dev, "error mapping dma_addr_key\n"); + kfree(key_iv); return -EINVAL; } @@ -189,8 +192,9 @@ static int set_aes_key_iv(struct aml_aes_dev *dd, u32 *key, ; aml_write_crypto_reg(dd->status, 0xf); dma_unmap_single(dd->dev, dma_addr_key, - sizeof(key_iv), DMA_TO_DEVICE); + DMA_KEY_IV_BUF_SIZE, DMA_TO_DEVICE); + kfree(key_iv); return 0; } @@ -228,6 +232,7 @@ static size_t aml_aes_sg_copy(struct scatterlist **sg, size_t *offset, static size_t aml_aes_sg_dma(struct aml_aes_dev *dd, struct dma_dsc *dsc, uint32_t *nents, size_t total) { + struct device *dev = dd->dev; size_t count = 0; size_t process = 0; size_t count_total = 0; @@ -253,14 +258,14 @@ static size_t aml_aes_sg_dma(struct aml_aes_dev *dd, struct dma_dsc *dsc, if (dd->in_sg != dd->out_sg) { err = dma_map_sg(dd->dev, dd->in_sg, *nents, DMA_TO_DEVICE); if (!err) { - dev_err(dd->dev, "dma_map_sg() error\n"); + dev_err(dev, "dma_map_sg() error\n"); return 0; } err = dma_map_sg(dd->dev, dd->out_sg, *nents, DMA_FROM_DEVICE); if (!err) { - dev_err(dd->dev, "dma_map_sg() error\n"); + dev_err(dev, "dma_map_sg() error\n"); dma_unmap_sg(dd->dev, dd->in_sg, *nents, DMA_TO_DEVICE); return 0; @@ -269,7 +274,7 @@ static size_t aml_aes_sg_dma(struct aml_aes_dev *dd, struct dma_dsc *dsc, err = dma_map_sg(dd->dev, dd->in_sg, *nents, DMA_BIDIRECTIONAL); if (!err) { - dev_err(dd->dev, "dma_map_sg() error\n"); + dev_err(dev, "dma_map_sg() error\n"); return 0; } dma_sync_sg_for_device(dd->dev, dd->in_sg, @@ -465,6 +470,7 @@ static int aml_aes_write_ctrl(struct aml_aes_dev *dd) static int aml_aes_handle_queue(struct aml_aes_dev *dd, struct ablkcipher_request *req) { + struct device *dev = dd->dev; struct crypto_async_request *async_req, *backlog; struct aml_aes_ctx *ctx; struct aml_aes_reqctx *rctx; @@ -516,7 +522,7 @@ static int aml_aes_handle_queue(struct aml_aes_dev *dd, (dd->flags & AES_FLAGS_CTR)) err = aml_aes_crypt_dma_start(dd); else { - pr_err("size %zd is not multiple of %d", + dev_err(dev, "size %zd is not multiple of %d", dd->total, AML_AES_DMA_THRESHOLD); err = -EINVAL; } @@ -532,6 +538,7 @@ static int aml_aes_handle_queue(struct aml_aes_dev *dd, static int aml_aes_crypt_dma_stop(struct aml_aes_dev *dd) { + struct device *dev = dd->dev; int err = -EINVAL; size_t count; @@ -567,7 +574,8 @@ static int aml_aes_crypt_dma_stop(struct aml_aes_dev *dd) dd->dma_size, 1); if (count != dd->dma_size) { err = -EINVAL; - pr_err("not all data converted: %zu\n", count); + dev_err(dev, "not all data converted: %zu\n", + count); } /* install IV for CBC */ if (dd->flags & AES_FLAGS_CBC) { @@ -584,6 +592,7 @@ static int aml_aes_crypt_dma_stop(struct aml_aes_dev *dd) static int aml_aes_buff_init(struct aml_aes_dev *dd) { + struct device *dev = dd->dev; int err = -ENOMEM; dd->buf_in = (void *)__get_free_pages(GFP_KERNEL, 0); @@ -593,7 +602,7 @@ static int aml_aes_buff_init(struct aml_aes_dev *dd) dd->buflen &= ~(AES_BLOCK_SIZE - 1); if (!dd->buf_in || !dd->buf_out || !dd->descriptor) { - dev_err(dd->dev, "unable to alloc pages.\n"); + dev_err(dev, "unable to alloc pages.\n"); goto err_alloc; } @@ -601,7 +610,7 @@ static int aml_aes_buff_init(struct aml_aes_dev *dd) dd->dma_addr_in = dma_map_single(dd->dev, dd->buf_in, dd->buflen, DMA_TO_DEVICE); if (dma_mapping_error(dd->dev, dd->dma_addr_in)) { - dev_err(dd->dev, "dma %zd bytes error\n", dd->buflen); + dev_err(dev, "dma %zd bytes error\n", dd->buflen); err = -EINVAL; goto err_map_in; } @@ -609,7 +618,7 @@ static int aml_aes_buff_init(struct aml_aes_dev *dd) dd->dma_addr_out = dma_map_single(dd->dev, dd->buf_out, dd->buflen, DMA_FROM_DEVICE); if (dma_mapping_error(dd->dev, dd->dma_addr_out)) { - dev_err(dd->dev, "dma %zd bytes error\n", dd->buflen); + dev_err(dev, "dma %zd bytes error\n", dd->buflen); err = -EINVAL; goto err_map_out; } @@ -618,7 +627,7 @@ static int aml_aes_buff_init(struct aml_aes_dev *dd) PAGE_SIZE, DMA_TO_DEVICE); if (dma_mapping_error(dd->dev, dd->dma_descript_tab)) { - dev_err(dd->dev, "dma descriptor error\n"); + dev_err(dev, "dma descriptor error\n"); err = -EINVAL; goto err_map_descriptor; } @@ -638,7 +647,7 @@ err_map_in: free_page((uintptr_t)dd->descriptor); err_alloc: if (err) - pr_err("error: %d\n", err); + dev_err(dev, "error: %d\n", err); return err; } @@ -911,7 +920,6 @@ static struct crypto_alg aes_lite_algs[] = { .cra_u.ablkcipher = { .min_keysize = AES_MIN_KEY_SIZE, .max_keysize = AES_MAX_KEY_SIZE, - .ivsize = AES_BLOCK_SIZE, .setkey = aml_aes_lite_setkey, .encrypt = aml_aes_ecb_encrypt, .decrypt = aml_aes_ecb_decrypt, @@ -997,6 +1005,7 @@ static void aml_aes_queue_task(unsigned long data) static void aml_aes_done_task(unsigned long data) { struct aml_aes_dev *dd = (struct aml_aes_dev *) data; + struct device *dev = dd->dev; int err; err = aml_aes_crypt_dma_stop(dd); @@ -1014,7 +1023,7 @@ static void aml_aes_done_task(unsigned long data) dd->in_sg = sg_next(dd->in_sg); dd->out_sg = sg_next(dd->out_sg); if (!dd->in_sg || !dd->out_sg) { - pr_err("aml-aes: sg invalid\n"); + dev_err(dev, "aml-aes: sg invalid\n"); err = -EINVAL; break; } @@ -1034,11 +1043,12 @@ static void aml_aes_done_task(unsigned long data) static irqreturn_t aml_aes_irq(int irq, void *dev_id) { struct aml_aes_dev *aes_dd = dev_id; + struct device *dev = aes_dd->dev; uint8_t status = aml_read_crypto_reg(aes_dd->status); if (status) { if (status == 0x1) - pr_err("irq overwrite\n"); + dev_err(dev, "irq overwrite\n"); if (aes_dd->dma->dma_busy == DMA_FLAG_MAY_OCCUPY) return IRQ_HANDLED; if ((aes_dd->flags & AES_FLAGS_DMA) && @@ -1079,7 +1089,7 @@ static int aml_aes_register_algs(struct aml_aes_dev *dd, err_aes_algs: for (j = 0; j < i; j++) - crypto_unregister_alg(&aes_algs[j]); + crypto_unregister_alg(&(aes_info->algs[j])); return err; } @@ -1092,7 +1102,7 @@ static int aml_aes_probe(struct platform_device *pdev) int err = -EPERM; const struct aml_aes_info *aes_info = NULL; - aes_dd = kzalloc(sizeof(struct aml_aes_dev), GFP_KERNEL); + aes_dd = devm_kzalloc(dev, sizeof(struct aml_aes_dev), GFP_KERNEL); if (aes_dd == NULL) { err = -ENOMEM; goto aes_dd_err; @@ -1100,9 +1110,8 @@ static int aml_aes_probe(struct platform_device *pdev) match = of_match_device(aml_aes_dt_match, &pdev->dev); if (!match) { - pr_err("%s: cannot find match dt\n", __func__); + dev_err(dev, "%s: cannot find match dt\n", __func__); err = -EINVAL; - kfree(aes_dd); goto aes_dd_err; } aes_info = match->data; @@ -1121,8 +1130,8 @@ static int aml_aes_probe(struct platform_device *pdev) (unsigned long)aes_dd); crypto_init_queue(&aes_dd->queue, AML_AES_QUEUE_LENGTH); - err = request_irq(aes_dd->irq, aml_aes_irq, IRQF_SHARED, "aml-aes", - aes_dd); + err = devm_request_irq(dev, aes_dd->irq, aml_aes_irq, IRQF_SHARED, + "aml-aes", aes_dd); if (err) { dev_err(dev, "unable to request aes irq.\n"); goto aes_irq_err; @@ -1154,13 +1163,9 @@ err_algs: spin_unlock(&aml_aes.lock); aml_aes_buff_cleanup(aes_dd); err_aes_buff: - free_irq(aes_dd->irq, aes_dd); aes_irq_err: - tasklet_kill(&aes_dd->done_task); tasklet_kill(&aes_dd->queue_task); - kfree(aes_dd); - aes_dd = NULL; aes_dd_err: dev_err(dev, "initialization failed.\n"); @@ -1169,6 +1174,7 @@ aes_dd_err: static int aml_aes_remove(struct platform_device *pdev) { + struct device *dev = &pdev->dev; static struct aml_aes_dev *aes_dd; const struct of_device_id *match; const struct aml_aes_info *aes_info = NULL; @@ -1178,7 +1184,7 @@ static int aml_aes_remove(struct platform_device *pdev) return -ENODEV; match = of_match_device(aml_aes_dt_match, &pdev->dev); if (!match) { - pr_err("%s: cannot find match dt\n", __func__); + dev_err(dev, "%s: cannot find match dt\n", __func__); return -EINVAL; } aes_info = match->data; @@ -1191,12 +1197,6 @@ static int aml_aes_remove(struct platform_device *pdev) tasklet_kill(&aes_dd->done_task); tasklet_kill(&aes_dd->queue_task); - if (aes_dd->irq > 0) - free_irq(aes_dd->irq, aes_dd); - - kfree(aes_dd); - aes_dd = NULL; - return 0; } diff --git a/drivers/amlogic/crypto/aml-crypto-dma.c b/drivers/amlogic/crypto/aml-crypto-dma.c index 0412b75d8eeb..03b3b05f0673 100644 --- a/drivers/amlogic/crypto/aml-crypto-dma.c +++ b/drivers/amlogic/crypto/aml-crypto-dma.c @@ -37,8 +37,6 @@ #include #include #include -#include -#include #include "aml-crypto-dma.h" u32 swap_ulong32(u32 val) diff --git a/drivers/amlogic/crypto/aml-crypto-dma.h b/drivers/amlogic/crypto/aml-crypto-dma.h index 48e0a4abd67f..12ab5d9ca4da 100644 --- a/drivers/amlogic/crypto/aml-crypto-dma.h +++ b/drivers/amlogic/crypto/aml-crypto-dma.h @@ -19,8 +19,6 @@ #define _AML_CRYPTO_H_ #include -/* #define CRYPTO_DEBUG */ - /* Reserved 4096 bytes and table is 12 bytes each */ #define MAX_NUM_TABLES 341 @@ -117,6 +115,7 @@ struct dma_dsc { #define DMA_FLAG_AES_IN_USE BIT(2) #define DMA_FLAG_SHA_IN_USE BIT(3) +#define DMA_KEY_IV_BUF_SIZE (48) struct aml_dma_dev { spinlock_t dma_lock; uint32_t thread; @@ -136,17 +135,13 @@ u32 get_dma_sts0_offset(void); extern void __iomem *cryptoreg; -extern int debug; -#ifndef CRYPTO_DEBUG -#define dbgp(level, fmt, arg...) -#else +extern u32 debug; #define dbgp(level, fmt, arg...) \ do { \ - if (likely(debug >= level)) \ + if (likely(debug > level)) \ pr_debug("%s: " fmt, __func__, ## arg);\ else \ pr_info("%s: " fmt, __func__, ## arg); \ } while (0) #endif -#endif diff --git a/drivers/amlogic/crypto/aml-dma.c b/drivers/amlogic/crypto/aml-dma.c index 9e74d0f24594..463716465f7e 100644 --- a/drivers/amlogic/crypto/aml-dma.c +++ b/drivers/amlogic/crypto/aml-dma.c @@ -17,6 +17,7 @@ #include #include +#include #include #include #include @@ -42,10 +43,8 @@ #include #include "aml-crypto-dma.h" -int debug = 2; -#ifdef CRYPTO_DEBUG -module_param(debug, int, 0644); -#endif +static struct dentry *aml_dma_debug_dent; +u32 debug = 3; void __iomem *cryptoreg; @@ -78,6 +77,27 @@ MODULE_DEVICE_TABLE(of, aml_dma_dt_match); #define aml_aes_dt_match NULL #endif +static int aml_dma_init_dbgfs(struct device *dev) +{ + struct dentry *file = NULL; + + if (!aml_dma_debug_dent) { + aml_dma_debug_dent = debugfs_create_dir("aml_dma", NULL); + if (!aml_dma_debug_dent) { + dev_err(dev, "can not create debugfs directory\n"); + return -ENOMEM; + } + file = debugfs_create_u32("debug", 0644, + aml_dma_debug_dent, &debug); + if (!file) { + dev_err(dev, "can not create entry in debugfs directory\n"); + return -ENOMEM; + } + } + return 0; +} + + static int aml_dma_probe(struct platform_device *pdev) { struct aml_dma_dev *dma_dd; @@ -89,7 +109,7 @@ static int aml_dma_probe(struct platform_device *pdev) int err = -EPERM; const struct meson_dma_data *priv_data; - dma_dd = kzalloc(sizeof(struct aml_dma_dev), GFP_KERNEL); + dma_dd = devm_kzalloc(dev, sizeof(struct aml_dma_dev), GFP_KERNEL); if (dma_dd == NULL) { err = -ENOMEM; goto dma_err; @@ -106,8 +126,7 @@ static int aml_dma_probe(struct platform_device *pdev) dev_err(dev, "error to get normal IORESOURCE_MEM.\n"); goto dma_err; } else { - cryptoreg = ioremap(res_base->start, - resource_size(res_base)); + cryptoreg = devm_ioremap_resource(dev, res_base); if (!cryptoreg) { dev_err(dev, "failed to remap crypto reg\n"); goto dma_err; @@ -118,17 +137,21 @@ static int aml_dma_probe(struct platform_device *pdev) dma_dd->irq = res_irq->start; dma_dd->dma_busy = 0; platform_set_drvdata(pdev, dma_dd); + + err = aml_dma_init_dbgfs(dev); + if (err) + goto dma_err; + dev_info(dev, "Aml dma\n"); err = of_platform_populate(np, NULL, NULL, dev); - if (err != 0) - iounmap(cryptoreg); + goto dma_err; return err; dma_err: - kfree(dma_dd); + debugfs_remove_recursive(aml_dma_debug_dent); dev_err(dev, "initialization failed.\n"); return err; @@ -142,8 +165,7 @@ static int aml_dma_remove(struct platform_device *pdev) if (!dma_dd) return -ENODEV; - iounmap(cryptoreg); - kfree(dma_dd); + debugfs_remove_recursive(aml_dma_debug_dent); return 0; } diff --git a/drivers/amlogic/crypto/aml-sha-dma.c b/drivers/amlogic/crypto/aml-sha-dma.c index fde19f1322c6..3a39ef2609c9 100644 --- a/drivers/amlogic/crypto/aml-sha-dma.c +++ b/drivers/amlogic/crypto/aml-sha-dma.c @@ -40,7 +40,6 @@ #include #include #include -#include #include "aml-crypto-dma.h" /* SHA flags */ @@ -459,9 +458,7 @@ static int aml_sha_update_dma_stop(struct aml_sha_dev *dd) static int aml_sha_update_req(struct aml_sha_dev *dd, struct ahash_request *req) { int err; -#ifdef CRYPTO_DEBUG struct aml_sha_reqctx *ctx = ahash_request_ctx(req); -#endif dbgp(1, "update_req: ctx: %p, total: %u, digcnt: 0x%llx 0x%llx\n", ctx, ctx->total, ctx->digcnt[1], ctx->digcnt[0]); @@ -474,9 +471,7 @@ static int aml_sha_update_req(struct aml_sha_dev *dd, struct ahash_request *req) static int aml_sha_final_req(struct aml_sha_dev *dd, struct ahash_request *req) { int err = 0; -#ifdef CRYPTO_DEBUG struct aml_sha_reqctx *ctx = ahash_request_ctx(req); -#endif err = aml_sha_update_dma_slow(dd, req); @@ -1092,7 +1087,7 @@ static struct ahash_alg sha_algs[] = { .base = { .cra_name = "sha1", .cra_driver_name = "aml-sha1", - .cra_priority = 200, + .cra_priority = 150, .cra_flags = CRYPTO_ALG_ASYNC, .cra_blocksize = SHA1_BLOCK_SIZE, .cra_ctxsize = sizeof(struct aml_sha_ctx), @@ -1118,7 +1113,7 @@ static struct ahash_alg sha_algs[] = { .base = { .cra_name = "sha256", .cra_driver_name = "aml-sha256", - .cra_priority = 200, + .cra_priority = 150, .cra_flags = CRYPTO_ALG_ASYNC, .cra_blocksize = SHA256_BLOCK_SIZE, .cra_ctxsize = sizeof(struct aml_sha_ctx), @@ -1144,7 +1139,7 @@ static struct ahash_alg sha_algs[] = { .base = { .cra_name = "sha224", .cra_driver_name = "aml-sha224", - .cra_priority = 200, + .cra_priority = 150, .cra_flags = CRYPTO_ALG_ASYNC, .cra_blocksize = SHA224_BLOCK_SIZE, .cra_ctxsize = sizeof(struct aml_sha_ctx), @@ -1171,7 +1166,7 @@ static struct ahash_alg sha_algs[] = { .base = { .cra_name = "hmac(sha1)", .cra_driver_name = "aml-hmac-sha1", - .cra_priority = 200, + .cra_priority = 150, .cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK, .cra_blocksize = SHA1_BLOCK_SIZE, @@ -1199,7 +1194,7 @@ static struct ahash_alg sha_algs[] = { .base = { .cra_name = "hmac(sha224)", .cra_driver_name = "aml-hmac-sha224", - .cra_priority = 200, + .cra_priority = 150, .cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK, .cra_blocksize = SHA224_BLOCK_SIZE, @@ -1227,7 +1222,7 @@ static struct ahash_alg sha_algs[] = { .base = { .cra_name = "hmac(sha256)", .cra_driver_name = "aml-hmac-sha256", - .cra_priority = 200, + .cra_priority = 150, .cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK, .cra_blocksize = SHA256_BLOCK_SIZE, @@ -1285,7 +1280,7 @@ static irqreturn_t aml_sha_irq(int irq, void *dev_id) if (status) { if (status == 0x1) - pr_err("irq overwrite\n"); + dev_err(sha_dd->dev, "irq overwrite\n"); if (sha_dd->dma->dma_busy == DMA_FLAG_MAY_OCCUPY) return IRQ_HANDLED; if (sha_dd->flags & SHA_FLAGS_DMA_ACTIVE && @@ -1335,7 +1330,7 @@ static int aml_sha_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; int err = -EPERM; - sha_dd = kzalloc(sizeof(struct aml_sha_dev), GFP_KERNEL); + sha_dd = devm_kzalloc(dev, sizeof(struct aml_sha_dev), GFP_KERNEL); if (sha_dd == NULL) { err = -ENOMEM; goto sha_dd_err; @@ -1355,8 +1350,8 @@ static int aml_sha_probe(struct platform_device *pdev) (unsigned long)sha_dd); crypto_init_queue(&sha_dd->queue, AML_SHA_QUEUE_LENGTH); - err = request_irq(sha_dd->irq, aml_sha_irq, IRQF_SHARED, "aml-sha", - sha_dd); + err = devm_request_irq(dev, sha_dd->irq, aml_sha_irq, IRQF_SHARED, + "aml-sha", sha_dd); if (err) { dev_err(dev, "unable to request sha irq.\n"); goto res_err; @@ -1364,7 +1359,6 @@ static int aml_sha_probe(struct platform_device *pdev) aml_sha_hw_init(sha_dd); - spin_lock(&aml_sha.lock); list_add_tail(&sha_dd->list, &aml_sha.dev_list); spin_unlock(&aml_sha.lock); @@ -1381,12 +1375,8 @@ err_algs: spin_lock(&aml_sha.lock); list_del(&sha_dd->list); spin_unlock(&aml_sha.lock); - - free_irq(sha_dd->irq, sha_dd); res_err: tasklet_kill(&sha_dd->done_task); - kfree(sha_dd); - sha_dd = NULL; sha_dd_err: dev_err(dev, "initialization failed.\n"); @@ -1408,12 +1398,6 @@ static int aml_sha_remove(struct platform_device *pdev) tasklet_kill(&sha_dd->done_task); - if (sha_dd->irq >= 0) - free_irq(sha_dd->irq, sha_dd); - - kfree(sha_dd); - sha_dd = NULL; - return 0; } diff --git a/drivers/amlogic/crypto/aml-tdes-dma.c b/drivers/amlogic/crypto/aml-tdes-dma.c index 99f32ba26663..b2198ccc6977 100644 --- a/drivers/amlogic/crypto/aml-tdes-dma.c +++ b/drivers/amlogic/crypto/aml-tdes-dma.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -39,7 +40,8 @@ #include #include #include -#include +//#include +#include #include "aml-crypto-dma.h" /* TDES flags */ @@ -54,6 +56,7 @@ #define AML_TDES_QUEUE_LENGTH 50 +#define SUPPORT_FAST_DMA 0 struct aml_tdes_dev; struct aml_tdes_ctx { @@ -63,6 +66,8 @@ struct aml_tdes_ctx { u32 key[3*DES_KEY_SIZE / sizeof(u32)]; u16 block_size; + struct crypto_skcipher *fallback; + u16 same_key; }; struct aml_tdes_reqctx { @@ -115,6 +120,11 @@ struct aml_tdes_drv { spinlock_t lock; }; +struct aml_tdes_info { + struct crypto_alg *algs; + uint32_t num_algs; +}; + static struct aml_tdes_drv aml_tdes = { .dev_list = LIST_HEAD_INIT(aml_tdes.dev_list), .lock = __SPIN_LOCK_UNLOCKED(aml_tdes.lock), @@ -124,42 +134,43 @@ static int set_tdes_key_iv(struct aml_tdes_dev *dd, u32 *key, u32 keylen, u32 *iv) { struct dma_dsc *dsc = dd->descriptor; - uint32_t key_iv[12]; + struct device *dev = dd->dev; + uint32_t *key_iv = kzalloc(DMA_KEY_IV_BUF_SIZE, GFP_ATOMIC); uint32_t *piv = key_iv + 8; uint32_t len = keylen; - uint32_t processed = 0; dma_addr_t dma_addr_key; uint32_t i = 0; - memset(key_iv, 0, sizeof(key_iv)); + if (!key_iv) { + dev_err(dev, "error allocating key_iv buffer\n"); + return -EINVAL; + } memcpy(key_iv, key, keylen); if (iv) { memcpy(piv, iv, 8); - len = 48; /* full key storage */ } - if (!len) - return -EPERM; + len = DMA_KEY_IV_BUF_SIZE; /* full key storage */ dma_addr_key = dma_map_single(dd->dev, key_iv, - sizeof(key_iv), DMA_TO_DEVICE); + DMA_KEY_IV_BUF_SIZE, DMA_TO_DEVICE); if (dma_mapping_error(dd->dev, dma_addr_key)) { - dev_err(dd->dev, "error mapping dma_addr_key\n"); + dev_err(dev, "error mapping dma_addr_key\n"); + kfree(key_iv); return -EINVAL; } while (len > 0) { - processed = len > 16 ? 16 : len; dsc[i].src_addr = (uint32_t)dma_addr_key + i * 16; dsc[i].tgt_addr = i * 16; dsc[i].dsc_cfg.d32 = 0; - dsc[i].dsc_cfg.b.length = processed; + dsc[i].dsc_cfg.b.length = len > 16 ? 16 : len; dsc[i].dsc_cfg.b.mode = MODE_KEY; dsc[i].dsc_cfg.b.eoc = 0; dsc[i].dsc_cfg.b.owner = 1; i++; - len -= processed; + len -= 16; } dsc[i - 1].dsc_cfg.b.eoc = 1; @@ -172,8 +183,9 @@ static int set_tdes_key_iv(struct aml_tdes_dev *dd, ; aml_write_crypto_reg(dd->status, 0xf); dma_unmap_single(dd->dev, dma_addr_key, - sizeof(key_iv), DMA_TO_DEVICE); + DMA_KEY_IV_BUF_SIZE, DMA_TO_DEVICE); + kfree(key_iv); return 0; } @@ -209,11 +221,15 @@ static size_t aml_tdes_sg_copy(struct scatterlist **sg, size_t *offset, return off; } +#if SUPPORT_FAST_DMA static size_t aml_tdes_sg_dma(struct aml_tdes_dev *dd, struct dma_dsc *dsc, uint32_t *nents, size_t total) { + struct device *dev = dd->dev; size_t count = 0; size_t process = 0; + size_t count_total = 0; + size_t count_sg = 0; uint32_t i = 0; int err = 0; struct scatterlist *in_sg = dd->in_sg; @@ -221,44 +237,62 @@ static size_t aml_tdes_sg_dma(struct aml_tdes_dev *dd, struct dma_dsc *dsc, dma_addr_t addr_in, addr_out; while (total && in_sg && out_sg && (in_sg->length == out_sg->length) + && IS_ALIGNED(in_sg->length, DES_BLOCK_SIZE) && *nents < MAX_NUM_TABLES) { process = min_t(unsigned int, total, in_sg->length); count += process; *nents += 1; + if (process != in_sg->length) + dd->out_offset = dd->in_offset = in_sg->length; total -= process; in_sg = sg_next(in_sg); out_sg = sg_next(out_sg); } - err = dma_map_sg(dd->dev, dd->in_sg, *nents, DMA_TO_DEVICE); - if (!err) { - dev_err(dd->dev, "dma_map_sg() error\n"); - return 0; - } + if (dd->in_sg != dd->out_sg) { + err = dma_map_sg(dd->dev, dd->in_sg, *nents, DMA_TO_DEVICE); + if (!err) { + dev_err(dev, "dma_map_sg() error\n"); + return 0; + } - err = dma_map_sg(dd->dev, dd->out_sg, *nents, - DMA_FROM_DEVICE); - if (!err) { - dev_err(dd->dev, "dma_map_sg() error\n"); - dma_unmap_sg(dd->dev, dd->in_sg, *nents, - DMA_TO_DEVICE); - return 0; + err = dma_map_sg(dd->dev, dd->out_sg, *nents, + DMA_FROM_DEVICE); + if (!err) { + dev_err(dev, "dma_map_sg() error\n"); + dma_unmap_sg(dd->dev, dd->in_sg, *nents, + DMA_TO_DEVICE); + return 0; + } + } else { + err = dma_map_sg(dd->dev, dd->in_sg, *nents, + DMA_BIDIRECTIONAL); + if (!err) { + dev_err(dev, "dma_map_sg() error\n"); + return 0; + } + dma_sync_sg_for_device(dd->dev, dd->in_sg, + *nents, DMA_TO_DEVICE); } in_sg = dd->in_sg; out_sg = dd->out_sg; + count_total = count; for (i = 0; i < *nents; i++) { + count_sg = count_total > sg_dma_len(in_sg) ? + sg_dma_len(in_sg) : count_total; addr_in = sg_dma_address(in_sg); addr_out = sg_dma_address(out_sg); dsc[i].src_addr = (uintptr_t)addr_in; dsc[i].tgt_addr = (uintptr_t)addr_out; dsc[i].dsc_cfg.d32 = 0; - dsc[i].dsc_cfg.b.length = sg_dma_len(in_sg); + dsc[i].dsc_cfg.b.length = count_sg; in_sg = sg_next(in_sg); out_sg = sg_next(out_sg); + count_total -= count_sg; } return count; } - +#endif static struct aml_tdes_dev *aml_tdes_find_dev(struct aml_tdes_ctx *ctx) { struct aml_tdes_dev *tdes_dd = NULL; @@ -362,11 +396,14 @@ static int aml_tdes_crypt_dma_start(struct aml_tdes_dev *dd) dd->fast_nents = 0; } +#if SUPPORT_FAST_DMA if (fast) { count = aml_tdes_sg_dma(dd, dsc, &dd->fast_nents, dd->total); dd->flags |= TDES_FLAGS_FAST; nents = dd->fast_nents; - } else { + } else +#endif + { /* slow dma */ /* use cache buffers */ count = aml_tdes_sg_copy(&dd->in_sg, &dd->in_offset, @@ -472,6 +509,7 @@ static int aml_tdes_handle_queue(struct aml_tdes_dev *dd, static int aml_tdes_crypt_dma_stop(struct aml_tdes_dev *dd) { + struct device *dev = dd->dev; int err = -EINVAL; size_t count; @@ -480,10 +518,17 @@ static int aml_tdes_crypt_dma_stop(struct aml_tdes_dev *dd) dma_sync_single_for_cpu(dd->dev, dd->dma_descript_tab, PAGE_SIZE, DMA_FROM_DEVICE); if (dd->flags & TDES_FLAGS_FAST) { - dma_unmap_sg(dd->dev, dd->out_sg, + if (dd->in_sg != dd->out_sg) { + dma_unmap_sg(dd->dev, dd->out_sg, dd->fast_nents, DMA_FROM_DEVICE); - dma_unmap_sg(dd->dev, dd->in_sg, + dma_unmap_sg(dd->dev, dd->in_sg, dd->fast_nents, DMA_TO_DEVICE); + } else { + dma_sync_sg_for_cpu(dd->dev, dd->in_sg, + dd->fast_nents, DMA_FROM_DEVICE); + dma_unmap_sg(dd->dev, dd->in_sg, + dd->fast_nents, DMA_BIDIRECTIONAL); + } } else { dma_sync_single_for_cpu(dd->dev, dd->dma_addr_out, dd->dma_size, DMA_FROM_DEVICE); @@ -494,7 +539,8 @@ static int aml_tdes_crypt_dma_stop(struct aml_tdes_dev *dd) dd->dma_size, 1); if (count != dd->dma_size) { err = -EINVAL; - pr_err("not all data converted: %zu\n", count); + dev_err(dev, "not all data converted: %zu\n", + count); } } dd->flags &= ~TDES_FLAGS_DMA; @@ -506,6 +552,7 @@ static int aml_tdes_crypt_dma_stop(struct aml_tdes_dev *dd) static int aml_tdes_buff_init(struct aml_tdes_dev *dd) { + struct device *dev = dd->dev; int err = -ENOMEM; dd->buf_in = (void *)__get_free_pages(GFP_KERNEL, 0); @@ -515,7 +562,7 @@ static int aml_tdes_buff_init(struct aml_tdes_dev *dd) dd->buflen &= ~(DES_BLOCK_SIZE - 1); if (!dd->buf_in || !dd->buf_out || !dd->descriptor) { - dev_err(dd->dev, "unable to alloc pages.\n"); + dev_err(dev, "unable to alloc pages.\n"); goto err_alloc; } @@ -523,7 +570,7 @@ static int aml_tdes_buff_init(struct aml_tdes_dev *dd) dd->dma_addr_in = dma_map_single(dd->dev, dd->buf_in, dd->buflen, DMA_TO_DEVICE); if (dma_mapping_error(dd->dev, dd->dma_addr_in)) { - dev_err(dd->dev, "dma %zd bytes error\n", dd->buflen); + dev_err(dev, "dma %zd bytes error\n", dd->buflen); err = -EINVAL; goto err_map_in; } @@ -531,7 +578,7 @@ static int aml_tdes_buff_init(struct aml_tdes_dev *dd) dd->dma_addr_out = dma_map_single(dd->dev, dd->buf_out, dd->buflen, DMA_FROM_DEVICE); if (dma_mapping_error(dd->dev, dd->dma_addr_out)) { - dev_err(dd->dev, "dma %zd bytes error\n", dd->buflen); + dev_err(dev, "dma %zd bytes error\n", dd->buflen); err = -EINVAL; goto err_map_out; } @@ -540,7 +587,7 @@ static int aml_tdes_buff_init(struct aml_tdes_dev *dd) PAGE_SIZE, DMA_TO_DEVICE); if (dma_mapping_error(dd->dev, dd->dma_descript_tab)) { - dev_err(dd->dev, "dma descriptor error\n"); + dev_err(dev, "dma descriptor error\n"); err = -EINVAL; goto err_map_descriptor; } @@ -561,7 +608,7 @@ err_map_in: free_page((uintptr_t)dd->descriptor); err_alloc: if (err) - pr_err("error: %d\n", err); + dev_err(dev, "error: %d\n", err); return err; } @@ -591,6 +638,31 @@ static int aml_tdes_crypt(struct ablkcipher_request *req, unsigned long mode) } ctx->block_size = DES_BLOCK_SIZE; + if (ctx->fallback && ctx->same_key) { + char *__subreq_desc = kzalloc(sizeof(struct skcipher_request) + + crypto_skcipher_reqsize(ctx->fallback), + GFP_ATOMIC); + struct skcipher_request *subreq = (void *)__subreq_desc; + int ret = 0; + + if (!subreq) + return -ENOMEM; + + skcipher_request_set_tfm(subreq, ctx->fallback); + skcipher_request_set_callback(subreq, req->base.flags, NULL, + NULL); + skcipher_request_set_crypt(subreq, req->src, req->dst, + req->nbytes, req->info); + + if (mode & TDES_FLAGS_ENCRYPT) + ret = crypto_skcipher_encrypt(subreq); + else + ret = crypto_skcipher_decrypt(subreq); + + skcipher_request_free(subreq); + return ret; + } + dd = aml_tdes_find_dev(ctx); if (!dd) return -ENODEV; @@ -667,7 +739,10 @@ static int aml_tdes_cbc_decrypt(struct ablkcipher_request *req) static int aml_tdes_cra_init(struct crypto_tfm *tfm) { + struct aml_tdes_ctx *ctx = crypto_tfm_ctx(tfm); + tfm->crt_ablkcipher.reqsize = sizeof(struct aml_tdes_reqctx); + ctx->fallback = NULL; return 0; } @@ -676,7 +751,7 @@ static void aml_tdes_cra_exit(struct crypto_tfm *tfm) { } -static struct crypto_alg des_algs[] = { +static struct crypto_alg des_tdes_algs[] = { { .cra_name = "ecb(des)", .cra_driver_name = "ecb-des-aml", @@ -718,9 +793,6 @@ static struct crypto_alg des_algs[] = { .decrypt = aml_tdes_cbc_decrypt, } }, -}; - -static struct crypto_alg tdes_algs[] = { { .cra_name = "ecb(des3_ede)", .cra_driver_name = "ecb-tdes-aml", @@ -764,6 +836,114 @@ static struct crypto_alg tdes_algs[] = { } }; +static int aml_tdes_lite_cra_init(struct crypto_tfm *tfm) +{ + struct aml_tdes_ctx *ctx = crypto_tfm_ctx(tfm); + const char *alg_name = crypto_tfm_alg_name(tfm); + const u32 flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK; + + tfm->crt_ablkcipher.reqsize = sizeof(struct aml_tdes_reqctx); + + /* Allocate a fallback and abort if it failed. */ + ctx->fallback = crypto_alloc_skcipher(alg_name, 0, + flags); + if (IS_ERR(ctx->fallback)) { + pr_err("aml-tdes: fallback '%s' could not be loaded.\n", + alg_name); + return PTR_ERR(ctx->fallback); + } + + return 0; +} + +static void aml_tdes_lite_cra_exit(struct crypto_tfm *tfm) +{ + struct aml_tdes_ctx *ctx = crypto_tfm_ctx(tfm); + + if (ctx->fallback) + crypto_free_skcipher(ctx->fallback); + + ctx->fallback = NULL; +} + +static int aml_tdes_lite_setkey(struct crypto_ablkcipher *tfm, const u8 *key, + unsigned int keylen) +{ + struct aml_tdes_ctx *ctx = crypto_ablkcipher_ctx(tfm); + int ret = 0; + u64 *tmp = NULL; + + if ((keylen != 2 * DES_KEY_SIZE) && (keylen != 3 * DES_KEY_SIZE)) { + crypto_ablkcipher_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN); + return -EINVAL; + } + + memcpy(ctx->key, key, keylen); + ctx->keylen = keylen; + + tmp = (u64 *)ctx->key; + if (keylen == 2 * DES_KEY_SIZE) + ctx->same_key = !(tmp[0] ^ tmp[1]); + else + ctx->same_key = !((tmp[0] ^ tmp[1]) | (tmp[0] ^ tmp[2])); + + if (ctx->same_key) { + crypto_skcipher_clear_flags(ctx->fallback, CRYPTO_TFM_REQ_MASK); + crypto_skcipher_set_flags(ctx->fallback, tfm->base.crt_flags & + CRYPTO_TFM_REQ_MASK); + ret = crypto_skcipher_setkey(ctx->fallback, key, keylen); + } + + return ret; +} + + +static struct crypto_alg tdes_lite_algs[] = { + { + .cra_name = "ecb(des3_ede)", + .cra_driver_name = "ecb-tdes-lite-aml", + .cra_priority = 200, + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | + CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK, + .cra_blocksize = DES_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct aml_tdes_ctx), + .cra_alignmask = 0, + .cra_type = &crypto_ablkcipher_type, + .cra_module = THIS_MODULE, + .cra_init = aml_tdes_lite_cra_init, + .cra_exit = aml_tdes_lite_cra_exit, + .cra_u.ablkcipher = { + .min_keysize = 2 * DES_KEY_SIZE, + .max_keysize = 3 * DES_KEY_SIZE, + .setkey = aml_tdes_lite_setkey, + .encrypt = aml_tdes_ecb_encrypt, + .decrypt = aml_tdes_ecb_decrypt, + } + }, + { + .cra_name = "cbc(des3_ede)", + .cra_driver_name = "cbc-tdes-lite-aml", + .cra_priority = 200, + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | + CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK, + .cra_blocksize = DES_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct aml_tdes_ctx), + .cra_alignmask = 0, + .cra_type = &crypto_ablkcipher_type, + .cra_module = THIS_MODULE, + .cra_init = aml_tdes_lite_cra_init, + .cra_exit = aml_tdes_lite_cra_exit, + .cra_u.ablkcipher = { + .min_keysize = 2 * DES_KEY_SIZE, + .max_keysize = 3 * DES_KEY_SIZE, + .ivsize = DES_BLOCK_SIZE, + .setkey = aml_tdes_lite_setkey, + .encrypt = aml_tdes_cbc_encrypt, + .decrypt = aml_tdes_cbc_decrypt, + } + } +}; + static void aml_tdes_queue_task(unsigned long data) { struct aml_tdes_dev *dd = (struct aml_tdes_dev *)data; @@ -774,6 +954,7 @@ static void aml_tdes_queue_task(unsigned long data) static void aml_tdes_done_task(unsigned long data) { struct aml_tdes_dev *dd = (struct aml_tdes_dev *) data; + struct device *dev = dd->dev; int err; err = aml_tdes_crypt_dma_stop(dd); @@ -790,7 +971,7 @@ static void aml_tdes_done_task(unsigned long data) dd->in_sg = sg_next(dd->in_sg); dd->out_sg = sg_next(dd->out_sg); if (!dd->in_sg || !dd->out_sg) { - pr_err("aml-tdes: sg invalid\n"); + dev_err(dev, "aml-tdes: sg invalid\n"); err = -EINVAL; break; } @@ -810,11 +991,12 @@ static void aml_tdes_done_task(unsigned long data) static irqreturn_t aml_tdes_irq(int irq, void *dev_id) { struct aml_tdes_dev *tdes_dd = dev_id; + struct device *dev = tdes_dd->dev; uint8_t status = aml_read_crypto_reg(tdes_dd->status); if (status) { if (status == 0x1) - pr_err("irq overwrite\n"); + dev_err(dev, "irq overwrite\n"); if (tdes_dd->dma->dma_busy == DMA_FLAG_MAY_OCCUPY) return IRQ_HANDLED; if ((tdes_dd->dma->dma_busy & DMA_FLAG_TDES_IN_USE) && @@ -831,29 +1013,22 @@ static irqreturn_t aml_tdes_irq(int irq, void *dev_id) return IRQ_NONE; } -static void aml_tdes_unregister_algs(struct aml_tdes_dev *dd) +static void aml_tdes_unregister_algs(struct aml_tdes_dev *dd, + const struct aml_tdes_info *tdes_info) { - int i = 0; + int i; - for (; i < ARRAY_SIZE(des_algs); i++) - crypto_unregister_alg(&des_algs[i]); - - for (; i < ARRAY_SIZE(tdes_algs); i++) - crypto_unregister_alg(&tdes_algs[i]); + for (i = 0; i < tdes_info->num_algs; i++) + crypto_unregister_alg(&(tdes_info->algs[i])); } -static int aml_tdes_register_algs(struct aml_tdes_dev *dd) +static int aml_tdes_register_algs(struct aml_tdes_dev *dd, + const struct aml_tdes_info *tdes_info) { - int err = 0, i = 0, j = 0, k = 0; + int err, i, j; - for (; i < ARRAY_SIZE(des_algs); i++) { - err = crypto_register_alg(&des_algs[i]); - if (err) - goto err_des_algs; - } - - for (; k < ARRAY_SIZE(tdes_algs); k++) { - err = crypto_register_alg(&tdes_algs[k]); + for (i = 0; i < tdes_info->num_algs; i++) { + err = crypto_register_alg(&(tdes_info->algs[i])); if (err) goto err_tdes_algs; } @@ -861,28 +1036,58 @@ static int aml_tdes_register_algs(struct aml_tdes_dev *dd) return 0; err_tdes_algs: - for (j = 0; j < k; j++) - crypto_unregister_alg(&tdes_algs[j]); - -err_des_algs: for (j = 0; j < i; j++) - crypto_unregister_alg(&des_algs[j]); + crypto_unregister_alg(&(tdes_info->algs[j])); return err; } +struct aml_tdes_info aml_des_tdes = { + .algs = des_tdes_algs, + .num_algs = ARRAY_SIZE(des_tdes_algs), +}; + +struct aml_tdes_info aml_tdes_lite = { + .algs = tdes_lite_algs, + .num_algs = ARRAY_SIZE(tdes_lite_algs), +}; + +#ifdef CONFIG_OF +static const struct of_device_id aml_tdes_dt_match[] = { + { .compatible = "amlogic,des_dma,tdes_dma", + .data = &aml_des_tdes, + }, + { .compatible = "amlogic,tdes_dma", + .data = &aml_tdes_lite, + }, + {}, +}; +#else +#define aml_tdes_dt_match NULL +#endif + static int aml_tdes_probe(struct platform_device *pdev) { struct aml_tdes_dev *tdes_dd; struct device *dev = &pdev->dev; int err = -EPERM; + const struct of_device_id *match; + const struct aml_tdes_info *tdes_info = NULL; - tdes_dd = kzalloc(sizeof(struct aml_tdes_dev), GFP_KERNEL); + tdes_dd = devm_kzalloc(dev, sizeof(struct aml_tdes_dev), GFP_KERNEL); if (tdes_dd == NULL) { err = -ENOMEM; goto tdes_dd_err; } + match = of_match_device(aml_tdes_dt_match, &pdev->dev); + if (!match) { + dev_err(dev, "%s: cannot find match dt\n", __func__); + err = -EINVAL; + goto tdes_dd_err; + } + + tdes_info = match->data; tdes_dd->dev = dev; tdes_dd->dma = dev_get_drvdata(dev->parent); tdes_dd->thread = tdes_dd->dma->thread; @@ -899,8 +1104,8 @@ static int aml_tdes_probe(struct platform_device *pdev) (unsigned long)tdes_dd); crypto_init_queue(&tdes_dd->queue, AML_TDES_QUEUE_LENGTH); - err = request_irq(tdes_dd->irq, aml_tdes_irq, IRQF_SHARED, "aml-tdes", - tdes_dd); + err = devm_request_irq(dev, tdes_dd->irq, aml_tdes_irq, IRQF_SHARED, + "aml-tdes", tdes_dd); if (err) { dev_err(dev, "unable to request tdes irq.\n"); goto tdes_irq_err; @@ -918,7 +1123,7 @@ static int aml_tdes_probe(struct platform_device *pdev) list_add_tail(&tdes_dd->list, &aml_tdes.dev_list); spin_unlock(&aml_tdes.lock); - err = aml_tdes_register_algs(tdes_dd); + err = aml_tdes_register_algs(tdes_dd, tdes_info); if (err) goto err_algs; @@ -932,13 +1137,9 @@ err_algs: spin_unlock(&aml_tdes.lock); aml_tdes_buff_cleanup(tdes_dd); err_tdes_buff: - free_irq(tdes_dd->irq, tdes_dd); tdes_irq_err: - tasklet_kill(&tdes_dd->done_task); tasklet_kill(&tdes_dd->queue_task); - kfree(tdes_dd); - tdes_dd = NULL; tdes_dd_err: dev_err(dev, "initialization failed.\n"); @@ -948,38 +1149,33 @@ tdes_dd_err: static int aml_tdes_remove(struct platform_device *pdev) { static struct aml_tdes_dev *tdes_dd; + struct device *dev = &pdev->dev; + const struct of_device_id *match; + const struct aml_tdes_info *tdes_info = NULL; tdes_dd = platform_get_drvdata(pdev); if (!tdes_dd) return -ENODEV; + + match = of_match_device(aml_tdes_dt_match, &pdev->dev); + if (!match) { + dev_err(dev, "%s: cannot find match dt\n", __func__); + return -EINVAL; + } + + tdes_info = match->data; spin_lock(&aml_tdes.lock); list_del(&tdes_dd->list); spin_unlock(&aml_tdes.lock); - aml_tdes_unregister_algs(tdes_dd); + aml_tdes_unregister_algs(tdes_dd, tdes_info); tasklet_kill(&tdes_dd->done_task); tasklet_kill(&tdes_dd->queue_task); - if (tdes_dd->irq > 0) - free_irq(tdes_dd->irq, tdes_dd); - - kfree(tdes_dd); - tdes_dd = NULL; - return 0; } -#ifdef CONFIG_OF -static const struct of_device_id aml_tdes_dt_match[] = { - { .compatible = "amlogic,des_dma,tdes_dma", - }, - {}, -}; -#else -#define aml_tdes_dt_match NULL -#endif - static struct platform_driver aml_tdes_driver = { .probe = aml_tdes_probe, .remove = aml_tdes_remove, diff --git a/drivers/amlogic/ddr_tool/ddr_bandwidth.c b/drivers/amlogic/ddr_tool/ddr_bandwidth.c index 513ed839bc68..fcb43354794f 100644 --- a/drivers/amlogic/ddr_tool/ddr_bandwidth.c +++ b/drivers/amlogic/ddr_tool/ddr_bandwidth.c @@ -74,7 +74,7 @@ static void cal_ddr_usage(struct ddr_bandwidth *db, struct ddr_grant *dg) freq = db->ops->get_freq(db); mul = dg->all_grant; mul *= 10000ULL; - mul /= 16; + do_div(mul, db->bytes_per_cycle); cnt = db->clock_count; do_div(mul, cnt); db->total_usage = mul; @@ -203,7 +203,8 @@ static ssize_t threshold_show(struct class *cla, struct class_attribute *attr, char *buf) { return sprintf(buf, "%d\n", - aml_db->threshold / 16 / (aml_db->clock_count / 10000)); + aml_db->threshold / aml_db->bytes_per_cycle + / (aml_db->clock_count / 10000)); } static ssize_t threshold_store(struct class *cla, @@ -218,7 +219,8 @@ static ssize_t threshold_store(struct class *cla, if (val > 10000) val = 10000; - aml_db->threshold = val * 16 * (aml_db->clock_count / 10000); + aml_db->threshold = val * aml_db->bytes_per_cycle + * (aml_db->clock_count / 10000); return count; } @@ -522,7 +524,7 @@ static void ddr_extcon_free(void) * to run, so add __ref to indicate it is okay to call __init function * ddr_find_port_desc */ -static int __ref ddr_bandwidth_probe(struct platform_device *pdev) +static int __init ddr_bandwidth_probe(struct platform_device *pdev) { int r = 0; #ifdef CONFIG_OF @@ -545,6 +547,11 @@ static int __ref ddr_bandwidth_probe(struct platform_device *pdev) goto inval; } + if (is_meson_txl_package_950() || is_meson_gxl_package_805X()) + aml_db->bytes_per_cycle = 8; + else + aml_db->bytes_per_cycle = 16; + /* set channel */ if (aml_db->cpu_type < MESON_CPU_MAJOR_ID_GXTVBB) { aml_db->channels = 1; @@ -599,7 +606,7 @@ static int __ref ddr_bandwidth_probe(struct platform_device *pdev) #endif aml_db->clock_count = DEFAULT_CLK_CNT; aml_db->mode = MODE_DISABLE; - aml_db->threshold = DEFAULT_THRESHOLD * 16 * + aml_db->threshold = DEFAULT_THRESHOLD * aml_db->bytes_per_cycle * (aml_db->clock_count / 10000); if (aml_db->cpu_type <= MESON_CPU_MAJOR_ID_GXTVBB) aml_db->ops = &gx_ddr_bw_ops; @@ -664,13 +671,13 @@ static struct platform_driver ddr_bandwidth_driver = { .of_match_table = aml_ddr_bandwidth_dt_match, #endif }, - .probe = ddr_bandwidth_probe, .remove = ddr_bandwidth_remove, }; static int __init ddr_bandwidth_init(void) { - return platform_driver_register(&ddr_bandwidth_driver); + return platform_driver_probe(&ddr_bandwidth_driver, + ddr_bandwidth_probe); } static void __exit ddr_bandwidth_exit(void) diff --git a/drivers/amlogic/ddr_tool/ddr_port_desc.c b/drivers/amlogic/ddr_tool/ddr_port_desc.c index bce96aae833e..190d4ea72b60 100644 --- a/drivers/amlogic/ddr_tool/ddr_port_desc.c +++ b/drivers/amlogic/ddr_tool/ddr_port_desc.c @@ -421,6 +421,41 @@ static struct ddr_port_desc ddr_port_desc_txhd[] __initdata = { { .port_id = 47, .port_name = "DEMOD" } }; +static struct ddr_port_desc ddr_port_desc_tl1[] __initdata = { + { .port_id = 0, .port_name = "ARM" }, + { .port_id = 1, .port_name = "MALI0" }, + { .port_id = 3, .port_name = "HDCP_HDMI" }, + { .port_id = 4, .port_name = "HEVC FRONT" }, + { .port_id = 5, .port_name = "TEST" }, + { .port_id = 6, .port_name = "USB3.0" }, + { .port_id = 7, .port_name = "DEVICE" }, + { .port_id = 8, .port_name = "HEVC BACK" }, + { .port_id = 16, .port_name = "VPU READ1" }, + { .port_id = 17, .port_name = "VPU READ2" }, + { .port_id = 18, .port_name = "VPU READ3" }, + { .port_id = 19, .port_name = "VPU WRITE1" }, + { .port_id = 20, .port_name = "VPU WRITE2" }, + { .port_id = 21, .port_name = "VDEC" }, + { .port_id = 22, .port_name = "HCODEC" }, + { .port_id = 23, .port_name = "GE2D" }, + /* start of each device */ + { .port_id = 32, .port_name = "SPICC1" }, + { .port_id = 33, .port_name = "USB0" }, + { .port_id = 34, .port_name = "DMA" }, + { .port_id = 35, .port_name = "ARB0" }, + { .port_id = 36, .port_name = "SD_EMMC_B" }, + { .port_id = 37, .port_name = "USB1" }, + { .port_id = 38, .port_name = "AUDIO" }, + { .port_id = 39, .port_name = "AIFIFO" }, + { .port_id = 41, .port_name = "PASER" }, + { .port_id = 42, .port_name = "AO CPU" }, + { .port_id = 43, .port_name = "SD_EMMC_C" }, + { .port_id = 44, .port_name = "SPICC2" }, + { .port_id = 45, .port_name = "ETHERNET" }, + { .port_id = 46, .port_name = "SANA" }, + { .port_id = 47, .port_name = "DEMOD" } +}; + static struct ddr_port_desc *chip_ddr_port; static unsigned char chip_ddr_port_num; @@ -489,6 +524,11 @@ int __init ddr_find_port_desc(int cpu_type, struct ddr_port_desc **desc) desc_size = ARRAY_SIZE(ddr_port_desc_g12b); break; + case MESON_CPU_MAJOR_ID_TL1: + *desc = ddr_port_desc_tl1; + desc_size = ARRAY_SIZE(ddr_port_desc_tl1); + break; + default: return -EINVAL; } diff --git a/drivers/amlogic/ddr_tool/dmc_g12.c b/drivers/amlogic/ddr_tool/dmc_g12.c index 8276e157f4f6..8e35e212697e 100644 --- a/drivers/amlogic/ddr_tool/dmc_g12.c +++ b/drivers/amlogic/ddr_tool/dmc_g12.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -76,12 +77,31 @@ static size_t g12_dmc_dump_reg(char *buf) return sz; } +static void show_violation_mem(unsigned long addr) +{ + struct page *page; + unsigned long *p, *q; + + if (!pfn_valid(__phys_to_pfn(addr))) + return; + + page = phys_to_page(addr); + p = kmap_atomic(page); + if (!p) + return; + + q = p + ((addr & (PAGE_SIZE - 1)) / sizeof(*p)); + pr_info(DMC_TAG "[%08lx]:%016lx, f:%8lx, m:%p, a:%ps\n", + (unsigned long)q, *q, page->flags & 0xffffffff, + page->mapping, + (void *)get_page_trace(page)); + kunmap_atomic(p); +} + static void check_violation(struct dmc_monitor *mon) { int i, port, subport; unsigned long addr, status; - struct page *page; - unsigned long *p; char id_str[4]; char off1 = 21, off2 = 10; @@ -112,16 +132,7 @@ static void check_violation(struct dmc_monitor *mon) pr_info(DMC_TAG", addr:%08lx, s:%08lx, ID:%s, sub:%s, c:%ld\n", addr, status, to_ports(port), to_sub_ports(port, subport, id_str), mon->same_page); - if (pfn_valid(__phys_to_pfn(addr))) { - page = phys_to_page(addr); - p = (page_address(page) + (addr & (PAGE_SIZE - 1))); -#if defined(CONFIG_AMLOGIC_PAGE_TRACE) - pr_info(DMC_TAG" [%08lx]:%016lx, f:%8lx, m:%p, a:%pf\n", - addr, *p, page->flags & 0xffffffff, - page->mapping, - (void *)get_page_trace(page)); -#endif - } + show_violation_mem(addr); if (!port) /* dump stack for CPU write */ dump_stack(); diff --git a/drivers/amlogic/ddr_tool/dmc_gx.c b/drivers/amlogic/ddr_tool/dmc_gx.c index bc07f7a31d21..7871970cdd6a 100644 --- a/drivers/amlogic/ddr_tool/dmc_gx.c +++ b/drivers/amlogic/ddr_tool/dmc_gx.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -80,12 +81,31 @@ static size_t gx_dmc_dump_reg(char *buf) return sz; } +static void show_violation_mem(unsigned long addr) +{ + struct page *page; + unsigned long *p, *q; + + if (!pfn_valid(__phys_to_pfn(addr))) + return; + + page = phys_to_page(addr); + p = kmap_atomic(page); + if (!p) + return; + + q = p + ((addr & (PAGE_SIZE - 1)) / sizeof(*p)); + pr_info(DMC_TAG "[%08lx]:%016lx, f:%8lx, m:%p, a:%ps\n", + (unsigned long)q, *q, page->flags & 0xffffffff, + page->mapping, + (void *)get_page_trace(page)); + kunmap_atomic(p); +} + static void check_violation(struct dmc_monitor *mon) { int i, port, subport; unsigned long addr, status; - struct page *page; - unsigned long *p; char id_str[4]; for (i = 1; i < 8; i += 2) { @@ -109,16 +129,7 @@ static void check_violation(struct dmc_monitor *mon) pr_info(DMC_TAG", addr:%08lx, s:%08lx, ID:%s, sub:%s, c:%ld\n", addr, status, to_ports(port), to_sub_ports(port, subport, id_str), mon->same_page); - if (pfn_valid(__phys_to_pfn(addr))) { - page = phys_to_page(addr); - p = (page_address(page) + (addr & (PAGE_SIZE - 1))); -#if defined(CONFIG_AMLOGIC_PAGE_TRACE) - pr_info(DMC_TAG" [%08lx]:%016lx, f:%8lx, m:%p, a:%pf\n", - addr, *p, page->flags & 0xffffffff, - page->mapping, - (void *)get_page_trace(page)); -#endif - } + show_violation_mem(addr); if (!port) /* dump stack for CPU write */ dump_stack(); diff --git a/drivers/amlogic/debug/Kconfig b/drivers/amlogic/debug/Kconfig index 34af20905279..f8df94eac08a 100644 --- a/drivers/amlogic/debug/Kconfig +++ b/drivers/amlogic/debug/Kconfig @@ -13,3 +13,21 @@ config AMLOGIC_DEBUG_LOCKUP Debug lockup in isr and deaklock whit irq disabled. When enable this config, Watchdog should be disabled. +config AMLOGIC_DEBUG_ATRACE + bool "Amlogic Kernel ATrace" + depends on AMLOGIC_DEBUG + default y + help + Add android atrace compatible function + +config AMLOGIC_DEBUG_FTRACE_PSTORE + bool "Amlogic ftrace pstore debug" + depends on AMLOGIC_DEBUG + depends on PSTORE_FTRACE + default y + help + Dump function call and register access to ramoops after watchdog + reboot. + Enable if doubt. + + diff --git a/drivers/amlogic/debug/Makefile b/drivers/amlogic/debug/Makefile index 2f07bf942da5..9b2e3f18c519 100644 --- a/drivers/amlogic/debug/Makefile +++ b/drivers/amlogic/debug/Makefile @@ -1 +1,3 @@ obj-$(CONFIG_AMLOGIC_DEBUG_LOCKUP) += debug_lockup.o +obj-$(CONFIG_AMLOGIC_DEBUG_ATRACE) += meson_atrace.o +obj-$(CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE)+= debug_ftrace_ramoops.o diff --git a/drivers/amlogic/debug/debug_ftrace_ramoops.c b/drivers/amlogic/debug/debug_ftrace_ramoops.c new file mode 100644 index 000000000000..145c66f14266 --- /dev/null +++ b/drivers/amlogic/debug/debug_ftrace_ramoops.c @@ -0,0 +1,147 @@ +/* + * drivers/amlogic/debug/debug_ftrace_ramoops.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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include <../../../fs/pstore/internal.h> +#include +#include +#include + +static DEFINE_PER_CPU(int, en); + +#define IRQ_D 1 + +unsigned int dump_iomap; +core_param(dump_iomap, dump_iomap, uint, 0664); + +unsigned int ramoops_ftrace_en; +EXPORT_SYMBOL(ramoops_ftrace_en); + +int ramoops_io_en; +EXPORT_SYMBOL(ramoops_io_en); +core_param(ramoops_io_en, ramoops_io_en, int, 0664); + +const char *record_name[PSTORE_FLAG_IO_MAX] = { + "NULL", + "FUNC", + "IO-R", + "IO-W", + "IO-R-E", + "IO-W-E", +}; + +void notrace pstore_ftrace_save(struct pstore_ftrace_record *rec) +{ + int cpu = raw_smp_processor_id(); + + if (unlikely(oops_in_progress) || unlikely(per_cpu(en, cpu))) + return; + per_cpu(en, cpu) = 1; + pstore_ftrace_encode_cpu(rec, cpu); + strlcpy(rec->comm, current->comm, sizeof(rec->comm) - 1); + rec->pid = current->pid; + rec->time = trace_clock_local(); + psinfo->write_buf(PSTORE_TYPE_FTRACE, 0, NULL, 0, (void *)rec, + 0, sizeof(*rec), psinfo); + per_cpu(en, cpu) = 0; +} +EXPORT_SYMBOL(pstore_ftrace_save); + +static void notrace pstore_function_dump(struct pstore_ftrace_record *rec, + struct seq_file *s) +{ + unsigned long sec = 0, ms = 0; + unsigned long long time = rec->time; + + do_div(time, 1000000); + sec = (unsigned long)time / 1000; + ms = (unsigned long)time % 1000; + seq_printf(s, "[%04ld.%03ld@%d] <%5d-%s> <%pf <- %pF>\n", + sec, ms, pstore_ftrace_decode_cpu(rec), rec->pid, rec->comm, + (void *)rec->ip, (void *)rec->parent_ip); +} + +void notrace pstore_io_rw_dump(struct pstore_ftrace_record *rec, + struct seq_file *s) +{ + unsigned long sec = 0, ms = 0; + unsigned long long time = rec->time; + unsigned int cpu = pstore_ftrace_decode_cpu(rec); + + do_div(time, 1000000); + sec = (unsigned long)time / 1000; + ms = (unsigned long)time % 1000; + seq_printf(s, "[%04ld.%03ld@%d] <%5d-%6s> <%6s %08lx-%8lx> <%pf <- %pF>\n", + sec, ms, cpu, rec->pid, rec->comm, record_name[rec->flag], + rec->val1, (rec->flag == PSTORE_FLAG_IO_W) ? rec->val2 : 0, + (void *)rec->ip, (void *)rec->parent_ip); +} + +void notrace pstore_ftrace_dump(struct pstore_ftrace_record *rec, + struct seq_file *s) +{ + switch (rec->flag & PSTORE_FLAG_MASK) { + case PSTORE_FLAG_FUNC: + pstore_function_dump(rec, s); + break; + case PSTORE_FLAG_IO_R: + case PSTORE_FLAG_IO_W: + case PSTORE_FLAG_IO_W_END: + case PSTORE_FLAG_IO_R_END: + pstore_io_rw_dump(rec, s); + break; + default: + seq_printf(s, "Unknown Msg:%x\n", rec->flag); + } +} + +void notrace pstore_io_save(unsigned long reg, unsigned long val, + unsigned long parant, unsigned int flag, + unsigned long *irq_flag) +{ + struct pstore_ftrace_record rec; + + if (!ramoops_ftrace_en || !ramoops_io_en) + return; + + if ((flag == PSTORE_FLAG_IO_R || flag == PSTORE_FLAG_IO_W) && IRQ_D) + local_irq_save(*irq_flag); + + rec.ip = CALLER_ADDR0; + rec.parent_ip = parant; + rec.flag = flag; + rec.val1 = reg; + rec.val2 = val; + pstore_ftrace_save(&rec); + + if ((flag == PSTORE_FLAG_IO_R_END || flag == PSTORE_FLAG_IO_W_END) && + IRQ_D) + local_irq_restore(*irq_flag); +} +EXPORT_SYMBOL(pstore_io_save); + diff --git a/drivers/amlogic/debug/meson_atrace.c b/drivers/amlogic/debug/meson_atrace.c new file mode 100644 index 000000000000..f27132623503 --- /dev/null +++ b/drivers/amlogic/debug/meson_atrace.c @@ -0,0 +1,21 @@ +/* + * drivers/amlogic/debug/meson_atrace.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 CREATE_TRACE_POINTS +#include + +EXPORT_TRACEPOINT_SYMBOL_GPL(tracing_mark_write); diff --git a/drivers/amlogic/defendkey/defendkey.c b/drivers/amlogic/defendkey/defendkey.c index 1ee1a1c4a1b5..a82f49d4949d 100644 --- a/drivers/amlogic/defendkey/defendkey.c +++ b/drivers/amlogic/defendkey/defendkey.c @@ -36,12 +36,13 @@ #include #include "securekey.h" #include +#include #define DEFENDKEY_DEVICE_NAME "defendkey" #define DEFENDKEY_CLASS_NAME "defendkey" void __iomem *mem_base_virt; unsigned long mem_size; -unsigned long random_virt; +//unsigned long random_virt; struct defendkey_mem { unsigned long base; @@ -201,7 +202,7 @@ static ssize_t defendkey_write(struct file *file, pr_info("defendkey: mem_base_phy:%lx mem_size:%lx mem_base_virt:%p\n", mem_base_phy, mem_size, mem_base_virt); - random = readl((void *)random_virt); + random = get_random_long(); #ifdef CONFIG_ARM64_A32 option_random = (random << 8); @@ -400,7 +401,6 @@ static int aml_defendkey_probe(struct platform_device *pdev) { int ret = -1; u64 val64; - struct resource *res; struct device *devp; @@ -421,19 +421,7 @@ static int aml_defendkey_probe(struct platform_device *pdev) mem_size = val64; if (mem_size > defendkey_rmem.size) { dev_err(&pdev->dev, "Reserved memory is not enough!\n"); - return -EINVAL; - } - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (IS_ERR(res)) { - dev_err(&pdev->dev, "reg: cannot obtain I/O memory region"); - ret = PTR_ERR(res); - goto error1; - } - - random_virt = (unsigned long)devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR((void *)random_virt)) { - ret = PTR_ERR((void *)random_virt); + ret = -EINVAL; goto error1; } diff --git a/drivers/amlogic/drm/am_meson_vpu.c b/drivers/amlogic/drm/am_meson_vpu.c index fccfdc20a88a..9c7850b715b3 100644 --- a/drivers/amlogic/drm/am_meson_vpu.c +++ b/drivers/amlogic/drm/am_meson_vpu.c @@ -208,7 +208,7 @@ static struct osd_device_data_s osd_g12a = { .cpu_id = __MESON_CPU_MAJOR_ID_G12A, .osd_ver = OSD_HIGH_ONE, .afbc_type = MALI_AFBC, - .osd_count = 3, + .osd_count = 4, .has_deband = 1, .has_lut = 1, .has_rdma = 1, @@ -223,7 +223,7 @@ static struct osd_device_data_s osd_g12b = { .cpu_id = __MESON_CPU_MAJOR_ID_G12B, .osd_ver = OSD_HIGH_ONE, .afbc_type = MALI_AFBC, - .osd_count = 3, + .osd_count = 4, .has_deband = 1, .has_lut = 1, .has_rdma = 1, @@ -240,15 +240,22 @@ static struct page *logo_page; static struct delayed_work osd_dwork; static struct platform_device *gp_dev; + int am_meson_crtc_dts_info_set(const void *dt_match_data) { struct osd_device_data_s *osd_meson; osd_meson = (struct osd_device_data_s *)dt_match_data; - if (osd_meson) + if (osd_meson) { memcpy(&osd_meson_dev, osd_meson, sizeof(struct osd_device_data_s)); - else { + osd_meson_dev.viu1_osd_count = osd_meson_dev.osd_count; + if (osd_meson_dev.has_viu2) { + /* set viu1 osd count */ + osd_meson_dev.viu1_osd_count--; + osd_meson_dev.viu2_index = osd_meson_dev.viu1_osd_count; + } + } else { DRM_ERROR("%s data NOT match\n", __func__); return -1; } diff --git a/drivers/amlogic/efuse/efuse64.c b/drivers/amlogic/efuse/efuse64.c index e9b524ef57a7..ed4e2f9414f8 100644 --- a/drivers/amlogic/efuse/efuse64.c +++ b/drivers/amlogic/efuse/efuse64.c @@ -229,19 +229,6 @@ static int odroid_provision(struct odroid_efuse_t *fuse) return 0; } - -#include - -void odroid_get_ether_addr(unsigned char *addr) -{ - loff_t pos = 0x46; - int ret; - - ret = efuse_read_usr(addr, ETH_ALEN, &pos); - if (ret < 0) - memset(addr, 0, ETH_ALEN); -} -EXPORT_SYMBOL(odroid_get_ether_addr); #endif static long efuse_unlocked_ioctl(struct file *file, unsigned int cmd, diff --git a/drivers/amlogic/efuse/efuse_hw64.c b/drivers/amlogic/efuse/efuse_hw64.c index 6da11f489755..f73959033bf9 100644 --- a/drivers/amlogic/efuse/efuse_hw64.c +++ b/drivers/amlogic/efuse/efuse_hw64.c @@ -33,7 +33,7 @@ #include #include -static long meson_efuse_fn_smc(struct efuse_hal_api_arg *arg) +static long meson64_efuse_fn_smc(struct efuse_hal_api_arg *arg) { long ret; unsigned int cmd, offset, size; @@ -71,16 +71,18 @@ static long meson_efuse_fn_smc(struct efuse_hal_api_arg *arg) return 0; } -int meson_trustzone_efuse(struct efuse_hal_api_arg *arg) +int meson64_trustzone_efuse(struct efuse_hal_api_arg *arg) { int ret; + struct cpumask org_cpumask; if (!arg) return -1; + cpumask_copy(&org_cpumask, ¤t->cpus_allowed); set_cpus_allowed_ptr(current, cpumask_of(0)); - ret = meson_efuse_fn_smc(arg); - set_cpus_allowed_ptr(current, cpu_all_mask); + ret = meson64_efuse_fn_smc(arg); + set_cpus_allowed_ptr(current, &org_cpumask); return ret; } @@ -101,7 +103,7 @@ unsigned long efuse_aml_sec_boot_check(unsigned long nType, memcpy((void *)sharemem_input_base, (const void *)pBuffer, nLength); - __flush_dcache_area(sharemem_input_base, nLength); + //__flush_dcache_area(sharemem_input_base, nLength); asm __volatile__("" : : : "memory"); @@ -122,18 +124,20 @@ unsigned long efuse_aml_sec_boot_check(unsigned long nType, unsigned long efuse_amlogic_set(char *buf, size_t count) { unsigned long ret; + struct cpumask org_cpumask; + cpumask_copy(&org_cpumask, ¤t->cpus_allowed); set_cpus_allowed_ptr(current, cpumask_of(0)); ret = efuse_aml_sec_boot_check(AML_D_P_W_EFUSE_AMLOGIC, (unsigned long)buf, (unsigned long)count, 0); - set_cpus_allowed_ptr(current, cpu_all_mask); + set_cpus_allowed_ptr(current, &org_cpumask); return ret; } -ssize_t meson_trustzone_efuse_get_max(struct efuse_hal_api_arg *arg) +ssize_t meson64_trustzone_efuse_get_max(struct efuse_hal_api_arg *arg) { ssize_t ret; unsigned int cmd; @@ -160,12 +164,14 @@ ssize_t efuse_get_max(void) { struct efuse_hal_api_arg arg; int ret; + struct cpumask org_cpumask; arg.cmd = EFUSE_HAL_API_USER_MAX; + cpumask_copy(&org_cpumask, ¤t->cpus_allowed); set_cpus_allowed_ptr(current, cpumask_of(0)); - ret = meson_trustzone_efuse_get_max(&arg); - set_cpus_allowed_ptr(current, cpu_all_mask); + ret = meson64_trustzone_efuse_get_max(&arg); + set_cpus_allowed_ptr(current, &org_cpumask); if (ret == 0) { pr_info("ERROR: can not get efuse user max bytes!!!\n"); @@ -187,7 +193,7 @@ ssize_t _efuse_read(char *buf, size_t count, loff_t *ppos) arg.size = count; arg.buffer = (unsigned long)buf; arg.retcnt = (unsigned long)&retcnt; - ret = meson_trustzone_efuse(&arg); + ret = meson64_trustzone_efuse(&arg); if (ret == 0) { *ppos += retcnt; return retcnt; @@ -211,7 +217,7 @@ ssize_t _efuse_write(const char *buf, size_t count, loff_t *ppos) arg.buffer = (unsigned long)buf; arg.retcnt = (unsigned long)&retcnt; - ret = meson_trustzone_efuse(&arg); + ret = meson64_trustzone_efuse(&arg); if (ret == 0) { *ppos = retcnt; return retcnt; diff --git a/drivers/amlogic/ethernet/phy/amlogic.c b/drivers/amlogic/ethernet/phy/amlogic.c index e94026241a55..4db2444ec9bd 100644 --- a/drivers/amlogic/ethernet/phy/amlogic.c +++ b/drivers/amlogic/ethernet/phy/amlogic.c @@ -386,7 +386,6 @@ static struct phy_driver amlogic_internal_driver[] = { .read_status = genphy_read_status, .suspend = genphy_suspend, .resume = genphy_resume, - .remove = internal_phy_remove, } }; module_phy_driver(amlogic_internal_driver); diff --git a/drivers/amlogic/i2c/aml_slave.c b/drivers/amlogic/i2c/aml_slave.c index a82966ba7128..e4b7e7a88612 100644 --- a/drivers/amlogic/i2c/aml_slave.c +++ b/drivers/amlogic/i2c/aml_slave.c @@ -229,7 +229,7 @@ static int i2c_slave_probe(struct platform_device *pdev) return 0; } - +#if 0 static int __init i2c_auto_test_setup(char *s) { if (s != NULL) @@ -238,7 +238,7 @@ static int __init i2c_auto_test_setup(char *s) return 0; } __setup("i2c_auto_test=", i2c_auto_test_setup); - +#endif static int i2c_slave_remove(struct platform_device *pdev) { struct aml_i2c_slave *slave; diff --git a/drivers/amlogic/i2c/i2c-meson-master.c b/drivers/amlogic/i2c/i2c-meson-master.c index 8bd7d4797ed5..17458e76adbc 100644 --- a/drivers/amlogic/i2c/i2c-meson-master.c +++ b/drivers/amlogic/i2c/i2c-meson-master.c @@ -110,6 +110,7 @@ struct meson_i2c { int count; int pos; int error; + int retries; spinlock_t lock; struct completion done; @@ -161,13 +162,31 @@ static void meson_i2c_write_tokens(struct meson_i2c *i2c) /* * Count = clk/freq = H + L * Duty = H/(H + L) = 1/2 -- duty 50% + * 1. register desription + * in I2C_CONTROL_REG , n = [28:29][21:12], control the high level time + * n consists of 12bit, [21:12] is the low 10bit, + * [28:29] is the bit 11 and 12. + * in I2C_SLAVE_ADDRESS, m = [27:16], control the low level time, + * bit 28 enable the function + * + * 2.I2C controller internal characteristic * H = n + delay * L = 2m + * (H:high clock counts equals n + 15 clocks which + * cost by sampling and filtering + * L:low clock counts equals m multiply by 2) + * + * 3.high level and low level relationship: + * H/L = (n + 15)/2m = 1/1 + * H+L = 2m + n +15 = Count + * Count = 166M/freq = 166M/100k * * => * * n = Count/2 - delay * m = Count/4 + * + * n equals div_h, m equals div_l below * Standard Mode : 100k */ static void meson_i2c_set_clk_div_std(struct meson_i2c *i2c) @@ -324,6 +343,8 @@ static void meson_i2c_prepare_xfer(struct meson_i2c *i2c) if (write) meson_i2c_put_data(i2c, i2c->msg->buf + i2c->pos, i2c->count); + + i2c->retries = 0; } static void meson_i2c_stop(struct meson_i2c *i2c) @@ -346,7 +367,6 @@ static irqreturn_t meson_i2c_irq(int irqno, void *dev_id) spin_lock(&i2c->lock); - meson_i2c_reset_tokens(i2c); ctrl = readl(i2c->regs + REG_CTRL); dev_dbg(i2c->dev, "irq: state %d, pos %d, count %d, ctrl %08x\n", @@ -360,12 +380,15 @@ static irqreturn_t meson_i2c_irq(int irqno, void *dev_id) * condition. */ dev_dbg(i2c->dev, "error bit set\n"); - i2c->error = -ENXIO; - i2c->state = STATE_IDLE; - complete(&i2c->done); + if (++i2c->retries >= i2c->adap.retries) { + i2c->error = -ENXIO; + i2c->state = STATE_IDLE; + complete(&i2c->done); + } goto out; } + meson_i2c_reset_tokens(i2c); switch (i2c->state) { case STATE_READ: if (i2c->count > 0) { diff --git a/drivers/amlogic/iio/adc/meson_saradc.c b/drivers/amlogic/iio/adc/meson_saradc.c index dc58464eb710..9b4ab35f53f2 100644 --- a/drivers/amlogic/iio/adc/meson_saradc.c +++ b/drivers/amlogic/iio/adc/meson_saradc.c @@ -38,6 +38,7 @@ #include #include #include +#include #define MESON_SAR_ADC_REG0 0x00 #define MESON_SAR_ADC_REG0_PANEL_DETECT BIT(31) @@ -110,8 +111,8 @@ #define MESON_SAR_ADC_FIFO_RD_SAMPLE_VALUE_MASK GENMASK(11, 0) #define MESON_SAR_ADC_AUX_SW 0x1c - #define MESON_SAR_ADC_AUX_SW_MUX_SEL_CHAN_MASK(_chan) \ - (GENMASK(10, 8) << (((_chan) - 2) * 2)) + #define MESON_SAR_ADC_AUX_SW_MUX_SEL_CHAN_SHIFT(_chan) \ + (8 + (((_chan) - 2) * 3)) #define MESON_SAR_ADC_AUX_SW_VREF_P_MUX BIT(6) #define MESON_SAR_ADC_AUX_SW_VREF_N_MUX BIT(5) #define MESON_SAR_ADC_AUX_SW_MODE_SEL BIT(4) @@ -174,6 +175,9 @@ */ #define MESON_SAR_ADC_REG11 0x2c #define MESON_SAR_ADC_REG11_VREF_SEL BIT(0) + #define MESON_SAR_ADC_REG11_EOC BIT(1) + #define MESON_SAR_ADC_REG11_VREF_EN BIT(5) + #define MESON_SAR_ADC_REG11_CMV_SEL BIT(6) #define MESON_SAR_ADC_REG11_BANDGAP_EN BIT(13) #define MESON_SAR_ADC_REG11_CHNL_REGS_EN BIT(30) #define MESON_SAR_ADC_REG11_FIFO_EN BIT(31) @@ -210,9 +214,7 @@ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ BIT(IIO_CHAN_INFO_AVERAGE_RAW) | \ BIT(IIO_CHAN_INFO_PROCESSED), \ - .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \ - BIT(IIO_CHAN_INFO_CALIBBIAS) | \ - BIT(IIO_CHAN_INFO_CALIBSCALE), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ .scan_type = { \ .sign = 'u', \ .storagebits = 16, \ @@ -305,9 +307,15 @@ enum vref_select { * * @reg3_ring_counter_disable: to disable continuous ring counter. * gxl and later: 1; others(gxtvbb etc): 0 + * @reg11_vref_en: g12a and later: 0; others(gxl etc): 1 + * @reg11_cmv_sel: g12a and later: 0; others(gxl etc): 1 + * @reg11_eoc: g12a and later: 1; others(gxl etc): 0 */ struct meson_sar_adc_reg_diff { bool reg3_ring_counter_disable; + bool reg11_vref_en; + bool reg11_cmv_sel; + bool reg11_eoc; }; /* @@ -316,6 +324,7 @@ struct meson_sar_adc_reg_diff { * @obt_temp_chan6: whether to read data of temp sensor by channel 6 * @has_bl30_integration: * @vref_sel: txlx and later: VDDA; others(txl etc): calibration voltage + * @calib_enable: txlx and later: disable; others(txl etc): enable * @period_support: periodic sampling support * @has_chnl_regs: whether support for chnl[X] registers * @resolution: gxl and later: 12bit; others(gxtvbb etc): 10bit @@ -326,10 +335,12 @@ struct meson_sar_adc_data { bool obt_temp_chan6; bool has_bl30_integration; bool vref_sel; + bool calib_enable; bool period_support; bool has_chnl_regs; unsigned int resolution; const char *name; + const struct regmap_config *regmap_config; struct meson_sar_adc_reg_diff regs_diff; }; @@ -351,13 +362,27 @@ struct meson_sar_adc_priv { u8 *datum_buf; }; -static const struct regmap_config meson_sar_adc_regmap_config = { +static const struct regmap_config meson_sar_adc_regmap_config_g12a = { .reg_bits = 8, .val_bits = 32, .reg_stride = 4, .max_register = MESON_SAR_ADC_CHNL67, }; +static const struct regmap_config meson_sar_adc_regmap_config_gxbb = { + .reg_bits = 8, + .val_bits = 32, + .reg_stride = 4, + .max_register = MESON_SAR_ADC_REG13, +}; + +static const struct regmap_config meson_sar_adc_regmap_config_meson8 = { + .reg_bits = 8, + .val_bits = 32, + .reg_stride = 4, + .max_register = MESON_SAR_ADC_DELTA_10, +}; + static unsigned int meson_sar_adc_get_fifo_count(struct iio_dev *indio_dev) { struct meson_sar_adc_priv *priv = iio_priv(indio_dev); @@ -430,7 +455,10 @@ static int meson_sar_adc_read_raw_sample(struct iio_dev *indio_dev, fifo_val &= GENMASK(priv->data->resolution - 1, 0); /* to fix the sample value by software */ - *val = meson_sar_adc_calib_val(indio_dev, fifo_val); + if (priv->data->calib_enable) + *val = meson_sar_adc_calib_val(indio_dev, fifo_val); + else + *val = fifo_val; return 0; } @@ -471,7 +499,10 @@ static int meson_sar_adc_read_raw_sample_from_chnl(struct iio_dev *indio_dev, fifo_val &= GENMASK(priv->data->resolution - 1, 0); /* to fix the sample value by software */ - *val = meson_sar_adc_calib_val(indio_dev, fifo_val); + if (priv->data->calib_enable) + *val = meson_sar_adc_calib_val(indio_dev, fifo_val); + else + *val = fifo_val; return 0; } @@ -529,7 +560,7 @@ static void meson_sar_adc_enable_channel(struct iio_dev *indio_dev, MESON_SAR_ADC_CHAN_LIST_MAX_INDEX_MASK, regval); /* map channel index 0 to the channel which we want to read */ - regval = chan->channel << MESON_SAR_ADC_CHAN_LIST_ENTRY_SHIFT(idx), + regval = chan->channel << MESON_SAR_ADC_CHAN_LIST_ENTRY_SHIFT(idx); regmap_update_bits(priv->regmap, MESON_SAR_ADC_CHAN_LIST, MESON_SAR_ADC_CHAN_LIST_ENTRY_MASK(idx), regval); @@ -589,6 +620,7 @@ static int meson_sar_adc_lock(struct iio_dev *indio_dev) mutex_lock(&indio_dev->mlock); if (priv->data->has_bl30_integration) { +again: /* wait until BL30 releases it's lock (so we can use * the SAR ADC) */ @@ -606,10 +638,10 @@ static int meson_sar_adc_lock(struct iio_dev *indio_dev) MESON_SAR_ADC_DELAY_KERNEL_BUSY); isb(); dsb(sy); - udelay(1); + udelay(5); regmap_read(priv->regmap, MESON_SAR_ADC_DELAY, &val); if (val & MESON_SAR_ADC_DELAY_BL30_BUSY) - return -ETIMEDOUT; + goto again; } return 0; @@ -619,10 +651,14 @@ static void meson_sar_adc_unlock(struct iio_dev *indio_dev) { struct meson_sar_adc_priv *priv = iio_priv(indio_dev); - if (priv->data->has_bl30_integration) + if (priv->data->has_bl30_integration) { /* allow BL30 to use the SAR ADC again */ regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELAY, MESON_SAR_ADC_DELAY_KERNEL_BUSY, 0); + isb(); + dsb(sy); + udelay(5); + } mutex_unlock(&indio_dev->mlock); } @@ -737,10 +773,16 @@ static int meson_sar_adc_iio_info_read_raw(struct iio_dev *indio_dev, return IIO_VAL_FRACTIONAL_LOG2; case IIO_CHAN_INFO_CALIBBIAS: + if (!priv->data->calib_enable) + return -EINVAL; + *val = priv->calibbias; return IIO_VAL_INT; case IIO_CHAN_INFO_CALIBSCALE: + if (!priv->data->calib_enable) + return -EINVAL; + *val = priv->calibscale / MILLION; *val2 = priv->calibscale % MILLION; return IIO_VAL_INT_PLUS_MICRO; @@ -835,6 +877,7 @@ static int meson_sar_adc_init(struct iio_dev *indio_dev) { struct meson_sar_adc_priv *priv = iio_priv(indio_dev); int regval, ret; + int i; /* * make sure we start at CH7 input since the other muxes are only used @@ -895,6 +938,55 @@ static int meson_sar_adc_init(struct iio_dev *indio_dev) MESON_SAR_ADC_REG3_CTRL_CONT_RING_COUNTER_EN, FIELD_PREP(MESON_SAR_ADC_REG3_CTRL_CONT_RING_COUNTER_EN, priv->data->regs_diff.reg3_ring_counter_disable)); + + /* + * set up the input channel muxes in MESON_SAR_ADC_CHAN_10_SW + * (0 = SAR_ADC_CH0, 1 = SAR_ADC_CH1) + */ + regval = FIELD_PREP(MESON_SAR_ADC_CHAN_10_SW_CHAN0_MUX_SEL_MASK, 0); + regmap_update_bits(priv->regmap, MESON_SAR_ADC_CHAN_10_SW, + MESON_SAR_ADC_CHAN_10_SW_CHAN0_MUX_SEL_MASK, + regval); + + regmap_update_bits(priv->regmap, MESON_SAR_ADC_CHAN_10_SW, + MESON_SAR_ADC_CHAN_10_SW_CHAN0_XP_DRIVE_SW, + MESON_SAR_ADC_CHAN_10_SW_CHAN0_XP_DRIVE_SW); + + regmap_update_bits(priv->regmap, MESON_SAR_ADC_CHAN_10_SW, + MESON_SAR_ADC_CHAN_10_SW_CHAN0_YP_DRIVE_SW, + MESON_SAR_ADC_CHAN_10_SW_CHAN0_YP_DRIVE_SW); + + regval = FIELD_PREP(MESON_SAR_ADC_CHAN_10_SW_CHAN1_MUX_SEL_MASK, 1); + regmap_update_bits(priv->regmap, MESON_SAR_ADC_CHAN_10_SW, + MESON_SAR_ADC_CHAN_10_SW_CHAN1_MUX_SEL_MASK, + regval); + + regmap_update_bits(priv->regmap, MESON_SAR_ADC_CHAN_10_SW, + MESON_SAR_ADC_CHAN_10_SW_CHAN1_XP_DRIVE_SW, + MESON_SAR_ADC_CHAN_10_SW_CHAN1_XP_DRIVE_SW); + + regmap_update_bits(priv->regmap, MESON_SAR_ADC_CHAN_10_SW, + MESON_SAR_ADC_CHAN_10_SW_CHAN1_YP_DRIVE_SW, + MESON_SAR_ADC_CHAN_10_SW_CHAN1_YP_DRIVE_SW); + /* + * set up the input channel muxes in MESON_SAR_ADC_AUX_SW + * (2 = SAR_ADC_CH2, 3 = SAR_ADC_CH3, ...) and enable + * MESON_SAR_ADC_AUX_SW_YP_DRIVE_SW and + * MESON_SAR_ADC_AUX_SW_XP_DRIVE_SW like the vendor driver. + */ + regval = 0; + for (i = 2; i <= 7; i++) + regval |= i << MESON_SAR_ADC_AUX_SW_MUX_SEL_CHAN_SHIFT(i); + regval |= MESON_SAR_ADC_AUX_SW_YP_DRIVE_SW; + regval |= MESON_SAR_ADC_AUX_SW_XP_DRIVE_SW; + regmap_write(priv->regmap, MESON_SAR_ADC_AUX_SW, regval); + + /* must be set to <1> for g12a and later SoCs */ + regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG11, + MESON_SAR_ADC_REG11_EOC, + FIELD_PREP(MESON_SAR_ADC_REG11_EOC, + priv->data->regs_diff.reg11_eoc)); + /* select the vref */ regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG11, MESON_SAR_ADC_REG11_VREF_SEL, @@ -922,9 +1014,20 @@ static int meson_sar_adc_hw_enable(struct iio_dev *indio_dev) return ret; } + regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG11, + MESON_SAR_ADC_REG11_VREF_EN, + FIELD_PREP(MESON_SAR_ADC_REG11_VREF_EN, + priv->data->regs_diff.reg11_vref_en)); + + regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG11, + MESON_SAR_ADC_REG11_CMV_SEL, + FIELD_PREP(MESON_SAR_ADC_REG11_CMV_SEL, + priv->data->regs_diff.reg11_cmv_sel)); + regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG11, MESON_SAR_ADC_REG11_BANDGAP_EN, MESON_SAR_ADC_REG11_BANDGAP_EN); + regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG3, MESON_SAR_ADC_REG3_ADC_EN, MESON_SAR_ADC_REG3_ADC_EN); @@ -1302,8 +1405,12 @@ struct meson_sar_adc_data meson_sar_adc_g12a_data = { .vref_sel = VDDA_AS_VREF, .resolution = SAR_ADC_12BIT, .name = "meson-g12a-saradc", + .regmap_config = &meson_sar_adc_regmap_config_g12a, .regs_diff = { .reg3_ring_counter_disable = BIT_HIGH, + .reg11_vref_en = BIT_LOW, + .reg11_cmv_sel = BIT_LOW, + .reg11_eoc = BIT_HIGH, }, }; @@ -1313,8 +1420,12 @@ struct meson_sar_adc_data meson_sar_adc_txlx_data = { .vref_sel = VDDA_AS_VREF, .resolution = SAR_ADC_12BIT, .name = "meson-txlx-saradc", + .regmap_config = &meson_sar_adc_regmap_config_gxbb, .regs_diff = { .reg3_ring_counter_disable = BIT_HIGH, + .reg11_vref_en = BIT_HIGH, + .reg11_cmv_sel = BIT_HIGH, + .reg11_eoc = BIT_LOW, }, }; @@ -1324,8 +1435,12 @@ struct meson_sar_adc_data meson_sar_adc_axg_data = { .vref_sel = VDDA_AS_VREF, .resolution = SAR_ADC_12BIT, .name = "meson-axg-saradc", + .regmap_config = &meson_sar_adc_regmap_config_gxbb, .regs_diff = { .reg3_ring_counter_disable = BIT_HIGH, + .reg11_vref_en = BIT_HIGH, + .reg11_cmv_sel = BIT_HIGH, + .reg11_eoc = BIT_LOW, }, }; @@ -1333,10 +1448,15 @@ struct meson_sar_adc_data meson_sar_adc_txl_data = { .obt_temp_chan6 = false, .has_bl30_integration = true, .vref_sel = CALIB_VOL_AS_VREF, + .calib_enable = true, .resolution = SAR_ADC_12BIT, .name = "meson-txl-saradc", + .regmap_config = &meson_sar_adc_regmap_config_gxbb, .regs_diff = { .reg3_ring_counter_disable = BIT_HIGH, + .reg11_vref_en = BIT_HIGH, + .reg11_cmv_sel = BIT_HIGH, + .reg11_eoc = BIT_LOW, }, }; @@ -1344,10 +1464,15 @@ struct meson_sar_adc_data meson_sar_adc_gxl_data = { .obt_temp_chan6 = false, .has_bl30_integration = true, .vref_sel = CALIB_VOL_AS_VREF, + .calib_enable = true, .resolution = SAR_ADC_12BIT, .name = "meson-gxl-saradc", + .regmap_config = &meson_sar_adc_regmap_config_gxbb, .regs_diff = { .reg3_ring_counter_disable = BIT_HIGH, + .reg11_vref_en = BIT_HIGH, + .reg11_cmv_sel = BIT_HIGH, + .reg11_eoc = BIT_LOW, }, }; @@ -1355,10 +1480,15 @@ struct meson_sar_adc_data meson_sar_adc_gxm_data = { .obt_temp_chan6 = false, .has_bl30_integration = true, .vref_sel = CALIB_VOL_AS_VREF, + .calib_enable = true, .resolution = SAR_ADC_12BIT, .name = "meson-gxm-saradc", + .regmap_config = &meson_sar_adc_regmap_config_gxbb, .regs_diff = { .reg3_ring_counter_disable = BIT_HIGH, + .reg11_vref_en = BIT_HIGH, + .reg11_cmv_sel = BIT_HIGH, + .reg11_eoc = BIT_LOW, }, }; @@ -1366,8 +1496,10 @@ struct meson_sar_adc_data meson_sar_adc_m8b_data = { .obt_temp_chan6 = true, .has_bl30_integration = true, .vref_sel = CALIB_VOL_AS_VREF, + .calib_enable = true, .resolution = SAR_ADC_10BIT, .name = "meson-m8b-saradc", + .regmap_config = &meson_sar_adc_regmap_config_meson8, .regs_diff = { .reg3_ring_counter_disable = BIT_LOW, }, @@ -1407,8 +1539,10 @@ static int meson_sar_adc_probe(struct platform_device *pdev) struct resource *res; void __iomem *base; const struct of_device_id *match; + struct iio_chan_spec *chan; int ret; int irq; + int i; indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*priv)); if (!indio_dev) { @@ -1443,7 +1577,7 @@ static int meson_sar_adc_probe(struct platform_device *pdev) return -EINVAL; priv->regmap = devm_regmap_init_mmio(&pdev->dev, base, - &meson_sar_adc_regmap_config); + priv->data->regmap_config); if (IS_ERR(priv->regmap)) return PTR_ERR(priv->regmap); @@ -1480,8 +1614,6 @@ static int meson_sar_adc_probe(struct platform_device *pdev) return ret; } - priv->calibscale = MILLION; - if (priv->data->period_support) { ret = of_property_read_u32(pdev->dev.of_node, "amlogic,delay-per-tick", &priv->delay_per_tick); @@ -1520,10 +1652,24 @@ static int meson_sar_adc_probe(struct platform_device *pdev) if (ret) goto err; - ret = meson_sar_adc_calib(indio_dev); - if (ret) - dev_warn(&pdev->dev, "calibration failed\n"); + if (priv->data->calib_enable) { + priv->calibscale = MILLION; + for (i = 0; i < indio_dev->num_channels; i++) { + chan = (struct iio_chan_spec *)indio_dev->channels + i; + if (chan->channel < 0) + continue; + + chan->info_mask_shared_by_all = + BIT(IIO_CHAN_INFO_CALIBBIAS) | + BIT(IIO_CHAN_INFO_CALIBSCALE); + + } + ret = meson_sar_adc_calib(indio_dev); + if (ret) + dev_warn(&pdev->dev, "calibration failed\n"); + + } platform_set_drvdata(pdev, indio_dev); ret = iio_device_register(indio_dev); @@ -1557,6 +1703,9 @@ static int __maybe_unused meson_sar_adc_suspend(struct device *dev) struct iio_dev *indio_dev = dev_get_drvdata(dev); int ret; + if (is_pm_freeze_mode()) + return 0; + if (iio_buffer_enabled(indio_dev)) { ret = meson_sar_adc_buffer_predisable(indio_dev); if (ret) @@ -1575,6 +1724,9 @@ static int __maybe_unused meson_sar_adc_resume(struct device *dev) struct iio_dev *indio_dev = dev_get_drvdata(dev); int ret; + if (is_pm_freeze_mode()) + return 0; + ret = meson_sar_adc_hw_enable(indio_dev); if (ret) return ret; diff --git a/drivers/amlogic/input/keyboard/adc_keypad.c b/drivers/amlogic/input/keyboard/adc_keypad.c index 7182e595ab89..c1ad72014e22 100644 --- a/drivers/amlogic/input/keyboard/adc_keypad.c +++ b/drivers/amlogic/input/keyboard/adc_keypad.c @@ -576,6 +576,8 @@ static int meson_adc_kp_remove(struct platform_device *pdev) static int meson_adc_kp_suspend(struct platform_device *pdev, pm_message_t state) { + if (is_pm_freeze_mode()) + return 0; return 0; } @@ -584,6 +586,9 @@ static int meson_adc_kp_resume(struct platform_device *pdev) struct adc_key *key; struct meson_adc_kp *kp = platform_get_drvdata(pdev); + if (is_pm_freeze_mode()) + return 0; + if (get_resume_method() == POWER_KEY_WAKEUP) { list_for_each_entry(key, &kp->adckey_head, list) { if (key->code == KEY_POWER) { diff --git a/drivers/amlogic/input/keyboard/gpio_keypad.c b/drivers/amlogic/input/keyboard/gpio_keypad.c index 3fa6ea35bc30..fd43e6e2748e 100644 --- a/drivers/amlogic/input/keyboard/gpio_keypad.c +++ b/drivers/amlogic/input/keyboard/gpio_keypad.c @@ -343,6 +343,9 @@ static int meson_gpio_kp_suspend(struct platform_device *dev, { struct gpio_keypad *pdata; + if (is_pm_freeze_mode()) + return 0; + pdata = (struct gpio_keypad *)platform_get_drvdata(dev); if (!pdata->use_irq) del_timer(&(pdata->polling_timer)); @@ -354,6 +357,9 @@ static int meson_gpio_kp_resume(struct platform_device *dev) int i; struct gpio_keypad *pdata; + if (is_pm_freeze_mode()) + return 0; + pdata = (struct gpio_keypad *)platform_get_drvdata(dev); if (!pdata->use_irq) mod_timer(&(pdata->polling_timer), diff --git a/drivers/amlogic/input/remote/rc_common.h b/drivers/amlogic/input/remote/rc_common.h index 762a972c94ea..fdc6b8f09d0a 100644 --- a/drivers/amlogic/input/remote/rc_common.h +++ b/drivers/amlogic/input/remote/rc_common.h @@ -1,10 +1,20 @@ /* - * include/uapi/linux/rc_common.h from the kernel directory, but it can be used - * in kernel and user space. + * drivers/amlogic/input/remote/rc_common.h * - * Written by Amlogic + * 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 _UAPI_RC_COMMON_H_ #define _UAPI_RC_COMMON_H_ @@ -76,5 +86,10 @@ struct ir_sw_decode_para { #define REMOTE_IOC_SET_KEY_MAPPING_TAB _IOW('I', 4, __u32) #define REMOTE_IOC_SET_SW_DECODE_PARA _IOW('I', 5, __u32) #define REMOTE_IOC_GET_DATA_VERSION _IOR('I', 121, __u32) +#define REMOTE_IOC_SET_IR_LEARNING _IOW('I', 6, __u32) +#define REMOTE_IOC_GET_IR_LEARNING _IOR('I', 7, __u32) +#define REMOTE_IOC_GET_RAW_DATA _IOR('I', 8, __u32) +#define REMOTE_IOC_GET_SUM_CNT0 _IOR('I', 9, __u32) +#define REMOTE_IOC_GET_SUM_CNT1 _IOR('I', 10, __u32) #endif diff --git a/drivers/amlogic/input/remote/remote_cdev.c b/drivers/amlogic/input/remote/remote_cdev.c index 60d1be2a74c1..6bd8e66f14ad 100644 --- a/drivers/amlogic/input/remote/remote_cdev.c +++ b/drivers/amlogic/input/remote/remote_cdev.c @@ -48,6 +48,7 @@ static long remote_ioctl(struct file *file, unsigned int cmd, void __user *parg = (void __user *)arg; unsigned long flags; u32 value; + u8 val; int retval = 0; if (!parg) { @@ -107,11 +108,15 @@ static long remote_ioctl(struct file *file, unsigned int cmd, spin_lock_irqsave(&chip->slock, flags); ptable = seek_map_tab(chip, ir_map->tab.custom_code); if (ptable) { + dev_info(chip->dev, "remove custom_code 0x%08X from ir map table\n", + ir_map->tab.custom_code); if (ptable == chip->cur_tab) chip->cur_tab = ir_map; list_del(&ptable->list); ir_tab_free(ptable); } + dev_info(chip->dev, "add custom_code 0x%08X to ir map table\n", + ir_map->tab.custom_code); list_add_tail(&ir_map->list, &chip->map_tab_head); spin_unlock_irqrestore(&chip->slock, flags); chip->key_num.update_flag = false; @@ -126,6 +131,93 @@ static long remote_ioctl(struct file *file, unsigned int cmd, } chip->r_dev->max_frame_time = sw_data.max_frame_time; break; + case REMOTE_IOC_GET_IR_LEARNING: + if (copy_to_user(parg, &chip->r_dev->ir_learning_on, + sizeof(u8))) { + retval = -EFAULT; + goto err; + } + break; + + case REMOTE_IOC_SET_IR_LEARNING: + /*reset demudolation and carrier detect*/ + if (chip->r_dev->demod_enable) + demod_reset(chip); + + if (copy_from_user(&val, parg, sizeof(u8))) { + retval = -EFAULT; + goto err; + } + + chip->r_dev->ir_learning_on = !!val; + if (!!val) { + if (remote_pulses_malloc(chip) < 0) { + retval = -ENOMEM; + goto err; + } + chip->set_register_config(chip, REMOTE_TYPE_RAW_NEC); + /*backup protocol*/ + chip->r_dev->protocol = chip->protocol; + chip->protocol = REMOTE_TYPE_RAW_NEC; + } else { + chip->protocol = chip->r_dev->protocol; + chip->set_register_config(chip, chip->protocol); + remote_pulses_free(chip); + chip->r_dev->ir_learning_done = false; + } + break; + + case REMOTE_IOC_GET_RAW_DATA: + if (copy_to_user(parg, chip->r_dev->pulses, + sizeof(struct pulse_group) + + chip->r_dev->max_learned_pulse * + sizeof(unsigned int))) { + retval = -EFAULT; + goto err; + } + /*clear to prepear next frame*/ + memset(chip->r_dev->pulses, 0, sizeof(struct pulse_group) + + chip->r_dev->max_learned_pulse * + sizeof(unsigned int)); + + if (chip->r_dev->demod_enable) + demod_reset(chip); + + /*finish reading data ,enable state machine */ + remote_reg_update_bits(chip, MULTI_IR_ID, REG_REG1, BIT(15), + BIT(15)); + + chip->r_dev->ir_learning_done = false; + + break; + + case REMOTE_IOC_GET_SUM_CNT0: + if (chip->r_dev->demod_enable) { + remote_reg_read(chip, MULTI_IR_ID, REG_DEMOD_SUM_CNT0, + &value); + if (copy_to_user(parg, &value, sizeof(u32))) { + retval = -EFAULT; + goto err; + } + } else { + retval = -EFAULT; + goto err; + } + break; + + case REMOTE_IOC_GET_SUM_CNT1: + if (chip->r_dev->demod_enable) { + remote_reg_read(chip, MULTI_IR_ID, REG_DEMOD_SUM_CNT1, + &value); + if (copy_to_user(parg, &value, sizeof(u32))) { + retval = -EFAULT; + goto err; + } + } else { + retval = -EFAULT; + goto err; + } + break; default: retval = -ENOTTY; diff --git a/drivers/amlogic/input/remote/remote_core.h b/drivers/amlogic/input/remote/remote_core.h index 6b2d623991f3..b0f72517c271 100644 --- a/drivers/amlogic/input/remote/remote_core.h +++ b/drivers/amlogic/input/remote/remote_core.h @@ -58,7 +58,11 @@ enum raw_event_type { RAW_STOP_EVENT = (1 << 3), }; - +struct pulse_group { + int len; + /*bit 0-30 durations, bit31: level*/ + unsigned int pulse[0]; +}; struct remote_raw_handle; struct remote_dev { @@ -75,6 +79,19 @@ struct remote_dev { unsigned long delay_off; int led_blink; + /*for ir learnning feature*/ +#define MAX_LEARNED_PULSE 256 + /*ir learnning switch*/ + u8 ir_learning_on; + u8 ir_learning_done; + u8 demod_enable; + u8 use_fifo; + u8 auto_report; + int max_learned_pulse; + int protocol; + struct timer_list learning_done; + struct pulse_group *pulses; + struct timer_list timer_keyup; unsigned long keyup_jiffies; unsigned long keyup_delay; diff --git a/drivers/amlogic/input/remote/remote_meson.c b/drivers/amlogic/input/remote/remote_meson.c index 9458ee14929c..f53e1399c95d 100644 --- a/drivers/amlogic/input/remote/remote_meson.c +++ b/drivers/amlogic/input/remote/remote_meson.c @@ -43,10 +43,51 @@ #include static void amlremote_tasklet(unsigned long data); - +static void learning_done_workqueue(struct work_struct *work); +static void get_fifo_data_work(struct work_struct *work); DECLARE_TASKLET_DISABLED(tasklet, amlremote_tasklet, 0); +static void learning_done_workqueue(struct work_struct *work) +{ + struct delayed_work *w = container_of(work, struct delayed_work, work); + struct remote_chip *chip = + container_of(w, struct remote_chip, ir_workqueue); + char *envp[2] = { "LEARN_DONE", NULL}; + + kobject_uevent_env(&chip->dev->kobj, KOBJ_CHANGE, envp); +} + +int remote_pulses_malloc(struct remote_chip *chip) +{ + struct remote_dev *r_dev = chip->r_dev; + int len = r_dev->max_learned_pulse; + int ret = 0; + + if (r_dev->pulses) { + dev_info(chip->dev, "ir learning pulse already exists\n"); + return -EEXIST; + } + + r_dev->pulses = kzalloc(sizeof(struct pulse_group) + + len * sizeof(unsigned int), GFP_KERNEL); + + if (!r_dev->pulses) { + dev_err(chip->dev, "ir learning pulse alloc err\n"); + ret = -ENOMEM; + } + + return ret; +} + +void remote_pulses_free(struct remote_chip *chip) +{ + struct remote_dev *r_dev = chip->r_dev; + + kfree(r_dev->pulses); + r_dev->pulses = NULL; +} + int remote_reg_read(struct remote_chip *chip, unsigned char id, unsigned int reg, unsigned int *val) { @@ -73,6 +114,19 @@ int remote_reg_write(struct remote_chip *chip, unsigned char id, return 0; } +int remote_reg_update_bits(struct remote_chip *chip, unsigned char id, + unsigned int reg, unsigned int mask, unsigned int val) +{ + int orig = 0; + + remote_reg_read(chip, id, reg, &orig); + orig &= ~mask; + orig |= val & mask; + remote_reg_write(chip, id, reg, orig); + + return 0; +} + int ir_scancode_sort(struct ir_map_tab *ir_map) { bool is_sorted; @@ -300,9 +354,64 @@ static void amlremote_tasklet(unsigned long data) } +static void get_fifo_data_work(struct work_struct *work) +{ + struct remote_chip *chip = + container_of(work, struct remote_chip, fifo_work); + struct remote_dev *r_dev = chip->r_dev; + int val = 0; + int is_fifo_pending = 0; + int is_fifo_timeout = 0; + int is_fifo_empty = 0; + u32 duration = 0; + + remote_reg_read(chip, MULTI_IR_ID, REG_FIFO, &val); + is_fifo_pending = (val >> 30) & 0x01; + is_fifo_timeout = (val >> 29) & 0x01; + is_fifo_empty = (val >> 27) & 0x01; + + /*disable interrupt*/ + remote_reg_update_bits(chip, MULTI_IR_ID, REG_FIFO, GENMASK(22, 23), 0); + + if (is_fifo_pending || is_fifo_timeout) { + /*clear state*/ + remote_reg_update_bits(chip, MULTI_IR_ID, REG_FIFO, + GENMASK(29, 30), GENMASK(29, 30)); + + for (; !is_fifo_empty; ) { + + remote_reg_read(chip, MULTI_IR_ID, REG_WITH, &val); + val = val & GENMASK(12, 0); + + duration = val; + r_dev->pulses->pulse[r_dev->pulses->len] = duration; + + if (r_dev->pulses->len % 2 == 1) + r_dev->pulses->pulse[r_dev->pulses->len] + |= BIT(31); + + r_dev->pulses->len++; + + remote_reg_read(chip, MULTI_IR_ID, REG_FIFO, &val); + is_fifo_empty = (val >> 27) & 0x01; + + } + } + + /*enable interrupt*/ + remote_reg_update_bits(chip, MULTI_IR_ID, REG_FIFO, GENMASK(22, 23), + GENMASK(22, 23)); + + if (r_dev->auto_report) + mod_timer(&r_dev->learning_done, + jiffies + msecs_to_jiffies(50)); +} + static irqreturn_t ir_interrupt(int irq, void *dev_id) { struct remote_chip *rc = (struct remote_chip *)dev_id; + struct remote_dev *r_dev = rc->r_dev; + struct pulse_group *pgs; int contr_status = 0; int val = 0; u32 duration; @@ -312,12 +421,40 @@ static irqreturn_t ir_interrupt(int irq, void *dev_id) remote_reg_read(rc, MULTI_IR_ID, REG_REG1, &val); val = (val & 0x1FFF0000) >> 16; - sprintf(buf, "d:%d\n", val); + sprintf(buf, "duration:%d\n", val); debug_log_printk(rc->r_dev, buf); /** *software decode multiple protocols by using Time Measurement of *multif-format IR controller */ + + if (r_dev->ir_learning_on && !r_dev->ir_learning_done) { + pgs = r_dev->pulses; + if (pgs->len >= r_dev->max_learned_pulse) { + remote_reg_update_bits(rc, MULTI_IR_ID, REG_REG1, + BIT(15), 0); + return IRQ_HANDLED; + } + if (!r_dev->use_fifo) { + if (r_dev->auto_report) + mod_timer(&r_dev->learning_done, + jiffies + msecs_to_jiffies(50)); + /*get pulse durations unit:10us*/ + pgs->pulse[pgs->len] = val & GENMASK(30, 0); + /*get pulse level*/ + remote_reg_read(rc, MULTI_IR_ID, REG_STATUS, &val); + val = !!((val >> 8) & 0x01); + pgs->pulse[pgs->len] &= ~BIT(31); + if (val) + pgs->pulse[pgs->len] |= BIT(31); + + r_dev->pulses->len++; + } else { + schedule_work(&rc->fifo_work); + } + return IRQ_HANDLED; + } + if (MULTI_IR_SOFTWARE_DECODE(rc->protocol)) { rc->ir_work = MULTI_IR_ID; duration = val*10*1000; @@ -508,6 +645,18 @@ static int ir_get_devtree_pdata(struct platform_device *pdev) } dev_info(chip->dev, "led_blink_frq = %ld\n", chip->r_dev->delay_on); + ret = of_property_read_bool(pdev->dev.of_node, "demod_enable"); + if (ret) + chip->r_dev->demod_enable = 1; + + ret = of_property_read_bool(pdev->dev.of_node, "use_fifo"); + if (ret) + chip->r_dev->use_fifo = 1; + + ret = of_property_read_bool(pdev->dev.of_node, "auto_report"); + if (ret) + chip->r_dev->auto_report = 1; + p = devm_pinctrl_get_select_default(&pdev->dev); if (IS_ERR(p)) { dev_err(chip->dev, "pinctrl error, %ld\n", PTR_ERR(p)); @@ -547,13 +696,52 @@ static int ir_get_devtree_pdata(struct platform_device *pdev) /*create map table */ - ret = get_custom_tables(pdev->dev.of_node, chip); - if (ret < 0) - return -1; + get_custom_tables(pdev->dev.of_node, chip); return 0; } +void demod_init(struct remote_chip *chip) +{ + int val; + unsigned int mask; + + mask = GENMASK(29, 16) | BIT(31); + val = BIT(31) | (0x1FF << 16); + + remote_reg_update_bits(chip, MULTI_IR_ID, REG_DEMOD_CNTL1, mask, val); +} + +void demod_reset(struct remote_chip *chip) +{ + unsigned int mask; + + mask = BIT(30); + remote_reg_update_bits(chip, MULTI_IR_ID, REG_DEMOD_CNTL0, mask, mask); +} + +static void ir_learning_done(unsigned long cookie) +{ + + struct remote_dev *dev = (struct remote_dev *)cookie; + struct remote_chip *chip = (struct remote_chip *) dev->platform_data; + unsigned long flags; + + if (dev->pulses->len < 3) { + dev->pulses->len = 0; + return; + } + + spin_lock_irqsave(&chip->slock, flags); + dev->ir_learning_done = true; + spin_unlock_irqrestore(&chip->slock, flags); + + /*data recive done*/ + remote_reg_update_bits(chip, MULTI_IR_ID, REG_REG1, BIT(15), 0); + schedule_delayed_work(&chip->ir_workqueue, msecs_to_jiffies(100)); + +} + static int ir_hardware_init(struct platform_device *pdev) { int ret; @@ -646,6 +834,7 @@ static int remote_probe(struct platform_device *pdev) chip->r_dev->set_custom_code = set_custom_code; chip->r_dev->is_valid_custom = is_valid_custom; chip->r_dev->is_next_repeat = is_next_repeat; + chip->r_dev->max_learned_pulse = MAX_LEARNED_PULSE; chip->set_register_config = ir_register_default_config; platform_set_drvdata(pdev, chip); @@ -669,6 +858,11 @@ static int remote_probe(struct platform_device *pdev) led_trigger_register_simple("rc_feedback", &dev->led_feedback); + setup_timer(&dev->learning_done, ir_learning_done, (unsigned long)dev); + if (dev->demod_enable) + demod_init(chip); + INIT_DELAYED_WORK(&chip->ir_workqueue, learning_done_workqueue); + INIT_WORK(&chip->fifo_work, get_fifo_data_work); return 0; error_register_remote: @@ -707,6 +901,9 @@ static int remote_resume(struct device *dev) unsigned long flags; unsigned char cnt; + if (is_pm_freeze_mode()) + return 0; + dev_info(dev, "remote resume\n"); /*resume register config*/ spin_lock_irqsave(&chip->slock, flags); @@ -745,6 +942,15 @@ static int remote_suspend(struct device *dev) { struct remote_chip *chip = dev_get_drvdata(dev); + if (chip->r_dev->ir_learning_on) { + cancel_work_sync(&chip->fifo_work); + del_timer_sync(&chip->r_dev->learning_done); + cancel_delayed_work_sync(&chip->ir_workqueue); + } + + if (is_pm_freeze_mode()) + return 0; + dev_info(dev, "remote suspend\n"); disable_irq(chip->irqno); return 0; diff --git a/drivers/amlogic/input/remote/remote_meson.h b/drivers/amlogic/input/remote/remote_meson.h index 282664193e25..79dcb5e1c50e 100644 --- a/drivers/amlogic/input/remote/remote_meson.h +++ b/drivers/amlogic/input/remote/remote_meson.h @@ -25,8 +25,13 @@ #define IR_DATA_IS_VALID(data) (data & 0x8) #define IR_CONTROLLER_BUSY(x) ((x >> 7) & 0x1) - #define CURSOR_MOVE_ACCELERATE {0, 2, 2, 4, 4, 6, 8, 10, 12, 14, 16, 18} +/*bit 31: enable fifo mode + * bit 21-23: time out/level trigger interrupt + * bit 13-20: trigger interrupt when receive specified numbers of pulse + * bit 0-12: trigger interrupt when time out + */ +#define FIFO_REG_VAL ((1 << 31) | (7 << 21) | (80 << 13) | (5000 << 0)) enum IR_CONTR_NUMBER { MULTI_IR_ID = 0, @@ -104,6 +109,8 @@ struct remote_chip { struct remote_range reg_duration; char *dev_name; int protocol; + struct delayed_work ir_workqueue; + struct work_struct fifo_work; dev_t chr_devno; struct class *chr_class; @@ -167,23 +174,36 @@ enum { }; enum remote_reg { - REG_LDR_ACTIVE = 0x00<<2, - REG_LDR_IDLE = 0x01<<2, - REG_LDR_REPEAT = 0x02<<2, - REG_BIT_0 = 0x03<<2, - REG_REG0 = 0x04<<2, - REG_FRAME = 0x05<<2, - REG_STATUS = 0x06<<2, - REG_REG1 = 0x07<<2, - REG_REG2 = 0x08<<2, - REG_DURATN2 = 0x09<<2, - REG_DURATN3 = 0x0a<<2, - REG_FRAME1 = 0x0b<<2, - REG_STATUS1 = 0x0c<<2, - REG_STATUS2 = 0x0d<<2, - REG_REG3 = 0x0e<<2, - REG_FRAME_RSV0 = 0x0f<<2, - REG_FRAME_RSV1 = 0x10<<2 + REG_LDR_ACTIVE = 0x00 << 2, + REG_LDR_IDLE = 0x01 << 2, + REG_LDR_REPEAT = 0x02 << 2, + REG_BIT_0 = 0x03 << 2, + REG_REG0 = 0x04 << 2, + REG_FRAME = 0x05 << 2, + REG_STATUS = 0x06 << 2, + REG_REG1 = 0x07 << 2, + REG_REG2 = 0x08 << 2, + REG_DURATN2 = 0x09 << 2, + REG_DURATN3 = 0x0a << 2, + REG_FRAME1 = 0x0b << 2, + REG_STATUS1 = 0x0c << 2, + REG_STATUS2 = 0x0d << 2, + REG_REG3 = 0x0e << 2, + REG_FRAME_RSV0 = 0x0f << 2, + REG_FRAME_RSV1 = 0x10 << 2, + REG_IRQ_CTL = 0x12 << 2, + REG_FIFO = 0x13 << 2, + REG_WITH = 0x14 << 2, + REG_REPEAT_DET = 0x15 << 2, + REG_DEMOD_CNTL0 = 0x20 << 2, + REG_DEMOD_CNTL1 = 0x21 << 2, + REG_DEMOD_IIR_THD = 0x22 << 2, + REG_DEMOD_THD0 = 0x23 << 2, + REG_DEMOD_THD1 = 0x24 << 2, + REG_DEMOD_SUM_CNT0 = 0x25 << 2, + REG_DEMOD_SUM_CNT1 = 0x26 << 2, + REG_DEMOD_CNT0 = 0x27 << 2, + REG_DEMOD_CNT1 = 0x28 << 2 }; int ir_register_default_config(struct remote_chip *chip, int type); @@ -195,11 +215,18 @@ int remote_reg_read(struct remote_chip *chip, unsigned char id, unsigned int reg, unsigned int *val); int remote_reg_write(struct remote_chip *chip, unsigned char id, unsigned int reg, unsigned int val); +int remote_reg_update_bits(struct remote_chip *chip, unsigned char id, + unsigned int reg, unsigned int mask, unsigned int val); int ir_scancode_sort(struct ir_map_tab *ir_map); struct ir_map_tab_list *seek_map_tab(struct remote_chip *chip, int custom_code); +const struct aml_remote_reg_proto **ir_get_proto_reg(void); void ir_tab_free(struct ir_map_tab_list *ir_map_list); #if defined(CONFIG_IR_HK_LIRC_HELPER) extern void remote_wakeup_decode_type(int dec_type); #endif +int remote_pulses_malloc(struct remote_chip *chip); +void remote_pulses_free(struct remote_chip *chip); +void demod_reset(struct remote_chip *chip); +void demod_init(struct remote_chip *chip); #endif diff --git a/drivers/amlogic/input/remote/remote_regmap.c b/drivers/amlogic/input/remote/remote_regmap.c index 46715687a7e4..f1b506c626bf 100644 --- a/drivers/amlogic/input/remote/remote_regmap.c +++ b/drivers/amlogic/input/remote/remote_regmap.c @@ -88,7 +88,7 @@ static struct remote_reg_map regs_default_nec_sw[] = { { REG_LDR_IDLE, 0}, { REG_LDR_REPEAT, 0}, { REG_BIT_0, 0}, - { REG_REG0, ((3 << 28) | (0xFA0 << 12) | (9))}, + { REG_REG0, ((7 << 28) | (0xFA0 << 12) | (9))}, { REG_STATUS, 0}, { REG_REG1, 0x8574}, { REG_REG2, 0x02}, @@ -108,9 +108,9 @@ static struct remote_reg_map regs_default_rc5[] = { /*bit[0-3]: RC5; bit[8]: MSB first mode; bit[11]: compare frame method*/ { REG_REG2, ((1 << 13) | (1 << 11) | (1 << 8) | 0x7)}, /*Half bit for RC5 format: 888.89us*/ - { REG_DURATN2, ((49 << 16) | (40 << 0))}, + { REG_DURATN2, ((53 << 16) | (38 << 0))}, /*RC5 typically 1777.78us for whole bit*/ - { REG_DURATN3, ((94 << 16) | (83 << 0))}, + { REG_DURATN3, ((99 << 16) | (81 << 0))}, { REG_REG3, 0} }; @@ -134,6 +134,53 @@ static struct remote_reg_map regs_default_rc6[] = { {REG_DURATN3, ((51 << 16) | (38 << 0))}, }; +static struct remote_reg_map regs_default_toshiba[] = { + { REG_LDR_ACTIVE, (280 << 16) | (180 << 0)}, + { REG_LDR_IDLE, (280 << 16) | (180 << 0)}, + { REG_LDR_REPEAT, (150 << 16) | (60 << 0)}, + { REG_BIT_0, (72 << 16) | (40 << 0)}, + { REG_REG0, (7 << 28) | (0xFA0 << 12) | 0x13}, + { REG_STATUS, (134 << 20) | (90 << 10)}, + { REG_REG1, 0x9f00}, + { REG_REG2, (0x05) | (1 << 24) | (23 << 11)}, + { REG_DURATN2, 0x00}, + { REG_DURATN3, 0x00}, + { REG_REPEAT_DET, (1 << 31) | (0xFA0 << 16) | (10 << 0)}, + { REG_REG3, 0x2AF8}, +}; + +static int ir_toshiba_get_scancode(struct remote_chip *chip) +{ + int code = 0; + int decode_status = 0; + int status = 0; + + remote_reg_read(chip, MULTI_IR_ID, REG_STATUS, &decode_status); + if (decode_status & 0x01) + status |= REMOTE_REPEAT; + chip->decode_status = status; /*set decode status*/ + remote_reg_read(chip, MULTI_IR_ID, REG_FRAME, &code); + remote_dbg(chip->dev, "framecode=0x%x\n", code); + chip->r_dev->cur_hardcode = code; + code = (code >> 16) & 0xff; + return code; + +} + +static int ir_toshiba_get_decode_status(struct remote_chip *chip) +{ + int status = chip->decode_status; + return status; +} + +static u32 ir_toshiba_get_custom_code(struct remote_chip *chip) +{ + u32 custom_code; + + custom_code = (chip->r_dev->cur_hardcode) & 0xffff; + return custom_code; +} + void set_hardcode(struct remote_chip *chip, int code) { remote_dbg(chip->dev, "framecode=0x%x\n", code); @@ -499,6 +546,15 @@ static struct aml_remote_reg_proto reg_rc6 = { .get_custom_code = ir_rc6_get_custom_code, }; +static struct aml_remote_reg_proto reg_toshiba = { + .protocol = REMOTE_TYPE_TOSHIBA, + .name = "TOSHIBA", + .reg_map = regs_default_toshiba, + .reg_map_size = ARRAY_SIZE(regs_default_toshiba), + .get_scancode = ir_toshiba_get_scancode, + .get_decode_status = ir_toshiba_get_decode_status, + .get_custom_code = ir_toshiba_get_custom_code, +}; const struct aml_remote_reg_proto *remote_reg_proto[] = { ®_nec, @@ -509,9 +565,15 @@ const struct aml_remote_reg_proto *remote_reg_proto[] = { ®_rc5, ®_rc6, ®_legacy_nec, + ®_toshiba, NULL }; +const struct aml_remote_reg_proto **ir_get_proto_reg(void) +{ + return remote_reg_proto; +} + static int ir_contr_init(struct remote_chip *chip, int type, unsigned char id) { const struct aml_remote_reg_proto **reg_proto = remote_reg_proto; @@ -566,6 +628,11 @@ static int ir_contr_init(struct remote_chip *chip, int type, unsigned char id) chip->ir_contr[id].get_custom_code = (*reg_proto)->get_custom_code; chip->ir_contr[id].set_custom_code = (*reg_proto)->set_custom_code; + if (chip->r_dev->ir_learning_on && chip->r_dev->use_fifo) + remote_reg_write(chip, id, REG_FIFO, FIFO_REG_VAL); + else + remote_reg_write(chip, id, REG_FIFO, 0); + return 0; } diff --git a/drivers/amlogic/input/remote/sysfs.c b/drivers/amlogic/input/remote/sysfs.c index b7df3e5a276f..5bd084cd9a04 100644 --- a/drivers/amlogic/input/remote/sysfs.c +++ b/drivers/amlogic/input/remote/sysfs.c @@ -43,16 +43,29 @@ static ssize_t protocol_show(struct device *dev, struct device_attribute *attr, char *buf) { struct remote_chip *chip = dev_get_drvdata(dev); + const struct aml_remote_reg_proto **supported_proto = + ir_get_proto_reg(); + int len; if (ENABLE_LEGACY_IR(chip->protocol)) - return sprintf(buf, "protocol=%s&%s (0x%x)\n", + len = sprintf(buf, "current protocol = %s&%s (0x%x)\n", chip->ir_contr[LEGACY_IR_ID].proto_name, chip->ir_contr[MULTI_IR_ID].proto_name, chip->protocol); + else + len = sprintf(buf, "currnet protocol = %s (0x%x)\n", + chip->ir_contr[MULTI_IR_ID].proto_name, + chip->protocol); - return sprintf(buf, "protocol=%s (0x%x)\n", - chip->ir_contr[MULTI_IR_ID].proto_name, - chip->protocol); + len += sprintf(buf + len, "supported protocol:\n"); + + for ( ; (*supported_proto) != NULL ; ) { + len += sprintf(buf + len, "%s (0x%x)\n", + ((*supported_proto)->name), ((*supported_proto)->protocol)); + supported_proto++; + } + + return len; } static ssize_t protocol_store(struct device *dev, @@ -308,6 +321,169 @@ static ssize_t led_frq_store(struct device *dev, return count; } +static ssize_t ir_learning_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + + struct remote_chip *chip = dev_get_drvdata(dev); + struct remote_dev *r_dev = chip->r_dev; + + return sprintf(buf, "%d\n", r_dev->ir_learning_on); +} + +static ssize_t ir_learning_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + int ret = 0; + int val = 0; + + struct remote_chip *chip = dev_get_drvdata(dev); + struct remote_dev *r_dev = chip->r_dev; + + ret = kstrtoint(buf, 0, &val); + if (ret != 0) + return -EINVAL; + if (r_dev->ir_learning_on == val) + return count; + + disable_irq(chip->irqno); + mutex_lock(&chip->file_lock); + r_dev->ir_learning_on = !!val; + if (!!val) { + if (r_dev->demod_enable) + demod_reset(chip); + + if (remote_pulses_malloc(chip) < 0) { + mutex_unlock(&chip->file_lock); + enable_irq(chip->irqno); + return -ENOMEM; + } + chip->set_register_config(chip, REMOTE_TYPE_RAW_NEC); + r_dev->protocol = chip->protocol;/*backup protocol*/ + chip->protocol = REMOTE_TYPE_RAW_NEC; + } else { + chip->protocol = r_dev->protocol; + chip->set_register_config(chip, chip->protocol); + remote_pulses_free(chip); + chip->r_dev->ir_learning_done = false; + } + mutex_unlock(&chip->file_lock); + enable_irq(chip->irqno); + return count; +} + +static ssize_t learned_pulse_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int len = 0; + int i = 0; + + struct remote_chip *chip = dev_get_drvdata(dev); + struct remote_dev *r_dev = chip->r_dev; + + if (!r_dev->pulses) + return len; + + disable_irq(chip->irqno); + mutex_lock(&chip->file_lock); + for (i = 0; i < r_dev->pulses->len; i++) + len += sprintf(buf + len, "%lds", + r_dev->pulses->pulse[i] & GENMASK(30, 0)); + + len += sprintf(buf + len, "\n"); + + remote_reg_update_bits(chip, MULTI_IR_ID, REG_REG1, BIT(15), BIT(15)); + + r_dev->ir_learning_done = false; + + mutex_unlock(&chip->file_lock); + enable_irq(chip->irqno); + + return len; +} + +static ssize_t learned_pulse_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct remote_chip *chip = dev_get_drvdata(dev); + struct remote_dev *r_dev = chip->r_dev; + + if (!r_dev->pulses) + return count; + + disable_irq(chip->irqno); + mutex_lock(&chip->file_lock); + if (buf[0] == 'c') { + memset(r_dev->pulses, 0, sizeof(struct pulse_group) + + r_dev->max_learned_pulse * sizeof(u32)); + remote_reg_update_bits(chip, MULTI_IR_ID, REG_REG1, BIT(15), + BIT(15)); + + r_dev->ir_learning_done = false; + } + mutex_unlock(&chip->file_lock); + enable_irq(chip->irqno); + return count; +} + +static ssize_t sum_cnt0_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int val = 0; + struct remote_chip *chip = dev_get_drvdata(dev); + + remote_reg_read(chip, MULTI_IR_ID, REG_DEMOD_SUM_CNT0, &val); + + return sprintf(buf, "%d\n", val); +} + +static ssize_t sum_cnt1_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + + int val = 0; + struct remote_chip *chip = dev_get_drvdata(dev); + + remote_reg_read(chip, MULTI_IR_ID, REG_DEMOD_SUM_CNT1, &val); + + return sprintf(buf, "%d\n", val); + +} + +static ssize_t use_fifo_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct remote_chip *chip = dev_get_drvdata(dev); + + return sprintf(buf, "%d\n", chip->r_dev->use_fifo); +} + +static ssize_t use_fifo_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + int val = 0; + int len = 0; + struct remote_chip *chip = dev_get_drvdata(dev); + + len = kstrtoint(buf, 0, &val); + + if (len != 0) { + dev_err(chip->dev, "input parameter error\n"); + return -EINVAL; + } + + chip->r_dev->use_fifo = val; + + return count; +} + +DEVICE_ATTR_RW(use_fifo); +DEVICE_ATTR_RO(sum_cnt0); +DEVICE_ATTR_RO(sum_cnt1); +DEVICE_ATTR_RW(learned_pulse); +DEVICE_ATTR_RW(ir_learning); DEVICE_ATTR_RW(led_frq); DEVICE_ATTR_RW(led_blink); DEVICE_ATTR_RW(repeat_enable); @@ -326,6 +502,11 @@ static struct attribute *remote_attrs[] = { &dev_attr_debug_log.attr, &dev_attr_led_blink.attr, &dev_attr_led_frq.attr, + &dev_attr_ir_learning.attr, + &dev_attr_learned_pulse.attr, + &dev_attr_sum_cnt0.attr, + &dev_attr_sum_cnt1.attr, + &dev_attr_use_fifo.attr, NULL, }; diff --git a/drivers/amlogic/input/touchscreen/focaltech_touch/focaltech_flash.h b/drivers/amlogic/input/touchscreen/focaltech_touch/focaltech_flash.h index 53eed3e731b1..95a8a5422d9e 100644 --- a/drivers/amlogic/input/touchscreen/focaltech_touch/focaltech_flash.h +++ b/drivers/amlogic/input/touchscreen/focaltech_touch/focaltech_flash.h @@ -1,15 +1,20 @@ -/************************************************************************ -* Copyright (C) 2010-2017, Focaltech Systems (R)All Rights Reserved. -* -* File Name: focaltech_flash.h -* -* Author: fupeipei -* -* Created: 2016-08-07 -* -* Abstract: -* -************************************************************************/ +/* + * drivers/amlogic/input/touchscreen/focaltech_touch/focaltech_flash.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 __LINUX_FOCALTECH_FLASH_H__ #define __LINUX_FOCALTECH_FLASH_H__ diff --git a/drivers/amlogic/input/touchscreen/focaltech_touch/focaltech_flash/focaltech_upgrade_common.h b/drivers/amlogic/input/touchscreen/focaltech_touch/focaltech_flash/focaltech_upgrade_common.h index 8b522b250b2e..a94ef90db532 100755 --- a/drivers/amlogic/input/touchscreen/focaltech_touch/focaltech_flash/focaltech_upgrade_common.h +++ b/drivers/amlogic/input/touchscreen/focaltech_touch/focaltech_flash/focaltech_upgrade_common.h @@ -1,15 +1,20 @@ -/************************************************************************ -* Copyright (C) 2010-2017, Focaltech Systems (R)All Rights Reserved. -* -* File Name: focaltech_upgrade_common.h -* -* Author: fupeipei -* -* Created: 2016-08-16 -* -* Abstract: -* -************************************************************************/ +/* + * focaltech_upgrade_common.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 __LINUX_FOCALTECH_UPGRADE_COMMON_H__ #define __LINUX_FOCALTECH_UPGRADE_COMMON_H__ diff --git a/drivers/amlogic/input/touchscreen/goodix_gt9xx/gt9xx_firmware.h b/drivers/amlogic/input/touchscreen/goodix_gt9xx/gt9xx_firmware.h index e36d0afa6732..f2ce16eb6d57 100644 --- a/drivers/amlogic/input/touchscreen/goodix_gt9xx/gt9xx_firmware.h +++ b/drivers/amlogic/input/touchscreen/goodix_gt9xx/gt9xx_firmware.h @@ -1,14 +1,20 @@ -/* Copyright Statement: -*This firmware are protected under relevant copyright laws,this information contained -*herein is confidential and proprietary to Goodix. -* -* Copyright (C) 2010 - 2016 Goodix. Ltd. -* -*WARNING:The GTP_COMPATIBLE_MODE part of this file was generated by the specialized tools, -*please do not modify it manually! -* -*/ - +/* + * drivers/amlogic/input/touchscreen/goodix_gt9xx/gt9xx_firmware.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 _GT9XX_FIRMWARE_H_ #define _GT9XX_FIRMWARE_H_ diff --git a/drivers/amlogic/iomap/iomap.c b/drivers/amlogic/iomap/iomap.c index b5645c2f6df2..2998450a9b1b 100644 --- a/drivers/amlogic/iomap/iomap.c +++ b/drivers/amlogic/iomap/iomap.c @@ -39,7 +39,7 @@ static const struct of_device_id iomap_dt_match[] = { static void __iomem *meson_reg_map[IO_BUS_MAX] = { NULL }; -int aml_reg_read(u32 bus_type, unsigned int reg, unsigned int *val) +inline int aml_reg_read(u32 bus_type, unsigned int reg, unsigned int *val) { if (bus_type < IO_BUS_MAX && (meson_reg_map[bus_type] != NULL)) { *val = readl((meson_reg_map[bus_type]+reg)); @@ -49,7 +49,7 @@ int aml_reg_read(u32 bus_type, unsigned int reg, unsigned int *val) } EXPORT_SYMBOL(aml_reg_read); -int aml_reg_write(u32 bus_type, unsigned int reg, unsigned int val) +inline int aml_reg_write(u32 bus_type, unsigned int reg, unsigned int val) { if (bus_type < IO_BUS_MAX && (meson_reg_map[bus_type] != NULL)) { writel(val, (meson_reg_map[bus_type]+reg)); diff --git a/drivers/amlogic/irblaster/Kconfig b/drivers/amlogic/irblaster/Kconfig index 6c35ae80350a..6e35faa39216 100644 --- a/drivers/amlogic/irblaster/Kconfig +++ b/drivers/amlogic/irblaster/Kconfig @@ -1,11 +1,34 @@ # -# Input core configuration +# Amlogic IRBLASTER # -config AMLOGIC_IRBLASTER - bool "Amlogic irblaster device surport" + +menuconfig AMLOGIC_IRBLASTER_CORE + tristate "Amlogic IRBLASTER Support" default n help - Say Y here if you want to use the amlogic irblaster. + This is the core code of amlogic irblaster. Say Y you + can use the core api to implement the irblaster controller driver + and use the api in the core to control the irblaster. + This option alone add core code. +if AMLOGIC_IRBLASTER_CORE +config AMLOGIC_IRBLASTER_MESON + tristate "Amlogic Meson SoC irblaster driver" + default n + help + This enable irblaster support for soc mesom (irblaster communication + controller) available in Amlogic Meson SoCs. + If you want to use meson irblaster interface, + say Y here.If you are not sure, say N. +config AMLOGIC_IRBLASTER_PROTOCOL + tristate "Add Amlogic Meson irblaster encode" + default n + help + This enables encode mode support for the irblaster (communication + controller) available in Amlogic Meson SoCs. + If you want to use meson irblaster interface, + say Y here.If you are not sure, say N. + +endif diff --git a/drivers/amlogic/irblaster/Makefile b/drivers/amlogic/irblaster/Makefile index c406f7a50d1b..22c05b0257b6 100644 --- a/drivers/amlogic/irblaster/Makefile +++ b/drivers/amlogic/irblaster/Makefile @@ -1,6 +1,4 @@ -# -# Makefile for the remote control drivers -# - -# Each configuration option enables a list of files. -obj-$(CONFIG_AMLOGIC_IRBLASTER) += irblaster.o meson-irblaster.o +obj-$(CONFIG_AMLOGIC_IRBLASTER_CORE) += core.o sysfs.o +obj-$(CONFIG_AMLOGIC_IRBLASTER_MESON) += irblaster-meson.o aml-irblaster.o +obj-$(CONFIG_AMLOGIC_IRBLASTER_PROTOCOL) += encoder.o irblaster-nec-encoder.o \ + irblaster-rca-encoder.o diff --git a/drivers/amlogic/irblaster/aml-irblaster.c b/drivers/amlogic/irblaster/aml-irblaster.c new file mode 100644 index 000000000000..79c7d27b2fb5 --- /dev/null +++ b/drivers/amlogic/irblaster/aml-irblaster.c @@ -0,0 +1,430 @@ +/* + * drivers/amlogic/irblaster/aml-irblaster.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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define AO_IR_BLASTER_ADDR0 (0x0) +#define AO_IR_BLASTER_ADDR1 (0x4) +#define AO_IR_BLASTER_ADDR2 (0x8) +#define AO_IR_BLASTER_ADDR3 (0xc) + +#define DEFAULT_CARRIER_FREQ (38000) +#define DEFAULT_DUTY_CYCLE (50) +#define BLASTER_DEVICE_COUNT (32) + +#ifdef CONFIG_AMLOGIC_IRBLASTER_PROTOCOL +#define DEFAULT_IRBLASTER_PROTOCOL IRBLASTER_PROTOCOL_NEC +#endif + +#define IR_TX_EVENT_SIZE 4 +#define IR_TX_BUFFER_SIZE 1024 + +struct tx_event { + struct list_head list; + unsigned int size; + unsigned int buffer[IR_TX_BUFFER_SIZE]; +}; + +DECLARE_KFIFO(fifo, struct tx_event *, IR_TX_EVENT_SIZE); + +struct aml_irblaster_dev { + struct irblaster_chip chip; + struct device *dev; + struct task_struct *thread; + struct completion blaster_completion; + struct mutex lock; + spinlock_t irblaster_lock; /* use to send data */ + void __iomem *reg_base; + void __iomem *reset_base; + unsigned int winnum; + unsigned int winarray[MAX_PLUSE]; +}; + +static struct aml_irblaster_dev * +to_aml_irblaster(struct irblaster_chip *chip) +{ + return container_of(chip, struct aml_irblaster_dev, chip); +} + +static struct tx_event *event_get(struct aml_irblaster_dev *cw) +{ + struct tx_event *ev = NULL; + + ev = devm_kzalloc(cw->dev, + sizeof(struct tx_event), GFP_KERNEL); + return ev; +} + +static void event_put(struct aml_irblaster_dev *cw, struct tx_event *ev) +{ + devm_kfree(cw->dev, ev); +} + +static int send_bit(struct aml_irblaster_dev *cw, unsigned int hightime, + unsigned int lowtime, unsigned int cycle) +{ + unsigned int count_delay; + uint32_t val; + int n = 0; + int tb[3] = { + 1, 10, 100 + }; + /* + * MODULATOR_TB: + * 00: system clock clk + * 01: mpeg_xtal3_tick + * 10: mpeg_1uS_tick + * 11: mpeg_10uS_tick + * lowtime<1024,n=0,timebase=1us + * 1024<=lowtime<10240,n=1,timebase=10us + * AO_IR_BLASTER_ADDR2 + * bit12: output level(or modulation enable/disable:1=enable) + * bit[11:10]: Timebase : + * 00=1us + * 01=10us + * 10=100us + * 11=Modulator clock + * bit[9:0]: Count of timebase units to delay + */ + count_delay = (((hightime + cycle/2) / cycle) - 1) & 0x3ff; + val = (0x10000 | (1 << 12)) | (3 << 10) | (count_delay << 0); + writel_relaxed(val, cw->reg_base + AO_IR_BLASTER_ADDR2); + + /* + * lowtime<1024,n=0,timebase=1us + * 1024<=lowtime<10240,n=1,timebase=10us + * 10240<=lowtime,n=2,timebase=100us + */ + n = lowtime >> 10; + if (n > 0 && n < 10) + n = 1; + else if (n >= 10) + n = 2; + lowtime = (lowtime + (tb[n] >> 1))/tb[n]; + count_delay = (lowtime-1) & 0x3ff; + val = (0x10000 | (0 << 12)) | + (n << 10) | (count_delay << 0); + writel_relaxed(val, cw->reg_base + AO_IR_BLASTER_ADDR2); + + return 0; +} + +static void send_all_frame(struct aml_irblaster_dev *cw) +{ + int i, k; + int exp = 0x00; + unsigned int *pData; + unsigned int consumerir_cycle; + unsigned int high_ct, low_ct; + unsigned long cnt, flags; + + consumerir_cycle = 1000 / (cw->chip.state.freq / 1000); + + /*reset*/ + writel_relaxed(readl_relaxed(cw->reset_base) | + (1 << 23), cw->reset_base); + udelay(2); + writel_relaxed(readl_relaxed(cw->reset_base) & + ~(1 << 23), cw->reset_base); + + /* + * 1.disable ir blaster + * 2.set the modulator_tb = 2'10; mpeg_1uS_tick 1us + */ + writel_relaxed((1 << 2) | (2 << 12) | (1<<2), + cw->reg_base + AO_IR_BLASTER_ADDR0); + + /* + * 1. set mod_high_count = 13 + * 2. set mod_low_count = 13 + * 3. 60khz 8, 38k-13us, 12 + */ + high_ct = consumerir_cycle * cw->chip.state.duty/100; + low_ct = consumerir_cycle - high_ct; + writel_relaxed(((high_ct - 1) << 16) | ((low_ct - 1) << 0), + cw->reg_base + AO_IR_BLASTER_ADDR1); + + /* Setting this bit to 1 initializes the output to be high.*/ + writel_relaxed(readl_relaxed(cw->reg_base + AO_IR_BLASTER_ADDR0) & + ~(1 << 2), cw->reg_base + AO_IR_BLASTER_ADDR0); + + /*enable irblaster*/ + writel_relaxed(readl_relaxed(cw->reg_base + AO_IR_BLASTER_ADDR0) | + (1 << 0), cw->reg_base + AO_IR_BLASTER_ADDR0); + + k = cw->winnum; +#define SEND_BIT_NUM 64 + exp = cw->winnum / SEND_BIT_NUM; + pData = cw->winarray; + + while (exp) { + spin_lock_irqsave(&cw->irblaster_lock, flags); + for (i = 0; i < SEND_BIT_NUM/2; i++) { + send_bit(cw, *pData, *(pData+1), consumerir_cycle); + pData += 2; + } + + spin_unlock_irqrestore(&cw->irblaster_lock, flags); + cnt = jiffies + msecs_to_jiffies(1000); + while (!(readl_relaxed(cw->reg_base + AO_IR_BLASTER_ADDR0) & + (1<<24)) && time_is_after_eq_jiffies(cnt)) + ; + + cnt = jiffies + msecs_to_jiffies(1000); + while ((readl_relaxed(cw->reg_base + AO_IR_BLASTER_ADDR0) & + (1<<26)) && time_is_after_eq_jiffies(cnt)) + ; + + /*reset*/ + writel_relaxed(readl_relaxed(cw->reset_base) | (1 << 23), + cw->reset_base); + udelay(2); + writel_relaxed(readl_relaxed(cw->reset_base) & ~(1 << 23), + cw->reset_base); + exp--; + } + + exp = (cw->winnum % SEND_BIT_NUM) & (~(1)); + spin_lock_irqsave(&cw->irblaster_lock, flags); + for (i = 0; i < exp; ) { + send_bit(cw, *pData, *(pData+1), consumerir_cycle); + pData += 2; + i += 2; + } + + spin_unlock_irqrestore(&cw->irblaster_lock, flags); + cnt = jiffies + msecs_to_jiffies(1000); + while (!(readl_relaxed(cw->reg_base + AO_IR_BLASTER_ADDR0) & + (1<<24)) && time_is_after_eq_jiffies(cnt)) + ; + + cnt = jiffies + msecs_to_jiffies(1000); + while ((readl_relaxed(cw->reg_base + AO_IR_BLASTER_ADDR0) & + (1<<26)) && time_is_after_eq_jiffies(cnt)) + ; + + complete(&cw->blaster_completion); +} + +int aml_irblaster_send(struct irblaster_chip *chip, + unsigned int *data, + unsigned int len) +{ + int i, ret; + struct tx_event *ev; + struct aml_irblaster_dev *irblaster_dev = to_aml_irblaster(chip); + + init_completion(&irblaster_dev->blaster_completion); + ev = event_get(irblaster_dev); + ev->size = len; + for (i = 0; i < ev->size; i++) + ev->buffer[i] = data[i]; + + /* to send cycle */ + kfifo_put(&fifo, (const struct tx_event *)ev); + /* to wake up ir_tx_thread */ + wake_up_process(irblaster_dev->thread); + /* return after processing */ + ret = wait_for_completion_interruptible_timeout + (&irblaster_dev->blaster_completion, + msecs_to_jiffies(chip->sum_time / 1000)); + if (!ret) { + pr_err("failed to send all data ret = %d\n", ret); + return -ETIMEDOUT; + } + + return 0; +} + +static int ir_tx_thread(void *data) +{ + int retval, i; + unsigned long cnt; + struct aml_irblaster_dev *irblaster_dev + = (struct aml_irblaster_dev *)data; + struct tx_event *ev = NULL; + + while (!kthread_should_stop()) { + retval = kfifo_len(&fifo); + if (retval <= 0) { + set_current_state(TASK_INTERRUPTIBLE); + if (kthread_should_stop()) + set_current_state(TASK_RUNNING); + schedule(); + continue; + } + + retval = kfifo_get(&fifo, &ev); + if (retval) { + irblaster_dev->winnum = ev->size; + for (i = 0; i < irblaster_dev->winnum; i++) + irblaster_dev->winarray[i] = ev->buffer[i]; + + send_all_frame(irblaster_dev); + event_put(irblaster_dev, ev); + cnt = jiffies + msecs_to_jiffies(1000); + while (!(readl_relaxed(irblaster_dev->reg_base + + AO_IR_BLASTER_ADDR0) & (1<<24)) && + time_is_after_eq_jiffies(cnt)) + ; + + cnt = jiffies + msecs_to_jiffies(1000); + while ((readl_relaxed(irblaster_dev->reg_base + + AO_IR_BLASTER_ADDR0) & (1<<26)) && + time_is_after_eq_jiffies(cnt)) + ; + + } else + pr_err("kfifo_get fail\n"); + } + + return 0; +} + +static struct irblaster_ops aml_irblaster_ops = { + .send = aml_irblaster_send, +}; + +static int aml_irblaster_probe(struct platform_device *pdev) +{ + struct aml_irblaster_dev *irblaster_dev = NULL; + struct resource *reg_mem = NULL; + struct resource *reset_mem = NULL; + void __iomem *reg_base = NULL; + void __iomem *reset_base = NULL; + int err; + + if (!pdev->dev.of_node) { + dev_err(&pdev->dev, "pdev->dev.of_node == NULL!\n"); + return -EINVAL; + } + + irblaster_dev = devm_kzalloc(&pdev->dev, + sizeof(struct aml_irblaster_dev), + GFP_KERNEL); + if (!irblaster_dev) + return -ENOMEM; + + platform_set_drvdata(pdev, irblaster_dev); + irblaster_dev->dev = &pdev->dev; + + reg_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!IS_ERR_OR_NULL(reg_mem)) { + reg_base = devm_ioremap_resource(&pdev->dev, reg_mem); + if (IS_ERR(reg_base)) { + dev_err(&pdev->dev, "reg0: cannot obtain I/O memory region.\n"); + return PTR_ERR(reg_base); + } + } else { + dev_err(&pdev->dev, "get IORESOURCE_MEM error.\n"); + return PTR_ERR(reg_base); + } + + reset_mem = platform_get_resource(pdev, IORESOURCE_MEM, 1); + if (!IS_ERR_OR_NULL(reset_mem)) { + reset_base = devm_ioremap_resource(&pdev->dev, + reset_mem); + if (IS_ERR(reset_base)) { + dev_err(&pdev->dev, "reg1: cannot obtain I/O memory region.\n"); + return PTR_ERR(reset_base); + } + } else { + dev_err(&pdev->dev, "get IORESOURCE_MEM error.\n"); + return PTR_ERR(reset_mem); + } + + spin_lock_init(&irblaster_dev->irblaster_lock); + init_completion(&irblaster_dev->blaster_completion); + irblaster_dev->reg_base = reg_base; + irblaster_dev->reset_base = reset_base; + irblaster_dev->chip.dev = &pdev->dev; + irblaster_dev->chip.ops = &aml_irblaster_ops; + irblaster_dev->chip.of_irblaster_n_cells = 2; + irblaster_dev->chip.state.freq = DEFAULT_CARRIER_FREQ; + irblaster_dev->chip.state.duty = DEFAULT_DUTY_CYCLE; +#ifdef CONFIG_AMLOGIC_IRBLASTER_PROTOCOL + irblaster_dev->chip.state.protocol = DEFAULT_IRBLASTER_PROTOCOL; + irblaster_set_protocol(&irblaster_dev->chip, + DEFAULT_IRBLASTER_PROTOCOL); +#endif + err = irblasterchip_add(&irblaster_dev->chip); + if (err < 0) { + dev_err(&pdev->dev, "failed to register irblaster chip: %d\n", + err); + return err; + } + + irblaster_dev->thread = kthread_run(ir_tx_thread, irblaster_dev, + "ir-blaster-thread"); + + return 0; +} + +static int aml_irblaster_remove(struct platform_device *pdev) +{ + struct aml_irblaster_dev *irblaster_dev = platform_get_drvdata(pdev); + + irblasterchip_remove(&irblaster_dev->chip); + + return 0; +} + +static const struct of_device_id irblaster_dt_match[] = { + { + .compatible = "amlogic, aml_irblaster", + }, + {}, +}; + +static struct platform_driver aml_irblaster_driver = { + .probe = aml_irblaster_probe, + .remove = aml_irblaster_remove, + .suspend = NULL, + .resume = NULL, + .driver = { + .name = "aml-irblaster", + .owner = THIS_MODULE, + .of_match_table = irblaster_dt_match, + }, +}; + +static int __init aml_irblaster_init(void) +{ + return platform_driver_register(&aml_irblaster_driver); +} + +static void __exit aml_irblaster_exit(void) +{ + platform_driver_unregister(&aml_irblaster_driver); +} + +fs_initcall_sync(aml_irblaster_init); +module_exit(aml_irblaster_exit); +MODULE_AUTHOR("Amlogic, Inc."); +MODULE_DESCRIPTION("Amlogic ir blaster driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/amlogic/irblaster/core.c b/drivers/amlogic/irblaster/core.c new file mode 100644 index 000000000000..dfc5b7897ff5 --- /dev/null +++ b/drivers/amlogic/irblaster/core.c @@ -0,0 +1,366 @@ +/* + * drivers/amlogic/irblaster/core.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 +#include +#include +#include +#include +#include +#include + +void irblaster_chip_data_clear(struct irblaster_chip *chip) +{ + chip->buffer = NULL; + chip->buffer_len = 0; + chip->sum_time = 0; +} + +/** + * irblaster_send() - send raw level data + * @chip: irblaster controller + * @data: raw level data (us) + * @len: raw len + */ +int irblaster_send(struct irblaster_chip *chip, unsigned int *data, + unsigned int len) +{ + unsigned int sum_time = 0; + int err, i; + + if (!chip || (len % 2 == 1) || len == 0 || len > MAX_PLUSE) { + pr_err("%s(): parameter error\n", __func__); + return -EINVAL; + } + + for (i = 0; i < len; i++) + sum_time += data[i]; + + chip->buffer = data; + chip->buffer_len = len; + chip->sum_time = sum_time; + + if (chip->ops->send) { + err = chip->ops->send(chip, data, len); + if (err) + return err; + } else { + pr_err("%s(): irblaster func %s not found\n", + __func__, __func__); + return -EINVAL; + } + + irblaster_chip_data_clear(chip); + + return 0; +} + +/** + * irblaster_set_freq() - set irblaster freq + * @chip: irblaster controller + * @freq: irblaster freq (HZ) + */ +int irblaster_set_freq(struct irblaster_chip *chip, unsigned int freq) +{ + int ret; + + if (!chip || freq <= 0) + return -EINVAL; + + if (chip->ops->set_freq) { + ret = chip->ops->set_freq(chip, freq); + if (ret) + return -EINVAL; + } + + chip->state.freq = freq; + + return 0; +} + +/** + * irblaster_get_freq() - get irblaster freq + * @chip: irblaster controller + */ +unsigned int irblaster_get_freq(struct irblaster_chip *chip) +{ + unsigned int freq; + + if (!chip) + return -EINVAL; + + if (chip->ops->get_freq) { + freq = chip->ops->get_freq(chip); + if (freq == 0) + return -EINVAL; + } else { + freq = chip->state.freq; + } + + return freq; +} + +/** + * irblaster_set_duty() - set irblaster duty + * @chip: irblaster controller + * @duty: irblaster duty + */ +int irblaster_set_duty(struct irblaster_chip *chip, unsigned int duty) +{ + int ret; + + if (!chip || duty <= 0 || duty > 100) + return -EINVAL; + + if (chip->ops->set_duty) { + ret = chip->ops->set_duty(chip, duty); + if (ret) + return -EINVAL; + } + + chip->state.duty = duty; + + return 0; +} + +/** + * irblaster_set_duty() - set irblaster duty + * @chip: irblaster controller + * @duty: irblaster duty + */ +unsigned int irblaster_get_duty(struct irblaster_chip *chip) +{ + unsigned int duty; + + if (chip->ops->get_duty) { + duty = chip->ops->get_duty(chip); + if (duty == 0) + return -EINVAL; + } else { + duty = chip->state.duty; + } + + return duty; +} + +/** + * irblasterchip_remove() - remove a irblaster Controller + * @chip: the irblaster chip to remove + * @Returns: 0 on success or a negative error code on failure. + */ +int irblasterchip_remove(struct irblaster_chip *chip) +{ + mutex_lock(&irblaster_lock); + list_del_init(&chip->list); + + if (chip->dev) + of_node_put(chip->dev->of_node); + + irblasterchip_sysfs_unexport(chip); + mutex_unlock(&irblaster_lock); + + return 0; +} +EXPORT_SYMBOL_GPL(irblasterchip_remove); + +static bool irblaster_ops_check(struct irblaster_ops *ops) +{ + /* These one interfaces are the most basic of the irblaster */ + if (ops->send) + return true; + + return false; +} + +/** + * irblasterchip_add() - register a new irblaster Controller + * @chip: the irblaster chip to add + * @Returns: 0 on success or a negative error code on failure. + */ +int irblasterchip_add(struct irblaster_chip *chip) +{ + if (!chip || !chip->dev || !chip->ops) + return -EINVAL; + + if (!irblaster_ops_check(chip->ops)) + return -EINVAL; + + mutex_lock(&irblaster_lock); + atomic_set(&chip->request, IRBLASTER_EXPORTED); + INIT_LIST_HEAD(&chip->list); + list_add(&chip->list, &irblaster_chips); + irblasterchip_sysfs_export(chip); + mutex_unlock(&irblaster_lock); + + return 0; +} +EXPORT_SYMBOL_GPL(irblasterchip_add); + +/** + * irblaster_put() - release a irblaster controller + * @chip: irblaster controller + */ +void irblaster_put(struct irblaster_chip *chip) +{ + if (!chip) + return; + + mutex_lock(&irblaster_lock); + atomic_set(&chip->request, IRBLASTER_EXPORTED); + irblaster_chip_data_clear(chip); + irblasterchip_sysfs_export(chip); + mutex_unlock(&irblaster_lock); +} +EXPORT_SYMBOL_GPL(irblaster_put); + +static struct irblaster_chip *of_node_to_irblasterchip(struct device_node *np) +{ + struct irblaster_chip *chip; + + mutex_lock(&irblaster_lock); + list_for_each_entry(chip, &irblaster_chips, list) + if (chip->dev && chip->dev->of_node == np) { + mutex_unlock(&irblaster_lock); + if (atomic_read(&chip->request) == IRBLASTER_REQUESTED) + return ERR_PTR(-EPROBE_DEFER); + return chip; + } + + mutex_unlock(&irblaster_lock); + return ERR_PTR(-EPROBE_DEFER); +} + +static int irblaster_set_default_state(struct irblaster_chip *pc, + const struct of_phandle_args *args) +{ + int ret; + + if (pc->of_irblaster_n_cells < 2 || + args->args[0] <= 0 || args->args[1] > 100) + return -EINVAL; + + pc->state.freq = args->args[0]; + pc->state.duty = args->args[1]; + + ret = irblaster_set_freq(pc, pc->state.freq); + if (ret) + return -EINVAL; + + ret = irblaster_set_duty(pc, pc->state.duty); + if (ret) + return -EINVAL; + + return 0; +} + +/** + * of_irblaster_get() - request a irblaster via the irblaster framework + * @np: device node to get the irblaster from + * @con_id: consumer name + * + * Returns the irblaster controller parsed from the phandle and index + * specified in the "irblaster-config" property of a device tree node + * or a negative error-code on failure. Values parsed from the device + * tree are stored in the returned irblaster device object. + * + * Returns: A pointer to the requested irblaster controller or an ERR_PTR() + * -encoded error code on failure. + */ +struct irblaster_chip *of_irblaster_get(struct device_node *np, + const char *con_id) +{ + struct of_phandle_args args; + struct irblaster_chip *pc; + int err, index = 0; + + err = of_parse_phandle_with_args(np, "irblaster-config", + "#irblaster-cells", index, + &args); + if (err) { + pr_err("%s(): can't parse \"irblaster-config\" property\n", + __func__); + return ERR_PTR(err); + } + + pc = of_node_to_irblasterchip(args.np); + if (IS_ERR(pc)) { + pr_err("%s(): irblaster chip not found\n", __func__); + pc = ERR_PTR(-EINVAL); + goto put; + } + + if (args.args_count != pc->of_irblaster_n_cells) { + pr_err("%s: wrong #irblaster-cells for %s\n", np->full_name, + args.np->full_name); + pc = ERR_PTR(-EINVAL); + goto put; + } + + err = irblaster_set_default_state(pc, &args); + if (err < 0) { + pr_err("%s(): irblaster get state fail\n", __func__); + pc = ERR_PTR(-EINVAL); + goto put; + } + + atomic_set(&pc->request, IRBLASTER_REQUESTED); + irblasterchip_sysfs_unexport(pc); +put: + of_node_put(args.np); + + return pc; +} +EXPORT_SYMBOL_GPL(of_irblaster_get); + +static void devm_irblaster_release(struct device *dev, void *res) +{ + irblaster_put(*(struct irblaster_chip **)res); +} + +/** + * devm_of_irblaster_get() - resource managed of_irblaster_get() + * @dev: device for irblaster consumer + * @np: device node to get the irblaster from + * @con_id: consumer name + * + * This function performs like of_irblaster_get() but the acquired irblaster + * device will automatically be released on driver detach. + * + * Returns: A pointer to the requested irblaster device or an ERR_PTR()-encoded + * error code on failure. + */ +struct irblaster_chip *devm_of_irblaster_get(struct device *dev, + struct device_node *np, + const char *con_id) +{ + struct irblaster_chip **dr, *chip; + + dr = devres_alloc(devm_irblaster_release, sizeof(*dr), GFP_KERNEL); + if (!dr) + return ERR_PTR(-ENOMEM); + + chip = of_irblaster_get(np, con_id); + if (!IS_ERR(chip)) { + *dr = chip; + devres_add(dev, dr); + } else { + devres_free(dr); + } + + return chip; +} +EXPORT_SYMBOL_GPL(devm_of_irblaster_get); diff --git a/drivers/amlogic/irblaster/encoder.c b/drivers/amlogic/irblaster/encoder.c new file mode 100644 index 000000000000..757fa18f8fa8 --- /dev/null +++ b/drivers/amlogic/irblaster/encoder.c @@ -0,0 +1,267 @@ +/* + * drivers/amlogic/irblaster/encoder.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 +#include +#include +#include +#include +#include +#include +#include + +static int irblaster_raw_gen_pulse_space(unsigned int *data, + unsigned int *max, + unsigned int pulse_width, + unsigned int space_width, + unsigned int len) +{ + if (!*max) + return -ENOBUFS; + data[len - *max] = pulse_width; + if (!--*max) + return -ENOBUFS; + data[len - *max] = space_width; + --*max; + + return 0; +} + +/** + * irblaster_raw_gen() - Encode data to raw events with pulse-length modulation. + * @data: Pointer to data + * @timings: Pulse distance modulation timings. + * @raw: Data bits to encode. + * @Returns: buff len on success. + * + * Encodes the @n least significant bits of @data using space-distance + * modulation with the timing characteristics described by @timings, writing up + * to data using the *data pointer. + */ +int irblaster_raw_gen(unsigned int *data, + const struct irblaster_raw_timings *timings, + u32 raw) +{ + int i, ret, max; + int len = timings->data_size; + unsigned int space; + + max = len; + if (timings->header_pulse) { + ret = irblaster_raw_gen_pulse_space(data, &max, + timings->header_pulse, + timings->header_space, + len); + if (ret) + return ret; + } + + if (timings->msb_first) { + for (i = timings->raw_nbits - 1; i >= 0; --i) { + space = timings->bit_space[(raw >> i) & 1]; + ret = irblaster_raw_gen_pulse_space(data, &max, + timings->bit_pulse, + space, len); + if (ret) + return ret; + } + } else { + for (i = 0; i < timings->raw_nbits; ++i, raw >>= 1) { + space = timings->bit_space[raw & 1]; + ret = irblaster_raw_gen_pulse_space(data, &max, + timings->bit_pulse, + space, len); + if (ret) + return ret; + } + } + + ret = irblaster_raw_gen_pulse_space(data, &max, + timings->trailer_pulse, + timings->trailer_space, + len); + if (ret) + return ret; + + return len; +} + +unsigned int protocol_show_select(struct irblaster_chip *chip, char *buf) +{ + struct irblaster_raw_handler *protocol; + unsigned int len = 0; + + mutex_lock(&irblaster_raw_handler_lock); + list_for_each_entry(protocol, &irblaster_raw_handler_list, list) { + if (chip->protocol && + chip->state.protocol == protocol->protocol) + len += scnprintf(buf + len, PAGE_SIZE - len, "[%s] ", + protocol->name); + else + len += scnprintf(buf + len, PAGE_SIZE - len, "%s ", + protocol->name); + } + + len += scnprintf(len + buf, PAGE_SIZE - len, "\n"); + mutex_unlock(&irblaster_raw_handler_lock); + + return len; +} + +unsigned int protocol_store_select(const char *buf) +{ + struct irblaster_raw_handler *protocol; + + mutex_lock(&irblaster_raw_handler_lock); + list_for_each_entry(protocol, &irblaster_raw_handler_list, list) { + if (sysfs_streq(buf, protocol->name)) { + mutex_unlock(&irblaster_raw_handler_lock); + return protocol->protocol; + } + } + mutex_unlock(&irblaster_raw_handler_lock); + + return 0; +} + +/** + * irblaster_raw_handler_register() + * - register a new raw_handle + * @ir_raw_handler: the raw_handle to add + * @Returns: 0 on success + */ +int irblaster_raw_handler_register(struct irblaster_raw_handler *ir_raw_handler) +{ + mutex_lock(&irblaster_raw_handler_lock); + list_add_tail(&ir_raw_handler->list, &irblaster_raw_handler_list); + mutex_unlock(&irblaster_raw_handler_lock); + + return 0; +} +EXPORT_SYMBOL(irblaster_raw_handler_register); + +/** + * irblaster_raw_handler_unregister() + * - unregister a raw_handle + * @ir_raw_handler: the raw_handle to remove + */ +void irblaster_raw_handler_unregister(struct irblaster_raw_handler + *ir_raw_handler) +{ + mutex_lock(&irblaster_raw_handler_lock); + list_del(&ir_raw_handler->list); + mutex_unlock(&irblaster_raw_handler_lock); +} +EXPORT_SYMBOL(irblaster_raw_handler_unregister); + +/** + * irblaster_send_key() - send key with addr and commmand + * @chip: irblaster controller + * @addr: remote control ID + * @commmand: key + */ +int irblaster_send_key(struct irblaster_chip *chip, unsigned int addr, + unsigned int commmand) +{ + int ret; + unsigned int *data; + + if (!chip) + return -EINVAL; + + if (chip->ops->send_key) { + ret = chip->ops->send_key(chip, addr, commmand); + if (ret) { + pr_err("%s(): irblaster_send fail\n", + __func__); + return -EINVAL; + } + } else { + data = kzalloc(sizeof(uint32_t) * MAX_PLUSE, GFP_KERNEL); + if (!data) + return -ENOMEM; + + if (chip->protocol->encode) { + ret = chip->protocol->encode(chip->state.protocol, + addr, commmand, data); + if (ret <= 0) { + pr_err("%s(): irblaster encode fail\n", + __func__); + goto err; + } + } else { + pr_err("%s(): irblaster func %s not found\n", + __func__, __func__); + goto err; + } + + ret = irblaster_send(chip, data, + chip->protocol->timing->data_size); + if (ret) { + pr_err("%s(): irblaster_send fail\n", __func__); + goto err; + } + + kfree(data); + } + + return 0; +err: + kfree(data); + return -EINVAL; +} + +/** + * irblaster_set_protocol() - set irblaster protocol + * @chip: irblaster controller + * @ir_protocol: irblaster protocol + */ +int irblaster_set_protocol(struct irblaster_chip *chip, + enum irblaster_protocol ir_protocol) +{ + struct irblaster_raw_handler *protocol; + + if (!chip || ir_protocol < 0 || ir_protocol >= IRBLASTER_PROTOCOL_MAX) + return -EINVAL; + + mutex_lock(&irblaster_raw_handler_lock); + + list_for_each_entry(protocol, &irblaster_raw_handler_list, list) + if (protocol->protocol == ir_protocol) { + chip->state.protocol = ir_protocol; + chip->protocol = protocol; + mutex_unlock(&irblaster_raw_handler_lock); + return 0; + } + + mutex_unlock(&irblaster_raw_handler_lock); + pr_err("%s(): irblaster protocol is not found\n", __func__); + + return -EINVAL; +} + +/** + * irblaster_get_protocol() - get irblaster protocol + * @chip: irblaster controller + */ +enum irblaster_protocol irblaster_get_protocol(struct irblaster_chip *chip) +{ + if (!chip) + return -EINVAL; + + return chip->state.protocol; +} diff --git a/drivers/amlogic/irblaster/irblaster-meson.c b/drivers/amlogic/irblaster/irblaster-meson.c new file mode 100644 index 000000000000..41a7f526bce6 --- /dev/null +++ b/drivers/amlogic/irblaster/irblaster-meson.c @@ -0,0 +1,415 @@ +/* + * drivers/amlogic/irblaster/irblaster-meson.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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Amlogic AO_IR_BLASTER_ADDR0 bits */ +#define BLASTER_BUSY BIT(26) +#define BLASTER_FIFO_FULL BIT(25) +#define BLASTER_FIFO_EMPTY BIT(24) +#define BLASTER_FIFO_LEVEL (0xff << 16) +#define BLASTER_MODULATOR_TB_SYSTEM_CLOCK (0x0 << 12) +#define BLASTER_MODULATOR_TB_XTAL3_TICK (0x1 << 12) +#define BLASTER_MODULATOR_TB_1US_TICK (0x2 << 12) +#define BLASTER_MODULATOR_TB_10US_TICK (0x3 << 12) +#define BLASTER_SLOW_CLOCK_DIV (0xff << 4) +#define BLASTER_SLOW_CLOCK_MODE BIT(3) +#define BLASTER_INIT_HIGH BIT(2) +#define BLASTER_INIT_LOW BIT(1) +#define BLASTER_ENABLE BIT(0) + +/* Amlogic AO_IR_BLASTER_ADDR1 bits */ +#define BLASTER_MODULATION_LOW_COUNT(c) ((c) << 16) +#define BLASTER_MODULATION_HIGH_COUNT(c) ((c) << 0) + +/* Amlogic AO_IR_BLASTER_ADDR2 bits */ +#define BLASTER_WRITE_FIFO BIT(16) +#define BLASTER_MODULATION_ENABLE BIT(12) +#define BLASTER_TIMEBASE_1US (0x0 << 10) +#define BLASTER_TIMEBASE_10US (0x1 << 10) +#define BLASTER_TIMEBASE_100US (0x2 << 10) +#define BLASTER_TIMEBASE_MODULATION_CLOCK (0x3 << 10) + +/* Amlogic AO_IR_BLASTER_ADDR3 bits */ +#define BLASTER_FIFO_THD_PENDING BIT(16) +#define BLASTER_FIFO_IRQ_ENABLE BIT(8) +#define BLASTER_FIFO_IRQ_THRESHOLD(c) (((c) & 0xff) << 0) + +#define DEFAULT_CARRIER_FREQ (38000) +#define DEFAULT_DUTY_CYCLE (50) + +#ifdef CONFIG_AMLOGIC_IRBLASTER_PROTOCOL +#define DEFAULT_IRBLASTER_PROTOCOL IRBLASTER_PROTOCOL_NEC +#endif + +#define LIMIT_DUTY (25) +#define MAX_DUTY (75) +#define LIMIT_FREQ (25000) +#define MAX_FREQ (60000) +#define COUNT_DELAY_MASK (0X3ff) +#define TIMEBASE_SHIFT (10) +#define BLASTER_KFIFO_SIZE (4) + +#define AO_IR_BLASTER_ADDR0 (0x0) +#define AO_IR_BLASTER_ADDR1 (0x4) +#define AO_IR_BLASTER_ADDR2 (0x8) +#define AO_IR_BLASTER_ADDR3 (0xc) +#define AO_RTI_GEN_CTNL_REG0 (0x0) + +#define CONSUMERIR_TRANSMIT 0x5500 +#define GET_CARRIER 0x5501 +#define SET_CARRIER 0x5502 +#define SET_DUTYCYCLE 0x5503 + +struct meson_irblaster_dev { + struct device *dev; + struct work_struct blaster_work; + struct irblaster_chip chip; + struct completion blaster_completion; + unsigned int count; + unsigned int irq; + unsigned int buffer_size; + unsigned int *buffer; + spinlock_t irblaster_lock; /* use to send data */ + void __iomem *reg_base; + void __iomem *reset_base; +}; + +static void meson_irblaster_tasklet(unsigned long data); +DECLARE_TASKLET_DISABLED(irblaster_tasklet, meson_irblaster_tasklet, 0); + +static struct meson_irblaster_dev * +to_meson_irblaster(struct irblaster_chip *chip) +{ + return container_of(chip, struct meson_irblaster_dev, chip); +} + +static void blaster_initialize(struct meson_irblaster_dev *dev) +{ + unsigned int carrier_cycle = 1000 / (dev->chip.state.freq / 1000); + unsigned int high_ct, low_ct; + + /* + *1. disable ir blaster + *2. set the modulator_tb = 2'10; mpeg_1uS_tick 1us + *3. set initializes the output to be high + */ + writel_relaxed((~BLASTER_ENABLE) & (BLASTER_MODULATOR_TB_1US_TICK | + BLASTER_INIT_HIGH), dev->reg_base + AO_IR_BLASTER_ADDR0); + /* + *1. set mod_high_count = 13 + *2. set mod_low_count = 13 + *3. 60khz-8us, 38k-13us + */ + high_ct = carrier_cycle * dev->chip.state.duty / 100; + low_ct = carrier_cycle - high_ct; + writel_relaxed((BLASTER_MODULATION_LOW_COUNT(low_ct - 1) | + BLASTER_MODULATION_HIGH_COUNT(high_ct - 1)), + dev->reg_base + AO_IR_BLASTER_ADDR1); + /*mask initialize output to be high*/ + writel_relaxed(readl_relaxed(dev->reg_base + AO_IR_BLASTER_ADDR0) & + ~BLASTER_INIT_HIGH, + dev->reg_base + AO_IR_BLASTER_ADDR0); + /* + *1. set fifo irq enable + *2. set fifo irq threshold + */ + writel_relaxed(BLASTER_FIFO_IRQ_ENABLE | + BLASTER_FIFO_IRQ_THRESHOLD(8), + dev->reg_base + AO_IR_BLASTER_ADDR3); + /*enable irblaster*/ + writel_relaxed(readl_relaxed(dev->reg_base + AO_IR_BLASTER_ADDR0) | + BLASTER_ENABLE, + dev->reg_base + AO_IR_BLASTER_ADDR0); +} + +static int write_to_fifo(struct meson_irblaster_dev *dev, + unsigned int hightime, + unsigned int lowtime) +{ + unsigned int count_delay; + unsigned int cycle = 1000 / (dev->chip.state.freq / 1000); + u32 val; + int n = 0; + int tb[3] = { + 1, 10, 100 + }; + + /* + * hightime: modulator signal. + * MODULATOR_TB: + * 00: system clock + * 01: mpeg_xtal3_tick + * 10: mpeg_1uS_tick + * 11: mpeg_10uS_tick + * + * AO_IR_BLASTER_ADDR2 + * bit12: output level(or modulation enable/disable:1=enable) + * bit[11:10]: Timebase : + * 00=1us + * 01=10us + * 10=100us + * 11=Modulator clock + * bit[9:0]: Count of timebase units to delay + */ + + count_delay = (((hightime + cycle / 2) / cycle) - 1) & COUNT_DELAY_MASK; + val = (BLASTER_WRITE_FIFO | BLASTER_MODULATION_ENABLE | + BLASTER_TIMEBASE_MODULATION_CLOCK | (count_delay << 0)); + writel_relaxed(val, dev->reg_base + AO_IR_BLASTER_ADDR2); + + /* + * lowtime<1024,n=0,timebase=1us + * 1024<=lowtime<10240,n=1,timebase=10us + * 10240<=lowtime,n=2,timebase=100us + */ + n = lowtime >> 10; + if (n > 0 && n < 10) + n = 1; + else if (n >= 10) + n = 2; + lowtime = (lowtime + (tb[n] >> 1)) / tb[n]; + count_delay = (lowtime - 1) & COUNT_DELAY_MASK; + val = (BLASTER_WRITE_FIFO & (~BLASTER_MODULATION_ENABLE)) | + (n << TIMEBASE_SHIFT) | (count_delay << 0); + writel_relaxed(val, dev->reg_base + AO_IR_BLASTER_ADDR2); + + return 0; +} + +static void send_all_data(struct meson_irblaster_dev *dev) +{ + int i; + unsigned int *pdata = NULL; + unsigned long flags; + + pdata = &dev->buffer[dev->count]; + spin_lock_irqsave(&dev->irblaster_lock, flags); + for (i = 0; (i < 120) && (dev->count < dev->buffer_size);) { + write_to_fifo(dev, *pdata, *(pdata + 1)); + pdata += 2; + dev->count += 2; + i += 2; + } + spin_unlock_irqrestore(&dev->irblaster_lock, flags); +} + +int meson_irblaster_send(struct irblaster_chip *chip, + unsigned int *data, + unsigned int len) +{ + int ret, i, sum_time = 0; + unsigned int high_ct, low_ct; + unsigned int cycle; + struct meson_irblaster_dev *irblaster_dev = to_meson_irblaster(chip); + + init_completion(&irblaster_dev->blaster_completion); + irblaster_dev->buffer = data; + irblaster_dev->buffer_size = len; + irblaster_dev->count = 0; + + for (i = 0; i < irblaster_dev->buffer_size; i++) + sum_time = sum_time + data[i]; + + /* + * 1. set mod_high_count = 13 + * 2. set mod_low_count = 13 + * 3. 60khz-8us, 38k-13us + */ + cycle = 1000 / (irblaster_dev->chip.state.freq / 1000); + high_ct = cycle * irblaster_dev->chip.state.duty / 100; + low_ct = cycle - high_ct; + writel_relaxed((BLASTER_MODULATION_LOW_COUNT(low_ct - 1) | + BLASTER_MODULATION_HIGH_COUNT(high_ct - 1)), + irblaster_dev->reg_base + AO_IR_BLASTER_ADDR1); + + send_all_data(irblaster_dev); + ret = wait_for_completion_interruptible_timeout + (&irblaster_dev->blaster_completion, + msecs_to_jiffies(sum_time / 1000)); + if (!ret) { + pr_err("failed to send all data ret = %d\n", ret); + return -ETIMEDOUT; + } + + return 0; +} + +static struct irblaster_ops meson_irblaster_ops = { + .send = meson_irblaster_send, +}; + +static void meson_irblaster_tasklet(unsigned long data) +{ + struct meson_irblaster_dev *dev = (struct meson_irblaster_dev *)data; + + if (dev->count < dev->buffer_size) + send_all_data(dev); +} + +static irqreturn_t meson_blaster_interrupt(int irq, void *dev_id) +{ + struct meson_irblaster_dev *dev = dev_id; + + /*clear pending bit*/ + writel_relaxed(readl_relaxed(dev->reg_base + AO_IR_BLASTER_ADDR3) & + (~BLASTER_FIFO_THD_PENDING), + dev->reg_base + AO_IR_BLASTER_ADDR3); + + if (dev->count >= dev->buffer_size) { + complete(&dev->blaster_completion); + return IRQ_HANDLED; + } + + tasklet_schedule(&irblaster_tasklet); + return IRQ_HANDLED; +} + +static int meson_irblaster_probe(struct platform_device *pdev) +{ + struct meson_irblaster_dev *irblaster_dev = NULL; + struct resource *reg_mem = NULL; + void __iomem *reg_base = NULL; + int err, ret; + + if (!pdev->dev.of_node) { + dev_err(&pdev->dev, "pdev->dev.of_node == NULL!\n"); + return -EINVAL; + } + + irblaster_dev = devm_kzalloc(&pdev->dev, + sizeof(struct meson_irblaster_dev), + GFP_KERNEL); + if (!irblaster_dev) + return -ENOMEM; + + spin_lock_init(&irblaster_dev->irblaster_lock); + platform_set_drvdata(pdev, irblaster_dev); + irblaster_dev->dev = &pdev->dev; + + reg_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!IS_ERR_OR_NULL(reg_mem)) { + reg_base = devm_ioremap_resource(&pdev->dev, reg_mem); + if (IS_ERR(reg_base)) { + dev_err(&pdev->dev, "reg0: cannot obtain I/O memory region.\n"); + return PTR_ERR(reg_base); + } + } else { + dev_err(&pdev->dev, "get IORESOURCE_MEM error.\n"); + return PTR_ERR(reg_base); + } + + irblaster_dev->irq = irq_of_parse_and_map(pdev->dev.of_node, 0); + if (!irblaster_dev->irq) { + dev_err(&pdev->dev, "irq: Failed to request irq number.\n"); + return -ENODEV; + } + + init_completion(&irblaster_dev->blaster_completion); + ret = devm_request_irq(&pdev->dev, irblaster_dev->irq, + meson_blaster_interrupt, + IRQF_TRIGGER_RISING, + dev_name(&pdev->dev), + irblaster_dev); + if (ret) { + pr_err("Failed to request irq.\n"); + return ret; + } + + irblaster_dev->reg_base = reg_base; + irblaster_dev->chip.dev = &pdev->dev; + irblaster_dev->chip.ops = &meson_irblaster_ops; + irblaster_dev->chip.of_irblaster_n_cells = 2; + irblaster_dev->chip.state.freq = DEFAULT_CARRIER_FREQ; + irblaster_dev->chip.state.duty = DEFAULT_DUTY_CYCLE; +#ifdef CONFIG_AMLOGIC_IRBLASTER_PROTOCOL + irblaster_dev->chip.state.protocol = DEFAULT_IRBLASTER_PROTOCOL; + irblaster_set_protocol(&irblaster_dev->chip, + DEFAULT_IRBLASTER_PROTOCOL); +#endif + err = irblasterchip_add(&irblaster_dev->chip); + if (err < 0) { + dev_err(&pdev->dev, "failed to register irblaster chip: %d\n", + err); + return err; + } + + irblaster_tasklet.data = (unsigned long)irblaster_dev; + tasklet_enable(&irblaster_tasklet); + + /*initial blaster*/ + blaster_initialize(irblaster_dev); + + return 0; +} + +static int meson_irblaster_remove(struct platform_device *pdev) +{ + struct meson_irblaster_dev *irblaster_dev = platform_get_drvdata(pdev); + + tasklet_disable(&irblaster_tasklet); + tasklet_kill(&irblaster_tasklet); + irblasterchip_remove(&irblaster_dev->chip); + + return 0; +} + +static const struct of_device_id irblaster_dt_match[] = { + { + .compatible = "amlogic, meson_irblaster", + }, + {}, +}; +MODULE_DEVICE_TABLE(of, irblaster_dt_match); + +static struct platform_driver meson_irblaster_driver = { + .probe = meson_irblaster_probe, + .remove = meson_irblaster_remove, + .driver = { + .name = "meson_irblaster", + .owner = THIS_MODULE, + .of_match_table = irblaster_dt_match, + }, +}; + +static int __init meson_irblaster_init(void) +{ + return platform_driver_register(&meson_irblaster_driver); +} + +static void __exit meson_irblaster_exit(void) +{ + platform_driver_unregister(&meson_irblaster_driver); +} + +fs_initcall_sync(meson_irblaster_init); +module_exit(meson_irblaster_exit); +MODULE_AUTHOR("Amlogic, Inc."); +MODULE_DESCRIPTION("Amlogic ir blaster driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/amlogic/irblaster/irblaster-nec-encoder.c b/drivers/amlogic/irblaster/irblaster-nec-encoder.c new file mode 100644 index 000000000000..107383ff3729 --- /dev/null +++ b/drivers/amlogic/irblaster/irblaster-nec-encoder.c @@ -0,0 +1,180 @@ +/* + * drivers/amlogic/irblaster/irblaster-nec-encoder.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 +#include + +#define NEC_NBITS 32 +#define NEC_UNIT 562 /* ns */ +#define NEC_HEADER_PULSE 9000 +#define NEC_HEADER_SPACE 4500 +#define NEC_BIT_PULSE 560 +#define NEC_BIT_0_SPACE 560 +#define NEC_BIT_1_SPACE 1690 +#define NEC_TRAILER_PULSE 560 +#define NEC_TRAILER_SPACE 5600 /* even longer in reality */ + +static struct irblaster_raw_timings irblaster_nec_timings = { + .header_pulse = NEC_HEADER_PULSE, + .header_space = NEC_HEADER_SPACE, + .bit_pulse = NEC_BIT_PULSE, + .bit_space[0] = NEC_BIT_0_SPACE, + .bit_space[1] = NEC_BIT_1_SPACE, + .trailer_pulse = NEC_TRAILER_PULSE, + .trailer_space = NEC_TRAILER_SPACE, + .msb_first = 0, + .raw_nbits = NEC_NBITS, + .data_size = (NEC_NBITS + 2) * 2, +}; + +static u32 irblaster_nec32_scancode_to_raw(enum irblaster_protocol protocol, + unsigned int addrs, + unsigned int commmand) +{ + unsigned int addr = 0, addr_inv, data, data_inv; + + data = commmand & 0xff; + addr_inv = addr & 0xff; + addr = addrs & 0xff; + data_inv = data & 0xff; + + return data_inv << 24 | + data << 16 | + addr_inv << 8 | + addr; +} + +static u32 irblaster_necx_scancode_to_raw(enum irblaster_protocol protocol, + unsigned int addrs, + unsigned int commmand) +{ + unsigned int addr, addr_inv, data, data_inv; + + data = commmand & 0xff; + addr = addrs & 0xff; + addr_inv = addr & 0xff; + data_inv = data ^ 0xff; + + return data_inv << 24 | + data << 16 | + addr_inv << 8 | + addr; +} + +static u32 irblaster_nec_scancode_to_raw(enum irblaster_protocol protocol, + unsigned int addrs, + unsigned int commmand) +{ + unsigned int addr, addr_inv, data, data_inv; + + data = commmand & 0xff; + addr = addrs & 0xff; + addr_inv = addr ^ 0xff; + data_inv = data ^ 0xff; + + return data_inv << 24 | + data << 16 | + addr_inv << 8 | + addr; +} + +int irblaster_nec_encode(enum irblaster_protocol protocol, + unsigned int addr, + unsigned int commmand, + unsigned int *data) +{ + u32 raw, ret; + + if (protocol >= IRBLASTER_PROTOCOL_MAX) + return -ENODEV; + + /* Convert a NEC scancode to raw NEC data */ + switch (protocol) { + case IRBLASTER_PROTOCOL_NEC: + raw = irblaster_nec_scancode_to_raw(protocol, addr, commmand); + break; + case IRBLASTER_PROTOCOL_NECX: + raw = irblaster_necx_scancode_to_raw(protocol, addr, commmand); + break; + case IRBLASTER_PROTOCOL_NEC32: + raw = irblaster_nec32_scancode_to_raw(protocol, addr, commmand); + break; + default: + raw = irblaster_nec_scancode_to_raw(protocol, addr, commmand); + break; + } + + /* Modulate the raw data using a pulse distance modulation */ + ret = irblaster_raw_gen(data, &irblaster_nec_timings, raw); + if (ret < 0) + return ret; + + return ret; +} + +static struct irblaster_raw_handler irblaster_nec_handler[] = { + { + .name = "NEC", + .protocol = IRBLASTER_PROTOCOL_NEC, + .encode = irblaster_nec_encode, + .freq = 38000, + .duty = 50, + .timing = &irblaster_nec_timings, + }, + { + .name = "NECX", + .protocol = IRBLASTER_PROTOCOL_NECX, + .encode = irblaster_nec_encode, + .freq = 38000, + .duty = 50, + .timing = &irblaster_nec_timings, + }, + { + .name = "NEC32", + .protocol = IRBLASTER_PROTOCOL_NEC32, + .encode = irblaster_nec_encode, + .freq = 38000, + .duty = 50, + .timing = &irblaster_nec_timings, + } +}; + +static int __init irblaster_nec_decode_init(void) +{ + int i; + + for (i = 0; i < sizeof(irblaster_nec_handler) / + sizeof(struct irblaster_raw_handler); i++) + irblaster_raw_handler_register(irblaster_nec_handler + i); + + return 0; +} + +static void __exit irblaster_nec_decode_exit(void) +{ + int i; + + for (i = 0; i < sizeof(irblaster_nec_handler) / + sizeof(struct irblaster_raw_handler); i++) + irblaster_raw_handler_unregister(irblaster_nec_handler + i); +} + +fs_initcall(irblaster_nec_decode_init); +module_exit(irblaster_nec_decode_exit); + +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("NEC IR protocol decoder"); diff --git a/drivers/amlogic/irblaster/irblaster-rca-encoder.c b/drivers/amlogic/irblaster/irblaster-rca-encoder.c new file mode 100644 index 000000000000..21068b608ca0 --- /dev/null +++ b/drivers/amlogic/irblaster/irblaster-rca-encoder.c @@ -0,0 +1,99 @@ +/* + * drivers/amlogic/irblaster/irblaster-rca-encoder.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 +#include + +#define RCA_NBITS 24 +#define RCA_UNIT 500 /* ns */ +#define RCA_HEADER_PULSE 4000 +#define RCA_HEADER_SPACE 4000 +#define RCA_BIT_PULSE 500 +#define RCA_BIT_0_SPACE 1000 +#define RCA_BIT_1_SPACE 2000 +#define RCA_TRAILER_PULSE 500 +#define RCA_TRAILER_SPACE 5600 /* even longer in reality */ + +static struct irblaster_raw_timings irblaster_rca_timings = { + .header_pulse = RCA_HEADER_PULSE, + .header_space = RCA_HEADER_SPACE, + .bit_pulse = RCA_BIT_PULSE, + .bit_space[0] = RCA_BIT_0_SPACE, + .bit_space[1] = RCA_BIT_1_SPACE, + .trailer_pulse = RCA_TRAILER_PULSE, + .trailer_space = RCA_TRAILER_SPACE, + .msb_first = 1, + .raw_nbits = RCA_NBITS, + .data_size = (RCA_NBITS + 2) * 2, +}; + +static u32 irblaster_rca_scancode_to_raw(enum irblaster_protocol protocol, + unsigned int addrs, + unsigned int commmand) +{ + unsigned int addr, addr_inv, data, data_inv; + + data = commmand & 0xff; + addr = addrs & 0x0f; + addr_inv = addr ^ 0x0f; + data_inv = data ^ 0xff; + + return addr << 20 | + data << 12 | + addr_inv << 8 | + data_inv; +} + +int irblaster_rca_encode(enum irblaster_protocol protocol, unsigned int addr, + unsigned int commmand, unsigned int *data) +{ + u32 raw, ret; + + /* Convert a RCA scancode to raw rca data */ + raw = irblaster_rca_scancode_to_raw(protocol, addr, commmand); + + /* Modulate the raw data using a pulse distance modulation */ + ret = irblaster_raw_gen(data, &irblaster_rca_timings, raw); + if (ret < 0) + return ret; + + return ret; +} + +static struct irblaster_raw_handler irblaster_rca_handler = { + .name = "RCA", + .protocol = IRBLASTER_PROTOCOL_RCA, + .encode = irblaster_rca_encode, + .freq = 38000, + .duty = 50, + .timing = &irblaster_rca_timings, +}; + +static int __init irblaster_rca_decode_init(void) +{ + return irblaster_raw_handler_register(&irblaster_rca_handler); +} + +static void __exit irblaster_rca_decode_exit(void) +{ + irblaster_raw_handler_unregister(&irblaster_rca_handler); +} + +fs_initcall(irblaster_rca_decode_init); +module_exit(irblaster_rca_decode_exit); +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("RCA IR protocol decoder"); diff --git a/drivers/amlogic/irblaster/sysfs.c b/drivers/amlogic/irblaster/sysfs.c new file mode 100644 index 000000000000..650be648b476 --- /dev/null +++ b/drivers/amlogic/irblaster/sysfs.c @@ -0,0 +1,275 @@ +/* + * drivers/amlogic/irblaster/sysfs.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 +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_AMLOGIC_IRBLASTER_PROTOCOL +#include +#endif +static ssize_t send_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct irblaster_chip *chip = dev_get_drvdata(dev); + int i = 0, j = 0, m = 0; + int val, ret; + char tone[PS_SIZE]; + unsigned int *buffer; + + buffer = kzalloc(sizeof(uint32_t) * MAX_PLUSE, GFP_KERNEL); + if (!buffer) + return -ENOMEM; + + mutex_lock(&chip->sys_lock); + while (buf[i] != '\0') { + if (buf[i] == 's') { + tone[j] = '\0'; + ret = kstrtoint(tone, 10, &val); + if (ret) { + pr_err("Invalid tone\n"); + mutex_unlock(&chip->sys_lock); + return ret; + } + buffer[m] = val * 10; + j = 0; + i++; + m++; + if (m >= MAX_PLUSE) + break; + continue; + } + tone[j] = buf[i]; + i++; + j++; + if (j >= PS_SIZE) { + pr_err("send timing value is out of range\n"); + mutex_unlock(&chip->sys_lock); + kfree(buffer); + return -ENOMEM; + } + } + + ret = irblaster_send(chip, buffer, m); + if (ret) + pr_err("send raw data fail\n"); + + irblaster_chip_data_clear(chip); + mutex_unlock(&chip->sys_lock); + kfree(buffer); + + return ret ? : count; +} + +#ifdef CONFIG_AMLOGIC_IRBLASTER_PROTOCOL +static ssize_t send_key_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct irblaster_chip *chip = dev_get_drvdata(dev); + unsigned int addr, command; + int ret; + + ret = sscanf(buf, "%x %x", &addr, &command); + if (ret != 2) { + pr_err("Can't parse addr and command,usage:[addr command]\n"); + return -EINVAL; + } + mutex_lock(&chip->sys_lock); + ret = irblaster_send_key(chip, addr, command); + if (ret) + pr_err("send key fail\n"); + + mutex_unlock(&chip->sys_lock); + + return ret ? : count; +} +#endif + +static ssize_t carrier_freq_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct irblaster_chip *chip = dev_get_drvdata(dev); + + return sprintf(buf, "%d\n", chip->state.freq); +} + +static ssize_t carrier_freq_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct irblaster_chip *chip = dev_get_drvdata(dev); + int ret = 0, val; + + ret = kstrtoint(buf, 10, &val); + if (ret) { + pr_err("Invalid input for carrier_freq\n"); + return ret; + } + + mutex_lock(&chip->sys_lock); + ret = irblaster_set_freq(chip, val); + if (ret) + pr_err("set freq fail\n"); + + mutex_unlock(&chip->sys_lock); + + return ret ? : count; +} + +static ssize_t duty_cycle_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct irblaster_chip *chip = dev_get_drvdata(dev); + + return sprintf(buf, "%d\n", chip->state.duty); +} + +static ssize_t duty_cycle_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct irblaster_chip *chip = dev_get_drvdata(dev); + int ret = 0, val; + + ret = kstrtoint(buf, 10, &val); + if (ret) { + pr_err("Invalid input for duty_cycle\n"); + return ret; + } + + mutex_lock(&chip->sys_lock); + ret = irblaster_set_duty(chip, val); + if (ret) + pr_err("set duty fail\n"); + + mutex_unlock(&chip->sys_lock); + + return ret ? : count; +} + +#ifdef CONFIG_AMLOGIC_IRBLASTER_PROTOCOL +static ssize_t protocol_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct irblaster_chip *chip = dev_get_drvdata(dev); + unsigned int len; + + len = protocol_show_select(chip, buf); + + return len; +} + +static ssize_t protocol_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct irblaster_chip *chip = dev_get_drvdata(dev); + unsigned int ret, protocol; + + protocol = protocol_store_select(buf); + if (protocol >= IRBLASTER_PROTOCOL_MAX) + pr_err("protocol is not found\n"); + + ret = irblaster_set_protocol(chip, protocol); + if (ret) + pr_err("set protocol fail\n"); + + return ret ? : count; +} +#endif + +//static DEVICE_ATTR(debug, 0644, show_debug, store_debug); +static DEVICE_ATTR_WO(send); +#ifdef CONFIG_AMLOGIC_IRBLASTER_PROTOCOL +static DEVICE_ATTR_WO(send_key); +#endif +static DEVICE_ATTR_RW(carrier_freq); +static DEVICE_ATTR_RW(duty_cycle); +#ifdef CONFIG_AMLOGIC_IRBLASTER_PROTOCOL +static DEVICE_ATTR_RW(protocol); +#endif + +static struct attribute *irblaster_chip_attrs[] = { +// &dev_attr_debug.attr, + &dev_attr_send.attr, +#ifdef CONFIG_AMLOGIC_IRBLASTER_PROTOCOL + &dev_attr_send_key.attr, +#endif + &dev_attr_carrier_freq.attr, + &dev_attr_duty_cycle.attr, +#ifdef CONFIG_AMLOGIC_IRBLASTER_PROTOCOL + &dev_attr_protocol.attr, +#endif + NULL, +}; +ATTRIBUTE_GROUPS(irblaster_chip); + +static struct class irblaster_class = { + .name = "irblaster", + .owner = THIS_MODULE, + .dev_groups = irblaster_chip_groups, +}; + +static int irblasterchip_sysfs_match(struct device *parent, const void *data) +{ + return dev_get_drvdata(parent) == data; +} + +void irblasterchip_sysfs_export(struct irblaster_chip *chip) +{ + struct device *parent; + + /* + * If device_create() fails the irblaster_chip is still usable by + * the kernel its just not exported. + */ + parent = device_create(&irblaster_class, chip->dev, MKDEV(0, 0), chip, + "irblaster%d", chip->base); + if (IS_ERR(parent)) { + dev_warn(chip->dev, + "device_create failed for irblaster_chip sysfs export\n"); + } + + mutex_init(&chip->sys_lock); +} + +void irblasterchip_sysfs_unexport(struct irblaster_chip *chip) +{ + struct device *parent; + + parent = class_find_device(&irblaster_class, NULL, chip, + irblasterchip_sysfs_match); + if (parent) { + /* for class_find_device() */ + put_device(parent); + device_unregister(parent); + } +} + +static int __init irblaster_sysfs_init(void) +{ + return class_register(&irblaster_class); +} +subsys_initcall(irblaster_sysfs_init); diff --git a/drivers/amlogic/irqchip/irq-meson-gpio.c b/drivers/amlogic/irqchip/irq-meson-gpio.c index a875b218f026..b1d15049edfd 100644 --- a/drivers/amlogic/irqchip/irq-meson-gpio.c +++ b/drivers/amlogic/irqchip/irq-meson-gpio.c @@ -40,11 +40,13 @@ #define REG_EDGE_POL_MASK(x) (BIT(x) | BIT(16 + (x))) #define REG_EDGE_POL_EDGE(x) BIT(x) #define REG_EDGE_POL_LOW(x) BIT(16 + (x)) +#define REG_EDGE_BOTH_EDGE(x) BIT(8 + (x)) #define REG_PIN_SEL_SHIFT(x) (((x) % 4) * 8) #define REG_FILTER_SEL_SHIFT(x) ((x) * 4) struct meson_gpio_irq_params { unsigned int nr_hwirq; + u8 support_double_edge; }; static const struct meson_gpio_irq_params meson8_params = { @@ -83,6 +85,16 @@ static const struct meson_gpio_irq_params tl1_params = { .nr_hwirq = 102, }; +static const struct meson_gpio_irq_params sm1_params = { + .nr_hwirq = 100, + .support_double_edge = 1, +}; + +static const struct meson_gpio_irq_params tm2_params = { + .nr_hwirq = 104, + .support_double_edge = 1, +}; + static const struct of_device_id meson_irq_gpio_matches[] = { { .compatible = "amlogic,meson8-gpio-intc", .data = &meson8_params }, { .compatible = "amlogic,meson8b-gpio-intc", .data = &meson8b_params }, @@ -93,11 +105,14 @@ static const struct of_device_id meson_irq_gpio_matches[] = { { .compatible = "amlogic,meson-g12a-gpio-intc", .data = &g12a_params }, { .compatible = "amlogic,meson-txl-gpio-intc", .data = &txl_params }, { .compatible = "amlogic,meson-tl1-gpio-intc", .data = &tl1_params }, + { .compatible = "amlogic,meson-sm1-gpio-intc", .data = &sm1_params }, + { .compatible = "amlogic,meson-tm2-gpio-intc", .data = &tm2_params }, { } }; struct meson_gpio_irq_controller { unsigned int nr_hwirq; + u8 support_double_edge; void __iomem *base; u32 channel_irqs[NUM_CHANNEL]; DECLARE_BITMAP(channel_map, NUM_CHANNEL); @@ -200,8 +215,16 @@ static int meson_gpio_irq_type_setup(struct meson_gpio_irq_controller *ctl, */ type &= IRQ_TYPE_SENSE_MASK; - if (type == IRQ_TYPE_EDGE_BOTH) - return -EINVAL; + if (type == IRQ_TYPE_EDGE_BOTH) { + if (!ctl->support_double_edge) + return -EINVAL; + val |= REG_EDGE_BOTH_EDGE(idx); + spin_lock(&ctl->lock); + meson_gpio_irq_update_bits(ctl, REG_EDGE_POL, + REG_EDGE_BOTH_EDGE(idx), val); + spin_unlock(&ctl->lock); + return 0; + } if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) val |= REG_EDGE_POL_EDGE(idx); @@ -211,6 +234,14 @@ static int meson_gpio_irq_type_setup(struct meson_gpio_irq_controller *ctl, spin_lock(&ctl->lock); + /* Double-edge has priority over all others. If a double-edge gpio + * changes to another method's, we need to reset the corresponding bit + * of double-edge register. + */ + if (ctl->support_double_edge) + meson_gpio_irq_update_bits(ctl, REG_EDGE_POL, + REG_EDGE_BOTH_EDGE(idx), 0); + meson_gpio_irq_update_bits(ctl, REG_EDGE_POL, REG_EDGE_POL_MASK(idx), val); @@ -369,6 +400,7 @@ static int __init meson_gpio_irq_parse_dt(struct device_node *node, params = match->data; ctl->nr_hwirq = params->nr_hwirq; + ctl->support_double_edge = params->support_double_edge; ret = of_property_read_variable_u32_array(node, "amlogic,channel-interrupts", diff --git a/drivers/amlogic/jtag/meson_jtag.c b/drivers/amlogic/jtag/meson_jtag.c index ddca757f80e7..a080ef5574bb 100644 --- a/drivers/amlogic/jtag/meson_jtag.c +++ b/drivers/amlogic/jtag/meson_jtag.c @@ -101,6 +101,23 @@ static inline char *select_to_name(int select) } } +static inline int name_to_select(const char *s) +{ + int select; + + if (!strncmp(s, "disable", 7)) + select = AMLOGIC_JTAG_DISABLE; + else if (!strncmp(s, "apao", 4)) + select = AMLOGIC_JTAG_APAO; + else if (!strncmp(s, "apee", 4)) + select = AMLOGIC_JTAG_APEE; + else { + pr_err("unknown select: %s\n", s); + select = AMLOGIC_JTAG_DISABLE; + } + + return select; +} static void aml_jtag_option_parse(struct aml_jtag_dev *jdev, const char *s) { @@ -108,15 +125,7 @@ static void aml_jtag_option_parse(struct aml_jtag_dev *jdev, const char *s) unsigned long value; int ret; - if (!strncmp(s, "disable", 7)) - jdev->select = AMLOGIC_JTAG_DISABLE; - else if (!strncmp(s, "apao", 4)) - jdev->select = AMLOGIC_JTAG_APAO; - else if (!strncmp(s, "apee", 4)) - jdev->select = AMLOGIC_JTAG_APEE; - else - pr_err("unknown select: %s", s); - + jdev->select = name_to_select(s); cluster = strchr(s, ','); if (cluster != NULL) { cluster++; @@ -138,19 +147,10 @@ static int __init setup_jtag(char *p) unsigned long value; int ret; + if (!p) + return -EINVAL; jtag_select_setup = true; - - if (!strncmp(p, "disable", 7)) - jtag_select = AMLOGIC_JTAG_DISABLE; - else if (!strncmp(p, "apao", 4)) - jtag_select = AMLOGIC_JTAG_APAO; - else if (!strncmp(p, "apee", 4)) - jtag_select = AMLOGIC_JTAG_APEE; - else - jtag_select = AMLOGIC_JTAG_DISABLE; - - pr_info("jtag select %s\n", select_to_name(jtag_select)); - + jtag_select = name_to_select(p); cluster = strchr(p, ','); if (cluster != NULL) { cluster++; @@ -176,106 +176,17 @@ static int __init setup_jtag(char *p) */ __setup("jtag=", setup_jtag); - -/* - * request gpios for jtag apao. - * - * @return: 0 success, other failed - * - */ -static int aml_jtag_apao_request_gpios(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct aml_jtag_dev *jdev = platform_get_drvdata(pdev); - const unsigned int *gpios = jdev->ao_gpios; - - int ngpio, i, ret; - - ngpio = jdev->ao_ngpios; - - for (i = 0; i < ngpio; i++) { - ret = devm_gpio_request(dev, gpios[i], "apao"); - if (ret) { - pr_err("can't request gpio %d", gpios[i]); - return -ENOENT; - } - pr_info("request gpio %d for apao\n", gpios[i]); - } - - return 0; -} - -static int aml_jtag_apao_free_gpios(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct aml_jtag_dev *jdev = platform_get_drvdata(pdev); - const unsigned int *gpios = jdev->ao_gpios; - - int ngpio, i; - - ngpio = jdev->ao_ngpios; - - for (i = 0; i < ngpio; i++) - devm_gpio_free(dev, gpios[i]); - - return 0; -} - - -/* - * request gpios for jtag apee. - * - * @return: 0 success, other failed - * - */ -static int aml_jtag_apee_request_gpios(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct aml_jtag_dev *jdev = platform_get_drvdata(pdev); - const unsigned int *gpios = jdev->ee_gpios; - - int ngpio, i, ret; - - ngpio = jdev->ee_ngpios; - - for (i = 0; i < ngpio; i++) { - ret = devm_gpio_request(dev, gpios[i], "apee"); - if (ret) { - pr_err("can't request gpio %d", gpios[i]); - return -ENOENT; - } - pr_info("request gpio %d for apee\n", gpios[i]); - } - - return 0; -} - -static int aml_jtag_apee_free_gpios(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct aml_jtag_dev *jdev = platform_get_drvdata(pdev); - const unsigned int *gpios = jdev->ee_gpios; - - int ngpio, i; - - ngpio = jdev->ee_ngpios; - - for (i = 0; i < ngpio; i++) - devm_gpio_free(dev, gpios[i]); - - return 0; -} - - #ifdef CONFIG_MACH_MESON8B static int aml_jtag_select_tee(struct platform_device *pdev) { struct aml_jtag_dev *jdev = platform_get_drvdata(pdev); uint32_t select = jdev->select; + struct cpumask org_cpumask; - pr_info("set state %u\n", select); + cpumask_copy(&org_cpumask, ¤t->cpus_allowed); set_cpus_allowed_ptr(current, cpumask_of(0)); + pr_info("meson8b select %s\n", select_to_name(jdev->select)); switch (select) { case AMLOGIC_JTAG_DISABLE: meson_secure_jtag_disable(); @@ -291,7 +202,7 @@ static int aml_jtag_select_tee(struct platform_device *pdev) writel_relaxed(0x0, jdev->base); break; } - set_cpus_allowed_ptr(current, cpu_all_mask); + set_cpus_allowed_ptr(current, &org_cpumask); return 0; } @@ -309,7 +220,7 @@ static int aml_jtag_select_ree(struct platform_device *pdev) pr_err("failed to iomap regs"); return -ENODEV; } - + pr_info("meson8b select %s\n", select_to_name(jdev->select)); switch (sel) { case AMLOGIC_JTAG_DISABLE: writel_relaxed(0x0, jdev->base); @@ -353,6 +264,7 @@ static unsigned long __invoke_psci_fn_smc(unsigned long function_id, struct arm_smccc_res res; arm_smccc_smc(function_id, arg0, arg1, arg2, 0, 0, 0, 0, &res); + return res.a0; } @@ -381,6 +293,7 @@ static int aml_jtag_select(struct platform_device *pdev) struct aml_jtag_dev *jdev = platform_get_drvdata(pdev); unsigned int select = jdev->select; unsigned int state = AMLOGIC_JTAG_STATE_OFF; + struct cpumask org_cpumask; if (select != AMLOGIC_JTAG_DISABLE) state = AMLOGIC_JTAG_STATE_ON; @@ -388,54 +301,75 @@ static int aml_jtag_select(struct platform_device *pdev) if (jdev->cluster != CLUSTER_DISABLE) select |= jdev->cluster << CLUSTER_BIT; - pr_info("set state %u\n", select); - + pr_info("select %s\n", select_to_name(select)); + cpumask_copy(&org_cpumask, ¤t->cpus_allowed); set_cpus_allowed_ptr(current, cpumask_of(0)); aml_set_jtag_state(state, select); - set_cpus_allowed_ptr(current, cpu_all_mask); + set_cpus_allowed_ptr(current, &org_cpumask); return 0; } #endif -static void aml_jtag_setup(struct aml_jtag_dev *jdev) +static int aml_jtag_setup(struct aml_jtag_dev *jdev) { - struct platform_device *pdev = jdev->pdev; unsigned int old_select = jdev->old_select; unsigned int select = jdev->select; + struct pinctrl_state *s; + int ret; if (old_select == select) - return; - - /* free gpios */ - switch (old_select) { - case AMLOGIC_JTAG_APAO: - aml_jtag_apao_free_gpios(pdev); - break; - case AMLOGIC_JTAG_APEE: - aml_jtag_apee_free_gpios(pdev); - break; - default: - break; + return 0; + if (!jdev->jtag_pinctrl) { + jdev->jtag_pinctrl = devm_pinctrl_get(&jdev->pdev->dev); + if (IS_ERR_OR_NULL(jdev->jtag_pinctrl)) { + dev_err(&jdev->pdev->dev, "could not get pinctrl handle\n"); + return -EINVAL; + } } - - /* free gpios */ + /* set pinmux */ switch (select) { case AMLOGIC_JTAG_APAO: - aml_jtag_apao_request_gpios(pdev); + s = pinctrl_lookup_state(jdev->jtag_pinctrl, "jtag_apao_pins"); + if (IS_ERR_OR_NULL(s)) { + dev_err(&jdev->pdev->dev, + "could not get jtag_apao_pins state\n"); + return -EINVAL; + } + ret = pinctrl_select_state(jdev->jtag_pinctrl, s); + if (ret) { + dev_err(&jdev->pdev->dev, "failed to set pinctrl\n"); + return -EINVAL; + } break; case AMLOGIC_JTAG_APEE: - aml_jtag_apee_request_gpios(pdev); + s = pinctrl_lookup_state(jdev->jtag_pinctrl, "jtag_apee_pins"); + if (IS_ERR_OR_NULL(s)) { + dev_err(&jdev->pdev->dev, + "could not get jtag_apee_pins state\n"); + return -EINVAL; + } + ret = pinctrl_select_state(jdev->jtag_pinctrl, s); + if (ret) { + dev_err(&jdev->pdev->dev, "failed to set pinctrl\n"); + return -EINVAL; + } break; default: + if (old_select != AMLOGIC_JTAG_DISABLE) { + devm_pinctrl_put(jdev->jtag_pinctrl); + jdev->jtag_pinctrl = NULL; + } break; } + /* save to global */ + global_select = jdev->select; aml_jtag_select(jdev->pdev); - jdev->old_select = select; + return 0; } static ssize_t jtag_select_show(struct class *cls, @@ -448,23 +382,23 @@ static ssize_t jtag_select_show(struct class *cls, len += sprintf(buf + len, "usage:\n"); len += sprintf(buf + len, " echo [apao|apee] > select\n"); len += sprintf(buf + len, " echo [apao|apee]{,[0|1]} > select\n"); + return len; } - static ssize_t jtag_select_store(struct class *cls, struct class_attribute *attr, const char *buffer, size_t count) { struct aml_jtag_dev *jdev; + int ret; jdev = container_of(cls, struct aml_jtag_dev, cls); aml_jtag_option_parse(jdev, buffer); - /* save to global */ - global_select = jdev->select; - - aml_jtag_setup(jdev); + ret = aml_jtag_setup(jdev); + if (ret < 0) + return ret; return count; } @@ -474,63 +408,13 @@ static struct class_attribute aml_jtag_attrs[] = { __ATTR_NULL, }; - static int aml_jtag_dt_parse(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct device_node *np = dev->of_node; struct aml_jtag_dev *jdev = platform_get_drvdata(pdev); const char *tmp; - - int ao_ngpios, ee_ngpios; - unsigned int *ao_gpios, *ee_gpios; - int ret, i, gpio; - - - ao_ngpios = of_gpio_named_count(np, "jtagao-gpios"); - if (ao_ngpios <= 0) { - pr_err("ao gpios not specified\n"); - return -EINVAL; - } - - ee_ngpios = of_gpio_named_count(np, "jtagee-gpios"); - if (ee_ngpios <= 0) { - pr_err("ee gpios not specified\n"); - return -EINVAL; - } - - jdev->ao_ngpios = ao_ngpios; - jdev->ee_ngpios = ee_ngpios; - - ao_gpios = devm_kzalloc(dev, sizeof(unsigned int) * ao_ngpios, - GFP_KERNEL); - ee_gpios = devm_kzalloc(dev, sizeof(unsigned int) * ee_ngpios, - GFP_KERNEL); - if (!ao_gpios || !ee_gpios) { - pr_err("failed to allocate memory for gpios\n"); - return -ENOMEM; - } - - for (i = 0; i < ao_ngpios; i++) { - gpio = of_get_named_gpio(dev->of_node, "jtagao-gpios", i); - if (!gpio_is_valid(gpio)) { - pr_err("gpio %d is not valid", gpio); - return -EINVAL; - } - ao_gpios[i] = gpio; - } - - for (i = 0; i < ee_ngpios; i++) { - gpio = of_get_named_gpio(dev->of_node, "jtagee-gpios", i); - if (!gpio_is_valid(gpio)) { - pr_err("gpio %d is not valid", gpio); - return -EINVAL; - } - ee_gpios[i] = gpio; - } - - jdev->ao_gpios = ao_gpios; - jdev->ee_gpios = ee_gpios; + int ret; /* otherwise set select with dt */ ret = of_property_read_string(np, "select", &tmp); @@ -538,34 +422,22 @@ static int aml_jtag_dt_parse(struct platform_device *pdev) pr_err("select not configured\n"); return -EINVAL; } - pr_info("select is configured %s\n", tmp); - - if (!strcmp(tmp, "disable")) - jdev->select = AMLOGIC_JTAG_DISABLE; - else if (!strcmp(tmp, "apao")) - jdev->select = AMLOGIC_JTAG_APAO; - else if (!strcmp(tmp, "apee")) - jdev->select = AMLOGIC_JTAG_APEE; - else - pr_err("unknown select: %s", tmp); - + jdev->select = name_to_select(tmp); return 0; } - - static int aml_jtag_probe(struct platform_device *pdev) { struct aml_jtag_dev *jdev; int ret; /* kzalloc device */ - jdev = kzalloc(sizeof(struct aml_jtag_dev), GFP_KERNEL); + jdev = devm_kzalloc(&pdev->dev, + sizeof(struct aml_jtag_dev), GFP_KERNEL); /* set driver data */ jdev->pdev = pdev; platform_set_drvdata(pdev, jdev); - ret = aml_jtag_dt_parse(pdev); if (ret) return -EINVAL; @@ -575,12 +447,8 @@ static int aml_jtag_probe(struct platform_device *pdev) if (jtag_select_setup) { jdev->select = jtag_select; jdev->cluster = jtag_cluster; - pr_info("select is replaced by boot param\n"); } - /* save to global */ - global_select = jdev->select; - /* create class attributes */ jdev->cls.name = AML_JTAG_NAME; jdev->cls.owner = THIS_MODULE; @@ -592,26 +460,25 @@ static int aml_jtag_probe(struct platform_device *pdev) } /* setup jtag */ - aml_jtag_setup(jdev); + ret = aml_jtag_setup(jdev); + if (ret < 0) { + class_unregister(&jdev->cls); + return ret; + } - pr_info("module probed ok\n"); return 0; } - static int __exit aml_jtag_remove(struct platform_device *pdev) { struct aml_jtag_dev *jdev = platform_get_drvdata(pdev); class_unregister(&jdev->cls); platform_set_drvdata(pdev, NULL); - kfree(jdev); - pr_info("module removed ok\n"); return 0; } - static const struct of_device_id aml_jtag_dt_match[] = { { .compatible = "amlogic, jtag", @@ -619,7 +486,6 @@ static const struct of_device_id aml_jtag_dt_match[] = { {}, }; - static struct platform_driver aml_jtag_driver = { .driver = { .name = AML_JTAG_NAME, @@ -630,10 +496,8 @@ static struct platform_driver aml_jtag_driver = { .remove = __exit_p(aml_jtag_remove), }; - static int __init aml_jtag_init(void) { - pr_info("module init\n"); if (platform_driver_register(&aml_jtag_driver)) { pr_err("failed to register driver\n"); return -ENODEV; @@ -651,7 +515,6 @@ fs_initcall(aml_jtag_init); static void __exit aml_jtag_exit(void) { - pr_info("module exit\n"); platform_driver_unregister(&aml_jtag_driver); } diff --git a/drivers/amlogic/jtag/meson_jtag.h b/drivers/amlogic/jtag/meson_jtag.h index 41713a601351..1b9556cde650 100644 --- a/drivers/amlogic/jtag/meson_jtag.h +++ b/drivers/amlogic/jtag/meson_jtag.h @@ -27,6 +27,7 @@ struct aml_jtag_dev { struct platform_device *pdev; + struct pinctrl *jtag_pinctrl; struct class cls; #ifdef CONFIG_MACH_MESON8B diff --git a/drivers/amlogic/mailbox/scpi_protocol.c b/drivers/amlogic/mailbox/scpi_protocol.c index 20f05c10b454..cc5f3692d15d 100644 --- a/drivers/amlogic/mailbox/scpi_protocol.c +++ b/drivers/amlogic/mailbox/scpi_protocol.c @@ -60,6 +60,42 @@ enum scpi_error_codes { SCPI_ERR_MAX }; +static int scpi_freq_map_table[] = { + 0, + 0, + 1200, + 1300, + 1400, + 1500, + 1600, + 1700, + 1800, + 1900, + 2000, + 2100, + 2200, + 2300, + 2400, + 0 +}; +static int scpi_volt_map_table[] = { + 0, + 0, + 900, + 910, + 920, + 930, + 940, + 950, + 960, + 970, + 980, + 990, + 1000, + 1010, + 1020, + 0 +}; struct scpi_data_buf { int client_id; @@ -84,6 +120,7 @@ static int high_priority_cmds[] = { SCPI_CMD_SENSOR_CFG_BOUNDS, SCPI_CMD_WAKEUP_REASON_GET, SCPI_CMD_WAKEUP_REASON_CLR, + SCPI_CMD_INIT_DSP, }; static struct scpi_dvfs_info *scpi_opps[MAX_DVFS_DOMAINS]; @@ -520,6 +557,29 @@ int scpi_clr_wakeup_reason(void) } EXPORT_SYMBOL_GPL(scpi_clr_wakeup_reason); +int scpi_init_dsp_cfg0(u32 id, u32 addr, u32 cfg0) +{ + struct scpi_data_buf sdata; + struct mhu_data_buf mdata; + u32 temp = 0; + struct __packed { + u32 id; + u32 addr; + u32 cfg0; + } buf; + buf.id = id; + buf.addr = addr; + buf.cfg0 = cfg0; + + SCPI_SETUP_DBUF(sdata, mdata, SCPI_CL_NONE, + SCPI_CMD_INIT_DSP, buf, temp); + if (scpi_execute_cmd(&sdata)) + return -EPERM; + + return 0; +} +EXPORT_SYMBOL_GPL(scpi_init_dsp_cfg0); + int scpi_get_cec_val(enum scpi_std_cmd index, u32 *p_cec) { struct scpi_data_buf sdata; @@ -559,3 +619,55 @@ u8 scpi_get_ethernet_calc(void) return buf.eth_calc; } EXPORT_SYMBOL_GPL(scpi_get_ethernet_calc); + +int scpi_get_cpuinfo(enum scpi_get_pfm_type type, u32 *freq, u32 *vol) +{ + struct scpi_data_buf sdata; + struct mhu_data_buf mdata; + u8 index = 0; + int ret; + + struct __packed { + u32 status; + u8 pfm_info[4]; + } buf; + + SCPI_SETUP_DBUF(sdata, mdata, SCPI_CL_NONE, + SCPI_CMD_GET_CPUINFO, index, buf); + if (scpi_execute_cmd(&sdata)) + return -EPERM; + + switch (type) { + case SCPI_CPUINFO_VERSION: + ret = buf.pfm_info[0]; + break; + case SCPI_CPUINFO_CLUSTER0: + index = (buf.pfm_info[1] >> 4) & 0xf; + *freq = scpi_freq_map_table[index]; + index = buf.pfm_info[1] & 0xf; + *vol = scpi_volt_map_table[index]; + ret = 0; + break; + case SCPI_CPUINFO_CLUSTER1: + index = (buf.pfm_info[2] >> 4) & 0xf; + *freq = scpi_freq_map_table[index]; + index = buf.pfm_info[2] & 0xf; + *vol = scpi_volt_map_table[index]; + ret = 0; + break; + case SCPI_CPUINFO_SLT: + index = (buf.pfm_info[3] >> 4) & 0xf; + *freq = scpi_freq_map_table[index]; + index = buf.pfm_info[3] & 0xf; + *vol = scpi_volt_map_table[index]; + ret = 0; + break; + default: + *freq = 0; + *vol = 0; + ret = -1; + break; + }; + return ret; +} +EXPORT_SYMBOL_GPL(scpi_get_cpuinfo); diff --git a/drivers/amlogic/media/camera/common/vm.c b/drivers/amlogic/media/camera/common/vm.c index b5ceeabd83ff..c994df2a3fec 100644 --- a/drivers/amlogic/media/camera/common/vm.c +++ b/drivers/amlogic/media/camera/common/vm.c @@ -1635,9 +1635,22 @@ static int simulate_task(void *data) *********************************************** */ -int alloc_vm_canvas(struct vm_device_s *vdevp) +int vm_buffer_init(struct vm_device_s *vdevp) { - int j; + int i, j; + u32 canvas_width, canvas_height; + u32 decbuf_size; + resource_size_t buf_start; + unsigned int buf_size; + int buf_num = 0; + int local_pool_size = 0; + + init_completion(&vdevp->vb_start_sema); + init_completion(&vdevp->vb_done_sema); + + buf_start = vdevp->buffer_start; + buf_size = vdevp->buffer_size; + if (vdevp->index == 0) { for (j = 0; j < MAX_CANVAS_INDEX; j++) { memset(&(vdevp->vm_canvas[j]), -1, sizeof(int)); @@ -1660,25 +1673,6 @@ int alloc_vm_canvas(struct vm_device_s *vdevp) } } - return 0; -} - -int vm_buffer_init(struct vm_device_s *vdevp) -{ - int i; - u32 canvas_width, canvas_height; - u32 decbuf_size; - resource_size_t buf_start; - unsigned int buf_size; - int buf_num = 0; - int local_pool_size = 0; - - init_completion(&vdevp->vb_start_sema); - init_completion(&vdevp->vb_done_sema); - - buf_start = vdevp->buffer_start; - buf_size = vdevp->buffer_size; - if (!buf_start || !buf_size) goto exit; @@ -2205,11 +2199,6 @@ static int vm_driver_probe(struct platform_device *pdev) vm_device[vdevp->index] = vdevp; vdevp->pdev = pdev; platform_set_drvdata(pdev, vdevp); - ret = alloc_vm_canvas(vdevp); - if (ret != 0) { - pr_err("alloc vm canvas failed\n"); - return ret; - } vm_buffer_init(vdevp); ret = init_vm_device(vdevp, pdev); if (ret != 0) diff --git a/drivers/amlogic/media/camera/common/vm.h b/drivers/amlogic/media/camera/common/vm.h index 9c297e25da7f..50305fcde63e 100644 --- a/drivers/amlogic/media/camera/common/vm.h +++ b/drivers/amlogic/media/camera/common/vm.h @@ -95,7 +95,6 @@ struct display_frame_s { int start_vm_task(struct vm_device_s *vdevp); int start_simulate_task(void); -int alloc_vm_canvas(struct vm_device_s *vdevp); extern int get_vm_status(void); extern void set_vm_status(int flag); diff --git a/drivers/amlogic/media/camera/gc2145.c b/drivers/amlogic/media/camera/gc2145.c index b194a8577078..3150faf2663b 100644 --- a/drivers/amlogic/media/camera/gc2145.c +++ b/drivers/amlogic/media/camera/gc2145.c @@ -503,8 +503,7 @@ static struct v4l2_frmsize_discrete static struct v4l2_frmsize_discrete gc2145_pic_resolution[] = { {1600, 1200}, - {800, 600}, - {640, 480} + {800, 600} }; #ifndef GC2145_MIRROR @@ -1819,23 +1818,23 @@ void GC2145_set_resolution(struct gc2145_device *dev, int height, int width) if ((width * height < 1600 * 1200)) { while (1) { - buf[0] = gc2145_uxga[i].addr; - buf[1] = gc2145_uxga[i].val; - if (gc2145_uxga[i].val == 0xff && - gc2145_uxga[i].addr == 0xff) { - pr_info("success in gc2145_uxga.\n"); + buf[0] = gc2145_svga[i].addr; + buf[1] = gc2145_svga[i].val; + if (gc2145_svga[i].val == 0xff && + gc2145_svga[i].addr == 0xff) { + pr_info("success in gc2145_svga.\n"); break; } if ((i2c_put_byte_add8(client, buf, 2)) < 0) { - pr_err("fail in gc2145_uxga.\n"); + pr_err("fail in gc2145_svga.\n"); return; } i++; } gc2145_frmintervals_active.numerator = 1; gc2145_frmintervals_active.denominator = 15; - GC2145_h_active = 1600; - GC2145_v_active = 1200; + GC2145_h_active = 800; + GC2145_v_active = 600; mdelay(80); } else if (width * height >= 1200 * 1600) { buf[0] = 0xfe; @@ -3404,7 +3403,6 @@ static int gc2145_probe(struct i2c_client *client, pr_err("Create class gc2145 fail.\n"); return -ENOMEM; } - gc2145_dev = device_create(gc2145_class, NULL, MKDEV(0, 1), NULL, "dev"); device_create_file(gc2145_dev, &dev_attr_gc2145); diff --git a/drivers/amlogic/media/common/arch/registers/register_map.c b/drivers/amlogic/media/common/arch/registers/register_map.c index e333b065d2fb..390d0dbee951 100644 --- a/drivers/amlogic/media/common/arch/registers/register_map.c +++ b/drivers/amlogic/media/common/arch/registers/register_map.c @@ -51,7 +51,7 @@ enum { static void __iomem *codecio_reg_map[CODECIO_BUS_MAX]; -static int codecio_reg_read(u32 bus_type, unsigned int reg, unsigned int *val) +static inline int codecio_reg_read(u32 bus_type, u32 reg, u32 *val) { if (bus_type < CODECIO_BUS_MAX) { if (codecio_reg_map[bus_type] == NULL) { @@ -65,7 +65,7 @@ static int codecio_reg_read(u32 bus_type, unsigned int reg, unsigned int *val) return -1; } -static int codecio_reg_write(u32 bus_type, unsigned int reg, unsigned int val) +static inline int codecio_reg_write(u32 bus_type, u32 reg, u32 val) { if (bus_type < CODECIO_BUS_MAX) { if (codecio_reg_map[bus_type] == NULL) { diff --git a/drivers/amlogic/media/common/arch/registers/register_ops_m8.c b/drivers/amlogic/media/common/arch/registers/register_ops_m8.c index 2d51a44ba976..a0323e574d6a 100644 --- a/drivers/amlogic/media/common/arch/registers/register_ops_m8.c +++ b/drivers/amlogic/media/common/arch/registers/register_ops_m8.c @@ -32,6 +32,8 @@ MESON_CPU_MAJOR_ID_G12A, \ MESON_CPU_MAJOR_ID_G12B, \ MESON_CPU_MAJOR_ID_TL1, \ + MESON_CPU_MAJOR_ID_SM1, \ + MESON_CPU_MAJOR_ID_TM2, \ 0} #define REGISTER_FOR_GXCPU {\ MESON_CPU_MAJOR_ID_GXBB, \ @@ -44,21 +46,9 @@ MESON_CPU_MAJOR_ID_G12A, \ MESON_CPU_MAJOR_ID_G12B, \ MESON_CPU_MAJOR_ID_TL1, \ + MESON_CPU_MAJOR_ID_SM1, \ + MESON_CPU_MAJOR_ID_TM2, \ 0} -int codec_apb_read(unsigned int reg) -{ - unsigned int val = 0; - - aml_reg_read(IO_APB_BUS_BASE, reg << 2, &val); - return val; -} -EXPORT_SYMBOL(codec_apb_read); - -void codec_apb_write(unsigned int reg, unsigned int val) -{ - aml_reg_write(IO_APB_BUS_BASE, reg << 2, val); -} -EXPORT_SYMBOL(codec_apb_write); static struct chip_register_ops m8_ops[] __initdata = { {IO_DOS_BUS, 0, codecio_read_dosbus, codecio_write_dosbus}, diff --git a/drivers/amlogic/media/common/canvas/canvas_mgr.c b/drivers/amlogic/media/common/canvas/canvas_mgr.c index 56ab75ddb3c3..db416df15659 100644 --- a/drivers/amlogic/media/common/canvas/canvas_mgr.c +++ b/drivers/amlogic/media/common/canvas/canvas_mgr.c @@ -375,7 +375,7 @@ canvas_pool_map_show(struct class *class, int ret; int i; ssize_t size = 0; - struct canvas_info info; + struct canvas_info info = {NULL, 0, NULL, 0}; struct canvas_s canvas; if (jiffies - pool->last_cat_map > 5 * HZ) { diff --git a/drivers/amlogic/media/common/codec_mm/codec_mm.c b/drivers/amlogic/media/common/codec_mm/codec_mm.c index c6dabedcb13f..33466a84ceaa 100644 --- a/drivers/amlogic/media/common/codec_mm/codec_mm.c +++ b/drivers/amlogic/media/common/codec_mm/codec_mm.c @@ -326,44 +326,40 @@ static void *codec_mm_search_vaddr(unsigned long phy_addr) u8 *codec_mm_vmap(ulong addr, u32 size) { u8 *vaddr = NULL; - ulong phys = addr; - u32 offset = phys & ~PAGE_MASK; - u32 npages = PAGE_ALIGN(size) / PAGE_SIZE; struct page **pages = NULL; - pgprot_t pgprot; - int i; + u32 i, npages, offset = 0; + ulong phys, page_start; + pgprot_t pgprot = PAGE_KERNEL; - if (!PageHighMem(phys_to_page(phys))) - return phys_to_virt(phys); + if (!PageHighMem(phys_to_page(addr))) + return phys_to_virt(addr); - if (offset) - npages++; + offset = offset_in_page(addr); + page_start = addr - offset; + npages = DIV_ROUND_UP(size + offset, PAGE_SIZE); - pages = vmalloc(sizeof(struct page *) * npages); + pages = kmalloc_array(npages, sizeof(struct page *), GFP_KERNEL); if (!pages) return NULL; for (i = 0; i < npages; i++) { - pages[i] = phys_to_page(phys); - phys += PAGE_SIZE; + phys = page_start + i * PAGE_SIZE; + pages[i] = pfn_to_page(phys >> PAGE_SHIFT); } - /*nocache*/ - pgprot = pgprot_writecombine(PAGE_KERNEL); - vaddr = vmap(pages, npages, VM_MAP, pgprot); if (!vaddr) { pr_err("the phy(%lx) vmaped fail, size: %d\n", - addr - offset, npages << PAGE_SHIFT); - vfree(pages); + page_start, npages << PAGE_SHIFT); + kfree(pages); return NULL; } - vfree(pages); + kfree(pages); if (debug_mode & 0x20) { pr_info("[HIGH-MEM-MAP] %s, pa(%lx) to va(%p), size: %d\n", - __func__, addr, vaddr + offset, npages << PAGE_SHIFT); + __func__, page_start, vaddr, npages << PAGE_SHIFT); } return vaddr + offset; @@ -374,7 +370,8 @@ void codec_mm_unmap_phyaddr(u8 *vaddr) { void *addr = (void *)(PAGE_MASK & (ulong)vaddr); - vunmap(addr); + if (is_vmalloc_or_module_addr(vaddr)) + vunmap(addr); } EXPORT_SYMBOL(codec_mm_unmap_phyaddr); @@ -874,14 +871,20 @@ void codec_mm_dma_flush(void *vaddr, phy_addr = page_to_phys(vmalloc_to_page(vaddr)) + offset_in_page(vaddr); if (phy_addr && PageHighMem(phys_to_page(phy_addr))) - flush_cache_vunmap(phy_addr, phy_addr + size); + dma_sync_single_for_device(mgt->dev, + phy_addr, size, dir); return; } /* only apply to the lowmem. */ dma_addr = dma_map_single(mgt->dev, vaddr, size, dir); - if (dma_addr) - dma_unmap_single(mgt->dev, dma_addr, size, dir); + if (dma_mapping_error(mgt->dev, dma_addr)) { + pr_err("dma map %d bytes error\n", size); + return; + } + + dma_sync_single_for_device(mgt->dev, dma_addr, size, dir); + dma_unmap_single(mgt->dev, dma_addr, size, dir); } EXPORT_SYMBOL(codec_mm_dma_flush); @@ -1099,8 +1102,14 @@ int codec_mm_extpool_pool_alloc( CODEC_MM_FLAGS_FOR_LOCAL_MGR | CODEC_MM_FLAGS_CMA); if (mem) { + struct page *mm = mem->mem_handle; + + if (mem->from_flags == + AMPORTS_MEM_FLAGS_FROM_GET_FROM_CMA_RES) + mm = phys_to_page( + (unsigned long)mm); if (for_tvp) { - cma_mmu_op(mem->mem_handle, + cma_mmu_op(mm, mem->page_count, 0); } @@ -1109,7 +1118,7 @@ int codec_mm_extpool_pool_alloc( mem); if (ret < 0) { if (for_tvp) { - cma_mmu_op(mem->mem_handle, + cma_mmu_op(mm, mem->page_count, 1); } @@ -1160,7 +1169,13 @@ static int codec_mm_extpool_pool_release(struct extpool_mgt_s *tvp_pool) slot_mem_size = gen_pool_size(gpool); gen_pool_destroy(tvp_pool->gen_pool[i]); if (tvp_pool->mm[i]) { - cma_mmu_op(tvp_pool->mm[i]->mem_handle, + struct page *mm = tvp_pool->mm[i]->mem_handle; + + if (tvp_pool->mm[i]->from_flags == + AMPORTS_MEM_FLAGS_FROM_GET_FROM_CMA_RES) + mm = phys_to_page( + (unsigned long)mm); + cma_mmu_op(mm, tvp_pool->mm[i]->page_count, 1); codec_mm_release(tvp_pool->mm[i], diff --git a/drivers/amlogic/media/common/codec_mm/codec_mm_scatter.c b/drivers/amlogic/media/common/codec_mm/codec_mm_scatter.c index f36336aa9a0d..82edec1efbc3 100644 --- a/drivers/amlogic/media/common/codec_mm/codec_mm_scatter.c +++ b/drivers/amlogic/media/common/codec_mm/codec_mm_scatter.c @@ -43,6 +43,8 @@ #include "codec_mm_priv.h" #include "codec_mm_scatter_priv.h" +#include + #define SCATTER_MEM "SCATTER_MEM" @@ -175,10 +177,21 @@ struct codec_mm_scatter_mgt { int alloc_1_10ms_cnt; int alloc_10_100ms_cnt; int alloc_100ms_up_cnt; +/*free time states*/ + int free_max_us; + u64 free_total_us; + int free_cnt; + int free_10us_less_cnt; + int free_10_50us_cnt; + int free_50_100us_cnt; + int free_100_1000us_cnt; + int free_1_10ms_cnt; + int free_10_100ms_cnt; + int free_100ms_up_cnt; struct delayed_work dealy_work; int scatter_task_run_num; - struct codec_mm_scatter *cache_sc; + struct codec_mm_scatter *cache_scs[2]; int cached_pages; spinlock_t list_lock; struct mutex monitor_lock; @@ -187,6 +200,8 @@ struct codec_mm_scatter_mgt { struct list_head scatter_list; /*scatter list */ struct codec_mm_scatter *scmap[MAX_SC_LIST];/*used for valid check. */ }; +#define is_cache_sc(smgt, mms) ((smgt->cache_scs[0] == mms) ||\ + (smgt->cache_scs[1] == mms)) static struct codec_mm_scatter_s g_scatter; static struct codec_mm_scatter_mgt *scatter_mgt; @@ -272,6 +287,12 @@ static inline void codec_mm_scatter_lock( { mutex_lock(&mms->mutex); } +static inline int codec_mm_scatter_trylock( + struct codec_mm_scatter *mms) +{ + return mutex_trylock(&mms->mutex); +} + static inline void codec_mm_list_lock( struct codec_mm_scatter_mgt *smgt) { @@ -365,6 +386,39 @@ static void codec_mm_update_alloc_time( } } +static void codec_mm_update_free_time( + struct codec_mm_scatter_mgt *smgt, u64 startus) +{ + int spend_time_us; + + spend_time_us = (int)(codec_mm_get_current_us() - startus); + if (spend_time_us > 0 && spend_time_us < 100000000) { + /* >0 && less than 100s*/ + /*else think time base changed.*/ + smgt->free_cnt++; + if (spend_time_us < 10) + smgt->free_10us_less_cnt++; + else if (spend_time_us < 50) + smgt->free_10_50us_cnt++; + else if (spend_time_us < 100) + smgt->free_50_100us_cnt++; + else if (spend_time_us < 1000) + smgt->free_100_1000us_cnt++; + else if (spend_time_us < 10000) + smgt->free_1_10ms_cnt++; + else if (spend_time_us < 100000) + smgt->free_10_100ms_cnt++; + else + smgt->free_100ms_up_cnt++; + + smgt->free_total_us += spend_time_us; + if (spend_time_us > smgt->free_max_us) { + /*..*/ + smgt->free_max_us = spend_time_us; + } + } +} + static void codec_mm_clear_alloc_infos_in( struct codec_mm_scatter_mgt *smgt) { @@ -378,6 +432,17 @@ static void codec_mm_clear_alloc_infos_in( smgt->alloc_100ms_up_cnt = 0; smgt->alloc_total_us = 0; smgt->alloc_max_us = 0; + + smgt->free_cnt = 0; + smgt->free_10us_less_cnt = 0; + smgt->free_10_50us_cnt = 0; + smgt->free_50_100us_cnt = 0; + smgt->free_100_1000us_cnt = 0; + smgt->free_1_10ms_cnt = 0; + smgt->free_10_100ms_cnt = 0; + smgt->free_100ms_up_cnt = 0; + smgt->free_total_us = 0; + smgt->free_max_us = 0; } void codec_mm_clear_alloc_infos(void) { @@ -1022,19 +1087,60 @@ static int codec_mm_page_alloc_from_slot( return alloced; } +/*flags & 1; alloc.*/ +static struct codec_mm_scatter *codec_mm_get_next_cache_scatter( + struct codec_mm_scatter_mgt *smgt, + struct codec_mm_scatter *cur_mms, + int flags) +{ + struct codec_mm_scatter *mms = NULL; + + codec_mm_list_lock(smgt); + if (cur_mms) { + if (smgt->cache_scs[0] == cur_mms) + mms = smgt->cache_scs[1]; + else + mms = smgt->cache_scs[0]; + } else if (smgt->cache_scs[0] && smgt->cache_scs[1]) { + int more_pages = flags & 1; + int id = -1; + + if (smgt->cache_scs[0]->page_cnt >= + smgt->cache_scs[1]->page_cnt) + id = more_pages ? 0 : 1; + else + id = more_pages ? 1 : 0; + mms = smgt->cache_scs[id]; + } else { + if (smgt->cache_scs[0]) + mms = smgt->cache_scs[0]; + else + mms = smgt->cache_scs[1]; + } + codec_mm_list_unlock(smgt); + return mms; +} + static int codec_mm_page_alloc_from_free_scatter( struct codec_mm_scatter_mgt *smgt, - phy_addr_type *pages, int num) + struct codec_mm_scatter *src_mms, + phy_addr_type *pages, int num, int wait) { struct codec_mm_scatter *mms; int need = num; int alloced = 0; - mms = smgt->cache_sc; + mms = src_mms; if (!mms) return 0; - codec_mm_scatter_lock(mms); + ATRACE_COUNTER("mmu alloc", MMU_ALLOC_from_cache_scatter_1); + if (!wait) { + if (!codec_mm_scatter_trylock(mms)) + return 0;/*mms is locked try another.*/ + } else + codec_mm_scatter_lock(mms); + ATRACE_COUNTER("mmu alloc", MMU_ALLOC_from_cache_scatter_2); alloced = min(mms->page_cnt, need); if (alloced > 0) { mms->page_cnt -= alloced; @@ -1053,13 +1159,35 @@ static int codec_mm_page_alloc_from_free_scatter( memset(&mms->pages_list[mms->page_tail + 1], 0, alloced * sizeof(phy_addr_type)); } + ATRACE_COUNTER("mmu alloc", MMU_ALLOC_from_cache_scatter_3); codec_mm_list_lock(smgt); - smgt->cached_pages = mms->page_cnt; + ATRACE_COUNTER("mmu alloc", MMU_ALLOC_from_cache_scatter_4); + smgt->cached_pages -= alloced; codec_mm_list_unlock(smgt); codec_mm_scatter_unlock(mms); + ATRACE_COUNTER("mmu alloc", MMU_ALLOC_from_cache_scatter_5); return alloced; } +static int codec_mm_page_alloc_from_cache_scatter( + struct codec_mm_scatter_mgt *smgt, + phy_addr_type *pages, int num) +{ + struct codec_mm_scatter *src_mms; + int alloced; + + src_mms = codec_mm_get_next_cache_scatter(smgt, NULL, 1); + alloced = codec_mm_page_alloc_from_free_scatter(smgt, + src_mms, pages, num, 0); + if (alloced < num) { + src_mms = codec_mm_get_next_cache_scatter(smgt, src_mms, 1); + alloced += codec_mm_page_alloc_from_free_scatter(smgt, + src_mms, &pages[alloced], num - alloced, 1); + } + return alloced; +} + + static int codec_mm_page_alloc_all_locked( struct codec_mm_scatter_mgt *smgt, phy_addr_type *pages, int num, int iscache) @@ -1072,17 +1200,25 @@ static int codec_mm_page_alloc_all_locked( while (alloced < num) { new_alloc = 0; if (can_from_scatter) { - new_alloc = codec_mm_page_alloc_from_free_scatter( + ATRACE_COUNTER("mmu alloc", + MMU_ALLOC_from_free_scatter); + new_alloc = codec_mm_page_alloc_from_cache_scatter( smgt, pages + alloced, num - alloced); + ATRACE_COUNTER("mmu alloc", + MMU_ALLOC_from_free_scatter_end); if (new_alloc <= 0) can_from_scatter = 0; } else if (can_from_slot) { + ATRACE_COUNTER("mmu alloc", + MMU_ALLOC_from_slot); new_alloc = codec_mm_page_alloc_from_slot( smgt, pages + alloced, num - alloced); + ATRACE_COUNTER("mmu alloc", + MMU_ALLOC_from_slot_end); if (new_alloc <= 0) can_from_slot = 0; } else if (!smgt->no_alloc_from_sys && !smgt->tvp_mode) { @@ -1102,18 +1238,24 @@ static int codec_mm_page_alloc_all_locked( static int codec_mm_pages_free_to_scatter( struct codec_mm_scatter_mgt *smgt, - struct codec_mm_scatter *src_mms) + struct codec_mm_scatter *src_mms, + struct codec_mm_scatter *dst_mms, + int wait) { - struct codec_mm_scatter *dst_mms; int moved = 0; int left; if (src_mms->page_used >= src_mms->page_cnt) return -1; /*no need free. */ - dst_mms = smgt->cache_sc; if (!dst_mms || src_mms == dst_mms) return 0; - codec_mm_scatter_lock(dst_mms); + ATRACE_COUNTER("mmu_free", MMU_FREE_SCATTER_START_DTS); + if (!wait) { + if (!codec_mm_scatter_trylock(dst_mms)) + return -2;/*mms is locked try another.*/ + } else + codec_mm_scatter_lock(dst_mms); + ATRACE_COUNTER("mmu_free", MMU_FREE_SCATTER_START_DTS_LOCK); moved = min(src_mms->page_cnt - src_mms->page_used, dst_mms->page_max_cnt - dst_mms->page_cnt); left = src_mms->page_cnt - moved; @@ -1128,13 +1270,34 @@ static int codec_mm_pages_free_to_scatter( dst_mms->page_tail += moved; src_mms->page_cnt -= moved; src_mms->page_tail -= moved; + ATRACE_COUNTER("mmu_free", MMU_FREE_SCATTER_START_SMGT); codec_mm_list_lock(smgt); - smgt->cached_pages = dst_mms->page_cnt; + ATRACE_COUNTER("mmu_free", MMU_FREE_SCATTER_START_SMGT_LOCK); + smgt->cached_pages += moved; codec_mm_list_unlock(smgt); + ATRACE_COUNTER("mmu_free", MMU_FREE_SCATTER_START_SMGT_LOCK_DONE); codec_mm_scatter_unlock(dst_mms); + ATRACE_COUNTER("mmu_free", MMU_FREE_SCATTER_START_DTS_LOCK_DONE); return moved; } +static int codec_mm_page_free_to_cache_scatter( + struct codec_mm_scatter_mgt *smgt, + struct codec_mm_scatter *src_mms) +{ + struct codec_mm_scatter *dst_mms; + int alloced; + + dst_mms = codec_mm_get_next_cache_scatter(smgt, NULL, 0); + alloced = codec_mm_pages_free_to_scatter(smgt, src_mms, + dst_mms, 0); + if (alloced == -2) { + dst_mms = codec_mm_get_next_cache_scatter(smgt, dst_mms, 0); + alloced += codec_mm_pages_free_to_scatter(smgt, src_mms, + dst_mms, 1); + } + return alloced; +} /* @@ -1206,8 +1369,8 @@ static int codec_mm_scatter_free_pages_in_locked( } codec_mm_list_lock(smgt); smgt->alloced_page_num -= freeNum; - if (smgt->cache_sc == mms) - smgt->cached_pages = mms->page_cnt; + if (is_cache_sc(smgt, mms)) + smgt->cached_pages -= freeNum; codec_mm_list_unlock(smgt); return 0; } @@ -1235,7 +1398,9 @@ static int codec_mm_scatter_free_tail_pages_in( if (!mms) return -1; + ATRACE_COUNTER("mmu_free", MMU_FREE_SCATTER_START); codec_mm_scatter_lock(mms); + ATRACE_COUNTER("mmu_free", MMU_FREE_SCATTER_START_LOCK); if (free_mode == 1) start_free_id = mms->page_used; if (free_mode == 2) { @@ -1262,6 +1427,7 @@ static int codec_mm_scatter_free_tail_pages_in( free_mode); } codec_mm_scatter_unlock(mms); + ATRACE_COUNTER("mmu_free", MMU_FREE_SCATTER_START_LOCK_DONE); return -1; } smgt = (struct codec_mm_scatter_mgt *)mms->manager; @@ -1271,17 +1437,25 @@ static int codec_mm_scatter_free_tail_pages_in( if (fast_mode == 1) { codec_mm_scatter_unlock(mms); + ATRACE_COUNTER("mmu_free", MMU_FREE_SCATTER_START_LOCK_DONE); return 0; } if (fast_mode == 2 || fast_mode == 3) { - codec_mm_pages_free_to_scatter(smgt, mms); + u64 startus; + + startus = codec_mm_get_current_us(); + codec_mm_page_free_to_cache_scatter(smgt, mms); + codec_mm_update_free_time(smgt, startus); if (fast_mode == 2 || mms->page_used == mms->page_cnt) { codec_mm_scatter_unlock(mms); + ATRACE_COUNTER("mmu_free", + MMU_FREE_SCATTER_START_LOCK_DONE); return 0; } } codec_mm_scatter_free_pages_in_locked(mms, start_free_id); codec_mm_scatter_unlock(mms); + ATRACE_COUNTER("mmu_free", MMU_FREE_SCATTER_START_LOCK_DONE); return 0; } @@ -1469,7 +1643,7 @@ static int codec_mm_scatter_inc_user_in1( if (old_user >= 0) { ret = atomic_add_return(cnt, &mms->user_cnt); if (old_user == 1) - mms->tofree_jiffies = 0; + mms->tofree_jiffies = jiffies; } codec_mm_list_unlock(smgt); return ret <= 0 ? ret : 0; /*must add before user cnt >= 0 */ @@ -1513,13 +1687,8 @@ static int codec_mm_scatter_dec_user_in1( after_users = atomic_sub_return(cnt, &mms->user_cnt); if (after_users == 0) { /*is free time*/ - if (delay_free_ms > 0) - mms->tofree_jiffies = jiffies + - delay_free_ms * HZ/1000; - else { - mms->page_used = 0; - mms->tofree_jiffies = 0; - } + mms->tofree_jiffies = jiffies + + delay_free_ms * HZ/1000; } } codec_mm_list_unlock(smgt); @@ -1622,7 +1791,7 @@ struct codec_mm_scatter *codec_mm_scatter_alloc_new( if (page_num > 0) { ret = codec_mm_page_alloc_all_locked(smgt, mms->pages_list, page_num, - mms == smgt->cache_sc); + is_cache_sc(smgt, mms)); if (ret <= 0) goto error; mms->page_cnt = ret; @@ -1662,7 +1831,9 @@ struct codec_mm_scatter *codec_mm_scatter_alloc( smgt = codec_mm_get_scatter_mgt(istvp); startus = codec_mm_get_current_us(); alloced_mms = NULL; + ATRACE_COUNTER("mmu alloc", MMU_ALLOC_SCATTER_START); codec_mm_list_lock(smgt); + ATRACE_COUNTER("mmu alloc", MMU_ALLOC_SCATTER_START_LOCK); if (!list_empty(&smgt->scatter_list)) { /*try find a free scatter. */ pos = smgt->scatter_list.prev; /*free on prev. */ while (pos != &smgt->scatter_list) { @@ -1681,17 +1852,26 @@ struct codec_mm_scatter *codec_mm_scatter_alloc( pos = next; } } + ATRACE_COUNTER("mmu alloc", MMU_ALLOC_SCATTER_START_LOCK_DONE); codec_mm_list_unlock(smgt); if (!alloced_mms) { /* *just alloc mms first, *alloc pages later. */ + ATRACE_COUNTER("mmu alloc", + MMU_ALLOC_SCATTER_ALLOC_NEW); alloced_mms = codec_mm_scatter_alloc_new(smgt, max_page, 0); + ATRACE_COUNTER("mmu alloc", + MMU_ALLOC_SCATTER_ALLOC_NEW_END); } if (alloced_mms) { + ATRACE_COUNTER("mmu alloc", + MMU_ALLOC_SCATTER_ALLOC_WANT_PAGE_IN); ret = codec_mm_scatter_alloc_want_pages_in(smgt, alloced_mms, page_num); + ATRACE_COUNTER("mmu alloc", + MMU_ALLOC_SCATTER_ALLOC_WANT_PAGE_IN_END); if (ret < 0) { atomic_sub(1000, &alloced_mms->user_cnt); return NULL; @@ -1709,20 +1889,22 @@ static int codec_mm_scatter_alloc_want_pages_in( struct codec_mm_scatter *mms, int want_pages) { - int ret; + int ret = 0; if (want_pages > mms->page_max_cnt) return CODEC_MM_S_ERR(100); + ATRACE_COUNTER("mmu alloc", MMU_ALLOC_SCATTER_LOCK); codec_mm_scatter_lock(mms); codec_mm_list_lock(smgt); mms->page_used = want_pages; codec_mm_list_unlock(smgt); + ATRACE_COUNTER("mmu alloc", MMU_ALLOC_SCATTER_LOCK_END); if (want_pages > mms->page_cnt) { ret = codec_mm_page_alloc_all_locked( smgt, &mms->pages_list[mms->page_tail + 1], want_pages - mms->page_cnt, - mms == smgt->cache_sc); + is_cache_sc(smgt, mms)); if (ret <= 0) { codec_mm_scatter_unlock(mms); ERR_LOG("can't alloc want pages %d\n", want_pages); @@ -1731,12 +1913,14 @@ static int codec_mm_scatter_alloc_want_pages_in( mms->page_cnt += ret; mms->page_tail += ret; } - if (mms == smgt->cache_sc) { - codec_mm_list_lock(smgt); - if (smgt->cache_sc)/*update cache pages*/ - smgt->cached_pages = smgt->cache_sc->page_cnt; - codec_mm_list_unlock(smgt); - } + ATRACE_COUNTER("mmu alloc", MMU_ALLOC_LIST_LOCK_START); + codec_mm_list_lock(smgt); + ATRACE_COUNTER("mmu alloc", MMU_ALLOC_LIST_LOCK); + if (ret > 0 && is_cache_sc(smgt, mms)) + smgt->cached_pages += ret; + + codec_mm_list_unlock(smgt); + ATRACE_COUNTER("mmu alloc", MMU_ALLOC_LIST_LOCK_END); codec_mm_scatter_unlock(mms); if (smgt->cached_pages < smgt->keep_size_PAGE / 2) { /*try alloc more cache.*/ @@ -1878,6 +2062,18 @@ static int codec_mm_scatter_info_dump_in( smgt->alloc_10_100ms_cnt, smgt->alloc_100ms_up_cnt ); + BUFPRINT("\tfree time max us:%d\n", + smgt->free_max_us); + BUFPRINT("\tfree cnt:%d step:%d:%d:%d:%d:%d:%d:%d\n", + smgt->free_cnt, + smgt->free_10us_less_cnt, + smgt->free_10_50us_cnt, + smgt->free_50_100us_cnt, + smgt->free_100_1000us_cnt, + smgt->free_1_10ms_cnt, + smgt->free_10_100ms_cnt, + smgt->free_100ms_up_cnt + ); { int average_timeus; u64 divider = smgt->alloc_total_us; @@ -1887,6 +2083,13 @@ static int codec_mm_scatter_info_dump_in( 0 : (int)divider); BUFPRINT("\talloc time average us:%d\n", average_timeus); + divider = smgt->free_total_us; + + do_div(divider, smgt->free_cnt); + average_timeus = (smgt->free_cnt == 0 ? + 0 : (int)divider); + BUFPRINT("\tfree time average us:%d\n", + average_timeus); } #undef BUFPRINT @@ -2173,8 +2376,10 @@ static int codec_mm_dump_all_scatters_in(struct codec_mm_scatter_mgt *smgt) } } while (0); INFO_LOG("start dump free scatters!\n"); - if (smgt->cache_sc) - codec_mm_dump_scatter(smgt->cache_sc, 0, 0); + if (smgt->cache_scs[0]) + codec_mm_dump_scatter(smgt->cache_scs[0], 0, 0); + if (smgt->cache_scs[1]) + codec_mm_dump_scatter(smgt->cache_scs[1], 0, 0); codec_mm_list_unlock(smgt); INFO_LOG("finished dump all scatters!\n"); return 0; @@ -2221,6 +2426,7 @@ int codec_mm_scatter_mgt_delay_free_swith( int is_tvp) { struct codec_mm_scatter_mgt *smgt; +// unsigned long ret = 0; smgt = codec_mm_get_scatter_mgt(is_tvp); codec_mm_list_lock(smgt); @@ -2237,7 +2443,7 @@ int codec_mm_scatter_mgt_delay_free_swith( } } codec_mm_list_unlock(smgt); - if (on && wait_size_M > 0 && !is_tvp) { + if (on && wait_size_M > 0 /*&& !is_tvp*/) { smgt->force_cache_on = 1; smgt->force_cache_page_cnt = wait_size_M >> PAGE_SHIFT; smgt->delay_free_timeout_jiffies64 = @@ -2245,9 +2451,8 @@ int codec_mm_scatter_mgt_delay_free_swith( codec_mm_schedule_delay_work(smgt, 0, 1);/*start cache*/ #if 0 while (smgt->total_page_num < smgt->force_cache_page_cnt) { - if (smgt->cache_sc && - (smgt->cached_pages >= - smgt->cache_sc->page_max_cnt - 100)) { + if (smgt->cache_scs[0] && + (smgt->cached_pages >= 65000)) { /*cache sc fulled.*/ break; } @@ -2303,7 +2508,7 @@ static void codec_mm_scatter_cache_manage( (smgt->force_cache_on &&/*on star cache*/ (smgt->total_page_num < smgt->force_cache_page_cnt)) ) {/*first 500ms ,alloc double.*/ - mms = smgt->cache_sc; + mms = codec_mm_get_next_cache_scatter(smgt, NULL, 0); if (mms) { int need; int once_alloc = 1000;/*once 4M*/ @@ -2326,11 +2531,15 @@ static void codec_mm_scatter_cache_manage( if (need > mms->page_max_cnt) need = mms->page_max_cnt - 4; if (need > mms->page_cnt) { + ATRACE_COUNTER("mmu alloc", + MMU_ALLOC_SCATTER_ALLOC_WANT_PAGE_IN_2); alloced = !codec_mm_scatter_alloc_want_pages_in( smgt, mms, need); + ATRACE_COUNTER("mmu alloc", + MMU_ALLOC_SCATTER_ALLOC_WANT_PAGE_IN_2_END); } else { alloced = 0; } @@ -2351,7 +2560,7 @@ static void codec_mm_scatter_cache_manage( time_after64(get_jiffies_64(), smgt->delay_free_timeout_jiffies64)) { /*wait time out can free.*/ - mms = smgt->cache_sc; + mms = codec_mm_get_next_cache_scatter(smgt, NULL, 0); if (mms) {/*only free some 1M cache*/ codec_mm_scatter_less_pages(mms, 256); @@ -2367,11 +2576,11 @@ static void codec_mm_scatter_cache_manage( } if (smgt->keep_size_PAGE > 0 && smgt->delay_free_on) { if (((smgt->force_cache_on || - (total_free_page < smgt->keep_size_PAGE)) && - !smgt->tvp_mode) && + (total_free_page < smgt->keep_size_PAGE)) /*&&*/ + /*!smgt->tvp_mode*/) && alloced) {/*if failed may deadlock...*/ /*ignore keep on tvp mode.*/ - if (smgt->force_cache_on) + if (smgt->force_cache_on && !smgt->tvp_mode) codec_mm_schedule_delay_work(smgt, 0, 1); else codec_mm_schedule_delay_work(smgt, 10, 0); @@ -2391,26 +2600,43 @@ static int codec_mm_scatter_scatter_arrange( struct list_head *pos, *tmp; int n = 0; - if (smgt->delay_free_on > 0 && !smgt->cache_sc) { - /*no free scatter.*/ + if (smgt->delay_free_on > 0 && !smgt->cache_scs[0]) { + /*cache1*/ mms = codec_mm_scatter_alloc_new(smgt, 16384, 0); if (mms) { codec_mm_list_lock(smgt); list_del_init(&mms->list); - smgt->cache_sc = mms; + smgt->cache_scs[0] = mms; + codec_mm_list_unlock(smgt); + } + /*cache2*/ + mms = codec_mm_scatter_alloc_new(smgt, 16384, 0); + if (mms) { + codec_mm_list_lock(smgt); + list_del_init(&mms->list); + smgt->cache_scs[1] = mms; codec_mm_list_unlock(smgt); } } - if (smgt->delay_free_on <= 0 && smgt->cache_sc && + if (smgt->delay_free_on <= 0 && smgt->cache_scs[0] && time_after64(get_jiffies_64(), smgt->delay_free_timeout_jiffies64)) { + struct codec_mm_scatter *mms0, *mms1; codec_mm_list_lock(smgt); - mms = smgt->cache_sc; - smgt->cache_sc = NULL; + mms0 = smgt->cache_scs[0]; + mms1 = smgt->cache_scs[1]; + smgt->cache_scs[0] = NULL; + smgt->cache_scs[1] = NULL; smgt->cached_pages = 0; codec_mm_list_unlock(smgt); - codec_mm_scatter_dec_owner_user(mms, 0); - codec_mm_scatter_free_on_nouser(smgt, mms); + if (mms0) { + codec_mm_scatter_dec_owner_user(mms0, 0); + codec_mm_scatter_free_on_nouser(smgt, mms0); + } + if (mms1) { + codec_mm_scatter_dec_owner_user(mms1, 0); + codec_mm_scatter_free_on_nouser(smgt, mms1); + } } codec_mm_list_lock(smgt); @@ -2461,6 +2687,7 @@ static int codec_mm_scatter_scatter_clear( break; } } + if ((to_free_mms != NULL) && (((to_free_mms_cnt > 1 || !smgt->delay_free_on) && time_after(jiffies, to_free_mms->tofree_jiffies)) || @@ -2506,8 +2733,9 @@ static int codec_mm_scatter_free_all_ignorecache_in( /*disabled free on first. */ smgt->delay_free_on = 0; codec_mm_list_lock(smgt); - mms = smgt->cache_sc; - smgt->cache_sc = NULL; + mms = smgt->cache_scs[0]; + smgt->cache_scs[0] = smgt->cache_scs[1]; + smgt->cache_scs[1] = NULL; smgt->cached_pages = 0; codec_mm_list_unlock(smgt); if (mms) { @@ -2518,7 +2746,7 @@ static int codec_mm_scatter_free_all_ignorecache_in( } /*alloced again on timer?*/ /* check again. */ - } while (smgt->cache_sc != NULL); + } while (smgt->cache_scs[0] != NULL); do { need_retry = codec_mm_scatter_scatter_clear(smgt, 1); } while ((smgt->scatters_cnt > 0) && (retry_num++ < 1000)); diff --git a/drivers/amlogic/media/common/ge2d/Makefile b/drivers/amlogic/media/common/ge2d/Makefile index 666b3f396535..c5ad76327c0b 100644 --- a/drivers/amlogic/media/common/ge2d/Makefile +++ b/drivers/amlogic/media/common/ge2d/Makefile @@ -5,7 +5,8 @@ ge2d-objs = bitblt.o \ ge2d_wq.o \ stretchblt.o \ ge2d_main.o \ - blend.o + blend.o \ + ge2d_dmabuf.o obj-$(CONFIG_AMLOGIC_MEDIA_GE2D) += ge2d.o ccflags-y += -Iinclude/linux/media/ge2d/ diff --git a/drivers/amlogic/media/common/ge2d/ge2d_dmabuf.c b/drivers/amlogic/media/common/ge2d/ge2d_dmabuf.c new file mode 100644 index 000000000000..3ed7684d1f98 --- /dev/null +++ b/drivers/amlogic/media/common/ge2d/ge2d_dmabuf.c @@ -0,0 +1,682 @@ +/* + * drivers/amlogic/media/common/ge2d/ge2d_dmabuf.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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ge2d_log.h" +#include "ge2d_dmabuf.h" + +static void clear_dma_buffer(struct aml_dma_buffer *buffer, int index); + +static void *aml_mm_vmap(phys_addr_t phys, unsigned long size) +{ + u32 offset, npages; + struct page **pages = NULL; + pgprot_t pgprot = PAGE_KERNEL; + void *vaddr; + int i; + + offset = offset_in_page(phys); + npages = DIV_ROUND_UP(size + offset, PAGE_SIZE); + + pages = vmalloc(sizeof(struct page *) * npages); + if (!pages) + return NULL; + for (i = 0; i < npages; i++) { + pages[i] = phys_to_page(phys); + phys += PAGE_SIZE; + } + /* pgprot = pgprot_writecombine(PAGE_KERNEL); */ + + vaddr = vmap(pages, npages, VM_MAP, pgprot); + if (!vaddr) { + pr_err("vmaped fail, size: %d\n", + npages << PAGE_SHIFT); + vfree(pages); + return NULL; + } + vfree(pages); + ge2d_log_dbg("[HIGH-MEM-MAP] pa(%lx) to va(%p), size: %d\n", + (unsigned long)phys, vaddr, npages << PAGE_SHIFT); + return vaddr; +} + +static void *aml_map_phyaddr_to_virt(dma_addr_t phys, unsigned long size) +{ + void *vaddr = NULL; + + if (!PageHighMem(phys_to_page(phys))) + return phys_to_virt(phys); + vaddr = aml_mm_vmap(phys, size); + return vaddr; +} + +/* dma free*/ +static void aml_dma_put(void *buf_priv) +{ + struct aml_dma_buf *buf = buf_priv; + struct page *cma_pages = NULL; + void *vaddr = (void *)(PAGE_MASK & (ulong)buf->vaddr); + + if (!atomic_dec_and_test(&buf->refcount)) { + ge2d_log_dbg("ge2d aml_dma_put, refcont=%d\n", + atomic_read(&buf->refcount)); + return; + } + cma_pages = phys_to_page(buf->dma_addr); + if (is_vmalloc_or_module_addr(vaddr)) + vunmap(vaddr); + + if (!dma_release_from_contiguous(buf->dev, cma_pages, + buf->size >> PAGE_SHIFT)) { + pr_err("failed to release cma buffer\n"); + } + buf->vaddr = NULL; + clear_dma_buffer((struct aml_dma_buffer *)buf->priv, buf->index); + put_device(buf->dev); + kfree(buf); + ge2d_log_dbg("ge2d free:aml_dma_buf=0x%p,buf->index=%d\n", + buf, buf->index); +} + +static void *aml_dma_alloc(struct device *dev, unsigned long attrs, + unsigned long size, enum dma_data_direction dma_dir, + gfp_t gfp_flags) +{ + struct aml_dma_buf *buf; + struct page *cma_pages = NULL; + dma_addr_t paddr = 0; + + if (WARN_ON(!dev)) + return (void *)(-EINVAL); + + buf = kzalloc(sizeof(struct aml_dma_buf), GFP_KERNEL | gfp_flags); + if (!buf) + return NULL; + + if (attrs) + buf->attrs = attrs; + cma_pages = dma_alloc_from_contiguous(dev, + size >> PAGE_SHIFT, 0); + if (cma_pages) { + paddr = page_to_phys(cma_pages); + } else { + pr_err("failed to alloc cma pages.\n"); + return NULL; + } + buf->vaddr = aml_map_phyaddr_to_virt(paddr, size); + buf->dev = get_device(dev); + buf->size = size; + buf->dma_dir = dma_dir; + buf->dma_addr = paddr; + atomic_inc(&buf->refcount); + ge2d_log_dbg("aml_dma_buf=0x%p, refcont=%d\n", + buf, atomic_read(&buf->refcount)); + + return buf; +} + +static int aml_dma_mmap(void *buf_priv, struct vm_area_struct *vma) +{ + struct aml_dma_buf *buf = buf_priv; + unsigned long pfn = 0; + unsigned long vsize = vma->vm_end - vma->vm_start; + int ret = -1; + + if (!buf || !vma) { + pr_err("No memory to map\n"); + return -EINVAL; + } + + pfn = buf->dma_addr >> PAGE_SHIFT; + ret = remap_pfn_range(vma, vma->vm_start, pfn, + vsize, vma->vm_page_prot); + if (ret) { + pr_err("Remapping memory, error: %d\n", ret); + return ret; + } + vma->vm_flags |= VM_DONTEXPAND; + ge2d_log_dbg("mapped dma addr 0x%08lx at 0x%08lx, size %d\n", + (unsigned long)buf->dma_addr, vma->vm_start, + buf->size); + return 0; +} + +/*********************************************/ +/* DMABUF ops for exporters */ +/*********************************************/ +struct aml_attachment { + struct sg_table sgt; + enum dma_data_direction dma_dir; +}; + +static int aml_dmabuf_ops_attach(struct dma_buf *dbuf, struct device *dev, + struct dma_buf_attachment *dbuf_attach) +{ + struct aml_attachment *attach; + struct aml_dma_buf *buf = dbuf->priv; + int num_pages = PAGE_ALIGN(buf->size) / PAGE_SIZE; + struct sg_table *sgt; + struct scatterlist *sg; + phys_addr_t phys = buf->dma_addr; + unsigned int i; + int ret; + + attach = kzalloc(sizeof(*attach), GFP_KERNEL); + if (!attach) + return -ENOMEM; + + sgt = &attach->sgt; + /* Copy the buf->base_sgt scatter list to the attachment, as we can't + * map the same scatter list to multiple attachments at the same time. + */ + ret = sg_alloc_table(sgt, num_pages, GFP_KERNEL); + if (ret) { + kfree(attach); + return -ENOMEM; + } + for_each_sg(sgt->sgl, sg, sgt->nents, i) { + struct page *page = phys_to_page(phys); + + if (!page) { + sg_free_table(sgt); + kfree(attach); + return -ENOMEM; + } + sg_set_page(sg, page, PAGE_SIZE, 0); + phys += PAGE_SIZE; + } + + attach->dma_dir = DMA_NONE; + dbuf_attach->priv = attach; + + return 0; +} + +static void aml_dmabuf_ops_detach(struct dma_buf *dbuf, + struct dma_buf_attachment *db_attach) +{ + struct aml_attachment *attach = db_attach->priv; + struct sg_table *sgt; + + if (!attach) + return; + + sgt = &attach->sgt; + + /* release the scatterlist cache */ + if (attach->dma_dir != DMA_NONE) + dma_unmap_sg(db_attach->dev, sgt->sgl, sgt->orig_nents, + attach->dma_dir); + sg_free_table(sgt); + kfree(attach); + db_attach->priv = NULL; + +} + +static struct sg_table *aml_dmabuf_ops_map( + struct dma_buf_attachment *db_attach, enum dma_data_direction dma_dir) +{ + struct aml_attachment *attach = db_attach->priv; + /* stealing dmabuf mutex to serialize map/unmap operations */ + struct mutex *lock = &db_attach->dmabuf->lock; + struct sg_table *sgt; + + mutex_lock(lock); + + sgt = &attach->sgt; + /* return previously mapped sg table */ + if (attach->dma_dir == dma_dir) { + mutex_unlock(lock); + return sgt; + } + + /* release any previous cache */ + if (attach->dma_dir != DMA_NONE) { + dma_unmap_sg(db_attach->dev, sgt->sgl, sgt->orig_nents, + attach->dma_dir); + attach->dma_dir = DMA_NONE; + } + /* mapping to the client with new direction */ + sgt->nents = dma_map_sg(db_attach->dev, sgt->sgl, sgt->orig_nents, + dma_dir); + if (!sgt->nents) { + pr_err("failed to map scatterlist\n"); + mutex_unlock(lock); + return (void *)(-EIO); + } + + attach->dma_dir = dma_dir; + + mutex_unlock(lock); + return sgt; +} + +static void aml_dmabuf_ops_unmap(struct dma_buf_attachment *db_attach, + struct sg_table *sgt, enum dma_data_direction dma_dir) +{ + /* nothing to be done here */ +} + +static void aml_dmabuf_ops_release(struct dma_buf *dbuf) +{ + /* drop reference obtained in vb2_dc_get_dmabuf */ + aml_dma_put(dbuf->priv); +} + +static void *aml_dmabuf_ops_kmap(struct dma_buf *dbuf, unsigned long pgnum) +{ + struct aml_dma_buf *buf = dbuf->priv; + + return buf->vaddr ? buf->vaddr + pgnum * PAGE_SIZE : NULL; +} + +static void *aml_dmabuf_ops_vmap(struct dma_buf *dbuf) +{ + struct aml_dma_buf *buf = dbuf->priv; + + return buf->vaddr; +} + +static int aml_dmabuf_ops_mmap(struct dma_buf *dbuf, + struct vm_area_struct *vma) +{ + return aml_dma_mmap(dbuf->priv, vma); +} + +static struct dma_buf_ops ge2d_dmabuf_ops = { + .attach = aml_dmabuf_ops_attach, + .detach = aml_dmabuf_ops_detach, + .map_dma_buf = aml_dmabuf_ops_map, + .unmap_dma_buf = aml_dmabuf_ops_unmap, + .kmap = aml_dmabuf_ops_kmap, + .kmap_atomic = aml_dmabuf_ops_kmap, + .vmap = aml_dmabuf_ops_vmap, + .mmap = aml_dmabuf_ops_mmap, + .release = aml_dmabuf_ops_release, +}; + +static struct dma_buf *get_dmabuf(void *buf_priv, unsigned long flags) +{ + struct aml_dma_buf *buf = buf_priv; + struct dma_buf *dbuf; + DEFINE_DMA_BUF_EXPORT_INFO(exp_info); + + exp_info.ops = &ge2d_dmabuf_ops; + exp_info.size = buf->size; + exp_info.flags = flags; + exp_info.priv = buf; + if (WARN_ON(!buf->vaddr)) + return NULL; + + dbuf = dma_buf_export(&exp_info); + if (IS_ERR(dbuf)) + return NULL; + + /* dmabuf keeps reference to vb2 buffer */ + atomic_inc(&buf->refcount); + ge2d_log_dbg("get_dmabuf, refcount=%d\n", + atomic_read(&buf->refcount)); + return dbuf; +} + +/* ge2d dma-buf api.h*/ +static int find_empty_dma_buffer(struct aml_dma_buffer *buffer) +{ + int i; + int found = 0; + + for (i = 0; i < AML_MAX_DMABUF; i++) { + if (buffer->gd_buffer[i].alloc) + continue; + else { + ge2d_log_dbg("find_empty_dma_buffer i=%d\n", i); + found = 1; + break; + } + } + if (found) + return i; + else + return -1; +} + +static void clear_dma_buffer(struct aml_dma_buffer *buffer, int index) +{ + mutex_lock(&(buffer->lock)); + buffer->gd_buffer[index].mem_priv = NULL; + buffer->gd_buffer[index].index = 0; + buffer->gd_buffer[index].alloc = 0; + mutex_unlock(&(buffer->lock)); +} + +void *ge2d_dma_buffer_create(void) +{ + int i; + struct aml_dma_buffer *buffer; + + buffer = kzalloc(sizeof(*buffer), GFP_KERNEL); + if (!buffer) + return NULL; + + mutex_init(&buffer->lock); + for (i = 0; i < AML_MAX_DMABUF; i++) { + buffer->gd_buffer[i].mem_priv = NULL; + buffer->gd_buffer[i].index = 0; + buffer->gd_buffer[i].alloc = 0; + } + return buffer; +} + +void ge2d_dma_buffer_destroy(struct aml_dma_buffer *buffer) +{ + kfree(buffer); +} + +int ge2d_dma_buffer_alloc(struct aml_dma_buffer *buffer, + struct device *dev, + struct ge2d_dmabuf_req_s *ge2d_req_buf) +{ + void *buf; + struct aml_dma_buf *dma_buf; + unsigned int size; + int index; + + if (WARN_ON(!dev)) + return (-EINVAL); + if (!ge2d_req_buf) + return (-EINVAL); + if (!buffer) + return (-EINVAL); + + size = PAGE_ALIGN(ge2d_req_buf->len); + if (size == 0) + return (-EINVAL); + buf = aml_dma_alloc(dev, 0, size, ge2d_req_buf->dma_dir, + GFP_HIGHUSER | __GFP_ZERO); + if (!buf) + return (-ENOMEM); + mutex_lock(&(buffer->lock)); + index = find_empty_dma_buffer(buffer); + if ((index < 0) || (index >= AML_MAX_DMABUF)) { + pr_err("no empty buffer found\n"); + mutex_unlock(&(buffer->lock)); + aml_dma_put(buf); + return (-ENOMEM); + } + ((struct aml_dma_buf *)buf)->priv = buffer; + ((struct aml_dma_buf *)buf)->index = index; + buffer->gd_buffer[index].mem_priv = buf; + buffer->gd_buffer[index].index = index; + buffer->gd_buffer[index].alloc = 1; + mutex_unlock(&(buffer->lock)); + ge2d_req_buf->index = index; + dma_buf = (struct aml_dma_buf *)buf; + if (dma_buf->dma_dir == DMA_FROM_DEVICE) + dma_sync_single_for_cpu(dma_buf->dev, + dma_buf->dma_addr, + dma_buf->size, DMA_FROM_DEVICE); + return 0; +} + +int ge2d_dma_buffer_free(struct aml_dma_buffer *buffer, int index) +{ + struct aml_dma_buf *buf; + + if (!buffer) + return (-EINVAL); + if ((index < 0) || (index >= AML_MAX_DMABUF)) + return (-EINVAL); + + buf = buffer->gd_buffer[index].mem_priv; + if (!buf) { + pr_err("aml_dma_buf is null\n"); + return (-EINVAL); + } + aml_dma_put(buf); + return 0; +} + +int ge2d_dma_buffer_export(struct aml_dma_buffer *buffer, + struct ge2d_dmabuf_exp_s *ge2d_exp_buf) +{ + struct aml_dma_buf *buf; + struct dma_buf *dbuf; + int ret, index; + unsigned int flags; + + if (!ge2d_exp_buf) + return (-EINVAL); + if (!buffer) + return (-EINVAL); + + index = ge2d_exp_buf->index; + if ((index < 0) || (index >= AML_MAX_DMABUF)) + return (-EINVAL); + + flags = ge2d_exp_buf->flags; + buf = buffer->gd_buffer[index].mem_priv; + if (!buf) { + pr_err("aml_dma_buf is null\n"); + return (-EINVAL); + } + + dbuf = get_dmabuf(buf, flags & O_ACCMODE); + if (IS_ERR_OR_NULL(dbuf)) { + pr_err("failed to export buffer %d\n", index); + return -EINVAL; + } + ret = dma_buf_fd(dbuf, flags & ~O_ACCMODE); + if (ret < 0) { + pr_err("buffer %d, failed to export (%d)\n", + index, ret); + dma_buf_put(dbuf); + return ret; + } + + ge2d_log_dbg("buffer %d,exported as %d descriptor\n", + index, ret); + ge2d_exp_buf->fd = ret; + return 0; +} + +int ge2d_dma_buffer_map(struct aml_dma_cfg *cfg) +{ + long ret = -1; + int fd = -1; + struct dma_buf *dbuf = NULL; + struct dma_buf_attachment *d_att = NULL; + struct sg_table *sg = NULL; + void *vaddr = NULL; + struct device *dev = NULL; + enum dma_data_direction dir; + + if (cfg == NULL || (cfg->fd < 0) || cfg->dev == NULL) { + pr_err("error input param"); + return -EINVAL; + } + fd = cfg->fd; + dev = cfg->dev; + dir = cfg->dir; + + dbuf = dma_buf_get(fd); + if (IS_ERR(dbuf)) { + pr_err("failed to get dma buffer"); + return -EINVAL; + } + + d_att = dma_buf_attach(dbuf, dev); + if (IS_ERR(d_att)) { + pr_err("failed to set dma attach"); + goto attach_err; + } + + sg = dma_buf_map_attachment(d_att, dir); + if (IS_ERR(sg)) { + pr_err("failed to get dma sg"); + goto map_attach_err; + } + + ret = dma_buf_begin_cpu_access(dbuf, dir); + if (ret != 0) { + pr_err("failed to access dma buff"); + goto access_err; + } + + vaddr = dma_buf_vmap(dbuf); + if (vaddr == NULL) { + pr_err("failed to vmap dma buf"); + goto vmap_err; + } + cfg->dbuf = dbuf; + cfg->attach = d_att; + cfg->vaddr = vaddr; + cfg->sg = sg; + ge2d_log_dbg("%s, dbuf=0x%p\n", __func__, dbuf); + return ret; + +vmap_err: + dma_buf_end_cpu_access(dbuf, dir); + +access_err: + dma_buf_unmap_attachment(d_att, sg, dir); + +map_attach_err: + dma_buf_detach(dbuf, d_att); + +attach_err: + dma_buf_put(dbuf); + + return ret; +} + +int ge2d_dma_buffer_get_phys(struct aml_dma_cfg *cfg, unsigned long *addr) +{ + struct sg_table *sg_table; + struct page *page; + int ret; + + ret = ge2d_dma_buffer_map(cfg); + if (ret < 0) { + pr_err("gdc_dma_buffer_map failed\n"); + return ret; + } + if (cfg->sg) { + sg_table = cfg->sg; + page = sg_page(sg_table->sgl); + *addr = PFN_PHYS(page_to_pfn(page)); + ret = 0; + } + return ret; +} + +void ge2d_dma_buffer_unmap(struct aml_dma_cfg *cfg) +{ + int fd = -1; + struct dma_buf *dbuf = NULL; + struct dma_buf_attachment *d_att = NULL; + struct sg_table *sg = NULL; + void *vaddr = NULL; + struct device *dev = NULL; + enum dma_data_direction dir; + + if (cfg == NULL || (cfg->fd < 0) || cfg->dev == NULL + || cfg->dbuf == NULL || cfg->vaddr == NULL + || cfg->attach == NULL || cfg->sg == NULL) { + pr_err("Error input param"); + return; + } + fd = cfg->fd; + dev = cfg->dev; + dir = cfg->dir; + dbuf = cfg->dbuf; + vaddr = cfg->vaddr; + d_att = cfg->attach; + sg = cfg->sg; + + dma_buf_vunmap(dbuf, vaddr); + + dma_buf_end_cpu_access(dbuf, dir); + + dma_buf_unmap_attachment(d_att, sg, dir); + + dma_buf_detach(dbuf, d_att); + + dma_buf_put(dbuf); + + ge2d_log_dbg("%s, dbuf=0x%p\n", __func__, dbuf); +} + +void ge2d_dma_buffer_dma_flush(struct device *dev, int fd) +{ + struct dma_buf *dmabuf; + struct aml_dma_buf *buf; + + ge2d_log_dbg("ge2d_dma_buffer_dma_flush fd=%d\n", fd); + dmabuf = dma_buf_get(fd); + if (IS_ERR(dmabuf)) { + pr_err("dma_buf_get failed\n"); + return; + } + buf = dmabuf->priv; + if (!buf) { + pr_err("error input param"); + return; + } + if ((buf->size > 0) && (buf->dev == dev)) + dma_sync_single_for_device(buf->dev, buf->dma_addr, + buf->size, DMA_TO_DEVICE); + dma_buf_put(dmabuf); +} + +void ge2d_dma_buffer_cache_flush(struct device *dev, int fd) +{ + struct dma_buf *dmabuf; + struct aml_dma_buf *buf; + + ge2d_log_dbg("ge2d_dma_buffer_cache_flush fd=%d\n", fd); + dmabuf = dma_buf_get(fd); + if (IS_ERR(dmabuf)) { + pr_err("dma_buf_get failed\n"); + return; + } + buf = dmabuf->priv; + if (!buf) { + pr_err("error input param"); + return; + } + if ((buf->size > 0) && (buf->dev == dev)) + dma_sync_single_for_cpu(buf->dev, buf->dma_addr, + buf->size, DMA_FROM_DEVICE); + dma_buf_put(dmabuf); +} + + diff --git a/drivers/amlogic/media/common/ge2d/ge2d_dmabuf.h b/drivers/amlogic/media/common/ge2d/ge2d_dmabuf.h new file mode 100644 index 000000000000..c3c03d30bb6a --- /dev/null +++ b/drivers/amlogic/media/common/ge2d/ge2d_dmabuf.h @@ -0,0 +1,81 @@ +/* + * drivers/amlogic/media/common/ge2d/ge2d_dmabuf.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 _GE2D_DMABUF_H_ +#define _GE2D_DMABUF_H_ + +#include +#include +#include + +/* Amlogic Headers */ +#include + +#define AML_MAX_DMABUF 32 + +struct aml_dma_buf { + struct device *dev; + void *cookie; + void *vaddr; + unsigned int size; + enum dma_data_direction dma_dir; + unsigned long attrs; + unsigned int index; + dma_addr_t dma_addr; + atomic_t refcount; + /* DMABUF related */ + struct dma_buf_attachment *db_attach; + void *priv; +}; + +struct aml_dma_buf_priv { + void *mem_priv; + int index; + unsigned int alloc; + struct dma_buf *dbuf; +}; + +struct aml_dma_buffer { + struct mutex lock; + struct aml_dma_buf_priv gd_buffer[AML_MAX_DMABUF]; +}; + +struct aml_dma_cfg { + int fd; + void *dev; + void *vaddr; + struct dma_buf *dbuf; + struct dma_buf_attachment *attach; + struct sg_table *sg; + enum dma_data_direction dir; +}; + + +void *ge2d_dma_buffer_create(void); +void ge2d_dma_buffer_destroy(struct aml_dma_buffer *buffer); +int ge2d_dma_buffer_alloc(struct aml_dma_buffer *buffer, + struct device *dev, + struct ge2d_dmabuf_req_s *ge2d_req_buf); +int ge2d_dma_buffer_free(struct aml_dma_buffer *buffer, int index); +int ge2d_dma_buffer_export(struct aml_dma_buffer *buffer, + struct ge2d_dmabuf_exp_s *ge2d_exp_buf); +int ge2d_dma_buffer_map(struct aml_dma_cfg *cfg); +void ge2d_dma_buffer_unmap(struct aml_dma_cfg *cfg); +int ge2d_dma_buffer_get_phys(struct aml_dma_cfg *cfg, unsigned long *addr); +void ge2d_dma_buffer_dma_flush(struct device *dev, int fd); +void ge2d_dma_buffer_cache_flush(struct device *dev, int fd); +#endif diff --git a/drivers/amlogic/media/common/ge2d/ge2d_hw.c b/drivers/amlogic/media/common/ge2d/ge2d_hw.c index 85d5657f0081..a9eaba3577a9 100644 --- a/drivers/amlogic/media/common/ge2d/ge2d_hw.c +++ b/drivers/amlogic/media/common/ge2d/ge2d_hw.c @@ -798,6 +798,32 @@ void ge2d_set_cmd(struct ge2d_cmd_s *cfg) x_yc_ratio = ge2d_reg_get_bits(GE2D_GEN_CTRL0, 11, 1); y_yc_ratio = ge2d_reg_get_bits(GE2D_GEN_CTRL0, 10, 1); + /* src:yuv , dst: rgb */ + if ((cfg->src1_fmt & GE2D_FORMAT_YUV) && + ((cfg->dst_fmt & GE2D_FORMAT_YUV) == 0)) { + if (x_yc_ratio) { + if ((cfg->src1_x_rev + cfg->dst_x_rev) == 1) { + x_extra_bit_start = 3; + x_extra_bit_end = 2; + x_chr_phase = 0x4c; + } else { + x_extra_bit_start = 2; + x_extra_bit_end = 3; + x_chr_phase = 0xc4; + } + } + if (y_yc_ratio) { + if ((cfg->src1_y_rev + cfg->dst_y_rev) == 1) { + y_extra_bit_start = 3; + y_extra_bit_end = 2; + y_chr_phase = 0x4c; + } else { + y_extra_bit_start = 2; + y_extra_bit_end = 3; + y_chr_phase = 0xc4; + } + } + } else { if (x_yc_ratio) { if ((cfg->src1_x_rev + cfg->dst_x_rev) == 1) { x_extra_bit_start = 3; @@ -820,8 +846,8 @@ void ge2d_set_cmd(struct ge2d_cmd_s *cfg) y_extra_bit_end = 3; y_chr_phase = 0x4c; } + } } - ge2d_reg_write(GE2D_SRC1_X_START_END, (x_extra_bit_start << 30) | /* x start extra */ ((cfg->src1_x_start & 0x3fff) << 16) | @@ -894,29 +920,25 @@ void ge2d_set_cmd(struct ge2d_cmd_s *cfg) cfg->hsc_div_length = (124 << 24) / cfg->hsc_phase_step; multo = cfg->hsc_phase_step * cfg->hsc_div_length; -#ifndef CONFIG_GE2D_ADV_NUM cfg->hsc_adv_num = multo >> 24; -#endif cfg->hsc_adv_phase = multo & 0xffffff; } if (!gaul_filter_used) { rate_w = (widtho * 10) / widthi; rate_h = (heighto * 10) / heighti; - if (rate_w == 10) { + if (rate_h == 10) { /* not scaler case */ - cfg->sc_vsc_en = 1; - cfg->vsc_rpt_l0_num = 1; cfg->vsc_ini_phase = 0; ge2d_reg_set_bits(GE2D_SC_MISC_CTRL, ((0 << 1) | (0 << 0)), 8, 2); - } else if (rate_w < 10) { + } else if (rate_h < 10) { /* scaler down case */ cfg->sc_vsc_en = 1; cfg->vsc_rpt_l0_num = 1; - if (rate_w != 0) + if (rate_h != 0) cfg->vsc_ini_phase = - 0x5000000/rate_w - 0x800000; + 0x5000000/rate_h - 0x800000; else cfg->vsc_ini_phase = 0x5000000; } else { @@ -924,23 +946,21 @@ void ge2d_set_cmd(struct ge2d_cmd_s *cfg) cfg->sc_vsc_en = 1; cfg->vsc_rpt_l0_num = 2; cfg->vsc_ini_phase = - 0x800000 + 0x5000000/rate_w; + 0x800000 + 0x5000000/rate_h; } - if (rate_h == 10) { + if (rate_w == 10) { /* not scaler case */ - cfg->sc_hsc_en = 1; - cfg->hsc_rpt_p0_num = 1; cfg->hsc_ini_phase = 0; ge2d_reg_set_bits(GE2D_SC_MISC_CTRL, ((0 << 1) | (0 << 0)), 8, 2); - } else if (rate_h < 10) { + } else if (rate_w < 10) { /* scaler down case */ cfg->sc_hsc_en = 1; cfg->hsc_rpt_p0_num = 1; - if (rate_h != 0) + if (rate_w != 0) cfg->hsc_ini_phase = - 0x5000000/rate_h - 0x800000; + 0x5000000/rate_w - 0x800000; else cfg->hsc_ini_phase = 0x5000000; } else { @@ -948,7 +968,7 @@ void ge2d_set_cmd(struct ge2d_cmd_s *cfg) cfg->sc_hsc_en = 1; cfg->hsc_rpt_p0_num = 2; cfg->hsc_ini_phase = - 0x800000 + 0x5000000/rate_h; + 0x800000 + 0x5000000/rate_w; } /* expand src1/src2 color with 1 */ ge2d_reg_set_bits(GE2D_GEN_CTRL2, 1, 27, 1); @@ -974,10 +994,12 @@ void ge2d_set_cmd(struct ge2d_cmd_s *cfg) ); if (cfg->hsc_adv_num > 255) cfg->hsc_adv_num = cfg->hsc_adv_num >> 8; + else + cfg->hsc_adv_num = 0; ge2d_reg_write(GE2D_HSC_INI_CTRL, (cfg->hsc_rpt_p0_num << 29) | (cfg->hsc_adv_num << 24) | - (cfg->hsc_ini_phase << 0) + ((cfg->hsc_ini_phase & 0xffffff) << 0) ); #else ge2d_reg_write(GE2D_HSC_ADV_CTRL, @@ -986,7 +1008,7 @@ void ge2d_set_cmd(struct ge2d_cmd_s *cfg) ); ge2d_reg_write(GE2D_HSC_INI_CTRL, (cfg->hsc_rpt_p0_num << 29) | - (cfg->hsc_ini_phase << 0) + ((cfg->hsc_ini_phase & 0xffffff) << 0) ); #endif diff --git a/drivers/amlogic/media/common/ge2d/ge2d_io.h b/drivers/amlogic/media/common/ge2d/ge2d_io.h index 55f5b7505ccc..f5f69df58ca1 100644 --- a/drivers/amlogic/media/common/ge2d/ge2d_io.h +++ b/drivers/amlogic/media/common/ge2d/ge2d_io.h @@ -21,6 +21,8 @@ #include #include #include +#include +#include #include "ge2d_log.h" @@ -129,5 +131,56 @@ static inline void ge2d_reg_set_bits(uint32_t reg, (((value) & ((1L << (len)) - 1)) << (start)))); } +static void ge2d_hiu_setb(unsigned int _reg, unsigned int _value, + unsigned int _start, unsigned int _len) +{ + aml_write_hiubus(_reg, ((aml_read_hiubus(_reg) & + ~(((1L << (_len))-1) << (_start))) | + (((_value)&((1L<<(_len))-1)) << (_start)))); +} +static void ge2d_ao_setb(unsigned int _reg, unsigned int _value, + unsigned int _start, unsigned int _len) +{ + aml_write_aobus(_reg, ((aml_read_aobus(_reg) & + ~(((1L << (_len))-1) << (_start))) | + (((_value)&((1L<<(_len))-1)) << (_start)))); +} + +static void ge2d_c_setb(unsigned int _reg, unsigned int _value, + unsigned int _start, unsigned int _len) +{ + aml_write_cbus(_reg, ((aml_read_cbus(_reg) & + ~(((1L << (_len))-1) << (_start))) | + (((_value)&((1L<<(_len))-1)) << (_start)))); +} + +static inline void ge2d_set_pwr_tbl_bits(unsigned int table_type, + unsigned int reg, unsigned int val, + unsigned int start, unsigned int len) +{ + switch (table_type) { + case CBUS_BASE: + ge2d_c_setb(reg, val, start, len); + break; + case AOBUS_BASE: + ge2d_ao_setb(reg, val, start, len); + break; + case HIUBUS_BASE: + ge2d_hiu_setb(reg, val, start, len); + break; + case GEN_PWR_SLEEP0: + power_ctrl_sleep(val ? 0 : 1, start); + break; + case GEN_PWR_ISO0: + power_ctrl_iso(val ? 0 : 1, start); + break; + case MEM_PD_REG0: + power_ctrl_mempd0(val ? 0 : 1, 0xFF, start); + break; + default: + ge2d_log_err("unsupported bus type\n"); + break; + } +} #endif diff --git a/drivers/amlogic/media/common/ge2d/ge2d_main.c b/drivers/amlogic/media/common/ge2d/ge2d_main.c index 666f675f1e61..6481d9c3cbb8 100644 --- a/drivers/amlogic/media/common/ge2d/ge2d_main.c +++ b/drivers/amlogic/media/common/ge2d/ge2d_main.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #ifdef CONFIG_COMPAT @@ -38,6 +39,7 @@ /* Amlogic Headers */ #include #include +#include #include #include #ifdef CONFIG_AMLOGIC_ION @@ -47,9 +49,12 @@ #include "ge2dgen.h" #include "ge2d_log.h" #include "ge2d_wq.h" +#include "ge2d_dmabuf.h" #define GE2D_CLASS_NAME "ge2d" #define MAX_GE2D_CLK 500000000 +#define HHI_MEM_PD_REG0 0x40 +#define RESET2_LEVEL 0x422 struct ge2d_device_s { char name[20]; @@ -210,6 +215,197 @@ static int ge2d_open(struct inode *inode, struct file *file) return 0; } +static int ge2d_ioctl_config_ex_mem(struct ge2d_context_s *context, + unsigned int cmd, unsigned long args) +{ + struct config_para_ex_memtype_s *ge2d_config_ex_mem; + struct config_ge2d_para_ex_s ge2d_para_config; + int ret = 0; +#ifdef CONFIG_COMPAT + struct compat_config_para_ex_memtype_s __user *uf_ex_mem; + struct compat_config_ge2d_para_ex_s __user *uf_ge2d_para; + int r = 0; + int i, j; +#endif + void __user *argp = (void __user *)args; + + memset(&ge2d_para_config, 0, sizeof(struct config_ge2d_para_ex_s)); + switch (cmd) { + case GE2D_CONFIG_EX_MEM: + ret = copy_from_user(&ge2d_para_config, argp, + sizeof(struct config_ge2d_para_ex_s)); + ge2d_config_ex_mem = &(ge2d_para_config.para_config_memtype); + ret = ge2d_context_config_ex_mem(context, ge2d_config_ex_mem); + break; +#ifdef CONFIG_COMPAT + case GE2D_CONFIG_EX32_MEM: + uf_ge2d_para = (struct compat_config_ge2d_para_ex_s *)argp; + r |= get_user(ge2d_para_config.para_config_memtype.ge2d_magic, + &uf_ge2d_para->para_config_memtype.ge2d_magic); + ge2d_config_ex_mem = &(ge2d_para_config.para_config_memtype); + + if (ge2d_para_config.para_config_memtype.ge2d_magic + == sizeof(struct config_para_ex_memtype_s)) { + struct config_para_ex_ion_s *pge2d_config_ex; + + uf_ex_mem = + (struct compat_config_para_ex_memtype_s *)argp; + pge2d_config_ex = + &(ge2d_config_ex_mem->_ge2d_config_ex); + r = copy_from_user( + &pge2d_config_ex->src_para, + &uf_ex_mem->_ge2d_config_ex.src_para, + sizeof(struct src_dst_para_ex_s)); + r |= copy_from_user( + &pge2d_config_ex->src2_para, + &uf_ex_mem->_ge2d_config_ex.src2_para, + sizeof(struct src_dst_para_ex_s)); + r |= copy_from_user( + &pge2d_config_ex->dst_para, + &uf_ex_mem->_ge2d_config_ex.dst_para, + sizeof(struct src_dst_para_ex_s)); + r |= copy_from_user(&pge2d_config_ex->src_key, + &uf_ex_mem->_ge2d_config_ex.src_key, + sizeof(struct src_key_ctrl_s)); + r |= copy_from_user(&pge2d_config_ex->src2_key, + &uf_ex_mem->_ge2d_config_ex.src2_key, + sizeof(struct src_key_ctrl_s)); + + r |= get_user(pge2d_config_ex->src1_cmult_asel, + &uf_ex_mem->_ge2d_config_ex.src1_cmult_asel); + r |= get_user(pge2d_config_ex->src2_cmult_asel, + &uf_ex_mem->_ge2d_config_ex.src2_cmult_asel); + r |= get_user(pge2d_config_ex->alu_const_color, + &uf_ex_mem->_ge2d_config_ex.alu_const_color); + r |= get_user(pge2d_config_ex->src1_gb_alpha_en, + &uf_ex_mem->_ge2d_config_ex.src1_gb_alpha_en); + r |= get_user(pge2d_config_ex->src1_gb_alpha, + &uf_ex_mem->_ge2d_config_ex.src1_gb_alpha); +#ifdef CONFIG_GE2D_SRC2 + r |= get_user(pge2d_config_ex->src2_gb_alpha_en, + &uf_ex_mem->_ge2d_config_ex.src2_gb_alpha_en); + r |= get_user(pge2d_config_ex->src2_gb_alpha, + &uf_ex_mem->_ge2d_config_ex.src2_gb_alpha); +#endif + r |= get_user(pge2d_config_ex->op_mode, + &uf_ex_mem->_ge2d_config_ex.op_mode); + r |= get_user(pge2d_config_ex->bitmask_en, + &uf_ex_mem->_ge2d_config_ex.bitmask_en); + r |= get_user(pge2d_config_ex->bytemask_only, + &uf_ex_mem->_ge2d_config_ex.bytemask_only); + r |= get_user(pge2d_config_ex->bitmask, + &uf_ex_mem->_ge2d_config_ex.bitmask); + r |= get_user(pge2d_config_ex->dst_xy_swap, + &uf_ex_mem->_ge2d_config_ex.dst_xy_swap); + r |= get_user(pge2d_config_ex->hf_init_phase, + &uf_ex_mem->_ge2d_config_ex.hf_init_phase); + r |= get_user(pge2d_config_ex->hf_rpt_num, + &uf_ex_mem->_ge2d_config_ex.hf_rpt_num); + r |= get_user(pge2d_config_ex->hsc_start_phase_step, + &uf_ex_mem->_ge2d_config_ex + .hsc_start_phase_step); + r |= get_user(pge2d_config_ex->hsc_phase_slope, + &uf_ex_mem->_ge2d_config_ex.hsc_phase_slope); + r |= get_user(pge2d_config_ex->vf_init_phase, + &uf_ex_mem->_ge2d_config_ex.vf_init_phase); + r |= get_user(pge2d_config_ex->vf_rpt_num, + &uf_ex_mem->_ge2d_config_ex.vf_rpt_num); + r |= get_user(pge2d_config_ex->vsc_start_phase_step, + &uf_ex_mem->_ge2d_config_ex + .vsc_start_phase_step); + r |= get_user(pge2d_config_ex->vsc_phase_slope, + &uf_ex_mem->_ge2d_config_ex.vsc_phase_slope); + r |= get_user( + pge2d_config_ex->src1_vsc_phase0_always_en, + &uf_ex_mem->_ge2d_config_ex + .src1_vsc_phase0_always_en); + r |= get_user( + pge2d_config_ex->src1_hsc_phase0_always_en, + &uf_ex_mem->_ge2d_config_ex + .src1_hsc_phase0_always_en); + r |= get_user( + pge2d_config_ex->src1_hsc_rpt_ctrl, + &uf_ex_mem->_ge2d_config_ex.src1_hsc_rpt_ctrl); + r |= get_user( + pge2d_config_ex->src1_vsc_rpt_ctrl, + &uf_ex_mem->_ge2d_config_ex.src1_vsc_rpt_ctrl); + + for (i = 0; i < 4; i++) { + struct config_planes_ion_s *psrc_planes; + + psrc_planes = + &pge2d_config_ex->src_planes[i]; + r |= get_user(psrc_planes->addr, + &uf_ex_mem->_ge2d_config_ex + .src_planes[i].addr); + r |= get_user(psrc_planes->w, + &uf_ex_mem->_ge2d_config_ex + .src_planes[i].w); + r |= get_user(psrc_planes->h, + &uf_ex_mem->_ge2d_config_ex + .src_planes[i].h); + r |= get_user(psrc_planes->shared_fd, + &uf_ex_mem->_ge2d_config_ex + .src_planes[i].shared_fd); + } + + for (i = 0; i < 4; i++) { + struct config_planes_ion_s *psrc2_planes; + + psrc2_planes = + &pge2d_config_ex->src2_planes[i]; + r |= get_user(psrc2_planes->addr, + &uf_ex_mem->_ge2d_config_ex + .src2_planes[i].addr); + r |= get_user(psrc2_planes->w, + &uf_ex_mem->_ge2d_config_ex + .src2_planes[i].w); + r |= get_user(psrc2_planes->h, + &uf_ex_mem->_ge2d_config_ex + .src2_planes[i].h); + r |= get_user(psrc2_planes->shared_fd, + &uf_ex_mem->_ge2d_config_ex + .src2_planes[i].shared_fd); + } + + for (j = 0; j < 4; j++) { + struct config_planes_ion_s *pdst_planes; + + pdst_planes = + &pge2d_config_ex->dst_planes[j]; + r |= get_user(pdst_planes->addr, + &uf_ex_mem->_ge2d_config_ex + .dst_planes[j].addr); + r |= get_user(pdst_planes->w, + &uf_ex_mem->_ge2d_config_ex + .dst_planes[j].w); + r |= get_user(pdst_planes->h, + &uf_ex_mem->_ge2d_config_ex + .dst_planes[j].h); + r |= get_user(pdst_planes->shared_fd, + &uf_ex_mem->_ge2d_config_ex + .dst_planes[j].shared_fd); + } + + r |= get_user(ge2d_config_ex_mem->src1_mem_alloc_type, + &uf_ex_mem->src1_mem_alloc_type); + r |= get_user(ge2d_config_ex_mem->src2_mem_alloc_type, + &uf_ex_mem->src2_mem_alloc_type); + r |= get_user(ge2d_config_ex_mem->dst_mem_alloc_type, + &uf_ex_mem->dst_mem_alloc_type); + + } + if (r) { + pr_err("GE2D_CONFIG_EX32 get parameter failed .\n"); + return -EFAULT; + } + ret = ge2d_context_config_ex_mem(context, ge2d_config_ex_mem); + break; +#endif + } + return ret; +} + static long ge2d_ioctl(struct file *filp, unsigned int cmd, unsigned long args) { struct ge2d_context_s *context = NULL; @@ -217,6 +413,8 @@ static long ge2d_ioctl(struct file *filp, unsigned int cmd, unsigned long args) struct ge2d_para_s para; struct config_para_ex_s ge2d_config_ex; struct config_para_ex_ion_s ge2d_config_ex_ion; + struct ge2d_dmabuf_req_s ge2d_req_buf; + struct ge2d_dmabuf_exp_s ge2d_exp_buf; int ret = 0; #ifdef CONFIG_COMPAT struct compat_config_para_s __user *uf; @@ -226,12 +424,15 @@ static long ge2d_ioctl(struct file *filp, unsigned int cmd, unsigned long args) int i, j; #endif int cap_mask = 0; + int index = 0, dma_fd; void __user *argp = (void __user *)args; context = (struct ge2d_context_s *)filp->private_data; memset(&ge2d_config, 0, sizeof(struct config_para_s)); memset(&ge2d_config_ex, 0, sizeof(struct config_para_ex_s)); memset(&ge2d_config_ex_ion, 0, sizeof(struct config_para_ex_ion_s)); + memset(&ge2d_req_buf, 0, sizeof(struct ge2d_dmabuf_req_s)); + memset(&ge2d_exp_buf, 0, sizeof(struct ge2d_dmabuf_exp_s)); #ifdef CONFIG_AMLOGIC_MEDIA_GE2D_MORE_SECURITY switch (cmd) { case GE2D_CONFIG: @@ -538,6 +739,39 @@ static long ge2d_ioctl(struct file *filp, unsigned int cmd, unsigned long args) case GE2D_SET_COEF: case GE2D_ANTIFLICKER_ENABLE: break; + case GE2D_REQUEST_BUFF: + ret = copy_from_user(&ge2d_req_buf, argp, + sizeof(struct ge2d_dmabuf_req_s)); + if (ret < 0) { + pr_err("Error user param\n"); + return -EINVAL; + } + break; + case GE2D_EXP_BUFF: + ret = copy_from_user(&ge2d_exp_buf, argp, + sizeof(struct ge2d_dmabuf_exp_s)); + if (ret < 0) { + pr_err("Error user param\n"); + return -EINVAL; + } + break; + case GE2D_FREE_BUFF: + ret = copy_from_user(&index, argp, + sizeof(int)); + if (ret < 0) { + pr_err("Error user param\n"); + return -EINVAL; + } + break; + case GE2D_SYNC_DEVICE: + case GE2D_SYNC_CPU: + ret = copy_from_user(&dma_fd, argp, + sizeof(int)); + if (ret < 0) { + pr_err("Error user param\n"); + return -EINVAL; + } + break; case GE2D_CONFIG_OLD: case GE2D_CONFIG_EX_OLD: case GE2D_SRCCOLORKEY_OLD: @@ -568,6 +802,12 @@ static long ge2d_ioctl(struct file *filp, unsigned int cmd, unsigned long args) #endif ret = ge2d_context_config_ex_ion(context, &ge2d_config_ex_ion); break; + case GE2D_CONFIG_EX_MEM: +#ifdef CONFIG_COMPAT + case GE2D_CONFIG_EX32_MEM: +#endif + ret = ge2d_ioctl_config_ex_mem(context, cmd, args); + break; case GE2D_SET_COEF: ge2d_wq_set_scale_coef(context, args & 0xff, args >> 16); break; @@ -744,6 +984,27 @@ static long ge2d_ioctl(struct file *filp, unsigned int cmd, unsigned long args) para.dst_rect.x, para.dst_rect.y, para.dst_rect.w, para.dst_rect.h); break; + case GE2D_REQUEST_BUFF: + ret = ge2d_buffer_alloc(&ge2d_req_buf); + if (ret == 0) + ret = copy_to_user(argp, &ge2d_req_buf, + sizeof(struct ge2d_dmabuf_req_s)); + break; + case GE2D_EXP_BUFF: + ret = ge2d_buffer_export(&ge2d_exp_buf); + if (ret == 0) + ret = copy_to_user(argp, &ge2d_exp_buf, + sizeof(struct ge2d_dmabuf_exp_s)); + break; + case GE2D_FREE_BUFF: + ret = ge2d_buffer_free(index); + break; + case GE2D_SYNC_DEVICE: + ge2d_buffer_dma_flush(dma_fd); + break; + case GE2D_SYNC_CPU: + ge2d_buffer_cache_flush(dma_fd); + break; } return ret; } @@ -774,6 +1035,32 @@ static int ge2d_release(struct inode *inode, struct file *file) return -1; } +static struct ge2d_ctrl_s default_poweron_ctrl[] = { + /* power up ge2d */ + {GEN_PWR_SLEEP0, AO_RTI_GEN_PWR_SLEEP0, 0, 19, 1, 0}, + /* Power up memory */ + {MEM_PD_REG0, HHI_MEM_PD_REG0, 0, 18, 8, 100}, + /* reset */ + {CBUS_BASE, RESET2_LEVEL, 0, 6, 1, 0}, + /* remove isolation */ + {GEN_PWR_ISO0, AO_RTI_GEN_PWR_ISO0, 0, 19, 1, 0}, + /* pull up reset */ + {CBUS_BASE, RESET2_LEVEL, 1, 6, 1, 0} + }; +static struct ge2d_ctrl_s default_poweroff_ctrl[] = { + /* reset */ + {CBUS_BASE, RESET2_LEVEL, 0, 6, 1, 0}, + /* add isolation */ + {GEN_PWR_ISO0, AO_RTI_GEN_PWR_ISO0, 1, 19, 1, 0}, + /* Power down memory */ + {MEM_PD_REG0, HHI_MEM_PD_REG0, 0xFF, 18, 8, 0}, + /* power down ge2d */ + {GEN_PWR_SLEEP0, AO_RTI_GEN_PWR_SLEEP0, 1, 19, 1, 0} + }; + +struct ge2d_power_table_s default_poweron_table = {5, default_poweron_ctrl}; +struct ge2d_power_table_s default_poweroff_table = {4, default_poweroff_ctrl}; + static struct ge2d_device_data_s ge2d_gxl = { .ge2d_rate = 400000000, .src2_alp = 0, @@ -781,6 +1068,7 @@ static struct ge2d_device_data_s ge2d_gxl = { .deep_color = 0, .hang_flag = 0, .fifo = 0, + .has_self_pwr = 0, }; static struct ge2d_device_data_s ge2d_gxm = { @@ -790,6 +1078,7 @@ static struct ge2d_device_data_s ge2d_gxm = { .deep_color = 0, .hang_flag = 0, .fifo = 0, + .has_self_pwr = 0, }; static struct ge2d_device_data_s ge2d_txl = { @@ -799,6 +1088,7 @@ static struct ge2d_device_data_s ge2d_txl = { .deep_color = 1, .hang_flag = 0, .fifo = 0, + .has_self_pwr = 0, }; static struct ge2d_device_data_s ge2d_txlx = { @@ -808,6 +1098,7 @@ static struct ge2d_device_data_s ge2d_txlx = { .deep_color = 1, .hang_flag = 1, .fifo = 1, + .has_self_pwr = 0, }; static struct ge2d_device_data_s ge2d_axg = { @@ -817,6 +1108,7 @@ static struct ge2d_device_data_s ge2d_axg = { .deep_color = 1, .hang_flag = 1, .fifo = 1, + .has_self_pwr = 0, }; static struct ge2d_device_data_s ge2d_g12a = { @@ -826,6 +1118,19 @@ static struct ge2d_device_data_s ge2d_g12a = { .deep_color = 1, .hang_flag = 1, .fifo = 1, + .has_self_pwr = 0, +}; + +static struct ge2d_device_data_s ge2d_sm1 = { + .ge2d_rate = 500000000, + .src2_alp = 1, + .canvas_status = 0, + .deep_color = 1, + .hang_flag = 1, + .fifo = 1, + .has_self_pwr = 1, + .poweron_table = &default_poweron_table, + .poweroff_table = &default_poweroff_table, }; static const struct of_device_id ge2d_dt_match[] = { @@ -853,6 +1158,10 @@ static const struct of_device_id ge2d_dt_match[] = { .compatible = "amlogic, ge2d-g12a", .data = &ge2d_g12a, }, + { + .compatible = "amlogic, ge2d-sm1", + .data = &ge2d_sm1, + }, {}, }; @@ -961,6 +1270,9 @@ static int ge2d_probe(struct platform_device *pdev) (void *)res.start, (int)resource_size(&res)); } } + ret = of_reserved_mem_device_init(&(pdev->dev)); + if (ret < 0) + ge2d_log_info("reserved mem init failed\n"); ret = ge2d_wq_init(pdev, irq, clk_gate); diff --git a/drivers/amlogic/media/common/ge2d/ge2d_wq.c b/drivers/amlogic/media/common/ge2d/ge2d_wq.c index a35947df88de..d55c4c476ef6 100644 --- a/drivers/amlogic/media/common/ge2d/ge2d_wq.c +++ b/drivers/amlogic/media/common/ge2d/ge2d_wq.c @@ -26,6 +26,7 @@ #include #include #include +#include /* Amlogic Headers */ #include @@ -41,9 +42,11 @@ #include "ge2d_io.h" #include "ge2d_reg.h" #include "ge2d_wq.h" +#include "ge2d_dmabuf.h" #include "osd_io.h" #include "osd_hw.h" + #define OSD1_CANVAS_INDEX 0x40 #define OSD2_CANVAS_INDEX 0x43 #define OSD3_CANVAS_INDEX 0x41 @@ -117,18 +120,70 @@ static const int default_ge2d_color_lut[] = { GE2D_FORMAT_S32_ARGB,/* BPP_TYPE_32_ARGB=32, */ }; +static void ge2d_pre_init(void) +{ + struct ge2d_gen_s ge2d_gen_cfg; + + ge2d_gen_cfg.interrupt_ctrl = 0x02; + ge2d_gen_cfg.dp_on_cnt = 0; + ge2d_gen_cfg.dp_off_cnt = 0; + ge2d_gen_cfg.dp_onoff_mode = 0; + ge2d_gen_cfg.vfmt_onoff_en = 0; + /* fifo size control, 00: 512, 01: 256, 10: 128 11: 96 */ + ge2d_gen_cfg.fifo_size = 0; + /* fifo burst control, 00: 24x64, 01: 32x64 + * 10: 48x64, 11:64x64 + */ + ge2d_gen_cfg.burst_ctrl = 0; + ge2d_set_gen(&ge2d_gen_cfg); +} + static int ge2d_clk_config(bool enable) { if (ge2d_clk == NULL) return -1; - if (enable) { + if (enable) clk_prepare_enable(ge2d_clk); - } else { + else clk_disable_unprepare(ge2d_clk); - } + return 0; } + +void ge2d_pwr_config(bool enable) +{ + int i, table_size; + struct ge2d_ctrl_s tmp; + struct ge2d_ctrl_s *power_table; + + if (ge2d_meson_dev.has_self_pwr) { + if (enable) { + power_table = ge2d_meson_dev.poweron_table->power_table; + table_size = ge2d_meson_dev.poweron_table->table_size; + } else { + power_table = + ge2d_meson_dev.poweroff_table->power_table; + table_size = ge2d_meson_dev.poweroff_table->table_size; + } + + for (i = 0; i < table_size; i++) { + tmp = power_table[i]; + ge2d_set_pwr_tbl_bits(tmp.table_type, tmp.reg, tmp.val, + tmp.start, tmp.len); + if (tmp.udelay > 0) + udelay(tmp.udelay); + } + } + + ge2d_clk_config(enable); + + if (enable) { + ge2d_soft_rst(); + ge2d_pre_init(); + } +} + static int get_queue_member_count(struct list_head *head) { int member_count = 0; @@ -334,7 +389,25 @@ static int ge2d_process_work_queue(struct ge2d_context_s *wq) pos = pos->next; list_move_tail(&pitem->list, &wq->free_queue); spin_unlock(&wq->lock); - + /* if dma buf detach it */ + if (pitem->config.src_dma_cfg.dma_used) { + ge2d_dma_buffer_unmap((struct aml_dma_cfg * + )pitem->config.src_dma_cfg.dma_cfg); + pitem->config.src_dma_cfg.dma_used = 0; + kfree(pitem->config.src_dma_cfg.dma_cfg); + } + if (pitem->config.src2_dma_cfg.dma_used) { + ge2d_dma_buffer_unmap((struct aml_dma_cfg * + )pitem->config.src2_dma_cfg.dma_cfg); + pitem->config.src2_dma_cfg.dma_used = 0; + kfree(pitem->config.src2_dma_cfg.dma_cfg); + } + if (pitem->config.dst_dma_cfg.dma_used) { + ge2d_dma_buffer_unmap((struct aml_dma_cfg * + )pitem->config.dst_dma_cfg.dma_cfg); + pitem->config.dst_dma_cfg.dma_used = 0; + kfree(pitem->config.dst_dma_cfg.dma_cfg); + } pitem = (struct ge2d_queue_item_s *)pos; } while (pos != head); ge2d_manager.last_wq = wq; @@ -351,6 +424,29 @@ static irqreturn_t ge2d_wq_handle(int irq_number, void *para) return IRQ_HANDLED; } +struct ge2d_dma_cfg_s *ge2d_wq_get_dma_cfg(struct ge2d_context_s *wq, + unsigned int data_type) +{ + struct ge2d_dma_cfg_s *dma_cfg = NULL; + + switch (data_type) { + case AML_GE2D_SRC: + dma_cfg = &wq->config.src_dma_cfg; + break; + case AML_GE2D_SRC2: + dma_cfg = &wq->config.src2_dma_cfg; + break; + case AML_GE2D_DST: + dma_cfg = &wq->config.dst_dma_cfg; + break; + default: + ge2d_log_err("wrong data_type\n"); + break; + } + + return dma_cfg; +} + struct ge2d_src1_data_s *ge2d_wq_get_src_data(struct ge2d_context_s *wq) { return &wq->config.src1_data; @@ -463,12 +559,12 @@ static int ge2d_monitor_thread(void *data) /* setup current_wq here. */ while (ge2d_manager.process_queue_state != GE2D_PROCESS_QUEUE_STOP) { ret = down_interruptible(&manager->event.cmd_in_sem); - ge2d_clk_config(true); + ge2d_pwr_config(true); while ((manager->current_wq = get_next_work_queue(manager)) != NULL) ge2d_process_work_queue(manager->current_wq); if (!ge2d_dump_reg_enable) - ge2d_clk_config(false); + ge2d_pwr_config(false); } ge2d_log_info("exit ge2d_monitor_thread\n"); return 0; @@ -928,6 +1024,58 @@ static int build_ge2d_addr_config_ion( return ret; } +static int build_ge2d_addr_config_dma( + struct ge2d_context_s *context, + struct config_planes_ion_s *plane, + unsigned int format, + unsigned int *addr, + unsigned int *stride, + unsigned int dir, + unsigned int data_type + ) +{ + int ret = -1; + int bpp_value = bpp(format); + unsigned long addr_temp = 0; + + bpp_value /= 8; + ge2d_log_dbg("build_ge2d_addr_config_ion bpp_value=%d\n", + bpp_value); + if (plane) { + if (plane[0].shared_fd) { + struct ge2d_dma_cfg_s *cfg = NULL; + struct aml_dma_cfg *dma_cfg = NULL; + + cfg = ge2d_wq_get_dma_cfg(context, data_type); + if (!cfg) + return -1; + cfg->dma_used = 1; + dma_cfg = kzalloc(sizeof(*dma_cfg), GFP_KERNEL); + dma_cfg->fd = plane[0].shared_fd; + dma_cfg->dev = &(ge2d_manager.pdev->dev); + dma_cfg->dir = dir; + cfg->dma_cfg = dma_cfg; + ret = ge2d_dma_buffer_get_phys(dma_cfg, &addr_temp); + if (ret != 0) + return ret; + } + plane[0].addr += addr_temp; + if (plane[0].addr) { + *addr = plane[0].addr; + *stride = plane[0].w * bpp_value; + ret = 0; + } + /* not support multi-src_planes */ + if ((plane[1].addr) || + (plane[2].addr) || + (plane[3].addr)) { + ge2d_log_info("ge2d not support NV21 mode\n"); + ret = -1; + } + } + return ret; +} + static int build_ge2d_config_ex(struct config_planes_s *plane, unsigned int format, unsigned int *canvas_index, @@ -1066,6 +1214,92 @@ static int build_ge2d_config_ex_ion(struct config_planes_ion_s *plane, } return ret; } +static int build_ge2d_config_ex_dma(struct ge2d_context_s *context, + struct config_planes_ion_s *plane, + unsigned int format, + unsigned int *canvas_index, + int index, + unsigned int *r_offset, + unsigned int dir, + unsigned int data_type) +{ + int bpp_value = bpp(format); + int ret = -1; + unsigned long addr; + + bpp_value /= 8; + index &= 0xff; + if (plane) { + if (plane[0].shared_fd) { + struct ge2d_dma_cfg_s *cfg = NULL; + struct aml_dma_cfg *dma_cfg = NULL; + + cfg = ge2d_wq_get_dma_cfg(context, data_type); + if (!cfg) + return -1; + cfg->dma_used = 1; + dma_cfg = kzalloc(sizeof(*dma_cfg), GFP_KERNEL); + dma_cfg->fd = plane[0].shared_fd; + dma_cfg->dev = &(ge2d_manager.pdev->dev); + dma_cfg->dir = dir; + cfg->dma_cfg = dma_cfg; + ret = ge2d_dma_buffer_get_phys(dma_cfg, &addr); + if (ret != 0) + return ret; + + plane[0].addr += addr; + *canvas_index = index; + *r_offset += 1; +#ifdef CONFIG_AMLOGIC_MEDIA_CANVAS + canvas_config(index++, plane[0].addr, + plane[0].w * bpp_value, + plane[0].h, + CANVAS_ADDR_NOWRAP, + CANVAS_BLKMODE_LINEAR); +#endif + ret = 0; + } + /* multi-src_planes */ + if (plane[1].addr) { + plane[1].addr += plane[0].addr; + *canvas_index |= index << 8; + *r_offset += 1; +#ifdef CONFIG_AMLOGIC_MEDIA_CANVAS + canvas_config(index++, plane[1].addr, + plane[1].w * bpp_value, + plane[1].h, + CANVAS_ADDR_NOWRAP, + CANVAS_BLKMODE_LINEAR); +#endif + } + if (plane[2].addr) { + plane[2].addr += plane[0].addr; + *canvas_index |= index << 16; + *r_offset += 1; +#ifdef CONFIG_AMLOGIC_MEDIA_CANVAS + canvas_config(index++, plane[2].addr, + plane[2].w * bpp_value, + plane[2].h, + CANVAS_ADDR_NOWRAP, + CANVAS_BLKMODE_LINEAR); +#endif + } + if (plane[3].addr) { + plane[3].addr += plane[0].addr; + *canvas_index |= index << 24; + *r_offset += 1; +#ifdef CONFIG_AMLOGIC_MEDIA_CANVAS + canvas_config(index++, plane[3].addr, + plane[3].w * bpp_value, + plane[3].h, + CANVAS_ADDR_NOWRAP, + CANVAS_BLKMODE_LINEAR); +#endif + } + } + return ret; +} + int ge2d_context_config_ex(struct ge2d_context_s *context, struct config_para_ex_s *ge2d_config) { @@ -1806,6 +2040,11 @@ int ge2d_context_config_ex_ion(struct ge2d_context_s *context, ge2d_cmd_cfg->hsc_rpt_p0_num = ge2d_config->hf_rpt_num; ge2d_cmd_cfg->src1_cmult_asel = ge2d_config->src1_cmult_asel; ge2d_cmd_cfg->src2_cmult_asel = ge2d_config->src2_cmult_asel; + + ge2d_cmd_cfg->src1_fmt = ge2d_config->src_para.format; + ge2d_cmd_cfg->src2_fmt = ge2d_config->src2_para.format; + ge2d_cmd_cfg->dst_fmt = ge2d_config->dst_para.format; + context->config.update_flag = UPDATE_ALL; /* context->config.src1_data.ddr_burst_size_y = 3; */ /* context->config.src1_data.ddr_burst_size_cb = 3; */ @@ -1814,6 +2053,528 @@ int ge2d_context_config_ex_ion(struct ge2d_context_s *context, return 0; } +int ge2d_context_config_ex_mem(struct ge2d_context_s *context, + struct config_para_ex_memtype_s *ge2d_config_mem) +{ + struct src_dst_para_s tmp; + unsigned int index = 0; + unsigned int alloc_canvas_offset = 0; + struct ge2d_src1_gen_s *src1_gen_cfg; + struct ge2d_src2_dst_data_s *src2_dst_data_cfg; + struct ge2d_src2_dst_gen_s *src2_dst_gen_cfg; + struct ge2d_dp_gen_s *dp_gen_cfg; + struct ge2d_cmd_s *ge2d_cmd_cfg; + int top, left, width, height; + unsigned int src_addr = 0, src2_addr = 0, dst_addr = 0; + unsigned int src_stride = 0, src2_stride = 0, dst_stride = 0; + struct config_para_ex_ion_s *ge2d_config; + + ge2d_config = &(ge2d_config_mem->_ge2d_config_ex); + /* setup src and dst */ + switch (ge2d_config->src_para.mem_type) { + case CANVAS_OSD0: + case CANVAS_OSD1: + if (setup_display_property(&tmp, + (ge2d_config->src_para.mem_type == CANVAS_OSD0) ? + OSD1_CANVAS_INDEX : OSD2_CANVAS_INDEX) < 0) + return -1; + ge2d_config->src_para.canvas_index = tmp.canvas_index; + ge2d_config->src_para.format = tmp.ge2d_color_index; + src_addr = tmp.phy_addr; + src_stride = tmp.stride; + + ge2d_log_dbg("ge2d: src1-->type: osd%d, format: 0x%x !!\n", + ge2d_config->src_para.mem_type - CANVAS_OSD0, + ge2d_config->src_para.format); + + top = ge2d_config->src_para.top; + left = ge2d_config->src_para.left; + width = ge2d_config->src_para.width; + height = ge2d_config->src_para.height; + if ((left + width > tmp.xres) || + (top + height > tmp.yres)) { + ge2d_log_dbg("ge2d src error: out of range\n"); + return -1; + } + ge2d_config->src_para.width = tmp.xres; + ge2d_config->src_para.height = tmp.yres; + ge2d_log_dbg("ge2d osd phy_addr:0x%x,stride=0x%x,format:0x%x\n", + src_addr, + src_stride, + ge2d_config->src_para.format); + break; + case CANVAS_ALLOC: + top = ge2d_config->src_para.top; + left = ge2d_config->src_para.left; + width = ge2d_config->src_para.width; + height = ge2d_config->src_para.height; + if ((left + width > ge2d_config->src_planes[0].w) + || (top + height > ge2d_config->src_planes[0].h)) { + ge2d_log_dbg("ge2d error: src alloc, out of range\n"); + return -1; + } + if (ge2d_meson_dev.canvas_status == 1) { + if (ge2d_config_mem->src1_mem_alloc_type == + AML_GE2D_MEM_ION) { + if (build_ge2d_addr_config_ion( + &ge2d_config->src_planes[0], + ge2d_config->src_para.format, + &src_addr, + &src_stride) < 0) + return -1; + ge2d_log_dbg("ge2d ion alloc phy_addr:0x%x,stride=0x%x,format:0x%x\n", + src_addr, + src_stride, + ge2d_config->src_para.format); + } else if (ge2d_config_mem->src1_mem_alloc_type == + AML_GE2D_MEM_DMABUF) { + if (build_ge2d_addr_config_dma( + context, + &ge2d_config->src_planes[0], + ge2d_config->src_para.format, + &src_addr, + &src_stride, + DMA_TO_DEVICE, + AML_GE2D_SRC) < 0) + return -1; + ge2d_log_dbg("ge2d dma alloc phy_addr:0x%x,stride=0x%x,format:0x%x\n", + src_addr, + src_stride, + ge2d_config->src_para.format); + } + } else { + if (ge2d_config_mem->src1_mem_alloc_type == + AML_GE2D_MEM_ION) { + if (build_ge2d_config_ex_ion( + &ge2d_config->src_planes[0], + ge2d_config->src_para.format, + &index, + ALLOC_CANVAS_INDEX + + alloc_canvas_offset, + &alloc_canvas_offset) < 0) + return -1; + ge2d_config->src_para.canvas_index = index; + ge2d_log_dbg("ge2d ion alloc canvas index:0x%x, format:0x%x\n", + index, ge2d_config->src_para.format); + } else if (ge2d_config_mem->src1_mem_alloc_type == + AML_GE2D_MEM_DMABUF) { + if (build_ge2d_config_ex_dma( + context, + &ge2d_config->src_planes[0], + ge2d_config->src_para.format, + &index, + ALLOC_CANVAS_INDEX + + alloc_canvas_offset, + &alloc_canvas_offset, + DMA_TO_DEVICE, + AML_GE2D_SRC) < 0) + return -1; + ge2d_config->src_para.canvas_index = index; + ge2d_log_dbg("ge2d dma alloc canvas index:0x%x, format:0x%x\n", + index, ge2d_config->src_para.format); + } + } + break; + default: + break; + } + + switch (ge2d_config->src2_para.mem_type) { + case CANVAS_OSD0: + case CANVAS_OSD1: + if (setup_display_property(&tmp, + (ge2d_config->src2_para.mem_type == CANVAS_OSD0) ? + OSD1_CANVAS_INDEX : OSD2_CANVAS_INDEX) < 0) + return -1; + ge2d_config->src2_para.canvas_index = tmp.canvas_index; + ge2d_config->src2_para.format = tmp.ge2d_color_index; + src2_addr = tmp.phy_addr; + src2_stride = tmp.stride; + + ge2d_log_dbg("ge2d: src2-->type: osd%d, format: 0x%x !!\n", + ge2d_config->src2_para.mem_type - CANVAS_OSD0, + ge2d_config->src2_para.format); + + top = ge2d_config->src2_para.top; + left = ge2d_config->src2_para.left; + width = ge2d_config->src2_para.width; + height = ge2d_config->src2_para.height; + if ((left + width > tmp.xres) || (top + height > tmp.yres)) { + ge2d_log_dbg("ge2d error: src2: osd%d, out of range\n", + ge2d_config->src2_para.mem_type - CANVAS_OSD0); + return -1; + } + ge2d_config->src2_para.width = tmp.xres; + ge2d_config->src2_para.height = tmp.yres; + ge2d_log_dbg("ge2d osd phy_addr:0x%x,stride=0x%x,format:0x%x\n", + src2_addr, + src2_stride, + ge2d_config->src2_para.format); + break; + case CANVAS_ALLOC: + top = ge2d_config->src2_para.top; + left = ge2d_config->src2_para.left; + width = ge2d_config->src2_para.width; + height = ge2d_config->src2_para.height; + if ((left + width > ge2d_config->src2_planes[0].w) + || (top + height > ge2d_config->src2_planes[0].h)) { + ge2d_log_dbg("ge2d error: src2: alloc, out of range\n"); + return -1; + } + /*if (ge2d_config->src2_planes[0].addr == + * ge2d_config->src_planes[0].addr) + * index = ge2d_config->src_para.canvas_index; + * else + */ + if (ge2d_meson_dev.canvas_status == 1) { + if (ge2d_config_mem->src2_mem_alloc_type == + AML_GE2D_MEM_ION) { + if (build_ge2d_addr_config_ion( + &ge2d_config->src2_planes[0], + ge2d_config->src2_para.format, + &src2_addr, + &src2_stride) < 0) + return -1; + ge2d_log_dbg("ge2d ion alloc phy_addr:0x%x,stride=0x%x,format:0x%x\n", + src2_addr, + src2_stride, + ge2d_config->src2_para.format); + } else if (ge2d_config_mem->src2_mem_alloc_type == + AML_GE2D_MEM_DMABUF) { + if (build_ge2d_addr_config_dma( + context, + &ge2d_config->src2_planes[0], + ge2d_config->src2_para.format, + &src2_addr, + &src2_stride, + DMA_TO_DEVICE, + AML_GE2D_SRC2) < 0) + return -1; + ge2d_log_dbg("ge2d dma alloc phy_addr:0x%x,stride=0x%x,format:0x%x\n", + src2_addr, + src2_stride, + ge2d_config->src2_para.format); + } + } else { + if (ge2d_config_mem->src2_mem_alloc_type == + AML_GE2D_MEM_ION) { + if (build_ge2d_config_ex_ion( + &ge2d_config->src2_planes[0], + ge2d_config->src2_para.format, + &index, + ALLOC_CANVAS_INDEX + + alloc_canvas_offset, + &alloc_canvas_offset) < 0) + return -1; + ge2d_config->src2_para.canvas_index = index; + ge2d_log_dbg("ge2d src2 ion alloc, canvas index:0x%x,format:0x%x\n", + index, ge2d_config->src2_para.format); + } else if (ge2d_config_mem->src2_mem_alloc_type == + AML_GE2D_MEM_DMABUF) { + if (build_ge2d_config_ex_dma( + context, + &ge2d_config->src2_planes[0], + ge2d_config->src2_para.format, + &index, + ALLOC_CANVAS_INDEX + + alloc_canvas_offset, + &alloc_canvas_offset, + DMA_TO_DEVICE, + AML_GE2D_SRC2) < 0) + return -1; + ge2d_config->src2_para.canvas_index = index; + ge2d_log_dbg("ge2d src2 dma alloc, canvas index:0x%x,format:0x%x\n", + index, ge2d_config->src2_para.format); + } + } + break; + default: + break; + } + + switch (ge2d_config->dst_para.mem_type) { + case CANVAS_OSD0: + case CANVAS_OSD1: + if (setup_display_property(&tmp, + (ge2d_config->dst_para.mem_type == CANVAS_OSD0) ? + OSD1_CANVAS_INDEX : OSD2_CANVAS_INDEX) < 0) + return -1; + ge2d_config->dst_para.canvas_index = tmp.canvas_index; + ge2d_config->dst_para.format = tmp.ge2d_color_index; + dst_addr = tmp.phy_addr; + dst_stride = tmp.stride; + + ge2d_log_dbg("ge2d: dst-->type: osd%d, format: 0x%x !!\n", + ge2d_config->dst_para.mem_type - CANVAS_OSD0, + ge2d_config->dst_para.format); + + top = ge2d_config->dst_para.top; + left = ge2d_config->dst_para.left; + width = ge2d_config->dst_para.width; + height = ge2d_config->dst_para.height; + if ((left + width > tmp.xres) || (top + height > tmp.yres)) { + ge2d_log_dbg("ge2d error: dst: osd%d, out of range\n", + ge2d_config->dst_para.mem_type - CANVAS_OSD0); + return -1; + } + ge2d_config->dst_para.width = tmp.xres; + ge2d_config->dst_para.height = tmp.yres; + ge2d_log_dbg("ge2d osd phy_addr:0x%x,stride=0x%x,format:0x%x\n", + dst_addr, + dst_stride, + ge2d_config->dst_para.format); + break; + case CANVAS_ALLOC: + top = ge2d_config->dst_para.top; + left = ge2d_config->dst_para.left; + width = ge2d_config->dst_para.width; + height = ge2d_config->dst_para.height; + if ((left + width > ge2d_config->dst_planes[0].w) + || (top + height > ge2d_config->dst_planes[0].h)) { + ge2d_log_dbg("ge2d error: dst: alloc, out of range\n"); + return -1; + } + /*if (ge2d_config->dst_planes[0].addr == + * ge2d_config->src_planes[0].addr) + * index = ge2d_config->src_para.canvas_index; + * else if (ge2d_config->dst_planes[0].addr == + * ge2d_config->src2_planes[0].addr) + * index = ge2d_config->src2_para.canvas_index; + * else + */ + if (ge2d_meson_dev.canvas_status == 1) { + if (ge2d_config_mem->dst_mem_alloc_type == + AML_GE2D_MEM_ION) { + if (build_ge2d_addr_config_ion( + &ge2d_config->dst_planes[0], + ge2d_config->dst_para.format, + &dst_addr, + &dst_stride) < 0) + return -1; + ge2d_log_dbg("ge2d ion alloc phy_addr:0x%x,stride=0x%x,format:0x%x\n", + dst_addr, + dst_stride, + ge2d_config->dst_para.format); + } else if (ge2d_config_mem->dst_mem_alloc_type == + AML_GE2D_MEM_DMABUF) { + if (build_ge2d_addr_config_dma( + context, + &ge2d_config->dst_planes[0], + ge2d_config->dst_para.format, + &dst_addr, + &dst_stride, + DMA_FROM_DEVICE, + AML_GE2D_DST) < 0) + return -1; + ge2d_log_dbg("ge2d dma alloc phy_addr:0x%x,stride=0x%x,format:0x%x\n", + dst_addr, + dst_stride, + ge2d_config->dst_para.format); + } + } else { + if (ge2d_config_mem->dst_mem_alloc_type == + AML_GE2D_MEM_ION) { + if (build_ge2d_config_ex_ion( + &ge2d_config->dst_planes[0], + ge2d_config->dst_para.format, + &index, + ALLOC_CANVAS_INDEX + + alloc_canvas_offset, + &alloc_canvas_offset) < 0) + return -1; + ge2d_config->dst_para.canvas_index = index; + ge2d_log_dbg("ge2d: dst ion alloc, index:0x%x, format:0x%x\n", + index, ge2d_config->dst_para.format); + } else if (ge2d_config_mem->dst_mem_alloc_type == + AML_GE2D_MEM_DMABUF) { + if (build_ge2d_config_ex_dma( + context, + &ge2d_config->dst_planes[0], + ge2d_config->dst_para.format, + &index, + ALLOC_CANVAS_INDEX + + alloc_canvas_offset, + &alloc_canvas_offset, + DMA_FROM_DEVICE, + AML_GE2D_DST) < 0) + return -1; + ge2d_config->dst_para.canvas_index = index; + ge2d_log_dbg("ge2d: dst dma alloc, index:0x%x, format:0x%x\n", + index, ge2d_config->dst_para.format); + } + } + break; + default: + break; + } + + ge2dgen_rendering_dir(context, ge2d_config->src_para.x_rev, + ge2d_config->src_para.y_rev, + ge2d_config->dst_para.x_rev, + ge2d_config->dst_para.y_rev, + ge2d_config->dst_xy_swap); + ge2dgen_const_color(context, ge2d_config->alu_const_color); + + ge2dgen_src(context, ge2d_config->src_para.canvas_index, + ge2d_config->src_para.format, + src_addr, + src_stride); + ge2dgen_src_clip(context, ge2d_config->src_para.left, + ge2d_config->src_para.top, + ge2d_config->src_para.width, + ge2d_config->src_para.height); + ge2dgen_src_key(context, ge2d_config->src_key.key_enable, + ge2d_config->src_key.key_color, + ge2d_config->src_key.key_mask, + ge2d_config->src_key.key_mode); +#ifdef CONFIG_GE2D_SRC2 + ge2dgent_src_gbalpha(context, ge2d_config->src1_gb_alpha, + ge2d_config->src2_gb_alpha); +#else + ge2dgent_src_gbalpha(context, ge2d_config->src1_gb_alpha, 0); +#endif + ge2dgen_src_color(context, ge2d_config->src_para.color); + + ge2dgen_src2(context, ge2d_config->src2_para.canvas_index, + ge2d_config->src2_para.format, + src2_addr, + src2_stride); + ge2dgen_src2_clip(context, ge2d_config->src2_para.left, + ge2d_config->src2_para.top, + ge2d_config->src2_para.width, + ge2d_config->src2_para.height); + + ge2dgen_dst(context, ge2d_config->dst_para.canvas_index, + ge2d_config->dst_para.format, + dst_addr, + dst_stride); + ge2dgen_dst_clip(context, ge2d_config->dst_para.left, + ge2d_config->dst_para.top, + ge2d_config->dst_para.width, + ge2d_config->dst_para.height, + DST_CLIP_MODE_INSIDE); + + src1_gen_cfg = ge2d_wq_get_src_gen(context); + src1_gen_cfg->fill_mode = ge2d_config->src_para.fill_mode; + src1_gen_cfg->chfmt_rpt_pix = 0; + src1_gen_cfg->cvfmt_rpt_pix = 0; + /* src1_gen_cfg->clipx_start_ex = 0; */ + /* src1_gen_cfg->clipx_end_ex = 1; */ + /* src1_gen_cfg->clipy_start_ex = 1; */ + /* src1_gen_cfg->clipy_end_ex = 1; */ + + src2_dst_data_cfg = ge2d_wq_get_dst_data(context); + src2_dst_data_cfg->src2_def_color = ge2d_config->src2_para.color; + + src2_dst_gen_cfg = ge2d_wq_get_dst_gen(context); + src2_dst_gen_cfg->src2_fill_mode = ge2d_config->src2_para.fill_mode; + + dp_gen_cfg = ge2d_wq_get_dp_gen(context); + + dp_gen_cfg->src1_vsc_phase0_always_en = + ge2d_config->src1_hsc_phase0_always_en; + dp_gen_cfg->src1_hsc_phase0_always_en = + ge2d_config->src1_vsc_phase0_always_en; + if ((context->config.v_scale_coef_type == FILTER_TYPE_GAU0) || + (context->config.v_scale_coef_type == FILTER_TYPE_GAU0_BOT) || + (context->config.v_scale_coef_type == FILTER_TYPE_GAU1) || + (context->config.h_scale_coef_type == FILTER_TYPE_GAU0) || + (context->config.h_scale_coef_type == FILTER_TYPE_GAU0_BOT) || + (context->config.h_scale_coef_type == FILTER_TYPE_GAU1)) { + /* 1bit, 0: using minus, 1: using repeat data */ + dp_gen_cfg->src1_hsc_rpt_ctrl = ge2d_config->src1_hsc_rpt_ctrl; + /* 1bit, 0: using minus 1: using repeat data */ + dp_gen_cfg->src1_vsc_rpt_ctrl = ge2d_config->src1_vsc_rpt_ctrl; + } else { + /* 1bit, 0: using minus, 1: using repeat data */ + dp_gen_cfg->src1_hsc_rpt_ctrl = 1; + /* 1bit, 0: using minus 1: using repeat data */ + dp_gen_cfg->src1_vsc_rpt_ctrl = 1; + } + dp_gen_cfg->src1_gb_alpha = ge2d_config->src1_gb_alpha & 0xff; + dp_gen_cfg->src1_gb_alpha_en = ge2d_config->src1_gb_alpha_en & 1; +#ifdef CONFIG_GE2D_SRC2 + dp_gen_cfg->src2_gb_alpha = ge2d_config->src2_gb_alpha & 0xff; + dp_gen_cfg->src2_gb_alpha_en = ge2d_config->src2_gb_alpha_en & 1; +#endif + dp_gen_cfg->src2_key_en = ge2d_config->src2_key.key_enable; + dp_gen_cfg->src2_key_mode = ge2d_config->src2_key.key_mode; + dp_gen_cfg->src2_key = ge2d_config->src2_key.key_color; + dp_gen_cfg->src2_key_mask = ge2d_config->src2_key.key_mask; + + dp_gen_cfg->bitmask_en = ge2d_config->bitmask_en; + dp_gen_cfg->bitmask = ge2d_config->bitmask; + dp_gen_cfg->bytemask_only = ge2d_config->bytemask_only; + + ge2d_cmd_cfg = ge2d_wq_get_cmd(context); + + ge2d_cmd_cfg->src1_fill_color_en = ge2d_config->src_para.fill_color_en; + + ge2d_cmd_cfg->src2_x_rev = ge2d_config->src2_para.x_rev; + ge2d_cmd_cfg->src2_y_rev = ge2d_config->src2_para.y_rev; + ge2d_cmd_cfg->src2_fill_color_en = + ge2d_config->src2_para.fill_color_en; +#ifdef CONFIG_GE2D_SRC2 + ge2d_cmd_cfg->src2_cmult_ad = ge2d_config->src2_cmult_ad; +#endif + + ge2d_cmd_cfg->vsc_phase_slope = ge2d_config->vsc_phase_slope; + ge2d_cmd_cfg->vsc_ini_phase = ge2d_config->vf_init_phase; + ge2d_cmd_cfg->vsc_phase_step = ge2d_config->vsc_start_phase_step; + ge2d_cmd_cfg->vsc_rpt_l0_num = ge2d_config->vf_rpt_num; + + /* let internal decide */ + ge2d_cmd_cfg->hsc_phase_slope = ge2d_config->hsc_phase_slope; + ge2d_cmd_cfg->hsc_ini_phase = ge2d_config->hf_init_phase; + ge2d_cmd_cfg->hsc_phase_step = ge2d_config->hsc_start_phase_step; + ge2d_cmd_cfg->hsc_rpt_p0_num = ge2d_config->hf_rpt_num; + ge2d_cmd_cfg->src1_cmult_asel = ge2d_config->src1_cmult_asel; + ge2d_cmd_cfg->src2_cmult_asel = ge2d_config->src2_cmult_asel; + context->config.update_flag = UPDATE_ALL; + /* context->config.src1_data.ddr_burst_size_y = 3; */ + /* context->config.src1_data.ddr_burst_size_cb = 3; */ + /* context->config.src1_data.ddr_burst_size_cr = 3; */ + /* context->config.src2_dst_data.ddr_burst_size= 3; */ + + return 0; +} + +int ge2d_buffer_alloc(struct ge2d_dmabuf_req_s *ge2d_req_buf) +{ + struct device *dev; + + dev = &(ge2d_manager.pdev->dev); + return ge2d_dma_buffer_alloc(ge2d_manager.buffer, + dev, ge2d_req_buf); +} + +int ge2d_buffer_export(struct ge2d_dmabuf_exp_s *ge2d_exp_buf) +{ + return ge2d_dma_buffer_export(ge2d_manager.buffer, ge2d_exp_buf); +} + +int ge2d_buffer_free(int index) +{ + return ge2d_dma_buffer_free(ge2d_manager.buffer, index); + +} + +void ge2d_buffer_dma_flush(int dma_fd) +{ + struct device *dev; + + dev = &(ge2d_manager.pdev->dev); + ge2d_dma_buffer_dma_flush(dev, dma_fd); +} + +void ge2d_buffer_cache_flush(int dma_fd) +{ + struct device *dev; + + dev = &(ge2d_manager.pdev->dev); + ge2d_dma_buffer_cache_flush(dev, dma_fd); +} + struct ge2d_context_s *create_ge2d_work_queue(void) { int i; @@ -1906,8 +2667,6 @@ EXPORT_SYMBOL(destroy_ge2d_work_queue); int ge2d_wq_init(struct platform_device *pdev, int irq, struct clk *clk) { - struct ge2d_gen_s ge2d_gen_cfg; - ge2d_manager.pdev = pdev; ge2d_irq = irq; ge2d_clk = clk; @@ -1933,21 +2692,10 @@ int ge2d_wq_init(struct platform_device *pdev, INIT_LIST_HEAD(&ge2d_manager.process_queue); ge2d_manager.last_wq = NULL; ge2d_manager.ge2d_thread = NULL; - ge2d_clk_config(true); - ge2d_soft_rst(); - ge2d_gen_cfg.interrupt_ctrl = 0x02; - ge2d_gen_cfg.dp_on_cnt = 0; - ge2d_gen_cfg.dp_off_cnt = 0; - ge2d_gen_cfg.dp_onoff_mode = 0; - ge2d_gen_cfg.vfmt_onoff_en = 0; - /* fifo size control, 00: 512, 01: 256, 10: 128 11: 96 */ - ge2d_gen_cfg.fifo_size = 0; - /* fifo burst control, 00: 24x64, 01: 32x64 - * 10: 48x64, 11:64x64 - */ - ge2d_gen_cfg.burst_ctrl = 0; - ge2d_set_gen(&ge2d_gen_cfg); - ge2d_clk_config(false); + ge2d_manager.buffer = ge2d_dma_buffer_create(); + if (!ge2d_manager.buffer) + return -1; + if (ge2d_start_monitor()) { ge2d_log_err("ge2d create thread error\n"); return -1; @@ -1966,6 +2714,8 @@ int ge2d_wq_deinit(void) } ge2d_irq = -1; clk_disable_unprepare(ge2d_clk); + ge2d_dma_buffer_destroy(ge2d_manager.buffer); + ge2d_manager.buffer = NULL; ge2d_manager.pdev = NULL; return 0; } diff --git a/drivers/amlogic/media/common/ge2d/ge2d_wq.h b/drivers/amlogic/media/common/ge2d/ge2d_wq.h index 00b7a2952648..ae81fe7e95d7 100644 --- a/drivers/amlogic/media/common/ge2d/ge2d_wq.h +++ b/drivers/amlogic/media/common/ge2d/ge2d_wq.h @@ -34,4 +34,10 @@ extern int ge2d_wq_init(struct platform_device *pdev, int irq, struct clk *clk); extern int ge2d_wq_deinit(void); +int ge2d_buffer_alloc(struct ge2d_dmabuf_req_s *ge2d_req_buf); +int ge2d_buffer_free(int index); +int ge2d_buffer_export(struct ge2d_dmabuf_exp_s *ge2d_exp_buf); +void ge2d_buffer_dma_flush(int dma_fd); +void ge2d_buffer_cache_flush(int dma_fd); +void ge2d_pwr_config(bool enable); #endif diff --git a/drivers/amlogic/media/common/ge2d/ge2dgen.c b/drivers/amlogic/media/common/ge2d/ge2dgen.c index 687b2a675eaf..2fa47aa138b6 100644 --- a/drivers/amlogic/media/common/ge2d/ge2dgen.c +++ b/drivers/amlogic/media/common/ge2d/ge2dgen.c @@ -87,6 +87,8 @@ static inline void _set_dst_format( unsigned int format_src, unsigned int format_dst) { + unsigned int y_yc_ratio; + src2_dst_data_cfg->dst_format_all = format_dst; src2_dst_data_cfg->dst_format = (format_dst >> 8) & 3; src2_dst_data_cfg->dst_endian = (format_dst & GE2D_ENDIAN_MASK) >> @@ -112,6 +114,8 @@ static inline void _set_dst_format( } else dp_gen_cfg->conv_matrix_en = 0; + y_yc_ratio = (format_dst >> 0) & 1; + /* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */ /* for dest is nv21 or nv12 in m6. */ if ((format_dst & GE2D_FORMAT_YUV) && @@ -119,7 +123,10 @@ static inline void _set_dst_format( src2_dst_data_cfg->dst_format = 0; src2_dst_data_cfg->dst_mode_8b_sel = 0; src2_dst_data_cfg->dst2_pixel_byte_width = 1; - src2_dst_data_cfg->dst2_discard_mode = 0xf; + if (y_yc_ratio == 0) + src2_dst_data_cfg->dst2_discard_mode = 0xc; + else + src2_dst_data_cfg->dst2_discard_mode = 0xf; src2_dst_data_cfg->dst2_enable = 1; src2_dst_data_cfg->dst2_color_map = src2_dst_data_cfg->dst_color_map - 5; diff --git a/drivers/amlogic/media/common/ge2d/stretchblt.c b/drivers/amlogic/media/common/ge2d/stretchblt.c index 0c04197185af..cae54f36a7b2 100644 --- a/drivers/amlogic/media/common/ge2d/stretchblt.c +++ b/drivers/amlogic/media/common/ge2d/stretchblt.c @@ -115,7 +115,7 @@ static void _stretchblt_noalpha(struct ge2d_context_s *wq, ge2d_cmd_cfg->color_logic_op = LOGIC_OPERATION_COPY; ge2d_cmd_cfg->alpha_blend_mode = OPERATION_LOGIC; ge2d_cmd_cfg->alpha_logic_op = LOGIC_OPERATION_SET; - ge2d_cmd_cfg->wait_done_flag = 1; + ge2d_cmd_cfg->wait_done_flag = blk; ge2d_wq_add_work(wq); } diff --git a/drivers/amlogic/media/common/rdma/rdma.c b/drivers/amlogic/media/common/rdma/rdma.c index 83d3420e3902..21fece89cea2 100644 --- a/drivers/amlogic/media/common/rdma/rdma.c +++ b/drivers/amlogic/media/common/rdma/rdma.c @@ -47,140 +47,225 @@ #define Wr_reg_bits(adr, val, start, len) \ WRITE_VCBUS_REG_BITS(adr, val, start, len) -static int vsync_rdma_handle; -static int irq_count; -static int enable; -static int cur_enable; -static int pre_enable_; -static int debug_flag; -static int vsync_cfg_count; -static u32 force_rdma_config; -static bool first_config; -static bool rdma_done; +#define RDMA_NUM 2 +static int second_rdma_feature; +static int rdma_num = RDMA_NUM; +static int vsync_rdma_handle[RDMA_NUM]; +static int irq_count[RDMA_NUM]; +static int enable[RDMA_NUM]; +static int cur_enable[RDMA_NUM]; +static int pre_enable_[RDMA_NUM]; +static int debug_flag[RDMA_NUM]; +static int vsync_cfg_count[RDMA_NUM]; +static u32 force_rdma_config[RDMA_NUM]; +static bool first_config[RDMA_NUM]; +static bool rdma_done[RDMA_NUM]; static void vsync_rdma_irq(void *arg); +static void line_n_int_rdma_irq(void *arg); struct rdma_op_s vsync_rdma_op = { vsync_rdma_irq, NULL }; +struct rdma_op_s line_n_int_rdma_op = { + line_n_int_rdma_irq, + NULL +}; -void vsync_rdma_config(void) +static void set_rdma_trigger_line(void) +{ + int trigger_line; + + switch (aml_read_vcbus(VPU_VIU_VENC_MUX_CTRL) & 0x3) { + case 0: + trigger_line = aml_read_vcbus(ENCL_VIDEO_VAVON_ELINE) + - aml_read_vcbus(ENCL_VIDEO_VSO_BLINE); + break; + case 1: + if ((aml_read_vcbus(ENCI_VIDEO_MODE) & 1) == 0) + trigger_line = 260; /* 480i */ + else + trigger_line = 310; /* 576i */ + break; + case 2: + if (aml_read_vcbus(ENCP_VIDEO_MODE) & (1 << 12)) + trigger_line = aml_read_vcbus(ENCP_DE_V_END_EVEN); + else + trigger_line = aml_read_vcbus(ENCP_VIDEO_VAVON_ELINE) + - aml_read_vcbus(ENCP_VIDEO_VSO_BLINE); + break; + case 3: + trigger_line = aml_read_vcbus(ENCT_VIDEO_VAVON_ELINE) + - aml_read_vcbus(ENCT_VIDEO_VSO_BLINE); + break; + } + aml_write_vcbus(VPP_INT_LINE_NUM, trigger_line); +} + +void _vsync_rdma_config(int rdma_type) { int iret = 0; - int enable_ = cur_enable & 0xf; + int enable_ = cur_enable[rdma_type] & 0xf; - if (vsync_rdma_handle <= 0) + if (vsync_rdma_handle[rdma_type] <= 0) return; /* first frame not use rdma */ - if (!first_config) { - cur_enable = enable; - pre_enable_ = enable_; - first_config = true; - rdma_done = false; + if (!first_config[rdma_type]) { + cur_enable[rdma_type] = enable[rdma_type]; + pre_enable_[rdma_type] = enable_; + first_config[rdma_type] = true; + rdma_done[rdma_type] = false; return; } /* if rdma mode changed, reset rdma */ - if (pre_enable_ != enable_) { - rdma_clear(vsync_rdma_handle); - force_rdma_config = 1; + if (pre_enable_[rdma_type] != enable_) { + rdma_clear(vsync_rdma_handle[rdma_type]); + force_rdma_config[rdma_type] = 1; } - if (force_rdma_config) - rdma_done = true; + if (force_rdma_config[rdma_type]) + rdma_done[rdma_type] = true; if (enable_ == 1) { - if (rdma_done) + if (rdma_done[rdma_type]) iret = rdma_watchdog_setting(0); else iret = rdma_watchdog_setting(1); } else { /* not vsync mode */ iret = rdma_watchdog_setting(0); - force_rdma_config = 1; + force_rdma_config[rdma_type] = 1; } - rdma_done = false; + rdma_done[rdma_type] = false; if (iret) - force_rdma_config = 1; + force_rdma_config[rdma_type] = 1; iret = 0; - if (force_rdma_config) { + if (force_rdma_config[rdma_type]) { if (enable_ == 1) { - iret = rdma_config(vsync_rdma_handle, - RDMA_TRIGGER_VSYNC_INPUT); + if (rdma_type == VSYNC_RDMA) + iret = rdma_config(vsync_rdma_handle[rdma_type], + RDMA_TRIGGER_VSYNC_INPUT); + else if (rdma_type == LINE_N_INT_RDMA) { + set_rdma_trigger_line(); + iret = rdma_config(vsync_rdma_handle[rdma_type], + RDMA_TRIGGER_LINE_INPUT); + } if (iret) - vsync_cfg_count++; + vsync_cfg_count[rdma_type]++; } else if (enable_ == 2) /*manually in cur vsync*/ - rdma_config(vsync_rdma_handle, + rdma_config(vsync_rdma_handle[rdma_type], RDMA_TRIGGER_MANUAL); else if (enable_ == 3) ; else if (enable_ == 4) - rdma_config(vsync_rdma_handle, + rdma_config(vsync_rdma_handle[rdma_type], RDMA_TRIGGER_DEBUG1); /*for debug*/ else if (enable_ == 5) - rdma_config(vsync_rdma_handle, + rdma_config(vsync_rdma_handle[rdma_type], RDMA_TRIGGER_DEBUG2); /*for debug*/ else if (enable_ == 6) ; if (!iret) - force_rdma_config = 1; + force_rdma_config[rdma_type] = 1; else - force_rdma_config = 0; + force_rdma_config[rdma_type] = 0; } - pre_enable_ = enable_; - cur_enable = enable; + pre_enable_[rdma_type] = enable_; + cur_enable[rdma_type] = enable[rdma_type]; } + +void vsync_rdma_config(void) +{ + _vsync_rdma_config(VSYNC_RDMA); + if (second_rdma_feature && + is_meson_g12b_revb()) + _vsync_rdma_config(LINE_N_INT_RDMA); +} + EXPORT_SYMBOL(vsync_rdma_config); +void _vsync_rdma_config_pre(int rdma_type) +{ + int enable_ = cur_enable[rdma_type] & 0xf; + + if (vsync_rdma_handle[rdma_type] == 0) + return; + if (enable_ == 3)/*manually in next vsync*/ + rdma_config(vsync_rdma_handle[rdma_type], 0); + else if (enable_ == 6) + rdma_config(vsync_rdma_handle[rdma_type], 0x101); /*for debug*/ +} + void vsync_rdma_config_pre(void) { - int enable_ = cur_enable & 0xf; - - if (vsync_rdma_handle == 0) - return; - if (enable_ == 3)/*manually in next vsync*/ - rdma_config(vsync_rdma_handle, 0); - else if (enable_ == 6) - rdma_config(vsync_rdma_handle, 0x101); /*for debug*/ + _vsync_rdma_config_pre(VSYNC_RDMA); + if (second_rdma_feature && + is_meson_g12b_revb()) + _vsync_rdma_config_pre(LINE_N_INT_RDMA); } EXPORT_SYMBOL(vsync_rdma_config_pre); static void vsync_rdma_irq(void *arg) { int iret; - int enable_ = cur_enable & 0xf; + int enable_ = cur_enable[VSYNC_RDMA] & 0xf; if (enable_ == 1) { /*triggered by next vsync*/ - iret = rdma_config(vsync_rdma_handle, + iret = rdma_config(vsync_rdma_handle[VSYNC_RDMA], RDMA_TRIGGER_VSYNC_INPUT); if (iret) - vsync_cfg_count++; + vsync_cfg_count[VSYNC_RDMA]++; } else - iret = rdma_config(vsync_rdma_handle, 0); - pre_enable_ = enable_; + iret = rdma_config(vsync_rdma_handle[VSYNC_RDMA], 0); + pre_enable_[VSYNC_RDMA] = enable_; if ((!iret) || (enable_ != 1)) - force_rdma_config = 1; + force_rdma_config[VSYNC_RDMA] = 1; else - force_rdma_config = 0; - rdma_done = true; - irq_count++; + force_rdma_config[VSYNC_RDMA] = 0; + rdma_done[VSYNC_RDMA] = true; + irq_count[VSYNC_RDMA]++; return; } +static void line_n_int_rdma_irq(void *arg) +{ + int iret; + int enable_ = cur_enable[LINE_N_INT_RDMA] & 0xf; + + if (enable_ == 1) { + /*triggered by next vsync*/ + //set_rdma_trigger_line(); + iret = rdma_config(vsync_rdma_handle[LINE_N_INT_RDMA], + RDMA_TRIGGER_LINE_INPUT); + if (iret) + vsync_cfg_count[LINE_N_INT_RDMA]++; + } else + iret = rdma_config(vsync_rdma_handle[LINE_N_INT_RDMA], 0); + pre_enable_[LINE_N_INT_RDMA] = enable_; + + if ((!iret) || (enable_ != 1)) + force_rdma_config[LINE_N_INT_RDMA] = 1; + else + force_rdma_config[LINE_N_INT_RDMA] = 0; + rdma_done[VSYNC_RDMA] = true; + irq_count[VSYNC_RDMA]++; +} + u32 VSYNC_RD_MPEG_REG(u32 adr) { - int enable_ = cur_enable & 0xf; + int enable_ = cur_enable[VSYNC_RDMA] & 0xf; u32 read_val = Rd(adr); - if ((enable_ != 0) && (vsync_rdma_handle > 0)) - read_val = rdma_read_reg(vsync_rdma_handle, adr); + if ((enable_ != 0) && (vsync_rdma_handle[VSYNC_RDMA] > 0)) + read_val = rdma_read_reg(vsync_rdma_handle[VSYNC_RDMA], adr); return read_val; } @@ -188,13 +273,13 @@ EXPORT_SYMBOL(VSYNC_RD_MPEG_REG); int VSYNC_WR_MPEG_REG(u32 adr, u32 val) { - int enable_ = cur_enable & 0xf; + int enable_ = cur_enable[VSYNC_RDMA] & 0xf; - if ((enable_ != 0) && (vsync_rdma_handle > 0)) { - rdma_write_reg(vsync_rdma_handle, adr, val); + if ((enable_ != 0) && (vsync_rdma_handle[VSYNC_RDMA] > 0)) { + rdma_write_reg(vsync_rdma_handle[VSYNC_RDMA], adr, val); } else { Wr(adr, val); - if (debug_flag & 1) + if (debug_flag[VSYNC_RDMA] & 1) pr_info("VSYNC_WR(%x)<=%x\n", adr, val); } return 0; @@ -203,27 +288,94 @@ EXPORT_SYMBOL(VSYNC_WR_MPEG_REG); int VSYNC_WR_MPEG_REG_BITS(u32 adr, u32 val, u32 start, u32 len) { - int enable_ = cur_enable & 0xf; + int enable_ = cur_enable[VSYNC_RDMA] & 0xf; - if ((enable_ != 0) && (vsync_rdma_handle > 0)) { - rdma_write_reg_bits(vsync_rdma_handle, adr, val, start, len); + if ((enable_ != 0) && (vsync_rdma_handle[VSYNC_RDMA] > 0)) { + rdma_write_reg_bits(vsync_rdma_handle[VSYNC_RDMA], + adr, val, start, len); } else { u32 read_val = Rd(adr); u32 write_val = (read_val & ~(((1L<<(len))-1)<<(start))) |((unsigned int)(val) << (start)); Wr(adr, write_val); - if (debug_flag & 1) + if (debug_flag[VSYNC_RDMA] & 1) pr_info("VSYNC_WR(%x)<=%x\n", adr, write_val); } return 0; } EXPORT_SYMBOL(VSYNC_WR_MPEG_REG_BITS); +u32 _VSYNC_RD_MPEG_REG(u32 adr) +{ + u32 read_val = 0; + + if (second_rdma_feature && is_meson_g12b_revb()) { + int enable_ = cur_enable[LINE_N_INT_RDMA] & 0xf; + + read_val = Rd(adr); + + if ((enable_ != 0) && + (vsync_rdma_handle[LINE_N_INT_RDMA] > 0)) + read_val = rdma_read_reg + (vsync_rdma_handle[LINE_N_INT_RDMA], adr); + } else { + read_val = VSYNC_RD_MPEG_REG(adr); + } + return read_val; +} +EXPORT_SYMBOL(_VSYNC_RD_MPEG_REG); + +int _VSYNC_WR_MPEG_REG(u32 adr, u32 val) +{ + if (second_rdma_feature && is_meson_g12b_revb()) { + int enable_ = cur_enable[LINE_N_INT_RDMA] & 0xf; + + if ((enable_ != 0) && + (vsync_rdma_handle[LINE_N_INT_RDMA] > 0)) { + rdma_write_reg + (vsync_rdma_handle[LINE_N_INT_RDMA], adr, val); + } else { + Wr(adr, val); + if (debug_flag[LINE_N_INT_RDMA] & 1) + pr_info("VSYNC_WR(%x)<=%x\n", adr, val); + } + } else { + VSYNC_WR_MPEG_REG(adr, val); + } + return 0; +} +EXPORT_SYMBOL(_VSYNC_WR_MPEG_REG); + +int _VSYNC_WR_MPEG_REG_BITS(u32 adr, u32 val, u32 start, u32 len) +{ + if (second_rdma_feature && is_meson_g12b_revb()) { + int enable_ = cur_enable[LINE_N_INT_RDMA] & 0xf; + + if ((enable_ != 0) && + (vsync_rdma_handle[LINE_N_INT_RDMA] > 0)) { + rdma_write_reg_bits + (vsync_rdma_handle[LINE_N_INT_RDMA], + adr, val, start, len); + } else { + u32 read_val = Rd(adr); + u32 write_val = (read_val & ~(((1L<<(len))-1)<<(start))) + |((unsigned int)(val) << (start)); + Wr(adr, write_val); + if (debug_flag[LINE_N_INT_RDMA] & 1) + pr_info("VSYNC_WR(%x)<=%x\n", adr, write_val); + } + } else { + VSYNC_WR_MPEG_REG_BITS(adr, val, start, len); + } + return 0; +} +EXPORT_SYMBOL(_VSYNC_WR_MPEG_REG_BITS); + bool is_vsync_rdma_enable(void) { bool ret; - int enable_ = cur_enable & 0xf; + int enable_ = cur_enable[VSYNC_RDMA] & 0xf; ret = (enable_ != 0); return ret; @@ -232,53 +384,88 @@ EXPORT_SYMBOL(is_vsync_rdma_enable); void enable_rdma_log(int flag) { - if (flag) - debug_flag |= 0x1; - else - debug_flag &= (~0x1); + if (flag) { + debug_flag[VSYNC_RDMA] |= 0x1; + debug_flag[LINE_N_INT_RDMA] |= 0x1; + } else { + debug_flag[VSYNC_RDMA] &= (~0x1); + debug_flag[LINE_N_INT_RDMA] &= (~0x1); + } } EXPORT_SYMBOL(enable_rdma_log); void enable_rdma(int enable_flag) { - enable = enable_flag; + enable[VSYNC_RDMA] = enable_flag; + enable[LINE_N_INT_RDMA] = enable_flag; } EXPORT_SYMBOL(enable_rdma); -struct rdma_op_s *get_rdma_ops(void) +struct rdma_op_s *get_rdma_ops(int rdma_type) { - return &vsync_rdma_op; + if (rdma_type == VSYNC_RDMA) + return &vsync_rdma_op; + else if (rdma_type == LINE_N_INT_RDMA) + return &line_n_int_rdma_op; + else + return NULL; } -void set_rdma_handle(int handle) +void set_rdma_handle(int rdma_type, int handle) { - vsync_rdma_handle = handle; + vsync_rdma_handle[rdma_type] = handle; pr_info("%s video rdma handle = %d.\n", __func__, - vsync_rdma_handle); + vsync_rdma_handle[rdma_type]); + +} + +u32 is_line_n_rdma_enable(void) +{ + return second_rdma_feature; } static int __init rdma_init(void) { - cur_enable = 0; - enable = 1; - force_rdma_config = 1; + second_rdma_feature = 0; + if (is_meson_g12b_revb()) + second_rdma_feature = 1; + + cur_enable[VSYNC_RDMA] = 0; + enable[VSYNC_RDMA] = 1; + force_rdma_config[VSYNC_RDMA] = 1; + + if (second_rdma_feature) { + cur_enable[LINE_N_INT_RDMA] = 0; + enable[LINE_N_INT_RDMA] = 1; + force_rdma_config[LINE_N_INT_RDMA] = 1; + } + return 0; } module_init(rdma_init); -MODULE_PARM_DESC(enable, "\n enable\n"); -module_param(enable, uint, 0664); +MODULE_PARM_DESC(second_rdma_feature, + "\n second_rdma_feature enable\n"); +module_param(second_rdma_feature, uint, 0664); -MODULE_PARM_DESC(irq_count, "\n irq_count\n"); -module_param(irq_count, uint, 0664); +MODULE_PARM_DESC(enable, + "\n vsync rdma enable\n"); +module_param_array(enable, uint, &rdma_num, 0664); -MODULE_PARM_DESC(debug_flag, "\n debug_flag\n"); -module_param(debug_flag, uint, 0664); +MODULE_PARM_DESC(irq_count, + "\n vsync rdma irq_count\n"); +module_param_array(irq_count, uint, &rdma_num, 0664); -MODULE_PARM_DESC(vsync_cfg_count, "\n vsync_cfg_count\n"); -module_param(vsync_cfg_count, uint, 0664); +MODULE_PARM_DESC(debug_flag, + "\n vsync rdma debug_flag\n"); +module_param_array(debug_flag, uint, &rdma_num, 0664); -MODULE_PARM_DESC(force_rdma_config, "\n force_rdma_config\n"); -module_param(force_rdma_config, uint, 0664); +MODULE_PARM_DESC(vsync_cfg_count, + "\n vsync rdma vsync_cfg_count\n"); +module_param_array(vsync_cfg_count, uint, &rdma_num, 0664); + +MODULE_PARM_DESC(force_rdma_config, + "\n vsync rdma force_rdma_config\n"); +module_param_array(force_rdma_config, uint, &rdma_num, 0664); diff --git a/drivers/amlogic/media/common/rdma/rdma.h b/drivers/amlogic/media/common/rdma/rdma.h index 8c98077ddff8..7a3c0a750df5 100644 --- a/drivers/amlogic/media/common/rdma/rdma.h +++ b/drivers/amlogic/media/common/rdma/rdma.h @@ -17,6 +17,11 @@ #ifndef RDMA_VSYNC_H_ #define RDMA_VSYNC_H_ + +enum { + VSYNC_RDMA, + LINE_N_INT_RDMA, +}; void vsync_rdma_config(void); void vsync_rdma_config_pre(void); bool is_vsync_rdma_enable(void); @@ -25,7 +30,7 @@ void enable_rdma_log(int flag); void enable_rdma(int enable_flag); extern int rdma_watchdog_setting(int flag); int rdma_init2(void); -struct rdma_op_s *get_rdma_ops(void); -void set_rdma_handle(int handle); +struct rdma_op_s *get_rdma_ops(int rdma_type); +void set_rdma_handle(int rdma_type, int handle); #endif diff --git a/drivers/amlogic/media/common/rdma/rdma_mgr.c b/drivers/amlogic/media/common/rdma/rdma_mgr.c index c9502de22142..cf15d3adf26e 100644 --- a/drivers/amlogic/media/common/rdma/rdma_mgr.c +++ b/drivers/amlogic/media/common/rdma/rdma_mgr.c @@ -825,11 +825,19 @@ MODULE_PARM_DESC(trace_reg, "\n trace_addr\n"); module_param(trace_reg, ushort, 0664); static struct rdma_device_data_s rdma_meson = { + .cpu_type = CPU_NORMAL, + .rdma_ver = RDMA_VER_1, + .trigger_mask_len = 8, +}; + +static struct rdma_device_data_s rdma_g12b = { + .cpu_type = CPU_G12B, .rdma_ver = RDMA_VER_1, .trigger_mask_len = 8, }; static struct rdma_device_data_s rdma_tl1 = { + .cpu_type = CPU_NORMAL, .rdma_ver = RDMA_VER_2, .trigger_mask_len = 16, }; @@ -839,6 +847,10 @@ static const struct of_device_id rdma_dt_match[] = { .compatible = "amlogic, meson, rdma", .data = &rdma_meson, }, + { + .compatible = "amlogic, meson-g12b, rdma", + .data = &rdma_g12b, + }, { .compatible = "amlogic, meson-tl1, rdma", .data = &rdma_tl1, @@ -846,6 +858,15 @@ static const struct of_device_id rdma_dt_match[] = { {}, }; +u32 is_meson_g12b_revb(void) +{ + if (rdma_meson_dev.cpu_type == CPU_G12B && + is_meson_rev_b()) + return 1; + else + return 0; +} + /* static int __devinit rdma_probe(struct platform_device *pdev) */ static int rdma_probe(struct platform_device *pdev) { @@ -880,7 +901,8 @@ static int rdma_probe(struct platform_device *pdev) pr_err("dev %s NOT found\n", __func__); return -ENODEV; } - pr_info("%s,ver:%d, len:%d\n", __func__, + pr_info("%s,cpu_type:%d, ver:%d, len:%d\n", __func__, + rdma_meson_dev.cpu_type, rdma_meson_dev.rdma_ver, rdma_meson_dev.trigger_mask_len); switch_vpu_mem_pd_vmod(VPU_RDMA, VPU_MEM_POWER_ON); @@ -933,9 +955,16 @@ static int rdma_probe(struct platform_device *pdev) info->rdma_dev = pdev; - handle = rdma_register(get_rdma_ops(), NULL, RDMA_TABLE_SIZE); - set_rdma_handle(handle); + handle = rdma_register(get_rdma_ops(VSYNC_RDMA), + NULL, RDMA_TABLE_SIZE); + set_rdma_handle(VSYNC_RDMA, handle); + if (is_meson_g12b_revb()) { + pr_info("g12b revb!!!!\n"); + handle = rdma_register(get_rdma_ops(LINE_N_INT_RDMA), + NULL, RDMA_TABLE_SIZE); + set_rdma_handle(LINE_N_INT_RDMA, handle); + } return 0; } diff --git a/drivers/amlogic/media/common/v4l_util/Kconfig b/drivers/amlogic/media/common/v4l_util/Kconfig index 5511b627ea43..bbf86618fc6f 100644 --- a/drivers/amlogic/media/common/v4l_util/Kconfig +++ b/drivers/amlogic/media/common/v4l_util/Kconfig @@ -3,7 +3,7 @@ # config AMLOGIC_VIDEOBUF_RESOURCE - bool "Amlogic V4L UTIL Support" + tristate "Amlogic V4L UTIL Support" select VIDEOBUF2_DMA_CONTIG select V4L2_MEM2MEM_DEV default n diff --git a/drivers/amlogic/media/common/vfm/vframe_provider.c b/drivers/amlogic/media/common/vfm/vframe_provider.c index e20806043cb4..af6d1bd24c70 100644 --- a/drivers/amlogic/media/common/vfm/vframe_provider.c +++ b/drivers/amlogic/media/common/vfm/vframe_provider.c @@ -367,6 +367,33 @@ void vf_unreg_provider(struct vframe_provider_s *prov) } } EXPORT_SYMBOL(vf_unreg_provider); +void vf_light_reg_provider(struct vframe_provider_s *prov) +{ + struct vframe_provider_s *p = NULL; + struct vframe_receiver_s *receiver = NULL; + int i; + + for (i = 0; i < MAX_PROVIDER_NUM; i++) { + p = provider_table[i]; + if (p && !strcmp(p->name, prov->name)) { + if (vfm_debug_flag & 1) + pr_err("%s:%s\n", __func__, prov->name); + receiver = vf_get_receiver(prov->name); + if (receiver && receiver->ops + && receiver->ops->event_cb) { + receiver->ops->event_cb( + VFRAME_EVENT_PROVIDER_REG, + (void *)prov->name, + receiver->op_arg); + } else{ + pr_err("%s Error to notify receiver\n", + __func__); + } + break; + } + } +} +EXPORT_SYMBOL(vf_light_reg_provider); void vf_light_unreg_provider(struct vframe_provider_s *prov) { diff --git a/drivers/amlogic/media/common/vpu/vpu.c b/drivers/amlogic/media/common/vpu/vpu.c index d7f3cffa5a4a..8524fc83911d 100644 --- a/drivers/amlogic/media/common/vpu/vpu.c +++ b/drivers/amlogic/media/common/vpu/vpu.c @@ -39,7 +39,9 @@ /* v04: add g12a support */ /* v05: add txl support */ /* v20180925: add tl1 support */ -#define VPU_VERION "v20180925" +/* v20190314: add sm1 support */ +/* v20190329: add tm2 support */ +#define VPU_VERION "v20190329" int vpu_debug_print_flag; static spinlock_t vpu_mem_lock; @@ -789,8 +791,16 @@ static ssize_t vpu_mem_debug(struct class *class, struct class_attribute *attr, _reg0 = HHI_VPU_MEM_PD_REG0; _reg1 = HHI_VPU_MEM_PD_REG1; _reg2 = HHI_VPU_MEM_PD_REG2; - _reg3 = HHI_VPU_MEM_PD_REG3; - _reg4 = HHI_VPU_MEM_PD_REG4; + switch (vpu_conf.data->chip_type) { + case VPU_CHIP_SM1: + _reg3 = HHI_VPU_MEM_PD_REG3_SM1; + _reg4 = HHI_VPU_MEM_PD_REG4_SM1; + break; + default: + _reg3 = HHI_VPU_MEM_PD_REG3; + _reg4 = HHI_VPU_MEM_PD_REG4; + break; + } switch (buf[0]) { case 'r': VPUPR("mem_pd0: 0x%08x\n", vpu_hiu_read(_reg0)); @@ -799,9 +809,9 @@ static ssize_t vpu_mem_debug(struct class *class, struct class_attribute *attr, if (vpu_conf.data->mem_pd_reg2_valid) VPUPR("mem_pd2: 0x%08x\n", vpu_hiu_read(_reg2)); if (vpu_conf.data->mem_pd_reg3_valid) - VPUPR("mem_pd2: 0x%08x\n", vpu_hiu_read(_reg3)); + VPUPR("mem_pd3: 0x%08x\n", vpu_hiu_read(_reg3)); if (vpu_conf.data->mem_pd_reg4_valid) - VPUPR("mem_pd2: 0x%08x\n", vpu_hiu_read(_reg4)); + VPUPR("mem_pd4: 0x%08x\n", vpu_hiu_read(_reg4)); break; case 'w': ret = sscanf(buf, "w %u %u", &tmp[0], &tmp[1]); @@ -939,6 +949,7 @@ static ssize_t vpu_print_debug(struct class *class, static ssize_t vpu_debug_info(struct class *class, struct class_attribute *attr, char *buf) { + unsigned int _reg0, _reg1, _reg2, _reg3, _reg4; unsigned int level_max, clk; ssize_t len = 0; int ret; @@ -952,6 +963,20 @@ static ssize_t vpu_debug_info(struct class *class, return len; } + _reg0 = HHI_VPU_MEM_PD_REG0; + _reg1 = HHI_VPU_MEM_PD_REG1; + _reg2 = HHI_VPU_MEM_PD_REG2; + switch (vpu_conf.data->chip_type) { + case VPU_CHIP_SM1: + _reg3 = HHI_VPU_MEM_PD_REG3_SM1; + _reg4 = HHI_VPU_MEM_PD_REG4_SM1; + break; + default: + _reg3 = HHI_VPU_MEM_PD_REG3; + _reg4 = HHI_VPU_MEM_PD_REG4; + break; + } + clk = get_vpu_clk(); level_max = vpu_conf.data->clk_level_max - 1; @@ -971,22 +996,22 @@ static ssize_t vpu_debug_info(struct class *class, len += sprintf(buf+len, "mem_pd:\n" " mem_pd0: 0x%08x\n", - vpu_hiu_read(HHI_VPU_MEM_PD_REG0)); + vpu_hiu_read(_reg0)); if (vpu_conf.data->mem_pd_reg1_valid) { len += sprintf(buf+len, " mem_pd1: 0x%08x\n", - vpu_hiu_read(HHI_VPU_MEM_PD_REG1)); + vpu_hiu_read(_reg1)); } if (vpu_conf.data->mem_pd_reg2_valid) { len += sprintf(buf+len, " mem_pd2: 0x%08x\n", - vpu_hiu_read(HHI_VPU_MEM_PD_REG2)); + vpu_hiu_read(_reg2)); } if (vpu_conf.data->mem_pd_reg3_valid) { len += sprintf(buf+len, " mem_pd3: 0x%08x\n", - vpu_hiu_read(HHI_VPU_MEM_PD_REG3)); + vpu_hiu_read(_reg3)); } if (vpu_conf.data->mem_pd_reg4_valid) { len += sprintf(buf+len, " mem_pd4: 0x%08x\n", - vpu_hiu_read(HHI_VPU_MEM_PD_REG4)); + vpu_hiu_read(_reg4)); } #ifdef CONFIG_VPU_DYNAMIC_ADJ @@ -1107,9 +1132,9 @@ static int vpu_suspend(struct platform_device *pdev, pm_message_t state) static int vpu_resume(struct platform_device *pdev) { + set_vpu_clk(vpu_conf.clk_level); VPUPR("resume clk: %uHz(0x%x)\n", get_vpu_clk(), (vpu_hiu_read(HHI_VPU_CLK_CNTL))); - set_vpu_clk(vpu_conf.clk_level); return 0; } #endif @@ -1232,6 +1257,8 @@ static struct vpu_data_s vpu_data_gxb = { .module_init_table_cnt = 0, .module_init_table = NULL, + .hdmi_iso_pre_table = vpu_hdmi_iso_pre_gxb, + .hdmi_iso_table = vpu_hdmi_iso_gxb, .reset_table = vpu_reset_gx, }; @@ -1257,6 +1284,8 @@ static struct vpu_data_s vpu_data_gxtvbb = { .module_init_table_cnt = 0, .module_init_table = NULL, + .hdmi_iso_pre_table = vpu_hdmi_iso_pre_gxb, + .hdmi_iso_table = vpu_hdmi_iso_gxb, .reset_table = vpu_reset_gx, }; @@ -1282,6 +1311,8 @@ static struct vpu_data_s vpu_data_gxl = { .module_init_table_cnt = 0, .module_init_table = NULL, + .hdmi_iso_pre_table = vpu_hdmi_iso_pre_gxb, + .hdmi_iso_table = vpu_hdmi_iso_gxb, .reset_table = vpu_reset_gx, }; @@ -1308,6 +1339,8 @@ static struct vpu_data_s vpu_data_gxm = { .module_init_table_cnt = sizeof(vpu_module_init_gxm) / sizeof(struct vpu_ctrl_s), .module_init_table = vpu_module_init_gxm, + .hdmi_iso_pre_table = vpu_hdmi_iso_pre_gxb, + .hdmi_iso_table = vpu_hdmi_iso_gxb, .reset_table = vpu_reset_gx, }; @@ -1333,6 +1366,8 @@ static struct vpu_data_s vpu_data_txl = { .module_init_table_cnt = 0, .module_init_table = NULL, + .hdmi_iso_pre_table = vpu_hdmi_iso_pre_gxb, + .hdmi_iso_table = vpu_hdmi_iso_gxb, .reset_table = vpu_reset_gx, }; @@ -1359,6 +1394,8 @@ static struct vpu_data_s vpu_data_txlx = { .module_init_table_cnt = sizeof(vpu_module_init_txlx) / sizeof(struct vpu_ctrl_s), .module_init_table = vpu_module_init_txlx, + .hdmi_iso_pre_table = vpu_hdmi_iso_pre_gxb, + .hdmi_iso_table = vpu_hdmi_iso_gxb, .reset_table = vpu_reset_txlx, }; @@ -1384,6 +1421,8 @@ static struct vpu_data_s vpu_data_axg = { .module_init_table_cnt = 0, .module_init_table = NULL, + .hdmi_iso_pre_table = vpu_hdmi_iso_pre_gxb, + .hdmi_iso_table = vpu_hdmi_iso_gxb, .reset_table = vpu_reset_txlx, }; @@ -1409,6 +1448,8 @@ static struct vpu_data_s vpu_data_g12a = { .module_init_table_cnt = 0, .module_init_table = NULL, + .hdmi_iso_pre_table = vpu_hdmi_iso_pre_gxb, + .hdmi_iso_table = vpu_hdmi_iso_gxb, .reset_table = vpu_reset_txlx, }; @@ -1434,6 +1475,8 @@ static struct vpu_data_s vpu_data_g12b = { .module_init_table_cnt = 0, .module_init_table = NULL, + .hdmi_iso_pre_table = vpu_hdmi_iso_pre_gxb, + .hdmi_iso_table = vpu_hdmi_iso_gxb, .reset_table = vpu_reset_txlx, }; @@ -1459,6 +1502,62 @@ static struct vpu_data_s vpu_data_tl1 = { .module_init_table_cnt = 0, .module_init_table = NULL, + .hdmi_iso_pre_table = vpu_hdmi_iso_pre_gxb, + .hdmi_iso_table = vpu_hdmi_iso_gxb, + .reset_table = vpu_reset_tl1, +}; + +static struct vpu_data_s vpu_data_sm1 = { + .chip_type = VPU_CHIP_SM1, + .chip_name = "sm1", + .clk_level_dft = CLK_LEVEL_DFT_G12A, + .clk_level_max = CLK_LEVEL_MAX_G12A, + .fclk_div_table = fclk_div_table_g12a, + + .gp_pll_valid = 0, + .mem_pd_reg1_valid = 1, + .mem_pd_reg2_valid = 1, + .mem_pd_reg3_valid = 1, + .mem_pd_reg4_valid = 1, + + .mem_pd_table_cnt = + sizeof(vpu_mem_pd_sm1) / sizeof(struct vpu_ctrl_s), + .clk_gate_table_cnt = + sizeof(vpu_clk_gate_g12a) / sizeof(struct vpu_ctrl_s), + .mem_pd_table = vpu_mem_pd_sm1, + .clk_gate_table = vpu_clk_gate_g12a, + + .module_init_table_cnt = 0, + .module_init_table = NULL, + .hdmi_iso_pre_table = vpu_hdmi_iso_pre_gxb, + .hdmi_iso_table = vpu_hdmi_iso_sm1, + .reset_table = vpu_reset_txlx, +}; + +static struct vpu_data_s vpu_data_tm2 = { + .chip_type = VPU_CHIP_TM2, + .chip_name = "tm2", + .clk_level_dft = CLK_LEVEL_DFT_G12A, + .clk_level_max = CLK_LEVEL_MAX_G12A, + .fclk_div_table = fclk_div_table_g12a, + + .gp_pll_valid = 0, + .mem_pd_reg1_valid = 1, + .mem_pd_reg2_valid = 1, + .mem_pd_reg3_valid = 1, + .mem_pd_reg4_valid = 1, + + .mem_pd_table_cnt = + sizeof(vpu_mem_pd_tm2) / sizeof(struct vpu_ctrl_s), + .clk_gate_table_cnt = + sizeof(vpu_clk_gate_g12a) / sizeof(struct vpu_ctrl_s), + .mem_pd_table = vpu_mem_pd_tm2, + .clk_gate_table = vpu_clk_gate_g12a, + + .module_init_table_cnt = 0, + .module_init_table = NULL, + .hdmi_iso_pre_table = vpu_hdmi_iso_pre_gxb, + .hdmi_iso_table = vpu_hdmi_iso_sm1, .reset_table = vpu_reset_tl1, }; @@ -1503,6 +1602,14 @@ static const struct of_device_id vpu_of_table[] = { .compatible = "amlogic, vpu-tl1", .data = &vpu_data_tl1, }, + { + .compatible = "amlogic, vpu-sm1", + .data = &vpu_data_sm1, + }, + { + .compatible = "amlogic, vpu-tm2", + .data = &vpu_data_tm2, + }, {}, }; diff --git a/drivers/amlogic/media/common/vpu/vpu.h b/drivers/amlogic/media/common/vpu/vpu.h index 997f96c9c8ea..b3a50088f1e7 100644 --- a/drivers/amlogic/media/common/vpu/vpu.h +++ b/drivers/amlogic/media/common/vpu/vpu.h @@ -36,10 +36,13 @@ enum vpu_chip_e { VPU_CHIP_G12A, VPU_CHIP_G12B, VPU_CHIP_TL1, + VPU_CHIP_SM1, + VPU_CHIP_TM2, VPU_CHIP_MAX, }; #define VPU_REG_END 0xffff +#define VPU_HDMI_ISO_CNT_MAX 5 #define VPU_RESET_CNT_MAX 10 struct fclk_div_s { @@ -87,6 +90,8 @@ struct vpu_data_s { unsigned int module_init_table_cnt; struct vpu_ctrl_s *module_init_table; + struct vpu_ctrl_s *hdmi_iso_pre_table; + struct vpu_ctrl_s *hdmi_iso_table; struct vpu_reset_s *reset_table; }; diff --git a/drivers/amlogic/media/common/vpu/vpu_ctrl.h b/drivers/amlogic/media/common/vpu/vpu_ctrl.h index ca0eb494511b..30e39dcb3605 100644 --- a/drivers/amlogic/media/common/vpu/vpu_ctrl.h +++ b/drivers/amlogic/media/common/vpu/vpu_ctrl.h @@ -379,7 +379,7 @@ static struct vpu_ctrl_s vpu_mem_pd_tl1[] = { {VPU_VENCP, HHI_VPU_MEM_PD_REG1, 0x3, 20, 2}, {VPU_VENCL, HHI_VPU_MEM_PD_REG1, 0x3, 22, 2}, {VPU_VENCI, HHI_VPU_MEM_PD_REG1, 0x3, 24, 2}, - {VPU_LS_STTS, HHI_VPU_MEM_PD_REG1, 0x3, 26, 2}, + {VPU_LC_STTS, HHI_VPU_MEM_PD_REG1, 0x3, 26, 2}, {VPU_LDIM_STTS, HHI_VPU_MEM_PD_REG1, 0x3, 28, 2}, {VPU_VD2_OSD2_SCALE, HHI_VPU_MEM_PD_REG1, 0x3, 30, 2}, {VPU_VIU_WM, HHI_VPU_MEM_PD_REG2, 0x3, 0, 2}, @@ -394,7 +394,7 @@ static struct vpu_ctrl_s vpu_mem_pd_tl1[] = { {VPU_DS, HHI_VPU_MEM_PD_REG2, 0x3, 18, 2}, {VPU_LUT3D, HHI_VPU_MEM_PD_REG2, 0x3, 20, 2}, {VPU_VIU2_OSD_ROT, HHI_VPU_MEM_PD_REG2, 0x3, 22, 2}, - {VPU_VI_DIPRE, HHI_VPU_MEM_PD_REG2, 0xf, 24, 4}, + {VPU_DI_PRE, HHI_VPU_MEM_PD_REG2, 0xf, 24, 4}, {VPU_RDMA, HHI_VPU_MEM_PD_REG2, 0x3, 30, 2}, {VPU_TCON, HHI_VPU_MEM_PD_REG3, 0x3, 0, 16}, {VPU_TCON, HHI_VPU_MEM_PD_REG3, 0x3, 16, 16}, @@ -404,6 +404,116 @@ static struct vpu_ctrl_s vpu_mem_pd_tl1[] = { {VPU_MOD_MAX, VPU_REG_END, 0, 0, 0}, }; +static struct vpu_ctrl_s vpu_mem_pd_sm1[] = { + /* vpu module, reg, val, bit, len */ + {VPU_VIU_OSD1, HHI_VPU_MEM_PD_REG0, 0x3, 0, 2}, + {VPU_VIU_OSD2, HHI_VPU_MEM_PD_REG0, 0x3, 2, 2}, + {VPU_VIU_VD1, HHI_VPU_MEM_PD_REG0, 0x3, 4, 2}, + {VPU_VIU_VD2, HHI_VPU_MEM_PD_REG0, 0x3, 6, 2}, + {VPU_VIU_CHROMA, HHI_VPU_MEM_PD_REG0, 0x3, 8, 2}, + {VPU_VIU_OFIFO, HHI_VPU_MEM_PD_REG0, 0x3, 10, 2}, + {VPU_VIU_SCALE, HHI_VPU_MEM_PD_REG0, 0x3, 12, 2}, + {VPU_VIU_OSD_SCALE, HHI_VPU_MEM_PD_REG0, 0x3, 14, 2}, + {VPU_VIU_VDIN0, HHI_VPU_MEM_PD_REG0, 0x3, 16, 2}, + {VPU_VIU_VDIN1, HHI_VPU_MEM_PD_REG0, 0x3, 18, 2}, + {VPU_VIU_SRSCL, HHI_VPU_MEM_PD_REG0, 0x3, 20, 2}, + {VPU_AFBC_DEC1, HHI_VPU_MEM_PD_REG0, 0x3, 22, 2}, + {VPU_VIU_DI_SCALE, HHI_VPU_MEM_PD_REG0, 0x3, 24, 2}, + {VPU_DI_PRE, HHI_VPU_MEM_PD_REG0, 0x3, 26, 2}, + {VPU_DI_POST, HHI_VPU_MEM_PD_REG0, 0x3, 28, 2}, + {VPU_SHARP, HHI_VPU_MEM_PD_REG0, 0x3, 30, 2}, + {VPU_VIU2, HHI_VPU_MEM_PD_REG1, 0xf, 0, 4}, + {VPU_VKSTONE, HHI_VPU_MEM_PD_REG1, 0x3, 4, 2}, + {VPU_DOLBY_CORE3, HHI_VPU_MEM_PD_REG1, 0x3, 6, 2}, + {VPU_DOLBY0, HHI_VPU_MEM_PD_REG1, 0x3, 8, 2}, + {VPU_DOLBY1A, HHI_VPU_MEM_PD_REG1, 0x3, 10, 2}, + {VPU_DOLBY1B, HHI_VPU_MEM_PD_REG1, 0x3, 12, 2}, + {VPU_VPU_ARB, HHI_VPU_MEM_PD_REG1, 0x3, 14, 2}, + {VPU_AFBC_DEC, HHI_VPU_MEM_PD_REG1, 0x3, 16, 2}, + {VPU_VD2_SCALE, HHI_VPU_MEM_PD_REG1, 0x3, 18, 2}, + {VPU_VENCP, HHI_VPU_MEM_PD_REG1, 0x3, 20, 2}, + {VPU_VENCL, HHI_VPU_MEM_PD_REG1, 0x3, 22, 2}, + {VPU_VENCI, HHI_VPU_MEM_PD_REG1, 0x3, 24, 2}, + {VPU_LC_STTS, HHI_VPU_MEM_PD_REG1, 0x3, 26, 2}, + {VPU_LDIM_STTS, HHI_VPU_MEM_PD_REG1, 0x3, 28, 2}, + {VPU_VD2_OSD2_SCALE, HHI_VPU_MEM_PD_REG1, 0x3, 30, 2}, + {VPU_VIU_WM, HHI_VPU_MEM_PD_REG2, 0x3, 0, 2}, + {VPU_TCON, HHI_VPU_MEM_PD_REG2, 0x3, 2, 2}, + {VPU_VIU_OSD3, HHI_VPU_MEM_PD_REG2, 0x3, 4, 2}, + {VPU_VIU_OSD4, HHI_VPU_MEM_PD_REG2, 0x3, 6, 2}, + {VPU_MAIL_AFBCD, HHI_VPU_MEM_PD_REG2, 0x3, 8, 2}, + {VPU_VD1_SCALE, HHI_VPU_MEM_PD_REG2, 0x3, 10, 2}, + {VPU_OSD_BLD34, HHI_VPU_MEM_PD_REG2, 0x3, 12, 2}, + {VPU_PRIME_DOLBY_RAM, HHI_VPU_MEM_PD_REG2, 0x3, 14, 2}, + {VPU_VD2_OFIFO, HHI_VPU_MEM_PD_REG2, 0x3, 16, 2}, + {VPU_DS, HHI_VPU_MEM_PD_REG2, 0x3, 18, 2}, + {VPU_LUT3D, HHI_VPU_MEM_PD_REG2, 0x3, 20, 2}, + {VPU_VIU2, HHI_VPU_MEM_PD_REG2, 0x3, 22, 2}, + {VPU_DI_PRE, HHI_VPU_MEM_PD_REG2, 0x3, 24, 2}, + {VPU_RDMA, HHI_VPU_MEM_PD_REG2, 0x3, 30, 2}, + {VPU_TCON, HHI_VPU_MEM_PD_REG3_SM1, 0x3, 0, 16}, + {VPU_TCON, HHI_VPU_MEM_PD_REG3_SM1, 0x3, 16, 16}, + {VPU_AXI_WR1, HHI_VPU_MEM_PD_REG4_SM1, 0x3, 0, 2}, + {VPU_AXI_WR0, HHI_VPU_MEM_PD_REG4_SM1, 0x3, 2, 2}, + {VPU_MOD_MAX, VPU_REG_END, 0, 0, 0}, +}; + +static struct vpu_ctrl_s vpu_mem_pd_tm2[] = { + /* vpu module, reg, val, bit, len */ + {VPU_VIU_OSD1, HHI_VPU_MEM_PD_REG0, 0x3, 0, 2}, + {VPU_VIU_OSD2, HHI_VPU_MEM_PD_REG0, 0x3, 2, 2}, + {VPU_VIU_VD1, HHI_VPU_MEM_PD_REG0, 0x3, 4, 2}, + {VPU_VIU_VD2, HHI_VPU_MEM_PD_REG0, 0x3, 6, 2}, + {VPU_VIU_CHROMA, HHI_VPU_MEM_PD_REG0, 0x3, 8, 2}, + {VPU_VIU_OFIFO, HHI_VPU_MEM_PD_REG0, 0x3, 10, 2}, + {VPU_VIU_SCALE, HHI_VPU_MEM_PD_REG0, 0x3, 12, 2}, + {VPU_VIU_OSD_SCALE, HHI_VPU_MEM_PD_REG0, 0x3, 14, 2}, + {VPU_VIU_VDIN0, HHI_VPU_MEM_PD_REG0, 0x3, 16, 2}, + {VPU_VIU_VDIN1, HHI_VPU_MEM_PD_REG0, 0x3, 18, 2}, + {VPU_VIU_SRSCL, HHI_VPU_MEM_PD_REG0, 0x3, 20, 2}, + {VPU_AFBC_DEC1, HHI_VPU_MEM_PD_REG0, 0x3, 22, 2}, + {VPU_VIU_DI_SCALE, HHI_VPU_MEM_PD_REG0, 0x3, 24, 2}, + {VPU_DI_PRE, HHI_VPU_MEM_PD_REG0, 0x3, 26, 2}, + {VPU_DI_POST, HHI_VPU_MEM_PD_REG0, 0x3, 28, 2}, + {VPU_SHARP, HHI_VPU_MEM_PD_REG0, 0x3, 30, 2}, + {VPU_VIU2, HHI_VPU_MEM_PD_REG1, 0xf, 0, 4}, + {VPU_VKSTONE, HHI_VPU_MEM_PD_REG1, 0x3, 4, 2}, + {VPU_DOLBY_CORE3, HHI_VPU_MEM_PD_REG1, 0x3, 6, 2}, + {VPU_DOLBY0, HHI_VPU_MEM_PD_REG1, 0x3, 8, 2}, + {VPU_DOLBY1A, HHI_VPU_MEM_PD_REG1, 0x3, 10, 2}, + {VPU_DOLBY1B, HHI_VPU_MEM_PD_REG1, 0x3, 12, 2}, + {VPU_VPU_ARB, HHI_VPU_MEM_PD_REG1, 0x3, 14, 2}, + {VPU_AFBC_DEC, HHI_VPU_MEM_PD_REG1, 0x3, 16, 2}, + {VPU_VD2_SCALE, HHI_VPU_MEM_PD_REG1, 0x3, 18, 2}, + {VPU_VENCP, HHI_VPU_MEM_PD_REG1, 0x3, 20, 2}, + {VPU_VENCL, HHI_VPU_MEM_PD_REG1, 0x3, 22, 2}, + {VPU_VENCI, HHI_VPU_MEM_PD_REG1, 0x3, 24, 2}, + {VPU_LC_STTS, HHI_VPU_MEM_PD_REG1, 0x3, 26, 2}, + {VPU_LDIM_STTS, HHI_VPU_MEM_PD_REG1, 0x3, 28, 2}, + {VPU_VD2_OSD2_SCALE, HHI_VPU_MEM_PD_REG1, 0x3, 30, 2}, + {VPU_VIU_WM, HHI_VPU_MEM_PD_REG2, 0x3, 0, 2}, + {VPU_TCON, HHI_VPU_MEM_PD_REG2, 0x3, 2, 2}, + {VPU_VIU_OSD3, HHI_VPU_MEM_PD_REG2, 0x3, 4, 2}, + {VPU_VIU_OSD4, HHI_VPU_MEM_PD_REG2, 0x3, 6, 2}, + {VPU_MAIL_AFBCD, HHI_VPU_MEM_PD_REG2, 0x3, 8, 2}, + {VPU_VD1_SCALE, HHI_VPU_MEM_PD_REG2, 0x3, 10, 2}, + {VPU_OSD_BLD34, HHI_VPU_MEM_PD_REG2, 0x3, 12, 2}, + {VPU_PRIME_DOLBY_RAM, HHI_VPU_MEM_PD_REG2, 0x3, 14, 2}, + {VPU_VD2_OFIFO, HHI_VPU_MEM_PD_REG2, 0x3, 16, 2}, + {VPU_DS, HHI_VPU_MEM_PD_REG2, 0x3, 18, 2}, + {VPU_LUT3D, HHI_VPU_MEM_PD_REG2, 0x3, 20, 2}, + {VPU_DI_PRE, HHI_VPU_MEM_PD_REG2, 0x3, 24, 2}, + {VPU_DOLBY_S0, HHI_VPU_MEM_PD_REG2, 0x3, 26, 2}, + {VPU_DOLBY_S1, HHI_VPU_MEM_PD_REG2, 0x3, 28, 2}, + {VPU_RDMA, HHI_VPU_MEM_PD_REG2, 0x3, 30, 2}, + {VPU_TCON, HHI_VPU_MEM_PD_REG3, 0x3, 0, 16}, + {VPU_TCON, HHI_VPU_MEM_PD_REG3, 0x3, 16, 16}, + {VPU_AXI_WR1, HHI_VPU_MEM_PD_REG4, 0x3, 0, 2}, + {VPU_AXI_WR0, HHI_VPU_MEM_PD_REG4, 0x3, 2, 2}, + {VPU_DMA, HHI_VPU_MEM_PD_REG4, 0xf, 4, 4}, + {VPU_MOD_MAX, VPU_REG_END, 0, 0, 0}, +}; + /* ******************************************************* */ /* VPU clock gate table */ /* ******************************************************* */ @@ -579,7 +689,31 @@ static struct vpu_ctrl_s vpu_clk_gate_g12a[] = { }; /* ******************************************************* */ -/* VPU module init table */ +/* VPU_HDMI ISO pre: before reset */ +/* ******************************************************* */ +static struct vpu_ctrl_s vpu_hdmi_iso_pre_gxb[] = { + /* reg, val, bit, len */ + {AO_RTI_GEN_PWR_SLEEP0, 1, 8, 1}, + {VPU_REG_END, 0, 0, 0}, +}; + +/* ******************************************************* */ +/* VPU_HDMI ISO */ +/* ******************************************************* */ +static struct vpu_ctrl_s vpu_hdmi_iso_gxb[] = { + /* reg, val, bit, len */ + {AO_RTI_GEN_PWR_SLEEP0, 1, 9, 1}, + {VPU_REG_END, 0, 0, 0}, +}; + +static struct vpu_ctrl_s vpu_hdmi_iso_sm1[] = { + /* reg, val, bit, len */ + {AO_RTI_GEN_PWR_ISO0, 1, 8, 1}, + {VPU_REG_END, 0, 0, 0}, +}; + +/* ******************************************************* */ +/* VPU module init table */ /* ******************************************************* */ static struct vpu_ctrl_s vpu_module_init_gxm[] = { /* 0, reg, val, bit, len */ @@ -603,7 +737,7 @@ static struct vpu_ctrl_s vpu_module_init_txlx[] = { }; /* ******************************************************* */ -/* VPU reset table */ +/* VPU reset table */ /* ******************************************************* */ static struct vpu_reset_s vpu_reset_gx[] = { /* reg, mask */ diff --git a/drivers/amlogic/media/common/vpu/vpu_module.h b/drivers/amlogic/media/common/vpu/vpu_module.h index 30f0cd9b0401..72e1b4fa7c56 100644 --- a/drivers/amlogic/media/common/vpu/vpu_module.h +++ b/drivers/amlogic/media/common/vpu/vpu_module.h @@ -40,6 +40,7 @@ static char *vpu_mod_table[] = { "di_post", "viu_sharpness_line_buffer", + "viu2", "viu2_osd1", "viu2_osd2", "viu2_vd1", @@ -77,12 +78,14 @@ static char *vpu_mod_table[] = { "ds", "lut3d", "viu2_osd_rotation", - "vi_dipre", + "dolby_s0", + "dolby_s1", "rdma", "axi_wr1", "axi_wr0", "afbce", + "dma" "vpu_mod_max", diff --git a/drivers/amlogic/media/common/vpu/vpu_power_init.c b/drivers/amlogic/media/common/vpu/vpu_power_init.c index 07c5c848e638..35384e0d6934 100644 --- a/drivers/amlogic/media/common/vpu/vpu_power_init.c +++ b/drivers/amlogic/media/common/vpu/vpu_power_init.c @@ -44,6 +44,7 @@ void vpu_module_init_config(void) cnt = vpu_conf.data->module_init_table_cnt; ctrl_table = vpu_conf.data->module_init_table; if (ctrl_table) { + i = 0; while (i < cnt) { if (ctrl_table[i].reg == VPU_REG_END) break; @@ -60,7 +61,8 @@ void vpu_module_init_config(void) vpu_vcbus_write(VPU_RDARB_MODE_L1C1, 0x210000); vpu_vcbus_write(VPU_RDARB_MODE_L1C2, 0x10000); vpu_vcbus_write(VPU_RDARB_MODE_L2C1, 0x900000); - vpu_vcbus_write(VPU_WRARB_MODE_L2C1, 0x20000); + /*from vlsi feijun*/ + vpu_vcbus_write(VPU_WRARB_MODE_L2C1, 0x170000/*0x20000*/); if (vpu_debug_print_flag) VPUPR("%s finish\n", __func__); @@ -70,17 +72,32 @@ void vpu_power_on(void) { struct vpu_ctrl_s *ctrl_table; struct vpu_reset_s *reset_table; - unsigned int _reg, _bit, _len, mask; + unsigned int _reg, _val, _bit, _len, mask; int i = 0, cnt; VPUPR("vpu_power_on\n"); - vpu_ao_setb(AO_RTI_GEN_PWR_SLEEP0, 0, 8, 1); /* [8] power on */ + /* power on VPU_HDMI ISO */ + ctrl_table = vpu_conf.data->hdmi_iso_pre_table; + if (ctrl_table) { + i = 0; + while (i < VPU_HDMI_ISO_CNT_MAX) { + if (ctrl_table[i].reg == VPU_REG_END) + break; + _reg = ctrl_table[i].reg; + _val = 0; + _bit = ctrl_table[i].bit; + _len = ctrl_table[i].len; + vpu_ao_setb(_reg, _val, _bit, _len); + i++; + } + } udelay(20); /* power up memories */ cnt = vpu_conf.data->mem_pd_table_cnt; ctrl_table = vpu_conf.data->mem_pd_table; + i = 0; while (i < cnt) { if (ctrl_table[i].vmod == VPU_MOD_MAX) break; @@ -123,7 +140,20 @@ void vpu_power_on(void) } /* Remove VPU_HDMI ISO */ - vpu_ao_setb(AO_RTI_GEN_PWR_SLEEP0, 0, 9, 1); /* [9] VPU_HDMI */ + ctrl_table = vpu_conf.data->hdmi_iso_table; + if (ctrl_table) { + i = 0; + while (i < VPU_HDMI_ISO_CNT_MAX) { + if (ctrl_table[i].reg == VPU_REG_END) + break; + _reg = ctrl_table[i].reg; + _val = 0; + _bit = ctrl_table[i].bit; + _len = ctrl_table[i].len; + vpu_ao_setb(_reg, _val, _bit, _len); + i++; + } + } if (vpu_debug_print_flag) VPUPR("%s finish\n", __func__); @@ -139,12 +169,26 @@ void vpu_power_off(void) /* Power down VPU_HDMI */ /* Enable Isolation */ - vpu_ao_setb(AO_RTI_GEN_PWR_SLEEP0, 1, 9, 1); /* ISO */ + ctrl_table = vpu_conf.data->hdmi_iso_table; + if (ctrl_table) { + i = 0; + while (i < VPU_HDMI_ISO_CNT_MAX) { + if (ctrl_table[i].reg == VPU_REG_END) + break; + _reg = ctrl_table[i].reg; + _val = ctrl_table[i].val; + _bit = ctrl_table[i].bit; + _len = ctrl_table[i].len; + vpu_ao_setb(_reg, _val, _bit, _len); + i++; + } + } udelay(20); /* power down memories */ cnt = vpu_conf.data->mem_pd_table_cnt; ctrl_table = vpu_conf.data->mem_pd_table; + i = 0; while (i < cnt) { if (ctrl_table[i].vmod == VPU_MOD_MAX) break; @@ -166,7 +210,20 @@ void vpu_power_off(void) udelay(20); /* Power down VPU domain */ - vpu_ao_setb(AO_RTI_GEN_PWR_SLEEP0, 1, 8, 1); /* PDN */ + ctrl_table = vpu_conf.data->hdmi_iso_pre_table; + if (ctrl_table) { + i = 0; + while (i < VPU_HDMI_ISO_CNT_MAX) { + if (ctrl_table[i].reg == VPU_REG_END) + break; + _reg = ctrl_table[i].reg; + _val = ctrl_table[i].val; + _bit = ctrl_table[i].bit; + _len = ctrl_table[i].len; + vpu_ao_setb(_reg, _val, _bit, _len); + i++; + } + } vpu_hiu_setb(HHI_VAPBCLK_CNTL, 0, 8, 1); vpu_hiu_setb(HHI_VPU_CLK_CNTL, 0, 8, 1); diff --git a/drivers/amlogic/media/common/vpu/vpu_reg.h b/drivers/amlogic/media/common/vpu/vpu_reg.h index 4bac30b96647..903be7d6fdcc 100644 --- a/drivers/amlogic/media/common/vpu/vpu_reg.h +++ b/drivers/amlogic/media/common/vpu/vpu_reg.h @@ -28,7 +28,8 @@ * ********************************* */ -#define AO_RTI_GEN_PWR_SLEEP0 (0x3a << 2) +#define AO_RTI_GEN_PWR_SLEEP0 (0x03a << 2) +#define AO_RTI_GEN_PWR_ISO0 (0x03b << 2) /* HHI bus */ #define HHI_GP1_PLL_CNTL 0x16 @@ -42,6 +43,8 @@ #define HHI_VPU_MEM_PD_REG2 0x4d #define HHI_VPU_MEM_PD_REG3 0x4e #define HHI_VPU_MEM_PD_REG4 0x4c +#define HHI_VPU_MEM_PD_REG3_SM1 0x43 +#define HHI_VPU_MEM_PD_REG4_SM1 0x44 #define HHI_VPU_CLKC_CNTL 0x6d #define HHI_VPU_CLK_CNTL 0x6f diff --git a/drivers/amlogic/media/deinterlace/deinterlace.c b/drivers/amlogic/media/deinterlace/deinterlace.c index 4a0afc00e6e7..7dfbda56894a 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace.c +++ b/drivers/amlogic/media/deinterlace/deinterlace.c @@ -105,7 +105,7 @@ static int mpeg2vdin_en; #endif static int queue_print_flag = -1; -static int di_reg_unreg_cnt = 100; +static int di_reg_unreg_cnt = 1000; static bool overturn; static bool check_start_drop_prog; static bool mcpre_en = true; @@ -113,7 +113,7 @@ static bool mcpre_en = true; static bool mc_mem_alloc; static unsigned int di_pre_rdma_enable; - +static struct mutex di_event_mutex; static unsigned int di_force_bit_mode = 10; module_param(di_force_bit_mode, uint, 0664); @@ -129,7 +129,7 @@ static di_dev_t *de_devp; static dev_t di_devno; static struct class *di_clsp; -static const char version_s[] = "2018-12-04a"; +static const char version_s[] = "2019-0422b:vscale_skip v is odd"; static int bypass_state = 1; static int bypass_all; @@ -272,6 +272,8 @@ static int di_receiver_event_fun(int type, void *data, void *arg); static void di_uninit_buf(unsigned int disable_mirror); static void log_buffer_state(unsigned char *tag); /* static void put_get_disp_buf(void); */ +static unsigned int isbypass_flag = true; +static unsigned int needbypass_flag = true; static const struct vframe_receiver_op_s di_vf_receiver = { @@ -526,27 +528,57 @@ int get_di_dump_state_flag(void) } /*--------------------------*/ +static void parse_param_di(char *buf_orig, char **parm) +{ + char *ps, *token; + unsigned int n = 0; + char delim1[3] = " "; + char delim2[2] = "\n"; + + ps = buf_orig; + strcat(delim1, delim2); + while (1) { + token = strsep(&ps, delim1); + if (token == NULL) + break; + if (*token == '\0') + continue; + parm[n++] = token; + } +} + static ssize_t store_dbg(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { + u32 val; + char *buf_orig, *parm[8] = {NULL}; + + buf_orig = kstrdup(buf, GFP_KERNEL); + parse_param_di(buf_orig, (char **)&parm); if (strncmp(buf, "buf", 3) == 0) { struct di_buf_s *di_buf_tmp = 0; - if (kstrtoul(buf + 3, 16, (unsigned long *)&di_buf_tmp)) + if (kstrtoul(buf + 3, 16, (unsigned long *)&di_buf_tmp)) { + kfree(buf_orig); return count; + } dump_di_buf(di_buf_tmp); } else if (strncmp(buf, "vframe", 6) == 0) { vframe_t *vf = 0; - if (kstrtoul(buf + 6, 16, (unsigned long *)&vf)) + if (kstrtoul(buf + 6, 16, (unsigned long *)&vf)) { + kfree(buf_orig); return count; + } dump_vframe(vf); } else if (strncmp(buf, "pool", 4) == 0) { unsigned long idx = 0; - if (kstrtoul(buf + 4, 10, &idx)) + if (kstrtoul(buf + 4, 10, &idx)) { + kfree(buf_orig); return count; + } dump_pool(get_queue_by_idx(idx)); } else if (strncmp(buf, "state", 4) == 0) { dump_state(); @@ -576,12 +608,17 @@ store_dbg(struct device *dev, } else if (strncmp(buf, "pstep", 5) == 0) { pre_run_flag = DI_RUN_FLAG_STEP; } else if (strncmp(buf, "dumpreg", 7) == 0) { - if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) + if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) { dump_di_reg_g12(); - else + dump_afbcd_reg(); + } else pr_info("add new debugfs: cat /sys/kernel/debug/di/dumpreg\n"); + } else if (strncmp(buf, "dumpafbc", 8) == 0) { + dump_afbcd_reg(); } else if (strncmp(buf, "dumpmif", 7) == 0) { dump_mif_size_state(&di_pre_stru, &di_post_stru); + } else if (strncmp(buf, "dumppostmif", 11) == 0) { + dump_post_mif_reg(); } else if (strncmp(buf, "recycle_buf", 11) == 0) { recycle_keep_buffer(); } else if (strncmp(buf, "recycle_post", 12) == 0) { @@ -589,10 +626,38 @@ store_dbg(struct device *dev, di_vf_put(di_vf_get(NULL), NULL); } else if (strncmp(buf, "mem_map", 7) == 0) { dump_buf_addr(di_buf_local, MAX_LOCAL_BUF_NUM * 2); + } else if (strncmp(buf, "afbc_on", 7) == 0) { + if (kstrtoint(parm[1], 10, &val) < 0) { + kfree(buf_orig); + return count; + } + if (!val) + afbc_sw(false); + afbc_disable_flag = val > 0 ? 0:1; + pr_info("afbc_disable_flag:%d\n", afbc_disable_flag); } else { - pr_info("DI no support cmd %s!!!\n", buf); + pr_info("DI no support cmd %s\n", buf); + pr_info("supported cmd list:\n"); + pr_info("\t vframe\n"); + pr_info("\t state\n"); + pr_info("\t prog_proc_config 0/1\n"); + pr_info("\t init_flag 0/1\n"); + pr_info("\t run\n"); + pr_info("\t pause\n"); + pr_info("\t step\n"); + pr_info("\t prun\n"); + pr_info("\t ppause\n"); + pr_info("\t pstep\n"); + pr_info("\t dumpreg\n"); + pr_info("\t dumpmif\n"); + pr_info("\t dumppostmif\n"); + pr_info("\t recycle_buf\n"); + pr_info("\t recycle_post\n"); + pr_info("\t mem_map\n"); + pr_info("\t afbc_on 0/1\n"); } + kfree(buf_orig); return count; } static int __init di_read_canvas_reverse(char *str) @@ -1520,9 +1585,11 @@ static unsigned char is_source_change(vframe_t *vframe) ((di_pre_stru.cur_inp_type & VIDTYPE_VIU_FIELD) != (vframe->type & VIDTYPE_VIU_FIELD)) ) { - /* just scan mode changed */ - if (!di_pre_stru.force_interlace) - pr_dbg("DI I<->P.\n"); + if (is_progressive(vframe)) { + pr_dbg("DI I->P.\n"); + } else { + pr_dbg("DI P->I.\n"); + } return 2; } return 0; @@ -1548,16 +1615,15 @@ unsigned char is_bypass(vframe_t *vf_in) int ret = 0; static vframe_t vf_tmp; + isbypass_flag = true; if (di_debug_flag & 0x10000) /* for debugging */ return (di_debug_flag >> 17) & 0x1; if (bypass_all) return 1; - if (di_pre_stru.cur_prog_flag && - ( - (di_pre_stru.cur_width > 1920) || (di_pre_stru.cur_height > 1080) - || (di_pre_stru.cur_inp_type & VIDTYPE_VIU_444)) - ) + + if ((di_pre_stru.cur_prog_flag) && + (!di_pre_stru.force_interlace)) return 1; if ((di_pre_stru.cur_width < 16) || (di_pre_stru.cur_height < 16)) @@ -1627,7 +1693,7 @@ unsigned char is_bypass(vframe_t *vf_in) ) return 1; } - + isbypass_flag = false; return 0; } @@ -1878,6 +1944,7 @@ static unsigned int di_cma_alloc(struct di_dev_s *devp) unsigned int start_time, end_time, delta_time; struct di_buf_s *buf_p = NULL; int itmp, alloc_cnt = 0; + u8 *tmp; start_time = jiffies_to_msecs(jiffies); queue_for_each_entry(buf_p, ptmp, QUEUE_LOCAL_FREE, list) { @@ -1923,6 +1990,24 @@ static unsigned int di_cma_alloc(struct di_dev_s *devp) di_pre_stru.mtn_size + di_pre_stru.count_size + di_pre_stru.mv_size; + tmp = di_vmap(buf_p->mcinfo_adr, + di_pre_stru.mcinfo_size, + &buf_p->bflg_vmap); + + if (buf_p->bflg_vmap == true) + buf_p->mcinfo_vaddr = + (unsigned short *)tmp; + else { + if (tmp == NULL) { + buf_p->mcinfo_vaddr = + NULL; + pr_err("DI: %s vmap fail\n", + __func__); + } else { + buf_p->mcinfo_vaddr = + (unsigned short *)tmp; + } + } } } } @@ -1987,6 +2072,12 @@ static void di_cma_release(struct di_dev_s *devp) } if ((ii >= USED_LOCAL_BUF_MAX) && (buf_p->pages != NULL)) { + + if (buf_p->bflg_vmap == true) { + di_unmap_phyaddr((u8 *)buf_p->mcinfo_vaddr); + buf_p->bflg_vmap = false; + } + if (dma_release_from_contiguous(&(devp->pdev->dev), buf_p->pages, devp->buffer_size >> PAGE_SHIFT)) { @@ -2049,10 +2140,11 @@ static int di_init_buf(int width, int height, unsigned char prog_flag) unsigned int mv_canvas_width = width, canvas_align_width = 32; unsigned long di_post_mem = 0, nrds_mem = 0; struct di_buf_s *keep_buf = di_post_stru.keep_buf; + u8 *tmp; if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) canvas_align_width = 64; - + pr_info("di: %s -S\n", __func__); frame_count = 0; disp_frame_count = 0; cur_post_ready_di_buf = NULL; @@ -2100,7 +2192,8 @@ static int di_init_buf(int width, int height, unsigned char prog_flag) mtn_size = (mtn_width * canvas_height)*4/16; count_size = (mtn_width * canvas_height)*4/16; mv_size = (mv_width * canvas_height)/5; - mc_size = canvas_height; + mc_size = roundup(canvas_height >> 1, canvas_align_width) << 1; + if (mc_mem_alloc) { di_buf_size = nr_size + mtn_size + count_size + mv_size + mc_size; @@ -2153,33 +2246,71 @@ static int di_init_buf(int width, int height, unsigned char prog_flag) di_buf->canvas_width[NR_CANVAS] = nr_canvas_width; di_buf->canvas_width[MTN_CANVAS] = mtn_canvas_width; di_buf->canvas_width[MV_CANVAS] = mv_canvas_width; + if (prog_flag) { di_buf->canvas_height = canvas_height; - di_buf->nr_adr = de_devp->mem_start + - di_buf_size * i; + + //use reserved memory + if (de_devp->flag_cma == 0) + di_buf->nr_adr = de_devp->mem_start + + di_buf_size * i; + di_buf->canvas_config_flag = 1; } else { di_buf->canvas_height = (canvas_height>>1); - di_buf->nr_adr = de_devp->mem_start + - di_buf_size * i; - di_buf->mtn_adr = de_devp->mem_start + - di_buf_size * i + - nr_size; - di_buf->cnt_adr = de_devp->mem_start + - di_buf_size * i + - nr_size + mtn_size; + di_buf->canvas_height = + roundup(di_buf->canvas_height, + canvas_align_width); - if (mc_mem_alloc) { - di_buf->mcvec_adr = de_devp->mem_start + + //use reserved memory + if (de_devp->flag_cma == 0) { + di_buf->nr_adr = de_devp->mem_start + + di_buf_size * i; + di_buf->mtn_adr = de_devp->mem_start + di_buf_size * i + - nr_size + mtn_size + count_size; - di_buf->mcinfo_adr = - de_devp->mem_start + - di_buf_size * i + nr_size + - mtn_size + count_size + mv_size; + nr_size; + di_buf->cnt_adr = de_devp->mem_start + + di_buf_size * i + + nr_size + mtn_size; + + if (mc_mem_alloc) { + di_buf->mcvec_adr = + de_devp->mem_start + + di_buf_size * i + + nr_size + mtn_size + + count_size; + di_buf->mcinfo_adr = + de_devp->mem_start + + di_buf_size * i + + nr_size + + mtn_size + + count_size + mv_size; + tmp = di_vmap( + di_buf->mcinfo_adr, + di_pre_stru. + mcinfo_size, + &di_buf->bflg_vmap); + + if (di_buf->bflg_vmap == true) + di_buf->mcinfo_vaddr = + (unsigned short *)tmp; + else { + if (tmp == NULL) { + di_buf->mcinfo_vaddr = + NULL; + pr_err("DI: %s vmap fail\n", + __func__); + } else { + di_buf->mcinfo_vaddr = + (unsigned short *)tmp; + } + } + } } + di_buf->canvas_config_flag = 2; } + di_buf->index = i; di_buf->vframe = &(vframe_local[i]); di_buf->vframe->private_data = di_buf; @@ -2199,8 +2330,11 @@ static int di_init_buf(int width, int height, unsigned char prog_flag) up(&di_sema); } #endif - di_post_mem = de_devp->mem_start + - di_buf_size*de_devp->buf_num_avail; + + //use reserved memory + if (de_devp->flag_cma == 0) + di_post_mem = de_devp->mem_start + + di_buf_size*de_devp->buf_num_avail; if (post_wr_en && post_wr_support) { di_post_buf_size = nr_width * canvas_height * 2; /* pre buffer must 2 more than post buffer */ @@ -2248,8 +2382,11 @@ static int di_init_buf(int width, int height, unsigned char prog_flag) (nr_width << 1); di_buf->canvas_height = canvas_height; di_buf->canvas_config_flag = 1; - di_buf->nr_adr = di_post_mem + - di_post_buf_size*i; + + //use reserved memory + if (de_devp->flag_cma == 0) + di_buf->nr_adr = di_post_mem + + di_post_buf_size*i; } queue_in(di_buf, QUEUE_POST_FREE); } @@ -2261,6 +2398,7 @@ static int di_init_buf(int width, int height, unsigned char prog_flag) nr_ds_buf_init(de_devp->flag_cma, nrds_mem, &(de_devp->pdev->dev)); } + pr_info("di: %s -E\n", __func__); return 0; } @@ -2419,6 +2557,11 @@ static void dump_state(void) dump_state_flag = 1; pr_info("version %s, init_flag %d, is_bypass %d\n", version_s, init_flag, is_bypass(NULL)); + pr_info("isbypass_flag %d, needbypass_flag %d\n", + isbypass_flag, needbypass_flag); + pr_info("di_pre_stru.bypass_flag=%d\n", + di_pre_stru.bypass_flag); + pr_info("afbcd support %d\n", afbc_is_supported()); pr_info("recovery_flag = %d, recovery_log_reason=%d, di_blocking=%d", recovery_flag, recovery_log_reason, di_blocking); pr_info("recovery_log_queue_idx=%d, recovery_log_di_buf=0x%p\n", @@ -2826,6 +2969,7 @@ static void pre_de_process(void) } else config_di_mif(&di_pre_stru.di_chan2_mif, di_pre_stru.di_chan2_buf_dup_p); + config_di_wr_mif(&di_pre_stru.di_nrwr_mif, &di_pre_stru.di_mtnwr_mif, di_pre_stru.di_wr_buf); @@ -2879,9 +3023,6 @@ static void pre_de_process(void) * we need to only leave one mask open * to prevent multiple entry for de_irq */ - - - enable_di_pre_aml(&di_pre_stru.di_inp_mif, &di_pre_stru.di_mem_mif, &di_pre_stru.di_chan2_mif, @@ -3043,7 +3184,8 @@ static void pre_de_done_buf_config(void) &glb_field_mot_num); if (pulldown_enable) pulldown_detection(&post_wr_buf->pd_config, - di_pre_stru.mtn_status, overturn); + di_pre_stru.mtn_status, overturn, + di_pre_stru.di_inp_buf->vframe); if (combing_fix_en) cur_lev = adaptive_combing_fixing( di_pre_stru.mtn_status, @@ -3350,9 +3492,14 @@ static bool pps_en; module_param_named(pps_en, pps_en, bool, 0644); static unsigned int pps_position = 1; module_param_named(pps_position, pps_position, uint, 0644); -static unsigned int pre_enable_mask = 3; +static unsigned int pre_enable_mask = 3;/*bit0:ma bit1:mc*/ module_param_named(pre_enable_mask, pre_enable_mask, uint, 0644); +static bool pre_hsc_down_en; +module_param_named(pre_hsc_down_en, pre_hsc_down_en, bool, 0644); +static int pre_hsc_down_width = 480; +module_param_named(pre_hsc_down_width, pre_hsc_down_width, int, 0644); + static unsigned char pre_de_buf_config(void) { struct di_buf_s *di_buf = NULL; @@ -3383,7 +3530,6 @@ static unsigned char pre_de_buf_config(void) #endif ) return 0; - di_patch_post_update_mc_sw(DI_MC_SW_OTHER, false); } else if (di_pre_stru.prog_proc_type == 2) { di_linked_buf_idx = peek_free_linked_buf(); @@ -3427,10 +3573,18 @@ static unsigned char pre_de_buf_config(void) if (vframe == NULL) return 0; - if (vframe->type & VIDTYPE_COMPRESS) { - vframe->width = vframe->compWidth; - vframe->height = vframe->compHeight; + /*for support compress from dec*/ + if (IS_COMP_MODE(vframe->type)) { + if (IS_VDIN_SRC(vframe->source_type) + && IS_I_SRC(vframe->type)) { + vframe->width = vframe->compWidth; + vframe->height = vframe->compHeight*2; + } else { + vframe->width = vframe->compWidth; + vframe->height = vframe->compHeight; + } } + di_print("DI: get %dth vf[0x%p] from frontend %u ms.\n", di_pre_stru.in_seq, vframe, jiffies_to_msecs(jiffies_64 - vframe->ready_jiffies64)); @@ -3515,8 +3669,11 @@ jiffies_to_msecs(jiffies_64 - vframe->ready_jiffies64)); queue_out(di_buf); change_type = is_source_change(vframe); /* source change, when i mix p,force p as i*/ - if (change_type == 1 || (change_type == 2 && - di_pre_stru.cur_prog_flag == 1)) { + if (change_type == 1 || (change_type == 2)) { + /* check if top/bot interleaved */ + if (change_type == 2) + /* source is i interleaves p fields */ + di_pre_stru.force_interlace = true; if (di_pre_stru.di_mem_buf_dup_p) { /*avoid only 2 i field then p field*/ if ( @@ -3565,15 +3722,25 @@ jiffies_to_msecs(jiffies_64 - vframe->ready_jiffies64)); di_buf->vframe->width, di_buf->vframe->height, di_buf->vframe->source_type); - if (di_buf->type & VIDTYPE_COMPRESS) { - di_pre_stru.cur_width = - di_buf->vframe->compWidth; - di_pre_stru.cur_height = - di_buf->vframe->compHeight; + + if (IS_COMP_MODE(di_buf->vframe->type)) { + if (IS_VDIN_SRC(di_buf->vframe->source_type) && + IS_I_SRC(di_buf->vframe->type)) { + di_pre_stru.cur_width = + di_buf->vframe->compWidth; + di_pre_stru.cur_height = + di_buf->vframe->compHeight*2; + } else { + di_pre_stru.cur_width = + di_buf->vframe->compWidth; + di_pre_stru.cur_height = + di_buf->vframe->compHeight; + } } else { di_pre_stru.cur_width = di_buf->vframe->width; di_pre_stru.cur_height = di_buf->vframe->height; } + di_pre_stru.cur_prog_flag = is_progressive(di_buf->vframe); if (di_pre_stru.cur_prog_flag) { @@ -3609,10 +3776,6 @@ jiffies_to_msecs(jiffies_64 - vframe->ready_jiffies64)); #endif di_pre_stru.field_count_for_cont = 0; } else if (di_pre_stru.cur_prog_flag == 0) { - /* check if top/bot interleaved */ - if (change_type == 2) - /* source is i interleaves p fields */ - di_pre_stru.force_interlace = true; if ((di_pre_stru.cur_inp_type & VIDTYPE_TYPEMASK) == (di_buf->vframe->type & VIDTYPE_TYPEMASK)) { @@ -3785,11 +3948,24 @@ jiffies_to_msecs(jiffies_64 - vframe->ready_jiffies64)); } } } else { + /*********************************/ + if ((di_buf->vframe->width >= 1920) && + (di_buf->vframe->height >= 1080) && + is_meson_tl1_cpu()) { + if (combing_fix_en) { + combing_fix_en = false; + fix_tl1_1080i_sawtooth_patch(); + } + } else + combing_fix_en = true; + + /*********************************/ if ( di_pre_stru.di_chan2_buf_dup_p == NULL) { di_pre_stru.field_count_for_cont = 0; /* ignore contp2rd and contprd */ } + di_buf->post_proc_flag = 1; di_pre_stru.di_inp_buf = di_buf; di_print("%s: %s[%d] => di_inp_buf\n", __func__, @@ -3853,7 +4029,11 @@ jiffies_to_msecs(jiffies_64 - vframe->ready_jiffies64)); vframe_type_name[di_buf->di_wr_linked_buf->type], di_buf->di_wr_linked_buf->index); #endif - if (di_pre_stru.cur_inp_type & VIDTYPE_COMPRESS) { + + /*for support compress from dec, not from vdin*/ + if (IS_COMP_MODE(di_pre_stru.cur_inp_type) && + (!(di_pre_stru.cur_inp_type & VIDTYPE_VIU_422))) { + /*compress type and not from vdin*/ di_pre_stru.di_inp_buf->vframe->width = di_pre_stru.di_inp_buf->vframe->compWidth; di_pre_stru.di_inp_buf->vframe->height = @@ -3875,7 +4055,15 @@ jiffies_to_msecs(jiffies_64 - vframe->ready_jiffies64)); } if (pps_dsth != di_buf->vframe->height) di_buf->vframe->height = pps_dsth; + } else if (de_devp->h_sc_down_en) { + if (pre_hsc_down_width != di_buf->vframe->width) { + pr_info("di: hscd %d to %d\n", di_buf->vframe->width, + pre_hsc_down_width); + di_buf->vframe->width = pre_hsc_down_width; + di_pre_stru.width_bk = pre_hsc_down_width; + } } + if (di_force_bit_mode == 10) { di_buf->vframe->bitdepth |= (BITDEPTH_Y10); if (full_422_pack) @@ -3908,7 +4096,6 @@ jiffies_to_msecs(jiffies_64 - vframe->ready_jiffies64)); if (bypass_state == 0) di_buf->vframe->type |= VIDTYPE_PRE_INTERLACE; } - if (is_bypass_post()) { if (bypass_post_state == 0) di_pre_stru.source_change_flag = 1; @@ -4265,6 +4452,10 @@ static irqreturn_t de_irq(int irq, void *dev_instance) trace_di_pre("PRE-IRQ-0", di_pre_stru.field_count_for_cont, di_pre_stru.irq_time[0]); + /*add from valsi wang.feng*/ + di_arb_sw(false); + di_arb_sw(true); + if (mcpre_en) { get_mcinfo_from_reg_in_irq(); if ((is_meson_gxlx_cpu() && @@ -4272,8 +4463,7 @@ static irqreturn_t de_irq(int irq, void *dev_instance) is_meson_txhd_cpu()) mc_pre_mv_irq(); calc_lmv_base_mcinfo((di_pre_stru.cur_height>>1), - di_pre_stru.di_wr_buf->mcinfo_adr, - di_pre_stru.mcinfo_size); + di_pre_stru.di_wr_buf->mcinfo_vaddr); } nr_process_in_irq(); if ((data32&0x200) && de_devp->nrds_enable) @@ -4398,6 +4588,7 @@ static void vscale_skip_disable_post(struct di_buf_s *di_buf, vframe_t *disp_vf) disp_vf->height = di_buf_i->vframe->height; disp_vf->duration = di_buf_i->vframe->duration; disp_vf->pts = di_buf_i->vframe->pts; + disp_vf->pts_us64 = di_buf_i->vframe->pts_us64; disp_vf->flag = di_buf_i->vframe->flag; disp_vf->canvas0Addr = di_post_idx[di_post_stru.canvas_id][0]; disp_vf->canvas1Addr = di_post_idx[di_post_stru.canvas_id][0]; @@ -4629,9 +4820,16 @@ de_post_process(void *arg, unsigned int zoom_start_x_lines, di_end_y = zoom_end_y_lines; di_height = di_end_y - di_start_y + 1; di_height = di_height / (di_vscale_skip_count_real + 1); + /* make sure the height is even number */ - if (di_height%2) - di_height++; + if (di_height%2) { + /*for skip mode,post only half line-1*/ + if (((di_height > 150) && (di_height < 1080)) && + di_vscale_skip_count_real) + di_height = di_height - 3; + else + di_height++; + } if (Rd(DI_POST_SIZE) != ((di_width - 1) | ((di_height - 1) << 16)) || di_post_stru.buf_type != di_buf->di_buf_dup_p[0]->type || @@ -4886,10 +5084,10 @@ de_post_process(void *arg, unsigned int zoom_start_x_lines, /*it means use previous field for MC*/ /*else not pulldown,mcdi_mcpreflag is 2*/ /*it means use forward & previous field for MC*/ - if (is_meson_txhd_cpu()) + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TXHD)) mc_pre_flag = 2; } else { - if (is_meson_txhd_cpu()) + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TXHD)) mc_pre_flag = 1; post_blend_mode = 1; } @@ -4926,8 +5124,7 @@ de_post_process(void *arg, unsigned int zoom_start_x_lines, di_post_stru.di_mcvecrd_mif.canvas_num = di_buf->di_buf_dup_p[2]->mcvec_canvas_idx; mc_pre_flag = is_meson_txl_cpu()?0:(overturn?1:0); - if (is_meson_txlx_cpu() || is_meson_gxlx_cpu() || - is_meson_txhd_cpu()) + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TXLX)) invert_mv = true; else if (!overturn) di_post_stru.di_buf2_mif.canvas0_addr0 = @@ -4939,10 +5136,10 @@ de_post_process(void *arg, unsigned int zoom_start_x_lines, /*it means use previous field for MC*/ /*else not pulldown,mcdi_mcpreflag is 2*/ /*it means use forward & previous field for MC*/ - if (is_meson_txhd_cpu()) + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TXHD)) mc_pre_flag = 2; } else { - if (is_meson_txhd_cpu()) + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TXHD)) mc_pre_flag = 1; post_blend_mode = 1; } @@ -5095,7 +5292,10 @@ de_post_process(void *arg, unsigned int zoom_start_x_lines, is_meson_gxlx_cpu() || is_meson_txhd_cpu() || is_meson_g12a_cpu() || - is_meson_g12b_cpu()) { + is_meson_g12b_cpu() || + is_meson_tl1_cpu() || + is_meson_tm2_cpu() || + is_meson_sm1_cpu()) { di_post_read_reverse_irq(overturn, mc_pre_flag, post_blend_en ? mcpre_en : false); /* disable mc for first 2 fieldes mv unreliable */ @@ -5259,16 +5459,20 @@ void drop_frame(int check_drop, int throw_flag, struct di_buf_s *di_buf) int i = 0, drop_flag = 0; di_lock_irqfiq_save(irq_flag2); - if ((frame_count == 0) && check_drop) + if ((frame_count == 0) && check_drop) { di_post_stru.start_pts = di_buf->vframe->pts; + di_post_stru.start_pts_us64 = di_buf->vframe->pts_us64; + } if ((check_drop && (frame_count < start_frame_drop_count)) || throw_flag) { drop_flag = 1; } else { if (check_drop && (frame_count == start_frame_drop_count)) { if ((di_post_stru.start_pts) - && (di_buf->vframe->pts == 0)) + && (di_buf->vframe->pts == 0)) { di_buf->vframe->pts = di_post_stru.start_pts; + di_buf->vframe->pts_us64 = di_post_stru.start_pts_us64; + } di_post_stru.start_pts = 0; } for (i = 0; i < 3; i++) { @@ -5873,10 +6077,21 @@ static void di_unreg_process_irq(void) #endif adpative_combing_exit(); enable_di_pre_mif(false, mcpre_en); - afbc_reg_sw(false); + /*disable afbc module when afbc working in DI*/ + afbc_reg_unreg_flag = 0; + #if 0 + if (IS_COMP_MODE(di_pre_stru.cur_inp_type) && + (!needbypass_flag && !isbypass_flag)) { + pr_info("DI: disable afbc\n"); + afbc_reg_sw(false); + afbc_input_sw(false); + } + #endif di_hw_uninit(); if (is_meson_txlx_cpu() || is_meson_txhd_cpu() - || is_meson_g12a_cpu() || is_meson_g12b_cpu()) { + || is_meson_g12a_cpu() || is_meson_g12b_cpu() + || is_meson_tl1_cpu() || is_meson_sm1_cpu() || + is_meson_tm2_cpu()) { di_pre_gate_control(false, mcpre_en); nr_gate_control(false); } else if (cpu_after_eq(MESON_CPU_MAJOR_ID_GXTVBB)) { @@ -5888,7 +6103,9 @@ static void di_unreg_process_irq(void) if (mirror_disable) { di_hw_disable(mcpre_en); if (is_meson_txlx_cpu() || is_meson_txhd_cpu() - || is_meson_g12a_cpu() || is_meson_g12b_cpu()) { + || is_meson_g12a_cpu() || is_meson_g12b_cpu() + || is_meson_tl1_cpu() || is_meson_sm1_cpu() || + is_meson_tm2_cpu()) { enable_di_post_mif(GATE_OFF); di_post_gate_control(false); di_top_gate_control(false, false); @@ -6000,7 +6217,9 @@ static void di_pre_size_change(unsigned short width, is_meson_gxlx_cpu() || is_meson_txhd_cpu() || is_meson_g12a_cpu() || - is_meson_g12b_cpu()) + is_meson_g12b_cpu() || + is_meson_tl1_cpu() || is_meson_tm2_cpu() || + is_meson_sm1_cpu()) film_mode_win_config(width, height); } if (cpu_after_eq(MESON_CPU_MAJOR_ID_TXL)) @@ -6032,6 +6251,15 @@ static void di_pre_size_change(unsigned short width, pps_h = di_pre_stru.cur_height>>1; di_pps_config(1, pps_w, pps_h, pps_dstw, (pps_dsth>>1)); } + + if (de_devp->h_sc_down_en) { + pps_w = di_pre_stru.cur_width; + di_inp_hsc_setting(pps_w, pre_hsc_down_width); + } else { + di_inp_hsc_setting(di_pre_stru.cur_width, + di_pre_stru.cur_width); + } + di_interrupt_ctrl(di_pre_stru.madi_enable, det3d_en?1:0, de_devp->nrds_enable, @@ -6041,6 +6269,7 @@ static void di_pre_size_change(unsigned short width, static bool need_bypass(struct vframe_s *vf) { + needbypass_flag = true; if (vf->type & VIDTYPE_MVC) return true; @@ -6074,6 +6303,7 @@ static bool need_bypass(struct vframe_s *vf) (vf->width > 720)) return true; + needbypass_flag = false; return false; } @@ -6095,6 +6325,7 @@ static void di_reg_process_irq(void) if (pre_run_flag == DI_RUN_FLAG_STEP) pre_run_flag = DI_RUN_FLAG_STEP_DONE; + di_pre_stru.reg_irq_busy = true; vframe = vf_peek(VFM_NAME); @@ -6106,6 +6337,7 @@ static void di_reg_process_irq(void) } di_pre_stru.bypass_flag = true; di_patch_post_update_mc_sw(DI_MC_SW_OTHER, false); + di_pre_stru.reg_irq_busy = false; return; } else { di_pre_stru.bypass_flag = false; @@ -6126,6 +6358,8 @@ static void di_reg_process_irq(void) } de_devp->nrds_enable = nrds_en; de_devp->pps_enable = pps_en; + /*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); if (post_wr_en && post_wr_support) diwr_set_power_control(1); @@ -6143,6 +6377,8 @@ static void di_reg_process_irq(void) de_devp->flags |= DI_VPU_CLKB_SET; enable_di_pre_mif(false, mcpre_en); di_pre_gate_control(true, mcpre_en); + di_rst_protect(true);/*2019-01-22 by VLSI feng.wang*/ + di_pre_nr_wr_done_sel(true); nr_gate_control(true); } else { /* if mcdi enable DI_CLKG_CTRL should be 0xfef60000 */ @@ -6192,9 +6428,15 @@ static void di_reg_process_irq(void) spin_unlock_irqrestore(&plist_lock, flags); #endif } + if (!reg_flag) + pr_err("di: warning unreg in reg irq\n"); calc_lmv_init(); first_field_type = (vframe->type & VIDTYPE_TYPEMASK); + + //pr_info("%s , %d\n", __func__, __LINE__); + //pr_info("filed type:0x%x, in H=%d, V=%d\n", + // first_field_type, vframe->width, nr_height); di_pre_size_change(vframe->width, nr_height, first_field_type); @@ -6206,11 +6448,13 @@ static void di_reg_process_irq(void) vframe->sig_fmt); di_patch_post_update_mc_sw(DI_MC_SW_REG, true); + cue_int(); if (de_devp->flags & DI_LOAD_REG_FLAG) up(&di_sema); init_flag = 1; di_pre_stru.reg_req_flag_irq = 1; } + di_pre_stru.reg_irq_busy = false; } static void di_process(void) @@ -6385,11 +6629,14 @@ static int di_task_handle(void *data) di_pre_stru.disable_req_flag) && (di_pre_stru.pre_de_busy == 0)) { di_unreg_process(); + #if 0 + /* if mirror mode, can't speed down the clk*/ /* set min rate for power saving */ if (de_devp->vpu_clkb) { clk_set_rate(de_devp->vpu_clkb, de_devp->clkb_min_rate); } + #endif } if (di_pre_stru.reg_req_flag_irq || di_pre_stru.reg_req_flag) { @@ -6430,7 +6677,9 @@ static int di_task_handle(void *data) #endif } } - if (is_meson_g12a_cpu() || is_meson_g12b_cpu()) { + if (is_meson_g12a_cpu() || is_meson_g12b_cpu() + || is_meson_tl1_cpu() || is_meson_tm2_cpu() || + is_meson_sm1_cpu()) { #ifdef CLK_TREE_SUPPORT clk_set_rate(de_devp->vpu_clkb, de_devp->clkb_max_rate); @@ -6493,20 +6742,25 @@ static int di_receiver_event_fun(int type, void *data, void *arg) { int i; ulong flags; + char *provider_name = (char *)data; if (type == VFRAME_EVENT_PROVIDER_QUREY_VDIN2NR) { return di_pre_stru.vdin2nr; } else if (type == VFRAME_EVENT_PROVIDER_UNREG) { + mutex_lock(&di_event_mutex); pr_dbg("%s , is_bypass() %d trick_mode %d bypass_all %d\n", __func__, is_bypass(NULL), trick_mode, bypass_all); - pr_info("%s: vf_notify_receiver unreg\n", __func__); + di_pre_stru.vdin_source = false; + pr_info("DI: %s: unreg\n", __func__); + pr_info("DI: provider name:%s\n", provider_name); di_pre_stru.unreg_req_flag = 1; di_pre_stru.vdin_source = false; trigger_pre_di_process(TRIGGER_PRE_BY_PROVERDER_UNREG); di_pre_stru.unreg_req_flag_cnt = 0; - while (di_pre_stru.unreg_req_flag) { - usleep_range(10000, 10001); + while (di_pre_stru.unreg_req_flag || + di_pre_stru.reg_irq_busy) { + usleep_range(1000, 1001); if (di_pre_stru.unreg_req_flag_cnt++ > di_reg_unreg_cnt) { reg_unreg_timeout_cnt++; @@ -6533,6 +6787,8 @@ static int di_receiver_event_fun(int type, void *data, void *arg) if (di_pre_stru.vdin_source) DI_Wr_reg_bits(VDIN_WR_CTRL, 0x3, 24, 3); #endif + mutex_unlock(&di_event_mutex); + pr_info("DI: unreg f\n"); } else if (type == VFRAME_EVENT_PROVIDER_RESET) { di_blocking = 1; @@ -6693,24 +6949,29 @@ light_unreg: } #endif } else if (type == VFRAME_EVENT_PROVIDER_REG) { - char *provider_name = (char *)data; char *receiver_name = NULL; + + mutex_lock(&di_event_mutex); if (de_devp->flags & DI_SUSPEND_FLAG) { pr_err("[DI] reg event device hasn't resumed\n"); + mutex_unlock(&di_event_mutex); return -1; } - bypass_state = 0; - di_pre_stru.reg_req_flag = 1; - pr_dbg("%s: vframe provider reg %s\n", __func__, - provider_name); if (reg_flag) { pr_err("[DI] no muti instance.\n"); + mutex_unlock(&di_event_mutex); return -1; } + pr_info("%s: vframe provider reg %s\n", __func__, + provider_name); + + bypass_state = 0; + di_pre_stru.reg_req_flag = 1; trigger_pre_di_process(TRIGGER_PRE_BY_PROVERDER_REG); + /*check unreg process*/ di_pre_stru.reg_req_flag_cnt = 0; while (di_pre_stru.reg_req_flag) { - usleep_range(10000, 10001); + usleep_range(1000, 1001); if (di_pre_stru.reg_req_flag_cnt++ > di_reg_unreg_cnt) { reg_unreg_timeout_cnt++; pr_dbg("%s:reg_req_flag timeout!!!\n", @@ -6738,6 +6999,8 @@ light_unreg: } else { pr_info("%s error receiver is null.\n", __func__); } + mutex_unlock(&di_event_mutex); + pr_info("DI: reg f\n"); } #ifdef DET3D else if (type == VFRAME_EVENT_PROVIDER_SET_3D_VFRAME_INTERLEAVE) { @@ -6756,7 +7019,7 @@ light_unreg: return 0; } - +#if 0 static void fast_process(void) { int i; @@ -6813,7 +7076,7 @@ static void fast_process(void) } } } - +#endif static vframe_t *di_vf_peek(void *arg) { vframe_t *vframe_ret = NULL; @@ -6831,7 +7094,7 @@ static vframe_t *di_vf_peek(void *arg) log_buffer_state("pek"); - fast_process(); + /*fast_process();*/ #ifdef SUPPORT_START_FRAME_HOLD if ((disp_frame_count == 0) && (is_bypass(NULL) == 0)) { int ready_count = list_count(QUEUE_POST_READY); @@ -7375,7 +7638,9 @@ static void set_di_flag(void) is_meson_gxlx_cpu() || is_meson_txhd_cpu() || is_meson_g12a_cpu() || - is_meson_g12b_cpu()) { + is_meson_g12b_cpu() || + is_meson_tl1_cpu() || is_meson_tm2_cpu() || + is_meson_sm1_cpu()) { mcpre_en = true; mc_mem_alloc = true; pulldown_enable = false; @@ -7392,7 +7657,9 @@ static void set_di_flag(void) is_meson_gxlx_cpu() || is_meson_txhd_cpu() || is_meson_g12a_cpu() || - is_meson_g12b_cpu()) { + is_meson_g12b_cpu() || + is_meson_tl1_cpu() || is_meson_tm2_cpu() || + is_meson_sm1_cpu()) { full_422_pack = true; } @@ -7403,7 +7670,9 @@ static void set_di_flag(void) full_422_pack = false; } post_hold_line = - (is_meson_g12a_cpu() || is_meson_g12b_cpu())?10:17; + (is_meson_g12a_cpu() || is_meson_g12b_cpu() + || is_meson_tl1_cpu() || is_meson_tm2_cpu() || + is_meson_sm1_cpu())?10:17; } else { post_hold_line = 8; /*2019-01-10: from VLSI feijun*/ mcpre_en = false; @@ -7413,6 +7682,8 @@ static void set_di_flag(void) use_2_interlace_buff = 0; di_force_bit_mode = 8; } + if (is_meson_tl1_cpu() || is_meson_tm2_cpu()) + pulldown_enable = true; if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) intr_mode = 3; if (di_pre_rdma_enable) { @@ -7423,6 +7694,7 @@ static void set_di_flag(void) pldn_dly1 = 2; } + mtn_int_combing_glbmot(); } static const struct reserved_mem_ops rmem_di_ops = { @@ -7516,6 +7788,8 @@ static int di_probe(struct platform_device *pdev) "nrds-enable", &(di_devp->nrds_enable)); ret = of_property_read_u32(pdev->dev.of_node, "pps-enable", &(di_devp->pps_enable)); + /*di pre h scaling down :sm1 tm2*/ + di_devp->h_sc_down_en = pre_hsc_down_en; if (di_devp->flag_cma >= 1) { #ifdef CONFIG_CMA @@ -7605,6 +7879,7 @@ static int di_probe(struct platform_device *pdev) device_create_file(di_devp->dev, &dev_attr_tvp_region); pd_device_files_add(di_devp->dev); nr_drv_init(di_devp->dev); + mutex_init(&di_event_mutex); init_flag = 0; reg_flag = 0; @@ -7617,13 +7892,14 @@ static int di_probe(struct platform_device *pdev) vf_reg_receiver(&di_vf_recv); vf_provider_init(&di_vf_prov, VFM_NAME, &deinterlace_vf_provider, NULL); active_flag = 1; + sema_init(&di_sema, 1); ret = request_irq(di_devp->pre_irq, &de_irq, IRQF_SHARED, "pre_di", (void *)"pre_di"); if (di_devp->post_wr_support) { ret = request_irq(di_devp->post_irq, &post_irq, IRQF_SHARED, "post_di", (void *)"post_di"); } - sema_init(&di_sema, 1); + //sema_init(&di_sema, 1); di_sema_init_flag = 1; di_hw_init(pulldown_enable, mcpre_en); set_di_flag(); @@ -7744,6 +8020,29 @@ static void di_shutdown(struct platform_device *pdev) } #ifdef CONFIG_PM + +static void di_clear_for_suspend(struct di_dev_s *di_devp) +{ + pr_info("%s\n", __func__); + + di_unreg_process();/*have flag*/ + if (di_pre_stru.unreg_req_flag_irq) + di_unreg_process_irq(); + +#ifdef CONFIG_CMA + if (di_pre_stru.cma_release_req) { + pr_info("\tcma_release\n"); + atomic_set(&di_devp->mem_flag, 0); + di_cma_release(di_devp); + di_pre_stru.cma_release_req = 0; + di_pre_stru.cma_alloc_done = 0; + } +#endif + hrtimer_cancel(&di_pre_hrtimer); + tasklet_kill(&di_pre_tasklet); //ary.sui + tasklet_disable(&di_pre_tasklet); + pr_info("%s end\n", __func__); +} static int save_init_flag; /* must called after lcd */ static int di_suspend(struct device *dev) @@ -7753,9 +8052,13 @@ static int di_suspend(struct device *dev) di_devp = dev_get_drvdata(dev); di_devp->flags |= DI_SUSPEND_FLAG; + + di_clear_for_suspend(di_devp);//add + /* fix suspend/resume crash problem */ save_init_flag = init_flag; init_flag = 0; +#if 0 /*2019-01-18*/ if (di_pre_stru.di_inp_buf) { if (vframe_in[di_pre_stru.di_inp_buf->index]) { vf_put(vframe_in[di_pre_stru.di_inp_buf->index], @@ -7765,7 +8068,7 @@ static int di_suspend(struct device *dev) VFRAME_EVENT_RECEIVER_PUT, NULL); } } - +#endif if (!is_meson_txlx_cpu()) switch_vpu_clk_gate_vmod(VPU_VPU_CLKB, @@ -7781,10 +8084,21 @@ static int di_resume(struct device *dev) struct di_dev_s *di_devp = NULL; di_devp = dev_get_drvdata(dev); + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TXL)) clk_prepare_enable(di_devp->vpu_clkb); init_flag = save_init_flag; di_devp->flags &= ~DI_SUSPEND_FLAG; + /*2018-01-18*/ + pr_info("%s\n", __func__); + tasklet_init(&di_pre_tasklet, pre_tasklet, + (unsigned long)(&di_pre_stru)); + tasklet_disable(&di_pre_tasklet); + hrtimer_init(&di_pre_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + di_pre_hrtimer.function = di_pre_hrtimer_func; + hrtimer_start(&di_pre_hrtimer, ms_to_ktime(10), HRTIMER_MODE_REL); + tasklet_enable(&di_pre_tasklet); + /************/ pr_info("di: resume module\n"); return 0; } @@ -7943,8 +8257,8 @@ module_param_named(overturn, overturn, bool, 0664); module_param_named(queue_print_flag, queue_print_flag, int, 0664); module_param_named(full_422_pack, full_422_pack, bool, 0644); module_param_named(cma_print, cma_print, bool, 0644); -#ifdef DEBUG_SUPPORT module_param_named(pulldown_enable, pulldown_enable, bool, 0644); +#ifdef DEBUG_SUPPORT #ifdef RUN_DI_PROCESS_IN_IRQ module_param_named(input2pre, input2pre, uint, 0664); module_param_named(input2pre_buf_miss_count, input2pre_buf_miss_count, diff --git a/drivers/amlogic/media/deinterlace/deinterlace.h b/drivers/amlogic/media/deinterlace/deinterlace.h index 0e38fdd681de..5fa47f5d7029 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace.h +++ b/drivers/amlogic/media/deinterlace/deinterlace.h @@ -75,6 +75,16 @@ #endif #endif +#define IS_VDIN_SRC(src) ( \ + (src == VFRAME_SOURCE_TYPE_TUNER) || \ + (src == VFRAME_SOURCE_TYPE_CVBS) || \ + (src == VFRAME_SOURCE_TYPE_COMP) || \ + (src == VFRAME_SOURCE_TYPE_HDMI)) + +#define IS_I_SRC(vftype) (vftype & VIDTYPE_INTERLACE_BOTTOM) + +#define IS_COMP_MODE(vftype) (vftype & VIDTYPE_COMPRESS) + enum process_fun_index_e { PROCESS_FUN_NULL = 0, PROCESS_FUN_DI, @@ -117,6 +127,8 @@ struct di_buf_s { int cnt_canvas_idx; unsigned long mcinfo_adr; int mcinfo_canvas_idx; + unsigned short *mcinfo_vaddr; + bool bflg_vmap; unsigned long mcvec_adr; int mcvec_canvas_idx; struct mcinfo_pre_s { @@ -235,6 +247,7 @@ struct di_dev_s { unsigned int post_wr_support; unsigned int nrds_enable; unsigned int pps_enable; + u32 h_sc_down_en;/*sm1, tm2 ...*/ /*struct mutex cma_mutex;*/ unsigned int flag_cma; struct page *total_pages; @@ -287,6 +300,7 @@ struct di_pre_stru_s { int reg_req_flag; int reg_req_flag_irq; int reg_req_flag_cnt; + int reg_irq_busy; int force_unreg_req_flag; int disable_req_flag; /* current source info */ @@ -374,6 +388,7 @@ struct di_post_stru_s { bool toggle_flag; bool vscale_skip_flag; uint start_pts; + u64 start_pts_us64; int buf_type; int de_post_process_done; int post_de_busy; diff --git a/drivers/amlogic/media/deinterlace/deinterlace_dbg.c b/drivers/amlogic/media/deinterlace/deinterlace_dbg.c index 5f5c7fdb2b18..f28e86986cf5 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace_dbg.c +++ b/drivers/amlogic/media/deinterlace/deinterlace_dbg.c @@ -34,6 +34,7 @@ #include #include "register.h" #include "deinterlace_dbg.h" +#include "deinterlace_hw.h" #include "di_pps.h" #include "nr_downscale.h" #include @@ -253,7 +254,9 @@ void dump_di_reg_g12(void) if (is_meson_txlx_cpu() || is_meson_txhd_cpu() || is_meson_g12a_cpu() || - is_meson_g12b_cpu()) + is_meson_g12b_cpu() || + is_meson_tl1_cpu() || is_meson_tm2_cpu() || + is_meson_sm1_cpu()) base_addr = 0xff900000; else base_addr = 0xd0100000; @@ -629,7 +632,9 @@ void dump_mif_size_state(struct di_pre_stru_s *pre_stru_p, { pr_info("======pre mif status======\n"); pr_info("DI_PRE_CTRL=0x%x\n", Rd(DI_PRE_CTRL)); - pr_info("DI_PRE_SIZE=0x%x\n", Rd(DI_PRE_SIZE)); + pr_info("DI_PRE_SIZE H=%d, V=%d\n", + (Rd(DI_PRE_SIZE)>>16)&0xffff, + Rd(DI_PRE_SIZE)&0xffff); pr_info("DNR_HVSIZE=0x%x\n", Rd(DNR_HVSIZE)); if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) { pr_info("CONTWR_CAN_SIZE=0x%x\n", Rd(0x37ec)); @@ -862,8 +867,8 @@ void dump_vframe(struct vframe_s *vf) vf->left_eye.width, vf->left_eye.height, vf->right_eye.start_x, vf->right_eye.start_y, vf->right_eye.width, vf->right_eye.height); - pr_info("mode_3d_enable %d, use_cnt %d,", - vf->mode_3d_enable, atomic_read(&vf->use_cnt)); + pr_info("mode_3d_enable %d", + vf->mode_3d_enable); pr_info("early_process_fun 0x%p, process_fun 0x%p, private_data %p\n", vf->early_process_fun, vf->process_fun, vf->private_data); @@ -1044,6 +1049,27 @@ void dump_buf_addr(struct di_buf_s *di_buf, unsigned int num) } } +void dump_afbcd_reg(void) +{ + u32 i; + u32 afbc_reg; + + pr_info("---- dump afbc eAFBC_DEC0 reg -----\n"); + for (i = 0; i < AFBC_REG_INDEX_NUB; i++) { + afbc_reg = reg_AFBC[eAFBC_DEC0][i]; + pr_info("reg 0x%x val:0x%x\n", afbc_reg, RDMA_RD(afbc_reg)); + } + pr_info("---- dump afbc eAFBC_DEC1 reg -----\n"); + for (i = 0; i < AFBC_REG_INDEX_NUB; i++) { + afbc_reg = reg_AFBC[eAFBC_DEC1][i]; + pr_info("reg 0x%x val:0x%x\n", afbc_reg, RDMA_RD(afbc_reg)); + } + pr_info("reg 0x%x val:0x%x\n", + VD1_AFBCD0_MISC_CTRL, RDMA_RD(VD1_AFBCD0_MISC_CTRL)); + pr_info("reg 0x%x val:0x%x\n", + VD2_AFBCD1_MISC_CTRL, RDMA_RD(VD2_AFBCD1_MISC_CTRL)); +} + /*2018-08-17 add debugfs*/ /*same as dump_state*/ static int seq_file_di_state_show(struct seq_file *seq, void *v) diff --git a/drivers/amlogic/media/deinterlace/deinterlace_dbg.h b/drivers/amlogic/media/deinterlace/deinterlace_dbg.h index ab4cbd98f4b1..21e83a9f8291 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace_dbg.h +++ b/drivers/amlogic/media/deinterlace/deinterlace_dbg.h @@ -18,6 +18,8 @@ #define _DI_DBG_H #include "deinterlace.h" +extern const unsigned int reg_AFBC[AFBC_DEC_NUB][AFBC_REG_INDEX_NUB]; + void parse_cmd_params(char *buf_orig, char **parm); void dump_di_pre_stru(struct di_pre_stru_s *di_pre_stru_p); void dump_di_post_stru(struct di_post_stru_s *di_post_stru_p); @@ -28,6 +30,7 @@ void dump_di_reg_g12(void); void print_di_buf(struct di_buf_s *di_buf, int format); void dump_pre_mif_state(void); void dump_post_mif_reg(void); +void dump_afbcd_reg(void); void dump_buf_addr(struct di_buf_s *di_buf, unsigned int num); void dump_mif_size_state(struct di_pre_stru_s *pre, struct di_post_stru_s *post); diff --git a/drivers/amlogic/media/deinterlace/deinterlace_hw.c b/drivers/amlogic/media/deinterlace/deinterlace_hw.c index 31b8fefd460a..c0da406757a6 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace_hw.c +++ b/drivers/amlogic/media/deinterlace/deinterlace_hw.c @@ -28,6 +28,7 @@ #include #include #include +#include #include "deinterlace_hw.h" #include "register.h" #include "register_nr4.h" @@ -59,6 +60,7 @@ module_param_named(pq_load_dbg, pq_load_dbg, uint, 0644); static bool pd22_flg_calc_en = true; static unsigned int ctrl_regs[SKIP_CTRE_NUM]; +u32 afbc_disable_flag; #ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA extern u32 VSYNC_RD_MPEG_REG(u32 adr); @@ -314,43 +316,46 @@ static struct mcinfo_lmv_s lines_mv[540]; static short offset_lmv = 100; module_param_named(offset_lmv, offset_lmv, short, 0644); -void calc_lmv_base_mcinfo(unsigned int vf_height, unsigned long mcinfo_adr, - unsigned int mcinfo_size) +void calc_lmv_base_mcinfo(unsigned int vf_height, unsigned short *mcinfo_vadr) { unsigned short i, top_str, bot_str, top_end, bot_end, j = 0; - unsigned short *mcinfo_vadr = NULL, lck_num; + unsigned short lck_num; unsigned short flg_m1 = 0, flg_i = 0, nLmvLckSt = 0; unsigned short lmv_lckstext[3] = {0, 0, 0}, nLmvLckEd; unsigned short lmv_lckedext[3] = {0, 0, 0}, nLmvLckNum; - bool bflg_vmap = false; - u8 *tmp; + //bool bflg_vmap = false; //mcinfo_vadr = (unsigned short *)phys_to_virt(mcinfo_adr); if (!lmv_lock_win_en) return; - tmp = di_vmap(mcinfo_adr, mcinfo_size, &bflg_vmap); - if (tmp == NULL) { + if (!cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) { + pr_debug("%s: only support G12A and after chips.\n", __func__); + return; + } + + //tmp = di_vmap(mcinfo_adr, mcinfo_size, &bflg_vmap); + if (mcinfo_vadr == NULL) { di_print("err:di_vmap failed\n"); return; } - mcinfo_vadr = (unsigned short *)tmp; for (i = 0; i < (vf_height>>1); i++) { lmvs_init(&lines_mv[i], *(mcinfo_vadr+i)); j = i + (vf_height>>1); - lmvs_init(&lines_mv[j], *(mcinfo_vadr+i+272)); + /*288 = (canvas height(1088)/2 align to 64)*/ + lmvs_init(&lines_mv[j], *(mcinfo_vadr+i+288)); if (pr_mcinfo_cnt && j < (vf_height - 10) && j > (vf_height - offset_lmv)) { pr_info("MCINFO[%u]=0x%x\t", j, - *(mcinfo_vadr + i + 272)); + *(mcinfo_vadr + i + 288)); if (i%16 == 0) pr_info("\n"); } } - if (bflg_vmap) - di_unmap_phyaddr(tmp); + //if (bflg_vmap) + //di_unmap_phyaddr(tmp); pr_mcinfo_cnt ? pr_mcinfo_cnt-- : (pr_mcinfo_cnt = 0); top_str = 0; @@ -466,7 +471,9 @@ void di_hw_init(bool pd_enable, bool mc_enable) unsigned short fifo_size_di = 0xc0; switch_vpu_clk_gate_vmod(VPU_VPU_CLKB, VPU_CLK_GATE_ON); if (is_meson_txlx_cpu() || is_meson_txhd_cpu() - || is_meson_g12a_cpu() || is_meson_g12b_cpu()) + || is_meson_g12a_cpu() || is_meson_g12b_cpu() + || is_meson_tl1_cpu() || is_meson_sm1_cpu() || + is_meson_tm2_cpu()) di_top_gate_control(true, true); else if (is_meson_gxl_cpu() || is_meson_gxm_cpu() || is_meson_gxlx_cpu()) @@ -479,13 +486,18 @@ void di_hw_init(bool pd_enable, bool mc_enable) is_meson_gxlx_cpu() || is_meson_txhd_cpu() || is_meson_g12a_cpu() || - is_meson_g12b_cpu()) { + is_meson_g12b_cpu() || is_meson_sm1_cpu() || + is_meson_tl1_cpu() || is_meson_tm2_cpu()) { /* vpp fifo max size on txl :128*3=384[0x180] */ /* di fifo max size on txl :96*3=288[0x120] */ fifo_size_vpp = 0x180; fifo_size_di = 0x120; } + /*enable lock win, suggestion from vlsi zheng.bao*/ + if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) + lmv_lock_win_en = 0; + DI_Wr(VD1_IF0_LUMA_FIFO_SIZE, fifo_size_vpp); DI_Wr(VD2_IF0_LUMA_FIFO_SIZE, fifo_size_vpp); /* 1a83 is vd2_if0_luma_fifo_size */ @@ -510,7 +522,8 @@ void di_hw_init(bool pd_enable, bool mc_enable) if (is_meson_txlx_cpu() || is_meson_txhd_cpu() || is_meson_g12a_cpu() || - is_meson_g12b_cpu()) { + is_meson_g12b_cpu() || is_meson_sm1_cpu() || + is_meson_tl1_cpu() || is_meson_tm2_cpu()) { di_pre_gate_control(true, true); di_post_gate_control(true); } @@ -528,7 +541,8 @@ void di_hw_init(bool pd_enable, bool mc_enable) if (is_meson_txlx_cpu() || is_meson_txhd_cpu() || is_meson_g12a_cpu() || - is_meson_g12b_cpu()) { + is_meson_g12b_cpu() || + is_meson_tl1_cpu() || is_meson_tm2_cpu()) { di_pre_gate_control(false, true); di_post_gate_control(false); di_top_gate_control(false, false); @@ -642,13 +656,34 @@ static void set_di_nrwr_mif(struct DI_SIM_MIF_s *nrwr_mif, /* wr ext en from gxtvbb */ RDMA_WR_BITS(DI_NRWR_Y, 1, 15, 1); RDMA_WR_BITS(DI_NRWR_Y, 3, 30, 2); + #if 0 RDMA_WR(DI_NRWR_CTRL, nrwr_mif->canvas_num| (urgent<<16)| 2<<26 | 1<<30); + #endif RDMA_WR_BITS(DI_NRWR_Y, nrwr_mif->bit_mode&0x1, 14, 1); + #if 0 if ((nrwr_mif->bit_mode&0x3) == 0x3) RDMA_WR_BITS(DI_NRWR_CTRL, 0x3, 22, 2); + #endif + + /*fix 1080i crash when di work on low speed*/ + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TXL) && + ((nrwr_mif->bit_mode&0x3) == 0x3)) { + RDMA_WR(DI_NRWR_CTRL, nrwr_mif->canvas_num| + (urgent<<16)| + 3<<22 | + 1<<24 | + 2<<26 |/*burst_lim 1->2 2->4*/ + 1<<30); /* urgent bit 16 */ + } else { + RDMA_WR(DI_NRWR_CTRL, nrwr_mif->canvas_num| + (urgent<<16)| + 1<<24 | + 2<<26 |/*burst_lim 1->2 2->4*/ + 1<<30); /* urgent bit 16 */ + } } void di_interrupt_ctrl(unsigned char ma_en, @@ -788,6 +823,96 @@ void enable_di_pre_aml( ); } } + +const unsigned int reg_AFBC[AFBC_DEC_NUB][AFBC_REG_INDEX_NUB] = { + { + AFBC_ENABLE, + AFBC_MODE, + AFBC_SIZE_IN, + AFBC_DEC_DEF_COLOR, + AFBC_CONV_CTRL, + AFBC_LBUF_DEPTH, + AFBC_HEAD_BADDR, + AFBC_BODY_BADDR, + AFBC_SIZE_OUT, + AFBC_OUT_YSCOPE, + AFBC_STAT, + AFBC_VD_CFMT_CTRL, + AFBC_VD_CFMT_W, + AFBC_MIF_HOR_SCOPE, + AFBC_MIF_VER_SCOPE, + AFBC_PIXEL_HOR_SCOPE, + AFBC_PIXEL_VER_SCOPE, + AFBC_VD_CFMT_H, + }, + { + VD2_AFBC_ENABLE, + VD2_AFBC_MODE, + VD2_AFBC_SIZE_IN, + VD2_AFBC_DEC_DEF_COLOR, + VD2_AFBC_CONV_CTRL, + VD2_AFBC_LBUF_DEPTH, + VD2_AFBC_HEAD_BADDR, + VD2_AFBC_BODY_BADDR, + VD2_AFBC_OUT_XSCOPE, + VD2_AFBC_OUT_YSCOPE, + VD2_AFBC_STAT, + VD2_AFBC_VD_CFMT_CTRL, + VD2_AFBC_VD_CFMT_W, + VD2_AFBC_MIF_HOR_SCOPE, + VD2_AFBC_MIF_VER_SCOPE, + VD2_AFBC_PIXEL_HOR_SCOPE, + VD2_AFBC_PIXEL_VER_SCOPE, + VD2_AFBC_VD_CFMT_H, + + }, + +}; + +static enum eAFBC_DEC afbc_get_decnub(void) +{ + enum eAFBC_DEC sel_dec = eAFBC_DEC0; + /* info from vlsi feijun + * gxl:have 1, AFBC_dec0 + * txlx:have 2, di only can use 1 + * g12a:have 2, di can use 2 + * tl1: have 1, AFBC_dec0 + */ + if (is_meson_gxl_cpu()) + sel_dec = eAFBC_DEC0; + else if (is_meson_txlx_cpu()) + sel_dec = eAFBC_DEC1; + else if (is_meson_g12a_cpu()) + sel_dec = eAFBC_DEC1; + else if (is_meson_tl1_cpu() || is_meson_tm2_cpu()) + sel_dec = eAFBC_DEC0; + return sel_dec; +} + +static const unsigned int *afbc_get_regbase(void) +{ + return ®_AFBC[afbc_get_decnub()][0]; +} + +bool afbc_is_supported(void) +{ + bool ret = false; + + if (afbc_disable_flag) + return false; + + /*currently support txlx and g12a*/ + if (is_meson_txlx_cpu()) + ret = false; + else if (is_meson_g12a_cpu()) + ret = false; + else if (is_meson_tl1_cpu() || is_meson_tm2_cpu()) + ret = true; + + return ret; + +} + /* * after g12a, framereset will not reset simple * wr mif of pre such as mtn&cont&mv&mcinfo wr @@ -872,161 +997,105 @@ void enable_afbc_input(struct vframe_s *vf) } #endif -enum eAFBC_REG { - eAFBC_ENABLE, - eAFBC_MODE, - eAFBC_SIZE_IN, - eAFBC_DEC_DEF_COLOR, - eAFBC_CONV_CTRL, - eAFBC_LBUF_DEPTH, - eAFBC_HEAD_BADDR, - eAFBC_BODY_BADDR, - eAFBC_SIZE_OUT, - eAFBC_OUT_YSCOPE, - eAFBC_STAT, - eAFBC_VD_CFMT_CTRL, - eAFBC_VD_CFMT_W, - eAFBC_MIF_HOR_SCOPE, - eAFBC_MIF_VER_SCOPE, - eAFBC_PIXEL_HOR_SCOPE, - eAFBC_PIXEL_VER_SCOPE, - eAFBC_VD_CFMT_H, -}; -enum eAFBC_DEC { - eAFBC_DEC0, - eAFBC_DEC1, -}; -#define AFBC_REG_INDEX_NUB (18) -#define AFBC_DEC_NUB (2) - -const unsigned int reg_AFBC[AFBC_DEC_NUB][AFBC_REG_INDEX_NUB] = { - { - AFBC_ENABLE, - AFBC_MODE, - AFBC_SIZE_IN, - AFBC_DEC_DEF_COLOR, - AFBC_CONV_CTRL, - AFBC_LBUF_DEPTH, - AFBC_HEAD_BADDR, - AFBC_BODY_BADDR, - AFBC_SIZE_OUT, - AFBC_OUT_YSCOPE, - AFBC_STAT, - AFBC_VD_CFMT_CTRL, - AFBC_VD_CFMT_W, - AFBC_MIF_HOR_SCOPE, - AFBC_MIF_VER_SCOPE, - AFBC_PIXEL_HOR_SCOPE, - AFBC_PIXEL_VER_SCOPE, - AFBC_VD_CFMT_H, - }, - { - VD2_AFBC_ENABLE, - VD2_AFBC_MODE, - VD2_AFBC_SIZE_IN, - VD2_AFBC_DEC_DEF_COLOR, - VD2_AFBC_CONV_CTRL, - VD2_AFBC_LBUF_DEPTH, - VD2_AFBC_HEAD_BADDR, - VD2_AFBC_BODY_BADDR, - VD2_AFBC_OUT_XSCOPE, - VD2_AFBC_OUT_YSCOPE, - VD2_AFBC_STAT, - VD2_AFBC_VD_CFMT_CTRL, - VD2_AFBC_VD_CFMT_W, - VD2_AFBC_MIF_HOR_SCOPE, - VD2_AFBC_MIF_VER_SCOPE, - VD2_AFBC_PIXEL_HOR_SCOPE, - VD2_AFBC_PIXEL_VER_SCOPE, - VD2_AFBC_VD_CFMT_H, - - }, - -}; #define AFBC_DEC_SEL (eAFBC_DEC1) - -static enum eAFBC_DEC afbc_get_decnub(void) -{ - enum eAFBC_DEC sel_dec = eAFBC_DEC0; - - if (is_meson_gxl_cpu()) - sel_dec = eAFBC_DEC0; - else if (is_meson_txlx_cpu()) - sel_dec = eAFBC_DEC1; - else if (is_meson_g12a_cpu()) - sel_dec = AFBC_DEC_SEL; - - - return sel_dec; -} - -static const unsigned int *afbc_get_regbase(void) -{ - return ®_AFBC[afbc_get_decnub()][0]; -} - -bool afbc_is_supported(void) -{ - bool ret = false; - - /*currently support txlx and g12a*/ - if (is_meson_txlx_cpu() - || is_meson_g12a_cpu()) - ret = true; - - return ret; - -} - -void enable_afbc_input(struct vframe_s *vf) +u32 enable_afbc_input(struct vframe_s *vf) { unsigned int r, u, v, w_aligned, h_aligned; - unsigned int out_height = 0; - unsigned int vfmt_rpt_first = 1, vt_ini_phase = 0; const unsigned int *reg = afbc_get_regbase(); + unsigned int vfmt_rpt_first = 1, vt_ini_phase = 0; + unsigned int out_height = 0; if (!afbc_is_supported()) - return; + return false; - if ((vf->type & VIDTYPE_COMPRESS)) { - // only reg for the first time + if (vf->type & VIDTYPE_COMPRESS) { + /*only reg for the first time*/ afbc_reg_sw(true); - afbc_sw_trig(true); + afbc_sw(true); } else { - afbc_sw_trig(false); - return; + afbc_sw(false); + return false; } - w_aligned = round_up((vf->width-1), 32); - h_aligned = round_up((vf->height-1), 4); + + w_aligned = round_up((vf->width), 32); + /*if (di_pre_stru.cur_inp_type & VIDTYPE_INTERLACE)*/ + if ((vf->type & VIDTYPE_INTERLACE) && + (vf->type & VIDTYPE_VIU_422)) + h_aligned = round_up((vf->height/2), 4);/*from vdin and is i */ + else + h_aligned = round_up((vf->height), 4); + + /*AFBCD working mode config*/ r = (3 << 24) | (10 << 16) | (1 << 14) | /*burst1 1*/ (vf->bitdepth & BITDEPTH_MASK); + if (vf->bitdepth & BITDEPTH_SAVING_MODE) r |= (1<<28); /* mem_saving_mode */ if (vf->type & VIDTYPE_SCATTER) r |= (1<<29); + out_height = h_aligned; - if ((vf->type & VIDTYPE_TYPEMASK) == VIDTYPE_INTERLACE_TOP) { - r |= 0x40; - vt_ini_phase = 0xc; - out_height = h_aligned>>1; - } else if ((vf->type & VIDTYPE_TYPEMASK) == - VIDTYPE_INTERLACE_BOTTOM) { - r |= 0x80; - vt_ini_phase = 0x4; - vfmt_rpt_first = 0; - out_height = h_aligned>>1; + if (!(vf->type & VIDTYPE_VIU_422)) { + /*from dec, process P as i*/ + if ((vf->type & VIDTYPE_TYPEMASK) == VIDTYPE_INTERLACE_TOP) { + r |= 0x40; + vt_ini_phase = 0xc; + vfmt_rpt_first = 1; + out_height = h_aligned>>1; + } else if ((vf->type & VIDTYPE_TYPEMASK) == + VIDTYPE_INTERLACE_BOTTOM) { + r |= 0x80; + vt_ini_phase = 0x4; + vfmt_rpt_first = 0; + out_height = h_aligned>>1; + } } RDMA_WR(reg[eAFBC_MODE], r); - RDMA_WR(reg[eAFBC_CONV_CTRL], 0x100); + + r = 0x1600; + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) { + /* un compress mode data from vdin bit block order is + * different with from dos + */ + if (!(vf->type & VIDTYPE_VIU_422)) + r |= (1 << 19); /* dos_uncomp */ + + if (vf->type & VIDTYPE_COMB_MODE) + r |= (1 << 20); + } + RDMA_WR(reg[eAFBC_ENABLE], r); + + r = 0x100; + /* TL1 add bit[13:12]: fmt_mode; 0:yuv444; 1:yuv422; 2:yuv420 + * di does not support yuv444, so for fmt yuv444 di will bypass+ + */ + if (is_meson_tl1_cpu() || is_meson_tm2_cpu()) { + if (vf->type & VIDTYPE_VIU_444) + r |= (0 << 12); + else if (vf->type & VIDTYPE_VIU_422) + r |= (1 << 12); + else + r |= (2 << 12); + } + RDMA_WR(reg[eAFBC_CONV_CTRL], r); + u = (vf->bitdepth >> (BITDEPTH_U_SHIFT)) & 0x3; v = (vf->bitdepth >> (BITDEPTH_V_SHIFT)) & 0x3; RDMA_WR(reg[eAFBC_DEC_DEF_COLOR], 0x3FF00000 | /*Y,bit20+*/ 0x80 << (u + 10) | 0x80 << v); + + u = (vf->bitdepth >> (BITDEPTH_U_SHIFT)) & 0x3; + v = (vf->bitdepth >> (BITDEPTH_V_SHIFT)) & 0x3; + RDMA_WR(reg[eAFBC_DEC_DEF_COLOR], + 0x3FF00000 | /*Y,bit20+*/ + 0x80 << (u + 10) | + 0x80 << v); + /* chroma formatter */ RDMA_WR(reg[eAFBC_VD_CFMT_CTRL], (1 << 21) |/* HFORMATTER_YC_RATIO_2_1 */ @@ -1035,25 +1104,46 @@ void enable_afbc_input(struct vframe_s *vf) (vt_ini_phase << 8) | (16 << 1)|/* VFORMATTER_PHASE_BIT */ 0);/* different with inp */ + #if 0 + if (((vf->width-1) != RDMA_RD(reg[eAFBC_PIXEL_HOR_SCOPE])) || + ((vf->height-1) != RDMA_RD(reg[eAFBC_PIXEL_VER_SCOPE]))) { + pr_info("[afbc] in vf type=0x%x\n", vf->type); + /*pr_info("cur_inp_type=0x%x\n", di_pre_stru.cur_inp_type);*/ + pr_info("[afbc] w_aligned=%d, h_aligned=%d\n", + w_aligned, h_aligned); + pr_info("[afbc] vfwidth=%d, vfheight=%d\n", + vf->width, vf->height); + pr_info("[afbc] out_height=%d\n", out_height); + } + #endif + if (vf->type & VIDTYPE_VIU_444) + RDMA_WR(reg[eAFBC_VD_CFMT_W], + (w_aligned << 16) | (w_aligned/2)); + else + RDMA_WR(reg[eAFBC_VD_CFMT_W], + (w_aligned << 16) | (w_aligned)); - RDMA_WR(reg[eAFBC_VD_CFMT_W], - (w_aligned << 16) | (w_aligned/2)); RDMA_WR(reg[eAFBC_MIF_HOR_SCOPE], - (0 << 16) | ((w_aligned>>5) - 1)); + (0 << 16) | ((w_aligned>>5)-1)); RDMA_WR(reg[eAFBC_MIF_VER_SCOPE], - (0 << 16) | ((h_aligned>>2) - 1)); + (0 << 16) | ((h_aligned>>2)-1)); RDMA_WR(reg[eAFBC_PIXEL_HOR_SCOPE], - (0 << 16) | (vf->width - 1)); + (0 << 16) | (vf->width-1)); + RDMA_WR(reg[eAFBC_PIXEL_VER_SCOPE], + 0 << 16 | (vf->height-1)); + RDMA_WR(reg[eAFBC_VD_CFMT_H], out_height); - RDMA_WR(reg[eAFBC_PIXEL_VER_SCOPE], - 0 << 16 | (vf->height-1)); - RDMA_WR(reg[eAFBC_SIZE_IN], h_aligned | w_aligned << 16); + RDMA_WR(reg[eAFBC_SIZE_IN], (vf->height) | w_aligned << 16); RDMA_WR(reg[eAFBC_SIZE_OUT], out_height | w_aligned << 16); + RDMA_WR(reg[eAFBC_HEAD_BADDR], vf->compHeadAddr>>4); RDMA_WR(reg[eAFBC_BODY_BADDR], vf->compBodyAddr>>4); + + return true; } +#if 0 static void afbcx_power_sw(enum eAFBC_DEC decsel, bool on) /*g12a*/ { unsigned int reg_ctrl; @@ -1068,22 +1158,23 @@ static void afbcx_power_sw(enum eAFBC_DEC decsel, bool on) /*g12a*/ RDMA_WR_BITS(reg_ctrl, 0x55, 0, 8); } +#endif static void afbcx_sw(bool on) /*g12a*/ { unsigned int tmp; unsigned int mask; unsigned int reg_ctrl, reg_en; enum eAFBC_DEC dec_sel; + const unsigned int *reg = afbc_get_regbase(); dec_sel = afbc_get_decnub(); if (dec_sel == eAFBC_DEC0) { reg_ctrl = VD1_AFBCD0_MISC_CTRL; - reg_en = AFBC_ENABLE; } else { reg_ctrl = VD2_AFBCD1_MISC_CTRL; - reg_en = VD2_AFBC_ENABLE; } + reg_en = reg[eAFBC_ENABLE]; mask = (3<<20) | (1<<12) | (1<<9); /*clear*/ @@ -1095,36 +1186,30 @@ static void afbcx_sw(bool on) /*g12a*/ | (1<<12) | (1<<9); RDMA_WR(reg_ctrl, tmp); + /*0:vd1 to di 1:vd2 to di */ RDMA_WR_BITS(VD2_AFBCD1_MISC_CTRL, (reg_ctrl == VD1_AFBCD0_MISC_CTRL)?0:1, 8, 1); - RDMA_WR(reg_en, 0x1600); + /*RDMA_WR(reg_en, 0x1600);*/ RDMA_WR_BITS(VIUB_MISC_CTRL0, 1, 16, 1); + /*TL1 add mem control bit */ + if (is_meson_tl1_cpu() || is_meson_tm2_cpu()) + RDMA_WR_BITS(VD1_AFBCD0_MISC_CTRL, 1, 22, 1); } else { RDMA_WR(reg_ctrl, tmp); RDMA_WR(reg_en, 0x1600); RDMA_WR_BITS(VIUB_MISC_CTRL0, 0, 16, 1); + if (is_meson_tl1_cpu() || is_meson_tm2_cpu()) + RDMA_WR_BITS(VD1_AFBCD0_MISC_CTRL, 0, 22, 1); } -// printk("%s,on[%d],CTRL[0x%x],en[0x%x]\n", __func__, on, -// RDMA_RD(VD1_AFBCD0_MISC_CTRL), -// RDMA_RD(VD1_AFBCD0_MISC_CTRL)); - - } static void afbc_sw_old(bool on)/*txlx*/ { enum eAFBC_DEC dec_sel; unsigned int reg_en; + const unsigned int *reg = afbc_get_regbase(); dec_sel = afbc_get_decnub(); - - if (dec_sel == eAFBC_DEC0) { - //reg_ctrl = VD1_AFBCD0_MISC_CTRL; - reg_en = AFBC_ENABLE; - } else { - //reg_ctrl = VD2_AFBCD1_MISC_CTRL; - reg_en = VD2_AFBC_ENABLE; - } - + reg_en = reg[eAFBC_ENABLE]; if (on) { /* DI inp(current data) switch to AFBC */ @@ -1145,26 +1230,20 @@ static void afbc_sw_old(bool on)/*txlx*/ } else { RDMA_WR(reg_en, 0); /* afbc to vpp(replace vd1) enable */ - if (RDMA_RD_BITS(VIU_MISC_CTRL1, 0, 1) != 0 || RDMA_RD_BITS(VIUB_MISC_CTRL0, 16, 1) != 0) { RDMA_WR_BITS(VIU_MISC_CTRL1, 0, 0, 1); RDMA_WR_BITS(VIUB_MISC_CTRL0, 0, 16, 1); } - - } } static bool afbc_is_used(void) { bool ret = false; - if (RDMA_RD_BITS(VIUB_MISC_CTRL0, 16, 1) == 1) ret = true; - //di_print("%s:%d\n",__func__,ret); - return ret; } static void afbc_power_sw(bool on) @@ -1172,6 +1251,7 @@ static void afbc_power_sw(bool on) /*afbc*/ enum eAFBC_DEC dec_sel; unsigned int vpu_sel; + unsigned int reg_ctrl; dec_sel = afbc_get_decnub(); if (dec_sel == eAFBC_DEC0) @@ -1182,15 +1262,30 @@ static void afbc_power_sw(bool on) switch_vpu_mem_pd_vmod(vpu_sel, on?VPU_MEM_POWER_ON:VPU_MEM_POWER_DOWN); - - if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) - afbcx_power_sw(dec_sel, on); - + if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) { + if (dec_sel == eAFBC_DEC0) + reg_ctrl = VD1_AFBCD0_MISC_CTRL; + else + reg_ctrl = VD2_AFBCD1_MISC_CTRL; + if (on) + RDMA_WR_BITS(reg_ctrl, 0, 0, 8); + else + RDMA_WR_BITS(reg_ctrl, 0x55, 0, 8); + } + /*afbcx_power_sw(dec_sel, on);*/ } -static int afbc_reg_unreg_flag; + +int afbc_reg_unreg_flag; +void afbc_sw(bool on) +{ + if (is_meson_gxl_cpu() || is_meson_txlx_cpu()) + afbc_sw_old(on); + else + afbcx_sw(on); +} + void afbc_reg_sw(bool on) { - if (!afbc_is_supported()) return; @@ -1199,25 +1294,18 @@ void afbc_reg_sw(bool on) afbc_reg_unreg_flag = 1; } if ((!on) && afbc_reg_unreg_flag) { - afbc_sw_trig(false); + afbc_sw(false); afbc_power_sw(false); afbc_reg_unreg_flag = 0; } - -} -static void afbc_sw(bool on) -{ - if (is_meson_gxl_cpu() || is_meson_txlx_cpu()) - afbc_sw_old(on); - else - afbcx_sw(on); - } +#if 0 void afbc_sw_trig(bool on) { afbc_sw(on); } -static void afbc_input_sw(bool on) +#endif +void afbc_input_sw(bool on) { const unsigned int *reg = afbc_get_regbase(); unsigned int reg_AFBC_ENABLE; @@ -1248,7 +1336,7 @@ void enable_mc_di_pre_g12(struct DI_MC_MIF_s *mcinford_mif, RDMA_WR_BITS(MCINFRD_SCOPE_X, mcinford_mif->size_x, 16, 13); RDMA_WR_BITS(MCINFRD_SCOPE_Y, mcinford_mif->size_y, 16, 13); - RDMA_WR_BITS(MCINFRD_CTRL1, mcvecwr_mif->canvas_num, 16, 8); + RDMA_WR_BITS(MCINFRD_CTRL1, mcinford_mif->canvas_num, 16, 8); RDMA_WR_BITS(MCINFRD_CTRL1, 2, 0, 3); RDMA_WR_BITS(MCVECWR_X, mcvecwr_mif->size_x, 0, 13); @@ -2681,11 +2769,22 @@ void di_post_switch_buffer( DI_VSYNC_WR_MPEG_REG_BITS(MCDI_MC_CRTL, di_mcvecrd_mif->vecrd_offset, 12, 3); if (di_mcvecrd_mif->blend_en) { - DI_VSYNC_WR_MPEG_REG_BITS(MCDI_MC_CRTL, - mcen_mode, 0, 2); - DI_VSYNC_WR_MPEG_REG_BITS(MCDI_MC_CRTL, 1, 11, 1); - DI_VSYNC_WR_MPEG_REG_BITS(MCDI_MC_CRTL, - 3, 18, 2); + if (blend_mode == 1) { + DI_VSYNC_WR_MPEG_REG_BITS(MCDI_MC_CRTL, + mcen_mode, 0, 2); + DI_VSYNC_WR_MPEG_REG_BITS(MCDI_MC_CRTL, + 0, 11, 1); + DI_VSYNC_WR_MPEG_REG_BITS(MCDI_MC_CRTL, + 2, 18, 2); + } else { + DI_VSYNC_WR_MPEG_REG_BITS(MCDI_MC_CRTL, + mcen_mode, 0, 2); + DI_VSYNC_WR_MPEG_REG_BITS(MCDI_MC_CRTL, + 1, 11, 1); + DI_VSYNC_WR_MPEG_REG_BITS(MCDI_MC_CRTL, + 3, 18, 2); + + } } else { DI_VSYNC_WR_MPEG_REG_BITS(MCDI_MC_CRTL, 0, 0, 2); @@ -3133,7 +3232,7 @@ void di_post_read_reverse_irq(bool reverse, unsigned char mc_pre_flag, DI_VSYNC_WR_MPEG_REG_BITS(MCDI_MCVECRD_X, 1, 30, 1); DI_VSYNC_WR_MPEG_REG_BITS(MCDI_MCVECRD_Y, 1, 30, 1); if (cpu_after_eq(MESON_CPU_MAJOR_ID_TXL)) { - if (cpu_after_eq(MESON_CPU_MAJOR_ID_TXLX)) { + if (is_meson_txlx_cpu()) { DI_VSYNC_WR_MPEG_REG_BITS(MCDI_MC_CRTL, pre_flag, 8, 2); flag_val = (pre_flag != 2) ? 0 : 1; @@ -3177,7 +3276,7 @@ void di_post_read_reverse_irq(bool reverse, unsigned char mc_pre_flag, DI_VSYNC_WR_MPEG_REG_BITS(MCDI_MCVECRD_X, 0, 30, 1); DI_VSYNC_WR_MPEG_REG_BITS(MCDI_MCVECRD_Y, 0, 30, 1); if (cpu_after_eq(MESON_CPU_MAJOR_ID_TXL)) { - if (cpu_after_eq(MESON_CPU_MAJOR_ID_TXLX)) { + if (is_meson_txlx_cpu()) { DI_VSYNC_WR_MPEG_REG_BITS(MCDI_MC_CRTL, pre_flag, 8, 2); flag_val = (pre_flag != 2) ? 0 : 1; @@ -3333,6 +3432,130 @@ void di_post_gate_control(bool gate) } } + +void di_async_reset(void) /*2019-01-17 add for debug*/ +{ + /*wrmif async reset*/ + RDMA_WR_BITS(VIUB_SW_RESET, 1, 14, 1); + RDMA_WR_BITS(VIUB_SW_RESET, 0, 14, 1); +} + +void di_pre_rst_frame(void) +{ + RDMA_WR(DI_PRE_CTRL, Rd(DI_PRE_CTRL) | (1 << 31)); +} + +void di_pre_nr_enable(bool on) +{ + if (on) + RDMA_WR_BITS(DI_PRE_CTRL, 1, 0, 1); + else + RDMA_WR_BITS(DI_PRE_CTRL, 0, 0, 1); +} + +void di_pre_nr_wr_done_sel(bool on) +{ + if (on) /*wait till response finish*/ + RDMA_WR_BITS(DI_CANVAS_URGENT0, 1, 8, 1); + else + RDMA_WR_BITS(DI_CANVAS_URGENT0, 0, 0, 1); + +} + +void di_rst_protect(bool on) +{ + if (on) + RDMA_WR_BITS(DI_NRWR_Y, 1, 15, 1); + else + RDMA_WR_BITS(DI_NRWR_Y, 0, 15, 1); +} + +/*bit 10,12,16,18 [3:1]*/ +/*#define PRE_ID_MASK (0x5140e) */ +#define PRE_ID_MASK (0x51400) + +/*bit 8,10,14,16*/ +#define PRE_ID_MASK_TL1 (0x14500) + +bool di_pre_idle(void) +{ + bool ret = false; + + if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) { + if ((RDMA_RD(DI_ARB_DBG_STAT_L1C1) & + PRE_ID_MASK_TL1) == PRE_ID_MASK_TL1) + ret = true; + } else { + if ((RDMA_RD(DI_ARB_DBG_STAT_L1C1_OLD) & + PRE_ID_MASK) == PRE_ID_MASK) + ret = true; + } + + return ret; +} + +void di_arb_sw(bool on) +{ + int i; + u32 REG_VPU_WRARB_REQEN_SLV_L1C1; + u32 REG_VPU_RDARB_REQEN_SLV_L1C1; + u32 REG_VPU_ARB_DBG_STAT_L1C1; + u32 WRARB_onval; + u32 WRARB_offval; + + if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) { + REG_VPU_WRARB_REQEN_SLV_L1C1 = DI_WRARB_REQEN_SLV_L1C1; + REG_VPU_RDARB_REQEN_SLV_L1C1 = DI_RDARB_REQEN_SLV_L1C1; + REG_VPU_ARB_DBG_STAT_L1C1 = DI_ARB_DBG_STAT_L1C1; + if (on) + WRARB_onval = 0x3f; + else + WRARB_offval = 0x3e; + } else { + REG_VPU_WRARB_REQEN_SLV_L1C1 = DI_WRARB_REQEN_SLV_L1C1_OLD; + REG_VPU_RDARB_REQEN_SLV_L1C1 = DI_RDARB_REQEN_SLV_L1C1_OLD; + REG_VPU_ARB_DBG_STAT_L1C1 = DI_ARB_DBG_STAT_L1C1_OLD; + if (on) + WRARB_onval = 0x3f; + else + WRARB_offval = 0x2b; + } + + if (on) { + RDMA_WR(REG_VPU_WRARB_REQEN_SLV_L1C1, WRARB_onval); + RDMA_WR(REG_VPU_RDARB_REQEN_SLV_L1C1, 0xffff); + } else { + /*close arb:*/ + RDMA_WR(REG_VPU_WRARB_REQEN_SLV_L1C1, WRARB_offval); + RDMA_WR(REG_VPU_RDARB_REQEN_SLV_L1C1, 0xf1f1); + + di_pre_nr_enable(false); /*by Feijun*/ + /*check status*/ + if (!di_pre_idle()) { + pr_err("di:err1:0x[%x]\n", + RDMA_RD(REG_VPU_ARB_DBG_STAT_L1C1)); + for (i = 0; i < 9; i++) { + if (di_pre_idle()) + break; + } + + if (!di_pre_idle()) { + di_pre_rst_frame(); + + for (i = 0; i < 9; i++) { + if (di_pre_idle()) + break; + } + if (!di_pre_idle()) + pr_err("di:err2\n"); + + } + } + if (di_pre_idle()) + di_async_reset(); + } +} + /* * enable/disable mc pre mif mcinfo&mv */ @@ -3430,14 +3653,14 @@ static void di_pre_data_mif_ctrl(bool enable) afbc_input_sw(true); } else { DI_Wr(DI_INP_GEN_REG, Rd(DI_INP_GEN_REG) | 0x1); - afbc_input_sw(false); + /*afbc_input_sw(false);*/ } #endif /* nrwr no clk gate en=0 */ - RDMA_WR_BITS(DI_NRWR_CTRL, 0, 24, 1); + /*RDMA_WR_BITS(DI_NRWR_CTRL, 0, 24, 1);*/ } else { /* nrwr no clk gate en=1 */ - RDMA_WR_BITS(DI_NRWR_CTRL, 1, 24, 1); + /*RDMA_WR_BITS(DI_NRWR_CTRL, 1, 24, 1);*/ /* nr wr req en =0 */ RDMA_WR_BITS(DI_PRE_CTRL, 0, 0, 1); /* disable input mif*/ @@ -3449,9 +3672,11 @@ static void di_pre_data_mif_ctrl(bool enable) if (Rd_reg_bits(VIU_MISC_CTRL1, 0, 1) == 1) RDMA_WR_BITS(VD2_AFBC_ENABLE, 0, 8, 1); #else - /* disable AFBC input */ - if (afbc_is_used()) - afbc_input_sw(false); + /* + * disable AFBC input at unreg + */ + //if (afbc_is_used()) + // afbc_input_sw(false); #endif } diff --git a/drivers/amlogic/media/deinterlace/deinterlace_hw.h b/drivers/amlogic/media/deinterlace/deinterlace_hw.h index d6b44d529836..d85c8b3202ab 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace_hw.h +++ b/drivers/amlogic/media/deinterlace/deinterlace_hw.h @@ -27,6 +27,34 @@ #define SKIP_CTRE_NUM 13 +enum eAFBC_REG { + eAFBC_ENABLE, /*0x1ae0*/ + eAFBC_MODE, /*0x1ae1*/ + eAFBC_SIZE_IN, /*0x1ae2*/ + eAFBC_DEC_DEF_COLOR, /*0x1ae3*/ + eAFBC_CONV_CTRL, /*0x1ae4*/ + eAFBC_LBUF_DEPTH, /*0x1ae5*/ + eAFBC_HEAD_BADDR, /*0x1ae6*/ + eAFBC_BODY_BADDR, /*0x1ae7*/ + eAFBC_SIZE_OUT, /*0x1ae8*/ + eAFBC_OUT_YSCOPE, /*0x1ae9*/ + eAFBC_STAT, /*0x1aea*/ + eAFBC_VD_CFMT_CTRL, /*0x1aeb*/ + eAFBC_VD_CFMT_W, /*0x1aec*/ + eAFBC_MIF_HOR_SCOPE, /*0x1aed*/ + eAFBC_MIF_VER_SCOPE, /*0x1aee*/ + eAFBC_PIXEL_HOR_SCOPE, /*0x1aef*/ + eAFBC_PIXEL_VER_SCOPE, /*0x1af0*/ + eAFBC_VD_CFMT_H, /*0x1af1*/ +}; + +enum eAFBC_DEC { + eAFBC_DEC0, + eAFBC_DEC1, +}; +#define AFBC_REG_INDEX_NUB (18) +#define AFBC_DEC_NUB (2) + struct DI_MIF_s { unsigned short luma_x_start0; unsigned short luma_x_end0; @@ -91,6 +119,7 @@ struct di_pq_parm_s { struct list_head list; }; +extern u32 afbc_disable_flag; void read_pulldown_info(unsigned int *glb_frm_mot_num, unsigned int *glb_fid_mot_num); void read_new_pulldown_info(struct FlmModReg_t *pFMRegp); @@ -109,7 +138,7 @@ void enable_di_pre_aml( struct DI_SIM_MIF_s *di_contwr_mif, unsigned char madi_en, unsigned char pre_field_num, unsigned char pre_vdin_link); -void enable_afbc_input(struct vframe_s *vf); +u32 enable_afbc_input(struct vframe_s *vf); void mc_pre_mv_irq(void); void enable_mc_di_pre(struct DI_MC_MIF_s *di_mcinford_mif, @@ -165,8 +194,7 @@ void enable_di_post_mif(enum gate_mode_e mode); void di_hw_uninit(void); void combing_pd22_window_config(unsigned int width, unsigned int height); void calc_lmv_init(void); -void calc_lmv_base_mcinfo(unsigned int vf_height, unsigned long mcinfo_adr, - unsigned int mcinfo_size); +void calc_lmv_base_mcinfo(unsigned int vf_height, unsigned short *mcinfo_vadr); void init_field_mode(unsigned short height); void film_mode_win_config(unsigned int width, unsigned int height); void pulldown_vof_win_config(struct pulldown_detected_s *wins); @@ -180,8 +208,11 @@ void di_txl_patch_prog(int prog_flg, unsigned int cnt, bool mc_en); bool afbc_is_supported(void); //extern void afbc_power_sw(bool on); extern void afbc_reg_sw(bool on); -extern void afbc_sw_trig(bool on); +/*extern void afbc_sw_trig(bool on);*/ +extern void afbc_sw(bool on); +extern void afbc_input_sw(bool on); extern void dump_vd2_afbc(void); +extern int afbc_reg_unreg_flag; extern u8 *di_vmap(ulong addr, u32 size, bool *bflg); extern void di_unmap_phyaddr(u8 *vaddr); @@ -197,4 +228,8 @@ extern int di_print(const char *fmt, ...); extern void di_patch_post_update_mc(void); extern void di_patch_post_update_mc_sw(unsigned int cmd, bool on); +extern void di_rst_protect(bool on); +extern void di_pre_nr_wr_done_sel(bool on); +extern void di_arb_sw(bool on); + #endif diff --git a/drivers/amlogic/media/deinterlace/deinterlace_mtn.c b/drivers/amlogic/media/deinterlace/deinterlace_mtn.c index cc92763eeca7..b9a3562fb430 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace_mtn.c +++ b/drivers/amlogic/media/deinterlace/deinterlace_mtn.c @@ -193,9 +193,11 @@ static unsigned int combing_bias_motion_setting[MAX_NUM_DI_REG] = { 0x02020606, 0x05080344, 0x40020a04, - 0x0001ff0c, /* 0x0001FF12 */ - 0x00400204, /* 0x00200204 */ - 0x00016404, /* 0x00012002 */ + /*idea from mingliang.dong & vlsi zheng.bao begin*/ + 0x0001FF12, /* 0x0001ff0c */ + 0x00200204, /* 0x00400204 */ + 0x00012002, /* 0x00016404 */ + /*idea from mingliang.dong & vlsi zheng.bao end*/ 0x00000142 }; @@ -211,10 +213,12 @@ static unsigned int combing_very_motion_setting[MAX_NUM_DI_REG] = { 0x0D200302, 0x02020606, 0x05080344, - 0x40020a04, /* 0x60000404,*/ - 0x0001ff0c, /* 0x0001FF12 */ - 0x00400204, /* 0x00200204 */ - 0x00016404, /* 0x00012002 */ + /*idea from mingliang.dong & vlsi zheng.bao begin*/ + 0x60000404, /* 0x40020a04*/ + 0x0001FF12, /* 0x0001ff0c */ + 0x00200204, /* 0x00400204 */ + 0x00012002, /* 0x00016404 */ + /*idea from mingliang.dong & vlsi zheng.bao end*/ 0x00000131 }; /*special for resolution test file*/ @@ -291,7 +295,12 @@ struct combing_status_s *adpative_combing_config(unsigned int width, cmb_param.prog_flag = prog; return &cmb_status; } - +void mtn_int_combing_glbmot(void) +{ + if (is_meson_tl1_cpu() || is_meson_tm2_cpu()) {/*from VLSI yanling.liu*/ + combing_glbmot_radprat[0] = 30; + } +} void adpative_combing_exit(void) { } @@ -596,8 +605,9 @@ static void set_combing_regs(int lvl, int bit_mode) DI_Wr_reg_bits(DI_MTN_1_CTRL1, ((*combing_setting_values[lvl])[0] & combing_setting_masks[i]), 0, 24); - if (bit_mode != 10 && - combing_setting_registers[i] == NR2_MATNR_DEGHOST) + /*working on db, driver don't handle this*/ + if (((bit_mode != 10) || cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) + && combing_setting_registers[i] == NR2_MATNR_DEGHOST) break; else if (i < GXTVBB_REG_START) { /* TODO: need change to check if @@ -619,6 +629,24 @@ static int di_debug_readreg; module_param(di_debug_readreg, int, 0644); MODULE_PARM_DESC(di_debug_readreg, "di_debug_readreg"); +/*from VLSI yanling.liu, the patch fix TL1 1080I in some dark */ +/*scenes and roller coasters have small sawtooth, when turn off*/ +/*combing_fix_en, set the registers*/ +void fix_tl1_1080i_sawtooth_patch(void) +{ + DI_Wr(0x1741, 0x0A0A1A22); + DI_Wr(0x1742, 0x0a100101); + DI_Wr(0x1743, 0x01020420); + DI_Wr(0x1744, 0x32210404); + DI_Wr(0x17a9, 0x0a100505); + DI_Wr(0x17aa, 0x04040101); + DI_Wr(0x17ab, 0x0a0a0a0a); + DI_Wr(0x17ac, 0x0f100101); + DI_Wr(0x17ad, 0x04040606); + DI_Wr(0x17ae, 0x02030202); + DI_Wr(0x17af, 0x60020a60); +} + int adaptive_combing_fixing( struct combing_status_s *cmb_status, unsigned int field_diff, diff --git a/drivers/amlogic/media/deinterlace/deinterlace_mtn.h b/drivers/amlogic/media/deinterlace/deinterlace_mtn.h index 019e01273ebe..13cc468c7e07 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace_mtn.h +++ b/drivers/amlogic/media/deinterlace/deinterlace_mtn.h @@ -39,9 +39,12 @@ struct combing_status_s *adpative_combing_config(unsigned int width, unsigned int height, enum vframe_source_type_e src_type, bool prog, enum tvin_sig_fmt_e fmt); +extern void fix_tl1_1080i_sawtooth_patch(void); int adaptive_combing_fixing( struct combing_status_s *cmb_status, unsigned int field_diff, unsigned int frame_diff, int bit_mode); void adpative_combing_exit(void); +extern void mtn_int_combing_glbmot(void); + #endif diff --git a/drivers/amlogic/media/deinterlace/di_pps.c b/drivers/amlogic/media/deinterlace/di_pps.c index 750be0179d03..302555429af8 100644 --- a/drivers/amlogic/media/deinterlace/di_pps.c +++ b/drivers/amlogic/media/deinterlace/di_pps.c @@ -388,10 +388,12 @@ static void f2v_get_vertical_phase(unsigned int zoom_ratio, vphase->phase = (offset_out - offset_in) >> 2; } } + /* * patch 1: inp scaler 0: di wr scaler + * support: TM2 + * not support: SM1 */ - void di_pps_config(unsigned char path, int src_w, int src_h, int dst_w, int dst_h) { @@ -1325,3 +1327,61 @@ RESTART: } #endif +/* + * di pre h scaling down function + * only have h scaling down + * support: sm1 tm2 ... + * 0x37b0 ~ 0x37b5 + */ +void di_inp_hsc_setting(uint32_t src_w, uint32_t dst_w) +{ + uint32_t i; + uint32_t hsc_en; + uint32_t horz_phase_step; + int *filt_coef0 = di_filt_coef0; + /*int *filt_coef1 = di_filt_coef1;*/ + /*int *filt_coef2 = di_filt_coef2;*/ + + if (src_w == dst_w) { + hsc_en = 0; + } else { + hsc_en = 1; + /*write horz filter coefs*/ + RDMA_WR(DI_VIU_HSC_COEF_IDX, 0x0100); + for (i = 0; i < 33; i++) + RDMA_WR(DI_VIU_HSC_COEF, filt_coef0[i]); /*bicubic*/ + + horz_phase_step = (src_w << 20) / dst_w; + horz_phase_step = (horz_phase_step << 4); + RDMA_WR(DI_VIU_HSC_WIDTHM1, (src_w-1)<<16 | (dst_w-1)); + RDMA_WR(DI_VIU_HSC_PHASE_STEP, horz_phase_step); + RDMA_WR(DI_VIU_HSC_PHASE_CTRL, 0); + } + RDMA_WR(DI_VIU_HSC_CTRL, + (4 << 20) | /* initial receive number*/ + (0 << 12) | /* initial pixel ptr*/ + (1 << 10) | /* repeat first pixel number*/ + (0 << 8) | /* sp422 mode*/ + (4 << 4) | /* horz scaler bank length*/ + (0 << 2) | /* phase0 always en*/ + (0 << 1) | /* nearest_en*/ + (hsc_en<<0)); /* hsc_en*/ +} + +/* + * 0x37b0 ~ 0x37b5 + */ +void dump_hdownscler_reg(unsigned int base_addr) +{ + unsigned int i = 0x374e; + + pr_info("-----dump hdownscler start-----\n"); + for (i = 0x37b0; i < 0x37b5; i++) { + pr_info("[0x%x][0x%x]=0x%x\n", + base_addr + (i << 2), + i, RDMA_RD(i)); + } + pr_info("-----dump hdownscler end-----\n"); +} + + diff --git a/drivers/amlogic/media/deinterlace/di_pps.h b/drivers/amlogic/media/deinterlace/di_pps.h index b78a020bd4fb..a607364651f3 100644 --- a/drivers/amlogic/media/deinterlace/di_pps.h +++ b/drivers/amlogic/media/deinterlace/di_pps.h @@ -18,6 +18,7 @@ #ifndef DI_PPS_H #define DI_PPS_H #include +#include #if 0 #define VPP_FLAG_WIDEMODE_MASK 0x0000000F #define VPP_FLAG_INTERLACE_OUT 0x00000010 @@ -53,6 +54,12 @@ enum f2v_vphase_type_e { F2V_TYPE_MAX }; /* frame to video conversion type */ #endif + +enum hdr2_scaler_e { + hdr2_scaler_postdi = 0, + hdr2_scaler_predi = 1, +}; + struct pps_f2v_vphase_s { unsigned char rcv_num; unsigned char rpt_num; @@ -98,4 +105,7 @@ struct pps_frame_par_s { void di_pps_config(unsigned char path, int src_w, int src_h, int dst_w, int dst_h); void dump_pps_reg(unsigned int base_addr); +void di_inp_hsc_setting(uint32_t src_w, uint32_t dst_w); +void dump_hdownscler_reg(unsigned int base_addr); + #endif diff --git a/drivers/amlogic/media/deinterlace/film_mode_fmw/film_fw1.c b/drivers/amlogic/media/deinterlace/film_mode_fmw/film_fw1.c index cd6b46782d14..609d08bf59d1 100644 --- a/drivers/amlogic/media/deinterlace/film_mode_fmw/film_fw1.c +++ b/drivers/amlogic/media/deinterlace/film_mode_fmw/film_fw1.c @@ -17,7 +17,9 @@ #include #include +#include #include "film_vof_soft.h" +#include "../deinterlace.h" static int DIweavedetec(struct sFlmSftPar *pPar, int nDif01); @@ -68,6 +70,8 @@ UINT8 FlmVOFSftInt(struct sFlmSftPar *pPar) pPar->dif01rate = 20; pPar->flag_di01th = 0; pPar->numthd = 60; + pPar->flm32_dif02_gap_th = 7; + pPar->flm32_luma_th = 90; pPar->sF32Dif02M0 = 4096;/* mpeg-4096, cvbs-8192 */ pPar->sF32Dif02M1 = 4096; @@ -230,6 +234,7 @@ static int dif01_ratio = 10; module_param(dif01_ratio, int, 0644); MODULE_PARM_DESC(dif01_ratio, "dif01_ratio"); + int comsum; int FlmVOFSftTop(UINT8 *rCmb32Spcl, unsigned short *rPstCYWnd0, @@ -239,7 +244,8 @@ int FlmVOFSftTop(UINT8 *rCmb32Spcl, unsigned short *rPstCYWnd0, UINT8 *dif01flag, UINT32 *rROFldDif01, UINT32 *rROFrmDif02, UINT32 *rROCmbInf, UINT32 glb_frame_mot_num, UINT32 glb_field_mot_num, unsigned int *combing_row_num, - unsigned int *frame_diff_avg, struct sFlmSftPar *pPar, bool reverse) + unsigned int *frame_diff_avg, struct sFlmSftPar *pPar, bool reverse, + struct vframe_s *vf) { static UINT32 DIF01[HISDIFNUM]; /* Last one is global */ static UINT32 DIF02[HISDIFNUM]; /* Last one is global */ @@ -374,7 +380,7 @@ int FlmVOFSftTop(UINT8 *rCmb32Spcl, unsigned short *rPstCYWnd0, } /* --------------------------------------------------------- */ /* Film-Detection */ - nS1 = FlmDetSft(&pRDat, nDIF01, nDIF02, nT0, pPar); + nS1 = FlmDetSft(&pRDat, nDIF01, nDIF02, nT0, pPar, vf); nS0 = FlmModsDet(&pRDat, rROFldDif01[0], rROFrmDif02[0]); /* --------------------------------------------------------- */ @@ -601,12 +607,12 @@ int FlmVOFSftTop(UINT8 *rCmb32Spcl, unsigned short *rPstCYWnd0, /* nDif02: Frame Difference */ /* WND: The index of Window */ int FlmDetSft(struct sFlmDatSt *pRDat, int *nDif01, int *nDif02, - int WND, struct sFlmSftPar *pPar) + int WND, struct sFlmSftPar *pPar, struct vframe_s *vf) { int nT0 = 0; /* 3-2 */ - Flm32DetSft(pRDat, nDif02, nDif01, pPar); + Flm32DetSft(pRDat, nDif02, nDif01, pPar, vf); /* Film2-2 Detection */ /* debug0304 */ @@ -619,7 +625,7 @@ int FlmDetSft(struct sFlmDatSt *pRDat, int *nDif01, int *nDif02, /* pFlm02[0:nLEN-1] : recursive, 0-2 dif */ /* pFlm01[0:nLEN-1] : recursive, 0-1 dif */ int Flm32DetSft(struct sFlmDatSt *pRDat, int *nDif02, - int *nDif01, struct sFlmSftPar *pPar) + int *nDif01, struct sFlmSftPar *pPar, struct vframe_s *vf) { int sFrmDifAvgRat = pPar->sFrmDifAvgRat; /* 16; //0~32 */ /* The Large Decision should be: (large>average+LgDifThrd) */ @@ -627,7 +633,6 @@ int Flm32DetSft(struct sFlmDatSt *pRDat, int *nDif02, int sF32StpWgt01 = pPar->sF32StpWgt01; /* 15; */ int sF32StpWgt02 = pPar->sF32StpWgt02; /* 15; */ int sF32DifLgRat = pPar->sF32DifLgRat; /* 16; Dif>Rat*Min-->Larger */ - /* int sF32DifSmRat = 16; //Dif*Rat Smaller */ UINT8 *pFlm02 = pRDat->pFrm32; @@ -661,6 +666,29 @@ int Flm32DetSft(struct sFlmDatSt *pRDat, int *nDif02, int nFlgChk2 = 0; int nFlgChk3 = 0; /* for Mit32VHLine */ + int luma_avg = 0; + int flm32_dif02_gap = 0; + + int flm32_luma_th = pPar->flm32_luma_th; // APL th + int flm32_dif02_gap_th = pPar->flm32_dif02_gap_th; + + /* ============================================= */ + /*patch for dark scenes don't into pulldown32 by vlsi yanling*/ + if (vf == NULL || !IS_VDIN_SRC(vf->source_type)) + luma_avg = flm32_luma_th; + else { + if (vf->prop.hist.pixel_sum > 0) + luma_avg = vf->prop.hist.luma_sum / + vf->prop.hist.pixel_sum; + else + luma_avg = flm32_luma_th; + } + if (luma_avg < flm32_luma_th) + flm32_dif02_gap = flm32_dif02_gap_th * 2; + else + flm32_dif02_gap = flm32_dif02_gap_th; + /*---------------------------------*/ + prt_flg = ((pr_pd >> 2) & 0x1); if (prt_flg) sprintf(debug_str, "#Dbg32:\n"); @@ -759,7 +787,6 @@ int Flm32DetSft(struct sFlmDatSt *pRDat, int *nDif02, nFlgChk1 = 0; nFlgChk2 = 0; } - /* ============================================= */ nT2 = 5 * nDif02[HISDIFNUM - 1] / (nMn + sFrmDifLgTDif + 1); nT2 = nT2>>1; @@ -779,7 +806,10 @@ int Flm32DetSft(struct sFlmDatSt *pRDat, int *nDif02, if (nSTP > 16) nSTP = 16; - + /*patch for dark scenes don't into pulldown32 by vlsi yanling*/ + if (((nMx + nMn/2) / (nMn + 1)) < flm32_dif02_gap) + nSTP = 0; + /*---------------*/ for (nT0 = 1; nT0 < HISDETNUM; nT0++) { pFlm02[nT0 - 1] = pFlm02[nT0]; pFlm02t[nT0 - 1] = pFlm02t[nT0]; @@ -1159,6 +1189,10 @@ int Flm22DetSft(struct sFlmDatSt *pRDat, int *nDif02, int flm22_comlev1 = pPar->flm22_comlev1; int flm22_comnum = pPar->flm22_comnum; + int dif_flag; + int flm22_min; + int flm22_th; + int cFlg = pFlg[HISDETNUM - 1]; int rFlg[4] = { 2, 3, 4, 1 }; @@ -1558,7 +1592,16 @@ int Flm22DetSft(struct sFlmDatSt *pRDat, int *nDif02, nFlm22Lvl -= nT1; } - if (flm22_flag) { + /* ---------------------- */ + /*DI:PQ patch fix 480i error into pulldown22(by yanling)*/ + flm22_min = nDif01[HISDIFNUM-1] > nDif01[HISDIFNUM-2] + ? nDif01[HISDIFNUM-2] : nDif01[HISDIFNUM-1]; + flm22_th = flm22_min/2; + dif_flag = abs(nDif01[HISDIFNUM-1]-nDif01[HISDIFNUM-2]) + > flm22_th ? 1:0; + dif_flag = nDif01[HISDIFNUM-1] > (1<<16) ? dif_flag : 0; + if (flm22_flag && dif_flag) { + /* ---------------------- */ if (pFlg[HISDETNUM-1] == 3 || pFlg[HISDETNUM-1] == 1) { if (comsum > flm22_comnum) { @@ -1581,8 +1624,9 @@ int Flm22DetSft(struct sFlmDatSt *pRDat, int *nDif02, if (nFlgCk21 < flm22_chk21_sml) nFlm22Lvl = nFlm22Lvl + flm22_comlev1 - nFlgCk21; if (prt_flg) { - pr_info("nFlm22Lvl=%d, nFlgCk20=%d, nFlgCk21=%d\n", - nFlm22Lvl, nFlgCk20, nFlgCk21); + pr_info("nFlm22Lvl=%d, nFlgCk20=%d, nFlgCk21=%d,flm22_min=%d,flm22_th=%d\n", + nFlm22Lvl, nFlgCk20, nFlgCk21, + flm22_min, flm22_th); } } /* for sony-mp3 */ diff --git a/drivers/amlogic/media/deinterlace/film_mode_fmw/film_vof_soft.h b/drivers/amlogic/media/deinterlace/film_mode_fmw/film_vof_soft.h index d5c2d4802772..0fa9ac8fcee8 100644 --- a/drivers/amlogic/media/deinterlace/film_mode_fmw/film_vof_soft.h +++ b/drivers/amlogic/media/deinterlace/film_mode_fmw/film_vof_soft.h @@ -18,6 +18,8 @@ #ifndef _FLMVOFSFT_H_ #define _FLMVOFSFT_H_ #include +#include + /* Film Detection and VOF detection Software implementation */ /* Designer: Xin.Hu@amlogic.com */ /* Date: 12/06/13 */ @@ -129,6 +131,9 @@ struct sFlmSftPar { int flag_di01th; int numthd; + int flm32_dif02_gap_th; + int flm32_luma_th; + UINT32 sF32Dif02M0; /* mpeg-4096, cvbs-8192 */ UINT32 sF32Dif02M1; /* mpeg-4096, cvbs-8192 */ unsigned int field_count; @@ -163,7 +168,8 @@ int FlmVOFSftTop(UINT8 *rCmb32Spcl, unsigned short *rPstCYWnd0, UINT8 *dif01flag, UINT32 *rROFldDif01, UINT32 *rROFrmDif02, UINT32 *rROCmbInf, UINT32 glb_frame_mot_num, UINT32 glb_field_mot_num, unsigned int *cmb_row_num, - unsigned int *frame_diff_avg, struct sFlmSftPar *pPar, bool reverse); + unsigned int *frame_diff_avg, struct sFlmSftPar *pPar, bool reverse, + struct vframe_s *vf); /* length of pFlm01/nDif01: [0:5]; */ /* iDx: index of minimum dif02 ([0:5] */ @@ -174,7 +180,7 @@ int Cal32Flm01(UINT8 *pFlm01, int *nDif01, int iDx, struct sFlmSftPar *pPar); /* nDif02: Frame Difference */ /* WND: The index of Window */ int FlmDetSft(struct sFlmDatSt *pRDat, int *nDif01, int *nDif02, int WND, - struct sFlmSftPar *pPar); + struct sFlmSftPar *pPar, struct vframe_s *vf); int VOFDetSub1(int *PREWV, int *nCNum, int nMod, UINT32 *nRCmb, int nROW, struct sFlmSftPar *pPar); @@ -186,7 +192,7 @@ int VOFDetSft(int *VOFWnd, int *nCNum, int *nGCmb, /* */ int Flm32DetSft(struct sFlmDatSt *pRDat, int *nDif02, int *nDif01, - struct sFlmSftPar *pPar); + struct sFlmSftPar *pPar, struct vframe_s *vf); /* Film2-2 Detection */ int Flm22DetSft(struct sFlmDatSt *pRDat, int *nDif02, diff --git a/drivers/amlogic/media/deinterlace/nr_drv.c b/drivers/amlogic/media/deinterlace/nr_drv.c index 4d93d465f2aa..76a1ba248e08 100644 --- a/drivers/amlogic/media/deinterlace/nr_drv.c +++ b/drivers/amlogic/media/deinterlace/nr_drv.c @@ -280,7 +280,10 @@ static void dnr_config(struct DNR_PARM_s *dnr_parm_p, DI_Wr(DNR_DM_CTRL, Rd(DNR_DM_CTRL)|(1 << 11)); DI_Wr_reg_bits(DNR_CTRL, dnr_en?1:0, 16, 1); /* dm for sd, hd will slower */ - DI_Wr(DNR_CTRL, 0x1df00); + if (is_meson_tl1_cpu() || is_meson_tm2_cpu()) + DI_Wr(DNR_CTRL, 0x1df00 | (0x03 << 18)); //5 line + else + DI_Wr(DNR_CTRL, 0x1df00); if (is_meson_gxlx_cpu()) { /* disable chroma dm according to baozheng */ DI_Wr_reg_bits(DNR_DM_CTRL, 0, 8, 1); @@ -353,7 +356,8 @@ static void linebuffer_config(unsigned short width) static void nr2_config(unsigned short width, unsigned short height) { if (is_meson_txlx_cpu() || is_meson_g12a_cpu() || - is_meson_g12b_cpu()) { + is_meson_g12b_cpu() || is_meson_tl1_cpu() || + is_meson_sm1_cpu() || is_meson_tm2_cpu()) { DI_Wr_reg_bits(NR4_TOP_CTRL, nr2_en, 2, 1); DI_Wr_reg_bits(NR4_TOP_CTRL, nr2_en, 15, 1); DI_Wr_reg_bits(NR4_TOP_CTRL, nr2_en, 17, 1); @@ -402,7 +406,8 @@ void nr_all_config(unsigned short width, unsigned short height, if (cpu_after_eq(MESON_CPU_MAJOR_ID_GXLX)) cue_config(nr_param.pcue_parm, field_type); if (is_meson_txlx_cpu() || is_meson_g12a_cpu() || - is_meson_g12b_cpu()) { + is_meson_g12b_cpu() || is_meson_tl1_cpu() || + is_meson_sm1_cpu() || is_meson_tm2_cpu()) { linebuffer_config(width); nr4_config(nr_param.pnr4_parm, width, height); } @@ -507,6 +512,18 @@ static void noise_meter_process(struct NR4_PARM_s *nr4_param_p, } else val1 = 64; DI_Wr_reg_bits(NR4_MCNR_MV_CTRL_REG, val1, 4, 8); + /*add for TL1------*/ + if (nr4_param_p->sw_nr4_noise_ctrl_dm_en == 1) { + if (nr4_param_p->sw_nr4_noise_sel == 0) { + val2 = val1 >= nr4_param_p->sw_nr4_noise_thd ? 1 : 0; + } else { + val2 = + field_sad >= nr4_param_p->sw_nr4_noise_thd ? 1 : 0; + } + + DI_Wr_reg_bits(DNR_DM_NR_BLND, val2, 24, 1); + } + /*------------------*/ /* scene change processing */ nr4_param_p->sw_nr4_scene_change_flg[0] = nr4_param_p->sw_nr4_scene_change_flg[1]; @@ -527,6 +544,16 @@ static void noise_meter_process(struct NR4_PARM_s *nr4_param_p, DI_Wr_reg_bits(NR4_TOP_CTRL, 1, 0, 1); else DI_Wr_reg_bits(NR4_TOP_CTRL, 0, 0, 1); + + /*fot TL1 **************/ + if (nr4_param_p->sw_dm_scene_change_en == 1) { + val = field_sad >= nr4_param_p->sw_nr4_scene_change_thd2 + && nr4_param_p->sw_nr4_field_sad[1] + >= nr4_param_p->sw_nr4_scene_change_thd2; + + DI_Wr_reg_bits(DNR_DM_CTRL, val, 12, 1); + } + /***********************/ nr4_param_p->sw_nr4_field_sad[0] = nr4_param_p->sw_nr4_field_sad[1]; nr4_param_p->sw_nr4_field_sad[1] = field_sad; } @@ -570,15 +597,24 @@ static void dnr_process(struct DNR_PARM_s *pDnrPrm) #ifdef DNR_HV_SHIFT int ro_hbof_stat_cnt[32], ro_vbof_stat_cnt[32], i = 0; #endif + int ll, lr; - if (ro_gbs_stat_lr != Rd(DNR_RO_GBS_STAT_LR) || - ro_gbs_stat_ll != Rd(DNR_RO_GBS_STAT_LL) || + if (is_meson_tl1_cpu() || is_meson_tm2_cpu()) { + ll = Rd(DNR_RO_GBS_STAT_LR); + lr = Rd(DNR_RO_GBS_STAT_LL); + } else { + ll = Rd(DNR_RO_GBS_STAT_LL); + lr = Rd(DNR_RO_GBS_STAT_LR); + + } + if (ro_gbs_stat_lr != lr || + ro_gbs_stat_ll != ll || ro_gbs_stat_rr != Rd(DNR_RO_GBS_STAT_RR) || ro_gbs_stat_dif != Rd(DNR_RO_GBS_STAT_DIF) || ro_gbs_stat_cnt != Rd(DNR_RO_GBS_STAT_CNT)) { - ro_gbs_stat_lr = Rd(DNR_RO_GBS_STAT_LR); - ro_gbs_stat_ll = Rd(DNR_RO_GBS_STAT_LL); + ro_gbs_stat_lr = lr; + ro_gbs_stat_ll = ll; ro_gbs_stat_rr = Rd(DNR_RO_GBS_STAT_RR); ro_gbs_stat_dif = Rd(DNR_RO_GBS_STAT_DIF); ro_gbs_stat_cnt = Rd(DNR_RO_GBS_STAT_CNT); @@ -691,13 +727,34 @@ static void cue_process_irq(void) if (nr_param.frame_count == 5) Wr_reg_bits(NR2_CUE_MODE, 7, 0, 4); } - +void cue_int(void) +{ + /*confirm with vlsi-liuyanling, G12a cue must be disabled*/ + if (is_meson_g12a_cpu()) { + cue_en = false; + cue_glb_mot_check_en = false; + } + if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12B)) { + if (cue_en) + Wr_reg_bits(NR2_CUE_MODE, 3, 10, 2); + } +} static bool glb_fieldck_en = true; module_param_named(glb_fieldck_en, glb_fieldck_en, bool, 0644); void adaptive_cue_adjust(unsigned int frame_diff, unsigned int field_diff) { struct CUE_PARM_s *pcue_parm = nr_param.pcue_parm; + unsigned int mask1, mask2; + + if (is_meson_tl1_cpu() || is_meson_tm2_cpu()) { + /*value from VLSI(yanling.liu) 2018-12-07: */ + mask1 = 0x50332; + mask2 = 0x00054357; + } else { /*ori value*/ + mask1 = 0x50323; + mask2 = 0x00054375; + } if (frame_diff > pcue_parm->glb_mot_framethr) { pcue_parm->frame_count = pcue_parm->frame_count > 0 ? @@ -722,10 +779,10 @@ void adaptive_cue_adjust(unsigned int frame_diff, unsigned int field_diff) /* for clockfuliness clip */ if (pcue_parm->field_count > (pcue_parm->glb_mot_fieldnum - 6)) { - Wr(NR2_CUE_MODE, 0x50323|(Rd(NR2_CUE_MODE)&0xc00)); + Wr(NR2_CUE_MODE, mask1|(Rd(NR2_CUE_MODE)&0xc00)); Wr(NR2_CUE_CON_MOT_TH, 0x03010e01); } else { - Wr(NR2_CUE_MODE, 0x00054375|(Rd(NR2_CUE_MODE)&0xc00)); + Wr(NR2_CUE_MODE, mask2|(Rd(NR2_CUE_MODE)&0xc00)); Wr(NR2_CUE_CON_MOT_TH, 0xa03c8c3c); } } @@ -782,7 +839,8 @@ void nr_process_in_irq(void) if (dnr_en) dnr_process(&dnr_param); if (is_meson_txlx_cpu() || is_meson_g12a_cpu() - || is_meson_g12a_cpu()) { + || is_meson_g12a_cpu() || is_meson_tl1_cpu() || + is_meson_sm1_cpu() || is_meson_tm2_cpu()) { noise_meter_process(nr_param.pnr4_parm, nr_param.frame_count); luma_enhancement_process(nr_param.pnr4_parm, nr_param.frame_count); @@ -929,6 +987,17 @@ static void nr4_params_init(struct NR4_PARM_s *nr4_parm_p) nr4_params[24].name = "nr4_debug"; nr4_params[24].addr = &(nr4_parm_p->nr4_debug); + nr4_params[25].name = "sw_nr4_noise_thd"; + nr4_params[25].addr = &(nr4_parm_p->sw_nr4_noise_thd); + nr4_params[26].name = "sw_nr4_noise_sel"; + nr4_params[26].addr = &(nr4_parm_p->sw_nr4_noise_sel); + nr4_params[27].name = "sw_nr4_noise_ctrl_dm_en"; + nr4_params[27].addr = &(nr4_parm_p->sw_nr4_noise_ctrl_dm_en); + nr4_params[28].name = "sw_nr4_scene_change_thd2"; + nr4_params[28].addr = &(nr4_parm_p->sw_nr4_scene_change_thd2); + nr4_params[29].name = "sw_dm_scene_change_en"; + nr4_params[29].addr = &(nr4_parm_p->sw_dm_scene_change_en); + }; static ssize_t nr4_param_store(struct device *dev, @@ -1007,6 +1076,12 @@ static void nr4_param_init(struct NR4_PARM_s *nr4_parm_p) nr4_parm_p->sw_nr4_sad2gain_lut[13] = 16; nr4_parm_p->sw_nr4_sad2gain_lut[14] = 14; nr4_parm_p->sw_nr4_sad2gain_lut[15] = 9; + + nr4_parm_p->sw_nr4_noise_thd = 32; + nr4_parm_p->sw_nr4_noise_sel = 0; + nr4_parm_p->sw_nr4_noise_ctrl_dm_en = 0; + nr4_parm_p->sw_nr4_scene_change_thd2 = 80; + nr4_parm_p->sw_dm_scene_change_en = 0; } static void cue_param_init(struct CUE_PARM_s *cue_parm_p) @@ -1117,7 +1192,10 @@ void nr_hw_init(void) { nr_gate_control(true); - DI_Wr(DNR_CTRL, 0x1df00); + if (is_meson_tl1_cpu() || is_meson_tm2_cpu()) + DI_Wr(DNR_CTRL, 0x1df00|(0x03<<18));//5 line + else + DI_Wr(DNR_CTRL, 0x1df00); DI_Wr(NR3_MODE, 0x3); DI_Wr(NR3_COOP_PARA, 0x28ff00); DI_Wr(NR3_CNOOP_GAIN, 0x881900); @@ -1130,7 +1208,8 @@ void nr_hw_init(void) void nr_gate_control(bool gate) { if (!is_meson_txlx_cpu() && !is_meson_g12a_cpu() - && !is_meson_g12b_cpu()) + && !is_meson_g12b_cpu() && !is_meson_sm1_cpu() + && !is_meson_tl1_cpu() && !is_meson_tm2_cpu()) return; if (gate) { /* enable nr auto gate */ diff --git a/drivers/amlogic/media/deinterlace/nr_drv.h b/drivers/amlogic/media/deinterlace/nr_drv.h index 0ec80d606847..0d0c714e22e0 100644 --- a/drivers/amlogic/media/deinterlace/nr_drv.h +++ b/drivers/amlogic/media/deinterlace/nr_drv.h @@ -24,7 +24,7 @@ struct nr_param_s { int *addr; }; -#define NR4_PARAMS_NUM 25 +#define NR4_PARAMS_NUM (30) //25 #define dnr_param_t struct nr_param_s #define nr4_param_t struct nr_param_s @@ -68,6 +68,16 @@ struct NR4_PARM_s { unsigned short width; unsigned short height; unsigned short border_offset; + + unsigned int sw_nr4_noise_thd;//u8 + /*u1, 0: use nr4 global gain, 1: use field sad;*/ + unsigned int sw_nr4_noise_sel; + unsigned int sw_nr4_noise_ctrl_dm_en;//u1 + + /*u8, threshold for scene change*/ + unsigned int sw_nr4_scene_change_thd2; + /*u1, enable dm scene change check*/ + unsigned int sw_dm_scene_change_en; }; struct CUE_PARM_s { @@ -170,5 +180,8 @@ void nr_process_in_irq(void); void nr_all_config(unsigned short nCol, unsigned short nRow, unsigned short type); bool set_nr_ctrl_reg_table(unsigned int addr, unsigned int value); + +extern void cue_int(void); + #endif diff --git a/drivers/amlogic/media/deinterlace/pulldown_drv.c b/drivers/amlogic/media/deinterlace/pulldown_drv.c index 94544a2f16be..7ab71aaed144 100644 --- a/drivers/amlogic/media/deinterlace/pulldown_drv.c +++ b/drivers/amlogic/media/deinterlace/pulldown_drv.c @@ -112,7 +112,7 @@ module_param(cmb_3point_rrat, uint, 0644); MODULE_PARM_DESC(cmb_3point_rrat, "cmb_3point_rrat/n"); unsigned int pulldown_detection(struct pulldown_detected_s *res, - struct combing_status_s *cmb_sts, bool reverse) + struct combing_status_s *cmb_sts, bool reverse, struct vframe_s *vf) { unsigned int glb_frame_mot_num, glb_field_mot_num, i; unsigned int mot_row = 0, mot_max = 0, ntmp = 0; @@ -142,7 +142,8 @@ unsigned int pulldown_detection(struct pulldown_detected_s *res, &cmb_sts->cmb_row_num, &cmb_sts->frame_diff_avg, &pd_param, - reverse); + reverse, + vf); difflag = dectres.dif01flag; if (dectres.rFlmPstMod == 1) @@ -411,6 +412,10 @@ static struct pd_param_s pd_params[] = { &(pd_param.flag_di01th) }, { "numthd", &(pd_param.numthd) }, + { "flm32_dif02_gap_th", + &(pd_param.flm32_dif02_gap_th) }, + { "flm32_luma_th", + &(pd_param.flm32_luma_th) }, { "sF32Dif02M0", &(pd_param.sF32Dif02M0) }, /* mpeg-4096, cvbs-8192 */ { "sF32Dif02M1", diff --git a/drivers/amlogic/media/deinterlace/pulldown_drv.h b/drivers/amlogic/media/deinterlace/pulldown_drv.h index 912119bc78f8..e670f0f5db36 100644 --- a/drivers/amlogic/media/deinterlace/pulldown_drv.h +++ b/drivers/amlogic/media/deinterlace/pulldown_drv.h @@ -46,7 +46,7 @@ struct pulldown_detected_s { unsigned char pulldown_init(unsigned short width, unsigned short height); unsigned int pulldown_detection(struct pulldown_detected_s *res, - struct combing_status_s *cmb_sts, bool reverse); + struct combing_status_s *cmb_sts, bool reverse, struct vframe_s *vf); void pulldown_vof_win_vshift(struct pulldown_detected_s *wins, unsigned short v_offset); diff --git a/drivers/amlogic/media/deinterlace/register.h b/drivers/amlogic/media/deinterlace/register.h index adeedbbe1b46..5d8a36acb1de 100644 --- a/drivers/amlogic/media/deinterlace/register.h +++ b/drivers/amlogic/media/deinterlace/register.h @@ -43,8 +43,10 @@ void DI_VSYNC_WR_MPEG_REG_BITS(unsigned int addr, unsigned int val, unsigned int start, unsigned int len); #define HHI_VPU_CLKB_CNTL 0x83 -#define VPU_WRARB_REQEN_SLV_L1C1 ((0x2795)) /* << 2) + 0xd0100000) */ -#define VPU_ARB_DBG_STAT_L1C1 ((0x27b4)) /* << 2) + 0xd0100000) */ + +#define DI_WRARB_REQEN_SLV_L1C1_OLD 0x2795 +#define DI_RDARB_REQEN_SLV_L1C1_OLD 0x2791 +#define DI_ARB_DBG_STAT_L1C1_OLD 0x27b4 #define VIUB_SW_RESET 0x2001 #define VIUB_SW_RESET0 0x2002 @@ -210,6 +212,15 @@ void DI_VSYNC_WR_MPEG_REG_BITS(unsigned int addr, #define DI_HSC_INI_PAT_CTRL 0x376b #define DI_SC_GCLK_CTRL 0x376c #define DI_SC_HOLD_LINE 0x376d + +/* DI H DOWN SCALER */ +#define DI_VIU_HSC_WIDTHM1 0x37b0 +#define DI_VIU_HSC_PHASE_STEP 0x37b1 +#define DI_VIU_HSC_CTRL 0x37b2 +#define DI_VIU_HSC_PHASE_CTRL 0x37b3 +#define DI_VIU_HSC_COEF 0x37b4 +#define DI_VIU_HSC_COEF_IDX 0x37b5 + /* NR DOWNSAMPLE */ #define NRDSWR_X 0x37f9 #define NRDSWR_Y 0x37fa diff --git a/drivers/amlogic/media/dtv_demod/aml_demod.c b/drivers/amlogic/media/dtv_demod/aml_demod.c index ea2b742f3585..63d44fa2df17 100644 --- a/drivers/amlogic/media/dtv_demod/aml_demod.c +++ b/drivers/amlogic/media/dtv_demod/aml_demod.c @@ -280,6 +280,7 @@ static long aml_demod_ioctl(struct file *file, dvbfe = aml_get_fe();/*get_si2177_tuner();*/ #if 0 if (dvbfe != NULL) + if (dvbfe->ops.tuner_ops.get_strength) strength = dvbfe->ops.tuner_ops.get_strength(dvbfe); #else strength = tuner_get_ch_power2(); @@ -323,7 +324,8 @@ static long aml_demod_ioctl(struct file *file, #if 0 /*ary temp for my_tool:*/ if (dvbfe != NULL) { pr_dbg("calling tuner ops\n"); - dvbfe->ops.tuner_ops.set_params(dvbfe); + if (dvbfe->ops.tuner_ops.set_params) + dvbfe->ops.tuner_ops.set_params(dvbfe); } #endif break; @@ -649,7 +651,6 @@ static ssize_t aml_demod_dbg_store(struct file *file, case 1://cmd switch (dbg_md) { case AML_DBG_DVBC_INIT: - Gxtv_Demod_Dvbc_v4_Init(); break; case AML_DBG_ATSC_INIT: demod_set_sys_atsc_v4(); diff --git a/drivers/amlogic/media/dtv_demod/amlfrontend.c b/drivers/amlogic/media/dtv_demod/amlfrontend.c index 0e9f226f8531..41af69a06497 100644 --- a/drivers/amlogic/media/dtv_demod/amlfrontend.c +++ b/drivers/amlogic/media/dtv_demod/amlfrontend.c @@ -51,8 +51,6 @@ #include #include "demod_func.h" -#include "depend.h" /**/ - #include "amlfrontend.h" /*dma_get_cma_size_int_byte*/ @@ -183,19 +181,21 @@ const char *name_fe_delivery_system[] = { "DVBC_ANNEX_C", "ANALOG", /*19*/ }; -void dbg_delsys(unsigned char id) -{ - if (id <= END_SYS_DELIVERY) - PR_INFO("%s:%s:\n", __func__, name_fe_delivery_system[id]); - else - PR_INFO("%s:%d\n", __func__, id); -} +static const char * const name_fe_n_mode[] = { + "AM_FE_UNKNOWN_N", + "AM_FE_QPSK_N", + "AM_FE_QAM_N", + "AM_FE_OFDM_N", + "AM_FE_ATSC_N", + "AM_FE_DTMB_N", + "AM_FE_ISDBT_N", + "AM_FE_NUM", +}; + static void dtvdemod_vdac_enable(bool on); static void dtvdemod_set_agc_pinmux(int on); - - static int Gxtv_Demod_Dvbc_Init(/*struct aml_fe_dev *dev, */int mode); static ssize_t dvbc_auto_sym_show(struct class *cls, struct class_attribute *attr, char *buf) @@ -933,8 +933,7 @@ static int gxtv_demod_dvbc_read_status_timer struct aml_demod_sts demod_sts; struct aml_demod_sta demod_sta; int strenth; - - int ilock; + int ilock = 0; /*check tuner*/ if (!timer_tuner_not_enough()) { @@ -944,9 +943,11 @@ static int gxtv_demod_dvbc_read_status_timer return 0; } } + /*demod_sts.ch_sts = qam_read_reg(0x6);*/ demod_sts.ch_sts = dvbc_get_ch_sts(); dvbc_status(&demod_sta, /*&demod_i2c,*/ &demod_sts); + if (demod_sts.ch_sts & 0x1) { ilock = 1; *status = @@ -963,6 +964,7 @@ static int gxtv_demod_dvbc_read_status_timer timer_disable(D_TIMER_DETECT); } } + if (last_lock != ilock) { PR_DBG("%s.\n", ilock ? "!! >> LOCK << !!" : "!! >> UNLOCK << !!"); @@ -972,6 +974,60 @@ static int gxtv_demod_dvbc_read_status_timer return 0; } +static int demod_dvbc_speed_up(enum fe_status *status) +{ + unsigned int cnt, i, sts, check_ok = 0; + struct aml_demod_sts demod_sts; + const int dvbc_count = 5; + int ilock = 0; + + if (*status == 0) { + for (cnt = 0; cnt < 10; cnt++) { + demod_sts.ch_sts = dvbc_get_ch_sts(); + + if (demod_sts.ch_sts & 0x1) { + /*have signal*/ + *status = + FE_HAS_LOCK | FE_HAS_SIGNAL | + FE_HAS_CARRIER | + FE_HAS_VITERBI | FE_HAS_SYNC; + ilock = 1; + check_ok = 1; + } else { + for (i = 0; i < dvbc_count; i++) { + sts = dvbc_get_status(); + + if (sts >= 0x3) + break; + + msleep(25); + } + + PR_DBG("[rsj]dvbc_status is 0x%x\n", sts); + + if (sts < 0x3) { + *status = FE_TIMEDOUT; + ilock = 0; + check_ok = 1; + } + } + + if (check_ok == 1) + break; + + msleep(20); + } + } + + if (last_lock != ilock) { + PR_DBG("%s : %s.\n", __func__, + ilock ? "!! >> LOCK << !!" : "!! >> UNLOCK << !!"); + last_lock = ilock; + } + + return 0; +} + static int gxtv_demod_dvbc_read_ber(struct dvb_frontend *fe, u32 *ber) { /*struct aml_fe_dev *dev = afe->dtv_demod;*/ @@ -1018,7 +1074,6 @@ static int gxtv_demod_dvbc_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) } /*extern int aml_fe_analog_set_frontend(struct dvb_frontend *fe);*/ - static int gxtv_demod_dvbc_set_frontend(struct dvb_frontend *fe) { struct dtv_frontend_properties *c = &fe->dtv_property_cache; @@ -1028,7 +1083,6 @@ static int gxtv_demod_dvbc_set_frontend(struct dvb_frontend *fe) PR_INFO("%s\n", __func__); /*timer_set_max(D_TIMER_DETECT, 4000);*/ /*timer_begain(D_TIMER_DETECT);*/ - memset(¶m, 0, sizeof(param)); param.ch_freq = c->frequency / 1000; param.mode = amdemod_qam(c->modulation); @@ -1136,194 +1190,6 @@ static int Gxtv_Demod_Dvbc_Init(/*struct aml_fe_dev *dev, */int mode) return 0; } -#if 0 -/*TL1*/ -void Gxtv_Demod_Dvbc_v4_Init(void) -{ - //struct dtv_frontend_properties *c = &fe->dtv_property_cache; - struct aml_demod_dvbc dvbc; - int nco_rate; - int tmp; - - //printf("frequency point is(KHz):"); - //scanf("%d", &tmp); - //dvbc.ch_freq = tmp; - //dvbc.ch_freq = 474000; - dvbc.ch_freq = 474000; - //dvbc.mode = tmp; - dvbc.mode = 4;// 0=16QAM, 1=32QAM, 2 = 64QAM, 3 = 128QAM, 4 = 256QAM - //dvbc.symb_rate = tmp; - dvbc.symb_rate = 5360;//6875;5056(J.83b 64QAM),5360(J.83b 256QAM) - //ioctl(fd, AML_DEMOD_DVBC_SET_CH, &dvbc); - dvbc.dat0 = 24000; - nco_rate = (24*256)/250+2; - - //app_apb_write_reg(0xf00*4,0x88); - demod_write_reg(DEMOD_TOP_REG0, 0x88); - //app_apb_write_reg(0xf08*4,0x201); - demod_write_reg(DEMOD_TOP_REG8, 0x201); - //app_apb_write_reg(0xf0c*4,0x11); //open write enable - demod_write_reg(DEMOD_TOP_REGC, 0x11); - //app_apb_write_reg(0xe20, - //((app_apb_read_reg(0xe20) &~ 0xff) | (nco_rate & 0xff))); - //app_apb_write_reg(0xe20, (app_apb_read_reg(0xe20) | (1 << 8))); - front_write_reg_v4(0x20, - ((front_read_reg_v4(0x20) & ~0xff) | (nco_rate & 0xff))); - front_write_reg_v4(0x20, (front_read_reg_v4(0x20) | (1 << 8))); - - //dvbc_reg_initial_tmp(&dvbc); - dvbc_reg_initial_tmp_v4(&dvbc); - - //printf("set J.83B(1) OR DVBC(2)"); - tmp = 2; - if (tmp == 1) { - //app_apb_write_reg(reg_reset,0x10f33); - qam_write_reg(0x7, 0x10f33); - //set_j83b_filter_reg(); - set_j83b_filter_reg_v4(); - } else { - //app_apb_write_reg(reg_reset,0xf33); - qam_write_reg(0x7, 0xf33); - } - - #if 0 - printf("select 0~3 mode:"); - scanf("%d", &tmp); - if (tmp == 0) { - //set_dvbc_reg_1(); - set_dvbc_reg_1_v4(); - //set_dvbc_reg_2(); - set_dvbc_reg_2_v4(); - } else if (tmp == 1) { - //set_dvbc_reg_1(); - set_dvbc_reg_1_v4(); - //set_j83b_reg_2(); - set_j83b_reg_2_v4(); - } else if (tmp == 2) { - //set_j83b_reg_1(); - set_j83b_reg_1_v4(); - //set_dvbc_reg_2(); - set_dvbc_reg_2_v4(); - } else if (tmp == 3) { - //set_j83b_reg_1(); - set_j83b_reg_1_v4(); - //set_j83b_reg_2(); - set_j83b_reg_2_v4(); - } - #endif - - #if 0 - app_apb_write_reg(0x48, 0x50e1000); - app_apb_write_reg(0xc0, 0x41f2f69); - #else - qam_write_reg(0x12, 0x50e1000); - qam_write_reg(0x30, 0x41f2f69); - #endif -} - -int uart_error_confirm(int a_0, int a_1) -{ - int flag_out_of_range; - int flag_error; - int flag_zero; - int flag_sta_check; - int st[2]; - int out; - - st[0] = a_0&0xf; - st[1] = (a_0>>4)&0xf; - if (st[1] == 0) - flag_sta_check = ((st[0] == 1) || (st[0] == 2)) ? 0 : 1; - if (st[1] == 1) - flag_sta_check = ((st[0] == 2) || (st[0] == 3)) ? 0 : 1; - if (st[1] == 2) - flag_sta_check = (st[0] == 3) ? 0 : 1; - if (st[1] == 3) - flag_sta_check = (st[0] == 4) ? 0 : 1; - if (st[1] == 4) - flag_sta_check = (st[0] == 6) ? 0 : 1; - if (st[1] == 6) - flag_sta_check = ((st[0] == 4) || (st[0] == 5)) ? 0 : 1; - - flag_zero = (a_0 == 0) ? 1 : 0; - flag_out_of_range = ((a_0 & 0xf) > 6) ? 1 : 0; - flag_error = (((a_0 >> 4) & 0x0fffffff) == (a_1 & 0x0fffffff)) ? 0 : 1; - out = ((flag_out_of_range == 1) || (flag_error == 1) - || (flag_zero == 1)) ? 1 : 0; - return out; -} - -void print_dvbc_result(void) -{ - //int timer1, - int time; - int i, tmp; - //float ftmp; - //struct aml_demod_sts sts; - int status[2], uart_error; - int record = 6, cnt = 0, cur_res = 0; - - //timer1 = read_time_usecond(); - status[0] = status[1] = 0; - time = 1; - i = 0; - while (i < time) { - status[0] = qam_read_reg(0x31); - //if((status[0]&0xf) == 5){ - // timer2=read_time_usecond(); - // printf("\n\n\n\n[sync timer]%d\n",timer2-timer1); - // break; - //} - uart_error = uart_error_confirm(status[0], status[1]); - usleep_range(10000, 10001); - status[1] = status[0]; - i = i + 1; - - //lg add state cnt - cur_res = status[1] & 0xf; - if (cur_res != 6) { - record = cur_res; - } else { - if (record != cur_res) - cnt++; - record = cur_res; - } - - // ioctl(fd, AML_DEMOD_DVBC_GET_CH, &sts); - //tmp = sts.ch_sts; - PR_INFO("sta %08x ulock_n %d ", qam_read_reg(0x6), cnt); - //ftmp = sts.ch_snr; - //ftmp /= 100.0; - //ftmp=(app_apb_read_reg(0x174)&0xfff0)/16/32; - //ftmp=(dvbc_read_reg(0x174)&0xfff0)/16/32; - //PR_INFO("snr %5.2f dB ", ftmp); - PR_INFO("eq status is %d ", qam_read_reg(0x5d)&0xf); - PR_INFO("npn_det %d impdet %d imp_n %d ", - qam_read_reg(0x58)>>20&0x1, qam_read_reg(0x58)>>16&0x3, - qam_read_reg(0x58)&0xffff); - // ftmp = sts.ch_ber; - // ftmp /= 1e6; - // printf("ber %.2e ", ftmp); - // if(ber_avg == 0) - // ber_avg = ftmp; - // ber_avg = ber_avg + (ftmp-ber_avg)/32; - // printf("beravg %.2e ", ber_avg); - tmp = (qam_read_reg(0x33)&0xffff); - //tmp = sts.ch_per; - PR_INFO("per %d ", tmp); - //ftmp=(dvbc_read_reg(0x34)&0xffff)/1e3; - // ftmp = sts.symb_rate; - //PR_INFO("srate %.3f ", ftmp); - //ftmp = (dvbc_read_reg(0x28)&0x7fffff)/1e3; - //PR_INFO("freqoff %.3f kHz ", ftmp); - tmp = (qam_read_reg(0x27)); - //PR_INFO("power %ddb,gain %.3d ", - //((tmp>>22) & 0x1ff)/16.0, tmp & 0x7ff); - PR_INFO("lock sta %x\n", qam_read_reg(0x6)); - } -} -#endif - static void gxtv_demod_dvbt_release(struct dvb_frontend *fe) { @@ -1755,8 +1621,8 @@ static int gxtv_demod_atsc_set_frontend(struct dvb_frontend *fe) if (atsc_flag != QAM_AUTO) atsc_flag = QAM_AUTO; /* demod_set_demod_reg(0x502, TXLX_ADC_REG6);*/ - if (!is_ic_ver(IC_VER_TL1)) - dd_tvafe_hiu_reg_write(D_HHI_DEMOD_CLK_CNTL, 0x502); + //sys_clk=167M + dd_tvafe_hiu_reg_write(D_HHI_DEMOD_CLK_CNTL, 0x502); demod_set_mode_ts(Gxtv_Dvbc); param_j83b.ch_freq = c->frequency / 1000; @@ -1777,7 +1643,6 @@ static int gxtv_demod_atsc_set_frontend(struct dvb_frontend *fe) ((front_read_reg_v4(0x20) & ~0xff) | (nco_rate & 0xff))); front_write_reg_v4(0x2f, 0x5);//for timeshift mosaic - dd_tvafe_hiu_reg_write(0x1d0, 0x502);//sys_clk=167M } dvbc_set_ch(&demod_status, /*&demod_i2c, */¶m_j83b); @@ -1787,8 +1652,6 @@ static int gxtv_demod_atsc_set_frontend(struct dvb_frontend *fe) set_j83b_filter_reg_v4(); qam_write_reg(0x12, 0x50e1000); qam_write_reg(0x30, 0x41f2f69); - //for timeshift mosaic issue - //qam_write_reg(0x84, 0x2190000); } } else if (c->modulation > QAM_AUTO) { @@ -1829,9 +1692,6 @@ static int gxtv_demod_atsc_set_frontend(struct dvb_frontend *fe) } } - if (is_ic_ver(IC_VER_TL1)) - return 0; - if ((auto_search_std == 1) && ((c->modulation <= QAM_AUTO) && (c->modulation != QPSK))) { unsigned char s = 0; @@ -1985,6 +1845,8 @@ static int atsc_j83b_detect_first(struct dvb_frontend *fe, enum fe_status *s) int cnt; int check_ok; + j83b_status = 0; + /*tuner:*/ if (dvb_tuner_delay > 9) msleep(dvb_tuner_delay); @@ -2003,11 +1865,6 @@ static int atsc_j83b_detect_first(struct dvb_frontend *fe, enum fe_status *s) for (cnt = 0; cnt < CNT_FIRST; cnt++) { gxtv_demod_atsc_read_status(fe, &cs); - if (is_ic_ver(IC_VER_TL1)) { - *s = cs; - return 0; - } - if (cs != 0x1f) { /*msleep(200);*/ PR_DBG("[j.83b] 1\n"); @@ -2056,7 +1913,7 @@ static int atsc_j83b_polling(struct dvb_frontend *fe, enum fe_status *s) PR_DBG("+7+"); - + j83b_status = 0; strenth = tuner_get_ch_power(fe); if (strenth < THRD_TUNER_STRENTH_J83) { *s = FE_TIMEDOUT; @@ -2095,6 +1952,9 @@ void atsc_polling(struct dvb_frontend *fe, enum fe_status *status) { struct dtv_frontend_properties *c = &fe->dtv_property_cache; + if (!demod_thread) + return; + if (c->modulation == QPSK) { PR_DBG("mode is qpsk, return;\n"); /*return;*/ @@ -2646,9 +2506,8 @@ int Gxtv_Demod_Dtmb_Init(struct amldtvdemod_device_s *dev) return 0; } + #ifdef DVB_CORE_ORI - - static int gxtv_demod_dvbc_tune(struct dvb_frontend *fe, bool re_tune, unsigned int mode_flags, unsigned int *delay, enum fe_status *status) { @@ -2659,7 +2518,9 @@ static int gxtv_demod_dvbc_tune(struct dvb_frontend *fe, bool re_tune, *delay = HZ / 4; -#if 1 + if (!demod_thread) + return 0; + if (re_tune) { /*first*/ dtvdd_devp->en_detect = 1; @@ -2669,11 +2530,14 @@ static int gxtv_demod_dvbc_tune(struct dvb_frontend *fe, bool re_tune, timer_begain(D_TIMER_DETECT); gxtv_demod_dvbc_read_status_timer(fe, status); + if (is_ic_ver(IC_VER_TL1)) + demod_dvbc_speed_up(status); + PR_DBG("tune finish!\n"); return ret; } -#endif + if (!dtvdd_devp->en_detect) { PR_DBGL("tune:not enable\n"); return ret; @@ -2828,14 +2692,17 @@ void dtmb_cma_release(struct amldtvdemod_device_s *devp) } #endif -static bool enter_mode(int mode) +static bool enter_mode(enum aml_fe_n_mode_t mode) { /*struct aml_fe_dev *dev = fe->dtv_demod;*/ struct amldtvdemod_device_s *devn = dtvdd_devp; int memstart_dtmb; bool ret = true; - PR_INFO("%s:%d\n", __func__, mode); + if (mode < AM_FE_NUM) + PR_INFO("%s:%s\n", __func__, name_fe_n_mode[mode]); + else + PR_ERR("%s:%d\n", __func__, mode); dtvdemod_set_agc_pinmux(1); @@ -2855,20 +2722,20 @@ static bool enter_mode(int mode) if (mode == AM_FE_DTMB_N) { Gxtv_Demod_Dtmb_Init(devn); - if (devn->cma_flag == 1) { - PR_DBG("CMA MODE, cma flag is %d,mem size is %d", - devn->cma_flag, devn->cma_mem_size); - if (dtmb_cma_alloc(devn)) { - memstart_dtmb = devn->mem_start; - } else { - ret = false; - return ret; + if (devn->cma_flag == 1) { + PR_DBG("CMA MODE, cma flag is %d,mem size is %d", + devn->cma_flag, devn->cma_mem_size); + if (dtmb_cma_alloc(devn)) { + memstart_dtmb = devn->mem_start; + } else { + ret = false; + return ret; + } + } else { + memstart_dtmb = devn->mem_start;/*??*/ } - } else { - memstart_dtmb = devn->mem_start;/*??*/ - } devn->act_dtmb = true; dtmb_set_mem_st(memstart_dtmb); @@ -2893,6 +2760,7 @@ static bool enter_mode(int mode) timer_set_max(D_TIMER_DETECT, 2000); /*reset is 4s*/ timer_set_max(D_TIMER_SET, 4000); + if (devn->cma_flag == 1) { PR_DBG("CMA MODE, cma flag is %d,mem size is %d", devn->cma_flag, @@ -2902,11 +2770,11 @@ static bool enter_mode(int mode) } else { ret = false; return ret; - } } else { memstart_dtmb = devn->mem_start;/*??*/ } + PR_DBG("[im]memstart is %x\n", memstart_dtmb); dvbt_write_reg((0x10 << 2), memstart_dtmb); } @@ -2915,40 +2783,43 @@ static bool enter_mode(int mode) } -static int leave_mode(int mode) +static int leave_mode(enum aml_fe_n_mode_t mode) { /* struct aml_fe_dev *dev = fe->dtv_demod;*/ struct amldtvdemod_device_s *devn = dtvdd_devp; - PR_INFO("%s:\n", __func__); + if (mode < AM_FE_NUM) + PR_INFO("%s:%s\n", __func__, name_fe_n_mode[mode]); + else + PR_ERR("%s:%d\n", __func__, mode); + dtvdd_devp->en_detect = 0; dtvdd_devp->last_delsys = SYS_UNDEFINED; + dtvdd_devp->n_mode = AM_FE_UNKNOWN_N; dtvpll_init_flag(0); /*dvbc_timer_exit();*/ if (cci_thread) dvbc_kill_cci_task(); - #if 0 - if (mode == AM_FE_DTMB_N) { - dtmb_poll_stop(); /*polling mode*/ - /* close arbit */ - demod_write_reg(DEMOD_TOP_REGC, 0x0); - if (devn->cma_flag == 1) + if (mode == AM_FE_DTMB_N) { + if (dtvdd_devp->act_dtmb) { + dtmb_poll_stop(); /*polling mode*/ + /* close arbit */ + demod_write_reg(DEMOD_TOP_REGC, 0x0); + dtvdd_devp->act_dtmb = false; + } + + if ((devn->cma_flag == 1) && dtvdd_devp->flg_cma_allc) { dtmb_cma_release(devn); + dtvdd_devp->flg_cma_allc = false; + } + } else if (mode == AM_FE_OFDM_N || mode == AM_FE_ISDBT_N) { + if ((devn->cma_flag == 1) && dtvdd_devp->flg_cma_allc) { + dtmb_cma_release(devn); + dtvdd_devp->flg_cma_allc = false; + } } - #else - if (dtvdd_devp->act_dtmb) { - dtmb_poll_stop(); /*polling mode*/ - /* close arbit */ - demod_write_reg(DEMOD_TOP_REGC, 0x0); - dtvdd_devp->act_dtmb = false; - } - if ((devn->cma_flag == 1) && dtvdd_devp->flg_cma_allc) { - dtmb_cma_release(devn); - dtvdd_devp->flg_cma_allc = false; - } - #endif adc_set_pll_cntl(0, 0x04, NULL); demod_mode_para = UNKNOWN; @@ -2958,9 +2829,7 @@ static int leave_mode(int mode) dtvdemod_set_agc_pinmux(0); msleep(200); - return 0; - } /* when can't get ic_config by dts, use this*/ const struct meson_ddemod_data data_gxtvbb = { @@ -3599,15 +3468,37 @@ static int __exit aml_dtvdemod_remove(struct platform_device *pdev) static void aml_dtvdemod_shutdown(struct platform_device *pdev) { + enum aml_fe_n_mode_t nmode = dtvdd_devp->n_mode; + pr_info("%s\n", __func__); if (dtvdd_devp->state != DTVDEMOD_ST_IDLE) { - leave_mode(0); + if (nmode != AM_FE_UNKNOWN_N) + leave_mode(nmode); dtvdd_devp->state = DTVDEMOD_ST_IDLE; } } +static int aml_dtvdemod_suspend(struct platform_device *pdev, + pm_message_t state) +{ + enum aml_fe_n_mode_t nmode = dtvdd_devp->n_mode; + + PR_INFO("%s, mode = %d\n", __func__, nmode); + + if (nmode != AM_FE_UNKNOWN_N) + leave_mode(nmode); + + return 0; +} + +static int aml_dtvdemod_resume(struct platform_device *pdev) +{ + PR_INFO("%s is called\n", __func__); + return 0; +} + static struct platform_driver aml_dtvdemod_driver = { .driver = { .name = "aml_dtv_demod", @@ -3618,6 +3509,10 @@ static struct platform_driver aml_dtvdemod_driver = { .shutdown = aml_dtvdemod_shutdown, .probe = aml_dtvdemod_probe, .remove = __exit_p(aml_dtvdemod_remove), +#ifdef CONFIG_PM + .suspend = aml_dtvdemod_suspend, + .resume = aml_dtvdemod_resume, +#endif }; @@ -3792,6 +3687,7 @@ static int delsys_set(struct dvb_frontend *fe, unsigned int delsys) } if (!support) { + #if 0 if (get_dtvpll_init_flag()) { /**/ PR_INFO("delsys:%d is not support!\n", cdelsys); @@ -3801,11 +3697,17 @@ static int delsys_set(struct dvb_frontend *fe, unsigned int delsys) dtvdd_devp->last_delsys = SYS_UNDEFINED; dtvdd_devp->n_mode = AM_FE_UNKNOWN_N; } + #endif + PR_INFO("delsys:%d is not support!\n", cdelsys); return 0; } - PR_DBG("%s:l=%d,c=%d\n", __func__, ldelsys, cdelsys); - dbg_delsys(cdelsys); + if (ldelsys <= END_SYS_DELIVERY && cdelsys <= END_SYS_DELIVERY) { + PR_DBG("%s:l=%s,c=%s\n", __func__, + name_fe_delivery_system[ldelsys], + name_fe_delivery_system[cdelsys]); + } else + PR_ERR("%s:last=%d,cur=%d\n", __func__, ldelsys, cdelsys); switch (cdelsys) { @@ -3869,29 +3771,36 @@ static int delsys_set(struct dvb_frontend *fe, unsigned int delsys) case SYS_DAB: case SYS_TURBO: case SYS_UNDEFINED: + return 0; + #ifdef CONFIG_AMLOGIC_DVB_COMPAT case SYS_ANALOG: -#endif - mode = AM_FE_UNKNOWN_N; if (get_dtvpll_init_flag()) { - PR_INFO("delsys not support!%d=\n", cdelsys); - leave_mode(mode); + PR_INFO("delsys not support : %d\n", cdelsys); + leave_mode(lmode); + if (fe->ops.tuner_ops.release) fe->ops.tuner_ops.release(fe); - dtvdd_devp->last_delsys = SYS_UNDEFINED; - dtvdd_devp->n_mode = AM_FE_UNKNOWN_N; } + return 0; +#endif } if (mode != AM_FE_UNKNOWN_N) { + if (lmode != AM_FE_UNKNOWN_N) { + leave_mode(lmode); + + if (fe->ops.tuner_ops.release) + fe->ops.tuner_ops.release(fe); + } + if (!enter_mode(mode)) { PR_INFO("enter_mode failed,leave!\n"); leave_mode(mode); + if (fe->ops.tuner_ops.release) - fe->ops.tuner_ops.release(fe); - dtvdd_devp->last_delsys = SYS_UNDEFINED; - dtvdd_devp->n_mode = AM_FE_UNKNOWN_N; + fe->ops.tuner_ops.release(fe); return 0; } } @@ -3899,16 +3808,15 @@ static int delsys_set(struct dvb_frontend *fe, unsigned int delsys) if (!get_dtvpll_init_flag()) { PR_INFO("pll is not set!\n"); leave_mode(mode); + if (fe->ops.tuner_ops.release) fe->ops.tuner_ops.release(fe); - dtvdd_devp->last_delsys = SYS_UNDEFINED; - dtvdd_devp->n_mode = AM_FE_UNKNOWN_N; return 0; } dtvdd_devp->last_delsys = cdelsys; -#if 1 /*ary add for test*/ PR_INFO("info type:%d", fe->ops.info.type); + if (mode == AM_FE_ATSC_N) fe->ops.info.type = FE_ATSC; else if (mode == AM_FE_OFDM_N) @@ -3920,9 +3828,8 @@ static int delsys_set(struct dvb_frontend *fe, unsigned int delsys) else if (mode == AM_FE_ISDBT_N) fe->ops.info.type = FE_ISDBT; - fe->ops.tuner_ops.set_config(fe, NULL); - -#endif + if (fe->ops.tuner_ops.set_config) + fe->ops.tuner_ops.set_config(fe, NULL); return 0; } @@ -3954,11 +3861,11 @@ static int aml_dtvdm_sleep(struct dvb_frontend *fe) if (get_dtvpll_init_flag()) { PR_INFO("%s\n", __func__); - leave_mode(nmode); + if (nmode != AM_FE_UNKNOWN_N) + leave_mode(nmode); + if (fe->ops.tuner_ops.release) fe->ops.tuner_ops.release(fe); - dtvdd_devp->last_delsys = SYS_UNDEFINED; - dtvdd_devp->n_mode = AM_FE_UNKNOWN_N; } return 0; } @@ -4334,11 +4241,11 @@ static void aml_dtvdm_release(struct dvb_frontend *fe) if (get_dtvpll_init_flag()) { PR_INFO("%s\n", __func__); - leave_mode(nmode); + if (nmode != AM_FE_UNKNOWN_N) + leave_mode(nmode); + if (fe->ops.tuner_ops.release) fe->ops.tuner_ops.release(fe); - dtvdd_devp->last_delsys = SYS_UNDEFINED; - dtvdd_devp->n_mode = AM_FE_UNKNOWN_N; } } diff --git a/drivers/amlogic/media/dtv_demod/atsc_func.c b/drivers/amlogic/media/dtv_demod/atsc_func.c index d95b1ef53ad2..1c1159624189 100644 --- a/drivers/amlogic/media/dtv_demod/atsc_func.c +++ b/drivers/amlogic/media/dtv_demod/atsc_func.c @@ -565,6 +565,7 @@ if (!field_test_version) { atsc_write_reg(0x54d, 0x08); atsc_write_reg(0x54c, 0x08); atsc_write_reg(0x53b, 0x0e); + atsc_write_reg(0x912, 0x50); } ar_flag = 0; } diff --git a/drivers/amlogic/media/dtv_demod/dtmb_func.c b/drivers/amlogic/media/dtv_demod/dtmb_func.c index 784690961b0a..90e7714e95ab 100644 --- a/drivers/amlogic/media/dtv_demod/dtmb_func.c +++ b/drivers/amlogic/media/dtv_demod/dtmb_func.c @@ -198,6 +198,12 @@ void dtmb_all_reset(void) dtmb_write_reg(DTMB_CHE_FD_TD_COEFF, temp_data); } } + + /*for non-standard signal, + *ignore calculatiing amplitude tps(transport parameter signalling) + */ + dtmb_write_reg(DTMB_CHE_IBDFE_CONF0, + dtmb_read_reg(DTMB_CHE_IBDFE_CONF0) & 0xfffff0ff); } void dtmb_initial(struct aml_demod_sta *demod_sta) diff --git a/drivers/amlogic/media/dtv_demod/dvbc_func.c b/drivers/amlogic/media/dtv_demod/dvbc_func.c index ca2ac4e98827..8bbb208c6074 100644 --- a/drivers/amlogic/media/dtv_demod/dvbc_func.c +++ b/drivers/amlogic/media/dtv_demod/dvbc_func.c @@ -331,7 +331,7 @@ int dvbc_set_ch(struct aml_demod_sta *demod_sta, ret = -1; } /* if (ret != 0) return ret; */ - demod_sta->dvb_mode = 0; + //demod_sta->dvb_mode = 0; demod_sta->ch_mode = mode; /* 0:16, 1:32, 2:64, 3:128, 4:256 */ demod_sta->agc_mode = 1; diff --git a/drivers/amlogic/media/dtv_demod/dvbc_v3.c b/drivers/amlogic/media/dtv_demod/dvbc_v3.c index 92bd3ccc007a..3457a51ec07a 100644 --- a/drivers/amlogic/media/dtv_demod/dvbc_v3.c +++ b/drivers/amlogic/media/dtv_demod/dvbc_v3.c @@ -367,8 +367,10 @@ void dvbc_reg_initial(struct aml_demod_sta *demod_sta) /* // configure min symbol_rate fb = 6.95M*/ qam_write_reg(0x12, (qam_read_reg(0x12) & ~(0xff<<8)) | 3400 * 256); + #if 0 if (is_ic_ver(IC_VER_TL1)) qam_write_reg(0x51, (qam_read_reg(0x51)&~(0x1<<28))); + #endif /* configure min symbol_rate fb = 6.95M */ /*dvbc_write_reg(QAM_BASE+0x0c0, 0xffffff68); // threshold */ @@ -432,40 +434,43 @@ void dvbc_reg_initial(struct aml_demod_sta *demod_sta) /* enable irq */ qam_write_reg(0x34, 0x7fff << 3); -#if 1 + /*if (is_meson_txlx_cpu()) {*/ - if (is_ic_ver(IC_VER_TXLX)) { + if (is_ic_ver(IC_VER_TXLX) || (is_ic_ver(IC_VER_TL1))) { /*my_tool setting j83b mode*/ qam_write_reg(0x7, 0x10f33); - /*j83b filter para*/ - qam_write_reg(0x40, 0x3f010201); - qam_write_reg(0x41, 0x0a003a3b); - qam_write_reg(0x42, 0xe1ee030e); - qam_write_reg(0x43, 0x002601f2); - qam_write_reg(0x44, 0x009b006b); - qam_write_reg(0x45, 0xb3a1905); - qam_write_reg(0x46, 0x1c396e07); - qam_write_reg(0x47, 0x3801cc08); - qam_write_reg(0x48, 0x10800a2); - qam_write_reg(0x12, 0x50e1000); - qam_write_reg(0x30, 0x41f2f69); - /*j83b_symbolrate(please see register doc)*/ - qam_write_reg(0x4d, 0x23d125f7); - /*for phase noise case 256qam*/ - qam_write_reg(0x9c, 0x2a232100); - qam_write_reg(0x57, 0x606040d); - /*for phase noise case 64qam*/ - qam_write_reg(0x54, 0x606050d); - qam_write_reg(0x52, 0x346dc); + + if (demod_sta->dvb_mode == Gxtv_Atsc || + is_ic_ver(IC_VER_TXLX)) { + /*j83b filter para*/ + qam_write_reg(0x40, 0x3f010201); + qam_write_reg(0x41, 0x0a003a3b); + qam_write_reg(0x42, 0xe1ee030e); + qam_write_reg(0x43, 0x002601f2); + qam_write_reg(0x44, 0x009b006b); + qam_write_reg(0x45, 0xb3a1905); + qam_write_reg(0x46, 0x1c396e07); + qam_write_reg(0x47, 0x3801cc08); + qam_write_reg(0x48, 0x10800a2); + qam_write_reg(0x12, 0x50e1000); + qam_write_reg(0x30, 0x41f2f69); + /*j83b_symbolrate(please see register doc)*/ + qam_write_reg(0x4d, 0x23d125f7); + /*for phase noise case 256qam*/ + qam_write_reg(0x9c, 0x2a232100); + qam_write_reg(0x57, 0x606040d); + /*for phase noise case 64qam*/ + qam_write_reg(0x54, 0x606050d); + qam_write_reg(0x52, 0x346dc); + } + qam_auto_scan(1); } -#endif - if (!is_ic_ver(IC_VER_TL1)) { - qam_write_reg(0x7, 0x10f23); - qam_write_reg(0x3a, 0x0); - qam_write_reg(0x7, 0x10f33); - qam_write_reg(0x3a, 0x4); - } + + qam_write_reg(0x7, 0x10f23); + qam_write_reg(0x3a, 0x0); + qam_write_reg(0x7, 0x10f33); + qam_write_reg(0x3a, 0x4); /*auto track*/ /* dvbc_set_auto_symtrack(); */ } diff --git a/drivers/amlogic/media/dtv_demod/include/addr_dtmb_che.h b/drivers/amlogic/media/dtv_demod/include/addr_dtmb_che.h index 34c28cba4cdf..7252c1ad23a6 100644 --- a/drivers/amlogic/media/dtv_demod/include/addr_dtmb_che.h +++ b/drivers/amlogic/media/dtv_demod/include/addr_dtmb_che.h @@ -22,6 +22,7 @@ #define DTMB_CHE_ADDR(x) (DTMB_DEMOD_BASE + (x << 2)) +#define DTMB_CHE_IBDFE_CONF0 DTMB_CHE_ADDR(0x8b) #define DTMB_CHE_TE_HREB_SNR DTMB_CHE_ADDR(0x8d) #define DTMB_CHE_MC_SC_TIMING_POWTHR DTMB_CHE_ADDR(0x8e) #define DTMB_CHE_MC_SC_PROTECT_GD DTMB_CHE_ADDR(0x8f) diff --git a/drivers/amlogic/media/dtv_demod/include/depend.h b/drivers/amlogic/media/dtv_demod/include/depend.h index b594c5b63bc6..c664860e223b 100644 --- a/drivers/amlogic/media/dtv_demod/include/depend.h +++ b/drivers/amlogic/media/dtv_demod/include/depend.h @@ -33,21 +33,21 @@ bool aml_dma_release_contiguous(struct device *dev, struct page *pages, /*void ary_test(void);*/ enum aml_fe_n_mode_t { /*same as aml_fe_mode_t in aml_fe.h*/ - AM_FE_UNKNOWN_N = 0, - AM_FE_QPSK_N = 1, - AM_FE_QAM_N = 2, - AM_FE_OFDM_N = 4, - AM_FE_ATSC_N = 8, + AM_FE_UNKNOWN_N, + AM_FE_QPSK_N, + AM_FE_QAM_N, + AM_FE_OFDM_N, + AM_FE_ATSC_N, /*AM_FE_ANALOG = 16,*/ - AM_FE_DTMB_N = 32, - AM_FE_ISDBT_N = 64 + AM_FE_DTMB_N, + AM_FE_ISDBT_N, + AM_FE_NUM, }; - /*----------------------------------*/ struct aml_exp_func { - int (*leave_mode)(int mode); + int (*leave_mode)(enum aml_fe_n_mode_t mode); }; #endif /*__DEPEND_H__*/ diff --git a/drivers/amlogic/media/enhancement/Kconfig b/drivers/amlogic/media/enhancement/Kconfig index d4c423730f77..9d1075b220ef 100644 --- a/drivers/amlogic/media/enhancement/Kconfig +++ b/drivers/amlogic/media/enhancement/Kconfig @@ -12,6 +12,7 @@ config AMLOGIC_MEDIA_ENHANCEMENT if AMLOGIC_MEDIA_ENHANCEMENT source "drivers/amlogic/media/enhancement/amvecm/Kconfig" source "drivers/amlogic/media/enhancement/amdolby_vision/Kconfig" +source "drivers/amlogic/media/enhancement/amprime_sl/Kconfig" endif endmenu diff --git a/drivers/amlogic/media/enhancement/Makefile b/drivers/amlogic/media/enhancement/Makefile index b5e365f74498..5a53ee3ae57e 100644 --- a/drivers/amlogic/media/enhancement/Makefile +++ b/drivers/amlogic/media/enhancement/Makefile @@ -1,2 +1,3 @@ -obj-$(CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM) += amvecm/ -obj-$(CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION) += amdolby_vision/ \ No newline at end of file +obj-$(CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM) += amvecm/ +obj-$(CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION) += amdolby_vision/ +obj-$(CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_PRIME_SL) += amprime_sl/ diff --git a/drivers/amlogic/media/enhancement/amdolby_vision/amdolby_vision.c b/drivers/amlogic/media/enhancement/amdolby_vision/amdolby_vision.c index d4d1c5861d7b..ada4287ba682 100644 --- a/drivers/amlogic/media/enhancement/amdolby_vision/amdolby_vision.c +++ b/drivers/amlogic/media/enhancement/amdolby_vision/amdolby_vision.c @@ -41,6 +41,8 @@ #include #include #include +#include +#include #include "amdolby_vision.h" #include @@ -51,11 +53,14 @@ #include #include #include /* for parse_para_pq */ +#include #include +#include DEFINE_SPINLOCK(dovi_lock); -static const struct dolby_vision_func_s *p_funcs; +static const struct dolby_vision_func_s *p_funcs_stb; +static const struct dolby_vision_func_s *p_funcs_tv; #define AMDOLBY_VISION_NAME "amdolby_vision" #define AMDOLBY_VISION_CLASS_NAME "amdolby_vision" @@ -66,6 +71,7 @@ struct amdolby_vision_dev_s { dev_t devno; struct device *dev; struct class *clsp; + wait_queue_head_t dv_queue; }; static struct amdolby_vision_dev_s amdolby_vision_dev; struct dv_device_data_s dv_meson_dev; @@ -374,7 +380,7 @@ uint16_t L2PQ_500_4000[] = { static uint32_t tv_max_lin = 200; static uint16_t tv_max_pq = 2372; -static unsigned int panel_max_lumin; +static unsigned int panel_max_lumin = 350; module_param(panel_max_lumin, uint, 0664); MODULE_PARM_DESC(panel_max_lumin, "\n panel_max_lumin\n"); @@ -576,6 +582,204 @@ struct TargetDisplayConfig def_tgt_display_cfg = { 0, /* chip_nolvl5 */ {0, 0, 0, 0, 0, 0, 0, 0} /* padding[8] */ }; +struct TargetDisplayConfig def_tgt_display_cfg_ll = { + 4095, /* gain */ + 0, /* offset */ + 39322, /* gamma */ + 2, /* eotf */ + 12, /* bitDepth */ + 0, /* rangeSpec */ + 42, /* diagSize */ + 2873, /* maxPq */ + 263, /* minPq */ + 2048, /* mSWeight */ + 16380, /* mSEdgeWeight */ + 0, /* minPQBias */ + 0, /* midPQBias */ + 0, /* maxPQBias */ + 0, /* trimSlopeBias */ + 0, /* trimOffsetBias */ + 0, /* trimPowerBias */ + 0, /* msWeightBias */ + 0, /* brightness */ + 0, /* contrast */ + 0, /* chromaWeightBias */ + 0, /* saturationGainBias */ + 2048, /* chromaWeight */ + 2048, /* saturationGain */ + 655, /* crossTalk */ + 0, /* tuningMode */ + 0, /* reserved0 */ + 0, /* dbgExecParamsPrintPeriod */ + 0, /* dbgDmMdPrintPeriod */ + 0, /* dbgDmCfgPrintPeriod */ + 2873, /* maxPq_dupli */ + 263, /* minPq_dupli */ + 12288, /* keyWeight */ + 24576, /* intensityVectorWeight */ + 24576, /* chromaVectorWeight */ + 0, /* chip_fpga_lowcomplex */ + { + -245, + -208, + -171, + -130, + -93, + -56, + -19, + 20, + 57, + 94, + 131, + 172, + 209, + 246, + }, + { + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + }, + { + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + }, + { + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + }, + { + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + }, + { + -3685, + -3070, + -2456, + -1842, + -1228, + -613, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + }, + { + 1, /* gdEnable */ + 4452, /* gdWMin */ + 165150720, /* gdWMax */ + 26214400, /* gdWMm */ + 20114920, /* gdWDynRngSqrt */ + 4096, /* gdWeightMean */ + 4096, /* gdWeightStd */ + 0, /* gdDelayMilliSec_hdmi */ + 1, /* gdRgb2YuvExt */ + { + {5967, 20067, 2026}, + {-3289, -11061, 14350}, + {14350, -13034, -1316} + }, /* gdM33Rgb2Yuv[3][3] */ + 15, /* gdM33Rgb2YuvScale2P */ + 1, /* gdRgb2YuvOffExt */ + {2048, 16384, 16384},/* gdV3Rgb2YuvOff[3] */ + 2152296, /* gdUpBound */ + 341634, /* gdLowBound */ + 0, /* lastMaxPq */ + 114, /*gdWMinPq */ + 2873, /*gdWMaxPq */ + 2081, /*gdWMmPq */ + 0, /*gdTriggerPeriod */ + 0, /* gdTriggerLinThresh */ + 0, /* gdDelayMilliSec_ott */ +#ifdef V1_5 + {0, 0, 0, 0, 0, 0}, +#else + {0, 0, 0, 0, 0, 0, 0, 0, 0} +#endif + }, +#ifdef V1_5 + {36, 23, 83, 181, 139, 88, 101}, + {0, 0, 0, 0, 0}, +#endif + 28049, /* min_lin */ + 165150720, /* max_lin */ + 0, /* backlight_scaler */ + 28049, /* min_lin_dupli */ + 165150720, /* max_lin_dupli */ + { + /* lms2RgbMat[3][3] */ + { + {17486, -13950, 560}, + {-4081, 8776, -599}, + {257, -562, 4401} + }, + 12, /* lms2RgbMatScale */ + {128, 128, 128}, /* whitePoint */ + 7, /* whitePointScale */ + {0, 0, 0} /* reserved[3] */ + }, + 0, /* reserved00 */ + 0, /* brightnessPreservation */ + 81920, /* iintensityVectorWeight */ + 24576, /* ichromaVectorWeight */ + 0, /* isaturationGainBias */ + 0, /* chip_12b_ocsc */ + 0, /* chip_512_tonecurve */ + 0, /* chip_nolvl5 */ + {0, 0, 0, 0, 0, 0, 0, 0} /* padding[8] */ +}; + #else struct TargetDisplayConfig def_tgt_display_cfg = { 2048, /* gain */ @@ -794,13 +998,7 @@ MODULE_PARM_DESC(debug_dolby_frame, "\n debug_dolby_frame\n"); #define dump_enable \ ((debug_dolby_frame >= 0xffff) || \ (debug_dolby_frame + 1 == frame_count)) -static int is_graphics_output_off(void) -{ - if (is_meson_g12()) - return !(READ_VPP_REG(OSD1_BLEND_SRC_CTRL) & (1<<8)); - else - return (!(READ_VPP_REG(VPP_MISC) & (1<<12))); -} + #define single_step_enable \ (((debug_dolby_frame >= 0xffff) || \ ((debug_dolby_frame + 1) == frame_count)) && \ @@ -824,7 +1022,7 @@ static struct dovi_setting_s dovi_setting; static struct dovi_setting_s new_dovi_setting; void *pq_config_fake; -void *tv_dovi_setting; +struct tv_dovi_setting_s *tv_dovi_setting; static bool pq_config_set_flag; struct ui_menu_params_s menu_param = {50, 50, 50}; static bool tv_dovi_setting_change_flag; @@ -871,6 +1069,21 @@ bool is_meson_gxm(void) else return false; } +bool is_meson_g12(void) +{ + if (dv_meson_dev.cpu_id == _CPU_MAJOR_ID_G12) + return true; + else + return false; +} + +bool is_meson_box(void) +{ + if (is_meson_gxm() || is_meson_g12()) + return true; + else + return false; +} bool is_meson_txlx(void) { @@ -887,7 +1100,6 @@ bool is_meson_txlx_tvmode(void) else return false; } - bool is_meson_txlx_stbmode(void) { if ((is_meson_txlx()) && (tv_mode == 0)) @@ -895,14 +1107,135 @@ bool is_meson_txlx_stbmode(void) else return false; } - -bool is_meson_g12(void) +bool is_meson_tm2(void) { - if (dv_meson_dev.cpu_id == _CPU_MAJOR_ID_G12) + if (dv_meson_dev.cpu_id == _CPU_MAJOR_ID_TM2) return true; else return false; } +bool is_meson_tm2_tvmode(void) +{ + if ((is_meson_tm2()) && (tv_mode == 1)) + return true; + else + return false; +} + +bool is_meson_tm2_stbmode(void) +{ + if ((is_meson_tm2()) && (tv_mode == 0)) + return true; + else + return false; +} + +bool is_meson_tvmode(void) +{ + if (is_meson_tm2_tvmode() || + is_meson_txlx_tvmode()) + return true; + else + return false; +} + +static u32 addr_map(u32 adr) +{ + u32 CORE1_BASE = 0; + u32 CORE1_1_BASE = 0; + u32 CORE2A_BASE = 0; + u32 CORE3_BASE = 0; + u32 CORETV_BASE = 0; + + if (is_meson_gxm() || is_meson_g12()) { + CORE1_BASE = 0x3300; + CORE2A_BASE = 0x3400; + CORE3_BASE = 0x3600; + } else if (is_meson_txlx()) { + CORE2A_BASE = 0x3400; + CORE3_BASE = 0x3600; + CORETV_BASE = 0x3300; + } else if (is_meson_tm2()) { + CORE1_BASE = 0x3300; + CORE1_1_BASE = 0x4400; + CORE2A_BASE = 0x3400; + CORE3_BASE = 0x3600; + CORETV_BASE = 0x4300; + } + + if (adr & CORE1_OFFSET) + adr = (adr & 0xffff) + CORE1_BASE; + else if (adr & CORE1_1_OFFSET) + adr = (adr & 0xffff) + CORE1_1_BASE; + else if (adr & CORE2A_OFFSET) + adr = (adr & 0xffff) + CORE2A_BASE; + else if (adr & CORE3_OFFSET) + adr = (adr & 0xffff) + CORE3_BASE; + else if (adr & CORETV_OFFSET) + adr = (adr & 0xffff) + CORETV_BASE; + + return adr; +} + +static u32 VSYNC_RD_DV_REG(u32 adr) +{ + adr = addr_map(adr); + return _VSYNC_RD_MPEG_REG(adr); +} + +static int VSYNC_WR_DV_REG(u32 adr, u32 val) +{ + adr = addr_map(adr); + _VSYNC_WR_MPEG_REG(adr, val); + return 0; +} + +static int VSYNC_WR_DV_REG_BITS(u32 adr, u32 val, u32 start, u32 len) +{ + adr = addr_map(adr); + _VSYNC_WR_MPEG_REG_BITS(adr, val, start, len); + return 0; +} + +static u32 READ_VPP_DV_REG(u32 adr) +{ + adr = addr_map(adr); + return READ_VPP_REG(adr); +} + +static int WRITE_VPP_DV_REG(u32 adr, const u32 val) +{ + adr = addr_map(adr); + WRITE_VPP_REG(adr, val); + return 0; +} + +void amdolby_vision_wakeup_queue(void) +{ + struct amdolby_vision_dev_s *devp = &amdolby_vision_dev; + + wake_up(&devp->dv_queue); +} + +static unsigned int amdolby_vision_poll(struct file *file, poll_table *wait) +{ + struct amdolby_vision_dev_s *devp = file->private_data; + unsigned int mask = 0; + + poll_wait(file, &devp->dv_queue, wait); + mask = (POLLIN | POLLRDNORM); + + return mask; +} + +static int is_graphics_output_off(void) +{ + if (is_meson_g12() || is_meson_tm2_stbmode()) + return !(READ_VPP_DV_REG(OSD1_BLEND_SRC_CTRL) & (1<<8)); + else + return (!(READ_VPP_DV_REG(VPP_MISC) & (1<<12))); +} + static void dump_tv_setting( struct tv_dovi_setting_s *setting, int frame_cnt, int debug_flag) @@ -1119,56 +1452,56 @@ static int stb_dolby_core1_set( FLAG_DISABE_CORE_SETTING)) return 0; - WRITE_VPP_REG( + WRITE_VPP_DV_REG( DOLBY_TV_CLKGATE_CTRL, 0x2800); if (reset) { if (!dolby_vision_core1_on) { - VSYNC_WR_MPEG_REG(VIU_SW_RESET, 1 << 9); - VSYNC_WR_MPEG_REG(VIU_SW_RESET, 0); - VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG(VIU_SW_RESET, 1 << 9); + VSYNC_WR_DV_REG(VIU_SW_RESET, 0); + VSYNC_WR_DV_REG( DOLBY_TV_CLKGATE_CTRL, 0x2800); } else reset = 0; } if (!bl_enable) - VSYNC_WR_MPEG_REG(DOLBY_TV_SWAP_CTRL5, 0x446); - VSYNC_WR_MPEG_REG(DOLBY_TV_SWAP_CTRL0, 0); - VSYNC_WR_MPEG_REG(DOLBY_TV_SWAP_CTRL1, + VSYNC_WR_DV_REG(DOLBY_TV_SWAP_CTRL5, 0x446); + VSYNC_WR_DV_REG(DOLBY_TV_SWAP_CTRL0, 0); + VSYNC_WR_DV_REG(DOLBY_TV_SWAP_CTRL1, ((hsize + 0x80) << 16) | (vsize + 0x40)); - VSYNC_WR_MPEG_REG(DOLBY_TV_SWAP_CTRL3, + VSYNC_WR_DV_REG(DOLBY_TV_SWAP_CTRL3, (hwidth << 16) | vwidth); - VSYNC_WR_MPEG_REG(DOLBY_TV_SWAP_CTRL4, + VSYNC_WR_DV_REG(DOLBY_TV_SWAP_CTRL4, (hpotch << 16) | vpotch); - VSYNC_WR_MPEG_REG(DOLBY_TV_SWAP_CTRL2, + VSYNC_WR_DV_REG(DOLBY_TV_SWAP_CTRL2, (hsize << 16) | vsize); - VSYNC_WR_MPEG_REG(DOLBY_TV_SWAP_CTRL6, 0xba000000); + VSYNC_WR_DV_REG(DOLBY_TV_SWAP_CTRL6, 0xba000000); if (dolby_vision_flags & FLAG_DISABLE_COMPOSER) composer_enable = 0; - VSYNC_WR_MPEG_REG(DOLBY_TV_SWAP_CTRL0, + VSYNC_WR_DV_REG(DOLBY_TV_SWAP_CTRL0, /* el dly 3, bl dly 1 after de*/ (el_41_mode ? (0x3 << 4) : (0x1 << 8)) | bl_enable << 0 | composer_enable << 1 | el_41_mode << 2); if (el_enable && (dolby_vision_mask & 1)) - VSYNC_WR_MPEG_REG_BITS( + VSYNC_WR_DV_REG_BITS( VIU_MISC_CTRL1, /* vd2 to core1 */ 0, 17, 1); else - VSYNC_WR_MPEG_REG_BITS( + VSYNC_WR_DV_REG_BITS( VIU_MISC_CTRL1, /* vd2 to vpp */ 1, 17, 1); if (dolby_vision_core1_on && !bypass_core1) - VSYNC_WR_MPEG_REG_BITS( + VSYNC_WR_DV_REG_BITS( VIU_MISC_CTRL1, /* enable core 1 */ 0, 16, 1); else if (dolby_vision_core1_on && bypass_core1) - VSYNC_WR_MPEG_REG_BITS( + VSYNC_WR_DV_REG_BITS( VIU_MISC_CTRL1, /* bypass core 1 */ 1, 16, 1); @@ -1194,31 +1527,31 @@ static int stb_dolby_core1_set( bypass_flag; if (dolby_vision_on_count < dolby_vision_run_mode_delay) { run_mode |= 1; - VSYNC_WR_MPEG_REG(VPP_VD1_CLIP_MISC0, + VSYNC_WR_DV_REG(VPP_VD1_CLIP_MISC0, (0x200 << 10) | 0x200); - VSYNC_WR_MPEG_REG(VPP_VD1_CLIP_MISC1, + VSYNC_WR_DV_REG(VPP_VD1_CLIP_MISC1, (0x200 << 10) | 0x200); } else if (dolby_vision_on_count == dolby_vision_run_mode_delay) { - VSYNC_WR_MPEG_REG(VPP_VD1_CLIP_MISC0, + VSYNC_WR_DV_REG(VPP_VD1_CLIP_MISC0, (0x200 << 10) | 0x200); - VSYNC_WR_MPEG_REG(VPP_VD1_CLIP_MISC1, + VSYNC_WR_DV_REG(VPP_VD1_CLIP_MISC1, (0x200 << 10) | 0x200); } else { - VSYNC_WR_MPEG_REG(VPP_VD1_CLIP_MISC0, + VSYNC_WR_DV_REG(VPP_VD1_CLIP_MISC0, (0x3ff << 20) | (0x3ff << 10) | 0x3ff); - VSYNC_WR_MPEG_REG(VPP_VD1_CLIP_MISC1, + VSYNC_WR_DV_REG(VPP_VD1_CLIP_MISC1, 0); } } if (reset) - VSYNC_WR_MPEG_REG(DOLBY_TV_REG_START + 1, run_mode); + VSYNC_WR_DV_REG(DOLBY_TV_REG_START + 1, run_mode); /* 962e work around to fix the uv swap issue when bl:el = 1:1 */ if (el_41_mode) - VSYNC_WR_MPEG_REG(DOLBY_TV_SWAP_CTRL5, 0x6); + VSYNC_WR_DV_REG(DOLBY_TV_SWAP_CTRL5, 0x6); else - VSYNC_WR_MPEG_REG(DOLBY_TV_SWAP_CTRL5, 0xa); + VSYNC_WR_DV_REG(DOLBY_TV_SWAP_CTRL5, 0xa); /* axi dma for reg table */ reg_size = prepare_stb_dolby_core1_reg( @@ -1228,25 +1561,25 @@ static int stb_dolby_core1_set( if (!dolby_vision_on) { /* dma1:11-0 tv_oo+g2l size, dma2:23-12 3d lut size */ - WRITE_VPP_REG(DOLBY_TV_AXI2DMA_CTRL1, + WRITE_VPP_DV_REG(DOLBY_TV_AXI2DMA_CTRL1, 0x00000080 | (reg_size << 23)); - WRITE_VPP_REG(DOLBY_TV_AXI2DMA_CTRL2, (u32)dma_paddr); + WRITE_VPP_DV_REG(DOLBY_TV_AXI2DMA_CTRL2, (u32)dma_paddr); /* dma3:23-12 cvm size */ - WRITE_VPP_REG(DOLBY_TV_AXI2DMA_CTRL3, + WRITE_VPP_DV_REG(DOLBY_TV_AXI2DMA_CTRL3, 0x80100000 | dma_start_line); - WRITE_VPP_REG(DOLBY_TV_AXI2DMA_CTRL0, 0x01000062); - WRITE_VPP_REG(DOLBY_TV_AXI2DMA_CTRL0, 0x80400042); + WRITE_VPP_DV_REG(DOLBY_TV_AXI2DMA_CTRL0, 0x01000062); + WRITE_VPP_DV_REG(DOLBY_TV_AXI2DMA_CTRL0, 0x80400042); } if (reset) { /* dma1:11-0 tv_oo+g2l size, dma2:23-12 3d lut size */ - VSYNC_WR_MPEG_REG(DOLBY_TV_AXI2DMA_CTRL1, + VSYNC_WR_DV_REG(DOLBY_TV_AXI2DMA_CTRL1, 0x00000080 | (reg_size << 23)); - VSYNC_WR_MPEG_REG(DOLBY_TV_AXI2DMA_CTRL2, (u32)dma_paddr); + VSYNC_WR_DV_REG(DOLBY_TV_AXI2DMA_CTRL2, (u32)dma_paddr); /* dma3:23-12 cvm size */ - VSYNC_WR_MPEG_REG(DOLBY_TV_AXI2DMA_CTRL3, + VSYNC_WR_DV_REG(DOLBY_TV_AXI2DMA_CTRL3, 0x80100000 | dma_start_line); - VSYNC_WR_MPEG_REG(DOLBY_TV_AXI2DMA_CTRL0, 0x01000062); - VSYNC_WR_MPEG_REG(DOLBY_TV_AXI2DMA_CTRL0, 0x80400042); + VSYNC_WR_DV_REG(DOLBY_TV_AXI2DMA_CTRL0, 0x01000062); + VSYNC_WR_DV_REG(DOLBY_TV_AXI2DMA_CTRL0, 0x80400042); } tv_dovi_setting_update_flag = true; @@ -1309,66 +1642,66 @@ static int tv_dolby_core1_set( FLAG_DISABE_CORE_SETTING)) return 0; - WRITE_VPP_REG( + WRITE_VPP_DV_REG( DOLBY_TV_CLKGATE_CTRL, 0x2800); if (reset) { - VSYNC_WR_MPEG_REG(VIU_SW_RESET, 1 << 9); - VSYNC_WR_MPEG_REG(VIU_SW_RESET, 0); - VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG(VIU_SW_RESET, 1 << 9); + VSYNC_WR_DV_REG(VIU_SW_RESET, 0); + VSYNC_WR_DV_REG( DOLBY_TV_CLKGATE_CTRL, 0x2800); } if (dolby_vision_flags & FLAG_DISABLE_COMPOSER) composer_enable = 0; - VSYNC_WR_MPEG_REG(DOLBY_TV_SWAP_CTRL0, + VSYNC_WR_DV_REG(DOLBY_TV_SWAP_CTRL0, /* el dly 3, bl dly 1 after de*/ (el_41_mode ? (0x3 << 4) : (0x1 << 8)) | bl_enable << 0 | composer_enable << 1 | el_41_mode << 2); - VSYNC_WR_MPEG_REG(DOLBY_TV_SWAP_CTRL1, + VSYNC_WR_DV_REG(DOLBY_TV_SWAP_CTRL1, ((hsize + 0x80) << 16 | (vsize + 0x40))); - VSYNC_WR_MPEG_REG(DOLBY_TV_SWAP_CTRL3, (hwidth << 16) | vwidth); - VSYNC_WR_MPEG_REG(DOLBY_TV_SWAP_CTRL4, (hpotch << 16) | vpotch); - VSYNC_WR_MPEG_REG(DOLBY_TV_SWAP_CTRL2, (hsize << 16) | vsize); + VSYNC_WR_DV_REG(DOLBY_TV_SWAP_CTRL3, (hwidth << 16) | vwidth); + VSYNC_WR_DV_REG(DOLBY_TV_SWAP_CTRL4, (hpotch << 16) | vpotch); + VSYNC_WR_DV_REG(DOLBY_TV_SWAP_CTRL2, (hsize << 16) | vsize); /*0x2c2d0:5-4-1-3-2-0*/ - VSYNC_WR_MPEG_REG_BITS(DOLBY_TV_SWAP_CTRL5, 0x2c2d0, 14, 18); - VSYNC_WR_MPEG_REG_BITS(DOLBY_TV_SWAP_CTRL5, 0xa, 0, 4); + VSYNC_WR_DV_REG_BITS(DOLBY_TV_SWAP_CTRL5, 0x2c2d0, 14, 18); + VSYNC_WR_DV_REG_BITS(DOLBY_TV_SWAP_CTRL5, 0xa, 0, 4); if ((hdmi) && (!hdr10)) - VSYNC_WR_MPEG_REG_BITS(DOLBY_TV_SWAP_CTRL5, 1, 4, 1); + VSYNC_WR_DV_REG_BITS(DOLBY_TV_SWAP_CTRL5, 1, 4, 1); else - VSYNC_WR_MPEG_REG_BITS(DOLBY_TV_SWAP_CTRL5, 0, 4, 1); + VSYNC_WR_DV_REG_BITS(DOLBY_TV_SWAP_CTRL5, 0, 4, 1); - VSYNC_WR_MPEG_REG_BITS(DOLBY_TV_SWAP_CTRL6, 1, 20, 1); + VSYNC_WR_DV_REG_BITS(DOLBY_TV_SWAP_CTRL6, 1, 20, 1); /* bypass dither */ - VSYNC_WR_MPEG_REG_BITS(DOLBY_TV_SWAP_CTRL6, 1, 25, 1); + VSYNC_WR_DV_REG_BITS(DOLBY_TV_SWAP_CTRL6, 1, 25, 1); if (src_chroma_format == 2) - VSYNC_WR_MPEG_REG_BITS(DOLBY_TV_SWAP_CTRL6, 1, 29, 1); + VSYNC_WR_DV_REG_BITS(DOLBY_TV_SWAP_CTRL6, 1, 29, 1); else if (src_chroma_format == 1) - VSYNC_WR_MPEG_REG_BITS(DOLBY_TV_SWAP_CTRL6, 0, 29, 1); + VSYNC_WR_DV_REG_BITS(DOLBY_TV_SWAP_CTRL6, 0, 29, 1); /* input 12 or 10 bit */ - VSYNC_WR_MPEG_REG_BITS(DOLBY_TV_SWAP_CTRL7, 12, 0, 8); + VSYNC_WR_DV_REG_BITS(DOLBY_TV_SWAP_CTRL7, 12, 0, 8); if (el_enable && (dolby_vision_mask & 1)) - VSYNC_WR_MPEG_REG_BITS( + VSYNC_WR_DV_REG_BITS( VIU_MISC_CTRL1, /* vd2 to core1 */ 0, 17, 1); else - VSYNC_WR_MPEG_REG_BITS( + VSYNC_WR_DV_REG_BITS( VIU_MISC_CTRL1, /* vd2 to vpp */ 1, 17, 1); if (dolby_vision_core1_on && !bypass_core1) - VSYNC_WR_MPEG_REG_BITS( + VSYNC_WR_DV_REG_BITS( VIU_MISC_CTRL1, /* enable core 1 */ 0, 16, 1); else if (dolby_vision_core1_on && bypass_core1) - VSYNC_WR_MPEG_REG_BITS( + VSYNC_WR_DV_REG_BITS( VIU_MISC_CTRL1, /* bypass core 1 */ 1, 16, 1); @@ -1379,43 +1712,43 @@ static int tv_dolby_core1_set( run_mode = tv_run_mode(vsize, hdmi, hdr10, el_41_mode); if (dolby_vision_on_count < dolby_vision_run_mode_delay) { run_mode = (run_mode & 0xfffffffc) | 1; - VSYNC_WR_MPEG_REG(VPP_VD1_CLIP_MISC0, + VSYNC_WR_DV_REG(VPP_VD1_CLIP_MISC0, (0x200 << 10) | 0x200); - VSYNC_WR_MPEG_REG(VPP_VD1_CLIP_MISC1, + VSYNC_WR_DV_REG(VPP_VD1_CLIP_MISC1, (0x200 << 10) | 0x200); } else if (dolby_vision_on_count == dolby_vision_run_mode_delay) { - VSYNC_WR_MPEG_REG(VPP_VD1_CLIP_MISC0, + VSYNC_WR_DV_REG(VPP_VD1_CLIP_MISC0, (0x200 << 10) | 0x200); - VSYNC_WR_MPEG_REG(VPP_VD1_CLIP_MISC1, + VSYNC_WR_DV_REG(VPP_VD1_CLIP_MISC1, (0x200 << 10) | 0x200); } else { - VSYNC_WR_MPEG_REG(VPP_VD1_CLIP_MISC0, + VSYNC_WR_DV_REG(VPP_VD1_CLIP_MISC0, (0x3ff << 20) | (0x3ff << 10) | 0x3ff); - VSYNC_WR_MPEG_REG(VPP_VD1_CLIP_MISC1, + VSYNC_WR_DV_REG(VPP_VD1_CLIP_MISC1, 0); } } - ((struct tv_dovi_setting_s *)tv_dovi_setting)->core1_reg_lut[1] = + tv_dovi_setting->core1_reg_lut[1] = 0x0000000100000000 | run_mode; if (reset) - VSYNC_WR_MPEG_REG(DOLBY_TV_REG_START + 1, run_mode); + VSYNC_WR_DV_REG(DOLBY_TV_REG_START + 1, run_mode); if (!dolby_vision_on) { - WRITE_VPP_REG(DOLBY_TV_AXI2DMA_CTRL1, 0x6f666080); - WRITE_VPP_REG(DOLBY_TV_AXI2DMA_CTRL2, (u32)dma_paddr); - WRITE_VPP_REG(DOLBY_TV_AXI2DMA_CTRL3, + WRITE_VPP_DV_REG(DOLBY_TV_AXI2DMA_CTRL1, 0x6f666080); + WRITE_VPP_DV_REG(DOLBY_TV_AXI2DMA_CTRL2, (u32)dma_paddr); + WRITE_VPP_DV_REG(DOLBY_TV_AXI2DMA_CTRL3, 0x80000000 | dma_start_line); - WRITE_VPP_REG(DOLBY_TV_AXI2DMA_CTRL0, 0x01000042); - WRITE_VPP_REG(DOLBY_TV_AXI2DMA_CTRL0, 0x80400042); + WRITE_VPP_DV_REG(DOLBY_TV_AXI2DMA_CTRL0, 0x01000042); + WRITE_VPP_DV_REG(DOLBY_TV_AXI2DMA_CTRL0, 0x80400042); } if (reset) { - VSYNC_WR_MPEG_REG(DOLBY_TV_AXI2DMA_CTRL1, 0x6f666080); - VSYNC_WR_MPEG_REG(DOLBY_TV_AXI2DMA_CTRL2, (u32)dma_paddr); - VSYNC_WR_MPEG_REG(DOLBY_TV_AXI2DMA_CTRL3, + VSYNC_WR_DV_REG(DOLBY_TV_AXI2DMA_CTRL1, 0x6f666080); + VSYNC_WR_DV_REG(DOLBY_TV_AXI2DMA_CTRL2, (u32)dma_paddr); + VSYNC_WR_DV_REG(DOLBY_TV_AXI2DMA_CTRL3, 0x80000000 | dma_start_line); - VSYNC_WR_MPEG_REG(DOLBY_TV_AXI2DMA_CTRL0, 0x01000042); - VSYNC_WR_MPEG_REG(DOLBY_TV_AXI2DMA_CTRL0, 0x80400042); + VSYNC_WR_DV_REG(DOLBY_TV_AXI2DMA_CTRL0, 0x01000042); + VSYNC_WR_DV_REG(DOLBY_TV_AXI2DMA_CTRL0, 0x80400042); } tv_dovi_setting_update_flag = true; @@ -1429,7 +1762,7 @@ int dolby_vision_update_setting(void) int i; uint64_t *p; - if (!p_funcs) + if (!p_funcs_stb && !p_funcs_tv) return -1; if (!tv_dovi_setting_update_flag) return 0; @@ -1446,9 +1779,8 @@ int dolby_vision_update_setting(void) setting_update_count++; return -1; } - if (is_meson_txlx_tvmode() && !force_stb_mode) { - dma_data = ((struct tv_dovi_setting_s *) - tv_dovi_setting)->core1_reg_lut; + if (is_meson_tvmode() && !force_stb_mode) { + dma_data = tv_dovi_setting->core1_reg_lut; size = 8 * TV_DMA_TBL_SIZE; memcpy(dma_vaddr, dma_data, size); } else if (is_meson_txlx_stbmode() || force_stb_mode) { @@ -1500,26 +1832,27 @@ static int dolby_core1_set( /* Register: dolby_path_ctrl[0] = 0 to enable BL*/ /* dolby_path_ctrl[1] = 0 to enable EL*/ /* dolby_path_ctrl[2] = 0 to enable OSD*/ - if (is_meson_g12() && frame_count == 1 - && dolby_vision_core1_on == 0) { + if ((is_meson_g12() || is_meson_tm2_stbmode()) && + frame_count == 1 && dolby_vision_core1_on == 0) { pr_dolby_dbg("((%s %d, register DOLBY_PATH_CTRL: %x))\n", - __func__, __LINE__, VSYNC_RD_MPEG_REG(DOLBY_PATH_CTRL)); - if ((VSYNC_RD_MPEG_REG(DOLBY_PATH_CTRL) & 0x1) != 0) { + __func__, __LINE__, + VSYNC_RD_DV_REG(DOLBY_PATH_CTRL)); + if ((VSYNC_RD_DV_REG(DOLBY_PATH_CTRL) & 0x1) != 0) { pr_dolby_dbg("BL is disable for 1st frame.Re-enable BL\n"); - VSYNC_WR_MPEG_REG_BITS(DOLBY_PATH_CTRL, 0, 0, 1); + VSYNC_WR_DV_REG_BITS(DOLBY_PATH_CTRL, 0, 0, 1); pr_dolby_dbg("((%s %d, enable_bl, DOLBY_PATH_CTRL: %x))\n", __func__, __LINE__, - VSYNC_RD_MPEG_REG(DOLBY_PATH_CTRL)); + VSYNC_RD_DV_REG(DOLBY_PATH_CTRL)); } if (el_enable) { - if ((VSYNC_RD_MPEG_REG(DOLBY_PATH_CTRL) & 0x10) != 0) { + if ((VSYNC_RD_DV_REG(DOLBY_PATH_CTRL) & 0x10) != 0) { pr_dolby_dbg("((%s %d enable el))\n", __func__, __LINE__); - VSYNC_WR_MPEG_REG_BITS(DOLBY_PATH_CTRL, + VSYNC_WR_DV_REG_BITS(DOLBY_PATH_CTRL, 0, 1, 1); pr_dolby_dbg("((%s %d, enable_el, DOLBY_PATH_CTRL: %x))\n", __func__, __LINE__, - VSYNC_RD_MPEG_REG(DOLBY_PATH_CTRL)); + VSYNC_RD_DV_REG(DOLBY_PATH_CTRL)); } } } @@ -1537,8 +1870,8 @@ static int dolby_core1_set( reset = true; if ((!dolby_vision_on || reset) && bl_enable) { - VSYNC_WR_MPEG_REG(VIU_SW_RESET, 1 << 9); - VSYNC_WR_MPEG_REG(VIU_SW_RESET, 0); + VSYNC_WR_DV_REG(VIU_SW_RESET, 1 << 9); + VSYNC_WR_DV_REG(VIU_SW_RESET, 0); reset = true; } @@ -1549,41 +1882,41 @@ static int dolby_core1_set( set_lut = true; if (bl_enable && el_enable && (dolby_vision_mask & 1)) { - if (is_meson_g12()) - VSYNC_WR_MPEG_REG_BITS( + if (is_meson_g12() || is_meson_tm2_stbmode()) + VSYNC_WR_DV_REG_BITS( DOLBY_PATH_CTRL, /* vd2 to core1 */ 0, 1, 1); else - VSYNC_WR_MPEG_REG_BITS( + VSYNC_WR_DV_REG_BITS( VIU_MISC_CTRL1, /* vd2 to core1 */ 0, 17, 1); } else { - if (is_meson_g12()) - VSYNC_WR_MPEG_REG_BITS( + if (is_meson_g12() || is_meson_tm2_stbmode()) + VSYNC_WR_DV_REG_BITS( DOLBY_PATH_CTRL, /* vd2 to core1 */ 1, 1, 1); else - VSYNC_WR_MPEG_REG_BITS( + VSYNC_WR_DV_REG_BITS( VIU_MISC_CTRL1, /* vd2 to vpp */ 1, 17, 1); } - VSYNC_WR_MPEG_REG(DOLBY_CORE1_CLKGATE_CTRL, 0); - /* VSYNC_WR_MPEG_REG(DOLBY_CORE1_SWAP_CTRL0, 0); */ - VSYNC_WR_MPEG_REG(DOLBY_CORE1_SWAP_CTRL1, + VSYNC_WR_DV_REG(DOLBY_CORE1_CLKGATE_CTRL, 0); + /* VSYNC_WR_DV_REG(DOLBY_CORE1_SWAP_CTRL0, 0); */ + VSYNC_WR_DV_REG(DOLBY_CORE1_SWAP_CTRL1, ((hsize + 0x80) << 16) | (vsize + 0x40)); - VSYNC_WR_MPEG_REG(DOLBY_CORE1_SWAP_CTRL3, (hwidth << 16) | vwidth); - VSYNC_WR_MPEG_REG(DOLBY_CORE1_SWAP_CTRL4, (hpotch << 16) | vpotch); - VSYNC_WR_MPEG_REG(DOLBY_CORE1_SWAP_CTRL2, (hsize << 16) | vsize); - VSYNC_WR_MPEG_REG(DOLBY_CORE1_SWAP_CTRL5, 0xa); + VSYNC_WR_DV_REG(DOLBY_CORE1_SWAP_CTRL3, (hwidth << 16) | vwidth); + VSYNC_WR_DV_REG(DOLBY_CORE1_SWAP_CTRL4, (hpotch << 16) | vpotch); + VSYNC_WR_DV_REG(DOLBY_CORE1_SWAP_CTRL2, (hsize << 16) | vsize); + VSYNC_WR_DV_REG(DOLBY_CORE1_SWAP_CTRL5, 0xa); - VSYNC_WR_MPEG_REG(DOLBY_CORE1_DMA_CTRL, 0x0); - VSYNC_WR_MPEG_REG(DOLBY_CORE1_REG_START + 4, 4); - VSYNC_WR_MPEG_REG(DOLBY_CORE1_REG_START + 2, 1); + VSYNC_WR_DV_REG(DOLBY_CORE1_DMA_CTRL, 0x0); + VSYNC_WR_DV_REG(DOLBY_CORE1_REG_START + 4, 4); + VSYNC_WR_DV_REG(DOLBY_CORE1_REG_START + 2, 1); /* bypass composer to get 12bit when SDR and HDR source */ #ifndef V2_4 @@ -1599,9 +1932,9 @@ static int dolby_core1_set( if (el_41_mode) bypass_flag |= 1 << 3; - VSYNC_WR_MPEG_REG(DOLBY_CORE1_REG_START + 1, + VSYNC_WR_DV_REG(DOLBY_CORE1_REG_START + 1, 0x70 | bypass_flag); /* bypass CVM and/or CSC */ - VSYNC_WR_MPEG_REG(DOLBY_CORE1_REG_START + 1, + VSYNC_WR_DV_REG(DOLBY_CORE1_REG_START + 1, 0x70 | bypass_flag); /* for delay */ if (dm_count == 0) count = 24; @@ -1611,7 +1944,7 @@ static int dolby_core1_set( if (reset || (p_core1_dm_regs[i] != last_dm[i])) - VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( DOLBY_CORE1_REG_START + 6 + i, p_core1_dm_regs[i]); @@ -1623,12 +1956,12 @@ static int dolby_core1_set( if (reset || (p_core1_comp_regs[i] != last_comp[i])) - VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( DOLBY_CORE1_REG_START + 6 + 44 + i, p_core1_comp_regs[i]); /* metadata program done */ - VSYNC_WR_MPEG_REG(DOLBY_CORE1_REG_START + 3, 1); + VSYNC_WR_DV_REG(DOLBY_CORE1_REG_START + 3, 1); if (lut_count == 0) count = 256 * 5; @@ -1636,92 +1969,113 @@ static int dolby_core1_set( count = lut_count; if (count && (set_lut || reset)) { if (dolby_vision_flags & FLAG_CLKGATE_WHEN_LOAD_LUT) - VSYNC_WR_MPEG_REG_BITS(DOLBY_CORE1_CLKGATE_CTRL, + VSYNC_WR_DV_REG_BITS(DOLBY_CORE1_CLKGATE_CTRL, 2, 2, 2); - VSYNC_WR_MPEG_REG(DOLBY_CORE1_DMA_CTRL, 0x1401); + VSYNC_WR_DV_REG(DOLBY_CORE1_DMA_CTRL, 0x1401); if (lut_endian) for (i = 0; i < count; i += 4) { - VSYNC_WR_MPEG_REG(DOLBY_CORE1_DMA_PORT, + VSYNC_WR_DV_REG(DOLBY_CORE1_DMA_PORT, p_core1_lut[i+3]); - VSYNC_WR_MPEG_REG(DOLBY_CORE1_DMA_PORT, + VSYNC_WR_DV_REG(DOLBY_CORE1_DMA_PORT, p_core1_lut[i+2]); - VSYNC_WR_MPEG_REG(DOLBY_CORE1_DMA_PORT, + VSYNC_WR_DV_REG(DOLBY_CORE1_DMA_PORT, p_core1_lut[i+1]); - VSYNC_WR_MPEG_REG(DOLBY_CORE1_DMA_PORT, + VSYNC_WR_DV_REG(DOLBY_CORE1_DMA_PORT, p_core1_lut[i]); } else for (i = 0; i < count; i++) - VSYNC_WR_MPEG_REG(DOLBY_CORE1_DMA_PORT, + VSYNC_WR_DV_REG(DOLBY_CORE1_DMA_PORT, p_core1_lut[i]); if (dolby_vision_flags & FLAG_CLKGATE_WHEN_LOAD_LUT) - VSYNC_WR_MPEG_REG_BITS(DOLBY_CORE1_CLKGATE_CTRL, + VSYNC_WR_DV_REG_BITS(DOLBY_CORE1_CLKGATE_CTRL, 0, 2, 2); } if (dolby_vision_on_count <= dolby_vision_run_mode_delay) { - VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VPP_VD1_CLIP_MISC0, (0x200 << 10) | 0x200); - VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VPP_VD1_CLIP_MISC1, (0x200 << 10) | 0x200); if (is_meson_g12()) - VSYNC_WR_MPEG_REG_BITS( + VSYNC_WR_DV_REG_BITS( DOLBY_PATH_CTRL, 1, 0, 1); else - VSYNC_WR_MPEG_REG_BITS( + VSYNC_WR_DV_REG_BITS( VIU_MISC_CTRL1, 1, 16, 1); } else { if (dolby_vision_on_count > dolby_vision_run_mode_delay) { - VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VPP_VD1_CLIP_MISC0, (0x3ff << 20) | (0x3ff << 10) | 0x3ff); - VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VPP_VD1_CLIP_MISC1, 0); } if (dolby_vision_core1_on && !bypass_core1) { if (is_meson_g12()) - VSYNC_WR_MPEG_REG_BITS( + VSYNC_WR_DV_REG_BITS( DOLBY_PATH_CTRL, - 0, - 0, 1); - else - VSYNC_WR_MPEG_REG_BITS( + 0, 0, 1); + else if (is_meson_tm2_stbmode()) { + VSYNC_WR_DV_REG_BITS( + DOLBY_PATH_CTRL, + 0, 8, 2); + VSYNC_WR_DV_REG_BITS( + DOLBY_PATH_CTRL, + 0, 10, 2); + VSYNC_WR_DV_REG_BITS( + DOLBY_PATH_CTRL, + 0, 17, 1); + VSYNC_WR_DV_REG_BITS( + DOLBY_PATH_CTRL, + 0, 21, 1); + VSYNC_WR_DV_REG_BITS( + DOLBY_PATH_CTRL, + 0, 24, 2); + VSYNC_WR_DV_REG_BITS( + DOLBY_PATH_CTRL, + 0, 0, 1); /* core1 */ + } else + VSYNC_WR_DV_REG_BITS( VIU_MISC_CTRL1, /* enable core 1 */ 0, 16, 1); } else if (dolby_vision_core1_on && bypass_core1) { if (is_meson_g12()) - VSYNC_WR_MPEG_REG_BITS( + VSYNC_WR_DV_REG_BITS( DOLBY_PATH_CTRL, - 1, - 0, 1); - else - VSYNC_WR_MPEG_REG_BITS( + 1, 0, 1); + else if (is_meson_tm2_stbmode()) { + VSYNC_WR_DV_REG_BITS( + DOLBY_PATH_CTRL, + 3, 0, 2); /* core1 */ + } else + VSYNC_WR_DV_REG_BITS( VIU_MISC_CTRL1, /* bypass core 1 */ 1, 16, 1); } } - if (is_meson_g12()) - VSYNC_WR_MPEG_REG(DOLBY_CORE1_SWAP_CTRL0, + if (is_meson_g12() || is_meson_tm2_stbmode()) + VSYNC_WR_DV_REG(DOLBY_CORE1_SWAP_CTRL0, (el_41_mode ? (0x3 << 4) : (0x0 << 4)) | bl_enable | composer_enable << 1 | el_41_mode << 2); else /* enable core1 */ - VSYNC_WR_MPEG_REG(DOLBY_CORE1_SWAP_CTRL0, + VSYNC_WR_DV_REG(DOLBY_CORE1_SWAP_CTRL0, bl_enable << 0 | composer_enable << 1 | el_41_mode << 2); @@ -1753,8 +2107,8 @@ static int dolby_core2_set( return 0; if (!dolby_vision_on || force_reset_core2) { - VSYNC_WR_MPEG_REG(VIU_SW_RESET, (1 << 10)); - VSYNC_WR_MPEG_REG(VIU_SW_RESET, 0); + VSYNC_WR_DV_REG(VIU_SW_RESET, (1 << 10)); + VSYNC_WR_DV_REG(VIU_SW_RESET, 0); force_reset_core2 = false; reset = true; } @@ -1771,31 +2125,31 @@ static int dolby_core2_set( VSYNC_WR_MPEG_REG(DOLBY_CORE2A_SWAP_CTRL1, ((hsize + g_htotal_add) << 16) | (vsize + g_vtotal_add + g_vsize_add)); - VSYNC_WR_MPEG_REG(DOLBY_CORE2A_SWAP_CTRL2, + VSYNC_WR_DV_REG(DOLBY_CORE2A_SWAP_CTRL2, (hsize << 16) | (vsize + g_vsize_add)); } - VSYNC_WR_MPEG_REG(DOLBY_CORE2A_SWAP_CTRL3, + VSYNC_WR_DV_REG(DOLBY_CORE2A_SWAP_CTRL3, (g_hwidth << 16) | g_vwidth); - VSYNC_WR_MPEG_REG(DOLBY_CORE2A_SWAP_CTRL4, + VSYNC_WR_DV_REG(DOLBY_CORE2A_SWAP_CTRL4, (g_hpotch << 16) | g_vpotch); if (is_meson_txlx_stbmode() || force_stb_mode) - VSYNC_WR_MPEG_REG(DOLBY_CORE2A_SWAP_CTRL5, 0xf8000000); - else if (is_meson_g12()) - VSYNC_WR_MPEG_REG(DOLBY_CORE2A_SWAP_CTRL5, 0xa8000000); + VSYNC_WR_DV_REG(DOLBY_CORE2A_SWAP_CTRL5, 0xf8000000); + else if (is_meson_g12() || is_meson_tm2_stbmode()) + VSYNC_WR_DV_REG(DOLBY_CORE2A_SWAP_CTRL5, 0xa8000000); else - VSYNC_WR_MPEG_REG(DOLBY_CORE2A_SWAP_CTRL5, 0x0); - VSYNC_WR_MPEG_REG(DOLBY_CORE2A_DMA_CTRL, 0x0); - VSYNC_WR_MPEG_REG(DOLBY_CORE2A_REG_START + 2, 1); + VSYNC_WR_DV_REG(DOLBY_CORE2A_SWAP_CTRL5, 0x0); + VSYNC_WR_DV_REG(DOLBY_CORE2A_DMA_CTRL, 0x0); + VSYNC_WR_DV_REG(DOLBY_CORE2A_REG_START + 2, 1); if (need_skip_cvm(1)) bypass_flag |= 1 << 0; - VSYNC_WR_MPEG_REG(DOLBY_CORE2A_REG_START + 2, 1); - VSYNC_WR_MPEG_REG(DOLBY_CORE2A_REG_START + 1, + VSYNC_WR_DV_REG(DOLBY_CORE2A_REG_START + 2, 1); + VSYNC_WR_DV_REG(DOLBY_CORE2A_REG_START + 1, 2 | bypass_flag); - VSYNC_WR_MPEG_REG(DOLBY_CORE2A_REG_START + 1, + VSYNC_WR_DV_REG(DOLBY_CORE2A_REG_START + 1, 2 | bypass_flag); - VSYNC_WR_MPEG_REG(DOLBY_CORE2A_CTRL, 0); + VSYNC_WR_DV_REG(DOLBY_CORE2A_CTRL, 0); - VSYNC_WR_MPEG_REG(DOLBY_CORE2A_CTRL, 0); + VSYNC_WR_DV_REG(DOLBY_CORE2A_CTRL, 0); if (dm_count == 0) count = 24; @@ -1805,7 +2159,7 @@ static int dolby_core2_set( if (reset || (p_core2_dm_regs[i] != last_dm[i])) { - VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( DOLBY_CORE2A_REG_START + 6 + i, p_core2_dm_regs[i]); set_lut = true; @@ -1815,7 +2169,7 @@ static int dolby_core2_set( set_lut = false; /* core2 metadata program done */ - VSYNC_WR_MPEG_REG(DOLBY_CORE2A_REG_START + 3, 1); + VSYNC_WR_DV_REG(DOLBY_CORE2A_REG_START + 3, 1); if (lut_count == 0) count = 256 * 5; @@ -1823,32 +2177,32 @@ static int dolby_core2_set( count = lut_count; if (count && (set_lut || reset)) { if (dolby_vision_flags & FLAG_CLKGATE_WHEN_LOAD_LUT) - VSYNC_WR_MPEG_REG_BITS(DOLBY_CORE2A_CLKGATE_CTRL, + VSYNC_WR_DV_REG_BITS(DOLBY_CORE2A_CLKGATE_CTRL, 2, 2, 2); - VSYNC_WR_MPEG_REG(DOLBY_CORE2A_DMA_CTRL, 0x1401); + VSYNC_WR_DV_REG(DOLBY_CORE2A_DMA_CTRL, 0x1401); if (lut_endian) for (i = 0; i < count; i += 4) { - VSYNC_WR_MPEG_REG(DOLBY_CORE2A_DMA_PORT, + VSYNC_WR_DV_REG(DOLBY_CORE2A_DMA_PORT, p_core2_lut[i+3]); - VSYNC_WR_MPEG_REG(DOLBY_CORE2A_DMA_PORT, + VSYNC_WR_DV_REG(DOLBY_CORE2A_DMA_PORT, p_core2_lut[i+2]); - VSYNC_WR_MPEG_REG(DOLBY_CORE2A_DMA_PORT, + VSYNC_WR_DV_REG(DOLBY_CORE2A_DMA_PORT, p_core2_lut[i+1]); - VSYNC_WR_MPEG_REG(DOLBY_CORE2A_DMA_PORT, + VSYNC_WR_DV_REG(DOLBY_CORE2A_DMA_PORT, p_core2_lut[i]); } else for (i = 0; i < count; i++) - VSYNC_WR_MPEG_REG(DOLBY_CORE2A_DMA_PORT, + VSYNC_WR_DV_REG(DOLBY_CORE2A_DMA_PORT, p_core2_lut[i]); /* core2 lookup table program done */ if (dolby_vision_flags & FLAG_CLKGATE_WHEN_LOAD_LUT) - VSYNC_WR_MPEG_REG_BITS( + VSYNC_WR_DV_REG_BITS( DOLBY_CORE2A_CLKGATE_CTRL, 0, 2, 2); } /* enable core2 */ - VSYNC_WR_MPEG_REG(DOLBY_CORE2A_SWAP_CTRL0, dolby_enable << 0); + VSYNC_WR_DV_REG(DOLBY_CORE2A_SWAP_CTRL0, dolby_enable << 0); return 0; } @@ -1892,7 +2246,7 @@ static int dolby_core3_set( && diag_enable) { cur_dv_mode = dv_ll_output_mode & 0xff; - if (is_meson_g12()) { + if (is_meson_g12() || is_meson_tm2_stbmode()) { if (dolby_vision_ll_policy == DOLBY_VISION_LL_YUV422) diag_mode = 0x20; else @@ -1911,65 +2265,64 @@ static int dolby_core3_set( new_dovi_setting.vsvdb_changed = 0; new_dovi_setting.mode_changed = 0; /* TODO: verify 962e case */ - if (is_meson_gxm() || - is_meson_g12()) { + if (is_meson_box() || is_meson_tm2_stbmode()) { if (new_dovi_setting.dovi_ll_enable && new_dovi_setting.diagnostic_enable == 0) { - VSYNC_WR_MPEG_REG_BITS( + VSYNC_WR_DV_REG_BITS( VPP_DOLBY_CTRL, 3, 6, 2); /* post matrix */ - VSYNC_WR_MPEG_REG_BITS( + VSYNC_WR_DV_REG_BITS( VPP_MATRIX_CTRL, 1, 0, 1); /* post matrix */ } else { - VSYNC_WR_MPEG_REG_BITS( + VSYNC_WR_DV_REG_BITS( VPP_DOLBY_CTRL, 0, 6, 2); /* post matrix */ - VSYNC_WR_MPEG_REG_BITS( + VSYNC_WR_DV_REG_BITS( VPP_MATRIX_CTRL, 0, 0, 1); /* post matrix */ } } else if (is_meson_txlx_stbmode() || force_stb_mode) { if (pps_state == 2) { - VSYNC_WR_MPEG_REG_BITS( + VSYNC_WR_DV_REG_BITS( VPP_DOLBY_CTRL, 1, 0, 1); /* skip pps/dither/cm */ - VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VPP_DAT_CONV_PARA0, 0x08000800); } else if (pps_state == 1) { - VSYNC_WR_MPEG_REG_BITS( + VSYNC_WR_DV_REG_BITS( VPP_DOLBY_CTRL, 0, 0, 1); /* enable pps/dither/cm */ - VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VPP_DAT_CONV_PARA0, 0x20002000); } if (new_dovi_setting.dovi_ll_enable && new_dovi_setting.diagnostic_enable == 0) { /*bypass gainoff to vks */ /*enable wn tp vks*/ - VSYNC_WR_MPEG_REG_BITS( + VSYNC_WR_DV_REG_BITS( VPP_DOLBY_CTRL, 0, 2, 1); - VSYNC_WR_MPEG_REG_BITS( + VSYNC_WR_DV_REG_BITS( VPP_DOLBY_CTRL, 1, 1, 1); - VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VPP_DAT_CONV_PARA1, 0x8000800); - VSYNC_WR_MPEG_REG_BITS( + VSYNC_WR_DV_REG_BITS( VPP_MATRIX_CTRL, 1, 0, 1); /* post matrix */ } else { /* bypass wm tp vks*/ - VSYNC_WR_MPEG_REG_BITS( + VSYNC_WR_DV_REG_BITS( VPP_DOLBY_CTRL, 1, 2, 1); - VSYNC_WR_MPEG_REG_BITS( + VSYNC_WR_DV_REG_BITS( VPP_DOLBY_CTRL, 0, 1, 1); - VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VPP_DAT_CONV_PARA1, 0x20002000); - if (is_meson_txlx_tvmode()) + if (is_meson_tvmode()) enable_rgb_to_yuv_matrix_for_dvll( 0, NULL, 12); else - VSYNC_WR_MPEG_REG_BITS( + VSYNC_WR_DV_REG_BITS( VPP_MATRIX_CTRL, 0, 0, 1); } @@ -1987,27 +2340,27 @@ static int dolby_core3_set( 1, &p_core3_dm_regs[18], 12); #endif - VSYNC_WR_MPEG_REG(DOLBY_CORE3_CLKGATE_CTRL, 0); - VSYNC_WR_MPEG_REG(DOLBY_CORE3_SWAP_CTRL1, + VSYNC_WR_DV_REG(DOLBY_CORE3_CLKGATE_CTRL, 0); + VSYNC_WR_DV_REG(DOLBY_CORE3_SWAP_CTRL1, ((hsize + htotal_add) << 16) | (vsize + vtotal_add + vsize_add + vsize_hold * 2)); - VSYNC_WR_MPEG_REG(DOLBY_CORE3_SWAP_CTRL2, + VSYNC_WR_DV_REG(DOLBY_CORE3_SWAP_CTRL2, (hsize << 16) | (vsize + vsize_add)); - VSYNC_WR_MPEG_REG(DOLBY_CORE3_SWAP_CTRL3, + VSYNC_WR_DV_REG(DOLBY_CORE3_SWAP_CTRL3, (0x80 << 16) | vsize_hold); - VSYNC_WR_MPEG_REG(DOLBY_CORE3_SWAP_CTRL4, + VSYNC_WR_DV_REG(DOLBY_CORE3_SWAP_CTRL4, (0x04 << 16) | vsize_hold); - VSYNC_WR_MPEG_REG(DOLBY_CORE3_SWAP_CTRL5, 0x0000); + VSYNC_WR_DV_REG(DOLBY_CORE3_SWAP_CTRL5, 0x0000); if (cur_dv_mode != DOLBY_VISION_OUTPUT_MODE_IPT_TUNNEL) - VSYNC_WR_MPEG_REG(DOLBY_CORE3_SWAP_CTRL6, 0); + VSYNC_WR_DV_REG(DOLBY_CORE3_SWAP_CTRL6, 0); else - VSYNC_WR_MPEG_REG(DOLBY_CORE3_SWAP_CTRL6, + VSYNC_WR_DV_REG(DOLBY_CORE3_SWAP_CTRL6, 0x10000000); /* swap UV */ - VSYNC_WR_MPEG_REG(DOLBY_CORE3_REG_START + 5, 7); - VSYNC_WR_MPEG_REG(DOLBY_CORE3_REG_START + 4, 4); - VSYNC_WR_MPEG_REG(DOLBY_CORE3_REG_START + 4, 2); - VSYNC_WR_MPEG_REG(DOLBY_CORE3_REG_START + 2, 1); + VSYNC_WR_DV_REG(DOLBY_CORE3_REG_START + 5, 7); + VSYNC_WR_DV_REG(DOLBY_CORE3_REG_START + 4, 4); + VSYNC_WR_DV_REG(DOLBY_CORE3_REG_START + 4, 2); + VSYNC_WR_DV_REG(DOLBY_CORE3_REG_START + 2, 1); /* Control Register, address 0x04 2:0 RW */ /* Output_operating mode*/ /* 00- IPT 12 bit 444 bypass Dolby Vision output*/ @@ -2015,8 +2368,8 @@ static int dolby_core3_set( /* 02- HDR10 output, RGB 10 bit 444 PQ*/ /* 03- Deep color SDR, RGB 10 bit 444 Gamma*/ /* 04- SDR, RGB 8 bit 444 Gamma*/ - VSYNC_WR_MPEG_REG(DOLBY_CORE3_REG_START + 1, cur_dv_mode); - VSYNC_WR_MPEG_REG(DOLBY_CORE3_REG_START + 1, cur_dv_mode); + VSYNC_WR_DV_REG(DOLBY_CORE3_REG_START + 1, cur_dv_mode); + VSYNC_WR_DV_REG(DOLBY_CORE3_REG_START + 1, cur_dv_mode); /* for delay */ if (dm_count == 0) @@ -2026,7 +2379,7 @@ static int dolby_core3_set( for (i = 0; i < count; i++) if (reset || (p_core3_dm_regs[i] != last_dm[i])) - VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( DOLBY_CORE3_REG_START + 0x6 + i, p_core3_dm_regs[i]); /* from addr 0x18 */ @@ -2035,29 +2388,29 @@ static int dolby_core3_set( for (i = 0; i < count; i++) { #ifdef FORCE_HDMI_META if ((i == 20) && (p_core3_md_regs[i] == 0x5140a3e)) - VSYNC_WR_MPEG_REG(DOLBY_CORE3_REG_START + 0x24 + i, + VSYNC_WR_DV_REG(DOLBY_CORE3_REG_START + 0x24 + i, (p_core3_md_regs[i] & 0xffffff00) | 0x80); else #endif - VSYNC_WR_MPEG_REG(DOLBY_CORE3_REG_START + 0x24 + i, + VSYNC_WR_DV_REG(DOLBY_CORE3_REG_START + 0x24 + i, p_core3_md_regs[i]); } for (; i < 30; i++) - VSYNC_WR_MPEG_REG(DOLBY_CORE3_REG_START + 0x24 + i, 0); + VSYNC_WR_DV_REG(DOLBY_CORE3_REG_START + 0x24 + i, 0); /* from addr 0x90 */ /* core3 metadata program done */ - VSYNC_WR_MPEG_REG(DOLBY_CORE3_REG_START + 3, 1); + VSYNC_WR_DV_REG(DOLBY_CORE3_REG_START + 3, 1); - VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( DOLBY_CORE3_DIAG_CTRL, diag_mode); if ((dolby_vision_flags & FLAG_CERTIFICAION) && !(dolby_vision_flags & FLAG_DISABLE_CRC)) - VSYNC_WR_MPEG_REG(0x36fb, 1); + VSYNC_WR_DV_REG(0x36fb, 1); /* enable core3 */ - VSYNC_WR_MPEG_REG(DOLBY_CORE3_SWAP_CTRL0, (dolby_enable << 0)); + VSYNC_WR_DV_REG(DOLBY_CORE3_SWAP_CTRL0, (dolby_enable << 0)); return 0; } @@ -2201,16 +2554,16 @@ static void osd_bypass(int bypass) static uint32_t osd_backup_mtx; if (bypass) { - osd_backup_ctrl = VSYNC_RD_MPEG_REG(VIU_OSD1_CTRL_STAT); - osd_backup_eotf = VSYNC_RD_MPEG_REG(VIU_OSD1_EOTF_CTL); - osd_backup_mtx = VSYNC_RD_MPEG_REG(VPP_MATRIX_CTRL); - VSYNC_WR_MPEG_REG_BITS(VIU_OSD1_EOTF_CTL, 0, 31, 1); - VSYNC_WR_MPEG_REG_BITS(VIU_OSD1_CTRL_STAT, 0, 3, 1); - VSYNC_WR_MPEG_REG_BITS(VPP_MATRIX_CTRL, 0, 7, 1); + osd_backup_ctrl = VSYNC_RD_DV_REG(VIU_OSD1_CTRL_STAT); + osd_backup_eotf = VSYNC_RD_DV_REG(VIU_OSD1_EOTF_CTL); + osd_backup_mtx = VSYNC_RD_DV_REG(VPP_MATRIX_CTRL); + VSYNC_WR_DV_REG_BITS(VIU_OSD1_EOTF_CTL, 0, 31, 1); + VSYNC_WR_DV_REG_BITS(VIU_OSD1_CTRL_STAT, 0, 3, 1); + VSYNC_WR_DV_REG_BITS(VPP_MATRIX_CTRL, 0, 7, 1); } else { - VSYNC_WR_MPEG_REG(VPP_MATRIX_CTRL, osd_backup_mtx); - VSYNC_WR_MPEG_REG(VIU_OSD1_CTRL_STAT, osd_backup_ctrl); - VSYNC_WR_MPEG_REG(VIU_OSD1_EOTF_CTL, osd_backup_eotf); + VSYNC_WR_DV_REG(VPP_MATRIX_CTRL, osd_backup_mtx); + VSYNC_WR_DV_REG(VIU_OSD1_CTRL_STAT, osd_backup_ctrl); + VSYNC_WR_DV_REG(VIU_OSD1_EOTF_CTL, osd_backup_eotf); } } @@ -2228,42 +2581,42 @@ static void video_effect_bypass(int bypass) if (bypass) { if (!is_video_effect_bypass) { viu_eotf_ctrl_backup = - VSYNC_RD_MPEG_REG(VIU_EOTF_CTL); + VSYNC_RD_DV_REG(VIU_EOTF_CTL); xvycc_lut_ctrl_backup = - VSYNC_RD_MPEG_REG(XVYCC_LUT_CTL); + VSYNC_RD_DV_REG(XVYCC_LUT_CTL); inv_lut_ctrl_backup = - VSYNC_RD_MPEG_REG(XVYCC_INV_LUT_CTL); + VSYNC_RD_DV_REG(XVYCC_INV_LUT_CTL); vpp_vadj_backup = - VSYNC_RD_MPEG_REG(VPP_VADJ_CTRL); + VSYNC_RD_DV_REG(VPP_VADJ_CTRL); vpp_gainoff_backup = - VSYNC_RD_MPEG_REG(VPP_GAINOFF_CTRL0); + VSYNC_RD_DV_REG(VPP_GAINOFF_CTRL0); vpp_ve_enable_ctrl_backup = - VSYNC_RD_MPEG_REG(VPP_VE_ENABLE_CTRL); + VSYNC_RD_DV_REG(VPP_VE_ENABLE_CTRL); xvycc_vd1_rgb_ctrst_backup = - VSYNC_RD_MPEG_REG(XVYCC_VD1_RGB_CTRST); + VSYNC_RD_DV_REG(XVYCC_VD1_RGB_CTRST); is_video_effect_bypass = true; } - VSYNC_WR_MPEG_REG(VIU_EOTF_CTL, 0); - VSYNC_WR_MPEG_REG(XVYCC_LUT_CTL, 0); - VSYNC_WR_MPEG_REG(XVYCC_INV_LUT_CTL, 0); - VSYNC_WR_MPEG_REG(VPP_VADJ_CTRL, 0); - VSYNC_WR_MPEG_REG(VPP_GAINOFF_CTRL0, 0); - VSYNC_WR_MPEG_REG(VPP_VE_ENABLE_CTRL, 0); - VSYNC_WR_MPEG_REG(XVYCC_VD1_RGB_CTRST, 0); + VSYNC_WR_DV_REG(VIU_EOTF_CTL, 0); + VSYNC_WR_DV_REG(XVYCC_LUT_CTL, 0); + VSYNC_WR_DV_REG(XVYCC_INV_LUT_CTL, 0); + VSYNC_WR_DV_REG(VPP_VADJ_CTRL, 0); + VSYNC_WR_DV_REG(VPP_GAINOFF_CTRL0, 0); + VSYNC_WR_DV_REG(VPP_VE_ENABLE_CTRL, 0); + VSYNC_WR_DV_REG(XVYCC_VD1_RGB_CTRST, 0); } else if (is_video_effect_bypass) { - VSYNC_WR_MPEG_REG(VIU_EOTF_CTL, + VSYNC_WR_DV_REG(VIU_EOTF_CTL, viu_eotf_ctrl_backup); - VSYNC_WR_MPEG_REG(XVYCC_LUT_CTL, + VSYNC_WR_DV_REG(XVYCC_LUT_CTL, xvycc_lut_ctrl_backup); - VSYNC_WR_MPEG_REG(XVYCC_INV_LUT_CTL, + VSYNC_WR_DV_REG(XVYCC_INV_LUT_CTL, inv_lut_ctrl_backup); - VSYNC_WR_MPEG_REG(VPP_VADJ_CTRL, + VSYNC_WR_DV_REG(VPP_VADJ_CTRL, vpp_vadj_backup); - VSYNC_WR_MPEG_REG(VPP_GAINOFF_CTRL0, + VSYNC_WR_DV_REG(VPP_GAINOFF_CTRL0, vpp_gainoff_backup); - VSYNC_WR_MPEG_REG(VPP_VE_ENABLE_CTRL, + VSYNC_WR_DV_REG(VPP_VE_ENABLE_CTRL, vpp_ve_enable_ctrl_backup); - VSYNC_WR_MPEG_REG(XVYCC_VD1_RGB_CTRST, + VSYNC_WR_DV_REG(XVYCC_VD1_RGB_CTRST, xvycc_vd1_rgb_ctrst_backup); } } @@ -2277,54 +2630,54 @@ static void osd_path_enable(int on) if (!on) { enable_osd_path(0, 0); - VSYNC_WR_MPEG_REG(VIU_OSD1_EOTF_CTL, 0); - VSYNC_WR_MPEG_REG(VIU_OSD1_OETF_CTL, 0); + VSYNC_WR_DV_REG(VIU_OSD1_EOTF_CTL, 0); + VSYNC_WR_DV_REG(VIU_OSD1_OETF_CTL, 0); } else { enable_osd_path(1, -1); if ((hdr_osd_reg.viu_osd1_eotf_ctl & 0x80000000) != 0) { addr_port = VIU_OSD1_EOTF_LUT_ADDR_PORT; data_port = VIU_OSD1_EOTF_LUT_DATA_PORT; - VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( addr_port, 0); for (i = 0; i < 16; i++) - VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( data_port, lut->r_map[i * 2] | (lut->r_map[i * 2 + 1] << 16)); - VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( data_port, lut->r_map[EOTF_LUT_SIZE - 1] | (lut->g_map[0] << 16)); for (i = 0; i < 16; i++) - VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( data_port, lut->g_map[i * 2 + 1] | (lut->b_map[i * 2 + 2] << 16)); for (i = 0; i < 16; i++) - VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( data_port, lut->b_map[i * 2] | (lut->b_map[i * 2 + 1] << 16)); - VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( data_port, lut->b_map[EOTF_LUT_SIZE - 1]); /* load eotf matrix */ - VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VIU_OSD1_EOTF_COEF00_01, hdr_osd_reg.viu_osd1_eotf_coef00_01); - VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VIU_OSD1_EOTF_COEF02_10, hdr_osd_reg.viu_osd1_eotf_coef02_10); - VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VIU_OSD1_EOTF_COEF11_12, hdr_osd_reg.viu_osd1_eotf_coef11_12); - VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VIU_OSD1_EOTF_COEF20_21, hdr_osd_reg.viu_osd1_eotf_coef20_21); - VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VIU_OSD1_EOTF_COEF22_RS, hdr_osd_reg.viu_osd1_eotf_coef22_rs); - VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VIU_OSD1_EOTF_CTL, hdr_osd_reg.viu_osd1_eotf_ctl); } @@ -2333,82 +2686,82 @@ static void osd_path_enable(int on) addr_port = VIU_OSD1_OETF_LUT_ADDR_PORT; data_port = VIU_OSD1_OETF_LUT_DATA_PORT; for (i = 0; i < 20; i++) { - VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( addr_port, i); - VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( data_port, lut->or_map[i * 2] | (lut->or_map[i * 2 + 1] << 16)); } - VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( addr_port, 20); - VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( data_port, lut->or_map[41 - 1] | (lut->og_map[0] << 16)); for (i = 0; i < 20; i++) { - VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( addr_port, 21 + i); - VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( data_port, lut->og_map[i * 2 + 1] | (lut->og_map[i * 2 + 2] << 16)); } for (i = 0; i < 20; i++) { - VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( addr_port, 41 + i); - VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( data_port, lut->ob_map[i * 2] | (lut->ob_map[i * 2 + 1] << 16)); } - VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( addr_port, 61); - VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( data_port, lut->ob_map[41 - 1]); - VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VIU_OSD1_OETF_CTL, hdr_osd_reg.viu_osd1_oetf_ctl); } } - VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VIU_OSD1_MATRIX_PRE_OFFSET0_1, hdr_osd_reg.viu_osd1_matrix_pre_offset0_1); - VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VIU_OSD1_MATRIX_PRE_OFFSET2, hdr_osd_reg.viu_osd1_matrix_pre_offset2); - VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VIU_OSD1_MATRIX_COEF00_01, hdr_osd_reg.viu_osd1_matrix_coef00_01); - VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VIU_OSD1_MATRIX_COEF02_10, hdr_osd_reg.viu_osd1_matrix_coef02_10); - VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VIU_OSD1_MATRIX_COEF11_12, hdr_osd_reg.viu_osd1_matrix_coef11_12); - VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VIU_OSD1_MATRIX_COEF20_21, hdr_osd_reg.viu_osd1_matrix_coef20_21); - VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VIU_OSD1_MATRIX_COEF22_30, hdr_osd_reg.viu_osd1_matrix_coef22_30); - VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VIU_OSD1_MATRIX_COEF31_32, hdr_osd_reg.viu_osd1_matrix_coef31_32); - VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VIU_OSD1_MATRIX_COEF40_41, hdr_osd_reg.viu_osd1_matrix_coef40_41); - VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VIU_OSD1_MATRIX_COLMOD_COEF42, hdr_osd_reg.viu_osd1_matrix_colmod_coef42); - VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VIU_OSD1_MATRIX_OFFSET0_1, hdr_osd_reg.viu_osd1_matrix_offset0_1); - VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VIU_OSD1_MATRIX_OFFSET2, hdr_osd_reg.viu_osd1_matrix_offset2); - VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VIU_OSD1_MATRIX_CTRL, hdr_osd_reg.viu_osd1_matrix_ctrl); } @@ -2422,27 +2775,26 @@ static uint32_t vpp_data_conv_para1_backup; void enable_dolby_vision(int enable) { uint32_t size = 0; - uint64_t *dma_data = ((struct tv_dovi_setting_s *) - tv_dovi_setting)->core1_reg_lut; + uint64_t *dma_data = tv_dovi_setting->core1_reg_lut; if (enable) { if (!dolby_vision_on) { dolby_ctrl_backup = - VSYNC_RD_MPEG_REG(VPP_DOLBY_CTRL); + VSYNC_RD_DV_REG(VPP_DOLBY_CTRL); viu_misc_ctrl_backup = - VSYNC_RD_MPEG_REG(VIU_MISC_CTRL1); + VSYNC_RD_DV_REG(VIU_MISC_CTRL1); vpp_matrix_backup = - VSYNC_RD_MPEG_REG(VPP_MATRIX_CTRL); + VSYNC_RD_DV_REG(VPP_MATRIX_CTRL); vpp_dummy1_backup = - VSYNC_RD_MPEG_REG(VPP_DUMMY_DATA1); + VSYNC_RD_DV_REG(VPP_DUMMY_DATA1); if (is_meson_txlx()) { vpp_data_conv_para0_backup = - VSYNC_RD_MPEG_REG(VPP_DAT_CONV_PARA0); + VSYNC_RD_DV_REG(VPP_DAT_CONV_PARA0); vpp_data_conv_para1_backup = - VSYNC_RD_MPEG_REG(VPP_DAT_CONV_PARA1); + VSYNC_RD_DV_REG(VPP_DAT_CONV_PARA1); setting_update_count = 0; } - if (is_meson_txlx_tvmode() && !force_stb_mode) { + if (is_meson_tvmode() && !force_stb_mode) { if (efuse_mode == 1) { size = 8 * TV_DMA_TBL_SIZE; memset(dma_vaddr, 0x0, size); @@ -2450,23 +2802,54 @@ void enable_dolby_vision(int enable) dma_data + 1, 8); } - if ((dolby_vision_mask & 1) - && dovi_setting_video_flag) { - VSYNC_WR_MPEG_REG_BITS( - VIU_MISC_CTRL1, - 0, - 16, 1); /* core1 */ - dolby_vision_core1_on = true; - } else { - VSYNC_WR_MPEG_REG_BITS( - VIU_MISC_CTRL1, - 1, - 16, 1); /* core1 */ - dolby_vision_core1_on = false; + if (is_meson_txlx_tvmode()) { + if ((dolby_vision_mask & 1) + && dovi_setting_video_flag) { + VSYNC_WR_DV_REG_BITS( + VIU_MISC_CTRL1, + 0, + 16, 1); /* core1 */ + dolby_vision_core1_on = true; + } else { + VSYNC_WR_DV_REG_BITS( + VIU_MISC_CTRL1, + 1, + 16, 1); /* core1 */ + dolby_vision_core1_on = false; + } + } else if (is_meson_tm2_tvmode()) { + if ((dolby_vision_mask & 1) + && dovi_setting_video_flag) { + VSYNC_WR_DV_REG_BITS( + DOLBY_PATH_CTRL, + 1, 8, 2); + VSYNC_WR_DV_REG_BITS( + DOLBY_PATH_CTRL, + 1, 10, 2); + VSYNC_WR_DV_REG_BITS( + DOLBY_PATH_CTRL, + 0, 16, 1); + VSYNC_WR_DV_REG_BITS( + DOLBY_PATH_CTRL, + 0, 20, 1); + VSYNC_WR_DV_REG_BITS( + DOLBY_PATH_CTRL, + 1, 24, 2); + VSYNC_WR_DV_REG_BITS( + DOLBY_PATH_CTRL, + 0, 0, 2); + dolby_vision_core1_on = true; + } else { + VSYNC_WR_DV_REG_BITS( + DOLBY_PATH_CTRL, + 3, 0, 2); + dolby_vision_core1_on = false; + } } + if (dolby_vision_flags & FLAG_CERTIFICAION) { /* bypass dither/PPS/SR/CM, EO/OE */ - VSYNC_WR_MPEG_REG_BITS( + VSYNC_WR_DV_REG_BITS( VPP_DOLBY_CTRL, 3, 0, 2); /* bypass all video effect */ video_effect_bypass(1); @@ -2474,13 +2857,13 @@ void enable_dolby_vision(int enable) /* before vadj1 */ /* 12 bit sign to unsign*/ /* before post blend */ - VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VPP_DAT_CONV_PARA0, 0x08000800); /* 12->10 before vadj2*/ /* 10->12 after gainoff */ - VSYNC_WR_MPEG_REG( - VPP_DAT_CONV_PARA1, 0x08000800); - WRITE_VPP_REG(0x33e7, 0xb); + VSYNC_WR_DV_REG( + VPP_DAT_CONV_PARA1, 0x20002000); + WRITE_VPP_DV_REG(0x33e7, 0xb); } else { /* bypass all video effect */ if (dolby_vision_flags @@ -2488,18 +2871,18 @@ void enable_dolby_vision(int enable) video_effect_bypass(1); /* 12->10 before vadj1*/ /* 10->12 before post blend */ - VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VPP_DAT_CONV_PARA0, 0x20002000); /* 12->10 before vadj2*/ /* 10->12 after gainoff */ - VSYNC_WR_MPEG_REG( - VPP_DAT_CONV_PARA1, 0x08000800); + VSYNC_WR_DV_REG( + VPP_DAT_CONV_PARA1, 0x20002000); } - VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VPP_DUMMY_DATA1, 0x80200); /* osd rgb to yuv, vpp out yuv to rgb */ - VSYNC_WR_MPEG_REG(VPP_MATRIX_CTRL, 0x81); + VSYNC_WR_DV_REG(VPP_MATRIX_CTRL, 0x81); pr_dolby_dbg("Dolby Vision TV core turn on\n"); } else if (is_meson_txlx_stbmode() || force_stb_mode) { @@ -2508,29 +2891,29 @@ void enable_dolby_vision(int enable) memset(dma_vaddr, 0x0, size); osd_bypass(1); if (dolby_vision_mask & 4) - VSYNC_WR_MPEG_REG_BITS(VPP_DOLBY_CTRL, + VSYNC_WR_DV_REG_BITS(VPP_DOLBY_CTRL, 1, 3, 1); /* core3 enable */ if ((dolby_vision_mask & 1) && dovi_setting_video_flag) { - VSYNC_WR_MPEG_REG_BITS( + VSYNC_WR_DV_REG_BITS( VIU_MISC_CTRL1, 0, 16, 1); /* core1 */ dolby_vision_core1_on = true; } else { - VSYNC_WR_MPEG_REG_BITS( + VSYNC_WR_DV_REG_BITS( VIU_MISC_CTRL1, 1, 16, 1); /* core1 */ dolby_vision_core1_on = false; } - VSYNC_WR_MPEG_REG_BITS( + VSYNC_WR_DV_REG_BITS( VIU_MISC_CTRL1, (((dolby_vision_mask & 1) && dovi_setting_video_flag) ? 0 : 1), 16, 1); /* core1 */ - VSYNC_WR_MPEG_REG_BITS( + VSYNC_WR_DV_REG_BITS( VIU_MISC_CTRL1, ((dolby_vision_mask & 2) ? 0 : 1), 18, 1); /* core2 */ @@ -2538,7 +2921,7 @@ void enable_dolby_vision(int enable) /* bypass dither/PPS/SR/CM*/ /* bypass EO/OE*/ /* bypass vadj2/mtx/gainoff */ - VSYNC_WR_MPEG_REG_BITS( + VSYNC_WR_DV_REG_BITS( VPP_DOLBY_CTRL, 7, 0, 3); /* bypass all video effect */ video_effect_bypass(1); @@ -2546,11 +2929,11 @@ void enable_dolby_vision(int enable) /* before vadj1 */ /* 12 bit sign to unsign*/ /* before post blend */ - VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VPP_DAT_CONV_PARA0, 0x08000800); /* 12->10 before vadj2*/ /* 10->12 after gainoff */ - VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VPP_DAT_CONV_PARA1, 0x20002000); } else { /* bypass all video effect */ @@ -2559,19 +2942,19 @@ void enable_dolby_vision(int enable) video_effect_bypass(1); /* 12->10 before vadj1*/ /* 10->12 before post blend */ - VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VPP_DAT_CONV_PARA0, 0x20002000); /* 12->10 before vadj2*/ /* 10->12 after gainoff */ - VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VPP_DAT_CONV_PARA1, 0x20002000); } - VSYNC_WR_MPEG_REG(VPP_DUMMY_DATA1, + VSYNC_WR_DV_REG(VPP_DUMMY_DATA1, 0x80200); - if (is_meson_txlx_tvmode()) - VSYNC_WR_MPEG_REG(VPP_MATRIX_CTRL, 1); + if (is_meson_tvmode()) + VSYNC_WR_DV_REG(VPP_MATRIX_CTRL, 1); else - VSYNC_WR_MPEG_REG(VPP_MATRIX_CTRL, 0); + VSYNC_WR_DV_REG(VPP_MATRIX_CTRL, 0); #ifdef V2_4 if (((dolby_vision_mode == DOLBY_VISION_OUTPUT_MODE_IPT_TUNNEL) @@ -2582,17 +2965,17 @@ void enable_dolby_vision(int enable) u32 *reg = (u32 *)&dovi_setting.dm_reg3; /* input u12 -0x800 to s12 */ - VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VPP_DAT_CONV_PARA1, 0x8000800); /* bypass vadj */ - VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VPP_VADJ_CTRL, 0); /* bypass gainoff */ - VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VPP_GAINOFF_CTRL0, 0); /* enable wm tp vks*/ /* bypass gainoff to vks */ - VSYNC_WR_MPEG_REG_BITS( + VSYNC_WR_DV_REG_BITS( VPP_DOLBY_CTRL, 1, 1, 2); enable_rgb_to_yuv_matrix_for_dvll( 1, ®[18], 12); @@ -2603,48 +2986,78 @@ void enable_dolby_vision(int enable) dolby_vision_ll_policy; #endif pr_dolby_dbg("Dolby Vision STB cores turn on\n"); - } else if (is_meson_g12()) { + } else if (is_meson_g12() || is_meson_tm2_stbmode()) { if (dolby_vision_mask & 4) - VSYNC_WR_MPEG_REG_BITS(VPP_DOLBY_CTRL, + VSYNC_WR_DV_REG_BITS(VPP_DOLBY_CTRL, 1, 3, 1); /* core3 enable */ else - VSYNC_WR_MPEG_REG_BITS(VPP_DOLBY_CTRL, + VSYNC_WR_DV_REG_BITS(VPP_DOLBY_CTRL, 0, 3, 1); /* bypass core3 */ - VSYNC_WR_MPEG_REG(VPP_WRAP_OSD1_MATRIX_EN_CTRL, + VSYNC_WR_DV_REG(VPP_WRAP_OSD1_MATRIX_EN_CTRL, 0x0); - VSYNC_WR_MPEG_REG(VPP_WRAP_OSD2_MATRIX_EN_CTRL, + VSYNC_WR_DV_REG(VPP_WRAP_OSD2_MATRIX_EN_CTRL, 0x0); - VSYNC_WR_MPEG_REG(VPP_WRAP_OSD3_MATRIX_EN_CTRL, + VSYNC_WR_DV_REG(VPP_WRAP_OSD3_MATRIX_EN_CTRL, 0x0); if (dolby_vision_mask & 2) - VSYNC_WR_MPEG_REG_BITS( + VSYNC_WR_DV_REG_BITS( DOLBY_PATH_CTRL, 0, 2, 1);/*core2 enable*/ else - VSYNC_WR_MPEG_REG_BITS( + VSYNC_WR_DV_REG_BITS( DOLBY_PATH_CTRL, 1, 2, 1);/*core2 bypass*/ - if ((dolby_vision_mask & 1) - && dovi_setting_video_flag) { - VSYNC_WR_MPEG_REG_BITS( - DOLBY_PATH_CTRL, - 0, - 0, 1); /* core1 */ - dolby_vision_core1_on = true; - } else { - VSYNC_WR_MPEG_REG_BITS( - DOLBY_PATH_CTRL, - 1, - 0, 1); /* core1 */ - dolby_vision_core1_on = false; + if (is_meson_g12()) { + if ((dolby_vision_mask & 1) + && dovi_setting_video_flag) { + VSYNC_WR_DV_REG_BITS( + DOLBY_PATH_CTRL, + 0, + 0, 1); /* core1 */ + dolby_vision_core1_on = true; + } else { + VSYNC_WR_DV_REG_BITS( + DOLBY_PATH_CTRL, + 1, + 0, 1); /* core1 */ + dolby_vision_core1_on = false; + } + } else if (is_meson_tm2_stbmode()) { + if ((dolby_vision_mask & 1) + && dovi_setting_video_flag) { + VSYNC_WR_DV_REG_BITS( + DOLBY_PATH_CTRL, + 0, 8, 2); + VSYNC_WR_DV_REG_BITS( + DOLBY_PATH_CTRL, + 0, 10, 2); + VSYNC_WR_DV_REG_BITS( + DOLBY_PATH_CTRL, + 0, 17, 1); + VSYNC_WR_DV_REG_BITS( + DOLBY_PATH_CTRL, + 0, 21, 1); + VSYNC_WR_DV_REG_BITS( + DOLBY_PATH_CTRL, + 0, 24, 2); + VSYNC_WR_DV_REG_BITS( + DOLBY_PATH_CTRL, + 0, 0, 2); /* core1 */ + dolby_vision_core1_on = true; + } else { + VSYNC_WR_DV_REG_BITS( + DOLBY_PATH_CTRL, + 3, 0, 2); /* core1 */ + dolby_vision_core1_on = false; + } } if (dolby_vision_flags & FLAG_CERTIFICAION) { /* bypass dither/PPS/SR/CM*/ /* bypass EO/OE*/ /* bypass vadj2/mtx/gainoff */ - VSYNC_WR_MPEG_REG_BITS( + VSYNC_WR_DV_REG_BITS( VPP_DOLBY_CTRL, 7, 0, 3); /* bypass all video effect */ video_effect_bypass(1); @@ -2652,11 +3065,11 @@ void enable_dolby_vision(int enable) /* before vadj1 */ /* 12 bit sign to unsign*/ /* before post blend */ - VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VPP_DAT_CONV_PARA0, 0x08000800); /* 12->10 before vadj2*/ /* 10->12 after gainoff */ - VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VPP_DAT_CONV_PARA1, 0x20002000); } else { /* bypass all video effect */ @@ -2665,15 +3078,15 @@ void enable_dolby_vision(int enable) video_effect_bypass(1); /* 12->10 before vadj1*/ /* 10->12 before post blend */ - VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VPP_DAT_CONV_PARA0, 0x20002000); /* 12->10 before vadj2*/ /* 10->12 after gainoff */ - VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VPP_DAT_CONV_PARA1, 0x20002000); } - VSYNC_WR_MPEG_REG(VPP_MATRIX_CTRL, 0); - VSYNC_WR_MPEG_REG(VPP_DUMMY_DATA1, + VSYNC_WR_DV_REG(VPP_MATRIX_CTRL, 0); + VSYNC_WR_DV_REG(VPP_DUMMY_DATA1, 0x80200); #ifdef V2_4 if (((dolby_vision_mode == @@ -2685,17 +3098,17 @@ void enable_dolby_vision(int enable) u32 *reg = (u32 *)&dovi_setting.dm_reg3; /* input u12 -0x800 to s12 */ - VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VPP_DAT_CONV_PARA1, 0x8000800); /* bypass vadj */ - VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VPP_VADJ_CTRL, 0); /* bypass gainoff */ - VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VPP_GAINOFF_CTRL0, 0); /* enable wm tp vks*/ /* bypass gainoff to vks */ - VSYNC_WR_MPEG_REG_BITS( + VSYNC_WR_DV_REG_BITS( VPP_DOLBY_CTRL, 1, 1, 2); enable_rgb_to_yuv_matrix_for_dvll( 1, ®[18], @@ -2709,7 +3122,7 @@ void enable_dolby_vision(int enable) #endif pr_dolby_dbg("Dolby Vision G12a turn on\n"); } else { - VSYNC_WR_MPEG_REG(VPP_DOLBY_CTRL, + VSYNC_WR_DV_REG(VPP_DOLBY_CTRL, /* cm_datx4_mode */ (0x0<<21) | /* reg_front_cti_bit_mode */ @@ -2729,7 +3142,7 @@ void enable_dolby_vision(int enable) (0x3<<8) | /* vpp_uns2s_mode 7:0 */ 0x1f); - VSYNC_WR_MPEG_REG_BITS( + VSYNC_WR_DV_REG_BITS( VIU_MISC_CTRL1, /* 23-20 ext mode */ (0 << 2) | @@ -2743,13 +3156,13 @@ void enable_dolby_vision(int enable) 18, 6); if ((dolby_vision_mask & 1) && dovi_setting_video_flag) { - VSYNC_WR_MPEG_REG_BITS( + VSYNC_WR_DV_REG_BITS( VIU_MISC_CTRL1, 0, 16, 1); /* core1 */ dolby_vision_core1_on = true; } else { - VSYNC_WR_MPEG_REG_BITS( + VSYNC_WR_DV_REG_BITS( VIU_MISC_CTRL1, 1, 16, 1); /* core1 */ @@ -2759,8 +3172,8 @@ void enable_dolby_vision(int enable) if ((dolby_vision_flags & FLAG_BYPASS_VPP) || (dolby_vision_flags & FLAG_CERTIFICAION)) video_effect_bypass(1); - VSYNC_WR_MPEG_REG(VPP_MATRIX_CTRL, 0); - VSYNC_WR_MPEG_REG(VPP_DUMMY_DATA1, 0x20000000); + VSYNC_WR_DV_REG(VPP_MATRIX_CTRL, 0); + VSYNC_WR_DV_REG(VPP_DUMMY_DATA1, 0x20000000); /* disable osd effect and shadow mode */ osd_path_enable(0); #ifdef V2_4 @@ -2772,7 +3185,7 @@ void enable_dolby_vision(int enable) dovi_setting.dovi_ll_enable) { u32 *reg = (u32 *)&dovi_setting.dm_reg3; - VSYNC_WR_MPEG_REG_BITS( + VSYNC_WR_DV_REG_BITS( VPP_DOLBY_CTRL, 3, 6, 2); /* post matrix */ enable_rgb_to_yuv_matrix_for_dvll( @@ -2789,7 +3202,7 @@ void enable_dolby_vision(int enable) if (!dolby_vision_core1_on && (dolby_vision_mask & 1) && dovi_setting_video_flag) { - VSYNC_WR_MPEG_REG_BITS( + VSYNC_WR_DV_REG_BITS( VIU_MISC_CTRL1, 0, 16, 1); /* core1 */ @@ -2797,7 +3210,7 @@ void enable_dolby_vision(int enable) } else if (dolby_vision_core1_on && (!(dolby_vision_mask & 1) || !dovi_setting_video_flag)){ - VSYNC_WR_MPEG_REG_BITS( + VSYNC_WR_DV_REG_BITS( VIU_MISC_CTRL1, 1, 16, 1); /* core1 */ @@ -2811,17 +3224,20 @@ void enable_dolby_vision(int enable) vsync_count = 0; } else { if (dolby_vision_on) { - if (is_meson_txlx_tvmode() && !force_stb_mode) { - VSYNC_WR_MPEG_REG_BITS( + if (is_meson_tvmode() && !force_stb_mode) { + VSYNC_WR_DV_REG_BITS( VIU_MISC_CTRL1, /* vd2 connect to vpp */ (1 << 1) | /* 16 core1 bl bypass */ (1 << 0), 16, 2); + if (is_meson_tm2_tvmode()) + VSYNC_WR_DV_REG_BITS( + DOLBY_PATH_CTRL, 3, 0, 2); #ifdef V1_5 - if (p_funcs) /* destroy ctx */ - p_funcs->tv_control_path( + if (p_funcs_tv) /* destroy ctx */ + p_funcs_tv->tv_control_path( FORMAT_INVALID, 0, NULL, 0, NULL, 0, @@ -2835,18 +3251,18 @@ void enable_dolby_vision(int enable) pr_dolby_dbg("Dolby Vision TV core turn off\n"); } else if (is_meson_txlx_stbmode() || force_stb_mode) { - VSYNC_WR_MPEG_REG_BITS( + VSYNC_WR_DV_REG_BITS( VIU_MISC_CTRL1, (1 << 2) | /* core2 bypass */ (1 << 1) | /* vd2 connect to vpp */ (1 << 0), /* core1 bl bypass */ 16, 3); - VSYNC_WR_MPEG_REG_BITS(VPP_DOLBY_CTRL, + VSYNC_WR_DV_REG_BITS(VPP_DOLBY_CTRL, 0, 3, 1); /* core3 disable */ osd_bypass(0); #ifdef V2_4 - if (p_funcs) /* destroy ctx */ - p_funcs->control_path( + if (p_funcs_stb) /* destroy ctx */ + p_funcs_stb->control_path( FORMAT_INVALID, 0, comp_buf[currentId], 0, md_buf[currentId], 0, @@ -2862,24 +3278,24 @@ void enable_dolby_vision(int enable) stb_core2_const_flag = false; memset(&dovi_setting, 0, sizeof(dovi_setting)); pr_dolby_dbg("Dolby Vision STB cores turn off\n"); - } else if (is_meson_g12()) { - VSYNC_WR_MPEG_REG(VPP_WRAP_OSD1_MATRIX_EN_CTRL, + } else if (is_meson_g12() || is_meson_tm2_stbmode()) { + VSYNC_WR_DV_REG(VPP_WRAP_OSD1_MATRIX_EN_CTRL, 0x1); - VSYNC_WR_MPEG_REG(VPP_WRAP_OSD2_MATRIX_EN_CTRL, + VSYNC_WR_DV_REG(VPP_WRAP_OSD2_MATRIX_EN_CTRL, 0x1); - VSYNC_WR_MPEG_REG(VPP_WRAP_OSD3_MATRIX_EN_CTRL, + VSYNC_WR_DV_REG(VPP_WRAP_OSD3_MATRIX_EN_CTRL, 0x1); - VSYNC_WR_MPEG_REG_BITS( + VSYNC_WR_DV_REG_BITS( DOLBY_PATH_CTRL, (1 << 2) | /* core2 bypass */ (1 << 1) | /* vd2 connect to vpp */ (1 << 0), /* core1 bl bypass */ 0, 3); - VSYNC_WR_MPEG_REG_BITS(VPP_DOLBY_CTRL, + VSYNC_WR_DV_REG_BITS(VPP_DOLBY_CTRL, 0, 3, 1); /* core3 disable */ #ifdef V2_4 - if (p_funcs) /* destroy ctx */ - p_funcs->control_path( + if (p_funcs_stb) /* destroy ctx */ + p_funcs_stb->control_path( FORMAT_INVALID, 0, comp_buf[currentId], 0, md_buf[currentId], 0, @@ -2896,20 +3312,20 @@ void enable_dolby_vision(int enable) memset(&dovi_setting, 0, sizeof(dovi_setting)); pr_dolby_dbg("Dolby Vision G12a turn off\n"); } else { - VSYNC_WR_MPEG_REG_BITS( + VSYNC_WR_DV_REG_BITS( VIU_MISC_CTRL1, (1 << 2) | /* core2 bypass */ (1 << 1) | /* vd2 connect to vpp */ (1 << 0), /* core1 bl bypass */ 16, 3); - VSYNC_WR_MPEG_REG_BITS(VPP_DOLBY_CTRL, + VSYNC_WR_DV_REG_BITS(VPP_DOLBY_CTRL, 0, 16, 1); /* core3 disable */ /* enable osd effect and*/ /* use default shadow mode */ osd_path_enable(1); #ifdef V2_4 - if (p_funcs) /* destroy ctx */ - p_funcs->control_path( + if (p_funcs_stb) /* destroy ctx */ + p_funcs_stb->control_path( FORMAT_INVALID, 0, comp_buf[currentId], 0, md_buf[currentId], 0, @@ -2926,56 +3342,55 @@ void enable_dolby_vision(int enable) memset(&dovi_setting, 0, sizeof(dovi_setting)); pr_dolby_dbg("Dolby Vision turn off\n"); } - VSYNC_WR_MPEG_REG(VIU_SW_RESET, 3 << 9); - VSYNC_WR_MPEG_REG(VIU_SW_RESET, 0); + VSYNC_WR_DV_REG(VIU_SW_RESET, 3 << 9); + VSYNC_WR_DV_REG(VIU_SW_RESET, 0); if (is_meson_txlx()) { - VSYNC_WR_MPEG_REG(VPP_DAT_CONV_PARA0, + VSYNC_WR_DV_REG(VPP_DAT_CONV_PARA0, vpp_data_conv_para0_backup); - VSYNC_WR_MPEG_REG(VPP_DAT_CONV_PARA1, + VSYNC_WR_DV_REG(VPP_DAT_CONV_PARA1, vpp_data_conv_para1_backup); - VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( DOLBY_TV_CLKGATE_CTRL, 0x2414); - VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( DOLBY_CORE2A_CLKGATE_CTRL, 0x4); - VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( DOLBY_CORE3_CLKGATE_CTRL, 0x414); - VSYNC_WR_MPEG_REG(DOLBY_TV_AXI2DMA_CTRL0, + VSYNC_WR_DV_REG(DOLBY_TV_AXI2DMA_CTRL0, 0x01000042); } - if (is_meson_gxm() || - is_meson_g12()) { - VSYNC_WR_MPEG_REG( + if (is_meson_box() || is_meson_tm2_stbmode()) { + VSYNC_WR_DV_REG( DOLBY_CORE1_CLKGATE_CTRL, 0x55555555); - VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( DOLBY_CORE2A_CLKGATE_CTRL, 0x55555555); - VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( DOLBY_CORE3_CLKGATE_CTRL, 0x55555555); } - VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VPP_VD1_CLIP_MISC0, (0x3ff << 20) | (0x3ff << 10) | 0x3ff); - VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VPP_VD1_CLIP_MISC1, 0); video_effect_bypass(0); - VSYNC_WR_MPEG_REG(VPP_DOLBY_CTRL, + VSYNC_WR_DV_REG(VPP_DOLBY_CTRL, dolby_ctrl_backup); /* always vd2 to vpp and bypass core 1 */ viu_misc_ctrl_backup |= - (VSYNC_RD_MPEG_REG(VIU_MISC_CTRL1) & 2); - VSYNC_WR_MPEG_REG(VIU_MISC_CTRL1, + (VSYNC_RD_DV_REG(VIU_MISC_CTRL1) & 2); + VSYNC_WR_DV_REG(VIU_MISC_CTRL1, viu_misc_ctrl_backup | (3 << 16)); - VSYNC_WR_MPEG_REG(VPP_MATRIX_CTRL, + VSYNC_WR_DV_REG(VPP_MATRIX_CTRL, vpp_matrix_backup); - VSYNC_WR_MPEG_REG(VPP_DUMMY_DATA1, + VSYNC_WR_DV_REG(VPP_DUMMY_DATA1, vpp_dummy1_backup); } frame_count = 0; @@ -3136,10 +3551,12 @@ static void dump_struct(void *structure, int struct_length, "/data/tmp/tmp", frame_nr-1); fp = filp_open(fn, O_RDWR|O_CREAT, 0666); if (fp == NULL) - pr_info("Error open file for writing %s\n", fn); - vfs_write(fp, structure, struct_length, &pos); - vfs_fsync(fp, 0); - filp_close(fp, NULL); + pr_info("Error open file for writing NULL\n"); + else { + vfs_write(fp, structure, struct_length, &pos); + vfs_fsync(fp, 0); + filp_close(fp, NULL); + } set_fs(old_fs); } @@ -3194,17 +3611,17 @@ static void dump_setting( for (i = DOLBY_CORE1_CLKGATE_CTRL; i <= DOLBY_CORE1_DMA_PORT; i++) pr_info("[0x%4x] = 0x%x\n", - i, READ_VPP_REG(i)); + i, READ_VPP_DV_REG(i)); pr_info("core1 real reg\n"); for (i = DOLBY_CORE1_REG_START; i <= DOLBY_CORE1_REG_START + 5; i++) pr_info("[0x%4x] = 0x%x\n", - i, READ_VPP_REG(i)); + i, READ_VPP_DV_REG(i)); pr_info("core1 composer real reg\n"); for (i = 0; i < 173 ; i++) pr_info("%08x\n", - READ_VPP_REG( + READ_VPP_DV_REG( DOLBY_CORE1_REG_START + 50 + i)); } else if (is_meson_txlx()) { @@ -3212,13 +3629,13 @@ static void dump_setting( for (i = DOLBY_TV_SWAP_CTRL0; i <= DOLBY_TV_STATUS1; i++) pr_info("[0x%4x] = 0x%x\n", - i, READ_VPP_REG(i)); + i, READ_VPP_DV_REG(i)); pr_info("core1 real reg\n"); for (i = DOLBY_TV_REG_START; i <= DOLBY_CORE1_REG_START + 5; i++) pr_info("[0x%4x] = 0x%x\n", - i, READ_VPP_REG(i)); + i, READ_VPP_DV_REG(i)); } } @@ -3260,12 +3677,12 @@ static void dump_setting( for (i = DOLBY_CORE2A_CLKGATE_CTRL; i <= DOLBY_CORE2A_DMA_PORT; i++) pr_info("[0x%4x] = 0x%x\n", - i, READ_VPP_REG(i)); + i, READ_VPP_DV_REG(i)); pr_info("core2 real reg\n"); for (i = DOLBY_CORE2A_REG_START; i <= DOLBY_CORE2A_REG_START + 5; i++) pr_info("[0x%4x] = 0x%x\n", - i, READ_VPP_REG(i)); + i, READ_VPP_DV_REG(i)); } if ((debug_flag & 0x20) && dump_enable && !is_graphics_output_off()) { @@ -3306,12 +3723,12 @@ static void dump_setting( for (i = DOLBY_CORE3_CLKGATE_CTRL; i <= DOLBY_CORE3_OUTPUT_CSC_CRC; i++) pr_info("[0x%4x] = 0x%x\n", - i, READ_VPP_REG(i)); + i, READ_VPP_DV_REG(i)); pr_info("core3 real reg\n"); for (i = DOLBY_CORE3_REG_START; i <= DOLBY_CORE3_REG_START + 67; i++) pr_info("[0x%4x] = 0x%x\n", - i, READ_VPP_REG(i)); + i, READ_VPP_DV_REG(i)); } if ((debug_flag & 0x40) && dump_enable @@ -3327,9 +3744,9 @@ static void dump_setting( void dolby_vision_dump_setting(int debug_flag) { pr_dolby_dbg("\n====== setting for frame %d ======\n", frame_count); - if (is_meson_txlx_tvmode() && !force_stb_mode) - dump_tv_setting((struct tv_dovi_setting_s *)tv_dovi_setting, - frame_count, debug_flag); + if (is_meson_tvmode() && !force_stb_mode) + dump_tv_setting(tv_dovi_setting, + frame_count, debug_flag); else dump_setting(&new_dovi_setting, frame_count, debug_flag); pr_dolby_dbg("=== setting for frame %d dumped ===\n\n", frame_count); @@ -3370,10 +3787,10 @@ static int dolby_vision_policy_process( const struct vinfo_s *vinfo; int mode_change = 0; - if ((!dolby_vision_enable) || (!p_funcs)) + if ((!dolby_vision_enable) || ((!p_funcs_stb) && (!p_funcs_tv))) return mode_change; - if (is_meson_txlx_tvmode() && !force_stb_mode) { + if (is_meson_tvmode() && !force_stb_mode) { if (dolby_vision_policy == DOLBY_VISION_FORCE_OUTPUT_MODE) { if (*mode == DOLBY_VISION_OUTPUT_MODE_BYPASS) { if (dolby_vision_mode != @@ -3512,8 +3929,9 @@ static int dolby_vision_policy_process( *mode = DOLBY_VISION_OUTPUT_MODE_BYPASS; mode_change = 1; } - } else if (is_meson_g12a_cpu() || is_meson_g12b_cpu()) { - /*g12 has a hardware bug. Therefore, dv cores + } else if ((is_meson_g12b_cpu() && is_meson_rev_a()) || + is_meson_g12a_cpu()) { + /*g12 verA has a hardware bug.Therefore,dv cores *must keep working even if under sdr mode */ if (dolby_vision_mode != @@ -3603,7 +4021,7 @@ bool is_dovi_frame(struct vframe_s *vf) req.dv_enhance_exist = 0; if ((vf->source_type == VFRAME_SOURCE_TYPE_HDMI) - && is_meson_txlx_tvmode() && !force_stb_mode) { + && is_meson_tvmode() && !force_stb_mode) { vf_notify_provider_by_name("dv_vdin", VFRAME_EVENT_RECEIVER_GET_AUX_DATA, (void *)&req); @@ -3699,7 +4117,7 @@ struct vframe_s *dolby_vision_vf_peek_el(struct vframe_s *vf) { int i; - if (dolby_vision_flags && p_funcs) { + if (dolby_vision_flags && (p_funcs_stb || p_funcs_tv)) { for (i = 0; i < 16; i++) { if (dv_vf[i][0] == vf) { if (dv_vf[i][1] @@ -3811,27 +4229,49 @@ static int parse_sei_and_meta( meta_buf[i+7]); } - if (!p_funcs) - return -1; + if (tv_mode) { + if (!p_funcs_tv) + return -1; + } else { + if (!p_funcs_stb) + return -1; + } /* prepare metadata parser */ spin_lock_irqsave(&dovi_lock, flags); parser_ready = 0; if (metadata_parser == NULL) { - metadata_parser = - p_funcs->metadata_parser_init( + if (is_meson_tvmode()) { + metadata_parser = + p_funcs_tv->metadata_parser_init( dolby_vision_flags & FLAG_CHANGE_SEQ_HEAD ? 1 : 0); - p_funcs->metadata_parser_reset(1); + p_funcs_tv->metadata_parser_reset(1); + } else { + metadata_parser = + p_funcs_stb->metadata_parser_init( + dolby_vision_flags + & FLAG_CHANGE_SEQ_HEAD + ? 1 : 0); + p_funcs_stb->metadata_parser_reset(1); + } if (metadata_parser != NULL) { parser_ready = 1; if (debug_dolby & 1) pr_dolby_dbg("metadata parser init OK\n"); } } else { - if (p_funcs->metadata_parser_reset( - metadata_parser_reset_flag) == 0) - metadata_parser_reset_flag = 0; + if (is_meson_tvmode()) { + if (p_funcs_tv->metadata_parser_reset( + metadata_parser_reset_flag + ) == 0) + metadata_parser_reset_flag = 0; + } else { + if (p_funcs_stb->metadata_parser_reset( + metadata_parser_reset_flag + ) == 0) + metadata_parser_reset_flag = 0; + } parser_ready = 1; } if (!parser_ready) { @@ -3845,13 +4285,22 @@ static int parse_sei_and_meta( } md_size = comp_size = 0; - rpu_ret = p_funcs->metadata_parser_process( - meta_buf, size + 2, - comp_buf[nextId] + *total_comp_size, - &comp_size, - md_buf[nextId] + *total_md_size, - &md_size, - true); + if (is_meson_tvmode()) + rpu_ret = p_funcs_tv->metadata_parser_process( + meta_buf, size + 2, + comp_buf[nextId] + *total_comp_size, + &comp_size, + md_buf[nextId] + *total_md_size, + &md_size, + true); + else + rpu_ret = p_funcs_stb->metadata_parser_process( + meta_buf, size + 2, + comp_buf[nextId] + *total_comp_size, + &comp_size, + md_buf[nextId] + *total_md_size, + &md_size, + true); if (rpu_ret < 0) { pr_dolby_error( "meta(%d), pts(%lld) -> metadata parser process fail\n", @@ -4468,10 +4917,10 @@ static uint32_t null_vf_cnt; static bool video_off_handled; static int is_video_output_off(struct vframe_s *vf) { - if ((READ_VPP_REG(VPP_MISC) & (1<<10)) == 0) { + if ((READ_VPP_DV_REG(VPP_MISC) & (1<<10)) == 0) { /*Not reset frame0/1 clipping*/ /*when core off to avoid green garbage*/ - if (is_meson_txlx_tvmode() && (vf == NULL) && + if (is_meson_tvmode() && (vf == NULL) && (dolby_vision_on_count <= dolby_vision_run_mode_delay)) return 0; if (vf == NULL) @@ -4514,7 +4963,7 @@ static void calculate_panel_max_pq( max_lin = (max_lin / 100) * 100 + 500; max_pq = L2PQ_500_4000[(max_lin - 500) / 100]; } - pr_info("panel max lumin changed from %d(%d) to %d(%d)\n", + pr_dolby_dbg("panel max lumin changed from %d(%d) to %d(%d)\n", tv_max_lin, tv_max_pq, max_lin, max_pq); tv_max_lin = max_lin; tv_max_pq = max_pq; @@ -4572,6 +5021,10 @@ int dolby_vision_parse_metadata( u32 graphic_min = 50; /* 0.0001 */ u32 graphic_max = 100; /* 1 */ int ret_flags = 0; + int ret = -1; + + memset(&req, 0, (sizeof(struct provider_aux_req_s))); + memset(&el_req, 0, (sizeof(struct provider_aux_req_s))); if (!dolby_vision_enable) return -1; @@ -4584,7 +5037,7 @@ int dolby_vision_parse_metadata( vf->compHeight : vf->height; } - if (is_meson_txlx_tvmode() && !force_stb_mode && vf + if (is_meson_tvmode() && !force_stb_mode && vf && (vf->source_type == VFRAME_SOURCE_TYPE_HDMI)) { req.vf = vf; req.bot_flag = 0; @@ -4617,8 +5070,7 @@ int dolby_vision_parse_metadata( src_format = FORMAT_DOVI; } else { if (toggle_mode == 2) - src_format = ((struct tv_dovi_setting_s *) - tv_dovi_setting)->src_format; + src_format = tv_dovi_setting->src_format; if (vf->type & VIDTYPE_VIU_422) src_chroma_format = 1; p_mdc = &vf->prop.master_display_colour; @@ -4708,9 +5160,8 @@ int dolby_vision_parse_metadata( } } else if (is_dolby_vision_stb_mode()) src_format = dovi_setting.src_format; - else if (is_meson_txlx_tvmode()) - src_format = ((struct tv_dovi_setting_s *) - tv_dovi_setting)->src_format; + else if (is_meson_tvmode()) + src_format = tv_dovi_setting->src_format; if ((src_format != FORMAT_DOVI) && is_hdr10_frame(vf)) { @@ -4833,8 +5284,7 @@ int dolby_vision_parse_metadata( if (is_dolby_vision_stb_mode()) el_flag = dovi_setting.el_flag; else - el_flag = ((struct tv_dovi_setting_s *) - tv_dovi_setting)->el_flag; + el_flag = tv_dovi_setting->el_flag; meta_flag_bl = 0; } if ((src_format == FORMAT_DOVI) @@ -4860,8 +5310,10 @@ int dolby_vision_parse_metadata( if ((src_format != FORMAT_DOVI) && metadata_parser && !bypass_release) { - if (p_funcs) - p_funcs->metadata_parser_release(); + if (p_funcs_stb) + p_funcs_stb->metadata_parser_release(); + if (p_funcs_tv) + p_funcs_tv->metadata_parser_release(); metadata_parser = NULL; } @@ -4890,13 +5342,27 @@ int dolby_vision_parse_metadata( return -1; } - if (!p_funcs) - return -1; + if (tv_mode) { + if (!p_funcs_tv) + return -1; + } else { + if (!p_funcs_stb) + return -1; + } /* TV core */ - if (is_meson_txlx_tvmode() && !force_stb_mode) { + if (is_meson_tvmode() && !force_stb_mode) { + if (src_format != tv_dovi_setting->src_format) + pq_config_set_flag = false; if (!pq_config_set_flag) { - memcpy(&(((struct pq_config_s *) + if ((dolby_vision_flags & FLAG_FORCE_DOVI_LL) + || (req.low_latency == 1)) + memcpy(&(((struct pq_config_s *) + pq_config_fake)->target_display_config), + &def_tgt_display_cfg_ll, + sizeof(def_tgt_display_cfg_ll)); + else + memcpy(&(((struct pq_config_s *) pq_config_fake)->target_display_config), &def_tgt_display_cfg, sizeof(def_tgt_display_cfg)); @@ -4906,10 +5372,8 @@ int dolby_vision_parse_metadata( vinfo, &(((struct pq_config_s *) pq_config_fake)->target_display_config)); - ((struct tv_dovi_setting_s *) - tv_dovi_setting)->video_width = w << 16; - ((struct tv_dovi_setting_s *) - tv_dovi_setting)->video_height = h << 16; + tv_dovi_setting->video_width = w << 16; + tv_dovi_setting->video_height = h << 16; ((struct pq_config_s *) pq_config_fake)->target_display_config.tuningMode = dolby_vision_tunning_mode; @@ -4933,10 +5397,9 @@ int dolby_vision_parse_metadata( ->target_display_config.tuningMode |= TUNINGMODE_EXTLEVEL4_DISABLE; - if (src_format != ((struct tv_dovi_setting_s *) - tv_dovi_setting)->src_format) { - if (p_funcs->tv_control_path) - p_funcs->tv_control_path( + if (src_format != tv_dovi_setting->src_format) { + if (p_funcs_tv && (p_funcs_tv->tv_control_path)) + p_funcs_tv->tv_control_path( FORMAT_INVALID, 0, NULL, 0, NULL, 0, @@ -4948,9 +5411,9 @@ int dolby_vision_parse_metadata( NULL); } #endif - if (!p_funcs->tv_control_path) + if ((!p_funcs_tv) || (!p_funcs_tv->tv_control_path)) return -1; - flag = p_funcs->tv_control_path( + flag = p_funcs_tv->tv_control_path( src_format, input_mode, comp_buf[currentId], total_comp_size, md_buf[currentId], total_md_size, @@ -4965,48 +5428,33 @@ int dolby_vision_parse_metadata( if (flag >= 0) { if (input_mode == INPUT_MODE_HDMI) { if (h > 1080) - ((struct tv_dovi_setting_s *) - tv_dovi_setting) - ->core1_reg_lut[1] = + tv_dovi_setting->core1_reg_lut[1] = 0x0000000100000043; else - ((struct tv_dovi_setting_s *) - tv_dovi_setting) - ->core1_reg_lut[1] = + tv_dovi_setting->core1_reg_lut[1] = 0x0000000100000042; } else { if (src_format == FORMAT_HDR10) - ((struct tv_dovi_setting_s *) - tv_dovi_setting) - ->core1_reg_lut[1] = + tv_dovi_setting->core1_reg_lut[1] = 0x000000010000404c; else if (el_halfsize_flag) - ((struct tv_dovi_setting_s *) - tv_dovi_setting) - ->core1_reg_lut[1] = + tv_dovi_setting->core1_reg_lut[1] = 0x000000010000004c; else - ((struct tv_dovi_setting_s *) - tv_dovi_setting) - ->core1_reg_lut[1] = + tv_dovi_setting->core1_reg_lut[1] = 0x0000000100000044; } /* enable CRC */ if (dolby_vision_flags & FLAG_CERTIFICAION) - ((struct tv_dovi_setting_s *) - tv_dovi_setting)->core1_reg_lut[3] = + tv_dovi_setting->core1_reg_lut[3] = 0x000000ea00000001; - ((struct tv_dovi_setting_s *) - tv_dovi_setting)->src_format = src_format; - ((struct tv_dovi_setting_s *) - tv_dovi_setting)->el_flag = el_flag; - ((struct tv_dovi_setting_s *)tv_dovi_setting) + tv_dovi_setting->src_format = src_format; + tv_dovi_setting->el_flag = el_flag; + tv_dovi_setting ->el_halfsize_flag = el_halfsize_flag; - ((struct tv_dovi_setting_s *) - tv_dovi_setting)->video_width = w; - ((struct tv_dovi_setting_s *) - tv_dovi_setting)->video_height = h; - ((struct tv_dovi_setting_s *)tv_dovi_setting) + tv_dovi_setting->video_width = w; + tv_dovi_setting->video_height = h; + tv_dovi_setting ->input_mode = input_mode; tv_dovi_setting_change_flag = true; dovi_setting_video_flag = video_frame; @@ -5027,19 +5475,16 @@ int dolby_vision_parse_metadata( flag, total_md_size); } - dump_tv_setting( - (struct tv_dovi_setting_s *)tv_dovi_setting, + dump_tv_setting(tv_dovi_setting, frame_count, debug_dolby); el_mode = el_flag; - return 0; /* setting updated */ + ret = 0; /* setting updated */ } else { - ((struct tv_dovi_setting_s *) - tv_dovi_setting)->video_width = 0; - ((struct tv_dovi_setting_s *) - tv_dovi_setting)->video_height = 0; + tv_dovi_setting->video_width = 0; + tv_dovi_setting->video_height = 0; pr_dolby_error("tv_control_path() failed\n"); } - return -1; + return ret; } /* STB core */ @@ -5125,7 +5570,7 @@ int dolby_vision_parse_metadata( || (dst_format != dovi_setting.dst_format) || ((!(dolby_vision_flags & FLAG_CERTIFICAION)) && (frame_count == 0))) - p_funcs->control_path( + p_funcs_stb->control_path( FORMAT_INVALID, 0, comp_buf[currentId], 0, md_buf[currentId], 0, @@ -5281,10 +5726,14 @@ int dolby_vision_parse_metadata( #endif new_dovi_setting.video_width = w << 16; new_dovi_setting.video_height = h << 16; - flag = p_funcs->control_path( + flag = p_funcs_stb->control_path( src_format, dst_format, - comp_buf[currentId], total_comp_size, - md_buf[currentId], total_md_size, + comp_buf[currentId], + ((src_format == FORMAT_DOVI) + || (src_format == FORMAT_DOVI_LL)) ? total_comp_size : 0, + md_buf[currentId], + ((src_format == FORMAT_DOVI) + || (src_format == FORMAT_DOVI_LL)) ? total_md_size : 0, pri_mode, src_bdp, 0, SIG_RANGE_SMPTE, /* bit/chroma/range */ graphic_min, @@ -5368,19 +5817,17 @@ int dolby_vision_wait_metadata(struct vframe_s *vf) if (dolby_vision_flags & FLAG_SINGLE_STEP) /* wait fake el for "step" */ return 1; - else - dolby_vision_flags |= FLAG_SINGLE_STEP; + + dolby_vision_flags |= FLAG_SINGLE_STEP; } if (dolby_vision_flags & FLAG_CERTIFICAION) { bool ott_mode = true; - if (is_meson_txlx_tvmode() + if (is_meson_tvmode() && !force_stb_mode) - ott_mode = - (((struct tv_dovi_setting_s *) - tv_dovi_setting)->input_mode != - INPUT_MODE_HDMI); + ott_mode = tv_dovi_setting->input_mode != + INPUT_MODE_HDMI; if ((setting_update_count > crc_count) && (ott_mode == true)) return 1; @@ -5480,7 +5927,7 @@ int dolby_vision_wait_metadata(struct vframe_s *vf) } /* don't use run mode when sdr -> dv and vd1 not disable */ if (dolby_vision_wait_init && - (READ_VPP_REG(VPP_MISC) & (1<<10))) + (READ_VPP_DV_REG(VPP_MISC) & (1<<10))) dolby_vision_on_count = dolby_vision_run_mode_delay + 1; } @@ -5544,14 +5991,14 @@ static void bypass_pps_path(u8 pps_state) if (is_meson_txlx_package_962E() || force_stb_mode) { if (pps_state == 2) { - VSYNC_WR_MPEG_REG_BITS( + VSYNC_WR_DV_REG_BITS( VPP_DOLBY_CTRL, 1, 0, 1); - VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VPP_DAT_CONV_PARA0, 0x08000800); } else if (pps_state == 1) { - VSYNC_WR_MPEG_REG_BITS( + VSYNC_WR_DV_REG_BITS( VPP_DOLBY_CTRL, 0, 0, 1); - VSYNC_WR_MPEG_REG( + VSYNC_WR_DV_REG( VPP_DAT_CONV_PARA0, 0x20002000); } } @@ -5573,10 +6020,14 @@ int dolby_vision_process(struct vframe_s *vf, u32 display_size, bool reset_flag = false; bool force_set = false; - if (!is_meson_gxm() && !is_meson_txlx() - && !is_meson_g12()) + if (!is_meson_box() && !is_meson_txlx() && !is_meson_tm2()) return -1; + if ((dolby_vision_enable == 1) && (tv_mode == 1)) { + amdolby_vision_wakeup_queue(); + pr_dolby_dbg("wake up dv status queue\n"); + } + if (dolby_vision_flags & FLAG_CERTIFICAION) { if (vf) { h_size = (vf->type & VIDTYPE_COMPRESS) ? @@ -5604,20 +6055,18 @@ int dolby_vision_process(struct vframe_s *vf, u32 display_size, & FLAG_FRAME_DELAY_MASK; bool ott_mode = true; - if (is_meson_txlx_tvmode() + if (is_meson_tvmode() && !force_stb_mode) ott_mode = - (((struct tv_dovi_setting_s *) - tv_dovi_setting)->input_mode != + (tv_dovi_setting->input_mode != INPUT_MODE_HDMI); if ((is_meson_txlx_stbmode() - || is_meson_gxm() - || is_meson_g12() + || is_meson_box() || force_stb_mode) && (setting_update_count == 1) && (crc_read_delay == 1)) { /* work around to enable crc for frame 0 */ - VSYNC_WR_MPEG_REG(0x36fb, 1); + VSYNC_WR_DV_REG(0x36fb, 1); crc_read_delay++; } else { crc_read_delay++; @@ -5648,10 +6097,8 @@ int dolby_vision_process(struct vframe_s *vf, u32 display_size, } #ifdef V2_4 - if (is_meson_txlx_stbmode() - || is_meson_gxm() - || is_meson_g12() - || force_stb_mode) { + if (is_meson_txlx_stbmode() || is_meson_box() + || is_meson_tm2_stbmode() || force_stb_mode) { if (last_dolby_vision_ll_policy != dolby_vision_ll_policy) { /* handle ll mode policy change */ @@ -5659,15 +6106,17 @@ int dolby_vision_process(struct vframe_s *vf, u32 display_size, } } #endif + if (!vf) { if (dolby_vision_flags & FLAG_TOGGLE_FRAME) dolby_vision_parse_metadata( NULL, 1, false); } + if (dolby_vision_mode == DOLBY_VISION_OUTPUT_MODE_BYPASS) { if (vinfo && sink_support_dolby_vision(vinfo)) dolby_vision_set_toggle_flag(1); - if (!is_meson_txlx_tvmode() || force_stb_mode) { + if (!is_meson_tvmode() || force_stb_mode) { if (vinfo && vinfo->vout_device && (!vinfo->vout_device->dv_info) && (vsync_count < FLAG_VSYNC_CNT)) { @@ -5678,7 +6127,7 @@ int dolby_vision_process(struct vframe_s *vf, u32 display_size, if (dolby_vision_status != BYPASS_PROCESS) { enable_dolby_vision(0); if (vinfo && - !is_meson_txlx_tvmode() && + !is_meson_tvmode() && !force_stb_mode) send_hdmi_pkt(FORMAT_SDR, vinfo); if (dolby_vision_flags & FLAG_TOGGLE_FRAME) @@ -5691,7 +6140,7 @@ int dolby_vision_process(struct vframe_s *vf, u32 display_size, || (dolby_vision_flags & FLAG_BYPASS_VPP)) video_effect_bypass(1); - if (!p_funcs) { + if (!p_funcs_stb && !p_funcs_tv) { dolby_vision_flags &= ~FLAG_TOGGLE_FRAME; tv_dovi_setting_change_flag = false; new_dovi_setting.video_width = 0; @@ -5710,7 +6159,7 @@ int dolby_vision_process(struct vframe_s *vf, u32 display_size, (dolby_vision_reset & 1) && (!dolby_vision_core1_on) && (dolby_vision_on_count == 0); - if (is_meson_txlx_tvmode() && !force_stb_mode) { + if (is_meson_tvmode() && !force_stb_mode) { if (tv_dovi_setting_change_flag) { if (vf && (vf->type & VIDTYPE_VIU_422)) src_chroma_format = 2; @@ -5721,22 +6170,17 @@ int dolby_vision_process(struct vframe_s *vf, u32 display_size, & FLAG_CERTIFICAION)) reset_flag = true; tv_dolby_core1_set( - ((struct tv_dovi_setting_s *) - tv_dovi_setting)->core1_reg_lut, + tv_dovi_setting->core1_reg_lut, h_size, v_size, dovi_setting_video_flag, /* BL enable */ dovi_setting_video_flag - && (((struct tv_dovi_setting_s *) - tv_dovi_setting)->el_flag), /* EL en */ - ((struct tv_dovi_setting_s *) - tv_dovi_setting)->el_halfsize_flag, + && (tv_dovi_setting->el_flag), + tv_dovi_setting->el_halfsize_flag, src_chroma_format, - ((struct tv_dovi_setting_s *) - tv_dovi_setting)->input_mode == + tv_dovi_setting->input_mode == INPUT_MODE_HDMI, - ((struct tv_dovi_setting_s *) - tv_dovi_setting)->src_format == + tv_dovi_setting->src_format == FORMAT_HDR10, reset_flag ); @@ -5751,8 +6195,7 @@ int dolby_vision_process(struct vframe_s *vf, u32 display_size, core1_disp_hsize = h_size; core1_disp_vsize = v_size; update_dolby_vision_status( - ((struct tv_dovi_setting_s *) - tv_dovi_setting)->src_format); + tv_dovi_setting->src_format); } } else { if ((new_dovi_setting.video_width & 0xffff) @@ -5821,29 +6264,24 @@ int dolby_vision_process(struct vframe_s *vf, u32 display_size, dolby_vision_on_count, reset_flag); } - } else if (is_meson_txlx_tvmode()) { + } else if (is_meson_tvmode()) { if ((dolby_vision_on_count <= dolby_vision_run_mode_delay) || force_set) { if (force_set) reset_flag = true; tv_dolby_core1_set( - ((struct tv_dovi_setting_s *) - tv_dovi_setting)->core1_reg_lut, + tv_dovi_setting->core1_reg_lut, h_size, v_size, dovi_setting_video_flag, /* BL enable */ dovi_setting_video_flag && - ((struct tv_dovi_setting_s *) - tv_dovi_setting)->el_flag, /*ELenable*/ - ((struct tv_dovi_setting_s *) - tv_dovi_setting)->el_halfsize_flag, + tv_dovi_setting->el_flag, /*ELenable*/ + tv_dovi_setting->el_halfsize_flag, src_chroma_format, - ((struct tv_dovi_setting_s *) - tv_dovi_setting)->input_mode == + tv_dovi_setting->input_mode == INPUT_MODE_HDMI, - ((struct tv_dovi_setting_s *) - tv_dovi_setting)->src_format == + tv_dovi_setting->src_format == FORMAT_HDR10, reset_flag); core1_disp_hsize = h_size; @@ -5854,8 +6292,7 @@ int dolby_vision_process(struct vframe_s *vf, u32 display_size, dolby_vision_on_count, reset_flag); } - } else if (is_meson_gxm() || - is_meson_g12()) { + } else if (is_meson_box() || is_meson_tm2_stbmode()) { if ((dolby_vision_on_count <= dolby_vision_run_mode_delay) || force_set) { @@ -5913,8 +6350,7 @@ EXPORT_SYMBOL(dolby_vision_set_toggle_flag); void set_dolby_vision_mode(int mode) { - if ((is_meson_gxm() || is_meson_txlx() || - is_meson_g12()) + if ((is_meson_box() || is_meson_txlx() || is_meson_tm2()) && dolby_vision_enable && (dolby_vision_request_mode == 0xff)) { if (dolby_vision_policy_process( @@ -5947,9 +6383,9 @@ EXPORT_SYMBOL(is_dolby_vision_enable); bool is_dolby_vision_stb_mode(void) { return force_stb_mode || - is_meson_txlx_stbmode() || - is_meson_gxm() || - is_meson_g12(); + is_meson_txlx_stbmode() || + is_meson_tm2_stbmode() || + is_meson_box(); } EXPORT_SYMBOL(is_dolby_vision_stb_mode); @@ -5959,58 +6395,63 @@ int register_dv_functions(const struct dolby_vision_func_s *func) unsigned int reg_clk; unsigned int reg_value; struct pq_config_s *pq_config; - struct tv_dovi_setting_s *dovi_setting; const struct vinfo_s *vinfo = get_current_vinfo(); - if (!p_funcs && func) { - pr_info("*** register_dv_functions. version %s ***\n", - func->version_info); + if ((!p_funcs_stb || !p_funcs_tv) && func) { + if (func->control_path && !p_funcs_stb) { + pr_info("*** register_dv_stb_functions. version %s ***\n", + func->version_info); + p_funcs_stb = func; + } else if (func->tv_control_path && !p_funcs_tv) { + pr_info("*** register_dv_tv_functions. version %s ***\n", + func->version_info); + p_funcs_tv = func; + } else + return ret; ret = 0; /* get efuse flag*/ - reg_clk = READ_VPP_REG(DOLBY_TV_CLKGATE_CTRL); - WRITE_VPP_REG(DOLBY_TV_CLKGATE_CTRL, 0x2800); - reg_value = READ_VPP_REG(DOLBY_TV_REG_START + 1); - if (is_meson_txlx_tvmode() - || is_meson_txlx_stbmode()) { + + if (is_meson_txlx() || is_meson_tm2()) { + reg_clk = READ_VPP_DV_REG(DOLBY_TV_CLKGATE_CTRL); + WRITE_VPP_DV_REG(DOLBY_TV_CLKGATE_CTRL, 0x2800); + reg_value = READ_VPP_DV_REG(DOLBY_TV_REG_START + 1); if ((reg_value & 0x400) == 0) efuse_mode = 0; else efuse_mode = 1; + WRITE_VPP_DV_REG(DOLBY_TV_CLKGATE_CTRL, reg_clk); } else { + reg_value = READ_VPP_DV_REG(DOLBY_CORE1_REG_START + 1); if ((reg_value & 0x100) == 0) efuse_mode = 0; else efuse_mode = 1; } - WRITE_VPP_REG(DOLBY_TV_CLKGATE_CTRL, reg_clk); - pr_dolby_dbg - ("efuse_mode=%d reg_value = 0x%x\n", - efuse_mode, - reg_value); + pr_dolby_dbg("efuse_mode=%d reg_value = 0x%x\n", + efuse_mode, reg_value); /*stb core doesn't need run mode*/ /*TV core need run mode and the value is 2*/ - if (is_meson_gxm() || is_meson_g12() || - is_meson_txlx_stbmode() || force_stb_mode) + if (is_meson_box() || is_meson_txlx_stbmode() + || is_meson_tm2_stbmode() || force_stb_mode) dolby_vision_run_mode_delay = 0; else dolby_vision_run_mode_delay = RUN_MODE_DELAY; - pq_config = vmalloc(sizeof(struct pq_config_s)); - if (pq_config == NULL) { - pr_info("[amdolby_vision] vmalloc failed for pq_config_s error!\n"); - return -1; + if (is_meson_txlx() || is_meson_tm2()) { + pq_config = vmalloc(sizeof(struct pq_config_s)); + if (!pq_config) + return -ENOMEM; + pq_config_fake = (struct pq_config_s *)pq_config; + + tv_dovi_setting = + vmalloc(sizeof(struct tv_dovi_setting_s)); + if (!tv_dovi_setting) + return -ENOMEM; } - pq_config_fake = (struct pq_config_s *)pq_config; - dovi_setting = vmalloc(sizeof(struct tv_dovi_setting_s)); - if (dovi_setting == NULL) { - pr_info("[amdolby_vision] vmalloc failed for tv_dovi_setting_s error!\n"); - return -1; - } - tv_dovi_setting = (struct tv_dovi_setting_s *)dovi_setting; /* adjust core2 setting to work around fixing with 1080p24hz */ if (is_meson_txlx()) g_vpotch = 0x20; - else if (is_meson_g12()) { + else if (is_meson_g12() || is_meson_tm2_stbmode()) { if (vinfo) { if ((vinfo->width < 1280) && (vinfo->height < 720) && @@ -6022,7 +6463,6 @@ int register_dv_functions(const struct dolby_vision_func_s *func) g_vpotch = 0x8; } else g_vpotch = 0x8; - p_funcs = func; } return ret; } @@ -6043,7 +6483,7 @@ int unregister_dv_functions(void) comp_buf[i] = NULL; } } - if (p_funcs) { + if (p_funcs_stb || p_funcs_tv) { pr_info("*** unregister_dv_functions ***\n"); if (pq_config_fake) { vfree(pq_config_fake); @@ -6053,7 +6493,8 @@ int unregister_dv_functions(void) vfree(tv_dovi_setting); tv_dovi_setting = NULL; } - p_funcs = NULL; + p_funcs_stb = NULL; + p_funcs_tv = NULL; ret = 0; } return ret; @@ -6097,13 +6538,13 @@ void tv_dolby_vision_insert_crc(bool print) crc_count++; return; } - if (is_meson_txlx_tvmode() + if (is_meson_tvmode() && !force_stb_mode) { - crc_enable = (READ_VPP_REG(0x33e7) == 0xb); - crc = READ_VPP_REG(0x33ef); + crc_enable = (READ_VPP_DV_REG(0x33e7) == 0xb); + crc = READ_VPP_DV_REG(0x33ef); } else { - crc_enable = true; /* (READ_VPP_REG(0x36fb) & 1); */ - crc = READ_VPP_REG(0x36fd); + crc_enable = true; /* (READ_VPP_DV_REG(0x36fb) & 1); */ + crc = READ_VPP_DV_REG(0x36fd); } if ((crc == 0) || (crc_enable == false) || (!crc_output_buf)) { crc_bypass_count++; @@ -6144,10 +6585,10 @@ void tv_dolby_vision_dma_table_modify(u32 tbl_id, uint64_t value) void tv_dolby_vision_efuse_info(void) { - if (p_funcs != NULL) { + if (p_funcs_tv != NULL) { pr_info("\n dv efuse info:\n"); pr_info("efuse_mode:%d, version: %s\n", - efuse_mode, p_funcs->version_info); + efuse_mode, p_funcs_tv->version_info); } else { pr_info("\n p_funcs is NULL\n"); pr_info("efuse_mode:%d\n", efuse_mode); @@ -6260,6 +6701,7 @@ static const struct file_operations amdolby_vision_fops = { #ifdef CONFIG_COMPAT .compat_ioctl = amdolby_vision_compat_ioctl, #endif + .poll = amdolby_vision_poll, }; static void parse_param_amdolby_vision(char *buf_orig, char **parm) @@ -6394,7 +6836,7 @@ static struct class_attribute amdolby_vision_class_attrs[] = { __ATTR(debug, 0644, amdolby_vision_debug_show, amdolby_vision_debug_store), __ATTR(dv_mode, 0644, - amdolby_vision_dv_mode_show, amdolby_vision_dv_mode_store), + amdolby_vision_dv_mode_show, amdolby_vision_dv_mode_store), __ATTR_NULL }; @@ -6410,6 +6852,11 @@ static struct dv_device_data_s dolby_vision_g12 = { .cpu_id = _CPU_MAJOR_ID_G12, }; +static struct dv_device_data_s dolby_vision_tm2 = { + .cpu_id = _CPU_MAJOR_ID_TM2, +}; + + static const struct of_device_id amlogic_dolby_vision_match[] = { { .compatible = "amlogic, dolby_vision_gxm", @@ -6427,6 +6874,14 @@ static const struct of_device_id amlogic_dolby_vision_match[] = { .compatible = "amlogic, dolby_vision_g12b", .data = &dolby_vision_g12, }, + { + .compatible = "amlogic, dolby_vision_sm1", + .data = &dolby_vision_g12, + }, + { + .compatible = "amlogic, dolby_vision_tm2", + .data = &dolby_vision_tm2, + }, {}, }; @@ -6493,6 +6948,7 @@ static int amdolby_vision_probe(struct platform_device *pdev) } dolby_vision_init_receiver(pdev); + init_waitqueue_head(&devp->dv_queue); pr_info("%s: ok\n", __func__); return 0; diff --git a/drivers/amlogic/media/enhancement/amdolby_vision/amdolby_vision.h b/drivers/amlogic/media/enhancement/amdolby_vision/amdolby_vision.h index 7aee3dffd2ed..456a1ff8bd83 100644 --- a/drivers/amlogic/media/enhancement/amdolby_vision/amdolby_vision.h +++ b/drivers/amlogic/media/enhancement/amdolby_vision/amdolby_vision.h @@ -20,7 +20,7 @@ #define V1_5 #define V2_4 /* driver version */ -#define DRIVER_VER "20181009" +#define DRIVER_VER "20181220" #include @@ -526,6 +526,7 @@ enum cpuID_e { _CPU_MAJOR_ID_GXM, _CPU_MAJOR_ID_TXLX, _CPU_MAJOR_ID_G12, + _CPU_MAJOR_ID_TM2, _CPU_MAJOR_ID_UNKNOWN, }; @@ -624,14 +625,14 @@ struct dolby_vision_func_s { extern int register_dv_functions(const struct dolby_vision_func_s *func); extern int unregister_dv_functions(void); #ifndef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA -#define VSYNC_WR_MPEG_REG(adr, val) WRITE_VPP_REG(adr, val) -#define VSYNC_RD_MPEG_REG(adr) READ_VPP_REG(adr) -#define VSYNC_WR_MPEG_REG_BITS(adr, val, start, len) \ +#define _VSYNC_WR_MPEG_REG(adr, val) WRITE_VPP_REG(adr, val) +#define _VSYNC_RD_MPEG_REG(adr) READ_VPP_REG(adr) +#define _VSYNC_WR_MPEG_REG_BITS(adr, val, start, len) \ WRITE_VPP_REG_BITS(adr, val, start, len) #else -extern int VSYNC_WR_MPEG_REG_BITS(u32 adr, u32 val, u32 start, u32 len); -extern u32 VSYNC_RD_MPEG_REG(u32 adr); -extern int VSYNC_WR_MPEG_REG(u32 adr, u32 val); +extern int _VSYNC_WR_MPEG_REG_BITS(u32 adr, u32 val, u32 start, u32 len); +extern u32 _VSYNC_RD_MPEG_REG(u32 adr); +extern int _VSYNC_WR_MPEG_REG(u32 adr, u32 val); #endif #endif diff --git a/drivers/amlogic/media/enhancement/amprime_sl/Kconfig b/drivers/amlogic/media/enhancement/amprime_sl/Kconfig new file mode 100644 index 000000000000..10dc1798f776 --- /dev/null +++ b/drivers/amlogic/media/enhancement/amprime_sl/Kconfig @@ -0,0 +1,15 @@ +# +# AMLOGIC amprime_sl devices configuration +# + +comment "Amlogic amprime_sl Drivers" + +menu "Amlogic amprime_sl Driver" + +config AMLOGIC_MEDIA_ENHANCEMENT_PRIME_SL + bool "Amlogic amprime_sl driver" + default n + help + "Amlogic amprime_sl module init" + +endmenu diff --git a/drivers/amlogic/media/enhancement/amprime_sl/Makefile b/drivers/amlogic/media/enhancement/amprime_sl/Makefile new file mode 100644 index 000000000000..97fbaf30c14c --- /dev/null +++ b/drivers/amlogic/media/enhancement/amprime_sl/Makefile @@ -0,0 +1,7 @@ +# +# Makefile for amprime_sl +# + +obj-$(CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_PRIME_SL) += amprime_sl.o amprime_sl_hw.o + + diff --git a/drivers/amlogic/media/enhancement/amprime_sl/amprime_sl.c b/drivers/amlogic/media/enhancement/amprime_sl/amprime_sl.c new file mode 100644 index 000000000000..79ebfc71fce3 --- /dev/null +++ b/drivers/amlogic/media/enhancement/amprime_sl/amprime_sl.c @@ -0,0 +1,511 @@ +/* + * drivers/amlogic/media/enhancement/amprime_sl/amprime_sl.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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "amprime_sl.h" +#include +#include + +/*======================================*/ + +static const struct hdr_prime_sl_func_s *p_funcs; +struct prime_sl_device_data_s prime_sl_meson_dev; +#define AMPRIME_SL_NAME "amprime_sl" +#define AMPRIME_SL_CLASS_NAME "amprime_sl" + +struct amprime_sl_dev_s { + dev_t devt; + struct cdev cdev; + dev_t devno; + struct device *dev; + struct class *clsp; +}; +static struct amprime_sl_dev_s amprime_sl_dev; +static struct prime_t prime_sl_setting; + +static uint prime_sl_enable = DISABLE; +module_param(prime_sl_enable, uint, 0664); +MODULE_PARM_DESC(prime_sl_enable, "\n prime_sl_enable\n"); + +static uint prime_sl_display_Brightness = 150; +module_param(prime_sl_display_Brightness, uint, 0664); +MODULE_PARM_DESC(prime_sl_display_Brightness, "\n prime_sl_display_Brightness\n"); + +bool is_prime_sl_enable(void) +{ + return prime_sl_enable; +} +EXPORT_SYMBOL(is_prime_sl_enable); + +static int parse_para(char *p) +{ + int data; + + data = cpu_to_le32((unsigned int)(*p)); + *p += 4; + return data; +} + +static int prime_sl_parse_sei_and_meta(char *p, unsigned int size) +{ + unsigned int i; + struct sl_hdr_metadata *sl_hdr_metadata + = &prime_sl_setting.prime_metadata; + + if (size != sizeof(struct sl_hdr_metadata)) { + pr_info("error metadata size\n"); + return 0; + } + + sl_hdr_metadata->partID = parse_para(p); + sl_hdr_metadata->majorSpecVersionID = parse_para(p); + sl_hdr_metadata->minorSpecVersionID = parse_para(p); + sl_hdr_metadata->payloadMode = parse_para(p); + sl_hdr_metadata->hdrPicColourSpace = parse_para(p); + sl_hdr_metadata->hdrDisplayColourSpace = parse_para(p); + sl_hdr_metadata->hdrDisplayMaxLuminance = parse_para(p); + sl_hdr_metadata->hdrDisplayMinLuminance = parse_para(p); + sl_hdr_metadata->sdrPicColourSpace = parse_para(p); + sl_hdr_metadata->sdrDisplayColourSpace = parse_para(p); + sl_hdr_metadata->sdrDisplayMaxLuminance = parse_para(p); + sl_hdr_metadata->sdrDisplayMinLuminance = parse_para(p); + for (i = 0; i < 4; i++) + sl_hdr_metadata->matrixCoefficient[i] = parse_para(p); + for (i = 0; i < 2; i++) + sl_hdr_metadata->chromaToLumaInjection[i] = parse_para(p); + for (i = 0; i < 3; i++) + sl_hdr_metadata->kCoefficient[i] = parse_para(p); + if (!sl_hdr_metadata->payloadMode) { + sl_hdr_metadata->u.variables.tmInputSignalBlackLevelOffset + = parse_para(p); + sl_hdr_metadata->u.variables.tmInputSignalWhiteLevelOffset + = parse_para(p); + sl_hdr_metadata->u.variables.shadowGain = parse_para(p); + sl_hdr_metadata->u.variables.highlightGain = parse_para(p); + sl_hdr_metadata->u.variables.midToneWidthAdjFactor + = parse_para(p); + sl_hdr_metadata->u.variables.tmOutputFineTuningNumVal + = parse_para(p); + for (i = 0; i < sl_hdr_metadata-> + u.variables.tmOutputFineTuningNumVal; i++) { + sl_hdr_metadata->u.variables.tmOutputFineTuningX[i] + = parse_para(p); + sl_hdr_metadata->u.variables.tmOutputFineTuningX[i] + = parse_para(p); + } + sl_hdr_metadata->u.variables.saturationGainNumVal + = parse_para(p); + for (i = 0; i < sl_hdr_metadata-> + u.variables.saturationGainNumVal; i++) { + sl_hdr_metadata->u.variables.saturationGainX[i] + = parse_para(p); + sl_hdr_metadata->u.variables.saturationGainY[i] + = parse_para(p); + } + } else { + sl_hdr_metadata->u.tables.luminanceMappingNumVal + = parse_para(p); + for (i = 0; i < sl_hdr_metadata-> + u.tables.luminanceMappingNumVal; i++) { + sl_hdr_metadata->u.tables.luminanceMappingX[i] + = parse_para(p); + sl_hdr_metadata->u.tables.luminanceMappingY[i] + = parse_para(p); + } + sl_hdr_metadata->u.tables.colourCorrectionNumVal + = parse_para(p); + for (i = 0; i < sl_hdr_metadata-> + u.tables.colourCorrectionNumVal; i++) { + sl_hdr_metadata->u.tables.colourCorrectionX[i] + = parse_para(p); + sl_hdr_metadata->u.tables.colourCorrectionY[i] + = parse_para(p); + } + } + return 0; +} + +static void prime_sl_parser_metadata(struct vframe_s *vf) +{ + struct provider_aux_req_s req; + struct prime_cfg_t *Cfg = &prime_sl_setting.Cfg; + char *p; + unsigned int size = 0; + unsigned int type = 0; + + if (vf && (vf->source_type == VFRAME_SOURCE_TYPE_OTHERS)) { + req.vf = vf; + req.bot_flag = 0; + req.aux_buf = NULL; + req.aux_size = 0; + req.dv_enhance_exist = 0; + req.low_latency = 0; + + Cfg->width = (vf->type & VIDTYPE_COMPRESS) ? + vf->compWidth : vf->width; + Cfg->height = (vf->type & VIDTYPE_COMPRESS) ? + vf->compHeight : vf->height; + Cfg->bit_depth = vf->bitdepth; + Cfg->yuv_range = (vf->signal_type >> 25) & 0x1; + Cfg->display_Brightness = prime_sl_display_Brightness; + + vf_notify_provider_by_name("prime_sl_dec", + VFRAME_EVENT_RECEIVER_GET_AUX_DATA, + (void *)&req); + + if (req.aux_buf && req.aux_size) { + p = req.aux_buf; + while (p < req.aux_buf + + req.aux_size - 8) { + size = cpu_to_le32((unsigned int)(*p)); + p += 4; + type = cpu_to_le32((unsigned int)(*p)); + p += 4; + if (type == 0x04000000)/*need to double check*/ + prime_sl_parse_sei_and_meta(p, size); + p += size; + } + } + } +} + +void prime_sl_process(struct vframe_s *vf) +{ + prime_sl_parser_metadata(vf); + if (!p_funcs) + p_funcs->prime_metadata_parser_process(&prime_sl_setting); + prime_sl_set_reg(&prime_sl_setting.prime_sl); + prime_sl_close(); +} +EXPORT_SYMBOL(prime_sl_process); + +static void dbg_setting(struct prime_sl_t *prime_sl) +{ + unsigned int i; + + pr_info("%s\n", __func__); + pr_info("\t legacy_mode_en\t%d\n", prime_sl->legacy_mode_en); + pr_info("\t clip_en\t%d\n", prime_sl->clip_en); + pr_info("\t reg_gclk_ctrl\t%d\n", prime_sl->reg_gclk_ctrl); + pr_info("\t gclk_ctrl\t%d\n", prime_sl->gclk_ctrl); + pr_info("\t primesl_en\t%d\n", + prime_sl->primesl_en); + pr_info("\t inv_chroma_ratio\t%d\n", + prime_sl->inv_chroma_ratio); + pr_info("\t inv_y_ratio\t%d\n", prime_sl->inv_y_ratio); + pr_info("\t l_headroom\t%d\n", prime_sl->l_headroom); + pr_info("\t footroom\t%d\n", prime_sl->footroom); + pr_info("\t c_headroom\t%d\n", prime_sl->c_headroom); + pr_info("\t mub\t%d\n", + prime_sl->mub); + pr_info("\t mua\t%d\n", prime_sl->mua); + + for (i = 0; i < 7; i++) + pr_info("\t oct[%d]\t%d\n", i, prime_sl->oct[i]); + for (i = 0; i < 3; i++) + pr_info("\t d_lut_threshold[%d]\t%d\n", i, + prime_sl->d_lut_threshold[i]); + for (i = 0; i < 4; i++) + pr_info("\t d_lut_step[%d]\t%d\n", i, prime_sl->d_lut_step[i]); + for (i = 0; i < 9; i++) + pr_info("\t rgb2yuv[%d]\t%d\n", i, prime_sl->rgb2yuv[i]); + for (i = 0; i < 65; i++) + pr_info("\t lut_c[%d]\t%d\n", i, prime_sl->lut_c[i]); + for (i = 0; i < 65; i++) + pr_info("\t lut_p[%d]\t%d\n", i, prime_sl->lut_p[i]); + for (i = 0; i < 65; i++) + pr_info("\t lut_d[%d]\t%d\n", i, prime_sl->lut_d[i]); +} + +static void dbg_config(struct prime_cfg_t *Cfg) +{ + pr_info("%s\n", __func__); + + pr_info("\t width\t%d\n", Cfg->width); + pr_info("\t height\t%d\n", Cfg->height); + pr_info("\t bit_depth\t%d\n", Cfg->bit_depth); + pr_info("\t display_OETF\t%d\n", Cfg->display_OETF); + pr_info("\t display_Brightness\t%d\n", + Cfg->display_Brightness); + pr_info("\t yuv_range\t%d\n", Cfg->yuv_range); +} + +static void dbg_metadata(struct sl_hdr_metadata *pmetadata) +{ + pr_info("%s\n", __func__); + + pr_info("\t partID\t%d\n", pmetadata->partID); + pr_info("\t majorSpecVersionID\t%d\n", + pmetadata->majorSpecVersionID); + pr_info("\t minorSpecVersionID\t%d\n", + pmetadata->minorSpecVersionID); + pr_info("\t payloadMode\t%d\n", + pmetadata->payloadMode); + pr_info("\t hdrPicColourSpace\t%d\n", + pmetadata->hdrPicColourSpace); + pr_info("\t hdrDisplayColourSpace\t%d\n", + pmetadata->hdrDisplayColourSpace); + pr_info("\t hdrDisplayMaxLuminance\t%d\n", + pmetadata->hdrDisplayMaxLuminance); + + pr_info("\t hdrDisplayMinLuminance\t%d\n", + pmetadata->hdrDisplayMinLuminance); + pr_info("\t sdrPicColourSpace\t%d\n", + pmetadata->sdrPicColourSpace); + pr_info("\t sdrDisplayColourSpace\t%d\n", + pmetadata->sdrDisplayColourSpace); + pr_info("\t sdrDisplayMaxLuminance\t%d\n", + pmetadata->sdrDisplayMaxLuminance); + pr_info("\t sdrDisplayMinLuminance\t%d\n", + pmetadata->sdrDisplayMinLuminance); + +} + +static ssize_t amprime_sl_debug_store(struct class *cla, + struct class_attribute *attr, + const char *buf, size_t count) +{ + + if (!buf) + return count; + + if (!strcmp(buf, "metadata")) { + dbg_metadata(&prime_sl_setting.prime_metadata); + dbg_config(&prime_sl_setting.Cfg); + } else if (!strcmp(buf, "setting")) + dbg_setting(&prime_sl_setting.prime_sl); + else + pr_info("unsupport commands\n"); + return count; + +} + +static struct class_attribute amprime_sl_class_attrs[] = { + __ATTR(debug, 0644, NULL, amprime_sl_debug_store), + __ATTR_NULL +}; + + +int register_prime_functions(const struct hdr_prime_sl_func_s *func) +{ + int ret = -1; + + if (!p_funcs && func) { + pr_info("*** register_prime_functions. version %s ***\n", + func->version_info); + ret = 0; + p_funcs = func; + p_funcs->prime_api_init(); + } + return ret; +} +EXPORT_SYMBOL(register_prime_functions); + +int unregister_prime_functions(void) +{ + int ret = -1; + + if (p_funcs) { + pr_info("*** unregister_prime_functions ***\n"); + p_funcs->prime_api_exit(); + p_funcs = NULL; + ret = 0; + } + return ret; +} +EXPORT_SYMBOL(unregister_prime_functions); + +static struct prime_sl_device_data_s prime_sl_g12 = { + .cpu_id = _CPU_MAJOR_ID_G12, +}; + +static struct prime_sl_device_data_s prime_sl_tl1 = { + .cpu_id = _CPU_MAJOR_ID_TL1, +}; + +static const struct of_device_id amprime_sl_match[] = { + { + .compatible = "amlogic, prime_sl_g12", + .data = &prime_sl_g12, + }, + { + .compatible = "amlogic, prime_sl_tl1", + .data = &prime_sl_tl1, + }, + {}, +}; + +static int amprime_sl_probe(struct platform_device *pdev) +{ + int ret = 0; + unsigned int i = 0; + struct amprime_sl_dev_s *devp = &rime_sl_dev; + + pr_info("amprime_sl probe start & ver: %s\n", DRIVER_VER); + if (pdev->dev.of_node) { + const struct of_device_id *match; + struct prime_sl_device_data_s *prime_sl_meson; + struct device_node *of_node = pdev->dev.of_node; + + match = of_match_node(amprime_sl_match, of_node); + if (match) { + prime_sl_meson = + (struct prime_sl_device_data_s *)match->data; + if (prime_sl_meson) + memcpy(&rime_sl_dev, prime_sl_meson, + sizeof(struct prime_sl_device_data_s)); + else { + pr_err("%s data NOT match\n", __func__); + return -ENODEV; + } + } else { + pr_err("%s NOT match\n", __func__); + return -ENODEV; + } + + } + pr_info("\n cpu_id=%d\n", prime_sl_meson_dev.cpu_id); + memset(devp, 0, (sizeof(struct amprime_sl_dev_s))); + ret = alloc_chrdev_region(&devp->devno, 0, 1, AMPRIME_SL_NAME); + if (ret < 0) + goto fail_alloc_region; + devp->clsp = class_create(THIS_MODULE, + AMPRIME_SL_CLASS_NAME); + if (IS_ERR(devp->clsp)) { + ret = PTR_ERR(devp->clsp); + goto fail_create_class; + } + + for (i = 0; amprime_sl_class_attrs[i].attr.name; i++) { + if (class_create_file(devp->clsp, + &rime_sl_class_attrs[i]) < 0) + goto fail_class_create_file; + } +/* cdev_init(&devp->cdev, &rime_sl_fops); + * devp->cdev.owner = THIS_MODULE; + * ret = cdev_add(&devp->cdev, devp->devno, 1); + * if (ret) + * goto fail_add_cdev; + * + * devp->dev = device_create(devp->clsp, NULL, devp->devno, + * NULL, AMPRIME_SL_NAME); + * if (IS_ERR(devp->dev)) { + * ret = PTR_ERR(devp->dev); + * goto fail_create_device; + * } + */ + pr_info("%s: probe ok\n", __func__); + return 0; +/* + * + *fail_create_device: + * pr_info("[amprime_sl.] : amprime_sl device create error.\n"); + * cdev_del(&devp->cdev); + * + *fail_add_cdev: + * pr_info("[amprime_sl.] : amprime_sl add device error.\n"); + */ +fail_class_create_file: + pr_info("[amprime_sl.] : amprime_sl class create file error.\n"); + for (i = 0; amprime_sl_class_attrs[i].attr.name; i++) + class_remove_file(devp->clsp, + &rime_sl_class_attrs[i]); + class_destroy(devp->clsp); +fail_create_class: + pr_info("[amdolby_vision.] : amdolby_vision class create error.\n"); + unregister_chrdev_region(devp->devno, 1); +fail_alloc_region: + pr_info("[amprime_sl.] : amprime_sl alloc error.\n"); + pr_info("[amprime_sl.] : amprime_sl.\n"); + return ret; +} + +static int __exit amprime_sl_remove(struct platform_device *pdev) +{ + struct amprime_sl_dev_s *devp = &rime_sl_dev; + + device_destroy(devp->clsp, devp->devno); + cdev_del(&devp->cdev); + class_destroy(devp->clsp); + unregister_chrdev_region(devp->devno, 1); + pr_info("[ amprime_sl.] : amprime_sl.\n"); + return 0; +} + +static struct platform_driver amprime_sl_driver = { + .driver = { + .owner = THIS_MODULE, + .name = "amprime_sl", + .of_match_table = amprime_sl_match, + }, + .probe = amprime_sl_probe, + .remove = __exit_p(amprime_sl_remove), +}; + +static int __init amprime_sl_init(void) +{ + pr_info("prime_sl module init\n"); + if (platform_driver_register(&rime_sl_driver)) { + pr_info("failed to register amprime_sl module\n"); + return -ENODEV; + } + return 0; +} + +static void __exit amprime_sl_exit(void) +{ + pr_info("prime_sl module exit\n"); +} + +module_init(amprime_sl_init); +module_exit(amprime_sl_exit); + +MODULE_DESCRIPTION("Amlogic HDR Prime SL driver"); +MODULE_LICENSE("GPL"); + diff --git a/drivers/amlogic/media/enhancement/amprime_sl/amprime_sl.h b/drivers/amlogic/media/enhancement/amprime_sl/amprime_sl.h new file mode 100644 index 000000000000..8466482f730a --- /dev/null +++ b/drivers/amlogic/media/enhancement/amprime_sl/amprime_sl.h @@ -0,0 +1,391 @@ +/* + * drivers/amlogic/media/enhancement/amprime_sl/amprime_sl.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 __AMPRIME_SL_H__ +#define __AMPRIME_SL_H__ + +#define DRIVER_VER "20190307" + +#define ENABLE 1 +#define DISABLE 0 + +enum cpuID_e { + _CPU_MAJOR_ID_G12, + _CPU_MAJOR_ID_TL1, + _CPU_MAJOR_ID_UNKNOWN, +}; + +struct prime_sl_device_data_s { + enum cpuID_e cpu_id; +}; + + +#define PRIMESL_LUTC_ADDR_PORT (0x3980) +#define PRIMESL_LUTC_DATA_PORT (0x3981) +#define PRIMESL_LUTP_ADDR_PORT (0x3982) +#define PRIMESL_LUTP_DATA_PORT (0x3983) +#define PRIMESL_LUTD_ADDR_PORT (0x3984) +#define PRIMESL_LUTD_DATA_PORT (0x3985) +#define PRIMESL_CTRL0 (0x3990) +union PRIMESL_CTRL0_BITS { + unsigned int d32; + struct { + unsigned int primesl_en:1, + gclk_ctrl:2, + reg_gclk_ctrl:1, + inv_y_ratio:11, + reserved3:1, + inv_chroma_ratio:11, + reserved2:1, + clip_en:1, + legacy_mode_en:1, + reserved1:2; + } b; +}; +#define PRIMESL_CTRL1 (0x3991) +union PRIMESL_CTRL1_BITS { + unsigned int d32; + struct { + unsigned int footroom:10, + reserved2:6, + l_headroom:10, + reserved1:6; + } b; +}; +#define PRIMESL_CTRL2 (0x3992) +union PRIMESL_CTRL2_BITS { + unsigned int d32; + struct { + unsigned int c_headroom:10, + reserved1:22; + } b; +}; +#define PRIMESL_CTRL3 (0x3993) +union PRIMESL_CTRL3_BITS { + unsigned int d32; + struct { + unsigned int mua:14, + reserved2:2, + mub:14, + reserved1:2; + } b; +}; +#define PRIMESL_CTRL4 (0x3994) +union PRIMESL_CTRL4_BITS { + unsigned int d32; + struct { + unsigned int oct_7_0:10, + reserved2:6, + oct_7_1:10, + reserved1:6; + } b; +}; +#define PRIMESL_CTRL5 (0x3995) +union PRIMESL_CTRL5_BITS { + unsigned int d32; + struct { + unsigned int oct_7_2:10, + reserved2:6, + oct_7_3:10, + reserved1:6; + } b; +}; +#define PRIMESL_CTRL6 (0x3996) +union PRIMESL_CTRL6_BITS { + unsigned int d32; + struct { + unsigned int oct_7_4:10, + reserved2:6, + oct_7_5:10, + reserved1:6; + } b; +}; +#define PRIMESL_CTRL7 (0x3997) +union PRIMESL_CTRL7_BITS { + unsigned int d32; + struct { + unsigned int oct_7_6:10, + reserved1:22; + } b; +}; +#define PRIMESL_CTRL8 (0x3998) +union PRIMESL_CTRL8_BITS { + unsigned int d32; + struct { + unsigned int d_lut_threshold_3_0:13, + reserved2:3, + d_lut_threshold_3_1:13, + reserved1:3; + } b; +}; +#define PRIMESL_CTRL9 (0x3999) +union PRIMESL_CTRL9_BITS { + unsigned int d32; + struct { + unsigned int d_lut_threshold_3_2:13, + reserved1:19; + } b; +}; +#define PRIMESL_CTRL10 (0x399a) +union PRIMESL_CTRL10_BITS { + unsigned int d32; + struct { + unsigned int d_lut_step_4_0:4, + d_lut_step_4_1:4, + d_lut_step_4_2:4, + d_lut_step_4_3:4, + reserved1:16; + } b; +}; +#define PRIMESL_CTRL11 (0x399b) +union PRIMESL_CTRL11_BITS { + unsigned int d32; + struct { + unsigned int rgb2yuv_9_1:13, + reserved2:3, + rgb2yuv_9_0:13, + reserved1:3; + } b; +}; +#define PRIMESL_CTRL12 (0x399c) +union PRIMESL_CTRL12_BITS { + unsigned int d32; + struct { + unsigned int rgb2yuv_9_3:13, + reserved2:3, + rgb2yuv_9_2:13, + reserved1:3; + } b; +}; +#define PRIMESL_CTRL13 (0x399d) +union PRIMESL_CTRL13_BITS { + unsigned int d32; + struct { + unsigned int rgb2yuv_9_5:13, + reserved2:3, + rgb2yuv_9_4:13, + reserved1:3; + } b; +}; +#define PRIMESL_CTRL14 (0x399e) +union PRIMESL_CTRL14_BITS { + unsigned int d32; + struct { + unsigned int rgb2yuv_9_7:13, + reserved2:3, + rgb2yuv_9_6:13, + reserved1:3; + } b; +}; +#define PRIMESL_CTRL15 (0x399f) +union PRIMESL_CTRL15_BITS { + unsigned int d32; + struct { + unsigned int rgb2yuv_9_8:13, + reserved1:19; + } b; +}; +#define PRIME_PRIMESL_EN (0) +#define PRIME_GCLK_CTRL (1) +#define PRIME_REG_GCLK_CTRL (2) +#define PRIME_INV_Y_RATIO (3) +#define PRIME_INV_CHROMA_RATIO (4) +#define PRIME_CLIP_EN (5) +#define PRIME_LEGACY_MODE_EN (6) +#define PRIME_FOOTROOM (7) +#define PRIME_L_HEADROOM (8) +#define PRIME_C_HEADROOM (9) +#define PRIME_MUA (10) +#define PRIME_MUB (11) +#define PRIME_OCT_7_0 (12) +#define PRIME_OCT_7_1 (13) +#define PRIME_OCT_7_2 (14) +#define PRIME_OCT_7_3 (15) +#define PRIME_OCT_7_4 (16) +#define PRIME_OCT_7_5 (17) +#define PRIME_OCT_7_6 (18) +#define PRIME_D_LUT_THRESHOLD_3_0 (19) +#define PRIME_D_LUT_THRESHOLD_3_1 (20) +#define PRIME_D_LUT_THRESHOLD_3_2 (21) +#define PRIME_D_LUT_STEP_4_0 (22) +#define PRIME_D_LUT_STEP_4_1 (23) +#define PRIME_D_LUT_STEP_4_2 (24) +#define PRIME_D_LUT_STEP_4_3 (25) +#define PRIME_RGB2YUV_9_0 (26) +#define PRIME_RGB2YUV_9_1 (27) +#define PRIME_RGB2YUV_9_2 (28) +#define PRIME_RGB2YUV_9_3 (29) +#define PRIME_RGB2YUV_9_4 (30) +#define PRIME_RGB2YUV_9_5 (31) +#define PRIME_RGB2YUV_9_6 (32) +#define PRIME_RGB2YUV_9_7 (33) +#define PRIME_RGB2YUV_9_8 (34) + + +struct prime_sl_t { + unsigned int legacy_mode_en; + unsigned int clip_en; + unsigned int reg_gclk_ctrl; + unsigned int gclk_ctrl; + unsigned int primesl_en; + + unsigned int inv_chroma_ratio; + unsigned int inv_y_ratio; + unsigned int l_headroom; + unsigned int footroom; + unsigned int c_headroom; + unsigned int mub; + unsigned int mua; + int oct[7]; + unsigned int d_lut_threshold[3]; + unsigned int d_lut_step[4]; + int rgb2yuv[9]; + + uint16_t olut_c[65]; /*from */ + uint16_t olut_p[65]; + uint16_t olut_d[65]; + + unsigned int lut_c[65]; + unsigned int lut_p[65]; + unsigned int lut_d[65]; +}; + +struct sl_hdr_metadata_variables { + int tmInputSignalBlackLevelOffset; + int tmInputSignalWhiteLevelOffset; + int shadowGain; + int highlightGain; + int midToneWidthAdjFactor; + int tmOutputFineTuningNumVal; + int tmOutputFineTuningX[10]; + int tmOutputFineTuningY[10]; + int saturationGainNumVal; + int saturationGainX[6]; + int saturationGainY[6]; +}; + +struct sl_hdr_metadata_tables { + int luminanceMappingNumVal; + int luminanceMappingX[65]; + int luminanceMappingY[65]; + int colourCorrectionNumVal; + int colourCorrectionX[65]; + int colourCorrectionY[65]; +}; + +struct sl_hdr_metadata { + int partID; + int majorSpecVersionID; + int minorSpecVersionID; + int payloadMode; + int hdrPicColourSpace; + int hdrDisplayColourSpace; + int hdrDisplayMaxLuminance; + int hdrDisplayMinLuminance; + int sdrPicColourSpace; + int sdrDisplayColourSpace; + int sdrDisplayMaxLuminance; + int sdrDisplayMinLuminance; + int matrixCoefficient[4]; + int chromaToLumaInjection[2]; + int kCoefficient[3]; + union { + struct sl_hdr_metadata_variables variables; + struct sl_hdr_metadata_tables tables; + } u; +}; + +struct prime_cfg_t { + unsigned int width; /*use?*/ + unsigned int height; /*use?*/ + unsigned int bit_depth; /*use?*/ + int display_OETF; /**/ + int yuv_range; + int display_Brightness; +}; + +struct prime_t { + + int en_ic; /*0: ic not support prime sl; 1: ic support prime sl*/ + int en_top; /*top prime sl switch*/ + int en_pause; + int en_checkdata; + int en_count; + int en_count_tsk; + int en_set; + int en_close; + + int ok_count; + int ok_set; + + int isr_mode; + unsigned int vs_cnt; + unsigned int ver_hw; + unsigned int ver_fw; + + struct prime_cfg_t *pCfg; + struct sl_hdr_metadata *pmta; + struct prime_sl_t *pps; + + struct prime_cfg_t Cfg; + struct sl_hdr_metadata prime_metadata; + struct prime_sl_t prime_sl; + + /*test*/ + unsigned int dbg_nub; + unsigned int dbg_metachange; + struct timeval tv[4][2]; + +}; + +extern void prime_api_init(void); +extern void prime_api_exit(void); +extern void prime_api_isr_process(void); +extern void prime_api_cmd_process(unsigned char cmd, int para); +extern unsigned int prime_api_info_show(char *buf, unsigned int size); +extern int prime_api_store(const char *buf, unsigned int para); +extern int prime_metadata_parser_process(struct prime_t *prime_sl_setting); + +struct hdr_prime_sl_func_s { + const char *version_info; + void (*prime_api_init)(void); + void (*prime_api_exit)(void); + void (*prime_api_isr_process)(void); + void (*prime_api_cmd_process)(unsigned char cmd, int para); + unsigned int (*prime_api_info_show)(char *buf, unsigned int size); + int (*prime_api_store)(const char *buf, unsigned int para); + int (*prime_metadata_parser_process)(struct prime_t *prime_sl_setting); +}; + +extern int register_prime_functions(const struct hdr_prime_sl_func_s *func); +extern int unregister_prime_functions(void); + +#ifndef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA +#define _VSYNC_WR_MPEG_REG(adr, val) WRITE_VPP_REG(adr, val) +#define _VSYNC_RD_MPEG_REG(adr) READ_VPP_REG(adr) +#define _VSYNC_WR_MPEG_REG_BITS(adr, val, start, len) \ + WRITE_VPP_REG_BITS(adr, val, start, len) +#else +extern int _VSYNC_WR_MPEG_REG_BITS(u32 adr, u32 val, u32 start, u32 len); +extern u32 _VSYNC_RD_MPEG_REG(u32 adr); +extern int _VSYNC_WR_MPEG_REG(u32 adr, u32 val); +#endif +extern void prime_sl_set_reg(const struct prime_sl_t *pS); +extern void prime_sl_close(void); + + +#endif /*__REG_G12A_PRIME_H__*/ diff --git a/drivers/amlogic/media/enhancement/amprime_sl/amprime_sl_hw.c b/drivers/amlogic/media/enhancement/amprime_sl/amprime_sl_hw.c new file mode 100644 index 000000000000..1eace541ba9c --- /dev/null +++ b/drivers/amlogic/media/enhancement/amprime_sl/amprime_sl_hw.c @@ -0,0 +1,289 @@ +/* + * drivers/amlogic/media/enhancement/amprime_sl/amprime_sl_hw.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 + + +#include +#include /*gettimeofday*/ +#include /*gettimeofday*/ + +#include /*WRITE_VPP_REG*/ +#include "amprime_sl.h" + +/*======================================*/ +/*#define USE_TASKLET 1*/ + +static inline void wbits_PRIMESL_CTRL0( + unsigned int primesl_en, unsigned int gclk_ctrl, + unsigned int reg_gclk_ctrl, unsigned int inv_y_ratio, + unsigned int inv_chroma_ratio, unsigned int clip_en, + unsigned int legacy_mode_en) +{ + union PRIMESL_CTRL0_BITS v; + + v.b.primesl_en = primesl_en; + v.b.gclk_ctrl = gclk_ctrl; + v.b.reg_gclk_ctrl = reg_gclk_ctrl; + v.b.inv_y_ratio = inv_y_ratio; + v.b.inv_chroma_ratio = inv_chroma_ratio; + v.b.clip_en = clip_en; + v.b.legacy_mode_en = legacy_mode_en; + _VSYNC_WR_MPEG_REG(PRIMESL_CTRL0, v.d32); +} +static inline void wbits_PRIMESL_CTRL1(unsigned int footroom, + unsigned int l_headroom) +{ + union PRIMESL_CTRL1_BITS v; + + v.b.footroom = footroom; + v.b.l_headroom = l_headroom; + _VSYNC_WR_MPEG_REG(PRIMESL_CTRL1, v.d32); +} +static inline void wbits_PRIMESL_CTRL2(unsigned int c_headroom) +{ + union PRIMESL_CTRL2_BITS v; + + v.b.c_headroom = c_headroom; + _VSYNC_WR_MPEG_REG(PRIMESL_CTRL2, v.d32); +} +static inline void wbits_PRIMESL_CTRL3(unsigned int mua, + unsigned int mub) +{ + union PRIMESL_CTRL3_BITS v; + + v.b.mua = mua; + v.b.mub = mub; + _VSYNC_WR_MPEG_REG(PRIMESL_CTRL3, v.d32); +} +static inline void wbits_PRIMESL_CTRL4(unsigned int oct_7_0, + unsigned int oct_7_1) +{ + union PRIMESL_CTRL4_BITS v; + + v.b.oct_7_0 = oct_7_0; + v.b.oct_7_1 = oct_7_1; + _VSYNC_WR_MPEG_REG(PRIMESL_CTRL4, v.d32); +} +static inline void wbits_PRIMESL_CTRL5(unsigned int oct_7_2, + unsigned int oct_7_3) +{ + union PRIMESL_CTRL5_BITS v; + + v.b.oct_7_2 = oct_7_2; + v.b.oct_7_3 = oct_7_3; + _VSYNC_WR_MPEG_REG(PRIMESL_CTRL5, v.d32); +} +static inline void wbits_PRIMESL_CTRL6(unsigned int oct_7_4, + unsigned int oct_7_5) +{ + union PRIMESL_CTRL6_BITS v; + + v.b.oct_7_4 = oct_7_4; + v.b.oct_7_5 = oct_7_5; + _VSYNC_WR_MPEG_REG(PRIMESL_CTRL6, v.d32); +} +static inline void wbits_PRIMESL_CTRL7(unsigned int oct_7_6) +{ + union PRIMESL_CTRL7_BITS v; + + v.b.oct_7_6 = oct_7_6; + _VSYNC_WR_MPEG_REG(PRIMESL_CTRL7, v.d32); +} +static inline void wbits_PRIMESL_CTRL8(unsigned int d_lut_threshold_3_0, + unsigned int d_lut_threshold_3_1) +{ + union PRIMESL_CTRL8_BITS v; + + v.b.d_lut_threshold_3_0 = d_lut_threshold_3_0; + v.b.d_lut_threshold_3_1 = d_lut_threshold_3_1; + _VSYNC_WR_MPEG_REG(PRIMESL_CTRL8, v.d32); +} +static inline void wbits_PRIMESL_CTRL9(unsigned int d_lut_threshold_3_2) +{ + union PRIMESL_CTRL9_BITS v; + + v.b.d_lut_threshold_3_2 = d_lut_threshold_3_2; + _VSYNC_WR_MPEG_REG(PRIMESL_CTRL9, v.d32); +} +static inline void wbits_PRIMESL_CTRL10(unsigned int d_lut_step_4_0, + unsigned int d_lut_step_4_1, + unsigned int d_lut_step_4_2, + unsigned int d_lut_step_4_3) +{ + union PRIMESL_CTRL10_BITS v; + + v.b.d_lut_step_4_0 = d_lut_step_4_0; + v.b.d_lut_step_4_1 = d_lut_step_4_1; + v.b.d_lut_step_4_2 = d_lut_step_4_2; + v.b.d_lut_step_4_3 = d_lut_step_4_3; + _VSYNC_WR_MPEG_REG(PRIMESL_CTRL10, v.d32); +} +static inline void wbits_PRIMESL_CTRL11(unsigned int rgb2yuv_9_1, + unsigned int rgb2yuv_9_0) +{ + union PRIMESL_CTRL11_BITS v; + + v.b.rgb2yuv_9_1 = rgb2yuv_9_1; + v.b.rgb2yuv_9_0 = rgb2yuv_9_0; + _VSYNC_WR_MPEG_REG(PRIMESL_CTRL11, v.d32); +} +static inline void wbits_PRIMESL_CTRL12(unsigned int rgb2yuv_9_3, + unsigned int rgb2yuv_9_2) +{ + union PRIMESL_CTRL12_BITS v; + + v.b.rgb2yuv_9_3 = rgb2yuv_9_3; + v.b.rgb2yuv_9_2 = rgb2yuv_9_2; + _VSYNC_WR_MPEG_REG(PRIMESL_CTRL12, v.d32); +} +static inline void wbits_PRIMESL_CTRL13(unsigned int rgb2yuv_9_5, + unsigned int rgb2yuv_9_4) +{ + union PRIMESL_CTRL13_BITS v; + + v.b.rgb2yuv_9_5 = rgb2yuv_9_5; + v.b.rgb2yuv_9_4 = rgb2yuv_9_4; + _VSYNC_WR_MPEG_REG(PRIMESL_CTRL13, v.d32); +} +static inline void wbits_PRIMESL_CTRL14(unsigned int rgb2yuv_9_7, + unsigned int rgb2yuv_9_6) +{ + union PRIMESL_CTRL14_BITS v; + + v.b.rgb2yuv_9_7 = rgb2yuv_9_7; + v.b.rgb2yuv_9_6 = rgb2yuv_9_6; + _VSYNC_WR_MPEG_REG(PRIMESL_CTRL14, v.d32); +} +static inline void wbits_PRIMESL_CTRL15(unsigned int rgb2yuv_9_8) +{ + union PRIMESL_CTRL15_BITS v; + + v.b.rgb2yuv_9_8 = rgb2yuv_9_8; + _VSYNC_WR_MPEG_REG(PRIMESL_CTRL15, v.d32); +} + +#define NOT_USR_WR_T 1 + +void slctr_set_rgb2yuv(const int *pTab)/*9byte*/ +{ +#ifdef NOT_USR_WR_T + wbits_PRIMESL_CTRL11(pTab[1], pTab[0]); + wbits_PRIMESL_CTRL12(pTab[3], pTab[2]); + wbits_PRIMESL_CTRL13(pTab[5], pTab[4]); + wbits_PRIMESL_CTRL14(pTab[7], pTab[6]); + wbits_PRIMESL_CTRL15(pTab[8]); + +#else + int i; + + for (i = 0; i < 9; i++) + WR_T(PRIME_RGB2YUV_9_0+i, (unsigned int)pTab[i]); +#endif +} + +void slctr_set_lutstep(const unsigned int *pTab)/*4byte*/ +{ + +#ifdef NOT_USR_WR_T + wbits_PRIMESL_CTRL10(pTab[0], pTab[1], pTab[2], pTab[3]); + +#else + int i; + + for (i = 0; i < 4; i++) + WR_T(PRIME_D_LUT_STEP_4_0+i, pTab[i]); + +#endif +} +void slctr_set_lutthrd(const unsigned int *pTab)/*3byte*/ +{ + +#ifdef NOT_USR_WR_T + wbits_PRIMESL_CTRL8(pTab[0], pTab[1]); + wbits_PRIMESL_CTRL9(pTab[2]); +#else + int i; + + for (i = 0; i < 3; i++) + WR_T(PRIME_D_LUT_THRESHOLD_3_0+i, pTab[i]); + +#endif +} +void slctr_set_oct(const int *pTab)/*7byte*/ +{ + +#ifdef NOT_USR_WR_T + wbits_PRIMESL_CTRL4(pTab[0], pTab[1]); + wbits_PRIMESL_CTRL5(pTab[2], pTab[3]); + wbits_PRIMESL_CTRL6(pTab[4], pTab[5]); + wbits_PRIMESL_CTRL7(pTab[6]); +#else + int i; + + for (i = 0; i < 7; i++) + WR_T(PRIME_OCT_7_0+i, (unsigned int)pTab[i]); +#endif +} +void slctr_set_lut_c(const int *pTab)/*7byte*/ +{ + int i; + + _VSYNC_WR_MPEG_REG(PRIMESL_LUTC_ADDR_PORT, 0); + for (i = 0; i < 65; i++) + _VSYNC_WR_MPEG_REG(PRIMESL_LUTC_DATA_PORT, pTab[i]); +} + +void slctr_set_lut_p(const int *pTab)/*7byte*/ +{ + int i; + + _VSYNC_WR_MPEG_REG(PRIMESL_LUTP_ADDR_PORT, 0); + for (i = 0; i < 65; i++) + _VSYNC_WR_MPEG_REG(PRIMESL_LUTP_DATA_PORT, pTab[i]); +} + +void slctr_set_lut_d(const int *pTab)/*7byte*/ +{ + int i; + + _VSYNC_WR_MPEG_REG(PRIMESL_LUTD_ADDR_PORT, 0); + for (i = 0; i < 65; i++) + _VSYNC_WR_MPEG_REG(PRIMESL_LUTD_DATA_PORT, pTab[i]); +} + +void prime_sl_set_reg(const struct prime_sl_t *pS) +{ + wbits_PRIMESL_CTRL1(pS->footroom, pS->l_headroom); + wbits_PRIMESL_CTRL2(pS->c_headroom); + wbits_PRIMESL_CTRL3(pS->mua, pS->mub); + slctr_set_oct(&pS->oct[0]); + slctr_set_lutthrd(&pS->d_lut_threshold[0]); + slctr_set_lutstep(&pS->d_lut_step[0]); + slctr_set_rgb2yuv(&pS->rgb2yuv[0]); + slctr_set_lut_c(&pS->lut_c[0]); + slctr_set_lut_p(&pS->lut_p[0]); + slctr_set_lut_d(&pS->lut_d[0]); + + wbits_PRIMESL_CTRL0(1, 0, 0, pS->inv_y_ratio, + pS->inv_chroma_ratio, 0, 0); +} +void prime_sl_close(void) +{ + wbits_PRIMESL_CTRL0(0, 0, 0, 0, 0, 0, 0); +} + diff --git a/drivers/amlogic/media/enhancement/amvecm/amcm.c b/drivers/amlogic/media/enhancement/amvecm/amcm.c index 7a8ad4cf9f35..1177a7793515 100644 --- a/drivers/amlogic/media/enhancement/amvecm/amcm.c +++ b/drivers/amlogic/media/enhancement/amvecm/amcm.c @@ -30,6 +30,7 @@ #include "amcm_regmap.h" #include #include "amcsc.h" +#include "local_contrast.h" #define pr_amcm_dbg(fmt, args...)\ do {\ @@ -161,8 +162,8 @@ void am_set_regmap(struct am_regs_s *p) if (!cm_en) { if (p->am_reg[i].addr == 0x208) { - if (get_cpu_type() == - MESON_CPU_MAJOR_ID_TL1) + if (get_cpu_type() >= + MESON_CPU_MAJOR_ID_G12A) p->am_reg[i].val = p->am_reg[i].val & 0xfffffffe; else @@ -244,6 +245,14 @@ void am_set_regmap(struct am_regs_s *p) } else { if (p->am_reg[i].addr == 0x1d26) break; + if (p->am_reg[i].addr == SRSHARP1_LC_TOP_CTRL) { + temp = + (p->am_reg[i].val & p->am_reg[i].mask) + >> 4; + temp &= 0x1; + if (!temp && lc_en) + lc_en = 0; + } if (pq_reg_wr_rdma) VSYNC_WR_MPEG_REG(p->am_reg[i].addr, (aml_read_vcbus(p->am_reg[i].addr) & @@ -270,7 +279,7 @@ void amcm_disable(void) WRITE_VPP_REG(VPP_CHROMA_ADDR_PORT, 0x208); temp = READ_VPP_REG(VPP_CHROMA_DATA_PORT); - if (get_cpu_type() == MESON_CPU_MAJOR_ID_TL1) { + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) { if (temp & 0x1) { WRITE_VPP_REG(VPP_CHROMA_ADDR_PORT, 0x208); @@ -296,7 +305,7 @@ void amcm_enable(void) WRITE_VPP_REG_BITS(VPP_MISC, 1, 28, 1); WRITE_VPP_REG(VPP_CHROMA_ADDR_PORT, 0x208); temp = READ_VPP_REG(VPP_CHROMA_DATA_PORT); - if (get_cpu_type() == MESON_CPU_MAJOR_ID_TL1) { + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) { if (!(temp & 0x1)) { WRITE_VPP_REG(VPP_CHROMA_ADDR_PORT, 0x208); @@ -422,7 +431,10 @@ void cm_latch_process(void) } while (0); if (cm_en && (cm_level_last != cm_level)) { cm_level_last = cm_level; - if ((!is_meson_gxtvbb_cpu()) && (!is_meson_txl_cpu())) + if ((!is_meson_gxtvbb_cpu()) && + (!is_meson_txl_cpu()) && + (!is_meson_txlx_cpu()) && + (!is_meson_tl1_cpu())) amcm_level_sel(cm_level); amcm_enable(); pr_amcm_dbg("\n[amcm..] set cm2 load OK!!!\n"); diff --git a/drivers/amlogic/media/enhancement/amvecm/amcm_regmap.h b/drivers/amlogic/media/enhancement/amvecm/amcm_regmap.h index 1c2c3d30bf89..bf8a1aa37064 100644 --- a/drivers/amlogic/media/enhancement/amvecm/amcm_regmap.h +++ b/drivers/amlogic/media/enhancement/amvecm/amcm_regmap.h @@ -918,6 +918,172 @@ static struct am_regs_s cmreg_enhancement = { } }; +/*sr0 sharpness reg*/ +struct am_regs_s sr0reg_cvbs = { + 109, + { + {REG_TYPE_VCBUS, SHARP0_SHARP_HVSIZE, 0xffffffff, 0x02d00240}, + {REG_TYPE_VCBUS, SHARP0_SHARP_HVBLANK_NUM, 0xffffffff, 0x00001e58}, + {REG_TYPE_VCBUS, SHARP0_NR_GAUSSIAN_MODE, 0xffffffff, 0x00000010}, + {REG_TYPE_VCBUS, SHARP0_PKOSHT_VSLUMA_LUT_L, 0xffffffff, 0x56667ac8}, + {REG_TYPE_VCBUS, SHARP0_PKOSHT_VSLUMA_LUT_H, 0xffffffff, 0x00000004}, + {REG_TYPE_VCBUS, SHARP0_PK_CON_2CIRHPGAIN_TH_RATE, + 0xffffffff, 0x14323218}, + {REG_TYPE_VCBUS, SHARP0_PK_CON_2CIRHPGAIN_LIMIT, + 0xffffffff, 0x50845e00}, + {REG_TYPE_VCBUS, SHARP0_PK_CON_2CIRBPGAIN_TH_RATE, + 0xffffffff, 0x14323218}, + {REG_TYPE_VCBUS, SHARP0_PK_CON_2CIRBPGAIN_LIMIT, + 0xffffffff, 0x508d5000}, + {REG_TYPE_VCBUS, SHARP0_PK_CON_2DRTHPGAIN_TH_RATE, + 0xffffffff, 0x14323218}, + {REG_TYPE_VCBUS, SHARP0_PK_CON_2DRTHPGAIN_LIMIT, + 0xffffffff, 0x3d3d1f00}, + {REG_TYPE_VCBUS, SHARP0_PK_CON_2DRTBPGAIN_TH_RATE, + 0xffffffff, 0x14323218}, + {REG_TYPE_VCBUS, SHARP0_PK_CON_2DRTBPGAIN_LIMIT, + 0xffffffff, 0x38390c00}, + {REG_TYPE_VCBUS, SHARP0_PK_CIRFB_LPF_MODE, 0xffffffff, 0x22202220}, + {REG_TYPE_VCBUS, SHARP0_PK_DRTFB_LPF_MODE, 0xffffffff, 0x22202220}, + {REG_TYPE_VCBUS, SHARP0_PK_CIRFB_HP_CORING, 0xffffffff, 0x00020202}, + {REG_TYPE_VCBUS, SHARP0_PK_CIRFB_BP_CORING, 0xffffffff, 0x00020202}, + {REG_TYPE_VCBUS, SHARP0_PK_DRTFB_HP_CORING, 0xffffffff, 0x00020202}, + {REG_TYPE_VCBUS, SHARP0_PK_DRTFB_BP_CORING, 0xffffffff, 0x00020202}, + {REG_TYPE_VCBUS, SHARP0_PK_CIRFB_BLEND_GAIN, 0xffffffff, 0x38402840}, + {REG_TYPE_VCBUS, SHARP0_NR_ALPY_SSD_GAIN_OFST, + 0xffffffff, 0x0000103e}, + {REG_TYPE_VCBUS, SHARP0_NR_ALP0Y_ERR2CURV_TH_RATE, + 0xffffffff, 0x0a195040}, + {REG_TYPE_VCBUS, SHARP0_NR_ALP0Y_ERR2CURV_LIMIT, + 0xffffffff, 0x3f003f00}, + {REG_TYPE_VCBUS, SHARP0_NR_ALP0C_ERR2CURV_TH_RATE, + 0xffffffff, 0x0a195040}, + {REG_TYPE_VCBUS, SHARP0_NR_ALP0C_ERR2CURV_LIMIT, + 0xffffffff, 0x3f003f00}, + {REG_TYPE_VCBUS, SHARP0_NR_ALP0_MIN_MAX, 0xffffffff, 0x003f003f}, + {REG_TYPE_VCBUS, SHARP0_NR_ALP1_MIERR_CORING, + 0xffffffff, 0x00000003}, + {REG_TYPE_VCBUS, SHARP0_NR_ALP1_ERR2CURV_TH_RATE, + 0xffffffff, 0x00180014}, + {REG_TYPE_VCBUS, SHARP0_NR_ALP1_ERR2CURV_LIMIT, + 0xffffffff, 0x00103f00}, + {REG_TYPE_VCBUS, SHARP0_NR_ALP1_MIN_MAX, 0xffffffff, 0x003f003f}, + {REG_TYPE_VCBUS, SHARP0_PK_ALP2_MIERR_CORING, + 0xffffffff, 0x00010001}, + {REG_TYPE_VCBUS, SHARP0_PK_ALP2_ERR2CURV_TH_RATE, + 0xffffffff, 0x0018000a}, + {REG_TYPE_VCBUS, SHARP0_PK_ALP2_ERR2CURV_LIMIT, + 0xffffffff, 0x00402000}, + {REG_TYPE_VCBUS, SHARP0_PK_ALP2_MIN_MAX, 0xffffffff, 0x0000003f}, + {REG_TYPE_VCBUS, SHARP0_PK_FINALGAIN_HP_BP, + 0xffffffff, 0x00001414}, + {REG_TYPE_VCBUS, SHARP0_PK_OS_HORZ_CORE_GAIN, + 0xffffffff, 0x08140214}, + {REG_TYPE_VCBUS, SHARP0_PK_OS_VERT_CORE_GAIN, + 0xffffffff, 0x08140214}, + {REG_TYPE_VCBUS, SHARP0_PK_OS_ADPT_MISC, + 0xffffffff, 0x2806c814}, + {REG_TYPE_VCBUS, SHARP0_PK_OS_STATIC, 0xffffffff, 0x2203f03f}, + {REG_TYPE_VCBUS, SHARP0_PK_NR_ENABLE, 0xffffffff, 0x00000000}, + {REG_TYPE_VCBUS, SHARP0_PK_DRT_SAD_MISC, 0xffffffff, 0x12120018}, + {REG_TYPE_VCBUS, SHARP0_NR_TI_DNLP_BLEND, 0xffffffff, 0x00000407}, + {REG_TYPE_VCBUS, SHARP0_TI_DIR_CORE_ALPHA, 0xffffffff, 0x0a00003f}, + {REG_TYPE_VCBUS, SHARP0_CTI_DIR_ALPHA, 0xffffffff, 0x0400003f}, + {REG_TYPE_VCBUS, SHARP0_LTI_CTI_DF_GAIN, 0xffffffff, 0x0c0c0c0c}, + {REG_TYPE_VCBUS, SHARP0_LTI_CTI_DIR_AC_DBG, 0xffffffff, 0x56ee0000}, + {REG_TYPE_VCBUS, SHARP0_HCTI_FLT_CLP_DC, 0xffffffff, 0x05555300}, + {REG_TYPE_VCBUS, SHARP0_HCTI_BST_GAIN, 0xffffffff, 0x050a0a00}, + {REG_TYPE_VCBUS, SHARP0_HCTI_BST_CORE, 0xffffffff, 0x03030303}, + {REG_TYPE_VCBUS, SHARP0_HCTI_CON_2_GAIN_0, 0xffffffff, 0x24193c05}, + {REG_TYPE_VCBUS, SHARP0_HCTI_CON_2_GAIN_1, 0xffffffff, 0x4b055014}, + {REG_TYPE_VCBUS, SHARP0_HCTI_OS_MARGIN, 0xffffffff, 0x00000000}, + {REG_TYPE_VCBUS, SHARP0_HLTI_FLT_CLP_DC, 0xffffffff, 0x00152100}, + {REG_TYPE_VCBUS, SHARP0_HLTI_BST_GAIN, 0xffffffff, 0x06060600}, + {REG_TYPE_VCBUS, SHARP0_HLTI_BST_CORE, 0xffffffff, 0x03030303}, + {REG_TYPE_VCBUS, SHARP0_HLTI_CON_2_GAIN_0, 0xffffffff, 0x24193c05}, + {REG_TYPE_VCBUS, SHARP0_HLTI_CON_2_GAIN_1, 0xffffffff, 0x66635e24}, + {REG_TYPE_VCBUS, SHARP0_HLTI_OS_MARGIN, 0xffffffff, 0x00000000}, + {REG_TYPE_VCBUS, SHARP0_VLTI_FLT_CON_CLP, 0xffffffff, 0x00002a94}, + {REG_TYPE_VCBUS, SHARP0_VLTI_BST_GAIN, 0xffffffff, 0x00202020}, + {REG_TYPE_VCBUS, SHARP0_VLTI_BST_CORE, 0xffffffff, 0x00050503}, + {REG_TYPE_VCBUS, SHARP0_VLTI_CON_2_GAIN_0, 0xffffffff, 0x193c0560}, + {REG_TYPE_VCBUS, SHARP0_VLTI_CON_2_GAIN_1, 0xffffffff, 0x5f501400}, + {REG_TYPE_VCBUS, SHARP0_VCTI_FLT_CON_CLP, 0xffffffff, 0x00002a94}, + {REG_TYPE_VCBUS, SHARP0_VCTI_BST_GAIN, 0xffffffff, 0x00101010}, + {REG_TYPE_VCBUS, SHARP0_VCTI_BST_CORE, 0xffffffff, 0x00050503}, + {REG_TYPE_VCBUS, SHARP0_VCTI_CON_2_GAIN_0, 0xffffffff, 0x193c0560}, + {REG_TYPE_VCBUS, SHARP0_VCTI_CON_2_GAIN_1, 0xffffffff, 0x5f501400}, + {REG_TYPE_VCBUS, SHARP0_SHARP_3DLIMIT, 0xffffffff, 0x03c0021c}, + /*{REG_TYPE_VCBUS, SHARP0_SHARP_SR2_CTRL, 0xffffffff, 0x0018103c},*/ + {REG_TYPE_VCBUS, SHARP0_SHARP_SR2_YBIC_HCOEF0, + 0xffffffff, 0x00004000}, + {REG_TYPE_VCBUS, SHARP0_SHARP_SR2_YBIC_HCOEF1, + 0xffffffff, 0xfc2424fc}, + {REG_TYPE_VCBUS, SHARP0_SHARP_SR2_CBIC_HCOEF0, + 0xffffffff, 0x00004000}, + {REG_TYPE_VCBUS, SHARP0_SHARP_SR2_CBIC_HCOEF1, + 0xffffffff, 0xfc2424fc}, + {REG_TYPE_VCBUS, SHARP0_SHARP_SR2_YBIC_VCOEF0, + 0xffffffff, 0x00004000}, + {REG_TYPE_VCBUS, SHARP0_SHARP_SR2_YBIC_VCOEF1, + 0xffffffff, 0xfc2424fc}, + {REG_TYPE_VCBUS, SHARP0_SHARP_SR2_CBIC_VCOEF0, + 0xffffffff, 0x00004000}, + {REG_TYPE_VCBUS, SHARP0_SHARP_SR2_CBIC_VCOEF1, + 0xffffffff, 0xfc2424fc}, + {REG_TYPE_VCBUS, SHARP0_SHARP_SR2_MISC, 0xffffffff, 0x00000000}, + {REG_TYPE_VCBUS, SHARP0_SR3_SAD_CTRL, 0xffffffff, 0x060606ff}, + {REG_TYPE_VCBUS, SHARP0_SR3_PK_CTRL0, 0xffffffff, 0x00000ffc}, + {REG_TYPE_VCBUS, SHARP0_SR3_PK_CTRL1, 0xffffffff, 0x112020cc}, + {REG_TYPE_VCBUS, SHARP0_DEJ_CTRL, 0xffffffff, 0x0000000f}, + {REG_TYPE_VCBUS, SHARP0_DEJ_ALPHA, 0xffffffff, 0x0f0f4646}, + {REG_TYPE_VCBUS, SHARP0_SR3_DRTLPF_EN, 0xffffffff, 0x00000037}, + {REG_TYPE_VCBUS, SHARP0_SR3_DRTLPF_ALPHA_0, + 0xffffffff, 0x0405050c}, + {REG_TYPE_VCBUS, SHARP0_SR3_DRTLPF_ALPHA_1, + 0xffffffff, 0x01040708}, + {REG_TYPE_VCBUS, SHARP0_SR3_DRTLPF_ALPHA_2, + 0xffffffff, 0x00000000}, + {REG_TYPE_VCBUS, SHARP0_SR3_DRTLPF_ALPHA_OFST, + 0xffffffff, 0x000e000e}, + {REG_TYPE_VCBUS, SHARP0_SR3_DERING_CTRL, + 0xffffffff, 0x1392281c}, + {REG_TYPE_VCBUS, SHARP0_SR3_DERING_LUMA2PKGAIN_0TO3, + 0xffffffff, 0xffffc81e}, + {REG_TYPE_VCBUS, SHARP0_SR3_DERING_LUMA2PKGAIN_4TO6, + 0xffffffff, 0x001832ff}, + {REG_TYPE_VCBUS, SHARP0_SR3_DERING_LUMA2PKOS_0TO3, + 0xffffffff, 0xffffc81e}, + {REG_TYPE_VCBUS, SHARP0_SR3_DERING_LUMA2PKOS_4TO6, + 0xffffffff, 0x001832ff}, + {REG_TYPE_VCBUS, SHARP0_SR3_DERING_GAINVS_MADSAD, + 0xffffffff, 0x00000048}, + {REG_TYPE_VCBUS, SHARP0_SR3_DERING_GAINVS_VR2MAX, + 0xffffffff, 0xffffec20}, + {REG_TYPE_VCBUS, SHARP0_SR3_DERING_PARAM0, + 0xffffffff, 0x000a2010}, + {REG_TYPE_VCBUS, SHARP0_SR3_DRTLPF_THETA, + 0xffffffff, 0xfec96420}, + {REG_TYPE_VCBUS, SHARP0_SATPRT_CTRL, 0xffffffff, 0x00054006}, + {REG_TYPE_VCBUS, SHARP0_SATPRT_DIVM, 0xffffffff, 0x00808080}, + {REG_TYPE_VCBUS, SHARP0_DB_FLT_CTRL, 0xffffffff, 0x06e222fa}, + {REG_TYPE_VCBUS, SHARP0_DB_FLT_YC_THRD, + 0xffffffff, 0x97659765}, + {REG_TYPE_VCBUS, SHARP0_DB_FLT_RANDLUT, + 0xffffffff, 0x00249249}, + {REG_TYPE_VCBUS, SHARP0_DB_FLT_PXI_THRD, + 0xffffffff, 0x00000000}, + {REG_TYPE_VCBUS, SHARP0_DB_FLT_SEED_Y, 0xffffffff, 0x60a52f20}, + {REG_TYPE_VCBUS, SHARP0_DB_FLT_SEED_U, 0xffffffff, 0x60a52f27}, + {REG_TYPE_VCBUS, SHARP0_DB_FLT_SEED_V, 0xffffffff, 0x60a52f22}, + {REG_TYPE_VCBUS, SHARP0_PKGAIN_VSLUMA_LUT_L, + 0xffffffff, 0x56667ac8}, + {REG_TYPE_VCBUS, SHARP0_PKGAIN_VSLUMA_LUT_H, + 0xffffffff, 0x00000004}, + {0} + } +}; + /*sr1 sharpness reg*/ struct am_regs_s sr1reg_sd_scale = { 109, diff --git a/drivers/amlogic/media/enhancement/amvecm/amcsc.c b/drivers/amlogic/media/enhancement/amvecm/amcsc.c index 08953ccfe8ec..12f5f98e78dc 100644 --- a/drivers/amlogic/media/enhancement/amvecm/amcsc.c +++ b/drivers/amlogic/media/enhancement/amvecm/amcsc.c @@ -3736,6 +3736,21 @@ void get_hdr_source_type(void) hdr_source_type = SDR_SOURCE; } +enum color_primary_e get_color_primary(void) +{ + enum color_primary_e color_pri; + + if (signal_color_primaries == 1) + color_pri = VPP_COLOR_PRI_BT709; + else if (signal_color_primaries == 3) + color_pri = VPP_COLOR_PRI_BT601; + else if (signal_color_primaries == 9) + color_pri = VPP_COLOR_PRI_BT2020; + else + color_pri = VPP_COLOR_PRI_NULL; + return color_pri; +} + static void cal_out_curve(uint panel_luma) { int index; @@ -6521,9 +6536,8 @@ int amvecm_matrix_process( toggle_frame = 0; /* when sdr mode change */ if ((vinfo->hdr_info.hdr_support & 0x4) && - ((get_cpu_type() == MESON_CPU_MAJOR_ID_GXL) || - (get_cpu_type() == MESON_CPU_MAJOR_ID_GXM) || - (get_cpu_type() == MESON_CPU_MAJOR_ID_G12A))) + ((cpu_after_eq(MESON_CPU_MAJOR_ID_GXL)) && + (vinfo->viu_color_fmt != COLOR_FMT_RGB444))) if (((sdr_process_mode != 1) && (sdr_mode > 0)) || ((sdr_process_mode > 0) && (sdr_mode == 0))) null_vf_cnt = toggle_frame; diff --git a/drivers/amlogic/media/enhancement/amvecm/amcsc.h b/drivers/amlogic/media/enhancement/amvecm/amcsc.h index 1657bb1ec616..b0ccbc040126 100644 --- a/drivers/amlogic/media/enhancement/amvecm/amcsc.h +++ b/drivers/amlogic/media/enhancement/amvecm/amcsc.h @@ -106,7 +106,7 @@ extern int amvecm_hdr_dbg(u32 sel); extern u32 get_video_enabled(void); extern void get_hdr_source_type(void); - +extern enum color_primary_e get_color_primary(void); /*hdr*/ /*#define DBG_BUF_SIZE (1024)*/ diff --git a/drivers/amlogic/media/enhancement/amvecm/amve.c b/drivers/amlogic/media/enhancement/amvecm/amve.c index e87b26a6f059..53b6dd9e890e 100644 --- a/drivers/amlogic/media/enhancement/amvecm/amve.c +++ b/drivers/amlogic/media/enhancement/amvecm/amve.c @@ -36,6 +36,7 @@ #include "amve_gamma_table.h" #include #include "dnlp_cal.h" +#include "local_contrast.h" #define pr_amve_dbg(fmt, args...)\ do {\ @@ -766,6 +767,14 @@ void ve_dnlp_latch_process(void) } } +void ve_lc_latch_process(void) +{ + if (vecm_latch_flag & FLAG_VE_LC_CURV) { + vecm_latch_flag &= ~FLAG_VE_LC_CURV; + lc_load_curve(&lc_curve_parm_load); + } +} + void ve_lcd_gamma_process(void) { if (vecm_latch_flag & FLAG_GAMMA_TABLE_EN) { @@ -868,6 +877,11 @@ void ve_new_dnlp_param_update(void) vecm_latch_flag |= FLAG_VE_NEW_DNLP; } +void ve_lc_curve_update(void) +{ + vecm_latch_flag |= FLAG_VE_LC_CURV; +} + static void video_data_limitation(int *val) { if (*val > 1023) @@ -1033,7 +1047,7 @@ void vpp_vd_adj1_contrast(signed int cont_val, struct vframe_s *vf) WRITE_VPP_REG_BITS(VPP_VADJ_CTRL, 0, 1, 1); } } - if (get_cpu_type() == MESON_CPU_MAJOR_ID_TL1) { + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) { vd1_contrast = (READ_VPP_REG(VPP_VADJ1_Y_2) & 0x7ff00) | (cont_val << 0); WRITE_VPP_REG(VPP_VADJ1_Y_2, vd1_contrast); @@ -1065,7 +1079,7 @@ void vpp_vd_adj1_brightness(signed int bri_val, struct vframe_s *vf) if (bri_val > 1023 || bri_val < -1024) return; - if (get_cpu_type() == MESON_CPU_MAJOR_ID_TL1) { + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) { vd1_brightness = (READ_VPP_REG(VPP_VADJ1_Y_2) & 0xff) | (bri_val << 8); @@ -1310,6 +1324,9 @@ void amvecm_3d_sync_process(void) #define SR_NOSCALE_LEVEL 0x10 static void amve_sr_reg_setting(unsigned int adaptive_level) { + if (is_meson_g12a_cpu() || is_meson_g12b_cpu() || + is_meson_sm1_cpu()) + goto g12_sr_reg_setting; if (adaptive_level & SR_SD_SCALE_LEVEL) am_set_regmap(&sr1reg_sd_scale); else if (adaptive_level & SR_HD_SCALE_LEVEL) @@ -1326,6 +1343,12 @@ static void amve_sr_reg_setting(unsigned int adaptive_level) am_set_regmap(&sr1reg_cvbs); else if (adaptive_level & SR_NOSCALE_LEVEL) am_set_regmap(&sr1reg_hv_noscale); + return; +g12_sr_reg_setting: + /*for g12a and g12b, load sr0 cvbs table when output cvbs mode*/ + if (adaptive_level & SR_CVBS_LEVEL) + am_set_regmap(&sr0reg_cvbs); + return; } void amve_sharpness_adaptive_setting(struct vframe_s *vf, unsigned int sps_h_en, unsigned int sps_v_en) @@ -1395,11 +1418,14 @@ void amvecm_fresh_overscan(struct vframe_s *vf) { unsigned int height = 0; unsigned int cur_overscan_timing = 0; + unsigned int cur_fmt; + unsigned int offset = TIMING_UHD + 1;/*av&atv*/ if (overscan_disable) return; if (is_dolby_vision_on()) return; + if (overscan_table[0].load_flag) { height = (vf->type & VIDTYPE_COMPRESS) ? vf->compHeight : vf->height; @@ -1431,19 +1457,57 @@ void amvecm_fresh_overscan(struct vframe_s *vf) vf->pic_mode.ve = overscan_table[overscan_timing].ve; vf->ratio_control |= DISP_RATIO_ADAPTED_PICMODE; } + if (overscan_table[offset].load_flag) { + cur_fmt = vf->sig_fmt; + if (cur_fmt == TVIN_SIG_FMT_CVBS_NTSC_M) + cur_overscan_timing = TIMING_NTST_M; + else if (cur_fmt == TVIN_SIG_FMT_CVBS_NTSC_443) + cur_overscan_timing = TIMING_NTST_443; + else if (cur_fmt == TVIN_SIG_FMT_CVBS_PAL_I) + cur_overscan_timing = TIMING_PAL_I; + else if (cur_fmt == TVIN_SIG_FMT_CVBS_PAL_M) + cur_overscan_timing = TIMING_PAL_M; + else if (cur_fmt == TVIN_SIG_FMT_CVBS_PAL_60) + cur_overscan_timing = TIMING_PAL_60; + else if (cur_fmt == TVIN_SIG_FMT_CVBS_PAL_CN) + cur_overscan_timing = TIMING_PAL_CN; + else if (cur_fmt == TVIN_SIG_FMT_CVBS_SECAM) + cur_overscan_timing = TIMING_SECAM; + else if (cur_fmt == TVIN_SIG_FMT_CVBS_NTSC_50) + cur_overscan_timing = TIMING_NTSC_50; + else + return; + overscan_timing = cur_overscan_timing; + overscan_screen_mode = + overscan_table[overscan_timing].screen_mode; + vf->pic_mode.AFD_enable = + overscan_table[overscan_timing].afd_enable; + vf->pic_mode.screen_mode = overscan_screen_mode; + vf->pic_mode.hs = overscan_table[overscan_timing].hs; + vf->pic_mode.he = overscan_table[overscan_timing].he; + vf->pic_mode.vs = overscan_table[overscan_timing].vs; + vf->pic_mode.ve = overscan_table[overscan_timing].ve; + vf->ratio_control |= DISP_RATIO_ADAPTED_PICMODE; + } } void amvecm_reset_overscan(void) { + unsigned int offset = TIMING_UHD + 1;/*av&atv*/ + enum ve_source_input_e source0; + + source0 = overscan_table[0].source; if (overscan_disable) return; if (overscan_timing != TIMING_MAX) { overscan_timing = TIMING_MAX; - if ((overscan_table[0].source != SOURCE_DTV) && - (overscan_table[0].source != SOURCE_MPEG)) { + if ((source0 != SOURCE_DTV) && (source0 != SOURCE_MPEG)) overscan_table[0].load_flag = 0; + else if (!atv_source_flg) + overscan_table[offset].load_flag = 0; + if ((source0 != SOURCE_DTV) && (source0 != SOURCE_MPEG) + && !atv_source_flg) overscan_screen_mode = 0xff; - } } } diff --git a/drivers/amlogic/media/enhancement/amvecm/amve.h b/drivers/amlogic/media/enhancement/amvecm/amve.h index d90c1e059d68..02110178715a 100644 --- a/drivers/amlogic/media/enhancement/amvecm/amve.h +++ b/drivers/amlogic/media/enhancement/amvecm/amve.h @@ -110,6 +110,8 @@ extern void ve_lcd_gamma_process(void); extern void lvds_freq_process(void); extern void ve_dnlp_param_update(void); extern void ve_new_dnlp_param_update(void); +extern void ve_lc_curve_update(void); +extern void ve_lc_latch_process(void); extern void ve_ogo_param_update(void); extern void am_set_regmap(struct am_regs_s *p); extern void sharpness_process(struct vframe_s *vf); @@ -155,6 +157,7 @@ extern void amve_sharpness_adaptive_setting(struct vframe_s *vf, extern void amve_sharpness_init(void); extern struct am_regs_s sr1reg_sd_scale; extern struct am_regs_s sr1reg_hd_scale; +extern struct am_regs_s sr0reg_cvbs; extern struct am_regs_s sr1reg_cvbs; extern struct am_regs_s sr1reg_hv_noscale; extern void amvecm_fresh_overscan(struct vframe_s *vf); diff --git a/drivers/amlogic/media/enhancement/amvecm/amvecm.c b/drivers/amlogic/media/enhancement/amvecm/amvecm.c index 027c4d0ca4da..89cfda3959f0 100644 --- a/drivers/amlogic/media/enhancement/amvecm/amvecm.c +++ b/drivers/amlogic/media/enhancement/amvecm/amvecm.c @@ -31,6 +31,8 @@ #include #include #include +#include +#include /* #include */ #include /* for parse_para_pq */ #include @@ -61,6 +63,7 @@ #include "vlock.h" #include "hdr/am_hdr10_plus.h" #include "local_contrast.h" +#include "arch/vpp_hdr_regs.h" #define pr_amvecm_dbg(fmt, args...)\ do {\ @@ -117,7 +120,7 @@ static unsigned int pre_hist_height, pre_hist_width; static unsigned int pc_mode = 0xff; static unsigned int pc_mode_last = 0xff; static struct hdr_metadata_info_s vpp_hdr_metadata_s; - +unsigned int atv_source_flg; /*bit0: brightness *bit1: brightness2 *bit2: saturation_hue @@ -128,7 +131,7 @@ static struct hdr_metadata_info_s vpp_hdr_metadata_s; static int vdj_mode_flg; struct am_vdj_mode_s vdj_mode_s; -void __iomem *amvecm_hiu_reg_base;/* = *ioremap(0xc883c000, 0x2000); */ +/*void __iomem *amvecm_hiu_reg_base;*//* = *ioremap(0xc883c000, 0x2000); */ static int debug_amvecm; module_param(debug_amvecm, int, 0664); @@ -180,7 +183,7 @@ unsigned int debug_game_mode_1; module_param(debug_game_mode_1, uint, 0664); MODULE_PARM_DESC(debug_game_mode_1, "\n debug_game_mode_1\n"); unsigned int pq_user_value; -unsigned int hdr_source_type = 0x1; +enum hdr_type_e hdr_source_type = HDRTYPE_SDR; #define SR0_OFFSET 0xc00 #define SR1_OFFSET 0xc80 @@ -236,7 +239,7 @@ __setup("pq=", amvecm_load_pq_val); static int amvecm_set_contrast2(int val) { val += 0x80; - if (get_cpu_type() == MESON_CPU_MAJOR_ID_TL1) { + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) { WRITE_VPP_REG_BITS(VPP_VADJ2_Y_2, val, 0, 8); WRITE_VPP_REG_BITS(VPP_VADJ2_MISC, 1, 0, 1); @@ -254,14 +257,14 @@ static int amvecm_set_brightness2(int val) if (get_cpu_type() <= MESON_CPU_MAJOR_ID_GXTVBB) WRITE_VPP_REG_BITS(VPP_VADJ2_Y, vdj_mode_s.brightness2, 8, 9); - else if (get_cpu_type() == MESON_CPU_MAJOR_ID_TL1) + else if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) WRITE_VPP_REG_BITS(VPP_VADJ2_Y_2, vdj_mode_s.brightness2, 8, 11); else WRITE_VPP_REG_BITS(VPP_VADJ2_Y, vdj_mode_s.brightness2 >> 1, 8, 10); - if (get_cpu_type() == MESON_CPU_MAJOR_ID_TL1) + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) WRITE_VPP_REG_BITS(VPP_VADJ2_MISC, 1, 0, 1); else WRITE_VPP_REG_BITS(VPP_VADJ_CTRL, 1, 2, 1); @@ -290,7 +293,7 @@ static ssize_t video_adj1_brightness_show(struct class *cla, val = (val << 23) >> 23; return sprintf(buf, "%d\n", val); - } else if (get_cpu_type() == MESON_CPU_MAJOR_ID_TL1) { + } else if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) { val = (READ_VPP_REG(VPP_VADJ1_Y_2) >> 8) & 0x7ff; val = (val << 21) >> 21; @@ -315,12 +318,12 @@ static ssize_t video_adj1_brightness_store(struct class *cla, if (get_cpu_type() <= MESON_CPU_MAJOR_ID_GXTVBB) WRITE_VPP_REG_BITS(VPP_VADJ1_Y, val, 8, 9); - else if (get_cpu_type() == MESON_CPU_MAJOR_ID_TL1) + else if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) WRITE_VPP_REG_BITS(VPP_VADJ1_Y_2, val, 8, 11); else WRITE_VPP_REG_BITS(VPP_VADJ1_Y, val >> 1, 8, 10); - if (get_cpu_type() == MESON_CPU_MAJOR_ID_TL1) + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) WRITE_VPP_REG_BITS(VPP_VADJ1_MISC, 1, 0, 1); else WRITE_VPP_REG_BITS(VPP_VADJ_CTRL, 1, 0, 1); @@ -331,7 +334,7 @@ static ssize_t video_adj1_brightness_store(struct class *cla, static ssize_t video_adj1_contrast_show(struct class *cla, struct class_attribute *attr, char *buf) { - if (get_cpu_type() == MESON_CPU_MAJOR_ID_TL1) + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) return sprintf(buf, "%d\n", (int)(READ_VPP_REG(VPP_VADJ1_Y_2) & 0xff) - 0x80); else @@ -352,7 +355,7 @@ static ssize_t video_adj1_contrast_store(struct class *cla, val += 0x80; - if (get_cpu_type() == MESON_CPU_MAJOR_ID_TL1) { + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) { WRITE_VPP_REG_BITS(VPP_VADJ1_Y_2, val, 0, 8); WRITE_VPP_REG_BITS(VPP_VADJ1_MISC, 1, 0, 1); } else { @@ -374,7 +377,7 @@ static ssize_t video_adj2_brightness_show(struct class *cla, val = (val << 23) >> 23; return sprintf(buf, "%d\n", val); - } else if (get_cpu_type() == MESON_CPU_MAJOR_ID_TL1) { + } else if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) { val = (READ_VPP_REG(VPP_VADJ2_Y_2) >> 8) & 0x7ff; val = (val << 21) >> 21; @@ -403,7 +406,7 @@ static ssize_t video_adj2_brightness_store(struct class *cla, static ssize_t video_adj2_contrast_show(struct class *cla, struct class_attribute *attr, char *buf) { - if (get_cpu_type() == MESON_CPU_MAJOR_ID_TL1) + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) return sprintf(buf, "%d\n", (int)(READ_VPP_REG(VPP_VADJ2_Y_2) & 0xff) - 0x80); else @@ -721,6 +724,7 @@ static ssize_t amvecm_vlock_store(struct class *cla, sel = VLOCK_SUPPORT; } else if (!strncmp(parm[0], "enable", 6)) { vecm_latch_flag |= FLAG_VLOCK_EN; + vlock_set_en(true); } else if (!strncmp(parm[0], "disable", 7)) { vecm_latch_flag |= FLAG_VLOCK_DIS; } else if (!strncmp(parm[0], "status", 6)) { @@ -733,8 +737,36 @@ static ssize_t amvecm_vlock_store(struct class *cla, vlock_log_stop(); } else if (!strncmp(parm[0], "log_print", 9)) { vlock_log_print(); + } else if (!strncmp(parm[0], "phase", 5)) { + if (kstrtol(parm[1], 10, &val) < 0) + return -EINVAL; + vlock_set_phase(val); + } else if (!strncmp(parm[0], "phlock_en", 9)) { + if (kstrtol(parm[1], 10, &val) < 0) + return -EINVAL; + vlock_set_phase_en(val); } else { - pr_info("unsupport cmd!!\n"); + pr_info("----cmd list -----\n"); + pr_info("vlock_mode val\n"); + pr_info("vlock_en val\n"); + pr_info("vlock_debug val\n"); + pr_info("vlock_adapt val\n"); + pr_info("vlock_dis_cnt_limit val\n"); + pr_info("vlock_delta_limit val\n"); + pr_info("vlock_dynamic_adjust val\n"); + pr_info("vlock_line_limit val\n"); + pr_info("vlock_dis_cnt_no_vf_limit val\n"); + pr_info("vlock_line_limit val\n"); + pr_info("vlock_support val\n"); + pr_info("enable\n"); + pr_info("disable\n"); + pr_info("status\n"); + pr_info("dump_reg\n"); + pr_info("log_start\n"); + pr_info("log_stop\n"); + pr_info("log_print\n"); + pr_info("phase persent\n"); + pr_info("phlock_en val\n"); } if (sel < VLOCK_PARAM_MAX) vlock_param_set(temp_val, sel); @@ -780,8 +812,14 @@ void vpp_get_vframe_hist_info(struct vframe_s *vf) unsigned int hist_height, hist_width; u64 divid; - hist_height = READ_VPP_REG_BITS(VPP_IN_H_V_SIZE, 0, 13); - hist_width = READ_VPP_REG_BITS(VPP_IN_H_V_SIZE, 16, 13); + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) { + /*TL1 remove VPP_IN_H_V_SIZE register*/ + hist_width = READ_VPP_REG_BITS(VPP_PREBLEND_H_SIZE, 0, 13); + hist_height = READ_VPP_REG_BITS(VPP_PREBLEND_H_SIZE, 16, 13); + } else { + hist_height = READ_VPP_REG_BITS(VPP_IN_H_V_SIZE, 0, 13); + hist_width = READ_VPP_REG_BITS(VPP_IN_H_V_SIZE, 16, 13); + } if ((hist_height != pre_hist_height) || (hist_width != pre_hist_width)) { @@ -1022,7 +1060,8 @@ void amvecm_video_latch(void) } /* #endif */ pq_user_latch_process(); - + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) + ve_lc_latch_process(); } int amvecm_on_vs( @@ -1072,7 +1111,8 @@ int amvecm_on_vs( /* add some flag to trigger */ if (vf) { /*gxlx sharpness adaptive setting*/ - if (is_meson_gxlx_cpu()) + if (is_meson_gxlx_cpu() || is_meson_g12a_cpu() + || is_meson_g12b_cpu() || is_meson_sm1_cpu()) amve_sharpness_adaptive_setting(vf, sps_h_en, sps_v_en); amvecm_bricon_process( @@ -1191,7 +1231,7 @@ static int amvecm_set_saturation_hue(int mab) mb = -512; mab = ((ma & 0x3ff) << 16) | (mb & 0x3ff); - if (get_cpu_type() == MESON_CPU_MAJOR_ID_TL1) + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) WRITE_VPP_REG(VPP_VADJ1_MA_MB_2, mab); else WRITE_VPP_REG(VPP_VADJ1_MA_MB, mab); @@ -1205,7 +1245,7 @@ static int amvecm_set_saturation_hue(int mab) md = (s16)((mab<<6)>>22); /* md = ma; */ mab = ((mc&0x3ff)<<16)|(md&0x3ff); - if (get_cpu_type() == MESON_CPU_MAJOR_ID_TL1) { + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) { WRITE_VPP_REG(VPP_VADJ1_MC_MD_2, mab); WRITE_VPP_REG_BITS(VPP_VADJ1_MISC, 1, 0, 1); } else { @@ -1260,7 +1300,7 @@ static int amvecm_set_saturation_hue_post(int val1, mab = ((ma & 0x3ff) << 16) | (mb & 0x3ff); pr_info("\n[amvideo..] saturation_post:%d hue_post:%d mab:%x\n", saturation_post, hue_post, mab); - if (get_cpu_type() == MESON_CPU_MAJOR_ID_TL1) + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) WRITE_VPP_REG(VPP_VADJ2_MA_MB_2, mab); else WRITE_VPP_REG(VPP_VADJ2_MA_MB, mab); @@ -1272,7 +1312,7 @@ static int amvecm_set_saturation_hue_post(int val1, mc = -512; md = (s16)((mab<<6)>>22); /* md = ma; */ mab = ((mc&0x3ff)<<16)|(md&0x3ff); - if (get_cpu_type() == MESON_CPU_MAJOR_ID_TL1) { + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) { WRITE_VPP_REG(VPP_VADJ2_MC_MD_2, mab); WRITE_VPP_REG_BITS(VPP_VADJ2_MISC, 1, 0, 1); } else { @@ -1296,6 +1336,41 @@ static int gamma_table_compare(struct tcon_gamma_table_s *table1, return flag; } +static void parse_overscan_table(unsigned int length, + struct ve_pq_table_s *amvecm_pq_load_table) +{ + unsigned int i; + unsigned int offset = TIMING_UHD + 1; + + memset(overscan_table, 0, sizeof(overscan_table)); + for (i = 0; i < length; i++) { + overscan_table[i].load_flag = + (amvecm_pq_load_table[i].src_timing >> 31) & 0x1; + overscan_table[i].afd_enable = + (amvecm_pq_load_table[i].src_timing >> 30) & 0x1; + overscan_table[i].screen_mode = + (amvecm_pq_load_table[i].src_timing >> 24) & 0x3f; + overscan_table[i].source = + (amvecm_pq_load_table[i].src_timing >> 16) & 0xff; + overscan_table[i].timing = + amvecm_pq_load_table[i].src_timing & 0xffff; + overscan_table[i].hs = + amvecm_pq_load_table[i].value1 & 0xffff; + overscan_table[i].he = + (amvecm_pq_load_table[i].value1 >> 16) & 0xffff; + overscan_table[i].vs = + amvecm_pq_load_table[i].value2 & 0xffff; + overscan_table[i].ve = + (amvecm_pq_load_table[i].value2 >> 16) & 0xffff; + } + /*because SOURCE_TV is 0,so need to add a flg to check ATV*/ + if ((overscan_table[offset].load_flag == 1) && + (overscan_table[offset].source == SOURCE_TV)) + atv_source_flg = 1; + else + atv_source_flg = 0; +} + static long amvecm_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { @@ -1304,7 +1379,7 @@ static long amvecm_ioctl(struct file *file, unsigned int mem_size; struct ve_pq_load_s vpp_pq_load; struct ve_pq_table_s *vpp_pq_load_table = NULL; - int i = 0; + enum color_primary_e color_pri; if (debug_amvecm & 2) pr_info("[amvecm..] %s: cmd_nr = 0x%x\n", @@ -1486,7 +1561,8 @@ static long amvecm_ioctl(struct file *file, break; } /*check pq_table length copy_from_user*/ - if (vpp_pq_load.length > PQ_TABLE_MAX_LENGTH) { + if ((vpp_pq_load.length > TIMING_MAX) || + (vpp_pq_load.length <= 0)) { ret = -EFAULT; pr_amvecm_dbg("[amvecm..] pq ioctl length check fail!!\n"); break; @@ -1503,28 +1579,7 @@ static long amvecm_ioctl(struct file *file, pr_amvecm_dbg("[amvecm..] ovescan copy fail!!\n"); break; } - for (i = 0; i < vpp_pq_load.length; i++) { - if (i >= TIMING_MAX) - break; - overscan_table[i].load_flag = - (vpp_pq_load_table[i].src_timing >> 31) & 0x1; - overscan_table[i].afd_enable = - (vpp_pq_load_table[i].src_timing >> 30) & 0x1; - overscan_table[i].screen_mode = - (vpp_pq_load_table[i].src_timing >> 24) & 0x3f; - overscan_table[i].source = - (vpp_pq_load_table[i].src_timing >> 16) & 0xff; - overscan_table[i].timing = - vpp_pq_load_table[i].src_timing & 0xffff; - overscan_table[i].hs = - vpp_pq_load_table[i].value1 & 0xffff; - overscan_table[i].he = - (vpp_pq_load_table[i].value1 >> 16) & 0xffff; - overscan_table[i].vs = - vpp_pq_load_table[i].value2 & 0xffff; - overscan_table[i].ve = - (vpp_pq_load_table[i].value2 >> 16) & 0xffff; - } + parse_overscan_table(vpp_pq_load.length, vpp_pq_load_table); break; case AMVECM_IOC_G_DNLP_STATE: if (copy_to_user((void __user *)arg, @@ -1555,6 +1610,13 @@ static long amvecm_ioctl(struct file *file, &cur_csc_type, sizeof(enum vpp_matrix_csc_e))) ret = -EFAULT; break; + case AMVECM_IOC_G_COLOR_PRI: + argp = (void __user *)arg; + color_pri = get_color_primary(); + if (copy_to_user(argp, + &color_pri, sizeof(enum color_primary_e))) + ret = -EFAULT; + break; case AMVECM_IOC_S_CSCTYPE: if (copy_from_user(&cur_csc_type, (void __user *)arg, @@ -1583,8 +1645,8 @@ static long amvecm_ioctl(struct file *file, vecm_latch_flag |= FLAG_VADJ1_BRI; } if (vdj_mode_flg & 0x2) { /*brightness2*/ - if ((vdj_mode_s.brightness2 < -255) || - (vdj_mode_s.brightness2 > 255)) { + if ((vdj_mode_s.brightness2 < -1024) || + (vdj_mode_s.brightness2 > 1023)) { pr_amvecm_dbg("load brightness2 value invalid!!!\n"); return -EINVAL; } @@ -1631,6 +1693,23 @@ static long amvecm_ioctl(struct file *file, ret = amvecm_set_contrast2(vdj_mode_s.contrast2); } break; + case AMVECM_IOC_S_LC_CURVE: + if (copy_from_user(&lc_curve_parm_load, + (void __user *)arg, + sizeof(struct ve_lc_curve_parm_s))) { + pr_amvecm_dbg("lc load curve parm fail\n"); + ret = -EFAULT; + } else { + ve_lc_curve_update(); + pr_amvecm_dbg("lc load curve parm success\n"); + } + break; + case AMVECM_IOC_G_HDR_TYPE: + argp = (void __user *)arg; + if (copy_to_user(argp, + &hdr_source_type, sizeof(enum hdr_type_e))) + ret = -EFAULT; + break; default: ret = -EINVAL; break; @@ -1681,9 +1760,11 @@ static void d_convert_str(int num, if (bit_chose == 10) snprintf(buf, sizeof(buf), "%d", num); - if (bit_chose == 16) + else if (bit_chose == 16) snprintf(buf, sizeof(buf), "%x", num); count = strlen(buf); + if (count > 4) + count = 4; for (i = 0; i < count; i++) buf[i + char_bit] = buf[i]; for (i = 0; i < char_bit; i++) @@ -1716,6 +1797,8 @@ static ssize_t amvecm_dnlp_debug_store(struct class *cla, stemp = kmalloc(400, GFP_KERNEL); if (!stemp) return 0; + memset(stemp, 0, 400); + buf_orig = kstrdup(buf, GFP_KERNEL); parse_param_amvecm(buf_orig, (char **)&parm); @@ -1895,6 +1978,101 @@ static ssize_t amvecm_dnlp_debug_store(struct class *cla, else pr_info("%d\n", wext_gain_copy[val]); } + } else if (!strcmp(parm[1], "adp_thrd")) { + if (parm[2] == NULL) { + pr_info("error cmd\n"); + goto free_buf; + } else if (!strcmp(parm[2], "all")) { + for (i = 0; i < 33; i++) + d_convert_str(adp_thrd_copy[i], + i, stemp, 4, 10); + pr_info("%s\n", stemp); + } else { + if (kstrtoul(parm[2], 10, &val) < 0) + goto free_buf; + + if ((val > 32) || (val < 0)) + pr_info("error cmd\n"); + else + pr_info("%d\n", adp_thrd_copy[val]); + } + } else if (!strcmp(parm[1], "reg_blk_boost_12")) { + if (parm[2] == NULL) { + pr_info("error cmd\n"); + goto free_buf; + } else if (!strcmp(parm[2], "all")) { + for (i = 0; i < 13; i++) + d_convert_str(reg_blk_boost_12_copy[i], + i, stemp, 4, 10); + pr_info("%s\n", stemp); + } else { + if (kstrtoul(parm[2], 10, &val) < 0) + goto free_buf; + + if ((val > 12) || (val < 0)) + pr_info("error cmd\n"); + else + pr_info("%d\n", + reg_blk_boost_12_copy[val]); + } + } else if (!strcmp(parm[1], "reg_adp_ofset_20")) { + if (parm[2] == NULL) { + pr_info("error cmd\n"); + goto free_buf; + } else if (!strcmp(parm[2], "all")) { + for (i = 0; i < 20; i++) + d_convert_str(reg_adp_ofset_20_copy[i], + i, stemp, 4, 10); + pr_info("%s\n", stemp); + } else { + if (kstrtoul(parm[2], 10, &val) < 0) + goto free_buf; + + if ((val > 19) || (val < 0)) + pr_info("error cmd\n"); + else + pr_info("%d\n", + reg_adp_ofset_20_copy[val]); + } + } else if (!strcmp(parm[1], "reg_mono_protect")) { + if (parm[2] == NULL) { + pr_info("error cmd\n"); + goto free_buf; + } else if (!strcmp(parm[2], "all")) { + for (i = 0; i < 6; i++) + d_convert_str(reg_mono_protect_copy[i], + i, stemp, 4, 10); + pr_info("%s\n", stemp); + } else { + if (kstrtoul(parm[2], 10, &val) < 0) + goto free_buf; + + if ((val > 5) || (val < 0)) + pr_info("error cmd\n"); + else + pr_info("%d\n", + reg_mono_protect_copy[val]); + } + } else if (!strcmp(parm[1], "reg_trend_wht_expand_lut8")) { + if (parm[2] == NULL) { + pr_info("error cmd\n"); + goto free_buf; + } else if (!strcmp(parm[2], "all")) { + for (i = 0; i < 9; i++) + d_convert_str( + reg_trend_wht_expand_lut8_copy[i], + i, stemp, 4, 10); + pr_info("%s\n", stemp); + } else { + if (kstrtoul(parm[2], 10, &val) < 0) + goto free_buf; + + if ((val > 8) || (val < 0)) + pr_info("error cmd\n"); + else + pr_info("%d\n", + reg_trend_wht_expand_lut8_copy[val]); + } } else if (!strcmp(parm[1], "ve_dnlp_tgt")) { /*read only curve*/ if (parm[2] == NULL) { @@ -2117,6 +2295,112 @@ static ssize_t amvecm_dnlp_debug_store(struct class *cla, else wext_gain_copy[num] = val; } + } else if (!strcmp(parm[1], "adp_thrd")) { + if (parm[2] == NULL) { + pr_info("error cmd\n"); + goto free_buf; + } else if (!strcmp(parm[2], "all")) { + str_sapr_to_d(parm[3], curve_val, 5); + for (i = 0; i < 33; i++) + adp_thrd_copy[i] = curve_val[i]; + } else { + if (kstrtoul(parm[2], 10, &val) < 0) + goto free_buf; + + num = val; + if (kstrtoul(parm[3], 10, &val) < 0) + goto free_buf; + + if (num > 32) + pr_info("error cmd\n"); + else + adp_thrd_copy[num] = val; + } + } else if (!strcmp(parm[1], "reg_blk_boost_12")) { + if (parm[2] == NULL) { + pr_info("error cmd\n"); + goto free_buf; + } else if (!strcmp(parm[2], "all")) { + str_sapr_to_d(parm[3], curve_val, 5); + for (i = 0; i < 13; i++) + reg_blk_boost_12_copy[i] = curve_val[i]; + } else { + if (kstrtoul(parm[2], 10, &val) < 0) + goto free_buf; + + num = val; + if (kstrtoul(parm[3], 10, &val) < 0) + goto free_buf; + + if (num > 12) + pr_info("error cmd\n"); + else + reg_blk_boost_12_copy[num] = val; + } + } else if (!strcmp(parm[1], "reg_adp_ofset_20")) { + if (parm[2] == NULL) { + pr_info("error cmd\n"); + goto free_buf; + } else if (!strcmp(parm[2], "all")) { + str_sapr_to_d(parm[3], curve_val, 5); + for (i = 0; i < 20; i++) + reg_adp_ofset_20_copy[i] = curve_val[i]; + } else { + if (kstrtoul(parm[2], 10, &val) < 0) + goto free_buf; + + num = val; + if (kstrtoul(parm[3], 10, &val) < 0) + goto free_buf; + + if (num > 19) + pr_info("error cmd\n"); + else + reg_adp_ofset_20_copy[num] = val; + } + } else if (!strcmp(parm[1], "reg_mono_protect")) { + if (parm[2] == NULL) { + pr_info("error cmd\n"); + goto free_buf; + } else if (!strcmp(parm[2], "all")) { + str_sapr_to_d(parm[3], curve_val, 5); + for (i = 0; i < 6; i++) + reg_mono_protect_copy[i] = curve_val[i]; + } else { + if (kstrtoul(parm[2], 10, &val) < 0) + goto free_buf; + + num = val; + if (kstrtoul(parm[3], 10, &val) < 0) + goto free_buf; + + if (num > 5) + pr_info("error cmd\n"); + else + reg_mono_protect_copy[num] = val; + } + } else if (!strcmp(parm[1], "reg_trend_wht_expand_lut8")) { + if (parm[2] == NULL) { + pr_info("error cmd\n"); + goto free_buf; + } else if (!strcmp(parm[2], "all")) { + str_sapr_to_d(parm[3], curve_val, 5); + for (i = 0; i < 9; i++) + reg_trend_wht_expand_lut8_copy[i] = + curve_val[i]; + } else { + if (kstrtoul(parm[2], 10, &val) < 0) + goto free_buf; + + num = val; + if (kstrtoul(parm[3], 10, &val) < 0) + goto free_buf; + + if (num > 8) + pr_info("error cmd\n"); + else + reg_trend_wht_expand_lut8_copy[num] = val; + } } } else if (!strcmp(parm[0], "ro")) { if (!strcmp(parm[1], "luma_avg4")) @@ -2201,7 +2485,7 @@ static ssize_t amvecm_contrast_store(struct class *cla, static ssize_t amvecm_saturation_hue_show(struct class *cla, struct class_attribute *attr, char *buf) { - if (get_cpu_type() == MESON_CPU_MAJOR_ID_TL1) + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) return sprintf(buf, "0x%x\n", READ_VPP_REG(VPP_VADJ1_MA_MB_2)); else @@ -2264,7 +2548,7 @@ void vpp_vd_adj1_saturation_hue(signed int sat_val, mab = ((ma & 0x3ff) << 16) | (mb & 0x3ff); pr_info("\n[amvideo..] saturation_pre:%d hue_pre:%d mab:%x\n", sat_val, hue_val, mab); - if (get_cpu_type() == MESON_CPU_MAJOR_ID_TL1) + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) WRITE_VPP_REG(VPP_VADJ1_MA_MB_2, mab); else WRITE_VPP_REG(VPP_VADJ1_MA_MB, mab); @@ -2277,7 +2561,7 @@ void vpp_vd_adj1_saturation_hue(signed int sat_val, md = (s16)((mab<<6)>>22); /* md = ma; */ mab = ((mc&0x3ff)<<16)|(md&0x3ff); - if (get_cpu_type() == MESON_CPU_MAJOR_ID_TL1) { + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) { WRITE_VPP_REG(VPP_VADJ1_MC_MD_2, mab); WRITE_VPP_REG_BITS(VPP_VADJ1_MISC, 1, 0, 1); } else { @@ -2757,6 +3041,8 @@ static ssize_t set_gamma_pattern_show(struct class *cla, pr_info("8bit: echo r g b > /sys/class/amvecm/gamma_pattern\n"); pr_info("10bit: echo r g b 0xa > /sys/class/amvecm/gamma_pattern\n"); pr_info(" r g b should be hex\n"); + pr_info("disable gamma pattern:\n"); + pr_info("echo disable > /sys/class/amvecm/gamma_pattern\n"); return 0; } @@ -2786,6 +3072,14 @@ static ssize_t set_gamma_pattern_store(struct class *cls, parm[n++] = token; } + if (!strcmp(parm[0], "disable")) { + vecm_latch_flag |= FLAG_GAMMA_TABLE_R; + vecm_latch_flag |= FLAG_GAMMA_TABLE_G; + vecm_latch_flag |= FLAG_GAMMA_TABLE_B; + kfree(buf_orig); + return count; + } + if (*(parm + 3) != NULL) { if (kstrtol(parm[3], 16, &val) < 0) { kfree(buf_orig); @@ -4744,16 +5038,36 @@ static void get_cm_hist(enum cm_hist_e hist_sel) kfree(hist); } -static void cm_init_config(void) +static void cm_init_config(int bitdepth) { - WRITE_VPP_REG(VPP_CHROMA_ADDR_PORT, XVYCC_YSCP_REG); - WRITE_VPP_REG(VPP_CHROMA_DATA_PORT, 0x3ff0000); - WRITE_VPP_REG(VPP_CHROMA_ADDR_PORT, XVYCC_USCP_REG); - WRITE_VPP_REG(VPP_CHROMA_DATA_PORT, 0x3ff0000); - WRITE_VPP_REG(VPP_CHROMA_ADDR_PORT, XVYCC_VSCP_REG); - WRITE_VPP_REG(VPP_CHROMA_DATA_PORT, 0x3ff0000); - WRITE_VPP_REG(VPP_CHROMA_ADDR_PORT, LUMA_ADJ0_REG); - WRITE_VPP_REG(VPP_CHROMA_DATA_PORT, 0x40400); + if (bitdepth == 10) { + WRITE_VPP_REG(VPP_CHROMA_ADDR_PORT, XVYCC_YSCP_REG); + WRITE_VPP_REG(VPP_CHROMA_DATA_PORT, 0x3ff0000); + WRITE_VPP_REG(VPP_CHROMA_ADDR_PORT, XVYCC_USCP_REG); + WRITE_VPP_REG(VPP_CHROMA_DATA_PORT, 0x3ff0000); + WRITE_VPP_REG(VPP_CHROMA_ADDR_PORT, XVYCC_VSCP_REG); + WRITE_VPP_REG(VPP_CHROMA_DATA_PORT, 0x3ff0000); + WRITE_VPP_REG(VPP_CHROMA_ADDR_PORT, LUMA_ADJ0_REG); + WRITE_VPP_REG(VPP_CHROMA_DATA_PORT, 0x40400); + } else if (bitdepth == 12) { + WRITE_VPP_REG(VPP_CHROMA_ADDR_PORT, XVYCC_YSCP_REG); + WRITE_VPP_REG(VPP_CHROMA_DATA_PORT, 0xfff0000); + WRITE_VPP_REG(VPP_CHROMA_ADDR_PORT, XVYCC_USCP_REG); + WRITE_VPP_REG(VPP_CHROMA_DATA_PORT, 0xfff0000); + WRITE_VPP_REG(VPP_CHROMA_ADDR_PORT, XVYCC_VSCP_REG); + WRITE_VPP_REG(VPP_CHROMA_DATA_PORT, 0xfff0000); + WRITE_VPP_REG(VPP_CHROMA_ADDR_PORT, LUMA_ADJ0_REG); + WRITE_VPP_REG(VPP_CHROMA_DATA_PORT, 0x100400); + } else { + WRITE_VPP_REG(VPP_CHROMA_ADDR_PORT, XVYCC_YSCP_REG); + WRITE_VPP_REG(VPP_CHROMA_DATA_PORT, 0x3ff0000); + WRITE_VPP_REG(VPP_CHROMA_ADDR_PORT, XVYCC_USCP_REG); + WRITE_VPP_REG(VPP_CHROMA_DATA_PORT, 0x3ff0000); + WRITE_VPP_REG(VPP_CHROMA_ADDR_PORT, XVYCC_VSCP_REG); + WRITE_VPP_REG(VPP_CHROMA_DATA_PORT, 0x3ff0000); + WRITE_VPP_REG(VPP_CHROMA_ADDR_PORT, LUMA_ADJ0_REG); + WRITE_VPP_REG(VPP_CHROMA_DATA_PORT, 0x40400); + } } static const char *amvecm_debug_usage_str = { @@ -4815,7 +5129,7 @@ static ssize_t amvecm_debug_store(struct class *cla, { char *buf_orig, *parm[8] = {NULL}; long val = 0; - unsigned int mode_sel, color, color_mode; + unsigned int mode_sel, color, color_mode, i; if (!buf) return count; @@ -4903,7 +5217,7 @@ static ssize_t amvecm_debug_store(struct class *cla, amvecm_sharpness_enable(13); pr_info("SR disable\n"); } - } else if (!strncmp(parm[0], "cm", 2)) { + } else if (!strcmp(parm[0], "cm")) { if (!strncmp(parm[1], "enable", 6)) { amcm_enable(); pr_info("enable cm\n"); @@ -5080,42 +5394,42 @@ static ssize_t amvecm_debug_store(struct class *cla, color_mode = 0; vpp_clip_config(mode_sel, color, color_mode); pr_info("vpp_clip_config done!\n"); - } else if (!strcmp(parm[0], "3dlut_set")) { - int *PLut3D; - unsigned int bitdepth; + } else if (!strcmp(parm[0], "3dlut_set")) { + int *PLut3D; + unsigned int bitdepth; - PLut3D = kmalloc(14739 * sizeof(int), GFP_KERNEL); - if (PLut3D == NULL) { - kfree(PLut3D); - goto free_buf; - } - if (parm[1]) { - if (kstrtoul(parm[1], 10, &val) < 0) { - kfree(PLut3D); - goto free_buf; - } - bitdepth = val; - } else { - pr_info("unsupport cmd\n"); - kfree(PLut3D); - goto free_buf; - } - - vpp_lut3d_table_init(PLut3D, bitdepth); - if (!strcmp(parm[2], "enable")) - vpp_set_lut3d(1, 1, PLut3D, 1); - else if (!strcmp(parm[2], "disable")) - vpp_set_lut3d(0, 0, PLut3D, 0); - else - pr_info("unsupprt cmd!\n"); + PLut3D = kmalloc(14739 * sizeof(int), GFP_KERNEL); + if (PLut3D == NULL) { kfree(PLut3D); - } else if (!strcmp(parm[0], "3dlut_dump")) { - if (!strcmp(parm[1], "init_tab")) - dump_plut3d_table(); - else if (!strcmp(parm[1], "reg_tab")) - dump_plut3d_reg_table(); - else - pr_info("unsupprt cmd!\n"); + goto free_buf; + } + if (parm[1]) { + if (kstrtoul(parm[1], 10, &val) < 0) { + kfree(PLut3D); + goto free_buf; + } + bitdepth = val; + } else { + pr_info("unsupport cmd\n"); + kfree(PLut3D); + goto free_buf; + } + + vpp_lut3d_table_init(PLut3D, bitdepth); + if (!strcmp(parm[2], "enable")) + vpp_set_lut3d(1, 1, PLut3D, 1); + else if (!strcmp(parm[2], "disable")) + vpp_set_lut3d(0, 0, PLut3D, 0); + else + pr_info("unsupprt cmd!\n"); + kfree(PLut3D); + } else if (!strcmp(parm[0], "3dlut_dump")) { + if (!strcmp(parm[1], "init_tab")) + dump_plut3d_table(); + else if (!strcmp(parm[1], "reg_tab")) + dump_plut3d_reg_table(); + else + pr_info("unsupprt cmd!\n"); } else if (!strcmp(parm[0], "cm_hist")) { if (!parm[1]) { pr_info("miss param1\n"); @@ -5215,9 +5529,18 @@ static ssize_t amvecm_debug_store(struct class *cla, cm_luma_bri_con(rd, bri, con, blk_lel); pr_info("cm hist bri_con set success\n"); } - } else { + } else if (!strcmp(parm[0], "dump_overscan_table")) { + for (i = 0; i < TIMING_MAX; i++) { + pr_info("*****dump overscan_tab[%d]*****\n", i); + pr_info("hs:%d, he:%d, vs:%d, ve:%d, screen_mode:%d, afd:%d, flag:%d.\n", + overscan_table[i].hs, overscan_table[i].he, + overscan_table[i].vs, overscan_table[i].ve, + overscan_table[i].screen_mode, + overscan_table[i].afd_enable, + overscan_table[i].load_flag); + } + } else pr_info("unsupport cmd\n"); - } kfree(buf_orig); return count; @@ -5359,6 +5682,238 @@ static ssize_t amvecm_get_hdr_type_store(struct class *cls, return count; } +static void lc_rd_reg(enum lc_reg_lut_e reg_sel, int data_type) +{ + int i, tmp, tmp1, tmp2; + int lut_data[63] = {0}; + char *stemp = NULL; + + if (data_type == 1) + goto dump_as_string; + + switch (reg_sel) { + case SATUR_LUT: + for (i = 0; i < 31 ; i++) { + tmp = READ_VPP_REG(SRSHARP1_LC_SAT_LUT_0_1 + i); + tmp1 = (tmp >> 16) & 0xfff; + tmp2 = tmp & 0xfff; + pr_info("reg_lc_satur_lut[%d] =%4d.\n", + 2*i, tmp1); + pr_info("reg_lc_satur_lut[%d] =%4d.\n", + 2*i + 1, tmp2); + } + tmp = READ_VPP_REG(SRSHARP1_LC_SAT_LUT_62); + pr_info("reg_lc_satur_lut[62] =%4d.\n", + tmp & 0xfff); + break; + case YMINVAL_LMT: + for (i = 0; i < 6 ; i++) { + tmp = READ_VPP_REG(LC_CURVE_YMINVAL_LMT_0_1 + i); + tmp1 = (tmp >> 16) & 0x3ff; + tmp2 = tmp & 0x3ff; + pr_info("reg_yminVal_lmt[%d] =%4d.\n", + 2*i, tmp1); + pr_info("reg_yminVal_lmt[%d] =%4d.\n", + 2*i + 1, tmp2); + } + break; + case YPKBV_YMAXVAL_LMT: + for (i = 0; i < 6 ; i++) { + tmp = READ_VPP_REG(LC_CURVE_YPKBV_YMAXVAL_LMT_0_1 + i); + tmp1 = (tmp >> 16) & 0x3ff; + tmp2 = tmp & 0x3ff; + pr_info("reg_lc_ypkBV_ymaxVal_lmt[%d] =%4d.\n", + 2*i, tmp1); + pr_info("reg_lc_ypkBV_ymaxVal_lmt[%d] =%4d.\n", + 2*i + 1, tmp2); + } + break; + case YPKBV_RAT: + tmp = READ_VPP_REG(LC_CURVE_YPKBV_RAT); + pr_info("reg_lc_ypkBV_ratio[0] =%4d.\n", + (tmp>>24) & 0xff); + pr_info("reg_lc_ypkBV_ratio[1] =%4d.\n", + (tmp>>16) & 0xff); + pr_info("reg_lc_ypkBV_ratio[2] =%4d.\n", + (tmp>>8) & 0xff); + pr_info("reg_lc_ypkBV_ratio[3] =%4d.\n", + tmp & 0xff); + break; + case YPKBV_SLP_LMT: + tmp = READ_VPP_REG(LC_CURVE_YPKBV_SLP_LMT); + pr_info("reg_lc_ypkBV_slope_lmt[0] =%4d.\n", + (tmp>>8) & 0xff); + pr_info("reg_lc_ypkBV_slope_lmt[1] =%4d.\n", + tmp & 0xff); + break; + case CNTST_LMT: + tmp = READ_VPP_REG(LC_CURVE_CONTRAST__LMT_LH); + pr_info("reg_lc_cntstlmt_low[0] =%4d.\n", + (tmp>>24) & 0xff); + pr_info("reg_lc_cntstlmt_high[0] =%4d.\n", + (tmp>>16) & 0xff); + pr_info("reg_lc_cntstlmt_low[1] =%4d.\n", + (tmp>>8) & 0xff); + pr_info("reg_lc_cntstlmt_high[1] =%4d.\n", + tmp & 0xff); + break; + default: + break; + } + return; + +dump_as_string: + stemp = kzalloc(300, GFP_KERNEL); + if (!stemp) + return; + switch (reg_sel) { + case SATUR_LUT: + for (i = 0; i < 31 ; i++) { + tmp = READ_VPP_REG(SRSHARP1_LC_SAT_LUT_0_1 + i); + tmp1 = (tmp >> 16) & 0xfff; + tmp2 = tmp & 0xfff; + lut_data[2*i] = tmp1; + lut_data[2*i + 1] = tmp2; + } + tmp = READ_VPP_REG(SRSHARP1_LC_SAT_LUT_62); + lut_data[62] = tmp & 0xfff; + for (i = 0; i < 63 ; i++) + d_convert_str(lut_data[i], + i, stemp, 4, 10); + pr_info("%s\n", stemp); + break; + case YMINVAL_LMT: + for (i = 0; i < 6 ; i++) { + tmp = READ_VPP_REG(LC_CURVE_YMINVAL_LMT_0_1 + i); + tmp1 = (tmp >> 16) & 0x3ff; + tmp2 = tmp & 0x3ff; + lut_data[2*i] = tmp1; + lut_data[2*i + 1] = tmp2; + } + for (i = 0; i < 12 ; i++) + d_convert_str(lut_data[i], + i, stemp, 4, 10); + pr_info("%s\n", stemp); + break; + case YPKBV_YMAXVAL_LMT: + for (i = 0; i < 6 ; i++) { + tmp = READ_VPP_REG(LC_CURVE_YPKBV_YMAXVAL_LMT_0_1 + i); + tmp1 = (tmp >> 16) & 0x3ff; + tmp2 = tmp & 0x3ff; + lut_data[2*i] = tmp1; + lut_data[2*i + 1] = tmp2; + } + for (i = 0; i < 12 ; i++) + d_convert_str(lut_data[i], + i, stemp, 4, 10); + pr_info("%s\n", stemp); + break; + case YPKBV_RAT: + tmp = READ_VPP_REG(LC_CURVE_YPKBV_RAT); + lut_data[0] = (tmp>>24) & 0xff; + lut_data[1] = (tmp>>16) & 0xff; + lut_data[2] = (tmp>>8) & 0xff; + lut_data[3] = tmp & 0xff; + for (i = 0; i < 4 ; i++) + d_convert_str(lut_data[i], + i, stemp, 4, 10); + pr_info("%s\n", stemp); + break; + default: + break; + } + kfree(stemp); + return; +} + +static void lc_wr_reg(int *p, enum lc_reg_lut_e reg_sel) +{ + int i, tmp, tmp1, tmp2; + + switch (reg_sel) { + case SATUR_LUT: + for (i = 0; i < 31 ; i++) { + tmp1 = *(p + 2*i); + tmp2 = *(p + 2*i + 1); + tmp = ((tmp1 & 0xfff)<<16) | (tmp2 & 0xfff); + WRITE_VPP_REG(SRSHARP1_LC_SAT_LUT_0_1 + i, tmp); + } + tmp = (*(p+62)) & 0xfff; + WRITE_VPP_REG(SRSHARP1_LC_SAT_LUT_62, tmp); + break; + case YMINVAL_LMT: + for (i = 0; i < 6 ; i++) { + tmp1 = *(p + 2*i); + tmp2 = *(p + 2*i + 1); + tmp = ((tmp1&0x3ff) << 16) | (tmp2 & 0x3ff); + WRITE_VPP_REG(LC_CURVE_YMINVAL_LMT_0_1 + i, tmp); + } + break; + case YPKBV_YMAXVAL_LMT: + for (i = 0; i < 6 ; i++) { + tmp1 = *(p + 2*i); + tmp2 = *(p + 2*i + 1); + tmp = ((tmp1&0x3ff) << 16) | (tmp2 & 0x3ff); + WRITE_VPP_REG(LC_CURVE_YPKBV_YMAXVAL_LMT_0_1 + i, tmp); + } + break; + case YPKBV_RAT: + tmp = (*p & 0xff) << 24 | (*(p+1) & 0xff) << 16 | + (*(p+2) & 0xff) << 8 | (*(p+3) & 0xff); + WRITE_VPP_REG(LC_CURVE_YPKBV_RAT, tmp); + break; + case YPKBV_SLP_LMT: + tmp = (*p & 0xff) << 8 | (*(p+1) & 0xff); + WRITE_VPP_REG(LC_CURVE_YPKBV_SLP_LMT, tmp); + break; + case CNTST_LMT: + tmp = (*p & 0xff) << 24 | (*(p+1) & 0xff) << 16 | + (*(p+2) & 0xff) << 8 | (*(p+3) & 0xff); + WRITE_VPP_REG(LC_CURVE_CONTRAST__LMT_LH, tmp); + break; + default: + break; + } +} + +unsigned int lc_saturation_curv[63]; +unsigned int lc_yminval_lmt_curv[12]; +unsigned int lc_ypkbv_ymaxval_lmt_curv[12]; +unsigned int lc_ypkbv_ratio_curv[4]; + +void lc_load_curve(struct ve_lc_curve_parm_s *p) +{ + unsigned int i; + + /*load lc parms*/ + lc_alg_parm.dbg_parm0 = p->param[lc_dbg_parm0]; + lc_alg_parm.dbg_parm1 = p->param[lc_dbg_parm1]; + lc_alg_parm.dbg_parm2 = p->param[lc_dbg_parm2]; + lc_alg_parm.dbg_parm3 = p->param[lc_dbg_parm3]; + lc_alg_parm.dbg_parm4 = p->param[lc_dbg_parm4]; + + /*load lc curve*/ + for (i = 0; i < 63; i++) + lc_saturation_curv[i] = p->ve_lc_saturation[i]; + for (i = 0; i < 12; i++) { + lc_yminval_lmt_curv[i] = + p->ve_lc_yminval_lmt[i]; + lc_ypkbv_ymaxval_lmt_curv[i] = + p->ve_lc_ypkbv_ymaxval_lmt[i]; + } + for (i = 0; i < 4; i++) + lc_ypkbv_ratio_curv[i] = p->ve_lc_ypkbv_ratio[i]; + + /*load lc_staturation curve*/ + lc_wr_reg(lc_saturation_curv, 0x1); + /*load lc_yminval_lmt*/ + lc_wr_reg(lc_yminval_lmt_curv, 0x2); + /*load lc_ypkbv_ymaxval_lmt*/ + lc_wr_reg(lc_ypkbv_ymaxval_lmt_curv, 0x4); + /*load lc_ypkbV_ratio*/ + lc_wr_reg(lc_ypkbv_ratio_curv, 0x8); +} + static ssize_t amvecm_lc_show(struct class *cla, struct class_attribute *attr, char *buf) { @@ -5370,6 +5925,36 @@ static ssize_t amvecm_lc_show(struct class *cla, "echo lc disable > /sys/class/amvecm/lc\n"); len += sprintf(buf+len, "echo lc_dbg value > /sys/class/amvecm/lc\n"); + len += sprintf(buf+len, + "echo lc_demo_mode enable/disable > /sys/class/amvecm/lc\n"); + len += sprintf(buf+len, + "echo lc_dump_reg parm1 > /sys/class/amvecm/lc\n"); + len += sprintf(buf+len, + "echo lc_rd_reg parm1 parm2 > /sys/class/amvecm/lc\n"); + len += sprintf(buf+len, + "parm1: 0x1,0x2,0x4,0x8,0x10,0x20...\n"); + len += sprintf(buf+len, + "parm2: decimal strings, each data width is 4.\n"); + len += sprintf(buf+len, + "echo dump_hist all > /sys/class/amvecm/lc\n"); + len += sprintf(buf+len, + "echo dump_hist chosen hs he vs ve cnt > /sys/class/amvecm/lc\n"); + len += sprintf(buf+len, + "echo dump_curve cnt > /sys/class/amvecm/lc\n"); + len += sprintf(buf+len, + "echo lc_osd_setting show > /sys/class/amvecm/lc\n"); + len += sprintf(buf+len, + "echo lc_osd_setting set xxx ... xxx > /sys/class/amvecm/lc\n"); + len += sprintf(buf+len, + "echo osd_iir_en val > /sys/class/amvecm/lc\n"); + len += sprintf(buf+len, + "echo iir_refresh show > /sys/class/amvecm/lc\n"); + len += sprintf(buf+len, + "echo iir_refresh set xxx ... xxx > /sys/class/amvecm/lc\n"); + len += sprintf(buf+len, + "echo scene_change_th val > /sys/class/amvecm/lc\n"); + len += sprintf(buf+len, + "echo irr_dbg_en val > /sys/class/amvecm/lc\n"); return len; } @@ -5378,10 +5963,18 @@ static ssize_t amvecm_lc_store(struct class *cls, const char *buf, size_t count) { char *buf_orig, *parm[8] = {NULL}; + int reg_lut[63] = {0}; + enum lc_reg_lut_e reg_sel; + int h, v, i, start_point; long val = 0; + char *stemp = NULL; + int curve_val[6] = {0}; if (!buf) return count; + stemp = kzalloc(100, GFP_KERNEL); + if (!stemp) + return 0; buf_orig = kstrdup(buf, GFP_KERNEL); parse_param_amvecm(buf_orig, (char **)&parm); @@ -5393,31 +5986,298 @@ static ssize_t amvecm_lc_store(struct class *cls, lc_en = 0; else pr_info("unsupprt cmd!\n"); + } else if (!strcmp(parm[0], "lc_version")) { + pr_info("lc driver version : %s\n", LC_VER); } else if (!strcmp(parm[0], "lc_dbg")) { - if (kstrtoul(parm[1], 16, &val) < 0) { - kfree(buf_orig); - return -EINVAL; - } + if (kstrtoul(parm[1], 16, &val) < 0) + goto free_buf; amlc_debug = val; - } else + } else if (!strcmp(parm[0], "lc_demo_mode")) { + if (!strcmp(parm[1], "enable")) + lc_demo_mode = 1; + else if (!strcmp(parm[1], "disable")) + lc_demo_mode = 0; + else + pr_info("unsupprt cmd!\n"); + } else if (!strcmp(parm[0], "dump_lut_data")) { + if (kstrtoul(parm[1], 16, &val) < 0) + goto free_buf; + reg_sel = val; + if (reg_sel == SATUR_LUT) + lc_rd_reg(SATUR_LUT, 0); + else if (reg_sel == YMINVAL_LMT) + lc_rd_reg(YMINVAL_LMT, 0); + else if (reg_sel == YPKBV_YMAXVAL_LMT) + lc_rd_reg(YPKBV_YMAXVAL_LMT, 0); + else if (reg_sel == YPKBV_RAT) + lc_rd_reg(YPKBV_RAT, 0); + else if (reg_sel == YPKBV_SLP_LMT) + lc_rd_reg(YPKBV_SLP_LMT, 0); + else if (reg_sel == CNTST_LMT) + lc_rd_reg(CNTST_LMT, 0); + else + pr_info("unsupprt cmd!\n"); + } else if (!strcmp(parm[0], "dump_lut_str")) { + if (kstrtoul(parm[1], 16, &val) < 0) + goto free_buf; + reg_sel = val; + if (reg_sel == SATUR_LUT) + lc_rd_reg(SATUR_LUT, 1); + else if (reg_sel == YMINVAL_LMT) + lc_rd_reg(YMINVAL_LMT, 1); + else if (reg_sel == YPKBV_YMAXVAL_LMT) + lc_rd_reg(YPKBV_YMAXVAL_LMT, 1); + else if (reg_sel == YPKBV_RAT) + lc_rd_reg(YPKBV_RAT, 1); + else + pr_info("unsupprt cmd!\n"); + } else if (!strcmp(parm[0], "lc_wr_lut")) { + if (kstrtoul(parm[1], 16, &val) < 0) + goto free_buf; + reg_sel = val; + if (parm[2] == NULL) + goto free_buf; + str_sapr_to_d(parm[2], reg_lut, 5); + if (reg_sel == SATUR_LUT) + lc_wr_reg(reg_lut, SATUR_LUT); + else if (reg_sel == YMINVAL_LMT) + lc_wr_reg(reg_lut, YMINVAL_LMT); + else if (reg_sel == YPKBV_YMAXVAL_LMT) + lc_wr_reg(reg_lut, YPKBV_YMAXVAL_LMT); + else if (reg_sel == YPKBV_RAT) + lc_wr_reg(reg_lut, YPKBV_RAT); + else if (reg_sel == YPKBV_SLP_LMT) + lc_wr_reg(reg_lut, YPKBV_SLP_LMT); + else if (reg_sel == CNTST_LMT) + lc_wr_reg(reg_lut, CNTST_LMT); + else + pr_info("unsupprt cmd!\n"); + } else if (!strcmp(parm[0], "dump_hist")) { + if (!strcmp(parm[1], "all")) { + /*dump all hist of one frame*/ + lc_hist_prcnt = 1; + amlc_debug = 0x8; + } else if (!strcmp(parm[1], "chosen")) { + /*dump multiple frames in selected area*/ + if (parm[6] == NULL) + goto free_buf; + if (kstrtoul(parm[2], 10, &val) < 0) + goto free_buf; + lc_hist_hs = val; + if (kstrtoul(parm[3], 10, &val) < 0) + goto free_buf; + lc_hist_he = val; + if (kstrtoul(parm[4], 10, &val) < 0) + goto free_buf; + lc_hist_vs = val; + if (kstrtoul(parm[5], 10, &val) < 0) + goto free_buf; + lc_hist_ve = val; + if (kstrtoul(parm[6], 10, &val) < 0) + goto free_buf; + lc_hist_prcnt = val; + amlc_debug = 0x6; + } else + pr_info("unsupprt cmd!\n"); + } else if (!strcmp(parm[0], "dump_curve")) { + if (kstrtoul(parm[1], 10, &val) < 0) + goto free_buf; + lc_curve_prcnt = val; + } else if (!strcmp(parm[0], "lc_osd_setting")) { + if (!strcmp(parm[1], "show")) { + pr_info("VNUM_STRT_BELOW: %d, VNUM_END_BELOW: %d\n", + vnum_start_below, vnum_end_below); + pr_info("VNUM_STRT_ABOVE: %d, VNUM_END_ABOVE: %d\n", + vnum_start_above, vnum_end_above); + pr_info("INVALID_BLK: %d, MIN_BV_PERCENT_TH: %d\n", + invalid_blk, min_bv_percent_th); + } else if (!strcmp(parm[1], "set")) { + if (parm[7] == NULL) + goto free_buf; + if (kstrtoul(parm[2], 10, &val) < 0) + goto free_buf; + vnum_start_below = val; + if (kstrtoul(parm[3], 10, &val) < 0) + goto free_buf; + vnum_end_below = val; + if (kstrtoul(parm[4], 10, &val) < 0) + goto free_buf; + vnum_start_above = val; + if (kstrtoul(parm[5], 10, &val) < 0) + goto free_buf; + vnum_end_above = val; + if (kstrtoul(parm[6], 10, &val) < 0) + goto free_buf; + invalid_blk = val; + if (kstrtoul(parm[7], 10, &val) < 0) + goto free_buf; + min_bv_percent_th = val; + } else + pr_info("unsupprt cmd!\n"); + } else if (!strcmp(parm[0], "osd_iir_en")) { + if (kstrtoul(parm[1], 10, &val) < 0) + goto free_buf; + osd_iir_en = val; + } else if (!strcmp(parm[0], "iir_refresh")) { + if (!strcmp(parm[1], "show")) { + pr_info("current state: alpha1: %d, alpha2: %d, refresh_bit: %d, ts: %d\n", + alpha1, alpha2, refresh_bit, ts); + } else if (!strcmp(parm[1], "set")) { + if (parm[5] == NULL) + goto free_buf; + if (kstrtoul(parm[2], 10, &val) < 0) + goto free_buf; + alpha1 = val; + if (kstrtoul(parm[3], 10, &val) < 0) + goto free_buf; + alpha2 = val; + if (kstrtoul(parm[4], 10, &val) < 0) + goto free_buf; + refresh_bit = val; + if (kstrtoul(parm[5], 10, &val) < 0) + goto free_buf; + ts = val; + pr_info("after setting: alpha1: %d, alpha2: %d, refresh_bit: %d, ts: %d\n", + alpha1, alpha2, refresh_bit, ts); + } else + pr_info("unsupprt cmd!\n"); + } else if (!strcmp(parm[0], "scene_change_th")) { + pr_info("current value: %d\n", scene_change_th); + if (kstrtoul(parm[1], 10, &val) < 0) + goto free_buf; + scene_change_th = val; + pr_info("setting value: %d\n", scene_change_th); + } else if (!strcmp(parm[0], "irr_dbg_en")) { + pr_info("current value: %d\n", amlc_iir_debug_en); + if (kstrtoul(parm[1], 10, &val) < 0) + goto free_buf; + amlc_iir_debug_en = val; + pr_info("setting value: %d\n", amlc_iir_debug_en); + } else if (!strcmp(parm[0], "get_blk_region")) { + val = READ_VPP_REG(LC_CURVE_HV_NUM); + h = (val >> 8) & 0x1f; + v = (val) & 0x1f; + if (!strcmp(parm[1], "htotal")) + pr_info("%d\n", h); + else if (!strcmp(parm[1], "vtotal")) + pr_info("%d\n", v); + else + pr_info("unsupprt cmd!\n"); + } else if (!strcmp(parm[0], "get_hist")) { + if (kstrtoul(parm[1], 10, &val) < 0) + goto free_buf; + h = val; + if (kstrtoul(parm[2], 10, &val) < 0) + goto free_buf; + v = val; + if ((h > 11) || (v > 7)) + goto free_buf; + start_point = (12*v+h)*17; + for (i = 0; i < 17; i++) + d_convert_str(lc_hist[start_point + i] >> 4, + i, stemp, 4, 10); + pr_info("%s\n", stemp); + } else if (!strcmp(parm[0], "get_curve")) { + if (kstrtoul(parm[1], 10, &val) < 0) + goto free_buf; + h = val; + if (kstrtoul(parm[2], 10, &val) < 0) + goto free_buf; + v = val; + if ((h > 11) || (v > 7)) + goto free_buf; + start_point = (12*v+h)*6; + for (i = 0; i < 6; i++) + d_convert_str(curve_nodes_cur[start_point + i], + i, stemp, 4, 10); + pr_info("%s\n", stemp); + } else if (!strcmp(parm[0], "set_curve")) { + if (parm[3] == NULL) + goto free_buf; + if (kstrtoul(parm[1], 10, &val) < 0) + goto free_buf; + h = val; + if (kstrtoul(parm[2], 10, &val) < 0) + goto free_buf; + v = val; + if ((h > 11) || (v > 7)) + goto free_buf; + start_point = (12*v+h)*6; + str_sapr_to_d(parm[3], curve_val, 5); + for (i = 0; i < 6; i++) + curve_nodes_cur[start_point + i] + = curve_val[i]; + } else if (!strcmp(parm[0], "stop_refresh")) + lc_curve_fresh = false; + else if (!strcmp(parm[0], "refresh_curve")) + lc_curve_fresh = true; + else pr_info("unsupprt cmd!\n"); kfree(buf_orig); + kfree(stemp); return count; + +free_buf: + pr_info("Missing parameters !\n"); + kfree(buf_orig); + kfree(stemp); + return -EINVAL; } +static void def_hdr_sdr_mode(void) +{ + sdr_mode = 0; +} /* #if (MESON_CPU_TYPE == MESON_CPU_TYPE_MESONG9TV) */ void init_pq_setting(void) { - if (get_cpu_type() == MESON_CPU_MAJOR_ID_TL1) { + + int bitdepth; + + if (is_meson_gxtvbb_cpu() || is_meson_txl_cpu() || + is_meson_txlx_cpu() || is_meson_txhd_cpu() || + is_meson_tl1_cpu() || is_meson_tm2_cpu()) + goto tvchip_pq_setting; + else if (is_meson_g12a_cpu() || is_meson_g12b_cpu() || + is_meson_sm1_cpu()) { + sr_offset[0] = SR0_OFFSET; + bitdepth = 12; + /*confirm with vlsi-Lunhai.Chen, for G12A/G12B, + *VPP_GCLK_CTRL1 must enable + */ + WRITE_VPP_REG_BITS(VPP_GCLK_CTRL1, 0xf, 0, 4); + cm_init_config(bitdepth); + /*dnlp off*/ + WRITE_VPP_REG_BITS(VPP_VE_ENABLE_CTRL, 0, + DNLP_EN_BIT, DNLP_EN_WID); + /*sr0 chroma filter bypass*/ + WRITE_VPP_REG(SRSHARP0_SHARP_SR2_CBIC_HCOEF0 + sr_offset[0], + 0x4000); + WRITE_VPP_REG(SRSHARP0_SHARP_SR2_CBIC_VCOEF0 + sr_offset[0], + 0x4000); + + /*kernel sdr2hdr match uboot setting*/ + def_hdr_sdr_mode(); + } + return; + +tvchip_pq_setting: + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) { + if (is_meson_tl1_cpu()) + bitdepth = 10; + else if (is_meson_tm2_cpu()) + bitdepth = 12; + else + bitdepth = 12; /*sr0 & sr1 register shfit*/ sr_offset[0] = SR0_OFFSET; sr_offset[1] = SR1_OFFSET; /*cm register init*/ - cm_init_config(); + cm_init_config(bitdepth); /*lc init*/ - lc_init(); + lc_init(bitdepth); } /*probe close sr0 peaking for switch on video*/ WRITE_VPP_REG_BITS(VPP_SRSHARP0_CTRL, 1, 0, 1); @@ -5459,16 +6319,16 @@ void amvecm_gamma_init(bool en) unsigned int i; unsigned short data[256]; + for (i = 0; i < 256; i++) { + data[i] = i << 2; + video_gamma_table_r.data[i] = data[i]; + video_gamma_table_g.data[i] = data[i]; + video_gamma_table_b.data[i] = data[i]; + } + if (en) { WRITE_VPP_REG_BITS(L_GAMMA_CNTL_PORT, 0, GAMMA_EN, 1); - - for (i = 0; i < 256; i++) { - data[i] = i << 2; - video_gamma_table_r.data[i] = data[i]; - video_gamma_table_g.data[i] = data[i]; - video_gamma_table_b.data[i] = data[i]; - } amve_write_gamma_table( data, H_SEL_R); @@ -5673,11 +6533,40 @@ static const struct file_operations amvecm_fops = { #endif .poll = amvecm_poll, }; + +static const struct vecm_match_data_s vecm_dt_xxx = { + .vlk_support = true, + .vlk_new_fsm = 0, + .vlk_hwver = vlock_hw_org, + .vlk_phlock_en = false, +}; + +static const struct vecm_match_data_s vecm_dt_tl1 = { + .vlk_support = true, + .vlk_new_fsm = 1, + .vlk_hwver = vlock_hw_ver2, + .vlk_phlock_en = true, +}; + +static const struct of_device_id aml_vecm_dt_match[] = { + { + .compatible = "amlogic, vecm", + .data = &vecm_dt_xxx, + }, + { + .compatible = "amlogic, vecm-tl1", + .data = &vecm_dt_tl1, + }, + {}, +}; + static void aml_vecm_dt_parse(struct platform_device *pdev) { struct device_node *node; unsigned int val; int ret; + const struct of_device_id *of_id; + struct vecm_match_data_s *matchdata; node = pdev->dev.of_node; /* get integer value */ @@ -5716,12 +6605,24 @@ static void aml_vecm_dt_parse(struct platform_device *pdev) pr_info("Can't find tx_op_color_primary.\n"); else tx_op_color_primary = val; + + /*get compatible matched device, to get chip related data*/ + of_id = of_match_device(aml_vecm_dt_match, &pdev->dev); + if (of_id != NULL) { + pr_info("%s", of_id->compatible); + matchdata = (struct vecm_match_data_s *)of_id->data; + } else { + matchdata = (struct vecm_match_data_s *)&vecm_dt_xxx; + pr_info("unable to get matched device\n"); + } + vlock_dt_match_init(matchdata); + /*vlock param config*/ vlock_param_config(node); } /* init module status */ amvecm_wb_init(wb_en); - amvecm_gamma_init(gamma_en); + amvecm_gamma_init(0); #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION if (!is_dolby_vision_enable()) #endif @@ -5812,11 +6713,7 @@ static int aml_vecm_probe(struct platform_device *pdev) /* register vout client */ vout_register_client(&vlock_notifier_nb); - /* #if (MESON_CPU_TYPE == MESON_CPU_TYPE_MESONG9TV) */ - if (is_meson_gxtvbb_cpu() || is_meson_txl_cpu() || - is_meson_txlx_cpu() || is_meson_txhd_cpu() || - is_meson_tl1_cpu()) - init_pq_setting(); + init_pq_setting(); /* #endif */ vpp_get_hist_en(); @@ -5840,21 +6737,9 @@ static int aml_vecm_probe(struct platform_device *pdev) else hdr_flag = (1 << 0) | (1 << 1) | (0 << 2) | (0 << 3); - if (is_meson_g12a_cpu() || is_meson_g12b_cpu()) - sdr_mode = 2; - - /*config vlock mode*/ - /*todo:txlx & g9tv support auto pll,*/ - /*but support not good,need vlsi support optimize*/ - vlock_mode = VLOCK_MODE_MANUAL_PLL; - if (is_meson_gxtvbb_cpu() || - is_meson_txl_cpu() || is_meson_txlx_cpu() - || is_meson_txhd_cpu()) - vlock_en = 1; - else - vlock_en = 0; hdr_init(&amvecm_dev.hdr_d); aml_vecm_dt_parse(pdev); + vlock_status_init(); probe_ok = 1; pr_info("%s: ok\n", __func__); @@ -5895,6 +6780,7 @@ static int __exit aml_vecm_remove(struct platform_device *pdev) cancel_work_sync(&aml_lcd_vlock_param_work); #endif probe_ok = 0; + lc_free(); pr_info("[amvecm.] : amvecm_exit.\n"); return 0; } @@ -5940,15 +6826,9 @@ static void amvecm_shutdown(struct platform_device *pdev) #ifdef CONFIG_AML_LCD aml_lcd_notifier_unregister(&aml_lcd_gamma_nb); #endif + lc_free(); } -static const struct of_device_id aml_vecm_dt_match[] = { - { - .compatible = "amlogic, vecm", - }, - {}, -}; - static struct platform_driver aml_vecm_driver = { .driver = { .name = "aml_vecm", @@ -5967,16 +6847,19 @@ static struct platform_driver aml_vecm_driver = { static int __init aml_vecm_init(void) { - unsigned int hiu_reg_base; + /*unsigned int hiu_reg_base;*/ pr_info("%s:module init\n", __func__); + #if 0 /* remap the hiu bus */ if (is_meson_txlx_cpu() || is_meson_txhd_cpu() || - is_meson_g12a_cpu() || is_meson_g12b_cpu()) + is_meson_g12a_cpu() || is_meson_g12b_cpu() + || is_meson_tl1_cpu()) hiu_reg_base = 0xff63c000; else hiu_reg_base = 0xc883c000; amvecm_hiu_reg_base = ioremap(hiu_reg_base, 0x2000); + #endif if (platform_driver_register(&aml_vecm_driver)) { pr_err("failed to register bl driver module\n"); return -ENODEV; @@ -5988,7 +6871,7 @@ static int __init aml_vecm_init(void) static void __exit aml_vecm_exit(void) { pr_info("%s:module exit\n", __func__); - iounmap(amvecm_hiu_reg_base); + /*iounmap(amvecm_hiu_reg_base);*/ platform_driver_unregister(&aml_vecm_driver); } diff --git a/drivers/amlogic/media/enhancement/amvecm/amvecm_vlock_regmap.h b/drivers/amlogic/media/enhancement/amvecm/amvecm_vlock_regmap.h index bdd4737d4570..45e74bfaa81b 100644 --- a/drivers/amlogic/media/enhancement/amvecm/amvecm_vlock_regmap.h +++ b/drivers/amlogic/media/enhancement/amvecm/amvecm_vlock_regmap.h @@ -27,34 +27,35 @@ struct vlock_regs_s { #define VLOCK_DEFAULT_REG_SIZE 20 static struct vlock_regs_s vlock_enc_setting[VLOCK_DEFAULT_REG_SIZE] = { /* optimize */ - {0x3000, 0xE3f50f10 }, + {0x3000, 0xE3f53f10 }, {0x3001, 0x41E3c3c }, - {0x3002, 0x6000000 }, - {0x3003, 0x20680680 }, - {0x3004, 0x280280 }, + {0x3002, 0x8000/*0x6000000*/ }, + {0x3003, 0x20709709/*0x20680680 */}, + {0x3004, 0x00709709/*0x280280 */}, {0x3005, 0x8020000 }, {0x3006, 0x0008000 }, {0x3007, 0x0000000 }, {0x3008, 0x0000000 }, - {0x3009, 0x0008000 }, + {0x3009, 0x8000/*x60000000 x0008000 */}, {0x300a, 0x8000000 }, {0x300b, 0x000a000 }, {0x300c, 0xa000000 }, {0x300d, 0x0004000 }, - {0x3010, 0x20001000 }, + {0x3010, 0x8ca/*0x20001000*/ }, {0x3016, 0x18000 }, {0x3017, 0x01080 }, {0x301d, 0x30501080 }, {0x301e, 0x7 }, {0x301f, 0x6000000 }, }; + static struct vlock_regs_s vlock_pll_setting[VLOCK_DEFAULT_REG_SIZE] = { /* optimize */ {0x3000, 0x07f13f1a }, {0x3001, 0x04053c32 }, {0x3002, 0x06000000 }, {0x3003, 0x20780780 }, - {0x3004, 0x00000000 }, + {0x3004, 0x00680680 }, {0x3005, 0x00080000 }, {0x3006, 0x00070000 }, {0x3007, 0x00000000 }, @@ -62,15 +63,28 @@ static struct vlock_regs_s vlock_pll_setting[VLOCK_DEFAULT_REG_SIZE] = { {0x3009, 0x00100000 }, {0x300a, 0x00600000 }, {0x300b, 0x00100000 }, - {0x300c, 0x00000000 }, + {0x300c, 0x00600000 }, {0x300d, 0x00004000 }, {0x3010, 0x20001000 }, {0x3016, 0x0003de00 }, - {0x3017, 0x00001080 }, + {0x3017, 0x00001010 }, {0x301d, 0x30501080 }, {0x301e, 0x00000007 }, {0x301f, 0x06000000 } }; +#define VLOCK_PHASE_REG_SIZE 9 +static struct vlock_regs_s vlock_pll_phase_setting[VLOCK_PHASE_REG_SIZE] = { + {0x3004, 0x00604680}, + {0x3009, 0x06000000}, + {0x300a, 0x00600000}, + {0x300b, 0x06000000}, + {0x300c, 0x00600000}, + {0x3025, 0x00002000}, + {0x3027, 0x00022002}, + {0x3028, 0x00001000}, + {0x302a, 0x00022002}, +}; + #endif diff --git a/drivers/amlogic/media/enhancement/amvecm/arch/vpp_dolbyvision_regs.h b/drivers/amlogic/media/enhancement/amvecm/arch/vpp_dolbyvision_regs.h index 0651c43e527e..cfc91d17397d 100644 --- a/drivers/amlogic/media/enhancement/amvecm/arch/vpp_dolbyvision_regs.h +++ b/drivers/amlogic/media/enhancement/amvecm/arch/vpp_dolbyvision_regs.h @@ -18,78 +18,101 @@ #ifndef VPP_DOLBYVISION_REGS_H #define VPP_DOLBYVISION_REGS_H -#define DOLBY_CORE1_REG_START 0x3300 -#define DOLBY_CORE1_CLKGATE_CTRL 0x33f2 -#define DOLBY_CORE1_SWAP_CTRL0 0x33f3 -#define DOLBY_CORE1_SWAP_CTRL1 0x33f4 -#define DOLBY_CORE1_SWAP_CTRL2 0x33f5 -#define DOLBY_CORE1_SWAP_CTRL3 0x33f6 -#define DOLBY_CORE1_SWAP_CTRL4 0x33f7 -#define DOLBY_CORE1_SWAP_CTRL5 0x33f8 -#define DOLBY_CORE1_DMA_CTRL 0x33f9 -#define DOLBY_CORE1_DMA_STATUS 0x33fa -#define DOLBY_CORE1_STATUS0 0x33fb -#define DOLBY_CORE1_STATUS1 0x33fc -#define DOLBY_CORE1_STATUS2 0x33fd -#define DOLBY_CORE1_STATUS3 0x33fe -#define DOLBY_CORE1_DMA_PORT 0x33ff +#define CORE1_OFFSET (0x1UL << 24) +#define CORE1_1_OFFSET (0x1UL << 25) +#define CORE2A_OFFSET (0x1UL << 26) +#define CORE3_OFFSET (0x1UL << 27) +#define CORETV_OFFSET (0x1UL << 28) -#define DOLBY_CORE2A_REG_START 0x3400 -#define DOLBY_CORE2A_CTRL 0x3401 -#define DOLBY_CORE2A_CLKGATE_CTRL 0x3432 -#define DOLBY_CORE2A_SWAP_CTRL0 0x3433 -#define DOLBY_CORE2A_SWAP_CTRL1 0x3434 -#define DOLBY_CORE2A_SWAP_CTRL2 0x3435 -#define DOLBY_CORE2A_SWAP_CTRL3 0x3436 -#define DOLBY_CORE2A_SWAP_CTRL4 0x3437 -#define DOLBY_CORE2A_SWAP_CTRL5 0x3438 -#define DOLBY_CORE2A_DMA_CTRL 0x3439 -#define DOLBY_CORE2A_DMA_STATUS 0x343a -#define DOLBY_CORE2A_STATUS0 0x343b -#define DOLBY_CORE2A_STATUS1 0x343c -#define DOLBY_CORE2A_STATUS2 0x343d -#define DOLBY_CORE2A_STATUS3 0x343e -#define DOLBY_CORE2A_DMA_PORT 0x343f +#define DOLBY_CORE1_REG_START (0x00 + CORE1_OFFSET) +#define DOLBY_CORE1_CLKGATE_CTRL (0xf2 + CORE1_OFFSET) +#define DOLBY_CORE1_SWAP_CTRL0 (0xf3 + CORE1_OFFSET) +#define DOLBY_CORE1_SWAP_CTRL1 (0xf4 + CORE1_OFFSET) +#define DOLBY_CORE1_SWAP_CTRL2 (0xf5 + CORE1_OFFSET) +#define DOLBY_CORE1_SWAP_CTRL3 (0xf6 + CORE1_OFFSET) +#define DOLBY_CORE1_SWAP_CTRL4 (0xf7 + CORE1_OFFSET) +#define DOLBY_CORE1_SWAP_CTRL5 (0xf8 + CORE1_OFFSET) +#define DOLBY_CORE1_DMA_CTRL (0xf9 + CORE1_OFFSET) +#define DOLBY_CORE1_DMA_STATUS (0xfa + CORE1_OFFSET) +#define DOLBY_CORE1_STATUS0 (0xfb + CORE1_OFFSET) +#define DOLBY_CORE1_STATUS1 (0xfc + CORE1_OFFSET) +#define DOLBY_CORE1_STATUS2 (0xfd + CORE1_OFFSET) +#define DOLBY_CORE1_STATUS3 (0xfe + CORE1_OFFSET) +#define DOLBY_CORE1_DMA_PORT (0xff + CORE1_OFFSET) -#define DOLBY_CORE3_REG_START 0x3600 -#define DOLBY_CORE3_CLKGATE_CTRL 0x36f0 -#define DOLBY_CORE3_SWAP_CTRL0 0x36f1 -#define DOLBY_CORE3_SWAP_CTRL1 0x36f2 -#define DOLBY_CORE3_SWAP_CTRL2 0x36f3 -#define DOLBY_CORE3_SWAP_CTRL3 0x36f4 -#define DOLBY_CORE3_SWAP_CTRL4 0x36f5 -#define DOLBY_CORE3_SWAP_CTRL5 0x36f6 -#define DOLBY_CORE3_SWAP_CTRL6 0x36f7 -#define DOLBY_CORE3_DIAG_CTRL 0x36f8 +#define DOLBY_CORE1_1_REG_START (0x00 + CORE1_1_OFFSET) +#define DOLBY_CORE1_1_CLKGATE_CTRL (0xf2 + CORE1_1_OFFSET) +#define DOLBY_CORE1_1_SWAP_CTRL0 (0xf3 + CORE1_1_OFFSET) +#define DOLBY_CORE1_1_SWAP_CTRL1 (0xf4 + CORE1_1_OFFSET) +#define DOLBY_CORE1_1_SWAP_CTRL2 (0xf5 + CORE1_1_OFFSET) +#define DOLBY_CORE1_1_SWAP_CTRL3 (0xf6 + CORE1_1_OFFSET) +#define DOLBY_CORE1_1_SWAP_CTRL4 (0xf7 + CORE1_1_OFFSET) +#define DOLBY_CORE1_1_SWAP_CTRL5 (0xf8 + CORE1_1_OFFSET) +#define DOLBY_CORE1_1_DMA_CTRL (0xf9 + CORE1_1_OFFSET) +#define DOLBY_CORE1_1_DMA_STATUS (0xfa + CORE1_1_OFFSET) +#define DOLBY_CORE1_1_STATUS0 (0xfb + CORE1_1_OFFSET) +#define DOLBY_CORE1_1_STATUS1 (0xfc + CORE1_1_OFFSET) +#define DOLBY_CORE1_1_STATUS2 (0xfd + CORE1_1_OFFSET) +#define DOLBY_CORE1_1_STATUS3 (0xfe + CORE1_1_OFFSET) +#define DOLBY_CORE1_1_DMA_PORT (0xff + CORE1_1_OFFSET) -#define DOLBY_CORE3_CRC_CTRL 0x36fb -#define DOLBY_CORE3_INPUT_CSC_CRC 0x36fc -#define DOLBY_CORE3_OUTPUT_CSC_CRC 0x36fd -#define VPP_WRAP_OSD1_MATRIX_EN_CTRL 0x3d6d -#define VPP_WRAP_OSD2_MATRIX_EN_CTRL 0x3d7d -#define VPP_WRAP_OSD3_MATRIX_EN_CTRL 0x3dbd +#define DOLBY_CORE2A_REG_START (0x00 + CORE2A_OFFSET) +#define DOLBY_CORE2A_CTRL (0x01 + CORE2A_OFFSET) +#define DOLBY_CORE2A_CLKGATE_CTRL (0x32 + CORE2A_OFFSET) +#define DOLBY_CORE2A_SWAP_CTRL0 (0x33 + CORE2A_OFFSET) +#define DOLBY_CORE2A_SWAP_CTRL1 (0x34 + CORE2A_OFFSET) +#define DOLBY_CORE2A_SWAP_CTRL2 (0x35 + CORE2A_OFFSET) +#define DOLBY_CORE2A_SWAP_CTRL3 (0x36 + CORE2A_OFFSET) +#define DOLBY_CORE2A_SWAP_CTRL4 (0x37 + CORE2A_OFFSET) +#define DOLBY_CORE2A_SWAP_CTRL5 (0x38 + CORE2A_OFFSET) +#define DOLBY_CORE2A_DMA_CTRL (0x39 + CORE2A_OFFSET) +#define DOLBY_CORE2A_DMA_STATUS (0x3a + CORE2A_OFFSET) +#define DOLBY_CORE2A_STATUS0 (0x3b + CORE2A_OFFSET) +#define DOLBY_CORE2A_STATUS1 (0x3c + CORE2A_OFFSET) +#define DOLBY_CORE2A_STATUS2 (0x3d + CORE2A_OFFSET) +#define DOLBY_CORE2A_STATUS3 (0x3e + CORE2A_OFFSET) +#define DOLBY_CORE2A_DMA_PORT (0x3f + CORE2A_OFFSET) +#define DOLBY_CORE3_REG_START (0x00 + CORE3_OFFSET) +#define DOLBY_CORE3_CLKGATE_CTRL (0xf0 + CORE3_OFFSET) +#define DOLBY_CORE3_SWAP_CTRL0 (0xf1 + CORE3_OFFSET) +#define DOLBY_CORE3_SWAP_CTRL1 (0xf2 + CORE3_OFFSET) +#define DOLBY_CORE3_SWAP_CTRL2 (0xf3 + CORE3_OFFSET) +#define DOLBY_CORE3_SWAP_CTRL3 (0xf4 + CORE3_OFFSET) +#define DOLBY_CORE3_SWAP_CTRL4 (0xf5 + CORE3_OFFSET) +#define DOLBY_CORE3_SWAP_CTRL5 (0xf6 + CORE3_OFFSET) +#define DOLBY_CORE3_SWAP_CTRL6 (0xf7 + CORE3_OFFSET) +#define DOLBY_CORE3_DIAG_CTRL (0xf8 + CORE3_OFFSET) +#define DOLBY_CORE3_CRC_CTRL (0xfb + CORE3_OFFSET) +#define DOLBY_CORE3_INPUT_CSC_CRC (0xfc + CORE3_OFFSET) +#define DOLBY_CORE3_OUTPUT_CSC_CRC (0xfd + CORE3_OFFSET) + +#define DOLBY_TV_REG_START (0x00 + CORETV_OFFSET) +#define DOLBY_TV_CLKGATE_CTRL (0xf1 + CORETV_OFFSET) +#define DOLBY_TV_SWAP_CTRL0 (0xf2 + CORETV_OFFSET) +#define DOLBY_TV_SWAP_CTRL1 (0xf3 + CORETV_OFFSET) +#define DOLBY_TV_SWAP_CTRL2 (0xf4 + CORETV_OFFSET) +#define DOLBY_TV_SWAP_CTRL3 (0xf5 + CORETV_OFFSET) +#define DOLBY_TV_SWAP_CTRL4 (0xf6 + CORETV_OFFSET) +#define DOLBY_TV_SWAP_CTRL5 (0xf7 + CORETV_OFFSET) +#define DOLBY_TV_SWAP_CTRL6 (0xf8 + CORETV_OFFSET) +#define DOLBY_TV_SWAP_CTRL7 (0xf9 + CORETV_OFFSET) +#define DOLBY_TV_AXI2DMA_CTRL0 (0xfa + CORETV_OFFSET) +#define DOLBY_TV_AXI2DMA_CTRL1 (0xfb + CORETV_OFFSET) +#define DOLBY_TV_AXI2DMA_CTRL2 (0xfc + CORETV_OFFSET) +#define DOLBY_TV_AXI2DMA_CTRL3 (0xfd + CORETV_OFFSET) +#define DOLBY_TV_STATUS0 (0xfe + CORETV_OFFSET) +#define DOLBY_TV_STATUS1 (0xff + CORETV_OFFSET) + + +#define VPP_WRAP_OSD1_MATRIX_EN_CTRL 0x3d6d +#define VPP_WRAP_OSD2_MATRIX_EN_CTRL 0x3d7d +#define VPP_WRAP_OSD3_MATRIX_EN_CTRL 0x3dbd #define DOLBY_PATH_CTRL 0x1a0c #define VIU_MISC_CTRL1 0x1a07 #define VPP_DOLBY_CTRL 0x1d93 #define VIU_SW_RESET 0x1a01 #define VPU_HDMI_FMT_CTRL 0x2743 -#define DOLBY_TV_REG_START 0x3300 -#define DOLBY_TV_CLKGATE_CTRL 0x33f1 -#define DOLBY_TV_SWAP_CTRL0 0x33f2 -#define DOLBY_TV_SWAP_CTRL1 0x33f3 -#define DOLBY_TV_SWAP_CTRL2 0x33f4 -#define DOLBY_TV_SWAP_CTRL3 0x33f5 -#define DOLBY_TV_SWAP_CTRL4 0x33f6 -#define DOLBY_TV_SWAP_CTRL5 0x33f7 -#define DOLBY_TV_SWAP_CTRL6 0x33f8 -#define DOLBY_TV_SWAP_CTRL7 0x33f9 -#define DOLBY_TV_AXI2DMA_CTRL0 0x33fa -#define DOLBY_TV_AXI2DMA_CTRL1 0x33fb -#define DOLBY_TV_AXI2DMA_CTRL2 0x33fc -#define DOLBY_TV_AXI2DMA_CTRL3 0x33fd -#define DOLBY_TV_STATUS0 0x33fe -#define DOLBY_TV_STATUS1 0x33ff #if 0 /* core 1 display manager 24 registers */ struct dm_register_ipcore_1_s { diff --git a/drivers/amlogic/media/enhancement/amvecm/arch/vpp_keystone_regs.h b/drivers/amlogic/media/enhancement/amvecm/arch/vpp_keystone_regs.h index 0e82be8b6ef3..fb401c329cbb 100644 --- a/drivers/amlogic/media/enhancement/amvecm/arch/vpp_keystone_regs.h +++ b/drivers/amlogic/media/enhancement/amvecm/arch/vpp_keystone_regs.h @@ -1,3 +1,20 @@ +/* + * drivers/amlogic/media/enhancement/amvecm/arch/vpp_keystone_regs.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 VPP_KEYSTONE_REGS_H #define VPP_KEYSTONE_REGS_H diff --git a/drivers/amlogic/media/enhancement/amvecm/arch/vpp_regs.h b/drivers/amlogic/media/enhancement/amvecm/arch/vpp_regs.h index ec7f6397a9ea..0f8e1bc534a9 100644 --- a/drivers/amlogic/media/enhancement/amvecm/arch/vpp_regs.h +++ b/drivers/amlogic/media/enhancement/amvecm/arch/vpp_regs.h @@ -331,7 +331,7 @@ #define VPU_VLOCK_RO_LINE_PIX_ADJ 0x3013 #define VPU_VLOCK_RO_OUTPUT_00_01 0x3014 #define VPU_VLOCK_RO_OUTPUT_10_11 0x3015 -#define VPU_VLOCK_MX4096 0x3016 +#define VPU_VLOCK_MX4096 0x3016 #define VPU_VLOCK_STBDET_WIN0_WIN1 0x3017 #define VPU_VLOCK_STBDET_CLP 0x3018 #define VPU_VLOCK_STBDET_ABS_WIN0 0x3019 @@ -339,9 +339,13 @@ #define VPU_VLOCK_STBDET_SGN_WIN0 0x301b #define VPU_VLOCK_STBDET_SGN_WIN1 0x301c #define VPU_VLOCK_ADJ_EN_SYNC_CTRL 0x301d -#define VPU_VLOCK_GCLK_EN 0x301e +#define VPU_VLOCK_GCLK_EN 0x301e #define VPU_VLOCK_LOOP1_ACCUM_LMT 0x301f #define VPU_VLOCK_RO_M_INT_FRAC 0x3020 +#define VPU_VLOCK_RO_PH_DIS 0x3021 +#define VPU_VLOCK_RO_PH_ERR 0x3022 +#define VPU_VLOCK_RO_LCK_TH 0x3023 +#define VPU_VLOCK_RO_LCK_FRM 0x3024 #define XVYCC_VD1_RGB_CTRST 0x3170 @@ -529,11 +533,19 @@ /*ve dither*/ #define VPP_VE_DITHER_CTRL 0x3120 +/* TL1 */ +/*offset 0x1000*/ +#define HHI_TCON_PLL_CNTL0 0x20 +#define HHI_TCON_PLL_CNTL1 0x21 +#define HHI_HDMI_PLL_VLOCK_CNTL 0xd1 + /* for pll bug */ -#define HHI_HDMI_PLL_CNTL 0x10c8 -#define HHI_HDMI_PLL_CNTL2 0x10c9 -#define HHI_VID_LOCK_CLK_CNTL 0x10f2 -#define HHI_HDMI_PLL_CNTL6 0x10cd + +#define HHI_HDMI_PLL_CNTL 0xc8 +#define HHI_HDMI_PLL_CNTL2 0xc9 +#define HHI_VID_LOCK_CLK_CNTL 0xf2 +#define HHI_HDMI_PLL_CNTL6 0xcd + /* for vlock enc mode adjust begin */ #define ENCL_VIDEO_MAX_LNCNT 0x1cbb #define ENCL_VIDEO_MAX_PXCNT 0x1cb0 @@ -552,13 +564,11 @@ #define ENCT_MAX_LINE_SWITCH_POINT 0x1c88 /* for vlock enc mode adjust end */ -#define HHI_VID_LOCK_CLK_CNTL 0x10f2 - #define VDIN_MEAS_VS_COUNT_LO 0x125c /*after GXL new add CNTL1,same with CNTL2 on G9TV/GXTVBB*/ -#define HHI_HDMI_PLL_CNTL1 0x10c9 +#define HHI_HDMI_PLL_CNTL1 0xc9 /*after GXL CNTL5[bit3] is same with CNTL6[bit20] on G9TV/GXTVBB*/ -#define HHI_HDMI_PLL_CNTL5 0x10cd +#define HHI_HDMI_PLL_CNTL5 0xcd /* #define VI_HIST_CTRL 0x2e00 */ diff --git a/drivers/amlogic/media/enhancement/amvecm/bitdepth.c b/drivers/amlogic/media/enhancement/amvecm/bitdepth.c index 558fffb092fa..ffabe341e99f 100644 --- a/drivers/amlogic/media/enhancement/amvecm/bitdepth.c +++ b/drivers/amlogic/media/enhancement/amvecm/bitdepth.c @@ -1,3 +1,20 @@ +/* + * drivers/amlogic/media/enhancement/amvecm/bitdepth.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 #include #include diff --git a/drivers/amlogic/media/enhancement/amvecm/bitdepth.h b/drivers/amlogic/media/enhancement/amvecm/bitdepth.h index 3b663770bec3..54cdce396fe2 100644 --- a/drivers/amlogic/media/enhancement/amvecm/bitdepth.h +++ b/drivers/amlogic/media/enhancement/amvecm/bitdepth.h @@ -1,3 +1,20 @@ +/* + * drivers/amlogic/media/enhancement/amvecm/bitdepth.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 BITDEPTH_H_ #define BITDEPTH_H_ diff --git a/drivers/amlogic/media/enhancement/amvecm/cm2_adj.h b/drivers/amlogic/media/enhancement/amvecm/cm2_adj.h index af816406600e..1745b50c42ee 100644 --- a/drivers/amlogic/media/enhancement/amvecm/cm2_adj.h +++ b/drivers/amlogic/media/enhancement/amvecm/cm2_adj.h @@ -1,3 +1,20 @@ +/* + * drivers/amlogic/media/enhancement/amvecm/cm2_adj.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 __CM2_ADJ__ #define __CM2_ADJ__ diff --git a/drivers/amlogic/media/enhancement/amvecm/dnlp_algorithm/dnlp_alg.h b/drivers/amlogic/media/enhancement/amvecm/dnlp_algorithm/dnlp_alg.h index 4b9dd616573b..5f63f5cc98d0 100644 --- a/drivers/amlogic/media/enhancement/amvecm/dnlp_algorithm/dnlp_alg.h +++ b/drivers/amlogic/media/enhancement/amvecm/dnlp_algorithm/dnlp_alg.h @@ -1,3 +1,19 @@ +/* + * drivers/amlogic/media/enhancement/amvecm/dnlp_algorithm/dnlp_alg.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ #ifndef __AM_DNLP_AGL_H #define __AM_DNLP_AGL_H @@ -60,6 +76,26 @@ struct param_for_dnlp_s { unsigned int dnlp_scurv_hgh1_th; unsigned int dnlp_scurv_hgh2_th; unsigned int dnlp_mtdrate_adp_en; + unsigned int dnlp_clahe_method; + unsigned int dnlp_ble_en; + unsigned int dnlp_norm; + unsigned int dnlp_scn_chg_th; + unsigned int dnlp_step_th; + unsigned int dnlp_iir_step_mux; + unsigned int dnlp_single_bin_bw; + unsigned int dnlp_single_bin_method; + unsigned int dnlp_reg_max_slop_1st; + unsigned int dnlp_reg_max_slop_mid; + unsigned int dnlp_reg_max_slop_fin; + unsigned int dnlp_reg_min_slop_1st; + unsigned int dnlp_reg_min_slop_mid; + unsigned int dnlp_reg_min_slop_fin; + unsigned int dnlp_reg_trend_wht_expand_mode; + unsigned int dnlp_reg_trend_blk_expand_mode; + unsigned int dnlp_ve_hist_cur_gain; + unsigned int dnlp_ve_hist_cur_gain_precise; + unsigned int dnlp_reg_mono_binrang_st; + unsigned int dnlp_reg_mono_binrang_ed; }; struct dnlp_alg_input_param_s { @@ -96,8 +132,12 @@ struct dnlp_dbg_rw_param_s { int *dnlp_scurv_hgh2; int *gain_var_lut49; int *wext_gain; + int *adp_thrd; + int *reg_blk_boost_12; + int *reg_adp_ofset_20; + int *reg_mono_protect; + int *reg_trend_wht_expand_lut8; }; - struct dnlp_dbg_print_s { int *dnlp_printk; }; diff --git a/drivers/amlogic/media/enhancement/amvecm/dnlp_cal.c b/drivers/amlogic/media/enhancement/amvecm/dnlp_cal.c index 299e4f4083c8..bd88c513664e 100644 --- a/drivers/amlogic/media/enhancement/amvecm/dnlp_cal.c +++ b/drivers/amlogic/media/enhancement/amvecm/dnlp_cal.c @@ -1,3 +1,20 @@ +/* + * drivers/amlogic/media/enhancement/amvecm/dnlp_cal.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 #include #include @@ -52,6 +69,11 @@ int *dnlp_scurv_hgh1_copy; int *dnlp_scurv_hgh2_copy; int *gain_var_lut49_copy; int *wext_gain_copy; +int *adp_thrd_copy; +int *reg_blk_boost_12_copy; +int *reg_adp_ofset_20_copy; +int *reg_mono_protect_copy; +int *reg_trend_wht_expand_lut8_copy; int *ro_luma_avg4_copy; int *ro_var_d8_copy; @@ -137,6 +159,29 @@ struct dnlp_parse_cmd_s dnlp_parse_cmd[] = { {"scurv_hgh1_th", &(dnlp_alg_param.dnlp_scurv_hgh1_th)}, {"scurv_hgh2_th", &(dnlp_alg_param.dnlp_scurv_hgh2_th)}, {"mtdrate_adp_en", &(dnlp_alg_param.dnlp_mtdrate_adp_en)}, + {"clahe_method", &(dnlp_alg_param.dnlp_clahe_method)}, + {"ble_en", &(dnlp_alg_param.dnlp_ble_en)}, + {"norm", &(dnlp_alg_param.dnlp_norm)}, + {"scn_chg_th", &(dnlp_alg_param.dnlp_scn_chg_th)}, + {"step_th", &(dnlp_alg_param.dnlp_step_th)}, + {"iir_step_mux", &(dnlp_alg_param.dnlp_iir_step_mux)}, + {"single_bin_bw", &(dnlp_alg_param.dnlp_single_bin_bw)}, + {"single_bin_method", &(dnlp_alg_param.dnlp_single_bin_method)}, + {"reg_max_slop_1st", &(dnlp_alg_param.dnlp_reg_max_slop_1st)}, + {"reg_max_slop_mid", &(dnlp_alg_param.dnlp_reg_max_slop_mid)}, + {"reg_max_slop_fin", &(dnlp_alg_param.dnlp_reg_max_slop_fin)}, + {"reg_min_slop_1st", &(dnlp_alg_param.dnlp_reg_min_slop_1st)}, + {"reg_min_slop_mid", &(dnlp_alg_param.dnlp_reg_min_slop_mid)}, + {"reg_min_slop_fin", &(dnlp_alg_param.dnlp_reg_min_slop_fin)}, + {"reg_trend_wht_expand_mode", + &(dnlp_alg_param.dnlp_reg_trend_wht_expand_mode)}, + {"reg_trend_blk_expand_mode", + &(dnlp_alg_param.dnlp_reg_trend_blk_expand_mode)}, + {"ve_hist_cur_gain", &(dnlp_alg_param.dnlp_ve_hist_cur_gain)}, + {"ve_hist_cur_gain_precise", + &(dnlp_alg_param.dnlp_ve_hist_cur_gain_precise)}, + {"reg_mono_binrang_st", &(dnlp_alg_param.dnlp_reg_mono_binrang_st)}, + {"reg_mono_binrang_ed", &(dnlp_alg_param.dnlp_reg_mono_binrang_ed)}, {"", NULL} }; @@ -149,6 +194,12 @@ void dnlp_alg_param_copy(void) dnlp_scurv_hgh2_copy = dnlp_dbg_rw_param->dnlp_scurv_hgh2; gain_var_lut49_copy = dnlp_dbg_rw_param->gain_var_lut49; wext_gain_copy = dnlp_dbg_rw_param->wext_gain; + adp_thrd_copy = dnlp_dbg_rw_param->adp_thrd; + reg_blk_boost_12_copy = dnlp_dbg_rw_param->reg_blk_boost_12; + reg_adp_ofset_20_copy = dnlp_dbg_rw_param->reg_adp_ofset_20; + reg_mono_protect_copy = dnlp_dbg_rw_param->reg_mono_protect; + reg_trend_wht_expand_lut8_copy = + dnlp_dbg_rw_param->reg_trend_wht_expand_lut8; ro_luma_avg4_copy = dnlp_dbg_ro_param->ro_luma_avg4; ro_var_d8_copy = dnlp_dbg_ro_param->ro_var_d8; @@ -240,6 +291,26 @@ void dnlp_alg_param_init(void) dnlp_alg_param.dnlp_scurv_hgh1_th = 176; dnlp_alg_param.dnlp_scurv_hgh2_th = 240; dnlp_alg_param.dnlp_mtdrate_adp_en = 1; + dnlp_alg_param.dnlp_clahe_method = 1; + dnlp_alg_param.dnlp_ble_en = 1; + dnlp_alg_param.dnlp_norm = 10; + dnlp_alg_param.dnlp_scn_chg_th = 48; + dnlp_alg_param.dnlp_step_th = 1; + dnlp_alg_param.dnlp_iir_step_mux = 1; + dnlp_alg_param.dnlp_single_bin_bw = 2; + dnlp_alg_param.dnlp_single_bin_method = 1; + dnlp_alg_param.dnlp_reg_max_slop_1st = 614; + dnlp_alg_param.dnlp_reg_max_slop_mid = 400; + dnlp_alg_param.dnlp_reg_max_slop_fin = 614; + dnlp_alg_param.dnlp_reg_min_slop_1st = 77; + dnlp_alg_param.dnlp_reg_min_slop_mid = 144; + dnlp_alg_param.dnlp_reg_min_slop_fin = 77; + dnlp_alg_param.dnlp_reg_trend_wht_expand_mode = 2; + dnlp_alg_param.dnlp_reg_trend_blk_expand_mode = 2; + dnlp_alg_param.dnlp_ve_hist_cur_gain = 8; + dnlp_alg_param.dnlp_ve_hist_cur_gain_precise = 8; + dnlp_alg_param.dnlp_reg_mono_binrang_st = 7; + dnlp_alg_param.dnlp_reg_mono_binrang_ed = 26; if (dnlp_alg_function != NULL) { dnlp_alg_function->dnlp_para_set(&dnlp_alg_output, @@ -483,6 +554,34 @@ void ve_set_v3_dnlp(struct ve_dnlp_curve_param_s *p) /* general settings */ if (dnlp_insmod_ok == 0) return; + /*load static curve*/ + memcpy(dnlp_scurv_low_copy, p->ve_dnlp_scurv_low, + sizeof(int) * DNLP_SCURV_LEN); + memcpy(dnlp_scurv_mid1_copy, p->ve_dnlp_scurv_mid1, + sizeof(int) * DNLP_SCURV_LEN); + memcpy(dnlp_scurv_mid2_copy, p->ve_dnlp_scurv_mid2, + sizeof(int) * DNLP_SCURV_LEN); + memcpy(dnlp_scurv_hgh1_copy, p->ve_dnlp_scurv_hgh1, + sizeof(int) * DNLP_SCURV_LEN); + memcpy(dnlp_scurv_hgh2_copy, p->ve_dnlp_scurv_hgh2, + sizeof(int) * DNLP_SCURV_LEN); + /*load gain var*/ + memcpy(gain_var_lut49_copy, p->ve_gain_var_lut49, + sizeof(int) * GAIN_VAR_LUT_LEN); + /*load wext gain*/ + memcpy(wext_gain_copy, p->ve_wext_gain, + sizeof(int) * WEXT_GAIN_LEN); + /*load new c curve lut for vlsi-kite.li*/ + memcpy(adp_thrd_copy, p->ve_adp_thrd, + sizeof(int) * ADP_THRD_LEN); + memcpy(reg_blk_boost_12_copy, p->ve_reg_blk_boost_12, + sizeof(int) * REG_BLK_BOOST_LEN); + memcpy(reg_adp_ofset_20_copy, p->ve_reg_adp_ofset_20, + sizeof(int) * REG_ADP_OFSET_LEN); + memcpy(reg_mono_protect_copy, p->ve_reg_mono_protect, + sizeof(int) * REG_MONO_PROT_LEN); + memcpy(reg_trend_wht_expand_lut8_copy, p->ve_reg_trend_wht_expand_lut8, + sizeof(int) * TREND_WHT_EXP_LUT_LEN); if ((ve_en != p->param[ve_dnlp_enable]) || (dnlp_sel != p->param[ve_dnlp_sel]) || @@ -538,6 +637,10 @@ void ve_set_v3_dnlp(struct ve_dnlp_curve_param_s *p) p->param[ve_dnlp_whtext_ofst]) || (dnlp_alg_param.dnlp_bwext_div4x_min != p->param[ve_dnlp_bwext_div4x_min]) || + (dnlp_alg_param.dnlp_iRgnBgn != + p->param[ve_dnlp_iRgnBgn]) || + (dnlp_alg_param.dnlp_iRgnEnd != + p->param[ve_dnlp_iRgnEnd]) || (dnlp_alg_param.dnlp_blk_cctr != p->param[ve_dnlp_blk_cctr]) || (dnlp_alg_param.dnlp_brgt_ctrl != @@ -563,7 +666,45 @@ void ve_set_v3_dnlp(struct ve_dnlp_curve_param_s *p) (dnlp_alg_param.dnlp_scurv_hgh2_th != p->param[ve_dnlp_scurv_hgh2_th]) || (dnlp_alg_param.dnlp_mtdrate_adp_en != - p->param[ve_dnlp_mtdrate_adp_en])) { + p->param[ve_dnlp_mtdrate_adp_en]) || + (dnlp_alg_param.dnlp_clahe_method != + p->param[ve_dnlp_clahe_method]) || + (dnlp_alg_param.dnlp_ble_en != + p->param[ve_dnlp_ble_en]) || + (dnlp_alg_param.dnlp_norm != + p->param[ve_dnlp_norm]) || + (dnlp_alg_param.dnlp_scn_chg_th != + p->param[ve_dnlp_scn_chg_th]) || + (dnlp_alg_param.dnlp_iir_step_mux != + p->param[ve_dnlp_iir_step_mux]) || + (dnlp_alg_param.dnlp_single_bin_bw != + p->param[ve_dnlp_single_bin_bw]) || + (dnlp_alg_param.dnlp_single_bin_method != + p->param[ve_dnlp_single_bin_method]) || + (dnlp_alg_param.dnlp_reg_max_slop_1st != + p->param[ve_dnlp_reg_max_slop_1st]) || + (dnlp_alg_param.dnlp_reg_max_slop_mid != + p->param[ve_dnlp_reg_max_slop_mid]) || + (dnlp_alg_param.dnlp_reg_max_slop_fin != + p->param[ve_dnlp_reg_max_slop_fin]) || + (dnlp_alg_param.dnlp_reg_min_slop_1st != + p->param[ve_dnlp_reg_min_slop_1st]) || + (dnlp_alg_param.dnlp_reg_min_slop_mid != + p->param[ve_dnlp_reg_min_slop_mid]) || + (dnlp_alg_param.dnlp_reg_min_slop_fin != + p->param[ve_dnlp_reg_min_slop_fin]) || + (dnlp_alg_param.dnlp_reg_trend_wht_expand_mode != + p->param[ve_dnlp_reg_trend_wht_expand_mode]) || + (dnlp_alg_param.dnlp_reg_trend_blk_expand_mode != + p->param[ve_dnlp_reg_trend_blk_expand_mode]) || + (dnlp_alg_param.dnlp_ve_hist_cur_gain != + p->param[ve_dnlp_ve_hist_cur_gain]) || + (dnlp_alg_param.dnlp_ve_hist_cur_gain_precise != + p->param[ve_dnlp_ve_hist_cur_gain_precise]) || + (dnlp_alg_param.dnlp_reg_mono_binrang_st != + p->param[ve_dnlp_reg_mono_binrang_st]) || + (dnlp_alg_param.dnlp_reg_mono_binrang_ed != + p->param[ve_dnlp_reg_mono_binrang_ed])) { if (dnlp_insmod_ok) *menu_chg_en_copy = 1; } else @@ -615,6 +756,8 @@ void ve_set_v3_dnlp(struct ve_dnlp_curve_param_s *p) dnlp_alg_param.dnlp_blkext_ofst = p->param[ve_dnlp_blkext_ofst]; dnlp_alg_param.dnlp_whtext_ofst = p->param[ve_dnlp_whtext_ofst]; dnlp_alg_param.dnlp_bwext_div4x_min = p->param[ve_dnlp_bwext_div4x_min]; + dnlp_alg_param.dnlp_iRgnBgn = p->param[ve_dnlp_iRgnBgn]; + dnlp_alg_param.dnlp_iRgnEnd = p->param[ve_dnlp_iRgnEnd]; /* brightness_plus */ dnlp_alg_param.dnlp_blk_cctr = p->param[ve_dnlp_blk_cctr]; @@ -634,27 +777,54 @@ void ve_set_v3_dnlp(struct ve_dnlp_curve_param_s *p) dnlp_alg_param.dnlp_mtdrate_adp_en = p->param[ve_dnlp_mtdrate_adp_en]; /* TODO: ve_dnlp_set_saturtn = p->dnlp_set_saturtn; */ + /*new c curve param add for vlsi-kiteli*/ + dnlp_alg_param.dnlp_mtdrate_adp_en = + p->param[ve_dnlp_mtdrate_adp_en]; + + dnlp_alg_param.dnlp_clahe_method = + p->param[ve_dnlp_clahe_method]; + dnlp_alg_param.dnlp_ble_en = + p->param[ve_dnlp_ble_en]; + dnlp_alg_param.dnlp_norm = + p->param[ve_dnlp_norm]; + dnlp_alg_param.dnlp_scn_chg_th = + p->param[ve_dnlp_scn_chg_th]; + dnlp_alg_param.dnlp_iir_step_mux = + p->param[ve_dnlp_iir_step_mux]; + dnlp_alg_param.dnlp_single_bin_bw = + p->param[ve_dnlp_single_bin_bw]; + dnlp_alg_param.dnlp_single_bin_method = + p->param[ve_dnlp_single_bin_method]; + dnlp_alg_param.dnlp_reg_max_slop_1st = + p->param[ve_dnlp_reg_max_slop_1st]; + dnlp_alg_param.dnlp_reg_max_slop_mid = + p->param[ve_dnlp_reg_max_slop_mid]; + dnlp_alg_param.dnlp_reg_max_slop_fin = + p->param[ve_dnlp_reg_max_slop_fin]; + dnlp_alg_param.dnlp_reg_min_slop_1st = + p->param[ve_dnlp_reg_min_slop_1st]; + dnlp_alg_param.dnlp_reg_min_slop_mid = + p->param[ve_dnlp_reg_min_slop_mid]; + dnlp_alg_param.dnlp_reg_min_slop_fin = + p->param[ve_dnlp_reg_min_slop_fin]; + dnlp_alg_param.dnlp_reg_trend_wht_expand_mode = + p->param[ve_dnlp_reg_trend_wht_expand_mode]; + dnlp_alg_param.dnlp_reg_trend_blk_expand_mode = + p->param[ve_dnlp_reg_trend_blk_expand_mode]; + dnlp_alg_param.dnlp_ve_hist_cur_gain = + p->param[ve_dnlp_ve_hist_cur_gain]; + dnlp_alg_param.dnlp_ve_hist_cur_gain_precise = + p->param[ve_dnlp_ve_hist_cur_gain_precise]; + dnlp_alg_param.dnlp_reg_mono_binrang_st = + p->param[ve_dnlp_reg_mono_binrang_st]; + dnlp_alg_param.dnlp_reg_mono_binrang_ed = + p->param[ve_dnlp_reg_mono_binrang_ed]; if (dnlp_insmod_ok == 0) return; dnlp_dbg_node_copy(); - /*load static curve*/ - for (i = 0; i < 65; i++) { - dnlp_scurv_low_copy[i] = p->ve_dnlp_scurv_low[i]; - dnlp_scurv_mid1_copy[i] = p->ve_dnlp_scurv_mid1[i]; - dnlp_scurv_mid2_copy[i] = p->ve_dnlp_scurv_mid2[i]; - dnlp_scurv_hgh1_copy[i] = p->ve_dnlp_scurv_hgh1[i]; - dnlp_scurv_hgh2_copy[i] = p->ve_dnlp_scurv_hgh2[i]; - } - /*load gain var*/ - for (i = 0; i < 49; i++) - gain_var_lut49_copy[i] = p->ve_gain_var_lut49[i]; - /*load wext gain*/ - for (i = 0; i < 48; i++) - wext_gain_copy[i] = p->ve_wext_gain[i]; - if (ve_en) { /* clear historic luma sum */ *ve_dnlp_luma_sum_copy = 0; diff --git a/drivers/amlogic/media/enhancement/amvecm/dnlp_cal.h b/drivers/amlogic/media/enhancement/amvecm/dnlp_cal.h index 6c3a99e9c6cd..0f592e871d24 100644 --- a/drivers/amlogic/media/enhancement/amvecm/dnlp_cal.h +++ b/drivers/amlogic/media/enhancement/amvecm/dnlp_cal.h @@ -1,3 +1,19 @@ +/* + * drivers/amlogic/media/enhancement/amvecm/dnlp_cal.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ #ifndef __AM_DNLP_CAL_H #define __AM_DNLP_CAL_H @@ -60,6 +76,26 @@ struct dnlp_alg_param_s { unsigned int dnlp_scurv_hgh1_th; unsigned int dnlp_scurv_hgh2_th; unsigned int dnlp_mtdrate_adp_en; + unsigned int dnlp_clahe_method; + unsigned int dnlp_ble_en; + unsigned int dnlp_norm; + unsigned int dnlp_scn_chg_th; + unsigned int dnlp_step_th; + unsigned int dnlp_iir_step_mux; + unsigned int dnlp_single_bin_bw; + unsigned int dnlp_single_bin_method; + unsigned int dnlp_reg_max_slop_1st; + unsigned int dnlp_reg_max_slop_mid; + unsigned int dnlp_reg_max_slop_fin; + unsigned int dnlp_reg_min_slop_1st; + unsigned int dnlp_reg_min_slop_mid; + unsigned int dnlp_reg_min_slop_fin; + unsigned int dnlp_reg_trend_wht_expand_mode; + unsigned int dnlp_reg_trend_blk_expand_mode; + unsigned int dnlp_ve_hist_cur_gain; + unsigned int dnlp_ve_hist_cur_gain_precise; + unsigned int dnlp_reg_mono_binrang_st; + unsigned int dnlp_reg_mono_binrang_ed; }; struct dnlp_parse_cmd_s { @@ -92,6 +128,11 @@ extern int *dnlp_scurv_hgh1_copy; extern int *dnlp_scurv_hgh2_copy; extern int *gain_var_lut49_copy; extern int *wext_gain_copy; +extern int *adp_thrd_copy; +extern int *reg_blk_boost_12_copy; +extern int *reg_adp_ofset_20_copy; +extern int *reg_mono_protect_copy; +extern int *reg_trend_wht_expand_lut8_copy; extern int *ro_luma_avg4_copy; extern int *ro_var_d8_copy; diff --git a/drivers/amlogic/media/enhancement/amvecm/keystone_correction.c b/drivers/amlogic/media/enhancement/amvecm/keystone_correction.c index 645bcf0ff95d..b88d85584778 100644 --- a/drivers/amlogic/media/enhancement/amvecm/keystone_correction.c +++ b/drivers/amlogic/media/enhancement/amvecm/keystone_correction.c @@ -1,3 +1,20 @@ +/* + * drivers/amlogic/media/enhancement/amvecm/keystone_correction.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 #include #include diff --git a/drivers/amlogic/media/enhancement/amvecm/keystone_correction.h b/drivers/amlogic/media/enhancement/amvecm/keystone_correction.h index 633aff4ad966..62dfc30c2ce0 100644 --- a/drivers/amlogic/media/enhancement/amvecm/keystone_correction.h +++ b/drivers/amlogic/media/enhancement/amvecm/keystone_correction.h @@ -1,3 +1,20 @@ +/* + * drivers/amlogic/media/enhancement/amvecm/keystone_correction.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 _KEYSTONE_CORRECTION_H_ #define _KEYSTONE_CORRECTION_H_ diff --git a/drivers/amlogic/media/enhancement/amvecm/local_contrast.c b/drivers/amlogic/media/enhancement/amvecm/local_contrast.c index 5f110182a041..bcbae917426a 100644 --- a/drivers/amlogic/media/enhancement/amvecm/local_contrast.c +++ b/drivers/amlogic/media/enhancement/amvecm/local_contrast.c @@ -1,5 +1,20 @@ +/* + * drivers/amlogic/media/enhancement/amvecm/local_contrast.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 */ #include #include #include @@ -10,6 +25,12 @@ #include "arch/vpp_regs.h" #include "local_contrast.h" +/*may define in other module*/ +#define CURV_NODES 6 +/*history message delay*/ +#define N 4 +/*hist bin num*/ +#define HIST_BIN 16 int amlc_debug; #define pr_amlc_dbg(fmt, args...)\ do {\ @@ -17,13 +38,89 @@ int amlc_debug; pr_info("AMVE: " fmt, ## args);\ } while (0) -int lc_en; +int lc_en = 1; +int lc_demo_mode; +int lc_en_chflg = 0xff; static int lc_flag = 0xff; +int osd_iir_en = 1; +int amlc_iir_debug_en; +/*osd related setting */ +int vnum_start_below = 5; +int vnum_end_below = 6; +int vnum_start_above = 1; +int vnum_end_above = 2; +int invalid_blk = 2; +/*u10,7000/21600=0.324*1024=331 */ +int min_bv_percent_th = 331; +/*control the refresh speed*/ +int alpha1 = 512; +int alpha2 = 512; +int refresh_bit = 12; +int ts = 6; +/*need tuning according to real situation ! (0~512)*/ +int scene_change_th = 50; + +/*chose block to get hist*/ +unsigned int lc_hist_vs; +unsigned int lc_hist_ve; +unsigned int lc_hist_hs; +unsigned int lc_hist_he; +/*lc curve data and hist data*/ +int *lc_szcurve;/*12*8*6+4*/ +int *curve_nodes_cur; +static int *curve_nodes_pre; +int *lc_hist;/*12*8*17*/ +static bool lc_malloc_ok; +/*print one or more frame data*/ +unsigned int lc_hist_prcnt; +unsigned int lc_curve_prcnt; +bool lc_curve_fresh = true; + +struct ve_lc_curve_parm_s lc_curve_parm_load; +struct lc_alg_param_s lc_alg_parm; + +/*lc saturation gain, low parameters*/ +/*static unsigned int lc_satur_gain[63] = { + * 51, 104, 158, 213, 269, 325, 382, 440, 498, + * 556, 615, 674, 734, 794, 854, 915, 976, 1037, + * 1099, 1161, 1223, 1286, 1348, 1411, 1475, 1538, + * 1602, 1666, 1730, 1795, 1859, 1924, 1989, 2054 + * 2120, 2186, 2251, 2318, 2384, 2450, 2517, 2584, + * 2651, 2718, 2785, 2853, 2921, 2988, 3057, 3125, + * 3193, 3262, 3330, 3399, 3468, 3537, 3607, 3676, + * 3746, 3815, 3885, 3955, 4026 + *}; + */ + +/*lc saturation gain, off parameters*/ +static unsigned int lc_satur_off[63] = { + 64, 128, 192, 256, 320, 384, 448, 512, 576, 640, + 704, 768, 832, 896, 960, 1024, 1088, 1152, 1216, + 1280, 1344, 1408, 1472, 1536, 1600, 1664, 1728, + 1792, 1856, 1920, 1984, 2048, 2112, 2176, 2240, + 2304, 2368, 2432, 2496, 2560, 2624, 2688, 2752, + 2816, 2880, 2944, 3008, 3072, 3136, 3200, 3264, + 3328, 3392, 3456, 3520, 3584, 3648, 3712, 3776, + 3840, 3904, 3968, 4032 +}; + +/*lc saturation gain, low parameters*/ +/*static unsigned int lc_satur_low[63] = {*/ +/* 84, 167, 249, 330, 411, 490, 568, 646, 723, 798,*/ +/* 873, 947, 1020, 1092, 1163, 1234, 1303, 1372, 1440,*/ +/* 1506, 1572, 1638, 1702, 1766, 1828, 1890, 1951,*/ +/* 2011, 2071, 2130, 2187, 2245, 2301, 2356, 2411,*/ +/* 2465, 2518, 2571, 2623, 2674, 2724, 2774, 2822,*/ +/* 2871, 2919, 2967, 3016, 3065, 3115, 3165, 3217,*/ +/* 3271, 3326, 3384, 3443, 3506, 3571, 3639, 3710,*/ +/* 3785, 3863, 3945, 4032*/ +/*};*/ /*local contrast begin*/ static void lc_mtx_set(enum lc_mtx_sel_e mtx_sel, enum lc_mtx_csc_e mtx_csc, - int mtx_en) + int mtx_en, + int bitdepth) { unsigned int matrix_coef00_01 = 0; unsigned int matrix_coef02_10 = 0; @@ -79,14 +176,72 @@ static void lc_mtx_set(enum lc_mtx_sel_e mtx_sel, return; switch (mtx_csc) { - case LC_MTX_RGB_YUV709L: + case LC_MTX_RGB_YUV601L: if (mtx_sel & (INP_MTX | OUTP_MTX)) { + WRITE_VPP_REG(matrix_coef00_01, 0x1070204); + WRITE_VPP_REG(matrix_coef02_10, 0x640f68); + WRITE_VPP_REG(matrix_coef11_12, 0xed601c2); + WRITE_VPP_REG(matrix_coef20_21, 0x01c20e87); + WRITE_VPP_REG(matrix_coef22, 0x0000fb7); + if (bitdepth == 10) { + WRITE_VPP_REG(matrix_offset0_1, 0x00400200); + WRITE_VPP_REG(matrix_clip, 0x3ff); + } else { + WRITE_VPP_REG(matrix_offset0_1, 0x01000800); + WRITE_VPP_REG(matrix_clip, 0xfff); + } + } else if (mtx_sel & STAT_MTX) { WRITE_VPP_REG(matrix_coef00_01, 0x00bb0275); WRITE_VPP_REG(matrix_coef02_10, 0x003f1f99); WRITE_VPP_REG(matrix_coef11_12, 0x1ea601c2); WRITE_VPP_REG(matrix_coef20_21, 0x01c21e67); WRITE_VPP_REG(matrix_coef22, 0x00001fd7); WRITE_VPP_REG(matrix_offset0_1, 0x00400200); + WRITE_VPP_REG(matrix_offset2, 0x00000200); + WRITE_VPP_REG(matrix_pre_offset0_1, 0x0); + WRITE_VPP_REG(matrix_pre_offset2, 0x0); + } + break; + case LC_MTX_YUV601L_RGB: + if (mtx_sel & (INP_MTX | OUTP_MTX)) { + WRITE_VPP_REG(matrix_coef00_01, 0x012a0000); + WRITE_VPP_REG(matrix_coef02_10, 0x198012a); + WRITE_VPP_REG(matrix_coef11_12, 0xf9c0f30); + WRITE_VPP_REG(matrix_coef20_21, 0x12a0204); + WRITE_VPP_REG(matrix_coef22, 0x0); + if (bitdepth == 10) { + WRITE_VPP_REG(matrix_pre_offset0_1, 0x00400200); + WRITE_VPP_REG(matrix_clip, 0x3ff); + } else { + WRITE_VPP_REG(matrix_pre_offset0_1, 0x01000800); + WRITE_VPP_REG(matrix_clip, 0xfff); + } + } else if (mtx_sel & STAT_MTX) { + WRITE_VPP_REG(matrix_coef00_01, 0x04A80000); + WRITE_VPP_REG(matrix_coef02_10, 0x072C04A8); + WRITE_VPP_REG(matrix_coef11_12, 0x1F261DDD); + WRITE_VPP_REG(matrix_coef20_21, 0x04A80876); + WRITE_VPP_REG(matrix_coef22, 0x0); + WRITE_VPP_REG(matrix_offset0_1, 0x0); + WRITE_VPP_REG(matrix_offset2, 0x0); + WRITE_VPP_REG(matrix_pre_offset0_1, 0x7c00600); + WRITE_VPP_REG(matrix_pre_offset2, 0x00000600); + } + break; + case LC_MTX_RGB_YUV709L: + if (mtx_sel & (INP_MTX | OUTP_MTX)) { + WRITE_VPP_REG(matrix_coef00_01, 0xba0273); + WRITE_VPP_REG(matrix_coef02_10, 0x3f0f9a); + WRITE_VPP_REG(matrix_coef11_12, 0xea701c0); + WRITE_VPP_REG(matrix_coef20_21, 0x1c00e6a); + WRITE_VPP_REG(matrix_coef22, 0xfd7); + if (bitdepth == 10) { + WRITE_VPP_REG(matrix_offset0_1, 0x00400200); + WRITE_VPP_REG(matrix_clip, 0x3ff); + } else { + WRITE_VPP_REG(matrix_offset0_1, 0x01000800); + WRITE_VPP_REG(matrix_clip, 0xfff); + } } else if (mtx_sel & STAT_MTX) { WRITE_VPP_REG(matrix_coef00_01, 0x00bb0275); WRITE_VPP_REG(matrix_coef02_10, 0x003f1f99); @@ -101,12 +256,18 @@ static void lc_mtx_set(enum lc_mtx_sel_e mtx_sel, break; case LC_MTX_YUV709L_RGB: if (mtx_sel & (INP_MTX | OUTP_MTX)) { - WRITE_VPP_REG(matrix_coef00_01, 0x04A80000); - WRITE_VPP_REG(matrix_coef02_10, 0x072C04A8); - WRITE_VPP_REG(matrix_coef11_12, 0x1F261DDD); - WRITE_VPP_REG(matrix_coef20_21, 0x04A80876); + WRITE_VPP_REG(matrix_coef00_01, 0x12b0000); + WRITE_VPP_REG(matrix_coef02_10, 0x1cc012b); + WRITE_VPP_REG(matrix_coef11_12, 0xfc90f77); + WRITE_VPP_REG(matrix_coef20_21, 0x12b021f); WRITE_VPP_REG(matrix_coef22, 0x0); - WRITE_VPP_REG(matrix_pre_offset0_1, 0x00400200); + if (bitdepth == 10) { + WRITE_VPP_REG(matrix_pre_offset0_1, 0x00400200); + WRITE_VPP_REG(matrix_clip, 0x3ff); + } else { + WRITE_VPP_REG(matrix_pre_offset0_1, 0x01000800); + WRITE_VPP_REG(matrix_clip, 0xfff); + } } else if (mtx_sel & STAT_MTX) { WRITE_VPP_REG(matrix_coef00_01, 0x04A80000); WRITE_VPP_REG(matrix_coef02_10, 0x072C04A8); @@ -128,7 +289,15 @@ static void lc_mtx_set(enum lc_mtx_sel_e mtx_sel, WRITE_VPP_REG(matrix_coef22, 0x400); WRITE_VPP_REG(matrix_offset0_1, 0x0); } else if (mtx_sel & STAT_MTX) { - + WRITE_VPP_REG(matrix_coef00_01, 0x04000000); + WRITE_VPP_REG(matrix_coef02_10, 0x0); + WRITE_VPP_REG(matrix_coef11_12, 0x04000000); + WRITE_VPP_REG(matrix_coef20_21, 0x0); + WRITE_VPP_REG(matrix_coef22, 0x400); + WRITE_VPP_REG(matrix_offset0_1, 0x0); + WRITE_VPP_REG(matrix_offset2, 0x0); + WRITE_VPP_REG(matrix_pre_offset0_1, 0x0); + WRITE_VPP_REG(matrix_pre_offset2, 0x0); } break; default: @@ -151,8 +320,8 @@ static void lc_stts_blk_config(int enable, col_start = 0; h_num = 12; v_num = 8; - blk_height = height / h_num; - blk_width = width / v_num; + blk_height = height / v_num; + blk_width = width / h_num; hend0 = col_start + blk_width - 1; hend1 = hend0 + blk_width; @@ -182,26 +351,26 @@ static void lc_stts_blk_config(int enable, ((((row_start & 0x1fff) << 16) & 0xffff0000) | (col_start & 0x1fff))); WRITE_VPP_REG(LC_STTS_HIST_SET_REGION, - (hend1 & 0x1fff) | (hend0 & 0x1fff)); + ((hend1 & 0x1fff)<<16) | (hend0 & 0x1fff)); WRITE_VPP_REG(LC_STTS_HIST_SET_REGION, - (vend1 & 0x1fff) | (vend0 & 0x1fff)); + ((vend1 & 0x1fff)<<16) | (vend0 & 0x1fff)); WRITE_VPP_REG(LC_STTS_HIST_SET_REGION, - (hend3 & 0x1fff) | (hend2 & 0x1fff)); + ((hend3 & 0x1fff)<<16) | (hend2 & 0x1fff)); WRITE_VPP_REG(LC_STTS_HIST_SET_REGION, - (vend3 & 0x1fff) | (vend2 & 0x1fff)); + ((vend3 & 0x1fff)<<16) | (vend2 & 0x1fff)); WRITE_VPP_REG(LC_STTS_HIST_SET_REGION, - (hend5 & 0x1fff) | (hend4 & 0x1fff)); + ((hend5 & 0x1fff)<<16) | (hend4 & 0x1fff)); WRITE_VPP_REG(LC_STTS_HIST_SET_REGION, - (vend5 & 0x1fff) | (vend4 & 0x1fff)); + ((vend5 & 0x1fff)<<16) | (vend4 & 0x1fff)); WRITE_VPP_REG(LC_STTS_HIST_SET_REGION, - (hend7 & 0x1fff) | (hend6 & 0x1fff)); + ((hend7 & 0x1fff)<<16) | (hend6 & 0x1fff)); WRITE_VPP_REG(LC_STTS_HIST_SET_REGION, - (vend7 & 0x1fff) | (vend6 & 0x1fff)); + ((vend7 & 0x1fff)<<16) | (vend6 & 0x1fff)); WRITE_VPP_REG(LC_STTS_HIST_SET_REGION, - (hend9 & 0x1fff) | (hend8 & 0x1fff)); + ((hend9 & 0x1fff)<<16) | (hend8 & 0x1fff)); WRITE_VPP_REG(LC_STTS_HIST_SET_REGION, - (hend11 & 0x1fff) | (hend10 & 0x1fff)); + ((hend11 & 0x1fff)<<16) | (hend10 & 0x1fff)); WRITE_VPP_REG(LC_STTS_HIST_SET_REGION, h_num); } @@ -212,7 +381,8 @@ static void lc_stts_en(int enable, int eol_en, int hist_mode, int lpf_en, - int din_sel) + int din_sel, + int bitdepth) { int data32; @@ -225,7 +395,7 @@ static void lc_stts_en(int enable, data32 = data32 | ((lpf_en & 0x1) << 21); WRITE_VPP_REG(LC_STTS_HIST_REGION_IDX, data32); - lc_mtx_set(STAT_MTX, LC_MTX_YUV709L_RGB, enable); + lc_mtx_set(STAT_MTX, LC_MTX_YUV709L_RGB, enable, bitdepth); WRITE_VPP_REG_BITS(LC_STTS_CTRL0, din_sel, 3, 3); /*lc hist stts enable*/ @@ -260,6 +430,7 @@ static void lc_curve_ctrl_config(int enable, } } + static void lc_blk_bdry_config(unsigned int height, unsigned int width) { width /= 12; @@ -314,7 +485,7 @@ static void lc_blk_bdry_config(unsigned int height, unsigned int width) } static void lc_top_config(int enable, int h_num, int v_num, - unsigned int height, unsigned int width) + unsigned int height, unsigned int width, int bitdepth, int flag) { /*lcinput_ysel*/ WRITE_VPP_REG_BITS(SRSHARP1_LC_INPUT_MUX, 5, 4, 3); @@ -328,14 +499,21 @@ static void lc_top_config(int enable, int h_num, int v_num, /*lc hblank*/ WRITE_VPP_REG_BITS(SRSHARP1_LC_TOP_CTRL, 8, 8, 8); - /*lc blend mode*/ - WRITE_VPP_REG_BITS(SRSHARP1_LC_TOP_CTRL, 0, 0, 1); + /*lc blend mode,default 1*/ + WRITE_VPP_REG_BITS(SRSHARP1_LC_TOP_CTRL, 1, 0, 1); /*lc curve mapping config*/ lc_blk_bdry_config(height, width); /*LC sync ctl*/ WRITE_VPP_REG_BITS(SRSHARP1_LC_TOP_CTRL, 0, 16, 1); /*lc enable need set at last*/ WRITE_VPP_REG_BITS(SRSHARP1_LC_TOP_CTRL, enable, 4, 1); + if (flag == 1) { + lc_mtx_set(INP_MTX, LC_MTX_YUV709L_RGB, 1, bitdepth); + lc_mtx_set(OUTP_MTX, LC_MTX_RGB_YUV709L, 1, bitdepth); + } else { + lc_mtx_set(INP_MTX, LC_MTX_YUV601L_RGB, 1, bitdepth); + lc_mtx_set(OUTP_MTX, LC_MTX_RGB_YUV601L, 1, bitdepth); + } } static void lc_disable(void) @@ -343,18 +521,22 @@ static void lc_disable(void) /*lc enable need set at last*/ WRITE_VPP_REG_BITS(SRSHARP1_LC_TOP_CTRL, 0, 4, 1); WRITE_VPP_REG_BITS(LC_CURVE_CTRL, 0, 0, 1); + WRITE_VPP_REG_BITS(LC_CURVE_RAM_CTRL, 0, 0, 1); /*lc hist stts enable*/ WRITE_VPP_REG_BITS(LC_STTS_HIST_REGION_IDX, 0, 31, 1); + lc_en_chflg = 0x0; } static void lc_config(int enable, struct vframe_s *vf, unsigned int sps_h_en, - unsigned int sps_v_en) + unsigned int sps_v_en, + int bitdepth) { int h_num, v_num; unsigned int height, width; static unsigned int vf_height, vf_width; + unsigned int flag; const struct vinfo_s *vinfo = get_current_vinfo(); height = vinfo->height; @@ -362,17 +544,25 @@ static void lc_config(int enable, h_num = 12; v_num = 8; - if (vf == NULL) + if (vf == NULL) { + vf_height = 0; + vf_width = 0; return; + } - if ((vf_height == vf->height) || - (vf_width == vf->width)) - return; + if ((vf_height == vf->height) && + (vf_width == vf->width)) { + if (!lc_en_chflg) + lc_en_chflg = 0xff; + else + return; + } vf_height = vf->height; vf_width = vf->width; - - lc_top_config(enable, h_num, v_num, height, width); + /*flag: 0 for 601; 1 for 709*/ + flag = (vf_height > 720) ? 1 : 0; + lc_top_config(enable, h_num, v_num, height, width, bitdepth, flag); if (sps_h_en == 1) width /= 2; @@ -381,101 +571,736 @@ static void lc_config(int enable, lc_curve_ctrl_config(enable, height, width); lc_stts_blk_config(enable, height, width); - lc_stts_en(enable, height, width, 0, 0, 1, 1, 4); + lc_stts_en(enable, height, width, 0, 0, 1, 1, 4, bitdepth); } -static void read_lc_curve(int *szCurveInfo) +static void read_lc_curve(int blk_vnum, int blk_hnum) { - int blk_hnum; - int blk_vnum; - int i; - unsigned int dwTemp; + int i, j; + unsigned int temp1, temp2; - dwTemp = READ_VPP_REG(LC_CURVE_HV_NUM); - blk_hnum = (dwTemp >> 8) & 0x1f; - blk_vnum = (dwTemp) & 0x1f; WRITE_VPP_REG(LC_CURVE_RAM_CTRL, 1); WRITE_VPP_REG(LC_CURVE_RAM_ADDR, 0); - for (i = 0; i < blk_hnum * blk_vnum; i++) { - szCurveInfo[i*2+0] = READ_VPP_REG(LC_CURVE_RAM_DATA); - szCurveInfo[i*2+1] = READ_VPP_REG(LC_CURVE_RAM_DATA); + for (i = 0; i < blk_vnum; i++) { + for (j = 0; j < blk_hnum; j++) { + temp1 = READ_VPP_REG(LC_CURVE_RAM_DATA); + temp2 = READ_VPP_REG(LC_CURVE_RAM_DATA); + lc_szcurve[(i*blk_hnum + j)*6+0] = + temp1 & 0x3ff;/*bit0:9*/ + lc_szcurve[(i*blk_hnum + j)*6+1] = + (temp1>>10) & 0x3ff;/*bit10:19*/ + lc_szcurve[(i*blk_hnum + j)*6+2] = + (temp1>>20) & 0x3ff;/*bit20:29*/ + lc_szcurve[(i*blk_hnum + j)*6+3] = + temp2 & 0x3ff;/*bit0:9*/ + lc_szcurve[(i*blk_hnum + j)*6+4] = + (temp2>>10) & 0x3ff;/*bit10:19*/ + lc_szcurve[(i*blk_hnum + j)*6+5] = + (temp2>>20) & 0x3ff;/*bit20:29*/ + } + } + WRITE_VPP_REG(LC_CURVE_RAM_CTRL, 0); +} + +static void lc_demo_wr_curve(int h_num, int v_num) +{ + int i, j, temp1, temp2; + + for (i = 0; i < v_num; i++) { + for (j = 0; j < h_num / 2; j++) { + temp1 = lc_szcurve[6 * (i * h_num + j) + 0] | + (lc_szcurve[6 * + (i * h_num + j) + 1] << 10) | + (lc_szcurve[6 * + (i * h_num + j) + 2] << 20); + temp2 = lc_szcurve[6 * (i * h_num + j) + 3] | + (lc_szcurve[6 * + (i * h_num + j) + 4] << 10) | + (lc_szcurve[6 * + (i * h_num + j) + 5] << 20); + VSYNC_WR_MPEG_REG(SRSHARP1_LC_MAP_RAM_DATA, temp1); + VSYNC_WR_MPEG_REG(SRSHARP1_LC_MAP_RAM_DATA, temp2); + } + for (j = h_num / 2; j < h_num; j++) { + VSYNC_WR_MPEG_REG(SRSHARP1_LC_MAP_RAM_DATA, + (0|(0<<10)|(512<<20))); + VSYNC_WR_MPEG_REG(SRSHARP1_LC_MAP_RAM_DATA, + (1023|(1023<<10)|(512<<20))); + } } } -static int set_lc_curve(int *szCurveInfo, int binit, int bcheck) +static int lc_demo_check_curve(int h_num, int v_num) +{ + int i, j, temp, temp1, flag; + + flag = 0; + for (i = 0; i < v_num; i++) { + for (j = 0; j < h_num / 2; j++) { + temp = READ_VPP_REG(SRSHARP1_LC_MAP_RAM_DATA); + temp1 = lc_szcurve[6 * (i * h_num + j) + 0] | + (lc_szcurve[6 * (i * h_num + j) + 1] << 10) | + (lc_szcurve[6 * (i * h_num + j) + 2] << 20); + if (temp != temp1) + flag = (2 * (i * h_num + j) + 0) | (1 << 31); + + temp = READ_VPP_REG(SRSHARP1_LC_MAP_RAM_DATA); + temp1 = lc_szcurve[6 * (i * h_num + j) + 3] | + (lc_szcurve[6 * (i * h_num + j) + 4] << 10) | + (lc_szcurve[6 * (i * h_num + j) + 5] << 20); + if (temp != temp1) + flag = (2 * (i * h_num + j) + 1) | (1 << 31); + } + for (j = h_num / 2; j < h_num; j++) { + temp = READ_VPP_REG(SRSHARP1_LC_MAP_RAM_DATA); + if (temp != (0|(0<<10)|(512<<20))) + flag = (2 * (i * h_num + j) + 0) | (1 << 31); + temp = READ_VPP_REG(SRSHARP1_LC_MAP_RAM_DATA); + if (temp != (1023|(1023<<10)|(512<<20))) + flag = (2 * (i * h_num + j) + 1) | (1 << 31); + } + } + return flag; +} +static int set_lc_curve(int binit, int bcheck) { int i, h_num, v_num; unsigned int hvTemp; int rflag; - int temp; + int temp, temp1; rflag = 0; hvTemp = READ_VPP_REG(SRSHARP1_LC_HV_NUM); h_num = (hvTemp >> 8) & 0x1f; v_num = hvTemp & 0x1f; - WRITE_VPP_REG_BITS(SRSHARP1_LC_MAP_RAM_CTRL, 1, 0, 1); + VSYNC_WR_MPEG_REG(SRSHARP1_LC_MAP_RAM_CTRL, 1); /*data sequence: ymin/minBv/pkBv/maxBv/ymaxv/ypkBv*/ if (binit) { - WRITE_VPP_REG(SRSHARP1_LC_MAP_RAM_ADDR, 0); + VSYNC_WR_MPEG_REG(SRSHARP1_LC_MAP_RAM_ADDR, 0); for (i = 0; i < h_num * v_num; i++) { - WRITE_VPP_REG(SRSHARP1_LC_MAP_RAM_DATA, + VSYNC_WR_MPEG_REG(SRSHARP1_LC_MAP_RAM_DATA, (0|(0<<10)|(512<<20))); - WRITE_VPP_REG(SRSHARP1_LC_MAP_RAM_DATA, + VSYNC_WR_MPEG_REG(SRSHARP1_LC_MAP_RAM_DATA, (1023|(1023<<10)|(512<<20))); } } else { - WRITE_VPP_REG(SRSHARP1_LC_MAP_RAM_ADDR, 0); - for (i = 0; i < h_num * v_num; i++) { - WRITE_VPP_REG(SRSHARP1_LC_MAP_RAM_DATA, - szCurveInfo[2 * i + 0]); - WRITE_VPP_REG(SRSHARP1_LC_MAP_RAM_DATA, - szCurveInfo[2 * i + 1]); - } + VSYNC_WR_MPEG_REG(SRSHARP1_LC_MAP_RAM_ADDR, 0); + if (lc_demo_mode) + lc_demo_wr_curve(h_num, v_num); + else + for (i = 0; i < h_num * v_num; i++) { + VSYNC_WR_MPEG_REG(SRSHARP1_LC_MAP_RAM_DATA, + lc_szcurve[6 * i + 0]| + (lc_szcurve[6 * i + 1]<<10)| + (lc_szcurve[6 * i + 2]<<20)); + VSYNC_WR_MPEG_REG(SRSHARP1_LC_MAP_RAM_DATA, + lc_szcurve[6 * i + 3]| + (lc_szcurve[6 * i + 4]<<10)| + (lc_szcurve[6 * i + 5]<<20)); + } } - WRITE_VPP_REG_BITS(SRSHARP1_LC_MAP_RAM_CTRL, 0, 0, 1); + VSYNC_WR_MPEG_REG(SRSHARP1_LC_MAP_RAM_CTRL, 0); if (bcheck) { - WRITE_VPP_REG_BITS(SRSHARP1_LC_MAP_RAM_CTRL, 1, 0, 1); - WRITE_VPP_REG(SRSHARP1_LC_MAP_RAM_ADDR, 0 | (1 << 31)); - for (i = 0; i < h_num * v_num; i++) { - temp = READ_VPP_REG(SRSHARP1_LC_MAP_RAM_DATA); - if (temp != szCurveInfo[2 * i + 0]) - rflag = (2 * i + 0) | (1 << 31); - temp = READ_VPP_REG(SRSHARP1_LC_MAP_RAM_DATA); - if (temp != szCurveInfo[2 * i + 1]) - rflag = (2 * i + 1) | (1 << 31); - } - WRITE_VPP_REG_BITS(SRSHARP1_LC_MAP_RAM_CTRL, 0, 0, 1); + VSYNC_WR_MPEG_REG(SRSHARP1_LC_MAP_RAM_CTRL, 1); + VSYNC_WR_MPEG_REG(SRSHARP1_LC_MAP_RAM_ADDR, 0 | (1 << 31)); + if (lc_demo_mode) + rflag = lc_demo_check_curve(h_num, v_num); + else + for (i = 0; i < h_num * v_num; i++) { + temp = READ_VPP_REG(SRSHARP1_LC_MAP_RAM_DATA); + temp1 = lc_szcurve[6 * i + 0]| + (lc_szcurve[6 * i + 1]<<10)| + (lc_szcurve[6 * i + 2]<<20); + if (temp != temp1) + rflag = (2 * i + 0) | (1 << 31); + temp = READ_VPP_REG(SRSHARP1_LC_MAP_RAM_DATA); + temp1 = lc_szcurve[6 * i + 3]| + (lc_szcurve[6 * i + 4]<<10)| + (lc_szcurve[6 * i + 5]<<20); + if (temp != temp1) + rflag = (2 * i + 1) | (1 << 31); + } + VSYNC_WR_MPEG_REG(SRSHARP1_LC_MAP_RAM_CTRL, 0); } return rflag; } - -static void lc_fw_curve_iir(struct vframe_s *vf) +/* + *function: detect osd and provide osd signal status + *output: + * osd_flag_cnt: signal indicate osd exist (process) + * frm_cnt: signal that record the sudden + * moment osd appear or disappear + */ +static int osd_det_func(int *osd_flag_cnt, + int *frm_cnt, + int blk_hist_sum, + int *lc_hist, + int blk_hnum, + int osd_vnum_strt, + int osd_vnum_end) { - if (!vf) - return; + int i, j; + int min_bin_value, min_bin_percent; + int osd_flag; + int valid_blk; + int percent_norm = (1<<10) - 1; + static int osd_hist_cnt; + + osd_flag = 0; + min_bin_value = 0; + + /*1.1, case 1: osd below,e.g. vnum=5,6(0~7)*/ + osd_hist_cnt = 0; + for (i = osd_vnum_strt; i <= osd_vnum_end; i++) {/*two line*/ + for (j = 0; j < blk_hnum; j++) { + min_bin_value = + lc_hist[(i*blk_hnum + j) * + (HIST_BIN + 1) + 0];/*first bin*/ + /*black osd means first bin value very large*/ + min_bin_percent = + (min_bin_value * percent_norm) / + (blk_hist_sum + 1); + if (min_bin_percent > min_bv_percent_th) + osd_hist_cnt++;/*black bin count*/ + if (amlc_debug == 0x2) + pr_info("v2-1:osd_hist_cnt:%d, min_bin_percent:%d, (th:%d)\n", + osd_hist_cnt, + min_bin_percent, + min_bv_percent_th); + } + } + /*how many block osd occupy*/ + valid_blk = (osd_vnum_end - osd_vnum_strt + 1) * blk_hnum - + invalid_blk; + /*we suppose when osd appear, + * 1)it came in certain area, + * 2)and almost all those area are black + */ + if (osd_hist_cnt > valid_blk) + osd_flag_cnt[1] = 1; + else + osd_flag_cnt[1] = 0; + /*detect the moment osd appear and disappear:*/ + osd_flag = ((osd_flag_cnt[1]&(~(osd_flag_cnt[0]))) + + ((~(osd_flag_cnt[1])) & osd_flag_cnt[0]));/*a^b*/ + /*set osd appear and disappear heavy iir time*/ + if (osd_flag && osd_iir_en) + *frm_cnt = 60 * ts; + + /*debug*/ + if ((amlc_iir_debug_en == 10) || (amlc_debug == 0x2)) { + pr_info("osd_log v2:osd_flag_cnt[0]:%d,osd_flag_cnt[1]:%d,osd_flag:%d,frm_cnt:%d\n", + osd_flag_cnt[0], + osd_flag_cnt[1], + osd_flag, + *frm_cnt); + if (*frm_cnt <= 0) + amlc_iir_debug_en = 0; + } + + return 0; } -void lc_init(void) +/* + *note 1: osd appear in 5,6(0,1,2,...7) line in Vnum = 8 situation + * if Vnum changed, debug osd location, find + * vnum_start_below, vnum_end_below(osd below situation,above situation is same) + * + * note 2: here just consider 2 situation: osd appear below or appear above + * + * function: 2 situation osd detect and provide + * osd status signal(osd_flag_cnt&frm_cnt) + */ +static int osd_detect(int *osd_flag_cnt_above, + int *osd_flag_cnt_below, + int *frm_cnt_above, + int *frm_cnt_below, + int *lc_hist, + int blk_hnum) +{ + int k; + unsigned long blk_hist_sum = 0; + + for (k = 0; k < HIST_BIN; k++) + blk_hist_sum += + lc_hist[(0*blk_hnum + 0) * + (HIST_BIN+1) + k];/*use blk[0,0],16bin*/ + /*above situation*/ + osd_det_func(osd_flag_cnt_above,/*out*/ + frm_cnt_above,/*out*/ + blk_hist_sum, + lc_hist, + blk_hnum, + vnum_start_above, + vnum_end_above); + /*below situation*/ + osd_det_func(osd_flag_cnt_below,/*out*/ + frm_cnt_below,/*out*/ + blk_hist_sum, + lc_hist, + blk_hnum, + vnum_start_below, + vnum_end_below); + + return 0; +} + +/*just temporarily define here to avoid grammar error*/ +static int video_scene_change_flag_en; +static int video_scene_change_flag; +/*function: detect global scene change signal + *output: scene_change_flag + */ +int global_scene_change(int *curve_nodes_cur, + int *curve_nodes_pre, + int blk_vnum, + int blk_hnum, + int *osd_flag_cnt_above, + int *osd_flag_cnt_below) +{ + int scene_change_flag; + static int scene_dif[N]; + static int frm_dif[N]; + /*store frame valid block for frm diff calc*/ + static int valid_blk_num[N]; + int frm_dif_osd, vnum_osd; + int addr_curv1; + int apl_cur, apl_pre; + int i, j; + + /*history message delay*/ + for (i = 0; i < N-1; i++) { + scene_dif[i] = scene_dif[i + 1]; + frm_dif[i] = frm_dif[i + 1]; + valid_blk_num[i] = valid_blk_num[i+1]; + } + + if (video_scene_change_flag_en) + scene_change_flag = + video_scene_change_flag;/*2.1 flag from front module*/ + else { + /* 2.2.1 use block APL to calculate frame dif: + * omap[5]: (yminV), minBV, pkBV, maxBV, (ymaxV),ypkBV + */ + frm_dif[N-1] = 0;/*update current result*/ + scene_dif[N-1] = 0; + valid_blk_num[N-1] = 0; + frm_dif_osd = 0; + vnum_osd = 0; + for (i = 0; i < blk_vnum; i++) { + for (j = 0; j < blk_hnum; j++) { + addr_curv1 = (i * blk_hnum + j); + apl_cur = curve_nodes_cur[addr_curv1 * + CURV_NODES + 2];/*apl value*/ + apl_pre = curve_nodes_pre[addr_curv1 * + CURV_NODES + 2]; + frm_dif[N-1] += + abs(apl_cur - apl_pre);/*frame motion*/ + + /*when have osd, + * remove them to calc frame motion + */ + if ((osd_flag_cnt_below[1]) && + (i >= vnum_start_below) && + (i <= vnum_end_below)) { + frm_dif_osd += abs(apl_cur - apl_pre); + vnum_osd = + vnum_end_below - + vnum_start_below + 1; + + } + + if ((osd_flag_cnt_above[1]) && + (i >= vnum_start_above) && + (i <= vnum_end_above)) { + frm_dif_osd += abs(apl_cur - apl_pre); + vnum_osd = + vnum_end_above - + vnum_start_above + 1; + } + } + } + /*remove osd to calc frame motion */ + frm_dif[N - 1] = frm_dif[N - 1] - frm_dif_osd; + valid_blk_num[N-1] = (blk_vnum - vnum_osd) * blk_hnum; + /*debug*/ + if ((amlc_debug == 0x4)) { + pr_info("#vnum_osd = %d;\n", vnum_osd); + pr_info("#valid_blk_num[%d] = %d\n", + N-1, valid_blk_num[N-1]); + pr_info("#valid_blk_num[%d] = %d\n", + N-2, valid_blk_num[N-2]); + } + + /*2.2.2motion dif.if motion dif too large, + * we think scene changed + */ + scene_dif[N-1] = abs((frm_dif[N - 1] / (valid_blk_num[N-1]+1)) - + (frm_dif[N - 2] / (valid_blk_num[N-2]+1))); + + if (scene_dif[N-1] > scene_change_th) + scene_change_flag = 1; + else + scene_change_flag = 0; + + /*debug*/ + if ((scene_dif[N-1] > scene_change_th) && amlc_iir_debug_en) { + for (i = 0; i < N; i++) + pr_info(" valid_blk_num[%d] = %d,\n", + i, valid_blk_num[i]); + for (i = 0; i < N; i++) + pr_info(" frm_dif[%d] = %d,\n", + i, frm_dif[i]); + pr_info("\n\n"); + for (i = 0; i < N; i++) + pr_info(" scene_dif[%d] = %d,\n", + i, scene_dif[i]); + pr_info(" scene_change_flag =%d\n\n", + scene_change_flag); + } + } + return scene_change_flag; +} +/* + *function: set tiir alpha based on different situation + *input: scene_change_flag, frm_cnt(frm_cnt_above,frm_cnt_below) + *out:refresh_alpha[96] + */ +int cal_iir_alpha(int *refresh_alpha, + int blk_vnum, + int blk_hnum, + int refresh, + int scene_change_flag, + int frm_cnt_above, + int frm_cnt_below) +{ + int addr_curv1; + int osd_local_p, osd_local_m; + int i, j, k; + + /* 3.1 global scene change,highest priority */ + if (scene_change_flag) {/*only use current curve*/ + for (i = 0; i < blk_vnum; i++) { + for (j = 0; j < blk_hnum; j++) { + for (k = 0; k < CURV_NODES; k++) { + addr_curv1 = (i * blk_hnum + j); + refresh_alpha[addr_curv1] = refresh; + } + } + } + } else {/*time domain alpha blend, may need optimize*/ + for (i = 0; i < blk_vnum; i++) { + for (j = 0; j < blk_hnum; j++) { + addr_curv1 = (i * blk_hnum + j); + refresh_alpha[addr_curv1] = + alpha1;/*normal iir*/ + } + } + } + + /*3.2 osd situation-1, osd below */ + if ((frm_cnt_below > 0)) { + osd_local_p = max(vnum_start_below - 1, 0); + osd_local_m = min(vnum_end_below + 1, blk_vnum); + + for (i = osd_local_p; i <= osd_local_m; i++) { + for (j = 0; j < blk_hnum; j++) { + addr_curv1 = (i * blk_hnum + j); + /*osd around(-1,osd,+1) use heavy iir*/ + refresh_alpha[addr_curv1] = alpha2; + } + } + } + /*3.2 osd situation-2, osd above */ + if ((frm_cnt_above > 0)) { + osd_local_p = max(vnum_start_below - 1, 0); + osd_local_m = min(vnum_end_below + 1, blk_vnum); + + for (i = osd_local_p; i <= osd_local_m; i++) { + for (j = 0; j < blk_hnum; j++) { + addr_curv1 = (i * blk_hnum + j); + /*osd around use heavy iir*/ + refresh_alpha[addr_curv1] = alpha2; + } + } + } + + return 0; +} +/*function: curve iir process + * out: curve_nodes_cur(after iir) + */ +int cal_curv_iir(int *curve_nodes_cur, + int *curve_nodes_pre, + int *refresh_alpha, + int blk_vnum, + int blk_hnum, + int refresh) +{ + int i, j, k; + int tmap[CURV_NODES]; + int addr_curv1, addr_curv2; + int node_cur, node_pre; + + for (i = 0; i < blk_vnum; i++) { + for (j = 0; j < blk_hnum; j++) { + addr_curv1 = (i * blk_hnum + j); + for (k = 0; k < CURV_NODES; k++) { + addr_curv2 = + (i * blk_hnum + j) * CURV_NODES + k; + node_cur =/*u12 calc*/ + (curve_nodes_cur[addr_curv2] << 2); + node_pre = (curve_nodes_pre[addr_curv2] << 2); + tmap[k] = + (node_cur * refresh_alpha[addr_curv1] + + node_pre * + (refresh - refresh_alpha[addr_curv1]) + + (1 << (refresh_bit - 1))) >> + refresh_bit; + /*output the iir result*/ + curve_nodes_cur[addr_curv2] = + (tmap[k] >> 2);/*back to u10*/ + /*delay for next iir*/ + curve_nodes_pre[addr_curv2] = + (tmap[k] >> 2); + } + } + } + return 0; +} + +/* + * attention ! + * note 1: + * video_scene_change_flag_en + * video_scene_change_flag + *should from front module,indicate scene changed; + * + * Note 2: OSD appear location + * vnum_start_below + * vnum_end_below (case1) + * vnum_start_above + * vnum_end_above (case2) + */ + + /* iir algorithm top level path */ +static void lc_fw_curve_iir(struct vframe_s *vf, + int *lc_hist, + int *lc_szcurve, + int blk_vnum, + int blk_hnum) +{ + int i; + int scene_change_flag; + /* osd detect */ + static int frm_cnt_below, frm_cnt_above; + static int osd_flag_cnt_below[2]; + static int osd_flag_cnt_above[2]; + /* alpha blend init */ + int refresh_alpha[96] = {0};/*96=vnum*hnum*/ + int refresh = 1 << refresh_bit; + + if (!vf) + return; + + if (!lc_curve_fresh) + goto stop_curvefresh; + /* pre: get curve nodes from szCurveInfo and save to curve_nodes_cur*/ + for (i = 0; i < 580; i++)/*12*8*6+4*/ + curve_nodes_cur[i] = lc_szcurve[i]; + /* pre: osd flag delay*/ + osd_flag_cnt_below[0] = osd_flag_cnt_below[1]; + osd_flag_cnt_above[0] = osd_flag_cnt_above[1]; + + /* step 1: osd detect*/ + osd_detect( + osd_flag_cnt_above,/*out*/ + osd_flag_cnt_below,/*out*/ + &frm_cnt_above,/*out*/ + &frm_cnt_below,/*out: osd case heavy iir time */ + lc_hist, + blk_hnum); + + /*step 2: scene change signal get: two method*/ + scene_change_flag = global_scene_change( + curve_nodes_cur, + curve_nodes_pre, + blk_vnum, + blk_hnum, + osd_flag_cnt_above, + osd_flag_cnt_below); + + /* step 3: set tiir alpha based on different situation */ + cal_iir_alpha(refresh_alpha,/*out*/ + blk_vnum, + blk_hnum, + refresh, + scene_change_flag, + frm_cnt_above, + frm_cnt_below); + + /* step 4: iir filter */ + cal_curv_iir(curve_nodes_cur,/*out: iir-ed curve*/ + /*out: store previous frame curve */ + curve_nodes_pre, + refresh_alpha, + blk_vnum, + blk_hnum, + refresh); + + for (i = 0; i < 580; i++) + lc_szcurve[i] = curve_nodes_cur[i];/*output*/ + + frm_cnt_below--; + if (frm_cnt_below < 0) + frm_cnt_below = 0; + + frm_cnt_above--; + if (frm_cnt_above < 0) + frm_cnt_above = 0; + return; + +stop_curvefresh: + for (i = 0; i < 580; i++) + lc_szcurve[i] = curve_nodes_cur[i];/*output*/ +} + +static void lc_read_region(int blk_vnum, int blk_hnum) +{ + int i, j, k; + int data32; + int rgb_min, rgb_max; + + WRITE_VPP_REG_BITS(0x4037, 1, 14, 1); + data32 = READ_VPP_REG(LC_STTS_HIST_START_RD_REGION); + + for (i = 0; i < blk_vnum; i++) + for (j = 0; j < blk_hnum; j++) { + data32 = READ_VPP_REG(LC_STTS_HIST_START_RD_REGION); + if ((i >= lc_hist_vs) && (i <= lc_hist_ve) && + (j >= lc_hist_hs) && (j <= lc_hist_he) && + (amlc_debug == 0x6) && lc_hist_prcnt) + pr_info("========[r,c](%2d,%2d)======\n", i, j); + + for (k = 0; k < 17; k++) { + data32 = READ_VPP_REG(LC_STTS_HIST_READ_REGION); + lc_hist[(i*blk_hnum+j)*17 + k] + = data32; + if ((i >= lc_hist_vs) && (i <= lc_hist_ve) && + (j >= lc_hist_hs) && (j <= lc_hist_he) + && (amlc_debug == 0x6) && + lc_hist_prcnt) { + /*print chosen hist*/ + if (k == 16) {/*last bin*/ + rgb_min = + (data32 >> 10) & 0x3ff; + rgb_max = (data32) & 0x3ff; + pr_info("[%2d]:%d,%d\n", + k, rgb_min, rgb_max); + } else + pr_info("[%2d]:%d\n", + k, data32); + } + } + } + + if ((amlc_debug == 0x8) && lc_hist_prcnt)/*print all hist data*/ + for (i = 0; i < 8*12*17; i++) + pr_info("%x\n", lc_hist[i]); + if (lc_hist_prcnt > 0) + lc_hist_prcnt--; +} + +static void lc_prt_curve(void) +{/*print curve node*/ + int i, j; + int dwTemp, blk_hnum, blk_vnum; + + dwTemp = READ_VPP_REG(LC_CURVE_HV_NUM); + blk_hnum = (dwTemp >> 8) & 0x1f; + blk_vnum = (dwTemp) & 0x1f; + pr_amlc_dbg("======lc_prt curve node=======\n"); + for (i = 0; i < blk_hnum*blk_vnum; i++) { + for (j = 0; j < 6 ; j++) + pr_amlc_dbg("%d\n", lc_szcurve[i*6 + j]); + pr_amlc_dbg("\n"); + } +} + +void lc_init(int bitdepth) { int h_num, v_num; unsigned int height, width; const struct vinfo_s *vinfo = get_current_vinfo(); + int i, tmp, tmp1, tmp2; height = vinfo->height; width = vinfo->width; h_num = 12; v_num = 8; + lc_szcurve = kzalloc(580 * sizeof(int), GFP_KERNEL); + if (!lc_szcurve) + return; + curve_nodes_cur = kzalloc(580 * sizeof(int), GFP_KERNEL); + if (!curve_nodes_cur) { + kfree(lc_szcurve); + return; + } + curve_nodes_pre = kzalloc(580 * sizeof(int), GFP_KERNEL); + if (!curve_nodes_pre) { + kfree(lc_szcurve); + kfree(curve_nodes_cur); + return; + } + lc_hist = kzalloc(1632 * sizeof(int), GFP_KERNEL); + if (!lc_hist) { + kfree(lc_szcurve); + kfree(curve_nodes_cur); + kfree(curve_nodes_pre); + return; + } + lc_malloc_ok = 1; if (!lc_en) return; - lc_top_config(0, h_num, v_num, height, width); - lc_mtx_set(INP_MTX, LC_MTX_YUV709L_RGB, 1); - lc_mtx_set(OUTP_MTX, LC_MTX_RGB_YUV709L, 1); + lc_top_config(0, h_num, v_num, height, width, bitdepth, 1); + WRITE_VPP_REG_BITS(LC_CURVE_RAM_CTRL, 0, 0, 1); - if (set_lc_curve(NULL, 1, 0)) + /*default LC low parameters*/ + WRITE_VPP_REG(LC_CURVE_CONTRAST_LH, 0x000b000b); + WRITE_VPP_REG(LC_CURVE_CONTRAST_SCL_LH, 0x00000b0b); + WRITE_VPP_REG(LC_CURVE_MISC0, 0x00023028); + WRITE_VPP_REG(LC_CURVE_YPKBV_RAT, 0x8cc0c060); + WRITE_VPP_REG(LC_CURVE_YPKBV_SLP_LMT, 0x00000b3a); + + WRITE_VPP_REG(LC_CURVE_YMINVAL_LMT_0_1, 0x0030005d); + WRITE_VPP_REG(LC_CURVE_YMINVAL_LMT_2_3, 0x00830091); + WRITE_VPP_REG(LC_CURVE_YMINVAL_LMT_4_5, 0x00a000c4); + WRITE_VPP_REG(LC_CURVE_YMINVAL_LMT_6_7, 0x00e00100); + WRITE_VPP_REG(LC_CURVE_YMINVAL_LMT_8_9, 0x01200140); + WRITE_VPP_REG(LC_CURVE_YMINVAL_LMT_10_11, 0x01600190); + + WRITE_VPP_REG(LC_CURVE_YPKBV_YMAXVAL_LMT_0_1, 0x004400b4); + WRITE_VPP_REG(LC_CURVE_YPKBV_YMAXVAL_LMT_2_3, 0x00fb0123); + WRITE_VPP_REG(LC_CURVE_YPKBV_YMAXVAL_LMT_4_5, 0x015901a2); + WRITE_VPP_REG(LC_CURVE_YPKBV_YMAXVAL_LMT_6_7, 0x01d90208); + WRITE_VPP_REG(LC_CURVE_YPKBV_YMAXVAL_LMT_8_9, 0x02400280); + WRITE_VPP_REG(LC_CURVE_YPKBV_YMAXVAL_LMT_10_11, 0x02d70310); + + for (i = 0; i < 31 ; i++) { + tmp1 = *(lc_satur_off + 2 * i); + tmp2 = *(lc_satur_off + 2 * i + 1); + tmp = ((tmp1 & 0xfff)<<16) | (tmp2 & 0xfff); + WRITE_VPP_REG(SRSHARP1_LC_SAT_LUT_0_1 + i, tmp); + } + tmp = (*(lc_satur_off + 62)) & 0xfff; + WRITE_VPP_REG(SRSHARP1_LC_SAT_LUT_62, tmp); + /*end*/ + + if (set_lc_curve(1, 0)) pr_amlc_dbg("%s: init fail", __func__); } @@ -483,32 +1308,63 @@ void lc_process(struct vframe_s *vf, unsigned int sps_h_en, unsigned int sps_v_en) { - int *szCurveInfo; + int blk_hnum, blk_vnum, dwTemp; + int bitdepth; if (get_cpu_type() < MESON_CPU_MAJOR_ID_TL1) return; + if (is_meson_tl1_cpu()) + bitdepth = 10; + else if (is_meson_tm2_cpu()) + bitdepth = 12; + else + bitdepth = 12; + if (!lc_en) { lc_disable(); return; } - - if ((vf == NULL) && (lc_flag == 0xff)) { - lc_disable(); - lc_flag = 0x0; + if (!lc_malloc_ok) { + pr_amlc_dbg("%s: lc malloc fail", __func__); + return; + } + if (vf == NULL) { + if (lc_flag == 0xff) { + lc_disable(); + lc_flag = 0x0; + } return; } - szCurveInfo = kmalloc(12 * 8 * 2 * sizeof(int), GFP_KERNEL); - - lc_config(lc_en, vf, sps_h_en, sps_v_en); - - read_lc_curve(szCurveInfo); - lc_fw_curve_iir(vf); - if (set_lc_curve(szCurveInfo, 0, 1)) + if (lc_flag == 0) { + lc_flag++; + return; + } + dwTemp = READ_VPP_REG(LC_CURVE_HV_NUM); + blk_hnum = (dwTemp >> 8) & 0x1f; + blk_vnum = (dwTemp) & 0x1f; + lc_config(lc_en, vf, sps_h_en, sps_v_en, bitdepth); + /*get each block curve*/ + read_lc_curve(blk_vnum, blk_hnum); + lc_read_region(blk_vnum, blk_hnum); + /*do time domain iir*/ + lc_fw_curve_iir(vf, lc_hist, + lc_szcurve, blk_vnum, blk_hnum); + if (lc_curve_prcnt > 0) { /*debug lc curve node*/ + lc_prt_curve(); + lc_curve_prcnt--; + } + if (set_lc_curve(0, 1)) pr_amlc_dbg("%s: set lc curve fail", __func__); lc_flag = 0xff; - kfree(szCurveInfo); } +void lc_free(void) +{ + kfree(lc_szcurve); + kfree(curve_nodes_cur); + kfree(curve_nodes_pre); + kfree(lc_hist); +} diff --git a/drivers/amlogic/media/enhancement/amvecm/local_contrast.h b/drivers/amlogic/media/enhancement/amvecm/local_contrast.h index ad742c8a583d..f62bd3b75966 100644 --- a/drivers/amlogic/media/enhancement/amvecm/local_contrast.h +++ b/drivers/amlogic/media/enhancement/amvecm/local_contrast.h @@ -21,6 +21,10 @@ #include +/*V1.0: Local_contrast Basic function, iir algorithm, debug interface for tool*/ +/*V1.1: add ioctrl load interface supprt*/ +#define LC_VER "Ref.2019/03/07-V1.1" + enum lc_mtx_sel_e { INP_MTX = 0x1, OUTP_MTX = 0x2, @@ -32,14 +36,66 @@ enum lc_mtx_csc_e { LC_MTX_NULL = 0, LC_MTX_YUV709L_RGB = 0x1, LC_MTX_RGB_YUV709L = 0x2, + LC_MTX_YUV601L_RGB = 0x3, + LC_MTX_RGB_YUV601L = 0x4, LC_MTX_MAX }; +enum lc_reg_lut_e { + SATUR_LUT = 0x1, + YMINVAL_LMT = 0x2, + YPKBV_YMAXVAL_LMT = 0x4, + YPKBV_RAT = 0x8, + YPKBV_SLP_LMT = 0x10, + CNTST_LMT = 0x20, + MAX_REG_LUT +}; + +struct lc_alg_param_s { + unsigned int dbg_parm0; + unsigned int dbg_parm1; + unsigned int dbg_parm2; + unsigned int dbg_parm3; + unsigned int dbg_parm4; +}; + + extern int amlc_debug; extern int lc_en; -extern void lc_init(void); +extern int lc_demo_mode; +extern unsigned int lc_hist_vs; +extern unsigned int lc_hist_ve; +extern unsigned int lc_hist_hs; +extern unsigned int lc_hist_he; +extern unsigned int lc_hist_prcnt; +extern unsigned int lc_curve_prcnt; +extern int osd_iir_en; +extern int amlc_iir_debug_en; +/*osd related setting */ +extern int vnum_start_below; +extern int vnum_end_below; +extern int vnum_start_above; +extern int vnum_end_above; +extern int invalid_blk; +/*u10,7000/21600=0.324*1024=331 */ +extern int min_bv_percent_th; +/*control the refresh speed*/ +extern int alpha1; +extern int alpha2; +extern int refresh_bit; +extern int ts; +extern int scene_change_th; +extern bool lc_curve_fresh; +extern int *lc_szcurve;/*12*8*6+4*/ +extern int *curve_nodes_cur; +extern int *lc_hist;/*12*8*17*/ +extern struct ve_lc_curve_parm_s lc_curve_parm_load; +extern struct lc_alg_param_s lc_alg_parm; + +extern void lc_init(int bitdepth); extern void lc_process(struct vframe_s *vf, unsigned int sps_h_en, unsigned int sps_v_en); +extern void lc_free(void); #endif diff --git a/drivers/amlogic/media/enhancement/amvecm/set_hdr2_v0.c b/drivers/amlogic/media/enhancement/amvecm/set_hdr2_v0.c index 79b40afc160f..f28f66561c79 100644 --- a/drivers/amlogic/media/enhancement/amvecm/set_hdr2_v0.c +++ b/drivers/amlogic/media/enhancement/amvecm/set_hdr2_v0.c @@ -1,7 +1,20 @@ +/* + * drivers/amlogic/media/enhancement/amvecm/set_hdr2_v0.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. + * + */ - - -/* Standard Linux headers */ #include #include #include @@ -80,22 +93,24 @@ int cgain_lut2[65] = { static int num_eo_y_lut_hdr = 143; int eo_y_lut_hdr[143] = { - 132288, 136832, 165440, 181832, 193440, 202088, 210400, 216476, 221882, - 227920, 231986, 235648, 239639, 243964, 247193, 249698, 252377, 271330, - 285261, 297148, 306377, 314682, 321922, 329204, 334486, 340750, 346085, - 350369, 355325, 360734, 363991, 367697, 371896, 376636, 379400, 382389, - 385731, 389458, 393410, 395711, 398260, 401078, 404188, 407615, 410492, - 412562, 414834, 417322, 420045, 423021, 426127, 427900, 429831, 431934, - 434222, 436709, 439410, 442342, 443945, 445668, 447230, 448187, 449224, - 450344, 451555, 452864, 454277, 455803, 457449, 458988, 459945, 460977, - 462089, 463286, 464576, 465964, 467458, 469066, 470795, 472655, 474655, - 475971, 477126, 478368, 479702, 481136, 482676, 484330, 486107, 488015, - 490063, 491891, 493071, 494339, 495699, 497159, 498727, 500409, 502262, - 504308, 506503, 508381, 509646, 511003, 512460, 512934, 513098, 513279, - 513477, 513691, 513923, 514172, 514438, 514720, 515017, 515328, 515650, - 515981, 516320, 516662, 517006, 517349, 517689, 518022, 518347, 518662, - 518968, 519263, 519549, 519827, 520097, 520363, 520625, 520888, 521155, - 521431, 521727, 522054, 522431, 522871, 523371, 523881, 524287 + 1032192, 1032192, 1032192, 1032192, 16384, 16384, 16384, 16384, + 32768, 32768, 32768, 32768, 40960, 40960, 40960, 49152, 49152, + 73728, 86016, 94208, 100352, 104448, 108544, 112640, 117760, 123904, + 128000, 133632, 137728, 141824, 146944, 150272, 153344, 157440, + 161536, 165248, 167808, 170880, 174208, 177792, 181056, 183360, + 185792, 188480, 191552, 194880, 197536, 199520, 201696, 204128, + 206688, 209568, 212640, 214480, 216336, 218320, 220464, 222832, + 225360, 228112, 230248, 231864, 233608, 235496, 237544, 239752, + 242136, 244712, 246628, 248132, 249748, 251492, 253364, 255388, + 257564, 259908, 262290, 263646, 265106, 266678, 268366, 270182, + 272134, 274230, 276486, 278717, 280017, 281415, 282915, 284525, + 286255, 288113, 290107, 292247, 294545, 295961, 297284, 298705, + 300229, 301866, 303622, 305507, 307530, 309701, 311664, 312915, + 314257, 315698, 317246, 318907, 320690, 322605, 324662, 326871, + 328461, 329735, 331104, 332575, 334155, 335853, 337679, 339642, + 341752, 344021, 345263, 346576, 347989, 349509, 351145, 352907, + 354805, 356848, 359050, 360935, 362214, 363593, 365080, 366684, + 368414, 370283, 372300, 374478, 376832 }; module_param_array(eo_y_lut_hdr, int, &num_eo_y_lut_hdr, 0664); MODULE_PARM_DESC(eo_y_lut_hdr, "\n eo_y_lut_hdr\n"); @@ -232,18 +247,19 @@ int oo_y_lut_hdr_hlg[149] = { static int num_hdr_sdr_lut = 149; int oo_y_lut_hdr_sdr[149] = { - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255 + 2844, 2844, 2844, 2844, 2844, 2844, 2844, 2844, 2844, 2844, 2844, + 2844, 2844, 2844, 2844, 2844, 2844, 2844, 2844, 2844, 2844, 2844, + 2844, 2844, 2844, 2844, 2844, 2844, 2844, 2844, 2844, 2844, 2844, + 2844, 2844, 2844, 2844, 2844, 2844, 2844, 2844, 2844, 2844, 2844, + 2844, 2844, 2844, 2844, 2844, 2844, 2844, 2844, 2844, 2844, 2844, + 2844, 2844, 2844, 2844, 2844, 2844, 2844, 2844, 2844, 2844, 2844, + 2844, 2844, 2844, 2844, 2844, 2844, 2844, 2844, 2844, 2844, 2844, + 2844, 2844, 2844, 2844, 2844, 2844, 2844, 2844, 2844, 2844, 2844, + 2844, 2844, 2844, 2844, 2844, 2844, 2844, 2844, 2844, 2844, 2810, + 2635, 2481, 2225, 2020, 1852, 1712, 1593, 1491, 1403, 1325, 1196, + 1092, 1006, 935, 874, 822, 776, 736, 668, 614, 568, 530, 497, 468, + 442, 419, 381, 349, 322, 299, 279, 261, 246, 233, 221, 210, 201, + 192, 184, 177, 170, 164, 158, 153, 148, 143, 139, 135, 131, 128 }; module_param_array(oo_y_lut_hdr_sdr, int, &num_hdr_sdr_lut, 0664); MODULE_PARM_DESC(oo_y_lut_hdr_sdr, "\n num_hdr_sdr_lut\n"); @@ -694,14 +710,18 @@ MODULE_PARM_DESC(hdr2_debug, "\n hdr2_debug\n"); /* gamut 3x3 matrix*/ /*standard 2020rgb->709rgb*/ -/*int ncl_2020_709[9] = {*/ - /*3401, -1204, -149, -255, 2320, -17, -37, -206, 2291};*/ +int ncl_2020_709[9] = { + 3401, -1204, -149, -255, 2320, -17, -37, -206, 2291}; /* dci-p3->709rgb*/ /*int ncl_2020_709[9] = {*/ /*2543, -459, -36, -88, 2133, 3, -41, -161, 2250};*/ -/* special primary->709rgb*/ -int ncl_2020_709[9] = { +/* standard2020->dcip3-d65 8bit*/ +int ncl_2020_p3[9] = { + 368, -96, -16, -16, 275, -3, 1, -8, 263}; + +/*for iptv special primary->709rgb*/ +int ncl_sp_709[9] = { 2684, -489, -147, -201, 2266, -17, -29, -171, 2248}; /*int cl_2020_709[9] =*/ @@ -744,6 +764,16 @@ static int bypass_coeff[15] = { 0, 0, 0, }; +unsigned int _log2(unsigned int value) +{ + unsigned int ret; + + for (ret = 0; value > 1; ret++) + value >>= 1; + + return ret; +} + /*in/out matrix*/ void set_hdr_matrix( enum hdr_module_sel module_sel, @@ -1137,9 +1167,60 @@ void set_hdr_matrix( if (hdr_mtx_param == NULL) return; - VSYNC_WR_MPEG_REG_BITS(hdr_ctrl, hdr_mtx_param->mtx_on, 13, 1); + + if ((is_meson_g12b_cpu() && is_meson_rev_b()) && + (module_sel & OSD1_HDR)) + _VSYNC_WR_MPEG_REG_BITS(hdr_ctrl, + hdr_mtx_param->mtx_on, 13, 1); + else + VSYNC_WR_MPEG_REG_BITS(hdr_ctrl, + hdr_mtx_param->mtx_on, 13, 1); if (mtx_sel & HDR_IN_MTX) { + if ((is_meson_g12b_cpu() && is_meson_rev_b()) && + (module_sel & OSD1_HDR)) { + for (i = 0; i < 15; i++) + mtx[i] = hdr_mtx_param->mtx_in[i]; + _VSYNC_WR_MPEG_REG(MATRIXI_EN_CTRL, + hdr_mtx_param->mtx_on); + /*yuv in*/ + _VSYNC_WR_MPEG_REG_BITS(hdr_ctrl, + hdr_mtx_param->mtx_on, 4, 1); + + _VSYNC_WR_MPEG_REG_BITS(hdr_ctrl, + hdr_mtx_param->mtx_only, + 16, 1); + _VSYNC_WR_MPEG_REG_BITS(hdr_ctrl, 0, 17, 1); + /*mtx in en*/ + _VSYNC_WR_MPEG_REG_BITS(hdr_ctrl, 1, 14, 1); + + _VSYNC_WR_MPEG_REG(MATRIXI_COEF00_01, + (mtx[0 * 3 + 0] << 16) | + (mtx[0 * 3 + 1] & 0x1FFF)); + _VSYNC_WR_MPEG_REG(MATRIXI_COEF02_10, + (mtx[0 * 3 + 2] << 16) | + (mtx[1 * 3 + 0] & 0x1FFF)); + _VSYNC_WR_MPEG_REG(MATRIXI_COEF11_12, + (mtx[1 * 3 + 1] << 16) | + (mtx[1 * 3 + 2] & 0x1FFF)); + _VSYNC_WR_MPEG_REG(MATRIXI_COEF20_21, + (mtx[2 * 3 + 0] << 16) | + (mtx[2 * 3 + 1] & 0x1FFF)); + _VSYNC_WR_MPEG_REG(MATRIXI_COEF22, + mtx[2 * 3 + 2]); + _VSYNC_WR_MPEG_REG(MATRIXI_OFFSET0_1, + (yuv2rgbpos[0] << 16) | + (yuv2rgbpos[1] & 0xFFF)); + _VSYNC_WR_MPEG_REG(MATRIXI_OFFSET2, + yuv2rgbpos[2]); + _VSYNC_WR_MPEG_REG(MATRIXI_PRE_OFFSET0_1, + (yuv2rgbpre[0] << 16) | + (yuv2rgbpre[1] & 0xFFF)); + _VSYNC_WR_MPEG_REG(MATRIXI_PRE_OFFSET2, + yuv2rgbpre[2]); + + return; + } for (i = 0; i < 15; i++) mtx[i] = hdr_mtx_param->mtx_in[i]; VSYNC_WR_MPEG_REG(MATRIXI_EN_CTRL, hdr_mtx_param->mtx_on); @@ -1170,19 +1251,22 @@ void set_hdr_matrix( (yuv2rgbpre[0] << 16)|(yuv2rgbpre[1] & 0xFFF)); VSYNC_WR_MPEG_REG(MATRIXI_PRE_OFFSET2, yuv2rgbpre[2]); - } else if (mtx_sel & HDR_GAMUT_MTX) { for (i = 0; i < 9; i++) gmut_coef[i/3][i%3] = hdr_mtx_param->mtx_gamut[i]; /*for g12a/g12b osd blend shift rtl bug*/ if ((is_meson_g12a_cpu() || - is_meson_g12b_cpu()) && + (is_meson_g12b_cpu() && is_meson_rev_a())) && (hdr_mtx_param->p_sel & HDR_BYPASS) && (module_sel & OSD1_HDR)) gmut_shift = 10; + else if (hdr_mtx_param->p_sel & HDR_SDR) + /*work around for gamut bug*/ + gmut_shift = 0;/*11*/ else - gmut_shift = 11; + /*default 11, set 12 avoid gamut overwrite*/ + gmut_shift = 12; for (i = 0; i < 3; i++) c_gain_lim_coef[i] = @@ -1191,7 +1275,7 @@ void set_hdr_matrix( adpscl_mode = 1; for (i = 0; i < 3; i++) { if ((is_meson_g12a_cpu() || - is_meson_g12b_cpu()) && + (is_meson_g12b_cpu() && is_meson_rev_a())) && (hdr_mtx_param->p_sel & HDR_BYPASS) && (module_sel & OSD1_HDR)) adpscl_enable[i] = 1; @@ -1217,68 +1301,165 @@ void set_hdr_matrix( adpscl_alpha[i] = 10 * in_luma * (1 << adp_scal_shift) / out_luma; - if (hdr_mtx_param->p_sel & HDR_SDR) { - if (i == 0) - adpscl_shift[i] = adp_scal_shift; - else - adpscl_shift[i] = adp_scal_shift - 2; - } else - adpscl_shift[i] = adp_scal_shift; - adpscl_ys_coef[i] = 1 << adp_scal_shift; adpscl_beta_s[i] = 0; adpscl_beta[i] = 0; } + /*shift0 is for x coordinate*/ + adpscl_shift[0] = adp_scal_shift; + /*shift1 is for scale multiple*/ + if (hdr_mtx_param->p_sel & HDR_SDR) + adpscl_shift[1] = adp_scal_shift - + _log2((1 << adp_scal_shift) / oo_y_lut_hdr_sdr[148]); + else + adpscl_shift[1] = adp_scal_shift - 1; + /*shift2 is not used, set default*/ + adpscl_shift[2] = adp_scal_shift; + /*gamut mode: 1->gamut before ootf*/ /*2->gamut after ootf*/ /*other->disable gamut*/ - VSYNC_WR_MPEG_REG_BITS(hdr_ctrl, 2, 6, 2); + if ((is_meson_g12b_cpu() && is_meson_rev_b()) && + (module_sel & OSD1_HDR)) { + _VSYNC_WR_MPEG_REG_BITS(hdr_ctrl, 1, 6, 2); - VSYNC_WR_MPEG_REG(GMUT_CTRL, gmut_shift); - VSYNC_WR_MPEG_REG(GMUT_COEF0, + _VSYNC_WR_MPEG_REG(GMUT_CTRL, gmut_shift); + _VSYNC_WR_MPEG_REG(GMUT_COEF0, + (gmut_coef[0][1] & 0xffff) << 16 | + (gmut_coef[0][0] & 0xffff)); + _VSYNC_WR_MPEG_REG(GMUT_COEF1, + (gmut_coef[1][0] & 0xffff) << 16 | + (gmut_coef[0][2] & 0xffff)); + _VSYNC_WR_MPEG_REG(GMUT_COEF2, + (gmut_coef[1][2] & 0xffff) << 16 | + (gmut_coef[1][1] & 0xffff)); + _VSYNC_WR_MPEG_REG(GMUT_COEF3, + (gmut_coef[2][1] & 0xffff) << 16 | + (gmut_coef[2][0] & 0xffff)); + _VSYNC_WR_MPEG_REG(GMUT_COEF4, + gmut_coef[2][2] & 0xffff); + + _VSYNC_WR_MPEG_REG(CGAIN_COEF0, + c_gain_lim_coef[1] << 16 | + c_gain_lim_coef[0]); + _VSYNC_WR_MPEG_REG_BITS(CGAIN_COEF1, + c_gain_lim_coef[2], 0, 12); + + _VSYNC_WR_MPEG_REG(ADPS_CTRL, + adpscl_enable[2] << 6 | + adpscl_enable[1] << 5 | + adpscl_enable[0] << 4 | + adpscl_mode); + _VSYNC_WR_MPEG_REG(ADPS_ALPHA0, + adpscl_alpha[1]<<16 | adpscl_alpha[0]); + _VSYNC_WR_MPEG_REG(ADPS_ALPHA1, + adpscl_shift[0] << 24 | + adpscl_shift[1] << 20 | + adpscl_shift[2] << 16 | + adpscl_alpha[2]); + _VSYNC_WR_MPEG_REG(ADPS_BETA0, + adpscl_beta_s[0] << 20 | adpscl_beta[0]); + _VSYNC_WR_MPEG_REG(ADPS_BETA1, + adpscl_beta_s[1] << 20 | adpscl_beta[1]); + _VSYNC_WR_MPEG_REG(ADPS_BETA2, + adpscl_beta_s[2] << 20 | adpscl_beta[2]); + _VSYNC_WR_MPEG_REG(ADPS_COEF0, + adpscl_ys_coef[1] << 16 | + adpscl_ys_coef[0]); + _VSYNC_WR_MPEG_REG(ADPS_COEF1, + adpscl_ys_coef[2]); + + return; + } + VSYNC_WR_MPEG_REG_BITS(hdr_ctrl, 1, 6, 2); + + VSYNC_WR_MPEG_REG(GMUT_CTRL, gmut_shift); + VSYNC_WR_MPEG_REG(GMUT_COEF0, (gmut_coef[0][1] & 0xffff) << 16 | (gmut_coef[0][0] & 0xffff)); - VSYNC_WR_MPEG_REG(GMUT_COEF1, + VSYNC_WR_MPEG_REG(GMUT_COEF1, (gmut_coef[1][0] & 0xffff) << 16 | (gmut_coef[0][2] & 0xffff)); - VSYNC_WR_MPEG_REG(GMUT_COEF2, + VSYNC_WR_MPEG_REG(GMUT_COEF2, (gmut_coef[1][2] & 0xffff) << 16 | (gmut_coef[1][1] & 0xffff)); - VSYNC_WR_MPEG_REG(GMUT_COEF3, + VSYNC_WR_MPEG_REG(GMUT_COEF3, (gmut_coef[2][1] & 0xffff) << 16 | (gmut_coef[2][0] & 0xffff)); - VSYNC_WR_MPEG_REG(GMUT_COEF4, + VSYNC_WR_MPEG_REG(GMUT_COEF4, gmut_coef[2][2] & 0xffff); - VSYNC_WR_MPEG_REG(CGAIN_COEF0, + VSYNC_WR_MPEG_REG(CGAIN_COEF0, c_gain_lim_coef[1] << 16 | c_gain_lim_coef[0]); - VSYNC_WR_MPEG_REG(CGAIN_COEF1, c_gain_lim_coef[2] | - 0x400 << 16); + VSYNC_WR_MPEG_REG_BITS(CGAIN_COEF1, c_gain_lim_coef[2], + 0, 12); - VSYNC_WR_MPEG_REG(ADPS_CTRL, adpscl_enable[2] << 6 | - adpscl_enable[1] << 5 | - adpscl_enable[0] << 4 | - adpscl_mode); + VSYNC_WR_MPEG_REG(ADPS_CTRL, adpscl_enable[2] << 6 | + adpscl_enable[1] << 5 | + adpscl_enable[0] << 4 | + adpscl_mode); VSYNC_WR_MPEG_REG(ADPS_ALPHA0, adpscl_alpha[1]<<16 | adpscl_alpha[0]); VSYNC_WR_MPEG_REG(ADPS_ALPHA1, adpscl_shift[0] << 24 | - adpscl_shift[1] << 20 | - adpscl_shift[2] << 16 | - adpscl_alpha[2]); - VSYNC_WR_MPEG_REG(ADPS_BETA0, + adpscl_shift[1] << 20 | + adpscl_shift[2] << 16 | + adpscl_alpha[2]); + VSYNC_WR_MPEG_REG(ADPS_BETA0, adpscl_beta_s[0] << 20 | adpscl_beta[0]); - VSYNC_WR_MPEG_REG(ADPS_BETA1, + VSYNC_WR_MPEG_REG(ADPS_BETA1, adpscl_beta_s[1] << 20 | adpscl_beta[1]); - VSYNC_WR_MPEG_REG(ADPS_BETA2, + VSYNC_WR_MPEG_REG(ADPS_BETA2, adpscl_beta_s[2] << 20 | adpscl_beta[2]); - VSYNC_WR_MPEG_REG(ADPS_COEF0, + VSYNC_WR_MPEG_REG(ADPS_COEF0, adpscl_ys_coef[1] << 16 | adpscl_ys_coef[0]); - VSYNC_WR_MPEG_REG(ADPS_COEF1, adpscl_ys_coef[2]); - + VSYNC_WR_MPEG_REG(ADPS_COEF1, adpscl_ys_coef[2]); } else if (mtx_sel & HDR_OUT_MTX) { + if ((is_meson_g12b_cpu() && is_meson_rev_b()) && + (module_sel & OSD1_HDR)) { + for (i = 0; i < 15; i++) + mtx[i] = hdr_mtx_param->mtx_out[i]; + _VSYNC_WR_MPEG_REG(CGAIN_OFFT, + (rgb2yuvpos[2] << 16) | rgb2yuvpos[1]); + _VSYNC_WR_MPEG_REG(MATRIXO_EN_CTRL, + hdr_mtx_param->mtx_on); + /*yuv in*/ + _VSYNC_WR_MPEG_REG_BITS(hdr_ctrl, + hdr_mtx_param->mtx_on, 4, 1); + + _VSYNC_WR_MPEG_REG_BITS(hdr_ctrl, + hdr_mtx_param->mtx_only, + 16, 1); + _VSYNC_WR_MPEG_REG_BITS(hdr_ctrl, 0, 17, 1); + /*mtx out en*/ + _VSYNC_WR_MPEG_REG_BITS(hdr_ctrl, 1, 15, 1); + + _VSYNC_WR_MPEG_REG(MATRIXO_COEF00_01, + (mtx[0 * 3 + 0] << 16) | + (mtx[0 * 3 + 1] & 0x1FFF)); + _VSYNC_WR_MPEG_REG(MATRIXO_COEF02_10, + (mtx[0 * 3 + 2] << 16) | + (mtx[1 * 3 + 0] & 0x1FFF)); + _VSYNC_WR_MPEG_REG(MATRIXO_COEF11_12, + (mtx[1 * 3 + 1] << 16) | + (mtx[1 * 3 + 2] & 0x1FFF)); + _VSYNC_WR_MPEG_REG(MATRIXO_COEF20_21, + (mtx[2 * 3 + 0] << 16) | + (mtx[2 * 3 + 1] & 0x1FFF)); + _VSYNC_WR_MPEG_REG(MATRIXO_COEF22, + mtx[2 * 3 + 2]); + _VSYNC_WR_MPEG_REG(MATRIXO_OFFSET0_1, + (rgb2yuvpos[0] << 16) | (rgb2yuvpos[1]&0xFFF)); + _VSYNC_WR_MPEG_REG(MATRIXO_OFFSET2, + rgb2yuvpos[2]); + _VSYNC_WR_MPEG_REG(MATRIXO_PRE_OFFSET0_1, + (rgb2yuvpre[0] << 16)|(rgb2yuvpre[1]&0xFFF)); + _VSYNC_WR_MPEG_REG(MATRIXO_PRE_OFFSET2, + rgb2yuvpre[2]); + return; + } for (i = 0; i < 15; i++) mtx[i] = hdr_mtx_param->mtx_out[i]; VSYNC_WR_MPEG_REG(CGAIN_OFFT, @@ -1312,7 +1493,6 @@ void set_hdr_matrix( VSYNC_WR_MPEG_REG(MATRIXO_PRE_OFFSET2, rgb2yuvpre[2]); } - } void set_eotf_lut( @@ -1353,7 +1533,18 @@ void set_eotf_lut( for (i = 0; i < HDR2_EOTF_LUT_SIZE; i++) lut[i] = hdr_lut_param->eotf_lut[i]; + if ((is_meson_g12b_cpu() && is_meson_rev_b()) && + (module_sel & OSD1_HDR)) { + _VSYNC_WR_MPEG_REG_BITS(hdr_ctrl, hdr_lut_param->lut_on, 3, 1); + if (!hdr_lut_param->lut_on) + return; + + _VSYNC_WR_MPEG_REG(eotf_lut_addr_port, 0x0); + for (i = 0; i < HDR2_EOTF_LUT_SIZE; i++) + _VSYNC_WR_MPEG_REG(eotf_lut_data_port, lut[i]); + return; + } VSYNC_WR_MPEG_REG_BITS(hdr_ctrl, hdr_lut_param->lut_on, 3, 1); if (!hdr_lut_param->lut_on) @@ -1403,6 +1594,23 @@ void set_ootf_lut( for (i = 0; i < HDR2_OOTF_LUT_SIZE; i++) lut[i] = hdr_lut_param->ogain_lut[i]; + if ((is_meson_g12b_cpu() && is_meson_rev_b()) && + (module_sel & OSD1_HDR)) { + _VSYNC_WR_MPEG_REG_BITS(hdr_ctrl, hdr_lut_param->lut_on, 1, 1); + + if (!hdr_lut_param->lut_on) + return; + + _VSYNC_WR_MPEG_REG(ootf_lut_addr_port, 0x0); + for (i = 0; i < HDR2_OOTF_LUT_SIZE / 2; i++) + _VSYNC_WR_MPEG_REG(ootf_lut_data_port, + (lut[i * 2 + 1] << 16) + + lut[i * 2]); + _VSYNC_WR_MPEG_REG(ootf_lut_data_port, lut[148]); + + return; + } + VSYNC_WR_MPEG_REG_BITS(hdr_ctrl, hdr_lut_param->lut_on, 1, 1); if (!hdr_lut_param->lut_on) @@ -1455,6 +1663,32 @@ void set_oetf_lut( for (i = 0; i < HDR2_OETF_LUT_SIZE; i++) lut[i] = hdr_lut_param->oetf_lut[i]; + if ((is_meson_g12b_cpu() && is_meson_rev_b()) && + (module_sel & OSD1_HDR)) { + _VSYNC_WR_MPEG_REG_BITS(hdr_ctrl, hdr_lut_param->lut_on, 2, 1); + + if (!hdr_lut_param->lut_on) + return; + + _VSYNC_WR_MPEG_REG(oetf_lut_addr_port, 0x0); + for (i = 0; i < HDR2_OETF_LUT_SIZE / 2; i++) { + if (hdr_lut_param->bitdepth == 10) + _VSYNC_WR_MPEG_REG(oetf_lut_data_port, + ((lut[i * 2 + 1] >> 2) << 16) + + (lut[i * 2] >> 2)); + else + _VSYNC_WR_MPEG_REG(oetf_lut_data_port, + (lut[i * 2 + 1] << 16) + + lut[i * 2]); + } + if (hdr_lut_param->bitdepth == 10) + _VSYNC_WR_MPEG_REG(oetf_lut_data_port, lut[148] >> 2); + else + _VSYNC_WR_MPEG_REG(oetf_lut_data_port, lut[148]); + + return; + } + VSYNC_WR_MPEG_REG_BITS(hdr_ctrl, hdr_lut_param->lut_on, 2, 1); if (!hdr_lut_param->lut_on) @@ -1470,8 +1704,12 @@ void set_oetf_lut( VSYNC_WR_MPEG_REG(oetf_lut_data_port, (lut[i * 2 + 1] << 16) + lut[i * 2]); - } + } + if (hdr_lut_param->bitdepth == 10) + VSYNC_WR_MPEG_REG(oetf_lut_data_port, lut[148] >> 2); + else VSYNC_WR_MPEG_REG(oetf_lut_data_port, lut[148]); + } void set_c_gain( @@ -1482,32 +1720,39 @@ void set_c_gain( unsigned int cgain_lut_addr_port = 0; unsigned int cgain_lut_data_port = 0; unsigned int hdr_ctrl = 0; + unsigned int cgain_coef1 = 0; unsigned int i = 0; if (module_sel & VD1_HDR) { cgain_lut_addr_port = VD1_CGAIN_LUT_ADDR_PORT; cgain_lut_data_port = VD1_CGAIN_LUT_DATA_PORT; hdr_ctrl = VD1_HDR2_CTRL; + cgain_coef1 = VD1_HDR2_CGAIN_COEF1; } else if (module_sel & VD2_HDR) { cgain_lut_addr_port = VD2_CGAIN_LUT_ADDR_PORT; cgain_lut_data_port = VD2_CGAIN_LUT_DATA_PORT; hdr_ctrl = VD2_HDR2_CTRL; + cgain_coef1 = VD2_HDR2_CGAIN_COEF1; } else if (module_sel & OSD1_HDR) { cgain_lut_addr_port = OSD1_CGAIN_LUT_ADDR_PORT; cgain_lut_data_port = OSD1_CGAIN_LUT_DATA_PORT; hdr_ctrl = OSD1_HDR2_CTRL; + cgain_coef1 = OSD1_HDR2_CGAIN_COEF1; } else if (module_sel & DI_HDR) { cgain_lut_addr_port = DI_CGAIN_LUT_ADDR_PORT; cgain_lut_data_port = DI_CGAIN_LUT_DATA_PORT; hdr_ctrl = DI_HDR2_CTRL; + cgain_coef1 = DI_HDR2_CGAIN_COEF1; } else if (module_sel & VDIN0_HDR) { cgain_lut_addr_port = VDIN0_CGAIN_LUT_ADDR_PORT; cgain_lut_data_port = VDIN0_CGAIN_LUT_DATA_PORT; hdr_ctrl = VDIN0_HDR2_CTRL; + cgain_coef1 = VDIN0_HDR2_CGAIN_COEF1; } else if (module_sel & VDIN1_HDR) { cgain_lut_addr_port = VDIN1_CGAIN_LUT_ADDR_PORT; cgain_lut_data_port = VDIN1_CGAIN_LUT_DATA_PORT; hdr_ctrl = VDIN1_HDR2_CTRL; + cgain_coef1 = VDIN1_HDR2_CGAIN_COEF1; } for (i = 0; i < HDR2_CGAIN_LUT_SIZE; i++) @@ -1515,9 +1760,35 @@ void set_c_gain( /*cgain mode: 0->y domin*/ /*cgain mode: 1->rgb domin, use r/g/b max*/ - VSYNC_WR_MPEG_REG_BITS(hdr_ctrl, hdr_lut_param->cgain_en, 12, 1); + if ((is_meson_g12b_cpu() && is_meson_rev_b()) && + (module_sel & OSD1_HDR)) { + _VSYNC_WR_MPEG_REG_BITS(hdr_ctrl, + hdr_lut_param->cgain_en, 12, 1); + _VSYNC_WR_MPEG_REG_BITS(hdr_ctrl, + hdr_lut_param->cgain_en, 0, 1); + + if (!hdr_lut_param->cgain_en) + return; + + _VSYNC_WR_MPEG_REG(cgain_lut_addr_port, 0x0); + for (i = 0; i < HDR2_CGAIN_LUT_SIZE / 2; i++) + _VSYNC_WR_MPEG_REG(cgain_lut_data_port, + (lut[i * 2 + 1] << 16) + lut[i * 2]); + _VSYNC_WR_MPEG_REG(cgain_lut_data_port, lut[64]); + return; + } + + /*cgain mode force 0*/ + VSYNC_WR_MPEG_REG_BITS(hdr_ctrl, 0, 12, 1); VSYNC_WR_MPEG_REG_BITS(hdr_ctrl, hdr_lut_param->cgain_en, 0, 1); + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) { + if (hdr_lut_param->bitdepth == 10) + VSYNC_WR_MPEG_REG_BITS(cgain_coef1, 0x400, 16, 13); + else if (hdr_lut_param->bitdepth == 12) + VSYNC_WR_MPEG_REG_BITS(cgain_coef1, 0x1000, 16, 13); + } + if (!hdr_lut_param->cgain_en) return; @@ -1586,7 +1857,7 @@ void hdr_func(enum hdr_module_sel module_sel, if (hdr_process_select & HDR_BYPASS) { /*for g12a/g12b osd blend shift rtl bug*/ if ((is_meson_g12a_cpu() || - is_meson_g12b_cpu()) && + (is_meson_g12b_cpu() && is_meson_rev_a())) && (module_sel & OSD1_HDR)) { for (i = 0; i < HDR2_OETF_LUT_SIZE; i++) { hdr_lut_param.oetf_lut[i] = oe_y_lut_bypass[i]; @@ -1643,7 +1914,7 @@ void hdr_func(enum hdr_module_sel module_sel, hdr_lut_param.bitdepth = bit_depth; /*for g12a/g12b osd blend shift rtl bug*/ if ((is_meson_g12a_cpu() || - is_meson_g12b_cpu()) && + (is_meson_g12b_cpu() && is_meson_rev_a())) && (module_sel & OSD1_HDR)) hdr_lut_param.cgain_en = LUT_ON; else @@ -1698,7 +1969,7 @@ void hdr_func(enum hdr_module_sel module_sel, hdr_lut_param.bitdepth = bit_depth; /*for g12a/g12b osd blend shift rtl bug*/ if ((is_meson_g12a_cpu() || - is_meson_g12b_cpu()) && + (is_meson_g12b_cpu() && is_meson_rev_a())) && (module_sel & OSD1_HDR)) hdr_lut_param.cgain_en = LUT_ON; else @@ -1711,7 +1982,7 @@ void hdr_func(enum hdr_module_sel module_sel, hdr_mtx_param.mtx_only = HDR_ONLY; /*for g12a/g12b osd blend shift rtl bug*/ if ((is_meson_g12a_cpu() || - is_meson_g12b_cpu()) && + (is_meson_g12b_cpu() && is_meson_rev_a())) && (hdr_process_select & HDR_BYPASS) && (module_sel & OSD1_HDR)) { for (i = 0; i < 15; i++) { @@ -1745,8 +2016,14 @@ void hdr_func(enum hdr_module_sel module_sel, hdr_mtx_param.mtx_cgain[i] = rgb2ycbcr_709[i]; hdr_mtx_param.mtx_ogain[i] = rgb2ycbcr_ncl2020[i]; hdr_mtx_param.mtx_out[i] = rgb2ycbcr_709[i]; - if (i < 9) - hdr_mtx_param.mtx_gamut[i] = ncl_2020_709[i]; + if (i < 9) { + if (hdr_process_select & HLG_SDR) + hdr_mtx_param.mtx_gamut[i] = + ncl_2020_709[i]; + else + hdr_mtx_param.mtx_gamut[i] = + ncl_2020_p3[i]; + } } hdr_mtx_param.mtx_on = MTX_ON; diff --git a/drivers/amlogic/media/enhancement/amvecm/set_hdr2_v0.h b/drivers/amlogic/media/enhancement/amvecm/set_hdr2_v0.h index 935d3d359c84..f9cd50c6371f 100644 --- a/drivers/amlogic/media/enhancement/amvecm/set_hdr2_v0.h +++ b/drivers/amlogic/media/enhancement/amvecm/set_hdr2_v0.h @@ -1,3 +1,20 @@ +/* + * drivers/amlogic/media/enhancement/amvecm/set_hdr2_v0.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. + * + */ + #include #ifndef MAX @@ -147,3 +164,15 @@ enum mtx_csc_e { extern void mtx_setting(enum vpp_matrix_e mtx_sel, enum mtx_csc_e mtx_csc, int mtx_on); + +#ifndef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA +#define _VSYNC_WR_MPEG_REG(adr, val) WRITE_VCBUS_REG(adr, val) +#define _VSYNC_RD_MPEG_REG(adr) READ_VCBUS_REG(adr) +#define _VSYNC_WR_MPEG_REG_BITS(adr, val, start, len) \ + WRITE_VCBUS_REG_BITS(adr, val, start, len) +#else +extern int _VSYNC_WR_MPEG_REG_BITS(u32 adr, + u32 val, u32 start, u32 len); +extern u32 _VSYNC_RD_MPEG_REG(u32 adr); +extern int _VSYNC_WR_MPEG_REG(u32 adr, u32 val); +#endif diff --git a/drivers/amlogic/media/enhancement/amvecm/vlock.c b/drivers/amlogic/media/enhancement/amvecm/vlock.c index 8ce8c0c088b7..49477b525bef 100644 --- a/drivers/amlogic/media/enhancement/amvecm/vlock.c +++ b/drivers/amlogic/media/enhancement/amvecm/vlock.c @@ -35,11 +35,13 @@ #include "amcm.h" /* video lock */ -/* 0:enc;1:pll; - * 2:manual pll; - * 3:manual_enc mode(only support lvds/vx1) +/* 0:off; + * 1:auto enc; VLOCK_MODE_AUTO_ENC + * 2:auto pll; + * 4:manual pll; VLOCK_MODE_MANUAL_PLL + * 8:manual_enc mode(only support lvds/vx1) */ -unsigned int vlock_mode = VLOCK_MODE_MANUAL_PLL; +enum VLOCK_MD vlock_mode = VLOCK_MODE_MANUAL_PLL; unsigned int vlock_en = 1; /* *0:only support 50->50;60->60;24->24;30->30; @@ -65,7 +67,7 @@ static unsigned int vlock_intput_type; static signed int vlock_line_limit = 3; static unsigned int vlock_enc_adj_limit; /* 0x3009 default setting for 2 line(1080p-output) is 0x8000 */ -static unsigned int vlock_capture_limit = 0x8000; +static unsigned int vlock_capture_limit = 0x10000/*0x8000*/; static unsigned int vlock_debug; static unsigned int vlock_dynamic_adjust = 1; @@ -79,7 +81,7 @@ static unsigned int pre_input_freq; static unsigned int pre_output_freq; static unsigned int vlock_dis_cnt; static bool vlock_vmode_changed; -static unsigned int vlock_vmode_change_status; +static unsigned int vlock_notify_event; static unsigned int pre_hiu_reg_m; static unsigned int pre_hiu_reg_frac; static signed int pre_enc_max_line; @@ -102,6 +104,12 @@ static unsigned int vlock_log_last_ivcnt; static unsigned int vlock_log_last_ovcnt; static unsigned int vlock_log_delta_m; static unsigned int vlock_log_delta_en; +static unsigned int hhi_pll_reg_m; +static unsigned int hhi_pll_reg_frac; + +static struct stvlock_sig_sts vlock; + +/*static unsigned int hhi_pll_reg_vlock_ctl;*/ module_param(vlock_log_size, uint, 0664); MODULE_PARM_DESC(vlock_log_size, "\n vlock_log_size\n"); module_param(vlock_log_cnt, uint, 0664); @@ -141,13 +149,17 @@ static unsigned int last_i_vsync; int amvecm_hiu_reg_read(unsigned int reg, unsigned int *val) { - *val = readl(amvecm_hiu_reg_base+((reg - 0x1000)<<2)); + /**val = readl(amvecm_hiu_reg_base+((reg - 0x1000)<<2));*/ + *val = aml_read_hiubus(reg); + /*pr_info("vlock rd hiu reg:0x%x,0x%x\n", (reg - 0x1000), *val);*/ return 0; } int amvecm_hiu_reg_write(unsigned int reg, unsigned int val) { - writel(val, (amvecm_hiu_reg_base+((reg - 0x1000)<<2))); + /*writel(val, (amvecm_hiu_reg_base+((reg - 0x1000)<<2)));*/ + /*pr_info("vlock rd hiu reg:0x%x,0x%x\n", (reg - 0x1000), val);*/ + aml_write_hiubus(reg, val); return 0; } static int amvecm_hiu_reg_write_bits(unsigned int reg, unsigned int value, @@ -162,6 +174,60 @@ static int amvecm_hiu_reg_write_bits(unsigned int reg, unsigned int value, return 0; } +u32 vlock_get_panel_pll_m(void) +{ + u32 val; + + amvecm_hiu_reg_read(hhi_pll_reg_m, &val); + return val; +} + +u32 vlock_get_panel_pll_frac(void) +{ + u32 val; + + amvecm_hiu_reg_read(hhi_pll_reg_frac, &val); + return val; +} + +void vlock_set_panel_pll_m(u32 val) +{ + u32 m = val; + + /*amvecm_hiu_reg_write(hhi_pll_reg_m, m);*/ + lcd_vlock_m_update(m); +} + +void vlock_set_panel_pll_frac(u32 val) +{ + u32 frac = val; + + /*amvecm_hiu_reg_write(hhi_pll_reg_frac, frac);*/ + lcd_vlock_farc_update(frac); +} + +void vlock_set_panel_pll(u32 m, u32 frac) +{ + vlock_set_panel_pll_m(m); + vlock_set_panel_pll_frac(frac); +} + +void vlock_set_panel_ss(u32 onoff) +{ + if (onoff) + lcd_ss_enable(1); + else + lcd_ss_enable(0); +} + +/*returen 1: use phase lock*/ +int phase_lock_check(void) +{ + unsigned int ret = 0; + + ret = READ_VPP_REG_BITS(VPU_VLOCK_RO_LCK_FRM, 17, 1); + return ret; +} static unsigned int vlock_check_input_hz(struct vframe_s *vf) { @@ -188,35 +254,60 @@ static unsigned int vlock_check_input_hz(struct vframe_s *vf) return ret_hz; } -static unsigned int vlock_check_output_hz(unsigned int sync_duration_num) +static unsigned int vlock_check_output_hz(unsigned int sync_duration_num, + unsigned int sync_duration_den) { unsigned int ret_hz = 0; + unsigned int tempHz; - switch (sync_duration_num) { - case 24: + tempHz = (sync_duration_num*100)/sync_duration_den; + + switch (tempHz) { + case 2400: ret_hz = 24; break; - case 30: + case 3000: ret_hz = 30; break; - case 50: + case 5000: ret_hz = 50; break; - case 60: + case 6000: ret_hz = 60; break; - case 100: + case 10000: ret_hz = 100; break; - case 120: + case 12000: ret_hz = 120; break; default: ret_hz = 0; break; } + + if ((ret_hz == 0) && (vlock_debug & VLOCK_DEBUG_INFO)) + pr_info("sync_duration_num:%d\n", sync_duration_num); + return ret_hz; } + +void vlock_reset(u32 onoff) +{ + if (onoff) { + /*cal accum1 value*/ + WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 1, 2, 1); + /*cal accum0 value*/ + WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 1, 5, 1); + } else { + /*cal accum1 value*/ + WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 2, 1); + /*cal accum0 value*/ + WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 5, 1); + } + /*pr_info("%s (%d)\n", __func__, onoff);*/ +} + /*vlock is support eq_after gxbb,but which is useful only for tv chip *after gxl,the enable/disable reg_bit is changed */ @@ -224,10 +315,9 @@ static void vlock_enable(bool enable) { unsigned int tmp_value; - amvecm_hiu_reg_read(HHI_HDMI_PLL_CNTL6, &tmp_value); - if (is_meson_gxtvbb_cpu()) { if (vlock_mode & VLOCK_MODE_MANUAL_PLL) { + amvecm_hiu_reg_read(HHI_HDMI_PLL_CNTL6, &tmp_value); amvecm_hiu_reg_write_bits(HHI_HDMI_PLL_CNTL6, 0, 20, 1); /*vlsi suggest config:don't enable load signal, *on gxtvbb this load signal will effect SSG, @@ -246,7 +336,24 @@ static void vlock_enable(bool enable) else amvecm_hiu_reg_write_bits(HHI_HDMI_PLL_CNTL5, enable, 3, 1); + } else if (vlock.dtdata->vlk_hwver >= vlock_hw_ver2) { + /*reset*/ + if (!(vlock_mode & VLOCK_MODE_MANUAL_PLL)) { + /*reset*/ + /*WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 1, 5, 1);*/ + /*WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 5, 1);*/ + } + + if (!enable) { + /*amvecm_hiu_reg_write_bits(*/ + /* HHI_HDMI_PLL_VLOCK_CNTL, 0, 0, 3);*/ + + /*WRITE_VPP_REG(VPU_VLOCK_CTRL, 0);*/ + } } + + if (vlock_debug & VLOCK_DEBUG_INFO) + pr_info(">>>[%s] (%d)\n", __func__, enable); } static void vlock_hw_reinit(struct vlock_regs_s *vlock_regs, unsigned int len) { @@ -256,22 +363,30 @@ static void vlock_hw_reinit(struct vlock_regs_s *vlock_regs, unsigned int len) return; for (i = 0; i < len; i++) WRITE_VPP_REG(vlock_regs[i].addr, vlock_regs[i].val); + + if (vlock_debug & VLOCK_DEBUG_INFO) + pr_info("[%s]\n", __func__); } static void vlock_setting(struct vframe_s *vf, unsigned int input_hz, unsigned int output_hz) { - unsigned int freq_hz = 0, hiu_reg_value_2_addr = HHI_HDMI_PLL_CNTL2; + unsigned int freq_hz = 0; unsigned int reg_value = 0, hiu_reg_value, hiu_reg_value_2; - unsigned int hiu_m_val, hiu_frac_val, temp_value; + unsigned int hiu_m_val = 0, hiu_frac_val = 0, temp_value; + if (vlock_debug & VLOCK_DEBUG_INFO) { + pr_info(">>>[%s]\n", __func__); + pr_info("inputHz:%d,outputHz:%d\n", input_hz, output_hz); + pr_info("type_original:0x%x\n", vf->type_original); + } amvecm_hiu_reg_write(HHI_VID_LOCK_CLK_CNTL, 0x80); - if ((vlock_mode & (VLOCK_MODE_AUTO_ENC | - VLOCK_MODE_MANUAL_ENC | - VLOCK_MODE_MANUAL_SOFT_ENC))) { + if (IS_ENC_MODE(vlock_mode)) { /*init default config for enc mode*/ vlock_hw_reinit(vlock_enc_setting, VLOCK_DEFAULT_REG_SIZE); /*vlock line limit*/ - WRITE_VPP_REG(VPU_VLOCK_OUTPUT0_CAPT_LMT, vlock_capture_limit); + /*WRITE_VPP_REG(VPU_VLOCK_OUTPUT0_CAPT_LMT,*/ + /* vlock_capture_limit);*/ + /* VLOCK_CNTL_EN disable */ vlock_enable(0); /* disable to adjust pll */ @@ -292,10 +407,12 @@ static void vlock_setting(struct vframe_s *vf, } /* enable to adjust enc */ WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 1, 30, 1); - /*clear accum1 value*/ - WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 1, 2, 1); - /*clear accum0 value*/ - WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 1, 5, 1); + if (get_cpu_type() < MESON_CPU_MAJOR_ID_TL1) { + /*clear accum1 value*/ + WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 1, 2, 1); + /*clear accum0 value*/ + WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 1, 5, 1); + } /*@20180314 new add*/ /* *set input & output freq @@ -303,8 +420,14 @@ static void vlock_setting(struct vframe_s *vf, *bit8~15:output freq */ if ((vf->type_original & VIDTYPE_TYPEMASK) && - !(vlock_mode & VLOCK_MODE_MANUAL_SOFT_ENC)) + !(vlock_mode & VLOCK_MODE_MANUAL_SOFT_ENC)) { + /*tl1 fix i problem*/ + if (get_cpu_type() < MESON_CPU_MAJOR_ID_TL1) input_hz = input_hz >> 1; + else + WRITE_VPP_REG_BITS(VPU_VLOCK_MISC_CTRL, + 1, 28, 1); + } freq_hz = input_hz | (output_hz << 8); WRITE_VPP_REG_BITS(VPU_VLOCK_MISC_CTRL, freq_hz, 0, 16); /* @@ -317,12 +440,15 @@ static void vlock_setting(struct vframe_s *vf, WRITE_VPP_REG_BITS(VPU_VLOCK_MISC_CTRL, input_hz, 16, 8); temp_value = READ_VPP_REG(enc_max_line_addr); - WRITE_VPP_REG_BITS(VPU_VLOCK_OROW_OCOL_MAX, temp_value, 0, 14); - temp_value = READ_VPP_REG(enc_max_pixel_addr); - WRITE_VPP_REG_BITS(VPU_VLOCK_OROW_OCOL_MAX, temp_value, 16, 14); + WRITE_VPP_REG_BITS(VPU_VLOCK_OROW_OCOL_MAX, + temp_value + 1, 0, 14); + /*tune pixel*/ + /*temp_value = READ_VPP_REG(enc_max_pixel_addr);*/ + /*WRITE_VPP_REG_BITS(VPU_VLOCK_OROW_OCOL_MAX,*/ + /* temp_value + 1, 16, 14);*/ WRITE_VPP_REG_BITS(VPU_VLOCK_ADJ_EN_SYNC_CTRL, vlock_latch_en_cnt, 8, 8); - WRITE_VPP_REG_BITS(enc_video_mode_addr, 0, 15, 1); + WRITE_VPP_REG_BITS(enc_video_mode_addr, 1, 15, 1); } if ((vlock_mode & (VLOCK_MODE_AUTO_PLL | VLOCK_MODE_MANUAL_PLL))) { @@ -333,8 +459,17 @@ static void vlock_setting(struct vframe_s *vf, *bit0~7:input freq *bit8~15:output freq */ - if (vf->type_original & VIDTYPE_TYPEMASK) - input_hz = input_hz >> 1; + if (vf->type_original & VIDTYPE_TYPEMASK) { + if (get_cpu_type() < MESON_CPU_MAJOR_ID_TL1) + input_hz = input_hz >> 1; + else + WRITE_VPP_REG_BITS(VPU_VLOCK_MISC_CTRL, + 1, 28, 1); + } else { + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) + WRITE_VPP_REG_BITS(VPU_VLOCK_MISC_CTRL, + 0, 28, 1); + } freq_hz = input_hz | (output_hz << 8); WRITE_VPP_REG_BITS(VPU_VLOCK_MISC_CTRL, freq_hz, 0, 16); /* @@ -349,10 +484,23 @@ static void vlock_setting(struct vframe_s *vf, /*set PLL M_INT;PLL M_frac*/ /* WRITE_VPP_REG_BITS(VPU_VLOCK_MX4096, */ /* READ_CBUS_REG_BITS(HHI_HDMI_PLL_CNTL,0,9),12,9); */ - amvecm_hiu_reg_read(HHI_HDMI_PLL_CNTL, &hiu_reg_value); - amvecm_hiu_reg_read(hiu_reg_value_2_addr, - &hiu_reg_value_2); - if (cpu_after_eq(MESON_CPU_MAJOR_ID_GXTVBB)) { + /*amvecm_hiu_reg_read(hhi_pll_reg_m, &hiu_reg_value);*/ + /*amvecm_hiu_reg_read(hhi_pll_reg_frac,*/ + /* &hiu_reg_value_2);*/ + hiu_reg_value = vlock_get_panel_pll_m(); + hiu_reg_value_2 = vlock_get_panel_pll_frac(); + + if (vlock_debug & VLOCK_DEBUG_INFO) { + pr_info("hhi_pll_reg_m:0x%x\n", hiu_reg_value); + pr_info("hhi_pll_reg_frac:0x%x\n", hiu_reg_value_2); + } + + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) { + hiu_m_val = hiu_reg_value & 0xff; + /*discard low 5 bits*/ + hiu_frac_val = (hiu_reg_value_2 >> 5) & 0xfff; + reg_value = (hiu_m_val << 12) + hiu_frac_val; + } else if (cpu_after_eq(MESON_CPU_MAJOR_ID_GXTVBB)) { hiu_m_val = hiu_reg_value & 0x1FF; hiu_frac_val = hiu_reg_value_2 & 0x3FF; if (hiu_reg_value_2 & 0x800) { @@ -366,6 +514,12 @@ static void vlock_setting(struct vframe_s *vf, } reg_value = (hiu_m_val << 12) + (hiu_frac_val << 2); + } else { + pr_info("err: m f value\n"); + } + if (vlock_debug & VLOCK_DEBUG_INFO) { + pr_info("hiu_m_val=0x%x\n", hiu_m_val); + pr_info("hiu_frac_val=0x%x\n", hiu_frac_val); } WRITE_VPP_REG_BITS(VPU_VLOCK_MX4096, reg_value, 0, 21); /*vlock_pll_adj_limit = (reg_value * 0x8000) >> 24;*/ @@ -375,7 +529,7 @@ static void vlock_setting(struct vframe_s *vf, /*enable vlock to adj pll*/ /* CFG_VID_LOCK_ADJ_EN disable */ - WRITE_VPP_REG_BITS(ENCL_MAX_LINE_SWITCH_POINT, 0, 13, 1); + WRITE_VPP_REG_BITS(enc_max_line_switch_addr, 0, 13, 1); /* disable to adjust enc */ WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 30, 1); /* VLOCK_CNTL_EN enable */ @@ -383,6 +537,21 @@ static void vlock_setting(struct vframe_s *vf, /* enable to adjust pll */ WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 1, 29, 1); } + + /*initial phase lock setting*/ + if (vlock.phlock_en) { + vlock_hw_reinit(vlock_pll_phase_setting, VLOCK_PHASE_REG_SIZE); + /*disable pll lock*/ + /*WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 3, 1);*/ + + /*enable pll mode and enc mode phase lock*/ + WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 3, 0, 2); + + /*reset*/ + /*WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 1, 2, 1);*/ + /*WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 1, 5, 1);*/ + } + /* vlock module output goes to which module */ switch (READ_VPP_REG_BITS(VPU_VIU_VENC_MUX_CTRL, 0, 2)) { case 0:/* ENCL */ @@ -404,33 +573,40 @@ static void vlock_setting(struct vframe_s *vf, else if (vf->source_type == VFRAME_SOURCE_TYPE_HDMI) /* Input Vsync source select from hdmi-rx */ WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 1, 16, 3); + + /*enable vlock*/ WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 1, 31, 1); } void vlock_vmode_check(void) { const struct vinfo_s *vinfo; - unsigned int t0, t1, hiu_reg_addr; + unsigned int t0, t1; if (vlock_en == 0) return; - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXL) - hiu_reg_addr = HHI_HDMI_PLL_CNTL1; - else - hiu_reg_addr = HHI_HDMI_PLL_CNTL2; + vinfo = get_current_vinfo(); vlock_vmode_changed = 0; - if ((vlock_vmode_change_status == VOUT_EVENT_MODE_CHANGE) || + if ((vlock_notify_event == VOUT_EVENT_MODE_CHANGE) || (pre_hiu_reg_m == 0)) { if (vlock_mode & (VLOCK_MODE_MANUAL_PLL | VLOCK_MODE_AUTO_PLL)) { - amvecm_hiu_reg_read(hiu_reg_addr, &t0); - amvecm_hiu_reg_read(HHI_HDMI_PLL_CNTL, &t1); - pre_hiu_reg_frac = t0 & 0xfff; - pre_hiu_reg_m = t1 & 0x1ff; + /*amvecm_hiu_reg_read(hhi_pll_reg_frac, &t0);*/ + /*amvecm_hiu_reg_read(hhi_pll_reg_m, &t1);*/ + t0 = vlock_get_panel_pll_m(); + t1 = vlock_get_panel_pll_frac(); + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) { + pre_hiu_reg_frac = (t0 >> 5) & 0xfff; + pre_hiu_reg_m = t1 & 0xff; + } else { + pre_hiu_reg_frac = t0 & 0xfff; + pre_hiu_reg_m = t1 & 0x1ff; + } } if ((vlock_mode & (VLOCK_MODE_MANUAL_ENC | VLOCK_MODE_AUTO_ENC | VLOCK_MODE_MANUAL_SOFT_ENC))) { + #if 0 switch (READ_VPP_REG_BITS(VPU_VIU_VENC_MUX_CTRL, 0, 2)) { case 0: @@ -466,20 +642,20 @@ void vlock_vmode_check(void) ENCL_MAX_LINE_SWITCH_POINT; break; } + #endif pre_enc_max_line = READ_VPP_REG(enc_max_line_addr); pre_enc_max_pixel = READ_VPP_REG(enc_max_pixel_addr); vlock_capture_limit = ((1 << 12) * vlock_line_limit) / vinfo->vtotal + 1; vlock_capture_limit <<= 12; } - vlock_vmode_change_status = 0; + vlock_notify_event = 0; vlock_vmode_changed = 1; } } static void vlock_disable_step1(void) { unsigned int m_reg_value, tmp_value, enc_max_line, enc_max_pixel; - unsigned int hiu_reg_addr; /* VLOCK_CNTL_EN disable */ vlock_enable(0); @@ -487,24 +663,56 @@ static void vlock_disable_step1(void) if ((vlock_mode & (VLOCK_MODE_MANUAL_PLL | VLOCK_MODE_AUTO_PLL | VLOCK_MODE_MANUAL_SOFT_ENC))) { - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXL) - hiu_reg_addr = HHI_HDMI_PLL_CNTL1; - else - hiu_reg_addr = HHI_HDMI_PLL_CNTL2; - amvecm_hiu_reg_read(hiu_reg_addr, &tmp_value); - m_reg_value = tmp_value & 0xfff; - if (m_reg_value != pre_hiu_reg_frac) { - tmp_value = (tmp_value & 0xfffff000) | - (pre_hiu_reg_frac & 0xfff); - amvecm_hiu_reg_write(hiu_reg_addr, tmp_value); - } - amvecm_hiu_reg_read(HHI_HDMI_PLL_CNTL, &tmp_value); - m_reg_value = tmp_value & 0x1ff; - if ((m_reg_value != pre_hiu_reg_m) && - (pre_hiu_reg_m != 0)) { - tmp_value = (tmp_value & 0xfffffe00) | - (pre_hiu_reg_m & 0x1ff); - amvecm_hiu_reg_write(HHI_HDMI_PLL_CNTL, tmp_value); + if (vlock.dtdata->vlk_hwver >= vlock_hw_ver2) { + #if 0 + amvecm_hiu_reg_read(hhi_pll_reg_frac, + &tmp_value); + m_reg_value = (tmp_value >> 5) & 0xfff; + if (m_reg_value != pre_hiu_reg_frac) { + tmp_value = (tmp_value & 0xfffff000) | + (pre_hiu_reg_frac & 0xfff); + amvecm_hiu_reg_write(hhi_pll_reg_frac, + tmp_value); + pr_info("restore f value=0x%x\n", tmp_value); + } + amvecm_hiu_reg_read(hhi_pll_reg_m, &tmp_value); + m_reg_value = tmp_value & 0xff; + if ((m_reg_value != pre_hiu_reg_m) && + (pre_hiu_reg_m != 0)) { + tmp_value = (tmp_value & 0xffffff00) | + (pre_hiu_reg_m & 0xff); + amvecm_hiu_reg_write(hhi_pll_reg_m, tmp_value); + pr_info("restore m value=0x%x\n", tmp_value); + } + #endif + /*restore the orginal pll setting*/ + tmp_value = vlock_get_panel_pll_m(); + m_reg_value = tmp_value & 0xff; + if (m_reg_value != (vlock.val_m & 0xff)) + vlock_set_panel_pll_m(vlock.val_m); + tmp_value = vlock_get_panel_pll_frac(); + m_reg_value = tmp_value & 0x1ffff; + if (m_reg_value != (vlock.val_frac & 0xfff)) + vlock_set_panel_pll_frac(vlock.val_frac); + /*amvecm_hiu_reg_write(hhi_pll_reg_frac,*/ + /* vlock.val_frac);*/ + pr_info("restore orignal m,f value\n"); + } else { + tmp_value = vlock_get_panel_pll_frac(); + m_reg_value = tmp_value & 0xfff; + if (m_reg_value != pre_hiu_reg_frac) { + tmp_value = (tmp_value & 0xfffff000) | + (pre_hiu_reg_frac & 0xfff); + vlock_set_panel_pll_frac(tmp_value); + } + tmp_value = vlock_get_panel_pll_m(); + m_reg_value = tmp_value & 0x1ff; + if ((m_reg_value != pre_hiu_reg_m) && + (pre_hiu_reg_m != 0)) { + tmp_value = (tmp_value & 0xfffffe00) | + (pre_hiu_reg_m & 0x1ff); + vlock_set_panel_pll_m(tmp_value); + } } } if ((vlock_mode & (VLOCK_MODE_MANUAL_ENC | @@ -537,15 +745,26 @@ static void vlock_disable_step1(void) } vlock_pll_stable_cnt = 0; vlock_enc_stable_flag = 0; + if (vlock_debug & VLOCK_DEBUG_INFO) + pr_info(">>>[%s]\n", __func__); } -static void vlock_disable_step2(void) +static bool vlock_disable_step2(void) { unsigned int temp_val; + bool ret = false; + /* need delay to disable follow regs(vlsi suggest!!!) */ if (vlock_dis_cnt > 0) vlock_dis_cnt--; - if (vlock_dis_cnt == 0) { + else if (vlock_dis_cnt == 0) { + if (vlock.dtdata->vlk_hwver >= vlock_hw_ver2) { + amvecm_hiu_reg_write_bits( + HHI_HDMI_PLL_VLOCK_CNTL, 0x4, 0, 3); + amvecm_hiu_reg_write_bits( + HHI_HDMI_PLL_VLOCK_CNTL, 0x0, 0, 3); + } + /* disable to adjust pll */ WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 29, 1); /* CFG_VID_LOCK_ADJ_EN disable */ @@ -556,11 +775,25 @@ static void vlock_disable_step2(void) /* disable vid_lock_en */ WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 31, 1); vlock_state = VLOCK_STATE_DISABLE_STEP2_DONE; - amvecm_hiu_reg_read(HHI_HDMI_PLL_CNTL6, &temp_val); - if (is_meson_gxtvbb_cpu() && (((temp_val >> 21) & 0x3) != 0)) - amvecm_hiu_reg_write_bits(HHI_HDMI_PLL_CNTL6, 0, 21, 2); + if (is_meson_gxtvbb_cpu()) { + amvecm_hiu_reg_read(HHI_HDMI_PLL_CNTL6, &temp_val); + if (((temp_val >> 21) & 0x3) != 0) + amvecm_hiu_reg_write_bits(HHI_HDMI_PLL_CNTL6, + 0, 21, 2); + } + ret = true; + + if (vlock_debug & VLOCK_DEBUG_INFO) + pr_info(">>>[%s]\n", __func__); } + + /*restore ss setting*/ + if (!vlock.ss_sts) + vlock_set_panel_ss(true); + + return ret; } + static void vlock_enable_step1(struct vframe_s *vf, struct vinfo_s *vinfo, unsigned int input_hz, unsigned int output_hz) { @@ -584,10 +817,13 @@ static void vlock_enable_step1(struct vframe_s *vf, struct vinfo_s *vinfo, vlock_sync_limit_flag = 0; vlock_vmode_changed = 0; vlock_dis_cnt = 0; - vlock_state = VLOCK_STATE_ENABLE_STEP1_DONE; + /*vlock_state = VLOCK_STATE_ENABLE_STEP1_DONE;*/ vlock_pll_stable_cnt = 0; vlock_log_cnt = 0; vlock_enc_stable_flag = 0; + + if (vlock_debug & VLOCK_DEBUG_INFO) + pr_info(">>>[%s]\n", __func__); } void vlock_log_start(void) @@ -715,6 +951,8 @@ static void vlock_enable_step3_enc(void) vlock_reg_get(); vlock_log_cnt++; } + if (vlock_debug & VLOCK_DEBUG_INFO) + pr_info(">>>[%s]\n", __func__); } static void vlock_enable_step3_soft_enc(void) @@ -823,7 +1061,7 @@ static void vlock_enable_step3_soft_enc(void) WRITE_VPP_REG(ENCL_VIDEO_MAX_LNCNT, pre_enc_max_line + line_adj); if (!(vlock_debug & VLOCK_DEBUG_ENC_PIXEL_ADJ_DIS)) - WRITE_VPP_REG(ENCL_MAX_LINE_SWITCH_POINT, + WRITE_VPP_REG(enc_max_line_switch_addr, pre_enc_max_pixel + pixel_adj); last_i_vsync = READ_VPP_REG(0x3011); @@ -840,7 +1078,10 @@ static void vlock_enable_step3_soft_enc(void) vlock_reg_get(); vlock_log_cnt++; } + if (vlock_debug & VLOCK_DEBUG_INFO) + pr_info(">>>[%s]\n", __func__); } + /*check pll adj value (0x3020),otherwise may cause blink*/ static void vlock_pll_adj_limit_check(unsigned int *pll_val) { @@ -863,15 +1104,16 @@ static void vlock_pll_adj_limit_check(unsigned int *pll_val) } } } + static void vlock_enable_step3_pll(void) { - unsigned int m_reg_value, tmp_value, abs_val, hiu_reg_addr; + unsigned int m_reg_value, tmp_value, abs_val; unsigned int ia, oa, abs_cnt; - - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXL) - hiu_reg_addr = HHI_HDMI_PLL_CNTL1; - else - hiu_reg_addr = HHI_HDMI_PLL_CNTL2; + unsigned int pre_m, new_m, tar_m, org_m; + u32 m_f_reg_value; + static u32 m_diff_cnt, f_diff_cnt; + u32 mchang = 0; + /*static u32 aaa;*/ /*vs_i*/ tmp_value = READ_VPP_REG(VPU_VLOCK_RO_VS_I_DIST); @@ -896,16 +1138,26 @@ static void vlock_enable_step3_pll(void) __func__, vlock_log_delta_vcnt, abs_val, vlock_log_last_ivcnt, vlock_log_last_ovcnt); - m_reg_value = READ_VPP_REG(VPU_VLOCK_RO_M_INT_FRAC); + m_f_reg_value = READ_VPP_REG(VPU_VLOCK_RO_M_INT_FRAC); if (vlock_log_en && (vlock_log_cnt < vlock_log_size)) { + #if 0 vlock_log[vlock_log_cnt]->pll_frac = (vlock_pll_val_last & 0xfff) >> 2; vlock_log[vlock_log_cnt]->pll_m = (vlock_pll_val_last >> 16) & 0x1ff; + #else + /*amvecm_hiu_reg_read(hhi_pll_reg_frac, &tmp_value);*/ + tmp_value = vlock_get_panel_pll_frac(); + vlock_log[vlock_log_cnt]->pll_frac = tmp_value; + + /*amvecm_hiu_reg_read(hhi_pll_reg_m, &tmp_value);*/ + tmp_value = vlock_get_panel_pll_m(); + vlock_log[vlock_log_cnt]->pll_m = tmp_value; + #endif vlock_reg_get(); vlock_log_cnt++; } - if (m_reg_value == 0) { + if (m_f_reg_value == 0) { vlock_state = VLOCK_STATE_ENABLE_FORCE_RESET; if (vlock_debug & VLOCK_DEBUG_INFO) pr_info("%s:vlock pll work abnormal! force reset vlock\n", @@ -913,18 +1165,26 @@ static void vlock_enable_step3_pll(void) return; } /*check adjust delta limit*/ - vlock_pll_adj_limit_check(&m_reg_value); + if (vlock.dtdata->vlk_hwver < vlock_hw_ver2) + vlock_pll_adj_limit_check(&m_f_reg_value); /*vlsi suggest config:don't enable load signal, *on gxtvbb this load signal will effect SSG, *which may result in flashes black */ + if (is_meson_gxtvbb_cpu()) { amvecm_hiu_reg_read(HHI_HDMI_PLL_CNTL6, &tmp_value); - if (is_meson_gxtvbb_cpu() && (((tmp_value >> 21) & 0x3) != 2)) + if (((tmp_value >> 21) & 0x3) != 2) amvecm_hiu_reg_write_bits(HHI_HDMI_PLL_CNTL6, 2, 21, 2); - /*add delta count check*/ - /*for interlace input need div 2*/ - if (vlock_intput_type) + } + + /* add delta count check + *for interlace input need div 2 + *0:progressive type + *1:interlace type + */ + if (vlock_intput_type && + (vlock.dtdata->vlk_hwver < vlock_hw_ver2)) ia = READ_VPP_REG(VPU_VLOCK_RO_VS_I_DIST) / 2; else ia = READ_VPP_REG(VPU_VLOCK_RO_VS_I_DIST); @@ -935,46 +1195,125 @@ static void vlock_enable_step3_pll(void) pr_info("%s:vlock input cnt abnormal!!\n", __func__); return; } - /*frac*/ - amvecm_hiu_reg_read(hiu_reg_addr, &tmp_value); - abs_val = abs(((m_reg_value & 0xfff) >> 2) - (tmp_value & 0xfff)); - if ((abs_val >= vlock_log_delta_frac) && (vlock_log_delta_en&(1<<3))) - pr_info("vlock frac delta:%d(0x%x,0x%x)\n", - abs_val, ((m_reg_value & 0xfff) >> 2), - (tmp_value & 0xfff)); - if ((abs_val >= vlock_delta_limit) && - (abs_cnt > vlock_delta_cnt_limit)) { - tmp_value = (tmp_value & 0xfffff000) | - ((m_reg_value & 0xfff) >> 2); - amvecm_hiu_reg_write(hiu_reg_addr, tmp_value); - vlock_pll_val_last &= 0xffff0000; - vlock_pll_val_last |= (m_reg_value & 0xfff); - } - /*check stable by diff frac*/ - if ((abs_val < (2 * vlock_delta_limit)) && - (abs_cnt < vlock_enc_adj_limit)) - vlock_pll_stable_cnt++; - else - vlock_pll_stable_cnt = 0; + /*m*/ - amvecm_hiu_reg_read(HHI_HDMI_PLL_CNTL, &tmp_value); - abs_val = abs(((m_reg_value >> 16) & 0x1ff) - (pre_hiu_reg_m & 0x1ff)); - if ((abs_val > vlock_log_delta_m) && (vlock_log_delta_en&(1<<4))) - pr_info("vlock m delta:%d(0x%x,0x%x)\n", - abs_val, ((m_reg_value >> 16) & 0x1ff), - (tmp_value & 0x1ff)); - if ((abs_val <= vlock_pll_m_limit) && - (((m_reg_value >> 16) & 0x1ff) != (tmp_value & 0x1ff)) && - (abs_cnt > vlock_delta_cnt_limit)) { - tmp_value = (tmp_value & 0xfffffe00) | - ((m_reg_value >> 16) & 0x1ff); - amvecm_hiu_reg_write(HHI_HDMI_PLL_CNTL, tmp_value); - vlock_pll_val_last &= 0x0000ffff; - vlock_pll_val_last |= (m_reg_value & 0xffff0000); + tmp_value = vlock_get_panel_pll_m(); + if (vlock.dtdata->vlk_hwver < vlock_hw_ver2) { + abs_val = abs(((m_f_reg_value >> 16) & 0xff) - + (pre_hiu_reg_m & 0xff)); + if ((abs_val > vlock_log_delta_m) && + (vlock_log_delta_en&(1<<4))) + pr_info("vlock m delta:%d(0x%x,0x%x)\n", + abs_val, ((m_f_reg_value >> 16) & 0x1ff), + (tmp_value & 0x1ff)); + if ((abs_val <= vlock_pll_m_limit) && + (((m_f_reg_value >> 16) & 0x1ff) != + (tmp_value & 0x1ff)) && + (abs_cnt > vlock_delta_cnt_limit)) { + tmp_value = (tmp_value & 0xfffffe00) | + ((m_f_reg_value >> 16) & 0x1ff); + vlock_set_panel_pll_m(tmp_value); + vlock_pll_val_last &= 0x0000ffff; + vlock_pll_val_last |= (m_f_reg_value & 0xffff0000); + } + } else { + pre_m = (tmp_value & 0xff); + new_m = ((m_f_reg_value >> 16) & 0x1ff); + org_m = (vlock.val_m & 0xff); + if ((pre_m != new_m) && (m_diff_cnt++ > VLOCK_UPDATE_M_CNT)) { + m_diff_cnt = 0; + if (new_m > pre_m) { + tar_m = ((pre_m + 1) < + (org_m + 1))?(pre_m + 1):(org_m + 1); + } else { + /*tar_m < pre_m*/ + tar_m = ((pre_m - 1) < + (org_m - 1))?(org_m - 1):(pre_m - 1); + } + m_reg_value = (tmp_value & 0xffffff00) + tar_m; + if (tar_m != (tmp_value & 0xffffff00)) { + vlock_set_panel_pll_m(m_reg_value); + mchang = 1; + if (vlock_debug & VLOCK_DEBUG_INFO) + pr_info("vlock m: pre=0x%x, rp=0x%x, wr=0x%x\n", + pre_m, new_m, m_reg_value); + } + #if 0 + /*for test*/ + pr_info("vlock m: 0x%x (%d)\n", vlock.val_m, aaa); + if (aaa == 0) { + aaa = 1; + vlock_set_panel_pll_m(vlock.val_m + 1); + } else if (aaa == 1) { + aaa = 2; + vlock_set_panel_pll_m(vlock.val_m); + } else if (aaa == 2) { + aaa = 3; + vlock_set_panel_pll_m(vlock.val_m - 1); + } else if (aaa == 3) { + aaa = 0; + vlock_set_panel_pll_m(vlock.val_m); + } + #endif + } } + + /*frac*/ + tmp_value = vlock_get_panel_pll_frac(); + if (vlock.dtdata->vlk_hwver < vlock_hw_ver2) { + abs_val = abs(((m_f_reg_value & 0xfff) >> 2) - + (tmp_value & 0xfff)); + if ((abs_val >= vlock_log_delta_frac) && + (vlock_log_delta_en&(1<<3))) + pr_info("vlock frac delta:%d(0x%x,0x%x)\n", + abs_val, ((m_f_reg_value & 0xfff) >> 2), + (tmp_value & 0xfff)); + if ((abs_val >= vlock_delta_limit) && + (abs_cnt > vlock_delta_cnt_limit)) { + tmp_value = (tmp_value & 0xfffff000) | + ((m_f_reg_value & 0xfff) >> 2); + /*amvecm_hiu_reg_write(hhi_pll_reg_frac, tmp_value);*/ + vlock_set_panel_pll_frac(tmp_value); + vlock_pll_val_last &= 0xffff0000; + vlock_pll_val_last |= (m_f_reg_value & 0xfff); + } + /*check stable by diff frac*/ + if ((abs_val < (2 * vlock_delta_limit)) && + (abs_cnt < vlock_enc_adj_limit)) + vlock_pll_stable_cnt++; + else + vlock_pll_stable_cnt = 0; + } else { + abs_val = abs((tmp_value & 0x1ffff) - + ((m_f_reg_value & 0xfff) << 5)); + + if (abs_val > (50 << 5)) + tmp_value = ((tmp_value & 0xfffe0000) | + (((tmp_value & 0x1ffff) + + ((m_f_reg_value & 0xfff) << 5)) >> 1)); + else + tmp_value = (tmp_value & 0xfffe0000) | + ((m_f_reg_value & 0xfff) << 5); + if (((tmp_value & 0x1ffff) != + (vlock_get_panel_pll_frac() & 0x1ffff)) && + !mchang) { + if (f_diff_cnt++ > VLOCK_UPDATE_F_CNT) { + f_diff_cnt = 0; + if (vlock_debug & VLOCK_DEBUG_INFO) + pr_info("vlock f: 0x%x\n", tmp_value); + vlock_set_panel_pll_frac(tmp_value);/*16:0*/ + } + } + } + /*check stable by diff m*/ - if (((m_reg_value >> 16) & 0x1ff) != (tmp_value & 0x1ff)) - vlock_pll_stable_cnt = 0; + if (vlock.dtdata->vlk_hwver >= vlock_hw_ver2) { + if (((m_f_reg_value >> 16) & 0xff) != (tmp_value & 0xff)) + vlock_pll_stable_cnt = 0; + } else { + if (((m_f_reg_value >> 16) & 0x1ff) != (tmp_value & 0x1ff)) + vlock_pll_stable_cnt = 0; + } } /* won't change this function internal seqence, * if really need change,please be carefull and check with vlsi @@ -994,10 +1333,12 @@ void amve_vlock_process(struct vframe_s *vf) } vinfo = get_current_vinfo(); input_hz = vlock_check_input_hz(vf); - output_hz = vlock_check_output_hz(vinfo->sync_duration_num); + output_hz = vlock_check_output_hz(vinfo->sync_duration_num, + vinfo->sync_duration_den); vlock_dis_cnt_no_vf = 0; if (vecm_latch_flag & FLAG_VLOCK_EN) { vlock_enable_step1(vf, vinfo, input_hz, output_hz); + vlock_state = VLOCK_STATE_ENABLE_STEP1_DONE; vlock_en = 1; vecm_latch_flag &= ~FLAG_VLOCK_EN; } @@ -1022,7 +1363,7 @@ void amve_vlock_process(struct vframe_s *vf) __func__); return; } - if (vlock_vmode_change_status == VOUT_EVENT_MODE_CHANGE_PRE) { + if (vlock_notify_event == VOUT_EVENT_MODE_CHANGE_PRE) { vlock_enable(0); if (vlock_debug & VLOCK_DEBUG_INFO) pr_info("[%s]auto disable vlock module for vmode change pre case!!!\n", @@ -1035,43 +1376,74 @@ void amve_vlock_process(struct vframe_s *vf) (input_hz != pre_input_freq) || (output_hz != pre_output_freq) || vlock_vmode_changed || - (vlock_state == VLOCK_STATE_ENABLE_FORCE_RESET)) + (vlock_state == VLOCK_STATE_ENABLE_FORCE_RESET)) { vlock_enable_step1(vf, vinfo, input_hz, output_hz); + vlock_state = VLOCK_STATE_ENABLE_STEP1_DONE; + } if ((vlock_sync_limit_flag < 10) && (vlock_state >= VLOCK_STATE_ENABLE_STEP1_DONE)) { vlock_sync_limit_flag++; if ((vlock_sync_limit_flag <= 3) && ((vlock_mode & (VLOCK_MODE_MANUAL_ENC | VLOCK_MODE_MANUAL_PLL)))) { + /*reset*/ WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 1, 5, 1); WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 1, 2, 1); + /*clear first 3 frame internal cnt*/ WRITE_VPP_REG(VPU_VLOCK_OVWRITE_ACCUM0, 0); WRITE_VPP_REG(VPU_VLOCK_OVWRITE_ACCUM1, 0); + if (vlock_debug & VLOCK_DEBUG_INFO) + pr_info("amve_vlock_process-0\n"); } if ((vlock_sync_limit_flag == 4) && ((vlock_mode & (VLOCK_MODE_MANUAL_ENC | VLOCK_MODE_MANUAL_PLL)))) { + /*release reset*/ WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 5, 1); WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 2, 1); + if (vlock_debug & VLOCK_DEBUG_INFO) + pr_info("amve_vlock_process-1\n"); } } + if ((vlock_sync_limit_flag == 5) && (vlock_state == VLOCK_STATE_ENABLE_STEP1_DONE)) { /*input_vs_cnt =*/ /*READ_VPP_REG_BITS(VPU_VLOCK_RO_VS_I_DIST,*/ /* 0, 28);*/ input_vs_cnt = XTAL_VLOCK_CLOCK/input_hz; - if (vf->type_original & VIDTYPE_TYPEMASK) + /*tl1 not need */ + if (!cpu_after_eq(MESON_CPU_MAJOR_ID_TL1) && + vf->type_original & VIDTYPE_TYPEMASK) input_vs_cnt = input_vs_cnt << 1; + WRITE_VPP_REG(VPU_VLOCK_LOOP1_IMISSYNC_MAX, input_vs_cnt*125/100); WRITE_VPP_REG(VPU_VLOCK_LOOP1_IMISSYNC_MIN, input_vs_cnt*70/100); + /*cal accum1 value*/ - WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 2, 1); + /*WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 2, 1);*/ /*cal accum0 value*/ - WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 5, 1); + /*WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 5, 1);*/ + vlock_reset(0); vlock_state = VLOCK_STATE_ENABLE_STEP2_DONE; + + /* + * tl1 auto pll,swich clk need after + *several frames + */ + if (vlock.dtdata->vlk_hwver >= vlock_hw_ver2) { + if (IS_AUTO_MODE(vlock_mode)) + amvecm_hiu_reg_write_bits( + HHI_HDMI_PLL_VLOCK_CNTL, 0x7, 0, 3); + else if (IS_MANUAL_MODE(vlock_mode)) + amvecm_hiu_reg_write_bits( + HHI_HDMI_PLL_VLOCK_CNTL, 0x6, 0, 3); + } + + if (vlock_debug & VLOCK_DEBUG_INFO) + pr_info("amve_vlock_process-2\n"); } else if (vlock_dynamic_adjust && (vlock_sync_limit_flag > 5) && (vlock_state == VLOCK_STATE_ENABLE_STEP2_DONE) && @@ -1149,18 +1521,645 @@ void amve_vlock_resume(void) } } +void vlock_clear_frame_counter(void) +{ + vlock.frame_cnt_in = 0; + vlock.frame_cnt_no = 0; + vlock_log_cnt = 0; + vlock.phlock_sts = false; + vlock.frqlock_sts = false; + vlock.pll_mode_pause = false; + /*vlock.frqlock_stable_cnt = 0;*/ +} + +void vlock_set_en(bool en) +{ + /*if (vlock.dtdata->vlk_support)*/ + vlock_en = en; +} + +void vlock_status_init(void) +{ + /*config vlock mode*/ + /*todo:txlx & g9tv support auto pll,*/ + /*but support not good,need vlsi support optimize*/ + vlock_mode = VLOCK_MODE_MANUAL_PLL; + if (is_meson_gxtvbb_cpu() || + is_meson_txl_cpu() || is_meson_txlx_cpu() + || is_meson_tl1_cpu() || is_meson_tm2_cpu()) + vlock_en = 1; + else + vlock_en = 0; + + /*initial pll register address*/ + if (is_meson_tl1_cpu() || is_meson_tm2_cpu()) { + hhi_pll_reg_m = HHI_TCON_PLL_CNTL0; + hhi_pll_reg_frac = HHI_TCON_PLL_CNTL1; + /*hhi_pll_reg_vlock_ctl = HHI_HDMI_PLL_VLOCK_CNTL;*/ + } else if (get_cpu_type() >= + MESON_CPU_MAJOR_ID_GXL) { + hhi_pll_reg_m = HHI_HDMI_PLL_CNTL; + hhi_pll_reg_frac = HHI_HDMI_PLL_CNTL2; + } else { + hhi_pll_reg_m = HHI_HDMI_PLL_CNTL; + hhi_pll_reg_frac = HHI_HDMI_PLL_CNTL2; + } + + /*initial enc register address*/ + switch (READ_VPP_REG_BITS(VPU_VIU_VENC_MUX_CTRL, + 0, 2)) { + case 0: + enc_max_line_addr = ENCL_VIDEO_MAX_LNCNT; + enc_max_pixel_addr = ENCL_VIDEO_MAX_PXCNT; + enc_video_mode_addr = ENCL_VIDEO_MODE; + enc_video_mode_adv_addr = ENCL_VIDEO_MODE_ADV; + enc_max_line_switch_addr = + ENCL_MAX_LINE_SWITCH_POINT; + break; +#if 0 /*enc mode not adapt to ENCP and ENCT*/ + case 2: + enc_max_line_addr = ENCP_VIDEO_MAX_LNCNT; + enc_max_pixel_addr = ENCP_VIDEO_MAX_PXCNT; + enc_video_mode_addr = ENCP_VIDEO_MODE; + enc_max_line_switch_addr = + ENCP_MAX_LINE_SWITCH_POINT; + break; + case 3: + enc_max_line_addr = ENCT_VIDEO_MAX_LNCNT; + enc_max_pixel_addr = ENCT_VIDEO_MAX_PXCNT; + enc_video_mode_addr = ENCT_VIDEO_MODE; + enc_max_line_switch_addr = + ENCT_MAX_LINE_SWITCH_POINT; + break; +#endif + default: + enc_max_line_addr = ENCL_VIDEO_MAX_LNCNT; + enc_max_pixel_addr = ENCL_VIDEO_MAX_PXCNT; + enc_video_mode_addr = ENCL_VIDEO_MODE; + enc_video_mode_adv_addr = ENCL_VIDEO_MODE_ADV; + enc_max_line_switch_addr = + ENCL_MAX_LINE_SWITCH_POINT; + break; + } + + /*back up orignal pll value*/ + vlock.val_m = vlock_get_panel_pll_m(); + vlock.val_frac = vlock_get_panel_pll_frac(); + + vlock.fsm_sts = VLOCK_STATE_NULL; + vlock.fsm_prests = VLOCK_STATE_NULL; + vlock.vf_sts = false; + vlock.vmd_chg = false; + vlock.md_support = false; + vlock.fsm_pause = false; + vlock.ss_sts = true; + vlock.phlock_sts = false; + vlock.frqlock_sts = false; + vlock.pll_mode_pause = false; + vlock.phlock_en = vlock.dtdata->vlk_phlock_en; + /* vlock.phlock_percent = phlock_percent; */ + vlock_clear_frame_counter(); + + pr_info("%s vlock_en:%d\n", __func__, vlock_en); +} + +void vlock_dt_match_init(struct vecm_match_data_s *pdata) +{ + vlock.dtdata = pdata; + /*vlock_en = vlock.dtdata.vlk_support;*/ + pr_info("vlock dt support: %d\n", vlock.dtdata->vlk_support); + pr_info("vlock dt new_fsm: %d\n", vlock.dtdata->vlk_new_fsm); + pr_info("vlock dt hwver: %d\n", vlock.dtdata->vlk_hwver); + pr_info("vlock dt phlock_en: %d\n", vlock.dtdata->vlk_phlock_en); +} + +void vlock_set_phase(u32 percent) +{ + u32 vs_i_val = READ_VPP_REG(VPU_VLOCK_RO_VS_I_DIST); + /*u32 vs_o_val = READ_VPP_REG(VPU_VLOCK_RO_VS_O_DIST);*/ + u32 data = 0; + + if (!vlock.phlock_en) + return; + + if (percent > 100) { + pr_info("percent val err:%d\n", percent); + return; + } + + vlock.phlock_percent = percent; + data = (vs_i_val * (100 + vlock.phlock_percent))/200; + WRITE_VPP_REG(VPU_VLOCK_LOOP1_PHSDIF_TGT, data); + + vlock_reset(1); + vlock_reset(0); +} + +void vlock_set_phase_en(u32 en) +{ + if (en) + vlock.phlock_en = true; + else + vlock.phlock_en = false; + pr_info("vlock phlock_en=%d\n", en); +} + +void vlock_phaselock_check(struct stvlock_sig_sts *pvlock, + struct vframe_s *vf) +{ + /*vs_i*/ + u32 ia = READ_VPP_REG(VPU_VLOCK_RO_VS_I_DIST); + u32 val, pre; + + if (vlock.phlock_en) { + if ((pvlock->frame_cnt_in%100) == 0) { + ia = READ_VPP_REG(VPU_VLOCK_RO_VS_I_DIST); + pre = READ_VPP_REG(VPU_VLOCK_LOOP1_PHSDIF_TGT); + val = (ia * (100 + vlock.phlock_percent))/200; + if (val != pre) { + WRITE_VPP_REG(VPU_VLOCK_LOOP1_PHSDIF_TGT, val); + vlock_reset(1); + vlock_reset(0); + } + } + } +} + +bool vlock_get_phlock_flag(void) +{ + u32 flag; + u32 sts; + + if (!vlock.phlock_en) + return false; + + flag = READ_VPP_REG(VPU_VLOCK_RO_LCK_FRM) >> 16; + flag = flag&0x01; + + if (vlock.dtdata->vlk_new_fsm) + sts = vlock.fsm_sts; + else + sts = vlock_state; + + if (flag && (sts == VLOCK_STATE_ENABLE_STEP2_DONE)) + return true; + else + return false; +} + +bool vlock_get_vlock_flag(void) +{ + u32 flag; + u32 sts; + + flag = READ_VPP_REG(VPU_VLOCK_RO_LCK_FRM) >> 17; + flag = flag&0x01; + + if (vlock.dtdata->vlk_new_fsm) + sts = vlock.fsm_sts; + else + sts = vlock_state; + + if (flag && (sts == VLOCK_STATE_ENABLE_STEP2_DONE)) + return true; + else + return false; +} + +void vlock_enc_timing_monitor(void) +{ + static unsigned int pre_line, pre_pixel; + unsigned int cur_line, cur_pixel; + unsigned int val; + + val = READ_VPP_REG(VPU_VLOCK_RO_LINE_PIX_ADJ); + cur_pixel = (val & 0x0000ffff); + cur_line = (val >> 16) & 0x0000ffff; + + if ((cur_line != pre_line) || (cur_pixel != pre_pixel)) { + pr_info("vlock line=0x%x pixel=0x%x\n", + cur_line, cur_pixel); + pre_line = cur_line; + pre_pixel = cur_pixel; + } +} + +#if 1 + +u32 vlock_fsm_check_support(struct stvlock_sig_sts *pvlock, + struct vframe_s *vf) +{ + u32 ret = true; + + if (((pvlock->input_hz != pvlock->output_hz) && (vlock_adapt == 0)) || + (pvlock->input_hz == 0) || (pvlock->output_hz == 0) || + (((vf->type_original & VIDTYPE_TYPEMASK) + != VIDTYPE_PROGRESSIVE) && + is_meson_txlx_package_962E())) { + + if (vlock_debug & VLOCK_DEBUG_INFO) { + pr_info("[%s] for no support case!!!\n", + __func__); + pr_info("input_hz:%d, output_hz:%d\n", + pvlock->input_hz, pvlock->output_hz); + pr_info("type_original:0x%x\n", vf->type_original); + } + ret = false; + } + + if (vlock_notify_event == VOUT_EVENT_MODE_CHANGE_PRE) { + if (vlock_debug & VLOCK_DEBUG_INFO) + pr_info("[%s] for vmode change pre case!!!\n", + __func__); + ret = false; + } + + return ret; +} + +u32 vlock_fsm_input_check(struct stvlock_sig_sts *vlock, struct vframe_s *vf) +{ + u32 ret = 0; + u32 vframe_sts; + struct vinfo_s *vinfo = NULL; + + if (vf == NULL) + vframe_sts = false; + else + vframe_sts = true; + + vlock_vmode_check(); + + if (vf != NULL) { + vinfo = get_current_vinfo(); + vlock->input_hz = vlock_check_input_hz(vf); + vlock->output_hz = vlock_check_output_hz( + vinfo->sync_duration_num, vinfo->sync_duration_den); + } + + /*check vf exist status*/ + if (vlock->vf_sts != vframe_sts) { + vlock->vf_sts = vframe_sts; + if (vlock_debug & VLOCK_DEBUG_INFO) + pr_info("vlock vfsts chg %d\n", vframe_sts); + ret = 1; + } else if (vlock_notify_event) { + /*check video mode status*/ + vlock->vmd_chg = true; + ret = 1; + if (vlock_debug & VLOCK_DEBUG_INFO) + pr_info("vlock vmode chg\n"); + } + + if (vlock->vf_sts) + vlock->md_support = vlock_fsm_check_support(vlock, vf); + + return ret; +} + +u32 vlock_fsm_to_en_func(struct stvlock_sig_sts *pvlock, + struct vframe_s *vf) +{ + u32 ret = 0; + struct vinfo_s *vinfo; + + if ((vf->source_type != pre_source_type) || + (vf->source_mode != pre_source_mode) || + (pvlock->input_hz != pre_input_freq) || + (pvlock->output_hz != pre_output_freq) || + vlock_vmode_changed || + (pvlock->fsm_sts == + VLOCK_STATE_ENABLE_FORCE_RESET)) { + + /*back up orignal pll value*/ + /*amvecm_hiu_reg_read(hhi_pll_reg_m, &vlock.val_m);*/ + /*amvecm_hiu_reg_read(hhi_pll_reg_frac, &vlock.val_frac);*/ + vlock.val_m = vlock_get_panel_pll_m(); + vlock.val_frac = vlock_get_panel_pll_frac(); + if (vlock_debug & VLOCK_DEBUG_INFO) { + pr_info("HIU pll m[0x%x]=0x%x\n", + hhi_pll_reg_m, vlock.val_m); + pr_info("HIU pll f[0x%x]=0x%x\n", + hhi_pll_reg_frac, vlock.val_frac); + } + vinfo = get_current_vinfo(); + vlock_enable_step1(vf, vinfo, + pvlock->input_hz, pvlock->output_hz); + if (IS_PLL_MODE(vlock_mode) && + pvlock->phlock_en) { + vlock_set_panel_ss(false); + pvlock->ss_sts = false; + } + ret = 1; + } + + return ret; +} + +u32 vlock_fsm_en_step1_func(struct stvlock_sig_sts *pvlock, + struct vframe_s *vf) +{ + u32 ret = 0; + u32 input_vs_cnt; + + if ((pvlock->frame_cnt_in <= 3) && + ((vlock_mode & (VLOCK_MODE_MANUAL_ENC | + VLOCK_MODE_MANUAL_PLL)))) { + /*WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 1, 5, 1);*/ + /*WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 1, 2, 1);*/ + vlock_reset(1); + /*clear first 3 frame internal cnt*/ + WRITE_VPP_REG(VPU_VLOCK_OVWRITE_ACCUM0, 0); + WRITE_VPP_REG(VPU_VLOCK_OVWRITE_ACCUM1, 0); + if (vlock_debug & VLOCK_DEBUG_INFO) + pr_info("%s -0\n", __func__); + } else if ((pvlock->frame_cnt_in == 4) && + ((vlock_mode & (VLOCK_MODE_MANUAL_ENC | + VLOCK_MODE_MANUAL_PLL)))) { + /*cal accum0 value*/ + /*WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 5, 1);*/ + /*cal accum1 value*/ + /*WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 2, 1);*/ + vlock_reset(0); + if (vlock_debug & VLOCK_DEBUG_INFO) + pr_info("%s -1\n", __func__); + } else if (pvlock->frame_cnt_in == 5) { + /*input_vs_cnt =*/ + /*READ_VPP_REG_BITS(VPU_VLOCK_RO_VS_I_DIST,*/ + /* 0, 28);*/ + input_vs_cnt = XTAL_VLOCK_CLOCK/pvlock->input_hz; + /*tl1 not need */ + if (!cpu_after_eq(MESON_CPU_MAJOR_ID_TL1) && + vf->type_original & VIDTYPE_TYPEMASK) + input_vs_cnt = input_vs_cnt << 1; + + WRITE_VPP_REG(VPU_VLOCK_LOOP1_IMISSYNC_MAX, + input_vs_cnt*125/100); + WRITE_VPP_REG(VPU_VLOCK_LOOP1_IMISSYNC_MIN, + input_vs_cnt*70/100); + /*cal accum1 value*/ + /*WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 2, 1);*/ + /*cal accum0 value*/ + /*WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 5, 1);*/ + vlock_reset(0); + /* + * tl1 auto pll,swich clk need after + *several frames + */ + if (vlock.dtdata->vlk_hwver >= vlock_hw_ver2) { + if (IS_AUTO_MODE(vlock_mode)) + amvecm_hiu_reg_write_bits( + HHI_HDMI_PLL_VLOCK_CNTL, 0x7, 0, 3); + else if (IS_MANUAL_MODE(vlock_mode)) + amvecm_hiu_reg_write_bits( + HHI_HDMI_PLL_VLOCK_CNTL, 0x6, 0, 3); + } + + ret = 1; + if (vlock_debug & VLOCK_DEBUG_INFO) + pr_info("%s -2\n", __func__); + } + + return ret; +} + +void vlock_fsm_check_lock_sts(struct stvlock_sig_sts *pvlock, + struct vframe_s *vf) +{ + u32 frqlock_sts = vlock_get_vlock_flag(); + u32 phlock_sts = vlock_get_phlock_flag(); + u32 pherr; + static u32 rstflag; + + /*check frq lock*/ + if (pvlock->frqlock_sts != frqlock_sts) { + if (vlock_debug & VLOCK_DEBUG_INFO) + pr_info("frq lock sts(%d,%d) cnt:%d\n", + pvlock->frqlock_sts, + frqlock_sts, pvlock->frame_cnt_in); + pvlock->frqlock_sts = frqlock_sts; + } + + /*check phase error*/ + if (IS_PLL_MODE(vlock_mode) && + pvlock->phlock_en) { + /*after frq lock, then enable phase lock*/ + /*check phase err*/ + pherr = READ_VPP_REG(VPU_VLOCK_RO_PH_ERR) & 0xffffff; + if (pherr & 0x800000) + pherr = 0xffffff - pherr + 1;/*negative value*/ + + if (rstflag) { + rstflag = false; + vlock_reset(0); + } else if (pherr > 0x1ff) { + if ((pvlock->frame_cnt_in%80) == 0) { + vlock_reset(1); + rstflag = true; + } + } + } + + /*check phase lock*/ + if (pvlock->phlock_en && + (pvlock->phlock_sts != phlock_sts)) { + if (vlock_debug & VLOCK_DEBUG_INFO) + pr_info("ph lock sts(%d,%d) cnt:%d\n", + pvlock->phlock_sts, + phlock_sts, pvlock->frame_cnt_in); + pvlock->phlock_sts = phlock_sts; + if (phlock_sts && !pvlock->ss_sts && + (pvlock->frame_cnt_in > 25)) { + vlock_set_panel_ss(true); + pvlock->ss_sts = true; + } + } + + /*pretect and enable ss*/ + if (IS_PLL_MODE(vlock_mode) && + pvlock->phlock_en) { + /*error check*/ + if ((pvlock->frame_cnt_in >= 3500) && (!pvlock->ss_sts)) { + if (vlock_debug & VLOCK_DEBUG_INFO) + pr_info("vlock warning: set back ss on(%d, %d)\n", + frqlock_sts, phlock_sts); + pvlock->pll_mode_pause = true; + pvlock->ss_sts = true; + vlock_set_panel_ss(true); + } + } +} + +u32 vlock_fsm_en_step2_func(struct stvlock_sig_sts *pvlock, + struct vframe_s *vf) +{ + u32 ret = 0; + + if (vlock_dynamic_adjust && + (cpu_after_eq(MESON_CPU_MAJOR_ID_GXTVBB)) && + (IS_MANUAL_MODE(vlock_mode))) { + if (IS_MANUAL_ENC_MODE(vlock_mode)) + vlock_enable_step3_enc(); + else if (IS_MANUAL_PLL_MODE(vlock_mode) && + (!pvlock->pll_mode_pause)) + vlock_enable_step3_pll(); + else if (IS_MANUAL_SOFTENC_MODE(vlock_mode)) + vlock_enable_step3_soft_enc(); + } + + if (IS_ENC_MODE(vlock_mode)) + vlock_enc_timing_monitor(); + + /*check phase*/ + vlock_phaselock_check(pvlock, vf); + + vlock_fsm_check_lock_sts(pvlock, vf); + + return ret; +} + + +void vlock_fsm_monitor(struct vframe_s *vf) +{ + u32 changed; + + if (vlock.fsm_pause) + return; + + changed = vlock_fsm_input_check(&vlock, vf); + switch (vlock.fsm_sts) { + case VLOCK_STATE_NULL: + if (vlock.vf_sts) { + /*have frame in*/ + if (vlock.frame_cnt_in++ >= VLOCK_START_CNT) { + /*vframe input valid*/ + if (vlock.md_support) { + if (vlock_fsm_to_en_func(&vlock, vf)) { + vlock_clear_frame_counter(); + vlock.fsm_sts = + VLOCK_STATE_ENABLE_STEP1_DONE; + } else { + /*error waitting here*/ + vlock_clear_frame_counter(); + } + } + } + } else if (vlock.vmd_chg) { + vlock_clear_frame_counter(); + vlock.vmd_chg = false; + vlock.fsm_sts = VLOCK_STATE_DISABLE_STEP2_DONE; + } else { + /*disabled and waitting here*/ + vlock_clear_frame_counter(); + } + break; + + case VLOCK_STATE_ENABLE_STEP1_DONE: + if (vlock.vf_sts) { + vlock.frame_cnt_in++; + if (vlock_fsm_en_step1_func(&vlock, vf)) + vlock.fsm_sts = VLOCK_STATE_ENABLE_STEP2_DONE; + } else if (vlock.vmd_chg) { + vlock_clear_frame_counter(); + vlock.vmd_chg = false; + vlock.fsm_sts = VLOCK_STATE_DISABLE_STEP1_DONE; + } else { + vlock.frame_cnt_in = 0; + if (vlock.frame_cnt_no++ > vlock_dis_cnt_no_vf_limit) { + /*go to disable state*/ + vlock_clear_frame_counter(); + vlock.fsm_sts = VLOCK_STATE_DISABLE_STEP1_DONE; + } + } + break; + + case VLOCK_STATE_ENABLE_STEP2_DONE: + if (vlock.vf_sts) { + vlock.frame_cnt_in++; + if (!vlock.md_support) { + /*function not support*/ + vlock_clear_frame_counter(); + vlock.fsm_sts = VLOCK_STATE_DISABLE_STEP1_DONE; + } else if (vecm_latch_flag & FLAG_VLOCK_DIS) { + /*disable vlock by vecm cmd*/ + vlock_disable_step1(); + vlock_disable_step2(); + vlock_en = 0; + vecm_latch_flag &= ~FLAG_VLOCK_DIS; + if (vlock_debug & VLOCK_DEBUG_INFO) + pr_info("[%s] vlock dis\n", __func__); + vlock_clear_frame_counter(); + vlock.fsm_sts = VLOCK_STATE_NULL; + } else { + /*normal mode*/ + vlock.frame_cnt_no = 0; + vlock_fsm_en_step2_func(&vlock, vf); + } + } else if (vlock.vmd_chg) { + vlock_clear_frame_counter(); + vlock.vmd_chg = false; + vlock.fsm_sts = VLOCK_STATE_DISABLE_STEP1_DONE; + } else { + /*no frame input*/ + if (vlock.frame_cnt_no++ > vlock_dis_cnt_no_vf_limit) { + /*go to disable state*/ + vlock_clear_frame_counter(); + vlock.fsm_sts = VLOCK_STATE_DISABLE_STEP1_DONE; + } + } + break; + + case VLOCK_STATE_DISABLE_STEP1_DONE: + vlock_disable_step1(); + if (vlock_disable_step2()) + vlock.fsm_sts = VLOCK_STATE_NULL; + else + vlock.fsm_sts = VLOCK_STATE_DISABLE_STEP2_DONE; + break; + + case VLOCK_STATE_DISABLE_STEP2_DONE: + if (vlock_disable_step2()) + vlock.fsm_sts = VLOCK_STATE_NULL; + break; + + default: + pr_info("err state %d\n", vlock.fsm_sts); + break; + } + + /*capture log*/ + if (((vlock_mode & (VLOCK_MODE_AUTO_PLL | + VLOCK_MODE_AUTO_ENC))) && + vlock_log_en && (vlock_log_cnt < vlock_log_size) && + (vlock_debug & VLOCK_DEBUG_AUTO_MODE_LOG_EN)) { + vlock_reg_get(); + vlock_log_cnt++; + } + + if ((vlock_debug & VLOCK_DEBUG_INFO) && + vlock.fsm_sts != vlock.fsm_prests) { + pr_info(">>> %s fsm %d to %d\n", __func__, + vlock.fsm_prests, vlock.fsm_sts); + vlock.fsm_prests = vlock.fsm_sts; + } +} +#endif + /*new packed separeted from amvecm_on_vs,avoid the influencec of repeate call, *which may affect vlock process */ void vlock_process(struct vframe_s *vf) { - if (probe_ok == 0) + if (probe_ok == 0 || !vlock_en) + return; + + if (vlock_debug & VLOCK_DEBUG_FSM_DIS) return; /* todo:vlock processs only for tv chip */ - if (is_meson_gxtvbb_cpu() || - is_meson_txl_cpu() || is_meson_txlx_cpu() - || is_meson_txhd_cpu()) { + if (vlock.dtdata->vlk_new_fsm) + vlock_fsm_monitor(vf); + else { if (vf != NULL) amve_vlock_process(vf); else @@ -1216,7 +2215,10 @@ void vlock_param_set(unsigned int val, enum vlock_param_e sel) } void vlock_status(void) { + struct vinfo_s *vinfo; + pr_info("\n current vlock parameters status:\n"); + pr_info("vlock driver version : %s\n", VLOCK_VER); pr_info("vlock_mode:%d\n", vlock_mode); pr_info("vlock_en:%d\n", vlock_en); pr_info("vlock_adapt:%d\n", vlock_adapt); @@ -1227,6 +2229,7 @@ void vlock_status(void) pr_info("vlock_debug:0x%x\n", vlock_debug); pr_info("vlock_dynamic_adjust:%d\n", vlock_dynamic_adjust); pr_info("vlock_state:%d\n", vlock_state); + pr_info("vecm_latch_flag:0x%x\n", vecm_latch_flag); pr_info("vlock_sync_limit_flag:%d\n", vlock_sync_limit_flag); pr_info("pre_hiu_reg_m:0x%x\n", pre_hiu_reg_m); pr_info("pre_hiu_reg_frac:0x%x\n", pre_hiu_reg_frac); @@ -1248,17 +2251,54 @@ void vlock_status(void) pr_info("vlock_intput_type:%d\n", vlock_intput_type); pr_info("vlock_pll_adj_limit:%d\n", vlock_pll_adj_limit); pr_info("vlock_pll_val_last:%d\n", vlock_pll_val_last); - pr_info("vlock driver version : %s\n", VLOCK_VER); + pr_info("vlk_fsm_sts:%d(2 is working)\n", vlock.fsm_sts); + pr_info("vlk_support:%d\n", vlock.dtdata->vlk_support); + pr_info("vlk_new_fsm:%d\n", vlock.dtdata->vlk_new_fsm); + pr_info("vlk_phlock_en:%d\n", vlock.dtdata->vlk_phlock_en); + pr_info("vlk_hwver:%d\n", vlock.dtdata->vlk_hwver); + pr_info("phlock flag:%d\n", vlock_get_phlock_flag()); + pr_info("vlock flag:%d\n", vlock_get_vlock_flag()); + pr_info("phase:%d\n", vlock.phlock_percent); + vinfo = get_current_vinfo(); + pr_info("vinfo sync_duration_num:%d\n", vinfo->sync_duration_num); + pr_info("vinfo sync_duration_den:%d\n", vinfo->sync_duration_den); + pr_info("vinfo video_clk:%d\n", vinfo->video_clk); + pr_info("vframe input_hz:%d\n", vlock.input_hz); + pr_info("vframe output_hz:%d\n", vlock.output_hz); } + void vlock_reg_dump(void) { unsigned int addr; + unsigned int val; pr_info("----dump vlock reg----\n"); - for (addr = (0x3000); addr <= (0x3020); addr++) + for (addr = (VPU_VLOCK_CTRL); addr <= (VPU_VLOCK_RO_M_INT_FRAC); addr++) pr_info("[0x%x]vcbus[0x%04x]=0x%08x\n", (0xd0100000+(addr<<2)), addr, READ_VPP_REG(addr)); + + if (vlock.dtdata->vlk_hwver >= vlock_hw_ver2) { + for (addr = (0x3021); addr <= (0x302b); addr++) + pr_info("[0x%x]vcbus[0x%04x]=0x%08x\n", + (0xd0100000+(addr<<2)), addr, + READ_VPP_REG(addr)); + amvecm_hiu_reg_read(HHI_HDMI_PLL_VLOCK_CNTL, &val); + pr_info("HIU [0x%04x]=0x%08x\n", HHI_HDMI_PLL_VLOCK_CNTL, val); + } + pr_info("[0x1cc8]=0x%08x\n", READ_VPP_REG(0x1cc8)); + + /*amvecm_hiu_reg_read(hhi_pll_reg_m, &val);*/ + val = vlock_get_panel_pll_m(); + pr_info("HIU pll m[0x%04x]=0x%08x\n", hhi_pll_reg_m, val); + /*amvecm_hiu_reg_read(hhi_pll_reg_frac, &val);*/ + val = vlock_get_panel_pll_frac(); + pr_info("HIU pll f[0x%04x]=0x%08x\n", hhi_pll_reg_frac, val); + + /*back up orignal pll value*/ + /*pr_info("HIU pll m[0x%x]=0x%x\n", hhi_pll_reg_m, vlock.val_m);*/ + /*pr_info("HIU pll f[0x%x]=0x%x\n", hhi_pll_reg_frac, vlock.val_frac);*/ + } /*work around method for vlock process hdmirx input interlace source.@20170803 **for interlace input,TOP and BOT have one line delta, @@ -1270,8 +2310,17 @@ void vlock_reg_dump(void) void vdin_vlock_input_sel(unsigned int type, enum vframe_source_type_e source_type) { + if (vlock.dtdata->vlk_hwver >= vlock_hw_ver2) + return; + /* + *1:fromhdmi rx , + *2:from tv-decoder, + *3:from dvin, + *4:from dvin, + *5:from 2nd bt656 + */ vlock_intput_type = type & VIDTYPE_TYPEMASK; - if ((vlock_intput_type == 0) || + if ((vlock_intput_type == VIDTYPE_PROGRESSIVE) || (vlock_mode & VLOCK_MODE_MANUAL_SOFT_ENC)) return; if (vlock_intput_type == VIDTYPE_INTERLACE_TOP) { @@ -1351,12 +2400,14 @@ void vlock_param_config(struct device_node *node) vlock_mode &= ~VLOCK_MODE_MANUAL_MIX_PLL_ENC; vlock_mode |= VLOCK_MODE_MANUAL_PLL; } + pr_info("param_config vlock_en:%d\n", vlock_en); } int vlock_notify_callback(struct notifier_block *block, unsigned long cmd, void *para) { const struct vinfo_s *vinfo; + u32 cnt = 0; vinfo = get_current_vinfo(); if (!vinfo) { @@ -1366,16 +2417,51 @@ int vlock_notify_callback(struct notifier_block *block, unsigned long cmd, if (vlock_debug & VLOCK_DEBUG_INFO) pr_info("current vmode=%s, vinfo w=%d,h=%d, cmd: 0x%lx\n", vinfo->name, vinfo->width, vinfo->height, cmd); + switch (cmd) { case VOUT_EVENT_MODE_CHANGE_PRE: - case VOUT_EVENT_MODE_CHANGE: - vlock_vmode_change_status = cmd; + vlock.fsm_pause = true; + vlock.fsm_sts = VLOCK_STATE_NULL; + vlock_notify_event = cmd; + if (vlock.dtdata->vlk_new_fsm && + (vlock.fsm_sts >= VLOCK_STATE_ENABLE_STEP1_DONE) && + (vlock.fsm_sts <= VLOCK_STATE_DISABLE_STEP1_DONE)) { + /*stop vlock*/ + vlock_disable_step1(); + while (!vlock_disable_step2()) { + if (cnt++ > 10) + break; + } + } + pr_info("vlock: event MODE_CHANGE_PRE %d\n", cnt); break; + + case VOUT_EVENT_MODE_CHANGE: + vlock.fsm_pause = false; + vlock.fsm_sts = VLOCK_STATE_NULL; + vlock_notify_event = cmd; + pr_info("vlock: event MODE_CHANGE\n"); + break; + default: break; } return 0; } +static int __init phlock_phase_config(char *str) +{ + unsigned char *ptr = str; + + pr_info("%s: bootargs is %s.\n", __func__, str); + if (strstr(ptr, "1")) + vlock.phlock_percent = 99; + else + vlock.phlock_percent = 40; + + return 0; +} +__setup("video_reverse=", phlock_phase_config); + /*video lock end*/ diff --git a/drivers/amlogic/media/enhancement/amvecm/vlock.h b/drivers/amlogic/media/enhancement/amvecm/vlock.h index 96784fb753f8..07e6e37cca9f 100644 --- a/drivers/amlogic/media/enhancement/amvecm/vlock.h +++ b/drivers/amlogic/media/enhancement/amvecm/vlock.h @@ -23,7 +23,7 @@ #include #include "linux/amlogic/media/amvecm/ve.h" -#define VLOCK_VER "Ref.2018/11/07a" +#define VLOCK_VER "Ref.2019/4/19:disable some log" #define VLOCK_REG_NUM 33 @@ -59,6 +59,28 @@ enum vlock_param_e { VLOCK_PARAM_MAX, }; +struct stvlock_sig_sts { + u32 fsm_sts; + u32 fsm_prests; + u32 fsm_pause; + u32 vf_sts; + u32 vmd_chg; + u32 frame_cnt_in; + u32 frame_cnt_no; + u32 input_hz; + u32 output_hz; + bool md_support; + u32 phlock_percent; + u32 phlock_sts; + u32 phlock_en; + u32 frqlock_sts; + /*u32 frqlock_stable_cnt;*/ + u32 ss_sts; + u32 pll_mode_pause; + struct vecm_match_data_s *dtdata; + u32 val_frac; + u32 val_m; +}; extern void amve_vlock_process(struct vframe_s *vf); extern void amve_vlock_resume(void); extern void vlock_param_set(unsigned int val, enum vlock_param_e sel); @@ -67,7 +89,7 @@ extern void vlock_reg_dump(void); extern void vlock_log_start(void); extern void vlock_log_stop(void); extern void vlock_log_print(void); - +extern int phase_lock_check(void); #define VLOCK_STATE_NULL 0 #define VLOCK_STATE_ENABLE_STEP1_DONE 1 @@ -77,12 +99,50 @@ extern void vlock_log_print(void); #define VLOCK_STATE_ENABLE_FORCE_RESET 5 /* video lock */ -#define VLOCK_MODE_AUTO_ENC (1 << 0) -#define VLOCK_MODE_AUTO_PLL (1 << 1) -#define VLOCK_MODE_MANUAL_PLL (1 << 2) -#define VLOCK_MODE_MANUAL_ENC (1 << 3) -#define VLOCK_MODE_MANUAL_SOFT_ENC (1 << 4) -#define VLOCK_MODE_MANUAL_MIX_PLL_ENC (1 << 5) +enum VLOCK_MD { + VLOCK_MODE_AUTO_ENC = 0x01, + VLOCK_MODE_AUTO_PLL = 0x02, + VLOCK_MODE_MANUAL_PLL = 0x04, + VLOCK_MODE_MANUAL_ENC = 0x08, + VLOCK_MODE_MANUAL_SOFT_ENC = 0x10, + VLOCK_MODE_MANUAL_MIX_PLL_ENC = 0x20, +}; + +#define IS_MANUAL_MODE(md) (md & \ + (VLOCK_MODE_MANUAL_PLL | \ + VLOCK_MODE_MANUAL_ENC | \ + VLOCK_MODE_MANUAL_SOFT_ENC)) + +#define IS_AUTO_MODE(md) (md & \ + (VLOCK_MODE_AUTO_PLL | \ + VLOCK_MODE_AUTO_ENC)) + +#define IS_PLL_MODE(md) (md & \ + (VLOCK_MODE_MANUAL_PLL | \ + VLOCK_MODE_AUTO_PLL)) + +#define IS_ENC_MODE(md) (md & \ + (VLOCK_MODE_MANUAL_ENC | \ + VLOCK_MODE_MANUAL_SOFT_ENC | \ + VLOCK_MODE_AUTO_ENC)) + +#define IS_AUTO_PLL_MODE(md) (md & \ + VLOCK_MODE_AUTO_PLL) + +#define IS_MANUAL_ENC_MODE(md) (md & \ + VLOCK_MODE_MANUAL_ENC) + +#define IS_MANUAL_PLL_MODE(md) (md & \ + VLOCK_MODE_MANUAL_PLL) + +#define IS_MANUAL_SOFTENC_MODE(md) (md & \ + VLOCK_MODE_MANUAL_SOFT_ENC) + +#define VLOCK_START_CNT 50 +#define VLOCK_WORK_CNT (VLOCK_START_CNT + 10) + +#define VLOCK_UPDATE_M_CNT 8 +#define VLOCK_UPDATE_F_CNT 4 #define XTAL_VLOCK_CLOCK 24000000/*vlock use xtal clock*/ @@ -95,18 +155,19 @@ extern void vlock_log_print(void); #define VLOCK_PLL_ADJ_LIMIT 9/*vlock pll adj limit(0x300a default)*/ /*vlock_debug mask*/ -#define VLOCK_DEBUG_INFO (1 << 0) -#define VLOCK_DEBUG_FLUSH_REG_DIS (1 << 1) -#define VLOCK_DEBUG_ENC_LINE_ADJ_DIS (1 << 2) -#define VLOCK_DEBUG_ENC_PIXEL_ADJ_DIS (1 << 3) -#define VLOCK_DEBUG_AUTO_MODE_LOG_EN (1 << 4) -#define VLOCK_DEBUG_PLL2ENC_DIS (1 << 5) +#define VLOCK_DEBUG_INFO (0x1) +#define VLOCK_DEBUG_FLUSH_REG_DIS (0x2) +#define VLOCK_DEBUG_ENC_LINE_ADJ_DIS (0x4) +#define VLOCK_DEBUG_ENC_PIXEL_ADJ_DIS (0x8) +#define VLOCK_DEBUG_AUTO_MODE_LOG_EN (0x10) +#define VLOCK_DEBUG_PLL2ENC_DIS (0x20) +#define VLOCK_DEBUG_FSM_DIS (0x40) /* 0:enc;1:pll;2:manual pll */ extern unsigned int vlock_mode; extern unsigned int vlock_en; extern unsigned int vecm_latch_flag; -extern void __iomem *amvecm_hiu_reg_base; +/*extern void __iomem *amvecm_hiu_reg_base;*/ extern unsigned int probe_ok; extern void lcd_ss_enable(bool flag); @@ -123,4 +184,13 @@ extern void vlock_lcd_param_work(struct work_struct *p_work); extern int vlock_notify_callback(struct notifier_block *block, unsigned long cmd, void *para); #endif +extern void vlock_status_init(void); +extern void vlock_dt_match_init(struct vecm_match_data_s *pdata); +extern void vlock_set_en(bool en); +extern void vlock_set_phase(u32 percent); +extern void vlock_set_phase_en(u32 en); + +extern void lcd_vlock_m_update(unsigned int vlock_m); +extern void lcd_vlock_farc_update(unsigned int vlock_farc); +extern int lcd_set_ss(unsigned int level, unsigned int freq, unsigned int mode); diff --git a/drivers/amlogic/media/frame_sync/ptsserv.c b/drivers/amlogic/media/frame_sync/ptsserv.c index dde139fb99eb..d9b4cca38e0d 100644 --- a/drivers/amlogic/media/frame_sync/ptsserv.c +++ b/drivers/amlogic/media/frame_sync/ptsserv.c @@ -55,6 +55,7 @@ struct pts_rec_s { struct list_head list; u32 offset; u32 val; + u32 size; u64 pts_uS64; } /*pts_rec_t */; @@ -230,7 +231,8 @@ int calculation_stream_delayed_ms(u8 type, u32 *latestbitrate, outtime = timestamp_pcrscr_get(); if (outtime == 0 || outtime == 0xffffffff) outtime = pTable->last_checkout_pts; - timestampe_delayed = (pTable->last_checkin_pts - outtime) / 90; + if (pTable->last_checkin_pts > outtime) + timestampe_delayed = (pTable->last_checkin_pts - outtime) / 90; pTable->last_pts_delay_ms = timestampe_delayed; if (get_buf_by_type_cb && stbuf_level_cb && stbuf_space_cb) { if ((timestampe_delayed < 10) @@ -276,7 +278,7 @@ int calculation_stream_delayed_ms(u8 type, u32 *latestbitrate, type))) diff = diff2; } - delay_ms = diff * 1000 / (1 + pTable->last_avg_bitrate / 8); + delay_ms = (diff * 1000) / (int)(1 + pTable->last_avg_bitrate / 8); if ((timestampe_delayed < 10) || ((abs (timestampe_delayed - delay_ms) > (3 * 1000)) @@ -640,7 +642,7 @@ int get_last_checkout_pts(u8 type) } EXPORT_SYMBOL(get_last_checkout_pts); -int pts_lookup(u8 type, u32 *val, u32 pts_margin) +int pts_lookup(u8 type, u32 *val, u32 *frame_size, u32 pts_margin) { u32 page, offset; @@ -648,18 +650,20 @@ int pts_lookup(u8 type, u32 *val, u32 pts_margin) if (type == PTS_TYPE_VIDEO) { offset = page * pts_table[PTS_TYPE_VIDEO].buf_size + offset; - pts_lookup_offset(PTS_TYPE_VIDEO, offset, val, pts_margin); + pts_lookup_offset( + PTS_TYPE_VIDEO, offset, val, frame_size, pts_margin); return 0; } else if (type == PTS_TYPE_AUDIO) { offset = page * pts_table[PTS_TYPE_AUDIO].buf_size + offset; - pts_lookup_offset(PTS_TYPE_AUDIO, offset, val, pts_margin); + pts_lookup_offset( + PTS_TYPE_AUDIO, offset, val, frame_size, pts_margin); return 0; } else return -EINVAL; } EXPORT_SYMBOL(pts_lookup); static int pts_lookup_offset_inline_locked(u8 type, u32 offset, u32 *val, - u32 pts_margin, u64 *uS64) + u32 *frame_size, u32 pts_margin, u64 *uS64) { struct pts_table_s *pTable; int lookup_threshold; @@ -752,6 +756,12 @@ static int pts_lookup_offset_inline_locked(u8 type, u32 offset, u32 *val, p2 = p; } + + /* if p2 lookup fail, set p2 = p */ + if (type == PTS_TYPE_VIDEO && p2 && p && + OFFSET_DIFF(offset, p2->offset) > lookup_threshold && + abs(OFFSET_DIFF(offset, p->offset)) < lookup_threshold) + p2 = p; } else if (OFFSET_LATER(p->offset, offset)) { list_for_each_entry_continue_reverse(p, &pTable-> @@ -771,6 +781,9 @@ static int pts_lookup_offset_inline_locked(u8 type, u32 offset, u32 *val, } else p2 = p; + if (type == PTS_TYPE_VIDEO) + *frame_size = p->size; + if ((p2) && (OFFSET_DIFF(offset, p2->offset) < lookup_threshold)) { if (p2->val == 0) /* FFT: set valid vpts */ @@ -782,8 +795,9 @@ static int pts_lookup_offset_inline_locked(u8 type, u32 offset, u32 *val, ("vpts look up offset<0x%x> -->", offset); pr_info - ("<0x%x:0x%x>, look_cnt = %d\n", - p2->offset, p2->val, look_cnt); + ("<0x%x:0x%x>, fsize %x, look_cnt = %d\n", + p2->offset, p2->val, + p2->size, look_cnt); } if (tsync_get_debug_apts() @@ -799,6 +813,7 @@ static int pts_lookup_offset_inline_locked(u8 type, u32 offset, u32 *val, } *val = p2->val; *uS64 = p2->pts_uS64; + *frame_size = p2->size; #ifdef CALC_CACHED_TIME pTable->last_checkout_pts = p2->val; @@ -914,7 +929,7 @@ static int pts_lookup_offset_inline_locked(u8 type, u32 offset, u32 *val, */ if (!pTable->first_lookup_ok) { *val = pTable->first_checkin_pts; - *uS64 = (u64)(*val) << 32; + *uS64 = div64_u64((u64)pTable->first_checkin_pts * 100, 9); pTable->first_lookup_ok = 1; pTable->first_lookup_is_fail = 1; @@ -1124,14 +1139,15 @@ static int pts_pick_by_offset_inline_locked(u8 type, u32 offset, u32 *val, static int pts_lookup_offset_inline(u8 type, u32 offset, u32 *val, - u32 pts_margin, u64 *uS64) + u32 *frame_size, u32 pts_margin, u64 *uS64) { unsigned long flags; int res; spin_lock_irqsave(&lock, flags); res = pts_lookup_offset_inline_locked( - type, offset, val, pts_margin, uS64); + type, offset, val, + frame_size, pts_margin, uS64); #if 0 if (timestamp_firstvpts_get() == 0 && res == 0 && (*val) != 0 @@ -1169,18 +1185,21 @@ static int pts_pick_by_offset_inline(u8 type, u32 offset, u32 *val, } -int pts_lookup_offset(u8 type, u32 offset, u32 *val, u32 pts_margin) +int pts_lookup_offset(u8 type, u32 offset, u32 *val, + u32 *frame_size, u32 pts_margin) { u64 pts_us; - return pts_lookup_offset_inline(type, offset, val, pts_margin, &pts_us); + return pts_lookup_offset_inline(type, offset, val, + frame_size, pts_margin, &pts_us); } EXPORT_SYMBOL(pts_lookup_offset); -int pts_lookup_offset_us64(u8 type, u32 offset, u32 *val, u32 pts_margin, - u64 *uS64) +int pts_lookup_offset_us64(u8 type, u32 offset, u32 *val, + u32 *frame_size, u32 pts_margin, u64 *uS64) { - return pts_lookup_offset_inline(type, offset, val, pts_margin, uS64); + return pts_lookup_offset_inline(type, offset, val, + frame_size, pts_margin, uS64); } EXPORT_SYMBOL(pts_lookup_offset_us64); diff --git a/drivers/amlogic/media/frame_sync/timestamp.c b/drivers/amlogic/media/frame_sync/timestamp.c index 472be72c92b2..03e3fe92fdec 100644 --- a/drivers/amlogic/media/frame_sync/timestamp.c +++ b/drivers/amlogic/media/frame_sync/timestamp.c @@ -22,6 +22,7 @@ #include #include #include +#include u32 acc_apts_inc; @@ -135,6 +136,19 @@ u32 timestamp_pcrscr_get(void) } EXPORT_SYMBOL(timestamp_pcrscr_get); +void timestamp_set_pcrlatency(u32 latency) +{ + if (latency < 500 * 90) + pcrscr_lantcy = latency; +} +EXPORT_SYMBOL(timestamp_set_pcrlatency); + +u32 timestamp_get_pcrlatency(void) +{ + return pcrscr_lantcy; +} +EXPORT_SYMBOL(timestamp_get_pcrlatency); + u32 timestamp_tsdemux_pcr_get(void) { if (tsdemux_pcrscr_get_cb) @@ -147,6 +161,7 @@ EXPORT_SYMBOL(timestamp_tsdemux_pcr_get); void timestamp_pcrscr_set(u32 pts) { /*pr_info("timestamp_pcrscr_set system time = %x\n", pts);*/ + ATRACE_COUNTER("PCRSCR", pts); system_time = pts; } EXPORT_SYMBOL(timestamp_pcrscr_set); @@ -210,6 +225,7 @@ void timestamp_pcrscr_inc(s32 inc) inc = inc * timestamp_inc_factor / PLL_FACTOR; #endif system_time += inc + system_time_inc_adj; + ATRACE_COUNTER("PCRSCR", system_time); } } EXPORT_SYMBOL(timestamp_pcrscr_inc); @@ -234,6 +250,7 @@ void timestamp_pcrscr_inc_scale(s32 inc, u32 base) system_time++; system_time_scale_remainder -= system_time_scale_base; } + ATRACE_COUNTER("PCRSCR", system_time); } } EXPORT_SYMBOL(timestamp_pcrscr_inc_scale); diff --git a/drivers/amlogic/media/frame_sync/tsync.c b/drivers/amlogic/media/frame_sync/tsync.c index df091fe34171..c6a9b410a6c3 100644 --- a/drivers/amlogic/media/frame_sync/tsync.c +++ b/drivers/amlogic/media/frame_sync/tsync.c @@ -829,6 +829,29 @@ void tsync_avevent_locked(enum avevent_e event, u32 param) t = timestamp_apts_get(); else t = timestamp_pcrscr_get(); + if (tsdemux_pcrscr_valid_cb && tsdemux_pcrscr_valid_cb() == 1) { + if (abs(param - oldpts) > tsync_av_threshold_min) { + vpts_discontinue = 1; + if (apts_discontinue == 1) { + apts_discontinue = 0; + vpts_discontinue = 0; + pr_info("set apts->pcrsrc,pcrsrc %x to %x,diff %d\n", + timestamp_pcrscr_get(), + timestamp_apts_get(), + timestamp_apts_get() + - timestamp_pcrscr_get()); + timestamp_pcrscr_set(param); + } else { + pr_info("set para->pcrsrc,pcrsrc %x to %x,diff %d\n", + timestamp_pcrscr_get(), param, + param-timestamp_pcrscr_get()); + timestamp_pcrscr_set( + timestamp_vpts_get()); + } + } + timestamp_vpts_set(param); + break; + } /* *amlog_level(LOG_LEVEL_ATTENTION, *"VIDEO_TSTAMP_DISCONTINUITY, 0x%x, 0x%x\n", t, param); @@ -860,6 +883,29 @@ void tsync_avevent_locked(enum avevent_e event, u32 param) amlog_level(LOG_LEVEL_ATTENTION, "audio discontinue, reset apts, 0x%x\n", param); + if (tsdemux_pcrscr_valid_cb && tsdemux_pcrscr_valid_cb() == 1) { + if (abs(param - oldpts) > tsync_av_threshold_min) { + apts_discontinue = 1; + if (vpts_discontinue == 1) { + pr_info("set para->pcrsrc,pcrsrc from %x to %x,diff %d\n", + timestamp_pcrscr_get(), param, + param-timestamp_pcrscr_get()); + apts_discontinue = 0; + vpts_discontinue = 0; + timestamp_pcrscr_set(param); + } else { + pr_info("set vpts->pcrsrc,pcrsrc from %x to %x,diff %d\n", + timestamp_pcrscr_get(), + timestamp_vpts_get(), + timestamp_vpts_get() + - timestamp_pcrscr_get()); + timestamp_pcrscr_set( + timestamp_vpts_get()); + } + } + timestamp_apts_set(param); + break; + } timestamp_apts_set(param); if (!tsync_enable) { timestamp_apts_set(param); @@ -1132,6 +1178,15 @@ void tsync_set_sync_vdiscont(int syncdiscont) } EXPORT_SYMBOL(tsync_set_sync_vdiscont); +int tsync_set_video_runmode(void) +{ + if (tsdemux_pcrscr_valid_cb && tsdemux_pcrscr_valid_cb() == 1) { + if (vpts_discontinue == 1 || apts_discontinue == 1) + return 1; + } + return 0; +} +EXPORT_SYMBOL(tsync_set_video_runmode); void tsync_set_automute_on(int automute_on) { tsync_automute_on = automute_on; @@ -1155,8 +1210,20 @@ int tsync_set_apts(unsigned int pts) t = timestamp_vpts_get(); else t = timestamp_pcrscr_get(); + if (tsdemux_pcrscr_valid_cb && tsdemux_pcrscr_valid_cb() == 1) { + timestamp_apts_set(pts); + if ((int)(timestamp_apts_get() - timestamp_pcrscr_get()) + > 30 * TIME_UNIT90K / 1000 + || (int)(timestamp_pcrscr_get() - timestamp_apts_get()) + > 80 * TIME_UNIT90K / 1000) { + timestamp_pcrscr_set(pts); + set_pts_realign(); + } + return 0; + } + /* do not switch tsync mode until first video toggled. */ if ((abs(oldpts - pts) > tsync_av_threshold_min) && - (!get_vsync_pts_inc_mode())) { /* is discontinue */ + (timestamp_firstvpts_get() > 0)) { /* is discontinue */ apts_discontinue = 1; tsync_mode_switch('A', abs(pts - t), pts - oldpts); /*if in VMASTER ,just wait */ @@ -1170,7 +1237,7 @@ int tsync_set_apts(unsigned int pts) t = timestamp_pcrscr_get(); if (tsync_mode == TSYNC_MODE_AMASTER) { - /* special used for Dobly Certification AVSync test */ + /* special used for Dolby Certification AVSync test */ if (dobly_avsync_test) { if (get_vsync_pts_inc_mode() && @@ -1932,12 +1999,33 @@ static ssize_t show_startsync_mode(struct class *class, return sprintf(buf, "0x%x\n", tsync_get_startsync_mode()); } +static ssize_t show_latency(struct class *class, + struct class_attribute *attr, char *buf) +{ + return sprintf(buf, "%u\n", timestamp_get_pcrlatency()); +} + +static ssize_t store_latency(struct class *class, + struct class_attribute *attr, + const char *buf, size_t size) +{ + unsigned int latency = 0; + ssize_t r; + + r = kstrtoint(buf, 0, &latency); + if (r != 0) + return -EINVAL; + timestamp_set_pcrlatency(latency); + return size; +} static ssize_t show_apts_lookup(struct class *class, struct class_attribute *attrr, char *buf) { + u32 frame_size; unsigned int pts = 0xffffffff; - pts_lookup_offset(PTS_TYPE_AUDIO, apts_lookup_offset, &pts, 300); + pts_lookup_offset(PTS_TYPE_AUDIO, apts_lookup_offset, + &pts, &frame_size, 300); return sprintf(buf, "0x%x\n", pts); } @@ -2019,6 +2107,7 @@ static struct class_attribute tsync_class_attrs[] = { NULL), __ATTR(checkin_firstapts, 0644, show_checkin_firstapts, NULL), + __ATTR(pts_latency, 0664, show_latency, store_latency), __ATTR_NULL }; diff --git a/drivers/amlogic/media/gdc/Makefile b/drivers/amlogic/media/gdc/Makefile index 5892420dac39..d0d4b2725e5d 100644 --- a/drivers/amlogic/media/gdc/Makefile +++ b/drivers/amlogic/media/gdc/Makefile @@ -1,8 +1,8 @@ FW_SRC := src/fw_lib/acamera_gdc.c \ src/platform/system_gdc_io.c \ - src/platform/system_log.c \ app/gdc_main.c \ - app/gdc_module.c + app/gdc_module.c \ + app/gdc_dmabuf.c FW_SRC_OBJ := $(FW_SRC:.c=.o) diff --git a/drivers/amlogic/media/gdc/app/gdc_dmabuf.c b/drivers/amlogic/media/gdc/app/gdc_dmabuf.c new file mode 100644 index 000000000000..6fbead4e611b --- /dev/null +++ b/drivers/amlogic/media/gdc/app/gdc_dmabuf.c @@ -0,0 +1,680 @@ +/* + * drivers/amlogic/media/gdc/app/gdc_dmabuf.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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "system_log.h" +#include "gdc_dmabuf.h" + +static void clear_dma_buffer(struct aml_dma_buffer *buffer, int index); + +static void *aml_mm_vmap(phys_addr_t phys, unsigned long size) +{ + u32 offset, npages; + struct page **pages = NULL; + pgprot_t pgprot = PAGE_KERNEL; + void *vaddr; + int i; + + offset = offset_in_page(phys); + npages = DIV_ROUND_UP(size + offset, PAGE_SIZE); + + pages = vmalloc(sizeof(struct page *) * npages); + if (!pages) + return NULL; + for (i = 0; i < npages; i++) { + pages[i] = phys_to_page(phys); + phys += PAGE_SIZE; + } + /* pgprot = pgprot_writecombine(PAGE_KERNEL); */ + + vaddr = vmap(pages, npages, VM_MAP, pgprot); + if (!vaddr) { + pr_err("vmaped fail, size: %d\n", + npages << PAGE_SHIFT); + vfree(pages); + return NULL; + } + vfree(pages); + gdc_log(LOG_INFO, "[HIGH-MEM-MAP] pa(%lx) to va(%p), size: %d\n", + (unsigned long)phys, vaddr, npages << PAGE_SHIFT); + return vaddr; +} + +static void *aml_map_phyaddr_to_virt(dma_addr_t phys, unsigned long size) +{ + void *vaddr = NULL; + + if (!PageHighMem(phys_to_page(phys))) + return phys_to_virt(phys); + vaddr = aml_mm_vmap(phys, size); + return vaddr; +} + +/* dma free*/ +static void aml_dma_put(void *buf_priv) +{ + struct aml_dma_buf *buf = buf_priv; + struct page *cma_pages = NULL; + void *vaddr = (void *)(PAGE_MASK & (ulong)buf->vaddr); + + if (!atomic_dec_and_test(&buf->refcount)) { + gdc_log(LOG_INFO, "gdc aml_dma_put, refcont=%d\n", + atomic_read(&buf->refcount)); + return; + } + cma_pages = phys_to_page(buf->dma_addr); + if (is_vmalloc_or_module_addr(vaddr)) + vunmap(vaddr); + if (!dma_release_from_contiguous(buf->dev, cma_pages, + buf->size >> PAGE_SHIFT)) { + pr_err("failed to release cma buffer\n"); + } + buf->vaddr = NULL; + clear_dma_buffer((struct aml_dma_buffer *)buf->priv, buf->index); + put_device(buf->dev); + kfree(buf); + gdc_log(LOG_INFO, "gdc free:aml_dma_buf=0x%p,buf->index=%d\n", + buf, buf->index); +} + +static void *aml_dma_alloc(struct device *dev, unsigned long attrs, + unsigned long size, enum dma_data_direction dma_dir, + gfp_t gfp_flags) +{ + struct aml_dma_buf *buf; + struct page *cma_pages = NULL; + dma_addr_t paddr = 0; + + if (WARN_ON(!dev)) + return (void *)(-EINVAL); + + buf = kzalloc(sizeof(struct aml_dma_buf), GFP_KERNEL); + if (!buf) + return NULL; + + if (attrs) + buf->attrs = attrs; + cma_pages = dma_alloc_from_contiguous(dev, + size >> PAGE_SHIFT, 0); + if (cma_pages) { + paddr = page_to_phys(cma_pages); + } else { + pr_err("failed to alloc cma pages.\n"); + return NULL; + } + buf->vaddr = aml_map_phyaddr_to_virt(paddr, size); + buf->dev = get_device(dev); + buf->size = size; + buf->dma_dir = dma_dir; + buf->dma_addr = paddr; + atomic_inc(&buf->refcount); + gdc_log(LOG_INFO, "aml_dma_buf=0x%p, refcont=%d\n", + buf, atomic_read(&buf->refcount)); + + return buf; +} + +static int aml_dma_mmap(void *buf_priv, struct vm_area_struct *vma) +{ + struct aml_dma_buf *buf = buf_priv; + unsigned long pfn = 0; + unsigned long vsize = vma->vm_end - vma->vm_start; + int ret = -1; + + if (!buf || !vma) { + pr_err("No memory to map\n"); + return -EINVAL; + } + + pfn = buf->dma_addr >> PAGE_SHIFT; + ret = remap_pfn_range(vma, vma->vm_start, pfn, + vsize, vma->vm_page_prot); + if (ret) { + pr_err("Remapping memory, error: %d\n", ret); + return ret; + } + vma->vm_flags |= VM_DONTEXPAND; + + gdc_log(LOG_INFO, "mapped dma addr 0x%08lx at 0x%08lx, size %d\n", + (unsigned long)buf->dma_addr, vma->vm_start, + buf->size); + return 0; +} + +/*********************************************/ +/* DMABUF ops for exporters */ +/*********************************************/ +struct aml_attachment { + struct sg_table sgt; + enum dma_data_direction dma_dir; +}; + +static int aml_dmabuf_ops_attach(struct dma_buf *dbuf, struct device *dev, + struct dma_buf_attachment *dbuf_attach) +{ + struct aml_attachment *attach; + struct aml_dma_buf *buf = dbuf->priv; + int num_pages = PAGE_ALIGN(buf->size) / PAGE_SIZE; + struct sg_table *sgt; + struct scatterlist *sg; + phys_addr_t phys = buf->dma_addr; + unsigned int i; + int ret; + + attach = kzalloc(sizeof(*attach), GFP_KERNEL); + if (!attach) + return -ENOMEM; + + sgt = &attach->sgt; + /* Copy the buf->base_sgt scatter list to the attachment, as we can't + * map the same scatter list to multiple attachments at the same time. + */ + ret = sg_alloc_table(sgt, num_pages, GFP_KERNEL); + if (ret) { + kfree(attach); + return -ENOMEM; + } + for_each_sg(sgt->sgl, sg, sgt->nents, i) { + struct page *page = phys_to_page(phys); + + if (!page) { + sg_free_table(sgt); + kfree(attach); + return -ENOMEM; + } + sg_set_page(sg, page, PAGE_SIZE, 0); + phys += PAGE_SIZE; + } + + attach->dma_dir = DMA_NONE; + dbuf_attach->priv = attach; + + return 0; +} + +static void aml_dmabuf_ops_detach(struct dma_buf *dbuf, + struct dma_buf_attachment *db_attach) +{ + struct aml_attachment *attach = db_attach->priv; + struct sg_table *sgt; + + if (!attach) + return; + + sgt = &attach->sgt; + + /* release the scatterlist cache */ + if (attach->dma_dir != DMA_NONE) + dma_unmap_sg(db_attach->dev, sgt->sgl, sgt->orig_nents, + attach->dma_dir); + sg_free_table(sgt); + kfree(attach); + db_attach->priv = NULL; + +} + +static struct sg_table *aml_dmabuf_ops_map( + struct dma_buf_attachment *db_attach, enum dma_data_direction dma_dir) +{ + struct aml_attachment *attach = db_attach->priv; + /* stealing dmabuf mutex to serialize map/unmap operations */ + struct mutex *lock = &db_attach->dmabuf->lock; + struct sg_table *sgt; + + mutex_lock(lock); + + sgt = &attach->sgt; + /* return previously mapped sg table */ + if (attach->dma_dir == dma_dir) { + mutex_unlock(lock); + return sgt; + } + + /* release any previous cache */ + if (attach->dma_dir != DMA_NONE) { + dma_unmap_sg(db_attach->dev, sgt->sgl, sgt->orig_nents, + attach->dma_dir); + attach->dma_dir = DMA_NONE; + } + + /* mapping to the client with new direction */ + sgt->nents = dma_map_sg(db_attach->dev, sgt->sgl, sgt->orig_nents, + dma_dir); + if (!sgt->nents) { + pr_err("failed to map scatterlist\n"); + mutex_unlock(lock); + return (void *)(-EIO); + } + + attach->dma_dir = dma_dir; + + mutex_unlock(lock); + return sgt; +} + +static void aml_dmabuf_ops_unmap(struct dma_buf_attachment *db_attach, + struct sg_table *sgt, enum dma_data_direction dma_dir) +{ + /* nothing to be done here */ +} + +static void aml_dmabuf_ops_release(struct dma_buf *dbuf) +{ + /* drop reference obtained in vb2_dc_get_dmabuf */ + aml_dma_put(dbuf->priv); +} + +static void *aml_dmabuf_ops_kmap(struct dma_buf *dbuf, unsigned long pgnum) +{ + struct aml_dma_buf *buf = dbuf->priv; + + return buf->vaddr ? buf->vaddr + pgnum * PAGE_SIZE : NULL; +} + +static void *aml_dmabuf_ops_vmap(struct dma_buf *dbuf) +{ + struct aml_dma_buf *buf = dbuf->priv; + + return buf->vaddr; +} + +static int aml_dmabuf_ops_mmap(struct dma_buf *dbuf, + struct vm_area_struct *vma) +{ + return aml_dma_mmap(dbuf->priv, vma); +} + +static struct dma_buf_ops gdc_dmabuf_ops = { + .attach = aml_dmabuf_ops_attach, + .detach = aml_dmabuf_ops_detach, + .map_dma_buf = aml_dmabuf_ops_map, + .unmap_dma_buf = aml_dmabuf_ops_unmap, + .kmap = aml_dmabuf_ops_kmap, + .kmap_atomic = aml_dmabuf_ops_kmap, + .vmap = aml_dmabuf_ops_vmap, + .mmap = aml_dmabuf_ops_mmap, + .release = aml_dmabuf_ops_release, +}; + +static struct dma_buf *get_dmabuf(void *buf_priv, unsigned long flags) +{ + struct aml_dma_buf *buf = buf_priv; + struct dma_buf *dbuf; + DEFINE_DMA_BUF_EXPORT_INFO(exp_info); + + exp_info.ops = &gdc_dmabuf_ops; + exp_info.size = buf->size; + exp_info.flags = flags; + exp_info.priv = buf; + + if (WARN_ON(!buf->vaddr)) + return NULL; + + dbuf = dma_buf_export(&exp_info); + if (IS_ERR(dbuf)) + return NULL; + + /* dmabuf keeps reference to vb2 buffer */ + atomic_inc(&buf->refcount); + gdc_log(LOG_INFO, "get_dmabuf, refcount=%d\n", + atomic_read(&buf->refcount)); + + return dbuf; +} + +/* ge2d dma-buf api.h*/ +static int find_empty_dma_buffer(struct aml_dma_buffer *buffer) +{ + int i; + int found = 0; + + for (i = 0; i < AML_MAX_DMABUF; i++) { + if (buffer->gd_buffer[i].alloc) + continue; + else { + gdc_log(LOG_INFO, "find_empty_dma_buffer i=%d\n", i); + found = 1; + break; + } + } + if (found) + return i; + else + return -1; +} + +static void clear_dma_buffer(struct aml_dma_buffer *buffer, int index) +{ + mutex_lock(&(buffer->lock)); + buffer->gd_buffer[index].mem_priv = NULL; + buffer->gd_buffer[index].index = 0; + buffer->gd_buffer[index].alloc = 0; + mutex_unlock(&(buffer->lock)); +} + +void *gdc_dma_buffer_create(void) +{ + int i; + struct aml_dma_buffer *buffer; + + buffer = kzalloc(sizeof(*buffer), GFP_KERNEL); + if (!buffer) + return NULL; + + mutex_init(&buffer->lock); + for (i = 0; i < AML_MAX_DMABUF; i++) { + buffer->gd_buffer[i].mem_priv = NULL; + buffer->gd_buffer[i].index = 0; + buffer->gd_buffer[i].alloc = 0; + } + return buffer; +} + +void gdc_dma_buffer_destroy(struct aml_dma_buffer *buffer) +{ + kfree(buffer); +} + +int gdc_dma_buffer_alloc(struct aml_dma_buffer *buffer, + struct device *dev, + struct gdc_dmabuf_req_s *gdc_req_buf) +{ + void *buf; + struct aml_dma_buf *dma_buf; + unsigned int size; + int index; + + if (WARN_ON(!dev)) + return (-EINVAL); + if (!gdc_req_buf) + return (-EINVAL); + if (!buffer) + return (-EINVAL); + + size = PAGE_ALIGN(gdc_req_buf->len); + if (size == 0) + return (-EINVAL); + buf = aml_dma_alloc(dev, 0, size, gdc_req_buf->dma_dir, + GFP_HIGHUSER | __GFP_ZERO); + if (!buf) + return (-ENOMEM); + mutex_lock(&(buffer->lock)); + index = find_empty_dma_buffer(buffer); + if ((index < 0) || (index >= AML_MAX_DMABUF)) { + pr_err("no empty buffer found\n"); + mutex_unlock(&(buffer->lock)); + aml_dma_put(buf); + return (-ENOMEM); + } + ((struct aml_dma_buf *)buf)->priv = buffer; + ((struct aml_dma_buf *)buf)->index = index; + buffer->gd_buffer[index].mem_priv = buf; + buffer->gd_buffer[index].index = index; + buffer->gd_buffer[index].alloc = 1; + mutex_unlock(&(buffer->lock)); + gdc_req_buf->index = index; + dma_buf = (struct aml_dma_buf *)buf; + if (dma_buf->dma_dir == DMA_FROM_DEVICE) + dma_sync_single_for_cpu(dma_buf->dev, + dma_buf->dma_addr, + dma_buf->size, DMA_FROM_DEVICE); + return 0; +} + +int gdc_dma_buffer_free(struct aml_dma_buffer *buffer, int index) +{ + struct aml_dma_buf *buf; + + if (!buffer) + return (-EINVAL); + if ((index) < 0 || (index >= AML_MAX_DMABUF)) + return (-EINVAL); + + buf = buffer->gd_buffer[index].mem_priv; + if (!buf) { + pr_err("aml_dma_buf is null\n"); + return (-EINVAL); + } + aml_dma_put(buf); + return 0; +} + +int gdc_dma_buffer_export(struct aml_dma_buffer *buffer, + struct gdc_dmabuf_exp_s *gdc_exp_buf) +{ + struct aml_dma_buf *buf; + struct dma_buf *dbuf; + int ret, index; + unsigned int flags; + + if (!gdc_exp_buf) + return (-EINVAL); + if (!buffer) + return (-EINVAL); + + index = gdc_exp_buf->index; + if ((index) < 0 || (index >= AML_MAX_DMABUF)) + return (-EINVAL); + + flags = gdc_exp_buf->flags; + buf = buffer->gd_buffer[index].mem_priv; + if (!buf) { + pr_err("aml_dma_buf is null\n"); + return (-EINVAL); + } + dbuf = get_dmabuf(buf, flags & O_ACCMODE); + if (IS_ERR_OR_NULL(dbuf)) { + pr_err("failed to export buffer %d\n", index); + return -EINVAL; + } + ret = dma_buf_fd(dbuf, flags & ~O_ACCMODE); + if (ret < 0) { + pr_err("buffer %d, failed to export (%d)\n", + index, ret); + dma_buf_put(dbuf); + return ret; + } + gdc_log(LOG_INFO, "buffer %d,exported as %d descriptor\n", + index, ret); + gdc_exp_buf->fd = ret; + return 0; +} + +int gdc_dma_buffer_map(struct aml_dma_cfg *cfg) +{ + long ret = -1; + int fd = -1; + struct dma_buf *dbuf = NULL; + struct dma_buf_attachment *d_att = NULL; + struct sg_table *sg = NULL; + void *vaddr = NULL; + struct device *dev = NULL; + enum dma_data_direction dir; + + + if (cfg == NULL || (cfg->fd < 0) || cfg->dev == NULL) { + pr_err("error input param"); + return -EINVAL; + } + fd = cfg->fd; + dev = cfg->dev; + dir = cfg->dir; + dbuf = dma_buf_get(fd); + if (IS_ERR(dbuf)) { + pr_err("failed to get dma buffer"); + return -EINVAL; + } + d_att = dma_buf_attach(dbuf, dev); + if (IS_ERR(d_att)) { + pr_err("failed to set dma attach"); + goto attach_err; + } + + sg = dma_buf_map_attachment(d_att, dir); + if (IS_ERR(sg)) { + pr_err("failed to get dma sg"); + goto map_attach_err; + } + + ret = dma_buf_begin_cpu_access(dbuf, dir); + if (ret != 0) { + pr_err("failed to access dma buff"); + goto access_err; + } + + vaddr = dma_buf_vmap(dbuf); + if (vaddr == NULL) { + pr_err("failed to vmap dma buf"); + goto vmap_err; + } + cfg->dbuf = dbuf; + cfg->attach = d_att; + cfg->vaddr = vaddr; + cfg->sg = sg; + gdc_log(LOG_INFO, "gdc_dma_buffer_map, dbuf=0x%p\n", dbuf); + + return ret; + +vmap_err: + dma_buf_end_cpu_access(dbuf, dir); + +access_err: + dma_buf_unmap_attachment(d_att, sg, dir); + +map_attach_err: + dma_buf_detach(dbuf, d_att); + +attach_err: + dma_buf_put(dbuf); + return ret; +} + +int gdc_dma_buffer_get_phys(struct aml_dma_cfg *cfg, unsigned long *addr) +{ + struct sg_table *sg_table; + struct page *page; + int ret; + + ret = gdc_dma_buffer_map(cfg); + if (ret < 0) { + pr_err("gdc_dma_buffer_map failed\n"); + return ret; + } + if (cfg->sg) { + sg_table = cfg->sg; + page = sg_page(sg_table->sgl); + *addr = PFN_PHYS(page_to_pfn(page)); + ret = 0; + } + return ret; +} + +void gdc_dma_buffer_unmap(struct aml_dma_cfg *cfg) +{ + int fd = -1; + struct dma_buf *dbuf = NULL; + struct dma_buf_attachment *d_att = NULL; + struct sg_table *sg = NULL; + void *vaddr = NULL; + struct device *dev = NULL; + enum dma_data_direction dir; + + if (cfg == NULL || (cfg->fd < 0) || cfg->dev == NULL + || cfg->dbuf == NULL || cfg->vaddr == NULL + || cfg->attach == NULL || cfg->sg == NULL) { + pr_err("Error input param"); + return; + } + + fd = cfg->fd; + dev = cfg->dev; + dir = cfg->dir; + dbuf = cfg->dbuf; + vaddr = cfg->vaddr; + d_att = cfg->attach; + sg = cfg->sg; + dma_buf_vunmap(dbuf, vaddr); + + dma_buf_end_cpu_access(dbuf, dir); + + dma_buf_unmap_attachment(d_att, sg, dir); + + dma_buf_detach(dbuf, d_att); + + dma_buf_put(dbuf); + gdc_log(LOG_INFO, "gdc_dma_buffer_unmap, dbuf=0x%p\n", dbuf); +} + +void gdc_dma_buffer_dma_flush(struct device *dev, int fd) +{ + struct dma_buf *dmabuf; + struct aml_dma_buf *buf; + + gdc_log(LOG_INFO, "gdc_dma_buffer_dma_flush fd=%d\n", fd); + dmabuf = dma_buf_get(fd); + if (IS_ERR(dmabuf)) { + pr_err("dma_buf_get failed\n"); + return; + } + buf = dmabuf->priv; + if (!buf) { + pr_err("error input param"); + return; + } + if ((buf->size > 0) && (buf->dev == dev)) + dma_sync_single_for_device(buf->dev, buf->dma_addr, + buf->size, DMA_TO_DEVICE); + dma_buf_put(dmabuf); +} + +void gdc_dma_buffer_cache_flush(struct device *dev, int fd) +{ + struct dma_buf *dmabuf; + struct aml_dma_buf *buf; + + gdc_log(LOG_INFO, "gdc_dma_buffer_cache_flush fd=%d\n", fd); + dmabuf = dma_buf_get(fd); + if (IS_ERR(dmabuf)) { + pr_err("dma_buf_get failed\n"); + return; + } + buf = dmabuf->priv; + if (!buf) { + pr_err("error input param"); + return; + } + if ((buf->size > 0) && (buf->dev == dev)) + dma_sync_single_for_cpu(buf->dev, buf->dma_addr, + buf->size, DMA_FROM_DEVICE); + dma_buf_put(dmabuf); +} diff --git a/drivers/amlogic/media/gdc/app/gdc_dmabuf.h b/drivers/amlogic/media/gdc/app/gdc_dmabuf.h new file mode 100644 index 000000000000..a6e988d20a2a --- /dev/null +++ b/drivers/amlogic/media/gdc/app/gdc_dmabuf.h @@ -0,0 +1,79 @@ +/* + * drivers/amlogic/media/gdc/app/gdc_dmabuf.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 _GDC_DMABUF_H_ +#define _GDC_DMABUF_H_ + +#include +#include +#include + + +#define AML_MAX_DMABUF 32 + +struct aml_dma_buf { + struct device *dev; + void *cookie; + void *vaddr; + unsigned int size; + enum dma_data_direction dma_dir; + unsigned long attrs; + unsigned int index; + dma_addr_t dma_addr; + atomic_t refcount; + /* DMABUF related */ + struct dma_buf_attachment *db_attach; + void *priv; +}; + +struct aml_dma_buf_priv { + void *mem_priv; + int index; + unsigned int alloc; + struct dma_buf *dbuf; +}; + +struct aml_dma_buffer { + struct mutex lock; + struct aml_dma_buf_priv gd_buffer[AML_MAX_DMABUF]; +}; + +struct aml_dma_cfg { + int fd; + void *dev; + void *vaddr; + struct dma_buf *dbuf; + struct dma_buf_attachment *attach; + struct sg_table *sg; + enum dma_data_direction dir; +}; + + +void *gdc_dma_buffer_create(void); +void gdc_dma_buffer_destroy(struct aml_dma_buffer *buffer); +int gdc_dma_buffer_alloc(struct aml_dma_buffer *buffer, + struct device *dev, + struct gdc_dmabuf_req_s *gdc_req_buf); +int gdc_dma_buffer_free(struct aml_dma_buffer *buffer, int index); +int gdc_dma_buffer_export(struct aml_dma_buffer *buffer, + struct gdc_dmabuf_exp_s *gdc_exp_buf); +int gdc_dma_buffer_map(struct aml_dma_cfg *cfg); +void gdc_dma_buffer_unmap(struct aml_dma_cfg *cfg); +int gdc_dma_buffer_get_phys(struct aml_dma_cfg *cfg, unsigned long *addr); +void gdc_dma_buffer_dma_flush(struct device *dev, int fd); +void gdc_dma_buffer_cache_flush(struct device *dev, int fd); +#endif diff --git a/drivers/amlogic/media/gdc/app/gdc_main.c b/drivers/amlogic/media/gdc/app/gdc_main.c index c6d631169821..538416dd9bb0 100644 --- a/drivers/amlogic/media/gdc/app/gdc_main.c +++ b/drivers/amlogic/media/gdc/app/gdc_main.c @@ -25,27 +25,27 @@ irqreturn_t interrupt_handler_next(int irq, void *param) { //handle the start of frame with gdc_process - struct gdc_settings *gdc_settings = (struct gdc_settings *)param; + struct gdc_cmd_s *gdc_cmd = (struct gdc_cmd_s *)param; - gdc_get_frame(gdc_settings); + gdc_get_frame(gdc_cmd); return IRQ_HANDLED; } -int gdc_run(struct gdc_settings *g) +int gdc_run(struct gdc_cmd_s *g) { gdc_stop(g); - LOG(LOG_INFO, "Done gdc load..\n"); + gdc_log(LOG_INFO, "Done gdc load..\n"); //initialise the gdc by the first configuration if (gdc_init(g) != 0) { - LOG(LOG_ERR, "Failed to initialise GDC block"); + gdc_log(LOG_ERR, "Failed to initialise GDC block"); return -1; } - LOG(LOG_INFO, "Done gdc config..\n"); + gdc_log(LOG_INFO, "Done gdc config..\n"); switch (g->gdc_config.format) { case NV12: @@ -70,10 +70,10 @@ int gdc_run(struct gdc_settings *g) g->v_base_addr); break; default: - LOG(LOG_ERR, "Error config format\n"); + gdc_log(LOG_ERR, "Error config format\n"); break; } - LOG(LOG_DEBUG, "call gdc process\n"); + gdc_log(LOG_DEBUG, "call gdc process\n"); return 0; } diff --git a/drivers/amlogic/media/gdc/app/gdc_module.c b/drivers/amlogic/media/gdc/app/gdc_module.c index 040218d9ac0e..678980b9c464 100644 --- a/drivers/amlogic/media/gdc/app/gdc_module.c +++ b/drivers/amlogic/media/gdc/app/gdc_module.c @@ -41,33 +41,46 @@ #include #include #include +#include + //gdc configuration sequence #include "gdc_config.h" +#include "gdc_dmabuf.h" -struct meson_gdc_dev_t *g_gdc_dev; +unsigned int gdc_log_level; +struct gdc_manager_s gdc_manager; +static int trace_mode_enable; +static char *config_out_file; +static int config_out_path_defined; + +#define WAIT_THRESHOLD 1000 +#define CONFIG_PATH_LENG 128 static const struct of_device_id gdc_dt_match[] = { {.compatible = "amlogic, g12b-gdc"}, {} }; MODULE_DEVICE_TABLE(of, gdc_dt_match); +static void meson_gdc_cache_flush(struct device *dev, + dma_addr_t addr, + size_t size); ////// static int meson_gdc_open(struct inode *inode, struct file *file) { - struct meson_gdc_dev_t *gdc_dev = g_gdc_dev; + struct meson_gdc_dev_t *gdc_dev = gdc_manager.gdc_dev; struct mgdc_fh_s *fh = NULL; char ion_client_name[32]; int rc = 0; fh = kzalloc(sizeof(*fh), GFP_KERNEL); if (fh == NULL) { - LOG(LOG_DEBUG, "devm alloc failed\n"); + gdc_log(LOG_DEBUG, "devm alloc failed\n"); return -ENOMEM; } get_task_comm(fh->task_comm, current); - LOG(LOG_DEBUG, "%s, %d, call from %s\n", + gdc_log(LOG_DEBUG, "%s, %d, call from %s\n", __func__, __LINE__, fh->task_comm); file->private_data = fh; @@ -78,7 +91,7 @@ static int meson_gdc_open(struct inode *inode, struct file *file) fh->gdev = gdc_dev; - LOG(LOG_CRIT, "Success open\n"); + gdc_log(LOG_INFO, "Success open\n"); return rc; } @@ -102,7 +115,7 @@ static int meson_gdc_release(struct inode *inode, struct file *file) fh->i_len >> PAGE_SHIFT); if (rc == false) { ret = ret - 1; - LOG(LOG_ERR, "Failed to release input buff\n"); + gdc_log(LOG_ERR, "Failed to release input buff\n"); } fh->i_kaddr = NULL; @@ -117,7 +130,7 @@ static int meson_gdc_release(struct inode *inode, struct file *file) fh->o_len >> PAGE_SHIFT); if (rc == false) { ret = ret - 1; - LOG(LOG_ERR, "Failed to release output buff\n"); + gdc_log(LOG_ERR, "Failed to release output buff\n"); } fh->o_kaddr = NULL; @@ -132,7 +145,7 @@ static int meson_gdc_release(struct inode *inode, struct file *file) fh->c_len >> PAGE_SHIFT); if (rc == false) { ret = ret - 1; - LOG(LOG_ERR, "Failed to release config buff\n"); + gdc_log(LOG_ERR, "Failed to release config buff\n"); } fh->c_kaddr = NULL; @@ -144,9 +157,9 @@ static int meson_gdc_release(struct inode *inode, struct file *file) fh = NULL; if (ret == 0) - LOG(LOG_CRIT, "Success release\n"); + gdc_log(LOG_INFO, "Success release\n"); else - LOG(LOG_ERR, "Error release\n"); + gdc_log(LOG_ERR, "Error release\n"); return ret; } @@ -159,7 +172,7 @@ static long meson_gdc_set_buff(void *f_fh, struct mgdc_fh_s *fh = NULL; if (f_fh == NULL || cma_pages == NULL || len == 0) { - LOG(LOG_ERR, "Error input param\n"); + gdc_log(LOG_ERR, "Error input param\n"); return -EINVAL; } @@ -179,6 +192,8 @@ static long meson_gdc_set_buff(void *f_fh, fh->o_paddr = page_to_phys(cma_pages); fh->o_kaddr = phys_to_virt(fh->o_paddr); fh->o_len = len; + meson_gdc_cache_flush(&fh->gdev->pdev->dev, + fh->o_paddr, fh->o_len); break; case CONFIG_BUFF_TYPE: if (fh->c_paddr != 0 && fh->c_kaddr != NULL) @@ -188,7 +203,7 @@ static long meson_gdc_set_buff(void *f_fh, fh->c_len = len; break; default: - LOG(LOG_ERR, "Error mmap type:0x%x\n", fh->mmap_type); + gdc_log(LOG_ERR, "Error mmap type:0x%x\n", fh->mmap_type); ret = -EINVAL; break; } @@ -197,51 +212,51 @@ static long meson_gdc_set_buff(void *f_fh, } static long meson_gdc_set_input_addr(uint32_t start_addr, - struct gdc_settings *gs) + struct gdc_cmd_s *gdc_cmd) { - struct gdc_config *gc = NULL; + struct gdc_config_s *gc = NULL; - if (gs == NULL || start_addr == 0) { - LOG(LOG_ERR, "Error input param\n"); + if (gdc_cmd == NULL || start_addr == 0) { + gdc_log(LOG_ERR, "Error input param\n"); return -EINVAL; } - gc = &gs->gdc_config; + gc = &gdc_cmd->gdc_config; switch (gc->format) { case NV12: - gs->y_base_addr = start_addr; - gs->uv_base_addr = start_addr + + gdc_cmd->y_base_addr = start_addr; + gdc_cmd->uv_base_addr = start_addr + gc->input_y_stride * gc->input_height; break; case YV12: - gs->y_base_addr = start_addr; - gs->u_base_addr = start_addr + + gdc_cmd->y_base_addr = start_addr; + gdc_cmd->u_base_addr = start_addr + gc->input_y_stride * gc->input_height; - gs->v_base_addr = gs->u_base_addr + + gdc_cmd->v_base_addr = gdc_cmd->u_base_addr + gc->input_c_stride * gc->input_height / 2; break; case Y_GREY: - gs->y_base_addr = start_addr; - gs->u_base_addr = 0; - gs->v_base_addr = 0; + gdc_cmd->y_base_addr = start_addr; + gdc_cmd->u_base_addr = 0; + gdc_cmd->v_base_addr = 0; break; case YUV444_P: - gs->y_base_addr = start_addr; - gs->u_base_addr = start_addr + + gdc_cmd->y_base_addr = start_addr; + gdc_cmd->u_base_addr = start_addr + gc->input_y_stride * gc->input_height; - gs->v_base_addr = gs->u_base_addr + + gdc_cmd->v_base_addr = gdc_cmd->u_base_addr + gc->input_c_stride * gc->input_height; break; case RGB444_P: - gs->y_base_addr = start_addr; - gs->u_base_addr = start_addr + + gdc_cmd->y_base_addr = start_addr; + gdc_cmd->u_base_addr = start_addr + gc->input_y_stride * gc->input_height; - gs->v_base_addr = gs->u_base_addr + + gdc_cmd->v_base_addr = gdc_cmd->u_base_addr + gc->input_c_stride * gc->input_height; break; default: - LOG(LOG_ERR, "Error config format\n"); + gdc_log(LOG_ERR, "Error config format\n"); return -EINVAL; break; } @@ -254,7 +269,7 @@ static void meson_gdc_dma_flush(struct device *dev, size_t size) { if (dev == NULL) { - LOG(LOG_ERR, "Error input param"); + gdc_log(LOG_ERR, "Error input param"); return; } @@ -266,7 +281,7 @@ static void meson_gdc_cache_flush(struct device *dev, size_t size) { if (dev == NULL) { - LOG(LOG_ERR, "Error input param"); + gdc_log(LOG_ERR, "Error input param"); return; } @@ -285,7 +300,7 @@ static long meson_gdc_dma_map(struct gdc_dma_cfg *cfg) enum dma_data_direction dir; if (cfg == NULL || (cfg->fd < 0) || cfg->dev == NULL) { - LOG(LOG_ERR, "Error input param"); + gdc_log(LOG_ERR, "Error input param"); return -EINVAL; } @@ -295,31 +310,31 @@ static long meson_gdc_dma_map(struct gdc_dma_cfg *cfg) dbuf = dma_buf_get(fd); if (dbuf == NULL) { - LOG(LOG_ERR, "Failed to get dma buffer"); + gdc_log(LOG_ERR, "Failed to get dma buffer"); return -EINVAL; } d_att = dma_buf_attach(dbuf, dev); if (d_att == NULL) { - LOG(LOG_ERR, "Failed to set dma attach"); + gdc_log(LOG_ERR, "Failed to set dma attach"); goto attach_err; } sg = dma_buf_map_attachment(d_att, dir); if (sg == NULL) { - LOG(LOG_ERR, "Failed to get dma sg"); + gdc_log(LOG_ERR, "Failed to get dma sg"); goto map_attach_err; } ret = dma_buf_begin_cpu_access(dbuf, dir); if (ret != 0) { - LOG(LOG_ERR, "Failed to access dma buff"); + gdc_log(LOG_ERR, "Failed to access dma buff"); goto access_err; } vaddr = dma_buf_vmap(dbuf); if (vaddr == NULL) { - LOG(LOG_ERR, "Failed to vmap dma buf"); + gdc_log(LOG_ERR, "Failed to vmap dma buf"); goto vmap_err; } @@ -345,7 +360,6 @@ attach_err: return ret; } - static void meson_gdc_dma_unmap(struct gdc_dma_cfg *cfg) { int fd = -1; @@ -359,7 +373,7 @@ static void meson_gdc_dma_unmap(struct gdc_dma_cfg *cfg) if (cfg == NULL || (cfg->fd < 0) || cfg->dev == NULL || cfg->dbuf == NULL || cfg->vaddr == NULL || cfg->attach == NULL || cfg->sg == NULL) { - LOG(LOG_ERR, "Error input param"); + gdc_log(LOG_ERR, "Error input param"); return; } @@ -382,21 +396,19 @@ static void meson_gdc_dma_unmap(struct gdc_dma_cfg *cfg) dma_buf_put(dbuf); } -static long meson_gdc_init_dma_addr(struct gdc_settings *gs) +static long meson_gdc_init_dma_addr(struct mgdc_fh_s *fh, + struct gdc_settings *gs) { long ret = -1; struct gdc_dma_cfg *dma_cfg = NULL; - struct gdc_config *gc = NULL; - struct mgdc_fh_s *fh = NULL; + struct gdc_cmd_s *gdc_cmd = &fh->gdc_cmd; + struct gdc_config_s *gc = &gdc_cmd->gdc_config; - if (gs == NULL || gs->fh == NULL) { - LOG(LOG_ERR, "Error input param\n"); + if (fh == NULL || gs == NULL) { + gdc_log(LOG_ERR, "Error input param\n"); return -EINVAL; } - gc = &gs->gdc_config; - fh = gs->fh; - switch (gc->format) { case NV12: dma_cfg = &fh->y_dma_cfg; @@ -407,11 +419,11 @@ static long meson_gdc_init_dma_addr(struct gdc_settings *gs) ret = meson_gdc_dma_map(dma_cfg); if (ret != 0) { - LOG(LOG_ERR, "Failed to get map dma buff"); + gdc_log(LOG_ERR, "Failed to get map dma buff"); return ret; } - gs->y_base_addr = virt_to_phys(dma_cfg->vaddr); + gdc_cmd->y_base_addr = virt_to_phys(dma_cfg->vaddr); dma_cfg = &fh->uv_dma_cfg; memset(dma_cfg, 0, sizeof(*dma_cfg)); @@ -421,11 +433,11 @@ static long meson_gdc_init_dma_addr(struct gdc_settings *gs) ret = meson_gdc_dma_map(dma_cfg); if (ret != 0) { - LOG(LOG_ERR, "Failed to get map dma buff"); + gdc_log(LOG_ERR, "Failed to get map dma buff"); return ret; } - gs->uv_base_addr = virt_to_phys(dma_cfg->vaddr); + gdc_cmd->uv_base_addr = virt_to_phys(dma_cfg->vaddr); break; case Y_GREY: dma_cfg = &fh->y_dma_cfg; @@ -436,35 +448,31 @@ static long meson_gdc_init_dma_addr(struct gdc_settings *gs) ret = meson_gdc_dma_map(dma_cfg); if (ret != 0) { - LOG(LOG_ERR, "Failed to get map dma buff"); + gdc_log(LOG_ERR, "Failed to get map dma buff"); return ret; } - - gs->y_base_addr = virt_to_phys(dma_cfg->vaddr); - gs->uv_base_addr = 0; + gdc_cmd->y_base_addr = virt_to_phys(dma_cfg->vaddr); + gdc_cmd->uv_base_addr = 0; break; default: - LOG(LOG_ERR, "Error image format"); + gdc_log(LOG_ERR, "Error image format"); break; } return ret; } -static void meson_gdc_deinit_dma_addr(struct gdc_settings *gs) +static void meson_gdc_deinit_dma_addr(struct mgdc_fh_s *fh) { struct gdc_dma_cfg *dma_cfg = NULL; - struct gdc_config *gc = NULL; - struct mgdc_fh_s *fh = NULL; + struct gdc_cmd_s *gdc_cmd = &fh->gdc_cmd; + struct gdc_config_s *gc = &gdc_cmd->gdc_config; - if (gs == NULL || gs->fh == NULL) { - LOG(LOG_ERR, "Error input param\n"); + if (fh == NULL) { + gdc_log(LOG_ERR, "Error input param\n"); return; } - gc = &gs->gdc_config; - fh = gs->fh; - switch (gc->format) { case NV12: dma_cfg = &fh->y_dma_cfg; @@ -478,169 +486,972 @@ static void meson_gdc_deinit_dma_addr(struct gdc_settings *gs) meson_gdc_dma_unmap(dma_cfg); break; default: - LOG(LOG_ERR, "Error image format"); + gdc_log(LOG_ERR, "Error image format"); break; } } +static int gdc_buffer_alloc(struct gdc_dmabuf_req_s *gdc_req_buf) +{ + struct device *dev; + + dev = &(gdc_manager.gdc_dev->pdev->dev); + return gdc_dma_buffer_alloc(gdc_manager.buffer, + dev, gdc_req_buf); +} + +static int gdc_buffer_export(struct gdc_dmabuf_exp_s *gdc_exp_buf) +{ + return gdc_dma_buffer_export(gdc_manager.buffer, gdc_exp_buf); +} + +static int gdc_buffer_free(int index) +{ + return gdc_dma_buffer_free(gdc_manager.buffer, index); + +} + +static void gdc_buffer_dma_flush(int dma_fd) +{ + struct device *dev; + + dev = &(gdc_manager.gdc_dev->pdev->dev); + gdc_dma_buffer_dma_flush(dev, dma_fd); +} + +static void gdc_buffer_cache_flush(int dma_fd) +{ + struct device *dev; + + dev = &(gdc_manager.gdc_dev->pdev->dev); + gdc_dma_buffer_cache_flush(dev, dma_fd); +} + +static long gdc_process_input_dma_info(struct mgdc_fh_s *fh, + struct gdc_settings_ex *gs_ex) +{ + long ret = -1; + unsigned long addr; + struct aml_dma_cfg *cfg = NULL; + struct gdc_cmd_s *gdc_cmd = &fh->gdc_cmd; + struct gdc_config_s *gc = &gdc_cmd->gdc_config; + + if (fh == NULL || gs_ex == NULL) { + gdc_log(LOG_ERR, "Error input param\n"); + return -EINVAL; + } + + switch (gc->format) { + case NV12: + if (gs_ex->input_buffer.plane_number == 1) { + cfg = &fh->dma_cfg.input_cfg_plane1; + cfg->fd = gs_ex->input_buffer.y_base_fd; + cfg->dev = &fh->gdev->pdev->dev; + cfg->dir = DMA_TO_DEVICE; + + ret = gdc_dma_buffer_get_phys(cfg, &addr); + if (ret < 0) { + gdc_log(LOG_ERR, + "dma import input fd %d failed\n", + gs_ex->input_buffer.y_base_fd); + return -EINVAL; + } + ret = meson_gdc_set_input_addr(addr, gdc_cmd); + if (ret != 0) { + gdc_log(LOG_ERR, "set input addr failed\n"); + return -EINVAL; + } + gdc_log(LOG_INFO, "1 plane get input addr=%x\n", + gdc_cmd->y_base_addr); + meson_gdc_dma_flush(&fh->gdev->pdev->dev, + gdc_cmd->y_base_addr, + gc->input_y_stride * gc->input_height); + } else if (gs_ex->input_buffer.plane_number == 2) { + cfg = &fh->dma_cfg.input_cfg_plane1; + cfg->fd = gs_ex->input_buffer.y_base_fd; + cfg->dev = &fh->gdev->pdev->dev; + cfg->dir = DMA_TO_DEVICE; + ret = gdc_dma_buffer_get_phys(cfg, &addr); + if (ret < 0) { + gdc_log(LOG_ERR, + "dma import input fd %d failed\n", + gs_ex->input_buffer.y_base_fd); + return -EINVAL; + } + gdc_cmd->y_base_addr = addr; + meson_gdc_dma_flush(&fh->gdev->pdev->dev, + gdc_cmd->y_base_addr, + gc->input_y_stride * gc->input_height); + cfg = &fh->dma_cfg.input_cfg_plane2; + cfg->fd = gs_ex->input_buffer.uv_base_fd; + cfg->dev = &fh->gdev->pdev->dev; + cfg->dir = DMA_TO_DEVICE; + ret = gdc_dma_buffer_get_phys(cfg, &addr); + if (ret < 0) { + gdc_log(LOG_ERR, + "dma import input fd %d failed\n", + gs_ex->input_buffer.uv_base_fd); + return -EINVAL; + } + gdc_cmd->uv_base_addr = addr; + meson_gdc_dma_flush(&fh->gdev->pdev->dev, + gdc_cmd->uv_base_addr, + gc->input_y_stride * gc->input_height / 2); + gdc_log(LOG_INFO, "2 plane get input addr=%x\n", + gdc_cmd->y_base_addr); + gdc_log(LOG_INFO, "2 plane get input addr=%x\n", + gdc_cmd->uv_base_addr); + } + break; + case Y_GREY: + cfg = &fh->dma_cfg.input_cfg_plane1; + cfg->fd = gs_ex->input_buffer.y_base_fd; + cfg->dev = &(fh->gdev->pdev->dev); + cfg->dir = DMA_TO_DEVICE; + ret = gdc_dma_buffer_get_phys(cfg, &addr); + if (ret < 0) { + gdc_log(LOG_ERR, + "dma import input fd %d failed\n", + gs_ex->input_buffer.shared_fd); + return -EINVAL; + } + gdc_cmd->y_base_addr = addr; + gdc_cmd->uv_base_addr = 0; + meson_gdc_dma_flush(&fh->gdev->pdev->dev, + gdc_cmd->y_base_addr, + gc->input_y_stride * gc->input_height); + break; + default: + gdc_log(LOG_ERR, "Error image format"); + break; + } + return 0; +} + +static long gdc_process_ex_info(struct mgdc_fh_s *fh, + struct gdc_settings_ex *gs_ex) +{ + long ret; + unsigned long addr = 0; + size_t len; + struct aml_dma_cfg *cfg = NULL; + struct gdc_cmd_s *gdc_cmd = &fh->gdc_cmd; + + if (fh == NULL || gs_ex == NULL) { + gdc_log(LOG_ERR, "Error input param\n"); + return -EINVAL; + } + memcpy(&(gdc_cmd->gdc_config), &(gs_ex->gdc_config), + sizeof(struct gdc_config_s)); + gdc_cmd->fh = fh; + if (gs_ex->output_buffer.mem_alloc_type == AML_GDC_MEM_ION) { + /* ion alloc */ + ret = meson_ion_share_fd_to_phys(fh->ion_client, + gs_ex->output_buffer.shared_fd, + (ion_phys_addr_t *)&addr, &len); + if (ret < 0) { + gdc_log(LOG_ERR, "ion import out fd %d failed\n", + gs_ex->output_buffer.shared_fd); + return -EINVAL; + } + } else if (gs_ex->output_buffer.mem_alloc_type == AML_GDC_MEM_DMABUF) { + /* dma alloc */ + cfg = &fh->dma_cfg.output_cfg; + cfg->fd = gs_ex->output_buffer.y_base_fd; + cfg->dev = &(gdc_manager.gdc_dev->pdev->dev); + cfg->dir = DMA_FROM_DEVICE; + ret = gdc_dma_buffer_get_phys(cfg, &addr); + if (ret < 0) { + gdc_log(LOG_ERR, "dma import out fd %d failed\n", + gs_ex->output_buffer.y_base_fd); + return -EINVAL; + } + + } + gdc_log(LOG_INFO, "%s, output addr=%lx\n", __func__, addr); + gdc_cmd->base_gdc = 0; + gdc_cmd->buffer_addr = addr; + gdc_cmd->current_addr = gdc_cmd->buffer_addr; + if (gs_ex->config_buffer.mem_alloc_type == AML_GDC_MEM_ION) { + /* ion alloc */ + ret = meson_ion_share_fd_to_phys(fh->ion_client, + gs_ex->config_buffer.shared_fd, + (ion_phys_addr_t *)&addr, &len); + if (ret < 0) { + gdc_log(LOG_ERR, "ion import config fd %d failed\n", + gs_ex->config_buffer.shared_fd); + return -EINVAL; + } + } else if (gs_ex->config_buffer.mem_alloc_type == AML_GDC_MEM_DMABUF) { + /* dma alloc */ + cfg = &fh->dma_cfg.config_cfg; + cfg->fd = gs_ex->config_buffer.y_base_fd; + cfg->dev = &(gdc_manager.gdc_dev->pdev->dev); + cfg->dir = DMA_TO_DEVICE; + ret = gdc_dma_buffer_get_phys(cfg, &addr); + if (ret < 0) { + gdc_log(LOG_ERR, "dma import config fd %d failed\n", + gs_ex->config_buffer.shared_fd); + return -EINVAL; + } + } + gdc_cmd->gdc_config.config_addr = addr; + gdc_log(LOG_INFO, "%s, config addr=%lx\n", __func__, addr); + + if (gs_ex->input_buffer.mem_alloc_type == AML_GDC_MEM_ION) { + /* ion alloc */ + ret = meson_ion_share_fd_to_phys(fh->ion_client, + gs_ex->input_buffer.shared_fd, + (ion_phys_addr_t *)&addr, &len); + if (ret < 0) { + gdc_log(LOG_ERR, "ion import input fd %d failed\n", + gs_ex->input_buffer.shared_fd); + return -EINVAL; + } + ret = meson_gdc_set_input_addr(addr, gdc_cmd); + if (ret != 0) { + gdc_log(LOG_ERR, "set input addr failed\n"); + return -EINVAL; + } + } else if (gs_ex->input_buffer.mem_alloc_type == AML_GDC_MEM_DMABUF) { + /* dma alloc */ + ret = gdc_process_input_dma_info(fh, gs_ex); + if (ret < 0) + return -EINVAL; + } + gdc_log(LOG_INFO, "%s, input addr=%x\n", + __func__, fh->gdc_cmd.y_base_addr); + mutex_lock(&fh->gdev->d_mutext); + + if (gs_ex->config_buffer.mem_alloc_type == AML_GDC_MEM_DMABUF) + gdc_buffer_dma_flush(gs_ex->config_buffer.shared_fd); + + ret = gdc_run(gdc_cmd); + if (ret < 0) + gdc_log(LOG_ERR, "gdc process failed ret = %ld\n", ret); + + ret = wait_for_completion_timeout(&fh->gdev->d_com, + msecs_to_jiffies(40)); + if (ret == 0) + gdc_log(LOG_ERR, "gdc timeout\n"); + + gdc_stop(gdc_cmd); + mutex_unlock(&fh->gdev->d_mutext); + #if 0 + if (gs_ex->output_buffer.mem_alloc_type == AML_GDC_MEM_DMABUF) + gdc_buffer_cache_flush(gs_ex->output_buffer.shared_fd); + #endif + if (gs_ex->input_buffer.mem_alloc_type == AML_GDC_MEM_DMABUF) { + gdc_dma_buffer_unmap(&fh->dma_cfg.input_cfg_plane1); + if (gs_ex->input_buffer.plane_number == 2) + gdc_dma_buffer_unmap(&fh->dma_cfg.input_cfg_plane2); + } + if (gs_ex->config_buffer.mem_alloc_type == AML_GDC_MEM_DMABUF) + gdc_dma_buffer_unmap(&fh->dma_cfg.config_cfg); + if (gs_ex->output_buffer.mem_alloc_type == AML_GDC_MEM_DMABUF) + gdc_dma_buffer_unmap(&fh->dma_cfg.output_cfg); + return 0; +} + +u8 __iomem *map_virt_from_phys(phys_addr_t phys, unsigned long total_size) +{ + u32 offset, npages; + struct page **pages = NULL; + pgprot_t pgprot; + u8 __iomem *vaddr; + int i; + + npages = PAGE_ALIGN(total_size) / PAGE_SIZE; + offset = phys & (~PAGE_MASK); + if (offset) + npages++; + pages = vmalloc(sizeof(struct page *) * npages); + if (!pages) + return NULL; + for (i = 0; i < npages; i++) { + pages[i] = phys_to_page(phys); + phys += PAGE_SIZE; + } + /*nocache*/ + pgprot = pgprot_noncached(PAGE_KERNEL); + + vaddr = vmap(pages, npages, VM_MAP, pgprot); + if (!vaddr) { + pr_err("vmaped fail, size: %d\n", + npages << PAGE_SHIFT); + vfree(pages); + return NULL; + } + vfree(pages); + + return vaddr; +} + +void unmap_virt_from_phys(u8 __iomem *vaddr) +{ + if (vaddr) { + /* unmap prevois vaddr */ + vunmap(vaddr); + vaddr = NULL; + } +} + +static void release_config_firmware(struct gdc_settings_with_fw *gs_with_fw) +{ + + if (gs_with_fw->fw_info.virt_addr) + unmap_virt_from_phys(gs_with_fw->fw_info.virt_addr); + if (gs_with_fw->fw_info.cma_pages) { + dma_release_from_contiguous( + &gdc_manager.gdc_dev->pdev->dev, + gs_with_fw->fw_info.cma_pages, + PAGE_ALIGN(gs_with_fw->gdc_config.config_size * 4) + >> PAGE_SHIFT); + + gs_with_fw->fw_info.cma_pages = NULL; + } +} + +static int load_firmware_by_name(struct gdc_settings_with_fw *gs_with_fw) +{ + int ret = -1; + const struct firmware *fw = NULL; + char *path = NULL; + struct fw_info_s *current_fw = &gs_with_fw->fw_info; + struct page *cma_pages = NULL; + void __iomem *virt_addr = NULL; + phys_addr_t phys_addr = 0; + + if (!current_fw->fw_name) { + gdc_log(LOG_ERR, "current firmware name is NULL, invalid\n"); + return -EINVAL; + } + + gdc_log(LOG_DEBUG, "Try to load %s ...\n", current_fw->fw_name); + + path = kzalloc(CONFIG_PATH_LENG, GFP_KERNEL); + if (!path) { + gdc_log(LOG_ERR, "cannot malloc fw_name!\n"); + return -ENOMEM; + } + snprintf(path, (CONFIG_PATH_LENG - 1), "%s/%s", + FIRMWARE_DIR, current_fw->fw_name); + + ret = request_firmware(&fw, path, &gdc_manager.gdc_dev->pdev->dev); + if (ret < 0) { + gdc_log(LOG_ERR, "Error : %d can't load the %s.\n", ret, path); + kfree(path); + return -ENOENT; + } + + if (fw->size <= 0) { + gdc_log(LOG_ERR, + "size error, wrong firmware or no enough mem.\n"); + ret = -ENOMEM; + goto release; + } + + cma_pages = dma_alloc_from_contiguous(&gdc_manager.gdc_dev->pdev->dev, + PAGE_ALIGN(fw->size) >> PAGE_SHIFT, 0); + if (cma_pages != NULL) { + phys_addr = page_to_phys(cma_pages); + virt_addr = map_virt_from_phys(phys_addr, + PAGE_ALIGN(fw->size)); + if (!virt_addr) { + gdc_log(LOG_ERR, "map_virt_from_phys failed\n"); + dma_release_from_contiguous( + &gdc_manager.gdc_dev->pdev->dev, + cma_pages, + PAGE_ALIGN(fw->size) >> PAGE_SHIFT); + ret = -ENOMEM; + goto release; + } + } else { + gdc_log(LOG_ERR, "Failed to alloc dma buff\n"); + ret = -ENOMEM; + goto release; + } + memcpy(virt_addr, (char *)fw->data, fw->size); + + gdc_log(LOG_DEBUG, + "current firmware virt_addr: 0x%p, fw->data: 0x%p.\n", + virt_addr, fw->data); + + gs_with_fw->gdc_config.config_addr = phys_addr; + gs_with_fw->gdc_config.config_size = fw->size / 4; + gs_with_fw->fw_info.cma_pages = cma_pages; + + gdc_log(LOG_DEBUG, "load firmware size : %zd, Name : %s.\n", + fw->size, path); + ret = fw->size; + +release: + release_firmware(fw); + kfree(path); + + return ret; +} + +static long gdc_process_with_fw(struct mgdc_fh_s *fh, + struct gdc_settings_with_fw *gs_with_fw) +{ + long ret = -1; + unsigned long addr = 0; + size_t len; + struct aml_dma_cfg *cfg = NULL; + struct gdc_cmd_s *gdc_cmd = &fh->gdc_cmd; + char *fw_name = NULL; + + if (fh == NULL || gs_with_fw == NULL) { + gdc_log(LOG_ERR, "Error input param\n"); + return -EINVAL; + } + + gs_with_fw->fw_info.virt_addr = NULL; + gs_with_fw->fw_info.cma_pages = NULL; + + memcpy(&(gdc_cmd->gdc_config), &(gs_with_fw->gdc_config), + sizeof(struct gdc_config_s)); + + fw_name = kzalloc(CONFIG_PATH_LENG, GFP_KERNEL); + if (!fw_name) { + gdc_log(LOG_ERR, "cannot malloc fw_name!\n"); + return -ENOMEM; + } + + gdc_cmd->fh = fh; + if (gs_with_fw->output_buffer.mem_alloc_type == AML_GDC_MEM_ION) { + /* ion alloc */ + ret = meson_ion_share_fd_to_phys(fh->ion_client, + gs_with_fw->output_buffer.shared_fd, + (ion_phys_addr_t *)&addr, &len); + if (ret < 0) { + gdc_log(LOG_ERR, "ion import out fd %d failed\n", + gs_with_fw->output_buffer.shared_fd); + ret = -EINVAL; + goto release_fw_name; + } + } else if (gs_with_fw->output_buffer.mem_alloc_type == + AML_GDC_MEM_DMABUF) { + /* dma alloc */ + cfg = &fh->dma_cfg.output_cfg; + cfg->fd = gs_with_fw->output_buffer.y_base_fd; + cfg->dev = &(gdc_manager.gdc_dev->pdev->dev); + cfg->dir = DMA_FROM_DEVICE; + ret = gdc_dma_buffer_get_phys(cfg, &addr); + if (ret < 0) { + gdc_log(LOG_ERR, "dma import out fd %d failed\n", + gs_with_fw->output_buffer.y_base_fd); + ret = -EINVAL; + goto release_fw_name; + } + } + gdc_log(LOG_INFO, "%s, output addr=%lx\n", __func__, addr); + gdc_cmd->base_gdc = 0; + gdc_cmd->buffer_addr = addr; + gdc_cmd->current_addr = gdc_cmd->buffer_addr; + + if (gs_with_fw->input_buffer.mem_alloc_type == AML_GDC_MEM_ION) { + /* ion alloc */ + ret = meson_ion_share_fd_to_phys(fh->ion_client, + gs_with_fw->input_buffer.shared_fd, + (ion_phys_addr_t *)&addr, &len); + if (ret < 0) { + gdc_log(LOG_ERR, "ion import input fd %d failed\n", + gs_with_fw->input_buffer.shared_fd); + ret = -EINVAL; + goto unmap; + } + ret = meson_gdc_set_input_addr(addr, gdc_cmd); + if (ret != 0) { + gdc_log(LOG_ERR, "set input addr failed\n"); + ret = -EINVAL; + goto unmap; + } + } else if (gs_with_fw->input_buffer.mem_alloc_type == + AML_GDC_MEM_DMABUF) { + /* dma alloc */ + gdc_process_input_dma_info(fh, + (struct gdc_settings_ex *)gs_with_fw); + } + gdc_log(LOG_INFO, "%s, input addr=%x\n", + __func__, fh->gdc_cmd.y_base_addr); + + /* load firmware */ + if (gs_with_fw->fw_info.fw_name != NULL) { + ret = load_firmware_by_name(gs_with_fw); + if (ret <= 0) { + gdc_log(LOG_ERR, "line %d,load FW %s failed\n", + __LINE__, gs_with_fw->fw_info.fw_name); + ret = -EINVAL; + goto release_fw; + } + } + + if (ret <= 0 || gs_with_fw->fw_info.fw_name == NULL) { + char in_info[64] = {}; + char out_info[64] = {}; + char *format = NULL; + struct fw_input_info_s *in = &gs_with_fw->fw_info.fw_input_info; + struct fw_output_info_s *out = + &gs_with_fw->fw_info.fw_output_info; + union transform_u *trans = + &gs_with_fw->fw_info.fw_output_info.trans; + + switch (gdc_cmd->gdc_config.format) { + case NV12: + format = "nv12"; + break; + case YV12: + format = "yv12"; + break; + case Y_GREY: + format = "ygrey"; + break; + case YUV444_P: + format = "yuv444p"; + break; + case RGB444_P: + format = "rgb444p"; + break; + default: + gdc_log(LOG_ERR, "unsupported gdc format\n"); + ret = -EINVAL; + goto release_fw; + } + snprintf(in_info, (64 - 1), "%d_%d_%d_%d_%d_%d", + in->with, in->height, + in->fov, in->diameter, + in->offsetX, in->offsetY); + + snprintf(out_info, (64 - 1), "%d_%d_%d_%d-%d_%d_%s", + out->offsetX, out->offsetY, + out->width, out->height, + out->pan, out->tilt, out->zoom); + + switch (gs_with_fw->fw_info.fw_type) { + case EQUISOLID: + snprintf(fw_name, (CONFIG_PATH_LENG - 1), + "equisolid-%s-%s-%s_%s_%d-%s.bin", + in_info, out_info, + trans->fw_equisolid.strengthX, + trans->fw_equisolid.strengthY, + trans->fw_equisolid.rotation, + format); + break; + case CYLINDER: + snprintf(fw_name, (CONFIG_PATH_LENG - 1), + "cylinder-%s-%s-%s_%d-%s.bin", + in_info, out_info, + trans->fw_cylinder.strength, + trans->fw_cylinder.rotation, + format); + break; + case EQUIDISTANT: + snprintf(fw_name, (CONFIG_PATH_LENG - 1), + "equidistant-%s-%s-%s_%d_%d_%d_%d_%d_%d_%d-%s.bin", + in_info, out_info, + trans->fw_equidistant.azimuth, + trans->fw_equidistant.elevation, + trans->fw_equidistant.rotation, + trans->fw_equidistant.fov_width, + trans->fw_equidistant.fov_height, + trans->fw_equidistant.keep_ratio, + trans->fw_equidistant.cylindricityX, + trans->fw_equidistant.cylindricityY, + format); + break; + case CUSTOM: + if (trans->fw_custom.fw_name != NULL) { + snprintf(fw_name, (CONFIG_PATH_LENG - 1), + "custom-%s-%s-%s-%s.bin", + in_info, out_info, + trans->fw_custom.fw_name, + format); + } else { + gdc_log(LOG_ERR, "custom fw_name is NULL\n"); + ret = -EINVAL; + goto release_fw; + } + break; + case AFFINE: + snprintf(fw_name, (CONFIG_PATH_LENG - 1), + "affine-%s-%s-%d-%s.bin", + in_info, out_info, + trans->fw_affine.rotation, + format); + break; + default: + gdc_log(LOG_ERR, "unsupported FW type\n"); + ret = -EINVAL; + goto release_fw; + } + + gs_with_fw->fw_info.fw_name = fw_name; + } + ret = load_firmware_by_name(gs_with_fw); + if (ret <= 0) { + gdc_log(LOG_ERR, "line %d,load FW %s failed\n", + __LINE__, gs_with_fw->fw_info.fw_name); + ret = -EINVAL; + goto release_fw; + } + + gdc_cmd->gdc_config.config_addr = + gs_with_fw->gdc_config.config_addr; + gdc_cmd->gdc_config.config_size = + gs_with_fw->gdc_config.config_size; + + mutex_lock(&fh->gdev->d_mutext); + ret = gdc_run(gdc_cmd); + if (ret < 0) + gdc_log(LOG_ERR, "gdc process failed ret = %ld\n", ret); + + ret = wait_for_completion_timeout(&fh->gdev->d_com, + msecs_to_jiffies(40)); + if (ret == 0) + gdc_log(LOG_ERR, "gdc timeout\n"); + + gdc_stop(gdc_cmd); + mutex_unlock(&fh->gdev->d_mutext); + +release_fw: + release_config_firmware(gs_with_fw); + +unmap: + if (gs_with_fw->input_buffer.mem_alloc_type == AML_GDC_MEM_DMABUF) { + gdc_dma_buffer_unmap(&fh->dma_cfg.input_cfg_plane1); + if (gs_with_fw->input_buffer.plane_number == 2) + gdc_dma_buffer_unmap(&fh->dma_cfg.input_cfg_plane2); + } + + if (gs_with_fw->output_buffer.mem_alloc_type == AML_GDC_MEM_DMABUF) + gdc_dma_buffer_unmap(&fh->dma_cfg.output_cfg); + +release_fw_name: + kfree(fw_name); + + return ret; +} +EXPORT_SYMBOL(gdc_process_with_fw); +int write_buf_to_file(char *path, char *buf, int size) +{ + int ret = 0; + struct file *fp = NULL; + mm_segment_t old_fs; + loff_t pos = 0; + int w_size = 0; + + if (!path || !config_out_path_defined) { + gdc_log(LOG_ERR, "please define path first\n"); + return -1; + } + + /* change to KERNEL_DS address limit */ + old_fs = get_fs(); + set_fs(KERNEL_DS); + + /* open file to write */ + fp = filp_open(path, O_WRONLY|O_CREAT, 0640); + if (IS_ERR(fp)) { + gdc_log(LOG_ERR, "open file error\n"); + ret = -1; + } + + /* Write buf to file */ + w_size = vfs_write(fp, buf, size, &pos); + gdc_log(LOG_INFO, "write w_size = %u, size = %u\n", w_size, size); + + vfs_fsync(fp, 0); + filp_close(fp, NULL); + set_fs(old_fs); + + return w_size; +} + static long meson_gdc_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { - long ret = 0; + long ret = -1; size_t len; struct mgdc_fh_s *fh = file->private_data; - struct gdc_settings *gs = &fh->gs; - struct gdc_config *gc = &gs->gdc_config; + struct gdc_settings gs; + struct gdc_cmd_s *gdc_cmd = &fh->gdc_cmd; + struct gdc_config_s *gc = &gdc_cmd->gdc_config; struct gdc_buf_cfg buf_cfg; struct page *cma_pages = NULL; + struct gdc_settings_ex gs_ex; + struct gdc_settings_with_fw gs_with_fw; + struct gdc_dmabuf_req_s gdc_req_buf; + struct gdc_dmabuf_exp_s gdc_exp_buf; ion_phys_addr_t addr; + int index, dma_fd; void __user *argp = (void __user *)arg; + void __iomem *config_virt_addr; + ktime_t start_time, stop_time, diff_time; + int process_time = 0; + int i = 0; + start_time.tv64 = 0; switch (cmd) { case GDC_PROCESS: - ret = copy_from_user(gs, argp, sizeof(*gs)); + ret = copy_from_user(&gs, argp, sizeof(gs)); if (ret < 0) { - LOG(LOG_ERR, "copy from user failed\n"); + gdc_log(LOG_ERR, "copy from user failed\n"); return -EINVAL; } - LOG(LOG_DEBUG, "sizeof(gs)=%zu, magic=%d\n", - sizeof(*gs), gs->magic); + gdc_log(LOG_DEBUG, "sizeof(gs)=%zu, magic=%d\n", + sizeof(gs), gs.magic); //configure gdc config, buffer address and resolution ret = meson_ion_share_fd_to_phys(fh->ion_client, - gs->out_fd, &addr, &len); + gs.out_fd, &addr, &len); if (ret < 0) { - LOG(LOG_ERR, "import out fd %d failed\n", gs->out_fd); + gdc_log(LOG_ERR, + "import out fd %d failed\n", gs.out_fd); return -EINVAL; } + memcpy(&gdc_cmd->gdc_config, &gs.gdc_config, + sizeof(struct gdc_config_s)); + gdc_cmd->buffer_addr = addr; + gdc_cmd->buffer_size = len; - gs->buffer_addr = addr; - gs->buffer_size = len; - - gs->base_gdc = 0; - gs->current_addr = gs->buffer_addr; + gdc_cmd->base_gdc = 0; + gdc_cmd->current_addr = gdc_cmd->buffer_addr; ret = meson_ion_share_fd_to_phys(fh->ion_client, gc->config_addr, &addr, &len); if (ret < 0) { - LOG(LOG_ERR, "import config fd failed\n"); + gdc_log(LOG_ERR, "import config fd failed\n"); return -EINVAL; } gc->config_addr = addr; ret = meson_ion_share_fd_to_phys(fh->ion_client, - gs->in_fd, &addr, &len); + gs.in_fd, &addr, &len); if (ret < 0) { - LOG(LOG_ERR, "import in fd %d failed\n", gs->in_fd); + gdc_log(LOG_ERR, "import in fd %d failed\n", gs.in_fd); return -EINVAL; } - ret = meson_gdc_set_input_addr(addr, gs); + ret = meson_gdc_set_input_addr(addr, gdc_cmd); if (ret != 0) { - LOG(LOG_ERR, "set input addr failed\n"); + gdc_log(LOG_ERR, "set input addr failed\n"); return -EINVAL; } - gs->fh = fh; - + gdc_cmd->fh = fh; mutex_lock(&fh->gdev->d_mutext); - ret = gdc_run(gs); + + if (trace_mode_enable >= 1) + start_time = ktime_get(); + + ret = gdc_run(gdc_cmd); if (ret < 0) - LOG(LOG_ERR, "gdc process ret = %ld\n", ret); + gdc_log(LOG_ERR, "gdc process ret = %ld\n", ret); ret = wait_for_completion_timeout(&fh->gdev->d_com, - msecs_to_jiffies(40)); + msecs_to_jiffies(WAIT_THRESHOLD)); if (ret == 0) - LOG(LOG_ERR, "gdc timeout\n"); + gdc_log(LOG_ERR, "gdc timeout\n"); - gdc_stop(gs); + if (ret == 0) { + gdc_log(LOG_ERR, "gdc timeout, status = 0x%x\n", + gdc_status_read()); + + if (trace_mode_enable >= 2) { + /* dump regs */ + for (i = 0; i <= 0xFF; i += 4) + gdc_log(LOG_ERR, "reg[0x%x] = 0x%x\n", + i, system_gdc_read_32(i)); + + /* dump config buffer */ + config_virt_addr = + map_virt_from_phys(gc->config_addr, + PAGE_ALIGN(gc->config_size * 4)); + ret = write_buf_to_file(config_out_file, + config_virt_addr, + (gc->config_size * 4)); + if (ret <= 0) + gdc_log(LOG_ERR, + "Failed to read_file_to_buf\n"); + unmap_virt_from_phys(config_virt_addr); + } + } + + gdc_stop(gdc_cmd); + + if (trace_mode_enable >= 1) { + stop_time = ktime_get(); + diff_time = ktime_sub(stop_time, start_time); + process_time = ktime_to_ms(diff_time); + if (process_time > 50) + gdc_log(LOG_ERR, "gdc process time = %d\n", + process_time); + } mutex_unlock(&fh->gdev->d_mutext); break; case GDC_RUN: - ret = copy_from_user(gs, argp, sizeof(*gs)); + ret = copy_from_user(&gs, argp, sizeof(gs)); if (ret < 0) - LOG(LOG_ERR, "copy from user failed\n"); + gdc_log(LOG_ERR, "copy from user failed\n"); - gs->buffer_addr = fh->o_paddr; - gs->buffer_size = fh->o_len; + memcpy(&gdc_cmd->gdc_config, &gs.gdc_config, + sizeof(struct gdc_config_s)); + gdc_cmd->buffer_addr = fh->o_paddr; + gdc_cmd->buffer_size = fh->o_len; - gs->base_gdc = 0; - gs->current_addr = gs->buffer_addr; + gdc_cmd->base_gdc = 0; + gdc_cmd->current_addr = gdc_cmd->buffer_addr; gc->config_addr = fh->c_paddr; - ret = meson_gdc_set_input_addr(fh->i_paddr, gs); + ret = meson_gdc_set_input_addr(fh->i_paddr, gdc_cmd); if (ret != 0) { - LOG(LOG_ERR, "set input addr failed\n"); + gdc_log(LOG_ERR, "set input addr failed\n"); return -EINVAL; } - gs->fh = fh; - + gdc_cmd->fh = fh; mutex_lock(&fh->gdev->d_mutext); meson_gdc_dma_flush(&fh->gdev->pdev->dev, fh->i_paddr, fh->i_len); meson_gdc_dma_flush(&fh->gdev->pdev->dev, fh->c_paddr, fh->c_len); - ret = gdc_run(gs); + + if (trace_mode_enable >= 1) + start_time = ktime_get(); + + ret = gdc_run(gdc_cmd); if (ret < 0) - LOG(LOG_ERR, "gdc process failed ret = %ld\n", ret); + gdc_log(LOG_ERR, "gdc process failed ret = %ld\n", ret); ret = wait_for_completion_timeout(&fh->gdev->d_com, - msecs_to_jiffies(40)); + msecs_to_jiffies(WAIT_THRESHOLD)); if (ret == 0) - LOG(LOG_ERR, "gdc timeout\n"); + gdc_log(LOG_ERR, "gdc timeout\n"); - gdc_stop(gs); + if (ret == 0) { + gdc_log(LOG_ERR, "gdc timeout, status = 0x%x\n", + gdc_status_read()); + + if (trace_mode_enable >= 2) { + /* dump regs */ + for (i = 0; i <= 0xFF; i += 4) + gdc_log(LOG_ERR, "reg[0x%x] = 0x%x\n", + i, system_gdc_read_32(i)); + + /* dump config buffer */ + config_virt_addr = + map_virt_from_phys(gc->config_addr, + PAGE_ALIGN(gc->config_size * 4)); + ret = write_buf_to_file(config_out_file, + config_virt_addr, + (gc->config_size * 4)); + if (ret <= 0) + gdc_log(LOG_ERR, + "Failed to read_file_to_buf\n"); + unmap_virt_from_phys(config_virt_addr); + } + } + + gdc_stop(gdc_cmd); + if (trace_mode_enable >= 1) { + stop_time = ktime_get(); + diff_time = ktime_sub(stop_time, start_time); + process_time = ktime_to_ms(diff_time); + if (process_time > 50) + gdc_log(LOG_ERR, "gdc process time = %d\n", + process_time); + } meson_gdc_cache_flush(&fh->gdev->pdev->dev, fh->o_paddr, fh->o_len); mutex_unlock(&fh->gdev->d_mutext); break; case GDC_HANDLE: - ret = copy_from_user(gs, argp, sizeof(*gs)); + ret = copy_from_user(&gs, argp, sizeof(gs)); if (ret < 0) - LOG(LOG_ERR, "copy from user failed\n"); + gdc_log(LOG_ERR, "copy from user failed\n"); - gs->buffer_addr = fh->o_paddr; - gs->buffer_size = fh->o_len; + memcpy(&gdc_cmd->gdc_config, &gs.gdc_config, + sizeof(struct gdc_config_s)); + gdc_cmd->buffer_addr = fh->o_paddr; + gdc_cmd->buffer_size = fh->o_len; - gs->base_gdc = 0; - gs->current_addr = gs->buffer_addr; + gdc_cmd->base_gdc = 0; + gdc_cmd->current_addr = gdc_cmd->buffer_addr; gc->config_addr = fh->c_paddr; - gs->fh = fh; - + gdc_cmd->fh = fh; mutex_lock(&fh->gdev->d_mutext); - ret = meson_gdc_init_dma_addr(gs); + ret = meson_gdc_init_dma_addr(fh, &gs); if (ret != 0) { mutex_unlock(&fh->gdev->d_mutext); - LOG(LOG_ERR, "Failed to init dma addr"); + gdc_log(LOG_ERR, "Failed to init dma addr"); return ret; } meson_gdc_dma_flush(&fh->gdev->pdev->dev, fh->c_paddr, fh->c_len); - ret = gdc_run(gs); + + + if (trace_mode_enable >= 1) + start_time = ktime_get(); + + ret = gdc_run(gdc_cmd); if (ret < 0) - LOG(LOG_ERR, "gdc process failed ret = %ld\n", ret); + gdc_log(LOG_ERR, "gdc process failed ret = %ld\n", ret); ret = wait_for_completion_timeout(&fh->gdev->d_com, - msecs_to_jiffies(40)); + msecs_to_jiffies(WAIT_THRESHOLD)); if (ret == 0) - LOG(LOG_ERR, "gdc timeout\n"); + gdc_log(LOG_ERR, "gdc timeout\n"); - gdc_stop(gs); + if (ret == 0) { + gdc_log(LOG_ERR, "gdc timeout, status = 0x%x\n", + gdc_status_read()); + + if (trace_mode_enable >= 2) { + /* dump regs */ + for (i = 0; i <= 0xFF; i += 4) + gdc_log(LOG_ERR, "reg[0x%x] = 0x%x\n", + i, system_gdc_read_32(i)); + + /* dump config buffer */ + config_virt_addr = + map_virt_from_phys(gc->config_addr, + PAGE_ALIGN(gc->config_size * 4)); + ret = write_buf_to_file(config_out_file, + config_virt_addr, + (gc->config_size * 4)); + if (ret <= 0) + gdc_log(LOG_ERR, + "Failed to read_file_to_buf\n"); + unmap_virt_from_phys(config_virt_addr); + } + } + + gdc_stop(gdc_cmd); + + if (trace_mode_enable >= 1) { + stop_time = ktime_get(); + diff_time = ktime_sub(stop_time, start_time); + process_time = ktime_to_ms(diff_time); + if (process_time > 50) + gdc_log(LOG_ERR, "gdc process time = %d\n", + process_time); + } meson_gdc_cache_flush(&fh->gdev->pdev->dev, fh->o_paddr, fh->o_len); - meson_gdc_deinit_dma_addr(gs); + meson_gdc_deinit_dma_addr(fh); mutex_unlock(&fh->gdev->d_mutext); break; case GDC_REQUEST_BUFF: ret = copy_from_user(&buf_cfg, argp, sizeof(buf_cfg)); if (ret < 0 || buf_cfg.type >= GDC_BUFF_TYPE_MAX) { - LOG(LOG_ERR, "Error user param\n"); + gdc_log(LOG_ERR, "Error user param\n"); return ret; } @@ -656,17 +1467,85 @@ static long meson_gdc_ioctl(struct file *file, unsigned int cmd, &fh->gdev->pdev->dev, cma_pages, buf_cfg.len >> PAGE_SHIFT); - LOG(LOG_ERR, "Failed to set buff\n"); + gdc_log(LOG_ERR, "Failed to set buff\n"); return ret; } } else { - LOG(LOG_ERR, "Failed to alloc dma buff\n"); + gdc_log(LOG_ERR, "Failed to alloc dma buff\n"); return -ENOMEM; } break; + case GDC_PROCESS_WITH_FW: + ret = copy_from_user(&gs_with_fw, argp, sizeof(gs_with_fw)); + if (ret < 0) + gdc_log(LOG_ERR, "copy from user failed\n"); + memcpy(&gdc_cmd->gdc_config, &gs_with_fw.gdc_config, + sizeof(struct gdc_config_s)); + ret = gdc_process_with_fw(fh, &gs_with_fw); + break; + case GDC_PROCESS_EX: + ret = copy_from_user(&gs_ex, argp, sizeof(gs_ex)); + if (ret < 0) + gdc_log(LOG_ERR, "copy from user failed\n"); + memcpy(&gdc_cmd->gdc_config, &gs_ex.gdc_config, + sizeof(struct gdc_config_s)); + ret = gdc_process_ex_info(fh, &gs_ex); + break; + case GDC_REQUEST_DMA_BUFF: + ret = copy_from_user(&gdc_req_buf, argp, + sizeof(struct gdc_dmabuf_req_s)); + if (ret < 0) { + pr_err("Error user param\n"); + return -EINVAL; + } + ret = gdc_buffer_alloc(&gdc_req_buf); + if (ret == 0) + ret = copy_to_user(argp, &gdc_req_buf, + sizeof(struct gdc_dmabuf_req_s)); + break; + case GDC_EXP_DMA_BUFF: + ret = copy_from_user(&gdc_exp_buf, argp, + sizeof(struct gdc_dmabuf_exp_s)); + if (ret < 0) { + pr_err("Error user param\n"); + return -EINVAL; + } + ret = gdc_buffer_export(&gdc_exp_buf); + if (ret == 0) + ret = copy_to_user(argp, &gdc_exp_buf, + sizeof(struct gdc_dmabuf_exp_s)); + break; + case GDC_FREE_DMA_BUFF: + ret = copy_from_user(&index, argp, + sizeof(int)); + if (ret < 0) { + pr_err("Error user param\n"); + return -EINVAL; + } + ret = gdc_buffer_free(index); + break; + case GDC_SYNC_DEVICE: + ret = copy_from_user(&dma_fd, argp, + sizeof(int)); + if (ret < 0) { + pr_err("Error user param\n"); + return -EINVAL; + } + gdc_buffer_dma_flush(dma_fd); + break; + case GDC_SYNC_CPU: + ret = copy_from_user(&dma_fd, argp, + sizeof(int)); + if (ret < 0) { + pr_err("Error user param\n"); + return -EINVAL; + } + gdc_buffer_cache_flush(dma_fd); + break; default: - LOG(LOG_ERR, "unsupported cmd 0x%x\n", cmd); + gdc_log(LOG_ERR, "unsupported cmd 0x%x\n", cmd); + return -EINVAL; break; } @@ -685,28 +1564,28 @@ static int meson_gdc_mmap(struct file *file_p, switch (fh->mmap_type) { case INPUT_BUFF_TYPE: ret = remap_pfn_range(vma, vma->vm_start, - fh->i_paddr >> PAGE_SHIFT, - buf_len, vma->vm_page_prot); - if (ret != 0) - LOG(LOG_ERR, "Failed to mmap input buffer\n"); + fh->i_paddr >> PAGE_SHIFT, + buf_len, vma->vm_page_prot); + if (ret != 0) + gdc_log(LOG_ERR, "Failed to mmap input buffer\n"); break; case OUTPUT_BUFF_TYPE: - ret = remap_pfn_range(vma, vma->vm_start, - fh->o_paddr >> PAGE_SHIFT, - buf_len, vma->vm_page_prot); - if (ret != 0) - LOG(LOG_ERR, "Failed to mmap input buffer\n"); + ret = remap_pfn_range(vma, vma->vm_start, + fh->o_paddr >> PAGE_SHIFT, + buf_len, vma->vm_page_prot); + if (ret != 0) + gdc_log(LOG_ERR, "Failed to mmap input buffer\n"); break; case CONFIG_BUFF_TYPE: - ret = remap_pfn_range(vma, vma->vm_start, - fh->c_paddr >> PAGE_SHIFT, - buf_len, vma->vm_page_prot); - if (ret != 0) - LOG(LOG_ERR, "Failed to mmap input buffer\n"); + ret = remap_pfn_range(vma, vma->vm_start, + fh->c_paddr >> PAGE_SHIFT, + buf_len, vma->vm_page_prot); + if (ret != 0) + gdc_log(LOG_ERR, "Failed to mmap input buffer\n"); break; default: - LOG(LOG_ERR, "Error mmap type:0x%x\n", fh->mmap_type); + gdc_log(LOG_ERR, "Error mmap type:0x%x\n", fh->mmap_type); break; } @@ -746,7 +1625,7 @@ static ssize_t gdc_reg_show(struct device *dev, static ssize_t gdc_reg_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) { - LOG(LOG_DEBUG, "%s, %d\n", __func__, __LINE__); + gdc_log(LOG_DEBUG, "%s, %d\n", __func__, __LINE__); return len; } static DEVICE_ATTR(gdc_reg, 0554, gdc_reg_show, gdc_reg_store); @@ -754,19 +1633,97 @@ static DEVICE_ATTR(gdc_reg, 0554, gdc_reg_show, gdc_reg_store); static ssize_t firmware1_show(struct device *dev, struct device_attribute *attr, char *buf) { - LOG(LOG_DEBUG, "%s, %d\n", __func__, __LINE__); + gdc_log(LOG_DEBUG, "%s, %d\n", __func__, __LINE__); return 1; } static ssize_t firmware1_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) { - LOG(LOG_DEBUG, "%s, %d\n", __func__, __LINE__); + gdc_log(LOG_DEBUG, "%s, %d\n", __func__, __LINE__); //gdc_fw_init(); return 1; } static DEVICE_ATTR(firmware1, 0664, firmware1_show, firmware1_store); +static ssize_t loglevel_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + ssize_t len = 0; + + len += sprintf(buf+len, "%d\n", gdc_log_level); + return len; +} + +static ssize_t loglevel_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t len) +{ + int res = 0; + int ret = 0; + + ret = kstrtoint(buf, 0, &res); + pr_info("log_level: %d->%d\n", gdc_log_level, res); + gdc_log_level = res; + + return len; +} + +static DEVICE_ATTR(loglevel, 0664, loglevel_show, loglevel_store); + +static ssize_t trace_mode_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + ssize_t len = 0; + + len += sprintf(buf+len, "trace_mode_enable: %d\n", + trace_mode_enable); + return len; +} + +static ssize_t trace_mode_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t len) +{ + int res = 0; + int ret = 0; + + ret = kstrtoint(buf, 0, &res); + pr_info("trace_mode: %d->%d\n", trace_mode_enable, res); + trace_mode_enable = res; + + return len; +} +static DEVICE_ATTR(trace_mode, 0664, trace_mode_show, trace_mode_store); + +static ssize_t config_out_path_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + ssize_t len = 0; + + if (config_out_path_defined) + len += sprintf(buf+len, "config out path: %s\n", + config_out_file); + else + len += sprintf(buf+len, "config out path is not set\n"); + + return len; +} + +static ssize_t config_out_path_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t len) +{ + if (strlen(buf) >= sizeof(config_out_file)) { + pr_info("err: path too long\n"); + } else { + strncpy(config_out_file, buf, CONFIG_PATH_LENG - 1); + config_out_path_defined = 1; + pr_info("set config out path: %s\n", config_out_file); + } + + return len; +} +static DEVICE_ATTR(config_out_path, 0664, config_out_path_show, + config_out_path_store); + irqreturn_t gdc_interrupt_handler(int irq, void *param) { struct meson_gdc_dev_t *gdc_dev = param; @@ -789,34 +1746,41 @@ static int gdc_platform_probe(struct platform_device *pdev) gdc_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!gdc_res) { - LOG(LOG_ERR, "Error, no IORESOURCE_MEM DT!\n"); + gdc_log(LOG_ERR, "Error, no IORESOURCE_MEM DT!\n"); return -ENOMEM; } if (init_gdc_io(pdev->dev.of_node) != 0) { - LOG(LOG_ERR, "Error on mapping gdc memory!\n"); + gdc_log(LOG_ERR, "Error on mapping gdc memory!\n"); return -ENOMEM; } of_reserved_mem_device_init(&(pdev->dev)); - device_create_file(&pdev->dev, &dev_attr_gdc_reg); - device_create_file(&pdev->dev, &dev_attr_firmware1); + /* alloc mem to store config out path*/ + config_out_file = kzalloc(CONFIG_PATH_LENG, GFP_KERNEL); + if (config_out_file == NULL) { + gdc_log(LOG_ERR, "config out alloc failed\n"); + return -ENOMEM; + } gdc_dev = devm_kzalloc(&pdev->dev, sizeof(*gdc_dev), GFP_KERNEL); if (gdc_dev == NULL) { - LOG(LOG_DEBUG, "devm alloc gdc dev failed\n"); + gdc_log(LOG_DEBUG, "devm alloc gdc dev failed\n"); return -ENOMEM; } gdc_dev->pdev = pdev; + gdc_dev->misc_dev.minor = meson_gdc_dev.minor; + gdc_dev->misc_dev.name = meson_gdc_dev.name; + gdc_dev->misc_dev.fops = meson_gdc_dev.fops; spin_lock_init(&gdc_dev->slock); gdc_dev->irq = platform_get_irq(pdev, 0); if (gdc_dev->irq < 0) { - LOG(LOG_DEBUG, "cannot find irq for gdc\n"); + gdc_log(LOG_DEBUG, "cannot find irq for gdc\n"); return -EINVAL; } @@ -831,9 +1795,9 @@ static int gdc_platform_probe(struct platform_device *pdev) iowrite32((3<<25)|(1<<24)|(0<<16)|(3<<9)|(1<<8)|(0<<0), clk_cntl); pd_cntl = of_iomap(pdev->dev.of_node, 2); reg_value = ioread32(pd_cntl); - LOG(LOG_DEBUG, "pd_cntl=%x\n", reg_value); + gdc_log(LOG_DEBUG, "pd_cntl=%x\n", reg_value); reg_value = reg_value & (~(3<<18)); - LOG(LOG_DEBUG, "pd_cntl=%x\n", reg_value); + gdc_log(LOG_DEBUG, "pd_cntl=%x\n", reg_value); iowrite32(reg_value, pd_cntl); #endif @@ -844,18 +1808,50 @@ static int gdc_platform_probe(struct platform_device *pdev) gdc_interrupt_handler, IRQF_SHARED, "gdc", gdc_dev); if (rc != 0) - LOG(LOG_ERR, "cannot create irq func gdc\n"); + gdc_log(LOG_ERR, "cannot create irq func gdc\n"); - g_gdc_dev = gdc_dev; + gdc_manager.buffer = gdc_dma_buffer_create(); + gdc_manager.gdc_dev = gdc_dev; + rc = misc_register(&gdc_dev->misc_dev); + if (rc < 0) { + dev_err(&pdev->dev, + "misc_register() for minor %d failed\n", + gdc_dev->misc_dev.minor); + } + device_create_file(gdc_dev->misc_dev.this_device, + &dev_attr_gdc_reg); + device_create_file(gdc_dev->misc_dev.this_device, + &dev_attr_firmware1); + device_create_file(gdc_dev->misc_dev.this_device, + &dev_attr_loglevel); + device_create_file(gdc_dev->misc_dev.this_device, + &dev_attr_trace_mode); + device_create_file(gdc_dev->misc_dev.this_device, + &dev_attr_config_out_path); - return misc_register(&meson_gdc_dev); + platform_set_drvdata(pdev, gdc_dev); + return rc; } static int gdc_platform_remove(struct platform_device *pdev) { - device_remove_file(&pdev->dev, &dev_attr_gdc_reg); - device_remove_file(&pdev->dev, &dev_attr_firmware1); + device_remove_file(meson_gdc_dev.this_device, + &dev_attr_gdc_reg); + device_remove_file(meson_gdc_dev.this_device, + &dev_attr_firmware1); + device_remove_file(meson_gdc_dev.this_device, + &dev_attr_loglevel); + device_remove_file(meson_gdc_dev.this_device, + &dev_attr_trace_mode); + device_remove_file(meson_gdc_dev.this_device, + &dev_attr_config_out_path); + + gdc_dma_buffer_destroy(gdc_manager.buffer); + gdc_manager.gdc_dev = NULL; + + kfree(config_out_file); + config_out_file = NULL; misc_deregister(&meson_gdc_dev); return 0; diff --git a/drivers/amlogic/media/gdc/inc/api/gdc_api.h b/drivers/amlogic/media/gdc/inc/api/gdc_api.h index 2f3fb8feec64..bc46e966c941 100644 --- a/drivers/amlogic/media/gdc/inc/api/gdc_api.h +++ b/drivers/amlogic/media/gdc/inc/api/gdc_api.h @@ -21,13 +21,19 @@ #include #include +enum gdc_memtype_s { + AML_GDC_MEM_ION, + AML_GDC_MEM_DMABUF, + AML_GDC_MEM_INVALID, +}; + struct gdc_buf_cfg { uint32_t type; unsigned long len; }; // each configuration addresses and size -struct gdc_config { +struct gdc_config_s { uint32_t format; uint32_t config_addr; //gdc config address uint32_t config_size; //gdc config size in 32bit @@ -41,13 +47,27 @@ struct gdc_config { uint32_t output_c_stride; //gdc output uv stride }; +struct gdc_buffer_info { + unsigned int mem_alloc_type; + unsigned int plane_number; + union { + unsigned int y_base_fd; + unsigned int shared_fd; + }; + union { + unsigned int uv_base_fd; + unsigned int u_base_fd; + }; + unsigned int v_base_fd; +}; + // overall gdc settings and state struct gdc_settings { uint32_t magic; //writing/reading to gdc base address, currently not read by api uint32_t base_gdc; //array of gdc configuration and sizes - struct gdc_config gdc_config; + struct gdc_config_s gdc_config; //update this index for new config //int gdc_config_total; //start memory to write gdc output framse @@ -88,6 +108,28 @@ struct gdc_settings { int32_t v_base_fd; }; +struct gdc_settings_ex { + uint32_t magic; + struct gdc_config_s gdc_config; + struct gdc_buffer_info input_buffer; + struct gdc_buffer_info config_buffer; + struct gdc_buffer_info output_buffer; +}; + +/* for gdc dma buf define */ +struct gdc_dmabuf_req_s { + int index; + unsigned int len; + unsigned int dma_dir; +}; + +struct gdc_dmabuf_exp_s { + int index; + unsigned int flags; + int fd; +}; +/* end of gdc dma buffer define */ + #define GDC_IOC_MAGIC 'G' #define GDC_PROCESS _IOW(GDC_IOC_MAGIC, 0x00, struct gdc_settings) #define GDC_PROCESS_NO_BLOCK _IOW(GDC_IOC_MAGIC, 0x01, struct gdc_settings) @@ -95,6 +137,15 @@ struct gdc_settings { #define GDC_REQUEST_BUFF _IOW(GDC_IOC_MAGIC, 0x03, struct gdc_settings) #define GDC_HANDLE _IOW(GDC_IOC_MAGIC, 0x04, struct gdc_settings) +#define GDC_PROCESS_EX _IOW(GDC_IOC_MAGIC, 0x05, struct gdc_settings_ex) +#define GDC_REQUEST_DMA_BUFF _IOW(GDC_IOC_MAGIC, 0x06, struct gdc_dmabuf_req_s) +#define GDC_EXP_DMA_BUFF _IOW(GDC_IOC_MAGIC, 0x07, struct gdc_dmabuf_exp_s) +#define GDC_FREE_DMA_BUFF _IOW(GDC_IOC_MAGIC, 0x08, int) +#define GDC_SYNC_DEVICE _IOW(GDC_IOC_MAGIC, 0x09, int) +#define GDC_SYNC_CPU _IOW(GDC_IOC_MAGIC, 0x0a, int) +#define GDC_PROCESS_WITH_FW _IOW(GDC_IOC_MAGIC, 0x0b, \ + struct gdc_settings_with_fw) + enum { INPUT_BUFF_TYPE = 0x1000, OUTPUT_BUFF_TYPE, @@ -111,6 +162,15 @@ enum { FMT_MAX }; +enum { + EQUISOLID = 1, + CYLINDER, + EQUIDISTANT, + CUSTOM, + AFFINE, + FW_TYPE_MAX +}; + struct gdc_dma_cfg { int fd; void *dev; @@ -121,6 +181,136 @@ struct gdc_dma_cfg { enum dma_data_direction dir; }; +struct gdc_cmd_s { + //writing/reading to gdc base address, currently not read by api + uint32_t base_gdc; + //array of gdc configuration and sizes + struct gdc_config_s gdc_config; + //update this index for new config + //int gdc_config_total; + //start memory to write gdc output framse + uint32_t buffer_addr; + //size of memory output frames to determine + //if it is enough and can do multiple write points + uint32_t buffer_size; + //current output address of gdc + uint32_t current_addr; + //set when expecting an interrupt from gdc + int32_t is_waiting_gdc; + + //input address for y and u, v planes + uint32_t y_base_addr; + union { + uint32_t uv_base_addr; + uint32_t u_base_addr; + }; + uint32_t v_base_addr; + + //when inititialised this callback will be called + //to update frame buffer addresses and offsets + void (*get_frame_buffer)(uint32_t y_base_addr, + uint32_t uv_base_addr, + uint32_t y_line_offset, + uint32_t uv_line_offset); + void *fh; +}; + +/* path: "/vendor/lib/firmware/gdc/" */ +#define FIRMWARE_DIR "gdc" + +struct fw_equisolid_s { + /* float */ + char strengthX[8]; + /* float */ + char strengthY[8]; + int rotation; +}; + +struct fw_cylinder_s { + /* float */ + char strength[8]; + int rotation; +}; + +struct fw_equidistant_s { + /* float */ + char azimuth[8]; + int elevation; + int rotation; + int fov_width; + int fov_height; + bool keep_ratio; + int cylindricityX; + int cylindricityY; +}; + +struct fw_custom_s { + char *fw_name; +}; + + +struct fw_affine_s { + int rotation; +}; + +struct fw_input_info_s { + int with; + int height; + int fov; + int diameter; + int offsetX; + int offsetY; +}; + +union transform_u { + struct fw_equisolid_s fw_equisolid; + struct fw_cylinder_s fw_cylinder; + struct fw_equidistant_s fw_equidistant; + struct fw_custom_s fw_custom; + struct fw_affine_s fw_affine; +}; + +struct fw_output_info_s { + int offsetX; + int offsetY; + int width; + int height; + union transform_u trans; + int pan; + int tilt; + /* float*/ + char zoom[8]; +}; + +struct firmware_info { + unsigned int format; + unsigned int trans_size_type; + char *file_name; + phys_addr_t phys_addr; + void __iomem *virt_addr; + unsigned int size; + struct page *cma_pages; + unsigned int loaded; +}; + +struct fw_info_s { + char *fw_name; + int fw_type; + struct page *cma_pages; + phys_addr_t phys_addr; + void __iomem *virt_addr; + struct fw_input_info_s fw_input_info; + struct fw_output_info_s fw_output_info; +}; + +struct gdc_settings_with_fw { + uint32_t magic; + struct gdc_config_s gdc_config; + struct gdc_buffer_info input_buffer; + struct gdc_buffer_info output_buffer; + struct fw_info_s fw_info; +}; + /** * Configure the output gdc configuration * @@ -128,30 +318,30 @@ struct gdc_dma_cfg { * * More than one gdc settings can be accessed by index to a gdc_config_t. * - * @param gdc_settings - overall gdc settings and state + * @param gdc_cmd_s - overall gdc settings and state * @param gdc_config_num - selects the current gdc config to be applied * * @return 0 - success * -1 - fail. */ -int gdc_init(struct gdc_settings *gdc_settings); +int gdc_init(struct gdc_cmd_s *gdc_cmd); /** * This function stops the gdc block * - * @param gdc_settings - overall gdc settings and state + * @param gdc_cmd_s - overall gdc settings and state * */ -void gdc_stop(struct gdc_settings *gdc_settings); +void gdc_stop(struct gdc_cmd_s *gdc_cmd); /** * This function starts the gdc block * * Writing 0->1 transition is necessary for trigger * - * @param gdc_settings - overall gdc settings and state + * @param gdc_cmd_s - overall gdc settings and state * */ -void gdc_start(struct gdc_settings *gdc_settings); +void gdc_start(struct gdc_cmd_s *gdc_cmd); /** * This function points gdc to @@ -160,7 +350,7 @@ void gdc_start(struct gdc_settings *gdc_settings); * * Shown inputs to GDC are Y and UV plane address and offsets * - * @param gdc_settings - overall gdc settings and state + * @param gdc_cmd_s - overall gdc settings and state * @param active_width - input width resolution * @param active_height - input height resolution * @param y_base_addr - input Y base address @@ -171,20 +361,20 @@ void gdc_start(struct gdc_settings *gdc_settings); * @return 0 - success * -1 - no interrupt from GDC. */ -int gdc_process(struct gdc_settings *gdc_settings, +int gdc_process(struct gdc_cmd_s *gdc_cmd, uint32_t y_base_addr, uint32_t uv_base_addr); -int gdc_process_yuv420p(struct gdc_settings *gdc_settings, +int gdc_process_yuv420p(struct gdc_cmd_s *gdc_cmd, uint32_t y_base_addr, uint32_t u_base_addr, uint32_t v_base_addr); -int gdc_process_y_grey(struct gdc_settings *gdc_settings, +int gdc_process_y_grey(struct gdc_cmd_s *gdc_cmd, uint32_t y_base_addr); -int gdc_process_yuv444p(struct gdc_settings *gdc_settings, +int gdc_process_yuv444p(struct gdc_cmd_s *gdc_cmd, uint32_t y_base_addr, uint32_t u_base_addr, uint32_t v_base_addr); -int gdc_process_rgb444p(struct gdc_settings *gdc_settings, +int gdc_process_rgb444p(struct gdc_cmd_s *gdc_cmd, uint32_t y_base_addr, uint32_t u_base_addr, uint32_t v_base_addr); @@ -198,12 +388,12 @@ int gdc_process_rgb444p(struct gdc_settings *gdc_settings, * * Y and UV plane address and offsets * - * @param gdc_settings - overall gdc settings and state + * @param gdc_cmd_s - overall gdc settings and state * * @return 0 - success * -1 - unexpected interrupt from GDC. */ -int gdc_get_frame(struct gdc_settings *gdc_settings); +int gdc_get_frame(struct gdc_cmd_s *gdc_cmd); /** * This function points gdc to its input resolution @@ -212,12 +402,12 @@ int gdc_get_frame(struct gdc_settings *gdc_settings); * * Shown inputs to GDC are Y and UV plane address and offsets * - * @param gdc_settings - overall gdc settings and state + * @param gdc_cmd_s - overall gdc settings and state * * @return 0 - success * -1 - no interrupt from GDC. */ -int gdc_run(struct gdc_settings *g); +int gdc_run(struct gdc_cmd_s *g); int32_t init_gdc_io(struct device_node *dn); diff --git a/drivers/amlogic/media/gdc/inc/gdc/gdc_config.h b/drivers/amlogic/media/gdc/inc/gdc/gdc_config.h index db8c9b7fb94e..dbf7300dea08 100644 --- a/drivers/amlogic/media/gdc/inc/gdc/gdc_config.h +++ b/drivers/amlogic/media/gdc/inc/gdc/gdc_config.h @@ -22,10 +22,17 @@ #include #include #include +#include #include "system_gdc_io.h" #include "gdc_api.h" +#include "gdc_dmabuf.h" +struct gdc_cmd_s; + +struct gdc_manager_s { + struct aml_dma_buffer *buffer; + struct meson_gdc_dev_t *gdc_dev; +}; -struct gdc_settings; struct meson_gdc_dev_t { struct platform_device *pdev; void *reg_base; @@ -35,6 +42,14 @@ struct meson_gdc_dev_t { struct mutex d_mutext; struct completion d_com; int irq; + struct miscdevice misc_dev; +}; + +struct gdc_dma_cfg_t { + struct aml_dma_cfg input_cfg_plane1; + struct aml_dma_cfg input_cfg_plane2; + struct aml_dma_cfg config_cfg; + struct aml_dma_cfg output_cfg; }; struct mgdc_fh_s { @@ -43,7 +58,7 @@ struct mgdc_fh_s { struct meson_gdc_dev_t *gdev; char task_comm[32]; struct ion_client *ion_client; - struct gdc_settings gs; + struct gdc_cmd_s gdc_cmd; uint32_t mmap_type; dma_addr_t i_paddr; dma_addr_t o_paddr; @@ -56,6 +71,7 @@ struct mgdc_fh_s { unsigned long c_len; struct gdc_dma_cfg y_dma_cfg; struct gdc_dma_cfg uv_dma_cfg; + struct gdc_dma_cfg_t dma_cfg; }; irqreturn_t interrupt_handler_next(int irq, void *param); diff --git a/drivers/amlogic/media/gdc/inc/sys/system_log.h b/drivers/amlogic/media/gdc/inc/sys/system_log.h index e9f0bc24d8f9..cae4ee0f2405 100644 --- a/drivers/amlogic/media/gdc/inc/sys/system_log.h +++ b/drivers/amlogic/media/gdc/inc/sys/system_log.h @@ -20,36 +20,27 @@ //changeable logs #include -#define FW_LOG_LEVEL LOG_ERR +extern unsigned int gdc_log_level; enum log_level_e { - LOG_NOTHING, - LOG_EMERG, - LOG_ALERT, + LOG_NO_THING, LOG_CRIT, LOG_ERR, LOG_WARNING, - LOG_NOTICE, LOG_INFO, LOG_DEBUG, - LOG_IRQ, LOG_MAX }; -extern const char *const gdc_log_level[LOG_MAX]; - -#define FILE (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__) - #if 1 -#define LOG(level, fmt, arg...) \ +#define gdc_log(level, fmt, ...) \ do { \ - if ((level) <= FW_LOG_LEVEL) \ - pr_info("%s: %s(%d) %s: " fmt "\n",\ - FILE, __func__, __LINE__, \ - gdc_log_level[level], ## arg); \ + if (level <= gdc_log_level) \ + pr_info("%s: "fmt, __func__, ##__VA_ARGS__); \ } while (0) + #else -#define LOG(...) +#define gdc_log(...) #endif #endif // __SYSTEM_LOG_H__ diff --git a/drivers/amlogic/media/gdc/src/fw_lib/acamera_gdc.c b/drivers/amlogic/media/gdc/src/fw_lib/acamera_gdc.c index 83a988ea5cd5..e86cff5b9b6d 100644 --- a/drivers/amlogic/media/gdc/src/fw_lib/acamera_gdc.c +++ b/drivers/amlogic/media/gdc/src/fw_lib/acamera_gdc.c @@ -36,32 +36,32 @@ * * More than one gdc settings can be accessed by index to a gdc_config_t. * - * @param gdc_settings - overall gdc settings and state + * @param gdc_cmd - overall gdc settings and state * @param gdc_config_num - selects the current gdc config to be applied * * @return 0 - success * -1 - fail. */ -int gdc_init(struct gdc_settings *gdc_settings) +int gdc_init(struct gdc_cmd_s *gdc_cmd) { - gdc_settings->is_waiting_gdc = 0; - gdc_settings->current_addr = gdc_settings->buffer_addr; + gdc_cmd->is_waiting_gdc = 0; + gdc_cmd->current_addr = gdc_cmd->buffer_addr; - if ((gdc_settings->gdc_config.output_width == 0) - || (gdc_settings->gdc_config.output_height == 0)) { - LOG(LOG_ERR, "Wrong GDC output resolution.\n"); + if ((gdc_cmd->gdc_config.output_width == 0) + || (gdc_cmd->gdc_config.output_height == 0)) { + gdc_log(LOG_ERR, "Wrong GDC output resolution.\n"); return -1; } //stop gdc gdc_start_flag_write(0); //set the configuration address and size to the gdc block - gdc_config_addr_write(gdc_settings->gdc_config.config_addr); - gdc_config_size_write(gdc_settings->gdc_config.config_size); + gdc_config_addr_write(gdc_cmd->gdc_config.config_addr); + gdc_config_size_write(gdc_cmd->gdc_config.config_size); //set the gdc output resolution - gdc_dataout_width_write(gdc_settings->gdc_config.output_width); - gdc_dataout_height_write(gdc_settings->gdc_config.output_height); + gdc_dataout_width_write(gdc_cmd->gdc_config.output_width); + gdc_dataout_height_write(gdc_cmd->gdc_config.output_height); return 0; } @@ -69,12 +69,12 @@ int gdc_init(struct gdc_settings *gdc_settings) /** * This function stops the gdc block * - * @param gdc_settings - overall gdc settings and state + * @param gdc_cmd - overall gdc settings and state * */ -void gdc_stop(struct gdc_settings *gdc_settings) +void gdc_stop(struct gdc_cmd_s *gdc_cmd) { - gdc_settings->is_waiting_gdc = 0; + gdc_cmd->is_waiting_gdc = 0; gdc_start_flag_write(0); } @@ -83,14 +83,14 @@ void gdc_stop(struct gdc_settings *gdc_settings) * * Writing 0->1 transition is necessary for trigger * - * @param gdc_settings - overall gdc settings and state + * @param gdc_cmd - overall gdc settings and state * */ -void gdc_start(struct gdc_settings *gdc_settings) +void gdc_start(struct gdc_cmd_s *gdc_cmd) { gdc_start_flag_write(0); //do a stop for sync gdc_start_flag_write(1); - gdc_settings->is_waiting_gdc = 1; + gdc_cmd->is_waiting_gdc = 1; } /** @@ -100,7 +100,7 @@ void gdc_start(struct gdc_settings *gdc_settings) * * Shown inputs to GDC are Y and UV plane address and offsets * - * @param gdc_settings - overall gdc settings and state + * @param gdc_cmd - overall gdc settings and state * @param active_width - input width resolution * @param active_height - input height resolution * @param y_base_addr - input Y base address @@ -111,27 +111,27 @@ void gdc_start(struct gdc_settings *gdc_settings) * @return 0 - success * -1 - no interrupt from GDC. */ -int gdc_process(struct gdc_settings *gdc_settings, +int gdc_process(struct gdc_cmd_s *gdc_cmd, uint32_t y_base_addr, uint32_t uv_base_addr) { - uint32_t gdc_out_base_addr = gdc_settings->current_addr; - uint32_t input_width = gdc_settings->gdc_config.input_width; - uint32_t input_height = gdc_settings->gdc_config.input_height; - uint32_t output_height = gdc_settings->gdc_config.output_height; - uint32_t i_y_line_offset = gdc_settings->gdc_config.input_y_stride; - uint32_t i_uv_line_offset = gdc_settings->gdc_config.input_c_stride; - uint32_t o_y_line_offset = gdc_settings->gdc_config.output_y_stride; - uint32_t o_uv_line_offset = gdc_settings->gdc_config.output_c_stride; + uint32_t gdc_out_base_addr = gdc_cmd->current_addr; + uint32_t input_width = gdc_cmd->gdc_config.input_width; + uint32_t input_height = gdc_cmd->gdc_config.input_height; + uint32_t output_height = gdc_cmd->gdc_config.output_height; + uint32_t i_y_line_offset = gdc_cmd->gdc_config.input_y_stride; + uint32_t i_uv_line_offset = gdc_cmd->gdc_config.input_c_stride; + uint32_t o_y_line_offset = gdc_cmd->gdc_config.output_y_stride; + uint32_t o_uv_line_offset = gdc_cmd->gdc_config.output_c_stride; - if (gdc_settings->is_waiting_gdc) { + if (gdc_cmd->is_waiting_gdc) { gdc_start_flag_write(0); - LOG(LOG_CRIT, "No interrupt Still waiting...\n"); + gdc_log(LOG_CRIT, "No interrupt Still waiting...\n"); gdc_start_flag_write(1); return -1; } - LOG(LOG_DEBUG, "starting GDC process.\n"); + gdc_log(LOG_DEBUG, "starting GDC process.\n"); gdc_datain_width_write(input_width); gdc_datain_height_write(input_height); @@ -152,7 +152,7 @@ int gdc_process(struct gdc_settings *gdc_settings, gdc_data2out_addr_write(gdc_out_base_addr); gdc_data2out_line_offset_write(o_uv_line_offset); - gdc_start(gdc_settings); + gdc_start(gdc_cmd); return 0; } @@ -164,7 +164,7 @@ int gdc_process(struct gdc_settings *gdc_settings, * * Shown inputs to GDC are Y and UV plane address and offsets * - * @param gdc_settings - overall gdc settings and state + * @param gdc_cmd - overall gdc settings and state * @param active_width - input width resolution * @param active_height - input height resolution * @param y_base_addr - input Y base address @@ -175,27 +175,27 @@ int gdc_process(struct gdc_settings *gdc_settings, * @return 0 - success * -1 - no interrupt from GDC. */ -int gdc_process_yuv420p(struct gdc_settings *gdc_settings, +int gdc_process_yuv420p(struct gdc_cmd_s *gdc_cmd, uint32_t y_base_addr, uint32_t u_base_addr, uint32_t v_base_addr) { - struct gdc_config *gc = &gdc_settings->gdc_config; - uint32_t gdc_out_base_addr = gdc_settings->current_addr; + struct gdc_config_s *gc = &gdc_cmd->gdc_config; + uint32_t gdc_out_base_addr = gdc_cmd->current_addr; uint32_t input_width = gc->input_width; uint32_t input_height = gc->input_height; uint32_t input_stride = gc->input_y_stride; uint32_t input_u_stride = gc->input_c_stride; uint32_t input_v_stride = gc->input_c_stride; - LOG(LOG_DEBUG, "is_waiting_gdc=%d\n", gdc_settings->is_waiting_gdc); - if (gdc_settings->is_waiting_gdc) { + gdc_log(LOG_DEBUG, "is_waiting_gdc=%d\n", gdc_cmd->is_waiting_gdc); + if (gdc_cmd->is_waiting_gdc) { gdc_start_flag_write(0); - LOG(LOG_CRIT, "No interrupt Still waiting...\n"); + gdc_log(LOG_CRIT, "No interrupt Still waiting...\n"); gdc_start_flag_write(1); return -1; } ///// - LOG(LOG_DEBUG, "starting GDC process.\n"); + gdc_log(LOG_DEBUG, "starting GDC process.\n"); //already set in gdc_init //uint32_t output_width = gc->output_width; @@ -231,7 +231,7 @@ int gdc_process_yuv420p(struct gdc_settings *gdc_settings, gdc_out_base_addr += output_height * output_u_stride / 2; gdc_data3out_addr_write(gdc_out_base_addr); gdc_data3out_line_offset_write(output_v_stride); - gdc_start(gdc_settings); + gdc_start(gdc_cmd); return 0; } @@ -244,7 +244,7 @@ int gdc_process_yuv420p(struct gdc_settings *gdc_settings, * * Shown inputs to GDC are Y plane address and offsets * - * @param gdc_settings - overall gdc settings and state + * @param gdc_cmd - overall gdc settings and state * @param active_width - input width resolution * @param active_height - input height resolution * @param y_base_addr - input Y base address @@ -253,25 +253,25 @@ int gdc_process_yuv420p(struct gdc_settings *gdc_settings, * @return 0 - success * -1 - no interrupt from GDC. */ -int gdc_process_y_grey(struct gdc_settings *gdc_settings, +int gdc_process_y_grey(struct gdc_cmd_s *gdc_cmd, uint32_t y_base_addr) { - struct gdc_config *gc = &gdc_settings->gdc_config; - uint32_t gdc_out_base_addr = gdc_settings->current_addr; + struct gdc_config_s *gc = &gdc_cmd->gdc_config; + uint32_t gdc_out_base_addr = gdc_cmd->current_addr; uint32_t input_width = gc->input_width; uint32_t input_height = gc->input_height; uint32_t input_stride = gc->input_y_stride; uint32_t output_stride = gc->output_y_stride; - LOG(LOG_DEBUG, "is_waiting_gdc=%d\n", gdc_settings->is_waiting_gdc); - if (gdc_settings->is_waiting_gdc) { + gdc_log(LOG_DEBUG, "is_waiting_gdc=%d\n", gdc_cmd->is_waiting_gdc); + if (gdc_cmd->is_waiting_gdc) { gdc_start_flag_write(0); - LOG(LOG_CRIT, "No interrupt Still waiting...\n"); + gdc_log(LOG_CRIT, "No interrupt Still waiting...\n"); gdc_start_flag_write(1); return -1; } - LOG(LOG_DEBUG, "starting GDC process.\n"); + gdc_log(LOG_DEBUG, "starting GDC process.\n"); gdc_datain_width_write(input_width); gdc_datain_height_write(input_height); @@ -283,7 +283,7 @@ int gdc_process_y_grey(struct gdc_settings *gdc_settings, gdc_data1out_addr_write(gdc_out_base_addr); gdc_data1out_line_offset_write(output_stride); - gdc_start(gdc_settings); + gdc_start(gdc_cmd); return 0; } @@ -295,7 +295,7 @@ int gdc_process_y_grey(struct gdc_settings *gdc_settings, * * Shown inputs to GDC are Y and UV plane address and offsets * - * @param gdc_settings - overall gdc settings and state + * @param gdc_cmd - overall gdc settings and state * @param active_width - input width resolution * @param active_height - input height resolution * @param y_base_addr - input Y base address @@ -306,11 +306,11 @@ int gdc_process_y_grey(struct gdc_settings *gdc_settings, * @return 0 - success * -1 - no interrupt from GDC. */ -int gdc_process_yuv444p(struct gdc_settings *gdc_settings, +int gdc_process_yuv444p(struct gdc_cmd_s *gdc_cmd, uint32_t y_base_addr, uint32_t u_base_addr, uint32_t v_base_addr) { - struct gdc_config *gc = &gdc_settings->gdc_config; - uint32_t gdc_out_base_addr = gdc_settings->current_addr; + struct gdc_config_s *gc = &gdc_cmd->gdc_config; + uint32_t gdc_out_base_addr = gdc_cmd->current_addr; uint32_t input_width = gc->input_width; uint32_t input_height = gc->input_height; uint32_t input_stride = gc->input_y_stride; @@ -321,15 +321,15 @@ int gdc_process_yuv444p(struct gdc_settings *gdc_settings, uint32_t output_u_stride = gc->output_c_stride; uint32_t output_v_stride = gc->output_c_stride; - LOG(LOG_DEBUG, "is_waiting_gdc=%d\n", gdc_settings->is_waiting_gdc); - if (gdc_settings->is_waiting_gdc) { + gdc_log(LOG_DEBUG, "is_waiting_gdc=%d\n", gdc_cmd->is_waiting_gdc); + if (gdc_cmd->is_waiting_gdc) { gdc_start_flag_write(0); - LOG(LOG_CRIT, "No interrupt Still waiting...\n"); + gdc_log(LOG_CRIT, "No interrupt Still waiting...\n"); gdc_start_flag_write(1); return -1; } - LOG(LOG_DEBUG, "starting GDC process.\n"); + gdc_log(LOG_DEBUG, "starting GDC process.\n"); gdc_datain_width_write(input_width); gdc_datain_height_write(input_height); @@ -358,7 +358,7 @@ int gdc_process_yuv444p(struct gdc_settings *gdc_settings, gdc_out_base_addr += output_height * output_u_stride; gdc_data3out_addr_write(gdc_out_base_addr); gdc_data3out_line_offset_write(output_v_stride); - gdc_start(gdc_settings); + gdc_start(gdc_cmd); return 0; } @@ -370,7 +370,7 @@ int gdc_process_yuv444p(struct gdc_settings *gdc_settings, * * Shown inputs to GDC are R\G\B plane address and offsets * - * @param gdc_settings - overall gdc settings and state + * @param gdc_cmd - overall gdc settings and state * @param active_width - input width resolution * @param active_height - input height resolution * @param y_base_addr - input R base address @@ -383,11 +383,11 @@ int gdc_process_yuv444p(struct gdc_settings *gdc_settings, * @return 0 - success * -1 - no interrupt from GDC. */ -int gdc_process_rgb444p(struct gdc_settings *gdc_settings, +int gdc_process_rgb444p(struct gdc_cmd_s *gdc_cmd, uint32_t y_base_addr, uint32_t u_base_addr, uint32_t v_base_addr) { - struct gdc_config *gc = &gdc_settings->gdc_config; - uint32_t gdc_out_base_addr = gdc_settings->current_addr; + struct gdc_config_s *gc = &gdc_cmd->gdc_config; + uint32_t gdc_out_base_addr = gdc_cmd->current_addr; uint32_t input_width = gc->input_width; uint32_t input_height = gc->input_height; uint32_t input_stride = gc->input_y_stride; @@ -398,15 +398,15 @@ int gdc_process_rgb444p(struct gdc_settings *gdc_settings, uint32_t output_u_stride = gc->output_c_stride; uint32_t output_v_stride = gc->output_c_stride; - LOG(LOG_DEBUG, "is_waiting_gdc=%d\n", gdc_settings->is_waiting_gdc); - if (gdc_settings->is_waiting_gdc) { + gdc_log(LOG_DEBUG, "is_waiting_gdc=%d\n", gdc_cmd->is_waiting_gdc); + if (gdc_cmd->is_waiting_gdc) { gdc_start_flag_write(0); - LOG(LOG_CRIT, "No interrupt Still waiting...\n"); + gdc_log(LOG_CRIT, "No interrupt Still waiting...\n"); gdc_start_flag_write(1); return -1; } - LOG(LOG_DEBUG, "starting GDC process.\n"); + gdc_log(LOG_DEBUG, "starting GDC process.\n"); gdc_datain_width_write(input_width); gdc_datain_height_write(input_height); @@ -435,7 +435,7 @@ int gdc_process_rgb444p(struct gdc_settings *gdc_settings, gdc_out_base_addr += output_height * output_u_stride; gdc_data3out_addr_write(gdc_out_base_addr); gdc_data3out_line_offset_write(output_v_stride); - gdc_start(gdc_settings); + gdc_start(gdc_cmd); return 0; } @@ -449,21 +449,21 @@ int gdc_process_rgb444p(struct gdc_settings *gdc_settings, * * Y and UV plane address and offsets * - * @param gdc_settings - overall gdc settings and state + * @param gdc_cmd - overall gdc settings and state * * @return 0 - success * -1 - unexpected interrupt from GDC. */ -int gdc_get_frame(struct gdc_settings *gdc_settings) +int gdc_get_frame(struct gdc_cmd_s *gdc_cmd) { - struct mgdc_fh_s *fh = gdc_settings->fh; + struct mgdc_fh_s *fh = gdc_cmd->fh; uint32_t y; uint32_t y_offset; uint32_t uv; uint32_t uv_offset; - if (!gdc_settings->is_waiting_gdc) { - LOG(LOG_CRIT, "Unexpected interrupt from GDC.\n"); + if (!gdc_cmd->is_waiting_gdc) { + gdc_log(LOG_CRIT, "Unexpected interrupt from GDC.\n"); return -1; } //// @@ -471,17 +471,17 @@ int gdc_get_frame(struct gdc_settings *gdc_settings) wake_up_interruptible(&fh->irq_queue); //pass the frame buffer parameters if callback is available - if (gdc_settings->get_frame_buffer) { + if (gdc_cmd->get_frame_buffer) { y = gdc_data1out_addr_read(); y_offset = gdc_data1out_line_offset_read(); uv = gdc_data2out_addr_read(); uv_offset = gdc_data2out_line_offset_read(); - gdc_settings->get_frame_buffer(y, + gdc_cmd->get_frame_buffer(y, uv, y_offset, uv_offset); } //done of the current frame and stop gdc block - gdc_stop(gdc_settings); + gdc_stop(gdc_cmd); //spin_unlock_irqrestore(&gdev->slock, flags); return 0; } diff --git a/drivers/amlogic/media/gdc/src/platform/system_gdc_io.c b/drivers/amlogic/media/gdc/src/platform/system_gdc_io.c index 378789fcbf53..fcb09ab321c6 100644 --- a/drivers/amlogic/media/gdc/src/platform/system_gdc_io.c +++ b/drivers/amlogic/media/gdc/src/platform/system_gdc_io.c @@ -30,7 +30,7 @@ int32_t init_gdc_io(struct device_node *dn) pr_info("reg base = %p\n", p_hw_base); if (!p_hw_base) { - LOG(LOG_DEBUG, "failed to map register, %p\n", p_hw_base); + gdc_log(LOG_DEBUG, "failed to map register, %p\n", p_hw_base); return -1; } @@ -39,28 +39,32 @@ int32_t init_gdc_io(struct device_node *dn) void close_gdc_io(struct device_node *dn) { - LOG(LOG_DEBUG, "IO functionality has been closed"); + gdc_log(LOG_DEBUG, "IO functionality has been closed"); } uint32_t system_gdc_read_32(uint32_t addr) { uint32_t result = 0; - if (p_hw_base == NULL) - LOG(LOG_ERR, "Failed to base address %d\n", addr); + if (p_hw_base == NULL) { + gdc_log(LOG_ERR, "Failed to base address %d\n", addr); + return 0; + } result = ioread32(p_hw_base + addr); - LOG(LOG_DEBUG, "r [0x%04x]= %08x\n", addr, result); + gdc_log(LOG_DEBUG, "r [0x%04x]= %08x\n", addr, result); return result; } void system_gdc_write_32(uint32_t addr, uint32_t data) { - if (p_hw_base == NULL) - LOG(LOG_ERR, "Failed to write %d to addr %d\n", data, addr); + if (p_hw_base == NULL) { + gdc_log(LOG_ERR, "Failed to write %d to addr %d\n", data, addr); + return; + } void *ptr = (void *)(p_hw_base + addr); iowrite32(data, ptr); - LOG(LOG_DEBUG, "w [0x%04x]= %08x\n", addr, data); + gdc_log(LOG_DEBUG, "w [0x%04x]= %08x\n", addr, data); } diff --git a/drivers/amlogic/media/osd/osd.h b/drivers/amlogic/media/osd/osd.h index 751fdc06a5f0..03dd77399ebc 100644 --- a/drivers/amlogic/media/osd/osd.h +++ b/drivers/amlogic/media/osd/osd.h @@ -106,7 +106,6 @@ enum color_index_e { #define FBIOPUT_OSD_CURSOR \ _IOWR(FB_IOC_MAGIC, 0x0, struct fb_cursor_user) - /* OSD color definition */ #define KEYCOLOR_FLAG_TARGET 1 #define KEYCOLOR_FLAG_ONHOLD 2 @@ -114,6 +113,8 @@ enum color_index_e { #define HW_OSD_COUNT 4 #define OSD_BLEND_LAYERS 4 +#define VIU_COUNT 2 + /* OSD block definition */ #define HW_OSD_BLOCK_COUNT 4 #define HW_OSD_BLOCK_REG_COUNT (HW_OSD_BLOCK_COUNT*2) @@ -277,6 +278,8 @@ enum cpuid_type_e { __MESON_CPU_MAJOR_ID_G12A, __MESON_CPU_MAJOR_ID_G12B, __MESON_CPU_MAJOR_ID_TL1, + __MESON_CPU_MAJOR_ID_SM1, + __MESON_CPU_MAJOR_ID_TM2, __MESON_CPU_MAJOR_ID_UNKNOWN, }; @@ -449,6 +452,8 @@ struct layer_fence_map_s { u32 ext_addr; u32 format; u32 compose_type; + u32 fb_width; + u32 fb_height; u32 src_x; u32 src_y; u32 src_w; @@ -505,6 +510,7 @@ struct osd_device_data_s { u32 vpp_fifo_len; u32 dummy_data; u32 has_viu2; + u32 osd0_sc_independ; u32 viu1_osd_count; u32 viu2_index; struct clk *vpu_clkc; @@ -703,7 +709,7 @@ struct hw_para_s { u32 scan_mode[HW_OSD_COUNT]; u32 order[HW_OSD_COUNT]; u32 premult_en[HW_OSD_COUNT]; - struct display_flip_info_s disp_info; + struct display_flip_info_s disp_info[VIU_COUNT]; struct osd_3d_mode_s mode_3d[HW_OSD_COUNT]; u32 updated[HW_OSD_COUNT]; /* u32 block_windows[HW_OSD_COUNT][HW_OSD_BLOCK_REG_COUNT]; */ @@ -718,7 +724,7 @@ struct hw_para_s { int use_h_filter_mode[HW_OSD_COUNT]; int use_v_filter_mode[HW_OSD_COUNT]; struct hw_list_s reg[HW_REG_INDEX_MAX]; - u32 field_out_en; + u32 field_out_en[VIU_COUNT]; u32 scale_workaround; u32 fb_for_4k2k; u32 antiflicker_mode; @@ -730,33 +736,35 @@ struct hw_para_s { struct osd_device_data_s osd_meson_dev; u32 urgent[HW_OSD_COUNT]; u32 osd_deband_enable; - u32 osd_fps; - u32 osd_fps_start; + u32 osd_fps[VIU_COUNT]; + u32 osd_fps_start[VIU_COUNT]; u32 osd_display_debug; ulong screen_base[HW_OSD_COUNT]; ulong screen_size[HW_OSD_COUNT]; ulong screen_base_backup[HW_OSD_COUNT]; ulong screen_size_backup[HW_OSD_COUNT]; - u32 vinfo_width; - u32 vinfo_height; + u32 vinfo_width[VIU_COUNT]; + u32 vinfo_height[VIU_COUNT]; u32 fb_drvier_probe; u32 afbc_force_reset; u32 afbc_regs_backup; u32 afbc_status_err_reset; u32 afbc_use_latch; - u32 hwc_enable; + u32 hwc_enable[VIU_COUNT]; u32 osd_use_latch[HW_OSD_COUNT]; u32 hw_cursor_en; u32 hw_rdma_en; u32 blend_bypass; u32 hdr_used; + u32 workaround_line; u32 basic_urgent; u32 two_ports; u32 afbc_err_cnt; u32 viu_type; + u32 line_n_rdma; struct hw_debug_s osd_debug; - int out_fence_fd; + int out_fence_fd[VIU_COUNT]; int in_fd[HW_OSD_COUNT]; - struct osd_fence_fun_s osd_fence[2]; + struct osd_fence_fun_s osd_fence[VIU_COUNT][2]; }; #endif /* _OSD_H_ */ diff --git a/drivers/amlogic/media/osd/osd_backup.c b/drivers/amlogic/media/osd/osd_backup.c index 64d9cd965f87..8209c6e206b8 100644 --- a/drivers/amlogic/media/osd/osd_backup.c +++ b/drivers/amlogic/media/osd/osd_backup.c @@ -648,7 +648,7 @@ static struct reg_item osd3_afbcd_recovery_table_g12a[] = { 0x0, 0x0000ffff, 1 }, { - VPU_MAFBC_PREFETCH_CFG_S1, 0x0, 3, 1 + VPU_MAFBC_PREFETCH_CFG_S2, 0x0, 3, 1 } }; @@ -1538,7 +1538,11 @@ static s32 get_recovery_item_g12a(u32 addr, u32 *value, u32 *mask) u32 regmask = table->mask; u32 real_value = osd_reg_read(addr); - if ((real_value & regmask) + if (enable_vd_zorder && + (addr == OSD2_BLEND_SRC_CTRL)) { + ret = 1; + table->recovery = 0; + } else if ((real_value & regmask) == (table->val & regmask)) { ret = 1; *mask = regmask; diff --git a/drivers/amlogic/media/osd/osd_debug.c b/drivers/amlogic/media/osd/osd_debug.c index 701da240af6e..c456a34543b0 100644 --- a/drivers/amlogic/media/osd/osd_debug.c +++ b/drivers/amlogic/media/osd/osd_debug.c @@ -66,7 +66,9 @@ static void osd_debug_dump_value(void) osd_log_info("--- OSD ---\n"); osd_log_info("bot_type: %d\n", hwpara->bot_type); - osd_log_info("field_out_en: %d\n", hwpara->field_out_en); + osd_log_info("field_out_en: %d\n", hwpara->field_out_en[VIU1]); + if (osd_hw.osd_meson_dev.has_viu2) + osd_log_info("field_out_en: %d\n", hwpara->field_out_en[VIU2]); if (hwpara->osd_meson_dev.osd_ver == OSD_HIGH_ONE) { struct hw_osd_blending_s *blend_para = NULL; diff --git a/drivers/amlogic/media/osd/osd_drm.c b/drivers/amlogic/media/osd/osd_drm.c index d2cb62783e21..3732b201d41d 100644 --- a/drivers/amlogic/media/osd/osd_drm.c +++ b/drivers/amlogic/media/osd/osd_drm.c @@ -563,11 +563,13 @@ static ssize_t osd_hwc_enable_read_file(struct file *file, char __user *userbuf, size_t count, loff_t *ppos) { + struct seq_file *s = file->private_data; + int osd_id = *(int *)s; char buf[128]; ssize_t len; unsigned int hwc_enable = 0; - osd_get_hwc_enable(&hwc_enable); + osd_get_hwc_enable(osd_id, &hwc_enable); len = snprintf(buf, 128, "%d\n", hwc_enable); return simple_read_from_buffer(userbuf, count, ppos, buf, len); } @@ -576,6 +578,8 @@ static ssize_t osd_hwc_enable_write_file(struct file *file, const char __user *userbuf, size_t count, loff_t *ppos) { + struct seq_file *s = file->private_data; + int osd_id = *(int *)s; char buf[128]; unsigned int hwc_enable = 0; int ret = 0; @@ -586,7 +590,7 @@ static ssize_t osd_hwc_enable_write_file(struct file *file, buf[count] = 0; ret = kstrtoint(buf, 0, &hwc_enable); osd_log_info("hwc enable: %d\n", hwc_enable); - osd_set_hwc_enable(hwc_enable); + osd_set_hwc_enable(osd_id, hwc_enable); return count; } @@ -594,6 +598,8 @@ static ssize_t osd_do_hwc_write_file(struct file *file, const char __user *userbuf, size_t count, loff_t *ppos) { + struct seq_file *s = file->private_data; + int osd_id = *(int *)s; char buf[128]; unsigned int do_hwc = 0; int ret = 0; @@ -605,7 +611,7 @@ static ssize_t osd_do_hwc_write_file(struct file *file, ret = kstrtoint(buf, 0, &do_hwc); osd_log_info("do_hwc: %d\n", do_hwc); if (do_hwc) - osd_do_hwc(); + osd_do_hwc(osd_id); return count; } diff --git a/drivers/amlogic/media/osd/osd_fb.c b/drivers/amlogic/media/osd/osd_fb.c index 80221a5dafd7..cf03b0f212d8 100644 --- a/drivers/amlogic/media/osd/osd_fb.c +++ b/drivers/amlogic/media/osd/osd_fb.c @@ -46,12 +46,16 @@ #include #include #include +#include /* Amlogic Headers */ #include #include #ifdef CONFIG_INSTABOOT #include #endif +#ifdef CONFIG_AMLOGIC_VPU +#include +#endif /* Local Headers */ #include "osd.h" #include "osd_fb.h" @@ -59,6 +63,7 @@ #include "osd_log.h" #include "osd_sync.h" #include "osd_io.h" +#include "osd_rdma.h" static __u32 var_screeninfo[5]; static struct osd_device_data_s osd_meson_dev; @@ -733,10 +738,18 @@ static int osd_check_var(struct fb_var_screeninfo *var, struct fb_info *info) static int osd_set_par(struct fb_info *info) { - const struct vinfo_s *vinfo; + const struct vinfo_s *vinfo = NULL; struct osd_fb_dev_s *fbdev = (struct osd_fb_dev_s *)info->par; struct osd_ctl_s *osd_ctrl = &fbdev->osd_ctl; u32 virt_end_x, virt_end_y; + u32 output_index; + + output_index = get_output_device_id(fbdev->fb_index); + +#ifdef CONFIG_ARCH_MESON64_ODROIDN2 + info->var.xres_virtual = info->var.xres; + info->var.yres_virtual = info->var.yres; +#endif #ifdef CONFIG_ARCH_MESON64_ODROIDN2 info->var.xres_virtual = info->var.xres; @@ -750,7 +763,9 @@ static int osd_set_par(struct fb_info *info) return -1; } } else { +#ifdef CONFIG_AMLOGIC_VOUT2_SERVE vinfo = get_current_vinfo2(); +#endif if (!vinfo) { osd_log_err("current vinfo NULL\n"); return -1; @@ -847,12 +862,19 @@ static int osd_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) ret = copy_from_user(&sync_request, argp, sizeof(struct fb_sync_request_s)); break; + // Only wait for vsync when not HW decoding. case FBIO_WAITFORVSYNC: - vsync_timestamp = (s32)osd_wait_vsync_event(); + if (get_vpu_mem_pd_vmod(VPU_VIU_VD1)) + vsync_timestamp = (s32)osd_wait_vsync_event(); + else + vsync_timestamp = 0; ret = copy_to_user(argp, &vsync_timestamp, sizeof(s32)); break; case FBIO_WAITFORVSYNC_64: - vsync_timestamp_64 = osd_wait_vsync_event(); + if (get_vpu_mem_pd_vmod(VPU_VIU_VD1)) + vsync_timestamp_64 = osd_wait_vsync_event(); + else + vsync_timestamp_64 = 0; ret = copy_to_user(argp, &vsync_timestamp_64, sizeof(s64)); break; case FBIOGET_OSD_SCALE_AXIS: @@ -935,7 +957,7 @@ static int osd_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) arg & 0xffff ? 1 : 0); break; case FBIOGET_OSD_FLUSH_RATE: - osd_get_flush_rate_hw(&flush_rate); + osd_get_flush_rate_hw(info->node, &flush_rate); if (copy_to_user(argp, &flush_rate, sizeof(u32))) return -EFAULT; break; @@ -1145,12 +1167,12 @@ static int osd_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) #endif break; case FBIOPUT_OSD_HWC_ENABLE: - osd_set_hwc_enable(hwc_enable); + osd_set_hwc_enable(info->node, hwc_enable); ret = 0; break; case FBIOPUT_OSD_DO_HWC: do_hwc_cmd.out_fen_fd = - osd_sync_do_hwc(&do_hwc_cmd); + osd_sync_do_hwc(info->node, &do_hwc_cmd); ret = copy_to_user(argp, &do_hwc_cmd, sizeof(struct do_hwc_cmd_s)); @@ -1971,13 +1993,14 @@ static int osd_cursor(struct fb_info *fbi, struct fb_cursor *var) { s16 startx = 0, starty = 0; struct osd_fb_dev_s *fb_dev = gp_fbdev_list[1]; + u32 output_index; if (fb_dev) { startx = fb_dev->osd_ctl.disp_start_x; starty = fb_dev->osd_ctl.disp_start_y; } - - if (osd_hw.hwc_enable) + output_index = get_output_device_id(fbi->node); + if (osd_hw.hwc_enable[output_index]) osd_cursor_hw_no_scale(fbi->node, (s16)var->hot.x, (s16)var->hot.y, (s16)startx, (s16)starty, fbi->var.xres, fbi->var.yres); @@ -2070,15 +2093,18 @@ int osd_notify_callback(struct notifier_block *block, unsigned long cmd, if ((!strcmp(vinfo->name, "invalid")) || (!strcmp(vinfo->name, "null"))) return -1; - osd_hw.vinfo_width = vinfo->width; - osd_hw.vinfo_height = vinfo->field_height; - osd_hw.field_out_en = is_interlaced(vinfo); + osd_hw.vinfo_width[VIU1] = vinfo->width; + osd_hw.vinfo_height[VIU1] = vinfo->field_height; + osd_hw.field_out_en[VIU1] = is_interlaced(vinfo); switch (cmd) { case VOUT_EVENT_MODE_CHANGE: set_osd_logo_freescaler(); + if (osd_hw.osd_meson_dev.cpu_id == __MESON_CPU_MAJOR_ID_G12B && + is_meson_rev_b()) + set_reset_rdma_trigger_line(); if ((osd_meson_dev.osd_ver == OSD_NORMAL) || (osd_meson_dev.osd_ver == OSD_SIMPLE) - || (osd_hw.hwc_enable == 0)) { + || (osd_hw.hwc_enable[VIU1] == 0)) { for (i = 0; i < osd_meson_dev.viu1_osd_count; i++) { fb_dev = gp_fbdev_list[i]; if (fb_dev == NULL) @@ -2109,7 +2135,7 @@ int osd_notify_callback(struct notifier_block *block, unsigned long cmd, case VOUT_EVENT_OSD_DISP_AXIS: if ((osd_meson_dev.osd_ver == OSD_NORMAL) || (osd_meson_dev.osd_ver == OSD_SIMPLE) - || (osd_hw.hwc_enable == 0)) { + || (osd_hw.hwc_enable[VIU1] == 0)) { disp_rect = (struct disp_rect_s *)para; for (i = 0; i < osd_meson_dev.viu1_osd_count; i++) { @@ -2160,111 +2186,6 @@ int osd_notify_callback(struct notifier_block *block, unsigned long cmd, return 0; } -#if 0 -int osd_notify_callback(struct notifier_block *block, unsigned long cmd, - void *para) -{ - struct vinfo_s *vinfo; - struct osd_fb_dev_s *fb_dev; - int i, blank; - struct disp_rect_s *disp_rect; - - vinfo = get_current_vinfo(); - if (!vinfo) { - osd_log_err("current vinfo NULL\n"); - return -1; - } - osd_log_info("current vmode=%s, cmd: 0x%lx\n", - vinfo->name, cmd); - if ((!strcmp(vinfo->name, "invalid")) || - (!strcmp(vinfo->name, "null"))) - return -1; - osd_hw.vinfo_width = vinfo->width; - osd_hw.vinfo_height = vinfo->field_height; - osd_hw.field_out_en = is_interlaced(vinfo); - switch (cmd) { - case VOUT_EVENT_MODE_CHANGE: - set_osd_logo_freescaler(); - for (i = 0; i < osd_meson_dev.viu1_osd_count; i++) { - fb_dev = gp_fbdev_list[i]; - if (fb_dev == NULL) - continue; - set_default_display_axis(&fb_dev->fb_info->var, - &fb_dev->osd_ctl, vinfo); - console_lock(); - osddev_update_disp_axis(fb_dev, 1); - if ((osd_meson_dev.osd_ver == OSD_NORMAL) - || (osd_meson_dev.osd_ver == OSD_SIMPLE)) - osd_set_antiflicker_hw(DEV_OSD1, vinfo, - gp_fbdev_list - [DEV_OSD1]->fb_info->var.yres); - else if (osd_meson_dev.osd_ver == OSD_HIGH_ONE) - osd_set_antiflicker_hw(i, vinfo, - gp_fbdev_list[i]->fb_info->var.yres); - osd_reg_write(VPP_POSTBLEND_H_SIZE, vinfo->width); - console_unlock(); - } - break; - case VOUT_EVENT_OSD_BLANK: - blank = *(int *)para; - for (i = 0; i < osd_meson_dev.viu1_osd_count; i++) { - fb_dev = gp_fbdev_list[i]; - if (fb_dev == NULL) - continue; - console_lock(); - osd_blank(blank, fb_dev->fb_info); - console_unlock(); - } - break; - case VOUT_EVENT_OSD_DISP_AXIS: - disp_rect = (struct disp_rect_s *)para; - for (i = 0; i < osd_meson_dev.viu1_osd_count; i++) { - if (!disp_rect) - break; - - /* vout serve send only two layer axis */ - if (i >= 2) - break; - - fb_dev = gp_fbdev_list[i]; - /* - * if osd layer preblend, - * it's position is controlled by vpp. - if (fb_dev->preblend_enable) - break; - */ - fb_dev->osd_ctl.disp_start_x = disp_rect->x; - fb_dev->osd_ctl.disp_start_y = disp_rect->y; - osd_log_dbg("set disp axis: x:%d y:%d w:%d h:%d\n", - disp_rect->x, disp_rect->y, - disp_rect->w, disp_rect->h); - if (disp_rect->x + disp_rect->w > vinfo->width) - fb_dev->osd_ctl.disp_end_x = vinfo->width - 1; - else - fb_dev->osd_ctl.disp_end_x = - fb_dev->osd_ctl.disp_start_x + - disp_rect->w - 1; - if (disp_rect->y + disp_rect->h > vinfo->height) - fb_dev->osd_ctl.disp_end_y = vinfo->height - 1; - else - fb_dev->osd_ctl.disp_end_y = - fb_dev->osd_ctl.disp_start_y + - disp_rect->h - 1; - disp_rect++; - osd_log_dbg("new disp axis: x0:%d y0:%d x1:%d y1:%d\n", - fb_dev->osd_ctl.disp_start_x, - fb_dev->osd_ctl.disp_start_y, - fb_dev->osd_ctl.disp_end_x, - fb_dev->osd_ctl.disp_end_y); - console_lock(); - osddev_update_disp_axis(fb_dev, 0); - console_unlock(); - } - break; - } - return 0; -} -#endif int osd_notify_callback_viu2(struct notifier_block *block, unsigned long cmd, void *para) { @@ -2285,6 +2206,8 @@ int osd_notify_callback_viu2(struct notifier_block *block, unsigned long cmd, vinfo->name, cmd); if (!strcmp(vinfo->name, "invalid")) return -1; + osd_hw.vinfo_width[VIU2] = vinfo->width; + osd_hw.vinfo_height[VIU2] = vinfo->field_height; i = osd_meson_dev.viu2_index; switch (cmd) { case VOUT_EVENT_MODE_CHANGE: @@ -2919,9 +2842,10 @@ static ssize_t show_flush_rate(struct device *device, struct device_attribute *attr, char *buf) { + struct fb_info *fb_info = dev_get_drvdata(device); u32 flush_rate = 0; - osd_get_flush_rate_hw(&flush_rate); + osd_get_flush_rate_hw(fb_info->node, &flush_rate); return snprintf(buf, PAGE_SIZE, "flush_rate:[%d]\n", flush_rate); } @@ -2973,15 +2897,22 @@ static ssize_t store_antiflicker(struct device *device, struct device_attribute *attr, const char *buf, size_t count) { - struct vinfo_s *vinfo; + struct vinfo_s *vinfo = NULL; unsigned int osd_antiflicker = 0; struct fb_info *fb_info = dev_get_drvdata(device); int res = 0; int ret = 0; + u32 output_index; ret = kstrtoint(buf, 0, &res); osd_antiflicker = res; - vinfo = get_current_vinfo(); + output_index = get_output_device_id(fb_info->node); + if (output_index == VIU1) + vinfo = get_current_vinfo(); +#ifdef CONFIG_AMLOGIC_VOUT2_SERVE + else if (output_index == VIU2) + vinfo = get_current_vinfo2(); +#endif if (!vinfo) { osd_log_err("get current vinfo NULL\n"); return 0; @@ -3052,9 +2983,18 @@ static ssize_t free_scale_switch(struct device *device, ret = kstrtoint(buf, 0, &res); free_scale_enable = res; - osd_switch_free_scale( - (fb_info->node == DEV_OSD0) ? DEV_OSD1 : DEV_OSD0, - 0, 0, fb_info->node, 1, free_scale_enable); + + if (osd_hw.osd_meson_dev.osd_ver == OSD_HIGH_ONE) + osd_switch_free_scale( + (fb_info->node == DEV_OSD0) ? DEV_OSD0 : DEV_OSD1, + 1, free_scale_enable, fb_info->node, 1, + free_scale_enable); + else + osd_switch_free_scale( + (fb_info->node == DEV_OSD0) ? DEV_OSD1 : DEV_OSD0, + 0, 0, fb_info->node, 1, + free_scale_enable); + osd_log_info("free_scale_switch to fb%d, mode: 0x%x\n", fb_info->node, free_scale_enable); return count; @@ -3088,9 +3028,10 @@ static ssize_t show_osd_fps(struct device *device, struct device_attribute *attr, char *buf) { + struct fb_info *fb_info = dev_get_drvdata(device); u32 osd_fps; - osd_get_fps(&osd_fps); + osd_get_fps(fb_info->node, &osd_fps); return snprintf(buf, 40, "%d\n", osd_fps); } @@ -3099,11 +3040,12 @@ static ssize_t store_osd_fps(struct device *device, struct device_attribute *attr, const char *buf, size_t count) { + struct fb_info *fb_info = dev_get_drvdata(device); int res = 0; int ret = 0; ret = kstrtoint(buf, 0, &res); - osd_set_fps(res); + osd_set_fps(fb_info->node, res); return count; } @@ -3190,9 +3132,10 @@ static ssize_t show_osd_background_size(struct device *device, struct device_attribute *attr, char *buf) { + struct fb_info *fb_info = dev_get_drvdata(device); struct display_flip_info_s disp_info; - osd_get_background_size(&disp_info); + osd_get_background_size(fb_info->node, &disp_info); return snprintf(buf, 80, "%d %d %d %d %d %d %d %d\n", disp_info.background_w, disp_info.background_h, @@ -3208,12 +3151,14 @@ static ssize_t store_osd_background_size(struct device *device, struct device_attribute *attr, const char *buf, size_t count) { + struct fb_info *fb_info = dev_get_drvdata(device); int parsed[8]; - if (likely(parse_para(buf, 8, parsed) == 8)) { + if (likely(parse_para(buf, 8, parsed) == 8)) osd_set_background_size( + fb_info->node, (struct display_flip_info_s *)&parsed); - } else + else osd_log_err("set background size error\n"); return count; @@ -3276,9 +3221,10 @@ static ssize_t show_osd_hwc_enalbe(struct device *device, struct device_attribute *attr, char *buf) { + struct fb_info *fb_info = dev_get_drvdata(device); u32 hwc_enalbe; - osd_get_hwc_enable(&hwc_enalbe); + osd_get_hwc_enable(fb_info->node, &hwc_enalbe); return snprintf(buf, 40, "%d\n", hwc_enalbe); } @@ -3287,13 +3233,14 @@ static ssize_t store_osd_hwc_enalbe(struct device *device, struct device_attribute *attr, const char *buf, size_t count) { + struct fb_info *fb_info = dev_get_drvdata(device); int res = 0; int ret = 0; ret = kstrtoint(buf, 0, &res); if (ret < 0) return -EINVAL; - osd_set_hwc_enable(res); + osd_set_hwc_enable(fb_info->node, res); return count; } @@ -3302,6 +3249,7 @@ static ssize_t store_do_hwc(struct device *device, struct device_attribute *attr, const char *buf, size_t count) { + struct fb_info *fb_info = dev_get_drvdata(device); int res = 0; int ret = 0; @@ -3309,7 +3257,7 @@ static ssize_t store_do_hwc(struct device *device, if (ret < 0) return -EINVAL; if (res) - osd_do_hwc(); + osd_do_hwc(fb_info->node); return count; } @@ -3343,13 +3291,14 @@ static ssize_t store_osd_single_step_mode(struct device *device, struct device_attribute *attr, const char *buf, size_t count) { + struct fb_info *fb_info = dev_get_drvdata(device); int res = 0; int ret = 0; ret = kstrtoint(buf, 0, &res); if (ret < 0) return -EINVAL; - osd_set_single_step_mode(res); + osd_set_single_step_mode(fb_info->node, res); return count; } @@ -3358,13 +3307,14 @@ static ssize_t store_osd_single_step(struct device *device, struct device_attribute *attr, const char *buf, size_t count) { + struct fb_info *fb_info = dev_get_drvdata(device); int res = 0; int ret = 0; ret = kstrtoint(buf, 0, &res); if (ret < 0) return -EINVAL; - osd_set_single_step(res); + osd_set_single_step(fb_info->node, res); return count; } @@ -3473,6 +3423,33 @@ static ssize_t show_osd_status(struct device *device, fb_info->node, osd_hw.enable[fb_info->node]); } +static ssize_t show_osd_line_n_rdma( + struct device *device, struct device_attribute *attr, + char *buf) +{ + int line_n_rdma; + + line_n_rdma = osd_get_line_n_rdma(); + + return snprintf(buf, PAGE_SIZE, "0x%x\n", line_n_rdma); +} + +static ssize_t store_osd_line_n_rdma( + struct device *device, struct device_attribute *attr, + const char *buf, size_t count) +{ + int line_n_rdma; + int ret = 0; + + ret = kstrtoint(buf, 0, &line_n_rdma); + if (ret < 0) + return -EINVAL; + + osd_set_line_n_rdma(line_n_rdma); + + return count; +} + static inline int str2lower(char *str) { while (*str != '\0') { @@ -3683,7 +3660,8 @@ static struct device_attribute osd_attrs[] = { show_osd_plane_alpha, store_osd_plane_alpha), __ATTR(osd_status, 0444, show_osd_status, NULL), - + __ATTR(osd_line_n_rdma, 0644, + show_osd_line_n_rdma, store_osd_line_n_rdma), }; static struct device_attribute osd_attrs_viu2[] = { @@ -3905,6 +3883,7 @@ static struct osd_device_data_s osd_gxbb = { .vpp_fifo_len = 0x77f, .dummy_data = 0x00808000, .has_viu2 = 0, + .osd0_sc_independ = 0, }; static struct osd_device_data_s osd_gxtvbb = { @@ -3920,6 +3899,7 @@ static struct osd_device_data_s osd_gxtvbb = { .vpp_fifo_len = 0xfff, .dummy_data = 0x0, .has_viu2 = 0, + .osd0_sc_independ = 0, }; static struct osd_device_data_s osd_gxl = { @@ -3935,6 +3915,7 @@ static struct osd_device_data_s osd_gxl = { .vpp_fifo_len = 0x77f, .dummy_data = 0x00808000, .has_viu2 = 0, + .osd0_sc_independ = 0, }; static struct osd_device_data_s osd_gxm = { @@ -3950,6 +3931,7 @@ static struct osd_device_data_s osd_gxm = { .vpp_fifo_len = 0xfff, .dummy_data = 0x00202000,/* dummy data is different */ .has_viu2 = 0, + .osd0_sc_independ = 0, }; static struct osd_device_data_s osd_txl = { @@ -3965,6 +3947,7 @@ static struct osd_device_data_s osd_txl = { .vpp_fifo_len = 0x77f, .dummy_data = 0x00808000, .has_viu2 = 0, + .osd0_sc_independ = 0, }; static struct osd_device_data_s osd_txlx = { @@ -3980,6 +3963,7 @@ static struct osd_device_data_s osd_txlx = { .vpp_fifo_len = 0x77f, .dummy_data = 0x00808000, .has_viu2 = 0, + .osd0_sc_independ = 0, }; static struct osd_device_data_s osd_axg = { @@ -3996,6 +3980,7 @@ static struct osd_device_data_s osd_axg = { .vpp_fifo_len = 0x400, .dummy_data = 0x00808000, .has_viu2 = 0, + .osd0_sc_independ = 0, }; static struct osd_device_data_s osd_g12a = { @@ -4011,6 +3996,7 @@ static struct osd_device_data_s osd_g12a = { .vpp_fifo_len = 0xfff,/* 2048 */ .dummy_data = 0x00808000, .has_viu2 = 1, + .osd0_sc_independ = 0, }; static struct osd_device_data_s osd_g12b = { @@ -4026,6 +4012,7 @@ static struct osd_device_data_s osd_g12b = { .vpp_fifo_len = 0xfff,/* 2048 */ .dummy_data = 0x00808000, .has_viu2 = 1, + .osd0_sc_independ = 0, }; static struct osd_device_data_s osd_tl1 = { @@ -4041,6 +4028,39 @@ static struct osd_device_data_s osd_tl1 = { .vpp_fifo_len = 0xfff,/* 2048 */ .dummy_data = 0x00808000, .has_viu2 = 1, + .osd0_sc_independ = 0, +}; + +static struct osd_device_data_s osd_sm1 = { + .cpu_id = __MESON_CPU_MAJOR_ID_SM1, + .osd_ver = OSD_HIGH_ONE, + .afbc_type = MALI_AFBC, + .osd_count = 4, + .has_deband = 1, + .has_lut = 1, + .has_rdma = 1, + .has_dolby_vision = 1, + .osd_fifo_len = 64, /* fifo len 64*8 = 512 */ + .vpp_fifo_len = 0xfff,/* 2048 */ + .dummy_data = 0x00808000, + .has_viu2 = 1, + .osd0_sc_independ = 0, +}; + +static struct osd_device_data_s osd_tm2 = { + .cpu_id = __MESON_CPU_MAJOR_ID_TM2, + .osd_ver = OSD_HIGH_ONE, + .afbc_type = MALI_AFBC, + .osd_count = 4, + .has_deband = 1, + .has_lut = 1, + .has_rdma = 1, + .has_dolby_vision = 0, + .osd_fifo_len = 64, /* fifo len 64*8 = 512 */ + .vpp_fifo_len = 0xfff,/* 2048 */ + .dummy_data = 0x00808000, + .has_viu2 = 1, + .osd0_sc_independ = 1, }; static const struct of_device_id meson_fb_dt_match[] = { @@ -4089,6 +4109,14 @@ static const struct of_device_id meson_fb_dt_match[] = { .compatible = "amlogic, meson-tl1", .data = &osd_tl1, }, + { + .compatible = "amlogic, meson-sm1", + .data = &osd_sm1, + }, + { + .compatible = "amlogic, meson-tm2", + .data = &osd_tm2, + }, {}, }; @@ -4130,7 +4158,6 @@ static int osd_probe(struct platform_device *pdev) return -ENODEV; } } - /* get interrupt resource */ int_viu_vsync = platform_get_irq_byname(pdev, "viu-vsync"); if (int_viu_vsync == -ENXIO) { @@ -4220,24 +4247,28 @@ static int osd_probe(struct platform_device *pdev) } #endif - /* get meson-fb resource from dt */ prop = of_get_property(pdev->dev.of_node, "scale_mode", NULL); - if (prop) + if (prop) { prop_idx = of_read_ulong(prop, 1); - /* Todo: only osd0 */ - osd_set_free_scale_mode_hw(DEV_OSD0, prop_idx); + /* Todo: only osd0 */ + osd_set_free_scale_mode_hw(DEV_OSD0, prop_idx); + } + prop = of_get_property(pdev->dev.of_node, "4k2k_fb", NULL); - if (prop) + if (prop) { prop_idx = of_read_ulong(prop, 1); - osd_set_4k2k_fb_mode_hw(prop_idx); + osd_set_4k2k_fb_mode_hw(prop_idx); + } + /* get default display mode from dt */ - ret = of_property_read_string(pdev->dev.of_node, - "display_mode_default", &str); + ret = of_property_read_string(pdev->dev.of_node, "display_mode_default", &str); + prop = of_get_property(pdev->dev.of_node, "pxp_mode", NULL); - if (prop) + if (prop) { prop_idx = of_read_ulong(prop, 1); - osd_set_pxp_mode(prop_idx); + osd_set_pxp_mode(prop_idx); + } prop = of_get_property(pdev->dev.of_node, "ddr_urgent", NULL); if (prop) { @@ -4245,9 +4276,11 @@ static int osd_probe(struct platform_device *pdev) osd_set_urgent(0, (prop_idx != 0) ? 1 : 0); osd_set_urgent(1, (prop_idx != 0) ? 1 : 0); } + prop = of_get_property(pdev->dev.of_node, "mem_alloc", NULL); - if (prop) + if (prop) { b_alloc_mem = of_read_ulong(prop, 1); + } vinfo = get_current_vinfo(); for (index = 0; index < osd_meson_dev.osd_count; index++) { diff --git a/drivers/amlogic/media/osd/osd_hw.c b/drivers/amlogic/media/osd/osd_hw.c index 5e8609b3553d..6152ca9e5a6f 100644 --- a/drivers/amlogic/media/osd/osd_hw.c +++ b/drivers/amlogic/media/osd/osd_hw.c @@ -33,7 +33,7 @@ #include #include #include - +#include /* Android Headers */ /* Amlogic sync headers */ @@ -54,6 +54,7 @@ #endif #ifdef CONFIG_AMLOGIC_MEDIA_VIDEO +#include #include #endif #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION @@ -74,7 +75,6 @@ #include "osd_hw_def.h" #include "osd_fb.h" -#define OSD_BLEND_SHIFT_WORKAROUND #ifdef CONFIG_AMLOGIC_VSYNC_FIQ_ENABLE #define FIQ_VSYNC #endif @@ -107,7 +107,7 @@ static int osd_afbc_dec_enable; static int ext_canvas_id[HW_OSD_COUNT]; static int osd_extra_idx[HW_OSD_COUNT][2]; static bool suspend_flag; - +static u32 rdma_dt_cnt; static void osd_clone_pan(u32 index, u32 yoffset, int debug_flag); static void osd_set_dummy_data(u32 index, u32 alpha); @@ -323,61 +323,67 @@ static int vpp_blend_setting_default(u32 index); #ifdef CONFIG_AMLOGIC_MEDIA_FB_OSD_SYNC_FENCE /* sync fence relative varible. */ -static int timeline_created; -static void *osd_timeline; -static u32 cur_streamline_val; +static int timeline_created[VIU_COUNT]; +static void *osd_timeline[VIU_COUNT]; +static u32 cur_streamline_val[VIU_COUNT]; /* thread control part */ -struct kthread_worker buffer_toggle_worker; -struct task_struct *buffer_toggle_thread; -struct kthread_work buffer_toggle_work; -struct list_head post_fence_list; -struct mutex post_fence_list_lock; -struct osd_layers_fence_map_s map_layers; +struct kthread_worker buffer_toggle_worker[VIU_COUNT]; +struct task_struct *buffer_toggle_thread[VIU_COUNT]; +struct kthread_work buffer_toggle_work[VIU_COUNT]; +struct list_head post_fence_list[VIU_COUNT]; +struct mutex post_fence_list_lock[VIU_COUNT]; /*post fence mutex*/ +struct osd_layers_fence_map_s map_layers[VIU_COUNT]; struct file *displayed_bufs[HW_OSD_COUNT]; static void osd_pan_display_single_fence( struct osd_fence_map_s *fence_map); static void osd_pan_display_layers_fence( struct osd_layers_fence_map_s *fence_map); +static void osd_pan_display_single_fence_viu2( + struct osd_fence_map_s *fence_map); +static void osd_pan_display_layers_fence_viu2( + struct osd_layers_fence_map_s *fence_map); -static void *osd_timeline_create(void) +static void *osd_timeline_create(u32 output_index) { - const char *tlName = "osd_timeline"; + char tlname[32] = {}; - if (osd_timeline == NULL) { - if (osd_hw.hwc_enable) + sprintf(tlname, "osd_timeline_%d", output_index); + if (!osd_timeline[output_index]) { + if (osd_hw.hwc_enable[output_index]) /* present fence */ - cur_streamline_val = 0; + cur_streamline_val[output_index] = 0; else - cur_streamline_val = 1; - osd_timeline = aml_sync_create_timeline(tlName); + cur_streamline_val[output_index] = 1; + osd_timeline[output_index] = aml_sync_create_timeline(tlname); osd_tprintk("osd timeline create\n"); } - - return osd_timeline; + return osd_timeline[output_index]; } -static int osd_timeline_create_fence(void) +static int osd_timeline_create_fence(u32 output_index) { int out_fence_fd = -1; u32 pt_val = 0; - pt_val = cur_streamline_val + 1; - out_fence_fd = aml_sync_create_fence(osd_timeline, pt_val); + pt_val = cur_streamline_val[output_index] + 1; + out_fence_fd = aml_sync_create_fence + (osd_timeline[output_index], pt_val); osd_tprintk("osd created out pt:%d, fence_fd:%d\n", pt_val, out_fence_fd); if (out_fence_fd >= 0) - cur_streamline_val++; + cur_streamline_val[output_index]++; else pr_info("create fence returned %d", out_fence_fd); return out_fence_fd; } -static void osd_timeline_increase(void) +static void osd_timeline_increase(u32 output_index) { - aml_sync_inc_timeline(osd_timeline, 1); - osd_tprintk("osd out timeline inc\n"); + aml_sync_inc_timeline(osd_timeline[output_index], 1); + osd_tprintk("osd out timeline %d inc\n", output_index); + } static struct fence *osd_get_fenceobj(int fencefd) @@ -446,15 +452,22 @@ static unsigned int supsend_delay; module_param(supsend_delay, uint, 0664); MODULE_PARM_DESC(supsend_delay, "supsend_delay"); +int enable_vd_zorder = 1; +MODULE_PARM_DESC(enable_vd_zorder, "\n enable_vd_zorder\n"); +module_param(enable_vd_zorder, uint, 0664); + static int vsync_enter_line_max; static int vsync_exit_line_max; static int vsync_line_threshold = 950; +static int line_threshold = 90; MODULE_PARM_DESC(vsync_enter_line_max, "\n vsync_enter_line_max\n"); module_param(vsync_enter_line_max, uint, 0664); MODULE_PARM_DESC(vsync_exit_line_max, "\n vsync_exit_line_max\n"); module_param(vsync_exit_line_max, uint, 0664); MODULE_PARM_DESC(vsync_line_threshold, "\n vsync_line_threshold\n"); module_param(vsync_line_threshold, uint, 0664); +MODULE_PARM_DESC(line_threshold, "\n line_threshold\n"); +module_param(line_threshold, uint, 0664); static unsigned int osd_filter_coefs_bicubic_sharp[] = { 0x01fa008c, 0x01fa0100, 0xff7f0200, 0xfe7f0300, @@ -687,48 +700,44 @@ static void f2v_get_vertical_phase( static bool osd_hdr_on; #endif -static int cnt; -#ifdef CONFIG_AMLOGIC_MEDIA_FB_OSD_SYNC_FENCE static int get_encp_line(void) { int enc_line = 0; + int active_line_begin = 0; + unsigned int reg = 0; switch (osd_reg_read(VPU_VIU_VENC_MUX_CTRL) & 0x3) { case 0: - enc_line = (osd_reg_read(ENCL_INFO_READ) >> 16) & 0x1fff; + reg = osd_reg_read(ENCL_INFO_READ); + active_line_begin = + osd_reg_read(ENCL_VIDEO_VAVON_BLINE); break; case 1: - enc_line = (osd_reg_read(ENCI_INFO_READ) >> 16) & 0x1fff; + reg = osd_reg_read(ENCI_INFO_READ); + active_line_begin = + osd_reg_read(ENCI_VFIFO2VD_LINE_TOP_START); break; case 2: - enc_line = (osd_reg_read(ENCP_INFO_READ) >> 16) & 0x1fff; + reg = osd_reg_read(ENCP_INFO_READ); + active_line_begin = + osd_reg_read(ENCP_VIDEO_VAVON_BLINE); break; case 3: - enc_line = (osd_reg_read(ENCT_INFO_READ) >> 16) & 0x1fff; + reg = osd_reg_read(ENCT_INFO_READ); + active_line_begin = + osd_reg_read(ENCT_VIDEO_VAVON_BLINE); break; } + enc_line = (reg >> 16) & 0x1fff; + enc_line -= active_line_begin; return enc_line; } -#endif static int get_enter_encp_line(void) { int enc_line = 0; - switch (osd_reg_read(VPU_VIU_VENC_MUX_CTRL) & 0x3) { - case 0: - enc_line = (osd_reg_read(ENCL_INFO_READ) >> 16) & 0x1fff; - break; - case 1: - enc_line = (osd_reg_read(ENCI_INFO_READ) >> 16) & 0x1fff; - break; - case 2: - enc_line = (osd_reg_read(ENCP_INFO_READ) >> 16) & 0x1fff; - break; - case 3: - enc_line = (osd_reg_read(ENCT_INFO_READ) >> 16) & 0x1fff; - break; - } + enc_line = get_encp_line(); if (enc_line > vsync_enter_line_max) vsync_enter_line_max = enc_line; return enc_line; @@ -738,20 +747,7 @@ static int get_exit_encp_line(void) { int enc_line = 0; - switch (osd_reg_read(VPU_VIU_VENC_MUX_CTRL) & 0x3) { - case 0: - enc_line = (osd_reg_read(ENCL_INFO_READ) >> 16) & 0x1fff; - break; - case 1: - enc_line = (osd_reg_read(ENCI_INFO_READ) >> 16) & 0x1fff; - break; - case 2: - enc_line = (osd_reg_read(ENCP_INFO_READ) >> 16) & 0x1fff; - break; - case 3: - enc_line = (osd_reg_read(ENCT_INFO_READ) >> 16) & 0x1fff; - break; - } + enc_line = get_encp_line(); if (enc_line > vsync_exit_line_max) vsync_exit_line_max = enc_line; return enc_line; @@ -804,12 +800,40 @@ static void osd_vpu_power_on_viu2(void) #endif } -static int get_osd_hwc_type(void) +u32 get_output_device_id(u32 index) +{ + u32 output_index = VIU1; + + if (osd_hw.osd_meson_dev.has_viu2) { + switch (osd_hw.osd_meson_dev.cpu_id) { + case __MESON_CPU_MAJOR_ID_G12A: + case __MESON_CPU_MAJOR_ID_G12B: + if (index == osd_hw.osd_meson_dev.viu2_index) + output_index = VIU2; + else + output_index = VIU1; + break; + case __MESON_CPU_MAJOR_ID_TL1: + if (index == osd_hw.osd_meson_dev.viu2_index) + output_index = VIU2; + else + output_index = VIU1; + break; + default: + break; + } + } + return output_index; +} + +static int get_osd_hwc_type(u32 index) { int ret = 0; + u32 output_index; + output_index = get_output_device_id(index); /* new hwcomposer enable */ - if (osd_hw.hwc_enable) { + if (osd_hw.hwc_enable[output_index]) { if (osd_hw.osd_meson_dev.osd_ver == OSD_HIGH_ONE) ret = OSD_G12A_NEW_HWC; else @@ -839,10 +863,10 @@ static void osd_toggle_buffer_single(struct kthread_work *work) struct osd_fence_map_s *data, *next; struct list_head saved_list; - mutex_lock(&post_fence_list_lock); - saved_list = post_fence_list; - list_replace_init(&post_fence_list, &saved_list); - mutex_unlock(&post_fence_list_lock); + mutex_lock(&post_fence_list_lock[VIU1]); + saved_list = post_fence_list[VIU1]; + list_replace_init(&post_fence_list[VIU1], &saved_list); + mutex_unlock(&post_fence_list_lock[VIU1]); list_for_each_entry_safe(data, next, &saved_list, list) { osd_pan_display_single_fence(data); list_del(&data->list); @@ -855,10 +879,10 @@ static void osd_toggle_buffer_layers(struct kthread_work *work) struct osd_layers_fence_map_s *data, *next; struct list_head saved_list; - mutex_lock(&post_fence_list_lock); - saved_list = post_fence_list; - list_replace_init(&post_fence_list, &saved_list); - mutex_unlock(&post_fence_list_lock); + mutex_lock(&post_fence_list_lock[VIU1]); + saved_list = post_fence_list[VIU1]; + list_replace_init(&post_fence_list[VIU1], &saved_list); + mutex_unlock(&post_fence_list_lock[VIU1]); list_for_each_entry_safe(data, next, &saved_list, list) { osd_pan_display_layers_fence(data); list_del(&data->list); @@ -869,38 +893,94 @@ static void osd_toggle_buffer_layers(struct kthread_work *work) static void osd_toggle_buffer(struct kthread_work *work) { - osd_hw.osd_fence[osd_hw.hwc_enable]. - toggle_buffer_handler(work); + u32 hwc_enable; + + hwc_enable = osd_hw.hwc_enable[VIU1]; + if (osd_hw.osd_fence[VIU1][hwc_enable].toggle_buffer_handler) + osd_hw.osd_fence[VIU1][hwc_enable] + .toggle_buffer_handler(work); } -static int out_fence_create(int *release_fence_fd) +static void osd_toggle_buffer_single_viu2(struct kthread_work *work) +{ + struct osd_fence_map_s *data, *next; + struct list_head saved_list; + + mutex_lock(&post_fence_list_lock[VIU2]); + saved_list = post_fence_list[VIU2]; + list_replace_init(&post_fence_list[VIU2], &saved_list); + mutex_unlock(&post_fence_list_lock[VIU2]); + list_for_each_entry_safe(data, next, &saved_list, list) { + osd_pan_display_single_fence_viu2(data); + list_del(&data->list); + kfree(data); + } +} + +static void osd_toggle_buffer_layers_viu2(struct kthread_work *work) +{ + struct osd_layers_fence_map_s *data, *next; + struct list_head saved_list; + + mutex_lock(&post_fence_list_lock[VIU2]); + saved_list = post_fence_list[VIU2]; + list_replace_init(&post_fence_list[VIU2], &saved_list); + mutex_unlock(&post_fence_list_lock[VIU2]); + list_for_each_entry_safe(data, next, &saved_list, list) { + osd_pan_display_layers_fence_viu2(data); + list_del(&data->list); + kfree(data); + } +} + +static void osd_toggle_buffer_viu2(struct kthread_work *work) +{ + u32 hwc_enable; + + hwc_enable = osd_hw.hwc_enable[VIU2]; + if (osd_hw.osd_fence[VIU2][hwc_enable].toggle_buffer_handler) + osd_hw.osd_fence[VIU2][hwc_enable] + .toggle_buffer_handler(work); +} + +static int out_fence_create(u32 output_index, int *release_fence_fd) { int out_fence_fd = -1; struct sched_param param = {.sched_priority = 2}; + char toggle_thread_name[32] = {}; - if (!timeline_created) { + if (!timeline_created[output_index]) { /* timeline has not been created */ - if (osd_timeline_create()) { - kthread_init_worker(&buffer_toggle_worker); - buffer_toggle_thread = kthread_run( + if (osd_timeline_create(output_index)) { + kthread_init_worker + (&buffer_toggle_worker[output_index]); + sprintf(toggle_thread_name, + "aml_buf_toggle_%d", output_index); + buffer_toggle_thread[output_index] = kthread_run( kthread_worker_fn, - &buffer_toggle_worker, - "aml_buf_toggle"); - if (IS_ERR(buffer_toggle_thread)) { + &buffer_toggle_worker[output_index], + toggle_thread_name); + if (IS_ERR(buffer_toggle_thread[output_index])) { osd_log_err("create osd toggle kthread failed"); return -1; } - sched_setscheduler(buffer_toggle_thread, - SCHED_FIFO, ¶m); - kthread_init_work( - &buffer_toggle_work, osd_toggle_buffer); - timeline_created = 1; + sched_setscheduler(buffer_toggle_thread[output_index], + SCHED_FIFO, ¶m); + if (output_index == VIU1) + kthread_init_work( + &buffer_toggle_work[output_index], + osd_toggle_buffer); + else if (output_index == VIU2) + kthread_init_work( + &buffer_toggle_work[output_index], + osd_toggle_buffer_viu2); + timeline_created[output_index] = 1; } } /* hwc_enable disable create fence every time */ - if (!osd_hw.hwc_enable) { - out_fence_fd = osd_timeline_create_fence(); + if (!osd_hw.hwc_enable[output_index]) { + out_fence_fd = osd_timeline_create_fence(output_index); if (out_fence_fd < 0) { osd_log_err("fence obj create fail\n"); out_fence_fd = -1; @@ -909,15 +989,16 @@ static int out_fence_create(int *release_fence_fd) /* hwc_enable enable create fence * when first sync request called */ - if (osd_hw.out_fence_fd == -1) { - out_fence_fd = osd_timeline_create_fence(); + if (osd_hw.out_fence_fd[output_index] == -1) { + out_fence_fd = osd_timeline_create_fence(output_index); if (out_fence_fd < 0) { osd_log_err("fence obj create fail\n"); out_fence_fd = -1; } - osd_hw.out_fence_fd = out_fence_fd; - } else - out_fence_fd = osd_hw.out_fence_fd; + osd_hw.out_fence_fd[output_index] = out_fence_fd; + } else { + out_fence_fd = osd_hw.out_fence_fd[output_index]; + } } if (release_fence_fd) *release_fence_fd = out_fence_fd; @@ -929,17 +1010,19 @@ int osd_sync_request(u32 index, u32 yres, struct fb_sync_request_s *request) int out_fence_fd = -1; int buf_num = 0; int in_fence_fd = -1; + u32 output_index = 0; struct osd_fence_map_s *fence_map = kzalloc(sizeof(struct osd_fence_map_s), GFP_KERNEL); - osd_hw.hwc_enable = 0; + output_index = get_output_device_id(index); + osd_hw.hwc_enable[output_index] = 0; if (request->sync_req.magic == FB_SYNC_REQUEST_MAGIC) { buf_num = find_buf_num(yres, request->sync_req.yoffset); if (!fence_map) { osd_log_err("could not allocate osd_fence_map\n"); return -ENOMEM; } - mutex_lock(&post_fence_list_lock); + mutex_lock(&post_fence_list_lock[output_index]); fence_map->op = 0xffffffff; fence_map->fb_index = index; fence_map->buf_num = buf_num; @@ -953,14 +1036,14 @@ int osd_sync_request(u32 index, u32 yres, struct fb_sync_request_s *request) fence_map->in_fence = osd_get_fenceobj( request->sync_req.in_fen_fd); fence_map->out_fd = - out_fence_create(&out_fence_fd); + out_fence_create(output_index, &out_fence_fd); } else { buf_num = find_buf_num(yres, request->sync_req_old.yoffset); if (!fence_map) { osd_log_err("could not allocate osd_fence_map\n"); return -ENOMEM; } - mutex_lock(&post_fence_list_lock); + mutex_lock(&post_fence_list_lock[output_index]); fence_map->op = 0xffffffff; fence_map->fb_index = index; fence_map->buf_num = buf_num; @@ -973,11 +1056,12 @@ int osd_sync_request(u32 index, u32 yres, struct fb_sync_request_s *request) fence_map->in_fence = osd_get_fenceobj( request->sync_req_old.in_fen_fd); fence_map->out_fd = - out_fence_create(&out_fence_fd); + out_fence_create(output_index, &out_fence_fd); } - list_add_tail(&fence_map->list, &post_fence_list); - mutex_unlock(&post_fence_list_lock); - kthread_queue_work(&buffer_toggle_worker, &buffer_toggle_work); + list_add_tail(&fence_map->list, &post_fence_list[output_index]); + mutex_unlock(&post_fence_list_lock[output_index]); + kthread_queue_work(&buffer_toggle_worker[output_index], + &buffer_toggle_work[output_index]); if (in_fence_fd >= 0) __close_fd(current->files, in_fence_fd); return out_fence_fd; @@ -992,6 +1076,7 @@ static int sync_render_single_fence(u32 index, u32 yres, int out_fence_fd = -1; int buf_num = 0; u32 xoffset, yoffset; + u32 output_index = 0; struct osd_fence_map_s *fence_map = NULL; if (index > OSD1) @@ -1004,7 +1089,8 @@ static int sync_render_single_fence(u32 index, u32 yres, osd_log_err("could not allocate osd_fence_map\n"); return -ENOMEM; } - mutex_lock(&post_fence_list_lock); + output_index = get_output_device_id(index); + mutex_lock(&post_fence_list_lock[output_index]); fence_map->op = 0xffffffff; fence_map->fb_index = index; fence_map->buf_num = buf_num; @@ -1032,13 +1118,15 @@ static int sync_render_single_fence(u32 index, u32 yres, osd_tprintk("direct render fence fd:%d\n", fence_map->in_fd); fence_map->in_fence = osd_get_fenceobj(fence_map->in_fd); fence_map->out_fd = - out_fence_create(&out_fence_fd); + out_fence_create(output_index, &out_fence_fd); /* Todo: */ - list_add_tail(&fence_map->list, &post_fence_list); - mutex_unlock(&post_fence_list_lock); - kthread_queue_work(&buffer_toggle_worker, &buffer_toggle_work); + list_add_tail(&fence_map->list, &post_fence_list[output_index]); + mutex_unlock(&post_fence_list_lock[output_index]); + kthread_queue_work(&buffer_toggle_worker[output_index], + &buffer_toggle_work[output_index]); request->out_fen_fd = out_fence_fd; - __close_fd(current->files, request->in_fen_fd); + if (request->in_fen_fd >= 0) + __close_fd(current->files, request->in_fen_fd); return out_fence_fd; } @@ -1049,17 +1137,19 @@ static int sync_render_layers_fence(u32 index, u32 yres, { int out_fence_fd = -1; s32 in_fence_fd; + u32 output_index = 0; struct osd_layers_fence_map_s *fence_map = NULL; if (index > OSD_MAX) return -1; + output_index = get_output_device_id(index); in_fence_fd = request->in_fen_fd; - mutex_lock(&post_fence_list_lock); - fence_map = &map_layers; + mutex_lock(&post_fence_list_lock[output_index]); + fence_map = &map_layers[output_index]; fence_map->cmd = LAYER_SYNC; fence_map->layer_map[index].fb_index = index; /* layer_map[index].enable will update if have blank ioctl */ - fence_map->layer_map[index].enable = 1; + fence_map->layer_map[index].enable = request->op; fence_map->layer_map[index].in_fd = request->in_fen_fd; if (request->shared_fd < 0) fence_map->layer_map[index].buf_file = NULL; @@ -1068,6 +1158,8 @@ static int sync_render_layers_fence(u32 index, u32 yres, fence_map->layer_map[index].ext_addr = phys_addr; fence_map->layer_map[index].format = request->format; fence_map->layer_map[index].compose_type = request->type; + fence_map->layer_map[index].fb_width = request->fb_width; + fence_map->layer_map[index].fb_height = request->fb_height; fence_map->layer_map[index].src_x = request->xoffset; fence_map->layer_map[index].src_y = request->yoffset; fence_map->layer_map[index].src_w = request->width; @@ -1094,15 +1186,17 @@ static int sync_render_layers_fence(u32 index, u32 yres, /* no longer put list, will put them via do_hwc */ fence_map->layer_map[index].in_fence = osd_get_fenceobj(in_fence_fd); fence_map->layer_map[index].out_fd = - out_fence_create(&out_fence_fd); - mutex_unlock(&post_fence_list_lock); + out_fence_create(output_index, &out_fence_fd); + mutex_unlock(&post_fence_list_lock[output_index]); osd_log_dbg(MODULE_FENCE, "sync_render_layers_fence:osd%d: ind_fd=%d,out_fd=%d\n", fence_map->layer_map[index].fb_index, fence_map->layer_map[index].in_fd, fence_map->layer_map[index].out_fd); request->out_fen_fd = out_fence_fd; - __close_fd(current->files, in_fence_fd); - __close_fd(current->files, request->shared_fd); + if (in_fence_fd >= 0) + __close_fd(current->files, in_fence_fd); + if (request->shared_fd >= 0) + __close_fd(current->files, request->shared_fd); return out_fence_fd; } @@ -1111,49 +1205,53 @@ int osd_sync_request_render(u32 index, u32 yres, u32 phys_addr, size_t len) { - int line; + int line, hwc_enable; + u32 output_index = 0; - cnt++; line = get_encp_line(); + output_index = get_output_device_id(index); osd_log_dbg2(MODULE_RENDER, - "enter osd_sync_request_render:cnt=%d,encp line=%d\n", - cnt, line); + "enter osd_sync_request_render:encp line=%d\n", + line); if (request->magic == FB_SYNC_REQUEST_RENDER_MAGIC_V1) - osd_hw.hwc_enable = 0; + osd_hw.hwc_enable[output_index] = 0; else if (request->magic == FB_SYNC_REQUEST_RENDER_MAGIC_V2) - osd_hw.hwc_enable = 1; - if (index == OSD4) - osd_hw.viu_type = VIU2; - else - osd_hw.viu_type = VIU1; - osd_hw.osd_fence[osd_hw.hwc_enable].sync_fence_handler( - index, yres, request, phys_addr, len); + osd_hw.hwc_enable[output_index] = 1; + output_index = get_output_device_id(index); + hwc_enable = osd_hw.hwc_enable[output_index]; + + if (osd_hw.osd_fence[output_index][hwc_enable].sync_fence_handler) + osd_hw.osd_fence[output_index][hwc_enable] + .sync_fence_handler(index, yres, + request, phys_addr, len); return request->out_fen_fd; } -int osd_sync_do_hwc(struct do_hwc_cmd_s *hwc_cmd) +int osd_sync_do_hwc(u32 index, struct do_hwc_cmd_s *hwc_cmd) { int out_fence_fd = -1; struct osd_layers_fence_map_s *fence_map = NULL; int line; + u32 output_index = 0; + output_index = get_output_device_id(index); line = get_encp_line(); osd_log_dbg2(MODULE_RENDER, - "enter osd_sync_do_hwc:cnt=%d,encp line=%d\n", - cnt, line); + "enter osd_sync_do_hwc:encp line=%d\n", + line); fence_map = kzalloc( sizeof(struct osd_layers_fence_map_s), GFP_KERNEL); if (!fence_map) return -ENOMEM; - osd_hw.hwc_enable = 1; - mutex_lock(&post_fence_list_lock); - memcpy(fence_map, &map_layers, - sizeof(struct osd_layers_fence_map_s)); + osd_hw.hwc_enable[output_index] = 1; + mutex_lock(&post_fence_list_lock[output_index]); + memcpy(fence_map, &map_layers[output_index], + sizeof(struct osd_layers_fence_map_s)); /* clear map_layers, need alloc next add_sync ioctl */ - memset(&map_layers, 0, - sizeof(struct osd_layers_fence_map_s)); + memset(&map_layers[output_index], 0, + sizeof(struct osd_layers_fence_map_s)); fence_map->out_fd = - out_fence_create(&out_fence_fd); + out_fence_create(output_index, &out_fence_fd); fence_map->disp_info.background_w = hwc_cmd->disp_info.background_w; fence_map->disp_info.background_h = @@ -1172,12 +1270,14 @@ int osd_sync_do_hwc(struct do_hwc_cmd_s *hwc_cmd) hwc_cmd->disp_info.position_h; fence_map->hdr_mode = hwc_cmd->hdr_mode; /* other info set via add_sync and blank ioctl */ - list_add_tail(&fence_map->list, &post_fence_list); + list_add_tail(&fence_map->list, &post_fence_list[output_index]); /* after do_hwc, clear osd_hw.out_fence_fd */ - if (timeline_created && osd_hw.out_fence_fd) - osd_hw.out_fence_fd = -1; - mutex_unlock(&post_fence_list_lock); - kthread_queue_work(&buffer_toggle_worker, &buffer_toggle_work); + if (timeline_created[output_index] && + osd_hw.out_fence_fd[output_index]) + osd_hw.out_fence_fd[output_index] = -1; + mutex_unlock(&post_fence_list_lock[output_index]); + kthread_queue_work(&buffer_toggle_worker[output_index], + &buffer_toggle_work[output_index]); if (get_logo_loaded()) { int logo_index; @@ -1251,7 +1351,7 @@ int osd_sync_request_render(u32 index, u32 yres, return -5566; } -int osd_sync_do_hwc(struct do_hwc_cmd_s *hwc_cmd) +int osd_sync_do_hwc(u32 output_index, struct do_hwc_cmd_s *hwc_cmd) { osd_log_err("osd_do_hwc not supported\n"); return -5566; @@ -1261,7 +1361,10 @@ int osd_sync_do_hwc(struct do_hwc_cmd_s *hwc_cmd) void osd_set_enable_hw(u32 index, u32 enable) { - if (osd_hw.hwc_enable) { + u32 output_index = 0; + + output_index = get_output_device_id(index); + if (osd_hw.hwc_enable[output_index]) { if (index > OSD_MAX) return; if ((osd_hw.osd_meson_dev.osd_ver < OSD_HIGH_ONE) @@ -1269,11 +1372,13 @@ void osd_set_enable_hw(u32 index, u32 enable) osd_enable_hw(index, enable); else { #ifdef CONFIG_AMLOGIC_MEDIA_FB_OSD_SYNC_FENCE - mutex_lock(&post_fence_list_lock); - map_layers.layer_map[index].fb_index = index; - map_layers.layer_map[index].enable = enable; - map_layers.cmd = BLANK_CMD; - mutex_unlock(&post_fence_list_lock); + mutex_lock(&post_fence_list_lock[output_index]); + map_layers[output_index].layer_map[index] + .fb_index = index; + map_layers[output_index].layer_map[index] + .enable = enable; + map_layers[output_index].cmd = BLANK_CMD; + mutex_unlock(&post_fence_list_lock[output_index]); osd_log_dbg(MODULE_BASE, "osd_set_enable_hw: osd%d,enable=%d\n", index, enable); #endif @@ -1674,6 +1779,8 @@ static u32 osd_get_hw_reset_flag(void) case __MESON_CPU_MAJOR_ID_G12A: case __MESON_CPU_MAJOR_ID_G12B: case __MESON_CPU_MAJOR_ID_TL1: + case __MESON_CPU_MAJOR_ID_SM1: + case __MESON_CPU_MAJOR_ID_TM2: { int i, afbc_enable = 0; @@ -1893,8 +2000,16 @@ void osd_wait_vsync_hw(void) if (pxp_mode) timeout = msecs_to_jiffies(50); - else - timeout = msecs_to_jiffies(1000); + else { + struct vinfo_s *vinfo; + + vinfo = get_current_vinfo(); + if (vinfo && (!strcmp(vinfo->name, "invalid") || + !strcmp(vinfo->name, "null"))) { + timeout = msecs_to_jiffies(1); + } else + timeout = msecs_to_jiffies(1000); + } wait_event_interruptible_timeout( osd_vsync_wq, vsync_hit, timeout); } @@ -1919,6 +2034,8 @@ s64 osd_wait_vsync_event(void) int is_interlaced(struct vinfo_s *vinfo) { + if (!vinfo) + return 0; if (vinfo->mode == VMODE_CVBS) return 1; if (vinfo->height != vinfo->field_height) @@ -1929,12 +2046,19 @@ int is_interlaced(struct vinfo_s *vinfo) int osd_set_scan_mode(u32 index) { - struct vinfo_s *vinfo; + struct vinfo_s *vinfo = NULL; u32 data32 = 0x0; s32 y_end = 0; + u32 output_index; + output_index = get_output_device_id(index); osd_hw.scan_mode[index] = SCAN_MODE_PROGRESSIVE; - vinfo = get_current_vinfo(); + if (output_index == VIU1) + vinfo = get_current_vinfo(); +#ifdef CONFIG_AMLOGIC_VOUT2_SERVE + else if (output_index == VIU2) + vinfo = get_current_vinfo2(); +#endif if (vinfo && (strcmp(vinfo->name, "invalid") && strcmp(vinfo->name, "null"))) { osd_hw.scale_workaround = 0; @@ -1950,7 +2074,7 @@ int osd_set_scan_mode(u32 index) if ((vinfo->width == 720) && (vinfo->height == 480)) { if (osd_hw.free_scale_mode[index]) { - osd_hw.field_out_en = 1; + osd_hw.field_out_en[output_index] = 1; switch (y_end) { case 719: osd_hw.bot_type = 2; @@ -1970,7 +2094,7 @@ int osd_set_scan_mode(u32 index) } else if ((vinfo->width == 720) && (vinfo->height == 576)) { if (osd_hw.free_scale_mode[index]) { - osd_hw.field_out_en = 1; + osd_hw.field_out_en[output_index] = 1; switch (y_end) { case 719: osd_hw.bot_type = 2; @@ -1991,7 +2115,7 @@ int osd_set_scan_mode(u32 index) } else if ((vinfo->width == 1920) && (vinfo->height == 1080)) { if (osd_hw.free_scale_mode[index]) { - osd_hw.field_out_en = 1; + osd_hw.field_out_en[output_index] = 1; switch (y_end) { case 719: osd_hw.bot_type = 1; @@ -2014,7 +2138,7 @@ int osd_set_scan_mode(u32 index) && (osd_hw.free_scale_enable[index])) if (!(osd_hw.osd_meson_dev.afbc_type)) osd_hw.scale_workaround = 1; - osd_hw.field_out_en = 0; + osd_hw.field_out_en[output_index] = 0; } else if (((vinfo->width == 720) && (vinfo->height == 480)) || ((vinfo->width == 720) @@ -2024,10 +2148,10 @@ int osd_set_scan_mode(u32 index) osd_v_filter_mode = 6; } if (osd_hw.free_scale_mode[index]) - osd_hw.field_out_en = 0; + osd_hw.field_out_en[output_index] = 0; } else { if (osd_hw.free_scale_mode[index]) - osd_hw.field_out_en = 0; + osd_hw.field_out_en[output_index] = 0; } } } @@ -2066,6 +2190,22 @@ u32 osd_get_gbl_alpha_hw(u32 index) return osd_hw.gbl_alpha[index]; } +void osd_set_line_n_rdma(u32 line_n_rdma) +{ + if (osd_hw.line_n_rdma != line_n_rdma) { + osd_hw.line_n_rdma = line_n_rdma; + if (osd_hw.line_n_rdma) + enable_line_n_rdma(); + else + enable_vsync_rdma(); + } +} + +u32 osd_get_line_n_rdma(void) +{ + return osd_hw.line_n_rdma; +} + void osd_set_color_key_hw(u32 index, u32 color_index, u32 colorkey) { u8 r = 0, g = 0, b = 0, a = (colorkey & 0xff000000) >> 24; @@ -2441,7 +2581,10 @@ static void osd_set_free_scale_enable_mode1(u32 index, u32 enable) void osd_set_free_scale_enable_hw(u32 index, u32 enable) { - if (osd_hw.free_scale_mode[index] && (index != OSD4)) { + if (osd_hw.free_scale_mode[index] + && (osd_hw.osd_meson_dev.has_viu2 ? + ((index != osd_hw.osd_meson_dev.viu2_index) ? + 1 : 0) : 1)) { osd_set_free_scale_enable_mode1(index, enable); if (osd_hw.osd_meson_dev.osd_ver == OSD_NORMAL) { u32 height_dst, height_src; @@ -2536,11 +2679,18 @@ void osd_set_scale_axis_hw(u32 index, s32 x0, s32 y0, s32 x1, s32 y1) void osd_get_window_axis_hw(u32 index, s32 *x0, s32 *y0, s32 *x1, s32 *y1) { - struct vinfo_s *vinfo; + struct vinfo_s *vinfo = NULL; s32 height; + u32 output_index; + output_index = get_output_device_id(index); if (osd_hw.osd_meson_dev.osd_ver <= OSD_NORMAL) { - vinfo = get_current_vinfo(); + if (output_index == VIU1) + vinfo = get_current_vinfo(); +#ifdef CONFIG_AMLOGIC_VOUT2_SERVE + else if (output_index == VIU2) + vinfo = get_current_vinfo2(); +#endif if (vinfo && (strcmp(vinfo->name, "invalid") && strcmp(vinfo->name, "null"))) { if (is_interlaced(vinfo)) { @@ -2576,15 +2726,17 @@ void osd_get_window_axis_hw(u32 index, s32 *x0, s32 *y0, s32 *x1, s32 *y1) void osd_set_window_axis_hw(u32 index, s32 x0, s32 y0, s32 x1, s32 y1) { - struct vinfo_s *vinfo; + struct vinfo_s *vinfo = NULL; s32 temp_y0, temp_y1; + u32 output_index; - #if 0 - if (osd_hw.hwc_enable && - (osd_hw.osd_display_debug != OSD_DISP_DEBUG)) - return; - #endif - vinfo = get_current_vinfo(); + output_index = get_output_device_id(index); + if (output_index == VIU1) + vinfo = get_current_vinfo(); +#ifdef CONFIG_AMLOGIC_VOUT2_SERVE + else if (output_index == VIU2) + vinfo = get_current_vinfo2(); +#endif mutex_lock(&osd_mutex); if (vinfo && (strcmp(vinfo->name, "invalid") && strcmp(vinfo->name, "null"))) { @@ -2621,13 +2773,12 @@ void osd_set_window_axis_hw(u32 index, s32 x0, s32 y0, s32 x1, s32 y1) if (osd_hw.free_dst_data[index].y_end >= 2159) osd_set_dummy_data(index, 0xff); osd_update_window_axis = true; - if (osd_hw.hwc_enable && - (osd_hw.osd_display_debug == OSD_DISP_DEBUG)) - osd_setting_blend(); + if (osd_hw.hwc_enable[output_index] && + (osd_hw.osd_display_debug == OSD_DISP_DEBUG)) + osd_setting_blend(output_index); mutex_unlock(&osd_mutex); } - s32 osd_get_position_from_reg( u32 index, s32 *src_x_start, s32 *src_x_end, @@ -2773,6 +2924,7 @@ void osd_enable_hw(u32 index, u32 enable) { int i = 0; int count = (pxp_mode == 1)?3:WAIT_AFBC_READY_COUNT; + u32 output_index; if (index == 0) { osd_log_info("osd[%d] enable: %d (%s)\n", @@ -2784,8 +2936,8 @@ void osd_enable_hw(u32 index, u32 enable) /* reset viu 31bit ?? */ if (!osd_hw.enable[index] && - osd_hw.osd_afbcd[index].enable && enable - && (get_osd_hwc_type() != OSD_G12A_NEW_HWC)) { + osd_hw.osd_afbcd[index].enable && enable && + (get_osd_hwc_type(index) != OSD_G12A_NEW_HWC)) { spin_lock_irqsave(&osd_lock, lock_flags); if (osd_hw.osd_meson_dev.afbc_type == MESON_AFBC) { osd_reg_write(VIU_SW_RESET, 0x80000000); @@ -2800,23 +2952,26 @@ void osd_enable_hw(u32 index, u32 enable) add_to_update_list(index, OSD_GBL_ALPHA); add_to_update_list(index, DISP_GEOMETRY); osd_wait_vsync_hw(); - } - while ((index == 0) && osd_hw.osd_afbcd[index].enable && + while ((index == 0) && osd_hw.osd_afbcd[index].enable && (osd_hw.osd_afbcd[index].phy_addr == 0) && enable && (i < count)) { - osd_wait_vsync_hw(); - i++; + osd_wait_vsync_hw(); + i++; + } + if (i > 0) + osd_log_info("osd[%d]: wait %d vsync first buffer ready.\n", + index, i); } - if (i > 0) - osd_log_info("osd[%d]: wait %d vsync first buffer ready.\n", - index, i); + osd_hw.enable[index] = enable; - if (get_osd_hwc_type() != OSD_G12A_NEW_HWC) { + output_index = get_output_device_id(index); + if (get_osd_hwc_type(index) != OSD_G12A_NEW_HWC) { add_to_update_list(index, OSD_ENABLE); osd_wait_vsync_hw(); - } else if (osd_hw.hwc_enable && osd_hw.osd_display_debug) - osd_setting_blend(); + } else if (osd_hw.hwc_enable[output_index] && + osd_hw.osd_display_debug) + osd_setting_blend(output_index); } void osd_set_2x_scale_hw(u32 index, u16 h_scale_enable, u16 v_scale_enable) @@ -2845,11 +3000,20 @@ void osd_set_2x_scale_hw(u32 index, u16 h_scale_enable, u16 v_scale_enable) osd_wait_vsync_hw(); } -void osd_get_flush_rate_hw(u32 *break_rate) +void osd_get_flush_rate_hw(u32 index, u32 *break_rate) { - const struct vinfo_s *vinfo; + const struct vinfo_s *vinfo = NULL; + u32 output_index; - vinfo = get_current_vinfo(); + output_index = get_output_device_id(index); + if (output_index == VIU1) + vinfo = get_current_vinfo(); +#ifdef CONFIG_AMLOGIC_VOUT2_SERVE + else if (output_index == VIU2) + vinfo = get_current_vinfo2(); +#endif + if (!vinfo) + return; *break_rate = vinfo->sync_duration_num / vinfo->sync_duration_den; } @@ -3006,34 +3170,35 @@ void osd_switch_free_scale( int i = 0; int count = (pxp_mode == 1)?3:WAIT_AFBC_READY_COUNT; - if (osd_hw.osd_meson_dev.osd_ver == OSD_HIGH_ONE) - return; osd_log_info("osd[%d] enable: %d scale:0x%x (%s)\n", pre_index, pre_enable, pre_scale, current->comm); osd_log_info("osd[%d] enable: %d scale:0x%x (%s)\n", next_index, next_enable, next_scale, current->comm); if (osd_hw.free_scale_mode[pre_index] || osd_hw.free_scale_mode[next_index]) { - while ((next_index == OSD1) - && osd_hw.osd_afbcd[next_index].enable - && (osd_hw.osd_afbcd[next_index].phy_addr == 0) - && next_enable && (i < count)) { - osd_wait_vsync_hw(); - i++; + if (osd_hw.osd_meson_dev.osd_ver == OSD_NORMAL) { + while ((next_index == OSD1) + && osd_hw.osd_afbcd[next_index].enable + && (osd_hw.osd_afbcd[next_index].phy_addr == 0) + && next_enable && (i < count)) { + osd_wait_vsync_hw(); + i++; + } + if (i > 0) + osd_log_info("osd[%d]: wait %d vsync first buffer ready.\n", + next_index, i); + } + if (pre_index != next_index) { + h_enable = (pre_scale & 0xffff0000 ? 1 : 0); + v_enable = (pre_scale & 0xffff ? 1 : 0); + osd_hw.free_scale[pre_index].h_enable = h_enable; + osd_hw.free_scale[pre_index].v_enable = v_enable; + osd_hw.free_scale_enable[pre_index] = pre_scale; + osd_hw.free_scale_backup[pre_index].h_enable = h_enable; + osd_hw.free_scale_backup[pre_index].v_enable = v_enable; + osd_hw.free_scale_enable_backup[pre_index] = pre_scale; + osd_hw.enable[pre_index] = pre_enable; } - if (i > 0) - osd_log_info("osd[%d]: wait %d vsync first buffer ready.\n", - next_index, i); - h_enable = (pre_scale & 0xffff0000 ? 1 : 0); - v_enable = (pre_scale & 0xffff ? 1 : 0); - osd_hw.free_scale[pre_index].h_enable = h_enable; - osd_hw.free_scale[pre_index].v_enable = v_enable; - osd_hw.free_scale_enable[pre_index] = pre_scale; - osd_hw.free_scale_backup[pre_index].h_enable = h_enable; - osd_hw.free_scale_backup[pre_index].v_enable = v_enable; - osd_hw.free_scale_enable_backup[pre_index] = pre_scale; - osd_hw.enable[pre_index] = pre_enable; - h_enable = (next_scale & 0xffff0000 ? 1 : 0); v_enable = (next_scale & 0xffff ? 1 : 0); osd_hw.free_scale[next_index].h_enable = h_enable; @@ -3054,14 +3219,16 @@ void osd_switch_free_scale( osd_afbc_dec_enable = 0; osd_hw.reg[OSD_GBL_ALPHA].update_func(next_index); } - - osd_hw.reg[OSD_COLOR_MODE].update_func(pre_index); - if (pre_scale) - osd_hw.reg[OSD_FREESCALE_COEF].update_func(pre_index); - osd_hw.reg[DISP_GEOMETRY].update_func(pre_index); - osd_hw.reg[DISP_FREESCALE_ENABLE].update_func(pre_index); - osd_hw.reg[OSD_ENABLE].update_func(pre_index); - + if (pre_index != next_index) { + osd_hw.reg[OSD_COLOR_MODE].update_func(pre_index); + if (pre_scale) + osd_hw.reg[OSD_FREESCALE_COEF]. + update_func(pre_index); + osd_hw.reg[DISP_GEOMETRY].update_func(pre_index); + osd_hw.reg[DISP_FREESCALE_ENABLE]. + update_func(pre_index); + osd_hw.reg[OSD_ENABLE].update_func(pre_index); + } osd_hw.reg[OSD_COLOR_MODE].update_func(next_index); if (next_scale) osd_hw.reg @@ -3073,7 +3240,8 @@ void osd_switch_free_scale( spin_unlock_irqrestore(&osd_lock, lock_flags); osd_wait_vsync_hw(); } else { - osd_enable_hw(pre_index, pre_enable); + if (pre_index != next_index) + osd_enable_hw(pre_index, pre_enable); osd_enable_hw(next_index, next_enable); } } @@ -3130,26 +3298,33 @@ void osd_set_deband(u32 osd_deband_enable) } -void osd_get_fps(u32 *osd_fps) +void osd_get_fps(u32 index, u32 *osd_fps) { - *osd_fps = osd_hw.osd_fps; + u32 output_index; + + output_index = get_output_device_id(index); + *osd_fps = osd_hw.osd_fps[output_index]; + } -void osd_set_fps(u32 osd_fps_start) +void osd_set_fps(u32 index, u32 osd_fps_start) { static int stime, etime; + u32 output_index; - osd_hw.osd_fps_start = osd_fps_start; + output_index = get_output_device_id(index); + osd_hw.osd_fps_start[output_index] = osd_fps_start; if (osd_fps_start) { /* start to calc fps */ stime = ktime_to_us(ktime_get()); - osd_hw.osd_fps = 0; + osd_hw.osd_fps[output_index] = 0; } else { /* stop to calc fps */ etime = ktime_to_us(ktime_get()); - osd_hw.osd_fps = (osd_hw.osd_fps * 1000000) + osd_hw.osd_fps[output_index] = + (osd_hw.osd_fps[output_index] * 1000000) / (etime - stime); - osd_log_info("osd fps:=%d\n", osd_hw.osd_fps); + osd_log_info("osd fps:=%d\n", osd_hw.osd_fps[output_index]); } } @@ -3163,16 +3338,22 @@ void osd_set_display_debug(u32 osd_display_debug_enable) osd_hw.osd_display_debug = osd_display_debug_enable; } -void osd_get_background_size(struct display_flip_info_s *disp_info) +void osd_get_background_size(u32 index, struct display_flip_info_s *disp_info) { - memcpy(disp_info, &osd_hw.disp_info, - sizeof(struct display_flip_info_s)); + u32 output_index; + + output_index = get_output_device_id(index); + memcpy(disp_info, &osd_hw.disp_info[output_index], + sizeof(struct display_flip_info_s)); } -void osd_set_background_size(struct display_flip_info_s *disp_info) +void osd_set_background_size(u32 index, struct display_flip_info_s *disp_info) { - memcpy(&osd_hw.disp_info, disp_info, - sizeof(struct display_flip_info_s)); + u32 output_index; + + output_index = get_output_device_id(index); + memcpy(&osd_hw.disp_info[output_index], disp_info, + sizeof(struct display_flip_info_s)); } void osd_get_hdr_used(u32 *val) @@ -3197,22 +3378,31 @@ void osd_set_afbc_format(u32 index, u32 format, u32 inter_format) osd_hw.osd_afbcd[index].inter_format = inter_format; } -void osd_get_hwc_enable(u32 *hwc_enable) +void osd_get_hwc_enable(u32 index, u32 *hwc_enable) { - *hwc_enable = osd_hw.hwc_enable; + u32 output_index; + + output_index = get_output_device_id(index); + *hwc_enable = osd_hw.hwc_enable[output_index]; } -void osd_set_hwc_enable(u32 hwc_enable) +void osd_set_hwc_enable(u32 index, u32 hwc_enable) { - osd_hw.hwc_enable = hwc_enable; + u32 output_index; + + output_index = get_output_device_id(index); + osd_hw.hwc_enable[output_index] = hwc_enable; /* setting default hwc path */ if (!hwc_enable) - osd_setting_blend(); + osd_setting_blend(OSD1); } -void osd_do_hwc(void) +void osd_do_hwc(u32 index) { - osd_setting_blend(); + u32 output_index; + + output_index = get_output_device_id(index); + osd_setting_blend(output_index); } static void osd_set_two_ports(bool set) @@ -3252,26 +3442,36 @@ void osd_set_urgent_info(u32 ports, u32 basic_urgent) osd_set_two_ports(osd_hw.two_ports); } -void osd_set_single_step_mode(u32 osd_single_step_mode) +void osd_set_single_step_mode(u32 index, u32 osd_single_step_mode) { + u32 output_index; + + output_index = get_output_device_id(index); + if (output_index != VIU1) + return; osd_hw.osd_debug.osd_single_step_mode = osd_single_step_mode; if ((osd_hw.osd_debug.wait_fence_release) && (osd_hw.osd_debug.osd_single_step_mode == 0)) { #ifdef CONFIG_AMLOGIC_MEDIA_FB_OSD_SYNC_FENCE - osd_timeline_increase(); + osd_timeline_increase(output_index); #endif osd_hw.osd_debug.wait_fence_release = false; } } -void osd_set_single_step(u32 osd_single_step) +void osd_set_single_step(u32 index, u32 osd_single_step) { + u32 output_index; + + output_index = get_output_device_id(index); + if (output_index != VIU1) + return; osd_hw.osd_debug.osd_single_step = osd_single_step; if ((osd_hw.osd_debug.wait_fence_release) && (osd_hw.osd_debug.osd_single_step > 0)) { #ifdef CONFIG_AMLOGIC_MEDIA_FB_OSD_SYNC_FENCE - osd_timeline_increase(); + osd_timeline_increase(output_index); #endif osd_hw.osd_debug.wait_fence_release = false; } @@ -3714,30 +3914,30 @@ static bool osd_direct_compose_pan_display(struct osd_fence_map_s *fence_map) height_dst) / height_src - 1; if (osd_hw.osd_reverse[index] == REVERSE_TRUE) { - x_start = osd_hw.vinfo_width + x_start = osd_hw.vinfo_width[VIU1] - freescale_dst[index].x_end - 1; - y_start = osd_hw.vinfo_height + y_start = osd_hw.vinfo_height[VIU1] - freescale_dst[index].y_end - 1; - x_end = osd_hw.vinfo_width + x_end = osd_hw.vinfo_width[VIU1] - freescale_dst[index].x_start - 1; - y_end = osd_hw.vinfo_height + y_end = osd_hw.vinfo_height[VIU1] - freescale_dst[index].y_start - 1; freescale_dst[index].x_start = x_start; freescale_dst[index].y_start = y_start; freescale_dst[index].x_end = x_end; freescale_dst[index].y_end = y_end; } else if (osd_hw.osd_reverse[index] == REVERSE_X) { - x_start = osd_hw.vinfo_width + x_start = osd_hw.vinfo_width[VIU1] - freescale_dst[index].x_end - 1; - x_end = osd_hw.vinfo_width + x_end = osd_hw.vinfo_width[VIU1] - freescale_dst[index].x_start - 1; freescale_dst[index].x_start = x_start; freescale_dst[index].x_end = x_end; } else if (osd_hw.osd_reverse[index] == REVERSE_Y) { - y_start = osd_hw.vinfo_height + y_start = osd_hw.vinfo_height[VIU1] - freescale_dst[index].y_end - 1; - y_end = osd_hw.vinfo_height + y_end = osd_hw.vinfo_height[VIU1] - freescale_dst[index].y_start - 1; freescale_dst[index].y_start = y_start; freescale_dst[index].y_end = y_end; @@ -3794,30 +3994,30 @@ static bool osd_direct_compose_pan_display(struct osd_fence_map_s *fence_map) osd_hw.dispdata[index].y_end = fence_map->dst_y + fence_map->dst_h - 1; if (osd_hw.osd_reverse[index] == REVERSE_TRUE) { - x_start = osd_hw.vinfo_width + x_start = osd_hw.vinfo_width[VIU1] - osd_hw.dispdata[index].x_end - 1; - y_start = osd_hw.vinfo_height + y_start = osd_hw.vinfo_height[VIU1] - osd_hw.dispdata[index].y_end - 1; - x_end = osd_hw.vinfo_width + x_end = osd_hw.vinfo_width[VIU1] - osd_hw.dispdata[index].x_start - 1; - y_end = osd_hw.vinfo_height + y_end = osd_hw.vinfo_height[VIU1] - osd_hw.dispdata[index].y_start - 1; osd_hw.dispdata[index].x_start = x_start; osd_hw.dispdata[index].y_start = y_start; osd_hw.dispdata[index].x_end = x_end; osd_hw.dispdata[index].y_end = y_end; } else if (osd_hw.osd_reverse[index] == REVERSE_X) { - x_start = osd_hw.vinfo_width + x_start = osd_hw.vinfo_width[VIU1] - osd_hw.dispdata[index].x_end - 1; - x_end = osd_hw.vinfo_width + x_end = osd_hw.vinfo_width[VIU1] - osd_hw.dispdata[index].x_start - 1; osd_hw.dispdata[index].x_start = x_start; osd_hw.dispdata[index].x_end = x_end; } else if (osd_hw.osd_reverse[index] == REVERSE_Y) { - y_start = osd_hw.vinfo_height + y_start = osd_hw.vinfo_height[VIU1] - osd_hw.dispdata[index].y_end - 1; - y_end = osd_hw.vinfo_height + y_end = osd_hw.vinfo_height[VIU1] - osd_hw.dispdata[index].y_start - 1; osd_hw.dispdata[index].y_start = y_start; osd_hw.dispdata[index].y_end = y_end; @@ -3840,19 +4040,27 @@ static void osd_pan_display_single_fence(struct osd_fence_map_s *fence_map) u32 osd_enable = 0; bool skip = false; const struct vinfo_s *vinfo; - + u32 output_index = VIU1; if (index >= OSD2) goto out; - if (timeline_created) { /* out fence created success. */ + vinfo = get_current_vinfo(); + if (vinfo && (!strcmp(vinfo->name, "invalid") || + !strcmp(vinfo->name, "null"))) + goto out; + + osd_hw.vinfo_width[output_index] = vinfo->width; + osd_hw.vinfo_height[output_index] = vinfo->height; + + if (timeline_created[output_index]) { /* out fence created success. */ ret = osd_wait_buf_ready(fence_map); if (ret < 0) osd_log_dbg(MODULE_BASE, "fence wait ret %d\n", ret); } if (ret) { osd_hw.buffer_alloc[index] = 1; - if (osd_hw.osd_fps_start) - osd_hw.osd_fps++; + if (osd_hw.osd_fps_start[output_index]) + osd_hw.osd_fps[output_index]++; if (fence_map->op == 0xffffffff) skip = true; else @@ -3865,14 +4073,6 @@ static void osd_pan_display_single_fence(struct osd_fence_map_s *fence_map) AFBC_EN | BLOCK_SPLIT | YUV_TRANSFORM | SUPER_BLOCK_ASPECT; } - vinfo = get_current_vinfo(); - if (vinfo) { - if ((strcmp(vinfo->name, "invalid")) && - (strcmp(vinfo->name, "null"))) { - osd_hw.vinfo_width = vinfo->width; - osd_hw.vinfo_height = vinfo->height; - } - } /* Todo: */ if (fence_map->ext_addr && fence_map->width && fence_map->height) { @@ -3909,6 +4109,7 @@ static void osd_pan_display_single_fence(struct osd_fence_map_s *fence_map) /* geometry and freescale need update with ioctl */ osd_hw.reg[DISP_GEOMETRY].update_func(index); + osd_hw.reg[DISP_OSD_REVERSE].update_func(index); if ((osd_hw.free_scale_enable[index] && osd_update_window_axis) || freescale_update) { @@ -3917,7 +4118,10 @@ static void osd_pan_display_single_fence(struct osd_fence_map_s *fence_map) .update_func(index); osd_update_window_axis = false; } - if ((osd_enable != osd_hw.enable[index]) + if ((osd_enable != osd_hw.enable[index] || + (osd_hw.osd_meson_dev.afbc_type + == MALI_AFBC && + osd_hw.osd_afbcd[index].enable)) && (skip == false) && (suspend_flag == false)) { osd_hw.enable[index] = osd_enable; @@ -4028,6 +4232,7 @@ static void osd_pan_display_single_fence(struct osd_fence_map_s *fence_map) if (color_mode) osd_hw.reg[OSD_COLOR_MODE].update_func(index); osd_hw.reg[DISP_GEOMETRY].update_func(index); + osd_hw.reg[DISP_OSD_REVERSE].update_func(index); if ((osd_hw.free_scale_enable[index] && osd_update_window_axis) || (osd_hw.free_scale_enable[index] @@ -4037,7 +4242,10 @@ static void osd_pan_display_single_fence(struct osd_fence_map_s *fence_map) .update_func(index); osd_update_window_axis = false; } - if ((osd_enable != osd_hw.enable[index]) + if ((osd_enable != osd_hw.enable[index] || + (osd_hw.osd_meson_dev.afbc_type + == MALI_AFBC && + osd_hw.osd_afbcd[index].enable)) && (skip == false) && (suspend_flag == false)) { osd_hw.enable[index] = osd_enable; @@ -4049,7 +4257,9 @@ static void osd_pan_display_single_fence(struct osd_fence_map_s *fence_map) osd_mali_afbc_start(); spin_unlock_irqrestore(&osd_lock, lock_flags); osd_wait_vsync_hw(); - } else if ((osd_enable != osd_hw.enable[index]) + } else if ((osd_enable != osd_hw.enable[index] || + (osd_hw.osd_meson_dev.afbc_type == MALI_AFBC && + osd_hw.osd_afbcd[index].enable)) && (skip == false)) { spin_lock_irqsave(&osd_lock, lock_flags); if (suspend_flag == false) { @@ -4064,20 +4274,24 @@ static void osd_pan_display_single_fence(struct osd_fence_map_s *fence_map) osd_wait_vsync_hw(); } } - if (timeline_created) { +#ifdef CONFIG_AMLOGIC_MEDIA_FB_EXT if (ret) - osd_timeline_increase(); + osd_ext_clone_pan(index); +#endif +out: + if (timeline_created[output_index]) { + if (ret) + osd_timeline_increase(output_index); else osd_log_err("------NOT signal out_fence ERROR\n"); } -#ifdef CONFIG_AMLOGIC_MEDIA_FB_EXT - if (ret) - osd_ext_clone_pan(index); -#endif -out: if (fence_map->in_fence) osd_put_fenceobj(fence_map->in_fence); +} +static void osd_pan_display_single_fence_viu2(struct osd_fence_map_s *fence_map) +{ + osd_log_err("osd hwc version not support viu2\n"); } static void osd_pan_display_update_info(struct layer_fence_map_s *layer_map) @@ -4086,6 +4300,7 @@ static void osd_pan_display_update_info(struct layer_fence_map_s *layer_map) const struct color_bit_define_s *color = NULL; u32 ext_addr = 0; u32 format = 0; + u32 output_index = 0; if (index > OSD_MAX) return; @@ -4093,6 +4308,10 @@ static void osd_pan_display_update_info(struct layer_fence_map_s *layer_map) osd_hw.in_fd[index] = layer_map->in_fd; osd_hw.buffer_alloc[index] = 1; osd_hw.enable[index] = layer_map->enable; + if (osd_hw.enable[index] == 0) { + osd_log_dbg(MODULE_BASE, "osd%d: blanked\n", index); + return; + } osd_hw.osd_afbcd[index].enable = (layer_map->afbc_inter_format & AFBC_EN) >> 31; if (layer_map->plane_alpha == 0xff) @@ -4158,12 +4377,10 @@ static void osd_pan_display_update_info(struct layer_fence_map_s *layer_map) /*ext_addr is no crop, so height = * layer_map->src_h + layer_map->src_y */ - canvas_config(osd_hw.fb_gem[index].canvas_idx, - ext_addr, - layer_map->byte_stride, - layer_map->src_h + layer_map->src_y, - CANVAS_ADDR_NOWRAP, - CANVAS_BLKMODE_LINEAR); + osd_hw.fb_gem[index].addr = ext_addr; + osd_hw.fb_gem[index].width = layer_map->byte_stride; + osd_hw.fb_gem[index].height = + layer_map->src_h + layer_map->src_y; osd_hw.screen_base[index] = ext_addr; osd_hw.screen_size[index] = layer_map->byte_stride * layer_map->src_h; @@ -4202,7 +4419,8 @@ static void osd_pan_display_update_info(struct layer_fence_map_s *layer_map) layer_map->byte_stride / 4; //BYTE_32_ALIGNED(layer_map->src_w); osd_hw.osd_afbcd[index].frame_height = - BYTE_8_ALIGNED(layer_map->src_h); + BYTE_8_ALIGNED(layer_map->fb_height); + /*BYTE_8_ALIGNED(layer_map->src_h);*/ osd_hw.screen_base[index] = ext_addr; osd_hw.screen_size[index] = layer_map->afbc_len; @@ -4246,7 +4464,8 @@ static void osd_pan_display_update_info(struct layer_fence_map_s *layer_map) layer_map->dst_x + layer_map->dst_w - 1; osd_hw.free_dst_data[index].y_end = layer_map->dst_y + layer_map->dst_h - 1; - if (osd_hw.field_out_en) { + output_index = get_output_device_id(index); + if (osd_hw.field_out_en[output_index]) { osd_hw.free_dst_data[index].y_start /= 2; osd_hw.free_dst_data[index].y_end /= 2; } @@ -4258,33 +4477,50 @@ static void osd_pan_display_update_info(struct layer_fence_map_s *layer_map) #endif } -static void osd_pan_display_layers_fence( +static void _osd_pan_display_layers_fence( + u32 output_index, + struct vinfo_s *vinfo, struct osd_layers_fence_map_s *fence_map) { - int i = 0, index = 0; + int i = 0; int ret; - int osd_count = osd_hw.osd_meson_dev.osd_count - 1; + int start_index = 0; + int backup_en = 0; + int osd_count = 0; /* osd_count need -1 when VIU2 enable */ struct layer_fence_map_s *layer_map = NULL; - struct vinfo_s *vinfo; - if (osd_hw.osd_meson_dev.osd_ver <= OSD_NORMAL) - osd_count = 1; - vinfo = get_current_vinfo(); - if (vinfo && (strcmp(vinfo->name, "invalid") && - strcmp(vinfo->name, "null"))) { - osd_hw.vinfo_width = vinfo->width; - osd_hw.vinfo_height = vinfo->field_height; + if (vinfo && (!strcmp(vinfo->name, "invalid") || + !strcmp(vinfo->name, "null"))) + /* vout is null, release fence */ + goto out; + + osd_hw.vinfo_width[output_index] = vinfo->width; + osd_hw.vinfo_height[output_index] = vinfo->field_height; + memcpy(&osd_hw.disp_info[output_index], &fence_map->disp_info, + sizeof(struct display_flip_info_s)); + if (output_index == VIU1) { + osd_count = osd_hw.osd_meson_dev.viu1_osd_count; + if (osd_hw.osd_meson_dev.osd_ver <= OSD_NORMAL) + osd_count = 1; + start_index = 0; + backup_en = 1; + } else if (output_index == VIU2) { + start_index = osd_hw.osd_meson_dev.viu2_index; + osd_count = start_index + 1; + backup_en = 0; + } else { + osd_log_err("invald output_index=%d\n", output_index); + return; } - osd_set_background_size(&(fence_map->disp_info)); - if (osd_hw.osd_fps_start) - osd_hw.osd_fps++; - clear_backup_info(); + if (osd_hw.osd_fps_start[output_index]) + osd_hw.osd_fps[output_index]++; + if (backup_en) + clear_backup_info(); osd_hw.hdr_used = fence_map->hdr_mode; - for (i = 0; i < osd_count; i++) { + for (i = start_index; i < osd_count; i++) { layer_map = &fence_map->layer_map[i]; - index = layer_map->fb_index; if (i != layer_map->fb_index) { osd_hw.screen_base[i] = 0; osd_hw.screen_size[i] = 0; @@ -4292,7 +4528,7 @@ static void osd_pan_display_layers_fence( continue; } /* wait in fence */ - if (timeline_created && layer_map->enable + if (timeline_created[output_index] && layer_map->enable && (fence_map->cmd == LAYER_SYNC)) { ret = osd_wait_buf_ready_combine(layer_map); if (ret < 0) @@ -4300,23 +4536,25 @@ static void osd_pan_display_layers_fence( "fence wait ret %d\n", ret); } osd_pan_display_update_info(layer_map); - save_layer_info(layer_map); + if (backup_en) + save_layer_info(layer_map); } /* set hw regs */ if (osd_hw.osd_display_debug != OSD_DISP_DEBUG) - osd_setting_blend(); + osd_setting_blend(output_index); +out: /* signal out fence */ - if (timeline_created) { + if (timeline_created[output_index]) { if (osd_hw.osd_debug.osd_single_step_mode) { /* single step mode */ if (osd_hw.osd_debug.osd_single_step > 0) { - osd_timeline_increase(); + osd_timeline_increase(output_index); osd_log_dbg(MODULE_FENCE, "signal out fence\n"); osd_hw.osd_debug.osd_single_step--; } else osd_hw.osd_debug.wait_fence_release = true; } else - osd_timeline_increase(); + osd_timeline_increase(output_index); } /*clear last displayed buffer.*/ for (i = 0; i < HW_OSD_COUNT; i++) { @@ -4326,7 +4564,7 @@ static void osd_pan_display_layers_fence( } } /* clear osd layer's order */ - for (i = 0; i < osd_count; i++) { + for (i = start_index; i < osd_count; i++) { layer_map = &fence_map->layer_map[i]; if (layer_map->buf_file) displayed_bufs[i] = layer_map->buf_file; @@ -4335,14 +4573,42 @@ static void osd_pan_display_layers_fence( osd_hw.order[i] = 0; } } + +static void osd_pan_display_layers_fence( + struct osd_layers_fence_map_s *fence_map) +{ + u32 output_index = VIU1; + struct vinfo_s *vinfo = NULL; + + vinfo = get_current_vinfo(); + + _osd_pan_display_layers_fence(output_index, + vinfo, fence_map); +} + +static void osd_pan_display_layers_fence_viu2( + struct osd_layers_fence_map_s *fence_map) +{ + u32 output_index = VIU2; + struct vinfo_s *vinfo = NULL; + +#ifdef CONFIG_AMLOGIC_VOUT2_SERVE + vinfo = get_current_vinfo2(); +#endif + + _osd_pan_display_layers_fence(output_index, + vinfo, fence_map); +} #endif void osd_pan_display_hw(u32 index, unsigned int xoffset, unsigned int yoffset) { long diff_x, diff_y; + u32 output_index; if (index >= HW_OSD_COUNT) return; + output_index = get_output_device_id(index); if (xoffset != osd_hw.pandata[index].x_start || yoffset != osd_hw.pandata[index].y_start) { diff_x = xoffset - osd_hw.pandata[index].x_start; @@ -4358,8 +4624,8 @@ void osd_pan_display_hw(u32 index, unsigned int xoffset, unsigned int yoffset) osd_hw.src_data[index].h = osd_hw.pandata[index].y_end - osd_hw.pandata[index].y_start + 1; add_to_update_list(index, DISP_GEOMETRY); - if (osd_hw.osd_fps_start) - osd_hw.osd_fps++; + if (osd_hw.osd_fps_start[output_index]) + osd_hw.osd_fps[output_index]++; /* osd_wait_vsync_hw(); */ } #ifdef CONFIG_AMLOGIC_MEDIA_FB_EXT @@ -4433,6 +4699,7 @@ static void osd_update_disp_freescale_enable(u32 index) struct hw_osd_reg_s *osd_reg = &hw_osd_reg_array[index]; u32 data32 = 0x0; u32 shift_workaround = 0; + u32 output_index = 0; if (osd_hw.osd_meson_dev.osd_ver != OSD_HIGH_ONE) osd_reg = &hw_osd_reg_array[0]; @@ -4442,12 +4709,9 @@ static void osd_update_disp_freescale_enable(u32 index) else vf_bank_len = 4; - if (osd_hw.hwc_enable && (index == OSD1) - && ((osd_hw.osd_meson_dev.cpu_id == - __MESON_CPU_MAJOR_ID_G12A) || - (osd_hw.osd_meson_dev.cpu_id == - __MESON_CPU_MAJOR_ID_G12B))) - shift_workaround = 1; + output_index = get_output_device_id(index); + if (osd_hw.hwc_enable[output_index] && (index == OSD1)) + shift_workaround = osd_hw.workaround_line; #ifndef NEW_PPS_PHASE if (osd_hw.bot_type == 1) { @@ -4504,7 +4768,7 @@ static void osd_update_disp_freescale_enable(u32 index) vf_phase_step = (src_h << 20) / dst_h; #ifdef NEW_PPS_PHASE - if (osd_hw.field_out_en) { + if (osd_hw.field_out_en[output_index]) { struct osd_f2v_vphase_s vphase; f2v_get_vertical_phase( @@ -4535,7 +4799,7 @@ static void osd_update_disp_freescale_enable(u32 index) bot_ini_phase = 0; } #else - if (osd_hw.field_out_en) /* interface output */ + if (osd_hw.field_out_en[output_index]) /* interface output */ bot_ini_phase = ((vf_phase_step / 2) >> 4); else bot_ini_phase = 0; @@ -4547,7 +4811,7 @@ static void osd_update_disp_freescale_enable(u32 index) data32 = 0x0; if (shift_workaround) { vsc_ini_rcv_num++; - if (osd_hw.field_out_en) + if (osd_hw.field_out_en[output_index]) vsc_bot_rcv_num++; } @@ -4569,7 +4833,7 @@ static void osd_update_disp_freescale_enable(u32 index) data32 |= (vf_bank_len & 0x7) | ((vsc_ini_rcv_num & 0xf) << 3) | ((vsc_ini_rpt_p0_num & 0x3) << 8); - if (osd_hw.field_out_en) + if (osd_hw.field_out_en[output_index]) data32 |= ((vsc_bot_rcv_num & 0xf) << 11) | ((vsc_bot_rpt_p0_num & 0x3) << 16) | (1 << 23); @@ -4604,8 +4868,8 @@ static void osd_update_disp_freescale_enable(u32 index) VSYNCOSD_WR_MPEG_REG( osd_reg->osd_vsc_init_phase, data32); } - if ((osd_hw.osd_meson_dev.osd_ver == OSD_HIGH_ONE) - && (!osd_hw.hwc_enable)) { + if ((osd_hw.osd_meson_dev.osd_ver == OSD_HIGH_ONE) && + (!osd_hw.hwc_enable[output_index])) { osd_setting_blending_scope(index); vpp_blend_setting_default(index); } @@ -4906,8 +5170,10 @@ static void osd_update_enable(u32 index) notify_to_amvideo(); VSYNCOSD_CLR_MPEG_REG_MASK(VPP_MISC, temp_val); } - VSYNCOSD_CLR_MPEG_REG_MASK( - osd_reg->osd_ctrl_stat, 1 << 0); + if (!(osd_hw.osd_meson_dev.cpu_id == + __MESON_CPU_MAJOR_ID_G12B)) + VSYNCOSD_CLR_MPEG_REG_MASK( + osd_reg->osd_ctrl_stat, 1 << 0); } if (osd_hw.osd_meson_dev.afbc_type == MESON_AFBC) { if ((osd_hw.osd_afbcd[index].enable == ENABLE) @@ -4962,14 +5228,16 @@ static void osd_update_enable(u32 index) if (osd_hw.enable[index] == ENABLE) postbld_src_sel = (index == 0) ? 3 : 4; if (index == 0) - VSYNCOSD_WR_MPEG_REG(OSD1_BLEND_SRC_CTRL, + VSYNCOSD_WR_MPEG_REG( + OSD1_BLEND_SRC_CTRL, (0 & 0xf) << 0 | (0 & 0x1) << 4 | (postbld_src_sel & 0xf) << 8 | (0 & 0x1) << 16| (1 & 0x1) << 20); - else if (index == 1) - VSYNCOSD_WR_MPEG_REG(OSD2_BLEND_SRC_CTRL, + else if ((index == 1) && (!enable_vd_zorder)) + VSYNCOSD_WR_MPEG_REG( + OSD2_BLEND_SRC_CTRL, (0 & 0xf) << 0 | (0 & 0x1) << 4 | (postbld_src_sel & 0xf) << 8 | @@ -4981,18 +5249,35 @@ static void osd_update_enable(u32 index) static void osd_update_disp_osd_reverse(u32 index) { - if (osd_hw.osd_reverse[index] == REVERSE_TRUE) + if (osd_hw.osd_reverse[index] == REVERSE_TRUE) { VSYNCOSD_WR_MPEG_REG_BITS( hw_osd_reg_array[index].osd_blk0_cfg_w0, 3, 28, 2); - else if (osd_hw.osd_reverse[index] == REVERSE_X) + if ((osd_hw.osd_meson_dev.afbc_type == MALI_AFBC) && + (osd_hw.osd_afbcd[index].enable == ENABLE)) + VSYNCOSD_WR_MPEG_REG_BITS( + hw_osd_reg_array[index].afbc_prefetch_cfg_s, 3, 0, 2); + } else if (osd_hw.osd_reverse[index] == REVERSE_X) { VSYNCOSD_WR_MPEG_REG_BITS( hw_osd_reg_array[index].osd_blk0_cfg_w0, 1, 28, 2); - else if (osd_hw.osd_reverse[index] == REVERSE_Y) + if ((osd_hw.osd_meson_dev.afbc_type == MALI_AFBC) && + (osd_hw.osd_afbcd[index].enable == ENABLE)) + VSYNCOSD_WR_MPEG_REG_BITS( + hw_osd_reg_array[index].afbc_prefetch_cfg_s, 1, 0, 2); + } else if (osd_hw.osd_reverse[index] == REVERSE_Y) { VSYNCOSD_WR_MPEG_REG_BITS( hw_osd_reg_array[index].osd_blk0_cfg_w0, 2, 28, 2); - else + if ((osd_hw.osd_meson_dev.afbc_type == MALI_AFBC) && + (osd_hw.osd_afbcd[index].enable == ENABLE)) + VSYNCOSD_WR_MPEG_REG_BITS( + hw_osd_reg_array[index].afbc_prefetch_cfg_s, 2, 0, 2); + } else { VSYNCOSD_WR_MPEG_REG_BITS( hw_osd_reg_array[index].osd_blk0_cfg_w0, 0, 28, 2); + if ((osd_hw.osd_meson_dev.afbc_type == MALI_AFBC) && + (osd_hw.osd_afbcd[index].enable == ENABLE)) + VSYNCOSD_WR_MPEG_REG_BITS( + hw_osd_reg_array[index].afbc_prefetch_cfg_s, 0, 0, 2); + } remove_from_update_list(index, DISP_OSD_REVERSE); } @@ -5013,21 +5298,24 @@ static void osd_update_disp_osd_rotate(u32 index) u32 data32; enum color_index_e idx; struct dispdata_s src_data; - const struct vinfo_s *vinfo; + const struct vinfo_s *vinfo = NULL; int out_y_crop_start, out_y_crop_end; - if (osd_hw.osd_meson_dev.cpu_id < __MESON_CPU_MAJOR_ID_G12B) + if (osd_hw.osd_meson_dev.cpu_id != __MESON_CPU_MAJOR_ID_G12B) return; src_fmt = get_viu2_src_format(); src_data.x = 0; src_data.y = 0; src_data.w = osd_hw.fb_gem[index].xres; src_data.h = osd_hw.fb_gem[index].yres; + src_data.h = osd_hw.fb_gem[index].yres; +#ifdef CONFIG_AMLOGIC_VOUT2_SERVE vinfo = get_current_vinfo2(); if (!vinfo) { osd_log_err("current vinfo NULL\n"); return; } +#endif out_y_crop_start = 0; out_y_crop_end = vinfo->height; src_width = src_data.w; @@ -5297,7 +5585,6 @@ static u32 blend_din_to_osd( return osd_index; } -#ifdef OSD_BLEND_SHIFT_WORKAROUND static u32 get_max_order(u32 order1, u32 order2) { u32 max_order = 0; @@ -5587,155 +5874,6 @@ static void generate_blend_din_table(struct hw_osd_blending_s *blending) blending->din_reoder_sel; } -#else -static void generate_blend_din_table(struct hw_osd_blending_s *blending) -{ - int i = 0; - int osd_count = osd_hw.osd_meson_dev.osd_count - 1; - - /* reorder[i] = osd[i]'s display layer */ - for (i = 0; i < OSD_BLEND_LAYERS; i++) - blending->osd_to_bdin_table[i] = -1; - blending->din_reoder_sel = 0; - switch (blending->layer_cnt) { - case 0: - break; - case 1: - for (i = 0; i < osd_count; i++) { - if (blending->reorder[i] != LAYER_UNSUPPORT) { - /* blend_din1 */ - blending->din_reoder_sel |= (i + 1) << 0; - /* blend_din1 -- osdx */ - blending->osd_to_bdin_table[0] = i; - break; - } - } - break; - case 2: - { - int temp_index[2] = {0}; - int j = 0; - - for (i = 0; i < osd_count; i++) { - if (blending->reorder[i] != LAYER_UNSUPPORT) { - /* save the osd index */ - temp_index[j] = i; - j++; - } - } - osd_log_dbg(MODULE_BLEND, "blend_din4==%d\n", - blending->reorder[temp_index[0]]); - osd_log_dbg(MODULE_BLEND, "blend_din1==%d\n", - blending->reorder[temp_index[1]]); - /* mode A_C */ - if (blending->osd_blend_mode == OSD_BLEND_A_C) { - /* blend_din1 */ - blending->din_reoder_sel |= (temp_index[0] + 1) << 0; - /* blend_din1 -- osdx */ - blending->osd_to_bdin_table[0] = temp_index[0]; - /* blend_din3 */ - blending->din_reoder_sel |= (temp_index[1] + 1) << 12; - /* blend_din3 -- osdx */ - blending->osd_to_bdin_table[3] = temp_index[1]; - /* exchane vpp osd blend in order */ - if (blending->reorder[temp_index[0]] < - blending->reorder[temp_index[1]]) { - blending->b_exchange_blend_in = true; - osd_log_dbg(MODULE_BLEND, "need exchange vpp order\n"); - } - } else { - if (blending->reorder[temp_index[0]] < - blending->reorder[temp_index[1]]) { - /* blend_din4 */ - blending->din_reoder_sel |= - (temp_index[0] + 1) << 12; - /* blend_din3 -- osdx */ - blending->osd_to_bdin_table[3] = temp_index[0]; - /* blend_din1 */ - blending->din_reoder_sel |= - (temp_index[1] + 1) << 0; - /* blend_din1 -- osdx */ - blending->osd_to_bdin_table[0] = temp_index[1]; - blending->b_exchange_din = true; - osd_log_dbg(MODULE_BLEND, "need exchange osd din order\n"); - } else { - /* blend_din1 */ - blending->din_reoder_sel |= - (temp_index[0] + 1) << 0; - /* blend_din1 -- osdx */ - blending->osd_to_bdin_table[0] = temp_index[0]; - /* blend_din3 */ - blending->din_reoder_sel |= - (temp_index[1] + 1) << 12; - /* blend_din3 -- osdx */ - blending->osd_to_bdin_table[3] = temp_index[1]; - } - } - break; - } - case 3: - /* blend_din1 is bottom, blend_din4 is top layer */ - /* mode A_BC */ - /* osd0 always used blend_din1 */ - /* blend_din1 */ - blending->din_reoder_sel |= 1 << 0; - /* blend_din1 -- osd1 */ - blending->osd_to_bdin_table[0] = OSD1; - if (blending->reorder[OSD2] > blending->reorder[OSD3]) { - /* blend_din4 */ - blending->din_reoder_sel |= (OSD3 + 1) << 12; - /* blend_din4 -- osd3 */ - blending->osd_to_bdin_table[3] = OSD3; - - /* blend_din3 */ - blending->din_reoder_sel |= (OSD2 + 1) << 8; - /* blend_din3 -- osd2 */ - blending->osd_to_bdin_table[2] = OSD2; - } else { - /* blend_din3 */ - blending->din_reoder_sel |= (OSD2 + 1) << 12; - /* blend_din3 -- osd2 */ - blending->osd_to_bdin_table[3] = OSD2; - - /* blend_din3 */ - blending->din_reoder_sel |= (OSD3 + 1) << 8; - /* blend_din3 -- osd2 */ - blending->osd_to_bdin_table[2] = OSD3; - - } - if (blending->reorder[OSD1] < blending->reorder[OSD3]) { - if (blending->osd_blend_mode == OSD_BLEND_A_BC) { - blending->b_exchange_blend_in = true; - osd_log_dbg(MODULE_BLEND, "need exchange vpp order\n"); - } else { - u32 temp1, temp2; - - blending->b_exchange_din = true; - osd_log_dbg(MODULE_BLEND, "need exchange osd din order\n"); - temp1 = blending->osd_to_bdin_table[2]; - temp2 = blending->osd_to_bdin_table[3]; - blending->osd_to_bdin_table[3] = - blending->osd_to_bdin_table[0]; - blending->osd_to_bdin_table[2] = temp2; - blending->osd_to_bdin_table[0] = temp1; - temp1 = blending->din_reoder_sel & 0xf000; - temp2 = blending->din_reoder_sel & 0x0f00; - blending->din_reoder_sel = (1 << 12); - blending->din_reoder_sel |= temp1 >> 4; - blending->din_reoder_sel |= temp2 >> 8; - } - } - break; - } - osd_log_dbg(MODULE_BLEND, "osd_to_bdin_table[i]=[%x,%x,%x,%x]\n", - blending->osd_to_bdin_table[0], - blending->osd_to_bdin_table[1], - blending->osd_to_bdin_table[2], - blending->osd_to_bdin_table[3]); - blending->blend_reg.din_reoder_sel = - blending->din_reoder_sel; -} -#endif static bool is_freescale_para_changed(u32 index) { static int first[HW_OSD_COUNT - 1] = {1}; @@ -5894,13 +6032,9 @@ static void set_blend_order(struct hw_osd_blending_s *blending) static void set_blend_din(struct hw_osd_blending_s *blending) { int i = 0, osd_index; -#ifdef OSD_BLEND_SHIFT_WORKAROUND /* workaround for shift issue */ /* blend_din_en must equal 5 */ u32 blend_din_en = 0x5; -#else - u32 blend_din_en = 0x9; -#endif if (!blending) return; @@ -5921,7 +6055,6 @@ static void set_blend_din(struct hw_osd_blending_s *blending) static void set_blend_mode(struct hw_osd_blending_s *blending) { u8 osd_blend_mode = OSD_BLEND_NONE; - //u32 osd_index; if (!blending) return; @@ -5945,11 +6078,7 @@ static void set_blend_mode(struct hw_osd_blending_s *blending) if (osd_hw.hdr_used) osd_blend_mode = OSD_BLEND_ABC; else -#ifdef OSD_BLEND_SHIFT_WORKAROUND osd_blend_mode = OSD_BLEND_AB_C; -#else - osd_blend_mode = OSD_BLEND_A_BC; -#endif break; } blending->osd_blend_mode = osd_blend_mode; @@ -6093,19 +6222,9 @@ static void osd_setting_blend1(struct hw_osd_blending_s *blending) } layer_blend = &(blending->layer_blend); blend_reg = &(blending->blend_reg); -#ifdef OSD_BLEND_SHIFT_WORKAROUND /* blend1_dout to blend2 */ blend_reg->din2_osd_sel = 0; -#else - /* input1 default route to blend1 */ - if (layer_blend->input1 & BYPASS_DIN) { - /* blend1_dout to dout1 */ - blend_reg->din2_osd_sel = 1; - layer_blend->input1 &= ~BYPASS_DIN; - } else - /* blend1_dout to blend2 */ - blend_reg->din2_osd_sel = 0; -#endif + if (layer_blend->input2 & BYPASS_DIN) { /* blend1_din3 bypass to dout1 */ blend_reg->din3_osd_sel = 1; @@ -6169,7 +6288,6 @@ static void osd_setting_blend1(struct hw_osd_blending_s *blending) } if (blend_reg->din3_osd_sel || layer_blend->input1 == BLEND_NO_DIN) { /* blend din3 bypass,output == input */ -#ifdef OSD_BLEND_SHIFT_WORKAROUND if (layer_blend->input2 == BLEND_NO_DIN) { memcpy(&layer_blend->output_data, &layer_blend->input1_data, @@ -6180,16 +6298,7 @@ static void osd_setting_blend1(struct hw_osd_blending_s *blending) sizeof(struct dispdata_s)); } layer_blend->output_data.h += workaround_line; -#else - layer_blend->output_data.x = 0; - layer_blend->output_data.y = 0; - layer_blend->output_data.w = - layer_blend->input2_data.x + - layer_blend->input2_data.w; - layer_blend->output_data.h = - layer_blend->input2_data.y + - layer_blend->input2_data.h; -#endif + } else calc_max_output(blending); blend_hsize = layer_blend->output_data.w; @@ -6222,7 +6331,6 @@ static void osd_setting_blend2(struct hw_osd_blending_s *blending) /* osd_blend_blend0_size share with blend2_size*/ blend_reg->osd_blend_blend0_size = blend_vsize << 16 | blend_hsize; -#ifdef OSD_BLEND_SHIFT_WORKAROUND switch (layer_blend->input2) { case BLEND1_DIN: blend1_input = 0; @@ -6232,19 +6340,7 @@ static void osd_setting_blend2(struct hw_osd_blending_s *blending) blend1_input = 1; break; } -#else - switch (layer_blend->input2) { - case BLEND1_DIN: - /* blend1_dout to blend2 */ - blend_reg->din2_osd_sel = 0; - break; - default: - /* blend1_dout to dout1 */ - blend_reg->din2_osd_sel = 1; - break; - } - blend1_input = blend_reg->din2_osd_sel; -#endif + /* premult set */ blend_reg->blend2_premult_en = 3; if (blend1_input) @@ -6256,11 +6352,9 @@ static void osd_setting_blend2(struct hw_osd_blending_s *blending) blend_vsize = layer_blend->output_data.h; blend_reg->osd_blend_blend0_size = blend_vsize << 16 | blend_hsize; -#ifdef OSD_BLEND_SHIFT_WORKAROUND /* blend 0 and blend1 size need same */ blend_reg->osd_blend_blend1_size = blend_reg->osd_blend_blend0_size; -#endif } osd_log_dbg2(MODULE_BLEND, "layer_blend2->output_data:%d,%d,%d,%d\n", layer_blend->output_data.x, @@ -6299,11 +6393,7 @@ static void vpp_setting_blend(struct hw_osd_blending_s *blending) switch (layer_blend->input1) { case BLEND1_DIN: blend_reg->postbld_src3_sel = POSTBLD_OSD2; -#ifdef OSD_BLEND_SHIFT_WORKAROUND if (layer_blend->blend_core1_bypass) -#else - if (blend_reg->din3_osd_sel) -#endif blend_reg->postbld_osd1_premult = 0; else blend_reg->postbld_osd1_premult = 1; @@ -6332,11 +6422,7 @@ static void vpp_setting_blend(struct hw_osd_blending_s *blending) switch (layer_blend->input2) { case BLEND1_DIN: blend_reg->postbld_src4_sel = POSTBLD_OSD2; -#ifdef OSD_BLEND_SHIFT_WORKAROUND if (layer_blend->blend_core1_bypass) -#else - if (blend_reg->din3_osd_sel) -#endif blend_reg->postbld_osd2_premult = 0; else blend_reg->postbld_osd2_premult = 1; @@ -6371,7 +6457,6 @@ static void vpp_setting_blend(struct hw_osd_blending_s *blending) blend_reg->vpp_osd2_blend_v_scope); } -/* input w, h is background */ static void osd_set_freescale(u32 index, struct hw_osd_blending_s *blending) @@ -6380,7 +6465,8 @@ static void osd_set_freescale(u32 index, struct layer_blend_reg_s *blend_reg; u32 width, height; u32 src_height; - u32 workaround_line = 1; + u32 workaround_line = osd_hw.workaround_line; + u32 output_index = 0; layer_blend = &(blending->layer_blend); blend_reg = &(blending->blend_reg); @@ -6392,6 +6478,7 @@ static void osd_set_freescale(u32 index, osd_hw.free_scale[index].h_enable = 1; osd_hw.free_scale[index].v_enable = 1; osd_hw.free_scale_mode[index] = 1; + output_index = get_output_device_id(index); if (index == OSD1) { osd_hw.free_src_data[index].x_start = @@ -6411,7 +6498,7 @@ static void osd_set_freescale(u32 index, * blending->screen_ratio_w >> OSD_CALC; height = (layer_blend->output_data.h - workaround_line) * blending->screen_ratio_h >> OSD_CALC; - if (osd_hw.field_out_en) + if (osd_hw.field_out_en[output_index]) height = height >> 1; } else { osd_hw.free_src_data[index].x_start = @@ -6466,7 +6553,7 @@ static void osd_set_freescale(u32 index, width = osd_hw.dst_data[index].w; height = osd_hw.dst_data[index].h; /* interleaced case */ - if (osd_hw.field_out_en) { + if (osd_hw.field_out_en[output_index]) { height = height >> 1; osd_hw.free_dst_data[index].y_start >>= 1; @@ -6480,7 +6567,7 @@ static void osd_set_freescale(u32 index, osd_hw.dst_data[index].y; width = osd_hw.dst_data[index].w; height = osd_hw.dst_data[index].h; - if (osd_hw.field_out_en) { + if (osd_hw.field_out_en[output_index]) { height = height >> 1; osd_hw.free_dst_data[index].y_start >>= 1; } @@ -6519,7 +6606,7 @@ static void osd_setting_blend0_input(u32 index, struct hw_osd_blending_s *blending) { struct layer_blend_s *layer_blend; - u32 workaround_line = 1; + u32 workaround_line = 0; /* for g12a blend shift issue */ layer_blend = &(blending->layer_blend); @@ -6609,7 +6696,6 @@ static void osd_setting_blend1_input(u32 index, layer_blend->output_data.h); } -/* every output is next path input */ static void set_blend_path(struct hw_osd_blending_s *blending) { struct layer_blend_s *layer_blend; @@ -6617,14 +6703,14 @@ static void set_blend_path(struct hw_osd_blending_s *blending) struct dispdata_s output1_data; u32 index = 0; u8 input1 = 0, input2 = 0; + u32 output_index; if (!blending) return; + output_index = get_output_device_id(index); layer_blend = &(blending->layer_blend); blend_reg = &(blending->blend_reg); -#ifdef OSD_BLEND_SHIFT_WORKAROUND layer_blend->blend_core1_bypass = 0; -#endif switch (blending->osd_blend_mode) { case OSD_BLEND_NONE: blend_reg->postbld_osd1_premult = 0; @@ -6665,13 +6751,13 @@ static void set_blend_path(struct hw_osd_blending_s *blending) layer_blend->input1_data.x = osd_hw.free_dst_data[index].x_start + - osd_hw.disp_info.position_x; + osd_hw.disp_info[output_index].position_x; layer_blend->input1_data.w = osd_hw.free_dst_data[index].x_end - osd_hw.free_dst_data[index].x_start + 1; layer_blend->input1_data.y = osd_hw.free_dst_data[index].y_start + - osd_hw.disp_info.position_y; + osd_hw.disp_info[output_index].position_y; layer_blend->input1_data.h = osd_hw.free_dst_data[index].y_end - osd_hw.free_dst_data[index].y_start + 1; @@ -6680,13 +6766,13 @@ static void set_blend_path(struct hw_osd_blending_s *blending) "first: set osd%d freescale\n", index); osd_set_freescale(index, blending); osd_hw.free_dst_data[index].x_start += - osd_hw.disp_info.position_x; + osd_hw.disp_info[output_index].position_x; osd_hw.free_dst_data[index].x_end += - osd_hw.disp_info.position_x; + osd_hw.disp_info[output_index].position_x; osd_hw.free_dst_data[index].y_start += - osd_hw.disp_info.position_y; + osd_hw.disp_info[output_index].position_y; osd_hw.free_dst_data[index].y_end += - osd_hw.disp_info.position_y; + osd_hw.disp_info[output_index].position_y; osd_setting_blend0_input(index, blending); osd_setting_blend0(blending); @@ -6732,9 +6818,6 @@ static void set_blend_path(struct hw_osd_blending_s *blending) index = blend_din_to_osd(input1, blending); if (index >= OSD_MAX) return; -#ifndef OSD_BLEND_SHIFT_WORKAROUND - osd_setting_blend0_input(index, blending); -#endif if (index != OSD1) { /* here used freescale osd1/osd2 */ osd_log_dbg2(MODULE_BLEND, @@ -6742,9 +6825,7 @@ static void set_blend_path(struct hw_osd_blending_s *blending) index); osd_set_freescale(index, blending); } -#ifdef OSD_BLEND_SHIFT_WORKAROUND osd_setting_blend0_input(index, blending); -#endif osd_setting_blend0(blending); memcpy(&output1_data, &(layer_blend->output_data), sizeof(struct dispdata_s)); @@ -6760,22 +6841,7 @@ static void set_blend_path(struct hw_osd_blending_s *blending) } layer_blend->input1 = BLEND_NO_DIN; layer_blend->input2 = input2; -#ifndef OSD_BLEND_SHIFT_WORKAROUND - if (osd_hw.blend_bypass) - layer_blend->input2 |= BYPASS_DIN; -#endif -#if 0 - layer_blend->input2_data.x = - osd_hw.free_dst_data[index].x_start; - layer_blend->input2_data.w = - osd_hw.free_dst_data[index].x_end - - osd_hw.free_dst_data[index].x_start + 1; - layer_blend->input2_data.y = - osd_hw.free_dst_data[index].y_start; - layer_blend->input2_data.h = - osd_hw.free_dst_data[index].y_end - - osd_hw.free_dst_data[index].y_start + 1; -#endif + osd_setting_blend1_input(index, blending); memcpy(&layer_blend->input2_data, &layer_blend->output_data, @@ -6797,13 +6863,13 @@ static void set_blend_path(struct hw_osd_blending_s *blending) layer_blend->input2 = BLEND_NO_DIN; layer_blend->input1_data.x = osd_hw.free_dst_data[OSD1].x_start + - osd_hw.disp_info.position_x; + osd_hw.disp_info[output_index].position_x; layer_blend->input1_data.w = osd_hw.free_dst_data[OSD1].x_end - osd_hw.free_dst_data[OSD1].x_start + 1; layer_blend->input1_data.y = osd_hw.free_dst_data[OSD1].y_start + - osd_hw.disp_info.position_y; + osd_hw.disp_info[output_index].position_y; layer_blend->input1_data.h = osd_hw.free_dst_data[OSD1].y_end - osd_hw.free_dst_data[OSD1].y_start + 1; @@ -6841,20 +6907,20 @@ static void set_blend_path(struct hw_osd_blending_s *blending) /* save freescale output */ output1_data.x = osd_hw.free_dst_data[index].x_start + - osd_hw.disp_info.position_x; + osd_hw.disp_info[output_index].position_x; output1_data.w = osd_hw.free_dst_data[index].x_end - osd_hw.free_dst_data[index].x_start + 1; output1_data.y = osd_hw.free_dst_data[index].y_start + - osd_hw.disp_info.position_y; + osd_hw.disp_info[output_index].position_y; output1_data.h = osd_hw.free_dst_data[index].y_end - osd_hw.free_dst_data[index].y_start + 1; osd_log_dbg2(MODULE_BLEND, "position_x=%d, y=%d\n", - osd_hw.disp_info.position_x, - osd_hw.disp_info.position_y); + osd_hw.disp_info[output_index].position_x, + osd_hw.disp_info[output_index].position_y); index = blend_din_to_osd(BLEND_DIN4, blending); if (index >= OSD_MAX) @@ -6863,41 +6929,19 @@ static void set_blend_path(struct hw_osd_blending_s *blending) osd_log_dbg2(MODULE_BLEND, "before blend1: set osd%d freescale\n", index); osd_set_freescale(index, blending); -#ifdef OSD_BLEND_SHIFT_WORKAROUND layer_blend->input1 = BLEND_NO_DIN; /* must bypass for shift workaround */ layer_blend->input2 = BLEND_DIN4 | BYPASS_DIN; layer_blend->blend_core1_bypass = 1; -#else - /* always route(bypass) to dout1 */ - layer_blend->input1 = BLEND_NO_DIN | BYPASS_DIN; - layer_blend->input2 = BLEND_DIN4; - if (osd_hw.blend_bypass) - layer_blend->input2 |= BYPASS_DIN; -#endif - #if 0 - layer_blend->input2_data.x = - osd_hw.free_dst_data[index].x_start + - osd_hw.disp_info.position_x; - layer_blend->input2_data.w = - osd_hw.free_dst_data[index].x_end - - osd_hw.free_dst_data[index].x_start + 1; - layer_blend->input2_data.y = - osd_hw.free_dst_data[index].y_start + - osd_hw.disp_info.position_y; - layer_blend->input2_data.h = - osd_hw.free_dst_data[index].y_end - - osd_hw.free_dst_data[index].y_start + 1; - #endif osd_setting_blend1_input(index, blending); memcpy(&layer_blend->input2_data, &layer_blend->output_data, sizeof(struct dispdata_s)); /* adjust offset*/ layer_blend->input2_data.x += - osd_hw.disp_info.position_x; + osd_hw.disp_info[output_index].position_x; layer_blend->input2_data.y += - osd_hw.disp_info.position_y; + osd_hw.disp_info[output_index].position_y; osd_setting_blend1(blending); @@ -6973,10 +7017,8 @@ static void set_blend_path(struct hw_osd_blending_s *blending) layer_blend->input2 = BLEND1_DIN; memcpy(&layer_blend->input1_data, &output1_data, sizeof(struct dispdata_s)); -#ifdef OSD_BLEND_SHIFT_WORKAROUND memcpy(&layer_blend->input2_data, &layer_blend->output_data, sizeof(struct dispdata_s)); -#endif osd_setting_blend2(blending); /* used osd0 freescale */ osd_set_freescale(OSD1, blending); @@ -6985,13 +7027,13 @@ static void set_blend_path(struct hw_osd_blending_s *blending) layer_blend->input2 = BLEND_NO_DIN; layer_blend->input1_data.x = osd_hw.free_dst_data[OSD1].x_start + - osd_hw.disp_info.position_x; + osd_hw.disp_info[output_index].position_x; layer_blend->input1_data.w = osd_hw.free_dst_data[OSD1].x_end - osd_hw.free_dst_data[OSD1].x_start + 1; layer_blend->input1_data.y = osd_hw.free_dst_data[OSD1].y_start + - osd_hw.disp_info.position_y; + osd_hw.disp_info[output_index].position_y; layer_blend->input1_data.h = osd_hw.free_dst_data[OSD1].y_end - osd_hw.free_dst_data[OSD1].y_start + 1; @@ -7026,13 +7068,13 @@ static void set_blend_path(struct hw_osd_blending_s *blending) /* save freescale output */ output1_data.x = osd_hw.free_dst_data[index].x_start + - osd_hw.disp_info.position_x; + osd_hw.disp_info[output_index].position_x; output1_data.w = osd_hw.free_dst_data[index].x_end - osd_hw.free_dst_data[index].x_start + 1; output1_data.y = osd_hw.free_dst_data[index].y_start + - osd_hw.disp_info.position_y; + osd_hw.disp_info[output_index].position_y; output1_data.h = osd_hw.free_dst_data[index].y_end - osd_hw.free_dst_data[index].y_start + 1; @@ -7044,13 +7086,13 @@ static void set_blend_path(struct hw_osd_blending_s *blending) osd_set_freescale(index, blending); layer_blend->input1_data.x = osd_hw.free_dst_data[index].x_start + - osd_hw.disp_info.position_x; + osd_hw.disp_info[output_index].position_x; layer_blend->input1_data.w = osd_hw.free_dst_data[index].x_end - osd_hw.free_dst_data[index].x_start + 1; layer_blend->input1_data.y = osd_hw.free_dst_data[index].y_start + - osd_hw.disp_info.position_y; + osd_hw.disp_info[output_index].position_y; layer_blend->input1_data.h = osd_hw.free_dst_data[index].y_end - osd_hw.free_dst_data[index].y_start + 1; @@ -7063,13 +7105,13 @@ static void set_blend_path(struct hw_osd_blending_s *blending) osd_set_freescale(index, blending); layer_blend->input2_data.x = osd_hw.free_dst_data[index].x_start + - osd_hw.disp_info.position_x; + osd_hw.disp_info[output_index].position_x; layer_blend->input2_data.w = osd_hw.free_dst_data[index].x_end - osd_hw.free_dst_data[index].x_start + 1; layer_blend->input2_data.y = osd_hw.free_dst_data[index].y_start + - osd_hw.disp_info.position_y; + osd_hw.disp_info[output_index].position_y; layer_blend->input2_data.h = osd_hw.free_dst_data[index].y_end - osd_hw.free_dst_data[index].y_start + 1; @@ -7100,7 +7142,6 @@ static void set_blend_path(struct hw_osd_blending_s *blending) } vpp_setting_blend(blending); break; -#ifdef OSD_BLEND_SHIFT_WORKAROUND case OSD_BLEND_AB_C: /* blend0 -->blend2-->sc->vpp_osd1 */ /* sc-->blend1-->blend2-->sc-->vpp_osd1 */ @@ -7150,13 +7191,13 @@ static void set_blend_path(struct hw_osd_blending_s *blending) osd_set_freescale(OSD1, blending); output1_data.x = osd_hw.free_dst_data[OSD1].x_start + - osd_hw.disp_info.position_x; + osd_hw.disp_info[output_index].position_x; output1_data.w = osd_hw.free_dst_data[OSD1].x_end - osd_hw.free_dst_data[OSD1].x_start + 1; output1_data.y = osd_hw.free_dst_data[OSD1].y_start + - osd_hw.disp_info.position_y; + osd_hw.disp_info[output_index].position_y; output1_data.h = osd_hw.free_dst_data[OSD1].y_end - osd_hw.free_dst_data[OSD1].y_start + 1; @@ -7176,13 +7217,572 @@ static void set_blend_path(struct hw_osd_blending_s *blending) layer_blend->input2_data.x = osd_hw.free_dst_data[index].x_start + - osd_hw.disp_info.position_x; + osd_hw.disp_info[output_index].position_x; layer_blend->input2_data.w = osd_hw.free_dst_data[index].x_end - osd_hw.free_dst_data[index].x_start + 1; layer_blend->input2_data.y = osd_hw.free_dst_data[index].y_start + - osd_hw.disp_info.position_y; + osd_hw.disp_info[output_index].position_y; + layer_blend->input2_data.h = + osd_hw.free_dst_data[index].y_end - + osd_hw.free_dst_data[index].y_start + 1; + + /* 2vpp input */ + if (!blending->b_exchange_blend_in) { + layer_blend->input1 = BLEND2_DIN; + layer_blend->input2 = BLEND1_DIN; + memcpy(&layer_blend->input1_data, &output1_data, + sizeof(struct dispdata_s)); + } else { + layer_blend->input1 = BLEND1_DIN; + layer_blend->input2 = BLEND2_DIN; + memcpy(&layer_blend->input1_data, + &layer_blend->input2_data, + sizeof(struct dispdata_s)); + memcpy(&layer_blend->input2_data, + &output1_data, + sizeof(struct dispdata_s)); + } + vpp_setting_blend(blending); + break; + } +} + +static void osd_setting_blend0_new(struct hw_osd_blending_s *blending) +{ + struct layer_blend_reg_s *blend_reg; + struct layer_blend_s *layer_blend; + u32 index = 0; + u32 bld_osd_h_start = 0, bld_osd_h_end = 0; + u32 bld_osd_v_start = 0, bld_osd_v_end = 0; + + if (!blending) + return; + layer_blend = &(blending->layer_blend); + blend_reg = &(blending->blend_reg); + /* blend0 only accept input1 */ + if (layer_blend->input1 & BYPASS_DIN) { + blend_reg->din0_byp_blend = 1; + layer_blend->input1 &= ~BYPASS_DIN; + } else + blend_reg->din0_byp_blend = 0; + if (layer_blend->input1 != BLEND_NO_DIN) { + /* calculate osd blend din scope */ + index = blend_din_to_osd(layer_blend->input1, blending); + if (index >= OSD_MAX) + return; + layer_blend->input1_data.x = + osd_hw.free_dst_data[index].x_start; + layer_blend->input1_data.y = + osd_hw.free_dst_data[index].y_start; + layer_blend->input1_data.w = + osd_hw.free_dst_data[index].x_end - + osd_hw.free_dst_data[index].x_start + 1; + layer_blend->input1_data.h = + osd_hw.free_dst_data[index].y_end - + osd_hw.free_dst_data[index].y_start + 1; + + bld_osd_h_start = + layer_blend->input1_data.x; + bld_osd_h_end = + layer_blend->input1_data.x + + layer_blend->input1_data.w - 1; + bld_osd_v_start = + layer_blend->input1_data.y; + bld_osd_v_end = + layer_blend->input1_data.y + + layer_blend->input1_data.h - 1; + blend_reg->osd_blend_din_scope_h[index] = + bld_osd_h_end << 16 | bld_osd_h_start; + blend_reg->osd_blend_din_scope_v[index] = + bld_osd_v_end << 16 | bld_osd_v_start; + } + layer_blend->output_data.x = 0; + layer_blend->output_data.y = 0; + layer_blend->output_data.w = layer_blend->input1_data.x + + layer_blend->input1_data.w; + layer_blend->output_data.h = layer_blend->input1_data.y + + layer_blend->input1_data.h; + osd_log_dbg2(MODULE_BLEND, + "blend0:input1_data[osd%d]:%d,%d,%d,%d\n", + index, + layer_blend->input1_data.x, + layer_blend->input1_data.y, + layer_blend->input1_data.w, + layer_blend->input1_data.h); + osd_log_dbg2(MODULE_BLEND, + "blend0:layer_blend->output_data:%d,%d,%d,%d\n", + layer_blend->output_data.x, + layer_blend->output_data.y, + layer_blend->output_data.w, + layer_blend->output_data.h); +} + +static void osd_setting_blend1_new(struct hw_osd_blending_s *blending) +{ + struct layer_blend_s *layer_blend; + struct layer_blend_reg_s *blend_reg; + u32 index = 0; + u32 blend_hsize, blend_vsize; + u32 bld_osd_h_start = 0, bld_osd_h_end = 0; + u32 bld_osd_v_start = 0, bld_osd_v_end = 0; + /* for g12a blend shift issue */ + + if (!blending) + return; + layer_blend = &(blending->layer_blend); + blend_reg = &(blending->blend_reg); + /* blend1_dout to blend2 */ + blend_reg->din2_osd_sel = 0; + + if (layer_blend->input2 & BYPASS_DIN) { + /* blend1_din3 bypass to dout1 */ + blend_reg->din3_osd_sel = 1; + layer_blend->input2 &= ~BYPASS_DIN; + } else + /* blend1_din3 input to blend1 */ + blend_reg->din3_osd_sel = 0; + + if (layer_blend->input1 != BLEND_NO_DIN) { + index = blend_din_to_osd(layer_blend->input1, blending); + if (index >= OSD_MAX) + return; + layer_blend->input1_data.x = + osd_hw.free_dst_data[index].x_start; + layer_blend->input1_data.y = + osd_hw.free_dst_data[index].y_start; + layer_blend->input1_data.w = + osd_hw.free_dst_data[index].x_end - + osd_hw.free_dst_data[index].x_start + 1; + layer_blend->input1_data.h = + osd_hw.free_dst_data[index].y_end - + osd_hw.free_dst_data[index].y_start + 1; + + /* calculate osd blend din scope */ + bld_osd_h_start = + layer_blend->input1_data.x; + bld_osd_h_end = + layer_blend->input1_data.x + + layer_blend->input1_data.w - 1; + bld_osd_v_start = + layer_blend->input1_data.y; + bld_osd_v_end = + layer_blend->input1_data.y + + layer_blend->input1_data.h - 1; + blend_reg->osd_blend_din_scope_h[index] = + bld_osd_h_end << 16 | bld_osd_h_start; + blend_reg->osd_blend_din_scope_v[index] = + bld_osd_v_end << 16 | bld_osd_v_start; + osd_log_dbg2(MODULE_BLEND, + "blend1:input1_data(osd%d):%d,%d,%d,%d\n", + index, + layer_blend->input1_data.x, + layer_blend->input1_data.y, + layer_blend->input1_data.w, + layer_blend->input1_data.h); + } + if (layer_blend->input2 != BLEND_NO_DIN) { + index = blend_din_to_osd(layer_blend->input2, blending); + if (index >= OSD_MAX) + return; + layer_blend->input2_data.x = + osd_hw.free_dst_data[index].x_start; + layer_blend->input2_data.y = + osd_hw.free_dst_data[index].y_start; + layer_blend->input2_data.w = + osd_hw.free_dst_data[index].x_end - + osd_hw.free_dst_data[index].x_start + 1; + layer_blend->input2_data.h = + osd_hw.free_dst_data[index].y_end - + osd_hw.free_dst_data[index].y_start + 1; + /* calculate osd blend din scope */ + bld_osd_h_start = + layer_blend->input2_data.x; + bld_osd_h_end = + layer_blend->input2_data.x + + layer_blend->input2_data.w - 1; + bld_osd_v_start = + layer_blend->input2_data.y; + bld_osd_v_end = + layer_blend->input2_data.y + + layer_blend->input2_data.h - 1; + blend_reg->osd_blend_din_scope_h[index] = + bld_osd_h_end << 16 | bld_osd_h_start; + blend_reg->osd_blend_din_scope_v[index] = + bld_osd_v_end << 16 | bld_osd_v_start; + osd_log_dbg2(MODULE_BLEND, + "layer_blend->input2_data:%d,%d,%d,%d\n", + layer_blend->input2_data.x, + layer_blend->input2_data.y, + layer_blend->input2_data.w, + layer_blend->input2_data.h); + } + if (blend_reg->din3_osd_sel || layer_blend->input1 == BLEND_NO_DIN) { + /* blend din3 bypass,output == input */ + if (layer_blend->input2 == BLEND_NO_DIN) { + memcpy(&layer_blend->output_data, + &layer_blend->input1_data, + sizeof(struct dispdata_s)); + } else { + memcpy(&layer_blend->output_data, + &layer_blend->input2_data, + sizeof(struct dispdata_s)); + } + } else + calc_max_output(blending); + blend_hsize = layer_blend->output_data.w; + blend_vsize = layer_blend->output_data.h; + blend_reg->osd_blend_blend1_size = + blend_vsize << 16 | blend_hsize; + + osd_log_dbg2(MODULE_BLEND, "layer_blend1->output_data:%d,%d,%d,%d\n", + layer_blend->output_data.x, + layer_blend->output_data.y, + layer_blend->output_data.w, + layer_blend->output_data.h); +} + +/* input w, h is background */ +static void osd_set_freescale_new(u32 index, + struct hw_osd_blending_s *blending) + +{ + struct layer_blend_s *layer_blend; + struct layer_blend_reg_s *blend_reg; + u32 width, height; + u32 src_height; + u32 output_index; + + layer_blend = &(blending->layer_blend); + blend_reg = &(blending->blend_reg); + if (index >= osd_hw.osd_meson_dev.viu1_osd_count) { + osd_log_err("error osd index=%d\n", index); + return; + } + output_index = get_output_device_id(index); + osd_hw.free_scale_enable[index] = 0x10001; + osd_hw.free_scale[index].h_enable = 1; + osd_hw.free_scale[index].v_enable = 1; + osd_hw.free_scale_mode[index] = 1; + + osd_hw.free_src_data[index].x_start = + osd_hw.src_data[index].x; + osd_hw.free_src_data[index].x_end = + osd_hw.src_data[index].x + + osd_hw.src_data[index].w - 1; + osd_hw.free_src_data[index].y_start = + osd_hw.src_data[index].y; + osd_hw.free_src_data[index].y_end = + osd_hw.src_data[index].y + + osd_hw.src_data[index].h - 1; + + /* direct used dst as freescale dst */ + osd_hw.free_dst_data[index].x_start = + osd_hw.dst_data[index].x; + osd_hw.free_dst_data[index].y_start = + osd_hw.dst_data[index].y; + width = osd_hw.dst_data[index].w; + height = osd_hw.dst_data[index].h; + if (osd_hw.field_out_en[output_index]) { + height = height >> 1; + osd_hw.free_dst_data[index].y_start >>= 1; + } + osd_hw.free_dst_data[index].x_end = + osd_hw.free_dst_data[index].x_start + + width - 1; + osd_hw.free_dst_data[index].y_end = + osd_hw.free_dst_data[index].y_start + + height - 1; + + src_height = osd_hw.free_src_data[index].x_end - + osd_hw.free_src_data[index].x_start + 1; + osd_set_dummy_data(index, 0xff); + osd_log_dbg2(MODULE_BLEND, "osd%d:free_src_data:%d,%d,%d,%d\n", + index, + osd_hw.free_src_data[index].x_start, + osd_hw.free_src_data[index].y_start, + osd_hw.free_src_data[index].x_end, + osd_hw.free_src_data[index].y_end); + osd_log_dbg2(MODULE_BLEND, "osd%d:free_dst_data:%d,%d,%d,%d\n", + index, + osd_hw.free_dst_data[index].x_start, + osd_hw.free_dst_data[index].y_start, + osd_hw.free_dst_data[index].x_end, + osd_hw.free_dst_data[index].y_end); +} + +/* every output is next path input */ +static void set_blend_path_new(struct hw_osd_blending_s *blending) +{ + struct layer_blend_s *layer_blend; + struct layer_blend_reg_s *blend_reg; + struct dispdata_s output1_data; + u32 index = 0; + u8 input1 = 0, input2 = 0; + u32 output_index; + + if (!blending) + return; + output_index = get_output_device_id(index); + + layer_blend = &(blending->layer_blend); + blend_reg = &(blending->blend_reg); + layer_blend->blend_core1_bypass = 0; + switch (blending->osd_blend_mode) { + case OSD_BLEND_NONE: + blend_reg->postbld_osd1_premult = 0; + blend_reg->postbld_src4_sel = POSTBLD_CLOSE; + blend_reg->postbld_src3_sel = POSTBLD_CLOSE; + blend_reg->postbld_osd2_premult = 0; + break; + case OSD_BLEND_A: + /* sc-->blend0-->blend2-->vpp_osd1 */ + layer_blend->input1 = BLEND_DIN1; + if (osd_hw.blend_bypass) + layer_blend->input1 |= BYPASS_DIN; + layer_blend->input2 = BLEND_NO_DIN; + index = blend_din_to_osd(BLEND_DIN1, blending); + if (index >= OSD_MAX) + return; + osd_set_freescale_new(index, blending); + osd_setting_blend0_new(blending); + if (!blend_reg->din0_byp_blend) { + layer_blend->input1 = BLEND0_DIN; + layer_blend->input2 = BLEND_NO_DIN; + memcpy(&layer_blend->input1_data, + &layer_blend->output_data, + sizeof(struct dispdata_s)); + /* same with blend0's background */ + osd_setting_blend2(blending); + } + layer_blend->input1 = BLEND2_DIN; + layer_blend->input2 = BLEND_NO_DIN; + memcpy(&(layer_blend->input1_data), + &(layer_blend->output_data), + sizeof(struct dispdata_s)); + layer_blend->input1_data.x += + osd_hw.disp_info[output_index].position_x; + layer_blend->input1_data.y += + osd_hw.disp_info[output_index].position_y; + vpp_setting_blend(blending); + break; + case OSD_BLEND_AC: + /* sc-->blend0 -->blend1-->blend2-->vpp_osd1 */ + /* sc-->blend0 & blend1-->blend2-->vpp_osd1 */ + if (!blending->b_exchange_din) { + input1 = BLEND_DIN1; + input2 = BLEND_DIN4; + } else { + input1 = BLEND_DIN4; + input2 = BLEND_DIN1; + } + layer_blend->input1 = input1; + layer_blend->input2 = BLEND_NO_DIN; + index = blend_din_to_osd(input1, blending); + if (index >= OSD_MAX) + return; + osd_set_freescale_new(index, blending); + osd_setting_blend0_new(blending); + /* save blend0 output */ + memcpy(&output1_data, &(layer_blend->output_data), + sizeof(struct dispdata_s)); + + index = blend_din_to_osd(input2, blending); + if (index >= OSD_MAX) + return; + osd_set_freescale_new(index, blending); + layer_blend->input1 = BLEND_NO_DIN; + layer_blend->input2 = input2; + osd_setting_blend1_new(blending); + + layer_blend->input1 = BLEND0_DIN; + layer_blend->input2 = BLEND1_DIN; + + /* blend0 output-> blend2 input1 */ + memcpy(&layer_blend->input1_data, &output1_data, + sizeof(struct dispdata_s)); + /* blend1 output-> blend2 input2 */ + memcpy(&layer_blend->input2_data, &layer_blend->output_data, + sizeof(struct dispdata_s)); + osd_setting_blend2(blending); + + layer_blend->input1 = BLEND2_DIN; + layer_blend->input2 = BLEND_NO_DIN; + memcpy(&(layer_blend->input1_data), + &(layer_blend->output_data), + sizeof(struct dispdata_s)); + layer_blend->input1_data.x += + osd_hw.disp_info[output_index].position_x; + layer_blend->input1_data.y += + osd_hw.disp_info[output_index].position_y; + vpp_setting_blend(blending); + break; + case OSD_BLEND_A_C: + /* sc-->blend0 -->blend2->vpp_osd1 */ + /* sc-->blend1 -->vpp_osd2 */ + layer_blend->input1 = BLEND_DIN1; + if (osd_hw.blend_bypass) + layer_blend->input1 |= BYPASS_DIN; + layer_blend->input2 = BLEND_NO_DIN; + index = blend_din_to_osd(BLEND_DIN1, blending); + if (index >= OSD_MAX) + return; + osd_set_freescale_new(index, blending); + osd_setting_blend0_new(blending); + if (!blend_reg->din0_byp_blend) { + layer_blend->input1 = BLEND0_DIN; + layer_blend->input2 = BLEND_NO_DIN; + memcpy(&layer_blend->input1_data, + &layer_blend->output_data, + sizeof(struct dispdata_s)); + /* background is same with blend0's background */ + osd_setting_blend2(blending); + } + /* save blend0/blend2 output */ + memcpy(&output1_data, &(layer_blend->output_data), + sizeof(struct dispdata_s)); + /* adjust input 1 offset*/ + output1_data.x += + osd_hw.disp_info[output_index].position_x; + output1_data.y += + osd_hw.disp_info[output_index].position_y; + + index = blend_din_to_osd(BLEND_DIN4, blending); + if (index >= OSD_MAX) + return; + osd_set_freescale_new(index, blending); + layer_blend->input1 = BLEND_NO_DIN; + layer_blend->input2 = BLEND_DIN4 | BYPASS_DIN; + layer_blend->blend_core1_bypass = 1; + osd_setting_blend1_new(blending); + /* adjust input 2 offset*/ + layer_blend->output_data.x += + osd_hw.disp_info[output_index].position_x; + layer_blend->output_data.y += + osd_hw.disp_info[output_index].position_y; + + if (!blending->b_exchange_blend_in) { + layer_blend->input1 = BLEND2_DIN; + layer_blend->input2 = BLEND1_DIN; + memcpy(&layer_blend->input1_data, &output1_data, + sizeof(struct dispdata_s)); + memcpy(&layer_blend->input2_data, + &layer_blend->output_data, + sizeof(struct dispdata_s)); + } else { + layer_blend->input1 = BLEND1_DIN; + layer_blend->input2 = BLEND2_DIN; + memcpy(&layer_blend->input1_data, + &layer_blend->output_data, + sizeof(struct dispdata_s)); + memcpy(&layer_blend->input2_data, &output1_data, + sizeof(struct dispdata_s)); + } + vpp_setting_blend(blending); + break; + case OSD_BLEND_ABC: + /* sc->blend0 -->blend2-->vpp_osd1 */ + /* sc-->blend1 -->blend2 */ + input1 = BLEND_DIN1; + input2 = BLEND_DIN4; + layer_blend->input1 = input1; + layer_blend->input2 = BLEND_NO_DIN; + index = blend_din_to_osd(input1, blending); + if (index >= OSD_MAX) + return; + osd_set_freescale_new(index, blending); + osd_setting_blend0_new(blending); + /* save blend0 output */ + memcpy(&output1_data, &(layer_blend->output_data), + sizeof(struct dispdata_s)); + + layer_blend->input1 = BLEND_DIN3; + layer_blend->input2 = input2; + index = blend_din_to_osd(layer_blend->input1, blending); + osd_set_freescale_new(index, blending); + index = blend_din_to_osd(layer_blend->input2, blending); + osd_set_freescale_new(index, blending); + osd_setting_blend1_new(blending); + + layer_blend->input1 = BLEND0_DIN; + layer_blend->input2 = BLEND1_DIN; + memcpy(&layer_blend->input1_data, &output1_data, + sizeof(struct dispdata_s)); + memcpy(&layer_blend->input2_data, &layer_blend->output_data, + sizeof(struct dispdata_s)); + osd_setting_blend2(blending); + + layer_blend->input1 = BLEND2_DIN; + layer_blend->input2 = BLEND_NO_DIN; + memcpy(&(layer_blend->input1_data), + &(layer_blend->output_data), + sizeof(struct dispdata_s)); + layer_blend->input1_data.x += + osd_hw.disp_info[output_index].position_x; + layer_blend->input1_data.y += + osd_hw.disp_info[output_index].position_y; + vpp_setting_blend(blending); + break; + case OSD_BLEND_AB_C: + /* sc-->blend0 -->blend2->vpp_osd1 */ + /* sc-->blend1-->blend2-->vpp_osd1 */ + /* sc -->vpp_osd2 */ + layer_blend->input1 = BLEND_DIN1; + layer_blend->input2 = BLEND_NO_DIN; + blending->blend_din = BLEND_DIN1; + index = blend_din_to_osd(BLEND_DIN1, blending); + if (index >= OSD_MAX) + return; + osd_set_freescale_new(index, blending); + osd_setting_blend0_new(blending); + /* save blend0 output */ + memcpy(&output1_data, &(layer_blend->output_data), + sizeof(struct dispdata_s)); + + /* din3 input to blend1 */ + layer_blend->input1 = BLEND_DIN3; + layer_blend->input2 = BLEND_NO_DIN | BYPASS_DIN; + layer_blend->blend_core1_bypass = 1; + blending->blend_din = BLEND_DIN3; + index = blend_din_to_osd(BLEND_DIN3, blending); + osd_set_freescale_new(index, blending); + osd_setting_blend1_new(blending); + + /* din1=>blend0 & din3-> blend1 ==> blend2 */ + layer_blend->input1 = BLEND0_DIN; + layer_blend->input2 = BLEND1_DIN; + memcpy(&layer_blend->input1_data, &output1_data, + sizeof(struct dispdata_s)); + memcpy(&layer_blend->input2_data, &layer_blend->output_data, + sizeof(struct dispdata_s)); + osd_setting_blend2(blending); + memcpy(&output1_data, &(layer_blend->output_data), + sizeof(struct dispdata_s)); + output1_data.x += + osd_hw.disp_info[output_index].position_x; + output1_data.y += + osd_hw.disp_info[output_index].position_y; + osd_log_dbg2(MODULE_BLEND, "output1_data:%d,%d,%d,%d\n", + output1_data.x, + output1_data.w, + output1_data.y, + output1_data.h); + + + /* din4 ==> vpp */ + index = blend_din_to_osd(BLEND_DIN4, blending); + blending->blend_din = BLEND_DIN4; + osd_set_freescale_new(index, blending); + layer_blend->input2_data.x = + osd_hw.free_dst_data[index].x_start + + osd_hw.disp_info[output_index].position_x; + layer_blend->input2_data.w = + osd_hw.free_dst_data[index].x_end - + osd_hw.free_dst_data[index].x_start + 1; + layer_blend->input2_data.y = + osd_hw.free_dst_data[index].y_start + + osd_hw.disp_info[output_index].position_y; layer_blend->input2_data.h = osd_hw.free_dst_data[index].y_end - osd_hw.free_dst_data[index].y_start + 1; @@ -7205,7 +7805,6 @@ static void set_blend_path(struct hw_osd_blending_s *blending) } vpp_setting_blend(blending); break; -#endif } } @@ -7214,16 +7813,16 @@ static void set_blend_reg(struct layer_blend_reg_s *blend_reg) int i; u32 reg_offset = 2; u32 osd1_alpha_div = 0, osd2_alpha_div = 0; -#ifdef OSD_BLEND_SHIFT_WORKAROUND u32 osd_count = OSD_BLEND_LAYERS; -#else - u32 osd_count = osd_hw.osd_meson_dev.viu1_osd_count; -#endif u32 dv_core2_hsize; u32 dv_core2_vsize; if (!blend_reg) return; + /* osd0 scale position before osd blend */ + if (osd_hw.osd_meson_dev.osd0_sc_independ) + VSYNCOSD_WR_MPEG_REG(VPP_OSD_SCALE_CTRL, 0x01); + /* osd blend ctrl */ VSYNCOSD_WR_MPEG_REG(VIU_OSD_BLEND_CTRL, 4 << 29| @@ -7252,12 +7851,15 @@ static void set_blend_reg(struct layer_blend_reg_s *blend_reg) (0 << 16) | (1 & 0x1) << 20); /* vpp osd2 blend ctrl */ - VSYNCOSD_WR_MPEG_REG(OSD2_BLEND_SRC_CTRL, - (0 & 0xf) << 0 | - (0 & 0x1) << 4 | - (blend_reg->postbld_src4_sel & 0xf) << 8 | - (0 << 16) | - (1 & 0x1) << 20); + if (!enable_vd_zorder) + VSYNCOSD_WR_MPEG_REG( + OSD2_BLEND_SRC_CTRL, + (0 & 0xf) << 0 | + (0 & 0x1) << 4 | + (blend_reg->postbld_src4_sel & 0xf) + << 8 | + (0 << 16) | + (1 & 0x1) << 20); VSYNCOSD_WR_MPEG_REG(VIU_OSD_BLEND_BLEND0_SIZE, blend_reg->osd_blend_blend0_size); @@ -7282,7 +7884,6 @@ static void set_blend_reg(struct layer_blend_reg_s *blend_reg) VIU_OSD_BLEND_DIN0_SCOPE_V + reg_offset * i, blend_reg->osd_blend_din_scope_v[i]); } -#ifdef OSD_BLEND_SHIFT_WORKAROUND else { if ((blend_reg->osd_blend_din_scope_v[i] & 0xffff) == 0) blend_reg->osd_blend_din_scope_v[i] = 0x43a0439; @@ -7290,7 +7891,6 @@ static void set_blend_reg(struct layer_blend_reg_s *blend_reg) VIU_OSD_BLEND_DIN0_SCOPE_V + reg_offset * i, blend_reg->osd_blend_din_scope_v[i]); } -#endif } dv_core2_vsize = (blend_reg->osd_blend_blend0_size >> 16) & 0xfff; @@ -7322,17 +7922,6 @@ static void uniformization_fb(u32 index, blending->screen_ratio_w; blending->dst_data.h = (osd_hw.dst_data[index].h << OSD_CALC) / blending->screen_ratio_h; - if (osd_hw.dst_data[index].w < osd_hw.disp_info.position_w) - osd_log_err("base dispframe w(%d) must >= position_w(%d)\n", - osd_hw.dst_data[index].w, osd_hw.disp_info.position_w); - if ((blending->dst_data.w + blending->dst_data.x) > - osd_hw.disp_info.background_w) { - blending->dst_data.w = osd_hw.disp_info.background_w - - blending->dst_data.x; - osd_log_info("blending w(%d) must < base fb w(%d)\n", - blending->dst_data.w + blending->dst_data.x, - osd_hw.disp_info.background_w); - } osd_log_dbg2(MODULE_BLEND, "uniformization:osd%d:dst_data:%d,%d,%d,%d\n", index, @@ -7342,17 +7931,29 @@ static void uniformization_fb(u32 index, blending->dst_data.h); } -static void adjust_dst_position(void) +static void adjust_dst_position(u32 output_index) { int i = 0; - int osd_count = osd_hw.osd_meson_dev.viu1_osd_count; + int osd_count = 0; + int start_index = 0; + + if (output_index == VIU1) { + osd_count = osd_hw.osd_meson_dev.viu1_osd_count; + start_index = 0; + } else if (output_index == VIU2) { + start_index = osd_hw.osd_meson_dev.viu2_index; + osd_count = start_index + 1; + } else { + osd_log_err("invald output_index=%d\n", output_index); + return; + } for (i = 0; i < osd_count; i++) { if (osd_hw.enable[i]) { osd_hw.dst_data[i].x -= - osd_hw.disp_info.position_x; + osd_hw.disp_info[output_index].position_x; osd_hw.dst_data[i].y -= - osd_hw.disp_info.position_y; + osd_hw.disp_info[output_index].position_y; if (osd_hw.dst_data[i].x < 0) osd_hw.dst_data[i].x = 0; if (osd_hw.dst_data[i].y < 0) @@ -7366,12 +7967,13 @@ static void adjust_dst_position(void) osd_hw.dst_data[i].h); } } - if (osd_hw.field_out_en) - osd_hw.disp_info.position_y /= 2; + if (osd_hw.field_out_en[output_index]) + osd_hw.disp_info[output_index].position_y /= 2; } -static int osd_setting_order(void) +static int osd_setting_order(u32 output_index) { +#define RDMA_DETECT_REG VIU_OSD2_TCOLOR_AG2 int i; struct layer_blend_reg_s *blend_reg; struct hw_osd_blending_s *blending; @@ -7380,18 +7982,19 @@ static int osd_setting_order(void) int line1; int line2; int vinfo_height; + u32 val; blending = &osd_blending; blend_reg = &(blending->blend_reg); - blending->vinfo_width = osd_hw.vinfo_width; - blending->vinfo_height = osd_hw.vinfo_height; + blending->vinfo_width = osd_hw.vinfo_width[output_index]; + blending->vinfo_height = osd_hw.vinfo_height[output_index]; blending->screen_ratio_w = - (osd_hw.disp_info.position_w << OSD_CALC) - / osd_hw.disp_info.background_w; + (osd_hw.disp_info[output_index].position_w << OSD_CALC) + / osd_hw.disp_info[output_index].background_w; blending->screen_ratio_h = - (osd_hw.disp_info.position_h << OSD_CALC) - / osd_hw.disp_info.background_h; + (osd_hw.disp_info[output_index].position_h << OSD_CALC) + / osd_hw.disp_info[output_index].background_h; blending->layer_cnt = get_available_layers(); set_blend_order(blending); @@ -7401,8 +8004,9 @@ static int osd_setting_order(void) blending->b_exchange_din = false; blending->b_exchange_blend_in = false; blending->osd1_freescale_disable = false; - adjust_dst_position(); - uniformization_fb(OSD1, blending); + adjust_dst_position(output_index); + if (!osd_hw.osd_meson_dev.osd0_sc_independ) + uniformization_fb(OSD1, blending); /* set blend mode */ set_blend_mode(blending); @@ -7411,14 +8015,19 @@ static int osd_setting_order(void) set_blend_din(blending); /* set blend path */ - set_blend_path(blending); + if (osd_hw.osd_meson_dev.osd0_sc_independ) + set_blend_path_new(blending); + else + set_blend_path(blending); line1 = get_enter_encp_line(); - vinfo_height = osd_hw.field_out_en ? - (osd_hw.vinfo_height * 2) : osd_hw.vinfo_height; - if (line1 >= vinfo_height) { + vinfo_height = osd_hw.field_out_en[output_index] ? + (osd_hw.vinfo_height[output_index] * 2) : + osd_hw.vinfo_height[output_index]; + /* if nearly vsync signal, wait vsync here */ + if (line1 >= vinfo_height * line_threshold / 100) { osd_log_dbg(MODULE_RENDER, - "enter osd_setting_order:cnt=%d,encp line=%d\n", - cnt, line1); + "enter osd_setting_order:encp line=%d\n", + line1); osd_wait_vsync_hw(); line1 = get_enter_encp_line(); } @@ -7430,6 +8039,13 @@ static int osd_setting_order(void) struct hw_osd_reg_s *osd_reg = &hw_osd_reg_array[i]; update = is_freescale_para_changed(i); + if (!osd_hw.osd_afbcd[i].enable) + canvas_config(osd_hw.fb_gem[i].canvas_idx, + osd_hw.fb_gem[i].addr, + osd_hw.fb_gem[i].width, + osd_hw.fb_gem[i].height, + CANVAS_ADDR_NOWRAP, + CANVAS_BLKMODE_LINEAR); osd_hw.reg[OSD_COLOR_MODE].update_func(i); if (!osd_hw.dim_layer[i]) { VSYNCOSD_WR_MPEG_REG(osd_reg->osd_dimm_ctrl, @@ -7456,6 +8072,7 @@ static int osd_setting_order(void) } osd_hw.reg[DISP_GEOMETRY].update_func(i); osd_hw.reg[OSD_GBL_ALPHA].update_func(i); + osd_hw.reg[DISP_OSD_REVERSE].update_func(i); if (update || osd_update_window_axis) { osd_set_scan_mode(i); osd_hw.reg @@ -7481,14 +8098,21 @@ static int osd_setting_order(void) set_blend_reg(blend_reg); save_blend_reg(blend_reg); + /* append RDMA_DETECT_REG at last and detect if rdma missed some regs */ + rdma_dt_cnt++; + VSYNCOSD_WR_MPEG_REG(RDMA_DETECT_REG, rdma_dt_cnt); spin_unlock_irqrestore(&osd_lock, lock_flags); line2 = get_exit_encp_line(); osd_log_dbg2(MODULE_RENDER, - "enter osd_setting_order:cnt=%d,encp line=%d\n", - cnt, line2); - if (line2 < line1) - osd_log_info("osd line %d,%d\n", line1, line2); + "enter osd_setting_order:encp line=%d\n", + line2); osd_wait_vsync_hw(); + val = osd_reg_read(RDMA_DETECT_REG); + /* if missed, need wait vsync */ + if (/*(line2 < line1) || */(val != rdma_dt_cnt)) { + osd_wait_vsync_hw(); + osd_log_dbg(MODULE_RENDER, "osd line %d,%d\n", line1, line2); + } return 0; } @@ -7531,12 +8155,16 @@ static void osd_setting_default_hwc(void) (postbld_osd1_premult & 0x1) << 16| (1 & 0x1) << 20); /* vpp osd2 blend ctrl */ - VSYNCOSD_WR_MPEG_REG(OSD2_BLEND_SRC_CTRL, - (0 & 0xf) << 0 | - (0 & 0x1) << 4 | - (postbld_src4_sel & 0xf) << 8 | - (postbld_osd2_premult & 0x1) << 16 | - (1 & 0x1) << 20); + if (!enable_vd_zorder) + VSYNCOSD_WR_MPEG_REG( + OSD2_BLEND_SRC_CTRL, + (0 & 0xf) << 0 | + (0 & 0x1) << 4 | + (postbld_src4_sel & 0xf) + << 8 | + (postbld_osd2_premult & 0x1) + << 16 | + (1 & 0x1) << 20); /* Do later: different format select different dummy_data */ /* used default dummy data */ @@ -7550,8 +8178,8 @@ static void osd_setting_default_hwc(void) 0x0 << 11 | 0x0); - blend_hsize = osd_hw.disp_info.background_w; - blend_vsize = osd_hw.disp_info.background_h; + blend_hsize = osd_hw.disp_info[VIU1].background_w; + blend_vsize = osd_hw.disp_info[VIU1].background_h; VSYNCOSD_WR_MPEG_REG(VIU_OSD_BLEND_BLEND0_SIZE, blend_vsize << 16 | @@ -7568,29 +8196,29 @@ static bool set_old_hwc_freescale(u32 index) u32 x_start, x_end, y_start, y_end, height_dst, height_src; if (osd_hw.osd_reverse[index] == REVERSE_TRUE) { - x_start = osd_hw.vinfo_width + x_start = osd_hw.vinfo_width[VIU1] - osd_hw.free_dst_data[index].x_end - 1; - y_start = osd_hw.vinfo_height + y_start = osd_hw.vinfo_height[VIU1] - osd_hw.free_dst_data[index].y_end - 1; - x_end = osd_hw.vinfo_width + x_end = osd_hw.vinfo_width[VIU1] - osd_hw.free_dst_data[index].x_start - 1; - y_end = osd_hw.vinfo_height + y_end = osd_hw.vinfo_height[VIU1] - osd_hw.free_dst_data[index].y_start - 1; osd_hw.free_dst_data[index].x_start = x_start; osd_hw.free_dst_data[index].y_start = y_start; osd_hw.free_dst_data[index].x_end = x_end; osd_hw.free_dst_data[index].y_end = y_end; } else if (osd_hw.osd_reverse[index] == REVERSE_X) { - x_start = osd_hw.vinfo_width + x_start = osd_hw.vinfo_width[VIU1] - osd_hw.free_dst_data[index].x_end - 1; - x_end = osd_hw.vinfo_width + x_end = osd_hw.vinfo_width[VIU1] - osd_hw.free_dst_data[index].x_start - 1; osd_hw.free_dst_data[index].x_start = x_start; osd_hw.free_dst_data[index].x_end = x_end; } else if (osd_hw.osd_reverse[index] == REVERSE_Y) { - y_start = osd_hw.vinfo_height + y_start = osd_hw.vinfo_height[VIU1] - osd_hw.free_dst_data[index].y_end - 1; - y_end = osd_hw.vinfo_height + y_end = osd_hw.vinfo_height[VIU1] - osd_hw.free_dst_data[index].y_start - 1; osd_hw.free_dst_data[index].y_start = y_start; osd_hw.free_dst_data[index].y_end = y_end; @@ -7622,101 +8250,6 @@ static bool set_old_hwc_freescale(u32 index) return false; } -#if 0 -static bool set_old_hwc_freescale(u32 index) -{ - u32 x_start, x_end, y_start, y_end; - u32 width_src = 0, width_dst = 0, height_src = 0, height_dst = 0; - u32 width, height; - u32 screen_ratio_w, screen_ratio_h; - - width_src = osd_hw.disp_info.background_w; - height_src = osd_hw.disp_info.background_h; - - width_dst = osd_hw.vinfo_width; - height_dst = osd_hw.vinfo_height; - screen_ratio_w = (osd_hw.disp_info.position_w << OSD_CALC) - / osd_hw.disp_info.background_w; - screen_ratio_h = (osd_hw.disp_info.position_h << OSD_CALC) - / osd_hw.disp_info.background_h; - osd_log_dbg("width_src:%d,%d\n", - width_src, height_src); - osd_log_dbg("width_src:%d,%d\n", - width_dst, height_dst); - - width = osd_hw.free_dst_data[index].x_end - - osd_hw.free_dst_data[index].x_start; - height = osd_hw.free_dst_data[index].y_end - - osd_hw.free_dst_data[index].y_start; - osd_hw.free_dst_data[index].x_start = - (osd_hw.free_dst_data[index].x_start - * screen_ratio_w >> OSD_CALC); - osd_hw.free_dst_data[index].y_start = - (osd_hw.free_dst_data[index].y_start - * screen_ratio_h >> OSD_CALC); - width = (width * screen_ratio_w >> OSD_CALC); - height = (height * screen_ratio_h >> OSD_CALC); - - osd_hw.free_dst_data[index].x_start += - osd_hw.disp_info.position_x; - osd_hw.free_dst_data[index].x_end = - osd_hw.free_dst_data[index].x_start + width; - osd_hw.free_dst_data[index].y_start += - osd_hw.disp_info.position_y; - osd_hw.free_dst_data[index].y_end = - osd_hw.free_dst_data[index].y_start + height; - - if (osd_hw.osd_reverse[index] == REVERSE_TRUE) { - x_start = osd_hw.vinfo_width - - osd_hw.free_dst_data[index].x_end - 1; - y_start = osd_hw.vinfo_height - - osd_hw.free_dst_data[index].y_end - 1; - x_end = osd_hw.vinfo_width - - osd_hw.free_dst_data[index].x_start - 1; - y_end = osd_hw.vinfo_height - - osd_hw.free_dst_data[index].y_start - 1; - osd_hw.free_dst_data[index].x_start = x_start; - osd_hw.free_dst_data[index].y_start = y_start; - osd_hw.free_dst_data[index].x_end = x_end; - osd_hw.free_dst_data[index].y_end = y_end; - } else if (osd_hw.osd_reverse[index] == REVERSE_X) { - x_start = osd_hw.vinfo_width - - osd_hw.free_dst_data[index].x_end - 1; - x_end = osd_hw.vinfo_width - - osd_hw.free_dst_data[index].x_start - 1; - osd_hw.free_dst_data[index].x_start = x_start; - osd_hw.free_dst_data[index].x_end = x_end; - } else if (osd_hw.osd_reverse[index] == REVERSE_Y) { - y_start = osd_hw.vinfo_height - - osd_hw.free_dst_data[index].y_end - 1; - y_end = osd_hw.vinfo_height - - osd_hw.free_dst_data[index].y_start - 1; - osd_hw.free_dst_data[index].y_start = y_start; - osd_hw.free_dst_data[index].y_end = y_end; - } - osd_log_dbg("free_dst_data: %x,%x,%x,%x\n", - osd_hw.free_dst_data[index].x_start, - osd_hw.free_dst_data[index].x_end, - osd_hw.free_dst_data[index].y_start, - osd_hw.free_dst_data[index].y_end); - if ((memcmp(&(osd_hw.free_src_data[index]), - &osd_hw.free_src_data_backup[index], - sizeof(struct pandata_s)) != 0) || - (memcmp(&(osd_hw.free_dst_data[index]), - &osd_hw.free_dst_data_backup[index], - sizeof(struct pandata_s)) != 0)) { - memcpy(&osd_hw.free_src_data_backup[index], - &osd_hw.free_src_data[index], - sizeof(struct pandata_s)); - memcpy(&osd_hw.free_dst_data_backup[index], - &osd_hw.free_dst_data[index], - sizeof(struct pandata_s)); - return true; - } else - return false; -} -#endif - static void osd_setting_old_hwc(void) { int index = OSD1; @@ -7724,10 +8257,18 @@ static void osd_setting_old_hwc(void) static u32 osd_enable; spin_lock_irqsave(&osd_lock, lock_flags); + if (!osd_hw.osd_afbcd[index].enable) + canvas_config(osd_hw.fb_gem[index].canvas_idx, + osd_hw.fb_gem[index].addr, + osd_hw.fb_gem[index].width, + osd_hw.fb_gem[index].height, + CANVAS_ADDR_NOWRAP, + CANVAS_BLKMODE_LINEAR); osd_hw.reg[OSD_COLOR_MODE].update_func(index); freescale_update = set_old_hwc_freescale(index); /* geometry and freescale need update with ioctl */ osd_hw.reg[DISP_GEOMETRY].update_func(index); + osd_hw.reg[DISP_OSD_REVERSE].update_func(index); if ((osd_hw.free_scale_enable[index] && osd_update_window_axis) || freescale_update) { @@ -7755,31 +8296,42 @@ static void osd_setting_viu2(void) { int index = OSD4; + if (!osd_hw.osd_afbcd[index].enable) + canvas_config(osd_hw.fb_gem[index].canvas_idx, + osd_hw.fb_gem[index].addr, + osd_hw.fb_gem[index].width, + osd_hw.fb_gem[index].height, + CANVAS_ADDR_NOWRAP, + CANVAS_BLKMODE_LINEAR); osd_hw.reg[OSD_COLOR_MODE].update_func(index); /* geometry and freescale need update with ioctl */ osd_hw.reg[DISP_GEOMETRY].update_func(index); + osd_hw.reg[DISP_OSD_REVERSE].update_func(index); if (!osd_hw.osd_display_debug) osd_hw.reg[OSD_ENABLE] .update_func(index); + osd_wait_vsync_hw(); } -int osd_setting_blend(void) +int osd_setting_blend(u32 output_index) { int ret; if (osd_hw.osd_meson_dev.osd_ver < OSD_HIGH_ONE) osd_setting_old_hwc(); else { - if (osd_hw.hwc_enable) { - if (osd_hw.viu_type == VIU1) { - ret = osd_setting_order(); + if (osd_hw.hwc_enable[output_index]) { + if (output_index == VIU1) { + ret = osd_setting_order(output_index); if (ret < 0) return -1; - } else if (osd_hw.viu_type == VIU2) + } else if (output_index == VIU2) { osd_setting_viu2(); - } else + } + } else { osd_setting_default_hwc(); + } } return 0; } @@ -7940,6 +8492,19 @@ static void osd_basic_update_disp_geometry(u32 index) osd_hw.src_data[index].h - 1) & 0x1fff) << 16; VSYNCOSD_WR_MPEG_REG(osd_reg->osd_blk0_cfg_w2, data32); buffer_h = ((data32 >> 16) & 0x1fff) - (data32 & 0x1fff) + 1; + if (osd_hw.osd_meson_dev.has_dolby_vision) { + VSYNCOSD_WR_MPEG_REG( + DOLBY_CORE2A_SWAP_CTRL1, + ((buffer_w + 0x40) << 16) + | (buffer_h + 0x80 + 0)); + VSYNCOSD_WR_MPEG_REG( + DOLBY_CORE2A_SWAP_CTRL2, + (buffer_w << 16) | (buffer_h + 0)); + +#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION + update_graphic_width_height(buffer_w, buffer_h); +#endif + } data32 = VSYNCOSD_RD_MPEG_REG(osd_reg->osd_ctrl_stat); data32 &= ~0x1ff008;//0x1ff00e; data32 |= osd_hw.gbl_alpha[index] << 12; @@ -8313,14 +8878,16 @@ void osd_init_hw(u32 logo_loaded, u32 osd_probe, osd_hdr_on = false; #endif osd_hw.hw_reset_flag = HW_RESET_NONE; - osd_hw.hwc_enable = 0; + osd_hw.hwc_enable[VIU1] = 0; + osd_hw.hwc_enable[VIU2] = 0; if (osd_hw.osd_meson_dev.osd_ver <= OSD_NORMAL) { osd_hw.hw_cursor_en = 1; if (osd_hw.osd_meson_dev.has_rdma) osd_hw.hw_rdma_en = 1; } else if (osd_hw.osd_meson_dev.osd_ver == OSD_HIGH_ONE) { osd_hw.hw_cursor_en = 0; - osd_hw.hw_rdma_en = 1; + if (osd_hw.osd_meson_dev.has_rdma) + osd_hw.hw_rdma_en = 1; /* g12a and g12b need delay */ supsend_delay = 50; } @@ -8329,7 +8896,7 @@ void osd_init_hw(u32 logo_loaded, u32 osd_probe, /* init vpu fifo control register */ data32 = osd_reg_read(VPP_OFIFO_SIZE); if (osd_hw.osd_meson_dev.osd_ver >= OSD_HIGH_ONE) { - data32 = 0; /* reset value 0xfff0fff */ + data32 &= ~((0xfff << 20) | 0x3fff); data32 |= (osd_hw.osd_meson_dev.vpp_fifo_len) << 20; data32 |= osd_hw.osd_meson_dev.vpp_fifo_len + 1; } else @@ -8407,17 +8974,24 @@ void osd_init_hw(u32 logo_loaded, u32 osd_probe, osd_hw.order[OSD1] = LAYER_1; osd_hw.order[OSD2] = LAYER_2; osd_hw.order[OSD3] = LAYER_3; - //osd_hw.osd_blend_mode = OSD_BLEND_NONE; - osd_hw.disp_info.background_w = 1920; - osd_hw.disp_info.background_h = 1080; - osd_hw.disp_info.fullscreen_w = 1920; - osd_hw.disp_info.fullscreen_h = 1080; - osd_hw.disp_info.position_x = 0; - osd_hw.disp_info.position_y = 0; - osd_hw.disp_info.position_w = 1920; - osd_hw.disp_info.background_h = 1080; - osd_hw.vinfo_width = 1920; - osd_hw.vinfo_height = 1080; + for (idx = 0; idx < VIU_COUNT; idx++) { + osd_hw.disp_info[idx].background_w = 1920; + osd_hw.disp_info[idx].background_h = 1080; + osd_hw.disp_info[idx].fullscreen_w = 1920; + osd_hw.disp_info[idx].fullscreen_h = 1080; + osd_hw.disp_info[idx].position_x = 0; + osd_hw.disp_info[idx].position_y = 0; + osd_hw.disp_info[idx].position_w = 1920; + osd_hw.disp_info[idx].background_h = 1080; + osd_hw.vinfo_width[idx] = 1920; + osd_hw.vinfo_height[idx] = 1080; + } + if ((osd_hw.osd_meson_dev.cpu_id == + __MESON_CPU_MAJOR_ID_G12A) || + ((osd_hw.osd_meson_dev.cpu_id == + __MESON_CPU_MAJOR_ID_G12B) && + is_meson_rev_a())) + osd_hw.workaround_line = 1; for (idx = 0; idx < osd_hw.osd_meson_dev.osd_count; idx++) { osd_hw.premult_en[idx] = 0; osd_hw.osd_afbcd[idx].format = COLOR_INDEX_32_ABGR; @@ -8433,7 +9007,7 @@ void osd_init_hw(u32 logo_loaded, u32 osd_probe, osd_hw.afbc_regs_backup = 1; } else { osd_hw.afbc_force_reset = 1; - osd_hw.afbc_regs_backup = 0; + osd_hw.afbc_regs_backup = 1; data32 = osd_reg_read(MALI_AFBCD_TOP_CTRL); osd_reg_write(MALI_AFBCD_TOP_CTRL, data32 | 0x800000); @@ -8449,13 +9023,11 @@ void osd_init_hw(u32 logo_loaded, u32 osd_probe, osd_reg_set_bits( hw_osd_reg_array[idx].osd_fifo_ctrl_stat, 1, 10, 2); - /* TODO: temp set at here, - * need check for logo - */ - if (idx > 0) - osd_reg_set_bits( - hw_osd_reg_array[idx].osd_ctrl_stat, - 0, 0, 1); + if (osd_hw.osd_meson_dev.cpu_id == + __MESON_CPU_MAJOR_ID_G12B) + osd_reg_set_bits + (hw_osd_reg_array[idx].osd_ctrl_stat, + 1, 0, 1); osd_reg_set_bits( hw_osd_reg_array[idx].osd_ctrl_stat, 0, 31, 1); @@ -8539,15 +9111,26 @@ void osd_init_hw(u32 logo_loaded, u32 osd_probe, } /* hwc_enable == 0 handler */ #ifdef CONFIG_AMLOGIC_MEDIA_FB_OSD_SYNC_FENCE - osd_hw.osd_fence[DISABLE].sync_fence_handler = + osd_hw.osd_fence[VIU1][DISABLE].sync_fence_handler = sync_render_single_fence; - osd_hw.osd_fence[DISABLE].toggle_buffer_handler = + osd_hw.osd_fence[VIU1][DISABLE].toggle_buffer_handler = osd_toggle_buffer_single; /* hwc_enable == 1 handler */ - osd_hw.osd_fence[ENABLE].sync_fence_handler = + osd_hw.osd_fence[VIU1][ENABLE].sync_fence_handler = sync_render_layers_fence; - osd_hw.osd_fence[ENABLE].toggle_buffer_handler = + osd_hw.osd_fence[VIU1][ENABLE].toggle_buffer_handler = osd_toggle_buffer_layers; + if (osd_hw.osd_meson_dev.has_viu2) { + osd_hw.osd_fence[VIU2][DISABLE].sync_fence_handler = + sync_render_single_fence; + osd_hw.osd_fence[VIU2][DISABLE].toggle_buffer_handler = + osd_toggle_buffer_single_viu2; + /* hwc_enable == 1 handler */ + osd_hw.osd_fence[VIU2][ENABLE].sync_fence_handler = + sync_render_layers_fence; + osd_hw.osd_fence[VIU2][ENABLE].toggle_buffer_handler = + osd_toggle_buffer_layers_viu2; + } #endif osd_hw.fb_gem[OSD1].canvas_idx = OSD1_CANVAS_INDEX; osd_hw.fb_gem[OSD2].canvas_idx = OSD2_CANVAS_INDEX; @@ -8558,7 +9141,8 @@ void osd_init_hw(u32 logo_loaded, u32 osd_probe, osd_extra_canvas_alloc(); osd_hw.antiflicker_mode = 0; osd_hw.osd_deband_enable = 1; - osd_hw.out_fence_fd = -1; + osd_hw.out_fence_fd[VIU1] = -1; + osd_hw.out_fence_fd[VIU2] = -1; osd_hw.blend_bypass = 0; osd_hw.afbc_err_cnt = 0; if (osd_hw.osd_meson_dev.osd_ver == OSD_SIMPLE) { @@ -8573,8 +9157,10 @@ void osd_init_hw(u32 logo_loaded, u32 osd_probe, osd_set_deband(osd_hw.osd_deband_enable); if (osd_hw.fb_drvier_probe) { #ifdef CONFIG_AMLOGIC_MEDIA_FB_OSD_SYNC_FENCE - INIT_LIST_HEAD(&post_fence_list); - mutex_init(&post_fence_list_lock); + INIT_LIST_HEAD(&post_fence_list[VIU1]); + mutex_init(&post_fence_list_lock[VIU1]); + INIT_LIST_HEAD(&post_fence_list[VIU2]); + mutex_init(&post_fence_list_lock[VIU2]); #endif #ifdef FIQ_VSYNC osd_hw.fiq_handle_item.handle = vsync_isr; @@ -8603,7 +9189,7 @@ void osd_init_hw(u32 logo_loaded, u32 osd_probe, #endif } if (osd_hw.hw_rdma_en) - osd_rdma_enable(1); + osd_rdma_enable(2); } @@ -8854,7 +9440,7 @@ void osd_cursor_hw_no_scale(u32 index, s16 x, s16 y, s16 xstart, s16 ystart, memcpy(&disp_tmp, &osd_hw.dispdata[OSD1], sizeof(struct pandata_s)); - if (osd_hw.field_out_en) { + if (osd_hw.field_out_en[VIU1]) { disp_tmp.y_start *= 2; disp_tmp.y_end *= 2; } @@ -8960,7 +9546,7 @@ void osd_cursor_hw_no_scale(u32 index, s16 x, s16 y, s16 xstart, s16 ystart, } } - if (osd_hw.field_out_en) + if (osd_hw.field_out_en[VIU1]) osd_hw.dispdata[OSD2].y_start /= 2; osd_hw.dispdata[OSD2].x_end = osd_hw.dispdata[OSD2].x_start + @@ -9000,15 +9586,19 @@ void osd_suspend_hw(void) osd_reg_read(VIU_OSD_BLEND_CTRL); osd_hw.reg_status_save1 = osd_reg_read(OSD1_BLEND_SRC_CTRL); - osd_hw.reg_status_save2 = - osd_reg_read(OSD2_BLEND_SRC_CTRL); + osd_hw.reg_status_save3 = osd_reg_read(VPP_RDARB_REQEN_SLV); osd_hw.reg_status_save4 = osd_reg_read(VPU_MAFBC_SURFACE_CFG); osd_reg_clr_mask(VIU_OSD_BLEND_CTRL, 0xf0000); osd_reg_clr_mask(OSD1_BLEND_SRC_CTRL, 0xf0f); - osd_reg_clr_mask(OSD2_BLEND_SRC_CTRL, 0xf0f); + if (!enable_vd_zorder) { + osd_hw.reg_status_save2 = + osd_reg_read(OSD2_BLEND_SRC_CTRL); + osd_reg_clr_mask( + OSD2_BLEND_SRC_CTRL, 0xf0f); + } osd_reg_clr_mask(VPP_RDARB_REQEN_SLV, rdarb_reqen_slv); osd_reg_write(VPU_MAFBC_SURFACE_CFG, 0); @@ -9063,8 +9653,9 @@ void osd_resume_hw(void) osd_hw.reg_status_save); osd_reg_write(OSD1_BLEND_SRC_CTRL, osd_hw.reg_status_save1); - osd_reg_write(OSD2_BLEND_SRC_CTRL, - osd_hw.reg_status_save2); + if (!enable_vd_zorder) + osd_reg_write(OSD2_BLEND_SRC_CTRL, + osd_hw.reg_status_save2); osd_reg_write(VPP_RDARB_REQEN_SLV, osd_hw.reg_status_save3); osd_reg_write(VPU_MAFBC_SURFACE_CFG, @@ -9434,6 +10025,7 @@ static const struct color_bit_define_s *convert_panel_format(u32 format) { const struct color_bit_define_s *color = NULL; + format &= ~AFBC_EN; switch (format) { case COLOR_INDEX_02_PAL4: case COLOR_INDEX_04_PAL16: @@ -9475,19 +10067,27 @@ static bool osd_direct_render(struct osd_plane_map_s *plane_map) u32 x_start, x_end, y_start, y_end; bool freescale_update = false; struct pandata_s freescale_dst[HW_OSD_COUNT]; + u32 output_index; + output_index = get_output_device_id(index); phy_addr = phy_addr + plane_map->byte_stride * plane_map->src_y; osd_hw.screen_base[index] = phy_addr; osd_hw.screen_size[index] = plane_map->byte_stride * plane_map->src_h; osd_log_dbg(MODULE_RENDER, "canvas_id=%x, phy_addr=%x\n", osd_hw.fb_gem[index].canvas_idx, phy_addr); - canvas_config(osd_hw.fb_gem[index].canvas_idx, - phy_addr, - plane_map->byte_stride, - plane_map->src_h, - CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_LINEAR); - if (osd_hw.hwc_enable) { + if (osd_hw.osd_meson_dev.osd_ver == OSD_SIMPLE) { + osd_hw.fb_gem[index].addr = phy_addr; + osd_hw.fb_gem[index].width = plane_map->byte_stride; + osd_update_phy_addr(0); + } else { + canvas_config(osd_hw.fb_gem[index].canvas_idx, + phy_addr, + plane_map->byte_stride, + plane_map->src_h, + CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_LINEAR); + } + if (osd_hw.hwc_enable[output_index]) { /* just get para, need update via do_hwc */ osd_hw.order[index] = plane_map->zorder; switch (plane_map->blend_mode) { @@ -9579,30 +10179,30 @@ static bool osd_direct_render(struct osd_plane_map_s *plane_map) ((plane_map->dst_y + plane_map->dst_h) * height_dst) / height_src - 1; if (osd_hw.osd_reverse[index] == REVERSE_TRUE) { - x_start = osd_hw.vinfo_width + x_start = osd_hw.vinfo_width[output_index] - freescale_dst[index].x_end - 1; - y_start = osd_hw.vinfo_height + y_start = osd_hw.vinfo_height[output_index] - freescale_dst[index].y_end - 1; - x_end = osd_hw.vinfo_width + x_end = osd_hw.vinfo_width[output_index] - freescale_dst[index].x_start - 1; - y_end = osd_hw.vinfo_height + y_end = osd_hw.vinfo_height[output_index] - freescale_dst[index].y_start - 1; freescale_dst[index].x_start = x_start; freescale_dst[index].y_start = y_start; freescale_dst[index].x_end = x_end; freescale_dst[index].y_end = y_end; } else if (osd_hw.osd_reverse[index] == REVERSE_X) { - x_start = osd_hw.vinfo_width + x_start = osd_hw.vinfo_width[output_index] - freescale_dst[index].x_end - 1; - x_end = osd_hw.vinfo_width + x_end = osd_hw.vinfo_width[output_index] - freescale_dst[index].x_start - 1; freescale_dst[index].x_start = x_start; freescale_dst[index].x_end = x_end; } else if (osd_hw.osd_reverse[index] == REVERSE_Y) { - y_start = osd_hw.vinfo_height + y_start = osd_hw.vinfo_height[output_index] - freescale_dst[index].y_end - 1; - y_end = osd_hw.vinfo_height + y_end = osd_hw.vinfo_height[output_index] - freescale_dst[index].y_start - 1; freescale_dst[index].y_start = y_start; freescale_dst[index].y_end = y_end; @@ -9668,30 +10268,30 @@ static bool osd_direct_render(struct osd_plane_map_s *plane_map) osd_hw.dispdata[index].y_end = plane_map->dst_y + plane_map->dst_h - 1; if (osd_hw.osd_reverse[index] == REVERSE_TRUE) { - x_start = osd_hw.vinfo_width + x_start = osd_hw.vinfo_width[output_index] - osd_hw.dispdata[index].x_end - 1; - y_start = osd_hw.vinfo_height + y_start = osd_hw.vinfo_height[output_index] - osd_hw.dispdata[index].y_end - 1; - x_end = osd_hw.vinfo_width + x_end = osd_hw.vinfo_width[output_index] - osd_hw.dispdata[index].x_start - 1; - y_end = osd_hw.vinfo_height + y_end = osd_hw.vinfo_height[output_index] - osd_hw.dispdata[index].y_start - 1; osd_hw.dispdata[index].x_start = x_start; osd_hw.dispdata[index].y_start = y_start; osd_hw.dispdata[index].x_end = x_end; osd_hw.dispdata[index].y_end = y_end; } else if (osd_hw.osd_reverse[index] == REVERSE_X) { - x_start = osd_hw.vinfo_width + x_start = osd_hw.vinfo_width[output_index] - osd_hw.dispdata[index].x_end - 1; - x_end = osd_hw.vinfo_width + x_end = osd_hw.vinfo_width[output_index] - osd_hw.dispdata[index].x_start - 1; osd_hw.dispdata[index].x_start = x_start; osd_hw.dispdata[index].x_end = x_end; } else if (osd_hw.osd_reverse[index] == REVERSE_Y) { - y_start = osd_hw.vinfo_height + y_start = osd_hw.vinfo_height[output_index] - osd_hw.dispdata[index].y_end - 1; - y_end = osd_hw.vinfo_height + y_end = osd_hw.vinfo_height[output_index] - osd_hw.dispdata[index].y_start - 1; osd_hw.dispdata[index].y_start = y_start; osd_hw.dispdata[index].y_end = y_end; @@ -9719,9 +10319,11 @@ static void osd_cursor_move(struct osd_plane_map_s *plane_map) u32 x, y; struct pandata_s disp_tmp; struct pandata_s free_dst_data_backup; + u32 output_index; if (index != OSD2) return; + output_index = get_output_device_id(index); phy_addr = phy_addr + plane_map->byte_stride * plane_map->src_y; osd_hw.screen_base[index] = phy_addr; osd_hw.screen_size[index] = @@ -9819,29 +10421,29 @@ static void osd_cursor_move(struct osd_plane_map_s *plane_map) osd_hw.pandata[OSD2].y_end - osd_hw.pandata[OSD2].y_start; if (osd_hw.osd_reverse[OSD2] == REVERSE_TRUE) { - x_start = osd_hw.vinfo_width + x_start = osd_hw.vinfo_width[output_index] - osd_hw.dispdata[index].x_end - 1; - y_start = osd_hw.vinfo_height + y_start = osd_hw.vinfo_height[output_index] - osd_hw.dispdata[index].y_end - 1; - x_end = osd_hw.vinfo_width + x_end = osd_hw.vinfo_width[output_index] - osd_hw.dispdata[index].x_start - 1; - y_end = osd_hw.vinfo_height + y_end = osd_hw.vinfo_height[output_index] - osd_hw.dispdata[index].y_start - 1; osd_hw.dispdata[index].x_start = x_start; osd_hw.dispdata[index].y_start = y_start; osd_hw.dispdata[index].x_end = x_end; osd_hw.dispdata[index].y_end = y_end; } else if (osd_hw.osd_reverse[OSD2] == REVERSE_X) { - x_start = osd_hw.vinfo_width + x_start = osd_hw.vinfo_width[output_index] - osd_hw.dispdata[index].x_end - 1; - x_end = osd_hw.vinfo_width + x_end = osd_hw.vinfo_width[output_index] - osd_hw.dispdata[index].x_start - 1; osd_hw.dispdata[index].x_start = x_start; osd_hw.dispdata[index].x_end = x_end; } else if (osd_hw.osd_reverse[OSD2] == REVERSE_Y) { - y_start = osd_hw.vinfo_height + y_start = osd_hw.vinfo_height[output_index] - osd_hw.dispdata[index].y_end - 1; - y_end = osd_hw.vinfo_height + y_end = osd_hw.vinfo_height[output_index] - osd_hw.dispdata[index].y_start - 1; osd_hw.dispdata[index].y_start = y_start; osd_hw.dispdata[index].y_end = y_end; @@ -9879,9 +10481,11 @@ void osd_page_flip(struct osd_plane_map_s *plane_map) bool freescale_update = false; u32 osd_enable = 0; u32 format = 0; - const struct vinfo_s *vinfo; + const struct vinfo_s *vinfo = NULL; + u32 output_index; - if (!osd_hw.hwc_enable) { + output_index = get_output_device_id(index); + if (!osd_hw.hwc_enable[output_index]) { if (index >= OSD2) return; } else { @@ -9890,16 +10494,24 @@ void osd_page_flip(struct osd_plane_map_s *plane_map) } osd_hw.buffer_alloc[index] = 1; - if (osd_hw.osd_fps_start) - osd_hw.osd_fps++; - + if (osd_hw.osd_fps_start[output_index]) + osd_hw.osd_fps[output_index]++; osd_enable = (plane_map->enable & 1) ? ENABLE : DISABLE; + + if (output_index == VIU1) + vinfo = get_current_vinfo(); +#ifdef CONFIG_AMLOGIC_VOUT2_SERVE + else if (output_index == VIU2) + vinfo = get_current_vinfo2(); +#endif vinfo = get_current_vinfo(); - if (vinfo && (strcmp(vinfo->name, "invalid") && - strcmp(vinfo->name, "null"))) { - osd_hw.vinfo_width = vinfo->width; - osd_hw.vinfo_height = vinfo->height; + if (vinfo && (!strcmp(vinfo->name, "invalid") || + !strcmp(vinfo->name, "null"))) { + return; } + osd_hw.vinfo_width[output_index] = vinfo->width; + osd_hw.vinfo_height[output_index] = vinfo->height; + osd_hw.osd_afbcd[index].enable = (plane_map->afbc_inter_format & AFBC_EN) >> 31; if (osd_hw.osd_meson_dev.osd_ver <= OSD_NORMAL) { @@ -9923,6 +10535,7 @@ void osd_page_flip(struct osd_plane_map_s *plane_map) plane_map->phy_addr; osd_hw.reg[OSD_COLOR_MODE].update_func(index); osd_hw.reg[DISP_GEOMETRY].update_func(index); + osd_hw.reg[DISP_OSD_REVERSE].update_func(index); if ((osd_hw.free_scale_enable[index] && osd_update_window_axis) || freescale_update) { @@ -9954,6 +10567,7 @@ void osd_page_flip(struct osd_plane_map_s *plane_map) osd_cursor_move(plane_map); osd_hw.reg[OSD_COLOR_MODE].update_func(index); osd_hw.reg[DISP_GEOMETRY].update_func(index); + osd_hw.reg[DISP_OSD_REVERSE].update_func(index); if ((osd_enable != osd_hw.enable[index]) && (suspend_flag == false)) { osd_hw.enable[index] = osd_enable; @@ -9992,8 +10606,9 @@ void osd_page_flip(struct osd_plane_map_s *plane_map) osd_hw.osd_afbcd[index].phy_addr = plane_map->phy_addr; osd_hw.reg[OSD_COLOR_MODE].update_func(index); - if (!osd_hw.hwc_enable) { + if (!osd_hw.hwc_enable[output_index]) { osd_hw.reg[DISP_GEOMETRY].update_func(index); + osd_hw.reg[DISP_OSD_REVERSE].update_func(index); if ((osd_hw.free_scale_enable[index] && osd_update_window_axis) || freescale_update) { diff --git a/drivers/amlogic/media/osd/osd_hw.h b/drivers/amlogic/media/osd/osd_hw.h index 61c14dc12b84..f86f0b29b2f2 100644 --- a/drivers/amlogic/media/osd/osd_hw.h +++ b/drivers/amlogic/media/osd/osd_hw.h @@ -30,6 +30,7 @@ extern int int_viu_vsync; extern int int_viu2_vsync; extern struct hw_para_s osd_hw; +extern int enable_vd_zorder; #ifdef CONFIG_HIBERNATION extern void osd_freeze_hw(void); @@ -101,7 +102,7 @@ extern void osd_set_block_mode_hw(u32 index, u32 mode); extern void osd_enable_3d_mode_hw(u32 index, u32 enable); extern void osd_set_2x_scale_hw(u32 index, u16 h_scale_enable, u16 v_scale_enable); -extern void osd_get_flush_rate_hw(u32 *break_rate); +extern void osd_get_flush_rate_hw(u32 index, u32 *break_rate); extern void osd_set_reverse_hw(u32 index, u32 reverse, u32 update); extern void osd_get_reverse_hw(u32 index, u32 *reverse); extern void osd_set_antiflicker_hw(u32 index, struct vinfo_s *vinfo, u32 yres); @@ -125,7 +126,7 @@ extern int osd_sync_request_render(u32 index, u32 yres, struct sync_req_render_s *request, u32 phys_addr, size_t len); -extern int osd_sync_do_hwc(struct do_hwc_cmd_s *hwc_cmd); +int osd_sync_do_hwc(u32 output_index, struct do_hwc_cmd_s *hwc_cmd); extern s64 osd_wait_vsync_event(void); extern void osd_cursor_hw(u32 index, s16 x, s16 y, s16 xstart, s16 ystart, u32 osd_w, u32 osd_h); @@ -164,8 +165,8 @@ extern void osd_get_urgent(u32 index, u32 *urgent); extern void osd_set_urgent(u32 index, u32 urgent); void osd_get_deband(u32 *osd_deband_enable); void osd_set_deband(u32 osd_deband_enable); -void osd_get_fps(u32 *osd_fps); -void osd_set_fps(u32 osd_fps_start); +void osd_get_fps(u32 index, u32 *osd_fps); +void osd_set_fps(u32 index, u32 osd_fps_start); extern void osd_get_info(u32 index, u32 *addr, u32 *width, u32 *height); void osd_update_scan_mode(void); void osd_update_3d_mode(void); @@ -179,15 +180,15 @@ int set_osd_logo_freescaler(void); int is_interlaced(struct vinfo_s *vinfo); void osd_get_display_debug(u32 *osd_display_debug_enable); void osd_set_display_debug(u32 osd_display_debug_enable); -void osd_get_background_size(struct display_flip_info_s *disp_info); -void osd_set_background_size(struct display_flip_info_s *disp_info); +void osd_get_background_size(u32 index, struct display_flip_info_s *disp_info); +void osd_set_background_size(u32 index, struct display_flip_info_s *disp_info); void osd_get_hdr_used(u32 *val); void osd_set_hdr_used(u32 val); void osd_get_afbc_format(u32 index, u32 *format, u32 *inter_format); void osd_set_afbc_format(u32 index, u32 format, u32 inter_format); -void osd_get_hwc_enable(u32 *hwc_enable); -void osd_set_hwc_enable(u32 hwc_enable); -void osd_do_hwc(void); +void osd_get_hwc_enable(u32 index, u32 *hwc_enable); +void osd_set_hwc_enable(u32 index, u32 hwc_enable); +void osd_do_hwc(u32 index); int osd_get_capbility(u32 index); void osd_backup_screen_info( u32 index, @@ -203,16 +204,19 @@ ssize_t dd_vmap_write(u32 index, const char __user *buf, int osd_set_clear(u32 index); void osd_page_flip(struct osd_plane_map_s *plane_map); void walk_through_update_list(void); -int osd_setting_blend(void); -void osd_set_hwc_enable(u32 hwc_enable); +int osd_setting_blend(u32 output_index); +void osd_set_hwc_enable(u32 index, u32 hwc_enable); void osd_set_urgent_info(u32 ports, u32 basic_urgent); void osd_get_urgent_info(u32 *ports, u32 *basic_urgent); -void osd_set_single_step_mode(u32 osd_single_step_mode); -void osd_set_single_step(u32 osd_single_step); +void osd_set_single_step_mode(u32 index, u32 osd_single_step_mode); +void osd_set_single_step(u32 index, u32 osd_single_step); void output_save_info(void); void osd_get_rotate(u32 index, u32 *osd_rotate); void osd_set_rotate(u32 index, u32 osd_rotate); void osd_get_afbc_err_cnt(u32 *err_cnt); void osd_get_dimm_info(u32 index, u32 *osd_dimm_layer, u32 *osd_dimm_color); void osd_set_dimm_info(u32 index, u32 osd_dimm_layer, u32 osd_dimm_color); +u32 osd_get_line_n_rdma(void); +void osd_set_line_n_rdma(u32 line_n_rdma); +u32 get_output_device_id(u32 index); #endif diff --git a/drivers/amlogic/media/osd/osd_rdma.c b/drivers/amlogic/media/osd/osd_rdma.c index f1d08ca33e4a..164d6412968d 100644 --- a/drivers/amlogic/media/osd/osd_rdma.c +++ b/drivers/amlogic/media/osd/osd_rdma.c @@ -33,7 +33,7 @@ #include #include #include - +#include /* Local Headers */ #include "osd.h" #include "osd_io.h" @@ -47,6 +47,7 @@ #include #endif #endif +#define RDMA_TRIGGER_LINE_INPUT (1 << 5) #if 0 #ifndef CONFIG_AMLOGIC_MEDIA_RDMA @@ -1085,9 +1086,19 @@ static int start_osd_rdma(char channel) data32 &= ~(1 << inc_bit); osd_reg_write(RDMA_ACCESS_AUTO, data32); #else - rdma_config(channel, - RDMA_TRIGGER_VSYNC_INPUT - | RDMA_AUTO_START_MASK); + if (osd_hw.osd_meson_dev.cpu_id == __MESON_CPU_MAJOR_ID_G12B && + is_meson_rev_b()) { + set_reset_rdma_trigger_line(); + rdma_config(channel, RDMA_TRIGGER_LINE_INPUT | + RDMA_AUTO_START_MASK); + osd_hw.line_n_rdma = 1; + + } else { + rdma_config(channel, + RDMA_TRIGGER_VSYNC_INPUT + | RDMA_AUTO_START_MASK); + osd_hw.line_n_rdma = 0; + } #endif return 1; } @@ -1113,6 +1124,41 @@ static int stop_rdma(char channel) return 0; } +void enable_line_n_rdma(void) +{ + unsigned long flags; + + osd_log_info("%s\n", __func__); + rdma_clear(OSD_RDMA_CHANNEL_INDEX); + spin_lock_irqsave(&rdma_lock, flags); + OSD_RDMA_STATUS_CLEAR_REJECT; + osd_reg_write(START_ADDR, table_paddr); + osd_reg_write(END_ADDR, table_paddr - 1); + item_count = 0; + spin_unlock_irqrestore(&rdma_lock, flags); + reset_rdma_table(); + rdma_config(OSD_RDMA_CHANNEL_INDEX, + RDMA_TRIGGER_LINE_INPUT | + RDMA_AUTO_START_MASK); +} + +void enable_vsync_rdma(void) +{ + unsigned long flags; + + osd_log_info("%s\n", __func__); + rdma_clear(OSD_RDMA_CHANNEL_INDEX); + spin_lock_irqsave(&rdma_lock, flags); + OSD_RDMA_STATUS_CLEAR_REJECT; + osd_reg_write(START_ADDR, table_paddr); + osd_reg_write(END_ADDR, table_paddr - 1); + item_count = 0; + spin_unlock_irqrestore(&rdma_lock, flags); + reset_rdma_table(); + rdma_config(OSD_RDMA_CHANNEL_INDEX, + RDMA_TRIGGER_VSYNC_INPUT + | RDMA_AUTO_START_MASK); +} void osd_rdma_interrupt_done_clear(void) { diff --git a/drivers/amlogic/media/osd/osd_rdma.h b/drivers/amlogic/media/osd/osd_rdma.h index 4e78e4f11c83..b1e5e4e6f4c4 100644 --- a/drivers/amlogic/media/osd/osd_rdma.h +++ b/drivers/amlogic/media/osd/osd_rdma.h @@ -69,4 +69,7 @@ extern int rdma_reset_tigger_flag; extern int rdma_mgr_irq_request; extern void osd_rdma_interrupt_done_clear(void); extern int osd_rdma_uninit(void); +void set_reset_rdma_trigger_line(void); +void enable_line_n_rdma(void); +void enable_vsync_rdma(void); #endif diff --git a/drivers/amlogic/media/osd/osd_reg.h b/drivers/amlogic/media/osd/osd_reg.h index 517ca97827f0..e2218bd572c1 100644 --- a/drivers/amlogic/media/osd/osd_reg.h +++ b/drivers/amlogic/media/osd/osd_reg.h @@ -392,7 +392,7 @@ #define VPP_OSD_SCALE_COEF_IDX 0x1dcc #define VPP_OSD_SCALE_COEF 0x1dcd #define VPP_INT_LINE_NUM 0x1dce - +#define VPP_OSD_SCALE_CTRL 0x1dff /* osd2 scaler */ #define OSD2_VSC_PHASE_STEP 0x3d00 #define OSD2_VSC_INI_PHASE 0x3d01 diff --git a/drivers/amlogic/media/osd/osd_sync.h b/drivers/amlogic/media/osd/osd_sync.h index 77f754ca68c5..dd8c085bebc1 100644 --- a/drivers/amlogic/media/osd/osd_sync.h +++ b/drivers/amlogic/media/osd/osd_sync.h @@ -88,6 +88,8 @@ struct sync_req_render_s { unsigned char plane_alpha; unsigned char dim_layer; unsigned int dim_color; + int fb_width; + int fb_height; int reserve; }; diff --git a/drivers/amlogic/media/video_processor/Kconfig b/drivers/amlogic/media/video_processor/Kconfig index e86e8eb2b8e9..ef42224d59d8 100644 --- a/drivers/amlogic/media/video_processor/Kconfig +++ b/drivers/amlogic/media/video_processor/Kconfig @@ -17,7 +17,7 @@ source "drivers/amlogic/media/video_processor/video_dev/Kconfig" 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" endif endmenu diff --git a/drivers/amlogic/media/video_processor/Makefile b/drivers/amlogic/media/video_processor/Makefile index 53464584c7d2..d6db469cbf2c 100644 --- a/drivers/amlogic/media/video_processor/Makefile +++ b/drivers/amlogic/media/video_processor/Makefile @@ -1,4 +1,6 @@ +obj-$(CONFIG_AMLOGIC_V4L_VIDEO) += video_dev/ 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 diff --git a/drivers/amlogic/media/video_processor/pic_dev/picdec.c b/drivers/amlogic/media/video_processor/pic_dev/picdec.c index 7d28ea390ed1..451718bf9fe0 100644 --- a/drivers/amlogic/media/video_processor/pic_dev/picdec.c +++ b/drivers/amlogic/media/video_processor/pic_dev/picdec.c @@ -778,6 +778,7 @@ static int picdec_memset_phyaddr(ulong phys, u32 size, u32 val) if (!p) return -1; memset(p, val, span); + codec_mm_dma_flush(p, span, DMA_TO_DEVICE); codec_mm_unmap_phyaddr(p); } return 0; @@ -887,6 +888,7 @@ static int copy_phybuf_to_file(ulong phys, u32 size, p = codec_mm_vmap(addr, span); if (!p) return -1; + codec_mm_dma_flush(p, span, DMA_FROM_DEVICE); vfs_write(fp, (char *)p, span, &pos); pos += span; diff --git a/drivers/amlogic/media/video_processor/ppmgr/ppmgr_drv.c b/drivers/amlogic/media/video_processor/ppmgr/ppmgr_drv.c index d33d14898795..352c0adc799e 100644 --- a/drivers/amlogic/media/video_processor/ppmgr/ppmgr_drv.c +++ b/drivers/amlogic/media/video_processor/ppmgr/ppmgr_drv.c @@ -31,11 +31,11 @@ #include #include #include +#include #include "ppmgr_log.h" #include "ppmgr_pri.h" #include "ppmgr_dev.h" -#include #define PPMGRDRV_INFO(fmt, args...) pr_info("PPMGRDRV: info: "fmt"", ## args) #define PPMGRDRV_DBG(fmt, args...) pr_debug("PPMGRDRV: dbg: "fmt"", ## args) @@ -1419,6 +1419,7 @@ void get_ppmgr_buf_info(unsigned int *start, unsigned int *size) *start = ppmgr_device.buffer_start; *size = ppmgr_device.buffer_size; } +EXPORT_SYMBOL(get_ppmgr_buf_info); static int ppmgr_open(struct inode *inode, struct file *file) { diff --git a/drivers/amlogic/media/video_processor/ppmgr/ppmgr_vpp.c b/drivers/amlogic/media/video_processor/ppmgr/ppmgr_vpp.c index d9560b43fd9e..225b887f82d4 100644 --- a/drivers/amlogic/media/video_processor/ppmgr/ppmgr_vpp.c +++ b/drivers/amlogic/media/video_processor/ppmgr/ppmgr_vpp.c @@ -46,7 +46,6 @@ #include #include #include -#include /*#include "../amports/video.h"*/ #include /*#include "../amports/vdec_reg.h"*/ @@ -178,9 +177,11 @@ static u32 tb_buffer_len = TB_DETECT_BUFFER_MAX_SIZE; static atomic_t tb_reset_flag; static u32 tb_init_mute; static atomic_t tb_skip_flag; +static atomic_t tb_run_flag; static bool tb_quit_flag; static struct TB_DetectFuncPtr *gfunc; static int tb_buffer_init(void); +static int tb_buffer_uninit(void); #endif const struct vframe_receiver_op_s *vf_ppmgr_reg_provider(void); @@ -2755,7 +2756,6 @@ static int process_vf_adjust(struct vframe_s *vf, /* extern int get_tv_process_type(struct vframe_s *vf); */ /* #endif */ static struct task_struct *task; -/* extern int video_property_notify(int flag); */ /* extern struct vframe_s *get_cur_dispbuf(void); */ /* extern enum platform_type_t get_platform_type(void); */ @@ -2835,7 +2835,10 @@ static int ppmgr_task(void *data) continue; process_vf_change(vf, context, &ge2d_config); - video_property_notify(2); + vf_notify_receiver( + PROVIDER_NAME, + VFRAME_EVENT_PROVIDER_PROPERTY_CHANGED, + NULL); vfq_lookup_start(&q_ready); vf = vfq_peek(&q_ready); @@ -3075,7 +3078,9 @@ static int ppmgr_task(void *data) /* wait tb task done */ while ((tb_buff_wptr >= 5) && (tb_buff_rptr - <= tb_buff_wptr - 5)) + <= tb_buff_wptr - 5) + && (atomic_read(&tb_run_flag) + == 1)) usleep_range( 4000, 5000); atomic_set(&detect_status, @@ -3165,7 +3170,9 @@ static int ppmgr_task(void *data) "tb detect skip case1\n"); goto SKIP_DETECT; } - if (tb_buff_wptr < tb_buffer_len) { + if ((tb_buff_wptr < tb_buffer_len) + && (atomic_read(&tb_run_flag) + == 1)) { ret = process_vf_tb_detect( vf, context, &ge2d_config); } else { @@ -3247,7 +3254,7 @@ SKIP_DETECT: vf_local_init(); vf_light_unreg_provider(&ppmgr_vf_prov); msleep(30); - vf_reg_provider(&ppmgr_vf_prov); + vf_light_reg_provider(&ppmgr_vf_prov); ppmgr_blocking = false; up(&thread_sem); PPMGRVPP_WARN("ppmgr rebuild from light-unregister\n"); @@ -3262,6 +3269,9 @@ SKIP_DETECT: } destroy_ge2d_work_queue(context); +#ifdef PPMGR_TB_DETECT + tb_buffer_uninit(); +#endif ppmgr_buffer_uninit(); while (!kthread_should_stop()) { /* may not call stop, wait.. @@ -3626,7 +3636,8 @@ void stop_ppmgr_task(void) static int tb_buffer_init(void) { int i; - int flags = CODEC_MM_FLAGS_DMA_CPU | CODEC_MM_FLAGS_CMA_CLEAR; + //int flags = CODEC_MM_FLAGS_DMA_CPU | CODEC_MM_FLAGS_CMA_CLEAR; + int flags = 0; if (tb_buffer_status) return tb_buffer_status; @@ -3675,7 +3686,8 @@ static int tb_buffer_init(void) detect_buf[i].paddr = tb_buffer_start + TB_DETECT_H * TB_DETECT_W * i; detect_buf[i].vaddr = - (ulong)phys_to_virt(detect_buf[i].paddr); + (ulong)codec_mm_vmap(detect_buf[i].paddr, + TB_DETECT_H * TB_DETECT_W); if (ppmgr_device.tb_detect & 0xc) { PPMGRVPP_INFO( "detect buff(%d) paddr: %lx, vaddr: %lx\n", @@ -3691,6 +3703,7 @@ static int tb_buffer_init(void) static int tb_buffer_uninit(void) { + int i; if (tb_src_canvas) { if (tb_src_canvas & 0xff) canvas_pool_map_free_canvas( @@ -3711,6 +3724,13 @@ static int tb_buffer_uninit(void) PPMGRVPP_INFO("tb cma free addr is %x, size is %x\n", (unsigned int)tb_buffer_start, (unsigned int)tb_buffer_size); + for (i = 0; i < tb_buffer_len; i++) { + if (detect_buf[i].vaddr) { + codec_mm_unmap_phyaddr( + (u8 *)detect_buf[i].vaddr); + detect_buf[i].vaddr = 0; + } + } codec_mm_free_for_dma( "tb_detect", tb_buffer_start); @@ -3731,6 +3751,7 @@ static void tb_detect_init(void) atomic_set(&tb_detect_flag, TB_DETECT_NC); atomic_set(&tb_reset_flag, 0); atomic_set(&tb_skip_flag, 0); + atomic_set(&tb_run_flag, 1); tb_detect_last_flag = TB_DETECT_NC; tb_buff_wptr = 0; tb_buff_rptr = 0; @@ -3829,9 +3850,9 @@ static int tb_task(void *data) atomic_set(&detect_status, tb_done); } } + atomic_set(&tb_run_flag, 0); while (!kthread_should_stop()) usleep_range(9000, 10000); - tb_buffer_uninit(); return 0; } diff --git a/drivers/amlogic/media/video_processor/video_dev/amlvideo.c b/drivers/amlogic/media/video_processor/video_dev/amlvideo.c index 252fa95fed95..f65c24a3f094 100644 --- a/drivers/amlogic/media/video_processor/video_dev/amlvideo.c +++ b/drivers/amlogic/media/video_processor/video_dev/amlvideo.c @@ -70,10 +70,14 @@ AMLVIDEO_MINOR_VERSION, AMLVIDEO_RELEASE) #define RECEIVER_NAME "amlvideo" #define PROVIDER_NAME "amlvideo" +#define RECEIVER_NAME_PIP "aml_video" +#define PROVIDER_NAME_PIP "aml_video" #define AMLVIDEO_POOL_SIZE 16 /*extern bool omx_secret_mode;*/ +static u32 omx_freerun_index = 0; + #define DUR2PTS(x) ((x) - ((x) >> 4)) #define DUR2PTS_RM(x) ((x) & 0xf) @@ -82,11 +86,12 @@ MODULE_AUTHOR("amlogic-sh"); MODULE_LICENSE("GPL"); /* static u32 vpts_remainder; */ static unsigned int video_nr_base = 10; +static unsigned int video_nr_base_second = 23; /* module_param(video_nr_base, uint, 0644); */ /* MODULE_PARM_DESC(video_nr_base, "videoX start number, 10 is defaut"); */ #ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC -static unsigned int n_devs = 1; +static unsigned int n_devs = 2; #else static unsigned int n_devs = 1; #endif @@ -186,11 +191,12 @@ static int amlvideo_vf_states(struct vframe_states *states, void *op_arg) /* unsigned long flags; */ /* spin_lock_irqsave(&lock, flags); */ struct vivi_dev *dev = (struct vivi_dev *)op_arg; + int avail_count = vfq_level(&dev->q_ready) + vfq_level(&dev->q_omx); states->vf_pool_size = AMLVIDEO_POOL_SIZE; states->buf_recycle_num = 0; - states->buf_free_num = AMLVIDEO_POOL_SIZE - vfq_level(&dev->q_ready); - states->buf_avail_num = vfq_level(&dev->q_ready); + states->buf_free_num = AMLVIDEO_POOL_SIZE - avail_count; + states->buf_avail_num = avail_count; /* spin_unlock_irqrestore(&lock, flags); */ return 0; } @@ -237,6 +243,8 @@ static int video_receiver_event_fun(int type, void *data, void *private_data) dev->first_frame = 0; vfq_init(&dev->q_ready, AMLVIDEO_POOL_SIZE + 1, &dev->amlvideo_pool_ready[0]); + vfq_init(&dev->q_omx, AMLVIDEO_POOL_SIZE + 1, + &dev->amlvideo_pool_omx[0]); } if (type == VFRAME_EVENT_PROVIDER_REG) { AMLVIDEO_DBG("AML:VFRAME_EVENT_PROVIDER_REG\n"); @@ -268,6 +276,8 @@ static int video_receiver_event_fun(int type, void *data, void *private_data) omx_secret_mode = true; vfq_init(&dev->q_ready, AMLVIDEO_POOL_SIZE + 1, &dev->amlvideo_pool_ready[0]); + vfq_init(&dev->q_omx, AMLVIDEO_POOL_SIZE + 1, + &dev->amlvideo_pool_omx[0]); vf_provider_init(&dev->video_vf_prov, dev->vf_provider_name, &amlvideo_vf_provider, dev); @@ -286,6 +296,8 @@ static int video_receiver_event_fun(int type, void *data, void *private_data) dev->first_frame = 0; vfq_init(&dev->q_ready, AMLVIDEO_POOL_SIZE + 1, &dev->amlvideo_pool_ready[0]); + vfq_init(&dev->q_omx, AMLVIDEO_POOL_SIZE + 1, + &dev->amlvideo_pool_omx[0]); vf_notify_receiver(dev->vf_provider_name, VFRAME_EVENT_PROVIDER_RESET, data); @@ -525,6 +537,28 @@ static int vidioc_querybuf(struct file *file, void *priv, struct v4l2_buffer *p) static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *p) { + u32 index; + struct vframe_s *vf; + struct vivi_dev *dev = video_drvdata(file); + while ((vf = vfq_peek(&dev->q_omx))) + { + index = (u32)vf->pts_us64; + if (p->index > index) + { + vf_put(vfq_pop(&dev->q_omx), dev->vf_receiver_name); + printk("vidioc_qbuf skip: index:%u:%u\n", p->index, index); + continue; + } + else if (p->index == index) + { + vf = (vfq_pop(&dev->q_omx)); + if (p->flags & V4L2_BUF_FLAG_DONE) + vf_put(vf, dev->vf_receiver_name); + else + vfq_push(&dev->q_ready, vf); + } + break; + } return 0; } @@ -559,6 +593,9 @@ static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) dev->am_parm.master_display_colour = dev->vf->prop.master_display_colour; + if (!dev->vf->pts_us64) + dev->vf->pts_us64 = ((u64)dev->vf->pts * 100) / 9; + if (dev->vf->pts_us64) { dev->first_frame = 1; pts_us64 = dev->vf->pts_us64; @@ -581,12 +618,13 @@ static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) if (dev->vf->next_vf_pts_valid) dev->vf->next_vf_pts = next_vf->pts; - vfq_push(&dev->q_ready, dev->vf); - p->index = 0; + p->index = omx_freerun_index; p->timestamp.tv_sec = pts_us64 >> 32; p->timestamp.tv_usec = pts_us64 & 0xFFFFFFFF; dev->last_pts_us64 = pts_us64; + dev->vf->pts_us64 = omx_freerun_index++; + vfq_push(&dev->q_omx, dev->vf); if ((dev->vf->type & VIDTYPE_COMPRESS) != 0) { p->timecode.type = dev->vf->compWidth; @@ -597,11 +635,6 @@ static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) } p->sequence = dev->frame_num++; - vf_notify_receiver( - dev->vf_provider_name, - VFRAME_EVENT_PROVIDER_VFRAME_READY, - NULL); - return ret; } @@ -887,7 +920,10 @@ static int __init amlvideo_create_instance(int inst) vfd->dev_debug = debug; vfd->v4l2_dev = &dev->v4l2_dev; dev->amlvideo_v4l_num = inst * 10 + video_nr_base; - + if (inst == 0) + dev->amlvideo_v4l_num = video_nr_base; + else + dev->amlvideo_v4l_num = (inst - 1) + video_nr_base_second; /* //////////////////////////////////////// */ /* vfd->v4l2_dev = &dev->v4l2_dev; */ /* //////////////////////////////////////// */ @@ -898,18 +934,19 @@ static int __init amlvideo_create_instance(int inst) goto rel_vdev; dev->inst = inst; -#if 0 - snprintf(dev->vf_receiver_name, AMLVIDEO_VF_NAME_SIZE, - (0) ? RECEIVER_NAME : RECEIVER_NAME ".%x", - inst & 0xff); - snprintf(dev->vf_provider_name, AMLVIDEO_VF_NAME_SIZE, - (0) ? PROVIDER_NAME : PROVIDER_NAME ".%x", - inst & 0xff); -#else - memcpy(dev->vf_receiver_name, RECEIVER_NAME, sizeof(RECEIVER_NAME)); - memcpy(dev->vf_provider_name, PROVIDER_NAME, sizeof(PROVIDER_NAME)); -#endif + if (inst != 0) { + snprintf(dev->vf_receiver_name, AMLVIDEO_VF_NAME_SIZE, + RECEIVER_NAME_PIP ".%x", inst & 0xff); + + snprintf(dev->vf_provider_name, AMLVIDEO_VF_NAME_SIZE, + PROVIDER_NAME_PIP ".%x", inst & 0xff); + } else { + memcpy(dev->vf_receiver_name, RECEIVER_NAME, + sizeof(RECEIVER_NAME)); + memcpy(dev->vf_provider_name, PROVIDER_NAME, + sizeof(PROVIDER_NAME)); + } vf_receiver_init(&dev->video_vf_recv, dev->vf_receiver_name, diff --git a/drivers/amlogic/media/video_processor/video_dev/amlvideo.h b/drivers/amlogic/media/video_processor/video_dev/amlvideo.h index e1ea5c93a391..ab5c1a25b809 100644 --- a/drivers/amlogic/media/video_processor/video_dev/amlvideo.h +++ b/drivers/amlogic/media/video_processor/video_dev/amlvideo.h @@ -75,10 +75,12 @@ struct vivi_dev { struct videobuf_res_privdata *res; struct vfq_s q_ready; + struct vfq_s q_omx; u8 first_frame; u64 last_pts_us64; struct vframe_s *vf; struct vframe_s *amlvideo_pool_ready[AMLVIDEO_POOL_SIZE + 1]; + struct vframe_s *amlvideo_pool_omx[AMLVIDEO_POOL_SIZE + 1]; int index; struct mutex vfpMutex; int amlvideo_v4l_num; diff --git a/drivers/amlogic/media/video_processor/video_dev/amlvideo2.c b/drivers/amlogic/media/video_processor/video_dev/amlvideo2.c index 8a582116cbd5..ccbde7be3392 100644 --- a/drivers/amlogic/media/video_processor/video_dev/amlvideo2.c +++ b/drivers/amlogic/media/video_processor/video_dev/amlvideo2.c @@ -77,7 +77,8 @@ /* #define USE_SEMA_QBUF */ /* #define USE_VDIN_PTS */ -/* #define MULTI_NODE */ +#define MULTI_NODE + #ifdef MULTI_NODE #define MAX_SUB_DEV_NODE 2 #else @@ -961,7 +962,8 @@ struct amlvideo2_node *node) } if ((node->crop_info.capture_crop_enable == 0) && - (node->porttype != TVIN_PORT_VIU1_VIDEO)) { + ((node->porttype != TVIN_PORT_VIU1_VIDEO) && + (node->porttype != TVIN_PORT_VIU1_WB0_VD1))) { output_axis_adjust( src_width, src_height, &dst_width, &dst_height, @@ -1323,7 +1325,8 @@ struct amlvideo2_node *node) if (src_width < src_height) cur_angle = (cur_angle + 90) % 360; if ((node->crop_info.capture_crop_enable == 0) && - (node->porttype != TVIN_PORT_VIU1_VIDEO)) { + ((node->porttype != TVIN_PORT_VIU1_VIDEO) && + (node->porttype != TVIN_PORT_VIU1_WB0_VD1))) { output_axis_adjust( src_width, src_height, &dst_width, &dst_height, @@ -1700,7 +1703,8 @@ struct amlvideo2_node *node) } if ((node->crop_info.capture_crop_enable == 0) && - (node->porttype != TVIN_PORT_VIU1_VIDEO)) { + ((node->porttype != TVIN_PORT_VIU1_VIDEO) && + (node->porttype != TVIN_PORT_VIU1_WB0_VD1))) { output_axis_adjust( src_width, src_height, &dst_width, &dst_height, @@ -2102,7 +2106,8 @@ struct amlvideo2_node *node) } if ((node->crop_info.capture_crop_enable == 0) && - (node->porttype != TVIN_PORT_VIU1_VIDEO)) { + ((node->porttype != TVIN_PORT_VIU1_VIDEO) && + (node->porttype != TVIN_PORT_VIU1_WB0_VD1))) { output_axis_adjust( src_width, src_height, &dst_width, &dst_height, @@ -2502,7 +2507,8 @@ struct amlvideo2_node *node) } if ((node->crop_info.capture_crop_enable == 0) && - (node->porttype != TVIN_PORT_VIU1_VIDEO)) { + ((node->porttype != TVIN_PORT_VIU1_VIDEO) && + (node->porttype != TVIN_PORT_VIU1_WB0_VD1))) { output_axis_adjust( src_width, src_height, &dst_width, &dst_height, @@ -3110,7 +3116,8 @@ int amlvideo2_ge2d_pre_process(struct vframe_s *vf, } if ((node->crop_info.capture_crop_enable == 0) && - (node->porttype != TVIN_PORT_VIU1_VIDEO)) { + ((node->porttype != TVIN_PORT_VIU1_VIDEO) && + (node->porttype != TVIN_PORT_VIU1_WB0_VD1))) { output_axis_adjust( src_width, src_height, &dst_width, &dst_height, @@ -3592,7 +3599,7 @@ static int amlvideo2_thread_tick(struct amlvideo2_fh *fh) if ((node->video_blocking) && (node->amlvideo2_pool_ready != NULL)) { vfq_init(&node->q_ready, - node->amlvideo2_pool_size + 1, + node->amlvideo2_pool_size, (struct vframe_s **)&(node->amlvideo2_pool_ready[0])); node->video_blocking = false; node->tmp_vf = NULL; @@ -4647,8 +4654,8 @@ static int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf) #ifdef PREVIOUS_VOUT_MODE static enum tvin_scan_mode_e vmode2scan_mode(enum vmode_e mode) { - enum tvin_scan_mode_e scan_mode = - TVIN_SCAN_MODE_NULL;/* 1: progressive 2:interlaced */ + enum tvin_scan_mode_e scan_mode = TVIN_SCAN_MODE_PROGRESSIVE; + //TVIN_SCAN_MODE_NULL;/* 1: progressive 2:interlaced */ switch (mode) { case VMODE_480I: @@ -4719,7 +4726,6 @@ static int amlvideo2_stop_tvin_service(struct amlvideo2_node *node) vops->stop_tvin_service(node->vdin_device_num); } - node->start_vdin_flag = 0; return ret; } @@ -4733,7 +4739,7 @@ static int amlvideo2_start_tvin_service(struct amlvideo2_node *node) vinfo = get_current_vinfo(); - if ((!node->start_vdin_flag) || (node->r_type != AML_RECEIVER_NONE)) + if (node->r_type != AML_RECEIVER_NONE) goto start; if (amlvideo2_dbg_en) @@ -4788,10 +4794,11 @@ static int amlvideo2_start_tvin_service(struct amlvideo2_node *node) para.dest_vactive = dst_h; if (para.scan_mode == TVIN_SCAN_MODE_INTERLACED) para.dest_vactive = para.dest_vactive / 2; - if (para.port == TVIN_PORT_VIU1_VIDEO) { - para.dest_hactive = 0; - para.dest_vactive = 0; - } + + if ((para.port == TVIN_PORT_VIU1_VIDEO) || + (para.port == TVIN_PORT_VIU1_WB0_VD1)) + para.cfmt = 1; + if (amlvideo2_dbg_en) { pr_info("node->r_type=%d, node->p_type=%d\n", node->r_type, node->p_type); @@ -4882,7 +4889,7 @@ int amlvideo2_notify_callback(struct notifier_block *block, unsigned long cmd, /* if local queue have vf , should give back to provider */ if (vfq_empty(&node->q_ready)) { - if (amlvideo2_dbg_en) + if (amlvideo2_dbg_en & 4) pr_info("q_ready is empty .\n"); } else { recycle_vf = vfq_pop(&node->q_ready); @@ -4890,12 +4897,12 @@ int amlvideo2_notify_callback(struct notifier_block *block, unsigned long cmd, vf_put(recycle_vf, node->recv.name); recycle_vf = vfq_pop(&node->q_ready); } - if (amlvideo2_dbg_en) + if (amlvideo2_dbg_en & 4) pr_info("already flush local vf .\n"); } /*debug provider vf state*/ - if (amlvideo2_dbg_en) { + if (amlvideo2_dbg_en & 4) { ret = vf_get_states(vfp, &states); if (ret == 0) { pr_info("vf_pool_size = %d, buf_free_num = %d .\n", @@ -4913,7 +4920,7 @@ int amlvideo2_notify_callback(struct notifier_block *block, unsigned long cmd, if (node->r_type == AML_RECEIVER_NONE) amlvideo2_start_thread(node->fh); - msleep(500); + ret = amlvideo2_start_tvin_service(node); if (ret < 0) { @@ -5054,16 +5061,16 @@ static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) } para.dest_hactive = dst_w; para.dest_vactive = dst_h; + para.reserved |= PARAM_STATE_SCREENCAP; if (para.scan_mode == TVIN_SCAN_MODE_INTERLACED) para.dest_vactive = para.dest_vactive / 2; - if (para.port == TVIN_PORT_VIU1_VIDEO) { + if ((para.port == TVIN_PORT_VIU1_VIDEO) || + (para.port == TVIN_PORT_VIU1_WB0_VD1)) { if (node->ge2d_multi_process_flag) { para.dest_hactive = 384; para.dest_vactive = 216; - } else { - para.dest_hactive = 0; - para.dest_vactive = 0; - } + } else + para.cfmt = 1; } if (amlvideo2_dbg_en) { pr_info("para.h_active: %d, para.v_active: %d,", @@ -5353,7 +5360,7 @@ int amlvideo2_cma_buf_init(struct amlvideo2_device *vid_dev, int node_id) return -1; } } else { - flags = CODEC_MM_FLAGS_DMA | + flags = CODEC_MM_FLAGS_DMA_CPU| CODEC_MM_FLAGS_CMA_CLEAR; if (node_id == 0) { if (vid_dev->node[node_id]-> @@ -5747,7 +5754,7 @@ static int amlvideo2_receiver_event_fun(int type, void *data, case VFRAME_EVENT_PROVIDER_REG: node->video_blocking = false; vfq_init(&node->q_ready, - node->amlvideo2_pool_size + 1, + node->amlvideo2_pool_size, (struct vframe_s **)&(node->amlvideo2_pool_ready[0])); break; case VFRAME_EVENT_PROVIDER_UNREG: @@ -5883,7 +5890,7 @@ static int amlvideo2_create_node(struct platform_device *pdev, int node_id) } if (vid_node->amlvideo2_pool_ready != NULL) { vfq_init(&vid_node->q_ready, - vid_node->amlvideo2_pool_size + 1, + vid_node->amlvideo2_pool_size, (struct vframe_s **)&(vid_node->amlvideo2_pool_ready[0])); } vid_node->context = create_ge2d_work_queue(); diff --git a/drivers/amlogic/media/video_processor/videosync/Kconfig b/drivers/amlogic/media/video_processor/videosync/Kconfig new file mode 100644 index 000000000000..cfaead140a94 --- /dev/null +++ b/drivers/amlogic/media/video_processor/videosync/Kconfig @@ -0,0 +1,11 @@ +menu "Amlogic videosync support" + +config AMLOGIC_VIDEOSYNC + tristate "amlogic videosync device support" + select VIDEO_DEV + default n + + ---help--- + Select to enable "Amlogic videosync support. + +endmenu diff --git a/drivers/amlogic/media/video_processor/videosync/Makefile b/drivers/amlogic/media/video_processor/videosync/Makefile new file mode 100644 index 000000000000..072e532f09a2 --- /dev/null +++ b/drivers/amlogic/media/video_processor/videosync/Makefile @@ -0,0 +1,3 @@ +asflags-y=-mfloat-abi=softfp -mfpu=neon + +obj-$(CONFIG_AMLOGIC_VIDEOSYNC) += videosync.o diff --git a/drivers/amlogic/media/video_processor/videosync/vfp.h b/drivers/amlogic/media/video_processor/videosync/vfp.h new file mode 100644 index 000000000000..4460d320d22e --- /dev/null +++ b/drivers/amlogic/media/video_processor/videosync/vfp.h @@ -0,0 +1,112 @@ +/* + * drivers/amlogic/media/video_processor/videosync/vfp.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 __VFP_H_ +#define __VFP_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 = 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/videosync/videosync.c b/drivers/amlogic/media/video_processor/videosync/videosync.c new file mode 100644 index 000000000000..23b6d0bb7a4c --- /dev/null +++ b/drivers/amlogic/media/video_processor/videosync/videosync.c @@ -0,0 +1,1251 @@ +/* + * drivers/amlogic/media/video_processor/videosync/videosync.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 "videosync.h" +#include +#include +#include +#include +#include + + +#define VIDEOSYNC_DEVICE_NAME "videosync" +#define RECEIVER_NAME "videosync" +#define PROVIDER_NAME "videosync" + +static bool videosync_inited;/*false*/ +static bool show_nosync;/*false*/ +static bool smooth_sync_enable; +static int enable_video_discontinue_report = 1; +static u32 system_time_scale_base = 1; +static s32 system_time_inc_adj;/*?*/ +static u32 vsync_pts_inc;/*?*/ +static u32 omx_version = 2; +static u32 vp_debug_flag; +static bool no_render;/* default: false */ +static bool async_mode;/* default: false */ +static u32 video_early_threshold = 900; /* default: 900=>10ms */ + + +/* video freerun mode */ +#define FREERUN_NONE 0 /* no freerun mode */ +#define FREERUN_NODUR 1 /* freerun without duration */ +#define FREERUN_DUR 2 /* freerun with duration */ +#define M_PTS_SMOOTH_MAX 45000 +#define M_PTS_SMOOTH_MIN 2250 +#define M_PTS_SMOOTH_ADJUST 900 +#define DURATION_GCD 750 + +static int omx_pts_interval_upper = 11000; +static int omx_pts_interval_lower = -5500; +#define DUR2PTS(x) ((x) - ((x) >> 4)) + +#define PRINT_ERROR 0X0 +#define PRINT_QUEUE_STATUS 0X0001 +#define PRINT_TIMESTAMP 0X0002 +#define PRINT_OTHER 0X0004 + +static struct videosync_dev *vp_dev; + +static int vp_print(char *name, int debug_flag, const char *fmt, ...) +{ + if ((vp_debug_flag & debug_flag) + || (debug_flag == PRINT_ERROR)) { + unsigned char buf[512]; + int len = 0; + va_list args; + + va_start(args, fmt); + len = sprintf(buf, "[%s]", name); + vsnprintf(buf + len, 512-len, fmt, args); + pr_info("%s", buf); + va_end(args); + } + return 0; +} + +static u32 ts_pcrscr_get(struct videosync_s *dev_s) +{ + u32 sys_time = 0; + /*unsigned long flags;*/ + sys_time = dev_s->system_time; + return sys_time; +} + +static void ts_pcrscr_set(struct videosync_s *dev_s, u32 pts) +{ + dev_s->system_time = pts; + vp_print(dev_s->vf_receiver_name, PRINT_TIMESTAMP, + "ts_pcrscr_set sys_time %d\n", dev_s->system_time); +} + +static void ts_pcrscr_enable(struct videosync_s *dev_s, u32 enable) +{ + dev_s->system_time_up = enable; +} +static u32 ts_pcrscr_enable_state(struct videosync_s *dev_s) +{ + return dev_s->system_time_up; +} + +void videosync_pcrscr_update(s32 inc, u32 base) +{ + int i = 0; + u32 r; + /*unsigned long flags;*/ + struct videosync_s *dev_s; + u32 current_omx_pts; + int diff; + + if (!videosync_inited) + return; + for (i = 0; i < VIDEOSYNC_S_COUNT; i++) { + dev_s = &vp_dev->video_prov[i]; + if (dev_s && dev_s->active_state == VIDEOSYNC_ACTIVE) { + if (system_time_scale_base != base) { + dev_s->system_time_scale_remainder = + dev_s->system_time_scale_remainder * + base / system_time_scale_base; + system_time_scale_base = base; + } + if (dev_s->system_time_up) { + dev_s->system_time += + div_u64_rem(90000ULL * inc, base, &r) + + system_time_inc_adj; + dev_s->system_time_scale_remainder += r; + if (dev_s->system_time_scale_remainder + >= system_time_scale_base) { + dev_s->system_time++; + dev_s->system_time_scale_remainder + -= system_time_scale_base; + } + vp_print(dev_s->vf_receiver_name, PRINT_OTHER, + "update sys_time %d, system_time_scale_base %d, inc %d\n", + dev_s->system_time, + system_time_scale_base, + inc); + } + + /*check if need to correct pcr by omx_pts*/ + current_omx_pts = dev_s->omx_pts; + diff = dev_s->system_time - current_omx_pts; + + if ((diff - omx_pts_interval_upper) > 0 + || (diff - omx_pts_interval_lower) < 0) { + vp_print(dev_s->vf_receiver_name, + PRINT_TIMESTAMP, + "sys_time=%d, omx_pts=%d, diff=%d\n", + dev_s->system_time, + current_omx_pts, + diff); + ts_pcrscr_set(dev_s, + current_omx_pts + DURATION_GCD); + } + } + } +} +EXPORT_SYMBOL(videosync_pcrscr_update); + +/* ----------------------------------------------------------------- + * videosync operations + * ----------------------------------------------------------------- + */ +static struct vframe_s *videosync_vf_peek(void *op_arg) +{ + struct vframe_s *vf = NULL; + struct videosync_s *dev_s = (struct videosync_s *)op_arg; + + vf = vfq_peek(&dev_s->ready_q); + return vf; +} + +static struct vframe_s *videosync_vf_get(void *op_arg) +{ + struct vframe_s *vf = NULL; + struct videosync_s *dev_s = (struct videosync_s *)op_arg; + + vf = vfq_pop(&dev_s->ready_q); + if (vf) { + dev_s->cur_dispbuf = vf; + dev_s->first_frame_toggled = 1; + } + return vf; +} + +static void videosync_vf_put(struct vframe_s *vf, void *op_arg) +{ + struct videosync_s *dev_s = (struct videosync_s *)op_arg; + + if (vf != NULL) { + vf_put(vf, dev_s->vf_receiver_name); + dev_s->put_frame_count++; + } else { + vp_print(dev_s->vf_receiver_name, 0, + "videosync_vf_put: NULL!\n"); + } +} + +static int videosync_event_cb(int type, void *data, void *private_data) +{ + return 0; +} + +static int videosync_buffer_states(struct videosync_buffer_states *states, + void *op_arg) +{ + struct videosync_s *dev_s = (struct videosync_s *)op_arg; + + states->buf_ready_num = vfq_level(&dev_s->ready_q); + states->buf_queued_num = vfq_level(&dev_s->queued_q); + states->total_num = dev_s->get_frame_count; + return 0; +} + +static int videosync_buffer_states_vf(struct vframe_states *states, + void *op_arg) +{ + struct videosync_s *dev_s = (struct videosync_s *)op_arg; + + states->vf_pool_size = VIDEOSYNC_S_POOL_SIZE; + states->buf_recycle_num = 0; + states->buf_free_num = VIDEOSYNC_S_POOL_SIZE + - vfq_level(&dev_s->ready_q) + - vfq_level(&dev_s->queued_q); + states->buf_avail_num = vfq_level(&dev_s->ready_q) + + vfq_level(&dev_s->queued_q); + + return 0; +} + +static const struct vframe_operations_s v4lvideo_vf_provider = { + .peek = videosync_vf_peek, + .get = videosync_vf_get, + .put = videosync_vf_put, + .event_cb = videosync_event_cb, + .vf_states = videosync_buffer_states_vf, +}; + +static void videosync_register(struct videosync_s *dev_s) +{ + vf_provider_init(&dev_s->video_vf_prov, + dev_s->vf_provider_name, + &v4lvideo_vf_provider, dev_s); + vf_reg_provider(&dev_s->video_vf_prov); + vf_notify_receiver(dev_s->vf_provider_name, + VFRAME_EVENT_PROVIDER_START, + NULL); +} + +static void videosync_unregister(struct videosync_s *dev_s) +{ + vf_unreg_provider(&dev_s->video_vf_prov); +} + +static ssize_t dump_queue_state_show(struct class *class, + struct class_attribute *attr, char *buf) +{ + int ret = 0; + int i = 0; + struct videosync_buffer_states states; + struct videosync_s *dev_s = NULL; + + if (vp_dev == NULL) + return -1; + + if (vp_dev->active_dev_s_num == 0) + ret += sprintf(buf, "no active videosync\n"); + else { + for (i = 0; i < VIDEOSYNC_S_COUNT; i++) { + dev_s = &vp_dev->video_prov[i]; + if (dev_s->active_state == VIDEOSYNC_INACTIVE) + continue; + + if (videosync_buffer_states(&states, dev_s) == 0) { + ret += sprintf(buf + ret, + "\n#------ %s state ------#\n", + dev_s->vf_receiver_name); + ret += sprintf(buf + ret, + "queued_q_size=%d\n", + states.buf_queued_num); + ret += sprintf(buf + ret, + "ready_q_size=%d\n", + states.buf_ready_num); + ret += sprintf(buf + ret, + "total frame count=%d\n", + states.total_num); + } + } + } + return ret; +} + +static ssize_t dump_pts_show(struct class *class, + struct class_attribute *attr, char *buf) +{ + int ret = 0; + int i = 0; + struct videosync_s *dev_s = NULL; + + if (vp_dev == NULL) + return -1; + + if (vp_dev->active_dev_s_num == 0) + ret += sprintf(buf, "no active videosync\n"); + else { + for (i = 0; i < VIDEOSYNC_S_COUNT; i++) { + dev_s = &vp_dev->video_prov[i]; + if (dev_s->active_state == VIDEOSYNC_INACTIVE) + continue; + + ret += sprintf(buf + ret, + "%s: ", dev_s->vf_receiver_name); + ret += sprintf(buf + ret, + "omx_pts=%d, ", dev_s->omx_pts); + ret += sprintf(buf + ret, + "system_time=%d\n", dev_s->system_time); + } + } + return ret; +} + +static ssize_t dump_get_put_framecount_show(struct class *class, + struct class_attribute *attr, char *buf) +{ + int ret = 0; + int i = 0; + struct videosync_s *dev_s = NULL; + + if (vp_dev == NULL) + return -1; + + if (vp_dev->active_dev_s_num == 0) + ret += sprintf(buf, "no active videosync\n"); + else { + for (i = 0; i < VIDEOSYNC_S_COUNT; i++) { + dev_s = &vp_dev->video_prov[i]; + if (dev_s->active_state == VIDEOSYNC_INACTIVE) + continue; + + ret += sprintf(buf + ret, + "%s: ", dev_s->vf_receiver_name); + ret += sprintf(buf + ret, + "get_frame_count=%d, put_frame_count=%d\n", + dev_s->get_frame_count, + dev_s->put_frame_count); + } + } + return ret; +} + +static ssize_t dump_rect_show(struct class *class, + struct class_attribute *attr, char *buf) +{ + int ret = 0; + int i = 0; + struct videosync_s *dev_s = NULL; + + if (vp_dev == NULL) + return -1; + + if (vp_dev->active_dev_s_num == 0) + ret += sprintf(buf, "no active videosync\n"); + else { + for (i = 0; i < VIDEOSYNC_S_COUNT; i++) { + dev_s = &vp_dev->video_prov[i]; + if (dev_s->active_state == VIDEOSYNC_INACTIVE) + continue; + + ret += sprintf(buf + ret, + "%s: ", dev_s->vf_receiver_name); + ret += sprintf(buf + ret, + "rect = [%d,%d,%d,%d], ", + dev_s->rect.left, + dev_s->rect.top, + dev_s->rect.width, + dev_s->rect.height); + ret += sprintf(buf + ret, + "zorder = %d\n", dev_s->zorder); + } + } + return ret; +} + +static struct class_attribute videosync_class_attrs[] = { + __ATTR_RO(dump_queue_state), + __ATTR_RO(dump_pts), + __ATTR_RO(dump_get_put_framecount), + __ATTR_RO(dump_rect), + __ATTR_NULL +}; +static struct class videosync_class = { + .name = "videosync", + .class_attrs = videosync_class_attrs, +}; + + +int videosync_assign_map(char **receiver_name, int *inst) +{ + int i = 0; + struct videosync_s *dev_s = NULL; + + mutex_lock(&vp_dev->vp_mutex); + for (i = 0; i < VIDEOSYNC_S_COUNT; i++) { + dev_s = &vp_dev->video_prov[i]; + if (dev_s->inst == *inst) { + *receiver_name = dev_s->vf_receiver_name; + pr_info("videosync_assign_map %s %p\n", + dev_s->vf_receiver_name, dev_s); + mutex_unlock(&vp_dev->vp_mutex); + return 0; + } + } + mutex_unlock(&vp_dev->vp_mutex); + return -ENODEV; +} + +int videosync_alloc_map(int *inst) +{ + int i = 0; + struct videosync_s *dev_s = NULL; + + mutex_lock(&vp_dev->vp_mutex); + for (i = 0; i < VIDEOSYNC_S_COUNT; i++) { + dev_s = &vp_dev->video_prov[i]; + if (dev_s->inst >= 0 && (!dev_s->mapped)) { + dev_s->mapped = true; + *inst = dev_s->inst; + pr_info("videosync_alloc_map %d OK\n", dev_s->inst); + mutex_unlock(&vp_dev->vp_mutex); + return 0; + } + } + mutex_unlock(&vp_dev->vp_mutex); + return -ENODEV; +} + +void videosync_release_map(int inst) +{ + + int i = 0; + struct videosync_s *dev_s = NULL; + + mutex_lock(&vp_dev->vp_mutex); + for (i = 0; i < VIDEOSYNC_S_COUNT; i++) { + dev_s = &vp_dev->video_prov[i]; + if (dev_s->inst == inst && (dev_s->mapped)) { + dev_s->mapped = false; + pr_info("videosync_release_map %d OK\n", inst); + break; + } + } + mutex_unlock(&vp_dev->vp_mutex); +} +void videosync_release_map_force(struct videosync_priv_s *priv) +{ + int i = 0; + struct videosync_s *dev_s = NULL; + + mutex_lock(&vp_dev->vp_mutex); + for (i = 0; i < VIDEOSYNC_S_COUNT; i++) { + dev_s = &vp_dev->video_prov[i]; + if (dev_s->inst == priv->vp_id && (dev_s->mapped)) { + dev_s->mapped = false; + pr_info("videosync_release_map_force %d OK\n", + priv->vp_id); + break; + } + } + mutex_unlock(&vp_dev->vp_mutex); +} + +static int videosync_open(struct inode *inode, struct file *file) +{ + struct videosync_priv_s *priv = NULL; + + pr_info("videosync_open\n"); + priv = kzalloc(sizeof(struct videosync_priv_s), GFP_KERNEL); + if (priv == NULL) { + pr_err("kzalloc videosync_priv_s failed!"); + } else { + priv->vp_id = -1; + priv->dev_s = NULL; + file->private_data = priv; + } + return 0; +} + +static int videosync_release(struct inode *inode, struct file *file) +{ + struct videosync_priv_s *priv = NULL; + + pr_info("videosync_release\n"); + if (file && file->private_data) { + priv = file->private_data; + + /*check if map released.*/ + videosync_release_map_force(priv); + + kfree(priv); + priv = NULL; + file->private_data = NULL; + } + + return 0; +} + +static int set_omx_pts(u32 *p) +{ + struct videosync_s *dev_s = NULL; + int ret = 0; + u32 tmp_pts = p[0]; + /*u32 vision = p[1];*/ + u32 set_from_hwc = p[2]; + u32 frame_num = p[3]; + u32 not_reset = p[4]; + u32 dev_id = p[6]; + + if (dev_id < VIDEOSYNC_S_COUNT) + dev_s = &vp_dev->video_prov[dev_id]; + + if (dev_s != NULL && dev_s->mapped) { + mutex_lock(&dev_s->omx_mutex); + vp_print(dev_s->vf_receiver_name, PRINT_TIMESTAMP, + "set omx_pts %d, hwc %d, not_reset %d, frame_num\n", + tmp_pts, set_from_hwc, not_reset, frame_num); + if (not_reset == 0) + dev_s->omx_pts = tmp_pts; + + mutex_unlock(&dev_s->omx_mutex); + + ts_pcrscr_enable(dev_s, 1); + } else { + ret = -EFAULT; + pr_err("[%s]cannot find dev_id %d device\n", + dev_s->vf_receiver_name, dev_id); + } + + return ret; + +} +static int set_omx_zorder(u32 *p) +{ + struct videosync_s *dev_s = NULL; + int ret = 0; + u32 dev_id = p[5]; + /*32 tmp_pts = p[6];*/ + + if (dev_id < VIDEOSYNC_S_COUNT) + dev_s = &vp_dev->video_prov[dev_id]; + + if (dev_s != NULL && dev_s->mapped) { + dev_s->zorder = p[0]; + dev_s->rect.left = p[1]; + dev_s->rect.top = p[2]; + dev_s->rect.width = p[3]; + dev_s->rect.height = p[4]; + + vp_print(dev_s->vf_receiver_name, PRINT_TIMESTAMP, + "set zorder %d: %d %d %d %d\n", + p[0], p[1], p[2], p[3], p[4]); + + } else { + ret = -EFAULT; + pr_err("[%s]cannot find dev_id %d device\n", + dev_s->vf_receiver_name, dev_id); + } + + return ret; + +} + +static long videosync_ioctl(struct file *file, + unsigned int cmd, + ulong arg) +{ + long ret = 0; + void __user *argp = (void __user *)arg; + struct videosync_priv_s *priv = NULL; + + switch (cmd) { + case VIDEOSYNC_IOC_ALLOC_ID:{ + u32 videosync_id = 0; + + ret = videosync_alloc_map(&videosync_id); + if (ret != 0) + break; + put_user(videosync_id, (u32 __user *)argp); + pr_info("alloc-id %d\n", videosync_id); + + if (file && file->private_data) { + priv = file->private_data; + priv->vp_id = videosync_id; + priv->dev_s = &vp_dev->video_prov[videosync_id]; + pr_info("get dev_s %p\n", priv->dev_s); + } + } + break; + case VIDEOSYNC_IOC_FREE_ID:{ + u32 videosync_id; + + get_user(videosync_id, (u32 __user *)argp); + pr_info("free-id %d\n", videosync_id); + videosync_release_map(videosync_id); + } + break; + + case VIDEOSYNC_IOC_SET_FREERUN_MODE: + if (arg > FREERUN_DUR) + ret = -EFAULT; + else { + if (file && file->private_data) { + priv = file->private_data; + if (priv && priv->dev_s) + priv->dev_s->freerun_mode = arg; + else + ret = -EFAULT; + } else { + ret = -EFAULT; + } + } + break; + + case VIDEOSYNC_IOC_GET_FREERUN_MODE: + if (file && file->private_data) { + priv = file->private_data; + if (priv && priv->dev_s) + put_user(priv->dev_s->freerun_mode, + (u32 __user *)argp); + else + ret = -EFAULT; + + } else + ret = -EFAULT; + + break; + case VIDEOSYNC_IOC_SET_OMX_VPTS:{ + u32 pts[7]; + + if (copy_from_user(pts, argp, sizeof(pts)) == 0) + ret = set_omx_pts(pts); + + } + break; + case VIDEOSYNC_IOC_SET_OMX_ZORDER:{ + u32 zorder[7]; + + if (copy_from_user(zorder, argp, sizeof(zorder)) == 0) + ret = set_omx_zorder(zorder); + + } + break; + case VIDEOSYNC_IOC_GET_OMX_VPTS: + if (file && file->private_data) { + priv = file->private_data; + if (priv && priv->dev_s) + put_user(priv->dev_s->omx_pts, + (u32 __user *)argp); + else + ret = -EFAULT; + } else { + ret = -EFAULT; + } + break; + case VIDEOSYNC_IOC_GET_OMX_VERSION: + put_user(omx_version, (u32 __user *)argp); + pr_info("get omx_version %d\n", omx_version); + break; + default: + pr_info("ioctl invalid cmd 0x%x\n", cmd); + return -EINVAL; + } + return ret; +} + +#ifdef CONFIG_COMPAT +static long videosync_compat_ioctl(struct file *file, + unsigned int cmd, + ulong arg) +{ + long ret = 0; + + ret = videosync_ioctl(file, cmd, (ulong)compat_ptr(arg)); + return ret; +} +#endif + +static void clear_queued_queue(struct videosync_s *dev_s) +{ + struct vframe_s *vf = NULL; + + vp_print(dev_s->vf_receiver_name, PRINT_QUEUE_STATUS, + "clear_queued_queue: size %d!\n", vfq_level(&dev_s->queued_q)); + + vf = vfq_pop(&dev_s->queued_q); + while (vf) { + vf_put(vf, dev_s->vf_receiver_name); + vf = vfq_pop(&dev_s->queued_q); + } + +} + +static void clear_ready_queue(struct videosync_s *dev_s) +{ + struct vframe_s *vf = NULL; + + vp_print(dev_s->vf_receiver_name, PRINT_QUEUE_STATUS, + "clear_ready_queue: size %d!\n", + vfq_level(&dev_s->ready_q)); + vf = vfq_pop(&dev_s->ready_q); + while (vf) { + vf_put(vf, dev_s->vf_receiver_name); + vf = vfq_pop(&dev_s->ready_q); + } +} + +static inline bool omx_vpts_expire(struct vframe_s *cur_vf, + struct vframe_s *next_vf, + struct videosync_s *dev_s) + +{ + u32 pts = next_vf->pts; +#ifdef VIDEO_PTS_CHASE + u32 vid_pts, scr_pts; +#endif + u32 systime; + u32 adjust_pts, org_vpts; + /*u32 dur_pts = 0;*/ + + if (dev_s->freerun_mode == FREERUN_NODUR) + return true; + + if (next_vf->duration == 0) + return true; + + systime = ts_pcrscr_get(dev_s); + + if (no_render) + dev_s->first_frame_toggled = 1; /*just for debug, not render*/ + + vp_print(dev_s->vf_receiver_name, PRINT_TIMESTAMP, + "sys_time=%d, vf->pts=%d, diff=%d\n", + systime, pts, (int)(systime - pts)); + + if (0) { + pts = + timestamp_vpts_get() + + (cur_vf ? DUR2PTS(cur_vf->duration) : 0); + } + /* check video PTS discontinuity */ + else if (ts_pcrscr_enable_state(dev_s) > 0 && + (enable_video_discontinue_report) && + (dev_s->first_frame_toggled) && + (abs(systime - pts) > tsync_vpts_discontinuity_margin()) && + ((next_vf->flag & VFRAME_FLAG_NO_DISCONTINUE) == 0 + || tsync_vpts_discontinuity_margin() <= 90000)) { + + vp_print(dev_s->vf_receiver_name, PRINT_TIMESTAMP, + "discontinue, systime = %d, next_vf->pts = %d\n", + systime, next_vf->pts); + return true; + } + + if (0/*smooth_sync_enable*/) { + org_vpts = timestamp_vpts_get(); + if ((abs(org_vpts + vsync_pts_inc - systime) < + M_PTS_SMOOTH_MAX) + && (abs(org_vpts + vsync_pts_inc - systime) > + M_PTS_SMOOTH_MIN)) { + + if (!dev_s->video_frame_repeat_count) { + dev_s->vpts_ref = org_vpts; + dev_s->video_frame_repeat_count++; + } + + if ((int)(org_vpts + vsync_pts_inc - systime) > 0) { + adjust_pts = + dev_s->vpts_ref + (vsync_pts_inc - + M_PTS_SMOOTH_ADJUST) * + dev_s->video_frame_repeat_count; + } else { + adjust_pts = + dev_s->vpts_ref + (vsync_pts_inc + + M_PTS_SMOOTH_ADJUST) * + dev_s->video_frame_repeat_count; + } + + return (int)(adjust_pts - pts) >= 0; + } + + if (dev_s->video_frame_repeat_count) { + dev_s->vpts_ref = 0; + dev_s->video_frame_repeat_count = 0; + } + } + + return (systime + video_early_threshold) > pts; + +} + +void videosync_sync(struct videosync_s *dev_s) +{ + int ready_q_size = 0; + struct vframe_s *vf; + + if (smooth_sync_enable) { + if (dev_s->video_frame_repeat_count) + dev_s->video_frame_repeat_count++; + } + + vf = vfq_peek(&dev_s->queued_q); + + while (vf) { + if (omx_vpts_expire(dev_s->cur_dispbuf, vf, dev_s) + || show_nosync) { + + vf = vfq_pop(&dev_s->queued_q); + if (vf) { + if (async_mode) { + if (vfq_level(&dev_s->ready_q) > 0) + clear_ready_queue(dev_s); + } + + vfq_push(&dev_s->ready_q, vf); + ready_q_size = vfq_level(&dev_s->ready_q); + vp_print(dev_s->vf_receiver_name, + PRINT_QUEUE_STATUS, + "add pts %d index 0x%x to ready_q, size %d\n", + vf->pts, vf->index, ready_q_size); + + vf_notify_receiver( + dev_s->vf_provider_name, + VFRAME_EVENT_PROVIDER_VFRAME_READY, + NULL); + if (ready_q_size > VIDEOSYNC_S_POOL_SIZE - 1) { + vp_print(dev_s->vf_receiver_name, + PRINT_QUEUE_STATUS, + "ready_q full!\n"); + break; + } + } + + vf = vfq_peek(&dev_s->queued_q); + if (!vf) + break; + } else { + break; + } + } + +} + + +static void prepare_queued_queue(struct videosync_dev *dev) +{ + int i = 0; + struct videosync_s *dev_s; + struct vframe_s *vf; + + for (i = 0; i < VIDEOSYNC_S_COUNT; i++) { + dev_s = &dev->video_prov[i]; + if (dev_s->active_state == VIDEOSYNC_INACTIVE) + continue; + + if (vfq_full(&dev_s->queued_q)) { + pr_info("[%s]queued_q full!\n", + dev_s->vf_receiver_name); + continue; + } + + if (vf_peek(dev_s->vf_receiver_name)) { + vf = vf_get(dev_s->vf_receiver_name); + if (vf) { + vfq_push(&dev_s->queued_q, vf); + dev_s->get_frame_count++; + vp_print(dev_s->vf_receiver_name, + PRINT_QUEUE_STATUS, + "add pts %d index 0x%x to queued_q, size %d\n", + vf->pts, + vf->index, + vfq_level(&dev_s->queued_q)); + } + } else { + vp_print(dev_s->vf_receiver_name, PRINT_OTHER, + "peek failed %d\n"); + } + } + +} +static void prepare_ready_queue(struct videosync_dev *dev) +{ + int i = 0; + struct videosync_s *dev_s; + + for (i = 0; i < VIDEOSYNC_S_COUNT; i++) { + dev_s = &dev->video_prov[i]; + if (dev_s->active_state == VIDEOSYNC_INACTIVE) + continue; + + if (vfq_full(&dev_s->ready_q)) { + pr_info("[%s]ready_q full!\n", dev_s->vf_receiver_name); + continue; + } + + videosync_sync(dev_s); + + if (no_render) + clear_ready_queue(dev_s);/*just for debug, not render*/ + + } + +} + +static void reinit_dev_s(struct videosync_s *dev_s) +{ + dev_s->get_frame_count = 0; + dev_s->put_frame_count = 0; + dev_s->system_time_up = 0; + dev_s->system_time = 0; + dev_s->first_frame_toggled = 0; + dev_s->freerun_mode = 0; + dev_s->system_time_scale_remainder = 0; + dev_s->omx_pts = 0; + dev_s->vpts_ref = 0; + dev_s->video_frame_repeat_count = 0; + dev_s->rect.top = 0; + dev_s->rect.left = 0; + dev_s->rect.width = 0; + dev_s->rect.height = 0; + dev_s->zorder = 0; +} +static int videosync_receiver_event_fun(int type, void *data, + void *private_data) +{ + struct videosync_s *dev_s = (struct videosync_s *)private_data; + unsigned long flags = 0; + struct videosync_dev *dev; + unsigned long time_left; + + if (type == VFRAME_EVENT_PROVIDER_UNREG) { + pr_info("videosync: try to unreg %p, %s\n", + dev_s, dev_s->vf_receiver_name); + dev = (struct videosync_dev *)dev_s->dev; + + spin_lock_irqsave(&dev->dev_s_num_slock, flags); + --dev->active_dev_s_num; + spin_unlock_irqrestore(&dev->dev_s_num_slock, flags); + + videosync_unregister(dev_s); + dev_s->receiver_register = false; + + if (dev_s->active_state == VIDEOSYNC_ACTIVE) { + dev_s->active_state = VIDEOSYNC_INACTIVE_REQ; + time_left = wait_for_completion_timeout( + &dev_s->inactive_done, + msecs_to_jiffies(100)); + if (time_left == 0) + vp_print(RECEIVER_NAME, PRINT_OTHER, + "videosync: unreg timeout\n"); + } + clear_ready_queue(dev_s); + clear_queued_queue(dev_s); + + /*tsync_avevent(VIDEO_STOP, 0);*/ + pr_info("videosync: unreg %p, %s\n", + dev_s, dev_s->vf_receiver_name); + } else if (type == VFRAME_EVENT_PROVIDER_REG) { + //omx_secret_mode = false; + struct videosync_dev *dev = (struct videosync_dev *)dev_s->dev; + + reinit_dev_s(dev_s); + //videosync_register(dev_s); + dev_s->receiver_register = true; + dev_s->active_state = VIDEOSYNC_ACTIVE; + + spin_lock_irqsave(&dev->dev_s_num_slock, flags); + ++dev->active_dev_s_num; + spin_unlock_irqrestore(&dev->dev_s_num_slock, flags); + + vfq_init(&dev_s->queued_q, VIDEOSYNC_S_POOL_SIZE + 1, + &dev_s->videosync_pool_queued[0]); + vfq_init(&dev_s->ready_q, VIDEOSYNC_S_POOL_SIZE + 1, + &dev_s->videosync_pool_ready[0]); + + init_completion(&dev_s->inactive_done); + complete(&dev->thread_active); + pr_info("videosync: reg %p, %s\n", + dev_s, dev_s->vf_receiver_name); + } else if (type == VFRAME_EVENT_PROVIDER_VFRAME_READY) { + + } else if (type == VFRAME_EVENT_PROVIDER_START) { + videosync_register(dev_s); + pr_info("videosync: start %p, %s\n", + dev_s, dev_s->vf_receiver_name); + } else if (type == VFRAME_EVENT_PROVIDER_QUREY_STATE) { + struct videosync_buffer_states states; + + videosync_buffer_states(&states, dev_s); + if (states.buf_queued_num + states.buf_ready_num > 0) + return RECEIVER_ACTIVE; + + vp_print(dev_s->vf_receiver_name, 0, + "buf queue empty!!\n"); + return RECEIVER_ACTIVE;/*return RECEIVER_INACTIVE;*/ + } + return 0; +} + +static const struct file_operations videosync_fops = { + + .owner = THIS_MODULE, + .open = videosync_open, + .release = videosync_release, + .unlocked_ioctl = videosync_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = videosync_compat_ioctl, +#endif + .poll = NULL, +}; + +static const struct vframe_receiver_op_s videosync_vf_receiver = { + .event_cb = videosync_receiver_event_fun, +}; + +static const struct videosync_operations_s videosync_vf_provider = { + .peek = videosync_vf_peek, + .get = videosync_vf_get, + .put = videosync_vf_put, + .event_cb = videosync_event_cb, + .buffer_states = videosync_buffer_states, +}; + +static int __init videosync_create_instance(int inst) +{ + struct videosync_s *dev_s; + + dev_s = &vp_dev->video_prov[inst]; + dev_s->dev = vp_dev; + dev_s->fd_num = 0; + dev_s->ops = &videosync_vf_provider; + dev_s->active_state = VIDEOSYNC_INACTIVE; + pr_info("videosync_create_instance dev_s %p,dev_s->dev %p\n", + dev_s, dev_s->dev); + + /* initialize locks */ + mutex_init(&dev_s->omx_mutex); + spin_lock_init(&dev_s->timestamp_lock); + + dev_s->inst = inst; + dev_s->index = inst; + dev_s->mapped = true; + snprintf(dev_s->vf_receiver_name, VIDEOSYNC_S_VF_RECEIVER_NAME_SIZE, + RECEIVER_NAME ".%x", inst & 0xff); + snprintf(dev_s->vf_provider_name, VIDEOSYNC_S_VF_RECEIVER_NAME_SIZE, + PROVIDER_NAME ".%x", inst & 0xff); + + pr_info("videosync_create_instance reg %s\n", + dev_s->vf_receiver_name); + + vf_receiver_init(&dev_s->vp_vf_receiver, + dev_s->vf_receiver_name, + &videosync_vf_receiver, dev_s); + + vf_reg_receiver(&dev_s->vp_vf_receiver); + + return 0; + +} + +static void __init videosync_destroy_instance(int inst) +{ + pr_info("videosync_destroy_instance %s\n", + vp_dev->video_prov[inst].vf_receiver_name); + vf_unreg_receiver(&vp_dev->video_prov[inst].vp_vf_receiver); +} + + +static void videosync_thread_tick(struct videosync_dev *dev) +{ + int i = 0; + struct videosync_s *dev_s; + unsigned long flags = 0; + unsigned long time_left; + + if (!dev) + return; + + for (i = 0; i < VIDEOSYNC_S_COUNT; i++) { + dev_s = &dev->video_prov[i]; + if (dev_s->active_state == VIDEOSYNC_INACTIVE_REQ) { + dev_s->active_state = VIDEOSYNC_INACTIVE; + complete(&dev_s->inactive_done); + } + } + + vp_print(RECEIVER_NAME, PRINT_OTHER, + "active num %d\n", dev->active_dev_s_num); + + spin_lock_irqsave(&dev->dev_s_num_slock, flags); + if (dev->active_dev_s_num > 0) { + spin_unlock_irqrestore(&dev->dev_s_num_slock, flags); + prepare_queued_queue(dev); + prepare_ready_queue(dev); + usleep_range(7000, 8000); + } else { + spin_unlock_irqrestore(&dev->dev_s_num_slock, flags); + vp_print(RECEIVER_NAME, PRINT_OTHER, + "videosync: no active dev, thread go to sleep\n"); + time_left = wait_for_completion_timeout(&dev->thread_active, + msecs_to_jiffies(500)); + if (time_left == 0) + vp_print(RECEIVER_NAME, PRINT_OTHER, + "videosync: thread_tick timeout\n"); + } +} + +static void videosync_sleep(struct videosync_dev *dev) +{ + videosync_thread_tick(dev); + try_to_freeze(); +} + +static int videosync_thread(void *data) +{ + struct videosync_dev *dev = (struct videosync_dev *)data; + + pr_info("videosync_thread started\n"); + + set_freezable(); + + while (!kthread_should_stop()) + videosync_sleep(dev); + + pr_info("videosync_thread exit\n"); + return 0; +} + + +static int __init videosync_init(void) +{ + int ret = -1, i; + struct device *devp; + + ret = class_register(&videosync_class); + if (ret < 0) + return ret; + ret = register_chrdev(VIDEOSYNC_MAJOR, "videosync", &videosync_fops); + if (ret < 0) { + pr_err("Can't allocate major for videosync device\n"); + goto error1; + } + + devp = device_create(&videosync_class, + NULL, + MKDEV(VIDEOSYNC_MAJOR, 0), + NULL, + VIDEOSYNC_DEVICE_NAME); + if (IS_ERR(devp)) { + pr_err("failed to create videosync device node\n"); + ret = PTR_ERR(devp); + return ret; + } + + vp_dev = kzalloc(sizeof(*vp_dev), GFP_KERNEL); + if (!vp_dev) + return -ENOMEM; + + vp_dev->video_prov = kzalloc( + VIDEOSYNC_S_COUNT * sizeof(struct videosync_s), + GFP_KERNEL); + if (!vp_dev->video_prov) + return -ENOMEM; + + mutex_init(&vp_dev->vp_mutex); + spin_lock_init(&vp_dev->dev_s_num_slock); + + for (i = 0; i < VIDEOSYNC_S_COUNT; i++) { + ret = videosync_create_instance(i); + if (ret) { + pr_err("videosync: error %d while create instance\n", + ret); + goto error1; + } + } + + init_completion(&vp_dev->thread_active); + vp_dev->kthread = kthread_run(videosync_thread, vp_dev, "videosync"); + videosync_inited = true; + return ret; + +error1: + kfree(vp_dev); + vp_dev = NULL; + unregister_chrdev(VIDEOSYNC_MAJOR, "videosync"); + class_unregister(&videosync_class); + return ret; +} + +static void __exit videosync_exit(void) +{ + int i, ret; + + complete(&vp_dev->thread_active); + + if (vp_dev->kthread) { + ret = kthread_stop(vp_dev->kthread); + if (ret < 0) + pr_info("%s, kthread_stop return %d.\n", __func__, ret); + vp_dev->kthread = NULL; + } + videosync_inited = false; + + for (i = 0; i < VIDEOSYNC_S_COUNT; i++) + videosync_destroy_instance(i); + + kfree(vp_dev->video_prov); + vp_dev->video_prov = NULL; + + kfree(vp_dev); + vp_dev = NULL; + + device_destroy(&videosync_class, MKDEV(VIDEOSYNC_MAJOR, 0)); + unregister_chrdev(VIDEOSYNC_MAJOR, VIDEOSYNC_DEVICE_NAME); + class_unregister(&videosync_class); +} + +module_init(videosync_init); +module_exit(videosync_exit); + +MODULE_PARM_DESC(smooth_sync_enable, "\n smooth_sync_enable\n"); +module_param(smooth_sync_enable, bool, 0664); + +MODULE_PARM_DESC(vp_debug_flag, "\n vp_debug_flag\n"); +module_param(vp_debug_flag, uint, 0664); + +MODULE_PARM_DESC(show_nosync, "\n show_nosync\n"); +module_param(show_nosync, bool, 0664); + +MODULE_PARM_DESC(no_render, "\n no_render\n"); +module_param(no_render, bool, 0664); + +MODULE_PARM_DESC(async_mode, "\n async_mode\n"); +module_param(async_mode, bool, 0664); + +MODULE_PARM_DESC(video_early_threshold, "\n video_early_threshold\n"); +module_param(video_early_threshold, uint, 0664); + diff --git a/drivers/amlogic/media/video_processor/videosync/videosync.h b/drivers/amlogic/media/video_processor/videosync/videosync.h new file mode 100644 index 000000000000..98bad9f651ae --- /dev/null +++ b/drivers/amlogic/media/video_processor/videosync/videosync.h @@ -0,0 +1,141 @@ +/* + * drivers/amlogic/media/video_processor/videosync/videosync.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 _VIDEOSYNC_H +#define _VIDEOSYNC_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "vfp.h" +#include + +#define VIDEOSYNC_S_COUNT 1 + +#define VIDEOSYNC_ACTIVE 0 +#define VIDEOSYNC_INACTIVE_REQ 1 +#define VIDEOSYNC_INACTIVE 2 + +struct videosync_priv_s { + int vp_id; /* reserved */ + struct videosync_s *dev_s; +}; + +struct videosync_dev { + struct videosync_s *video_prov; + struct task_struct *kthread; + struct completion thread_active; + struct mutex vp_mutex; + spinlock_t dev_s_num_slock; + u32 active_dev_s_num; +}; +extern bool omx_secret_mode; + +#define VIDEOSYNC_IOC_MAGIC 'P' +#define VIDEOSYNC_IOC_ALLOC_ID _IOR(VIDEOSYNC_IOC_MAGIC, 0x00, int) +#define VIDEOSYNC_IOC_FREE_ID _IOW(VIDEOSYNC_IOC_MAGIC, 0x01, int) +#define VIDEOSYNC_IOC_SET_FREERUN_MODE _IOW(VIDEOSYNC_IOC_MAGIC, 0x02, int) +#define VIDEOSYNC_IOC_GET_FREERUN_MODE _IOR(VIDEOSYNC_IOC_MAGIC, 0x03, int) +#define VIDEOSYNC_IOC_SET_OMX_VPTS _IOW(VIDEOSYNC_IOC_MAGIC, 0x04, unsigned int) +#define VIDEOSYNC_IOC_GET_OMX_VPTS _IOR(VIDEOSYNC_IOC_MAGIC, 0x05, unsigned int) +#define VIDEOSYNC_IOC_GET_OMX_VERSION \ + _IOR(VIDEOSYNC_IOC_MAGIC, 0x06, unsigned int) +#define VIDEOSYNC_IOC_SET_OMX_ZORDER \ + _IOW(VIDEOSYNC_IOC_MAGIC, 0x07, unsigned int) + +#define VIDEOSYNC_S_VF_RECEIVER_NAME_SIZE 32 +#define VIDEOSYNC_S_POOL_SIZE 16 +#define VIDEOSYNC_VF_NAME_SIZE 32 + +extern int videosync_assign_map(char **receiver_name, int *inst); + +struct videosync_buffer_states { + int buf_ready_num; + int buf_queued_num; + int total_num; +}; + +struct videosync_operations_s { + struct vframe_s *(*peek)(void *op_arg); + struct vframe_s *(*get)(void *op_arg); + void (*put)(struct vframe_s *, void *op_arg); + int (*event_cb)(int type, void *data, void *private_data); + int (*buffer_states)(struct videosync_buffer_states *states, + void *op_arg); +}; + +struct display_area { + u32 left; + u32 top; + u32 width; + u32 height; +}; +struct videosync_s { + void *dev; + int index; + int fd_num; + char vf_receiver_name[VIDEOSYNC_S_VF_RECEIVER_NAME_SIZE]; + int inst; + bool mapped; + bool receiver_register; + struct vframe_receiver_s vp_vf_receiver; + struct vfq_s queued_q; + struct vfq_s ready_q; + struct vframe_s *videosync_pool_queued[VIDEOSYNC_S_POOL_SIZE + 1]; + struct vframe_s *videosync_pool_ready[VIDEOSYNC_S_POOL_SIZE + 1]; + int active_state; + const struct videosync_operations_s *ops; + struct completion inactive_done; + struct vframe_s *cur_dispbuf; + spinlock_t timestamp_lock; + struct mutex omx_mutex; + u32 system_time_up; + u32 system_time; + u32 system_time_scale_remainder; + u32 omx_pts; + u32 vpts_ref; + u32 video_frame_repeat_count; + u32 freerun_mode; + u32 first_frame_toggled; + u32 get_frame_count; + u32 put_frame_count; + void *op_arg; + char *name; + struct display_area rect; + u32 zorder; + struct vframe_provider_s video_vf_prov; + char vf_provider_name[VIDEOSYNC_VF_NAME_SIZE]; +}; + + +#endif + diff --git a/drivers/amlogic/media/video_sink/Makefile b/drivers/amlogic/media/video_sink/Makefile index 7f5a423ba683..5e3d8c8cef7b 100644 --- a/drivers/amlogic/media/video_sink/Makefile +++ b/drivers/amlogic/media/video_sink/Makefile @@ -1,2 +1,6 @@ obj-y += amvideo.o amvideo-objs += video.o video_keeper.o vpp.o + +ifeq ($(CONFIG_AMLOGIC_MEDIA_VIDEOCAPTURE),y) +amvideo-objs += amvideocap.o +endif diff --git a/drivers/amlogic/media/video_sink/amvideocap.c b/drivers/amlogic/media/video_sink/amvideocap.c new file mode 100644 index 000000000000..172cd9cb8191 --- /dev/null +++ b/drivers/amlogic/media/video_sink/amvideocap.c @@ -0,0 +1,1225 @@ +/* + * drivers/amlogic/media/video_sink/amvideocap.c + * + * Copyright (C) 2015 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include "../../media_modules/stream_input/amports/amports_priv.h" +#include "amvideocap_priv.h" +/* +#if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 +#include +#endif +*/ + +#ifdef CONFIG_PM +#include +#endif + +#define DRIVER_NAME "amvideocap" +#define MODULE_NAME "amvideocap" +#define DEVICE_NAME "amvideocap" + +#define CAP_WIDTH_MAX 3840 +#define CAP_HEIGHT_MAX 2160 + +MODULE_DESCRIPTION("Video Frame capture"); +MODULE_AUTHOR("amlogic-bj"); +MODULE_LICENSE("GPL"); + +#define AMCAP_MAX_OPEND 16 +struct amvideocap_global_data { + struct class *class; + struct device *dev; + struct device *micro_dev; + int major; + unsigned long phyaddr; + unsigned long vaddr; + unsigned long size; + int opened_cnt; + int flags; + struct mutex lock; + struct video_frame_info want; + u64 wait_max_ms; +}; +static struct amvideocap_global_data amvideocap_gdata; +static struct ge2d_context_s *ge2d_amvideocap_context; +static inline struct amvideocap_global_data *getgctrl(void) +{ + return &amvideocap_gdata; +} + +static int use_cma; +#ifdef CONFIG_CMA +static struct platform_device *amvideocap_pdev; +static int cma_max_size; +#define CMA_NAME "amvideocap" +#endif +#define gLOCK() mutex_lock(&(getgctrl()->lock)) +#define gUNLOCK() mutex_unlock(&(getgctrl()->lock)) +#define gLOCKINIT() mutex_init(&(getgctrl()->lock)) + +/********************************************************* + * /dev/amvideo APIs + *********************************************************/ +static int amvideocap_open(struct inode *inode, struct file *file) +{ + struct amvideocap_private *priv; + gLOCK(); +#ifdef CONFIG_CMA + if (use_cma && amvideocap_pdev) { + unsigned long phybufaddr; + phybufaddr = codec_mm_alloc_for_dma(CMA_NAME, + cma_max_size * SZ_1M / PAGE_SIZE, + 4 + PAGE_SHIFT, CODEC_MM_FLAGS_CPU); + /* pr_err("%s: codec_mm_alloc_for_dma:%p\n", + __func__, (void *)phybufaddr); + */ + amvideocap_register_memory((unsigned char *)phybufaddr, + cma_max_size * SZ_1M); + } +#endif + if (!getgctrl()->phyaddr) { + gUNLOCK(); + pr_err("Error,no memory have register for amvideocap\n"); + return -ENOMEM; + } +#ifdef CONFIG_CMA + if (!getgctrl()->vaddr) { + getgctrl()->vaddr = (unsigned long)codec_mm_phys_to_virt( + getgctrl()->phyaddr); + if (!getgctrl()->vaddr) { + pr_err("%s: failed to remap y addr\n", __func__); + gUNLOCK(); + return -ENOMEM; + } + } +#endif + if (getgctrl()->opened_cnt > AMCAP_MAX_OPEND) { + gUNLOCK(); + pr_err("Too Many opend video cap files\n"); + return -EMFILE; + } + priv = kmalloc(sizeof(struct amvideocap_private), GFP_KERNEL); + if (!priv) { + gUNLOCK(); + pr_err("alloc memory failed for amvideo cap\n"); + return -ENOMEM; + } + memset(priv, 0, sizeof(struct amvideocap_private)); + getgctrl()->opened_cnt++; + gUNLOCK(); + file->private_data = priv; + priv->phyaddr = getgctrl()->phyaddr; + priv->vaddr = (u8 *) getgctrl()->vaddr; + priv->want = getgctrl()->want; + priv->src_rect.x = -1; + priv->src_rect.y = -1; + priv->src_rect.width = -1; + priv->src_rect.height = -1; + return 0; +} + +static int amvideocap_release(struct inode *inode, struct file *file) +{ + struct amvideocap_private *priv = file->private_data; + kfree(priv); +#ifdef CONFIG_CMA + if (use_cma && amvideocap_pdev) { + codec_mm_free_for_dma(CMA_NAME, getgctrl()->phyaddr); + /* + pr_err("%s: codec_mm_free_for_dma:%p\n", __func__, + (void *)getgctrl()->phyaddr); + */ + } +#endif + gLOCK(); + getgctrl()->opened_cnt--; + + gUNLOCK(); + return 0; +} + +static int amvideocap_format_to_byte4pix(int fmt) +{ + switch (fmt) { + case GE2D_FORMAT_S16_RGB_565: + return 2; + case GE2D_FORMAT_S24_BGR: + return 3; + case GE2D_FORMAT_S24_RGB: + return 3; + case GE2D_FORMAT_S32_ABGR: + return 4; + case GE2D_FORMAT_S32_RGBA: + return 4; + case GE2D_FORMAT_S32_BGRA: + return 4; + case GE2D_FORMAT_S32_ARGB: + return 4; + default: + return 4; + } +}; + +static int amvideocap_capture_get_frame +(struct amvideocap_private *priv, struct vframe_s **vf, int *cur_index) +{ + int ret; + ret = ext_get_cur_video_frame(vf, cur_index); + return ret; +} + +static int amvideocap_capture_put_frame +(struct amvideocap_private *priv, struct vframe_s *vf) +{ + return ext_put_video_frame(vf); +} + +static int amvideocap_get_input_format(struct vframe_s *vf) +{ + int format = GE2D_FORMAT_M24_NV21; + /* pr_debug("vf->type:0x%x\n", vf->type); */ + + if ((vf->type & VIDTYPE_VIU_422) == VIDTYPE_VIU_422) { + pr_debug + ("*****************Into VIDTYPE_VIU_422******************\n"); + format = GE2D_FORMAT_S16_YUV422; + } else if ((vf->type & VIDTYPE_VIU_444) == VIDTYPE_VIU_444) { + pr_debug + ("*****************Into VIDTYPE_VIU_444******************\n"); + format = GE2D_FORMAT_S24_YUV444; + } else if ((vf->type & VIDTYPE_VIU_NV21) == VIDTYPE_VIU_NV21) { + pr_debug + ("****************Into VIDTYPE_VIU_NV21******************\n"); + format = GE2D_FORMAT_M24_NV21; + } + return format; +} + +static ssize_t amvideocap_YUV_to_RGB( + struct amvideocap_private *priv, + u32 cur_index, int w, int h, + struct vframe_s *vf, int outfmt) +{ + struct config_para_ex_s ge2d_config; + struct canvas_s cs0, cs1, cs2, cd; + + void __iomem *psrc; + void __iomem *pdst; + int temp_cma_buf_size = 0; + unsigned long phybufaddr_8bit = 0; + struct timeval start, end; + unsigned long time_use; + int ret = 0; + struct canvas_s temp_cs0, temp_cs1, temp_cs2; + int temp_canvas_idx = -1; + int temp_y_index = -1; + int temp_u_index = -1; + int temp_v_index = -1; + unsigned char buf1[16]; + unsigned char buf2[16]; + unsigned char buf3[16]; + unsigned char buf_in[48]; + unsigned char buf_out[32]; + unsigned char tmp_buf[8]; + unsigned char in_cursor; + unsigned char out_cursor; + unsigned long read_size = 0; + unsigned int i; + unsigned char *line_start; + unsigned long counter = 0; + unsigned int w_align; + unsigned int h_align; + unsigned char tmp_char1; + int height_after_di; + + const char *amvideocap_owner = "amvideocapframe"; + int canvas_idx = canvas_pool_map_alloc_canvas(amvideocap_owner); + int y_index = cur_index & 0xff; + int u_index = (cur_index >> 8) & 0xff; + int v_index = (cur_index >> 16) & 0xff; + int input_x, input_y, input_width, input_height, intfmt; + memset(&ge2d_config, 0, sizeof(struct config_para_ex_s)); + intfmt = amvideocap_get_input_format(vf); + + if (((vf->bitdepth & BITDEPTH_Y10)) && + (intfmt == GE2D_FORMAT_S16_YUV422) && + (get_cpu_type() < MESON_CPU_MAJOR_ID_TXL)) { + temp_canvas_idx = + canvas_pool_map_alloc_canvas(amvideocap_owner); + if (temp_canvas_idx < 0) { + pr_err("alloc temp_canvas_idx failed"); + return -1; + } + temp_y_index = temp_canvas_idx & 0xff; + temp_u_index = (temp_canvas_idx >> 8) & 0xff; + temp_v_index = (temp_canvas_idx >> 16) & 0xff; + } + /* /unsigned long RGB_phy_addr=getgctrl()->phyaddr; */ + + if (!priv->phyaddr) { + pr_err("%s: failed to alloc y addr\n", __func__); + return -1; + } + pr_debug("RGB_phy_addr:%x\n", (unsigned int)priv->phyaddr); + + if (vf == NULL) { + pr_err("%s: vf is NULL\n", __func__); + return -1; + } + + canvas_config(canvas_idx, priv->phyaddr, + w * amvideocap_format_to_byte4pix(outfmt), h, + CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_LINEAR); + if (priv->src_rect.x < 0 || priv->src_rect.x > vf->width) + input_x = 0; + else + input_x = priv->src_rect.x; + + if (priv->src_rect.y < 0 || priv->src_rect.y > vf->height) + input_y = 0; + else + input_y = priv->src_rect.y; + + if (priv->src_rect.width < 0) + input_width = vf->width; + else if ((priv->src_rect.x + priv->src_rect.width) > vf->width) { + input_width = + priv->src_rect.x + priv->src_rect.width - vf->width; + } else + input_width = priv->src_rect.width; + + if (priv->src_rect.height < 0) + input_height = vf->height; + else if ((priv->src_rect.y + priv->src_rect.height) > vf->height) { + input_height = + priv->src_rect.y + priv->src_rect.height - vf->height; + } else + input_height = priv->src_rect.height; + + height_after_di = vf->height; + if (((vf->bitdepth & BITDEPTH_Y10)) && + ((intfmt == GE2D_FORMAT_S16_YUV422) || + ((intfmt == GE2D_FORMAT_S24_YUV444) && + (get_cpu_type() >= MESON_CPU_MAJOR_ID_TXL)))) { + pr_debug("input_height = %d , vf->type_original = %x\n" , + input_height, vf->type_original); + if ((vf->source_type == VFRAME_SOURCE_TYPE_HDMI) || + (vf->source_type == VFRAME_SOURCE_TYPE_CVBS) || + (vf->source_type == VFRAME_SOURCE_TYPE_TUNER)) { + if (vf->type_original & VIDTYPE_INTERLACE) { + height_after_di = vf->height >> 1; + input_height >>= 1; + } else { + height_after_di = vf->height; + } + } else { + /*local playback and DTV*/ + pr_debug("vf->prog_proc_config = %d", + vf->prog_proc_config); + if ((!vf->prog_proc_config) && + (!(vf->type_original & VIDTYPE_INTERLACE))) { + height_after_di = vf->height; + } else { + height_after_di = vf->height >> 1; + input_height >>= 1; + } + } + } else if (is_meson_g9tv_cpu() || is_meson_gxtvbb_cpu()) { + if (vf->type_original & VIDTYPE_INTERLACE) + input_height = input_height / 2; + } else { + if (intfmt == GE2D_FORMAT_S16_YUV422) + input_height = input_height / 2; + } + ge2d_config.alu_const_color = 0; + ge2d_config.bitmask_en = 0; + ge2d_config.src1_gb_alpha = 0; + ge2d_config.dst_xy_swap = 0; + + canvas_read(y_index, &cs0); + canvas_read(u_index, &cs1); + canvas_read(v_index, &cs2); + + if (((vf->bitdepth & BITDEPTH_Y10)) && + (intfmt == GE2D_FORMAT_S16_YUV422) && + (get_cpu_type() < MESON_CPU_MAJOR_ID_TXL)) { + pr_debug("vf->width = %d , vf->height = %d , vf->bitdepth = %d\n", + vf->width, vf->height, vf->bitdepth); + do_gettimeofday(&start); + psrc = phys_to_virt(cs0.addr); + w_align = ((vf->width + 32 - 1) & ~(32 - 1)); + h_align = ((vf->height + 32 - 1) & ~(32 - 1)); + temp_cma_buf_size = + (int)((w_align * h_align * 2)/(1024 * 1024)) + 1; + pr_debug("phybufaddr_8bit buffer size = %d\n", + temp_cma_buf_size); + phybufaddr_8bit = codec_mm_alloc_for_dma(CMA_NAME, + temp_cma_buf_size * SZ_1M / PAGE_SIZE, + 4 + PAGE_SHIFT, CODEC_MM_FLAGS_CPU); + if (!phybufaddr_8bit) + pr_err("failed to alloc phybufaddr_8bit\n"); + + canvas_config(temp_canvas_idx, phybufaddr_8bit, + w_align * 2, h_align, + CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_LINEAR); + canvas_read(temp_y_index, &temp_cs0); + canvas_read(temp_u_index, &temp_cs1); + canvas_read(temp_v_index, &temp_cs2); + + pdst = phys_to_virt(temp_cs0.addr); + + pr_debug("height_after_di = %d" , height_after_di); + line_start = psrc; + for (i = 0; i < height_after_di; i++) { + for (read_size = 0; read_size < w_align*3; + read_size += 48) { + /* swap 64bit */ + memcpy(buf1, line_start+read_size, 16); + memcpy(tmp_buf, buf1, 8); + memcpy(buf1, buf1+8, 8); + memcpy(buf1+8, tmp_buf, 8); + memcpy(buf_in+32, buf1, 16); + + memcpy(buf2, line_start+read_size+16, 16); + memcpy(tmp_buf, buf2, 8); + memcpy(buf2, buf2+8, 8); + memcpy(buf2+8, tmp_buf, 8); + memcpy(buf_in+16, buf2, 16); + + memcpy(buf3, line_start+read_size+32, 16); + memcpy(tmp_buf, buf3, 8); + memcpy(buf3, buf3+8, 8); + memcpy(buf3+8, tmp_buf, 8); + memcpy(buf_in, buf3, 16); + + in_cursor = 47; + out_cursor = 0; + + for (out_cursor = 0; out_cursor <= 30; + out_cursor += 2, in_cursor -= 3) { + buf_out[out_cursor] = + (buf_in[in_cursor-1] << 4) | + (buf_in[in_cursor-2] >> 4); + buf_out[out_cursor+1] = + buf_in[in_cursor]; + } + for (out_cursor = 0; out_cursor <= 24; + out_cursor += 8) { + /* y1 y4 */ + tmp_char1 = buf_out[1+out_cursor]; + buf_out[1+out_cursor] = + buf_out[7+out_cursor]; + buf_out[7+out_cursor] = tmp_char1; + + /* y2 y3 */ + tmp_char1 = buf_out[3+out_cursor]; + buf_out[3+out_cursor] = + buf_out[5+out_cursor]; + buf_out[5+out_cursor] = tmp_char1; + + /* u1 u2 */ + tmp_char1 = buf_out[out_cursor]; + buf_out[out_cursor] = + buf_out[2+out_cursor]; + buf_out[2+out_cursor] = tmp_char1; + + /* v1 v2 */ + tmp_char1 = buf_out[4+out_cursor]; + buf_out[4+out_cursor] = + buf_out[6+out_cursor]; + buf_out[6+out_cursor] = tmp_char1; + } + + memcpy(pdst+counter*32, buf_out, 32); + counter += 1; + } + line_start += cs0.width; + } + + codec_mm_dma_flush(pdst, + temp_cma_buf_size * SZ_1M, DMA_TO_DEVICE); + + counter = 0; + do_gettimeofday(&end); + time_use = (end.tv_sec - start.tv_sec) * 1000 + + (end.tv_usec - start.tv_usec) / 1000; + pr_debug("10to8 conversion cost time: %ldms\n", time_use); + } + + pr_debug("y_index=[0x%x] u_index=[0x%x] cur_index:%x\n", y_index, + u_index, cur_index); + + if (((vf->bitdepth & BITDEPTH_Y10)) && + (intfmt == GE2D_FORMAT_S16_YUV422) && + (get_cpu_type() < MESON_CPU_MAJOR_ID_TXL)) { + ge2d_config.src_planes[0].addr = temp_cs0.addr; + ge2d_config.src_planes[0].w = temp_cs0.width; + ge2d_config.src_planes[0].h = temp_cs0.height; + ge2d_config.src_planes[1].addr = temp_cs1.addr; + ge2d_config.src_planes[1].w = temp_cs1.width; + ge2d_config.src_planes[1].h = temp_cs1.height; + ge2d_config.src_planes[2].addr = temp_cs2.addr; + ge2d_config.src_planes[2].w = temp_cs2.width; + ge2d_config.src_planes[2].h = temp_cs2.height; + pr_debug("w=%d-height=%d\n", temp_cs0.width, temp_cs0.height); + pr_debug("cs0.width=%d, cs0.height=%d\n", cs0.width, cs0.height); + } else { + ge2d_config.src_planes[0].addr = cs0.addr; + ge2d_config.src_planes[0].w = cs0.width; + ge2d_config.src_planes[0].h = cs0.height; + ge2d_config.src_planes[1].addr = cs1.addr; + ge2d_config.src_planes[1].w = cs1.width; + ge2d_config.src_planes[1].h = cs1.height; + ge2d_config.src_planes[2].addr = cs2.addr; + ge2d_config.src_planes[2].w = cs2.width; + ge2d_config.src_planes[2].h = cs2.height; + pr_debug("w=%d-height=%d cur_index:%x\n", + cs0.width, cs0.height, cur_index); + } + + ge2d_config.src_key.key_enable = 0; + ge2d_config.src_key.key_mask = 0; + ge2d_config.src_key.key_mode = 0; + ge2d_config.src_key.key_color = 0; + + if (((vf->bitdepth & BITDEPTH_Y10)) && + (intfmt == GE2D_FORMAT_S16_YUV422) && + (get_cpu_type() < MESON_CPU_MAJOR_ID_TXL)) + ge2d_config.src_para.canvas_index = temp_canvas_idx; + else + ge2d_config.src_para.canvas_index = cur_index; + + ge2d_config.src_para.mem_type = CANVAS_TYPE_INVALID; + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_TXL) { + if (intfmt == GE2D_FORMAT_S16_YUV422) { + if ((vf->bitdepth & BITDEPTH_Y10) && + (vf->bitdepth & FULL_PACK_422_MODE)) { + pr_debug("format is yuv422 10bit .\n"); + ge2d_config.src_para.format = + GE2D_FORMAT_S16_10BIT_YUV422; + } else if (vf->bitdepth & BITDEPTH_Y10) { + pr_debug("format is yuv422 12bit .\n"); + ge2d_config.src_para.format = + GE2D_FORMAT_S16_12BIT_YUV422; + } else { + ge2d_config.src_para.format = intfmt; + } + } else if (intfmt == GE2D_FORMAT_S24_YUV444) { + if (vf->bitdepth & BITDEPTH_Y10) { + pr_debug("format is yuv444 10bit .\n"); + ge2d_config.src_para.format = + GE2D_FORMAT_S24_10BIT_YUV444; + } else { + ge2d_config.src_para.format = intfmt; + } + } else { + ge2d_config.src_para.format = intfmt; + } + } else { + ge2d_config.src_para.format = intfmt; + } + ge2d_config.src_para.fill_color_en = 0; + ge2d_config.src_para.fill_mode = 0; + ge2d_config.src_para.x_rev = 0; + ge2d_config.src_para.y_rev = 0; + ge2d_config.src_para.color = 0; + ge2d_config.src_para.left = input_x; + ge2d_config.src_para.top = input_y; + ge2d_config.src_para.width = input_width; + ge2d_config.src_para.height = input_height; + + canvas_read(canvas_idx, &cd); + pr_debug("cd.addr:%x\n", (unsigned int)cd.addr); + ge2d_config.dst_planes[0].addr = cd.addr; + ge2d_config.dst_planes[0].w = cd.width; + ge2d_config.dst_planes[0].h = cd.height; + + ge2d_config.dst_para.canvas_index = canvas_idx; + ge2d_config.dst_para.mem_type = CANVAS_TYPE_INVALID; + ge2d_config.dst_para.format = outfmt; + ge2d_config.dst_para.fill_color_en = 0; + ge2d_config.dst_para.fill_mode = 0; + ge2d_config.dst_para.x_rev = 0; + ge2d_config.dst_para.y_rev = 0; + ge2d_config.dst_xy_swap = 0; + ge2d_config.dst_para.color = 0; + ge2d_config.dst_para.top = 0; + ge2d_config.dst_para.left = 0; + ge2d_config.dst_para.width = w; + ge2d_config.dst_para.height = h; + + if (ge2d_context_config_ex(ge2d_amvideocap_context, &ge2d_config) < 0) { + pr_err("++ge2d configuration error.\n"); + return -1; + } + + stretchblt_noalpha_noblk(ge2d_amvideocap_context, + 0, + 0, + ge2d_config.src_para.width, + ge2d_config.src_para.height, + 0, + 0, + ge2d_config.dst_para.width, + ge2d_config.dst_para.height); + if (canvas_idx) + canvas_pool_map_free_canvas(canvas_idx); + + if (((vf->bitdepth & BITDEPTH_Y10)) && + (intfmt == GE2D_FORMAT_S16_YUV422) && + (get_cpu_type() < MESON_CPU_MAJOR_ID_TXL)) { + if (phybufaddr_8bit) { + ret = codec_mm_free_for_dma(CMA_NAME, phybufaddr_8bit); + if (ret != 0) + pr_err("phybufaddr_8bit cma buffer free failed .\n"); + } + if (temp_canvas_idx) + canvas_pool_map_free_canvas(temp_canvas_idx); + } + + return 0; +} + +static int amvideocap_capture_one_frame_l( + struct amvideocap_private *priv, + int curindex, int w, int h, + struct vframe_s *vf, int outge2dfmt) +{ + int ret; + /* TODO: mod gate */ + /* switch_mod_gate_by_name("ge2d", 1); */ + ret = amvideocap_YUV_to_RGB(priv, curindex, w, h, vf, outge2dfmt); + /* TODO: mod gate */ + /* switch_mod_gate_by_name("ge2d", 0); */ + return ret; +} + +static int amvideocap_capture_one_frame( + struct amvideocap_private *priv, + struct vframe_s *vfput, int index) +{ + int w, h, ge2dfmt; + int curindex; + struct vframe_s *vf = vfput; + int ret = 0; + pr_debug("%s:start vf=%p,index=%x\n", __func__, vf, index); + if (!vf) + ret = amvideocap_capture_get_frame(priv, &vf, &curindex); + else + curindex = index; + if (ret < 0 || !vf) + return -EAGAIN; + pr_debug("%s: get vf type=%x\n", __func__, vf->type); + +#define CHECK_AND_SETVAL(want, def) ((want) > 0 ? (want) : (def)) + ge2dfmt = CHECK_AND_SETVAL(priv->want.fmt, vf->type); + w = CHECK_AND_SETVAL(priv->want.width, vf->width); + h = CHECK_AND_SETVAL(priv->want.height, vf->height); +#undef CHECK_AND_SETVAL + + w = (w < CAP_WIDTH_MAX) ? w : CAP_WIDTH_MAX; + h = (h < CAP_HEIGHT_MAX) ? h : CAP_HEIGHT_MAX; + + ret = amvideocap_capture_one_frame_l(priv, curindex, w, h, vf, + priv->want.fmt); + amvideocap_capture_put_frame(priv, vf); + + if (!ret) { + pr_debug("%s: capture ok priv->want.fmt=%d\n", __func__, + priv->want.fmt); + priv->state = AMVIDEOCAP_STATE_FINISHED_CAPTURE; + priv->src.width = vf->width; + priv->src.height = vf->height; + priv->out.timestamp_ms = vf->pts * 1000 / 90; + priv->out.width = w; + priv->out.height = h; + priv->out.fmt = priv->want.fmt; + priv->out.width_aligned = priv->out.width; + priv->out.byte_per_pix = amvideocap_format_to_byte4pix( + priv->out.fmt); /* RGBn */ + } else + priv->state = AMVIDEOCAP_STATE_ERROR; + pr_debug("amvideocap_capture_one_frame priv->state=%d\n", priv->state); + return ret; +} + +static int amvideocap_capture_one_frame_wait( + struct amvideocap_private *priv, + int waitms) +{ + unsigned long timeout = jiffies + waitms * HZ / 1000; + int ret = 0; + struct amvideocap_req_data reqdata; + struct amvideocap_req req; + priv->sended_end_frame_cap_req = -EAGAIN; + priv->state = AMVIDEOCAP_STATE_ON_CAPTURE; + do { + if (ret == -EAGAIN) + usleep_range(500, 1000); + if (priv->want.at_flags == CAP_FLAG_AT_END) { + if (priv->sended_end_frame_cap_req == -EAGAIN) { + reqdata.privdata = priv; + req.callback = + amvideocap_capture_one_frame; + req.data = (unsigned long)&reqdata; + req.at_flags = priv->want.at_flags; + req.timestamp_ms = priv->want.timestamp_ms; + priv->sended_end_frame_cap_req = + ext_register_end_frame_callback(&req); + ret = -EAGAIN; + } else + if (priv->sended_end_frame_cap_req == -ENODATA || + priv->state == AMVIDEOCAP_STATE_ERROR) { + ret = -ENODATA; + } else + if (priv->state == AMVIDEOCAP_STATE_FINISHED_CAPTURE) + ret = 0; + } else { + ret = amvideocap_capture_one_frame(priv, NULL, 0); + pr_debug("amvideocap_capture_one_frame_wait ret=%d\n", + ret); + } + } while (ret == -EAGAIN && time_before(jiffies, timeout)); + ext_register_end_frame_callback(NULL); /*del req */ + return ret; +} + +static long amvideocap_ioctl(struct file *file, + unsigned int cmd, ulong arg) +{ + int ret = 0; + struct amvideocap_private *priv = file->private_data; + switch (cmd) { + case AMVIDEOCAP_IOW_SET_WANTFRAME_FORMAT: { + priv->want.fmt = arg; + break; + } + case AMVIDEOCAP_IOW_SET_WANTFRAME_WIDTH: { + priv->want.width = arg; + break; + } + case AMVIDEOCAP_IOW_SET_WANTFRAME_HEIGHT: { + priv->want.height = arg; + break; + } + case AMVIDEOCAP_IOW_SET_WANTFRAME_TIMESTAMP_MS: { + priv->want.timestamp_ms = arg; + break; + } + case AMVIDEOCAP_IOW_SET_WANTFRAME_AT_FLAGS: { + priv->want.at_flags = arg; + break; + } + case AMVIDEOCAP_IOR_GET_FRAME_FORMAT: { + if (copy_to_user + ((void *)arg, (void *)&priv->out.fmt, + sizeof(priv->out.fmt))) { + ret = -EFAULT; + break; + } + break; + } + case AMVIDEOCAP_IOR_GET_FRAME_WIDTH: { + if (copy_to_user + ((void *)arg, (void *)&priv->out.width, + sizeof(priv->out.width))) { + ret = -EFAULT; + break; + } + break; + } + case AMVIDEOCAP_IOR_GET_FRAME_HEIGHT: { + if (copy_to_user + ((void *)arg, (void *)&priv->out.height, + sizeof(priv->out.height))) { + ret = -EFAULT; + break; + } + break; + } + case AMVIDEOCAP_IOR_GET_FRAME_TIMESTAMP_MS: { + if (copy_to_user + ((void *)arg, (void *)&priv->out.timestamp_ms, + sizeof(priv->out.timestamp_ms))) { + ret = -EFAULT; + break; + } + break; + } + case AMVIDEOCAP_IOR_GET_SRCFRAME_FORMAT: { + if (copy_to_user + ((void *)arg, (void *)&priv->src.fmt, + sizeof(priv->src.fmt))) { + ret = -EFAULT; + break; + } + break; + } + case AMVIDEOCAP_IOR_GET_SRCFRAME_WIDTH: { + if (copy_to_user + ((void *)arg, (void *)&priv->src.width, + sizeof(priv->src.width))) { + ret = -EFAULT; + break; + } + break; + } + case AMVIDEOCAP_IOR_GET_SRCFRAME_HEIGHT: { + if (copy_to_user + ((void *)arg, (void *)&priv->src.height, + sizeof(priv->src.height))) { + ret = -EFAULT; + break; + } + break; + } + case AMVIDEOCAP_IOR_GET_STATE: { + if (copy_to_user + ((void *)arg, (void *)&priv->state, + sizeof(priv->state))) { + ret = -EFAULT; + break; + } + break; + } + case AMVIDEOCAP_IOW_SET_WANTFRAME_WAIT_MAX_MS: { + priv->wait_max_ms = arg; + break; + } + case AMVIDEOCAP_IOW_SET_START_CAPTURE: { + ret = amvideocap_capture_one_frame_wait(priv, arg); + break; + } + case AMVIDEOCAP_IOW_SET_CANCEL_CAPTURE: { + if (priv->sended_end_frame_cap_req) { + ext_register_end_frame_callback(NULL); /*del req */ + priv->sended_end_frame_cap_req = 0; + priv->state = AMVIDEOCAP_STATE_INIT; + } + break; + } + case AMVIDEOCAP_IOR_SET_SRC_X: { + priv->src_rect.x = arg; + break; + } + case AMVIDEOCAP_IOR_SET_SRC_Y: { + priv->src_rect.y = arg; + break; + } + case AMVIDEOCAP_IOR_SET_SRC_WIDTH: { + priv->src_rect.width = arg; + break; + } + case AMVIDEOCAP_IOR_SET_SRC_HEIGHT: { + priv->src_rect.height = arg; + break; + } + default: + pr_err("unkonw cmd=%x\n", cmd); + ret = -1; + } + return ret; +} + +#ifdef CONFIG_COMPAT +static long amvideocap_compat_ioctl(struct file *file, + unsigned int cmd, ulong arg) +{ + return amvideocap_ioctl(file, cmd, (ulong)compat_ptr(arg)); +} +#endif +static int amvideocap_mmap(struct file *file, + struct vm_area_struct *vma) +{ + struct amvideocap_private *priv = file->private_data; + unsigned long off = vma->vm_pgoff << PAGE_SHIFT; + unsigned vm_size = vma->vm_end - vma->vm_start; + if (!priv->phyaddr) + return -EIO; + + if (vm_size == 0) + return -EAGAIN; + /* pr_debug("mmap:%x\n",vm_size); */ + off += priv->phyaddr; + + vma->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP | VM_IO; + if (remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT, + vma->vm_end - vma->vm_start, + vma->vm_page_prot)) { + pr_err("set_cached: failed remap_pfn_range\n"); + return -EAGAIN; + } + pr_debug("amvideocap_mmap ok\n"); + return 0; +} + +static ssize_t amvideocap_read(struct file *file, char __user *buf, + size_t count, loff_t *ppos) +{ + struct amvideocap_private *priv = file->private_data; + int waitdelay; + int ret = 0; + int copied; + loff_t pos; + pos = *ppos; + if (priv->wait_max_ms > 0) + waitdelay = priv->wait_max_ms; + else { + if (priv->want.at_flags == CAP_FLAG_AT_END) /*need end */ + waitdelay = file->f_flags & O_NONBLOCK ? HZ : HZ * 100; + else + waitdelay = + file->f_flags & O_NONBLOCK ? + HZ / 100 : HZ * 10; + } + if (!pos) { /*trigger a new capture, */ + pr_debug("start amvideocap_read waitdelay=%d\n", waitdelay); + ret = amvideocap_capture_one_frame_wait(priv, waitdelay); + pr_debug("amvideocap_read=%d,priv->state=%d,priv->vaddr=%p\n", + ret, priv->state, priv->vaddr); + if ((ret == 0) + && (priv->state == AMVIDEOCAP_STATE_FINISHED_CAPTURE) + && (priv->vaddr != NULL)) { + int size = min((int)count, (priv->out.byte_per_pix * + priv->out.width_aligned * + priv->out.height)); + pr_debug + ("priv->out_width=%d priv->out_height=%d", + priv->out.width, priv->out.height); + pr_debug + (" priv->outfmt_byteppix=%d, size=%d\n", + priv->out.byte_per_pix, size); +#ifdef CONFIG_CMA + codec_mm_dma_flush(priv->vaddr, + cma_max_size * SZ_1M, DMA_FROM_DEVICE); +#endif + + copied = copy_to_user(buf, priv->vaddr, size); + if (copied) { + pr_err + ("amvideocap_read %d copy_to_user failed\n", + size); + } + ret = size; + } + } else { + /*read from old capture. */ + if (priv->state != AMVIDEOCAP_STATE_FINISHED_CAPTURE + || priv->vaddr == NULL) { + ret = 0; /*end. */ + } else { + int maxsize = + priv->out.byte_per_pix * + priv->out.width_aligned * priv->out.height; + if (pos < maxsize) { + int rsize = + min((int)count, (maxsize - (int)pos)); + copied = + copy_to_user(buf, priv->vaddr + pos, + rsize); + if (copied) { + pr_err + ("%s %d copy_to_user failed\n", + __func__, rsize); + } + ret = rsize; + } else { + ret = 0; /*end. */ + } + } + } + if (ret > 0) { + pos += ret; + *ppos = pos; + } + return ret; +} + +static const struct file_operations amvideocap_fops = { + .owner = THIS_MODULE, + .open = amvideocap_open, + .read = amvideocap_read, + .mmap = amvideocap_mmap, + .release = amvideocap_release, + .unlocked_ioctl = amvideocap_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = amvideocap_compat_ioctl, +#endif + /* / .poll = amvideocap_poll, */ +}; + +static ssize_t show_amvideocap_config(struct class *class, + struct class_attribute *attr, + char *buf) +{ + char *pbuf = buf; + ssize_t size = 0; + pbuf += sprintf(pbuf, "at_flags:%d\n", getgctrl()->want.at_flags); + pbuf += sprintf(pbuf, "timestampms:%lld\n", + getgctrl()->want.timestamp_ms); + pbuf += sprintf(pbuf, "width:%d\n", getgctrl()->want.width); + pbuf += sprintf(pbuf, "height:%d\n", getgctrl()->want.height); + pbuf += sprintf(pbuf, "format:%d\n", getgctrl()->want.fmt); + pbuf += sprintf(pbuf, "waitmaxms:%lld\n", getgctrl()->wait_max_ms); + size = pbuf - buf; + return size; +} + +static ssize_t store_amvideocap_config(struct class *class, + struct class_attribute *attr, + const char *buf, size_t size) +{ + int ret, val; + const char *pbuf = buf; + for (; pbuf && pbuf[0] != '\0';) { +#ifdef GETVAL +#undef GETVAL +#endif +#define GETVAL(tag, v) do { \ + val = 0;\ + ret = sscanf(pbuf, tag ":%d", &val); \ + if (ret == 1) { \ + v = val; \ + pbuf += strlen(tag); \ + goto tonext; \ + }; \ + } while (0) + GETVAL("timestamp", getgctrl()->want.timestamp_ms); + GETVAL("width", getgctrl()->want.width); + GETVAL("height", getgctrl()->want.height); + GETVAL("format", getgctrl()->want.fmt); + GETVAL("waitmaxms", getgctrl()->wait_max_ms); + GETVAL("at_flags", getgctrl()->want.at_flags); +#undef GETVAL + pbuf++; +tonext: + while (pbuf[0] != ';' && pbuf[0] != '\0') + pbuf++; + if (pbuf[0] == ';') + pbuf++; + } + return size; +} + +static struct class_attribute amvideocap_class_attrs[] = { + __ATTR(config, S_IRUGO | S_IWUSR | S_IWGRP, show_amvideocap_config, + store_amvideocap_config), + __ATTR_NULL +}; + +static struct class amvideocap_class = { + .name = MODULE_NAME, + .class_attrs = amvideocap_class_attrs, + }; + +s32 amvideocap_register_memory(unsigned char *phybufaddr, + int phybufsize) +{ + pr_debug("amvideocap_register_memory %p %d\n", phybufaddr, phybufsize); + getgctrl()->phyaddr = (unsigned long)phybufaddr; + getgctrl()->size = (unsigned long)phybufsize; + getgctrl()->vaddr = 0; + return 0; +} + +s32 amvideocap_dev_register(unsigned char *phybufaddr, int phybufsize) +{ + s32 r = 0; + pr_debug("amvideocap_dev_register\n"); + + gLOCKINIT(); + r = register_chrdev(0, DEVICE_NAME, &amvideocap_fops); + if (r < 0) { + pr_err("Can't register major for amvideocap device\n"); + return r; + } + getgctrl()->major = r; + r = class_register(&amvideocap_class); + if (r) { + pr_err("amvideocap class create fail.\n"); + goto err1; + } + getgctrl()->class = &amvideocap_class; + getgctrl()->dev = device_create(getgctrl()->class, + NULL, MKDEV(getgctrl()->major, 0), + NULL, DEVICE_NAME "0"); + if (getgctrl()->dev == NULL) { + pr_err("amvideocap device_create fail.\n"); + r = -EEXIST; + goto err2; + } + if (phybufaddr != NULL) { + getgctrl()->phyaddr = (unsigned long)phybufaddr; + getgctrl()->size = (unsigned long)phybufsize; + } + getgctrl()->wait_max_ms = 0; + getgctrl()->want.fmt = GE2D_FORMAT_S24_RGB; + getgctrl()->want.width = 0; + getgctrl()->want.height = 0; + getgctrl()->want.timestamp_ms = 0; + /*get last frame */ + getgctrl()->want.at_flags = CAP_FLAG_AT_CURRENT; + return 0; +err2: + class_unregister(&amvideocap_class); +err1: + unregister_chrdev(getgctrl()->major, DEVICE_NAME); + return r; +} + +s32 amvideocap_dev_unregister(void) +{ + device_destroy(getgctrl()->class, MKDEV(getgctrl()->major, 0)); + class_unregister(getgctrl()->class); + unregister_chrdev(getgctrl()->major, DEVICE_NAME); + + return 0; +} + +/******************************************************************* + * + * interface for Linux driver + * + * ******************************************************************/ + +static struct resource memobj; +/* for driver. */ +static int amvideocap_probe(struct platform_device *pdev) +{ + unsigned int buf_size; + struct resource *mem; + +#ifdef CONFIG_CMA + char buf[32]; + u32 value; + int ret; +#endif + + pr_err("amvideocap_probe,%s\n", pdev->dev.of_node->name); + +#ifdef CONFIG_CMA + snprintf(buf, sizeof(buf), "max_size"); + ret = of_property_read_u32(pdev->dev.of_node, buf, &value); + if (ret < 0) { + pr_err("cma size undefined.\n"); + use_cma = 0; + } else { + pr_err("use cma buf.\n"); + mem = &memobj; + mem->start = 0; + buf_size = 0; + cma_max_size = value; + amvideocap_pdev = pdev; + use_cma = 1; + } +#endif + + amvideocap_dev_register((unsigned char *)mem->start, buf_size); + return 0; +} + +static int amvideocap_remove(struct platform_device *plat_dev) +{ + /* struct rtc_device *rtc = platform_get_drvdata(plat_dev); */ + /* rtc_device_unregister(rtc); */ + /* device_remove_file(&plat_dev->dev, &dev_attr_irq); */ + amvideocap_dev_unregister(); + return 0; +} + + +static const struct of_device_id amlogic_amvideocap_dt_match[] = { + { + .compatible = "amlogic, amvideocap", + }, + {}, +}; + +/* general interface for a linux driver .*/ +struct platform_driver amvideocap_drv = { + .probe = amvideocap_probe, + .remove = amvideocap_remove, + .driver = { + .name = "amvideocap", + .of_match_table = amlogic_amvideocap_dt_match, + } +}; + +static int __init amvideocap_init_module(void) +{ + + pr_debug("amvideocap_init_module\n"); + if (ge2d_amvideocap_context == NULL) + ge2d_amvideocap_context = create_ge2d_work_queue(); + if ((platform_driver_register(&amvideocap_drv))) { + pr_err("failed to register amstream module\n"); + return -ENODEV; + } + return 0; + +} + +static void __exit amvideocap_remove_module(void) +{ + platform_driver_unregister(&amvideocap_drv); + if (ge2d_amvideocap_context) { + destroy_ge2d_work_queue(ge2d_amvideocap_context); + ge2d_amvideocap_context = NULL; + } + pr_debug("amvideocap module removed.\n"); +} + +module_init(amvideocap_init_module); +module_exit(amvideocap_remove_module); + +MODULE_DESCRIPTION("AMLOGIC amvideocap driver"); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Wang Jian "); diff --git a/drivers/amlogic/media/video_sink/amvideocap.h b/drivers/amlogic/media/video_sink/amvideocap.h new file mode 100644 index 000000000000..4712b5088a85 --- /dev/null +++ b/drivers/amlogic/media/video_sink/amvideocap.h @@ -0,0 +1,64 @@ +/* + * drivers/amlogic/media/video_sink/amvideocap.h + * + * Copyright (C) 2015 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * +*/ + +#ifndef __AMVIDEOCAP_HEADHER_ +#define __AMVIDEOCAP_HEADHER_ +#define AC_MAGIC 'V' +#include + +#define CAP_FLAG_AT_CURRENT 0 +#define CAP_FLAG_AT_TIME_WINDOW 1 +#define CAP_FLAG_AT_END 2 + +/* +format see linux/ge2d/ge2d.h +like: +GE2D_FORMAT_S24_RGB +*/ + +#define AMVIDEOCAP_IOW_SET_WANTFRAME_FORMAT _IOW((AC_MAGIC), 0x01, int) +#define AMVIDEOCAP_IOW_SET_WANTFRAME_WIDTH _IOW((AC_MAGIC), 0x02, int) +#define AMVIDEOCAP_IOW_SET_WANTFRAME_HEIGHT _IOW((AC_MAGIC), 0x03, int) +#define AMVIDEOCAP_IOW_SET_WANTFRAME_TIMESTAMP_MS _IOW((AC_MAGIC), 0x04, u64) +#define AMVIDEOCAP_IOW_SET_WANTFRAME_WAIT_MAX_MS _IOW((AC_MAGIC), 0x05, u64) +#define AMVIDEOCAP_IOW_SET_WANTFRAME_AT_FLAGS _IOW((AC_MAGIC), 0x06, int) + +#define AMVIDEOCAP_IOR_GET_FRAME_FORMAT _IOR((AC_MAGIC), 0x10, int) +#define AMVIDEOCAP_IOR_GET_FRAME_WIDTH _IOR((AC_MAGIC), 0x11, int) +#define AMVIDEOCAP_IOR_GET_FRAME_HEIGHT _IOR((AC_MAGIC), 0x12, int) +#define AMVIDEOCAP_IOR_GET_FRAME_TIMESTAMP_MS _IOR((AC_MAGIC), 0x13, int) + +#define AMVIDEOCAP_IOR_GET_SRCFRAME_FORMAT _IOR((AC_MAGIC), 0x20, int) +#define AMVIDEOCAP_IOR_GET_SRCFRAME_WIDTH _IOR((AC_MAGIC), 0x21, int) +#define AMVIDEOCAP_IOR_GET_SRCFRAME_HEIGHT _IOR((AC_MAGIC), 0x22, int) + +#define AMVIDEOCAP_IOR_GET_STATE _IOR((AC_MAGIC), 0x31, int) +#define AMVIDEOCAP_IOW_SET_START_CAPTURE _IOW((AC_MAGIC), 0x32, int) +#define AMVIDEOCAP_IOW_SET_CANCEL_CAPTURE _IOW((AC_MAGIC), 0x33, int) + +#define AMVIDEOCAP_IOR_SET_SRC_X _IOR((AC_MAGIC), 0x40, int) +#define AMVIDEOCAP_IOR_SET_SRC_Y _IOR((AC_MAGIC), 0x41, int) +#define AMVIDEOCAP_IOR_SET_SRC_WIDTH _IOR((AC_MAGIC), 0x42, int) +#define AMVIDEOCAP_IOR_SET_SRC_HEIGHT _IOR((AC_MAGIC), 0x43, int) + +enum amvideocap_state { + AMVIDEOCAP_STATE_INIT = 0, + AMVIDEOCAP_STATE_ON_CAPTURE = 200, + AMVIDEOCAP_STATE_FINISHED_CAPTURE = 300, + AMVIDEOCAP_STATE_ERROR = 0xffff, +}; +#endif /* __AMVIDEOCAP_HEADHER_ */ diff --git a/drivers/amlogic/media/video_sink/amvideocap_priv.h b/drivers/amlogic/media/video_sink/amvideocap_priv.h index 40b2fb28bdf1..3667ff0993d9 100644 --- a/drivers/amlogic/media/video_sink/amvideocap_priv.h +++ b/drivers/amlogic/media/video_sink/amvideocap_priv.h @@ -57,7 +57,7 @@ struct amvideocap_req_data { }; struct amvideocap_req { - int (*callback)(unsigned long data, struct vframe_s *vfput, + int (*callback)(struct amvideocap_private *privdata, struct vframe_s *vfput, int index); unsigned long data; int at_flags; /*AT_ */ diff --git a/drivers/amlogic/media/video_sink/video.c b/drivers/amlogic/media/video_sink/video.c index 4a88ab2b588a..c7a25697aca7 100644 --- a/drivers/amlogic/media/video_sink/video.c +++ b/drivers/amlogic/media/video_sink/video.c @@ -49,6 +49,7 @@ #include #include #include "video_priv.h" +#include #if defined(CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM) #include @@ -81,7 +82,6 @@ MODULE_AMLOG(LOG_LEVEL_ERROR, 0, LOG_DEFAULT_LEVEL_DESC, LOG_MASK_DESC); #define DISPLAY_CANVAS_MAX_INDEX2 0x15 #include "../common/rdma/rdma.h" #endif -#include #include #include @@ -91,6 +91,9 @@ MODULE_AMLOG(LOG_LEVEL_ERROR, 0, LOG_DEFAULT_LEVEL_DESC, LOG_MASK_DESC); #ifdef CONFIG_AMLOGIC_LEGACY_EARLY_SUSPEND #include #endif + +#define VIDEO_PIP + static u32 osd_vpp_misc; static u32 osd_vpp_misc_mask; static bool update_osd_vpp_misc; @@ -105,6 +108,8 @@ static int video_global_output = 1; /* video_pause_global: 0 is play, 1 is pause, 2 is invalid */ static int video_pause_global = 1; +static u32 cur_omx_index; + #ifdef CONFIG_GE2D_KEEP_FRAME /* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */ /* #include */ @@ -120,6 +125,12 @@ struct platform_resource_s { int mem_end; }; #endif + +struct video_frame_detect_s { + u32 interrupt_count; + u32 start_receive_count; +}; + static int debugflags; static int output_fps; static u32 omx_pts; @@ -144,6 +155,12 @@ static bool omx_drop_done; static bool video_start_post; static bool videopeek; static bool nopostvideostart; +static struct video_frame_detect_s video_frame_detect; +static struct timeval time_setomxpts = { + .tv_sec = 0, + .tv_usec = 0, +}; + /*----omx_info bit0: keep_last_frame, bit1~31: unused----*/ static u32 omx_info = 0x1; @@ -167,6 +184,7 @@ bool platform_type = 1; int bit_depth_flag = 8; bool omx_secret_mode; +EXPORT_SYMBOL(omx_secret_mode); #define DEBUG_FLAG_FFPLAY (1<<0) #define DEBUG_FLAG_CALC_PTS_INC (1<<1) @@ -183,20 +201,29 @@ static const struct vframe_receiver_op_s video_vf_receiver = { static struct vframe_receiver_s video_vf_recv; -#define RECEIVER4OSD_NAME "amvideo4osd" -static int video4osd_receiver_event_fun(int type, void *data, void *); +#ifdef VIDEO_PIP +#define RECEIVERPIP_NAME "videopip" +static int pip_receiver_event_fun(int type, void *data, void *); -static const struct vframe_receiver_op_s video4osd_vf_receiver = { - .event_cb = video4osd_receiver_event_fun +static const struct vframe_receiver_op_s videopip_vf_receiver = { + .event_cb = pip_receiver_event_fun }; -static struct vframe_receiver_s video4osd_vf_recv; +static struct vframe_receiver_s videopip_vf_recv; -static struct vframe_provider_s *osd_prov; +static struct vpp_frame_par_s *curpip_frame_par, *nextpip_frame_par; +static struct vpp_frame_par_s pip_frame_parms[2]; +static struct vframe_s *cur_pipbuf; +static struct vframe_s local_pip; +//int _videopip_set_disable(u32 val); +#endif static struct device *amvideo_dev; static struct device *amvideo_poll_dev; +static u32 cur_width; +static u32 cur_height; + #define DRIVER_NAME "amvideo" #define MODULE_NAME "amvideo" #define DEVICE_NAME "amvideo" @@ -233,14 +260,39 @@ static int video2_onoff_state = VIDEO_ENABLE_STATE_IDLE; static u32 hdmiin_frame_check; static u32 hdmiin_frame_check_cnt; + +/*frame_detect_flag: 1 enable, 0 disable */ +/*frame_detect_time: */ +/* How often "frame_detect_receive_count" and */ +/* "frame_detect_drop_count" are updated, suggested set 1(s) */ +/*frame_detect_fps: Set fps based on the video file, */ +/* If the FPS is 60, set it to 60000. */ +/*frame_detect_receive_count: */ +/* The number of frame that should be obtained during the test time. */ +/*frame_detect_drop_count: */ +/* The number of frame lost during test time. */ + + +static u32 frame_detect_flag; +static u32 frame_detect_time = 1; +static u32 frame_detect_fps = 60000; +static u32 frame_detect_receive_count; +static u32 frame_detect_drop_count; + #ifdef FIQ_VSYNC #define BRIDGE_IRQ INT_TIMER_C #define BRIDGE_IRQ_SET() WRITE_CBUS_REG(ISA_TIMERC, 1) #endif +#ifdef CONFIG_AMLOGIC_MEDIA_VIDEOCAPTURE +enum video_capture_state { + CAPTURE_STATE_OFF = 0, + CAPTURE_STATE_ON = 1, + CAPTURE_STATE_CAPTURE = 2, +}; - -#if 1 /* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */ +atomic_t capture_use_cnt = ATOMIC_INIT(CAPTURE_STATE_OFF); +#endif #define VD1_MEM_POWER_ON() \ do { \ @@ -283,22 +335,15 @@ static u32 hdmiin_frame_check_cnt; vpu_mem_power_off_count = VPU_MEM_POWEROFF_DELAY; \ spin_unlock_irqrestore(&delay_work_lock, flags); \ } while (0) -#else -#define VD1_MEM_POWER_ON() -#define VD2_MEM_POWER_ON() -#define PROT_MEM_POWER_ON() -#define VD1_MEM_POWER_OFF() -#define VD2_MEM_POWER_OFF() -#define PROT_MEM_POWER_OFF() -#endif #define VIDEO_LAYER_ON() \ do { \ unsigned long flags; \ spin_lock_irqsave(&video_onoff_lock, flags); \ - video_onoff_state = VIDEO_ENABLE_STATE_ON_REQ; \ - video_enabled = 1;\ - video_status_saved = 1;\ + if (video_onoff_state != VIDEO_ENABLE_STATE_ON_PENDING) \ + video_onoff_state = VIDEO_ENABLE_STATE_ON_REQ; \ + video_enabled = 1; \ + video_status_saved = 1; \ spin_unlock_irqrestore(&video_onoff_lock, flags); \ } while (0) @@ -309,6 +354,14 @@ static u32 hdmiin_frame_check_cnt; video_onoff_state = VIDEO_ENABLE_STATE_OFF_REQ; \ video_enabled = 0;\ video_status_saved = 0;\ + atomic_set(&capture_use_cnt, CAPTURE_STATE_OFF); \ + if (capture_frame_req && capture_frame_req->data) { \ + struct amvideocap_req_data *reqdata = \ + (struct amvideocap_req_data *)capture_frame_req->data; \ + if (reqdata && reqdata->privdata) \ + reqdata->privdata->state = 0xffff; \ + } \ + capture_frame_req = NULL; \ spin_unlock_irqrestore(&video_onoff_lock, flags); \ } while (0) @@ -316,7 +369,10 @@ static u32 hdmiin_frame_check_cnt; do { \ unsigned long flags; \ spin_lock_irqsave(&video2_onoff_lock, flags); \ - video2_onoff_state = VIDEO_ENABLE_STATE_ON_REQ; \ + if (video2_onoff_state != VIDEO_ENABLE_STATE_ON_PENDING) \ + video2_onoff_state = VIDEO_ENABLE_STATE_ON_REQ; \ + video2_enabled = 1; \ + video2_status_saved = 1; \ spin_unlock_irqrestore(&video2_onoff_lock, flags); \ } while (0) @@ -325,6 +381,8 @@ static u32 hdmiin_frame_check_cnt; unsigned long flags; \ spin_lock_irqsave(&video2_onoff_lock, flags); \ video2_onoff_state = VIDEO_ENABLE_STATE_OFF_REQ; \ + video2_enabled = 0; \ + video2_status_saved = 0; \ spin_unlock_irqrestore(&video2_onoff_lock, flags); \ } while (0) @@ -334,21 +392,12 @@ static u32 hdmiin_frame_check_cnt; VIDEO_LAYER_ON(); \ } while (0) -#if 0 /*TV_3D_FUNCTION_OPEN*/ -#define EnableVideoLayer2() \ - do { \ - VD2_MEM_POWER_ON(); \ - SET_VCBUS_REG_MASK(VPP_MISC + cur_dev->vpp_off, \ - VPP_VD2_PREBLEND | VPP_PREBLEND_EN | \ - (0x1ff << VPP_VD2_ALPHA_BIT)); \ - } while (0) -#else #define EnableVideoLayer2() \ do { \ VD2_MEM_POWER_ON(); \ VIDEO_LAYER2_ON(); \ } while (0) -#endif + #define VSYNC_EnableVideoLayer2() \ do { \ VD2_MEM_POWER_ON(); \ @@ -360,8 +409,7 @@ static u32 hdmiin_frame_check_cnt; #define DisableVideoLayer() \ do { \ CLEAR_VCBUS_REG_MASK(VPP_MISC + cur_dev->vpp_off, \ - VPP_VD1_PREBLEND | VPP_VD2_PREBLEND|\ - VPP_VD2_POSTBLEND | VPP_VD1_POSTBLEND); \ + VPP_VD1_PREBLEND | VPP_VD1_POSTBLEND); \ if (!legacy_vpp) { \ WRITE_VCBUS_REG( \ VD1_BLEND_SRC_CTRL + cur_dev->vpp_off, 0); \ @@ -369,13 +417,11 @@ static u32 hdmiin_frame_check_cnt; WRITE_VCBUS_REG(AFBC_ENABLE, 0);\ VIDEO_LAYER_OFF(); \ VD1_MEM_POWER_OFF(); \ - video_prot.video_started = 0; \ if (debug_flag & DEBUG_FLAG_BLACKOUT) { \ pr_info("DisableVideoLayer()\n"); \ } \ } while (0) -#if 1 /* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */ #define DisableVideoLayer_NoDelay() \ do { \ CLEAR_VCBUS_REG_MASK(VPP_MISC + cur_dev->vpp_off, \ @@ -390,28 +436,15 @@ static u32 hdmiin_frame_check_cnt; pr_info("DisableVideoLayer_NoDelay()\n"); \ } \ } while (0) -#else -#define DisableVideoLayer_NoDelay() DisableVideoLayer() -#endif -#if 0 /*TV_3D_FUNCTION_OPEN */ + #define DisableVideoLayer2() \ do { \ CLEAR_VCBUS_REG_MASK(VPP_MISC + cur_dev->vpp_off, \ - VPP_VD2_PREBLEND | VPP_PREBLEND_EN | \ - (0x1ff << VPP_VD2_ALPHA_BIT)); \ - WRITE_VCBUS_REG(VD2_AFBC_ENABLE, 0); \ - VD2_MEM_POWER_OFF(); \ - } while (0) -#else -#define DisableVideoLayer2() \ - do { \ - CLEAR_VCBUS_REG_MASK(VPP_MISC + cur_dev->vpp_off, \ - VPP_VD2_POSTBLEND | VPP_VD2_PREBLEND | \ - (0x1ff << VPP_VD2_ALPHA_BIT)); \ + VPP_VD2_POSTBLEND | VPP_VD2_PREBLEND); \ VIDEO_LAYER2_OFF(); \ VD2_MEM_POWER_OFF(); \ } while (0) -#endif + #define DisableVideoLayer_PREBELEND() \ do { CLEAR_VCBUS_REG_MASK(VPP_MISC + cur_dev->vpp_off, \ VPP_VD1_PREBLEND | VPP_VD2_PREBLEND); \ @@ -421,13 +454,6 @@ static u32 hdmiin_frame_check_cnt; } \ } while (0) -#ifndef CONFIG_AM_VIDEO2 -#define DisableVPP2VideoLayer() \ - CLEAR_VCBUS_REG_MASK(VPP2_MISC, \ - VPP_VD1_PREBLEND | VPP_VD2_PREBLEND | \ - VPP_VD2_POSTBLEND | VPP_VD1_POSTBLEND) - -#endif /*********************************************************/ #if DEBUG_TMP static struct switch_dev video1_state_sdev = { @@ -436,16 +462,22 @@ static struct switch_dev video1_state_sdev = { }; #endif +static DEFINE_MUTEX(video_layer_mutex); +static u32 layer_cap; + +static struct disp_info_s glayer_info[MAX_VD_LAYERS]; +static struct vframe_pic_mode_s gPic_info[MAX_VD_LAYERS]; + +static u32 reference_zorder = 128; + +/* default value 20 30 */ +static s32 black_threshold_width = 20; +static s32 black_threshold_height = 30; #define MAX_ZOOM_RATIO 300 -#if 1 /* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */ - #define VPP_PREBLEND_VD_V_END_LIMIT 2304 -#else -#define VPP_PREBLEND_VD_V_END_LIMIT 1080 -#endif #define DUR2PTS(x) ((x) - ((x) >> 4)) #define DUR2PTS_RM(x) ((x) & 0xf) @@ -458,11 +490,9 @@ static int vpts_chase_counter; static int vpts_chase_pts_diff; #endif - static int step_enable; static int step_flag; - /*seek values on.video_define.h*/ static int debug_flag; int get_video_debug_flags(void) @@ -527,6 +557,7 @@ const char video_dev_id2[] = "amvideo-dev2"; int onwaitendframe; static u32 vpp_hold_line = 8; +static u32 stop_update; struct video_dev_s video_dev[2] = { {0x1d00 - 0x1d00, 0x1a50 - 0x1a50}, @@ -547,10 +578,7 @@ struct video_pm_state_s { int mem_pd_vd1; int mem_pd_vd2; int mem_pd_di_post; - int mem_pd_prot2; - int mem_pd_prot3; }; - #endif #define PTS_LOGGING @@ -573,6 +601,9 @@ static int pts_trace; #define PTS_32_PATTERN_DETECT_RANGE 10 #define PTS_22_PATTERN_DETECT_RANGE 10 #define PTS_41_PATTERN_DETECT_RANGE 2 +#define PTS_32_PATTERN_DURATION 3750 +#define PTS_22_PATTERN_DURATION 3000 + enum video_refresh_pattern { PTS_32_PATTERN = 0, @@ -630,12 +661,10 @@ bool is_dolby_vision_stb_mode(void) } #endif -static struct amvideocap_req *capture_frame_req; -static struct video_prot_s video_prot; -static u32 video_angle; +static struct amvideocap_req *capture_frame_req = NULL; u32 get_video_angle(void) { - return video_angle; + return glayer_info[0].angle; } EXPORT_SYMBOL(get_video_angle); @@ -818,7 +847,7 @@ static void video_debugfs_exit(void) int video_scaler_notify(int flag) { video_scaler_mode = flag; - video_property_changed = true; + video_property_changed = 1; return 0; } @@ -834,6 +863,8 @@ u32 amvideo_get_scaler_para(int *x, int *y, int *w, int *h, u32 *ratio) void amvideo_set_scaler_para(int x, int y, int w, int h, int flag) { + struct disp_info_s *layer = &glayer_info[0]; + mutex_lock(&video_module_mutex); if (w < 2) w = 0; @@ -847,9 +878,13 @@ void amvideo_set_scaler_para(int x, int y, int w, int h, int flag) content_top = y; content_w = w; content_h = h; - } else - vpp_set_video_layer_position(x, y, w, h); - video_property_changed = true; + } else { + layer->layer_left = x; + layer->layer_top = y; + layer->layer_width = w; + layer->layer_height = h; + } + video_property_changed = 1; mutex_unlock(&video_module_mutex); } @@ -899,6 +934,13 @@ static u32 disp_canvas[2][2]; static u32 rdma_canvas_id; static u32 next_rdma_canvas_id = 1; +#ifdef VIDEO_PIP +static u32 pip_rdma_canvas_id; +static u32 pip_next_rdma_canvas_id = 1; +static struct vframe_s *pip_rdma_buf; +static struct vframe_s *pipbuf_to_put; +#endif + #define DISPBUF_TO_PUT_MAX 8 static struct vframe_s *dispbuf_to_put[DISPBUF_TO_PUT_MAX]; static int dispbuf_to_put_num; @@ -939,9 +981,6 @@ static u32 ori2_end_x_lines; static u32 ori2_start_y_lines; static u32 ori2_end_y_lines; -/* wide settings */ -static u32 wide_setting; - /* black out policy */ #if defined(CONFIG_JPEGLOGO) static u32 blackout; @@ -949,17 +988,44 @@ static u32 blackout; static u32 blackout = 1; #endif static u32 force_blackout; +static u32 blackout_pip; /* disable video */ + +#ifdef VIDEO_PIP +static u32 pip_frame_count; +static u32 disable_videopip = VIDEO_DISABLE_FORNEXT; +static int pip_property_changed; +static u32 pip_frame_ready_to_set; +static u32 pip_global_output = 1; +#if 0 +static u32 pip_v_skip; +static u32 pip_h_skip; +static u32 pip_start_x_lines; +static u32 pip_end_x_lines; +static u32 pip_start_y_lines; +static u32 pip_end_y_lines; +#endif +static u32 pip_loop; +#endif + static u32 disable_video = VIDEO_DISABLE_NONE; static u32 video_enabled __nosavedata; +static u32 video2_enabled __nosavedata; static u32 video_status_saved __nosavedata; +static u32 video2_status_saved __nosavedata; static u32 hold_video; u32 get_video_enabled(void) { return video_enabled; } + +u32 get_videopip_enabled(void) +{ + return video2_enabled; +} + /* show first frame*/ static bool show_first_frame_nosync; bool show_first_picture; @@ -980,24 +1046,11 @@ static const struct vinfo_s *vinfo; static struct vframe_s *cur_dispbuf; static struct vframe_s *cur_dispbuf2; static bool need_disable_vd2; +static bool last_mvc_status; void update_cur_dispbuf(void *buf) { cur_dispbuf = buf; } -int get_video0_frame_info(struct vframe_s *vf) -{ - unsigned long flags; - int ret = -1; - - spin_lock_irqsave(&lock, flags); - if (is_vpp_postblend() && cur_dispbuf && vf) { - *vf = *cur_dispbuf; - ret = 0; - } - spin_unlock_irqrestore(&lock, flags); - return ret; -} -EXPORT_SYMBOL(get_video0_frame_info); static struct vframe_s vf_local, vf_local2; static u32 vsync_pts_inc; @@ -1144,8 +1197,61 @@ void safe_disble_videolayer(void) #endif } - +#ifdef VIDEO_PIP +void safe_disble_videolayer2(void) +{ + DisableVideoLayer2(); +} +#endif /*********************************************************/ +#ifdef VIDEO_PIP +static inline struct vframe_s *pip_vf_peek(void) +{ + if (pip_loop) + return cur_dispbuf; + return vf_peek(RECEIVERPIP_NAME); +} + +static inline struct vframe_s *pip_vf_get(void) +{ + struct vframe_s *vf = NULL; + + if (pip_loop) + return cur_dispbuf; + + vf = vf_get(RECEIVERPIP_NAME); + + return vf; + +} + +#if 0 +static int pip_vf_get_states(struct vframe_states *states) +{ + int ret = -1; + unsigned long flags; + + spin_lock_irqsave(&lock, flags); + ret = vf_get_states_by_name(RECEIVERPIP_NAME, states); + spin_unlock_irqrestore(&lock, flags); + return ret; +} +#endif + +static inline void pip_vf_put(struct vframe_s *vf) +{ + struct vframe_provider_s *vfp = vf_get_provider(RECEIVERPIP_NAME); + + if (pip_loop) + return; + + if (vfp && vf) { + vf_put(vf, RECEIVERPIP_NAME); + /* video_notify_flag |= VIDEO_NOTIFY_PROVIDER_PUT; */ + } +} +#endif + static inline struct vframe_s *video_vf_peek(void) { struct vframe_s *vf = vf_peek(RECEIVER_NAME); @@ -1162,6 +1268,7 @@ static inline struct vframe_s *video_vf_peek(void) static inline struct vframe_s *video_vf_get(void) { struct vframe_s *vf = NULL; + int frame_width, frame_height; vf = vf_get(RECEIVER_NAME); @@ -1172,9 +1279,14 @@ static inline struct vframe_s *video_vf_get(void) vf->disp_pts = 0; vf->disp_pts_us64 = 0; } + if (vf->type & VIDTYPE_COMPRESS) { + frame_width = vf->compWidth; + frame_height = vf->compHeight; + } else { + frame_width = vf->width; + frame_height = vf->height; + } video_notify_flag |= VIDEO_NOTIFY_PROVIDER_GET; - atomic_set(&vf->use_cnt, 1); - /*always to 1,for first get from vfm provider */ if ((vf->type & VIDTYPE_MVC) && (framepacking_support) &&(framepacking_width) && (framepacking_height)) { vf->width = framepacking_width; @@ -1193,36 +1305,35 @@ static inline struct vframe_s *video_vf_get(void) } if (((process_3d_type & MODE_FORCE_3D_TO_2D_LR) || (process_3d_type & MODE_FORCE_3D_LR) - || (process_3d_type & MODE_FORCE_3D_FA_LR) - ) + || (process_3d_type & MODE_FORCE_3D_FA_LR)) && (!(vf->type & VIDTYPE_MVC)) && (vf->trans_fmt != TVIN_TFMT_3D_FP)) { vf->trans_fmt = TVIN_TFMT_3D_DET_LR; vf->left_eye.start_x = 0; vf->left_eye.start_y = 0; - vf->left_eye.width = vf->width / 2; - vf->left_eye.height = vf->height; + vf->left_eye.width = frame_width / 2; + vf->left_eye.height = frame_height; - vf->right_eye.start_x = vf->width / 2; + vf->right_eye.start_x = frame_width / 2; vf->right_eye.start_y = 0; - vf->right_eye.width = vf->width / 2; + vf->right_eye.width = frame_width / 2; + vf->right_eye.height = frame_height; } if (((process_3d_type & MODE_FORCE_3D_TO_2D_TB) || (process_3d_type & MODE_FORCE_3D_TB) - || (process_3d_type & MODE_FORCE_3D_FA_TB) - ) + || (process_3d_type & MODE_FORCE_3D_FA_TB)) && (!(vf->type & VIDTYPE_MVC)) && (vf->trans_fmt != TVIN_TFMT_3D_FP)) { vf->trans_fmt = TVIN_TFMT_3D_TB; vf->left_eye.start_x = 0; vf->left_eye.start_y = 0; - vf->left_eye.width = vf->width; - vf->left_eye.height = vf->height/2; + vf->left_eye.width = frame_width; + vf->left_eye.height = frame_height/2; vf->right_eye.start_x = 0; - vf->right_eye.start_y = vf->height/2; - vf->right_eye.width = vf->width; - vf->right_eye.height = vf->height/2; + vf->right_eye.start_y = frame_height/2; + vf->right_eye.width = frame_width; + vf->right_eye.height = frame_height/2; } receive_frame_count++; #endif @@ -1244,9 +1355,7 @@ static int video_vf_get_states(struct vframe_states *states) static inline void video_vf_put(struct vframe_s *vf) { - struct vframe_provider_s *vfp = vf_get_provider(RECEIVER_NAME); - - if (vfp && vf && atomic_dec_and_test(&vf->use_cnt)) { + if (vf) { vf_put(vf, RECEIVER_NAME); #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION if (is_dolby_vision_enable()) @@ -1256,15 +1365,6 @@ static inline void video_vf_put(struct vframe_s *vf) } } -int ext_get_cur_video_frame(struct vframe_s **vf, int *canvas_index) -{ - if (cur_dispbuf == NULL) - return -1; - atomic_inc(&cur_dispbuf->use_cnt); - *canvas_index = READ_VCBUS_REG(VD1_IF0_CANVAS0 + cur_dev->viu_off); - *vf = cur_dispbuf; - return 0; -} static void dump_vframe_status(const char *name) { int ret = -1; @@ -1298,12 +1398,17 @@ static void dump_vdin_reg(void) } #ifdef CONFIG_AMLOGIC_MEDIA_VIDEOCAPTURE +int ext_get_cur_video_frame(struct vframe_s **vf, int *canvas_index) +{ + if (cur_dispbuf == NULL) + return -1; + *canvas_index = READ_VCBUS_REG(VD1_IF0_CANVAS0 + cur_dev->viu_off); + *vf = cur_dispbuf; + return 0; +} int ext_put_video_frame(struct vframe_s *vf) { - if (vf == &vf_local) - return 0; - video_vf_put(vf); return 0; } @@ -1320,31 +1425,69 @@ static int is_need_framepacking_output(void) int ext_register_end_frame_callback(struct amvideocap_req *req) { - mutex_lock(&video_module_mutex); - capture_frame_req = req; - mutex_unlock(&video_module_mutex); - return 0; -} -int ext_frame_capture_poll(int endflags) -{ - mutex_lock(&video_module_mutex); - if (capture_frame_req && capture_frame_req->callback) { - struct vframe_s *vf; - int index; - int ret; - struct amvideocap_req *req = capture_frame_req; + int ret = -EAGAIN; + + if (!req) { + atomic_set(&capture_use_cnt, CAPTURE_STATE_ON); + ret = 0; + } + else if (atomic_read(&capture_use_cnt) == CAPTURE_STATE_ON && req) + { + capture_frame_req = req; + atomic_set(&capture_use_cnt, CAPTURE_STATE_CAPTURE); + ret = 0; + } + else if ( atomic_read(&capture_use_cnt) == CAPTURE_STATE_OFF) + ret = -ENODATA; + + return ret; +} + +int ext_frame_capture_poll(struct vframe_s *vf) +{ + int ret = -EAGAIN; + static int capture_frame_toggle = 0; + + if (capture_frame_toggle == 0 && vf) { + if (vf->duration > 0 && (96000 / vf->duration) > 30) + capture_frame_toggle = 1; + + if (atomic_read(&capture_use_cnt) == CAPTURE_STATE_CAPTURE && capture_frame_req && capture_frame_req->callback) { + struct amvideocap_req_data *reqdata = + (struct amvideocap_req_data *)capture_frame_req->data; + int index = READ_VCBUS_REG(VD1_IF0_CANVAS0 + cur_dev->viu_off); + + if (reqdata && reqdata->privdata) + ret = capture_frame_req->callback(reqdata->privdata, vf, index); - ret = ext_get_cur_video_frame(&vf, &index); - if (!ret) { - req->callback(req->data, vf, index); capture_frame_req = NULL; + atomic_set(&capture_use_cnt, CAPTURE_STATE_ON); } } - mutex_unlock(&video_module_mutex); - return 0; + else + capture_frame_toggle = 0; + + return ret; } #endif +static void update_layer_info(u8 layer_id) +{ + struct disp_info_s *layer; + + if (layer_id >= MAX_VD_LAYERS) + return; + + if (layer_id == 0) { + layer = &glayer_info[0]; + layer->reverse = reverse; + layer->proc_3d_type = process_3d_type; + } else if (layer_id == 1) { + layer = &glayer_info[1]; + layer->reverse = reverse; + layer->proc_3d_type = 0; + } +} static void vpp_settings_h(struct vpp_frame_par_s *framePtr) { @@ -1358,86 +1501,83 @@ static void vpp_settings_h(struct vpp_frame_par_s *framePtr) r3 = framePtr->VPP_hsc_endp - framePtr->VPP_hsc_startp; if ((framePtr->supscl_path == CORE0_PPS_CORE1) || - (framePtr->supscl_path == CORE1_AFTER_PPS)) + (framePtr->supscl_path == CORE1_AFTER_PPS) || + (framePtr->supscl_path == PPS_CORE0_CORE1) || + (framePtr->supscl_path == PPS_CORE0_POSTBLEND_CORE1)) r3 >>= framePtr->supsc1_hori_ratio; - if (framePtr->supscl_path == CORE0_AFTER_PPS) + if ((framePtr->supscl_path == CORE0_AFTER_PPS) || + (framePtr->supscl_path == PPS_CORE0_CORE1) || + (framePtr->supscl_path == PPS_CORE0_POSTBLEND_CORE1)) r3 >>= framePtr->supsc0_hori_ratio; - if (platform_type == 1) { - x_lines = zoom_end_x_lines / (framePtr->hscale_skip_count + 1); - if (process_3d_type & MODE_3D_OUT_TB) { - /* vd1 and vd2 do pre blend */ - VSYNC_WR_MPEG_REG(VPP_PREBLEND_VD1_H_START_END, + x_lines = zoom_end_x_lines / (framePtr->hscale_skip_count + 1); + if (process_3d_type & MODE_3D_OUT_TB) { + /* vd1 and vd2 do pre blend */ + VSYNC_WR_MPEG_REG(VPP_PREBLEND_VD1_H_START_END, + ((zoom_start_x_lines & VPP_VD_SIZE_MASK) << + VPP_VD1_START_BIT) | (((zoom_end_x_lines) & + VPP_VD_SIZE_MASK) << VPP_VD1_END_BIT)); + VSYNC_WR_MPEG_REG(VPP_BLEND_VD2_H_START_END, ((zoom_start_x_lines & VPP_VD_SIZE_MASK) << VPP_VD1_START_BIT) | (((zoom_end_x_lines) & VPP_VD_SIZE_MASK) << VPP_VD1_END_BIT)); - VSYNC_WR_MPEG_REG(VPP_BLEND_VD2_H_START_END, - ((zoom_start_x_lines & VPP_VD_SIZE_MASK) << - VPP_VD1_START_BIT) | (((zoom_end_x_lines) & - VPP_VD_SIZE_MASK) << VPP_VD1_END_BIT)); - VSYNC_WR_MPEG_REG(VPP_POSTBLEND_VD1_H_START_END + + VSYNC_WR_MPEG_REG(VPP_POSTBLEND_VD1_H_START_END + cur_dev->vpp_off, ((framePtr->VPP_hsc_startp & VPP_VD_SIZE_MASK) << VPP_VD1_START_BIT) | ((framePtr->VPP_hsc_endp & VPP_VD_SIZE_MASK) << VPP_VD1_END_BIT)); - } else if (process_3d_type & MODE_3D_OUT_LR) { - /* vd1 and vd2 do pre blend */ - VSYNC_WR_MPEG_REG(VPP_PREBLEND_VD1_H_START_END, + } else if (process_3d_type & MODE_3D_OUT_LR) { + /* vd1 and vd2 do pre blend */ + VSYNC_WR_MPEG_REG(VPP_PREBLEND_VD1_H_START_END, ((zoom_start_x_lines & VPP_VD_SIZE_MASK) << VPP_VD1_START_BIT) | (((x_lines >> 1) & VPP_VD_SIZE_MASK) << VPP_VD1_END_BIT)); - VSYNC_WR_MPEG_REG(VPP_BLEND_VD2_H_START_END, + VSYNC_WR_MPEG_REG(VPP_BLEND_VD2_H_START_END, ((((x_lines + 1) >> 1) & VPP_VD_SIZE_MASK) << VPP_VD1_START_BIT) | ((x_lines & VPP_VD_SIZE_MASK) << VPP_VD1_END_BIT)); - VSYNC_WR_MPEG_REG(VPP_POSTBLEND_VD1_H_START_END + + VSYNC_WR_MPEG_REG(VPP_POSTBLEND_VD1_H_START_END + cur_dev->vpp_off, ((framePtr->VPP_hsc_startp & VPP_VD_SIZE_MASK) << VPP_VD1_START_BIT) | ((framePtr->VPP_hsc_endp & VPP_VD_SIZE_MASK) << VPP_VD1_END_BIT)); - } else{ - if (!legacy_vpp) { - x_lines = (zoom_end_x_lines - - zoom_start_x_lines + 1) - / (framePtr->hscale_skip_count + 1); - VSYNC_WR_MPEG_REG( + } else{ + if (!legacy_vpp) { + x_lines = (zoom_end_x_lines - + zoom_start_x_lines + 1) + / (framePtr->hscale_skip_count + 1); + VSYNC_WR_MPEG_REG( VPP_PREBLEND_VD1_H_START_END, ((0 & VPP_VD_SIZE_MASK) << VPP_VD1_START_BIT) | (((x_lines - 1) & VPP_VD_SIZE_MASK) << VPP_VD1_END_BIT)); - } - VSYNC_WR_MPEG_REG(VPP_POSTBLEND_VD1_H_START_END + - cur_dev->vpp_off, - ((framePtr->VPP_hsc_startp & VPP_VD_SIZE_MASK) - << VPP_VD1_START_BIT) | - ((framePtr->VPP_hsc_endp & VPP_VD_SIZE_MASK) - << VPP_VD1_END_BIT)); - - VSYNC_WR_MPEG_REG(VPP_BLEND_VD2_H_START_END + - cur_dev->vpp_off, - ((framePtr->VPP_hd_start_lines_ & - VPP_VD_SIZE_MASK) << VPP_VD1_START_BIT) | - ((framePtr->VPP_hd_end_lines_ & - VPP_VD_SIZE_MASK) << VPP_VD1_END_BIT)); } - } else { - VSYNC_WR_MPEG_REG(VPP_POSTBLEND_VD1_H_START_END + + VSYNC_WR_MPEG_REG( + VPP_POSTBLEND_VD1_H_START_END + cur_dev->vpp_off, ((framePtr->VPP_hsc_startp & VPP_VD_SIZE_MASK) << VPP_VD1_START_BIT) | ((framePtr->VPP_hsc_endp & VPP_VD_SIZE_MASK) << VPP_VD1_END_BIT)); - - VSYNC_WR_MPEG_REG(VPP_BLEND_VD2_H_START_END + - cur_dev->vpp_off, - ((framePtr->VPP_hd_start_lines_ & - VPP_VD_SIZE_MASK) << VPP_VD1_START_BIT) | - ((framePtr->VPP_hd_end_lines_ & - VPP_VD_SIZE_MASK) << VPP_VD1_END_BIT)); +#ifdef VIDEO_PIP + if (!cur_pipbuf) +#endif + { + VSYNC_WR_MPEG_REG( + VPP_BLEND_VD2_H_START_END + + cur_dev->vpp_off, + ((framePtr->VPP_hd_start_lines_ & + VPP_VD_SIZE_MASK) + << VPP_VD1_START_BIT) | + ((framePtr->VPP_hd_end_lines_ & + VPP_VD_SIZE_MASK) + << VPP_VD1_END_BIT)); + } } + VSYNC_WR_MPEG_REG(VPP_HSC_REGION12_STARTP + cur_dev->vpp_off, (0 << VPP_REGION1_BIT) | @@ -1470,12 +1610,14 @@ static void vd2_settings_h(struct vframe_s *vf) VPP_hd_start_lines_ = 0; VPP_hd_end_lines_ = ((vf->type & VIDTYPE_COMPRESS) ? vf->compWidth : vf->width) - 1; - VSYNC_WR_MPEG_REG(VPP_BLEND_VD2_H_START_END + - cur_dev->vpp_off, - ((VPP_hd_start_lines_ & - VPP_VD_SIZE_MASK) << VPP_VD1_START_BIT) | - ((VPP_hd_end_lines_ & - VPP_VD_SIZE_MASK) << VPP_VD1_END_BIT)); + + VSYNC_WR_MPEG_REG( + VPP_BLEND_VD2_H_START_END + + cur_dev->vpp_off, + ((VPP_hd_start_lines_ & + VPP_VD_SIZE_MASK) << VPP_VD1_START_BIT) | + ((VPP_hd_end_lines_ & + VPP_VD_SIZE_MASK) << VPP_VD1_END_BIT)); } } @@ -1487,6 +1629,7 @@ static void vpp_settings_v(struct vpp_frame_par_s *framePtr) u32 v_phase; u32 v_skip_flag = 0; int x, y, w, h; + struct disp_info_s *layer = &glayer_info[0]; r = framePtr->VPP_vsc_endp - framePtr->VPP_vsc_startp; afbc_enble_flag = 0; @@ -1502,7 +1645,11 @@ static void vpp_settings_v(struct vpp_frame_par_s *framePtr) else { afbc_enble_flag = READ_VCBUS_REG(AFBC_ENABLE) & 0x100; v_phase = vpp_filter->vpp_vsc_start_phase_step; - vpp_get_video_layer_position(&x, &y, &w, &h); + + x = layer->layer_left; + y = layer->layer_top; + w = layer->layer_width; + h = layer->layer_height; if (v_phase * (framePtr->vscale_skip_count + 1) > 0x1000000) { if ((afbc_enble_flag) && (y < 0)) { if ((framePtr->VPP_vsc_endp < 0x250) || @@ -1528,34 +1675,33 @@ static void vpp_settings_v(struct vpp_frame_par_s *framePtr) } } - if (platform_type == 1) { - y_lines = zoom_end_y_lines / (framePtr->vscale_skip_count + 1); - if (process_3d_type & MODE_3D_OUT_TB) { - VSYNC_WR_MPEG_REG(VPP_PREBLEND_VD1_V_START_END, + y_lines = zoom_end_y_lines / (framePtr->vscale_skip_count + 1); + if (process_3d_type & MODE_3D_OUT_TB) { + VSYNC_WR_MPEG_REG(VPP_PREBLEND_VD1_V_START_END, ((zoom_start_y_lines & VPP_VD_SIZE_MASK) << VPP_VD1_START_BIT) | (((y_lines >> 1) & VPP_VD_SIZE_MASK) << VPP_VD1_END_BIT)); - VSYNC_WR_MPEG_REG( + VSYNC_WR_MPEG_REG( VPP_BLEND_VD2_V_START_END, ((((y_lines + 1) >> 1) & VPP_VD_SIZE_MASK) << VPP_VD1_START_BIT) | ((y_lines & VPP_VD_SIZE_MASK) << VPP_VD1_END_BIT)); - } else if (process_3d_type & MODE_3D_OUT_LR) { - VSYNC_WR_MPEG_REG(VPP_PREBLEND_VD1_V_START_END, + } else if (process_3d_type & MODE_3D_OUT_LR) { + VSYNC_WR_MPEG_REG(VPP_PREBLEND_VD1_V_START_END, ((zoom_start_y_lines & VPP_VD_SIZE_MASK) << VPP_VD1_START_BIT) | ((zoom_end_y_lines & VPP_VD_SIZE_MASK) << VPP_VD1_END_BIT)); - VSYNC_WR_MPEG_REG(VPP_BLEND_VD2_V_START_END, + VSYNC_WR_MPEG_REG(VPP_BLEND_VD2_V_START_END, ((zoom_start_y_lines & VPP_VD_SIZE_MASK) << VPP_VD1_START_BIT) | ((zoom_end_y_lines & VPP_VD_SIZE_MASK) << VPP_VD1_END_BIT)); - } else { - if ((framePtr->VPP_post_blend_vd_v_end_ - - framePtr->VPP_post_blend_vd_v_start_ + 1) > - VPP_PREBLEND_VD_V_END_LIMIT) { - VSYNC_WR_MPEG_REG(VPP_PREBLEND_VD1_V_START_END + + } else { + if ((framePtr->VPP_post_blend_vd_v_end_ - + framePtr->VPP_post_blend_vd_v_start_ + 1) > + VPP_PREBLEND_VD_V_END_LIMIT) { + VSYNC_WR_MPEG_REG(VPP_PREBLEND_VD1_V_START_END + cur_dev->vpp_off, ((framePtr->VPP_post_blend_vd_v_start_ & VPP_VD_SIZE_MASK) << @@ -1563,72 +1709,36 @@ static void vpp_settings_v(struct vpp_frame_par_s *framePtr) ((framePtr->VPP_post_blend_vd_v_end_ & VPP_VD_SIZE_MASK) << VPP_VD1_END_BIT)); - } else { - VSYNC_WR_MPEG_REG(VPP_PREBLEND_VD1_V_START_END + + } else { + VSYNC_WR_MPEG_REG(VPP_PREBLEND_VD1_V_START_END + cur_dev->vpp_off, ((0 & VPP_VD_SIZE_MASK) << VPP_VD1_START_BIT) | (((VPP_PREBLEND_VD_V_END_LIMIT - 1) & VPP_VD_SIZE_MASK) << VPP_VD1_END_BIT)); - } - - if (is_need_framepacking_output()) { - VSYNC_WR_MPEG_REG(VPP_BLEND_VD2_V_START_END + - cur_dev->vpp_off, - (((((framePtr->VPP_vd_end_lines_ - - framepacking_blank + 1) / 2) + framepacking_blank) & - VPP_VD_SIZE_MASK) << VPP_VD1_START_BIT) | - (((framePtr->VPP_vd_end_lines_) & - VPP_VD_SIZE_MASK) << VPP_VD1_END_BIT)); - } else { - VSYNC_WR_MPEG_REG(VPP_BLEND_VD2_V_START_END + - cur_dev->vpp_off, - ((((framePtr->VPP_vd_end_lines_ + 1) / 2) & - VPP_VD_SIZE_MASK) << VPP_VD1_START_BIT) | - (((framePtr->VPP_vd_end_lines_) & - VPP_VD_SIZE_MASK) << VPP_VD1_END_BIT)); - } - } - } else { - if ((framePtr->VPP_post_blend_vd_v_end_ - - framePtr->VPP_post_blend_vd_v_start_ + 1) > - VPP_PREBLEND_VD_V_END_LIMIT) { - VSYNC_WR_MPEG_REG(VPP_PREBLEND_VD1_V_START_END + - cur_dev->vpp_off, - ((framePtr->VPP_post_blend_vd_v_start_ - & VPP_VD_SIZE_MASK) << - VPP_VD1_START_BIT) | - ((framePtr->VPP_post_blend_vd_v_end_ & - VPP_VD_SIZE_MASK) - << VPP_VD1_END_BIT)); - } else { - VSYNC_WR_MPEG_REG(VPP_PREBLEND_VD1_V_START_END + - cur_dev->vpp_off, - ((0 & VPP_VD_SIZE_MASK) << - VPP_VD1_START_BIT) | - (((VPP_PREBLEND_VD_V_END_LIMIT - 1) & - VPP_VD_SIZE_MASK) << - VPP_VD1_END_BIT)); - } - if (is_need_framepacking_output()) { - VSYNC_WR_MPEG_REG(VPP_BLEND_VD2_V_START_END + - cur_dev->vpp_off, - (((((framePtr->VPP_vd_end_lines_ - +#ifdef VIDEO_PIP + if (!cur_pipbuf) +#endif + { + VSYNC_WR_MPEG_REG(VPP_BLEND_VD2_V_START_END + + cur_dev->vpp_off, + ((((framePtr->VPP_vd_end_lines_ + 1) / 2) & + VPP_VD_SIZE_MASK) << VPP_VD1_START_BIT) | + (((framePtr->VPP_vd_end_lines_) & + VPP_VD_SIZE_MASK) << VPP_VD1_END_BIT)); + } + if (is_need_framepacking_output()) { + VSYNC_WR_MPEG_REG( + VPP_BLEND_VD2_V_START_END + + cur_dev->vpp_off, + (((((framePtr->VPP_vd_end_lines_ - framepacking_blank + 1) / 2) + framepacking_blank) & - VPP_VD_SIZE_MASK) << VPP_VD1_START_BIT) | - (((framePtr->VPP_vd_end_lines_) & - VPP_VD_SIZE_MASK) << VPP_VD1_END_BIT)); - } else { - VSYNC_WR_MPEG_REG(VPP_BLEND_VD2_V_START_END + - cur_dev->vpp_off, - ((((framePtr->VPP_vd_end_lines_ + 1) / 2) & - VPP_VD_SIZE_MASK) << VPP_VD1_START_BIT) | - (((framePtr->VPP_vd_end_lines_) & - VPP_VD_SIZE_MASK) << VPP_VD1_END_BIT)); - } - + VPP_VD_SIZE_MASK) << VPP_VD1_START_BIT) | + (((framePtr->VPP_vd_end_lines_) & + VPP_VD_SIZE_MASK) << VPP_VD1_END_BIT)); + } } VSYNC_WR_MPEG_REG(VPP_VSC_REGION12_STARTP + cur_dev->vpp_off, 0); VSYNC_WR_MPEG_REG(VPP_VSC_REGION34_STARTP + cur_dev->vpp_off, @@ -1636,9 +1746,12 @@ static void vpp_settings_v(struct vpp_frame_par_s *framePtr) ((r & VPP_REGION_MASK) << VPP_REGION4_BIT)); if ((framePtr->supscl_path == CORE0_PPS_CORE1) || - (framePtr->supscl_path == CORE1_AFTER_PPS)) + (framePtr->supscl_path == CORE1_AFTER_PPS) || + (framePtr->supscl_path == PPS_CORE0_POSTBLEND_CORE1)) r >>= framePtr->supsc1_vert_ratio; - if (framePtr->supscl_path == CORE0_AFTER_PPS) + if ((framePtr->supscl_path == CORE0_AFTER_PPS) || + (framePtr->supscl_path == PPS_CORE0_CORE1) || + (framePtr->supscl_path == PPS_CORE0_POSTBLEND_CORE1)) r >>= framePtr->supsc0_vert_ratio; VSYNC_WR_MPEG_REG(VPP_VSC_REGION4_ENDP + cur_dev->vpp_off, r); @@ -1667,28 +1780,41 @@ static void vd2_settings_v(struct vframe_s *vf) } #ifdef TV_3D_FUNCTION_OPEN - static void zoom_get_horz_pos(struct vframe_s *vf, u32 vpp_3d_mode, u32 *ls, u32 *le, u32 *rs, u32 *re) { u32 crop_sx, crop_ex, crop_sy, crop_ey; + int frame_width, frame_height; + struct disp_info_s *layer = &glayer_info[0]; if (!vf) return; - vpp_get_video_source_crop(&crop_sy, &crop_sx, &crop_ey, &crop_ex); + + crop_sy = layer->crop_top; + crop_sx = layer->crop_left; + crop_ey = layer->crop_bottom; + crop_ex = layer->crop_right; + + if (vf->type & VIDTYPE_COMPRESS) { + frame_width = vf->compWidth; + frame_height = vf->compHeight; + } else { + frame_width = vf->width; + frame_height = vf->height; + } switch (vpp_3d_mode) { case VPP_3D_MODE_LR: /*half width,double height */ *ls = zoom_start_x_lines; *le = zoom_end_x_lines; - *rs = *ls + (vf->width >> 1); - *re = *le + (vf->width >> 1); + *rs = *ls + (frame_width >> 1); + *re = *le + (frame_width >> 1); if (process_3d_type & MODE_3D_OUT_LR) { *ls = zoom_start_x_lines; *le = zoom_end_x_lines >> 1; - *rs = *ls + (vf->width >> 1); - *re = *le + (vf->width >> 1); + *rs = *ls + (frame_width >> 1); + *re = *le + (frame_width >> 1); } break; case VPP_3D_MODE_TB: @@ -1721,13 +1847,29 @@ static void zoom_get_vert_pos(struct vframe_s *vf, u32 vpp_3d_mode, u32 *ls, u32 *le, u32 *rs, u32 *re) { u32 crop_sx, crop_ex, crop_sy, crop_ey, height; + int frame_width, frame_height; + struct disp_info_s *layer = &glayer_info[0]; - vpp_get_video_source_crop(&crop_sy, &crop_sx, &crop_ey, &crop_ex); + if (!vf) + return; + + crop_sy = layer->crop_top; + crop_sx = layer->crop_left; + crop_ey = layer->crop_bottom; + crop_ex = layer->crop_right; + + if (vf->type & VIDTYPE_COMPRESS) { + frame_width = vf->compWidth; + frame_height = vf->compHeight; + } else { + frame_width = vf->width; + frame_height = vf->height; + } if (vf->type & VIDTYPE_INTERLACE) - height = vf->height >> 1; + height = frame_height >> 1; else - height = vf->height; + height = frame_height; switch (vpp_3d_mode) { case VPP_3D_MODE_TB: @@ -1837,7 +1979,7 @@ static void zoom_get_vert_pos(struct vframe_s *vf, u32 vpp_3d_mode, u32 *ls, } #endif -static void zoom_display_horz(int hscale) +static void zoom_display_horz(struct vframe_s *vf, int hscale) { u32 ls = 0, le = 0, rs = 0, re = 0; #ifdef TV_REVERSE @@ -1845,7 +1987,7 @@ static void zoom_display_horz(int hscale) #endif #ifdef TV_3D_FUNCTION_OPEN if (process_3d_type & MODE_3D_ENABLE) { - zoom_get_horz_pos(cur_dispbuf, cur_frame_par->vpp_3d_mode, &ls, + zoom_get_horz_pos(vf, cur_frame_par->vpp_3d_mode, &ls, &le, &rs, &re); } else { ls = rs = zoom_start_x_lines; @@ -1881,6 +2023,13 @@ static void zoom_display_horz(int hscale) int l_aligned; int r_aligned; int h_skip = cur_frame_par->hscale_skip_count + 1; + int c_skip = 2; + + /* After TL1, afbc supports 420/422/444*/ + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) + if (vf && (vf->type & VIDTYPE_VIU_444)) + c_skip = 1; + if ((zoom_start_x_lines > 0) || (zoom_end_x_lines < ori_end_x_lines)) { l_aligned = round_down(ori_start_x_lines, 32); @@ -1891,7 +2040,7 @@ static void zoom_display_horz(int hscale) } VSYNC_WR_MPEG_REG(AFBC_VD_CFMT_W, (((r_aligned - l_aligned) / h_skip) << 16) | - ((r_aligned / 2 - l_aligned / 2) / h_skip)); + ((r_aligned / c_skip - l_aligned / c_skip) / h_skip)); VSYNC_WR_MPEG_REG(AFBC_MIF_HOR_SCOPE, ((l_aligned / 32) << 16) | @@ -1906,52 +2055,62 @@ static void zoom_display_horz(int hscale) #ifdef TV_REVERSE if (reverse) { content_w = zoom_end_x_lines - zoom_start_x_lines + 1; - content_l = (r_aligned - zoom_end_x_lines - 1) + - (zoom_start_x_lines - l_aligned); + content_l = (r_aligned - zoom_end_x_lines - 1); content_r = content_l + content_w - 1; VSYNC_WR_MPEG_REG(AFBC_PIXEL_HOR_SCOPE, (((content_l << 16)) | content_r) / h_skip); } else #endif { - VSYNC_WR_MPEG_REG(AFBC_PIXEL_HOR_SCOPE, - (((zoom_start_x_lines - l_aligned) << 16) | - (zoom_end_x_lines - l_aligned)) / h_skip); + if (((process_3d_type & MODE_3D_FA) + || (process_3d_type & MODE_FORCE_3D_FA_LR)) + && (cur_frame_par->vpp_3d_mode == 1)) { + /* do nothing*/ + } else { + VSYNC_WR_MPEG_REG(AFBC_PIXEL_HOR_SCOPE, + (((zoom_start_x_lines - l_aligned) << 16) | + (zoom_end_x_lines - l_aligned)) / h_skip); + } } VSYNC_WR_MPEG_REG(AFBC_SIZE_IN, (VSYNC_RD_MPEG_REG(AFBC_SIZE_IN) & 0xffff) | ((r_aligned - l_aligned) << 16)); } - VSYNC_WR_MPEG_REG( - VD2_IF0_LUMA_X0 + cur_dev->viu_off, - (ls << VDIF_PIC_START_BIT) | - (le << VDIF_PIC_END_BIT)); +#ifdef VIDEO_PIP + if (!cur_pipbuf) +#endif + { + VSYNC_WR_MPEG_REG( + VD2_IF0_LUMA_X0 + cur_dev->viu_off, + (ls << VDIF_PIC_START_BIT) | + (le << VDIF_PIC_END_BIT)); - VSYNC_WR_MPEG_REG( - VD2_IF0_CHROMA_X0 + cur_dev->viu_off, - (ls / 2 << VDIF_PIC_START_BIT) | - (le / 2 << VDIF_PIC_END_BIT)); + VSYNC_WR_MPEG_REG( + VD2_IF0_CHROMA_X0 + cur_dev->viu_off, + (ls / 2 << VDIF_PIC_START_BIT) | + (le / 2 << VDIF_PIC_END_BIT)); - VSYNC_WR_MPEG_REG( - VD2_IF0_LUMA_X1 + cur_dev->viu_off, - (rs << VDIF_PIC_START_BIT) | - (re << VDIF_PIC_END_BIT)); + VSYNC_WR_MPEG_REG( + VD2_IF0_LUMA_X1 + cur_dev->viu_off, + (rs << VDIF_PIC_START_BIT) | + (re << VDIF_PIC_END_BIT)); - VSYNC_WR_MPEG_REG( - VD2_IF0_CHROMA_X1 + cur_dev->viu_off, - (rs / 2 << VDIF_PIC_START_BIT) | - (re / 2 << VDIF_PIC_END_BIT)); + VSYNC_WR_MPEG_REG( + VD2_IF0_CHROMA_X1 + cur_dev->viu_off, + (rs / 2 << VDIF_PIC_START_BIT) | + (re / 2 << VDIF_PIC_END_BIT)); - VSYNC_WR_MPEG_REG( - VIU_VD2_FMT_W + cur_dev->viu_off, - (((zoom_end_x_lines - zoom_start_x_lines + - 1) >> hscale) << VD1_FMT_LUMA_WIDTH_BIT) | - (((zoom_end_x_lines / 2 - zoom_start_x_lines / 2 + - 1) >> hscale) << VD1_FMT_CHROMA_WIDTH_BIT)); + VSYNC_WR_MPEG_REG( + VIU_VD2_FMT_W + cur_dev->viu_off, + (((zoom_end_x_lines - zoom_start_x_lines + + 1) >> hscale) << VD1_FMT_LUMA_WIDTH_BIT) | + (((zoom_end_x_lines / 2 - zoom_start_x_lines / 2 + + 1) >> hscale) << VD1_FMT_CHROMA_WIDTH_BIT)); + } } -static void vd2_zoom_display_horz(int hscale) +static void vd2_zoom_display_horz(struct vframe_s *vf, int hscale) { u32 ls, le, rs, re; #ifdef TV_REVERSE @@ -1963,7 +2122,13 @@ static void vd2_zoom_display_horz(int hscale) if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXBB) { int l_aligned; int r_aligned; - int h_skip = cur_frame_par->hscale_skip_count + 1; + int h_skip = hscale + 1; + int c_skip = 2; + + /* After TL1, afbc supports 420/422/444*/ + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) + if (vf && (vf->type & VIDTYPE_VIU_444)) + c_skip = 1; if ((zoom2_start_x_lines > 0) || (zoom2_end_x_lines < ori2_end_x_lines)) { @@ -1975,7 +2140,7 @@ static void vd2_zoom_display_horz(int hscale) } VSYNC_WR_MPEG_REG(VD2_AFBC_VD_CFMT_W, (((r_aligned - l_aligned) / h_skip) << 16) | - ((r_aligned / 2 - l_aligned / 2) / h_skip)); + ((r_aligned / c_skip - l_aligned / c_skip) / h_skip)); VSYNC_WR_MPEG_REG(VD2_AFBC_MIF_HOR_SCOPE, ((l_aligned / 32) << 16) | @@ -2034,33 +2199,21 @@ static void vd2_zoom_display_horz(int hscale) << VD1_FMT_CHROMA_WIDTH_BIT)); } -static void zoom_display_vert(void) +static void zoom_display_vert(struct vframe_s *vf) { - u32 ls, le, rs, re; + u32 ls = 0, le = 0, rs = 0, re = 0; - /*if (platform_type == 1) {*/ - if (process_3d_type & MODE_3D_ENABLE) { - zoom_get_vert_pos(cur_dispbuf, - cur_frame_par->vpp_3d_mode, &ls, - &le, &rs, &re); - } else { - ls = rs = zoom_start_y_lines; - le = re = zoom_end_y_lines; - } - /*} else { - if (process_3d_type & MODE_3D_ENABLE) { - zoom_get_vert_pos(cur_dispbuf, - cur_frame_par->vpp_3d_mode, &ls, - &le, &rs, &re); - } else { - ls = rs = zoom_start_y_lines; - le = re = zoom_end_y_lines; - } + if (process_3d_type & MODE_3D_ENABLE) { + zoom_get_vert_pos(vf, + cur_frame_par->vpp_3d_mode, &ls, + &le, &rs, &re); + } else { + ls = rs = zoom_start_y_lines; + le = re = zoom_end_y_lines; } -*/ - if ((cur_dispbuf) && (cur_dispbuf->type & VIDTYPE_MVC)) { + if ((vf) && (vf->type & VIDTYPE_MVC)) { if (is_need_framepacking_output()) { VSYNC_WR_MPEG_REG( VD1_IF0_LUMA_Y0 + cur_dev->viu_off, @@ -2122,8 +2275,11 @@ static void zoom_display_vert(void) VD1_IF0_CHROMA_Y1 + cur_dev->viu_off, ((rs / 2) << VDIF_PIC_START_BIT) | ((re / 2) << VDIF_PIC_END_BIT)); - if (platform_type == 1) { - /* vd2 */ + +#ifdef VIDEO_PIP + if (!cur_pipbuf) +#endif + { VSYNC_WR_MPEG_REG( VD2_IF0_LUMA_Y0 + cur_dev->viu_off, (ls << VDIF_PIC_START_BIT) | @@ -2152,18 +2308,43 @@ static void zoom_display_vert(void) int ori_t_aligned; int ori_b_aligned; int v_skip = cur_frame_par->vscale_skip_count + 1; + int c_skip = 2; + + /* After TL1, afbc supports 420/422/444*/ + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) + if (vf && ((vf->type & VIDTYPE_VIU_444) + || (vf->type & VIDTYPE_VIU_422))) + c_skip = 1; + t_aligned = round_down(zoom_start_y_lines, 4); b_aligned = round_up(zoom_end_y_lines + 1, 4); ori_t_aligned = round_down(ori_start_y_lines, 4); ori_b_aligned = round_up(ori_end_y_lines + 1, 4); VSYNC_WR_MPEG_REG(AFBC_VD_CFMT_H, - (b_aligned - t_aligned) / 2 / v_skip); + (b_aligned - t_aligned) / c_skip / v_skip); - VSYNC_WR_MPEG_REG(AFBC_MIF_VER_SCOPE, - ((t_aligned / 4) << 16) | - ((b_aligned / 4) - 1)); + if (((process_3d_type & MODE_3D_FA) + || (process_3d_type & MODE_FORCE_3D_FA_TB)) + && (cur_frame_par->vpp_3d_mode == 2)) { + int block_h; + block_h = ori_b_aligned - ori_t_aligned; + block_h = block_h / 8; + if (toggle_3d_fa_frame == OUT_FA_B_FRAME) { + VSYNC_WR_MPEG_REG(AFBC_MIF_VER_SCOPE, + (((ori_t_aligned / 4) + block_h) << 16) | + ((ori_b_aligned / 4) - 1)); + } else { + VSYNC_WR_MPEG_REG(AFBC_MIF_VER_SCOPE, + ((ori_t_aligned / 4) << 16) | + ((ori_t_aligned / 4) + block_h - 1)); + } + } else { + VSYNC_WR_MPEG_REG(AFBC_MIF_VER_SCOPE, + ((t_aligned / 4) << 16) | + ((b_aligned / 4) - 1)); + } VSYNC_WR_MPEG_REG(AFBC_PIXEL_VER_SCOPE, ((zoom_start_y_lines - t_aligned) << 16) | (zoom_end_y_lines - t_aligned)); @@ -2186,7 +2367,7 @@ static void zoom_display_vert(void) } } -static void vd2_zoom_display_vert(void) +static void vd2_zoom_display_vert(struct vframe_s *vf, int vscale) { u32 ls, le, rs, re; @@ -2220,7 +2401,15 @@ static void vd2_zoom_display_vert(void) int b_aligned; int ori_t_aligned; int ori_b_aligned; - int v_skip = cur_frame_par->vscale_skip_count + 1; + int v_skip = vscale + 1; + int c_skip = 2; + + /* After TL1, afbc supports 420/422/444*/ + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) + if (vf && ((vf->type & VIDTYPE_VIU_444) + || (vf->type & VIDTYPE_VIU_422))) + c_skip = 1; + t_aligned = round_down(zoom2_start_y_lines, 4); b_aligned = round_up(zoom2_end_y_lines + 1, 4); @@ -2229,7 +2418,7 @@ static void vd2_zoom_display_vert(void) /* TODO: afbc setting only support 420 for now */ VSYNC_WR_MPEG_REG(VD2_AFBC_VD_CFMT_H, - (b_aligned - t_aligned) / 2 / v_skip); + (b_aligned - t_aligned) / c_skip / v_skip); VSYNC_WR_MPEG_REG(VD2_AFBC_MIF_VER_SCOPE, ((t_aligned / 4) << 16) | @@ -2418,609 +2607,6 @@ static void vsync_video_pattern(void) } #endif -/* for sdr/hdr/single dv switch with dual dv */ -static u32 last_el_status; -/* for dual dv switch with different el size */ -static u32 last_el_w; -bool has_enhanced_layer(struct vframe_s *vf) -{ - struct provider_aux_req_s req; - - if (!vf) - return 0; - if (vf->source_type != VFRAME_SOURCE_TYPE_OTHERS) - return 0; - if (!is_dolby_vision_on()) - return 0; - - req.vf = vf; - req.bot_flag = 0; - req.aux_buf = NULL; - req.aux_size = 0; - req.dv_enhance_exist = 0; - vf_notify_provider_by_name("dvbldec", - VFRAME_EVENT_RECEIVER_GET_AUX_DATA, - (void *)&req); - return req.dv_enhance_exist; -} -u32 property_changed_true; - -static u64 func_div(u64 number, u32 divid) -{ - u64 tmp = number; - - do_div(tmp, divid); - return tmp; -} - -static void vsync_toggle_frame(struct vframe_s *vf) -{ - u32 first_picture = 0; - unsigned long flags = 0; - bool vf_with_el = false; - bool force_toggle = false; - long long *clk_array; - - if (vf == NULL) - return; - frame_count++; - toggle_count++; - - if (is_dolby_vision_enable()) - vf_with_el = has_enhanced_layer(vf); - -#ifdef PTS_TRACE_DEBUG -#ifdef PTS_TRACE_START - if (pts_trace_his_rd < 16) { -#endif - pts_trace_his[pts_trace_his_rd] = pts_trace; - pts_his[pts_trace_his_rd] = vf->pts; - scr_his[pts_trace_his_rd] = timestamp_pcrscr_get(); - pts_trace_his_rd++; - if (pts_trace_his_rd >= 16) - pts_trace_his_rd = 0; -#ifdef PTS_TRACE_START - } -#endif -#endif - -#ifdef PTS_LOGGING - if (pts_escape_vsync == 1) { - pts_trace++; - pts_escape_vsync = 0; - } - vsync_video_pattern(); - pre_pts_trace = pts_trace; -#endif - -#if defined(PTS_LOGGING) || defined(PTS_TRACE_DEBUG) - pts_trace = 0; -#endif - - ori_start_x_lines = 0; - ori_end_x_lines = ((vf->type & VIDTYPE_COMPRESS) ? - vf->compWidth : vf->width) - 1; - ori_start_y_lines = 0; - ori_end_y_lines = ((vf->type & VIDTYPE_COMPRESS) ? - vf->compHeight : vf->height) - 1; - if (debug_flag & DEBUG_FLAG_PRINT_TOGGLE_FRAME) { - u32 pcr = timestamp_pcrscr_get(); - u32 vpts = timestamp_vpts_get(); - u32 apts = timestamp_apts_get(); - - pr_info("%s pts:%d.%06d pcr:%d.%06d vpts:%d.%06d apts:%d.%06d\n", - __func__, (vf->pts) / 90000, - ((vf->pts) % 90000) * 1000 / 90, (pcr) / 90000, - ((pcr) % 90000) * 1000 / 90, (vpts) / 90000, - ((vpts) % 90000) * 1000 / 90, (apts) / 90000, - ((apts) % 90000) * 1000 / 90); - } - - if (trickmode_i || trickmode_fffb) - trickmode_duration_count = trickmode_duration; - - if (vf->early_process_fun) { - if (vf->early_process_fun(vf->private_data, vf) == 1) { - /* video_property_changed = true; */ - first_picture = 1; - } - } else { -#ifdef CONFIG_AMLOGIC_MEDIA_DEINTERLACE - if ((DI_POST_REG_RD(DI_IF1_GEN_REG) & 0x1) != 0) { - /* check mif enable status, disable post di */ - VSYNC_WR_MPEG_REG(DI_POST_CTRL, 0x3 << 30); - VSYNC_WR_MPEG_REG(DI_POST_SIZE, - (32 - 1) | ((128 - 1) << 16)); - VSYNC_WR_MPEG_REG(DI_IF1_GEN_REG, - READ_VCBUS_REG(DI_IF1_GEN_REG) & - 0xfffffffe); - } -#endif - } - - timer_count = 0; - if ((vf->width == 0) && (vf->height == 0)) { - amlog_level(LOG_LEVEL_ERROR, - "Video: invalid frame dimension\n"); - return; - } - - if (hold_video) { - if ((cur_dispbuf != vf) - && (vf->source_type != VFRAME_SOURCE_TYPE_OSD)) { - new_frame_count++; - if (vf->pts != 0) { - amlog_mask(LOG_MASK_TIMESTAMP, - "vpts to: 0x%x, scr: 0x%x, abs_scr: 0x%x\n", - vf->pts, timestamp_pcrscr_get(), - READ_MPEG_REG(SCR_HIU)); - - timestamp_vpts_set(vf->pts); - last_frame_duration = vf->duration; - } else if (last_frame_duration) { - amlog_mask(LOG_MASK_TIMESTAMP, - "vpts inc: 0x%x, scr: 0x%x, abs_scr: 0x%x\n", - timestamp_vpts_get() + - DUR2PTS(cur_dispbuf->duration), - timestamp_pcrscr_get(), - READ_MPEG_REG(SCR_HIU)); - - timestamp_vpts_inc(DUR2PTS - (last_frame_duration)); - - vpts_remainder += - DUR2PTS_RM(last_frame_duration); - if (vpts_remainder >= 0xf) { - vpts_remainder -= 0xf; - timestamp_vpts_inc(-1); - } - } - video_vf_put(vf); - return; - } - } - - if ((cur_dispbuf) && (cur_dispbuf != &vf_local) && (cur_dispbuf != vf) - && (video_property_changed != 2)) { - if (cur_dispbuf->source_type == VFRAME_SOURCE_TYPE_OSD) { - if (osd_prov && osd_prov->ops && osd_prov->ops->put) { - osd_prov->ops->put(cur_dispbuf, - osd_prov->op_arg); - if (debug_flag & DEBUG_FLAG_BLACKOUT) { - pr_info( - "[v4o]pre vf is osd,put it\n"); - } - } - first_picture = 1; - if (debug_flag & DEBUG_FLAG_BLACKOUT) { - pr_info( - "[v4o] pre vf is osd, clear it to NULL\n"); - } - } else { - new_frame_count++; - if (new_frame_count == 1) - first_picture = 1; -#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA - if (is_vsync_rdma_enable()) { -#ifdef RDMA_RECYCLE_ORDERED_VFRAMES - if (dispbuf_to_put_num < DISPBUF_TO_PUT_MAX) { - dispbuf_to_put[dispbuf_to_put_num] = - cur_dispbuf; - dispbuf_to_put_num++; - } else - video_vf_put(cur_dispbuf); -#else - if (cur_rdma_buf == cur_dispbuf) { - dispbuf_to_put[0] = cur_dispbuf; - dispbuf_to_put_num = 1; - } else - video_vf_put(cur_dispbuf); -#endif - } else { - int i; - - for (i = 0; i < dispbuf_to_put_num; i++) { - if (dispbuf_to_put[i]) { - video_vf_put( - dispbuf_to_put[i]); - dispbuf_to_put[i] = NULL; - } - dispbuf_to_put_num = 0; - } - video_vf_put(cur_dispbuf); - } -#else - video_vf_put(cur_dispbuf); -#endif - if (debug_flag & DEBUG_FLAG_LATENCY) { - vf->ready_clock[3] = sched_clock(); - pr_info("video toggle latency %lld ms," - "video get latency %lld ms," - "vdin put latency %lld ms," - "first %lld ms.\n", - func_div(vf->ready_clock[3], 1000), - func_div(vf->ready_clock[2], 1000), - func_div(vf->ready_clock[1], 1000), - func_div(vf->ready_clock[0], 1000)); - cur_dispbuf->ready_clock[4] = sched_clock(); - clk_array = cur_dispbuf->ready_clock; - pr_info("video put latency %lld ms," - "video toggle latency %lld ms," - "video get latency %lld ms," - "vdin put latency %lld ms," - "first %lld ms.\n", - func_div(*(clk_array + 4), 1000), - func_div(*(clk_array + 3), 1000), - func_div(*(clk_array + 2), 1000), - func_div(*(clk_array + 1), 1000), - func_div(*clk_array, 1000)); - } - } - - } else - first_picture = 1; - - if (video_property_changed) { - property_changed_true = 2; - video_property_changed = false; - first_picture = 1; - } - if (property_changed_true > 0) { - property_changed_true--; - first_picture = 1; - } - - if (debug_flag & DEBUG_FLAG_BLACKOUT) { - if (first_picture) { - pr_info - ("[video4osd] first %s picture {%d,%d} pts:%x,\n", - (vf->source_type == - VFRAME_SOURCE_TYPE_OSD) ? "OSD" : "", vf->width, - vf->height, vf->pts); - } - } - /* switch buffer */ - post_canvas = vf->canvas0Addr; - if ((get_cpu_type() >= MESON_CPU_MAJOR_ID_GXBB) && - (vf->type & VIDTYPE_COMPRESS)) { - VSYNC_WR_MPEG_REG(AFBC_HEAD_BADDR, vf->compHeadAddr>>4); - VSYNC_WR_MPEG_REG(AFBC_BODY_BADDR, vf->compBodyAddr>>4); - } - if ((vf->canvas0Addr != 0) -#ifdef CONFIG_AMLOGIC_MEDIA_DEINTERLACE - && ((DI_POST_REG_RD(DI_POST_CTRL) & 0x1000) == 0) - /* check di_post_viu_link */ -#endif - ) { - -#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA - if (vf->canvas0Addr != (u32)-1) { - canvas_copy(vf->canvas0Addr & 0xff, - disp_canvas_index[rdma_canvas_id][0]); - canvas_copy((vf->canvas0Addr >> 8) & 0xff, - disp_canvas_index[rdma_canvas_id][1]); - canvas_copy((vf->canvas0Addr >> 16) & 0xff, - disp_canvas_index[rdma_canvas_id][2]); - } else { - vframe_canvas_set(&vf->canvas0_config[0], - vf->plane_num, - &disp_canvas_index[rdma_canvas_id][0]); - } - if (!vf_with_el) { - if (vf->canvas1Addr != (u32)-1) { - canvas_copy(vf->canvas1Addr & 0xff, - disp_canvas_index[rdma_canvas_id][3]); - canvas_copy((vf->canvas1Addr >> 8) & 0xff, - disp_canvas_index[rdma_canvas_id][4]); - canvas_copy((vf->canvas1Addr >> 16) & 0xff, - disp_canvas_index[rdma_canvas_id][5]); - } else { - vframe_canvas_set(&vf->canvas1_config[0], - vf->plane_num, - &disp_canvas_index[rdma_canvas_id][3]); - } - } - - VSYNC_WR_MPEG_REG( - VD1_IF0_CANVAS0 + cur_dev->viu_off, - disp_canvas[rdma_canvas_id][0]); - if (platform_type == 0) { - VSYNC_WR_MPEG_REG(VD1_IF0_CANVAS1 + cur_dev->viu_off, - disp_canvas[rdma_canvas_id][0]); - if (!vf_with_el) { - VSYNC_WR_MPEG_REG( - VD2_IF0_CANVAS0 + cur_dev->viu_off, - disp_canvas[rdma_canvas_id][1]); - VSYNC_WR_MPEG_REG( - VD2_IF0_CANVAS1 + cur_dev->viu_off, - disp_canvas[rdma_canvas_id][1]); - } - } else { - if (!vf_with_el) - VSYNC_WR_MPEG_REG( - VD2_IF0_CANVAS0 + cur_dev->viu_off, - disp_canvas[rdma_canvas_id][1]); - if (cur_frame_par && - (cur_frame_par->vpp_2pic_mode == 1)) { - VSYNC_WR_MPEG_REG(VD1_IF0_CANVAS1 + - cur_dev->viu_off, - disp_canvas[rdma_canvas_id][0]); - if (!vf_with_el) - VSYNC_WR_MPEG_REG(VD2_IF0_CANVAS1 + - cur_dev->viu_off, - disp_canvas[rdma_canvas_id][0]); - } else { - VSYNC_WR_MPEG_REG(VD1_IF0_CANVAS1 + - cur_dev->viu_off, - disp_canvas[rdma_canvas_id][1]); - if (!vf_with_el) - VSYNC_WR_MPEG_REG(VD2_IF0_CANVAS1 + - cur_dev->viu_off, - disp_canvas[rdma_canvas_id][0]); - } - } - if (cur_frame_par - && (process_3d_type & MODE_3D_ENABLE) - && (process_3d_type & MODE_3D_TO_2D_R) - && (cur_frame_par->vpp_2pic_mode == VPP_SELECT_PIC1) - && !vf_with_el) { - VSYNC_WR_MPEG_REG(VD1_IF0_CANVAS0 + cur_dev->viu_off, - disp_canvas[rdma_canvas_id][1]); - VSYNC_WR_MPEG_REG(VD1_IF0_CANVAS1 + cur_dev->viu_off, - disp_canvas[rdma_canvas_id][1]); - VSYNC_WR_MPEG_REG(VD2_IF0_CANVAS0 + cur_dev->viu_off, - disp_canvas[rdma_canvas_id][1]); - VSYNC_WR_MPEG_REG(VD2_IF0_CANVAS1 + cur_dev->viu_off, - disp_canvas[rdma_canvas_id][1]); - } - /* VSYNC_WR_MPEG_REG(VD2_IF0_CANVAS1,*/ - /*disp_canvas[rdma_canvas_id][1]); */ - next_rdma_canvas_id = rdma_canvas_id ? 0 : 1; -#else - canvas_copy(vf->canvas0Addr & 0xff, disp_canvas_index[0]); - canvas_copy((vf->canvas0Addr >> 8) & 0xff, - disp_canvas_index[1]); - canvas_copy((vf->canvas0Addr >> 16) & 0xff, - disp_canvas_index[2]); - canvas_copy(vf->canvas1Addr & 0xff, disp_canvas_index[3]); - canvas_copy((vf->canvas1Addr >> 8) & 0xff, - disp_canvas_index[4]); - canvas_copy((vf->canvas1Addr >> 16) & 0xff, - disp_canvas_index[5]); - if (platform_type == 0) { - VSYNC_WR_MPEG_REG( - VD1_IF0_CANVAS0 + cur_dev->viu_off, - disp_canvas[0]); - VSYNC_WR_MPEG_REG( - VD1_IF0_CANVAS1 + cur_dev->viu_off, - disp_canvas[0]); - if (!vf_with_el) { - VSYNC_WR_MPEG_REG( - VD2_IF0_CANVAS0 + cur_dev->viu_off, - disp_canvas[1]); - VSYNC_WR_MPEG_REG( - VD2_IF0_CANVAS1 + cur_dev->viu_off, - disp_canvas[1]); - } - } else { - VSYNC_WR_MPEG_REG(VD1_IF0_CANVAS0 + cur_dev->viu_off, - disp_canvas[0]); - if (!vf_with_el) - VSYNC_WR_MPEG_REG( - VD2_IF0_CANVAS0 + cur_dev->viu_off, - disp_canvas[0]); - if (cur_frame_par && - (cur_frame_par->vpp_2pic_mode == 1)) { - VSYNC_WR_MPEG_REG(VD1_IF0_CANVAS1 + - cur_dev->viu_off, - disp_canvas[0]); - if (!vf_with_el) - VSYNC_WR_MPEG_REG(VD2_IF0_CANVAS1 + - cur_dev->viu_off, - disp_canvas[0]); - } else { - VSYNC_WR_MPEG_REG(VD1_IF0_CANVAS1 + - cur_dev->viu_off, - disp_canvas[1]); - if (!vf_with_el) - VSYNC_WR_MPEG_REG(VD2_IF0_CANVAS1 + - cur_dev->viu_off, - disp_canvas[1]); - } - /* VSYNC_WR_MPEG_REG(VD2_IF0_CANVAS0 +*/ - /*cur_dev->viu_off, disp_canvas[0]); */ - /* VSYNC_WR_MPEG_REG(VD2_IF0_CANVAS1 +*/ - /*cur_dev->viu_off, disp_canvas[1]); */ - } -#endif - } - /* set video PTS */ - if (cur_dispbuf != vf) { - if (vf->source_type != VFRAME_SOURCE_TYPE_OSD) { - if (vf->pts != 0) { - amlog_mask(LOG_MASK_TIMESTAMP, - "vpts to: 0x%x, scr: 0x%x, abs_scr: 0x%x\n", - vf->pts, timestamp_pcrscr_get(), - READ_MPEG_REG(SCR_HIU)); - - timestamp_vpts_set(vf->pts); - } else if (cur_dispbuf) { - amlog_mask(LOG_MASK_TIMESTAMP, - "vpts inc: 0x%x, scr: 0x%x, abs_scr: 0x%x\n", - timestamp_vpts_get() + - DUR2PTS(cur_dispbuf->duration), - timestamp_pcrscr_get(), - READ_MPEG_REG(SCR_HIU)); - - timestamp_vpts_inc(DUR2PTS - (cur_dispbuf->duration)); - - vpts_remainder += - DUR2PTS_RM(cur_dispbuf->duration); - if (vpts_remainder >= 0xf) { - vpts_remainder -= 0xf; - timestamp_vpts_inc(-1); - } - } - } else { - first_picture = 1; - if (debug_flag & DEBUG_FLAG_BLACKOUT) { - pr_info( - "[v4o] cur vframe is osd, do not set PTS\n"); - } - } - vf->type_backup = vf->type; - } - - if (cur_dispbuf && vf && - (cur_dispbuf->ratio_control & - DISP_RATIO_ADAPTED_PICMODE) && - (cur_dispbuf->ratio_control == - vf->ratio_control) && - memcmp(&cur_dispbuf->pic_mode, &vf->pic_mode, - sizeof(struct vframe_pic_mode_s))) - force_toggle = true; - - if ((last_process_3d_type != process_3d_type) - || (last_el_status != vf_with_el)) - force_toggle = true; - - /* enable new config on the new frames */ - if (first_picture || force_toggle || - (cur_dispbuf && - ((cur_dispbuf->bufWidth != vf->bufWidth) || - (cur_dispbuf->width != vf->width) || - (cur_dispbuf->height != vf->height) || - (cur_dispbuf->bitdepth != vf->bitdepth) || - (cur_dispbuf->trans_fmt != vf->trans_fmt) || - (cur_dispbuf->ratio_control != vf->ratio_control) || - ((cur_dispbuf->type_backup & VIDTYPE_INTERLACE) != - (vf->type_backup & VIDTYPE_INTERLACE)) || - (cur_dispbuf->type != vf->type)))) { - last_process_3d_type = process_3d_type; - atomic_inc(&video_sizechange); - wake_up_interruptible(&amvideo_sizechange_wait); - amlog_mask(LOG_MASK_FRAMEINFO, - "%s %dx%d ar=0x%x\n", - ((vf->type & VIDTYPE_TYPEMASK) == - VIDTYPE_INTERLACE_TOP) ? "interlace-top" - : ((vf->type & VIDTYPE_TYPEMASK) - == VIDTYPE_INTERLACE_BOTTOM) - ? "interlace-bottom" : "progressive", vf->width, - vf->height, vf->ratio_control); -#ifdef TV_3D_FUNCTION_OPEN - amlog_mask(LOG_MASK_FRAMEINFO, - "%s trans_fmt=%u\n", __func__, vf->trans_fmt); - -#endif - next_frame_par = (&frame_parms[0] == next_frame_par) ? - &frame_parms[1] : &frame_parms[0]; - - vpp_set_filters(process_3d_type, wide_setting, vf, - next_frame_par, vinfo, - (is_dolby_vision_on() && - is_dolby_vision_stb_mode())); - - /* apply new vpp settings */ - frame_par_ready_to_set = 1; - - /* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */ - if ((get_cpu_type() >= MESON_CPU_MAJOR_ID_M8) - && !is_meson_mtvd_cpu()) { - if (((vf->width > 1920) && (vf->height > 1088)) || - ((vf->type & VIDTYPE_COMPRESS) && - (vf->compWidth > 1920) && - (vf->compHeight > 1080))) { - if (vpu_clk_level == 0) { - vpu_clk_level = 1; - - spin_lock_irqsave(&lock, flags); - vpu_delay_work_flag |= - VPU_DELAYWORK_VPU_CLK; - spin_unlock_irqrestore(&lock, flags); - } - } else { - if (vpu_clk_level == 1) { - vpu_clk_level = 0; - - spin_lock_irqsave(&lock, flags); - vpu_delay_work_flag |= - VPU_DELAYWORK_VPU_CLK; - spin_unlock_irqrestore(&lock, flags); - } - } - } - /* #endif */ - - } - last_el_status = vf_with_el; - - if (((vf->type & VIDTYPE_NO_VIDEO_ENABLE) == 0) && - ((!property_changed_true) || (vf != cur_dispbuf))) { - if (disable_video == VIDEO_DISABLE_FORNEXT) { - EnableVideoLayer(); - disable_video = VIDEO_DISABLE_NONE; - } - if (first_picture && (disable_video != VIDEO_DISABLE_NORMAL)) { - EnableVideoLayer(); - - if ((vf->type & VIDTYPE_MVC) || - (cur_dispbuf2 && (cur_dispbuf2->type & VIDTYPE_VD2))) - EnableVideoLayer2(); - else if (cur_dispbuf2 && - !(cur_dispbuf2->type & VIDTYPE_COMPRESS)) - VD2_MEM_POWER_ON(); - else if (vf_with_el) - EnableVideoLayer2(); - else if (need_disable_vd2) - DisableVideoLayer2(); - } - } - if (cur_dispbuf && (cur_dispbuf->type != vf->type)) { - if ((vf->type & VIDTYPE_MVC) || - (cur_dispbuf2 && (cur_dispbuf2->type & VIDTYPE_VD2))) - EnableVideoLayer2(); - else { - if (cur_dispbuf2 && - !(cur_dispbuf2->type & VIDTYPE_COMPRESS)) - VD2_MEM_POWER_ON(); - else if (vf_with_el) - EnableVideoLayer2(); - else if (need_disable_vd2) - DisableVideoLayer2(); - } - } - cur_dispbuf = vf; - if (first_picture) { - frame_par_ready_to_set = 1; - first_frame_toggled = 1; - -#ifdef VIDEO_PTS_CHASE - av_sync_flag = 0; -#endif - } - if (cur_dispbuf != &vf_local) - video_keeper_new_frame_notify(); - - if ((vf != &vf_local) && (vf) && !vsync_pts_aligned) { -#ifdef PTS_TRACE_DEBUG - pr_info("####timestamp_pcrscr_get() = 0x%x, vf->pts = 0x%x, vsync_pts_inc = %d\n", - timestamp_pcrscr_get(), vf->pts, vsync_pts_inc); -#endif - if ((abs(timestamp_pcrscr_get() - vf->pts) <= (vsync_pts_inc)) - && ((int)(timestamp_pcrscr_get() - vf->pts) >= 0)) { - /*vsync_pts_align = vsync_pts_inc / 4 - */ - /* (timestamp_pcrscr_get() - vf->pts);*/ - vsync_pts_align = 0; - vsync_pts_aligned = true; -#ifdef PTS_TRACE_DEBUG - pts_trace_his_rd = 0; - pr_info("####vsync_pts_align set to %d\n", - vsync_pts_align); -#endif - } - } -} static inline void vd1_path_select(bool afbc) { u32 misc_off = cur_dev->vpp_off; @@ -3124,6 +2710,1467 @@ static inline void vd2_path_select(bool afbc) } } +#ifdef VIDEO_PIP +s32 config_vd_pps( + u8 layer_id, + struct vpp_frame_par_s *cur_frame_par, + struct scaler_setting_s *setting, + const struct vinfo_s *info) +{ + struct vppfilter_mode_s *vpp_filter; + + if (!cur_frame_par || !info || !setting) + return -1; + + vpp_filter = &cur_frame_par->vpp_filter; + setting->frame_par = cur_frame_par; + setting->id = layer_id; + setting->misc_reg_offt = 0; + /* enable pps as default */ + setting->sc_top_enable = true; + setting->sc_h_enable = true; + setting->sc_v_enable = true; + + if ((vpp_filter->vpp_hsc_start_phase_step == 0x1000000) + && (vpp_filter->vpp_vsc_start_phase_step == 0x1000000) + && (vpp_filter->vpp_hsc_start_phase_step == + vpp_filter->vpp_hf_start_phase_step) + && !vpp_filter->vpp_pre_vsc_en + && !vpp_filter->vpp_pre_hsc_en + && !cur_frame_par->supsc0_enable + && !cur_frame_par->supsc1_enable + && bypass_pps) + setting->sc_top_enable = false; + + /* old chip: vd2 has no pps */ + if ((legacy_vpp || is_meson_tl1_cpu()) + && (setting->id != 0)) + setting->sc_top_enable = false; + + setting->vinfo_width = info->width; + setting->vinfo_height = info->height; + return 0; +} + +static inline void vd2_scaler_setting( + struct scaler_setting_s *setting) +{ + u32 misc_off, i; + u32 r1, r2, r3; + struct vpp_frame_par_s *frame_par; + struct vppfilter_mode_s *vpp_filter; + + if (legacy_vpp || !setting + || !setting->frame_par + || is_meson_tl1_cpu()) + return; + + frame_par = setting->frame_par; + misc_off = setting->misc_reg_offt; + vpp_filter = &frame_par->vpp_filter; + + if (setting->sc_top_enable) { + u32 sc_misc_val; + + sc_misc_val = VPP_SC_TOP_EN | VPP_SC_V1OUT_EN; + if (setting->sc_h_enable) { + sc_misc_val |= (((vpp_filter->vpp_pre_hsc_en & 1) + << VPP_SC_PREHORZ_EN_BIT) + | VPP_SC_HORZ_EN); + sc_misc_val |= ((vpp_filter->vpp_horz_coeff[0] & 7) + << VPP_SC_HBANK_LENGTH_BIT); + } + + if (setting->sc_v_enable) { + sc_misc_val |= (((vpp_filter->vpp_pre_vsc_en & 1) + << VPP_SC_PREVERT_EN_BIT) + | VPP_SC_VERT_EN); + sc_misc_val |= ((vpp_filter->vpp_pre_vsc_en & 1) + << VPP_LINE_BUFFER_EN_BIT); + sc_misc_val |= ((vpp_filter->vpp_vert_coeff[0] & 7) + << VPP_SC_VBANK_LENGTH_BIT); + } + VSYNC_WR_MPEG_REG( + VD2_SC_MISC + misc_off, + sc_misc_val); + } else { + setting->sc_v_enable = false; + setting->sc_h_enable = false; + VSYNC_WR_MPEG_REG_BITS( + VD2_SC_MISC + misc_off, + 0, VPP_SC_TOP_EN_BIT, + VPP_SC_TOP_EN_WID); + } + + /* horitontal filter settings */ + if (setting->sc_h_enable) { + if (vpp_filter->vpp_horz_coeff[1] & 0x8000) { + VSYNC_WR_MPEG_REG( + VD2_SCALE_COEF_IDX + misc_off, + VPP_COEF_HORZ | VPP_COEF_9BIT); + } else { + VSYNC_WR_MPEG_REG( + VD2_SCALE_COEF_IDX + misc_off, + VPP_COEF_HORZ); + } + for (i = 0; i < + (vpp_filter->vpp_horz_coeff[1] & 0xff); i++) { + VSYNC_WR_MPEG_REG( + VD2_SCALE_COEF + misc_off, + vpp_filter->vpp_horz_coeff[i + 2]); + } + r1 = frame_par->VPP_hsc_linear_startp + - frame_par->VPP_hsc_startp; + r2 = frame_par->VPP_hsc_linear_endp + - frame_par->VPP_hsc_startp; + r3 = frame_par->VPP_hsc_endp + - frame_par->VPP_hsc_startp; + + VSYNC_WR_MPEG_REG_BITS( + VD2_HSC_PHASE_CTRL + misc_off, + frame_par->VPP_hf_ini_phase_, + VPP_HSC_TOP_INI_PHASE_BIT, + VPP_HSC_TOP_INI_PHASE_WID); + + VSYNC_WR_MPEG_REG( + VD2_HSC_REGION12_STARTP + misc_off, + (0 << VPP_REGION1_BIT) | + ((r1 & VPP_REGION_MASK) + << VPP_REGION2_BIT)); + VSYNC_WR_MPEG_REG( + VD2_HSC_REGION34_STARTP + misc_off, + ((r2 & VPP_REGION_MASK) + << VPP_REGION3_BIT) | + ((r3 & VPP_REGION_MASK) + << VPP_REGION4_BIT)); + VSYNC_WR_MPEG_REG( + VD2_HSC_REGION4_ENDP + misc_off, r3); + + VSYNC_WR_MPEG_REG( + VD2_HSC_START_PHASE_STEP + misc_off, + vpp_filter->vpp_hf_start_phase_step); + + VSYNC_WR_MPEG_REG( + VD2_HSC_REGION1_PHASE_SLOPE + misc_off, + vpp_filter->vpp_hf_start_phase_slope); + + VSYNC_WR_MPEG_REG( + VD2_HSC_REGION3_PHASE_SLOPE + misc_off, + vpp_filter->vpp_hf_end_phase_slope); + } + + /* vertical filter settings */ + if (setting->sc_v_enable) { + VSYNC_WR_MPEG_REG_BITS( + VD2_VSC_PHASE_CTRL + misc_off, + (vpp_filter->vpp_vert_coeff[0] == 2) ? 1 : 0, + VPP_PHASECTL_DOUBLELINE_BIT, + VPP_PHASECTL_DOUBLELINE_WID); + VSYNC_WR_MPEG_REG( + VD2_SCALE_COEF_IDX + misc_off, + VPP_COEF_VERT); + for (i = 0; i < vpp_filter->vpp_vert_coeff[1]; i++) { + VSYNC_WR_MPEG_REG( + VD2_SCALE_COEF + misc_off, + vpp_filter->vpp_vert_coeff[i + 2]); + } + + /* vertical chroma filter settings */ + if (vpp_filter->vpp_vert_chroma_filter_en) { + const u32 *pCoeff = + vpp_filter->vpp_vert_chroma_coeff; + VSYNC_WR_MPEG_REG( + VD2_SCALE_COEF_IDX + misc_off, + VPP_COEF_VERT_CHROMA + |VPP_COEF_SEP_EN); + for (i = 0; i < pCoeff[1]; i++) + VSYNC_WR_MPEG_REG( + VD2_SCALE_COEF + misc_off, + pCoeff[i + 2]); + } + + r1 = frame_par->VPP_vsc_endp + - frame_par->VPP_vsc_startp; + VSYNC_WR_MPEG_REG( + VD2_VSC_REGION12_STARTP + misc_off, 0); + + VSYNC_WR_MPEG_REG( + VD2_VSC_REGION34_STARTP + misc_off, + ((r1 & VPP_REGION_MASK) + << VPP_REGION3_BIT) | + ((r1 & VPP_REGION_MASK) + << VPP_REGION4_BIT)); + + VSYNC_WR_MPEG_REG( + VD2_VSC_REGION4_ENDP + misc_off, r1); + + VSYNC_WR_MPEG_REG( + VD2_VSC_START_PHASE_STEP + misc_off, + vpp_filter->vpp_vsc_start_phase_step); + } + + VSYNC_WR_MPEG_REG( + VPP_VD2_HDR_IN_SIZE + misc_off, + (frame_par->VPP_pic_in_height_ << 16) + | frame_par->VPP_line_in_length_); +} + +s32 config_vd_blend( + u8 layer_id, + struct vpp_frame_par_s *cur_frame_par, + struct vframe_s *vf, + u32 layer_alpha, + struct blend_setting_s *setting) +{ + /* u32 type = 0; */ + u32 vskip, hskip; + + if (!cur_frame_par || !setting || !vf) + return -1; + + setting->frame_par = cur_frame_par; + setting->id = layer_id; + setting->misc_reg_offt = 0; + + setting->layer_alpha = layer_alpha; + setting->preblend_h_start = 0; + setting->preblend_h_end = 4096; + if ((cur_frame_par->VPP_post_blend_vd_v_end_ - + cur_frame_par->VPP_post_blend_vd_v_start_ + 1) + > VPP_PREBLEND_VD_V_END_LIMIT) { + setting->preblend_v_start = + cur_frame_par->VPP_post_blend_vd_v_start_; + setting->preblend_v_end = + cur_frame_par->VPP_post_blend_vd_v_end_; + } else { + setting->preblend_v_start = 0; + setting->preblend_v_end = + VPP_PREBLEND_VD_V_END_LIMIT - 1; + } + + setting->preblend_h_size = + cur_frame_par->VPP_line_in_length_; + + /* old chip, vd2 has no scaler, so only can use mif setting */ + if ((setting->id != 0) && + (legacy_vpp || is_meson_tl1_cpu())) { + vskip = cur_frame_par->vscale_skip_count; + hskip = cur_frame_par->hscale_skip_count; + + setting->postblend_h_start = + cur_frame_par->VPP_hd_start_lines_; + setting->postblend_h_end = + cur_frame_par->VPP_hd_start_lines_ + + (cur_frame_par->VPP_line_in_length_ >> hskip) - 1; + setting->postblend_v_start = + cur_frame_par->VPP_vd_start_lines_; + setting->postblend_v_end = + cur_frame_par->VPP_vd_start_lines_ + + (cur_frame_par->VPP_pic_in_height_ >> vskip) - 1; + setting->postblend_h_size = + cur_frame_par->VPP_post_blend_h_size_; + } else { + setting->postblend_h_start = + cur_frame_par->VPP_hsc_startp; + setting->postblend_h_end = + cur_frame_par->VPP_hsc_endp; + setting->postblend_v_start = + cur_frame_par->VPP_vsc_startp; + setting->postblend_v_end = + cur_frame_par->VPP_vsc_endp; + setting->postblend_h_size = + cur_frame_par->VPP_post_blend_h_size_; + } + + if (!legacy_vpp) { + u32 temp_h = cur_frame_par->VPP_pic_in_height_; + + temp_h <<= 16; + setting->preblend_h_size |= temp_h; + + temp_h = + cur_frame_par->VPP_post_blend_vd_v_end_ + 1; + temp_h <<= 16; + setting->postblend_h_size |= temp_h; + } + +#if 0 + /* TODO: need remove this work around check for afbc */ + type = vf->type; + if (cur_frame_par->nocomp) + type &= ~VIDTYPE_COMPRESS; + + if (type & VIDTYPE_COMPRESS) { + u32 v_phase; + struct vppfilter_mode_s *vpp_filter = + &cur_frame_par->vpp_filter; + v_phase = vpp_filter->vpp_vsc_start_phase_step; + v_phase *= (cur_frame_par->vscale_skip_count + 1); + if ((v_phase > 0x1000000) && + (layer->disp_info.layer_top < 0)) { + if ((cur_frame_par->VPP_vsc_endp > 0x6) && + ((cur_frame_par->VPP_vsc_endp < 0x250) + || (cur_frame_par->VPP_vsc_endp < + cur_frame_par->VPP_post_blend_vd_v_end_/2))) { + setting->postblend_v_end -= 6; + } + } + } +#endif + return 0; +} + +static inline void vd2_vpp_blend_setting( + struct blend_setting_s *setting) +{ + u32 misc_off; + u32 vd_size_mask = VPP_VD_SIZE_MASK; + + if (!setting) + return; + + /* g12a change to 13 bits */ + if (!legacy_vpp) + vd_size_mask = 0x1fff; + + misc_off = 0; + + /* vd2 preblend size should be same postblend size */ + /* preblend setting */ + VSYNC_WR_MPEG_REG( + VPP_BLEND_VD2_H_START_END + misc_off, + ((setting->postblend_h_start & vd_size_mask) + << VPP_VD1_START_BIT) | + ((setting->postblend_h_end & vd_size_mask) + << VPP_VD1_END_BIT)); + + VSYNC_WR_MPEG_REG( + VPP_BLEND_VD2_V_START_END + misc_off, + ((setting->postblend_v_start & vd_size_mask) + << VPP_VD1_START_BIT) | + ((setting->postblend_v_end & vd_size_mask) + << VPP_VD1_END_BIT)); +} + +static inline void proc_vd2_vsc_phase_per_vsync( + struct vpp_frame_par_s *frame_par, + struct vframe_s *vf, + u32 vout_type) +{ + struct f2v_vphase_s *vphase; + u32 misc_off, vin_type; + struct vppfilter_mode_s *vpp_filter; + + if (legacy_vpp || is_meson_tl1_cpu() + || !frame_par || !vf) + return; + + vpp_filter = &frame_par->vpp_filter; + misc_off = 0; + vin_type = vf->type & VIDTYPE_TYPEMASK; + /* vertical phase */ + vphase = &frame_par->VPP_vf_ini_phase_ + [vpp_phase_table[vin_type] + [vout_type]]; + VSYNC_WR_MPEG_REG( + VD2_VSC_INI_PHASE + misc_off, + ((u32) (vphase->phase) << 8)); + + if (vphase->repeat_skip >= 0) { + /* skip lines */ + VSYNC_WR_MPEG_REG_BITS( + VD2_VSC_PHASE_CTRL + misc_off, + skip_tab[vphase->repeat_skip], + VPP_PHASECTL_INIRCVNUMT_BIT, + VPP_PHASECTL_INIRCVNUM_WID + + VPP_PHASECTL_INIRPTNUM_WID); + } else { + /* repeat first line */ + VSYNC_WR_MPEG_REG_BITS( + VD2_VSC_PHASE_CTRL + misc_off, + 4, + VPP_PHASECTL_INIRCVNUMT_BIT, + VPP_PHASECTL_INIRCVNUM_WID); + VSYNC_WR_MPEG_REG_BITS( + VD2_VSC_PHASE_CTRL + misc_off, + 1 - vphase->repeat_skip, + VPP_PHASECTL_INIRPTNUMT_BIT, + VPP_PHASECTL_INIRPTNUM_WID); + } + + VSYNC_WR_MPEG_REG_BITS( + VD2_VSC_PHASE_CTRL + misc_off, + (vpp_filter->vpp_vert_coeff[0] == 2) ? 1 : 0, + VPP_PHASECTL_DOUBLELINE_BIT, + VPP_PHASECTL_DOUBLELINE_WID); +} + +static void pip_toggle_frame(struct vframe_s *vf) +{ + u32 first_picture = 0; + bool force_toggle = false; + + if (vf == NULL) + return; + + ori2_start_x_lines = 0; + ori2_end_x_lines = ((vf->type & VIDTYPE_COMPRESS) ? + vf->compWidth : vf->width) - 1; + ori2_start_y_lines = 0; + ori2_end_y_lines = ((vf->type & VIDTYPE_COMPRESS) ? + vf->compHeight : vf->height) - 1; + + if (debug_flag & DEBUG_FLAG_PRINT_TOGGLE_FRAME) + pr_info("%s()\n", __func__); + + if ((vf->width == 0) && (vf->height == 0)) { + amlog_level(LOG_LEVEL_ERROR, + "Video: invalid frame dimension\n"); + return; + } + if (cur_pipbuf + && (cur_pipbuf != &local_pip) + && (cur_pipbuf != vf)) { + pip_frame_count++; + if (pip_frame_count == 1) + first_picture = 1; +#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA + if (is_vsync_rdma_enable()) { + if (pip_rdma_buf == cur_pipbuf) + pipbuf_to_put = cur_pipbuf; + else + pip_vf_put(cur_pipbuf); + } else { + if (pipbuf_to_put) { + pip_vf_put( + pipbuf_to_put); + pipbuf_to_put = NULL; + } + pip_vf_put(cur_pipbuf); + } +#else + pip_vf_put(cur_pipbuf); +#endif + } else if (!cur_pipbuf + || (cur_pipbuf == &local_pip)) + first_picture = 1; + + /* switch buffer */ + if (vf->type & VIDTYPE_COMPRESS) { + VSYNC_WR_MPEG_REG(VD2_AFBC_HEAD_BADDR, + vf->compHeadAddr>>4); + VSYNC_WR_MPEG_REG(VD2_AFBC_BODY_BADDR, + vf->compBodyAddr>>4); + } + if (vf->canvas0Addr != 0) { +#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA + if (vf->canvas0Addr != (u32)-1) { + canvas_copy(vf->canvas0Addr & 0xff, + disp_canvas_index[pip_rdma_canvas_id][3]); + canvas_copy((vf->canvas0Addr >> 8) & 0xff, + disp_canvas_index[pip_rdma_canvas_id][4]); + canvas_copy((vf->canvas0Addr >> 16) & 0xff, + disp_canvas_index[pip_rdma_canvas_id][5]); + } else { + vframe_canvas_set(&vf->canvas0_config[0], + vf->plane_num, + &disp_canvas_index[pip_rdma_canvas_id][3]); + } + + VSYNC_WR_MPEG_REG( + VD2_IF0_CANVAS0 + cur_dev->viu_off, + disp_canvas[pip_rdma_canvas_id][1]); + + pip_next_rdma_canvas_id = pip_rdma_canvas_id ? 0 : 1; +#endif + } + + if (cur_pipbuf && + (cur_pipbuf->ratio_control & + DISP_RATIO_ADAPTED_PICMODE)) { + if (vf && (cur_pipbuf->ratio_control + == vf->ratio_control) + && memcmp(&cur_pipbuf->pic_mode, + &vf->pic_mode, + sizeof(struct vframe_pic_mode_s))) + force_toggle = true; + else if (memcmp(&cur_pipbuf->pic_mode, + &gPic_info[1], + sizeof(struct vframe_pic_mode_s))) + force_toggle = true; + } + + if (pip_property_changed) { + first_picture = 1; + pip_property_changed = 0; + } + if (cur_pipbuf != vf) + vf->type_backup = vf->type; + + /* enable new config on the new frames */ + if (first_picture || force_toggle || + (cur_pipbuf && + ((cur_pipbuf->bufWidth != vf->bufWidth) || + (cur_pipbuf->width != vf->width) || + (cur_pipbuf->height != vf->height) || + (cur_pipbuf->bitdepth != vf->bitdepth) || + (cur_pipbuf->trans_fmt != vf->trans_fmt) || + (cur_pipbuf->ratio_control != vf->ratio_control) || + ((cur_pipbuf->type_backup & VIDTYPE_INTERLACE) != + (vf->type_backup & VIDTYPE_INTERLACE)) || + (cur_pipbuf->type != vf->type)))) { + int iret; + + /* apply new vpp settings */ + nextpip_frame_par = + (&pip_frame_parms[0] == nextpip_frame_par) ? + &pip_frame_parms[1] : &pip_frame_parms[0]; + + update_layer_info(1); + iret = vpp_set_filters( + &glayer_info[1], vf, + nextpip_frame_par, vinfo, + true, 1); + + memcpy(&gPic_info[1], &vf->pic_mode, + sizeof(struct vframe_pic_mode_s)); + + if (iret == VppFilter_Success_and_Changed) + pip_property_changed = 1; + + pip_frame_ready_to_set = 1; + } + + if (((vf->type & VIDTYPE_NO_VIDEO_ENABLE) == 0) && + (!pip_property_changed || (vf != cur_pipbuf))) { + if (disable_videopip == VIDEO_DISABLE_FORNEXT) { + EnableVideoLayer2(); + disable_videopip = VIDEO_DISABLE_NONE; + } + if (first_picture && + (disable_videopip != + VIDEO_DISABLE_NORMAL)) { + EnableVideoLayer2(); + } + } + cur_pipbuf = vf; + if (first_picture) + pip_frame_ready_to_set = 1; + if (cur_pipbuf != &local_pip) + video_pip_keeper_new_frame_notify(); +} + +static void pip_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) +{ + u32 r; + u32 vphase, vini_phase; + u32 pat, loop; + static const u32 vpat[MAX_VSKIP_COUNT + 1] = { + 0, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf}; + u32 u, v; + u32 type, bit_mode = 0; + + if (!vf || !frame_par) { + pr_err("pip_set_dcu vf is NULL\n"); + return; + } + + type = vf->type; + pr_debug("pip_set_dcu %p, type:0x%x\n", vf, type); + + if (frame_par->nocomp) + type &= ~VIDTYPE_COMPRESS; + + if (type & VIDTYPE_COMPRESS) { + r = (3 << 24) | + (vpp_hold_line << 16) | + ((legacy_vpp ? 1 : 2) << 14) | /* burst1 */ + (vf->bitdepth & BITDEPTH_MASK); + + if (frame_par->hscale_skip_count) + r |= 0x33; + if (frame_par->vscale_skip_count) + r |= 0xcc; + +#ifdef TV_REVERSE + if (reverse) + r |= (1<<26) | (1<<27); +#endif + if (vf->bitdepth & BITDEPTH_SAVING_MODE) + r |= (1<<28); /* mem_saving_mode */ + if (type & VIDTYPE_SCATTER) + r |= (1<<29); + VSYNC_WR_MPEG_REG(VD2_AFBC_MODE, r); + + r = 0x1700; + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) { + if (vf && (vf->source_type + != VFRAME_SOURCE_TYPE_HDMI)) + r |= (1 << 19); /* dos_uncomp */ + } + VSYNC_WR_MPEG_REG(VD2_AFBC_ENABLE, r); + + r = 0x100; + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) { + if (type & VIDTYPE_VIU_444) + r |= 0; + else if (type & VIDTYPE_VIU_422) + r |= (1 << 12); + else + r |= (2 << 12); + } + VSYNC_WR_MPEG_REG(VD2_AFBC_CONV_CTRL, r); + + u = (vf->bitdepth >> (BITDEPTH_U_SHIFT)) & 0x3; + v = (vf->bitdepth >> (BITDEPTH_V_SHIFT)) & 0x3; + VSYNC_WR_MPEG_REG(VD2_AFBC_DEC_DEF_COLOR, + 0x3FF00000 | /*Y,bit20+*/ + 0x80 << (u + 10) | + 0x80 << v); + /* chroma formatter */ + r = HFORMATTER_EN | + (0x8 << VFORMATTER_PHASE_BIT) | + VFORMATTER_EN; +#if 0 /* def CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION */ + if (is_meson_txlx_package_962X() + && !is_dolby_vision_stb_mode() + && is_dolby_vision_on()) { + r |= HFORMATTER_REPEAT | + HFORMATTER_YC_RATIO_2_1 | + HFORMATTER_EN | + VFORMATTER_ALWAYS_RPT | + (0 << VFORMATTER_INIPHASE_BIT) | + (0x8 << VFORMATTER_PHASE_BIT) | + VFORMATTER_EN; + } else +#endif + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) { + r = HFORMATTER_YC_RATIO_2_1 | + HFORMATTER_EN | + VFORMATTER_RPTLINE0_EN | + (0x8 << VFORMATTER_PHASE_BIT) | + VFORMATTER_EN; + + if (is_dolby_vision_on()) + r |= HFORMATTER_REPEAT | + (0xc << VFORMATTER_INIPHASE_BIT); + else + r |= HFORMATTER_RRT_PIXEL0 | + (0 << VFORMATTER_INIPHASE_BIT); + + if (type & VIDTYPE_VIU_444) { + r &= ~HFORMATTER_EN; + r &= ~VFORMATTER_EN; + r &= ~HFORMATTER_YC_RATIO_2_1; + } else if (type & VIDTYPE_VIU_422) { + r &= ~VFORMATTER_EN; + } + } else { + r = HFORMATTER_YC_RATIO_2_1 | + HFORMATTER_EN | + VFORMATTER_RPTLINE0_EN | + (0x8 << VFORMATTER_PHASE_BIT) | + VFORMATTER_EN; + if (is_dolby_vision_on()) + r |= HFORMATTER_REPEAT | + (0xc << VFORMATTER_INIPHASE_BIT); + else + r |= HFORMATTER_RRT_PIXEL0 | + (0 << VFORMATTER_INIPHASE_BIT); + } + VSYNC_WR_MPEG_REG(VD2_AFBC_VD_CFMT_CTRL, r); + + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) { + if (type & VIDTYPE_COMPRESS_LOSS) + VSYNC_WR_MPEG_REG( + VD2_AFBCDEC_IQUANT_ENABLE, + ((1 << 11) | + (1 << 10) | + (1 << 4) | + (1 << 0))); + else + VSYNC_WR_MPEG_REG( + VD2_AFBCDEC_IQUANT_ENABLE, 0); + } + + vd2_path_select(true); + VSYNC_WR_MPEG_REG(VD2_IF0_GEN_REG + + cur_dev->viu_off, 0); + return; + } + + if ((vf->bitdepth & BITDEPTH_Y10) && + (!frame_par->nocomp)) { + if (vf->type & VIDTYPE_VIU_444) { + bit_mode = 2; + } else { + if (vf->bitdepth & FULL_PACK_422_MODE) + bit_mode = 3; + else + bit_mode = 1; + } + } else { + bit_mode = 0; + } + vd2_path_select(false); + if (!legacy_vpp) { + VSYNC_WR_MPEG_REG_BITS( + G12_VD2_IF0_GEN_REG3, + (bit_mode & 0x3), 8, 2); + } else { + VSYNC_WR_MPEG_REG_BITS( + VD2_IF0_GEN_REG3 + cur_dev->viu_off, + (bit_mode&0x3), 8, 2); + } + if (!(VSYNC_RD_MPEG_REG(VIU_MISC_CTRL1) & 0x1)) + VSYNC_WR_MPEG_REG(VD2_AFBC_ENABLE, 0); + if (type & VIDTYPE_VIU_NV21) + VSYNC_WR_MPEG_REG_BITS( + VD2_IF0_GEN_REG2 + + cur_dev->viu_off, 1, 0, 1); + else + VSYNC_WR_MPEG_REG_BITS( + VD2_IF0_GEN_REG2 + + cur_dev->viu_off, 0, 0, 1); + + r = (3 << VDIF_URGENT_BIT) | + (vpp_hold_line << VDIF_HOLD_LINES_BIT) | + VDIF_FORMAT_SPLIT | + VDIF_CHRO_RPT_LAST | VDIF_ENABLE; + /* | VDIF_RESET_ON_GO_FIELD;*/ + if (debug_flag & DEBUG_FLAG_GOFIELD_MANUL) + r |= 1<<7; /*for manul triggle gofiled.*/ + + if ((type & VIDTYPE_VIU_SINGLE_PLANE) == 0) + r |= VDIF_SEPARATE_EN; + else { + if (type & VIDTYPE_VIU_422) + r |= VDIF_FORMAT_422; + else { + r |= VDIF_FORMAT_RGB888_YUV444 | + VDIF_DEMUX_MODE_RGB_444; + } + } + + if (frame_par->hscale_skip_count) + r |= VDIF_CHROMA_HZ_AVG | VDIF_LUMA_HZ_AVG; + + VSYNC_WR_MPEG_REG(VD2_IF0_GEN_REG + cur_dev->viu_off, r); + +#ifdef TV_REVERSE + if (reverse) { + VSYNC_WR_MPEG_REG_BITS((VD2_IF0_GEN_REG2 + + cur_dev->viu_off), 0xf, 2, 4); + } else { + VSYNC_WR_MPEG_REG_BITS((VD2_IF0_GEN_REG2 + + cur_dev->viu_off), 0, 2, 4); + } +#endif + + /* chroma formatter */ + if (type & VIDTYPE_VIU_444) { + VSYNC_WR_MPEG_REG( + VIU_VD2_FMT_CTRL + cur_dev->viu_off, + HFORMATTER_YC_RATIO_1_1); + } else if (type & VIDTYPE_VIU_FIELD) { + vini_phase = 0xc << VFORMATTER_INIPHASE_BIT; + vphase = ((type & VIDTYPE_VIU_422) ? 0x10 : 0x08) + << VFORMATTER_PHASE_BIT; + if (is_meson_gxtvbb_cpu() || is_meson_txl_cpu() || + is_meson_txlx_cpu()) { + if ((vf->width >= 3840) && + (vf->height >= 2160) && + (type & VIDTYPE_VIU_422)) { + VSYNC_WR_MPEG_REG( + VIU_VD2_FMT_CTRL + cur_dev->viu_off, + HFORMATTER_RRT_PIXEL0 | + HFORMATTER_YC_RATIO_2_1 | + HFORMATTER_EN | + VFORMATTER_RPTLINE0_EN | + vini_phase | vphase); + } else { + VSYNC_WR_MPEG_REG( + VIU_VD2_FMT_CTRL + cur_dev->viu_off, + HFORMATTER_REPEAT | + HFORMATTER_YC_RATIO_2_1 | + HFORMATTER_EN | + VFORMATTER_RPTLINE0_EN | + vini_phase | vphase | + VFORMATTER_EN); + } + } else { + VSYNC_WR_MPEG_REG( + VIU_VD2_FMT_CTRL + cur_dev->viu_off, + HFORMATTER_REPEAT | + HFORMATTER_YC_RATIO_2_1 | + HFORMATTER_EN | + VFORMATTER_RPTLINE0_EN | + vini_phase | vphase | + VFORMATTER_EN); + } + } else if ((type & VIDTYPE_TYPEMASK) == VIDTYPE_INTERLACE_TOP) { + VSYNC_WR_MPEG_REG( + VIU_VD2_FMT_CTRL + cur_dev->viu_off, + HFORMATTER_YC_RATIO_2_1 | + HFORMATTER_EN | + VFORMATTER_RPTLINE0_EN | + (0xe << VFORMATTER_INIPHASE_BIT) | + (((type & VIDTYPE_VIU_422) ? 0x10 : 0x08) + << VFORMATTER_PHASE_BIT) | + VFORMATTER_EN); + } else { + VSYNC_WR_MPEG_REG( + VIU_VD2_FMT_CTRL + cur_dev->viu_off, + HFORMATTER_REPEAT | + HFORMATTER_YC_RATIO_2_1 | + HFORMATTER_EN | + VFORMATTER_RPTLINE0_EN | + (0xc << VFORMATTER_INIPHASE_BIT) | + (((type & VIDTYPE_VIU_422) ? 0x10 : 0x08) + << VFORMATTER_PHASE_BIT) | + VFORMATTER_EN); + } + + if (is_meson_txlx_cpu() + || cpu_after_eq( + MESON_CPU_MAJOR_ID_G12A)) + VSYNC_WR_MPEG_REG_BITS( + VIU_VD2_FMT_CTRL + cur_dev->viu_off, + 1, 29, 1); + + /* LOOP/SKIP pattern */ + pat = vpat[frame_par->vscale_skip_count]; + + if (type & VIDTYPE_VIU_FIELD) { + loop = 0; + + if (type & VIDTYPE_INTERLACE) + pat = vpat[frame_par->vscale_skip_count >> 1]; + } else if (type & VIDTYPE_MVC) { + loop = 0x11; + pat = 0x80; + } else if ((type & VIDTYPE_TYPEMASK) == VIDTYPE_INTERLACE_TOP) { + loop = 0x11; + pat <<= 4; + } else + loop = 0; + + VSYNC_WR_MPEG_REG( + VD2_IF0_RPT_LOOP + cur_dev->viu_off, + (loop << VDIF_CHROMA_LOOP1_BIT) | + (loop << VDIF_LUMA_LOOP1_BIT) | + (loop << VDIF_CHROMA_LOOP0_BIT) | + (loop << VDIF_LUMA_LOOP0_BIT)); + + VSYNC_WR_MPEG_REG( + VD2_IF0_LUMA0_RPT_PAT + cur_dev->viu_off, pat); + VSYNC_WR_MPEG_REG( + VD2_IF0_CHROMA0_RPT_PAT + cur_dev->viu_off, pat); + VSYNC_WR_MPEG_REG( + VD2_IF0_LUMA1_RPT_PAT + cur_dev->viu_off, pat); + VSYNC_WR_MPEG_REG( + VD2_IF0_CHROMA1_RPT_PAT + cur_dev->viu_off, pat); + + VSYNC_WR_MPEG_REG( + VD2_IF0_LUMA_PSEL + cur_dev->viu_off, 0); + VSYNC_WR_MPEG_REG( + VD2_IF0_CHROMA_PSEL + cur_dev->viu_off, 0); +} +#endif + +/* for sdr/hdr/single dv switch with dual dv */ +static u32 last_el_status; +/* for dual dv switch with different el size */ +static u32 last_el_w; +bool has_enhanced_layer(struct vframe_s *vf) +{ + struct provider_aux_req_s req; + + if (!vf) + return 0; + if (vf->source_type != VFRAME_SOURCE_TYPE_OTHERS) + return 0; + if (!is_dolby_vision_on()) + return 0; + + req.vf = vf; + req.bot_flag = 0; + req.aux_buf = NULL; + req.aux_size = 0; + req.dv_enhance_exist = 0; + vf_notify_provider_by_name("dvbldec", + VFRAME_EVENT_RECEIVER_GET_AUX_DATA, + (void *)&req); + return req.dv_enhance_exist; +} +u32 property_changed_true; + +static u64 func_div(u64 number, u32 divid) +{ + u64 tmp = number; + + do_div(tmp, divid); + return tmp; +} + +static void vsync_toggle_frame(struct vframe_s *vf, int line) +{ + static u32 last_pts; + u32 diff_pts; + u32 first_picture = 0; + unsigned long flags = 0; + bool vf_with_el = false; + bool force_toggle = false; + long long *clk_array; + bool is_mvc = false; + + ATRACE_COUNTER(__func__, line); + if (vf == NULL) + return; + ATRACE_COUNTER("vsync_toggle_frame_pts", vf->pts); + + diff_pts = vf->pts - last_pts; + if (last_pts && diff_pts < 90000) + ATRACE_COUNTER("vsync_toggle_frame_inc", diff_pts); + else + ATRACE_COUNTER("vsync_toggle_frame_inc", 0); /* discontinue */ + last_pts = vf->pts; + + frame_count++; + toggle_count++; + + if (vf->type & VIDTYPE_MVC) + is_mvc = true; + + if (is_dolby_vision_enable()) + vf_with_el = has_enhanced_layer(vf); + +#ifdef PTS_TRACE_DEBUG +#ifdef PTS_TRACE_START + if (pts_trace_his_rd < 16) { +#endif + pts_trace_his[pts_trace_his_rd] = pts_trace; + pts_his[pts_trace_his_rd] = vf->pts; + scr_his[pts_trace_his_rd] = timestamp_pcrscr_get(); + pts_trace_his_rd++; + if (pts_trace_his_rd >= 16) + pts_trace_his_rd = 0; +#ifdef PTS_TRACE_START + } +#endif +#endif + +#ifdef PTS_LOGGING + if (pts_escape_vsync == 1) { + pts_trace++; + pts_escape_vsync = 0; + } + vsync_video_pattern(); + pre_pts_trace = pts_trace; +#endif + +#if defined(PTS_LOGGING) || defined(PTS_TRACE_DEBUG) + pts_trace = 0; +#endif + + ori_start_x_lines = 0; + ori_end_x_lines = ((vf->type & VIDTYPE_COMPRESS) ? + vf->compWidth : vf->width) - 1; + ori_start_y_lines = 0; + ori_end_y_lines = ((vf->type & VIDTYPE_COMPRESS) ? + vf->compHeight : vf->height) - 1; + if (debug_flag & DEBUG_FLAG_PRINT_TOGGLE_FRAME) { + u32 pcr = timestamp_pcrscr_get(); + u32 vpts = timestamp_vpts_get(); + u32 apts = timestamp_apts_get(); + + pr_info("%s pts:%d.%06d pcr:%d.%06d vpts:%d.%06d apts:%d.%06d\n", + __func__, (vf->pts) / 90000, + ((vf->pts) % 90000) * 1000 / 90, (pcr) / 90000, + ((pcr) % 90000) * 1000 / 90, (vpts) / 90000, + ((vpts) % 90000) * 1000 / 90, (apts) / 90000, + ((apts) % 90000) * 1000 / 90); + } + + if (trickmode_i || trickmode_fffb) + trickmode_duration_count = trickmode_duration; + + if (vf->early_process_fun) { + if (vf->early_process_fun(vf->private_data, vf) == 1) { + /* video_property_changed = true; */ + first_picture = 1; + } + } else { +#ifdef CONFIG_AMLOGIC_MEDIA_DEINTERLACE + if ((DI_POST_REG_RD(DI_IF1_GEN_REG) & 0x1) != 0) { + /* check mif enable status, disable post di */ + VSYNC_WR_MPEG_REG(DI_POST_CTRL, 0x3 << 30); + VSYNC_WR_MPEG_REG(DI_POST_SIZE, + (32 - 1) | ((128 - 1) << 16)); + VSYNC_WR_MPEG_REG(DI_IF1_GEN_REG, + READ_VCBUS_REG(DI_IF1_GEN_REG) & + 0xfffffffe); + } +#endif + } + + timer_count = 0; + if ((vf->width == 0) && (vf->height == 0)) { + amlog_level(LOG_LEVEL_ERROR, + "Video: invalid frame dimension\n"); + ATRACE_COUNTER(__func__, __LINE__); + return; + } + + if (hold_video) { + if (cur_dispbuf != vf) { + new_frame_count++; + if (vf->pts != 0) { + amlog_mask(LOG_MASK_TIMESTAMP, + "vpts to: 0x%x, scr: 0x%x, abs_scr: 0x%x\n", + vf->pts, timestamp_pcrscr_get(), + READ_MPEG_REG(SCR_HIU)); + + timestamp_vpts_set(vf->pts); + last_frame_duration = vf->duration; + } else if (last_frame_duration) { + amlog_mask(LOG_MASK_TIMESTAMP, + "vpts inc: 0x%x, scr: 0x%x, abs_scr: 0x%x\n", + timestamp_vpts_get() + + DUR2PTS(cur_dispbuf->duration), + timestamp_pcrscr_get(), + READ_MPEG_REG(SCR_HIU)); + + timestamp_vpts_inc(DUR2PTS + (last_frame_duration)); + + vpts_remainder += + DUR2PTS_RM(last_frame_duration); + if (vpts_remainder >= 0xf) { + vpts_remainder -= 0xf; + timestamp_vpts_inc(-1); + } + } + if (vf->type & VIDTYPE_COMPRESS) { + cur_width = vf->compWidth; + cur_height = vf->compHeight; + } else { + cur_width = vf->width; + cur_height = vf->height; + } + video_vf_put(vf); + ATRACE_COUNTER(__func__, __LINE__); + return; + } + } + + if ((cur_dispbuf) && (cur_dispbuf != &vf_local) && (cur_dispbuf != vf) + && (video_property_changed != 2)) { + new_frame_count++; + if (new_frame_count == 1) + first_picture = 1; +#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA + if (is_vsync_rdma_enable()) { +#ifdef RDMA_RECYCLE_ORDERED_VFRAMES + if (dispbuf_to_put_num < DISPBUF_TO_PUT_MAX) { + dispbuf_to_put[dispbuf_to_put_num] = + cur_dispbuf; + dispbuf_to_put_num++; + } else + video_vf_put(cur_dispbuf); +#else + if (cur_rdma_buf == cur_dispbuf) { + dispbuf_to_put[0] = cur_dispbuf; + dispbuf_to_put_num = 1; + } else + video_vf_put(cur_dispbuf); +#endif + } else { + int i; + + for (i = 0; i < dispbuf_to_put_num; i++) { + if (dispbuf_to_put[i]) { + video_vf_put( + dispbuf_to_put[i]); + dispbuf_to_put[i] = NULL; + } + dispbuf_to_put_num = 0; + } + video_vf_put(cur_dispbuf); + } +#else + video_vf_put(cur_dispbuf); +#endif + if (debug_flag & DEBUG_FLAG_LATENCY) { + vf->ready_clock[3] = sched_clock(); + pr_info( + "video toggle latency %lld ms, video get latency %lld ms, vdin put latency %lld ms, first %lld ms.\n", + func_div(vf->ready_clock[3], 1000), + func_div(vf->ready_clock[2], 1000), + func_div(vf->ready_clock[1], 1000), + func_div(vf->ready_clock[0], 1000)); + cur_dispbuf->ready_clock[4] = sched_clock(); + clk_array = cur_dispbuf->ready_clock; + pr_info("video put latency %lld ms, video toggle latency %lld ms, video get latency %lld ms, vdin put latency %lld ms, first %lld ms.\n", + func_div(*(clk_array + 4), 1000), + func_div(*(clk_array + 3), 1000), + func_div(*(clk_array + 2), 1000), + func_div(*(clk_array + 1), 1000), + func_div(*clk_array, 1000)); + } + } else + first_picture = 1; + + if (video_property_changed) { + property_changed_true = 2; + video_property_changed = 0; + first_picture = 1; + } + if (property_changed_true > 0) { + property_changed_true--; + first_picture = 1; + } + + if ((debug_flag & DEBUG_FLAG_BLACKOUT) + && first_picture) + pr_info("first picture {%d,%d} pts:%x,\n", + vf->width, vf->height, vf->pts); + + /* switch buffer */ + post_canvas = vf->canvas0Addr; + if ((get_cpu_type() >= MESON_CPU_MAJOR_ID_GXBB) && + (vf->type & VIDTYPE_COMPRESS)) { + VSYNC_WR_MPEG_REG(AFBC_HEAD_BADDR, vf->compHeadAddr>>4); + VSYNC_WR_MPEG_REG(AFBC_BODY_BADDR, vf->compBodyAddr>>4); + } + if ((vf->canvas0Addr != 0) +#ifdef CONFIG_AMLOGIC_MEDIA_DEINTERLACE + && ((DI_POST_REG_RD(DI_POST_CTRL) & 0x1000) == 0) + /* check di_post_viu_link */ +#endif + ) { + +#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA + if (vf->canvas0Addr != (u32)-1) { + canvas_copy(vf->canvas0Addr & 0xff, + disp_canvas_index[rdma_canvas_id][0]); + canvas_copy((vf->canvas0Addr >> 8) & 0xff, + disp_canvas_index[rdma_canvas_id][1]); + canvas_copy((vf->canvas0Addr >> 16) & 0xff, + disp_canvas_index[rdma_canvas_id][2]); + } else { + vframe_canvas_set(&vf->canvas0_config[0], + vf->plane_num, + &disp_canvas_index[rdma_canvas_id][0]); + } + if (is_mvc || process_3d_type) { + if (vf->canvas1Addr != (u32)-1) { + canvas_copy(vf->canvas1Addr & 0xff, + disp_canvas_index[rdma_canvas_id][3]); + canvas_copy((vf->canvas1Addr >> 8) & 0xff, + disp_canvas_index[rdma_canvas_id][4]); + canvas_copy((vf->canvas1Addr >> 16) & 0xff, + disp_canvas_index[rdma_canvas_id][5]); + } else { + vframe_canvas_set(&vf->canvas1_config[0], + vf->plane_num, + &disp_canvas_index[rdma_canvas_id][3]); + } + } + + VSYNC_WR_MPEG_REG( + VD1_IF0_CANVAS0 + cur_dev->viu_off, + disp_canvas[rdma_canvas_id][0]); + if (is_mvc) + VSYNC_WR_MPEG_REG( + VD2_IF0_CANVAS0 + cur_dev->viu_off, + disp_canvas[rdma_canvas_id][1]); + if (cur_frame_par && + (cur_frame_par->vpp_2pic_mode == 1)) { + VSYNC_WR_MPEG_REG(VD1_IF0_CANVAS1 + + cur_dev->viu_off, + disp_canvas[rdma_canvas_id][0]); + if (is_mvc) + VSYNC_WR_MPEG_REG(VD2_IF0_CANVAS1 + + cur_dev->viu_off, + disp_canvas[rdma_canvas_id][0]); + } else { + VSYNC_WR_MPEG_REG(VD1_IF0_CANVAS1 + + cur_dev->viu_off, + disp_canvas[rdma_canvas_id][1]); + if (is_mvc) + VSYNC_WR_MPEG_REG(VD2_IF0_CANVAS1 + + cur_dev->viu_off, + disp_canvas[rdma_canvas_id][0]); + } + if (cur_frame_par + && (process_3d_type & MODE_3D_ENABLE) + && (process_3d_type & MODE_3D_TO_2D_R) + && (cur_frame_par->vpp_2pic_mode + == VPP_SELECT_PIC1)) { + VSYNC_WR_MPEG_REG(VD1_IF0_CANVAS0 + cur_dev->viu_off, + disp_canvas[rdma_canvas_id][1]); + VSYNC_WR_MPEG_REG(VD1_IF0_CANVAS1 + cur_dev->viu_off, + disp_canvas[rdma_canvas_id][1]); + if (is_mvc) { + VSYNC_WR_MPEG_REG( + VD2_IF0_CANVAS0 + cur_dev->viu_off, + disp_canvas[rdma_canvas_id][1]); + VSYNC_WR_MPEG_REG( + VD2_IF0_CANVAS1 + cur_dev->viu_off, + disp_canvas[rdma_canvas_id][1]); + } + } + next_rdma_canvas_id = rdma_canvas_id ? 0 : 1; +#else + canvas_copy(vf->canvas0Addr & 0xff, disp_canvas_index[0]); + canvas_copy((vf->canvas0Addr >> 8) & 0xff, + disp_canvas_index[1]); + canvas_copy((vf->canvas0Addr >> 16) & 0xff, + disp_canvas_index[2]); + if (is_mvc || process_3d_type) { + canvas_copy(vf->canvas1Addr & 0xff, + disp_canvas_index[3]); + canvas_copy((vf->canvas1Addr >> 8) & 0xff, + disp_canvas_index[4]); + canvas_copy((vf->canvas1Addr >> 16) & 0xff, + disp_canvas_index[5]); + } + VSYNC_WR_MPEG_REG( + VD1_IF0_CANVAS0 + cur_dev->viu_off, + disp_canvas[0]); + if (is_mvc) + VSYNC_WR_MPEG_REG( + VD2_IF0_CANVAS0 + cur_dev->viu_off, + disp_canvas[0]); + if (cur_frame_par && + (cur_frame_par->vpp_2pic_mode == 1)) { + VSYNC_WR_MPEG_REG(VD1_IF0_CANVAS1 + + cur_dev->viu_off, + disp_canvas[0]); + if (is_mvc) + VSYNC_WR_MPEG_REG(VD2_IF0_CANVAS1 + + cur_dev->viu_off, + disp_canvas[0]); + } else { + VSYNC_WR_MPEG_REG(VD1_IF0_CANVAS1 + + cur_dev->viu_off, + disp_canvas[1]); + if (is_mvc) + VSYNC_WR_MPEG_REG(VD2_IF0_CANVAS1 + + cur_dev->viu_off, + disp_canvas[1]); + } +#endif + } + /* set video PTS */ + if (cur_dispbuf != vf) { + if (vf->pts != 0) { + amlog_mask(LOG_MASK_TIMESTAMP, + "vpts to: 0x%x, scr: 0x%x, abs_scr: 0x%x\n", + vf->pts, timestamp_pcrscr_get(), + READ_MPEG_REG(SCR_HIU)); + timestamp_vpts_set(vf->pts); + } else if (cur_dispbuf) { + amlog_mask(LOG_MASK_TIMESTAMP, + "vpts inc: 0x%x, scr: 0x%x, abs_scr: 0x%x\n", + timestamp_vpts_get() + + DUR2PTS(cur_dispbuf->duration), + timestamp_pcrscr_get(), + READ_MPEG_REG(SCR_HIU)); + + timestamp_vpts_inc(DUR2PTS + (cur_dispbuf->duration)); + + vpts_remainder += + DUR2PTS_RM(cur_dispbuf->duration); + if (vpts_remainder >= 0xf) { + vpts_remainder -= 0xf; + timestamp_vpts_inc(-1); + } + } + vf->type_backup = vf->type; + } + + if (cur_dispbuf && + (cur_dispbuf->ratio_control & + DISP_RATIO_ADAPTED_PICMODE)) { + if (vf && (cur_dispbuf->ratio_control + == vf->ratio_control) + && memcmp(&cur_dispbuf->pic_mode, + &vf->pic_mode, + sizeof(struct vframe_pic_mode_s))) + force_toggle = true; + else if (memcmp(&cur_dispbuf->pic_mode, + &gPic_info[0], + sizeof(struct vframe_pic_mode_s))) + force_toggle = true; + } + + if ((last_process_3d_type != process_3d_type) + || (last_el_status != vf_with_el)) + force_toggle = true; + + /* enable new config on the new frames */ + if (first_picture || force_toggle || + (cur_dispbuf && + ((cur_dispbuf->bufWidth != vf->bufWidth) || + (cur_dispbuf->width != vf->width) || + (cur_dispbuf->height != vf->height) || + (cur_dispbuf->bitdepth != vf->bitdepth) || + (cur_dispbuf->trans_fmt != vf->trans_fmt) || + (cur_dispbuf->ratio_control != vf->ratio_control) || + ((cur_dispbuf->type_backup & VIDTYPE_INTERLACE) != + (vf->type_backup & VIDTYPE_INTERLACE)) || + (cur_dispbuf->type != vf->type)))) { + int iret; + + last_process_3d_type = process_3d_type; + atomic_inc(&video_sizechange); + wake_up_interruptible(&amvideo_sizechange_wait); + amlog_mask(LOG_MASK_FRAMEINFO, + "%s %dx%d ar=0x%x\n", + ((vf->type & VIDTYPE_TYPEMASK) == + VIDTYPE_INTERLACE_TOP) ? "interlace-top" + : ((vf->type & VIDTYPE_TYPEMASK) + == VIDTYPE_INTERLACE_BOTTOM) + ? "interlace-bottom" : "progressive", vf->width, + vf->height, vf->ratio_control); +#ifdef TV_3D_FUNCTION_OPEN + amlog_mask(LOG_MASK_FRAMEINFO, + "%s trans_fmt=%u\n", __func__, vf->trans_fmt); + +#endif + next_frame_par = (&frame_parms[0] == next_frame_par) ? + &frame_parms[1] : &frame_parms[0]; + + update_layer_info(0); + iret = vpp_set_filters( + &glayer_info[0], vf, + next_frame_par, vinfo, + (is_dolby_vision_on() && + is_dolby_vision_stb_mode()), 1); + + if (iret == VppFilter_Success_and_Changed) + video_property_changed = 1; + + memcpy(&gPic_info[0], &vf->pic_mode, + sizeof(struct vframe_pic_mode_s)); + + if (iret == VppFilter_Success_and_Changed) + video_property_changed = 1; + + /* apply new vpp settings */ + frame_par_ready_to_set = 1; + + if (((vf->width > 1920) && (vf->height > 1088)) || + ((vf->type & VIDTYPE_COMPRESS) && + (vf->compWidth > 1920) && + (vf->compHeight > 1080))) { + if (vpu_clk_level == 0) { + vpu_clk_level = 1; + spin_lock_irqsave(&lock, flags); + vpu_delay_work_flag |= + VPU_DELAYWORK_VPU_CLK; + spin_unlock_irqrestore(&lock, flags); + } + } else { + if (vpu_clk_level == 1) { + vpu_clk_level = 0; + spin_lock_irqsave(&lock, flags); + vpu_delay_work_flag |= + VPU_DELAYWORK_VPU_CLK; + spin_unlock_irqrestore(&lock, flags); + } + } + } + + /* if el is unnecessary, afbc2 need to be closed */ + if ((last_el_status == 1) && (vf_with_el == 0)) + need_disable_vd2 = true; + + if (((vf->type & VIDTYPE_MVC) == 0) + && last_mvc_status) + need_disable_vd2 = true; + + last_el_status = vf_with_el; + + if (((vf->type & VIDTYPE_NO_VIDEO_ENABLE) == 0) && + ((!property_changed_true) || (vf != cur_dispbuf))) { + if (disable_video == VIDEO_DISABLE_FORNEXT) { + EnableVideoLayer(); + disable_video = VIDEO_DISABLE_NONE; + } + if (first_picture && (disable_video != VIDEO_DISABLE_NORMAL)) { + EnableVideoLayer(); + if ((vf->type & VIDTYPE_MVC) || + (cur_dispbuf2 && (cur_dispbuf2->type & VIDTYPE_VD2))) + EnableVideoLayer2(); + else if (cur_dispbuf2 && + !(cur_dispbuf2->type & VIDTYPE_COMPRESS)) + VD2_MEM_POWER_ON(); + else if (vf_with_el) + EnableVideoLayer2(); + else if (need_disable_vd2) + DisableVideoLayer2(); + } + } + if (cur_dispbuf && (cur_dispbuf->type != vf->type)) { + if ((vf->type & VIDTYPE_MVC) || + (cur_dispbuf2 && (cur_dispbuf2->type & VIDTYPE_VD2))) + EnableVideoLayer2(); + else { + if (cur_dispbuf2 && + !(cur_dispbuf2->type & VIDTYPE_COMPRESS)) + VD2_MEM_POWER_ON(); + else if (vf_with_el) + EnableVideoLayer2(); + else if (need_disable_vd2) + DisableVideoLayer2(); + } + } + cur_dispbuf = vf; + if (cur_dispbuf && (cur_dispbuf->type & VIDTYPE_MVC)) + last_mvc_status = true; + else + last_mvc_status = false; + +#ifdef CONFIG_AMLOGIC_MEDIA_VIDEOCAPTURE + ext_frame_capture_poll(cur_dispbuf); +#endif + if (first_picture) { + frame_par_ready_to_set = 1; + first_frame_toggled = 1; + +#ifdef VIDEO_PTS_CHASE + av_sync_flag = 0; +#endif + } + if (cur_dispbuf != &vf_local) + video_keeper_new_frame_notify(); + + if ((vf != &vf_local) && (vf) && !vsync_pts_aligned) { +#ifdef PTS_TRACE_DEBUG + pr_info("####timestamp_pcrscr_get() = 0x%x, vf->pts = 0x%x, vsync_pts_inc = %d\n", + timestamp_pcrscr_get(), vf->pts, vsync_pts_inc); +#endif + if ((abs(timestamp_pcrscr_get() - vf->pts) <= (vsync_pts_inc)) + && ((int)(timestamp_pcrscr_get() - vf->pts) >= 0)) { + vsync_pts_align = vsync_pts_inc / 4 - + (timestamp_pcrscr_get() - vf->pts); + vsync_pts_aligned = true; +#ifdef PTS_TRACE_DEBUG + pts_trace_his_rd = 0; + pr_info("####vsync_pts_align set to %d\n", + vsync_pts_align); +#endif + } + } + if (stop_update) + frame_par_ready_to_set = 0; + ATRACE_COUNTER(__func__, 0); +} + static void viu_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) { u32 r; @@ -3133,13 +4180,17 @@ static void viu_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) 0, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf}; u32 u, v; u32 type, bit_mode = 0; - bool vf_with_el = false; + bool is_mvc = false; if (vf == NULL) { pr_info("viu_set_dcu vf NULL, return\n"); return; } + type = vf->type; + if (type & VIDTYPE_MVC) + is_mvc = true; + pr_debug("set dcu for vd1 %p, type:0x%x\n", vf, type); if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXBB) { if (frame_par->nocomp) @@ -3157,20 +4208,34 @@ static void viu_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) r |= 0xcc; #ifdef TV_REVERSE if (reverse) - r |= (1<<26)|(1<<27); + r |= (1<<26) | (1<<27); #endif if (vf->bitdepth & BITDEPTH_SAVING_MODE) r |= (1<<28); /* mem_saving_mode */ if (type & VIDTYPE_SCATTER) r |= (1<<29); VSYNC_WR_MPEG_REG(AFBC_MODE, r); - VSYNC_WR_MPEG_REG(AFBC_ENABLE, 0x1700); + + r = 0x1700; + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) { + if (vf && (vf->source_type + != VFRAME_SOURCE_TYPE_HDMI)) + r |= (1 << 19); /* dos_uncomp */ + + if (type & VIDTYPE_COMB_MODE) + r |= (1 << 20); + } + VSYNC_WR_MPEG_REG(AFBC_ENABLE, r); r = 0x100; - /* need check the vf->type 444/422/420 */ - /* current use 420 as default for tl1 */ - if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) - r |= (2 << 12); + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) { + if (type & VIDTYPE_VIU_444) + r |= 0; + else if (type & VIDTYPE_VIU_422) + r |= (1 << 12); + else + r |= (2 << 12); + } VSYNC_WR_MPEG_REG(AFBC_CONV_CTRL, r); u = (vf->bitdepth >> (BITDEPTH_U_SHIFT)) & 0x3; @@ -3180,61 +4245,60 @@ static void viu_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) 0x80 << (u + 10) | 0x80 << v); /* chroma formatter */ - /* TODO: afbc setting only cover 420 for now */ -/* -#ifdef TV_REVERSE - if (reverse) { + + r = 0; #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION - if (is_meson_txlx_package_962X() + if (is_meson_txlx_package_962X() && !is_dolby_vision_stb_mode() - && is_dolby_vision_on()) - VSYNC_WR_MPEG_REG( - AFBC_VD_CFMT_CTRL, - HFORMATTER_REPEAT | - HFORMATTER_YC_RATIO_2_1 | - HFORMATTER_EN | - VFORMATTER_ALWAYS_RPT | - (0 << VFORMATTER_INIPHASE_BIT) | - (0x8 << VFORMATTER_PHASE_BIT) | - VFORMATTER_EN); - else -#endif - VSYNC_WR_MPEG_REG(AFBC_VD_CFMT_CTRL, - HFORMATTER_REPEAT | - (0xc << VFORMATTER_INIPHASE_BIT) | - HFORMATTER_YC_RATIO_2_1 | - HFORMATTER_EN | - VFORMATTER_RPTLINE0_EN | - (0x8 << VFORMATTER_PHASE_BIT) | - VFORMATTER_EN); + && is_dolby_vision_on()) { + r = HFORMATTER_REPEAT | + HFORMATTER_YC_RATIO_2_1 | + HFORMATTER_EN | + VFORMATTER_ALWAYS_RPT | + (0 << VFORMATTER_INIPHASE_BIT) | + (0x8 << VFORMATTER_PHASE_BIT) | + VFORMATTER_EN; } else #endif -*/ - { -#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION - if (is_meson_txlx_package_962X() - && !is_dolby_vision_stb_mode() - && is_dolby_vision_on()) - VSYNC_WR_MPEG_REG( - AFBC_VD_CFMT_CTRL, - HFORMATTER_REPEAT | - HFORMATTER_YC_RATIO_2_1 | - HFORMATTER_EN | - VFORMATTER_ALWAYS_RPT | - (0 << VFORMATTER_INIPHASE_BIT) | - (0x8 << VFORMATTER_PHASE_BIT) | - VFORMATTER_EN); - else -#endif - VSYNC_WR_MPEG_REG(AFBC_VD_CFMT_CTRL, - HFORMATTER_REPEAT | + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) { + r = HFORMATTER_REPEAT | + HFORMATTER_YC_RATIO_2_1 | + HFORMATTER_EN | + VFORMATTER_RPTLINE0_EN | (0xc << VFORMATTER_INIPHASE_BIT) | - HFORMATTER_YC_RATIO_2_1 | - HFORMATTER_EN | - VFORMATTER_RPTLINE0_EN | - (0x8 << VFORMATTER_PHASE_BIT) | - VFORMATTER_EN); + (0x8 << VFORMATTER_PHASE_BIT) | + VFORMATTER_EN; + if (type & VIDTYPE_VIU_444) { + r &= ~HFORMATTER_EN; + r &= ~VFORMATTER_EN; + r &= ~HFORMATTER_YC_RATIO_2_1; + } else if (type & VIDTYPE_VIU_422) { + r &= ~VFORMATTER_EN; + } + } else { + r = HFORMATTER_REPEAT | + HFORMATTER_YC_RATIO_2_1 | + HFORMATTER_EN | + VFORMATTER_RPTLINE0_EN | + (0xc << VFORMATTER_INIPHASE_BIT) | + (0x8 << VFORMATTER_PHASE_BIT) | + VFORMATTER_EN; } + VSYNC_WR_MPEG_REG(AFBC_VD_CFMT_CTRL, r); + + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) { + if (type & VIDTYPE_COMPRESS_LOSS) + VSYNC_WR_MPEG_REG( + AFBCDEC_IQUANT_ENABLE, + ((1 << 11) | + (1 << 10) | + (1 << 4) | + (1 << 0))); + else + VSYNC_WR_MPEG_REG( + AFBCDEC_IQUANT_ENABLE, 0); + } + vd1_path_select(true); VSYNC_WR_MPEG_REG( @@ -3259,7 +4323,7 @@ static void viu_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) VSYNC_WR_MPEG_REG_BITS( G12_VD1_IF0_GEN_REG3, (bit_mode & 0x3), 8, 2); - if ((vf->type & VIDTYPE_MVC) && (!vf_with_el)) + if (is_mvc) VSYNC_WR_MPEG_REG_BITS( G12_VD2_IF0_GEN_REG3, (bit_mode & 0x3), 8, 2); @@ -3268,7 +4332,7 @@ static void viu_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) VD1_IF0_GEN_REG3 + cur_dev->viu_off, (bit_mode & 0x3), 8, 2); - if ((vf->type & VIDTYPE_MVC) && (!vf_with_el)) + if (is_mvc) VSYNC_WR_MPEG_REG_BITS( VD2_IF0_GEN_REG3 + cur_dev->viu_off, @@ -3307,15 +4371,14 @@ static void viu_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) VDIF_DEMUX_MODE_RGB_444; } } - if (is_dolby_vision_enable()) - vf_with_el = has_enhanced_layer(vf); + if (frame_par->hscale_skip_count) r |= VDIF_CHROMA_HZ_AVG | VDIF_LUMA_HZ_AVG; /*enable go field reset default according to vlsi*/ r |= VDIF_RESET_ON_GO_FIELD; VSYNC_WR_MPEG_REG(VD1_IF0_GEN_REG + cur_dev->viu_off, r); - if (!vf_with_el) + if (is_mvc) VSYNC_WR_MPEG_REG( VD2_IF0_GEN_REG + cur_dev->viu_off, r); @@ -3328,38 +4391,20 @@ static void viu_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) VSYNC_WR_MPEG_REG_BITS(VD1_IF0_GEN_REG2 + cur_dev->viu_off, 0, 0, 1); } -#if HAS_VPU_PROT - if (has_vpu_prot()) { - if (use_prot) { - if (vf->video_angle == 2) { - VSYNC_WR_MPEG_REG_BITS(VD1_IF0_GEN_REG2 - + - cur_dev->viu_off, - 0xf, 2, 4); - } else { - VSYNC_WR_MPEG_REG_BITS(VD1_IF0_GEN_REG2 - + - cur_dev->viu_off, - 0, 2, 4); - } - } - } -#else #ifdef TV_REVERSE if (reverse) { VSYNC_WR_MPEG_REG_BITS((VD1_IF0_GEN_REG2 + cur_dev->viu_off), 0xf, 2, 4); - if ((vf->type & VIDTYPE_MVC) && (!vf_with_el)) + if (is_mvc) VSYNC_WR_MPEG_REG_BITS((VD2_IF0_GEN_REG2 + cur_dev->viu_off), 0xf, 2, 4); } else { VSYNC_WR_MPEG_REG_BITS((VD1_IF0_GEN_REG2 + cur_dev->viu_off), 0, 2, 4); - if ((vf->type & VIDTYPE_MVC) && (!vf_with_el)) + if (is_mvc) VSYNC_WR_MPEG_REG_BITS((VD2_IF0_GEN_REG2 + cur_dev->viu_off), 0, 2, 4); } -#endif #endif } /* #endif */ @@ -3368,7 +4413,7 @@ static void viu_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) if (type & VIDTYPE_VIU_444) { VSYNC_WR_MPEG_REG(VIU_VD1_FMT_CTRL + cur_dev->viu_off, HFORMATTER_YC_RATIO_1_1); - if (!vf_with_el) + if (is_mvc) VSYNC_WR_MPEG_REG(VIU_VD2_FMT_CTRL + cur_dev->viu_off, HFORMATTER_YC_RATIO_1_1); } else if (type & VIDTYPE_VIU_FIELD) { @@ -3409,7 +4454,7 @@ static void viu_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) VIU_VD1_FMT_CTRL + cur_dev->viu_off, HFORMATTER_YC_RATIO_2_1 | HFORMATTER_EN | VFORMATTER_RPTLINE0_EN | vini_phase | vphase); - if (!vf_with_el) + if (is_mvc) VSYNC_WR_MPEG_REG( VIU_VD2_FMT_CTRL + cur_dev->viu_off, HFORMATTER_RRT_PIXEL0 | @@ -3425,7 +4470,7 @@ static void viu_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) HFORMATTER_YC_RATIO_2_1 | HFORMATTER_EN | VFORMATTER_RPTLINE0_EN | vini_phase | vphase | vformatter); - if (!vf_with_el) + if (is_mvc) VSYNC_WR_MPEG_REG( VIU_VD2_FMT_CTRL + cur_dev->viu_off, HFORMATTER_YC_RATIO_2_1 | @@ -3443,7 +4488,7 @@ static void viu_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) VFORMATTER_RPTLINE0_EN | vini_phase | vphase | vformatter); - if (!vf_with_el) + if (is_mvc) VSYNC_WR_MPEG_REG( VIU_VD2_FMT_CTRL + cur_dev->viu_off, HFORMATTER_YC_RATIO_2_1 | @@ -3460,7 +4505,7 @@ static void viu_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) (0xe << VFORMATTER_INIPHASE_BIT) | (((type & VIDTYPE_VIU_422) ? 0x10 : 0x08) << VFORMATTER_PHASE_BIT) | VFORMATTER_EN); - if (!vf_with_el) + if (is_mvc) VSYNC_WR_MPEG_REG(VIU_VD2_FMT_CTRL + cur_dev->viu_off, HFORMATTER_YC_RATIO_2_1 | HFORMATTER_EN | VFORMATTER_RPTLINE0_EN | (0xa << @@ -3475,7 +4520,7 @@ static void viu_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) VFORMATTER_INIPHASE_BIT) | (((type & VIDTYPE_VIU_422) ? 0x10 : 0x08) << VFORMATTER_PHASE_BIT) | VFORMATTER_EN); - if (!vf_with_el) + if (is_mvc) VSYNC_WR_MPEG_REG(VIU_VD2_FMT_CTRL + cur_dev->viu_off, HFORMATTER_YC_RATIO_2_1 | HFORMATTER_EN | @@ -3509,7 +4554,7 @@ static void viu_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) (((type & VIDTYPE_VIU_422) ? 0x10 : 0x08) << VFORMATTER_PHASE_BIT) | VFORMATTER_EN); } - if (!vf_with_el) + if (is_mvc) VSYNC_WR_MPEG_REG(VIU_VD2_FMT_CTRL + cur_dev->viu_off, HFORMATTER_YC_RATIO_2_1 | HFORMATTER_EN | @@ -3520,8 +4565,8 @@ static void viu_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) } #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION if ((is_meson_txlx_cpu() - || is_meson_g12a_cpu() - || is_meson_g12b_cpu()) + || cpu_after_eq( + MESON_CPU_MAJOR_ID_G12A)) && is_dolby_vision_on() && is_dolby_vision_stb_mode() && (vf->source_type == @@ -3556,7 +4601,7 @@ static void viu_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) (loop << VDIF_LUMA_LOOP1_BIT) | (loop << VDIF_CHROMA_LOOP0_BIT) | (loop << VDIF_LUMA_LOOP0_BIT)); - if (!vf_with_el) + if (is_mvc) VSYNC_WR_MPEG_REG( VD2_IF0_RPT_LOOP + cur_dev->viu_off, (loop << VDIF_CHROMA_LOOP1_BIT) | @@ -3574,8 +4619,6 @@ static void viu_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) pat = 0; else pat = 0x88; - } - if (!vf_with_el) { VSYNC_WR_MPEG_REG( VD2_IF0_LUMA0_RPT_PAT + cur_dev->viu_off, pat); VSYNC_WR_MPEG_REG( @@ -3586,46 +4629,14 @@ static void viu_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) VD2_IF0_CHROMA1_RPT_PAT + cur_dev->viu_off, pat); } - if (platform_type == 0) { - /* picture 0/1 control */ - if (((type & VIDTYPE_INTERLACE) == 0) && - ((type & VIDTYPE_VIU_FIELD) == 0) && - ((type & VIDTYPE_MVC) == 0)) { - /* progressive frame in two pictures */ + /* picture 0/1 control */ + if ((((type & VIDTYPE_INTERLACE) == 0) && + ((type & VIDTYPE_VIU_FIELD) == 0) && + ((type & VIDTYPE_MVC) == 0)) || + (frame_par->vpp_2pic_mode & 0x3)) { + /* progressive frame in two pictures */ + if (frame_par->vpp_2pic_mode & VPP_PIC1_FIRST) { VSYNC_WR_MPEG_REG(VD1_IF0_LUMA_PSEL + - cur_dev->viu_off, (2 << 26) | /* two pic mode */ - (2 << 24) | /* use own last line */ - (2 << 8) | /* toggle pic 0 and 1, use pic0 first */ - (0x01)); /* loop pattern */ - VSYNC_WR_MPEG_REG(VD1_IF0_CHROMA_PSEL + - cur_dev->viu_off, - (2 << 26) | /* two pic mode */ - (2 << 24) | /* use own last line */ - (2 << 8) | /* toggle pic 0 and 1, use pic0 first */ - (0x01)); /* loop pattern */ - } else { - VSYNC_WR_MPEG_REG(VD1_IF0_LUMA_PSEL + - cur_dev->viu_off, 0); - VSYNC_WR_MPEG_REG(VD1_IF0_CHROMA_PSEL + - cur_dev->viu_off, 0); - if (!vf_with_el) { - VSYNC_WR_MPEG_REG( - VD2_IF0_LUMA_PSEL + - cur_dev->viu_off, 0); - VSYNC_WR_MPEG_REG( - VD2_IF0_CHROMA_PSEL + - cur_dev->viu_off, 0); - } - } - } else { - /* picture 0/1 control */ - if ((((type & VIDTYPE_INTERLACE) == 0) && - ((type & VIDTYPE_VIU_FIELD) == 0) && - ((type & VIDTYPE_MVC) == 0)) || - (frame_par->vpp_2pic_mode & 0x3)) { - /* progressive frame in two pictures */ - if (frame_par->vpp_2pic_mode & VPP_PIC1_FIRST) { - VSYNC_WR_MPEG_REG(VD1_IF0_LUMA_PSEL + cur_dev->viu_off, (2 << 26) | /* two pic mode */ (2 << 24) | @@ -3634,7 +4645,7 @@ static void viu_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) /* toggle pic 0 and 1, use pic1 first*/ (0x01)); /* loop pattern */ - VSYNC_WR_MPEG_REG(VD1_IF0_CHROMA_PSEL + + VSYNC_WR_MPEG_REG(VD1_IF0_CHROMA_PSEL + cur_dev->viu_off, (2 << 26) | /* two pic mode */ (2 << 24) | @@ -3643,53 +4654,52 @@ static void viu_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) /* toggle pic 0 and 1,use pic1 first */ (0x01)); /* loop pattern */ - } else { - VSYNC_WR_MPEG_REG(VD1_IF0_LUMA_PSEL + - cur_dev->viu_off, (2 << 26) | - /* two pic mode */ - (2 << 24) | - /* use own last line */ - (2 << 8) | - /* toggle pic 0 and 1, use pic0 first */ - (0x01)); - /* loop pattern */ - VSYNC_WR_MPEG_REG(VD1_IF0_CHROMA_PSEL + - cur_dev->viu_off, (2 << 26) | - /* two pic mode */ - (2 << 24) | - /* use own last line */ - (2 << 8) | - /* toggle pic 0 and 1, use pic0 first */ - (0x01)); - /* loop pattern */ - } - } else if (process_3d_type & MODE_3D_OUT_FA_MASK) { - /*FA LR/TB output , do nothing*/ } else { - if (frame_par->vpp_2pic_mode & VPP_SELECT_PIC1) { - VSYNC_WR_MPEG_REG(VD1_IF0_LUMA_PSEL + + VSYNC_WR_MPEG_REG(VD1_IF0_LUMA_PSEL + + cur_dev->viu_off, (2 << 26) | + /* two pic mode */ + (2 << 24) | + /* use own last line */ + (2 << 8) | + /* toggle pic 0 and 1, use pic0 first */ + (0x01)); + /* loop pattern */ + VSYNC_WR_MPEG_REG(VD1_IF0_CHROMA_PSEL + + cur_dev->viu_off, (2 << 26) | + /* two pic mode */ + (2 << 24) | + /* use own last line */ + (2 << 8) | + /* toggle pic 0 and 1, use pic0 first */ + (0x01)); + /* loop pattern */ + } + } else if (process_3d_type & MODE_3D_OUT_FA_MASK) { + /*FA LR/TB output , do nothing*/ + } else { + if (frame_par->vpp_2pic_mode & VPP_SELECT_PIC1) { + VSYNC_WR_MPEG_REG(VD1_IF0_LUMA_PSEL + cur_dev->viu_off, 0); - VSYNC_WR_MPEG_REG(VD1_IF0_CHROMA_PSEL + + VSYNC_WR_MPEG_REG(VD1_IF0_CHROMA_PSEL + cur_dev->viu_off, 0); - if (!vf_with_el) { - VSYNC_WR_MPEG_REG(VD2_IF0_LUMA_PSEL + + if (is_mvc) { + VSYNC_WR_MPEG_REG(VD2_IF0_LUMA_PSEL + cur_dev->viu_off, 0); - VSYNC_WR_MPEG_REG(VD2_IF0_CHROMA_PSEL + + VSYNC_WR_MPEG_REG(VD2_IF0_CHROMA_PSEL + cur_dev->viu_off, 0); - } - } else { - VSYNC_WR_MPEG_REG(VD1_IF0_LUMA_PSEL + + } + } else { + VSYNC_WR_MPEG_REG(VD1_IF0_LUMA_PSEL + cur_dev->viu_off, 0); - VSYNC_WR_MPEG_REG(VD1_IF0_CHROMA_PSEL + + VSYNC_WR_MPEG_REG(VD1_IF0_CHROMA_PSEL + cur_dev->viu_off, 0); - if (!vf_with_el) { - VSYNC_WR_MPEG_REG( - VD2_IF0_LUMA_PSEL + - cur_dev->viu_off, 0); - VSYNC_WR_MPEG_REG( - VD2_IF0_CHROMA_PSEL + - cur_dev->viu_off, 0); - } + if (is_mvc) { + VSYNC_WR_MPEG_REG( + VD2_IF0_LUMA_PSEL + + cur_dev->viu_off, 0); + VSYNC_WR_MPEG_REG( + VD2_IF0_CHROMA_PSEL + + cur_dev->viu_off, 0); } } } @@ -3703,8 +4713,14 @@ static void vd2_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) static const u32 vpat[MAX_VSKIP_COUNT + 1] = { 0, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf}; u32 u, v; - u32 type = vf->type, bit_mode = 0; + u32 type, bit_mode = 0; + if (!vf) { + pr_err("vd2_set_dcu vf is NULL\n"); + return; + } + + type = vf->type; pr_debug("set dcu for vd2 %p, type:0x%x\n", vf, type); last_el_w = (vf->type & VIDTYPE_COMPRESS) ? @@ -3724,20 +4740,31 @@ static void vd2_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) #ifdef TV_REVERSE if (reverse) - r |= (1<<26)|(1<<27); + r |= (1<<26) | (1<<27); #endif if (vf->bitdepth & BITDEPTH_SAVING_MODE) r |= (1<<28); /* mem_saving_mode */ if (type & VIDTYPE_SCATTER) r |= (1<<29); VSYNC_WR_MPEG_REG(VD2_AFBC_MODE, r); - VSYNC_WR_MPEG_REG(VD2_AFBC_ENABLE, 0x1700); + + r = 0x1700; + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) { + if (vf && (vf->source_type + != VFRAME_SOURCE_TYPE_HDMI)) + r |= (1 << 19); /* dos_uncomp */ + } + VSYNC_WR_MPEG_REG(VD2_AFBC_ENABLE, r); r = 0x100; - /* need check the vf->type 444/422/420 */ - /* current use 420 as default for tl1 */ - if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) - r |= (2 << 12); + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) { + if (type & VIDTYPE_VIU_444) + r |= 0; + else if (type & VIDTYPE_VIU_422) + r |= (1 << 12); + else + r |= (2 << 12); + } VSYNC_WR_MPEG_REG(VD2_AFBC_CONV_CTRL, r); u = (vf->bitdepth >> (BITDEPTH_U_SHIFT)) & 0x3; @@ -3746,67 +4773,73 @@ static void vd2_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) 0x3FF00000 | /*Y,bit20+*/ 0x80 << (u + 10) | 0x80 << v); + /* chroma formatter */ - /* TODO: afbc setting only cover 420 for now */ -#ifdef TV_REVERSE - if (reverse) { + r = HFORMATTER_EN | + (0x8 << VFORMATTER_PHASE_BIT) | + VFORMATTER_EN; #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION - if (is_meson_txlx_package_962X() + if (is_meson_txlx_package_962X() && !is_dolby_vision_stb_mode() && is_dolby_vision_on()) { - VSYNC_WR_MPEG_REG( - VD2_AFBC_VD_CFMT_CTRL, - HFORMATTER_REPEAT | - HFORMATTER_YC_RATIO_2_1 | - HFORMATTER_EN | - VFORMATTER_ALWAYS_RPT | - (0 << VFORMATTER_INIPHASE_BIT) | - (0x8 << VFORMATTER_PHASE_BIT) | - VFORMATTER_EN); - } else -#endif - VSYNC_WR_MPEG_REG(VD2_AFBC_VD_CFMT_CTRL, - (is_dolby_vision_on() ? - HFORMATTER_REPEAT : - HFORMATTER_RRT_PIXEL0) | - HFORMATTER_YC_RATIO_2_1 | - HFORMATTER_EN | - VFORMATTER_RPTLINE0_EN | - (is_dolby_vision_on() ? - (0xc << VFORMATTER_INIPHASE_BIT) : 0) | - (0x8 << VFORMATTER_PHASE_BIT) | - VFORMATTER_EN); - } else { -#endif -#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION - if (is_meson_txlx_package_962X() - && !is_dolby_vision_stb_mode() - && is_dolby_vision_on()) { - VSYNC_WR_MPEG_REG( - VD2_AFBC_VD_CFMT_CTRL, - HFORMATTER_REPEAT | - HFORMATTER_YC_RATIO_2_1 | - HFORMATTER_EN | - VFORMATTER_ALWAYS_RPT | - (0 << VFORMATTER_INIPHASE_BIT) | - (0x8 << VFORMATTER_PHASE_BIT) | - VFORMATTER_EN); - } else -#endif - VSYNC_WR_MPEG_REG(VD2_AFBC_VD_CFMT_CTRL, - (is_dolby_vision_on() ? - HFORMATTER_REPEAT : - HFORMATTER_RRT_PIXEL0) | + r |= HFORMATTER_REPEAT | HFORMATTER_YC_RATIO_2_1 | HFORMATTER_EN | - VFORMATTER_RPTLINE0_EN | - (is_dolby_vision_on() ? - (0xc << VFORMATTER_INIPHASE_BIT) : 0) | + VFORMATTER_ALWAYS_RPT | + (0 << VFORMATTER_INIPHASE_BIT) | (0x8 << VFORMATTER_PHASE_BIT) | - VFORMATTER_EN); -#ifdef TV_REVERSE - } + VFORMATTER_EN; + } else #endif + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) { + r = HFORMATTER_YC_RATIO_2_1 | + HFORMATTER_EN | + VFORMATTER_RPTLINE0_EN | + (0x8 << VFORMATTER_PHASE_BIT) | + VFORMATTER_EN; + + if (is_dolby_vision_on()) + r |= HFORMATTER_REPEAT | + (0xc << VFORMATTER_INIPHASE_BIT); + else + r |= HFORMATTER_RRT_PIXEL0 | + (0 << VFORMATTER_INIPHASE_BIT); + + if (type & VIDTYPE_VIU_444) { + r &= ~HFORMATTER_EN; + r &= ~VFORMATTER_EN; + r &= ~HFORMATTER_YC_RATIO_2_1; + } else if (type & VIDTYPE_VIU_422) { + r &= ~VFORMATTER_EN; + } + } else { + r = HFORMATTER_YC_RATIO_2_1 | + HFORMATTER_EN | + VFORMATTER_RPTLINE0_EN | + (0x8 << VFORMATTER_PHASE_BIT) | + VFORMATTER_EN; + if (is_dolby_vision_on()) + r |= HFORMATTER_REPEAT | + (0xc << VFORMATTER_INIPHASE_BIT); + else + r |= HFORMATTER_RRT_PIXEL0 | + (0 << VFORMATTER_INIPHASE_BIT); + } + VSYNC_WR_MPEG_REG(VD2_AFBC_VD_CFMT_CTRL, r); + + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) { + if (type & VIDTYPE_COMPRESS_LOSS) + VSYNC_WR_MPEG_REG( + VD2_AFBCDEC_IQUANT_ENABLE, + ((1 << 11) | + (1 << 10) | + (1 << 4) | + (1 << 0))); + else + VSYNC_WR_MPEG_REG( + VD2_AFBCDEC_IQUANT_ENABLE, 0); + } + vd2_path_select(true); VSYNC_WR_MPEG_REG(VD2_IF0_GEN_REG + cur_dev->viu_off, 0); @@ -3994,8 +5027,8 @@ static void vd2_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) } #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION if ((is_meson_txlx_cpu() - || is_meson_g12a_cpu() - || is_meson_g12b_cpu()) + || cpu_after_eq( + MESON_CPU_MAJOR_ID_G12A)) && is_dolby_vision_on() && is_dolby_vision_stb_mode() && (vf->source_type == @@ -4079,8 +5112,6 @@ static void vd2_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) } } -#if 1 /* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */ - static int detect_vout_type(void) { int vout_type = VOUT_TYPE_PROG; @@ -4106,37 +5137,6 @@ static int detect_vout_type(void) return vout_type; } -#else -static int detect_vout_type(void) -{ -#if defined(CONFIG_AM_TCON_OUTPUT) - return VOUT_TYPE_PROG; -#else - int vout_type; - int encp_enable = READ_VCBUS_REG(ENCP_VIDEO_EN) & 1; - - if (encp_enable) { - if (READ_VCBUS_REG(ENCP_VIDEO_MODE) & (1 << 12)) { - /* 1080I */ - if (READ_VCBUS_REG(VENC_ENCP_LINE) < 562) - vout_type = VOUT_TYPE_TOP_FIELD; - - else - vout_type = VOUT_TYPE_BOT_FIELD; - - } else - vout_type = VOUT_TYPE_PROG; - - } else { - vout_type = (READ_VCBUS_REG(VENC_STATA) & 1) ? - VOUT_TYPE_BOT_FIELD : VOUT_TYPE_TOP_FIELD; - } - - return vout_type; -#endif -} -#endif - #ifdef INTERLACE_FIELD_MATCH_PROCESS static inline bool interlace_field_type_need_match(int vout_type, struct vframe_s *vf) @@ -4201,10 +5201,13 @@ static inline void vpts_perform_pulldown(struct vframe_s *next_vf, { int pattern_range, expected_curr_interval; int expected_prev_interval; + int next_vf_nextpts = 0; /* Dont do anything if we have invalid data */ - if (!next_vf || !next_vf->pts || !next_vf->next_vf_pts_valid) + if (!next_vf || !next_vf->pts) return; + if (next_vf->next_vf_pts_valid) + next_vf_nextpts = next_vf->next_vf_pts; switch (pts_pattern_detected) { case PTS_32_PATTERN: @@ -4221,6 +5224,9 @@ static inline void vpts_perform_pulldown(struct vframe_s *next_vf, default: return; } + if (!next_vf_nextpts) + next_vf_nextpts = next_vf->pts + + PTS_32_PATTERN_DURATION; break; case PTS_22_PATTERN: if (pre_pts_trace != 2) @@ -4228,6 +5234,9 @@ static inline void vpts_perform_pulldown(struct vframe_s *next_vf, pattern_range = PTS_22_PATTERN_DETECT_RANGE; expected_prev_interval = 2; expected_curr_interval = 2; + if (!next_vf_nextpts) + next_vf_nextpts = next_vf->pts + + PTS_22_PATTERN_DURATION; break; case PTS_41_PATTERN: /* TODO */ @@ -4250,7 +5259,7 @@ static inline void vpts_perform_pulldown(struct vframe_s *next_vf, if (/*((int)(nextPts + expected_prev_interval * */ /*vsync_pts_inc - next_vf->next_vf_pts) < 0) && */ ((int)(nextPts + (expected_prev_interval + 1) * - vsync_pts_inc - next_vf->next_vf_pts) >= 0)) { + vsync_pts_inc - next_vf_nextpts) >= 0)) { *expired = false; if (pts_log_enable[PTS_32_PATTERN] || pts_log_enable[PTS_22_PATTERN]) @@ -4283,9 +5292,9 @@ static inline void vpts_perform_pulldown(struct vframe_s *next_vf, >= 0) && ((int)(nextPts + vsync_pts_inc * (expected_prev_interval - 1) - - next_vf->next_vf_pts) < 0) && + - next_vf_nextpts) < 0) && ((int)(nextPts + expected_prev_interval * - vsync_pts_inc - next_vf->next_vf_pts) >= 0)) { + vsync_pts_inc - next_vf_nextpts) >= 0)) { *expired = true; if (pts_log_enable[PTS_32_PATTERN] || pts_log_enable[PTS_22_PATTERN]) @@ -4410,11 +5419,13 @@ static inline bool vpts_expire(struct vframe_s *cur_vf, /* pts==0 is a keep frame maybe. */ if (systime > next_vf->pts || next_vf->pts == 0) return true; - if (omx_secret_mode == true) + if (omx_secret_mode == true + && cur_omx_index >= next_vf->omx_index) return true; return false; - } else if (omx_secret_mode == true) + } else if (omx_secret_mode == true + && cur_omx_index >= next_vf->omx_index) return true; } else if (omx_run && omx_secret_mode @@ -4716,29 +5727,27 @@ static inline bool video_vf_dirty_put(struct vframe_s *vf) if (!vf->frame_dirty) return false; if (cur_dispbuf != vf) { - if (vf->source_type != VFRAME_SOURCE_TYPE_OSD) { - if (vf->pts != 0) { - amlog_mask(LOG_MASK_TIMESTAMP, - "vpts to vf->pts:0x%x,scr:0x%x,abs_scr: 0x%x\n", - vf->pts, timestamp_pcrscr_get(), - READ_MPEG_REG(SCR_HIU)); - timestamp_vpts_set(vf->pts); - } else if (cur_dispbuf) { - amlog_mask(LOG_MASK_TIMESTAMP, - "vpts inc:0x%x,scr: 0x%x, abs_scr: 0x%x\n", - timestamp_vpts_get() + - DUR2PTS(cur_dispbuf->duration), - timestamp_pcrscr_get(), - READ_MPEG_REG(SCR_HIU)); - timestamp_vpts_inc( - DUR2PTS(cur_dispbuf->duration)); + if (vf->pts != 0) { + amlog_mask(LOG_MASK_TIMESTAMP, + "vpts to vf->pts:0x%x,scr:0x%x,abs_scr: 0x%x\n", + vf->pts, timestamp_pcrscr_get(), + READ_MPEG_REG(SCR_HIU)); + timestamp_vpts_set(vf->pts); + } else if (cur_dispbuf) { + amlog_mask(LOG_MASK_TIMESTAMP, + "vpts inc:0x%x,scr: 0x%x, abs_scr: 0x%x\n", + timestamp_vpts_get() + + DUR2PTS(cur_dispbuf->duration), + timestamp_pcrscr_get(), + READ_MPEG_REG(SCR_HIU)); + timestamp_vpts_inc( + DUR2PTS(cur_dispbuf->duration)); - vpts_remainder += - DUR2PTS_RM(cur_dispbuf->duration); - if (vpts_remainder >= 0xf) { - vpts_remainder -= 0xf; - timestamp_vpts_inc(-1); - } + vpts_remainder += + DUR2PTS_RM(cur_dispbuf->duration); + if (vpts_remainder >= 0xf) { + vpts_remainder -= 0xf; + timestamp_vpts_inc(-1); } } } @@ -5083,6 +6092,197 @@ void set_hdr_to_frame(struct vframe_s *vf) } #endif +static int vpp_zorder_check(void) +{ + int force_flush = 0; + u32 layer0_sel = 0; /* vd1 */ + u32 layer1_sel = 1; /* vd2 */ + + if (legacy_vpp) + return 0; + + if (glayer_info[1].zorder < glayer_info[0].zorder) { + layer0_sel = 1; + layer1_sel = 0; + if ((glayer_info[0].zorder >= reference_zorder) + && (glayer_info[1].zorder < reference_zorder)) + layer0_sel++; + } else { + layer0_sel = 0; + layer1_sel = 1; + if ((glayer_info[1].zorder >= reference_zorder) + && (glayer_info[0].zorder < reference_zorder)) + layer1_sel++; + } + + glayer_info[0].cur_sel_port = layer0_sel; + glayer_info[1].cur_sel_port = layer1_sel; + + if ((glayer_info[0].cur_sel_port != + glayer_info[0].last_sel_port) || + (glayer_info[1].cur_sel_port != + glayer_info[1].last_sel_port)) { + force_flush = 1; + glayer_info[0].last_sel_port = + glayer_info[0].cur_sel_port; + glayer_info[1].last_sel_port = + glayer_info[1].cur_sel_port; + } + return force_flush; +} + +static bool black_threshold_check(u8 id) +{ + struct disp_info_s *layer = NULL; + bool ret = false; + + if (id >= MAX_VD_LAYERS) + return ret; + + if ((black_threshold_width <= 0) + || (black_threshold_height <= 0)) + return ret; + + layer = &glayer_info[id]; + if ((layer->layer_top == 0) + && (layer->layer_left == 0) + && (layer->layer_width <= 1) + && (layer->layer_height <= 1)) + /* special case to do full screen display */ + return ret; + + if ((layer->layer_width <= black_threshold_width) + || (layer->layer_height <= black_threshold_height)) + ret = true; + return ret; +} + +#ifdef TV_3D_FUNCTION_OPEN +inline void switch_3dView_per_vsync(void) +{ + u32 start_aligned, end_aligned, block_len; + u32 FA_enable = process_3d_type & MODE_3D_OUT_FA_MASK; + + if (FA_enable && (toggle_3d_fa_frame == OUT_FA_A_FRAME)) { + VSYNC_WR_MPEG_REG_BITS(VPP_MISC + + cur_dev->vpp_off, 1, 14, 1); + /* VPP_VD1_PREBLEND disable */ + VSYNC_WR_MPEG_REG_BITS(VPP_MISC + + cur_dev->vpp_off, 1, 10, 1); + /* VPP_VD1_POSTBLEND disable */ + VSYNC_WR_MPEG_REG(VD1_IF0_LUMA_PSEL + + cur_dev->viu_off, 0x4000000); + VSYNC_WR_MPEG_REG(VD1_IF0_CHROMA_PSEL + + cur_dev->viu_off, 0x4000000); + VSYNC_WR_MPEG_REG(VD2_IF0_LUMA_PSEL + + cur_dev->viu_off, 0x4000000); + VSYNC_WR_MPEG_REG(VD2_IF0_CHROMA_PSEL + + cur_dev->viu_off, 0x4000000); + if (cur_dispbuf->type & VIDTYPE_COMPRESS) { + if ((process_3d_type & MODE_FORCE_3D_FA_LR) + && (cur_frame_par->vpp_3d_mode == 1)) { + start_aligned = ori_start_x_lines; + end_aligned = ori_end_x_lines + 1; + block_len = + (end_aligned - start_aligned) / 2; + block_len = block_len / + (cur_frame_par->hscale_skip_count + 1); + VSYNC_WR_MPEG_REG(AFBC_PIXEL_HOR_SCOPE, + (start_aligned << 16) | + (start_aligned + block_len - 1)); + } + if ((process_3d_type & MODE_FORCE_3D_FA_TB) + && (cur_frame_par->vpp_3d_mode == 2)) { + start_aligned = + round_down(ori_start_y_lines, 4); + end_aligned = + round_up(ori_end_y_lines + 1, 4); + block_len = end_aligned - start_aligned; + block_len = block_len / 8; + VSYNC_WR_MPEG_REG(AFBC_MIF_VER_SCOPE, + ((start_aligned / 4) << 16) | + ((start_aligned / 4) + block_len - 1)); + } + } + } else if (FA_enable && + (toggle_3d_fa_frame == OUT_FA_B_FRAME)) { + VSYNC_WR_MPEG_REG_BITS(VPP_MISC + + cur_dev->vpp_off, 1, 14, 1); + /* VPP_VD1_PREBLEND disable */ + VSYNC_WR_MPEG_REG_BITS(VPP_MISC + + cur_dev->vpp_off, 1, 10, 1); + /* VPP_VD1_POSTBLEND disable */ + VSYNC_WR_MPEG_REG(VD1_IF0_LUMA_PSEL + + cur_dev->viu_off, 0); + VSYNC_WR_MPEG_REG(VD1_IF0_CHROMA_PSEL + + cur_dev->viu_off, 0); + VSYNC_WR_MPEG_REG(VD2_IF0_LUMA_PSEL + + cur_dev->viu_off, 0); + VSYNC_WR_MPEG_REG(VD2_IF0_CHROMA_PSEL + + cur_dev->viu_off, 0); + if (cur_dispbuf->type & VIDTYPE_COMPRESS) { + if ((process_3d_type & MODE_FORCE_3D_FA_LR) + && (cur_frame_par->vpp_3d_mode == 1)) { + start_aligned = ori_start_x_lines; + end_aligned = ori_end_x_lines + 1; + block_len = + (end_aligned - start_aligned) / 2; + block_len = block_len / + (cur_frame_par->hscale_skip_count + 1); + VSYNC_WR_MPEG_REG(AFBC_PIXEL_HOR_SCOPE, + ((start_aligned + block_len) << 16) | + (end_aligned - 1)); + } + if ((process_3d_type & MODE_FORCE_3D_FA_TB) + && (cur_frame_par->vpp_3d_mode == 2)) { + start_aligned = + round_down(ori_start_y_lines, 4); + end_aligned = + round_up(ori_end_y_lines + 1, 4); + block_len = end_aligned - start_aligned; + block_len = block_len / 8; + VSYNC_WR_MPEG_REG(AFBC_MIF_VER_SCOPE, + (((start_aligned / 4) + block_len) << 16) | + ((end_aligned / 4) - 1)); + } + } + } else if (FA_enable && + (toggle_3d_fa_frame == OUT_FA_BANK_FRAME)) { + /* output a banking frame */ + VSYNC_WR_MPEG_REG_BITS(VPP_MISC + + cur_dev->vpp_off, 0, 14, 1); + /* VPP_VD1_PREBLEND disable */ + VSYNC_WR_MPEG_REG_BITS(VPP_MISC + + cur_dev->vpp_off, 0, 10, 1); + /* VPP_VD1_POSTBLEND disable */ + } + + if ((process_3d_type & MODE_3D_OUT_TB) + || (process_3d_type & MODE_3D_OUT_LR)) { + if (cur_frame_par->vpp_2pic_mode & + VPP_PIC1_FIRST) { + VSYNC_WR_MPEG_REG(VD1_IF0_LUMA_PSEL + + cur_dev->viu_off, 0x4000000); + VSYNC_WR_MPEG_REG(VD1_IF0_CHROMA_PSEL + + cur_dev->viu_off, 0x4000000); + VSYNC_WR_MPEG_REG(VD2_IF0_LUMA_PSEL + + cur_dev->viu_off, 0); + VSYNC_WR_MPEG_REG(VD2_IF0_CHROMA_PSEL + + cur_dev->viu_off, 0); + } else { + VSYNC_WR_MPEG_REG(VD1_IF0_LUMA_PSEL + + cur_dev->viu_off, 0); + VSYNC_WR_MPEG_REG(VD1_IF0_CHROMA_PSEL + + cur_dev->viu_off, 0); + VSYNC_WR_MPEG_REG(VD2_IF0_LUMA_PSEL + + cur_dev->viu_off, 0x4000000); + VSYNC_WR_MPEG_REG(VD2_IF0_CHROMA_PSEL + + cur_dev->viu_off, 0x4000000); + } + } +} +#endif + #ifdef FIQ_VSYNC void vsync_fisr_in(void) #else @@ -5109,10 +6309,83 @@ static irqreturn_t vsync_isr_in(int irq, void *dev_id) int video2_off_req = 0; struct vframe_s *cur_dispbuf_back = cur_dispbuf; static struct vframe_s *pause_vf; + int force_flush = 0; + static u32 interrupt_count; if (debug_flag & DEBUG_FLAG_VSYNC_DONONE) return IRQ_HANDLED; + if (frame_detect_flag == 1 && + receive_frame_count && + frame_detect_time && + !atomic_read(&video_unreg_flag)) { + struct vinfo_s *video_info; + + video_info = get_current_vinfo(); + if (video_frame_detect.interrupt_count == 0) { + interrupt_count = 0; + video_frame_detect.interrupt_count = + frame_detect_time * + video_info->sync_duration_num / + video_info->sync_duration_den; + if (debug_flag & DEBUG_FLAG_FRAME_DETECT) { + pr_info("sync_duration_num = %d\n", + video_info->sync_duration_num); + pr_info("sync_duration_den = %d\n", + video_info->sync_duration_den); + } + video_frame_detect.start_receive_count = + receive_frame_count; + } + + interrupt_count++; + + if (interrupt_count == video_frame_detect.interrupt_count + 1) { + u32 receive_count; + u32 expect_frame_count; + + receive_count = receive_frame_count - + video_frame_detect.start_receive_count; + expect_frame_count = + video_frame_detect.interrupt_count * + frame_detect_fps * + video_info->sync_duration_den / + video_info->sync_duration_num / + 1000; + + if (receive_count < expect_frame_count) { + frame_detect_drop_count += + expect_frame_count - + receive_count; + if (debug_flag & DEBUG_FLAG_FRAME_DETECT) { + pr_info("drop_count = %d\n", + expect_frame_count - + receive_count); + } + frame_detect_receive_count += + expect_frame_count; + } else + frame_detect_receive_count += receive_count; + + if (debug_flag & DEBUG_FLAG_FRAME_DETECT) { + pr_info("expect count = %d\n", + expect_frame_count); + pr_info("receive_count = %d, time = %ds\n", + receive_count, + frame_detect_time); + pr_info("interrupt_count = %d\n", + video_frame_detect.interrupt_count); + pr_info("frame_detect_drop_count = %d\n", + frame_detect_drop_count); + pr_info("frame_detect_receive_count = %d\n", + frame_detect_receive_count); + } + interrupt_count = 0; + memset(&video_frame_detect, 0, + sizeof(struct video_frame_detect_s)); + } + } + #ifdef CONFIG_SUPPORT_VIDEO_ON_VPP2 const char *dev_id_s = (const char *)dev_id; int dev_id_len = strlen(dev_id_s); @@ -5126,7 +6399,7 @@ static irqreturn_t vsync_isr_in(int irq, void *dev_id) vinfo->sync_duration_num; vsync_pts_inc_scale = vinfo->sync_duration_den; vsync_pts_inc_scale_base = vinfo->sync_duration_num; - video_property_changed = true; + video_property_changed = 1; pr_info("Change to video 0\n"); } } else { @@ -5138,7 +6411,7 @@ static irqreturn_t vsync_isr_in(int irq, void *dev_id) vinfo->sync_duration_num; vsync_pts_inc_scale = vinfo->sync_duration_den; vsync_pts_inc_scale_base = vinfo->sync_duration_num; - video_property_changed = true; + video_property_changed = 1; pr_info("Change to video 1\n"); } } @@ -5184,7 +6457,7 @@ static irqreturn_t vsync_isr_in(int irq, void *dev_id) if ((vf) && ((vf->type & VIDTYPE_NO_VIDEO_ENABLE) == 0)) { if ((old_vmode != new_vmode) || (debug_flag == 8)) { debug_flag = 1; - video_property_changed = true; + video_property_changed = 1; pr_info("detect vout mode change!!!!!!!!!!!!\n"); old_vmode = new_vmode; } @@ -5290,6 +6563,8 @@ static irqreturn_t vsync_isr_in(int irq, void *dev_id) timestamp_pcrscr_inc_scale(vsync_pts_inc_scale, vsync_pts_inc_scale_base); timestamp_apts_inc(vsync_pts_inc / vsync_slow_factor); + videosync_pcrscr_update(vsync_pts_inc_scale, + vsync_pts_inc_scale_base); } else if (vsync_slow_factor > 1000) { u32 inc = (vsync_slow_factor / 1000) * vsync_pts_inc / 1000; @@ -5302,11 +6577,24 @@ static irqreturn_t vsync_isr_in(int irq, void *dev_id) } } if (omx_secret_mode == true) { + int diff = 0; + unsigned long delta1 = 0; + u32 system_time = timestamp_pcrscr_get(); - int diff = system_time - omx_pts; video_notify_flag |= VIDEO_NOTIFY_TRICK_WAIT; atomic_set(&trickmode_framedone, 1); + diff = system_time - omx_pts; + if (time_setomxpts.tv_sec > 0) { + struct timeval now; + + do_gettimeofday(&now); + delta1 = (now.tv_sec - time_setomxpts.tv_sec) + * 1000000LL + + (now.tv_usec - time_setomxpts.tv_usec); + diff -= delta1 * 90 / 1000; + } + if ((diff - omx_pts_interval_upper) > 0 || (diff - omx_pts_interval_lower) < 0 || (omx_pts_set_from_hwc_count < @@ -5349,25 +6637,21 @@ static irqreturn_t vsync_isr_in(int irq, void *dev_id) goto exit; #ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA - if (is_vsync_rdma_enable()) + if (is_vsync_rdma_enable()) { rdma_canvas_id = next_rdma_canvas_id; - else { - if (rdma_enable_pre) { - /*do not write register directly before RDMA is done */ - /*#if MESON_CPU_TYPE == MESON_CPU_TYPE_MESON6TV */ - if (is_meson_mtvd_cpu()) { - if (debug_flag & DEBUG_FLAG_RDMA_WAIT_1) { - while - ( - ((READ_VCBUS_REG(ENCL_INFO_READ) >> 16) - & 0x1fff) < 50); - } - } - /* #endif */ +#ifdef VIDEO_PIP + pip_rdma_canvas_id = pip_next_rdma_canvas_id; +#endif + } else { + if (rdma_enable_pre) goto exit; - } + rdma_canvas_id = 0; next_rdma_canvas_id = 1; +#ifdef VIDEO_PIP + pip_rdma_canvas_id = 0; + pip_next_rdma_canvas_id = 1; +#endif } for (i = 0; i < dispbuf_to_put_num; i++) { @@ -5377,21 +6661,13 @@ static irqreturn_t vsync_isr_in(int irq, void *dev_id) } dispbuf_to_put_num = 0; } -#endif - - if (osd_prov && osd_prov->ops && osd_prov->ops->get) { - vf = osd_prov->ops->get(osd_prov->op_arg); - if (vf) { - vf->source_type = VFRAME_SOURCE_TYPE_OSD; - vsync_toggle_frame(vf); - if (debug_flag & DEBUG_FLAG_BLACKOUT) { - pr_info - ("[video4osd] toggle osd_vframe {%d,%d}\n", - vf->width, vf->height); - } - goto SET_FILTER; - } +#ifdef VIDEO_PIP + if (pipbuf_to_put) { + pip_vf_put(pipbuf_to_put); + pipbuf_to_put = NULL; } +#endif +#endif if ((!cur_dispbuf) || (cur_dispbuf == &vf_local)) { @@ -5438,9 +6714,9 @@ static irqreturn_t vsync_isr_in(int irq, void *dev_id) cur_index; } } - vsync_toggle_frame(cur_dispbuf); + vsync_toggle_frame(cur_dispbuf, __LINE__); } else - video_property_changed = false; + video_property_changed = 0; } else { goto SET_FILTER; } @@ -5451,11 +6727,12 @@ static irqreturn_t vsync_isr_in(int irq, void *dev_id) /* setting video display property in underflow mode */ if ((!vf) && cur_dispbuf && (video_property_changed)) - vsync_toggle_frame(cur_dispbuf); + vsync_toggle_frame(cur_dispbuf, __LINE__); /*debug info for skip & repeate vframe case*/ if (!vf) { underflow++; + ATRACE_COUNTER("underflow", 1); if (video_dbg_vf&(1<<0)) dump_vframe_status("vdin0"); if (video_dbg_vf&(1<<1)) @@ -5466,6 +6743,8 @@ static irqreturn_t vsync_isr_in(int irq, void *dev_id) dump_vframe_status("ppmgr"); if (video_dbg_vf&(1<<4)) dump_vdin_reg(); + } else { + ATRACE_COUNTER("underflow", 0); } video_get_vf_cnt = 0; if (platform_type == 1) { @@ -5475,13 +6754,15 @@ static irqreturn_t vsync_isr_in(int irq, void *dev_id) } while (vf) { if (vpts_expire(cur_dispbuf, vf, toggle_cnt) || show_nosync) { + ATRACE_COUNTER(MODULE_NAME, __LINE__); if (debug_flag & DEBUG_FLAG_PTS_TRACE) pr_info("vpts = 0x%x, c.dur=0x%x, n.pts=0x%x, scr = 0x%x, pcr-pts-diff=%d, ptstrace=%d\n", timestamp_vpts_get(), (cur_dispbuf) ? cur_dispbuf->duration : 0, vf->pts, timestamp_pcrscr_get(), - timestamp_pcrscr_get() - vf->pts, + timestamp_pcrscr_get() - vf->pts + + vsync_pts_align, pts_trace); amlog_mask_if(toggle_cnt > 0, LOG_MASK_FRAMESKIP, "skipped\n"); @@ -5524,8 +6805,10 @@ static irqreturn_t vsync_isr_in(int irq, void *dev_id) hdmiin_frame_check_cnt = 0; vf = video_vf_get(); - if (!vf) + if (!vf) { + ATRACE_COUNTER(MODULE_NAME, __LINE__); break; + } if (debug_flag & DEBUG_FLAG_LATENCY) { vf->ready_clock[2] = sched_clock(); pr_info("video get latency %lld ms vdin put latency %lld ms. first %lld ms.\n", @@ -5533,8 +6816,10 @@ static irqreturn_t vsync_isr_in(int irq, void *dev_id) func_div(vf->ready_clock[1], 1000), func_div(vf->ready_clock[0], 1000)); } - if (video_vf_dirty_put(vf)) + if (video_vf_dirty_put(vf)) { + ATRACE_COUNTER(MODULE_NAME, __LINE__); break; + } if (vf && hdmiin_frame_check && (vf->source_type == VFRAME_SOURCE_TYPE_HDMI) && video_vf_disp_mode_check(vf)) @@ -5552,7 +6837,7 @@ static irqreturn_t vsync_isr_in(int irq, void *dev_id) video_3d_format = vf->trans_fmt; } } - vsync_toggle_frame(vf); + vsync_toggle_frame(vf, __LINE__); toggle_frame = vf; #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION if (is_dolby_vision_enable()) { @@ -5599,6 +6884,7 @@ static irqreturn_t vsync_isr_in(int irq, void *dev_id) if (video_get_vf_cnt >= 2) video_drop_vf_cnt++; } else { + ATRACE_COUNTER(MODULE_NAME, __LINE__); /* check if current frame's duration has expired, *in this example * it compares current frame display duration @@ -5610,6 +6896,7 @@ static irqreturn_t vsync_isr_in(int irq, void *dev_id) * The playback can be smoother than previous method. */ if (slowsync_repeat_enable) { + ATRACE_COUNTER(MODULE_NAME, __LINE__); if (duration_expire (cur_dispbuf, vf, frame_repeat_count * vsync_pts_inc) @@ -5641,9 +6928,12 @@ static irqreturn_t vsync_isr_in(int irq, void *dev_id) break; #endif vf = video_vf_get(); - if (!vf) + if (!vf) { + ATRACE_COUNTER(MODULE_NAME, + __LINE__); break; - vsync_toggle_frame(vf); + } + vsync_toggle_frame(vf, __LINE__); toggle_frame = vf; #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION if (is_dolby_vision_enable()) @@ -5676,9 +6966,11 @@ static irqreturn_t vsync_isr_in(int irq, void *dev_id) if (blackout | force_blackout) { if (cur_dispbuf != &vf_local) vsync_toggle_frame( - cur_dispbuf); + cur_dispbuf, + __LINE__); } else - vsync_toggle_frame(cur_dispbuf); + vsync_toggle_frame(cur_dispbuf, + __LINE__); if (is_dolby_vision_enable()) { pause_vf = cur_dispbuf; video_pause_global = 1; @@ -5713,6 +7005,21 @@ static irqreturn_t vsync_isr_in(int irq, void *dev_id) #endif SET_FILTER: +#ifdef VIDEO_PIP + vf = pip_vf_peek(); + /* setting video display property in underflow mode */ + if ((!vf) && cur_pipbuf && (pip_property_changed)) + pip_toggle_frame(cur_pipbuf); + if (vf) { + vf = pip_vf_get(); + if (vf) { + if (!vf->frame_dirty) + pip_toggle_frame(vf); + else + pip_vf_put(vf); + } + } +#endif #if defined(CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM) amvecm_on_vs( (cur_dispbuf != &vf_local) @@ -5849,183 +7156,195 @@ SET_FILTER: last_el_status = 0; } } - { -#if 0 - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXBB) { - if (cur_dispbuf->type & VIDTYPE_COMPRESS) { - /*SET_VCBUS_REG_MASK(VIU_MISC_CTRL0,*/ - /*VIU_MISC_AFBC_VD1);*/ - VSYNC_WR_MPEG_REG_BITS(VIU_MISC_CTRL0 + - cur_dev->viu_off, 1, 20, 1); - } else { - /*CLEAR_VCBUS_REG_MASK(VIU_MISC_CTRL0,*/ - /*VIU_MISC_AFBC_VD1);*/ - VSYNC_WR_MPEG_REG_BITS(VIU_MISC_CTRL0 + - cur_dev->viu_off, 0, 20, 1); - } - } + + if (cur_frame_par && + cur_frame_par->hscale_skip_count) { + VSYNC_WR_MPEG_REG_BITS(VIU_VD1_FMT_CTRL + + cur_dev->viu_off, 1, 20, 1); + /* HFORMATTER_EN */ +#ifdef VIDEO_PIP + if (!cur_pipbuf) #endif - - if (platform_type == 1) { - if (cur_frame_par && cur_frame_par->hscale_skip_count) { - VSYNC_WR_MPEG_REG_BITS(VIU_VD1_FMT_CTRL + - cur_dev->viu_off, 1, 20, 1); - /* HFORMATTER_EN */ - VSYNC_WR_MPEG_REG_BITS(VIU_VD2_FMT_CTRL + - cur_dev->viu_off, 1, 20, 1); - /* HFORMATTER_EN */ - } - if (process_3d_type & MODE_3D_OUT_FA_MASK) { - if (toggle_3d_fa_frame == OUT_FA_A_FRAME) { - VSYNC_WR_MPEG_REG_BITS(VPP_MISC + - cur_dev->vpp_off, 1, 14, 1); - /* VPP_VD1_PREBLEND disable */ - VSYNC_WR_MPEG_REG_BITS(VPP_MISC + - cur_dev->vpp_off, 1, 10, 1); - /* VPP_VD1_POSTBLEND disable */ - VSYNC_WR_MPEG_REG(VD1_IF0_LUMA_PSEL + - cur_dev->viu_off, 0x4000000); - VSYNC_WR_MPEG_REG(VD1_IF0_CHROMA_PSEL + - cur_dev->viu_off, 0x4000000); - VSYNC_WR_MPEG_REG(VD2_IF0_LUMA_PSEL + - cur_dev->viu_off, 0x4000000); - VSYNC_WR_MPEG_REG(VD2_IF0_CHROMA_PSEL + - cur_dev->viu_off, 0x4000000); - } else if (OUT_FA_B_FRAME == - toggle_3d_fa_frame) { - VSYNC_WR_MPEG_REG_BITS(VPP_MISC + - cur_dev->vpp_off, 1, 14, 1); - /* VPP_VD1_PREBLEND disable */ - VSYNC_WR_MPEG_REG_BITS(VPP_MISC + - cur_dev->vpp_off, 1, 10, 1); - /* VPP_VD1_POSTBLEND disable */ - VSYNC_WR_MPEG_REG(VD1_IF0_LUMA_PSEL + - cur_dev->viu_off, 0); - VSYNC_WR_MPEG_REG(VD1_IF0_CHROMA_PSEL + - cur_dev->viu_off, 0); - VSYNC_WR_MPEG_REG( - VD2_IF0_LUMA_PSEL + - cur_dev->viu_off, 0); - VSYNC_WR_MPEG_REG( - VD2_IF0_CHROMA_PSEL + - cur_dev->viu_off, 0); - } else if (toggle_3d_fa_frame == - OUT_FA_BANK_FRAME) { - /* output a banking frame */ - VSYNC_WR_MPEG_REG_BITS(VPP_MISC + - cur_dev->vpp_off, 0, 14, 1); - /* VPP_VD1_PREBLEND disable */ - VSYNC_WR_MPEG_REG_BITS(VPP_MISC + - cur_dev->vpp_off, 0, 10, 1); - /* VPP_VD1_POSTBLEND disable */ - } - } - if ((process_3d_type & MODE_3D_OUT_TB) - || (process_3d_type & MODE_3D_OUT_LR)) { - if (cur_frame_par && - (cur_frame_par->vpp_2pic_mode & - VPP_PIC1_FIRST)) { - VSYNC_WR_MPEG_REG(VD1_IF0_LUMA_PSEL + - cur_dev->viu_off, 0x4000000); - VSYNC_WR_MPEG_REG(VD1_IF0_CHROMA_PSEL + - cur_dev->viu_off, 0x4000000); - VSYNC_WR_MPEG_REG(VD2_IF0_LUMA_PSEL + - cur_dev->viu_off, 0); - VSYNC_WR_MPEG_REG(VD2_IF0_CHROMA_PSEL + - cur_dev->viu_off, 0); - } else { - VSYNC_WR_MPEG_REG(VD1_IF0_LUMA_PSEL + - cur_dev->viu_off, 0); - VSYNC_WR_MPEG_REG(VD1_IF0_CHROMA_PSEL + - cur_dev->viu_off, 0); - VSYNC_WR_MPEG_REG(VD2_IF0_LUMA_PSEL + - cur_dev->viu_off, 0x4000000); - VSYNC_WR_MPEG_REG(VD2_IF0_CHROMA_PSEL + - cur_dev->viu_off, 0x4000000); - } -/* - *VSYNC_WR_MPEG_REG_BITS(VPP_MISC + - *cur_dev->vpp_off,1,15,1);//VPP_VD2_PREBLEND enable - *VSYNC_WR_MPEG_REG_BITS(VPP_MISC + - *cur_dev->vpp_off,1,11,1);//VPP_VD2_POSTBLEND enable - *VSYNC_WR_MPEG_REG_BITS(VPP_MISC + - *cur_dev->vpp_off,1,6,1);//PREBLEND enable must be set! - *VSYNC_WR_MPEG_REG_BITS(VPP_MISC + - *cur_dev->vpp_off,0x1ff, - *VPP_VD2_ALPHA_BIT,9);//vd2 alpha must set - */ - } - -/* - *else{ - *VSYNC_WR_MPEG_REG_BITS(VPP_MISC + - *cur_dev->vpp_off,0,15,1);//VPP_VD2_PREBLEND enable - *VSYNC_WR_MPEG_REG_BITS(VPP_MISC + - *cur_dev->vpp_off,1,11,1);//VPP_VD2_POSTBLEND enable - *VSYNC_WR_MPEG_REG_BITS(VPP_MISC + - *cur_dev->vpp_off,0,6,1);//PREBLEND enable - *VSYNC_WR_MPEG_REG_BITS(VPP_MISC + - *cur_dev->vpp_off,0,VPP_VD2_ALPHA_BIT,9);//vd2 alpha must set - *} - */ + VSYNC_WR_MPEG_REG_BITS(VIU_VD2_FMT_CTRL + + cur_dev->viu_off, 1, 20, 1); + /* HFORMATTER_EN */ } - /* vertical phase */ - vphase = - &cur_frame_par->VPP_vf_ini_phase_ + +#ifdef TV_3D_FUNCTION_OPEN + switch_3dView_per_vsync(); +#endif + /* vertical phase */ + vphase = &cur_frame_par->VPP_vf_ini_phase_ [vpp_phase_table[vin_type] [vout_type]]; - VSYNC_WR_MPEG_REG(VPP_VSC_INI_PHASE + cur_dev->vpp_off, - ((u32) (vphase->phase) << 8)); + VSYNC_WR_MPEG_REG( + VPP_VSC_INI_PHASE + cur_dev->vpp_off, + ((u32) (vphase->phase) << 8)); - if (vphase->repeat_skip >= 0) { - /* skip lines */ - VSYNC_WR_MPEG_REG_BITS(VPP_VSC_PHASE_CTRL + + if (vphase->repeat_skip >= 0) { + /* skip lines */ + VSYNC_WR_MPEG_REG_BITS(VPP_VSC_PHASE_CTRL + cur_dev->vpp_off, skip_tab[vphase->repeat_skip], VPP_PHASECTL_INIRCVNUMT_BIT, VPP_PHASECTL_INIRCVNUM_WID + VPP_PHASECTL_INIRPTNUM_WID); - - } else { - /* repeat first line */ - VSYNC_WR_MPEG_REG_BITS(VPP_VSC_PHASE_CTRL + + } else { + /* repeat first line */ + VSYNC_WR_MPEG_REG_BITS(VPP_VSC_PHASE_CTRL + cur_dev->vpp_off, 4, VPP_PHASECTL_INIRCVNUMT_BIT, VPP_PHASECTL_INIRCVNUM_WID); - VSYNC_WR_MPEG_REG_BITS(VPP_VSC_PHASE_CTRL + + VSYNC_WR_MPEG_REG_BITS(VPP_VSC_PHASE_CTRL + cur_dev->vpp_off, 1 - vphase->repeat_skip, VPP_PHASECTL_INIRPTNUMT_BIT, VPP_PHASECTL_INIRPTNUM_WID); - } - if (platform_type == 1) { - if (force_3d_scaler == 3 && - cur_frame_par && - cur_frame_par->vpp_3d_scale) { - VSYNC_WR_MPEG_REG_BITS( - VPP_VSC_PHASE_CTRL, 3, - VPP_PHASECTL_DOUBLELINE_BIT, 2); - } else if (force_3d_scaler == 1 && - cur_frame_par && - cur_frame_par->vpp_3d_scale) { - VSYNC_WR_MPEG_REG_BITS( - VPP_VSC_PHASE_CTRL, 1, - VPP_PHASECTL_DOUBLELINE_BIT, - VPP_PHASECTL_DOUBLELINE_WID); - } else if (force_3d_scaler == 2 && - cur_frame_par && - cur_frame_par->vpp_3d_scale) { - VSYNC_WR_MPEG_REG_BITS( - VPP_VSC_PHASE_CTRL, 2, - VPP_PHASECTL_DOUBLELINE_BIT, 2); - } else { - VSYNC_WR_MPEG_REG_BITS( - VPP_VSC_PHASE_CTRL, 0, - VPP_PHASECTL_DOUBLELINE_BIT, 2); - } - } + } + if (force_3d_scaler == 3 && + cur_frame_par && + cur_frame_par->vpp_3d_scale) { + VSYNC_WR_MPEG_REG_BITS( + VPP_VSC_PHASE_CTRL, 3, + VPP_PHASECTL_DOUBLELINE_BIT, 2); + } else if (force_3d_scaler == 1 && + cur_frame_par && + cur_frame_par->vpp_3d_scale) { + VSYNC_WR_MPEG_REG_BITS( + VPP_VSC_PHASE_CTRL, 1, + VPP_PHASECTL_DOUBLELINE_BIT, + VPP_PHASECTL_DOUBLELINE_WID); + } else if (force_3d_scaler == 2 && + cur_frame_par && + cur_frame_par->vpp_3d_scale) { + VSYNC_WR_MPEG_REG_BITS( + VPP_VSC_PHASE_CTRL, 2, + VPP_PHASECTL_DOUBLELINE_BIT, 2); + } else { + VSYNC_WR_MPEG_REG_BITS( + VPP_VSC_PHASE_CTRL, 0, + VPP_PHASECTL_DOUBLELINE_BIT, 2); } } +#ifdef VIDEO_PIP + if (pip_frame_ready_to_set) + curpip_frame_par = nextpip_frame_par; + + if (cur_pipbuf) { + int need_afbc = (cur_pipbuf->type & VIDTYPE_COMPRESS); + int afbc_need_reset = + video2_enabled && + need_afbc && + (!(READ_VCBUS_REG(VD2_AFBC_ENABLE) & 0x100)); + /*video on && afbc is off && is compress frame.*/ + if (pip_frame_ready_to_set || afbc_need_reset) + pip_set_dcu(curpip_frame_par, cur_pipbuf); + + if (cur_pipbuf && curpip_frame_par) { + if (curpip_frame_par->hscale_skip_count) { + VSYNC_WR_MPEG_REG_BITS( + VIU_VD2_FMT_CTRL + + cur_dev->viu_off, 1, 20, 1); + /* HFORMATTER_EN */ + } + proc_vd2_vsc_phase_per_vsync( + curpip_frame_par, cur_pipbuf, vout_type); + } + } + + if (pip_frame_ready_to_set) { +#if 0 + u32 h_size, v_size; + + if (pip_start_x_lines < pip_end_x_lines) + h_size = pip_end_x_lines - pip_start_x_lines + 1; + else + h_size = ori2_end_x_lines - ori2_start_x_lines + 1; + + if (pip_start_y_lines < pip_end_y_lines) + v_size = pip_end_y_lines - pip_start_y_lines + 1; + else + v_size = ori2_end_y_lines - ori2_start_y_lines + 1; + + zoom2_start_x_lines = ori2_start_x_lines; + zoom2_end_x_lines = ori2_end_x_lines; + zoom2_start_y_lines = ori2_start_y_lines; + zoom2_end_y_lines = ori2_end_y_lines; + + if (h_size < (zoom2_end_x_lines - zoom2_start_x_lines + 1)) + zoom2_end_x_lines = zoom2_start_x_lines + h_size - 1; + else if (h_size > (zoom2_end_x_lines - zoom2_start_x_lines + 1)) + h_size = zoom2_end_x_lines - zoom2_start_x_lines + 1; + + if (v_size < (zoom2_end_y_lines - zoom2_start_y_lines + 1)) + zoom2_end_y_lines = zoom2_start_y_lines + v_size - 1; + else if (v_size > (zoom2_end_y_lines - zoom2_start_y_lines + 1)) + v_size = (zoom2_end_y_lines - zoom2_start_y_lines + 1); + + if (vinfo) { + if (pip_start_x_lines + h_size > vinfo->width) { + h_size = vinfo->width - pip_start_x_lines; + zoom2_end_x_lines = + zoom2_start_x_lines + h_size - 1; + } + if (pip_start_y_lines + v_size > vinfo->height) { + v_size = vinfo->height - pip_start_y_lines; + zoom2_end_y_lines = + zoom2_start_y_lines + v_size - 1; + } + } +#endif + struct scaler_setting_s local_pps; + struct blend_setting_s local_blend; + struct vpp_frame_par_s *par = curpip_frame_par; + + if (cur_pipbuf->type & VIDTYPE_INTERLACE) { + if (cur_pipbuf->type & VIDTYPE_VIU_FIELD) { + zoom2_start_y_lines = + par->VPP_vd_start_lines_ >> 1; + zoom2_end_y_lines = + ((par->VPP_vd_end_lines_ + 1) + >> 1) - 1; + } else { + zoom2_start_y_lines = + par->VPP_vd_start_lines_; + zoom2_end_y_lines = + par->VPP_vd_end_lines_; + } + } else { + if (cur_pipbuf->type & VIDTYPE_VIU_FIELD) { + zoom2_start_y_lines = + par->VPP_vd_start_lines_; + zoom2_end_y_lines = + par->VPP_vd_end_lines_; + } else { + zoom2_start_y_lines = + par->VPP_vd_start_lines_ >> 1; + zoom2_end_y_lines = + ((par->VPP_vd_end_lines_ + 1) + >> 1) - 1; + } + } + zoom2_start_x_lines = + par->VPP_hd_start_lines_; + zoom2_end_x_lines = + par->VPP_hd_end_lines_; + config_vd_pps( + 1, par, &local_pps, vinfo); + config_vd_blend( + 1, par, cur_pipbuf, + (legacy_vpp ? 0x1ff : 0x100), &local_blend); + vd2_scaler_setting(&local_pps); + vd2_zoom_display_horz( + cur_pipbuf, + par->hscale_skip_count); + vd2_zoom_display_vert( + cur_pipbuf, + par->vscale_skip_count); + vd2_vpp_blend_setting(&local_blend); + pip_frame_ready_to_set = 0; + } +#endif if (((frame_par_ready_to_set) || (frame_par_force_to_set)) && (cur_frame_par)) { @@ -6036,7 +7355,15 @@ SET_FILTER: u32 zoom_start_y, zoom_end_y; correct_vd1_mif_size_for_DV(cur_frame_par); if (cur_dispbuf->type & VIDTYPE_INTERLACE) { - if (cur_dispbuf->type & VIDTYPE_VIU_FIELD) { + if (cur_dispbuf->type + & VIDTYPE_COMPRESS) { + /* for vdin afbc and interlace case */ + zoom_start_y = + cur_frame_par->VPP_vd_start_lines_; + zoom_end_y = + cur_frame_par->VPP_vd_end_lines_; + } else if (cur_dispbuf->type + & VIDTYPE_VIU_FIELD) { zoom_start_y = cur_frame_par->VPP_vd_start_lines_ >> 1; @@ -6074,11 +7401,12 @@ SET_FILTER: zoom_start_x_lines = cur_frame_par->VPP_hd_start_lines_; zoom_end_x_lines = cur_frame_par->VPP_hd_end_lines_; - zoom_display_horz(cur_frame_par->hscale_skip_count); + zoom_display_horz(cur_dispbuf, + cur_frame_par->hscale_skip_count); zoom_start_y_lines = zoom_start_y; zoom_end_y_lines = zoom_end_y; - zoom_display_vert(); + zoom_display_vert(cur_dispbuf); if (is_dolby_vision_enable() && cur_dispbuf2) { zoom2_start_x_lines = ori2_start_x_lines; zoom2_end_x_lines = ori2_end_x_lines; @@ -6086,8 +7414,10 @@ SET_FILTER: zoom2_end_y_lines = ori2_end_y_lines; correct_vd2_mif_size_for_DV( cur_frame_par, cur_dispbuf); - vd2_zoom_display_horz(0); - vd2_zoom_display_vert(); + vd2_zoom_display_horz(cur_dispbuf2, + cur_frame_par->hscale_skip_count); + vd2_zoom_display_vert(cur_dispbuf2, + cur_frame_par->vscale_skip_count); } } /*vpp input size setting*/ @@ -6367,6 +7697,17 @@ SET_FILTER: (VPP_OSD1_POSTBLEND | VPP_OSD2_POSTBLEND)) vpp_misc_set |= VPP_POSTBLEND_EN; } + +#ifdef VIDEO_PIP + if (cur_pipbuf && (video2_enabled == 1) + && ((vpp_misc_save & VPP_VD2_POSTBLEND) == 0) + && (video2_onoff_state == VIDEO_ENABLE_STATE_IDLE)) { + vpp_misc_set |= + VPP_VD2_POSTBLEND | + VPP_POSTBLEND_EN; + } +#endif + if ((video_enabled == 1) && ((vpp_misc_save & VPP_VD1_POSTBLEND) == 0) && (video_onoff_state == VIDEO_ENABLE_STATE_IDLE)) { vpp_misc_set |= @@ -6387,7 +7728,7 @@ SET_FILTER: VPP_VSC_START_PHASE_STEP + cur_dev->vpp_off); if ((vpp_filter->vpp_hf_start_phase_step != h_phase_step) || (vpp_filter->vpp_vsc_start_phase_step != v_phase_step)) { - video_property_changed = true; + video_property_changed = 1; /*pr_info("frame info register rdma write fail!\n");*/ } } @@ -6415,6 +7756,7 @@ SET_FILTER: pr_info("VsyncEnableVideoLayer\n"); vpu_delay_work_flag |= VPU_VIDEO_LAYER1_CHANGED; + force_flush = 1; } else if (video_onoff_state == VIDEO_ENABLE_STATE_OFF_REQ) { vpp_misc_set &= ~(VPP_VD1_PREBLEND | VPP_VD1_POSTBLEND); @@ -6434,6 +7776,7 @@ SET_FILTER: if (debug_flag & DEBUG_FLAG_BLACKOUT) pr_info("VsyncDisableVideoLayer\n"); video1_off_req = 1; + force_flush = 1; } spin_unlock_irqrestore(&video_onoff_lock, flags); @@ -6456,7 +7799,9 @@ SET_FILTER: if (is_dolby_vision_on()) vpp_misc_set &= ~(VPP_VD2_PREBLEND | VPP_VD2_POSTBLEND | VPP_PREBLEND_EN); - else if (process_3d_type) + else if (process_3d_type || + (cur_dispbuf && + (cur_dispbuf->type & VIDTYPE_MVC))) vpp_misc_set |= VPP_VD2_PREBLEND | VPP_PREBLEND_EN; else if (!legacy_vpp) @@ -6465,7 +7810,13 @@ SET_FILTER: else vpp_misc_set |= VPP_VD2_PREBLEND | VPP_PREBLEND_EN; - +#ifdef VIDEO_PIP + if (cur_pipbuf) { + vpp_misc_set &= + ~(VPP_PREBLEND_EN | VPP_VD2_PREBLEND); + vpp_misc_set |= VPP_VD2_POSTBLEND; + } +#endif /* g12a has no alpha overflow check in hardware */ if (!legacy_vpp) vpp_misc_set |= (0x100 << VPP_VD2_ALPHA_BIT); @@ -6476,26 +7827,35 @@ SET_FILTER: if (debug_flag & DEBUG_FLAG_BLACKOUT) pr_info("VsyncEnableVideoLayer2\n"); + force_flush = 1; } else if (video2_onoff_state == VIDEO_ENABLE_STATE_OFF_REQ) { vpp_misc_set &= ~(VPP_VD2_PREBLEND | - VPP_VD2_POSTBLEND | VPP_PREBLEND_EN); + VPP_VD2_POSTBLEND | VPP_PREBLEND_EN + | (0x1ff << VPP_VD2_ALPHA_BIT)); video2_onoff_state = VIDEO_ENABLE_STATE_IDLE; video_onoff_time = jiffies_to_msecs(jiffies); if (debug_flag & DEBUG_FLAG_BLACKOUT) pr_info("VsyncDisableVideoLayer2\n"); video2_off_req = 1; + force_flush = 1; } spin_unlock_irqrestore(&video2_onoff_lock, flags); } - if (video_global_output == 0) { + if ((video_global_output == 0) + || black_threshold_check(0)) { video_enabled = 0; vpp_misc_set &= ~(VPP_VD1_PREBLEND | VPP_VD2_PREBLEND | VPP_VD2_POSTBLEND | VPP_VD1_POSTBLEND | VPP_PREBLEND_EN); +#ifdef VIDEO_PIP + /* should keep video2 display */ + if (cur_pipbuf && video2_enabled) + vpp_misc_set |= VPP_VD2_POSTBLEND; +#endif } else { video_enabled = video_status_saved; } @@ -6503,13 +7863,55 @@ SET_FILTER: if (!video_enabled && (vpp_misc_set & VPP_VD1_POSTBLEND)) vpp_misc_set &= ~(VPP_VD1_PREBLEND | - VPP_VD2_PREBLEND | - VPP_VD2_POSTBLEND | VPP_VD1_POSTBLEND | VPP_PREBLEND_EN); +#ifdef VIDEO_PIP + if ((pip_global_output == 0) + || black_threshold_check(1)) { + video2_enabled = 0; + vpp_misc_set &= ~(VPP_VD2_PREBLEND | + VPP_VD2_POSTBLEND); + } else { + video2_enabled = video2_status_saved; + } + + if (!video2_enabled && + (vpp_misc_set & VPP_VD2_POSTBLEND)) + vpp_misc_set &= ~(VPP_VD2_PREBLEND | + VPP_VD2_POSTBLEND); +#endif + if (!legacy_vpp) { u32 set_value = 0; + force_flush |= vpp_zorder_check(); + + /* for sr core0, put it between prebld & pps as default */ + if (cur_frame_par && + (cur_frame_par->sr_core_support & + SUPER_CORE0_SUPPORT)) + if (cur_frame_par->sr0_position) + vpp_misc_set |= + PREBLD_SR0_VD1_SCALER; + else + vpp_misc_set &= + ~SR0_AFTER_DNLP; + else + vpp_misc_set |= + PREBLD_SR0_VD1_SCALER; + /* for sr core1, put it before post blend as default */ + if (cur_frame_par && + (cur_frame_par->sr_core_support & + SUPER_CORE1_SUPPORT)) + if (cur_frame_par->sr1_position) + vpp_misc_set |= + DNLP_SR1_CM; + else + vpp_misc_set &= + ~SR1_AFTER_POSTBLEN; + else + vpp_misc_set |= + DNLP_SR1_CM; vpp_misc_set &= ((1 << 29) | VPP_CM_ENABLE | @@ -6521,6 +7923,14 @@ SET_FILTER: VPP_PREBLEND_EN | VPP_POSTBLEND_EN | 0xf); + + /* if vd2 is bottom layer, need remove alpha for vd2 */ + if (((vpp_misc_set & VPP_VD1_POSTBLEND) == 0) + && (vpp_misc_set & VPP_VD2_POSTBLEND)) { + vpp_misc_set &= ~(0x1ff << VPP_VD2_ALPHA_BIT); + vpp_misc_set |= (0x100 << VPP_VD2_ALPHA_BIT); + } + vpp_misc_save &= ((1 << 29) | VPP_CM_ENABLE | (0x1ff << VPP_VD2_ALPHA_BIT) | @@ -6531,31 +7941,61 @@ SET_FILTER: VPP_PREBLEND_EN | VPP_POSTBLEND_EN | 0xf); - if (vpp_misc_set != vpp_misc_save) { - /* vd1 need always enable pre bld */ - if (vpp_misc_set & VPP_VD1_POSTBLEND) - set_value = - ((1 << 16) | /* post bld premult*/ - (1 << 8) | /* post src */ - (1 << 4) | /* pre bld premult*/ - (1 << 0)); /* pre bld src 1 */ - VSYNC_WR_MPEG_REG( - VD1_BLEND_SRC_CTRL + cur_dev->vpp_off, - set_value); + if ((vpp_misc_set != vpp_misc_save) + || force_flush) { + u32 port_val[3] = {0, 0, 0}; + u32 vd1_port, vd2_port, icnt; + u32 post_blend_reg[3] = { + VD1_BLEND_SRC_CTRL, + VD2_BLEND_SRC_CTRL, + OSD2_BLEND_SRC_CTRL + }; - set_value = 0; + /* just reset the select port */ + if ((glayer_info[0].cur_sel_port > 2) + || (glayer_info[1].cur_sel_port > 2)) { + glayer_info[0].cur_sel_port = 0; + glayer_info[1].cur_sel_port = 1; + } + + vd1_port = glayer_info[0].cur_sel_port; + vd2_port = glayer_info[1].cur_sel_port; + + /* post bld premult*/ + port_val[0] |= (1 << 16); + + /* vd2 path sel */ if (vpp_misc_set & VPP_VD2_POSTBLEND) - set_value = - ((1 << 20) | - (1 << 16) | /* post bld premult*/ - (2 << 8)); /* post src */ + port_val[1] |= (1 << 20); + else + port_val[1] &= ~(1 << 20); + + /* osd2 path sel */ + port_val[2] |= (1 << 20); + + if (vpp_misc_set & VPP_VD1_POSTBLEND) { + /* post src */ + port_val[vd1_port] |= (1 << 8); + port_val[0] |= + ((1 << 4) | /* pre bld premult*/ + (1 << 0)); /* pre bld src 1 */ + } else + port_val[0] &= ~0xff; + + if (vpp_misc_set & VPP_VD2_POSTBLEND) + /* post src */ + port_val[vd2_port] |= (2 << 8); else if (vpp_misc_set & VPP_VD2_PREBLEND) - set_value = + port_val[1] |= ((1 << 4) | /* pre bld premult*/ (2 << 0)); /* pre bld src 1 */ - VSYNC_WR_MPEG_REG( - VD2_BLEND_SRC_CTRL + cur_dev->vpp_off, - set_value); + + for (icnt = 0; icnt < 3; icnt++) + VSYNC_WR_MPEG_REG( + post_blend_reg[icnt] + + cur_dev->vpp_off, + port_val[icnt]); + set_value = vpp_misc_set; set_value &= ((1 << 29) | VPP_CM_ENABLE | @@ -6564,7 +8004,7 @@ SET_FILTER: VPP_VD1_PREBLEND | VPP_VD2_POSTBLEND | VPP_VD1_POSTBLEND | - 7); + 0xf); if ((vpp_misc_set & VPP_VD2_PREBLEND) && (vpp_misc_set & VPP_VD1_PREBLEND)) set_value |= VPP_PREBLEND_EN; @@ -6582,6 +8022,37 @@ SET_FILTER: /*vpp_misc_set maybe have same,but need off.*/ /* if vd1 off, disable vd2 also */ +#ifdef VIDEO_PIP + if (video2_off_req && cur_pipbuf) { + if ((debug_flag & DEBUG_FLAG_BLACKOUT) + && video2_off_req) + pr_info("VD2 AFBC off now.\n"); + VSYNC_WR_MPEG_REG(VD2_AFBC_ENABLE, 0); + VSYNC_WR_MPEG_REG(VD2_IF0_GEN_REG, 0); + if (!legacy_vpp) { + VSYNC_WR_MPEG_REG( + VD2_BLEND_SRC_CTRL + cur_dev->vpp_off, 0); + } + if (cur_pipbuf && (cur_pipbuf == &local_pip)) + cur_pipbuf = NULL; + } else if (!cur_pipbuf && + (video2_off_req || video1_off_req)) { + if ((debug_flag & DEBUG_FLAG_BLACKOUT) + && video2_off_req) + pr_info("VD2 AFBC off now.\n"); + VSYNC_WR_MPEG_REG(VD2_AFBC_ENABLE, 0); + VSYNC_WR_MPEG_REG(VD2_IF0_GEN_REG, 0); + if (!legacy_vpp) { + VSYNC_WR_MPEG_REG( + VD2_BLEND_SRC_CTRL + cur_dev->vpp_off, 0); + } + last_el_w = 0; + last_el_status = 0; + if (cur_dispbuf2 && (cur_dispbuf2 == &vf_local2)) + cur_dispbuf2 = NULL; + need_disable_vd2 = false; + } +#else if (video2_off_req || video1_off_req) { if ((debug_flag & DEBUG_FLAG_BLACKOUT) && video2_off_req) @@ -6599,6 +8070,8 @@ SET_FILTER: cur_dispbuf2 = NULL; need_disable_vd2 = false; } +#endif + if (video1_off_req) { /* * video layer off, swith off afbc, @@ -6619,8 +8092,8 @@ SET_FILTER: VSYNC_WR_MPEG_REG_BITS( VIU_MISC_CTRL1, 1, 16, 1); /* bypass core1 */ - else if (is_meson_g12a_cpu() - || is_meson_g12b_cpu()) + else if (cpu_after_eq( + MESON_CPU_MAJOR_ID_G12A)) VSYNC_WR_MPEG_REG_BITS( DOLBY_PATH_CTRL, 1, 0, 1); } @@ -6629,6 +8102,9 @@ SET_FILTER: } #ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA cur_rdma_buf = cur_dispbuf; +#ifdef VIDEO_PIP + pip_rdma_buf = cur_pipbuf; +#endif /* vsync_rdma_config(); */ vsync_rdma_process(); if (debug_flag & DEBUG_FLAG_PRINT_RDMA) { @@ -6772,9 +8248,11 @@ int get_current_vscale_skip_count(struct vframe_s *vf) int ret = 0; static struct vpp_frame_par_s frame_par; - vpp_set_filters(process_3d_type, wide_setting, vf, &frame_par, vinfo, + vpp_set_filters( + &glayer_info[0], + vf, &frame_par, vinfo, (is_dolby_vision_on() && - is_dolby_vision_stb_mode())); + is_dolby_vision_stb_mode()), 0); ret = frame_par.vscale_skip_count; if (cur_frame_par && (process_3d_type & MODE_3D_ENABLE)) ret |= (cur_frame_par->vpp_3d_mode<<8); @@ -6812,6 +8290,10 @@ static void video_vf_unreg_provider(void) atomic_set(&video_unreg_flag, 1); while (atomic_read(&video_inirq_flag) > 0) schedule(); + memset(&video_frame_detect, 0, + sizeof(struct video_frame_detect_s)); + frame_detect_drop_count = 0; + frame_detect_receive_count = 0; spin_lock_irqsave(&lock, flags); #ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA @@ -6849,9 +8331,30 @@ static void video_vf_unreg_provider(void) vsync_freerun = 0; vsync_pts_align = 0; vsync_pts_aligned = false; - video_prot.video_started = 0; + +#ifdef VIDEO_PIP + if (pip_loop) { +#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA + pipbuf_to_put = NULL; + pip_rdma_buf = NULL; +#endif + if (cur_pipbuf) { + local_pip = *cur_pipbuf; + cur_pipbuf = &local_pip; + cur_pipbuf->video_angle = 0; + } + pip_frame_count = 0; + } +#endif spin_unlock_irqrestore(&lock, flags); +#ifdef VIDEO_PIP + if (pip_loop) { + disable_videopip = VIDEO_DISABLE_FORNEXT; + DisableVideoLayer2(); + } +#endif + if (blackout | force_blackout) { safe_disble_videolayer(); try_free_keep_video(1); @@ -6889,6 +8392,9 @@ static void video_vf_unreg_provider(void) show_first_picture = false; show_first_frame_nosync = false; + time_setomxpts.tv_sec = 0; + time_setomxpts.tv_usec = 0; + #ifdef PTS_LOGGING { int pattern; @@ -6961,10 +8467,16 @@ static int get_display_info(void *data) s32 w, h, x, y; struct vdisplay_info_s *info_para = (struct vdisplay_info_s *)data; const struct vinfo_s *info = get_current_vinfo(); + struct disp_info_s *layer = &glayer_info[0]; if ((!cur_frame_par) || (!info)) return -1; - vpp_get_video_layer_position(&x, &y, &w, &h); + + x = layer->layer_left; + y = layer->layer_top; + w = layer->layer_width; + h = layer->layer_height; + if ((w == 0) || (w > info->width)) w = info->width; if ((h == 0) || (h > info->height)) @@ -7080,25 +8592,88 @@ static int video_receiver_event_fun(int type, void *data, void *private_data) #endif } else if (type == VFRAME_EVENT_PROVIDER_QUREY_DISPLAY_INFO) { get_display_info(data); - } + } else if (type == VFRAME_EVENT_PROVIDER_PROPERTY_CHANGED) + video_property_changed = 1; return 0; } -static int video4osd_receiver_event_fun(int type, void *data, - void *private_data) +#ifdef VIDEO_PIP +static void pip_vf_unreg_provider(void) { - if (type == VFRAME_EVENT_PROVIDER_UNREG) { - osd_prov = NULL; - if (debug_flag & DEBUG_FLAG_BLACKOUT) - pr_info("[video4osd] clear osd_prov\n"); - } else if (type == VFRAME_EVENT_PROVIDER_REG) { - osd_prov = vf_get_provider(RECEIVER4OSD_NAME); + ulong flags; + int keeped = 0; - if (debug_flag & DEBUG_FLAG_BLACKOUT) - pr_info("[video4osd] set osd_prov\n"); + /* atomic_set(&video_unreg_flag, 1); */ + while (atomic_read(&video_inirq_flag) > 0) + schedule(); + spin_lock_irqsave(&lock, flags); + +#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA + pipbuf_to_put = NULL; + pip_rdma_buf = NULL; +#endif + if (cur_pipbuf) { + local_pip = *cur_pipbuf; + cur_pipbuf = &local_pip; + cur_pipbuf->video_angle = 0; } + pip_frame_count = 0; + spin_unlock_irqrestore(&lock, flags); + + if (blackout_pip | force_blackout) { + safe_disble_videolayer2(); + try_free_keep_videopip(1); + } + + if (cur_pipbuf) + keeped = vf_keep_pip_current_locked(cur_pipbuf, NULL); + + if (keeped < 0) {/*keep failed.*/ + pr_info("videopip keep failed, disable video now!\n"); + safe_disble_videolayer2(); + try_free_keep_videopip(1); + } + + /*disable_videopip = VIDEO_DISABLE_FORNEXT;*/ + /*DisableVideoLayer2();*/ +} + +static void pip_vf_light_unreg_provider(int need_keep_frame) +{ + ulong flags; + + spin_lock_irqsave(&lock, flags); +#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA + pipbuf_to_put = NULL; + pip_rdma_buf = NULL; +#endif + + if (cur_pipbuf) { + local_pip = *cur_pipbuf; + cur_pipbuf = &local_pip; + } + spin_unlock_irqrestore(&lock, flags); + if (need_keep_frame) { + if (cur_pipbuf) { + vf_keep_pip_current_locked(cur_pipbuf, NULL); + } + } +} + +static int pip_receiver_event_fun( + int type, void *data, void *private_data) +{ + if (type == VFRAME_EVENT_PROVIDER_UNREG) + pip_vf_unreg_provider(); + else if (type == VFRAME_EVENT_PROVIDER_RESET) + pip_vf_light_unreg_provider(1); + else if (type == VFRAME_EVENT_PROVIDER_LIGHT_UNREG) + pip_vf_light_unreg_provider(0); + else if (type == VFRAME_EVENT_PROVIDER_REG) + pip_vf_light_unreg_provider(0); return 0; } +#endif unsigned int get_post_canvas(void) { @@ -7120,6 +8695,19 @@ u32 set_blackout_policy(int policy) } EXPORT_SYMBOL(set_blackout_policy); +u32 get_blackout_pip_policy(void) +{ + return blackout_pip | force_blackout; +} +EXPORT_SYMBOL(get_blackout_pip_policy); + +u32 set_blackout_pip_policy(int policy) +{ + blackout_pip = policy; + return 0; +} +EXPORT_SYMBOL(set_blackout_pip_policy); + u8 is_vpp_postblend(void) { if (READ_VCBUS_REG(VPP_MISC + cur_dev->vpp_off) & VPP_VD1_POSTBLEND) @@ -7148,33 +8736,49 @@ int _video_set_disable(u32 val) if ((disable_video == VIDEO_DISABLE_FORNEXT) && cur_dispbuf && (cur_dispbuf != &vf_local)) - video_property_changed = true; + video_property_changed = 1; try_free_keep_video(0); } else { if (cur_dispbuf && (cur_dispbuf != &vf_local)) { EnableVideoLayer(); - video_property_changed = true; + video_property_changed = 1; } } return 0; } -static void _set_video_crop(int *p) +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; - vpp_get_video_source_crop(&last_t, &last_l, &last_b, &last_r); - vpp_set_video_source_crop(p[0], p[1], p[2], p[3]); - vpp_get_video_source_crop(&new_t, &new_l, &new_b, &new_r); + 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)) { - video_property_changed = true; + || (new_b != last_b) || (new_r != last_r)) { + if (layer->layer_id == 0) + video_property_changed = 1; +#ifdef VIDEO_PIP + else if (layer->layer_id == 1) + pip_property_changed = 1; +#endif } } -static void _set_video_window(int *p) +static void _set_video_window( + struct disp_info_s *layer, int *p) { int w, h; int *parsed = p; @@ -7183,10 +8787,13 @@ static void _set_video_window(int *p) #ifdef TV_REVERSE int temp, temp1; const struct vinfo_s *info = get_current_vinfo(); +#endif - /* pr_info(KERN_DEBUG "%s: %u*/ - /*get vinfo(%d,%d).\n", __func__, __LINE__,*/ - /*info->width, info->height); */ + if (!layer) + return; + +#ifdef TV_REVERSE + /* FIXME: use layer info */ if (reverse) { temp = parsed[0]; temp1 = parsed[1]; @@ -7196,7 +8803,12 @@ static void _set_video_window(int *p) parsed[3] = info->height - temp1 - 1; } #endif - vpp_get_video_layer_position(&last_x, &last_y, &last_w, &last_h); + + 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; @@ -7226,19 +8838,31 @@ static void _set_video_window(int *p) } else #endif { - if ((w == 1) && (h == 1)) { - w = h = 0; - vpp_set_video_layer_position(parsed[0], parsed[1], 0, - 0); - } else if ((w > 0) && (h > 0)) { - vpp_set_video_layer_position(parsed[0], parsed[1], w, - h); + 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; } } - vpp_get_video_layer_position(&new_x, &new_y, &new_w, &new_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)) { - video_property_changed = true; + || (last_w != new_w) || (last_h != new_h)) { + if (layer->layer_id == 0) + video_property_changed = 1; +#ifdef VIDEO_PIP + else if (layer->layer_id == 1) + pip_property_changed = 1; +#endif } } #if ENABLE_UPDATE_HDR_FROM_USER @@ -7288,6 +8912,7 @@ static void set_omx_pts(u32 *p) u32 session = p[5]; unsigned int try_cnt = 0x1000; + cur_omx_index = frame_num; mutex_lock(&omx_mutex); if (omx_pts_set_index < frame_num) omx_pts_set_index = frame_num; @@ -7307,8 +8932,11 @@ static void set_omx_pts(u32 *p) pr_info("[set_omx_pts]tmp_pts:%d, set_from_hwc:%d,frame_num=%d, not_reset=%d\n", tmp_pts, set_from_hwc, frame_num, not_reset); - if (not_reset == 0) + if (not_reset == 0) { omx_pts = tmp_pts; + ATRACE_COUNTER("omxpts", omx_pts); + do_gettimeofday(&time_setomxpts); + } /* kodi may render first frame, then drop dozens of frames */ if (set_from_hwc == 0 && omx_run == true && frame_num <= 2 && not_reset == 0) { @@ -7363,6 +8991,47 @@ static void set_omx_pts(u32 *p) mutex_unlock(&omx_mutex); } +static int alloc_layer(u32 layer_id) +{ + int ret = -EINVAL; + + if (layer_id == 0) { + if (layer_cap & LAYER0_BUSY) { + ret = -EBUSY; + } else if (layer_cap & LAYER0_AVAIL) { + ret = 0; + layer_cap |= LAYER0_BUSY; + } + } else if (layer_id == 1) { + if (layer_cap & LAYER1_BUSY) { + ret = -EBUSY; + } else if (layer_cap & LAYER1_AVAIL) { + ret = 0; + layer_cap |= LAYER1_BUSY; + } + } + return ret; +} + +static int free_layer(u32 layer_id) +{ + int ret = -EINVAL; + + if (layer_id == 0) { + if ((layer_cap & LAYER0_BUSY) + && (layer_cap & LAYER0_AVAIL)) { + ret = 0; + layer_cap &= ~LAYER0_BUSY; + } + } else if (layer_id == 1) { + if ((layer_cap & LAYER1_BUSY) + && (layer_cap & LAYER1_AVAIL)) { + ret = 0; + layer_cap &= ~LAYER1_BUSY; + } + } + return ret; +} /********************************************************* * /dev/amvideo APIs @@ -7370,29 +9039,25 @@ static void set_omx_pts(u32 *p) */ static int amvideo_open(struct inode *inode, struct file *file) { + file->private_data = NULL; return 0; } static int amvideo_poll_open(struct inode *inode, struct file *file) { + file->private_data = NULL; return 0; } static int amvideo_release(struct inode *inode, struct file *file) { - if (blackout | force_blackout) { - /* DisableVideoLayer();*/ - /*don't need it ,it have problem on pure music playing */ - } + file->private_data = NULL; return 0; } static int amvideo_poll_release(struct inode *inode, struct file *file) { - if (blackout | force_blackout) { - /* DisableVideoLayer();*/ - /*don't need it ,it have problem on pure music playing */ - } + file->private_data = NULL; return 0; } @@ -7400,6 +9065,30 @@ static long amvideo_ioctl(struct file *file, unsigned int cmd, ulong arg) { long ret = 0; void __user *argp = (void __user *)arg; + struct disp_info_s *layer = &glayer_info[0]; + u32 layer_id; + + switch (cmd) { + case AMSTREAM_IOC_GLOBAL_SET_VIDEOPIP_OUTPUT: + case AMSTREAM_IOC_GLOBAL_GET_VIDEOPIP_OUTPUT: + case AMSTREAM_IOC_GET_VIDEOPIP_DISABLE: + case AMSTREAM_IOC_SET_VIDEOPIP_DISABLE: + case AMSTREAM_IOC_GET_VIDEOPIP_AXIS: + case AMSTREAM_IOC_SET_VIDEOPIP_AXIS: + case AMSTREAM_IOC_GET_VIDEOPIP_CROP: + case AMSTREAM_IOC_SET_VIDEOPIP_CROP: + case AMSTREAM_IOC_GET_PIP_SCREEN_MODE: + case AMSTREAM_IOC_SET_PIP_SCREEN_MODE: + case AMSTREAM_IOC_GET_PIP_ZORDER: + case AMSTREAM_IOC_SET_PIP_ZORDER: + layer = &glayer_info[1]; + break; + default: + break; + } + + if (file->private_data) + layer = (struct disp_info_s *)file->private_data; switch (cmd) { case AMSTREAM_IOC_SET_HDR_INFO:{ @@ -7514,19 +9203,38 @@ static long amvideo_ioctl(struct file *file, unsigned int cmd, ulong arg) } break; + case AMSTREAM_IOC_GET_VIDEOPIP_DISABLE: + put_user(disable_videopip, (u32 __user *)argp); + break; case AMSTREAM_IOC_GET_VIDEO_DISABLE: - put_user(disable_video, (u32 __user *)argp); + if (layer->layer_id == 0) + put_user(disable_video, (u32 __user *)argp); +#ifdef VIDEO_PIP + else if (layer->layer_id == 1) + put_user(disable_videopip, (u32 __user *)argp); +#endif break; - case AMSTREAM_IOC_SET_VIDEO_DISABLE:{ - u32 val; + case AMSTREAM_IOC_SET_VIDEOPIP_DISABLE: + { + u32 val; - if (copy_from_user(&val, argp, sizeof(u32)) == 0) - ret = _video_set_disable(val); - else - ret = -EFAULT; + if (copy_from_user(&val, argp, sizeof(u32)) == 0) + ret = _videopip_set_disable(val); + else + ret = -EFAULT; + } + break; + case AMSTREAM_IOC_SET_VIDEO_DISABLE: + { + u32 val; + + if (copy_from_user(&val, argp, sizeof(u32)) == 0) { + ret = _video_set_disable(val); + } else + ret = -EFAULT; + } break; - } case AMSTREAM_IOC_GET_VIDEO_DISCONTINUE_REPORT: put_user(enable_video_discontinue_report, (u32 __user *)argp); @@ -7536,10 +9244,12 @@ static long amvideo_ioctl(struct file *file, unsigned int cmd, ulong arg) enable_video_discontinue_report = (arg == 0) ? 0 : 1; break; - case AMSTREAM_IOC_GET_VIDEO_AXIS:{ + case AMSTREAM_IOC_GET_VIDEOPIP_AXIS: + case AMSTREAM_IOC_GET_VIDEO_AXIS: + { int axis[4]; #ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER_PPSCALER - if (video_scaler_mode) { + if (video_scaler_mode && (layer->layer_id == 0)) { axis[0] = content_left; axis[1] = content_top; axis[2] = content_w; @@ -7547,10 +9257,10 @@ static long amvideo_ioctl(struct file *file, unsigned int cmd, ulong arg) } else #endif { - vpp_get_video_layer_position( - &axis[0], &axis[1], - &axis[2], - &axis[3]); + axis[0] = layer->layer_left; + axis[1] = layer->layer_top; + axis[2] = layer->layer_width; + axis[3] = layer->layer_height; } axis[2] = axis[0] + axis[2] - 1; @@ -7561,21 +9271,27 @@ static long amvideo_ioctl(struct file *file, unsigned int cmd, ulong arg) } break; - case AMSTREAM_IOC_SET_VIDEO_AXIS:{ + case AMSTREAM_IOC_SET_VIDEOPIP_AXIS: + case AMSTREAM_IOC_SET_VIDEO_AXIS: + { int axis[4]; if (copy_from_user(axis, argp, sizeof(axis)) == 0) - _set_video_window(axis); + _set_video_window(layer, axis); else ret = -EFAULT; } break; - case AMSTREAM_IOC_GET_VIDEO_CROP:{ + case AMSTREAM_IOC_GET_VIDEOPIP_CROP: + case AMSTREAM_IOC_GET_VIDEO_CROP: + { int crop[4]; { - vpp_get_video_source_crop(&crop[0], &crop[1], - &crop[2], &crop[3]); + crop[0] = layer->crop_top; + crop[1] = layer->crop_left; + crop[2] = layer->crop_bottom; + crop[3] = layer->crop_right; } if (copy_to_user(argp, &crop[0], sizeof(crop)) != 0) @@ -7583,30 +9299,40 @@ static long amvideo_ioctl(struct file *file, unsigned int cmd, ulong arg) } break; - case AMSTREAM_IOC_SET_VIDEO_CROP:{ + case AMSTREAM_IOC_SET_VIDEOPIP_CROP: + case AMSTREAM_IOC_SET_VIDEO_CROP: + { int crop[4]; if (copy_from_user(crop, argp, sizeof(crop)) == 0) - _set_video_crop(crop); + _set_video_crop(layer, crop); else ret = -EFAULT; } break; + case AMSTREAM_IOC_GET_PIP_SCREEN_MODE: case AMSTREAM_IOC_GET_SCREEN_MODE: - if (copy_to_user(argp, &wide_setting, sizeof(u32)) != 0) + if (copy_to_user(argp, &layer->wide_mode, sizeof(u32)) != 0) ret = -EFAULT; break; - case AMSTREAM_IOC_SET_SCREEN_MODE:{ + case AMSTREAM_IOC_SET_PIP_SCREEN_MODE: + case AMSTREAM_IOC_SET_SCREEN_MODE: + { u32 mode; if (copy_from_user(&mode, argp, sizeof(u32)) == 0) { if (mode >= VIDEO_WIDEOPTION_MAX) ret = -EINVAL; - else if (mode != wide_setting) { - wide_setting = mode; - video_property_changed = true; + else if (mode != layer->wide_mode) { + layer->wide_mode = mode; + if (layer->layer_id == 0) + video_property_changed = 1; +#ifdef VIDEO_PIP + else if (layer->layer_id == 1) + pip_property_changed = 1; +#endif } } else ret = -EFAULT; @@ -7631,6 +9357,24 @@ static long amvideo_ioctl(struct file *file, unsigned int cmd, ulong arg) } break; + case AMSTREAM_IOC_GET_BLACKOUT_PIP_POLICY: + if (copy_to_user(argp, &blackout_pip, sizeof(u32)) != 0) + ret = -EFAULT; + break; + + case AMSTREAM_IOC_SET_BLACKOUT_PIP_POLICY:{ + u32 mode; + + if (copy_from_user(&mode, argp, sizeof(u32)) == 0) { + if (mode > 2) + ret = -EINVAL; + else + blackout_pip = mode; + } else + ret = -EFAULT; + } + break; + case AMSTREAM_IOC_CLEAR_VBUF:{ unsigned long flags; while (atomic_read(&video_inirq_flag) > 0 || @@ -7647,6 +9391,19 @@ static long amvideo_ioctl(struct file *file, unsigned int cmd, ulong arg) safe_disble_videolayer(); break; + case AMSTREAM_IOC_CLEAR_PIP_VBUF:{ + unsigned long flags; + + spin_lock_irqsave(&lock, flags); + cur_pipbuf = NULL; + spin_unlock_irqrestore(&lock, flags); + } + break; + + case AMSTREAM_IOC_CLEAR_VIDEOPIP: + safe_disble_videolayer2(); + break; + case AMSTREAM_IOC_SET_FREERUN_MODE: if (arg > FREERUN_DUR) ret = -EFAULT; @@ -7680,7 +9437,7 @@ static long amvideo_ioctl(struct file *file, unsigned int cmd, ulong arg) process_3d_type = type; if (mvc_flag) process_3d_type |= MODE_3D_MVC; - video_property_changed = true; + video_property_changed = 1; if ((process_3d_type & MODE_3D_FA) && cur_dispbuf && !cur_dispbuf->trans_fmt) @@ -7733,15 +9490,32 @@ static long amvideo_ioctl(struct file *file, unsigned int cmd, ulong arg) vsync_slow_factor = arg; break; + case AMSTREAM_IOC_GLOBAL_SET_VIDEOPIP_OUTPUT: case AMSTREAM_IOC_GLOBAL_SET_VIDEO_OUTPUT: - if (arg != 0) - video_global_output = 1; - else - video_global_output = 0; + if (layer->layer_id == 0) { + if (arg != 0) + video_global_output = 1; + else + video_global_output = 0; + } +#ifdef VIDEO_PIP + else if (layer->layer_id == 1) { + if (arg != 0) + pip_global_output = 1; + else + pip_global_output = 0; + } +#endif break; + case AMSTREAM_IOC_GLOBAL_GET_VIDEOPIP_OUTPUT: case AMSTREAM_IOC_GLOBAL_GET_VIDEO_OUTPUT: - put_user(video_global_output, (u32 __user *)argp); + if (layer->layer_id == 0) + put_user(video_global_output, (u32 __user *)argp); +#ifdef VIDEO_PIP + else if (layer->layer_id == 1) + put_user(pip_global_output, (u32 __user *)argp); +#endif break; case AMSTREAM_IOC_GET_VIDEO_LAYER1_ON: { @@ -7761,6 +9535,7 @@ static long amvideo_ioctl(struct file *file, unsigned int cmd, ulong arg) put_user(video_onoff_state, (u32 __user *)argp); break; } + case AMSTREAM_IOC_GET_FIRST_FRAME_TOGGLED: put_user(first_frame_toggled, (u32 __user *)argp); break; @@ -7769,6 +9544,70 @@ static long amvideo_ioctl(struct file *file, unsigned int cmd, ulong arg) videopeek = true; nopostvideostart = true; break; + + case AMSTREAM_IOC_GET_PIP_ZORDER: + case AMSTREAM_IOC_GET_ZORDER: + put_user(layer->zorder, (u32 __user *)argp); + break; + + case AMSTREAM_IOC_SET_PIP_ZORDER: + case AMSTREAM_IOC_SET_ZORDER:{ + u32 zorder, new_prop = 0; + + if (copy_from_user(&zorder, argp, sizeof(u32)) == 0) { + if (layer->zorder != zorder) + new_prop = 1; + layer->zorder = zorder; + if ((layer->layer_id == 0) && new_prop) + video_property_changed = 1; +#ifdef VIDEO_PIP + else if ((layer->layer_id == 1) && new_prop) + pip_property_changed = 1; +#endif + } else + ret = -EFAULT; + } + break; + + case AMSTREAM_IOC_QUERY_LAYER: + mutex_lock(&video_layer_mutex); + put_user(layer_cap, (u32 __user *)argp); + mutex_unlock(&video_layer_mutex); + ret = 0; + break; + + case AMSTREAM_IOC_ALLOC_LAYER: + if (copy_from_user(&layer_id, argp, sizeof(u32)) == 0) { + if (layer_id >= MAX_VD_LAYERS) { + ret = -EINVAL; + } else { + mutex_lock(&video_layer_mutex); + if (file->private_data) { + ret = -EBUSY; + } else { + ret = alloc_layer(layer_id); + if (!ret) + file->private_data = + (void *)&glayer_info[layer_id]; + } + mutex_unlock(&video_layer_mutex); + } + } else + ret = -EFAULT; + break; + + case AMSTREAM_IOC_FREE_LAYER: + mutex_lock(&video_layer_mutex); + if (!file->private_data) { + ret = -EINVAL; + } else { + ret = free_layer(layer->layer_id); + if (!ret) + file->private_data = NULL; + } + mutex_unlock(&video_layer_mutex); + break; + default: return -EINVAL; } @@ -7810,6 +9649,23 @@ static long amvideo_compat_ioctl(struct file *file, unsigned int cmd, ulong arg) case AMSTREAM_IOC_GET_VSYNC_SLOW_FACTOR: case AMSTREAM_IOC_GLOBAL_GET_VIDEO_OUTPUT: case AMSTREAM_IOC_GET_VIDEO_LAYER1_ON: + case AMSTREAM_IOC_GLOBAL_SET_VIDEOPIP_OUTPUT: + case AMSTREAM_IOC_GLOBAL_GET_VIDEOPIP_OUTPUT: + case AMSTREAM_IOC_GET_VIDEOPIP_DISABLE: + case AMSTREAM_IOC_SET_VIDEOPIP_DISABLE: + case AMSTREAM_IOC_GET_VIDEOPIP_AXIS: + case AMSTREAM_IOC_SET_VIDEOPIP_AXIS: + case AMSTREAM_IOC_GET_VIDEOPIP_CROP: + case AMSTREAM_IOC_SET_VIDEOPIP_CROP: + case AMSTREAM_IOC_GET_PIP_SCREEN_MODE: + case AMSTREAM_IOC_SET_PIP_SCREEN_MODE: + case AMSTREAM_IOC_GET_PIP_ZORDER: + case AMSTREAM_IOC_SET_PIP_ZORDER: + case AMSTREAM_IOC_GET_ZORDER: + case AMSTREAM_IOC_SET_ZORDER: + case AMSTREAM_IOC_QUERY_LAYER: + case AMSTREAM_IOC_ALLOC_LAYER: + case AMSTREAM_IOC_FREE_LAYER: arg = (unsigned long) compat_ptr(arg); case AMSTREAM_IOC_TRICKMODE: case AMSTREAM_IOC_VPAUSE: @@ -7824,12 +9680,15 @@ static long amvideo_compat_ioctl(struct file *file, unsigned int cmd, ulong arg) case AMSTREAM_IOC_SET_VIDEO_DISCONTINUE_REPORT: case AMSTREAM_IOC_CLEAR_VBUF: case AMSTREAM_IOC_CLEAR_VIDEO: + case AMSTREAM_IOC_CLEAR_PIP_VBUF: + case AMSTREAM_IOC_CLEAR_VIDEOPIP: case AMSTREAM_IOC_SET_FREERUN_MODE: case AMSTREAM_IOC_DISABLE_SLOW_SYNC: case AMSTREAM_IOC_SET_3D_TYPE: case AMSTREAM_IOC_SET_VSYNC_UPINT: case AMSTREAM_IOC_SET_VSYNC_SLOW_FACTOR: case AMSTREAM_IOC_GLOBAL_SET_VIDEO_OUTPUT: + case AMSTREAM_IOC_GET_FIRST_FRAME_TOGGLED: case AMSTREAM_IOC_SET_VIDEOPEEK: return amvideo_ioctl(file, cmd, arg); default: @@ -7930,12 +9789,13 @@ static int parse_para(const char *para, int para_num, int *result) return count; } -static void set_video_crop(const char *para) +static void set_video_crop( + struct disp_info_s *layer, const char *para) { int parsed[4]; if (likely(parse_para(para, 4, parsed) == 4)) - _set_video_crop(parsed); + _set_video_crop(layer, parsed); amlog_mask(LOG_MASK_SYSFS, "video crop=>x0:%d,y0:%d,x1:%d,y1:%d\n ", parsed[0], parsed[1], parsed[2], parsed[3]); @@ -7944,19 +9804,23 @@ static void set_video_crop(const char *para) static void set_video_speed_check(const char *para) { int parsed[2]; + struct disp_info_s *layer = &glayer_info[0]; - if (likely(parse_para(para, 2, parsed) == 2)) - vpp_set_video_speed_check(parsed[0], parsed[1]); + if (likely(parse_para(para, 2, parsed) == 2)) { + layer->speed_check_height = parsed[0]; + layer->speed_check_width = parsed[1]; + } amlog_mask(LOG_MASK_SYSFS, "video speed_check=>h:%d,w:%d\n ", parsed[0], parsed[1]); } -static void set_video_window(const char *para) +static void set_video_window( + struct disp_info_s *layer, const char *para) { int parsed[4]; if (likely(parse_para(para, 4, parsed) == 4)) - _set_video_window(parsed); + _set_video_window(layer, parsed); amlog_mask(LOG_MASK_SYSFS, "video=>x0:%d,y0:%d,x1:%d,y1:%d\n ", parsed[0], parsed[1], parsed[2], parsed[3]); @@ -7969,13 +9833,14 @@ static ssize_t video_3d_scale_store(struct class *cla, #ifdef TV_3D_FUNCTION_OPEN u32 enable; int r; + struct disp_info_s *layer = &glayer_info[0]; r = kstrtouint(buf, 0, &enable); if (r < 0) return -EINVAL; - vpp_set_3d_scale(enable); - video_property_changed = true; + layer->vpp_3d_scale = enable ? true : false; + video_property_changed = 1; amlog_mask(LOG_MASK_SYSFS, "%s:%s 3d scale.\n", __func__, enable ? "enable" : "disable"); #endif @@ -7998,7 +9863,7 @@ static ssize_t video_sr_store(struct class *cla, if (likely(parse_para(buf, 1, parsed) == 1)) { if (super_scaler != (parsed[0] & 0x1)) { super_scaler = parsed[0] & 0x1; - video_property_changed = true; + video_property_changed = 1; } } mutex_unlock(&video_module_mutex); @@ -8010,8 +9875,12 @@ static ssize_t video_crop_show(struct class *cla, struct class_attribute *attr, char *buf) { u32 t, l, b, r; + struct disp_info_s *layer = &glayer_info[0]; - vpp_get_video_source_crop(&t, &l, &b, &r); + t = layer->crop_top; + l = layer->crop_left; + b = layer->crop_bottom; + r = layer->crop_right; return snprintf(buf, 40, "%d %d %d %d\n", t, l, b, r); } @@ -8019,9 +9888,11 @@ static ssize_t video_crop_store(struct class *cla, struct class_attribute *attr, const char *buf, size_t count) { + struct disp_info_s *layer = &glayer_info[0]; + mutex_lock(&video_module_mutex); - set_video_crop(buf); + set_video_crop(layer, buf); mutex_unlock(&video_module_mutex); @@ -8154,6 +10025,8 @@ static ssize_t video_axis_show(struct class *cla, char *buf) { int x, y, w, h; + struct disp_info_s *layer = &glayer_info[0]; + #ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER_PPSCALER if (video_scaler_mode) { x = content_left; @@ -8163,7 +10036,10 @@ static ssize_t video_axis_show(struct class *cla, } else #endif { - vpp_get_video_layer_position(&x, &y, &w, &h); + x = layer->layer_left; + y = layer->layer_top; + w = layer->layer_width; + h = layer->layer_height; } return snprintf(buf, 40, "%d %d %d %d\n", x, y, x + w - 1, y + h - 1); } @@ -8172,9 +10048,11 @@ static ssize_t video_axis_store(struct class *cla, struct class_attribute *attr, const char *buf, size_t count) { + struct disp_info_s *layer = &glayer_info[0]; + mutex_lock(&video_module_mutex); - set_video_window(buf); + set_video_window(layer, buf); mutex_unlock(&video_module_mutex); @@ -8185,8 +10063,10 @@ static ssize_t video_global_offset_show(struct class *cla, struct class_attribute *attr, char *buf) { int x, y; + struct disp_info_s *layer = &glayer_info[0]; - vpp_get_global_offset(&x, &y); + x = layer->global_offset_x; + y = layer->global_offset_y; return snprintf(buf, 40, "%d %d\n", x, y); } @@ -8196,12 +10076,14 @@ static ssize_t video_global_offset_store(struct class *cla, const char *buf, size_t count) { int parsed[2]; + struct disp_info_s *layer = &glayer_info[0]; mutex_lock(&video_module_mutex); if (likely(parse_para(buf, 2, parsed) == 2)) { - vpp_set_global_offset(parsed[0], parsed[1]); - video_property_changed = true; + layer->global_offset_x = parsed[0]; + layer->global_offset_y = parsed[1]; + video_property_changed = 1; amlog_mask(LOG_MASK_SYSFS, "video_offset=>x0:%d,y0:%d\n ", @@ -8217,7 +10099,10 @@ static ssize_t video_zoom_show(struct class *cla, struct class_attribute *attr, char *buf) { - u32 r = vpp_get_zoom_ratio(); + u32 r; + struct disp_info_s *layer = &glayer_info[0]; + + r = layer->zoom_ratio; return snprintf(buf, 40, "%d\n", r); } @@ -8228,14 +10113,15 @@ static ssize_t video_zoom_store(struct class *cla, { unsigned long r; int ret = 0; + struct disp_info_s *layer = &glayer_info[0]; ret = kstrtoul(buf, 0, (unsigned long *)&r); if (ret < 0) return -EINVAL; - if ((r <= MAX_ZOOM_RATIO) && (r != vpp_get_zoom_ratio())) { - vpp_set_zoom_ratio(r); - video_property_changed = true; + if ((r <= MAX_ZOOM_RATIO) && (r != layer->zoom_ratio)) { + layer->zoom_ratio = r; + video_property_changed = 1; } return count; @@ -8244,6 +10130,7 @@ static ssize_t video_zoom_store(struct class *cla, static ssize_t video_screen_mode_show(struct class *cla, struct class_attribute *attr, char *buf) { + struct disp_info_s *layer = &glayer_info[0]; static const char * const wide_str[] = { "normal", "full stretch", "4-3", "16-9", "non-linear", "normal-noscaleup", @@ -8252,9 +10139,10 @@ static ssize_t video_screen_mode_show(struct class *cla, "16-9 combined", "Custom AR", "AFD" }; - if (wide_setting < ARRAY_SIZE(wide_str)) { - return sprintf(buf, "%d:%s\n", wide_setting, - wide_str[wide_setting]); + if (layer->wide_mode < ARRAY_SIZE(wide_str)) { + return sprintf(buf, "%d:%s\n", + layer->wide_mode, + wide_str[layer->wide_mode]); } else return 0; } @@ -8265,14 +10153,16 @@ static ssize_t video_screen_mode_store(struct class *cla, { unsigned long mode; int ret = 0; + struct disp_info_s *layer = &glayer_info[0]; ret = kstrtoul(buf, 0, (unsigned long *)&mode); if (ret < 0) return -EINVAL; - if ((mode < VIDEO_WIDEOPTION_MAX) && (mode != wide_setting)) { - wide_setting = mode; - video_property_changed = true; + if ((mode < VIDEO_WIDEOPTION_MAX) + && (mode != layer->wide_mode)) { + layer->wide_mode = mode; + video_property_changed = 1; } return count; @@ -8753,7 +10643,11 @@ static ssize_t video_test_screen_store(struct class *cla, #endif /* show test screen YUV blend*/ - if (is_meson_gxm_cpu() || + if (!legacy_vpp) + WRITE_VCBUS_REG( + VPP_POST_BLEND_BLEND_DUMMY_DATA, + test_screen & 0x00ffffff); + else if (is_meson_gxm_cpu() || (get_cpu_type() == MESON_CPU_MAJOR_ID_TXLX)) /* bit width change to 10bit in gxm, 10/12 in txlx*/ WRITE_VCBUS_REG(VPP_DUMMY_DATA1, @@ -8819,7 +10713,11 @@ static ssize_t video_rgb_screen_store(struct class *cla, #endif /* show test screen YUV blend*/ yuv_eight = rgb2yuv(rgb_screen & 0x00ffffff); - if (is_meson_gxtvbb_cpu()) { + if (!legacy_vpp) { + WRITE_VCBUS_REG( + VPP_POST_BLEND_BLEND_DUMMY_DATA, + yuv_eight & 0x00ffffff); + } else if (is_meson_gxtvbb_cpu()) { WRITE_VCBUS_REG(VPP_DUMMY_DATA1, rgb_screen & 0x00ffffff); } else if (cpu_after_eq(MESON_CPU_MAJOR_ID_TXL)) { @@ -8841,7 +10739,12 @@ static ssize_t video_nonlinear_factor_show(struct class *cla, struct class_attribute *attr, char *buf) { - return sprintf(buf, "%d\n", vpp_get_nonlinear_factor()); + u32 factor; + struct disp_info_s *layer = &glayer_info[0]; + + factor = vpp_get_nonlinear_factor(layer); + + return sprintf(buf, "%d\n", factor); } static ssize_t video_nonlinear_factor_store(struct class *cla, @@ -8850,13 +10753,14 @@ static ssize_t video_nonlinear_factor_store(struct class *cla, { int r; u32 factor; + struct disp_info_s *layer = &glayer_info[0]; r = kstrtoint(buf, 0, &factor); if (r < 0) return -EINVAL; - if (vpp_set_nonlinear_factor(factor) == 0) - video_property_changed = true; + if (vpp_set_nonlinear_factor(layer, factor) == 0) + video_property_changed = 1; return count; } @@ -8919,7 +10823,8 @@ static ssize_t video_hold_store(struct class *cla, const char *buf, size_t count) { int r; - + cur_width = 0; + cur_height = 0; if (debug_flag & DEBUG_FLAG_BLACKOUT) pr_info("%s(%s)\n", __func__, buf); @@ -8956,8 +10861,10 @@ static ssize_t video_speed_check_show(struct class *cla, struct class_attribute *attr, char *buf) { u32 h, w; + struct disp_info_s *layer = &glayer_info[0]; - vpp_get_video_speed_check(&h, &w); + h = layer->speed_check_height; + w = layer->speed_check_width; return snprintf(buf, 40, "%d %d\n", h, w); } @@ -8966,9 +10873,7 @@ static ssize_t video_speed_check_store(struct class *cla, struct class_attribute *attr, const char *buf, size_t count) { - set_video_speed_check(buf); - return strnlen(buf, count); } @@ -8989,7 +10894,7 @@ static ssize_t threedim_mode_store(struct class *cla, process_3d_type = type; if (mvc_flag) process_3d_type |= MODE_3D_MVC; - video_property_changed = true; + video_property_changed = 1; if ((process_3d_type & MODE_3D_FA) && cur_dispbuf && !cur_dispbuf->trans_fmt) /*notify di 3d mode is frame alternative mode,1*/ @@ -9084,6 +10989,8 @@ static ssize_t frame_width_show(struct class *cla, struct class_attribute *attr, char *buf) { + if (hold_video == 1) + return sprintf(buf, "%d\n", cur_width); if (cur_dispbuf) { if (cur_dispbuf->type & VIDTYPE_COMPRESS) return sprintf(buf, "%d\n", cur_dispbuf->compWidth); @@ -9097,6 +11004,8 @@ static ssize_t frame_width_show(struct class *cla, static ssize_t frame_height_show(struct class *cla, struct class_attribute *attr, char *buf) { + if (hold_video == 1) + return sprintf(buf, "%d\n", cur_height); if (cur_dispbuf) { if (cur_dispbuf->type & VIDTYPE_COMPRESS) return sprintf(buf, "%d\n", cur_dispbuf->compHeight); @@ -9451,6 +11360,18 @@ static ssize_t video_vsync_slow_factor_store(struct class *cla, return count; } +static ssize_t vframe_ready_cnt_show(struct class *cla, + struct class_attribute *attr, char *buf) +{ + int ret = -1; + struct vframe_states states; + + ret = video_vf_get_states(&states); + + return snprintf(buf, 10, "%d\n", (ret == 0) ? + states.buf_avail_num : 0); +} + static ssize_t fps_info_show(struct class *cla, struct class_attribute *attr, char *buf) { @@ -9485,11 +11406,11 @@ static ssize_t video_layer1_state_show(struct class *cla, void set_video_angle(u32 s_value) { - if ((s_value <= 3) && (video_angle != s_value)) { - video_angle = s_value; - video_prot.angle_changed = 1; - video_prot.video_started = 1; - pr_info("video_prot angle:%d\n", video_angle); + struct disp_info_s *layer = &glayer_info[0]; + + if ((s_value <= 3) && (layer->angle != s_value)) { + layer->angle = s_value; + pr_info("video angle:%d\n", layer->angle); } } EXPORT_SYMBOL(set_video_angle); @@ -9497,7 +11418,9 @@ EXPORT_SYMBOL(set_video_angle); static ssize_t video_angle_show(struct class *cla, struct class_attribute *attr, char *buf) { - return snprintf(buf, 40, "%d\n", video_angle); + struct disp_info_s *layer = &glayer_info[0]; + + return snprintf(buf, 40, "%d\n", layer->angle); } static ssize_t video_angle_store(struct class *cla, @@ -9669,6 +11592,427 @@ static ssize_t video_inuse_store(struct class *class, return count; } +static ssize_t video_zorder_show( + struct class *cla, + struct class_attribute *attr, + char *buf) +{ + struct disp_info_s *layer = &glayer_info[0]; + + return sprintf(buf, "%d\n", layer->zorder); +} + +static ssize_t video_zorder_store( + struct class *cla, + struct class_attribute *attr, + const char *buf, size_t count) +{ + int zorder; + int ret = 0; + struct disp_info_s *layer = &glayer_info[0]; + + ret = kstrtoint(buf, 0, &zorder); + if (ret < 0) + return -EINVAL; + + if (zorder != layer->zorder) { + layer->zorder = zorder; + video_property_changed = 1; + } + return count; +} + +static ssize_t black_threshold_show( + struct class *cla, + struct class_attribute *attr, + char *buf) +{ + return sprintf(buf, "width: %d, height: %d\n", + black_threshold_width, + black_threshold_height); +} + +static ssize_t black_threshold_store( + struct class *cla, + struct class_attribute *attr, + const char *buf, size_t count) +{ + int parsed[2]; + + if (likely(parse_para(buf, 2, parsed) == 2)) { + black_threshold_width = parsed[0]; + black_threshold_height = parsed[1]; + } + return strnlen(buf, count); +} + +#ifdef VIDEO_PIP +int _videopip_set_disable(u32 val) +{ + if (val > VIDEO_DISABLE_FORNEXT) + return -EINVAL; + + disable_videopip = val; + + if (disable_videopip != VIDEO_DISABLE_NONE) { + DisableVideoLayer2(); + + if ((disable_videopip == VIDEO_DISABLE_FORNEXT) + && cur_pipbuf && (cur_pipbuf != &local_pip)) + pip_property_changed = 1; + try_free_keep_videopip(0); + } else { + if (cur_pipbuf && (cur_pipbuf != &local_pip)) + EnableVideoLayer2(); + } + + return 0; +} + +static ssize_t videopip_blackout_policy_show(struct class *cla, + struct class_attribute *attr, + char *buf) +{ + return sprintf(buf, "%d\n", blackout_pip); +} + +static ssize_t videopip_blackout_policy_store(struct class *cla, + struct class_attribute *attr, + const char *buf, size_t count) +{ + int r; + + r = kstrtoint(buf, 0, &blackout_pip); + if (r < 0) + return -EINVAL; + + return count; +} + +static ssize_t videopip_axis_show( + struct class *cla, + struct class_attribute *attr, + char *buf) +{ + int x0, y0, x1, y1; + struct disp_info_s *layer = &glayer_info[1]; + + x0 = layer->layer_left; + y0 = layer->layer_top; + x1 = layer->layer_width + x0 - 1; + y1 = layer->layer_height + y0 - 1; + return snprintf(buf, 40, "%d %d %d %d\n", x0, y0, x1, y1); +} + +static ssize_t videopip_axis_store( + struct class *cla, + struct class_attribute *attr, + const char *buf, size_t count) +{ + struct disp_info_s *layer = &glayer_info[1]; + + mutex_lock(&video_module_mutex); + + set_video_window(layer, buf); + + mutex_unlock(&video_module_mutex); + + return strnlen(buf, count); +} + +static ssize_t videopip_crop_show( + struct class *cla, + struct class_attribute *attr, + char *buf) +{ + u32 t, l, b, r; + struct disp_info_s *layer = &glayer_info[1]; + + t = layer->crop_top; + l = layer->crop_left; + b = layer->crop_bottom; + r = layer->crop_right; + return snprintf(buf, 40, "%d %d %d %d\n", t, l, b, r); +} + +static ssize_t videopip_crop_store( + struct class *cla, + struct class_attribute *attr, + const char *buf, size_t count) +{ + struct disp_info_s *layer = &glayer_info[1]; + + mutex_lock(&video_module_mutex); + + set_video_crop(layer, buf); + + mutex_unlock(&video_module_mutex); + + return strnlen(buf, count); +} + +static ssize_t videopip_disable_show( + struct class *cla, struct class_attribute *attr, char *buf) +{ + return sprintf(buf, "%d\n", disable_videopip); +} + +static ssize_t videopip_disable_store( + struct class *cla, + struct class_attribute *attr, + const char *buf, size_t count) +{ + int r; + int val; + + if (debug_flag & DEBUG_FLAG_BLACKOUT) + pr_info("%s(%s)\n", __func__, buf); + + r = kstrtoint(buf, 0, &val); + if (r < 0) + return -EINVAL; + + if (_videopip_set_disable(val) < 0) + return -EINVAL; + + return count; +} + +static ssize_t videopip_screen_mode_show( + struct class *cla, + struct class_attribute *attr, + char *buf) +{ + struct disp_info_s *layer = &glayer_info[1]; + static const char * const wide_str[] = { + "normal", "full stretch", "4-3", "16-9", "non-linear", + "normal-noscaleup", + "4-3 ignore", "4-3 letter box", "4-3 pan scan", "4-3 combined", + "16-9 ignore", "16-9 letter box", "16-9 pan scan", + "16-9 combined", "Custom AR", "AFD" + }; + + if (layer->wide_mode < ARRAY_SIZE(wide_str)) { + return sprintf(buf, "%d:%s\n", + layer->wide_mode, + wide_str[layer->wide_mode]); + } else + return 0; +} + +static ssize_t videopip_screen_mode_store( + struct class *cla, + struct class_attribute *attr, + const char *buf, size_t count) +{ + unsigned long mode; + int ret = 0; + struct disp_info_s *layer = &glayer_info[1]; + + ret = kstrtoul(buf, 0, (unsigned long *)&mode); + if (ret < 0) + return -EINVAL; + + if ((mode < VIDEO_WIDEOPTION_MAX) + && (mode != layer->wide_mode)) { + layer->wide_mode = mode; + pip_property_changed = 1; + } + return count; +} + +static ssize_t videopip_loop_show( + struct class *cla, struct class_attribute *attr, char *buf) +{ + return sprintf(buf, "%d\n", pip_loop); +} + +static ssize_t videopip_loop_store( + struct class *cla, + struct class_attribute *attr, + const char *buf, size_t count) +{ + int r; + int val; + + r = kstrtoint(buf, 0, &val); + if (r < 0) + return -EINVAL; + + pip_loop = val; + return count; +} + +static ssize_t videopip_global_output_show( + struct class *cla, + struct class_attribute *attr, + char *buf) +{ + return sprintf(buf, "%d\n", pip_global_output); +} + +static ssize_t videopip_global_output_store( + struct class *cla, + struct class_attribute *attr, + const char *buf, size_t count) +{ + int r; + + r = kstrtoint(buf, 0, &pip_global_output); + if (r < 0) + return -EINVAL; + + pr_info("%s(%d)\n", __func__, pip_global_output); + + return count; +} + +static ssize_t videopip_zorder_show( + struct class *cla, + struct class_attribute *attr, + char *buf) +{ + struct disp_info_s *layer = &glayer_info[1]; + + return sprintf(buf, "%d\n", layer->zorder); +} + +static ssize_t videopip_zorder_store( + struct class *cla, + struct class_attribute *attr, + const char *buf, size_t count) +{ + int zorder; + int ret = 0; + struct disp_info_s *layer = &glayer_info[1]; + + ret = kstrtoint(buf, 0, &zorder); + if (ret < 0) + return -EINVAL; + + if (zorder != layer->zorder) { + layer->zorder = zorder; + pip_property_changed = 1; + } + return count; +} + +static ssize_t videopip_state_show( + struct class *cla, + struct class_attribute *attr, + char *buf) +{ + ssize_t len = 0; + struct vppfilter_mode_s *vpp_filter = NULL; + + if (!curpip_frame_par) + return len; + vpp_filter = &curpip_frame_par->vpp_filter; + len += sprintf(buf + len, + "zoom2_start_x_lines:%u.zoom2_end_x_lines:%u.\n", + zoom2_start_x_lines, zoom2_end_x_lines); + len += sprintf(buf + len, + "zoom2_start_y_lines:%u.zoom2_end_y_lines:%u.\n", + zoom2_start_y_lines, zoom2_end_y_lines); + len += sprintf(buf + len, "frame parameters: pic_in_height %u.\n", + curpip_frame_par->VPP_pic_in_height_); + len += sprintf(buf + len, + "frame parameters: VPP_line_in_length_ %u.\n", + curpip_frame_par->VPP_line_in_length_); + len += sprintf(buf + len, "vscale_skip_count %u.\n", + curpip_frame_par->vscale_skip_count); + len += sprintf(buf + len, "hscale_skip_count %u.\n", + curpip_frame_par->hscale_skip_count); + len += sprintf(buf + len, "supscl_path %u.\n", + curpip_frame_par->supscl_path); + len += sprintf(buf + len, "supsc0_enable %u.\n", + curpip_frame_par->supsc0_enable); + len += sprintf(buf + len, "supsc1_enable %u.\n", + curpip_frame_par->supsc1_enable); + len += sprintf(buf + len, "supsc0_hori_ratio %u.\n", + curpip_frame_par->supsc0_hori_ratio); + len += sprintf(buf + len, "supsc1_hori_ratio %u.\n", + curpip_frame_par->supsc1_hori_ratio); + len += sprintf(buf + len, "supsc0_vert_ratio %u.\n", + curpip_frame_par->supsc0_vert_ratio); + len += sprintf(buf + len, "supsc1_vert_ratio %u.\n", + curpip_frame_par->supsc1_vert_ratio); + len += sprintf(buf + len, "spsc0_h_in %u.\n", + curpip_frame_par->spsc0_h_in); + len += sprintf(buf + len, "spsc1_h_in %u.\n", + curpip_frame_par->spsc1_h_in); + len += sprintf(buf + len, "spsc0_w_in %u.\n", + curpip_frame_par->spsc0_w_in); + len += sprintf(buf + len, "spsc1_w_in %u.\n", + curpip_frame_par->spsc1_w_in); + len += sprintf(buf + len, "video_input_w %u.\n", + curpip_frame_par->video_input_w); + len += sprintf(buf + len, "video_input_h %u.\n", + curpip_frame_par->video_input_h); + len += sprintf(buf + len, "clk_in_pps %u.\n", + curpip_frame_par->clk_in_pps); + len += + sprintf(buf + len, "hscale phase step 0x%x.\n", + vpp_filter->vpp_hsc_start_phase_step); + len += + sprintf(buf + len, "vscale phase step 0x%x.\n", + vpp_filter->vpp_vsc_start_phase_step); + len += + sprintf(buf + len, "pps pre hsc enable %d.\n", + vpp_filter->vpp_pre_hsc_en); + len += + sprintf(buf + len, "pps pre vsc enable %d.\n", + vpp_filter->vpp_pre_vsc_en); + len += + sprintf(buf + len, "hscale filter coef %d.\n", + vpp_filter->vpp_horz_filter); + len += + sprintf(buf + len, "vscale filter coef %d.\n", + vpp_filter->vpp_vert_filter); + len += + sprintf(buf + len, "vpp_vert_chroma_filter_en %d.\n", + vpp_filter->vpp_vert_chroma_filter_en); + len += + sprintf(buf + len, "post_blend_vd_h_start 0x%x.\n", + curpip_frame_par->VPP_post_blend_vd_h_start_); + len += + sprintf(buf + len, "post_blend_vd_h_end 0x%x.\n", + curpip_frame_par->VPP_post_blend_vd_h_end_); + len += + sprintf(buf + len, "post_blend_vd_v_start 0x%x.\n", + curpip_frame_par->VPP_post_blend_vd_v_start_); + len += + sprintf(buf + len, "post_blend_vd_v_end 0x%x.\n", + curpip_frame_par->VPP_post_blend_vd_v_end_); + len += + sprintf(buf + len, "VPP_hd_start_lines_ 0x%x.\n", + curpip_frame_par->VPP_hd_start_lines_); + len += + sprintf(buf + len, "VPP_hd_end_lines_ 0x%x.\n", + curpip_frame_par->VPP_hd_end_lines_); + len += + sprintf(buf + len, "VPP_vd_start_lines_ 0x%x.\n", + curpip_frame_par->VPP_vd_start_lines_); + len += + sprintf(buf + len, "VPP_vd_end_lines_ 0x%x.\n", + curpip_frame_par->VPP_vd_end_lines_); + len += + sprintf(buf + len, "VPP_hsc_startp 0x%x.\n", + curpip_frame_par->VPP_hsc_startp); + len += + sprintf(buf + len, "VPP_hsc_endp 0x%x.\n", + curpip_frame_par->VPP_hsc_endp); + len += + sprintf(buf + len, "VPP_vsc_startp 0x%x.\n", + curpip_frame_par->VPP_vsc_startp); + len += + sprintf(buf + len, "VPP_vsc_endp 0x%x.\n", + curpip_frame_par->VPP_vsc_endp); + return len; +} + +#endif + static struct class_attribute amvideo_class_attrs[] = { __ATTR(axis, 0664, @@ -9694,6 +12038,10 @@ static struct class_attribute amvideo_class_attrs[] = { 0664, video_blackout_policy_show, video_blackout_policy_store), + __ATTR(blackout_pip_policy, + 0664, + videopip_blackout_policy_show, + videopip_blackout_policy_store), __ATTR(video_seek_flag, 0664, video_seek_flag_show, @@ -9703,9 +12051,9 @@ static struct class_attribute amvideo_class_attrs[] = { video_disable_show, video_disable_store), __ATTR(video_global_output, - 0664, - video_global_output_show, - video_global_output_store), + 0664, + video_global_output_show, + video_global_output_store), __ATTR(hold_video, 0664, video_hold_show, @@ -9816,6 +12164,14 @@ static struct class_attribute amvideo_class_attrs[] = { 0664, video_inuse_show, video_inuse_store), + __ATTR(video_zorder, + 0664, + video_zorder_show, + video_zorder_store), + __ATTR(black_threshold, + 0664, + black_threshold_show, + black_threshold_store), __ATTR_RO(frame_addr), __ATTR_RO(frame_canvas_width), __ATTR_RO(frame_canvas_height), @@ -9827,8 +12183,40 @@ static struct class_attribute amvideo_class_attrs[] = { __ATTR_RO(vframe_states), __ATTR_RO(video_state), __ATTR_RO(fps_info), + __ATTR_RO(vframe_ready_cnt), __ATTR_RO(video_layer1_state), __ATTR_RO(pic_mode_info), +#ifdef VIDEO_PIP + __ATTR(axis_pip, + 0664, + videopip_axis_show, + videopip_axis_store), + __ATTR(crop_pip, + 0664, + videopip_crop_show, + videopip_crop_store), + __ATTR(disable_videopip, + 0664, + videopip_disable_show, + videopip_disable_store), + __ATTR(screen_mode_pip, + 0664, + videopip_screen_mode_show, + videopip_screen_mode_store), + __ATTR(videopip_loop, + 0664, + videopip_loop_show, + videopip_loop_store), + __ATTR(pip_global_output, + 0664, + videopip_global_output_show, + videopip_global_output_store), + __ATTR(videopip_zorder, + 0664, + videopip_zorder_show, + videopip_zorder_store), + __ATTR_RO(videopip_state), +#endif __ATTR_NULL }; @@ -9973,10 +12361,8 @@ int vout_notify_callback(struct notifier_block *block, unsigned long cmd, new_vmode = vinfo->mode; break; case VOUT_EVENT_OSD_PREBLEND_ENABLE: - vpp_set_osd_layer_preblend(para); break; case VOUT_EVENT_OSD_DISP_AXIS: - vpp_set_osd_layer_position(para); break; } return 0; @@ -10005,10 +12391,8 @@ int vout2_notify_callback(struct notifier_block *block, unsigned long cmd, spin_unlock_irqrestore(&lock, flags); break; case VOUT_EVENT_OSD_PREBLEND_ENABLE: - vpp_set_osd_layer_preblend(para); break; case VOUT_EVENT_OSD_DISP_AXIS: - vpp_set_osd_layer_position(para); break; } return 0; @@ -10219,20 +12603,6 @@ static int __init video_early_init(void) u32 cur_hold_line; -#if 0 /* if (0 >= VMODE_MAX) //DEBUG_TMP */ -#if 1 /* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */ - if (cpu_after_eq(MESON_CPU_MAJOR_ID_GXTVBB)) - WRITE_VCBUS_REG_BITS(VPP_OFIFO_SIZE, 0xfff, - VPP_OFIFO_SIZE_BIT, VPP_OFIFO_SIZE_WID); - else - WRITE_VCBUS_REG_BITS(VPP_OFIFO_SIZE, 0x77f, - VPP_OFIFO_SIZE_BIT, VPP_OFIFO_SIZE_WID); -#if 0 /* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESONG9TV */ - WRITE_VCBUS_REG_BITS(VPP_OFIFO_SIZE, 0x800, VPP_OFIFO_SIZE_BIT, - VPP_OFIFO_SIZE_WID); -#endif -#endif /* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */ -#else if (!legacy_vpp) { WRITE_VCBUS_REG_BITS(VPP_OFIFO_SIZE, 0x1000, VPP_OFIFO_SIZE_BIT, VPP_OFIFO_SIZE_WID); @@ -10241,12 +12611,10 @@ static int __init video_early_init(void) } else if (cpu_after_eq(MESON_CPU_MAJOR_ID_GXTVBB)) WRITE_VCBUS_REG_BITS(VPP_OFIFO_SIZE, 0xfff, VPP_OFIFO_SIZE_BIT, VPP_OFIFO_SIZE_WID); -#endif -#if 1 /* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */ WRITE_VCBUS_REG(VPP_PREBLEND_VD1_H_START_END, 4096); WRITE_VCBUS_REG(VPP_BLEND_VD2_H_START_END, 4096); -#endif + if (is_meson_txl_cpu() || is_meson_txlx_cpu()) { /* fifo max size on txl :128*3=384[0x180] */ WRITE_VCBUS_REG( @@ -10255,27 +12623,9 @@ static int __init video_early_init(void) VD2_IF0_LUMA_FIFO_SIZE + cur_dev->viu_off, 0x180); } -#if 0 /* if (0 >= VMODE_MAX) //DEBUG_TMP */ - CLEAR_VCBUS_REG_MASK(VPP_VSC_PHASE_CTRL, - VPP_PHASECTL_TYPE_INTERLACE); - SET_VCBUS_REG_MASK(VPP_MISC, VPP_OUT_SATURATE); - WRITE_VCBUS_REG(VPP_HOLD_LINES + cur_dev->vpp_off, 0x08080808); -#endif - #ifdef CONFIG_SUPPORT_VIDEO_ON_VPP2 -#if 0 /* if (0 >= VMODE_MAX) //DEBUG_TMP */ - CLEAR_VCBUS_REG_MASK(VPP2_VSC_PHASE_CTRL, - VPP_PHASECTL_TYPE_INTERLACE); - SET_VCBUS_REG_MASK(VPP2_MISC, VPP_OUT_SATURATE); - WRITE_VCBUS_REG(VPP2_HOLD_LINES, 0x08080808); -#endif -#if 1 /* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */ WRITE_VCBUS_REG_BITS(VPP2_OFIFO_SIZE, 0x800, - VPP_OFIFO_SIZE_BIT, VPP_OFIFO_SIZE_WID); -#else - WRITE_VCBUS_REG_BITS(VPP2_OFIFO_SIZE, 0x780, - VPP_OFIFO_SIZE_BIT, VPP_OFIFO_SIZE_WID); -#endif + VPP_OFIFO_SIZE_BIT, VPP_OFIFO_SIZE_WID); /* *WRITE_VCBUS_REG_BITS(VPU_OSD3_MMC_CTRL, 1, 12, 2); *select vdisp_mmc_arb for VIU2_OSD1 request @@ -10317,15 +12667,30 @@ static int __init video_early_init(void) vpp_hold_line = cur_hold_line; /* Temp force set dmc */ - if (!legacy_vpp) + if (!legacy_vpp) { WRITE_DMCREG( DMC_AM0_CHAN_CTRL, 0x8ff403cf); - - /* force bypass dolby for TL1. There is no dolby function */ - if (is_meson_tl1_cpu()) + /* for vd1 & vd2 dummy alpha*/ + WRITE_VCBUS_REG( + VPP_POST_BLEND_DUMMY_ALPHA, + 0x7fffffff); WRITE_VCBUS_REG_BITS( - DOLBY_PATH_CTRL, 0xf, 0, 6); + VPP_MISC1, 0x100, 0, 9); + } + if (is_meson_tl1_cpu() || is_meson_tm2_cpu()) { + /* force bypass dolby for TL1, no dolby function */ + if (is_meson_tl1_cpu()) + WRITE_VCBUS_REG_BITS( + DOLBY_PATH_CTRL, 0xf, 0, 6); + /* disable latch for sr core0/1 scaler */ + WRITE_VCBUS_REG_BITS( + SRSHARP0_SHARP_SYNC_CTRL, 1, 0, 1); + WRITE_VCBUS_REG_BITS( + SRSHARP1_SHARP_SYNC_CTRL, 1, 8, 1); + } else if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12B)) + WRITE_VCBUS_REG_BITS( + SRSHARP0_SHARP_SYNC_CTRL, 1, 0, 1); return 0; } @@ -10450,7 +12815,7 @@ static struct platform_driver amvideom_driver = { static int __init video_init(void) { - int r = 0; + int r = 0, i; /* *#ifdef CONFIG_ARCH_MESON1 *ulong clk = clk_get_rate(clk_get_sys("clk_other_pll", NULL)); @@ -10482,8 +12847,7 @@ static int __init video_init(void) } #endif - if (is_meson_g12a_cpu() || is_meson_g12b_cpu() - || is_meson_tl1_cpu()) { + if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) { cur_dev->viu_off = 0x3200 - 0x1a50; legacy_vpp = false; } @@ -10504,6 +12868,8 @@ static int __init video_init(void) cur_dispbuf = NULL; cur_dispbuf2 = NULL; amvideo_register_client(&amvideo_notifier); + /* set supoer_scaler to false default*/ + super_scaler = false; #ifdef FIQ_VSYNC /* enable fiq bridge */ @@ -10578,11 +12944,66 @@ static int __init video_init(void) goto err5; } + /* make vd1 below vd2 */ + for (i = 0; i < MAX_VD_LAYERS; i++) { + vpp_disp_info_init(&glayer_info[i], i); + memset(&gPic_info[i], 0, sizeof(struct vframe_pic_mode_s)); + glayer_info[i].wide_mode = 1; + glayer_info[i].zorder = reference_zorder - 2 + i; + glayer_info[i].cur_sel_port = i; + glayer_info[i].last_sel_port = i; + if (legacy_vpp) { + glayer_info[i].afbc_support = true; + glayer_info[i].pps_support = + (i == 0) ? true : false; + } else if (is_meson_tl1_cpu()) { + glayer_info[i].afbc_support = + (i == 0) ? true : false; + glayer_info[i].pps_support = + (i == 0) ? true : false; + } else if (is_meson_tm2_cpu()) { + glayer_info[i].afbc_support = + (i == 0) ? true : false; + glayer_info[i].pps_support = true; + } else { + glayer_info[i].afbc_support = true; + glayer_info[i].pps_support = true; + } + } + + if (legacy_vpp) + layer_cap = + LAYER1_AFBC | + LAYER1_AVAIL | + LAYER0_AFBC | + LAYER0_SCALER | + LAYER0_AVAIL; + else if (is_meson_tl1_cpu()) + layer_cap = + LAYER1_AVAIL | + LAYER0_AFBC | + LAYER0_SCALER | + LAYER0_AVAIL; + else if (is_meson_tm2_cpu()) + layer_cap = + LAYER1_SCALER | + LAYER1_AVAIL | + LAYER0_AFBC | + LAYER0_SCALER | + LAYER0_AVAIL; + else + layer_cap = + LAYER1_AFBC | + LAYER1_SCALER | + LAYER1_AVAIL | + LAYER0_AFBC | + LAYER0_SCALER | + LAYER0_AVAIL; + init_waitqueue_head(&amvideo_trick_wait); init_waitqueue_head(&amvideo_sizechange_wait); -#if 1 /* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */ + INIT_WORK(&vpu_delay_work, do_vpu_delay_work); -#endif #ifdef CONFIG_AM_VOUT vout_hook(); @@ -10627,9 +13048,13 @@ static int __init video_init(void) NULL); vf_reg_receiver(&video_vf_recv); - vf_receiver_init(&video4osd_vf_recv, RECEIVER4OSD_NAME, - &video4osd_vf_receiver, NULL); - vf_reg_receiver(&video4osd_vf_recv); +#ifdef VIDEO_PIP + vf_receiver_init( + &videopip_vf_recv, RECEIVERPIP_NAME, + &videopip_vf_receiver, NULL); + vf_reg_receiver(&videopip_vf_recv); +#endif + #if DEBUG_TMP switch_dev_register(&video1_state_sdev); switch_set_state(&video1_state_sdev, 0); @@ -10670,7 +13095,9 @@ static void __exit video_exit(void) video_debugfs_exit(); vf_unreg_receiver(&video_vf_recv); - vf_unreg_receiver(&video4osd_vf_recv); +#ifdef VIDEO_PIP + vf_unreg_receiver(&videopip_vf_recv); +#endif DisableVideoLayer(); DisableVideoLayer2(); @@ -10724,9 +13151,6 @@ MODULE_PARM_DESC(underflow, "\n Underflow count\n"); module_param(next_peek_underflow, uint, 0664); MODULE_PARM_DESC(skip, "\n Underflow count\n"); -module_param(hdmiin_frame_check, uint, 0664); -MODULE_PARM_DESC(hdmiin_frame_check, "\n hdmiin_frame_check\n"); - module_param(step_enable, uint, 0664); MODULE_PARM_DESC(step_enable, "\n step_enable\n"); @@ -10805,6 +13229,24 @@ module_param(receive_frame_count, int, 0664); MODULE_PARM_DESC(display_frame_count, "\n display_frame_count\n"); module_param(display_frame_count, int, 0664); +module_param(frame_detect_time, uint, 0664); +MODULE_PARM_DESC(frame_detect_time, "\n frame_detect_time\n"); + +module_param(frame_detect_flag, uint, 0664); +MODULE_PARM_DESC(frame_detect_flag, "\n frame_detect_flag\n"); + +module_param(frame_detect_fps, uint, 0664); +MODULE_PARM_DESC(frame_detect_fps, "\n frame_detect_fps\n"); + +module_param(frame_detect_receive_count, uint, 0664); +MODULE_PARM_DESC(frame_detect_receive_count, "\n frame_detect_receive_count\n"); + +module_param(frame_detect_drop_count, uint, 0664); +MODULE_PARM_DESC(frame_detect_drop_count, "\n frame_detect_drop_count\n"); + + + + MODULE_PARM_DESC(bypass_pps, "\n pps_bypass\n"); module_param(bypass_pps, bool, 0664); @@ -10841,6 +13283,12 @@ module_param(toggle_count, uint, 0664); MODULE_PARM_DESC(vpp_hold_line, "\n vpp_hold_line\n"); module_param(vpp_hold_line, uint, 0664); +MODULE_PARM_DESC(stop_update, "\n stop_update\n"); +module_param(stop_update, uint, 0664); + +MODULE_PARM_DESC(reference_zorder, "\n reference_zorder\n"); +module_param(reference_zorder, uint, 0664); + MODULE_DESCRIPTION("AMLOGIC video output driver"); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Tim Yao "); diff --git a/drivers/amlogic/media/video_sink/video_keeper.c b/drivers/amlogic/media/video_sink/video_keeper.c index 1dbfcd4ba6b8..262b93de5922 100644 --- a/drivers/amlogic/media/video_sink/video_keeper.c +++ b/drivers/amlogic/media/video_sink/video_keeper.c @@ -64,10 +64,15 @@ static DEFINE_MUTEX(video_keeper_mutex); static unsigned long keep_y_addr, keep_u_addr, keep_v_addr; static int keep_video_on; +static int keep_video_pip_on; static int keep_id; static int keep_head_id; +static int keep_pip_id; +static int keep_pip_head_id; static int keep_el_id; static int keep_el_head_id; +static int keep_pip_el_id; +static int keep_pip_el_head_id; #define Y_BUFFER_SIZE 0x400000 /* for 1920*1088 */ #define U_BUFFER_SIZE 0x100000 /* compatible with NV21 */ @@ -145,8 +150,9 @@ static int ge2d_store_frame_YUV444(u32 cur_index) yaddr = keep_phy_addr(keep_y_addr); canvas_config(ydupindex, - (ulong) yaddr, - cs.width, cs.height, CANVAS_ADDR_NOWRAP, cs.blkmode); + (ulong) yaddr, + cs.width, cs.height, + CANVAS_ADDR_NOWRAP, cs.blkmode); canvas_read(ydupindex, &cd); src_index = y_index; @@ -194,8 +200,9 @@ static int ge2d_store_frame_YUV444(u32 cur_index) return -1; } - stretchblt_noalpha(ge2d_video_context, 0, 0, cs.width, cs.height, - 0, 0, cs.width, cs.height); + stretchblt_noalpha(ge2d_video_context, + 0, 0, cs.width, cs.height, + 0, 0, cs.width, cs.height); return 0; } @@ -226,11 +233,13 @@ static int ge2d_store_frame_NV21(u32 cur_index) canvas_read(y_index, &cs0); canvas_read(u_index, &cs1); canvas_config(ydupindex, - (ulong) yaddr, - cs0.width, cs0.height, CANVAS_ADDR_NOWRAP, cs0.blkmode); + (ulong) yaddr, + cs0.width, cs0.height, + CANVAS_ADDR_NOWRAP, cs0.blkmode); canvas_config(udupindex, - (ulong) uaddr, - cs1.width, cs1.height, CANVAS_ADDR_NOWRAP, cs1.blkmode); + (ulong) uaddr, + cs1.width, cs1.height, + CANVAS_ADDR_NOWRAP, cs1.blkmode); canvas_read(ydupindex, &cd); src_index = ((y_index & 0xff) | ((u_index << 8) & 0x0000ff00)); @@ -280,8 +289,9 @@ static int ge2d_store_frame_NV21(u32 cur_index) return -1; } - stretchblt_noalpha(ge2d_video_context, 0, 0, cs0.width, cs0.height, - 0, 0, cs0.width, cs0.height); + stretchblt_noalpha(ge2d_video_context, + 0, 0, cs0.width, cs0.height, + 0, 0, cs0.width, cs0.height); return 0; } @@ -322,8 +332,10 @@ static int ge2d_store_frame_YUV420(u32 cur_index) yaddr = keep_phy_addr(keep_y_addr); canvas_config(ydupindex, - (ulong) yaddr, - cs.width, cs.height, CANVAS_ADDR_NOWRAP, cs.blkmode); + (ulong) yaddr, + cs.width, cs.height, + CANVAS_ADDR_NOWRAP, cs.blkmode); + canvas_read(ydupindex, &cd); ge2d_config.dst_planes[0].addr = cd.addr; ge2d_config.dst_planes[0].w = cd.width; @@ -371,8 +383,9 @@ static int ge2d_store_frame_YUV420(u32 cur_index) pr_info("++ge2d configing error.\n"); return -1; } - stretchblt_noalpha(ge2d_video_context, 0, 0, cs.width, cs.height, 0, 0, - cs.width, cs.height); + stretchblt_noalpha(ge2d_video_context, + 0, 0, cs.width, cs.height, + 0, 0, cs.width, cs.height); /* U data */ ge2d_config.alu_const_color = 0; @@ -393,8 +406,10 @@ static int ge2d_store_frame_YUV420(u32 cur_index) uaddr = keep_phy_addr(keep_u_addr); canvas_config(udupindex, - (ulong) uaddr, - cs.width, cs.height, CANVAS_ADDR_NOWRAP, cs.blkmode); + (ulong) uaddr, + cs.width, cs.height, + CANVAS_ADDR_NOWRAP, cs.blkmode); + canvas_read(udupindex, &cd); ge2d_config.dst_planes[0].addr = cd.addr; ge2d_config.dst_planes[0].w = cd.width; @@ -442,8 +457,9 @@ static int ge2d_store_frame_YUV420(u32 cur_index) pr_info("++ge2d configing error.\n"); return -1; } - stretchblt_noalpha(ge2d_video_context, 0, 0, cs.width, cs.height, 0, 0, - cs.width, cs.height); + stretchblt_noalpha(ge2d_video_context, + 0, 0, cs.width, cs.height, + 0, 0, cs.width, cs.height); /* operation top line */ /* V data */ @@ -465,8 +481,10 @@ static int ge2d_store_frame_YUV420(u32 cur_index) vaddr = keep_phy_addr(keep_v_addr); canvas_config(vdupindex, - (ulong) vaddr, - cs.width, cs.height, CANVAS_ADDR_NOWRAP, cs.blkmode); + (ulong) vaddr, + cs.width, cs.height, + CANVAS_ADDR_NOWRAP, cs.blkmode); + ge2d_config.dst_planes[0].addr = cd.addr; ge2d_config.dst_planes[0].w = cd.width; ge2d_config.dst_planes[0].h = cd.height; @@ -513,14 +531,14 @@ static int ge2d_store_frame_YUV420(u32 cur_index) pr_info("++ge2d configing error.\n"); return -1; } - stretchblt_noalpha(ge2d_video_context, 0, 0, cs.width, cs.height, 0, 0, - cs.width, cs.height); + stretchblt_noalpha(ge2d_video_context, + 0, 0, cs.width, cs.height, + 0, 0, cs.width, cs.height); return 0; } static void ge2d_keeplastframe_block(int cur_index, int format) { - /* u32 cur_index; */ u32 y_index, u_index, v_index; #ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA u32 y_index2, u_index2, v_index2; @@ -579,10 +597,9 @@ static void ge2d_keeplastframe_block(int cur_index, int format) video_module_unlock(); } - #endif -#define FETCHBUF_SIZE (64*1024) /*DEBUG_TMP*/ +#define FETCHBUF_SIZE (64*1024) /*DEBUG_TMP*/ static int canvas_dup(ulong dst, ulong src_paddr, ulong size) { void *src_addr = codec_mm_phys_to_virt(src_paddr); @@ -636,13 +653,14 @@ static int alloc_keep_buffer(void) flags = CODEC_MM_FLAGS_DMA | CODEC_MM_FLAGS_FOR_VDECODER; #endif if ((flags & CODEC_MM_FLAGS_FOR_VDECODER) && - codec_mm_video_tvp_enabled())/*TVP TODO for MULTI*/ + codec_mm_video_tvp_enabled()) + /*TVP TODO for MULTI*/ flags |= CODEC_MM_FLAGS_TVP; if (!keep_y_addr) { keep_y_addr = codec_mm_alloc_for_dma( - MEM_NAME, - PAGE_ALIGN(Y_BUFFER_SIZE)/PAGE_SIZE, 0, flags); + MEM_NAME, + PAGE_ALIGN(Y_BUFFER_SIZE)/PAGE_SIZE, 0, flags); if (!keep_y_addr) { pr_err("%s: failed to alloc y addr\n", __func__); goto err1; @@ -651,8 +669,8 @@ static int alloc_keep_buffer(void) if (!keep_u_addr) { keep_u_addr = codec_mm_alloc_for_dma( - MEM_NAME, - PAGE_ALIGN(U_BUFFER_SIZE)/PAGE_SIZE, 0, flags); + MEM_NAME, + PAGE_ALIGN(U_BUFFER_SIZE)/PAGE_SIZE, 0, flags); if (!keep_u_addr) { pr_err("%s: failed to alloc u addr\n", __func__); goto err1; @@ -661,8 +679,8 @@ static int alloc_keep_buffer(void) if (!keep_v_addr) { keep_v_addr = codec_mm_alloc_for_dma( - MEM_NAME, - PAGE_ALIGN(V_BUFFER_SIZE)/PAGE_SIZE, 0, flags); + MEM_NAME, + PAGE_ALIGN(V_BUFFER_SIZE)/PAGE_SIZE, 0, flags); if (!keep_v_addr) { pr_err("%s: failed to alloc v addr\n", __func__); goto err1; @@ -680,7 +698,6 @@ static int alloc_keep_buffer(void) return -ENOMEM; } - /* *flags,used per bit: *deflaut free alloced keeper buffer. @@ -708,9 +725,30 @@ void try_free_keep_video(int flags) mutex_unlock(&video_keeper_mutex); } EXPORT_SYMBOL(try_free_keep_video); - #endif +void try_free_keep_videopip(int flags) +{ + int free_scatter_keeper = flags & 0x1; + + if (keep_video_pip_on || free_scatter_keeper) { + /*pr_info("disbled keep video before free keep buffer.\n");*/ + keep_video_pip_on = 0; + if (!get_videopip_enabled()) { + /*if not disable video,changed to 2 for */ + pr_info("disbled videopip for next before free keep buffer!\n"); + _videopip_set_disable(VIDEO_DISABLE_FORNEXT); + } else if (get_videopip_enabled()) { + safe_disble_videolayer2(); + } + } + mutex_lock(&video_keeper_mutex); + video_pip_keeper_new_frame_notify(); + free_alloced_keep_buffer(); + mutex_unlock(&video_keeper_mutex); +} +EXPORT_SYMBOL(try_free_keep_videopip); + static void video_keeper_update_keeper_mem( void *mem_handle, int type, int *id) @@ -730,12 +768,12 @@ static void video_keeper_update_keeper_mem( *id = ret; } } + static int video_keeper_frame_keep_locked( struct vframe_s *cur_dispbuf, struct vframe_s *cur_dispbuf_el) { int type = MEM_TYPE_CODEC_MM; - if (cur_dispbuf->type & VIDTYPE_SCATTER) type = MEM_TYPE_CODEC_MM_SCATTER; video_keeper_update_keeper_mem( @@ -763,6 +801,41 @@ static int video_keeper_frame_keep_locked( return (keep_id + keep_head_id) > 0; } +static int video_pip_keeper_frame_keep_locked( + struct vframe_s *cur_dispbuf, + struct vframe_s *cur_dispbuf_el) +{ + int type = MEM_TYPE_CODEC_MM; + + if (cur_dispbuf) { + if (cur_dispbuf->type & VIDTYPE_SCATTER) + type = MEM_TYPE_CODEC_MM_SCATTER; + video_keeper_update_keeper_mem( + cur_dispbuf->mem_handle, + type, + &keep_pip_id); + video_keeper_update_keeper_mem( + cur_dispbuf->mem_head_handle, + MEM_TYPE_CODEC_MM, + &keep_pip_head_id); + } + if (cur_dispbuf_el) { + if (cur_dispbuf_el->type & VIDTYPE_SCATTER) + type = MEM_TYPE_CODEC_MM_SCATTER; + else + type = MEM_TYPE_CODEC_MM; + video_keeper_update_keeper_mem( + cur_dispbuf_el->mem_handle, + type, + &keep_pip_el_id); + video_keeper_update_keeper_mem( + cur_dispbuf_el->mem_head_handle, + MEM_TYPE_CODEC_MM, + &keep_pip_el_head_id); + } + return (keep_pip_id + keep_pip_head_id) > 0; +} + /* * call in irq. *don't used mutex @@ -783,6 +856,7 @@ void video_keeper_new_frame_notify(void) codec_mm_keeper_unmask_keeper(keep_head_id, 120); keep_head_id = -1; } + if (keep_el_id > 0) { /*wait 80 ms for vsync post.*/ codec_mm_keeper_unmask_keeper(keep_el_id, 120); @@ -795,6 +869,37 @@ void video_keeper_new_frame_notify(void) } return; } + +void video_pip_keeper_new_frame_notify(void) +{ + if (keep_video_pip_on) { + pr_info("new frame show, pip free keeper\n"); + keep_video_pip_on = 0; + } + if (keep_pip_id > 0) { + /*wait 80 ms for vsync post.*/ + codec_mm_keeper_unmask_keeper(keep_pip_id, 120); + keep_pip_id = -1; + } + if (keep_pip_head_id > 0) { + /*wait 80 ms for vsync post.*/ + codec_mm_keeper_unmask_keeper(keep_pip_head_id, 120); + keep_pip_head_id = -1; + } + if (keep_pip_el_id > 0) { + /*wait 80 ms for vsync post.*/ + codec_mm_keeper_unmask_keeper(keep_pip_el_id, 120); + keep_pip_el_id = -1; + } + if (keep_pip_el_head_id > 0) { + /*wait 80 ms for vsync post.*/ + codec_mm_keeper_unmask_keeper(keep_pip_el_head_id, 120); + keep_pip_el_head_id = -1; + } + +} + + static unsigned int vf_keep_current_locked( struct vframe_s *cur_dispbuf, struct vframe_s *cur_dispbuf_el) @@ -809,28 +914,24 @@ static unsigned int vf_keep_current_locked( return 0; } - if (cur_dispbuf->source_type == VFRAME_SOURCE_TYPE_OSD) { - pr_info("keep exit is osd\n"); - return 0; - } - if (get_video_debug_flags() & DEBUG_FLAG_TOGGLE_SKIP_KEEP_CURRENT) { + if (get_video_debug_flags() & + DEBUG_FLAG_TOGGLE_SKIP_KEEP_CURRENT) { pr_info("keep exit is skip current\n"); return 0; } -#ifdef CONFIG_AMLOGIC_MEDIA_VIDEOCAPTURE - ext_frame_capture_poll(1); /*pull if have capture end frame */ -#endif if (get_blackout_policy()) { pr_info("keep exit is skip current\n"); return 0; } + if (VSYNC_RD_MPEG_REG(DI_IF1_GEN_REG) & 0x1) { pr_info("keep exit is di\n"); return 0; } - ret = video_keeper_frame_keep_locked(cur_dispbuf, + ret = video_keeper_frame_keep_locked( + cur_dispbuf, cur_dispbuf_el); if (ret) { /*keeped ok with codec keeper!*/ @@ -844,34 +945,34 @@ static unsigned int vf_keep_current_locked( } #endif - if ((get_cpu_type() >= MESON_CPU_MAJOR_ID_GXBB) && - (cur_dispbuf->type & VIDTYPE_COMPRESS)) { + if (cur_dispbuf->type & VIDTYPE_COMPRESS) { /* todo: duplicate compressed video frame */ pr_info("keep exit is skip VIDTYPE_COMPRESS\n"); return -1; } cur_index = READ_VCBUS_REG(VD1_IF0_CANVAS0 + - get_video_cur_dev()->viu_off); + get_video_cur_dev()->viu_off); y_index = cur_index & 0xff; u_index = (cur_index >> 8) & 0xff; v_index = (cur_index >> 16) & 0xff; canvas_read(y_index, &cd); - if ((cd.width * cd.height) <= 2048 * 1088 && - !keep_y_addr) { + if ((cd.width * cd.height) <= 2048 * 1088 + && !keep_y_addr) { alloc_keep_buffer(); } if (!keep_y_addr - || (cur_dispbuf->type & VIDTYPE_VIU_422) == VIDTYPE_VIU_422) { + || (cur_dispbuf->type & VIDTYPE_VIU_422) + == VIDTYPE_VIU_422) { /* no support VIDTYPE_VIU_422... */ pr_info("%s:no support VIDTYPE_VIU_422\n", __func__); return -1; } - if (get_video_debug_flags() & DEBUG_FLAG_BLACKOUT) { - pr_info("%s keep_y_addr=%p %x\n", __func__, (void *)keep_y_addr, - canvas_get_addr(y_index)); + pr_info("%s keep_y_addr=%p %x\n", + __func__, (void *)keep_y_addr, + canvas_get_addr(y_index)); } if ((cur_dispbuf->type & VIDTYPE_VIU_422) == VIDTYPE_VIU_422) { @@ -886,21 +987,20 @@ static unsigned int vf_keep_current_locked( return -1; } if (keep_phy_addr(keep_y_addr) != canvas_get_addr(y_index) && - canvas_dup(keep_phy_addr(keep_y_addr), - canvas_get_addr(y_index), - (cd.width) * (cd.height))) { + canvas_dup(keep_phy_addr(keep_y_addr), + canvas_get_addr(y_index), + (cd.width) * (cd.height))) { #ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA canvas_update_addr(disp_canvas_index[0][0], - keep_phy_addr(keep_y_addr)); + keep_phy_addr(keep_y_addr)); canvas_update_addr(disp_canvas_index[1][0], - keep_phy_addr(keep_y_addr)); + keep_phy_addr(keep_y_addr)); #else canvas_update_addr(y_index, keep_phy_addr(keep_y_addr)); #endif if (get_video_debug_flags() & DEBUG_FLAG_BLACKOUT) pr_info("%s: VIDTYPE_VIU_422\n", __func__); - } */ } else if ((cur_dispbuf->type & VIDTYPE_VIU_444) == VIDTYPE_VIU_444) { @@ -916,17 +1016,17 @@ static unsigned int vf_keep_current_locked( ge2d_keeplastframe_block(cur_index, GE2D_FORMAT_M24_YUV444); #else if (keep_phy_addr(keep_y_addr) != canvas_get_addr(y_index) && - canvas_dup(keep_phy_addr(keep_y_addr), - canvas_get_addr(y_index), - (cd.width) * (cd.height))) { + canvas_dup(keep_phy_addr(keep_y_addr), + canvas_get_addr(y_index), + (cd.width) * (cd.height))) { #ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA canvas_update_addr(disp_canvas_index[0][0], - keep_phy_addr(keep_y_addr)); + keep_phy_addr(keep_y_addr)); canvas_update_addr(disp_canvas_index[1][0], - keep_phy_addr(keep_y_addr)); + keep_phy_addr(keep_y_addr)); #else canvas_update_addr(y_index, - keep_phy_addr(keep_y_addr)); + keep_phy_addr(keep_y_addr)); #endif } #endif @@ -936,7 +1036,7 @@ static unsigned int vf_keep_current_locked( canvas_read(y_index, &cs0); canvas_read(u_index, &cs1); if ((Y_BUFFER_SIZE < (cs0.width * cs0.height)) - || (U_BUFFER_SIZE < (cs1.width * cs1.height))) { + || (U_BUFFER_SIZE < (cs1.width * cs1.height))) { pr_info("## [%s::%d] error: yuv data size larger", __func__, __LINE__); return -1; @@ -945,21 +1045,21 @@ static unsigned int vf_keep_current_locked( ge2d_keeplastframe_block(cur_index, GE2D_FORMAT_M24_NV21); #else if (keep_phy_addr(keep_y_addr) != canvas_get_addr(y_index) && - canvas_dup(keep_phy_addr(keep_y_addr), - canvas_get_addr(y_index), - (cs0.width * cs0.height)) - && canvas_dup(keep_phy_addr(keep_u_addr), - canvas_get_addr(u_index), - (cs1.width * cs1.height))) { + canvas_dup(keep_phy_addr(keep_y_addr), + canvas_get_addr(y_index), + (cs0.width * cs0.height)) + && canvas_dup(keep_phy_addr(keep_u_addr), + canvas_get_addr(u_index), + (cs1.width * cs1.height))) { #ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA canvas_update_addr(disp_canvas_index[0][0], - keep_phy_addr(keep_y_addr)); + keep_phy_addr(keep_y_addr)); canvas_update_addr(disp_canvas_index[1][0], - keep_phy_addr(keep_y_addr)); + keep_phy_addr(keep_y_addr)); canvas_update_addr(disp_canvas_index[0][1], - keep_phy_addr(keep_u_addr)); + keep_phy_addr(keep_u_addr)); canvas_update_addr(disp_canvas_index[1][1], - keep_phy_addr(keep_u_addr)); + keep_phy_addr(keep_u_addr)); #else canvas_update_addr(y_index, keep_phy_addr(keep_y_addr)); @@ -976,13 +1076,13 @@ static unsigned int vf_keep_current_locked( canvas_read(v_index, &cs2); if ((Y_BUFFER_SIZE < (cs0.width * cs0.height)) - || (U_BUFFER_SIZE < (cs1.width * cs1.height)) - || (V_BUFFER_SIZE < (cs2.width * cs2.height))) { + || (U_BUFFER_SIZE < (cs1.width * cs1.height)) + || (V_BUFFER_SIZE < (cs2.width * cs2.height))) { pr_info("## [%s::%d] error: yuv data size larger than buf size: %x,%x,%x, %x,%x, %x,%x, %x,%x,\n", - __func__, __LINE__, Y_BUFFER_SIZE, - U_BUFFER_SIZE, V_BUFFER_SIZE, cs0.width, - cs0.height, cs1.width, cs1.height, cs2.width, - cs2.height); + __func__, __LINE__, Y_BUFFER_SIZE, + U_BUFFER_SIZE, V_BUFFER_SIZE, cs0.width, + cs0.height, cs1.width, cs1.height, cs2.width, + cs2.height); return -1; } #ifdef CONFIG_GE2D_KEEP_FRAME @@ -990,28 +1090,28 @@ static unsigned int vf_keep_current_locked( #else if (keep_phy_addr(keep_y_addr) != canvas_get_addr(y_index) && /*must not the same address */ - canvas_dup(keep_phy_addr(keep_y_addr), - canvas_get_addr(y_index), - (cs0.width * cs0.height)) - && canvas_dup(keep_phy_addr(keep_u_addr), - canvas_get_addr(u_index), - (cs1.width * cs1.height)) + canvas_dup(keep_phy_addr(keep_y_addr), + canvas_get_addr(y_index), + (cs0.width * cs0.height)) + && canvas_dup(keep_phy_addr(keep_u_addr), + canvas_get_addr(u_index), + (cs1.width * cs1.height)) && canvas_dup(keep_phy_addr(keep_v_addr), - canvas_get_addr(v_index), - (cs2.width * cs2.height))) { + canvas_get_addr(v_index), + (cs2.width * cs2.height))) { #ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA canvas_update_addr(disp_canvas_index[0][0], - keep_phy_addr(keep_y_addr)); + keep_phy_addr(keep_y_addr)); canvas_update_addr(disp_canvas_index[1][0], - keep_phy_addr(keep_y_addr)); + keep_phy_addr(keep_y_addr)); canvas_update_addr(disp_canvas_index[0][1], - keep_phy_addr(keep_u_addr)); + keep_phy_addr(keep_u_addr)); canvas_update_addr(disp_canvas_index[1][1], - keep_phy_addr(keep_u_addr)); + keep_phy_addr(keep_u_addr)); canvas_update_addr(disp_canvas_index[0][2], - keep_phy_addr(keep_v_addr)); + keep_phy_addr(keep_v_addr)); canvas_update_addr(disp_canvas_index[1][2], - keep_phy_addr(keep_v_addr)); + keep_phy_addr(keep_v_addr)); #else canvas_update_addr(y_index, keep_phy_addr(keep_y_addr)); @@ -1031,6 +1131,47 @@ static unsigned int vf_keep_current_locked( return 1; } + +unsigned int vf_keep_pip_current_locked( + struct vframe_s *cur_dispbuf, + struct vframe_s *cur_dispbuf_el) +{ + //u32 cur_index; + //u32 y_index, u_index, v_index; + //struct canvas_s cs0, cs1, cs2, cd; + int ret; + + if (!cur_dispbuf) { + pr_info("keep pip exit without cur_dispbuf\n"); + return 0; + } + + if (get_video_debug_flags() & + DEBUG_FLAG_TOGGLE_SKIP_KEEP_CURRENT) { + pr_info("flag: keep pip exit is skip current\n"); + return 0; + } + + if (get_blackout_pip_policy()) { + pr_info("policy: keep exit is skip current\n"); + return 0; + } + + ret = video_pip_keeper_frame_keep_locked( + cur_dispbuf, + cur_dispbuf_el); + + if (ret) { + /*keeped ok with codec keeper!*/ + pr_info("keep pip buffer on!\n"); + keep_video_pip_on = 1; + return 1; + } + + keep_video_pip_on = 0; + return 0; +} + unsigned int vf_keep_current( struct vframe_s *cur_dispbuf, struct vframe_s *cur_dispbuf2) @@ -1038,8 +1179,8 @@ unsigned int vf_keep_current( unsigned int ret; mutex_lock(&video_keeper_mutex); - ret = vf_keep_current_locked(cur_dispbuf, - cur_dispbuf2); + ret = vf_keep_current_locked( + cur_dispbuf, cur_dispbuf2); mutex_unlock(&video_keeper_mutex); return ret; } diff --git a/drivers/amlogic/media/video_sink/video_priv.h b/drivers/amlogic/media/video_sink/video_priv.h index cca1ddf66398..bbaa0400e230 100644 --- a/drivers/amlogic/media/video_sink/video_priv.h +++ b/drivers/amlogic/media/video_sink/video_priv.h @@ -17,6 +17,9 @@ #ifndef VIDEO_PRIV_HEADER_HH #define VIDEO_PRIV_HEADER_HH + +#include + #define DEBUG_FLAG_BLACKOUT 0x1 #define DEBUG_FLAG_PRINT_TOGGLE_FRAME 0x2 #define DEBUG_FLAG_PRINT_RDMA 0x4 @@ -28,6 +31,8 @@ #define DEBUG_FLAG_GOFIELD_MANUL 0x100000 #define DEBUG_FLAG_LATENCY 0x200000 #define DEBUG_FLAG_PTS_TRACE 0x400000 +#define DEBUG_FLAG_FRAME_DETECT 0x800000 + /*for video.c's static int debug_flag;*/ #define VOUT_TYPE_TOP_FIELD 0 @@ -38,11 +43,99 @@ #define VIDEO_DISABLE_NORMAL 1 #define VIDEO_DISABLE_FORNEXT 2 +#define VIDEO_NOTIFY_TRICK_WAIT 0x01 +#define VIDEO_NOTIFY_PROVIDER_GET 0x02 +#define VIDEO_NOTIFY_PROVIDER_PUT 0x04 +#define VIDEO_NOTIFY_FRAME_WAIT 0x08 +#define VIDEO_NOTIFY_POS_CHANGED 0x10 + struct video_dev_s { int vpp_off; int viu_off; }; + +struct mif_pos_s { + u32 id; + u32 vd_reg_offt; + u32 afbc_reg_offt; + + /* frame original size */ + u32 src_w; + u32 src_h; + + /* mif start - end lines */ + u32 start_x_lines; + u32 end_x_lines; + u32 start_y_lines; + u32 end_y_lines; + + /* left and right eye position, skip flag. */ + /* And if non 3d case, left eye = right eye */ + u32 l_hs_luma; + u32 l_he_luma; + u32 l_hs_chrm; + u32 l_he_chrm; + u32 r_hs_luma; + u32 r_he_luma; + u32 r_hs_chrm; + u32 r_he_chrm; + u32 h_skip; + u32 l_vs_luma; + u32 l_ve_luma; + u32 l_vs_chrm; + u32 l_ve_chrm; + u32 r_vs_luma; + u32 r_ve_luma; + u32 r_vs_chrm; + u32 r_ve_chrm; + u32 v_skip; + + bool reverse; + + bool skip_afbc; +}; + +struct scaler_setting_s { + u32 id; + u32 misc_reg_offt; + + bool sc_h_enable; + bool sc_v_enable; + bool sc_top_enable; + + u32 vinfo_width; + u32 vinfo_height; + /* u32 VPP_pic_in_height_; */ + /* u32 VPP_line_in_length_; */ + + struct vpp_frame_par_s *frame_par; +}; + +struct blend_setting_s { + u32 id; + u32 misc_reg_offt; + + u32 layer_alpha; + + u32 preblend_h_start; + u32 preblend_h_end; + u32 preblend_v_start; + u32 preblend_v_end; + + u32 preblend_h_size; + + u32 postblend_h_start; + u32 postblend_h_end; + u32 postblend_v_start; + u32 postblend_v_end; + + u32 postblend_h_size; + + struct vpp_frame_par_s *frame_par; +}; + void safe_disble_videolayer(void); +void safe_disble_videolayer2(void); void update_cur_dispbuf(void *buf); /*for video related files only.*/ @@ -53,10 +146,13 @@ struct vframe_s *get_cur_dispbuf(void); int get_video_debug_flags(void); int _video_set_disable(u32 val); +int _videopip_set_disable(u32 val); u32 get_video_enabled(void); +u32 get_videopip_enabled(void); +struct device *get_video_device(void); #ifdef CONFIG_AMLOGIC_MEDIA_VIDEOCAPTURE -int ext_frame_capture_poll(int endflags); +int ext_frame_capture_poll(struct vframe_s *vf); #endif extern u32 disp_canvas_index[2][6]; diff --git a/drivers/amlogic/media/video_sink/vpp.c b/drivers/amlogic/media/video_sink/vpp.c index f165f4305455..4c4c8fdf7fb0 100644 --- a/drivers/amlogic/media/video_sink/vpp.c +++ b/drivers/amlogic/media/video_sink/vpp.c @@ -18,21 +18,12 @@ #include #include #include -/* #include */ #include - #include - #include #include #include -#include -#include -/*#include */ - -#include - #include "videolog.h" /* #define CONFIG_VIDEO_LOG */ #ifdef CONFIG_VIDEO_LOG @@ -42,6 +33,10 @@ #include #include +#include "video_priv.h" + +#define MAX_NONLINEAR_FACTOR 0x40 + /* vpp filter coefficients */ #define COEF_BICUBIC 0 #define COEF_3POINT_TRIANGLE 1 @@ -56,13 +51,21 @@ #define COEF_NULL 0xff #define TOTAL_FILTERS 10 -#define MAX_NONLINEAR_FACTOR 0x40 - #define VPP_SPEED_FACTOR 0x110ULL #define SUPER_SCALER_V_FACTOR 100 #define PPS_FRAC_BITS 24 #define PPS_INT_BITS 4 +struct filter_info_s { + u32 cur_vert_filter; + u32 cur_horz_filter; + u32 last_vert_filter; + u32 last_horz_filter; + u32 scaler_filter_cnt; +}; + +static struct filter_info_s gfilter[MAX_VD_LAYERS]; + const u32 vpp_filter_coefs_bicubic_sharp[] = { 3, 33 | 0x8000, @@ -248,8 +251,8 @@ MODULE_PARM_DESC(vpp_filter_fix, "vpp_filter_fix"); module_param(vpp_filter_fix, uint, 0664); #define MAX_COEFF_LEVEL 5 -uint num_coeff_level = MAX_COEFF_LEVEL; -uint vert_coeff_settings[MAX_COEFF_LEVEL] = { +static uint num_coeff_level = MAX_COEFF_LEVEL; +static uint vert_coeff_settings[MAX_COEFF_LEVEL] = { /* in:out */ COEF_BICUBIC, /* ratio < 1 */ @@ -269,7 +272,7 @@ uint vert_coeff_settings[MAX_COEFF_LEVEL] = { /* this setting is most smooth */ }; -uint horz_coeff_settings[MAX_COEFF_LEVEL] = { +static uint horz_coeff_settings[MAX_COEFF_LEVEL] = { /* in:out */ COEF_BICUBIC, /* ratio < 1 */ @@ -334,40 +337,40 @@ MODULE_PARM_DESC(vert_coeff_settings, "\n vert_coeff_settings\n"); module_param_array(horz_coeff_settings, uint, &num_coeff_level, 0664); MODULE_PARM_DESC(horz_coeff_settings, "\n horz_coeff_settings\n"); -bool vert_chroma_filter_en = true; +static bool vert_chroma_filter_en = true; module_param(vert_chroma_filter_en, bool, 0664); MODULE_PARM_DESC(vert_chroma_filter_en, "enable vertical chromafilter\n"); -bool vert_chroma_filter_force_en; +static bool vert_chroma_filter_force_en; module_param(vert_chroma_filter_force_en, bool, 0664); MODULE_PARM_DESC(vert_chroma_filter_force_en, "force enable vertical chromafilter\n"); -uint vert_chroma_filter_limit = 480; +static uint vert_chroma_filter_limit = 480; module_param(vert_chroma_filter_limit, uint, 0664); MODULE_PARM_DESC(vert_chroma_filter_limit, "vertical chromafilter limit\n"); -uint num_chroma_filter = TOTAL_FILTERS; +static uint num_chroma_filter = TOTAL_FILTERS; module_param_array(chroma_filter_table, uint, &num_chroma_filter, 0664); MODULE_PARM_DESC(chroma_filter_table, "\n chroma_filter_table\n"); -uint cur_vert_chroma_filter; +static uint cur_vert_chroma_filter; MODULE_PARM_DESC(cur_vert_chroma_filter, "cur_vert_chroma_filter"); module_param(cur_vert_chroma_filter, int, 0444); -uint cur_vert_filter; +static uint cur_vert_filter; MODULE_PARM_DESC(cur_vert_filter, "cur_vert_filter"); module_param(cur_vert_filter, int, 0444); -uint cur_horz_filter; +static uint cur_horz_filter; MODULE_PARM_DESC(cur_horz_filter, "cur_horz_filter"); module_param(cur_horz_filter, int, 0444); -uint cur_skip_line; +static uint cur_skip_line; MODULE_PARM_DESC(cur_skip_line, "cur_skip_line"); module_param(cur_skip_line, int, 0444); -unsigned int super_scaler_v_ratio = 133; +static unsigned int super_scaler_v_ratio = 133; MODULE_PARM_DESC(super_scaler_v_ratio, "super_scaler_v_ratio"); module_param(super_scaler_v_ratio, uint, 0664); @@ -375,39 +378,22 @@ static u32 skip_policy = 0x81; module_param(skip_policy, uint, 0664); MODULE_PARM_DESC(skip_policy, "\n skip_policy\n"); -unsigned int scaler_filter_cnt_limit = 10; +static unsigned int scaler_filter_cnt_limit = 10; MODULE_PARM_DESC(scaler_filter_cnt_limit, "scaler_filter_cnt_limit"); module_param(scaler_filter_cnt_limit, uint, 0664); -static uint last_vert_filter; -static uint last_horz_filter; -static uint scaler_filter_cnt; - -static u32 vpp_wide_mode; -static u32 vpp_zoom_ratio = 100; -static s32 vpp_zoom_center_x, vpp_zoom_center_y; -static u32 nonlinear_factor = MAX_NONLINEAR_FACTOR / 2; -static u32 osd_layer_preblend; -static s32 video_layer_top, video_layer_left, video_layer_width, - video_layer_height; -static u32 video_source_crop_top, video_source_crop_left, - video_source_crop_bottom, video_source_crop_right; -static u32 video_crop_top_resv, video_crop_left_resv, - video_crop_bottom_resv, video_crop_right_resv; -static s32 video_layer_global_offset_x, video_layer_global_offset_y; -static s32 osd_layer_top, osd_layer_left, osd_layer_width, osd_layer_height; -static u32 video_speed_check_width = 1800, video_speed_check_height = 1400; - #ifdef TV_3D_FUNCTION_OPEN -static bool vpp_3d_scale; static int force_filter_mode = 1; MODULE_PARM_DESC(force_filter_mode, "force_filter_mode"); module_param(force_filter_mode, int, 0664); #endif /*temp disable sr for power test*/ -bool super_scaler = true; +bool super_scaler = false; +module_param(super_scaler, bool, 0664); +MODULE_PARM_DESC(super_scaler, "super_scaler"); static unsigned int sr_support; static u32 sr_reg_offt; +static u32 sr_reg_offt2; /*for tl1*/ static unsigned int super_debug; module_param(super_debug, uint, 0664); MODULE_PARM_DESC(super_debug, "super_debug"); @@ -445,15 +431,15 @@ static unsigned int sr0_sr1_refresh = 1; module_param(sr0_sr1_refresh, uint, 0664); MODULE_PARM_DESC(sr0_sr1_refresh, "sr0_sr1_refresh"); -bool pre_scaler_en = true; +static bool pre_scaler_en = true; module_param(pre_scaler_en, bool, 0664); MODULE_PARM_DESC(pre_scaler_en, "pre_scaler_en"); -unsigned int force_vskip_cnt; +static unsigned int force_vskip_cnt; MODULE_PARM_DESC(force_vskip_cnt, "force_vskip_cnt"); module_param(force_vskip_cnt, uint, 0664); -unsigned int disable_adapted; +static unsigned int disable_adapted; MODULE_PARM_DESC(disable_adapted, "disable_adapted"); module_param(disable_adapted, uint, 0664); @@ -553,13 +539,15 @@ static void f2v_get_vertical_phase(u32 zoom_ratio, /* * V-shape non-linear mode */ -static void -calculate_non_linear_ratio(unsigned int middle_ratio, - unsigned int width_out, - struct vpp_frame_par_s *next_frame_par) +static void calculate_non_linear_ratio( + unsigned int nonlinear_factor, + unsigned int middle_ratio, + unsigned int width_out, + struct vpp_frame_par_s *next_frame_par) { unsigned int diff_ratio; - struct vppfilter_mode_s *vpp_filter = &next_frame_par->vpp_filter; + struct vppfilter_mode_s *vpp_filter = + &next_frame_par->vpp_filter; diff_ratio = middle_ratio * nonlinear_factor; vpp_filter->vpp_hf_start_phase_step = (middle_ratio << 6) - diff_ratio; @@ -588,26 +576,37 @@ calculate_non_linear_ratio(unsigned int middle_ratio, * (1.25 * 3840 / 1920) for 1080p mode. */ #define MIN_RATIO_1000 1250 -unsigned int min_skip_ratio = MIN_RATIO_1000; +static unsigned int min_skip_ratio = MIN_RATIO_1000; MODULE_PARM_DESC(min_skip_ratio, "min_skip_ratio"); module_param(min_skip_ratio, uint, 0664); -unsigned int max_proc_height = 2160; +static unsigned int max_proc_height = 2160; MODULE_PARM_DESC(max_proc_height, "max_proc_height"); module_param(max_proc_height, uint, 0664); -unsigned int cur_proc_height; +static unsigned int cur_proc_height; MODULE_PARM_DESC(cur_proc_height, "cur_proc_height"); module_param(cur_proc_height, uint, 0444); -unsigned int cur_skip_ratio; +static unsigned int cur_skip_ratio; MODULE_PARM_DESC(cur_skip_ratio, "cur_skip_ratio"); module_param(cur_skip_ratio, uint, 0444); -unsigned int cur_vf_type; +static unsigned int cur_vf_type; MODULE_PARM_DESC(cur_vf_type, "cur_vf_type"); module_param(cur_vf_type, uint, 0444); +static unsigned int cur_freq_ratio; +MODULE_PARM_DESC(cur_freq_ratio, "cur_freq_ratio"); +module_param(cur_freq_ratio, uint, 0444); -unsigned int custom_ar; +static unsigned int custom_ar; MODULE_PARM_DESC(custom_ar, "custom_ar"); module_param(custom_ar, uint, 0664); +static unsigned int force_use_ext_ar; +MODULE_PARM_DESC(force_use_ext_ar, "force_use_ext_ar"); +module_param(force_use_ext_ar, uint, 0664); + +static unsigned int force_no_compress; +MODULE_PARM_DESC(force_no_compress, "force_no_compress"); +module_param(force_no_compress, uint, 0664); + /* *test on txlx: *Time_out = (V_out/V_screen_total)/FPS_out; @@ -626,30 +625,42 @@ module_param(custom_ar, uint, 0664); *So need adjust bypass_ratio; */ -static int -vpp_process_speed_check(s32 width_in, - s32 height_in, - s32 height_out, - s32 height_screen, - struct vpp_frame_par_s *next_frame_par, - const struct vinfo_s *vinfo, struct vframe_s *vf) +static int vpp_process_speed_check( + u32 layer_id, + s32 width_in, + s32 height_in, + s32 height_out, + s32 height_screen, + u32 video_speed_check_width, + u32 video_speed_check_height, + struct vpp_frame_par_s *next_frame_par, + const struct vinfo_s *vinfo, struct vframe_s *vf) { u32 cur_ratio, bpp = 1; int min_ratio_1000 = 0; + int freq_ratio = 1; + u32 sync_duration_den = 1; u32 vtotal, htotal = 0, clk_in_pps = 0, clk_vpu = 0, clk_temp; u32 input_time_us = 0, display_time_us = 0, dummy_time_us = 0; u32 width_out = 0; u32 vpu_clk = 0, max_height = 2160; /* 4k mode */ - if (vf) + if (!vf) + return SPEED_CHECK_DONE; + + /* store the debug info for legacy */ + if (layer_id == 0) cur_vf_type = vf->type; - else - return 0; + if (force_vskip_cnt == 0xff)/*for debug*/ return SPEED_CHECK_DONE; + if (next_frame_par->vscale_skip_count < force_vskip_cnt) return SPEED_CHECK_VSKIP; + if (vinfo->sync_duration_den > 0) + sync_duration_den = vinfo->sync_duration_den; + if (vf->type & VIDTYPE_PRE_INTERLACE) { if (is_meson_txlx_cpu()) clk_in_pps = 250000000; @@ -697,13 +708,22 @@ vpp_process_speed_check(s32 width_in, if (clk_temp) dummy_time_us = (vtotal * htotal - height_out * width_out) / clk_temp; - display_time_us = 1000000 * vinfo->sync_duration_den / + display_time_us = 1000000 * sync_duration_den / vinfo->sync_duration_num; if (display_time_us > dummy_time_us) display_time_us = display_time_us - dummy_time_us; if (input_time_us > display_time_us) return SPEED_CHECK_VSKIP; } + + if ((vinfo->sync_duration_num / sync_duration_den) > 60) + freq_ratio = vinfo->sync_duration_num / + sync_duration_den / 60; + + if (freq_ratio < 1) + freq_ratio = 1; + cur_freq_ratio = freq_ratio; + /* #if (MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8) */ if ((get_cpu_type() >= MESON_CPU_MAJOR_ID_M8) && !is_meson_mtvd_cpu()) { if ((width_in <= 0) || (height_in <= 0) || (height_out <= 0) @@ -725,60 +745,65 @@ vpp_process_speed_check(s32 width_in, if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXBB) { cur_ratio = div_u64((u64)height_in * - (u64)vinfo->height * - 1000, - height_out * max_height); + (u64)vinfo->height * + 1000 * freq_ratio, + height_out * max_height); /* di process first, need more a bit of ratio */ if (vf->type & VIDTYPE_PRE_INTERLACE) cur_ratio = (cur_ratio * 105) / 100; if ((next_frame_par->vscale_skip_count > 0) && (vf->type & VIDTYPE_VIU_444)) cur_ratio = cur_ratio * 2; - cur_skip_ratio = cur_ratio; + + /* store the debug info for legacy */ + if (layer_id == 0) + cur_skip_ratio = cur_ratio; + if ((cur_ratio > min_ratio_1000) && - (vf->source_type != VFRAME_SOURCE_TYPE_TUNER) && - (vf->source_type != VFRAME_SOURCE_TYPE_CVBS)) + (vf->source_type != + VFRAME_SOURCE_TYPE_TUNER) && + (vf->source_type != + VFRAME_SOURCE_TYPE_CVBS)) return SPEED_CHECK_VSKIP; } if (vf->type & VIDTYPE_VIU_422) { /*TODO vpu */ - if (height_out == 0 - || div_u64((u64)VPP_SPEED_FACTOR * - (u64)width_in * - (u64)height_in * - (u64)vinfo->sync_duration_num * - (u64)vtotal, - height_out * - vinfo->sync_duration_den * - bypass_ratio) > clk_in_pps) - return SPEED_CHECK_VSKIP; - else - return SPEED_CHECK_DONE; - } else { - /*TODO vpu */ - if (height_out == 0 - || div_u64((u64)VPP_SPEED_FACTOR * + if (height_out == 0 || + div_u64((u64)VPP_SPEED_FACTOR * (u64)width_in * (u64)height_in * (u64)vinfo->sync_duration_num * (u64)vtotal, height_out * - vinfo->sync_duration_den * 256) + sync_duration_den * + bypass_ratio) > clk_in_pps) + return SPEED_CHECK_VSKIP; + else + return SPEED_CHECK_DONE; + } else { + /*TODO vpu */ + if (height_out == 0 || + div_u64((u64)VPP_SPEED_FACTOR * + (u64)width_in * + (u64)height_in * + (u64)vinfo->sync_duration_num * + (u64)vtotal, + height_out * + sync_duration_den * 256) > clk_in_pps) return SPEED_CHECK_VSKIP; /* 4K down scaling to non 4K > 30hz,*/ /*skip lines for memory bandwidth */ else if ((((vf->type & VIDTYPE_COMPRESS) - == 0) || (next_frame_par->nocomp)) - && - (height_in > 2048) && - (height_out < 2048) && - (vinfo->sync_duration_num > - (30 * vinfo->sync_duration_den)) && - (get_cpu_type() != - MESON_CPU_MAJOR_ID_GXTVBB) && - (get_cpu_type() != - MESON_CPU_MAJOR_ID_GXM)) + == 0) || (next_frame_par->nocomp)) + && (height_in > 2048) + && (height_out < 2048) + && (vinfo->sync_duration_num > + (30 * sync_duration_den)) + && (get_cpu_type() != + MESON_CPU_MAJOR_ID_GXTVBB) + && (get_cpu_type() != + MESON_CPU_MAJOR_ID_GXM)) return SPEED_CHECK_VSKIP; else return SPEED_CHECK_DONE; @@ -786,8 +811,8 @@ vpp_process_speed_check(s32 width_in, } else if (next_frame_par->hscale_skip_count == 0) { /*TODO vpu */ if (div_u64(VPP_SPEED_FACTOR * width_in * - vinfo->sync_duration_num * height_screen, - vinfo->sync_duration_den * 256) + vinfo->sync_duration_num * height_screen, + sync_duration_den * 256) > get_vpu_clk()) return SPEED_CHECK_HSKIP; else @@ -817,8 +842,9 @@ vpp_process_speed_check(s32 width_in, return SPEED_CHECK_VSKIP; } -static void -vpp_set_filters2(u32 process_3d_type, u32 width_in, +static int vpp_set_filters_internal( + struct disp_info_s *input, + u32 width_in, u32 height_in, u32 wid_out, u32 hei_out, @@ -847,41 +873,66 @@ vpp_set_filters2(u32 process_3d_type, u32 width_in, u32 width_out = wid_out; /* vinfo->width; */ u32 height_out = hei_out; /* vinfo->height; */ u32 aspect_ratio_out = - (vinfo->aspect_ratio_den << 8) / vinfo->aspect_ratio_num; + (vinfo->aspect_ratio_den << 10) / vinfo->aspect_ratio_num; bool fill_match = true; u32 orig_aspect = 0; u32 screen_aspect = 0; bool skip_policy_check = true; u32 vskip_step; + s32 video_layer_global_offset_x, video_layer_global_offset_y; + u32 video_source_crop_top, video_source_crop_left; + u32 video_source_crop_bottom, video_source_crop_right; + u32 vpp_zoom_ratio, nonlinear_factor; + u32 speed_check_width, speed_check_height; + s32 video_layer_top, video_layer_left; + s32 video_layer_width, video_layer_height; + u32 cur_custom_ar; +#ifdef TV_REVERSE + bool reverse = false; +#endif + int ret = VppFilter_Success; + u32 vert_chroma_filter; + struct filter_info_s *cur_filter; + s32 vpp_zoom_center_x, vpp_zoom_center_y; + u32 crop_ratio = 1; + u32 crop_left, crop_right, crop_top, crop_bottom; + u32 sar_width = 0, sar_height = 0; + bool ext_sar = false; + bool no_compress = false; - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXTVBB) { - if (likely(w_in > - (video_source_crop_left + video_source_crop_right))) { - w_in -= video_source_crop_left; - w_in -= video_source_crop_right; - h_crop_enable = true; - } + if (!input) + return VppFilter_Fail; - if (likely(h_in > - (video_source_crop_top + video_source_crop_bottom))) { - h_in -= video_source_crop_top; - h_in -= video_source_crop_bottom; - v_crop_enable = true; - } + cur_filter = &gfilter[input->layer_id]; + cur_custom_ar = input->custom_ar; + vpp_zoom_ratio = input->zoom_ratio; + vpp_zoom_center_x = input->zoom_center_x; + vpp_zoom_center_y = input->zoom_center_y; + speed_check_width = input->speed_check_width; + speed_check_height = input->speed_check_height; + nonlinear_factor = input->nonlinear_factor; + video_layer_global_offset_x = input->global_offset_x; + video_layer_global_offset_y = input->global_offset_y; + + video_layer_top = input->layer_top; + video_layer_left = input->layer_left; + video_layer_width = input->layer_width; + video_layer_height = input->layer_height; +#ifdef TV_REVERSE + reverse = input->reverse; +#endif + + if ((vf->type & VIDTYPE_MVC) || + (input->proc_3d_type & MODE_3D_ENABLE)) { + video_source_crop_left = 0; + video_source_crop_right = 0; + video_source_crop_top = 0; + video_source_crop_bottom = 0; } else { - if (likely(w_in > - (video_source_crop_left + video_source_crop_right))) { - w_in -= video_source_crop_left; - w_in -= video_source_crop_right; - h_crop_enable = true; - } - - if (likely(h_in > - (video_source_crop_top + video_source_crop_bottom))) { - h_in -= video_source_crop_top; - h_in -= video_source_crop_bottom; - v_crop_enable = true; - } + video_source_crop_left = input->crop_left; + video_source_crop_right = input->crop_right; + video_source_crop_top = input->crop_top; + video_source_crop_bottom = input->crop_bottom; } #ifndef TV_3D_FUNCTION_OPEN @@ -899,16 +950,62 @@ vpp_set_filters2(u32 process_3d_type, u32 width_in, #ifdef TV_3D_FUNCTION_OPEN else if ((next_frame_par->vpp_3d_mode == VPP_3D_MODE_LA) - && (process_3d_type & MODE_3D_ENABLE)) + && (input->proc_3d_type & MODE_3D_ENABLE)) vskip_step = 2; #endif else vskip_step = 1; + if (super_debug) + pr_info("sar_width=%d, sar_height = %d, %d\n", + vf->sar_width, vf->sar_height, + force_use_ext_ar); + +RESTART_ALL: + crop_left = video_source_crop_left / crop_ratio; + crop_right = video_source_crop_right / crop_ratio; + crop_top = video_source_crop_top / crop_ratio; + crop_bottom = video_source_crop_bottom / crop_ratio; + + if (likely(w_in > + (crop_left + crop_right))) { + w_in -= crop_left; + w_in -= crop_right; + h_crop_enable = true; + } + + if (likely(h_in > + (crop_top + crop_bottom))) { + h_in -= crop_top; + h_in -= crop_bottom; + v_crop_enable = true; + } + RESTART: aspect_factor = (vpp_flags & VPP_FLAG_AR_MASK) >> VPP_FLAG_AR_BITS; + /* don't use input->wide_mode */ wide_mode = vpp_flags & VPP_FLAG_WIDEMODE_MASK; + if ((vpp_flags & VPP_FLAG_AR_MASK) == VPP_FLAG_AR_MASK) { + ext_sar = true; + sar_width = vf->sar_width; + sar_height = vf->sar_height; + } else if (force_use_ext_ar) { + ext_sar = true; + sar_width = 1; + sar_height = 1; + } + + if (ext_sar && sar_width && sar_height) { + aspect_factor = + div_u64((u64)256ULL * + (u64)sar_height * + (u64)height_in, + (u32)(sar_width * width_in)); + } else { + ext_sar = false; + } + /* keep 8 bits resolution for aspect conversion */ if (wide_mode == VIDEO_WIDEOPTION_4_3) { if (vpp_flags & VPP_FLAG_PORTRAIT_MODE) @@ -916,101 +1013,111 @@ RESTART: else aspect_factor = 0xc0; wide_mode = VIDEO_WIDEOPTION_NORMAL; + ext_sar = false; } else if (wide_mode == VIDEO_WIDEOPTION_16_9) { if (vpp_flags & VPP_FLAG_PORTRAIT_MODE) aspect_factor = 0x1c7; else aspect_factor = 0x90; wide_mode = VIDEO_WIDEOPTION_NORMAL; + ext_sar = false; } else if ((wide_mode >= VIDEO_WIDEOPTION_4_3_IGNORE) - && (wide_mode <= VIDEO_WIDEOPTION_4_3_COMBINED)) { + && (wide_mode <= VIDEO_WIDEOPTION_4_3_COMBINED)) { if (aspect_factor != 0xc0) fill_match = false; orig_aspect = aspect_factor; screen_aspect = 0xc0; + ext_sar = false; } else if ((wide_mode >= VIDEO_WIDEOPTION_16_9_IGNORE) - && (wide_mode <= VIDEO_WIDEOPTION_16_9_COMBINED)) { + && (wide_mode <= VIDEO_WIDEOPTION_16_9_COMBINED)) { if (aspect_factor != 0x90) fill_match = false; orig_aspect = aspect_factor; screen_aspect = 0x90; + ext_sar = false; } else if (wide_mode == VIDEO_WIDEOPTION_CUSTOM) { - if (custom_ar != 0) - aspect_factor = custom_ar & 0x3ff; + if (cur_custom_ar != 0) { + aspect_factor = cur_custom_ar & 0x3ff; + ext_sar = false; + } wide_mode = VIDEO_WIDEOPTION_NORMAL; } else if (wide_mode == VIDEO_WIDEOPTION_AFD) { - if (aspect_factor == 0x90) + if (aspect_factor == 0x90) { wide_mode = VIDEO_WIDEOPTION_FULL_STRETCH; - else + ext_sar = false; + } else wide_mode = VIDEO_WIDEOPTION_NORMAL; } + /* if use the mode ar, will disable ext ar */ if (super_debug) pr_info("aspect_factor=%d,%d,%d,%d,%d,%d\n", aspect_factor, w_in, height_out, - width_out, h_in, aspect_ratio_out); + width_out, h_in, aspect_ratio_out >> 2); if ((aspect_factor == 0) + || (aspect_factor == + (VPP_FLAG_AR_MASK >> VPP_FLAG_AR_BITS)) || (wide_mode == VIDEO_WIDEOPTION_FULL_STRETCH) - || (wide_mode == VIDEO_WIDEOPTION_NONLINEAR)) + || (wide_mode == VIDEO_WIDEOPTION_NONLINEAR)) { aspect_factor = 0x100; - else { + height_after_ratio = h_in; + } else if (ext_sar) { + /* avoid the bit length overflow */ + u64 tmp = (u64)((u64)(width_out * width_in) * aspect_ratio_out); + + tmp = tmp >> 2; + height_after_ratio = + div_u64((u64)256ULL * + (u64)w_in * + (u64)height_out * + (u64)sar_height * + (u64)height_in, + (u32)tmp); + height_after_ratio /= sar_height; + aspect_factor = (height_after_ratio << 8) / h_in; + } else { + /* avoid the bit length overflow */ + u64 tmp = (u64)((u64)(width_out * h_in) * aspect_ratio_out); + + tmp = tmp >> 2; aspect_factor = div_u64((unsigned long long)w_in * height_out * - (aspect_factor << 8), - width_out * h_in * aspect_ratio_out); + (aspect_factor << 8), + (u32)tmp); + height_after_ratio = (h_in * aspect_factor) >> 8; } - if (osd_layer_preblend) - aspect_factor = 0x100; - - height_after_ratio = (h_in * aspect_factor) >> 8; - /* *if we have ever set a cropped display area for video layer * (by checking video_layer_width/video_height), then * it will override the input width_out/height_out for * ratio calculations, a.k.a we have a window for video content */ - if (osd_layer_preblend) { - if ((osd_layer_width == 0) || (osd_layer_height == 0)) { - video_top = 0; - video_left = 0; - video_width = width_out; - video_height = height_out; - - } else { - video_top = osd_layer_top; - video_left = osd_layer_left; - video_width = osd_layer_width; - video_height = osd_layer_height; - } + video_top = video_layer_top; + video_left = video_layer_left; + video_width = video_layer_width; + video_height = video_layer_height; + if ((video_top == 0) && (video_left == 0) && (video_width <= 1) + && (video_height <= 1)) { + /* special case to do full screen display */ + video_width = width_out; + video_height = height_out; } else { - video_top = video_layer_top; - video_left = video_layer_left; - video_width = video_layer_width; - video_height = video_layer_height; - if ((video_top == 0) && (video_left == 0) && (video_width <= 1) - && (video_height <= 1)) { - /* special case to do full screen display */ + if ((video_layer_width < 16) + && (video_layer_height < 16)) { + /* + *sanity check to move + *video out when the target size is too small + */ video_width = width_out; video_height = height_out; - } else { - if ((video_layer_width < 16) - && (video_layer_height < 16)) { - /* - *sanity check to move - *video out when the target size is too small - */ - video_width = width_out; - video_height = height_out; - video_left = width_out * 2; - } - video_top += video_layer_global_offset_y; - video_left += video_layer_global_offset_x; + video_left = width_out * 2; } + video_top += video_layer_global_offset_y; + video_left += video_layer_global_offset_x; } /*aspect ratio match */ @@ -1018,17 +1125,17 @@ RESTART: && (wide_mode <= VIDEO_WIDEOPTION_16_9_COMBINED) && orig_aspect) { if (vinfo->width && vinfo->height) - aspect_ratio_out = (vinfo->height << 8) / vinfo->width; + aspect_ratio_out = (vinfo->height << 10) / vinfo->width; - if ((video_height << 8) > (video_width * aspect_ratio_out)) { + if ((video_height << 10) > (video_width * aspect_ratio_out)) { u32 real_video_height = - (video_width * aspect_ratio_out) >> 8; + (video_width * aspect_ratio_out) >> 10; video_top += (video_height - real_video_height) >> 1; video_height = real_video_height; } else { u32 real_video_width = - (video_height << 8) / aspect_ratio_out; + (video_height << 10) / aspect_ratio_out; video_left += (video_width - real_video_width) >> 1; video_width = real_video_width; @@ -1061,8 +1168,7 @@ RESTART: } ratio_x = screen_ratio_x * w_in / video_width; - ratio_y = - screen_ratio_y * h_in / orig_aspect * + ratio_y = screen_ratio_y * h_in / orig_aspect * screen_aspect / video_height; } else { screen_width = video_width * vpp_zoom_ratio / 100; @@ -1081,9 +1187,10 @@ RESTART: ratio_y = (height_after_ratio << 18) / screen_height; if (super_debug) - pr_info("height_after_ratio=%d,%d,%d,%d,%d\n", - height_after_ratio, ratio_x, ratio_y, - aspect_factor, wide_mode); + pr_info("layer%d: height_after_ratio=%d,%d,%d,%d,%d\n", + input->layer_id, + height_after_ratio, ratio_x, ratio_y, + aspect_factor, wide_mode); if (wide_mode == VIDEO_WIDEOPTION_NORMAL) { ratio_x = ratio_y = max(ratio_x, ratio_y); @@ -1124,26 +1231,16 @@ RESTART: ini_vphase = vpp_zoom_center_y & 0xff; /* screen position for source */ -#ifdef TV_REVERSE - start = - video_top + (video_height + 1) / 2 - ((h_in << 17) + - (vpp_zoom_center_y << 10) + - (ratio_y >> 1)) / ratio_y; + start = video_top + (video_height + 1) / 2 - + ((h_in << 17) + + (vpp_zoom_center_y << 10) + + (ratio_y >> 1)) / ratio_y; end = ((h_in << 18) + (ratio_y >> 1)) / ratio_y + start - 1; if (super_debug) - pr_info("top:start =%d,%d,%d,%d %d,%d,%d\n", + pr_info("layer%d: top:start =%d,%d,%d,%d %d,%d,%d\n", + input->layer_id, start, end, video_top, video_height, h_in, ratio_y, vpp_zoom_center_y); -#else - start = - video_top + video_height / 2 - ((h_in << 17) + - (vpp_zoom_center_y << 10)) / ratio_y; - end = (h_in << 18) / ratio_y + start - 1; - if (super_debug) - pr_info("top:start =%d,%d,%d,%d %d,%d,%d\n", - start, end, video_top, - video_height, h_in, ratio_y, vpp_zoom_center_y); -#endif #ifdef TV_REVERSE if (reverse) { @@ -1153,10 +1250,8 @@ RESTART: temp = (-start * ratio_y) >> 18; next_frame_par->VPP_vd_end_lines_ = h_in - 1 - temp; - } else next_frame_par->VPP_vd_end_lines_ = h_in - 1; - } else { if (start < video_top) { temp = ((video_top - start) * ratio_y) >> 18; @@ -1165,8 +1260,7 @@ RESTART: } else next_frame_par->VPP_vd_end_lines_ = h_in - 1; } - temp = - next_frame_par->VPP_vd_end_lines_ - + temp = next_frame_par->VPP_vd_end_lines_ - (video_height * ratio_y >> 18); next_frame_par->VPP_vd_start_lines_ = (temp >= 0) ? temp : 0; } else @@ -1176,7 +1270,6 @@ RESTART: if (start < 0) { temp = (-start * ratio_y) >> 18; next_frame_par->VPP_vd_start_lines_ = temp; - } else next_frame_par->VPP_vd_start_lines_ = 0; temp_height = min((video_top + video_height - 1), @@ -1185,23 +1278,20 @@ RESTART: if (start < video_top) { temp = ((video_top - start) * ratio_y) >> 18; next_frame_par->VPP_vd_start_lines_ = temp; - } else next_frame_par->VPP_vd_start_lines_ = 0; temp_height = min((video_top + video_height - 1), (vinfo->height - 1)) - video_top + 1; } - - temp = - next_frame_par->VPP_vd_start_lines_ + + temp = next_frame_par->VPP_vd_start_lines_ + (temp_height * ratio_y >> 18); next_frame_par->VPP_vd_end_lines_ = (temp <= (h_in - 1)) ? temp : (h_in - 1); } if (v_crop_enable) { - next_frame_par->VPP_vd_start_lines_ += video_source_crop_top; - next_frame_par->VPP_vd_end_lines_ += video_source_crop_top; + next_frame_par->VPP_vd_start_lines_ += crop_top; + next_frame_par->VPP_vd_end_lines_ += crop_top; } if (vpp_flags & VPP_FLAG_INTERLACE_IN) @@ -1225,15 +1315,14 @@ RESTART: if (start >= end) { /* nothing to display */ next_frame_par->VPP_vsc_startp = 0; - next_frame_par->VPP_vsc_endp = 0; - } else { next_frame_par->VPP_vsc_startp = - (vpp_flags & VPP_FLAG_INTERLACE_OUT) ? (start >> 1) : start; - + (vpp_flags & VPP_FLAG_INTERLACE_OUT) ? + (start >> 1) : start; next_frame_par->VPP_vsc_endp = - (vpp_flags & VPP_FLAG_INTERLACE_OUT) ? (end >> 1) : end; + (vpp_flags & VPP_FLAG_INTERLACE_OUT) ? + (end >> 1) : end; } /* set filter co-efficients */ @@ -1259,27 +1348,16 @@ RESTART: next_frame_par->VPP_hf_ini_phase_ = vpp_zoom_center_x & 0xff; /* screen position for source */ -#ifdef TV_REVERSE - start = - video_left + (video_width + 1) / 2 - ((w_in << 17) + - (vpp_zoom_center_x << 10) + - (ratio_x >> 1)) / ratio_x; + start = video_left + (video_width + 1) / 2 - ((w_in << 17) + + (vpp_zoom_center_x << 10) + + (ratio_x >> 1)) / ratio_x; end = ((w_in << 18) + (ratio_x >> 1)) / ratio_x + start - 1; if (super_debug) - pr_info("left:start =%d,%d,%d,%d %d,%d,%d\n", + pr_info("layer%d: left:start =%d,%d,%d,%d %d,%d,%d\n", + input->layer_id, start, end, video_left, video_width, w_in, ratio_x, vpp_zoom_center_x); -#else - start = - video_left + video_width / 2 - ((w_in << 17) + - (vpp_zoom_center_x << 10)) / - ratio_x; - end = (w_in << 18) / ratio_x + start - 1; - if (super_debug) - pr_info("left:start =%d,%d,%d,%d %d,%d,%d\n", - start, end, video_left, - video_width, w_in, ratio_x, vpp_zoom_center_x); -#endif + /* calculate source horizontal clip */ #ifdef TV_REVERSE if (reverse) { @@ -1323,16 +1401,15 @@ RESTART: temp_width = min((video_left + video_width - 1), (vinfo->width - 1)) - video_left + 1; } - temp = - next_frame_par->VPP_hd_start_lines_ + + temp = next_frame_par->VPP_hd_start_lines_ + (temp_width * ratio_x >> 18); next_frame_par->VPP_hd_end_lines_ = (temp <= (w_in - 1)) ? temp : (w_in - 1); } if (h_crop_enable) { - next_frame_par->VPP_hd_start_lines_ += video_source_crop_left; - next_frame_par->VPP_hd_end_lines_ += video_source_crop_left; + next_frame_par->VPP_hd_start_lines_ += crop_left; + next_frame_par->VPP_hd_end_lines_ += crop_left; } next_frame_par->VPP_line_in_length_ = @@ -1363,9 +1440,10 @@ RESTART: } if ((wide_mode == VIDEO_WIDEOPTION_NONLINEAR) && (end > start)) { - calculate_non_linear_ratio(ratio_x, end - start, - next_frame_par); - + calculate_non_linear_ratio( + nonlinear_factor, + ratio_x, end - start, + next_frame_par); next_frame_par->VPP_hsc_linear_startp = next_frame_par->VPP_hsc_linear_endp = (start + end) / 2; } @@ -1380,6 +1458,7 @@ RESTART: || !next_frame_par->hscale_skip_count) && (!(vpp_flags & VPP_FLAG_VSCALE_DISABLE))) { int skip = vpp_process_speed_check( + input->layer_id, (next_frame_par->VPP_hd_end_lines_ - next_frame_par->VPP_hd_start_lines_ + 1) / (next_frame_par->hscale_skip_count + 1), @@ -1390,6 +1469,8 @@ RESTART: next_frame_par->VPP_vsc_startp + 1), vinfo->height >> ((vpp_flags & VPP_FLAG_INTERLACE_OUT) ? 1 : 0), + speed_check_width, + speed_check_height, next_frame_par, vinfo, vf); @@ -1409,9 +1490,20 @@ RESTART: if ((vf->type & VIDTYPE_COMPRESS) && (vf->canvas0Addr != 0) && - (next_frame_par->vscale_skip_count > 1) && (!next_frame_par->nocomp)) { - pr_info("Try DW buffer for compressed frame scaling.\n"); + if ((next_frame_par->vscale_skip_count > 1) + || !input->afbc_support + || force_no_compress) + no_compress = true; + } else + no_compress = false; + + if (no_compress) { + if ((vpp_flags & VPP_FLAG_MORE_LOG) + && input->afbc_support) + pr_info( + "layer%d: Try DW buffer for compressed frame scaling.\n", + input->layer_id); /* for VIDTYPE_COMPRESS, check if we can use double write * buffer when primary frame can not be scaled. @@ -1421,8 +1513,8 @@ RESTART: h_in = height_in = vf->height; next_frame_par->hscale_skip_count = 0; next_frame_par->vscale_skip_count = 0; - - goto RESTART; + crop_ratio = vf->compWidth / vf->width; + goto RESTART_ALL; } if ((skip_policy & 0xf0) && (skip_policy_check == true)) { @@ -1456,40 +1548,43 @@ RESTART: /* coeff selection before skip and apply pre_scaler */ filter->vpp_vert_filter = coeff(vert_coeff_settings, - filter->vpp_vsc_start_phase_step * - (next_frame_par->vscale_skip_count + 1), - 1, - ((vf->type_original & VIDTYPE_TYPEMASK) - != VIDTYPE_PROGRESSIVE), - vf->combing_cur_lev); + filter->vpp_vsc_start_phase_step * + (next_frame_par->vscale_skip_count + 1), + 1, + ((vf->type_original & VIDTYPE_TYPEMASK) + != VIDTYPE_PROGRESSIVE), + vf->combing_cur_lev); + filter->vpp_vert_coeff = filter_table[filter->vpp_vert_filter]; /* when local interlace or AV or ATV */ /* TODO: add 420 check for local */ if (vert_chroma_filter_force_en || (vert_chroma_filter_en - && (((vf->source_type == VFRAME_SOURCE_TYPE_OTHERS) - && (((vf->type_original & VIDTYPE_TYPEMASK) != VIDTYPE_PROGRESSIVE) || - (vf->height < vert_chroma_filter_limit))) - || (vf->source_type == VFRAME_SOURCE_TYPE_CVBS) - || (vf->source_type == VFRAME_SOURCE_TYPE_TUNER)))) { - cur_vert_chroma_filter - = chroma_filter_table[filter->vpp_vert_filter]; - filter->vpp_vert_chroma_coeff - = filter_table[cur_vert_chroma_filter]; + && (((vf->source_type == VFRAME_SOURCE_TYPE_OTHERS) + && (((vf->type_original & VIDTYPE_TYPEMASK) + != VIDTYPE_PROGRESSIVE) + || (vf->height < vert_chroma_filter_limit))) + || (vf->source_type == VFRAME_SOURCE_TYPE_CVBS) + || (vf->source_type == VFRAME_SOURCE_TYPE_TUNER)))) { + vert_chroma_filter = + chroma_filter_table[filter->vpp_vert_filter]; + filter->vpp_vert_chroma_coeff = + filter_table[vert_chroma_filter]; filter->vpp_vert_chroma_filter_en = true; } else { - cur_vert_chroma_filter = COEF_NULL; + vert_chroma_filter = COEF_NULL; filter->vpp_vert_chroma_filter_en = false; } + /* avoid hscaler fitler adjustion affect on picture shift*/ filter->vpp_horz_filter = coeff(horz_coeff_settings, - filter->vpp_hf_start_phase_step, - next_frame_par->VPP_hf_ini_phase_, - ((vf->type_original & VIDTYPE_TYPEMASK) - != VIDTYPE_PROGRESSIVE), - vf->combing_cur_lev); + filter->vpp_hf_start_phase_step, + next_frame_par->VPP_hf_ini_phase_, + ((vf->type_original & VIDTYPE_TYPEMASK) + != VIDTYPE_PROGRESSIVE), + vf->combing_cur_lev); /*for gxl cvbs out index*/ if ((vinfo->mode == VMODE_CVBS) && //DEBUG_TMP (filter->vpp_hf_start_phase_step == (1 << 24))) @@ -1513,9 +1608,8 @@ RESTART: filter->vpp_vsc_start_phase_step >>= 1; ratio_y >>= 1; f2v_get_vertical_phase(ratio_y, ini_vphase, - next_frame_par->VPP_vf_ini_phase_, - vpp_flags & VPP_FLAG_INTERLACE_OUT); - + next_frame_par->VPP_vf_ini_phase_, + vpp_flags & VPP_FLAG_INTERLACE_OUT); } else filter->vpp_pre_vsc_en = 0; @@ -1543,13 +1637,13 @@ RESTART: filter->vpp_vert_filter = vert_scaler_filter; } if (vert_chroma_filter_force_en && - vert_chroma_scaler_filter <= COEF_3D_FILTER) { - cur_vert_chroma_filter = vert_chroma_scaler_filter; - filter->vpp_vert_chroma_coeff - = filter_table[cur_vert_chroma_filter]; - filter->vpp_vert_chroma_filter_en = true; + (vert_chroma_scaler_filter <= COEF_3D_FILTER)) { + vert_chroma_filter = vert_chroma_scaler_filter; + filter->vpp_vert_chroma_coeff = + filter_table[vert_chroma_filter]; + filter->vpp_vert_chroma_filter_en = true; } else { - cur_vert_chroma_filter = COEF_NULL; + vert_chroma_filter = COEF_NULL; filter->vpp_vert_chroma_filter_en = false; } @@ -1558,90 +1652,44 @@ RESTART: filter->vpp_horz_filter = horz_scaler_filter; } -#ifdef TV_3D_FUNCTION_OPEN +#ifdef TV_3D_FUNCTION_OPEN /* final stage for 3D filter overwrite */ if ((next_frame_par->vpp_3d_scale) && force_filter_mode) { filter->vpp_vert_coeff = filter_table[COEF_3D_FILTER]; filter->vpp_vert_filter = COEF_3D_FILTER; } #endif - if ((last_vert_filter != filter->vpp_vert_filter) || - (last_horz_filter != filter->vpp_horz_filter)) { - last_vert_filter = filter->vpp_vert_filter; - last_horz_filter = filter->vpp_horz_filter; - scaler_filter_cnt = 0; + + if ((cur_filter->last_vert_filter != filter->vpp_vert_filter) || + (cur_filter->last_horz_filter != filter->vpp_horz_filter)) { + cur_filter->last_vert_filter = filter->vpp_vert_filter; + cur_filter->last_horz_filter = filter->vpp_horz_filter; + cur_filter->scaler_filter_cnt = 0; } else { - scaler_filter_cnt++; + cur_filter->scaler_filter_cnt++; } - if ((scaler_filter_cnt >= scaler_filter_cnt_limit) && - ((cur_vert_filter != filter->vpp_vert_filter) || - (cur_horz_filter != filter->vpp_horz_filter))) { - video_property_notify(1); - cur_vert_filter = filter->vpp_vert_filter; - cur_horz_filter = filter->vpp_horz_filter; - scaler_filter_cnt = scaler_filter_cnt_limit; + if ((cur_filter->scaler_filter_cnt >= + scaler_filter_cnt_limit) && + ((cur_filter->cur_vert_filter != + filter->vpp_vert_filter) || + (cur_filter->cur_horz_filter != + filter->vpp_horz_filter))) { + cur_filter->cur_vert_filter = filter->vpp_vert_filter; + cur_filter->cur_horz_filter = filter->vpp_horz_filter; + cur_filter->scaler_filter_cnt = scaler_filter_cnt_limit; + ret = VppFilter_Success_and_Changed; } - cur_skip_line = next_frame_par->vscale_skip_count; -#if HAS_VPU_PROT - if (has_vpu_prot()) { - if (get_prot_status()) { - s32 tmp_height = - (((s32) next_frame_par->VPP_vd_end_lines_ + - 1) << 18) / tmp_ratio_y; - s32 tmp_top = 0; - s32 tmp_bottom = 0; - -/* pr_info("height_out %d video_height %d\n", height_out, video_height); */ -/* pr_info("vf1 %d %d %d %d vs %d %d\n", next_frame_par->VPP_hd_start_lines_,*/ -/* next_frame_par->VPP_hd_end_lines_, */ -/* next_frame_par->VPP_vd_start_lines_, next_frame_par->VPP_vd_end_lines_, */ -/* next_frame_par->hscale_skip_count, next_frame_par->vscale_skip_count); */ - if ((s32) video_height > tmp_height) { - tmp_top = (s32) video_top + - (((s32) video_height - tmp_height) >> 1); - } else - tmp_top = (s32) video_top; - tmp_bottom = tmp_top + - (((s32) next_frame_par->VPP_vd_end_lines_ + 1) << 18) / - (s32) tmp_ratio_y; - if (tmp_bottom > (s32) height_out - && tmp_top < (s32) height_out) { - s32 tmp_end = - (s32) next_frame_par->VPP_vd_end_lines_ - - ((tmp_bottom - - (s32) height_out) * - (s32) tmp_ratio_y >> 18); - if (tmp_end < - (s32) next_frame_par->VPP_vd_end_lines_) { - next_frame_par->VPP_vd_end_lines_ = - tmp_end; - } - - } else if (tmp_bottom > (s32) height_out - && tmp_top >= (s32) height_out) - next_frame_par->VPP_vd_end_lines_ = 1; - next_frame_par->VPP_vd_end_lines_ = - next_frame_par->VPP_vd_end_lines_ - - h_in / height_out; - if ((s32) next_frame_par->VPP_vd_end_lines_ < - (s32) next_frame_par->VPP_vd_start_lines_) { - next_frame_par->VPP_vd_end_lines_ = - next_frame_par->VPP_vd_start_lines_; - } - if ((s32) next_frame_par->VPP_hd_end_lines_ < - (s32) next_frame_par->VPP_hd_start_lines_) { - next_frame_par->VPP_hd_end_lines_ = - next_frame_par->VPP_hd_start_lines_; - } -/* pr_info("tmp_top %d tmp_bottom %d tmp_height %d\n",*/ -/* tmp_top, tmp_bottom, tmp_height); */ -/* pr_info("vf2 %d %d %d %d\n", next_frame_par->VPP_hd_start_lines_,*/ -/* next_frame_par->VPP_hd_end_lines_, */ -/* next_frame_par->VPP_vd_start_lines_, next_frame_par->VPP_vd_end_lines_); */ - } + /* store the debug info for legacy */ + if (input->layer_id == 0) { + cur_vert_filter = cur_filter->cur_vert_filter; + cur_horz_filter = cur_filter->cur_horz_filter; + cur_vert_chroma_filter = vert_chroma_filter; + cur_skip_line = + next_frame_par->vscale_skip_count; } -#endif + + return ret; } /* *VPP_SRSHARP0_CTRL:0x1d91 @@ -1649,132 +1697,153 @@ RESTART: *[1]if sharpness is enable or vscaler is enable,must set to 1, *sharpness1;reg can only to be w on gxtvbb;which is fix after txl */ -int vpp_set_super_scaler_regs(int scaler_path_sel, - int reg_srscl0_enable, - int reg_srscl0_hsize, - int reg_srscl0_vsize, - int reg_srscl0_hori_ratio, - int reg_srscl0_vert_ratio, - int reg_srscl1_enable, - int reg_srscl1_hsize, - int reg_srscl1_vsize, - int reg_srscl1_hori_ratio, - int reg_srscl1_vert_ratio, - int vpp_postblend_out_width, - int vpp_postblend_out_height) +int vpp_set_super_scaler_regs( + int scaler_path_sel, + int reg_srscl0_enable, + int reg_srscl0_hsize, + int reg_srscl0_vsize, + int reg_srscl0_hori_ratio, + int reg_srscl0_vert_ratio, + int reg_srscl1_enable, + int reg_srscl1_hsize, + int reg_srscl1_vsize, + int reg_srscl1_hori_ratio, + int reg_srscl1_vert_ratio, + int vpp_postblend_out_width, + int vpp_postblend_out_height) { int tmp_data = 0; int tmp_data2 = 0; unsigned int data_path_chose; + int sr_core0_max_width = SUPER_CORE0_WIDTH_MAX; + + /* just work around for g12a not to disable sr core2 bit2 */ + if (is_meson_g12a_cpu() && (reg_srscl0_vert_ratio == 0)) + sr_core0_max_width = SUPER_CORE0_WIDTH_MAX << 1; /* top config */ tmp_data = VSYNC_RD_MPEG_REG(VPP_SRSHARP0_CTRL); if (sr0_sr1_refresh) { - if (reg_srscl0_hsize > SUPER_CORE0_WIDTH_MAX) { - if (((tmp_data >> 1)&0x1) != 0) + if (reg_srscl0_hsize > sr_core0_max_width) { + if (((tmp_data >> 1) & 0x1) != 0) VSYNC_WR_MPEG_REG_BITS(VPP_SRSHARP0_CTRL, 0, 1, 1); } else { - if (((tmp_data >> 1)&0x1) != 1) + if (((tmp_data >> 1) & 0x1) != 1) VSYNC_WR_MPEG_REG_BITS(VPP_SRSHARP0_CTRL, 1, 1, 1); } - if ((tmp_data&0x1) != 1) + if ((tmp_data & 0x1) != 1) VSYNC_WR_MPEG_REG_BITS(VPP_SRSHARP0_CTRL, 1, 0, 1); } tmp_data = VSYNC_RD_MPEG_REG(VPP_SRSHARP1_CTRL); if (sr0_sr1_refresh) { - if (((tmp_data >> 1)&0x1) != 1) + if (((tmp_data >> 1) & 0x1) != 1) VSYNC_WR_MPEG_REG_BITS(VPP_SRSHARP1_CTRL, 1, 1, 1); - if ((tmp_data&0x1) != 1) + if ((tmp_data & 0x1) != 1) VSYNC_WR_MPEG_REG_BITS(VPP_SRSHARP1_CTRL, 1, 0, 1); } /* core0 config */ tmp_data = VSYNC_RD_MPEG_REG( SRSHARP0_SHARP_SR2_CTRL + sr_reg_offt); if (sr0_sr1_refresh) { - if (((tmp_data >> 5)&0x1) != (reg_srscl0_vert_ratio&0x1)) + if (((tmp_data >> 5) & 0x1) != (reg_srscl0_vert_ratio&0x1)) VSYNC_WR_MPEG_REG_BITS( SRSHARP0_SHARP_SR2_CTRL + sr_reg_offt, reg_srscl0_vert_ratio&0x1, 5, 1); - if (((tmp_data >> 4)&0x1) != (reg_srscl0_hori_ratio&0x1)) + if (((tmp_data >> 4) & 0x1) != (reg_srscl0_hori_ratio&0x1)) VSYNC_WR_MPEG_REG_BITS( SRSHARP0_SHARP_SR2_CTRL + sr_reg_offt, reg_srscl0_hori_ratio&0x1, 4, 1); - if (reg_srscl0_hsize > SUPER_CORE0_WIDTH_MAX) { - if (((tmp_data >> 2)&0x1) != 0) + if (reg_srscl0_hsize > sr_core0_max_width) { + if (((tmp_data >> 2) & 0x1) != 0) VSYNC_WR_MPEG_REG_BITS( SRSHARP0_SHARP_SR2_CTRL + sr_reg_offt, 0, 2, 1); } else { - if (((tmp_data >> 2)&0x1) != 1) + if (((tmp_data >> 2) & 0x1) != 1) VSYNC_WR_MPEG_REG_BITS( SRSHARP0_SHARP_SR2_CTRL + sr_reg_offt, 1, 2, 1); } - if ((tmp_data & 0x1) == (reg_srscl0_hori_ratio&0x1)) + if ((tmp_data & 0x1) == (reg_srscl0_hori_ratio & 0x1)) VSYNC_WR_MPEG_REG_BITS( SRSHARP0_SHARP_SR2_CTRL + sr_reg_offt, - ((~(reg_srscl0_hori_ratio&0x1))&0x1), 0, 1); + ((~(reg_srscl0_hori_ratio & 0x1)) & 0x1), 0, 1); } /* core1 config */ if (sr_support & SUPER_CORE1_SUPPORT) { - if (is_meson_gxtvbb_cpu()) - tmp_data = sharpness1_sr2_ctrl_32d7; - else - tmp_data = VSYNC_RD_MPEG_REG( - SRSHARP1_SHARP_SR2_CTRL + sr_reg_offt); - if (is_meson_gxtvbb_cpu() || - (((tmp_data >> 5)&0x1) != (reg_srscl1_vert_ratio&0x1)) || - (((tmp_data >> 4)&0x1) != (reg_srscl1_hori_ratio&0x1)) || - ((tmp_data & 0x1) == (reg_srscl1_hori_ratio&0x1)) || - (((tmp_data >> 2)&0x1) != 1)) { - tmp_data = tmp_data & (~(1 << 5)); - tmp_data = tmp_data & (~(1 << 4)); - tmp_data = tmp_data & (~(1 << 2)); - tmp_data = tmp_data & (~(1 << 0)); - tmp_data |= ((reg_srscl1_vert_ratio&0x1) << 5); - tmp_data |= ((reg_srscl1_hori_ratio&0x1) << 4); - tmp_data |= (1 << 2); - tmp_data |= (((~(reg_srscl1_hori_ratio&0x1))&0x1) << 0); - if (sr0_sr1_refresh) { - VSYNC_WR_MPEG_REG( - SRSHARP1_SHARP_SR2_CTRL + sr_reg_offt, - tmp_data); - sharpness1_sr2_ctrl_32d7 = tmp_data; + if (is_meson_gxtvbb_cpu()) + tmp_data = sharpness1_sr2_ctrl_32d7; + else + tmp_data = VSYNC_RD_MPEG_REG( + SRSHARP1_SHARP_SR2_CTRL + + sr_reg_offt2); /*0xc80*/ + if (is_meson_gxtvbb_cpu() || + (((tmp_data >> 5) & 0x1) != + (reg_srscl1_vert_ratio & 0x1)) || + (((tmp_data >> 4) & 0x1) != + (reg_srscl1_hori_ratio & 0x1)) || + ((tmp_data & 0x1) == + (reg_srscl1_hori_ratio & 0x1)) || + (((tmp_data >> 2) & 0x1) != 1)) { + tmp_data = tmp_data & (~(1 << 5)); + tmp_data = tmp_data & (~(1 << 4)); + tmp_data = tmp_data & (~(1 << 2)); + tmp_data = tmp_data & (~(1 << 0)); + tmp_data |= ((reg_srscl1_vert_ratio & 0x1) << 5); + tmp_data |= ((reg_srscl1_hori_ratio & 0x1) << 4); + tmp_data |= (1 << 2); + tmp_data |= + (((~(reg_srscl1_hori_ratio & 0x1)) & 0x1) << 0); + if (sr0_sr1_refresh) { + VSYNC_WR_MPEG_REG( + SRSHARP1_SHARP_SR2_CTRL + + sr_reg_offt2, /*0xc80*/ + tmp_data); + sharpness1_sr2_ctrl_32d7 = tmp_data; + } } } - } /* size config */ tmp_data = ((reg_srscl0_hsize & 0x1fff) << 16) | - (reg_srscl0_vsize & 0x1fff); + (reg_srscl0_vsize & 0x1fff); tmp_data2 = VSYNC_RD_MPEG_REG( SRSHARP0_SHARP_HVSIZE + sr_reg_offt); if (tmp_data != tmp_data2) - VSYNC_WR_MPEG_REG(SRSHARP0_SHARP_HVSIZE + sr_reg_offt, - tmp_data); + VSYNC_WR_MPEG_REG( + SRSHARP0_SHARP_HVSIZE + sr_reg_offt, + tmp_data); tmp_data = ((reg_srscl1_hsize & 0x1fff) << 16) | - (reg_srscl1_vsize & 0x1fff); + (reg_srscl1_vsize & 0x1fff); if (sr_support & SUPER_CORE1_SUPPORT) { if (get_cpu_type() != MESON_CPU_MAJOR_ID_GXTVBB) tmp_data2 = VSYNC_RD_MPEG_REG( - SRSHARP1_SHARP_HVSIZE); + SRSHARP1_SHARP_HVSIZE + sr_reg_offt2); if (is_meson_gxtvbb_cpu() || (tmp_data != tmp_data2)) { VSYNC_WR_MPEG_REG( - SRSHARP1_SHARP_HVSIZE, tmp_data); + SRSHARP1_SHARP_HVSIZE + sr_reg_offt2, tmp_data); if (is_meson_gxtvbb_cpu()) sharpness1_sr2_ctrl_3280 = tmp_data; } } /*ve input size setting*/ - if (is_meson_txhd_cpu() || is_meson_g12a_cpu() || is_meson_g12b_cpu()) + if (is_meson_txhd_cpu() || + is_meson_g12a_cpu() || + is_meson_g12b_cpu() || + is_meson_sm1_cpu()) + tmp_data = ((reg_srscl0_hsize & 0x1fff) << 16) | + (reg_srscl0_vsize & 0x1fff); + else if ((is_meson_tl1_cpu() || is_meson_tm2_cpu()) && + ((scaler_path_sel == PPS_CORE0_CORE1) || + (scaler_path_sel == PPS_CORE0_POSTBLEND_CORE1))) tmp_data = ((reg_srscl0_hsize & 0x1fff) << 16) | (reg_srscl0_vsize & 0x1fff); else @@ -1784,8 +1853,8 @@ int vpp_set_super_scaler_regs(int scaler_path_sel, if (tmp_data != tmp_data2) VSYNC_WR_MPEG_REG(VPP_VE_H_V_SIZE, tmp_data); /*chroma blue stretch size setting*/ - if (is_meson_txlx_cpu() || is_meson_txhd_cpu() || is_meson_g12a_cpu() || - is_meson_g12b_cpu()) { + if (is_meson_txlx_cpu() || is_meson_txhd_cpu() + || (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A))) { tmp_data = (((vpp_postblend_out_width & 0x1fff) << 16) | (vpp_postblend_out_height & 0x1fff)); VSYNC_WR_MPEG_REG(VPP_OUT_H_V_SIZE, tmp_data); @@ -1814,23 +1883,16 @@ int vpp_set_super_scaler_regs(int scaler_path_sel, data_path_chose = 6; else data_path_chose = 5; - if ((scaler_path_sel == CORE0_PPS_CORE1) || - (scaler_path_sel == CORE1_BEFORE_PPS) || - (scaler_path_sel == CORE0_BEFORE_PPS)) { - if (is_meson_g12a_cpu() || is_meson_g12b_cpu()) - VSYNC_WR_MPEG_REG_BITS(VPP_MISC, 1, 1, 1); - else + if (get_cpu_type() <= MESON_CPU_MAJOR_ID_TXHD) { + if ((scaler_path_sel == CORE0_PPS_CORE1) || + (scaler_path_sel == CORE1_BEFORE_PPS) || + (scaler_path_sel == CORE0_BEFORE_PPS)) { VSYNC_WR_MPEG_REG_BITS(VPP_VE_ENABLE_CTRL, 0, data_path_chose, 1); - } else { - if (is_meson_g12a_cpu() || is_meson_g12b_cpu()) { - if (scaler_path_sel == CORE0_AFTER_PPS) - VSYNC_WR_MPEG_REG_BITS(VPP_MISC, 0, 1, 1); - else - VSYNC_WR_MPEG_REG_BITS(VPP_MISC, 1, 1, 1); - } else + } else { VSYNC_WR_MPEG_REG_BITS(VPP_VE_ENABLE_CTRL, 1, data_path_chose, 1); + } } if (super_scaler == 0) { VSYNC_WR_MPEG_REG(VPP_SRSHARP0_CTRL, 0); @@ -1840,9 +1902,11 @@ int vpp_set_super_scaler_regs(int scaler_path_sel, return 0; } -static void vpp_set_super_scaler(const struct vinfo_s *vinfo, - struct vpp_frame_par_s *next_frame_par, - bool bypass_sr0, bool bypass_sr1) +static void vpp_set_super_scaler( + u32 vpp_wide_mode, + const struct vinfo_s *vinfo, + struct vpp_frame_par_s *next_frame_par, + bool bypass_sr0, bool bypass_sr1) { unsigned int hor_sc_multiple_num, ver_sc_multiple_num, temp; u32 width_out = next_frame_par->VPP_hsc_endp - @@ -1851,10 +1915,13 @@ static void vpp_set_super_scaler(const struct vinfo_s *vinfo, next_frame_par->VPP_vsc_startp + 1; u32 src_width = next_frame_par->video_input_w; u32 src_height = next_frame_par->video_input_h; + u32 sr_path; /*for sr adjust*/ vpp_super_scaler_support(); + next_frame_par->sr_core_support = sr_support; + hor_sc_multiple_num = (1 << PPS_FRAC_BITS) / next_frame_par->vpp_filter.vpp_hsc_start_phase_step; ver_sc_multiple_num = SUPER_SCALER_V_FACTOR*(1 << PPS_FRAC_BITS)/ @@ -1869,14 +1936,14 @@ static void vpp_set_super_scaler(const struct vinfo_s *vinfo, /* step1: judge core0&core1 vertical enable or disable*/ if (ver_sc_multiple_num >= 2*SUPER_SCALER_V_FACTOR) { next_frame_par->supsc0_vert_ratio = - ((src_width < SUPER_CORE0_WIDTH_MAX/2) && + ((src_width < SUPER_CORE0_WIDTH_MAX / 2) && (sr_support & SUPER_CORE0_SUPPORT)) ? 1 : 0; next_frame_par->supsc1_vert_ratio = ((width_out < SUPER_CORE1_WIDTH_MAX) && - (src_width < SUPER_CORE1_WIDTH_MAX/2) && + (src_width < SUPER_CORE1_WIDTH_MAX / 2) && (sr_support & SUPER_CORE1_SUPPORT)) ? 1 : 0; if (next_frame_par->supsc0_vert_ratio && - (ver_sc_multiple_num < 4*SUPER_SCALER_V_FACTOR)) + (ver_sc_multiple_num < 4 * SUPER_SCALER_V_FACTOR)) next_frame_par->supsc1_vert_ratio = 0; next_frame_par->supsc0_enable = next_frame_par->supsc0_vert_ratio ? 1 : 0; @@ -1892,15 +1959,15 @@ static void vpp_set_super_scaler(const struct vinfo_s *vinfo, if ((hor_sc_multiple_num >= 2) && (vpp_wide_mode != VIDEO_WIDEOPTION_NONLINEAR)) { if ((src_width > SUPER_CORE0_WIDTH_MAX) || - ((src_width > SUPER_CORE0_WIDTH_MAX/2) && + ((src_width > SUPER_CORE0_WIDTH_MAX / 2) && next_frame_par->supsc0_vert_ratio) || - (((src_width << 1) > SUPER_CORE1_WIDTH_MAX/2) && + (((src_width << 1) > SUPER_CORE1_WIDTH_MAX / 2) && next_frame_par->supsc1_vert_ratio)) next_frame_par->supsc0_hori_ratio = 0; else if (sr_support & SUPER_CORE0_SUPPORT) next_frame_par->supsc0_hori_ratio = 1; if (((width_out >> 1) > SUPER_CORE1_WIDTH_MAX) || - (((width_out >> 1) > SUPER_CORE1_WIDTH_MAX/2) && + (((width_out >> 1) > SUPER_CORE1_WIDTH_MAX / 2) && next_frame_par->supsc1_vert_ratio) || (next_frame_par->supsc0_hori_ratio && (hor_sc_multiple_num < 4))) @@ -1931,7 +1998,7 @@ static void vpp_set_super_scaler(const struct vinfo_s *vinfo, } /* option add patch */ if ((ver_sc_multiple_num <= super_scaler_v_ratio) && - (src_height >= SUPER_CORE0_WIDTH_MAX/2) && + (src_height >= SUPER_CORE0_WIDTH_MAX / 2) && (src_height <= 1088) && (ver_sc_multiple_num > SUPER_SCALER_V_FACTOR) && (vinfo->height >= 2000)) { @@ -1947,6 +2014,14 @@ static void vpp_set_super_scaler(const struct vinfo_s *vinfo, next_frame_par->supsc0_hori_ratio = 0; next_frame_par->supsc0_vert_ratio = 0; } + + /* much vskip case, no need super scale up */ + if (next_frame_par->vscale_skip_count >= 2) { + next_frame_par->supsc0_enable = 0; + next_frame_par->supsc0_hori_ratio = 0; + next_frame_par->supsc0_vert_ratio = 0; + } + if (bypass_sr1 || !(sr_support & SUPER_CORE1_SUPPORT)) { next_frame_par->supsc1_enable = 0; next_frame_par->supsc1_hori_ratio = 0; @@ -1960,8 +2035,10 @@ static void vpp_set_super_scaler(const struct vinfo_s *vinfo, next_frame_par->supscl_path = CORE1_BEFORE_PPS; else next_frame_par->supscl_path = CORE1_AFTER_PPS; - } else if (is_meson_txhd_cpu() || is_meson_g12a_cpu() || - is_meson_g12b_cpu()) { + } else if (is_meson_txhd_cpu() || + is_meson_g12a_cpu() || + is_meson_g12b_cpu() || + is_meson_sm1_cpu()) { next_frame_par->supscl_path = CORE0_BEFORE_PPS; } else next_frame_par->supscl_path = CORE0_PPS_CORE1; @@ -1970,12 +2047,16 @@ static void vpp_set_super_scaler(const struct vinfo_s *vinfo, /*patch for width align 2*/ if (super_scaler && (width_out%2) && - (((next_frame_par->supscl_path == CORE0_AFTER_PPS) && + ((((next_frame_par->supscl_path == CORE0_AFTER_PPS) || + (next_frame_par->supscl_path == PPS_CORE0_CORE1) || + (next_frame_par->supscl_path == PPS_CORE0_POSTBLEND_CORE1)) && next_frame_par->supsc0_hori_ratio) || (((next_frame_par->supscl_path == CORE0_PPS_CORE1) || (next_frame_par->supscl_path == CORE0_CORE1_PPS) || (next_frame_par->supscl_path == CORE1_AFTER_PPS) || - (next_frame_par->supscl_path == CORE0_BEFORE_PPS)) && + (next_frame_par->supscl_path == CORE0_BEFORE_PPS) || + (next_frame_par->supscl_path == PPS_CORE0_CORE1) || + (next_frame_par->supscl_path == PPS_CORE0_POSTBLEND_CORE1)) && next_frame_par->supsc1_hori_ratio))) { temp = next_frame_par->VPP_hsc_endp; if (++temp >= vinfo->width) { @@ -1983,15 +2064,35 @@ static void vpp_set_super_scaler(const struct vinfo_s *vinfo, (next_frame_par->VPP_hsc_startp < next_frame_par->VPP_hsc_endp)) next_frame_par->VPP_hsc_startp--; - else if (next_frame_par->supscl_path == - CORE0_AFTER_PPS) { + else if (((next_frame_par->supscl_path == + PPS_CORE0_CORE1) || + (next_frame_par->supscl_path == + PPS_CORE0_POSTBLEND_CORE1)) && + next_frame_par->supsc0_hori_ratio && + next_frame_par->supsc1_hori_ratio) { + next_frame_par->supsc1_enable = 0; + next_frame_par->supsc1_hori_ratio = 0; + next_frame_par->supsc1_vert_ratio = 0; + next_frame_par->VPP_hsc_endp++; + } else if ((next_frame_par->supscl_path == + CORE0_AFTER_PPS) || + (((next_frame_par->supscl_path == + PPS_CORE0_CORE1) || + (next_frame_par->supscl_path == + PPS_CORE0_POSTBLEND_CORE1)) && + next_frame_par->supsc0_hori_ratio)) { next_frame_par->supsc0_enable = 0; next_frame_par->supsc0_hori_ratio = 0; next_frame_par->supsc0_vert_ratio = 0; } else if ((next_frame_par->supscl_path == CORE1_AFTER_PPS) || (next_frame_par->supscl_path == - CORE0_PPS_CORE1)) { + CORE0_PPS_CORE1) || + (((next_frame_par->supscl_path == + PPS_CORE0_CORE1) || + (next_frame_par->supscl_path == + PPS_CORE0_POSTBLEND_CORE1)) && + next_frame_par->supsc1_hori_ratio)) { next_frame_par->supsc1_enable = 0; next_frame_par->supsc1_hori_ratio = 0; next_frame_par->supsc1_vert_ratio = 0; @@ -2003,12 +2104,16 @@ static void vpp_set_super_scaler(const struct vinfo_s *vinfo, /*patch for height align 2*/ if (super_scaler && (height_out%2) && - (((next_frame_par->supscl_path == CORE0_AFTER_PPS) && + ((((next_frame_par->supscl_path == CORE0_AFTER_PPS) || + (next_frame_par->supscl_path == PPS_CORE0_CORE1) || + (next_frame_par->supscl_path == PPS_CORE0_POSTBLEND_CORE1)) && next_frame_par->supsc0_vert_ratio) || (((next_frame_par->supscl_path == CORE0_PPS_CORE1) || (next_frame_par->supscl_path == CORE0_CORE1_PPS) || (next_frame_par->supscl_path == CORE1_AFTER_PPS) || - (next_frame_par->supscl_path == CORE0_BEFORE_PPS)) && + (next_frame_par->supscl_path == CORE0_BEFORE_PPS) || + (next_frame_par->supscl_path == PPS_CORE0_CORE1) || + (next_frame_par->supscl_path == PPS_CORE0_POSTBLEND_CORE1)) && next_frame_par->supsc1_vert_ratio))) { temp = next_frame_par->VPP_vsc_endp; if (++temp >= vinfo->height) { @@ -2016,15 +2121,35 @@ static void vpp_set_super_scaler(const struct vinfo_s *vinfo, (next_frame_par->VPP_vsc_startp < next_frame_par->VPP_vsc_endp)) next_frame_par->VPP_vsc_startp--; - else if (next_frame_par->supscl_path == - CORE0_AFTER_PPS) { + else if (((next_frame_par->supscl_path == + PPS_CORE0_CORE1) || + (next_frame_par->supscl_path == + PPS_CORE0_POSTBLEND_CORE1)) && + next_frame_par->supsc0_vert_ratio && + next_frame_par->supsc1_vert_ratio) { + next_frame_par->supsc0_enable = 0; + next_frame_par->supsc0_hori_ratio = 0; + next_frame_par->supsc0_vert_ratio = 0; + next_frame_par->VPP_vsc_endp++; + } else if ((next_frame_par->supscl_path == + CORE0_AFTER_PPS) || + (((next_frame_par->supscl_path == + PPS_CORE0_CORE1) || + (next_frame_par->supscl_path == + PPS_CORE0_POSTBLEND_CORE1)) && + next_frame_par->supsc0_vert_ratio)) { next_frame_par->supsc0_enable = 0; next_frame_par->supsc0_hori_ratio = 0; next_frame_par->supsc0_vert_ratio = 0; } else if ((next_frame_par->supscl_path == CORE1_AFTER_PPS) || (next_frame_par->supscl_path == - CORE0_PPS_CORE1)) { + CORE0_PPS_CORE1) || + (((next_frame_par->supscl_path == + PPS_CORE0_CORE1) || + (next_frame_par->supscl_path == + PPS_CORE0_POSTBLEND_CORE1)) && + next_frame_par->supsc1_vert_ratio)) { next_frame_par->supsc1_enable = 0; next_frame_par->supsc1_hori_ratio = 0; next_frame_par->supsc1_vert_ratio = 0; @@ -2047,6 +2172,15 @@ static void vpp_set_super_scaler(const struct vinfo_s *vinfo, height_out >> next_frame_par->supsc0_vert_ratio; next_frame_par->spsc0_w_in = width_out >> next_frame_par->supsc0_hori_ratio; + } else if ((next_frame_par->supscl_path == PPS_CORE0_CORE1) + || (next_frame_par->supscl_path == + PPS_CORE0_POSTBLEND_CORE1)){ /*tl1*/ + next_frame_par->spsc0_h_in = + (height_out >> next_frame_par->supsc0_vert_ratio) >> + next_frame_par->supsc1_vert_ratio; + next_frame_par->spsc0_w_in = + (width_out >> next_frame_par->supsc0_hori_ratio) >> + next_frame_par->supsc1_hori_ratio; } else { next_frame_par->spsc0_h_in = src_height; next_frame_par->spsc0_w_in = src_width; @@ -2054,7 +2188,9 @@ static void vpp_set_super_scaler(const struct vinfo_s *vinfo, if ((next_frame_par->supscl_path == CORE0_PPS_CORE1) || (next_frame_par->supscl_path == CORE0_CORE1_PPS) || (next_frame_par->supscl_path == CORE1_AFTER_PPS) || - (next_frame_par->supscl_path == CORE0_BEFORE_PPS)) { + (next_frame_par->supscl_path == CORE0_BEFORE_PPS) || + (next_frame_par->supscl_path == PPS_CORE0_CORE1) || + (next_frame_par->supscl_path == PPS_CORE0_POSTBLEND_CORE1)) { next_frame_par->spsc1_h_in = (height_out >> next_frame_par->supsc1_vert_ratio); next_frame_par->spsc1_w_in = @@ -2101,16 +2237,73 @@ static void vpp_set_super_scaler(const struct vinfo_s *vinfo, next_frame_par->VPP_pic_in_height_ <<= next_frame_par->supsc1_vert_ratio; } + + sr_path = next_frame_par->supscl_path; + /* path config */ + if (is_meson_tl1_cpu() || is_meson_tm2_cpu()) { + if (sr_path == CORE0_PPS_CORE1) { + next_frame_par->sr0_position = 1; + next_frame_par->sr1_position = 1; + } else if (sr_path == PPS_CORE0_CORE1) { + next_frame_par->sr0_position = 0; + next_frame_par->sr1_position = 1; + } else if (sr_path == + PPS_CORE0_POSTBLEND_CORE1) { + next_frame_par->sr0_position = 0; + next_frame_par->sr1_position = 0; + } else if (sr_path == + CORE0_PPS_POSTBLEND_CORE1) { + next_frame_par->sr0_position = 1; + next_frame_par->sr1_position = 0; + } else { + next_frame_par->sr0_position = 1; + next_frame_par->sr1_position = 1; + } + } else if (is_meson_txhd_cpu() + || is_meson_g12a_cpu() + || is_meson_g12b_cpu() + || is_meson_sm1_cpu()) { + if (sr_path == CORE0_BEFORE_PPS) + next_frame_par->sr0_position = 1; + else if (sr_path == CORE0_AFTER_PPS) + next_frame_par->sr0_position = 0; + else + next_frame_par->sr0_position = 1; + next_frame_par->sr1_position = 0; + } else if (is_meson_gxlx_cpu()) { + if (sr_path == CORE1_BEFORE_PPS) + next_frame_par->sr1_position = 1; + else if (sr_path == CORE1_AFTER_PPS) + next_frame_par->sr1_position = 0; + else + next_frame_par->sr1_position = 1; + next_frame_par->sr0_position = 0; + } else if (is_meson_txlx_cpu() + || is_meson_txl_cpu() + || is_meson_gxtvbb_cpu()) { + if (sr_path == CORE0_PPS_CORE1) { + next_frame_par->sr0_position = 1; + next_frame_par->sr1_position = 1; + } else if (sr_path == + CORE0_PPS_POSTBLEND_CORE1) { + next_frame_par->sr0_position = 1; + next_frame_par->sr1_position = 0; + } else { + next_frame_par->sr0_position = 1; + next_frame_par->sr1_position = 1; + } + } + if (super_debug) { - pr_info("spsc0_w_in=%u, spsc0_h_in=%u, spsc1_w_in=%u, spsc1_h_in=%u.\n", + pr_info("layer0: spsc0_w_in=%u, spsc0_h_in=%u, spsc1_w_in=%u, spsc1_h_in=%u.\n", next_frame_par->spsc0_w_in, next_frame_par->spsc0_h_in, next_frame_par->spsc1_w_in, next_frame_par->spsc1_h_in); - pr_info("supsc0_hori=%d,supsc1_hori=%d,supsc0_v=%d,supsc1_v=%d\n", + pr_info("layer0: supsc0_hori=%d,supsc1_hori=%d,supsc0_v=%d,supsc1_v=%d\n", next_frame_par->supsc0_hori_ratio, next_frame_par->supsc1_hori_ratio, next_frame_par->supsc0_vert_ratio, next_frame_par->supsc1_vert_ratio); - pr_info("VPP_hd_start_lines= %d,%d,%d,%d, %d,%d,%d,%d, %d,%d\n", + pr_info("layer0: VPP_hd_start_lines= %d,%d,%d,%d, %d,%d,%d,%d, %d,%d\n", next_frame_par->VPP_hd_start_lines_, next_frame_par->VPP_hd_end_lines_, next_frame_par->VPP_vd_start_lines_, @@ -2123,8 +2316,10 @@ static void vpp_set_super_scaler(const struct vinfo_s *vinfo, next_frame_par->VPP_vsc_endp); } } + #ifdef TV_3D_FUNCTION_OPEN -void get_vpp_3d_mode(u32 process_3d_type, u32 trans_fmt, u32 *vpp_3d_mode) +void get_vpp_3d_mode( + u32 process_3d_type, u32 trans_fmt, u32 *vpp_3d_mode) { switch (trans_fmt) { case TVIN_TFMT_3D_LRH_OLOR: @@ -2152,19 +2347,28 @@ void get_vpp_3d_mode(u32 process_3d_type, u32 trans_fmt, u32 *vpp_3d_mode) break; } } -static void -vpp_get_video_source_size(u32 *src_width, u32 *src_height, + +static void vpp_get_video_source_size( + u32 *src_width, u32 *src_height, u32 process_3d_type, struct vframe_s *vf, struct vpp_frame_par_s *next_frame_par) { + int frame_width, frame_height; + if (vf->type & VIDTYPE_COMPRESS) { + frame_width = vf->compWidth; + frame_height = vf->compHeight; + } else { + frame_width = vf->width; + frame_height = vf->height; + } if ((process_3d_type & MODE_3D_AUTO) || - (((process_3d_type & MODE_3D_TO_2D_R) || - (process_3d_type & MODE_3D_TO_2D_L) || - (process_3d_type & MODE_3D_LR_SWITCH) || - (process_3d_type & MODE_FORCE_3D_TO_2D_TB) || - (process_3d_type & MODE_FORCE_3D_TO_2D_LR)) && - (process_3d_type & MODE_3D_ENABLE))) { + (((process_3d_type & MODE_3D_TO_2D_R) || + (process_3d_type & MODE_3D_TO_2D_L) || + (process_3d_type & MODE_3D_LR_SWITCH) || + (process_3d_type & MODE_FORCE_3D_TO_2D_TB) || + (process_3d_type & MODE_FORCE_3D_TO_2D_LR)) && + (process_3d_type & MODE_3D_ENABLE))) { if (vf->trans_fmt) { if (process_3d_type & MODE_3D_TO_2D_MASK) *src_height = vf->left_eye.height; @@ -2201,8 +2405,8 @@ vpp_get_video_source_size(u32 *src_width, u32 *src_height, break; case TVIN_TFMT_3D_DET_CHESSBOARD: default: - *src_width = vf->width; - *src_height = vf->height; + *src_width = frame_width; + *src_height = frame_height; next_frame_par->vpp_3d_mode = VPP_3D_MODE_NULL; next_frame_par->vpp_3d_scale = 0; next_frame_par->vpp_2pic_mode = 0; @@ -2210,100 +2414,99 @@ vpp_get_video_source_size(u32 *src_width, u32 *src_height, } } else if ((process_3d_type & MODE_3D_LR) || - (process_3d_type & MODE_FORCE_3D_LR)) { + (process_3d_type & MODE_FORCE_3D_LR)) { next_frame_par->vpp_3d_mode = VPP_3D_MODE_LR; if (process_3d_type & MODE_3D_TO_2D_MASK) { - *src_width = vf->width >> 1; - *src_height = vf->height; + *src_width = frame_width >> 1; + *src_height = frame_height; } else if (process_3d_type & MODE_3D_OUT_LR) { - *src_width = vf->width; - *src_height = vf->height; + *src_width = frame_width; + *src_height = frame_height; next_frame_par->vpp_2pic_mode = 1; } else { - *src_width = vf->width >> 1; - *src_height = vf->height << 1; + *src_width = frame_width >> 1; + *src_height = frame_height << 1; next_frame_par->vpp_2pic_mode = 1; } } else if ((process_3d_type & MODE_3D_TB) || - (process_3d_type & MODE_FORCE_3D_TB)) { + (process_3d_type & MODE_FORCE_3D_TB)) { next_frame_par->vpp_3d_mode = VPP_3D_MODE_TB; if (process_3d_type & MODE_3D_TO_2D_MASK) { - *src_width = vf->width; - *src_height = vf->height >> 1; + *src_width = frame_width; + *src_height = frame_height >> 1; } else if (process_3d_type & MODE_3D_OUT_LR) { - *src_width = vf->width << 1; - *src_height = vf->height >> 1; + *src_width = frame_width << 1; + *src_height = frame_height >> 1; next_frame_par->vpp_2pic_mode = 1; } else { - *src_width = vf->width; - *src_height = vf->height; + *src_width = frame_width; + *src_height = frame_height; next_frame_par->vpp_2pic_mode = 1; } if (process_3d_type & MODE_3D_MVC) { - *src_width = vf->width; - *src_height = vf->height << 1; + *src_width = frame_width; + *src_height = frame_height << 1; next_frame_par->vpp_2pic_mode = 2; next_frame_par->vpp_3d_mode = VPP_3D_MODE_FA; } } else if (process_3d_type & MODE_3D_LA) { next_frame_par->vpp_3d_mode = VPP_3D_MODE_LA; - *src_height = vf->height - 1; - *src_width = vf->width; + *src_height = frame_height - 1; + *src_width = frame_width; next_frame_par->vpp_2pic_mode = 0; next_frame_par->vpp_3d_scale = 1; if (process_3d_type & MODE_3D_TO_2D_MASK) { next_frame_par->vscale_skip_count = 1; next_frame_par->vpp_3d_scale = 0; } else if (process_3d_type & MODE_3D_OUT_TB) { - *src_height = vf->height << 1; + *src_height = frame_height << 1; next_frame_par->vscale_skip_count = 1; next_frame_par->vpp_3d_scale = 0; } else if (process_3d_type & MODE_3D_OUT_LR) { - *src_width = vf->width << 1; + *src_width = frame_width << 1; next_frame_par->vscale_skip_count = 1; next_frame_par->vpp_3d_scale = 0; } } else if ((process_3d_type & MODE_3D_FA) - || (process_3d_type & MODE_FORCE_3D_FA_LR) - || (process_3d_type & MODE_FORCE_3D_FA_TB)) { + || (process_3d_type & MODE_FORCE_3D_FA_LR) + || (process_3d_type & MODE_FORCE_3D_FA_TB)) { next_frame_par->vpp_3d_mode = VPP_3D_MODE_FA; if (process_3d_type & MODE_3D_TO_2D_MASK) { - if (process_3d_type & MODE_FORCE_3D_FA_TB) { next_frame_par->vpp_3d_mode = VPP_3D_MODE_TB; - *src_width = vf->width; - *src_height = vf->height >> 1; + *src_width = frame_width; + *src_height = frame_height >> 1; } if (process_3d_type & MODE_FORCE_3D_FA_LR) { next_frame_par->vpp_3d_mode = VPP_3D_MODE_LR; - *src_width = vf->width >> 1; - *src_height = vf->height; + *src_width = frame_width >> 1; + *src_height = frame_height; } if (process_3d_type & MODE_3D_MVC) { - *src_width = vf->width; - *src_height = vf->height; + *src_width = frame_width; + *src_height = frame_height; next_frame_par->vpp_3d_mode = VPP_3D_MODE_FA; } if (vf->trans_fmt == TVIN_TFMT_3D_FP) { next_frame_par->vpp_3d_mode = VPP_3D_MODE_TB; - *src_width = vf->width; + *src_width = frame_width; *src_height = vf->left_eye.height; } next_frame_par->vpp_2pic_mode = 0; } else if (process_3d_type & MODE_3D_OUT_LR) { - *src_width = vf->width << 1; - *src_height = vf->height; + *src_width = frame_width << 1; + *src_height = frame_height; next_frame_par->vpp_2pic_mode = 2; } else { - *src_width = vf->width; - *src_height = vf->height << 1; + *src_width = frame_width; + *src_height = frame_height << 1; next_frame_par->vpp_2pic_mode = 2; } } else { - *src_width = vf->width; - *src_height = vf->height; + *src_width = frame_width; + *src_height = frame_height; next_frame_par->vpp_3d_mode = VPP_3D_MODE_NULL; next_frame_par->vpp_2pic_mode = 0; next_frame_par->vpp_3d_scale = 0; @@ -2330,56 +2533,503 @@ vpp_get_video_source_size(u32 *src_width, u32 *src_height, } /*avoid dividing 0 error */ if (*src_width == 0 || *src_height == 0) { - *src_width = vf->width; - *src_height = vf->height; + *src_width = frame_width; + *src_height = frame_height; } } #endif -void -vpp_set_filters(u32 process_3d_type, u32 wide_mode, + +static int vpp_set_filters_no_scaler_internal( + struct disp_info_s *input, + u32 width_in, + u32 height_in, + u32 wid_out, + u32 hei_out, + const struct vinfo_s *vinfo, + u32 vpp_flags, + struct vpp_frame_par_s *next_frame_par, struct vframe_s *vf) +{ + s32 start, end; + s32 video_top, video_left, temp; + u32 video_width, video_height; + u32 ratio_x = 0; + u32 ratio_y = 0; + u32 ratio_tmp = 0; + int temp_width; + int temp_height; + struct vppfilter_mode_s *filter = &next_frame_par->vpp_filter; + u32 wide_mode; + s32 height_shift = 0; + u32 w_in = width_in; + u32 h_in = height_in; + bool h_crop_enable = false, v_crop_enable = false; + bool skip_policy_check = true; + u32 vskip_step; + s32 video_layer_global_offset_x, video_layer_global_offset_y; + u32 video_source_crop_top, video_source_crop_left; + u32 video_source_crop_bottom, video_source_crop_right; + s32 video_layer_top, video_layer_left; + s32 video_layer_width, video_layer_height; +#ifdef TV_REVERSE + bool reverse = false; +#endif + int ret = VppFilter_Success; + u32 crop_ratio = 1; + u32 crop_left, crop_right, crop_top, crop_bottom; + bool no_compress = false; + + if (!input) + return VppFilter_Fail; + + video_layer_global_offset_x = input->global_offset_x; + video_layer_global_offset_y = input->global_offset_y; + + video_layer_top = input->layer_top; + video_layer_left = input->layer_left; + video_layer_width = input->layer_width; + video_layer_height = input->layer_height; +#ifdef TV_REVERSE + reverse = input->reverse; +#endif + + if ((vf->type & VIDTYPE_MVC) || + (input->proc_3d_type & MODE_3D_ENABLE)) { + video_source_crop_left = 0; + video_source_crop_right = 0; + video_source_crop_top = 0; + video_source_crop_bottom = 0; + } else { + video_source_crop_left = input->crop_left; + video_source_crop_right = input->crop_right; + video_source_crop_top = input->crop_top; + video_source_crop_bottom = input->crop_bottom; + } + + next_frame_par->vscale_skip_count = 0; + next_frame_par->hscale_skip_count = 0; + next_frame_par->nocomp = false; + if (vpp_flags & VPP_FLAG_INTERLACE_IN) + next_frame_par->vscale_skip_count++; + if (vpp_flags & VPP_FLAG_INTERLACE_OUT) + height_shift++; + + if (vpp_flags & VPP_FLAG_INTERLACE_IN) + vskip_step = 2; + else + vskip_step = 1; + +RESTART_ALL: + crop_left = video_source_crop_left / crop_ratio; + crop_right = video_source_crop_right / crop_ratio; + crop_top = video_source_crop_top / crop_ratio; + crop_bottom = video_source_crop_bottom / crop_ratio; + + if (likely(w_in > + (crop_left + crop_right))) { + w_in -= crop_left; + w_in -= crop_right; + h_crop_enable = true; + } + + if (likely(h_in > + (crop_top + crop_bottom))) { + h_in -= crop_top; + h_in -= crop_bottom; + v_crop_enable = true; + } + +RESTART: + /* don't use input->wide_mode */ + wide_mode = vpp_flags & VPP_FLAG_WIDEMODE_MASK; + + /* + *if we have ever set a cropped display area for video layer + * (by checking video_layer_width/video_height), then + * it will override the input width_out/height_out for + * ratio calculations, a.k.a we have a window for video content + */ + video_top = video_layer_top; + video_left = video_layer_left; + video_width = video_layer_width; + video_height = video_layer_height; + if ((video_top == 0) && (video_left == 0) && (video_width <= 1) + && (video_height <= 1)) { + /* special case to do full screen display */ + video_width = video_layer_width; + video_height = video_layer_height; + } else { + video_top += video_layer_global_offset_y; + video_left += video_layer_global_offset_x; + } + + ratio_x = (1 << 18); + ratio_y = (1 << 18); + + /* screen position for source */ + start = video_top + (video_height + 1) / 2 - + ((h_in << 17) + + (ratio_y >> 1)) / ratio_y; + end = ((h_in << 18) + (ratio_y >> 1)) / ratio_y + start - 1; + if (super_debug) + pr_info("layer%d: top:start =%d,%d,%d,%d %d,%d\n", + input->layer_id, + start, end, video_top, + video_height, h_in, ratio_y); + +#ifdef TV_REVERSE + if (reverse) { + /* calculate source vertical clip */ + if (video_top < 0) { + if (start < 0) { + temp = (-start * ratio_y) >> 18; + next_frame_par->VPP_vd_end_lines_ = + h_in - 1 - temp; + } else + next_frame_par->VPP_vd_end_lines_ = h_in - 1; + } else { + if (start < video_top) { + temp = ((video_top - start) * ratio_y) >> 18; + next_frame_par->VPP_vd_end_lines_ = + h_in - 1 - temp; + } else + next_frame_par->VPP_vd_end_lines_ = h_in - 1; + } + temp = next_frame_par->VPP_vd_end_lines_ - + (video_height * ratio_y >> 18); + next_frame_par->VPP_vd_start_lines_ = (temp >= 0) ? temp : 0; + } else +#endif + { + if (video_top < 0) { + if (start < 0) { + temp = (-start * ratio_y) >> 18; + next_frame_par->VPP_vd_start_lines_ = temp; + } else + next_frame_par->VPP_vd_start_lines_ = 0; + temp_height = min((video_top + video_height - 1), + (vinfo->height - 1)); + } else { + if (start < video_top) { + temp = ((video_top - start) * ratio_y) >> 18; + next_frame_par->VPP_vd_start_lines_ = temp; + } else + next_frame_par->VPP_vd_start_lines_ = 0; + temp_height = min((video_top + video_height - 1), + (vinfo->height - 1)) - video_top + 1; + } + temp = next_frame_par->VPP_vd_start_lines_ + + (temp_height * ratio_y >> 18); + next_frame_par->VPP_vd_end_lines_ = + (temp <= (h_in - 1)) ? temp : (h_in - 1); + } + + if (v_crop_enable) { + next_frame_par->VPP_vd_start_lines_ += crop_top; + next_frame_par->VPP_vd_end_lines_ += crop_top; + } + + if (vpp_flags & VPP_FLAG_INTERLACE_IN) + next_frame_par->VPP_vd_start_lines_ &= ~1; + + next_frame_par->VPP_pic_in_height_ = + next_frame_par->VPP_vd_end_lines_ - + next_frame_par->VPP_vd_start_lines_ + 1; + next_frame_par->VPP_pic_in_height_ = + next_frame_par->VPP_pic_in_height_ / + (next_frame_par->vscale_skip_count + 1); + /* + *find overlapped region between + *[start, end], [0, height_out-1], + *[video_top, video_top+video_height-1] + */ + start = max(start, max(0, video_top)); + end = min(end, min((s32)(vinfo->height - 1), + (s32)(video_top + video_height - 1))); + + if (start >= end) { + /* nothing to display */ + next_frame_par->VPP_vsc_startp = 0; + next_frame_par->VPP_vsc_endp = 0; + } else { + next_frame_par->VPP_vsc_startp = + (vpp_flags & VPP_FLAG_INTERLACE_OUT) ? + (start >> 1) : start; + next_frame_par->VPP_vsc_endp = + (vpp_flags & VPP_FLAG_INTERLACE_OUT) ? + (end >> 1) : end; + } + + /* set filter co-efficients */ + ratio_y <<= height_shift; + ratio_tmp = ratio_y / (next_frame_par->vscale_skip_count + 1); + ratio_y = ratio_tmp; + + filter->vpp_vsc_start_phase_step = 0x1000000; + + /* horizontal */ + filter->vpp_hf_start_phase_slope = 0; + filter->vpp_hf_end_phase_slope = 0; + filter->vpp_hf_start_phase_step = 0x1000000; + + next_frame_par->VPP_hsc_linear_startp = next_frame_par->VPP_hsc_startp; + next_frame_par->VPP_hsc_linear_endp = next_frame_par->VPP_hsc_endp; + + filter->vpp_hsc_start_phase_step = 0x1000000; + next_frame_par->VPP_hf_ini_phase_ = 0; + + /* screen position for source */ + start = video_left + (video_width + 1) / 2 - + ((w_in << 17) + (ratio_x >> 1)) / ratio_x; + end = ((w_in << 18) + (ratio_x >> 1)) / ratio_x + start - 1; + if (super_debug) + pr_info("layer%d: left:start =%d,%d,%d,%d %d,%d\n", + input->layer_id, + start, end, video_left, + video_width, w_in, ratio_x); + + /* calculate source horizontal clip */ +#ifdef TV_REVERSE + if (reverse) { + if (video_left < 0) { + if (start < 0) { + temp = (-start * ratio_x) >> 18; + next_frame_par->VPP_hd_end_lines_ = + w_in - 1 - temp; + } else + next_frame_par->VPP_hd_end_lines_ = w_in - 1; + } else { + if (start < video_left) { + temp = ((video_left - start) * ratio_x) >> 18; + next_frame_par->VPP_hd_end_lines_ = + w_in - 1 - temp; + } else + next_frame_par->VPP_hd_end_lines_ = w_in - 1; + } + temp = next_frame_par->VPP_hd_end_lines_ - + (video_width * ratio_x >> 18); + next_frame_par->VPP_hd_start_lines_ = (temp >= 0) ? temp : 0; + } else +#endif + { + if (video_left < 0) { + if (start < 0) { + temp = (-start * ratio_x) >> 18; + next_frame_par->VPP_hd_start_lines_ = temp; + + } else + next_frame_par->VPP_hd_start_lines_ = 0; + temp_width = min((video_left + video_width - 1), + (vinfo->width - 1)); + } else { + if (start < video_left) { + temp = ((video_left - start) * ratio_x) >> 18; + next_frame_par->VPP_hd_start_lines_ = temp; + + } else + next_frame_par->VPP_hd_start_lines_ = 0; + temp_width = min((video_left + video_width - 1), + (vinfo->width - 1)) - video_left + 1; + } + temp = next_frame_par->VPP_hd_start_lines_ + + (temp_width * ratio_x >> 18); + next_frame_par->VPP_hd_end_lines_ = + (temp <= (w_in - 1)) ? temp : (w_in - 1); + } + + if (h_crop_enable) { + next_frame_par->VPP_hd_start_lines_ += crop_left; + next_frame_par->VPP_hd_end_lines_ += crop_left; + } + + next_frame_par->VPP_line_in_length_ = + next_frame_par->VPP_hd_end_lines_ - + next_frame_par->VPP_hd_start_lines_ + 1; + /* + *find overlapped region between + * [start, end], [0, width_out-1], + * [video_left, video_left+video_width-1] + */ + start = max(start, max(0, video_left)); + end = min(end, + min((s32)(vinfo->width - 1), + (s32)(video_left + video_width - 1))); + + if (start >= end) { + /* nothing to display */ + next_frame_par->VPP_hsc_startp = 0; + next_frame_par->VPP_hsc_endp = 0; + /* avoid mif set wrong or di out size overflow */ + next_frame_par->VPP_hd_start_lines_ = 0; + next_frame_par->VPP_hd_end_lines_ = 0; + next_frame_par->VPP_line_in_length_ = 0; + } else { + next_frame_par->VPP_hsc_startp = start; + next_frame_par->VPP_hsc_endp = end; + } + + /* + *check the painful bandwidth limitation and see + * if we need skip half resolution on source side for progressive + * frames. + */ + /* check vskip and hskip */ + if (((next_frame_par->vscale_skip_count < MAX_VSKIP_COUNT) + || !next_frame_par->hscale_skip_count) + && (!(vpp_flags & VPP_FLAG_VSCALE_DISABLE))) { + int skip = SPEED_CHECK_DONE; + + if (skip == SPEED_CHECK_VSKIP) { + u32 next_vskip = + next_frame_par->vscale_skip_count + vskip_step; + + if (next_vskip <= MAX_VSKIP_COUNT) { + next_frame_par->vscale_skip_count = next_vskip; + goto RESTART; + } else + next_frame_par->hscale_skip_count = 1; + } else if (skip == SPEED_CHECK_HSKIP) + next_frame_par->hscale_skip_count = 1; + } + + if ((vf->type & VIDTYPE_COMPRESS) && + (vf->canvas0Addr != 0) && + (!next_frame_par->nocomp)) { + if ((next_frame_par->vscale_skip_count > 1) + || !input->afbc_support + || force_no_compress) + no_compress = true; + } else + no_compress = false; + + if (no_compress) { + if ((vpp_flags & VPP_FLAG_MORE_LOG) + && input->afbc_support) + pr_info( + "layer%d: Try DW buffer for compressed frame scaling.\n", + input->layer_id); + + /* for VIDTYPE_COMPRESS, check if we can use double write + * buffer when primary frame can not be scaled. + */ + next_frame_par->nocomp = true; + w_in = width_in = vf->width; + h_in = height_in = vf->height; + next_frame_par->hscale_skip_count = 0; + next_frame_par->vscale_skip_count = 0; + if (vf->width && vf->compWidth) + crop_ratio = vf->compWidth / vf->width; + goto RESTART_ALL; + } + + if ((skip_policy & 0xf0) && (skip_policy_check == true)) { + skip_policy_check = false; + if (skip_policy & 0x40) { + next_frame_par->vscale_skip_count = skip_policy & 0xf; + goto RESTART; + } else if (skip_policy & 0x80) { + if ((((vf->width >= 4096) && + (!(vf->type & VIDTYPE_COMPRESS))) || + (vf->flag & VFRAME_FLAG_HIGH_BANDWIDTH)) + && (next_frame_par->vscale_skip_count == 0)) { + next_frame_par->vscale_skip_count = + skip_policy & 0xf; + goto RESTART; + } + } + } + + next_frame_par->video_input_h = next_frame_par->VPP_vd_end_lines_ - + next_frame_par->VPP_vd_start_lines_ + 1; + next_frame_par->video_input_h = next_frame_par->video_input_h / + (next_frame_par->vscale_skip_count + 1); + next_frame_par->video_input_w = next_frame_par->VPP_hd_end_lines_ - + next_frame_par->VPP_hd_start_lines_ + 1; + next_frame_par->video_input_w = next_frame_par->video_input_w / + (next_frame_par->hscale_skip_count + 1); + + filter->vpp_hsc_start_phase_step = 0x1000000; + + /* apply line skip */ + if (next_frame_par->hscale_skip_count) { + filter->vpp_hf_start_phase_step >>= 1; + filter->vpp_hsc_start_phase_step >>= 1; + next_frame_par->VPP_line_in_length_ >>= 1; + } + + return ret; +} + +int vpp_set_filters( + struct disp_info_s *input, struct vframe_s *vf, struct vpp_frame_par_s *next_frame_par, const struct vinfo_s *vinfo, - bool bypass_sr) + bool bypass_sr, u32 op_flag) { u32 src_width = 0; u32 src_height = 0; u32 vpp_flags = 0; u32 aspect_ratio = 0; + u32 process_3d_type; + u32 wide_mode; + int ret = VppFilter_Fail; + struct disp_info_s local_input; + + if (!input) + return ret; WARN_ON(vinfo == NULL); + /* use local var to avoid the input data be overwriten */ + memcpy(&local_input, input, sizeof(struct disp_info_s)); + + process_3d_type = local_input.proc_3d_type; + wide_mode = local_input.wide_mode; + next_frame_par->VPP_post_blend_vd_v_start_ = 0; next_frame_par->VPP_post_blend_vd_h_start_ = 0; next_frame_par->VPP_postproc_misc_ = 0x200; -#ifdef TV_3D_FUNCTION_OPEN next_frame_par->vscale_skip_count = 0; next_frame_par->hscale_skip_count = 0; + + if (vf->type & VIDTYPE_COMPRESS) { + src_width = vf->compWidth; + src_height = vf->compHeight; + } else { + src_width = vf->width; + src_height = vf->height; + } + +#ifdef TV_3D_FUNCTION_OPEN /* *check 3d mode change in display buffer or 3d type *get the source size according to 3d mode */ - if (process_3d_type & MODE_3D_ENABLE) { - vpp_get_video_source_size(&src_width, &src_height, - process_3d_type, vf, next_frame_par); - } else { - if (vf->type & VIDTYPE_COMPRESS) { - src_width = vf->compWidth; - src_height = vf->compHeight; + if (local_input.layer_id == 0) { + if (process_3d_type & MODE_3D_ENABLE) { + vpp_get_video_source_size( + &src_width, &src_height, + process_3d_type, + vf, next_frame_par); } else { - src_width = vf->width; - src_height = vf->height; + next_frame_par->vpp_3d_mode = + VPP_3D_MODE_NULL; + next_frame_par->vpp_2pic_mode = 0; + next_frame_par->vpp_3d_scale = 0; } + next_frame_par->trans_fmt = vf->trans_fmt; + get_vpp_3d_mode(process_3d_type, + next_frame_par->trans_fmt, + &next_frame_par->vpp_3d_mode); + if (local_input.vpp_3d_scale) + next_frame_par->vpp_3d_scale = 1; + } else { next_frame_par->vpp_3d_mode = VPP_3D_MODE_NULL; next_frame_par->vpp_2pic_mode = 0; next_frame_par->vpp_3d_scale = 0; + next_frame_par->trans_fmt = vf->trans_fmt; } - next_frame_par->trans_fmt = vf->trans_fmt; - get_vpp_3d_mode(process_3d_type, next_frame_par->trans_fmt, - &next_frame_par->vpp_3d_mode); - if (vpp_3d_scale) - next_frame_par->vpp_3d_scale = 1; amlog_mask(LOG_MASK_VPP, "%s: src_width %u,src_height %u.\n", __func__, src_width, src_height); #endif @@ -2404,7 +3054,10 @@ vpp_set_filters(u32 process_3d_type, u32 wide_mode, aspect_ratio = (vf->ratio_control & DISP_RATIO_ASPECT_RATIO_MASK) >> DISP_RATIO_ASPECT_RATIO_BIT; - if (vf->type & VIDTYPE_INTERLACE) + /* the height from vdin afbc will be half */ + /* so need no interlace in */ + if ((vf->type & VIDTYPE_INTERLACE) + && !(vf->type & VIDTYPE_COMPRESS)) vpp_flags = VPP_FLAG_INTERLACE_IN; if (vf->ratio_control & DISP_RATIO_PORTRAIT_MODE) @@ -2412,257 +3065,121 @@ vpp_set_filters(u32 process_3d_type, u32 wide_mode, if (vf->type & VIDTYPE_VSCALE_DISABLE) vpp_flags |= VPP_FLAG_VSCALE_DISABLE; -#ifndef TV_3D_FUNCTION_OPEN - if (vf->type & VIDTYPE_COMPRESS) { - src_width = vf->compWidth; - src_height = vf->compHeight; - } else { - src_width = vf->width; - src_height = vf->height; - } -#endif - if (vf->type & VIDTYPE_MVC) { - video_source_crop_top = 0; - video_source_crop_left = 0; - video_source_crop_bottom = 0; - video_source_crop_right = 0; - } else { - video_source_crop_top = video_crop_top_resv; - video_source_crop_left = video_crop_left_resv; - video_source_crop_bottom = video_crop_bottom_resv; - video_source_crop_right = video_crop_right_resv; - } if ((vf->ratio_control & DISP_RATIO_ADAPTED_PICMODE) && !disable_adapted) { if (vf->pic_mode.screen_mode != 0xff) wide_mode = vf->pic_mode.screen_mode; - if (vf->pic_mode.provider == PIC_MODE_PROVIDER_WSS) { - /* from wss, need add global setting */ - video_source_crop_top += vf->pic_mode.vs; - video_source_crop_left += vf->pic_mode.hs; - video_source_crop_bottom += vf->pic_mode.ve; - video_source_crop_right += vf->pic_mode.he; - } else { - /* from PQ database, final setting */ - video_source_crop_top = vf->pic_mode.vs; - video_source_crop_left = vf->pic_mode.hs; - video_source_crop_bottom = vf->pic_mode.ve; - video_source_crop_right = vf->pic_mode.he; - } + if (vf->pic_mode.AFD_enable && (vf->ratio_control & DISP_RATIO_INFOFRAME_AVAIL)) wide_mode = VIDEO_WIDEOPTION_AFD; - if (wide_mode == VIDEO_WIDEOPTION_CUSTOM) - custom_ar = vf->pic_mode.custom_ar; + if (wide_mode == VIDEO_WIDEOPTION_CUSTOM) { + if (!custom_ar) + local_input.custom_ar = custom_ar; + else + local_input.custom_ar = + vf->pic_mode.custom_ar; + } + if (vf->pic_mode.provider == PIC_MODE_PROVIDER_WSS) { + /* from wss, need add global setting */ + local_input.crop_top += vf->pic_mode.vs; + local_input.crop_left += vf->pic_mode.hs; + local_input.crop_bottom += vf->pic_mode.ve; + local_input.crop_right += vf->pic_mode.he; + } else { + /* from PQ database, final setting */ + local_input.crop_top = vf->pic_mode.vs; + local_input.crop_left = vf->pic_mode.hs; + local_input.crop_bottom = vf->pic_mode.ve; + local_input.crop_right = vf->pic_mode.he; + } } - vpp_wide_mode = wide_mode; + + if (!local_input.pps_support) + wide_mode = VIDEO_WIDEOPTION_NORMAL; + + /* don't restore the wide mode */ + /* input->wide_mode = wide_mode; */ vpp_flags |= wide_mode | (aspect_ratio << VPP_FLAG_AR_BITS); if (vinfo->field_height != vinfo->height) vpp_flags |= VPP_FLAG_INTERLACE_OUT; + if (op_flag & 1) + vpp_flags |= VPP_FLAG_MORE_LOG; + next_frame_par->VPP_post_blend_vd_v_end_ = vinfo->field_height - 1; next_frame_par->VPP_post_blend_vd_h_end_ = vinfo->width - 1; next_frame_par->VPP_post_blend_h_size_ = vinfo->width; - vpp_set_filters2(process_3d_type, src_width, src_height, - vinfo->width, vinfo->height, - vinfo, vpp_flags, next_frame_par, vf); + + if (local_input.pps_support) + ret = vpp_set_filters_internal( + &local_input, src_width, src_height, + vinfo->width, vinfo->height, + vinfo, vpp_flags, next_frame_par, vf); + else + ret = vpp_set_filters_no_scaler_internal( + &local_input, src_width, src_height, + vinfo->width, vinfo->height, + vinfo, vpp_flags, next_frame_par, vf); + /*config super scaler after set next_frame_par is calc ok for pps*/ - vpp_set_super_scaler(vinfo, next_frame_par, - (bypass_sr | bypass_spscl0), - (bypass_sr | bypass_spscl1)); + if (local_input.layer_id == 0) + vpp_set_super_scaler( + wide_mode, + vinfo, next_frame_par, + (bypass_sr | bypass_spscl0), + (bypass_sr | bypass_spscl1)); + return ret; } -void prot_get_parameter(u32 wide_mode, - struct vframe_s *vf, - struct vpp_frame_par_s *next_frame_par, - const struct vinfo_s *vinfo) -{ - u32 src_width = 0; - u32 src_height = 0; - u32 vpp_flags = 0; - u32 aspect_ratio = 0; - u32 process_3d_type = VPP_3D_MODE_NULL; - - WARN_ON(vinfo == NULL); - - next_frame_par->VPP_post_blend_vd_v_start_ = 0; - next_frame_par->VPP_post_blend_vd_h_start_ = 0; - - next_frame_par->VPP_postproc_misc_ = 0x200; - - /* check force ratio change flag in display buffer also - * if it exist then it will override the settings in display side - */ - if (vf->ratio_control & DISP_RATIO_FORCECONFIG) { - if ((vf->ratio_control & DISP_RATIO_CTRL_MASK) == - DISP_RATIO_KEEPRATIO) { - if (wide_mode == VIDEO_WIDEOPTION_FULL_STRETCH) - wide_mode = VIDEO_WIDEOPTION_NORMAL; - } else { - if (wide_mode == VIDEO_WIDEOPTION_NORMAL) - wide_mode = VIDEO_WIDEOPTION_FULL_STRETCH; - } - if (vf->ratio_control & DISP_RATIO_FORCE_NORMALWIDE) - wide_mode = VIDEO_WIDEOPTION_NORMAL; - else if (vf->ratio_control & DISP_RATIO_FORCE_FULL_STRETCH) - wide_mode = VIDEO_WIDEOPTION_FULL_STRETCH; - } - - aspect_ratio = (vf->ratio_control & DISP_RATIO_ASPECT_RATIO_MASK) - >> DISP_RATIO_ASPECT_RATIO_BIT; - - if (vf->type & VIDTYPE_INTERLACE) - vpp_flags = VPP_FLAG_INTERLACE_IN; - - if (vf->ratio_control & DISP_RATIO_PORTRAIT_MODE) - vpp_flags |= VPP_FLAG_PORTRAIT_MODE; - - if (vf->type & VIDTYPE_VSCALE_DISABLE) - vpp_flags |= VPP_FLAG_VSCALE_DISABLE; - - src_width = vf->width; - src_height = vf->height; - - vpp_wide_mode = wide_mode; - vpp_flags |= wide_mode | (aspect_ratio << VPP_FLAG_AR_BITS); - - if (vinfo->field_height != vinfo->height) - vpp_flags |= VPP_FLAG_INTERLACE_OUT; - - next_frame_par->VPP_post_blend_vd_v_end_ = - vinfo->field_height - 1; - next_frame_par->VPP_post_blend_vd_h_end_ = - vinfo->width - 1; - next_frame_par->VPP_post_blend_h_size_ = vinfo->width; - - vpp_set_filters2(process_3d_type, src_width, src_height, - vinfo->width, vinfo->height, - vinfo, vpp_flags, next_frame_par, vf); -} - -void vpp_set_osd_layer_preblend(u32 *enable) -{ - osd_layer_preblend = *enable; -} - -void vpp_set_osd_layer_position(s32 *para) -{ - if (IS_ERR_OR_NULL(¶[3])) { - pr_info("para[3] is null\n"); - return; - } - if (para[2] < 2 || para[3] < 2) - return; - - osd_layer_left = para[0]; - osd_layer_top = para[1]; - osd_layer_width = para[2]; - osd_layer_height = para[3]; -} - -void vpp_set_video_source_crop(u32 t, u32 l, u32 b, u32 r) -{ - video_crop_top_resv = t; - video_crop_left_resv = l; - video_crop_bottom_resv = b; - video_crop_right_resv = r; -} - -void vpp_get_video_source_crop(u32 *t, u32 *l, u32 *b, u32 *r) -{ - *t = video_crop_top_resv; - *l = video_crop_left_resv; - *b = video_crop_bottom_resv; - *r = video_crop_right_resv; -} - -void vpp_set_video_layer_position(s32 x, s32 y, s32 w, s32 h) -{ - if ((w < 0) || (h < 0)) - return; - - video_layer_left = x; - video_layer_top = y; - video_layer_width = w; - video_layer_height = h; -} - -void vpp_get_video_layer_position(s32 *x, s32 *y, s32 *w, s32 *h) -{ - *x = video_layer_left; - *y = video_layer_top; - *w = video_layer_width; - *h = video_layer_height; -} - -void vpp_set_global_offset(s32 x, s32 y) -{ - video_layer_global_offset_x = x; - video_layer_global_offset_y = y; -} - -void vpp_get_global_offset(s32 *x, s32 *y) -{ - *x = video_layer_global_offset_x; - *y = video_layer_global_offset_y; -} - -s32 vpp_set_nonlinear_factor(u32 f) +s32 vpp_set_nonlinear_factor( + struct disp_info_s *info, u32 f) { if (f < MAX_NONLINEAR_FACTOR) { - nonlinear_factor = f; + info->nonlinear_factor = f; return 0; } return -1; } -u32 vpp_get_nonlinear_factor(void) +u32 vpp_get_nonlinear_factor( + struct disp_info_s *info) { - return nonlinear_factor; + return info->nonlinear_factor; } -void vpp_set_zoom_ratio(u32 r) +void vpp_disp_info_init( + struct disp_info_s *info, u8 id) { - vpp_zoom_ratio = r; + if (info) { + memset(info, 0, sizeof(struct disp_info_s)); + info->nonlinear_factor = MAX_NONLINEAR_FACTOR / 2; + info->zoom_ratio = 100; + info->speed_check_width = 1800; + info->speed_check_height = 1400; + info->layer_id = id; + memset(&gfilter[id], 0, sizeof(struct filter_info_s)); + } } -u32 vpp_get_zoom_ratio(void) -{ - return vpp_zoom_ratio; -} - -void vpp_set_video_speed_check(u32 h, u32 w) -{ - video_speed_check_height = h; - video_speed_check_width = w; -} - -void vpp_get_video_speed_check(u32 *h, u32 *w) -{ - *h = video_speed_check_height; - *w = video_speed_check_width; -} - -#ifdef TV_3D_FUNCTION_OPEN -void vpp_set_3d_scale(bool enable) -{ - vpp_3d_scale = enable; -} -#endif - void vpp_super_scaler_support(void) { if (is_meson_gxlx_cpu()) { sr_support &= ~SUPER_CORE0_SUPPORT; sr_support |= SUPER_CORE1_SUPPORT; - } else if (is_meson_txhd_cpu() || is_meson_g12a_cpu() || - is_meson_g12b_cpu()) { + } else if (is_meson_txhd_cpu() || + is_meson_g12a_cpu() || + is_meson_g12b_cpu() || + is_meson_sm1_cpu()) { sr_support |= SUPER_CORE0_SUPPORT; sr_support &= ~SUPER_CORE1_SUPPORT; - } else if (is_meson_gxtvbb_cpu() || is_meson_txl_cpu() || - is_meson_txlx_cpu()) { + } else if (is_meson_gxtvbb_cpu() + || is_meson_txl_cpu() + || is_meson_txlx_cpu() + || is_meson_tl1_cpu() + || is_meson_tm2_cpu()) { sr_support |= SUPER_CORE0_SUPPORT; sr_support |= SUPER_CORE1_SUPPORT; } else { @@ -2673,12 +3190,19 @@ void vpp_super_scaler_support(void) sr_support &= ~SUPER_CORE0_SUPPORT; sr_support &= ~SUPER_CORE1_SUPPORT; } - scaler_path_sel = SCALER_PATH_MAX; - if (is_meson_g12a_cpu() || is_meson_g12b_cpu() - || is_meson_tl1_cpu()) + if (is_meson_g12a_cpu() || + is_meson_g12b_cpu() || + is_meson_sm1_cpu()) { sr_reg_offt = 0xc00; - else + sr_reg_offt2 = 0x00; + } else if (is_meson_tl1_cpu() + || is_meson_tm2_cpu()) { + sr_reg_offt = 0xc00; + sr_reg_offt2 = 0xc80; + } else { sr_reg_offt = 0; + sr_reg_offt2 = 0x00; + } } /*for gxlx only have core1 which will affact pip line*/ void vpp_bypass_ratio_config(void) diff --git a/drivers/amlogic/media/vin/tvin/bt656/bt656_601_in.c b/drivers/amlogic/media/vin/tvin/bt656/bt656_601_in.c index dc45d7568e61..4f02b42017ae 100644 --- a/drivers/amlogic/media/vin/tvin/bt656/bt656_601_in.c +++ b/drivers/amlogic/media/vin/tvin/bt656/bt656_601_in.c @@ -1127,14 +1127,17 @@ static int amvdec_656in_probe(struct platform_device *pdev) BT656PR("%s: start probe .\n", __func__); - if (is_meson_gxtvbb_cpu() || - is_meson_gxl_cpu() || is_meson_gxm_cpu()) { + if (is_meson_gxtvbb_cpu() || is_meson_gxl_cpu() || + is_meson_gxm_cpu() || is_meson_g12a_cpu() || + is_meson_g12b_cpu() || is_meson_tl1_cpu() || + is_meson_tm2_cpu()) { hw_cnt = 1; } else if (is_meson_gxbb_cpu()) { hw_cnt = 2; } else { hw_cnt = 0; } + if (hw_cnt == 0) { BT656ERR("no bt656 support for current chip\n"); return -EFAULT; @@ -1241,10 +1244,9 @@ static int amvdec_656in_probe(struct platform_device *pdev) if (IS_ERR(devp->gate_bt656_pclk)) { BT656ERR("%s: cannot get clk_gate_bt656_pclk1 !!!\n", __func__); - ret = -ENOENT; - goto fail_get_clktree; + //ret = -ENOENT; + //goto fail_get_clktree; } - /* set regmap */ BT656PR("%s: bt656[%d] start get ioremap .\n", __func__, devp->index); @@ -1278,7 +1280,7 @@ static int amvdec_656in_probe(struct platform_device *pdev) * &am656_decoder_ops_s, &am656_machine_ops, pdev->id); */ if (!tvin_frontend_init(&devp->frontend, &am656_decoder_ops_s, - &am656_machine_ops, devp->index)) { + &am656_machine_ops, devp->index-1)) { BT656PR("%s: tvin_frontend_init done :%d\n", __func__, devp->index); if (tvin_reg_frontend(&devp->frontend)) { diff --git a/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_drv.c b/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_drv.c index 2e99da3573fb..f05772e7d3ae 100644 --- a/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_drv.c +++ b/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_drv.c @@ -687,7 +687,7 @@ int hdmirx_hw_get_3d_structure(void) /* * hdmirx_get_vsi_info - get vsi info - * this func is used to get 3D format and dobly + * this func is used to get 3D format and dolby * vision state of current video */ void hdmirx_get_vsi_info(struct tvin_sig_property_s *prop) diff --git a/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_drv.h b/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_drv.h index b51798c975f8..d35ea36e5a5d 100644 --- a/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_drv.h +++ b/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_drv.h @@ -46,7 +46,7 @@ * * */ -#define RX_VER2 "ver.2018/10/30" +#define RX_VER2 "ver.2018/11/14" /*print type*/ #define LOG_EN 0x01 diff --git a/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_edid.c b/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_edid.c index c94ee5bbea0a..b25e571e9b9c 100644 --- a/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_edid.c +++ b/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_edid.c @@ -95,7 +95,7 @@ static unsigned char edid_14[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3B, }; -/* 1.4 edid,support dobly,MAT,DTS,ATMOS*/ +/* 1.4 edid,support dolby,MAT,DTS,ATMOS*/ static unsigned char edid_14_aud[] = { 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x05, 0xAC, 0x30, 0x00, 0x01, 0x00, 0x00, 0x00, diff --git a/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_hw.c b/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_hw.c index c36f4994326a..dc6d0255aed0 100644 --- a/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_hw.c +++ b/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_hw.c @@ -913,23 +913,22 @@ if (audio_info->cts != 0) { */ void rx_get_audio_status(struct rx_audio_stat_s *aud_sts) { -if ((rx.state == FSM_SIG_READY) && - (rx.pre.sw_vic != HDMI_UNKNOWN) && - (rx.pre.sw_vic != HDMI_UNSUPPORT) && - (rx.avmute_skip == 0)) { - aud_sts->aud_rcv_flag = - (rx.aud_info.aud_packet_received == 0) ? false : true; - aud_sts->aud_stb_flag = true; - aud_sts->aud_sr = rx.aud_info.real_sr; - aud_sts->aud_channel_cnt = rx.aud_info.channel_count; - aud_sts->aud_type = rx.aud_info.coding_type; - aud_sts->afifo_thres_pass = - ((hdmirx_rd_dwc(DWC_AUD_FIFO_STS) & - THS_PASS_STS) == 0) ? false : true; -} else { - memset(aud_sts, 0, - sizeof(struct rx_audio_stat_s)); -} + if ((rx.state == FSM_SIG_READY) && + (rx.pre.sw_vic != HDMI_UNKNOWN) && + (rx.pre.sw_vic != HDMI_UNSUPPORT) && + (rx.avmute_skip == 0)) { + aud_sts->aud_rcv_packet = rx.aud_info.aud_packet_received; + aud_sts->aud_stb_flag = true; + aud_sts->aud_sr = rx.aud_info.real_sr; + aud_sts->aud_channel_cnt = rx.aud_info.channel_count; + aud_sts->aud_type = rx.aud_info.coding_type; + aud_sts->afifo_thres_pass = + ((hdmirx_rd_dwc(DWC_AUD_FIFO_STS) & + THS_PASS_STS) == 0) ? false : true; + } else { + memset(aud_sts, 0, + sizeof(struct rx_audio_stat_s)); + } } EXPORT_SYMBOL(rx_get_audio_status); @@ -1003,6 +1002,28 @@ else return false; } +void rx_afifo_store_all_subpkt(bool all_pkt) +{ + static bool flag = true; + + if (all_pkt) { + if (log_level & AUDIO_LOG) + rx_pr("afifo store all subpkts: %d\n", flag); + /* when afifo overflow, try afifo store + * configuration alternatively + */ + if (flag) + hdmirx_wr_bits_dwc(DWC_AUD_FIFO_CTRL, + AFIF_SUBPACKETS, 0); + else + hdmirx_wr_bits_dwc(DWC_AUD_FIFO_CTRL, + AFIF_SUBPACKETS, 1); + flag = !flag; + } else + hdmirx_wr_bits_dwc(DWC_AUD_FIFO_CTRL, + AFIF_SUBPACKETS, 1); +} + /* * hdmirx_audio_fifo_rst - reset afifo */ diff --git a/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_hw.h b/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_hw.h index 8c64f4ed22ee..7c7efd3feaae 100644 --- a/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_hw.h +++ b/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_hw.h @@ -1171,6 +1171,7 @@ extern void rx_hpd_to_esm_handle(struct work_struct *work); extern void rx_hdcp14_resume(void); extern void hdmirx_load_firm_reset(int type); extern unsigned int hdmirx_packet_fifo_rst(void); +extern void rx_afifo_store_all_subpkt(bool all_pkt); extern unsigned int hdmirx_audio_fifo_rst(void); extern void hdmirx_phy_init(void); extern void hdmirx_hw_config(void); diff --git a/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_pktinfo.c b/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_pktinfo.c index d0ba34c96908..953e81970f0f 100644 --- a/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_pktinfo.c +++ b/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_pktinfo.c @@ -516,7 +516,7 @@ static void rx_pktdump_vsi(void *pdata) rx_pr("3d vdfmt: 0x%x\n", pktdata->sbpkt.vsi.vdfmt); if (pktdata->length == E_DV_LENGTH_24) { - /*dobly version v0 pkt*/ + /*dolby version v0 pkt*/ } else { if (pktdata->sbpkt.vsi.vdfmt == 0) { @@ -1378,7 +1378,7 @@ void rx_get_vsi_info(void) rx.vs_info_details.eff_tmax_pq = tmp; } } else if (pkt->ieee == 0x000c03) { - /* dobly10 */ + /* dolby10 */ if (pkt->length == E_DV_LENGTH_24) { rx.vs_info_details.dolby_vision = true; if ((pkt->sbpkt.payload.data[0] & 0xffff) == 0) diff --git a/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_wrapper.c b/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_wrapper.c index 8cb5cc3c78b0..bcc318d55c14 100644 --- a/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_wrapper.c +++ b/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_wrapper.c @@ -444,6 +444,11 @@ static int hdmi_rx_ctrl_irq_handler(void) if (log_level & 0x100) rx_pr("[irq] OVERFL\n"); rx.irq_flag |= IRQ_AUD_FLAG; + /* when afifo overflow in multi-channel case(VG-877), + * then store all subpkts into afifo, 8ch in and 8ch out + */ + if (rx.aud_info.auds_layout) + rx_afifo_store_all_subpkt(true); //if (rx.aud_info.real_sr != 0) //error |= hdmirx_audio_fifo_rst(); } @@ -2257,6 +2262,7 @@ void rx_main_state_machine(void) rx_get_audinfo(&rx.aud_info); hdmirx_config_audio(); rx_aud_pll_ctl(1); + rx_afifo_store_all_subpkt(false); hdmirx_audio_fifo_rst(); rx.stable_timestamp = rx.timestamp; rx_pr("Sig ready\n"); diff --git a/drivers/amlogic/media/vin/tvin/tvafe/tvafe.c b/drivers/amlogic/media/vin/tvin/tvafe/tvafe.c index f9e2416f1aa6..9d5cc275f907 100644 --- a/drivers/amlogic/media/vin/tvin/tvafe/tvafe.c +++ b/drivers/amlogic/media/vin/tvin/tvafe/tvafe.c @@ -101,6 +101,8 @@ static int cutwindow_val_h_level2 = 18; static int cutwindow_val_h_level3 = 20; static int cutwindow_val_h_level4 = 62;/*48-->62 for ntsc-m*/ +/*tvconfig snow config*/ +static bool snow_cfg; /*1: snow function on;*/ /*0: off snow function*/ bool tvafe_snow_function_flag; @@ -323,6 +325,7 @@ void tvafe_dec_start(struct tvin_frontend_s *fe, enum tvin_sig_fmt_e fmt) enum tvin_port_e port = devp->tvafe.parm.port; mutex_lock(&devp->afe_mutex); + manual_flag = 0; if (!(devp->flags & TVAFE_FLAG_DEV_OPENED)) { tvafe_pr_err("tvafe_dec_start(%d) decode havn't opened\n", @@ -645,6 +648,17 @@ bool tvafe_is_nosig(struct tvin_frontend_s *fe) if ((port >= TVIN_PORT_CVBS0) && (port <= TVIN_PORT_CVBS3)) { ret = tvafe_cvd2_no_sig(&tvafe->cvd2, &devp->mem); + /*fix black side when config atv snow*/ + if (ret && (port == TVIN_PORT_CVBS3) && + (devp->flags & TVAFE_FLAG_DEV_SNOW_FLAG) && + (tvafe->cvd2.config_fmt == TVIN_SIG_FMT_CVBS_PAL_I) && + (tvafe->cvd2.info.state != TVAFE_CVD2_STATE_FIND)) + tvafe_snow_config_acd(); + else if ((tvafe->cvd2.config_fmt == TVIN_SIG_FMT_CVBS_PAL_I) && + (tvafe->cvd2.info.state == TVAFE_CVD2_STATE_FIND) && + (port == TVIN_PORT_CVBS3)) + tvafe_snow_config_acd_resume(); + /* normal sigal & adc reg error, reload source mux */ if (tvafe->cvd2.info.adc_reload_en && !ret) tvafe_set_source_muxing(port, devp->pinmux); @@ -808,6 +822,18 @@ static bool tvafe_cvbs_get_secam_phase(struct tvin_frontend_s *fe) } +bool tvafe_get_snow_cfg(void) +{ + return snow_cfg; +} +EXPORT_SYMBOL(tvafe_get_snow_cfg); + +void tvafe_set_snow_cfg(bool cfg) +{ + snow_cfg = cfg; +} +EXPORT_SYMBOL(tvafe_set_snow_cfg); + /**check frame skip,only for av input*/ static bool tvafe_cvbs_check_frame_skip(struct tvin_frontend_s *fe) { @@ -878,6 +904,7 @@ static long tvafe_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { long ret = 0; + unsigned int snowcfg = 0; void __user *argp = (void __user *)arg; struct tvafe_dev_s *devp = file->private_data; struct tvafe_info_s *tvafe = &devp->tvafe; @@ -893,8 +920,8 @@ static long tvafe_ioctl(struct file *file, return -EPERM; mutex_lock(&devp->afe_mutex); - if (!(devp->flags & TVAFE_FLAG_DEV_OPENED)) { - + if (!(devp->flags & TVAFE_FLAG_DEV_OPENED) && + cmd != TVIN_IOC_S_AFE_SONWCFG) { tvafe_pr_info("%s, tvafe device is disable, ignore the command %d\n", __func__, cmd); mutex_unlock(&devp->afe_mutex); @@ -922,6 +949,20 @@ static long tvafe_ioctl(struct file *file, break; } + case TVIN_IOC_S_AFE_SONWCFG: + /*tl1/txhd tvconfig snow en/disable*/ + if (copy_from_user(&snowcfg, argp, + sizeof(unsigned int))) { + tvafe_pr_info("snowcfg: get param err\n"); + ret = -EINVAL; + break; + } + if (snowcfg == 1) + tvafe_set_snow_cfg(true); + else + tvafe_set_snow_cfg(false); + tvafe_pr_info("tvconfig snow:%d\n", snow_cfg); + break; case TVIN_IOC_S_AFE_SONWON: devp->flags |= TVAFE_FLAG_DEV_SNOW_FLAG; tvafe_snow_function_flag = true; @@ -963,6 +1004,21 @@ static long tvafe_ioctl(struct file *file, tvafe->cvd2.manual_fmt = fmt; tvafe_pr_info("%s: ioctl set cvd2 manual fmt:%s.\n", __func__, tvin_sig_fmt_str(fmt)); + if (fmt != TVIN_SIG_FMT_NULL) + manual_flag = 1; + break; + } + case TVIN_IOC_G_AFE_CVBS_STD: + { + enum tvin_sig_fmt_e fmt = TVIN_SIG_FMT_NULL; + + if (tvafe->cvd2.info.state == TVAFE_CVD2_STATE_FIND) + fmt = tvafe->cvd2.config_fmt; + if (copy_to_user(argp, &fmt, + sizeof(enum tvin_sig_fmt_e))) + ret = -EFAULT; + tvafe_pr_info("%s: ioctl get fmt:%s.\n", + __func__, tvin_sig_fmt_str(fmt)); break; } default: diff --git a/drivers/amlogic/media/vin/tvin/tvafe/tvafe.h b/drivers/amlogic/media/vin/tvin/tvafe/tvafe.h index 7fe836ff993c..c1b08ca3f650 100644 --- a/drivers/amlogic/media/vin/tvin/tvafe/tvafe.h +++ b/drivers/amlogic/media/vin/tvin/tvafe/tvafe.h @@ -32,7 +32,7 @@ /* ************************************************* */ /* *** macro definitions ********************************************* */ /* *********************************************************** */ -#define TVAFE_VER "Ref.2018/06/27" +#define TVAFE_VER "Ref.2019/04/24" /* used to set the flag of tvafe_dev_s */ #define TVAFE_FLAG_DEV_OPENED 0x00000010 @@ -94,6 +94,9 @@ struct tvafe_dev_s { unsigned int sizeof_tvafe_dev_s; }; +bool tvafe_get_snow_cfg(void); +void tvafe_set_snow_cfg(bool cfg); + typedef int (*hook_func_t)(void); extern void aml_fe_hook_cvd(hook_func_t atv_mode, hook_func_t cvd_hv_lock, hook_func_t get_fmt); diff --git a/drivers/amlogic/media/vin/tvin/tvafe/tvafe_avin_detect.c b/drivers/amlogic/media/vin/tvin/tvafe/tvafe_avin_detect.c index 60759b13e39e..31fda551713a 100644 --- a/drivers/amlogic/media/vin/tvin/tvafe/tvafe_avin_detect.c +++ b/drivers/amlogic/media/vin/tvin/tvafe/tvafe_avin_detect.c @@ -56,7 +56,7 @@ static unsigned int dc_level_adj = 4; /*0:635mv; 1:686mv; 2:733mv; 3:776mv; 4:816mv; 5:853mv; 6:887mv; 7:919mv*/ -static unsigned int comp_level_adj = 5; +static unsigned int comp_level_adj; /*0:use internal VDC to bias CVBS_in*/ /*1:use ground to bias CVBS_in*/ diff --git a/drivers/amlogic/media/vin/tvin/tvafe/tvafe_cvd.c b/drivers/amlogic/media/vin/tvin/tvafe/tvafe_cvd.c index 610992f3afd4..21bc2e93c3c9 100644 --- a/drivers/amlogic/media/vin/tvin/tvafe/tvafe_cvd.c +++ b/drivers/amlogic/media/vin/tvin/tvafe/tvafe_cvd.c @@ -27,6 +27,7 @@ #include #include "../tvin_global.h" #include "../tvin_format_table.h" +#include "tvafe.h" #include "tvafe_regs.h" #include "tvafe_cvd.h" #include "tvafe_debug.h" @@ -320,6 +321,8 @@ static void tvafe_cvd2_memory_init(struct tvafe_cvd2_mem_s *mem, cvd_vbi_mem_set(vbi_start, vbi_size); /*open front lpf for av ring*/ W_APB_BIT(ACD_REG_26, 1, 8, 1); + /*for vbi vcnt*/ + W_APB_BIT(ACD_REG_26, 1, 26, 1); #endif } @@ -418,8 +421,9 @@ static void tvafe_cvd2_write_mode_reg(struct tvafe_cvd2_s *cvd2, } /*setting for txhd snow*/ - if (tvafe_cpu_type() == CPU_TYPE_TXHD || - tvafe_cpu_type() == CPU_TYPE_TL1) { + if (tvafe_get_snow_cfg() && + (tvafe_cpu_type() == CPU_TYPE_TXHD || + tvafe_cpu_type() == CPU_TYPE_TL1)) { W_APB_BIT(CVD2_OUTPUT_CONTROL, 3, 5, 2); W_APB_REG(ACD_REG_6C, 0x80500000); } @@ -920,19 +924,14 @@ void tvafe_cvd2_get_signal_status(struct tvafe_cvd2_s *cvd2) !cvd2->hw_data[2].secam_detected) cvd2->hw.secam_detected = false; - if (cnt_dbg_en) { - - tvafe_pr_info("[%d]:cvd2->hw.acc3xx_cnt =%d,cvd2->hw.acc4xx_cnt=%d,acc425_cnt=%d\n", - __LINE__, - cvd2->hw.acc3xx_cnt, cvd2->hw.acc4xx_cnt, cvd2->hw.acc425_cnt); - tvafe_pr_info("[%d]:cvd2->hw.fsc_358=%d,cvd2->hw.fsc_425=%d,cvd2->hw.fsc_443 =%d\n", - __LINE__, - cvd2->hw.fsc_358, cvd2->hw.fsc_425, cvd2->hw.fsc_443); - } + if (cnt_dbg_en & 1) + tvafe_pr_info("acc4xx_cnt=%d,acc425_cnt=%d,acc3xx_cnt=%d,acc358_cnt=%d\n", + cvd2->hw.acc4xx_cnt, cvd2->hw.acc425_cnt, + cvd2->hw.acc3xx_cnt, cvd2->hw.acc358_cnt); if (cvd2->hw.acc3xx_cnt > CNT_VLD_TH) { if (cvd2->hw.acc358_cnt > - (cvd2->hw.acc3xx_cnt - (cvd2->hw.acc3xx_cnt>>2))) { + (cvd2->hw.acc3xx_cnt - (cvd2->hw.acc3xx_cnt>>3))) { cvd2->hw.fsc_358 = true; cvd2->hw.fsc_425 = false; @@ -958,8 +957,8 @@ void tvafe_cvd2_get_signal_status(struct tvafe_cvd2_s *cvd2) } if (++ cvd2->hw_data_cur >= 3) cvd2->hw_data_cur = 0; - if (cnt_dbg_en) - tvafe_pr_info("[%d]:cvd2->hw.fsc_358=%d,cvd2->hw.fsc_425=%d,cvd2->hw.fsc_443 =%d\n", + if (cnt_dbg_en & 2) + tvafe_pr_info("[%d]:hw.fsc_358=%d,hw.fsc_425=%d,hw.fsc_443 =%d\n", __LINE__, cvd2->hw.fsc_358, cvd2->hw.fsc_425, cvd2->hw.fsc_443); @@ -1128,9 +1127,10 @@ enum tvafe_cvbs_video_e tvafe_cvd2_get_lock_status( { enum tvafe_cvbs_video_e cvbs_lock_status = TVAFE_CVBS_VIDEO_HV_UNLOCKED; - if (!cvd2->hw.h_lock && !cvd2->hw.v_lock) + if (!cvd2->hw.h_lock && !cvd2->hw.v_lock) { cvbs_lock_status = TVAFE_CVBS_VIDEO_HV_UNLOCKED; - else if (cvd2->hw.h_lock && cvd2->hw.v_lock) { + lock_cnt = 0; + } else if (cvd2->hw.h_lock && cvd2->hw.v_lock) { cvbs_lock_status = TVAFE_CVBS_VIDEO_HV_LOCKED; lock_cnt++; } else if (cvd2->hw.h_lock) { @@ -1872,15 +1872,15 @@ static void tvafe_cvd2_auto_de(struct tvafe_cvd2_s *cvd2) W_APB_REG(ACD_REG_2E, tmp); scene_colorful_old = 0; if (cvd_dbg_en) - tvafe_pr_info("%s: vlines:%d, de_offset:%d tmp:%x\n", + tvafe_pr_info("%s: lrg vlines:%d, de_offset:%d tmp:%x\n", __func__, l_ave, lines->de_offset, tmp); } } else { if (lines->de_offset > 0) { tmp = ((TVAFE_CVD2_PAL_DE_START - - lines->de_offset) << 16) | + lines->de_offset + 1) << 16) | (288 + TVAFE_CVD2_PAL_DE_START - - lines->de_offset); + lines->de_offset + 1); W_APB_REG(ACD_REG_2E, tmp); scene_colorful_old = 0; if (cvd_dbg_en) @@ -1994,6 +1994,12 @@ static void tvafe_cvd2_reinit(struct tvafe_cvd2_s *cvd2) #ifdef TVAFE_SET_CVBS_PGA_EN tvafe_cvd2_reset_pga(); #endif + /*pali to nosignal,restore default vstart-end after auto de*/ + if (cvd2->config_fmt == TVIN_SIG_FMT_CVBS_PAL_I) { + W_APB_REG(ACD_REG_2E, 0x170137); + if (cvd_dbg_en) + pr_info("[tvafe..] %s: reset auto de.\n", __func__); + } /* init variable */ memset(&cvd2->info, 0, sizeof(struct tvafe_cvd2_info_s)); cvd2->cvd2_init_en = true; @@ -2009,16 +2015,8 @@ inline bool tvafe_cvd2_no_sig(struct tvafe_cvd2_s *cvd2, struct tvafe_cvd2_mem_s *mem) { static bool ret; - static int time_flag; tvafe_cvd2_get_signal_status(cvd2); - - /*TVAFE register status need more time to be stable.*/ - /*for double time delay.*/ - time_flag++; - if (time_flag%2 != 0) - return ret; - /* get signal status from HW */ /* search video mode */ @@ -2320,6 +2318,15 @@ inline void tvafe_cvd2_adj_hs(struct tvafe_cvd2_s *cvd2, cvd2->info.hs_adj_level = 0; acd_h = acd_h_back; } + } else { + /*signal unstable,set default value*/ + W_APB_REG(ACD_REG_2D, acd_h_back); + W_APB_BIT(CVD2_ACTIVE_VIDEO_HSTART, cvd_2e, + HACTIVE_START_BIT, HACTIVE_START_WID); + W_APB_BIT(ACD_REG_28, acd_128, 16, 5); + cvd2->info.hs_adj_en = 0; + cvd2->info.hs_adj_level = 0; + acd_h = acd_h_back; } } @@ -2637,7 +2644,6 @@ void tvafe_snow_config_acd(void) /*0x8e035e is debug test result*/ if (acd_h_config) W_APB_REG(ACD_REG_2D, acd_h_config); - acd_h = acd_h_back; } /*only for pal-i*/ void tvafe_snow_config_acd_resume(void) diff --git a/drivers/amlogic/media/vin/tvin/tvafe/tvafe_cvd.h b/drivers/amlogic/media/vin/tvin/tvafe/tvafe_cvd.h index 0a851375ea83..b6641539ccdf 100644 --- a/drivers/amlogic/media/vin/tvin/tvafe/tvafe_cvd.h +++ b/drivers/amlogic/media/vin/tvin/tvafe/tvafe_cvd.h @@ -32,7 +32,7 @@ /* vbi start line: unit is hcount value */ #define VBI_START_CC 0x54 #define VBI_START_WSS 0x54 -#define VBI_START_TT 0x82 +#define VBI_START_TT 0x64 #define VBI_START_VPS 0x82 /* cvd2 function enable/disable defines*/ diff --git a/drivers/amlogic/media/vin/tvin/tvafe/tvafe_debug.c b/drivers/amlogic/media/vin/tvin/tvafe/tvafe_debug.c index 44993fd201c9..98a1694bdcf0 100644 --- a/drivers/amlogic/media/vin/tvin/tvafe/tvafe_debug.c +++ b/drivers/amlogic/media/vin/tvin/tvafe/tvafe_debug.c @@ -31,6 +31,7 @@ #include "tvafe_regs.h" #include "tvafe_debug.h" #include "tvafe.h" +#include "../vdin/vdin_ctl.h" bool disableapi; bool force_stable; @@ -256,6 +257,18 @@ static ssize_t tvafe_store(struct device *dev, } } else if (!strncmp(buff, "afe_ver", strlen("afe_ver"))) { tvafe_pr_info("tvafe version : %s\n", TVAFE_VER); + } else if (!strncmp(buff, "snowcfg", strlen("snowcfg"))) { + if (kstrtoul(parm[1], 10, &val) < 0) { + kfree(buf_orig); + return -EINVAL; + } + if (val) { + tvafe_set_snow_cfg(true); + tvafe_pr_info("[tvafe..]hadware snow cfg en\n"); + } else { + tvafe_set_snow_cfg(false); + tvafe_pr_info("[tvafe..]hadware snow cfg dis\n"); + } } else if (!strncmp(buff, "snowon", strlen("snowon"))) { if (kstrtoul(parm[1], 10, &val) < 0) { kfree(buf_orig); @@ -371,6 +384,9 @@ static ssize_t tvafe_dumpmem_store(struct device *dev, struct tvafe_dev_s *devp; char delim1[3] = " "; char delim2[2] = "\n"; + unsigned int highmem_flag = 0; + unsigned long highaddr; + int i; strcat(delim1, delim2); if (!buff) @@ -403,15 +419,34 @@ static ssize_t tvafe_dumpmem_store(struct device *dev, kfree(buf_orig); return len; } - if (devp->cma_config_flag == 1) - buf = codec_mm_phys_to_virt(devp->mem.start); - else + highmem_flag = + PageHighMem(phys_to_page(devp->mem.start)); + pr_info("highmem_flag:%d\n", highmem_flag); + if (devp->cma_config_flag == 1 && + highmem_flag != 0) { + /*tvafe dts config 5M memory*/ + for (i = 0; + i < devp->cma_mem_size / SZ_1M; + i++) { + highaddr = devp->mem.start + i * SZ_1M; + buf = vdin_vmap(highaddr, SZ_1M); + if (!buf) { + pr_info("vdin_vmap error\n"); + return len; + } + pr_info("buf:0x%p\n", buf); + /*vdin_dma_flush(devp, buf, SZ_1M, DMA_FROM_DEVICE);*/ + vfs_write(filp, buf, SZ_1M, &pos); + vdin_unmap_phyaddr(buf); + } + } else { buf = phys_to_virt(devp->mem.start); - vfs_write(filp, buf, devp->mem.size, &pos); - tvafe_pr_info("write buffer %2d of %s.\n", - devp->mem.size, parm[1]); - tvafe_pr_info("devp->mem.start %x .\n", - devp->mem.start); + vfs_write(filp, buf, devp->mem.size, &pos); + tvafe_pr_info("write buffer %2d of %s.\n", + devp->mem.size, parm[1]); + tvafe_pr_info("devp->mem.start %x .\n", + devp->mem.start); + } vfs_fsync(filp, 0); filp_close(filp, NULL); set_fs(old_fs); @@ -450,10 +485,9 @@ static ssize_t tvafereg_store(struct device *dev, struct device_attribute *attr, const char *buff, size_t count) { struct tvafe_dev_s *devp; - unsigned int argn = 0, addr = 0, value = 0, end = 0; + unsigned int argn = 0, addr = 0, value = 0, end = 0, tmp = 0; char *p, *para, *buf_work, cmd = 0; char *argv[3]; - long tmp = 0; devp = dev_get_drvdata(dev); @@ -485,7 +519,7 @@ static ssize_t tvafereg_store(struct device *dev, if (argn < 2) { tvafe_pr_err("syntax error.\n"); } else{ - if (kstrtol(argv[1], 16, &tmp) == 0) + if (kstrtouint(argv[1], 16, &tmp) == 0) addr = tmp; else break; @@ -499,11 +533,11 @@ static ssize_t tvafereg_store(struct device *dev, if (argn < 3) { tvafe_pr_err("syntax error.\n"); } else{ - if (kstrtol(argv[1], 16, &tmp) == 0) + if (kstrtouint(argv[1], 16, &tmp) == 0) value = tmp; else break; - if (kstrtol(argv[2], 16, &tmp) == 0) + if (kstrtouint(argv[2], 16, &tmp) == 0) addr = tmp; else break; @@ -517,11 +551,11 @@ static ssize_t tvafereg_store(struct device *dev, if (argn < 3) { tvafe_pr_err("syntax error.\n"); } else{ - if (kstrtol(argv[1], 16, &tmp) == 0) + if (kstrtouint(argv[1], 16, &tmp) == 0) addr = tmp; else break; - if (kstrtol(argv[2], 16, &tmp) == 0) + if (kstrtouint(argv[2], 16, &tmp) == 0) end = tmp; else break; diff --git a/drivers/amlogic/media/vin/tvin/tvafe/tvafe_general.c b/drivers/amlogic/media/vin/tvin/tvafe/tvafe_general.c index 70c8faacf8e1..cec12d86767c 100644 --- a/drivers/amlogic/media/vin/tvin/tvafe/tvafe_general.c +++ b/drivers/amlogic/media/vin/tvin/tvafe/tvafe_general.c @@ -254,14 +254,16 @@ static enum tvafe_adc_ch_e tvafe_adc_pin_muxing( W_APB_BIT(TVFE_VAFE_CTRL1, 1, VAFE_IN_SEL_BIT, VAFE_IN_SEL_WID); - W_APB_BIT(TVFE_VAFE_CTRL2, 3, 4, 3); + if (tvafe_cpu_type() != CPU_TYPE_TL1) + W_APB_BIT(TVFE_VAFE_CTRL2, 3, 4, 3); ret = TVAFE_ADC_CH_0; } else if (pin == TVAFE_CVBS_IN1) { W_APB_BIT(TVFE_VAFE_CTRL1, 2, VAFE_IN_SEL_BIT, VAFE_IN_SEL_WID); - W_APB_BIT(TVFE_VAFE_CTRL2, 5, 4, 3); + if (tvafe_cpu_type() != CPU_TYPE_TL1) + W_APB_BIT(TVFE_VAFE_CTRL2, 5, 4, 3); ret = TVAFE_ADC_CH_1; } else if (pin == TVAFE_CVBS_IN2) { @@ -450,7 +452,7 @@ static void tvafe_set_cvbs_default(struct tvafe_cvd2_s *cvd2, (port == TVIN_PORT_CVBS2)) { W_APB_REG(TVFE_VAFE_CTRL0, 0x00490710); W_APB_REG(TVFE_VAFE_CTRL1, 0x0000110e); - W_APB_REG(TVFE_VAFE_CTRL2, 0x1fe09fd3); + W_APB_REG(TVFE_VAFE_CTRL2, 0x1fe09f83); } } else { W_APB_REG(TVFE_VAFE_CTRL0, 0x00090b00); @@ -706,19 +708,19 @@ int adc_set_pll_cntl(bool on, unsigned int module_sel, void *pDtvPara) adc_pll_lock_cnt++; } while (!R_HIU_BIT(HHI_ADC_PLL_CNTL0_TL1, 31, 1) && (adc_pll_lock_cnt < 10)); - tvafe_pr_info("b0=0x%x", + tvafe_pr_info("b0=0x%x\n", R_HIU_REG(HHI_ADC_PLL_CNTL0_TL1)); - tvafe_pr_info("b1=0x%x", + tvafe_pr_info("b1=0x%x\n", R_HIU_REG(HHI_ADC_PLL_CNTL1_TL1)); - tvafe_pr_info("b2=0x%x", + tvafe_pr_info("b2=0x%x\n", R_HIU_REG(HHI_ADC_PLL_CNTL2_TL1)); - tvafe_pr_info("b3=0x%x", + tvafe_pr_info("b3=0x%x\n", R_HIU_REG(HHI_ADC_PLL_CNTL3_TL1)); - tvafe_pr_info("b4=0x%x", + tvafe_pr_info("b4=0x%x\n", R_HIU_REG(HHI_ADC_PLL_CNTL4_TL1)); - tvafe_pr_info("b5=0x%x", + tvafe_pr_info("b5=0x%x\n", R_HIU_REG(HHI_ADC_PLL_CNTL5_TL1)); - tvafe_pr_info("b6=0x%x", + tvafe_pr_info("b6=0x%x\n", R_HIU_REG(HHI_ADC_PLL_CNTL6_TL1)); } else { @@ -800,7 +802,7 @@ int adc_set_pll_cntl(bool on, unsigned int module_sel, void *pDtvPara) W_HIU_REG(0xf3, 0x00800000); //HHI_AUDPLL_CLK_OUT_CNTL - W_HIU_REG(0x74, 0x501); + W_HIU_REG(HHI_DEMOD_CLK_CNTL, 0x501); } else if (tvafe_cpu_type() == CPU_TYPE_TXL || tvafe_cpu_type() == CPU_TYPE_TXLX || @@ -848,7 +850,7 @@ int adc_set_pll_cntl(bool on, unsigned int module_sel, void *pDtvPara) tvafe_pr_info("\n%s: on:%d,module:0x%x,flag:0x%x...\n", __func__, on, module_sel, adc_pll_chg); break; - case ADC_EN_DTV_DEMODPLL: /* dtv demod default*/ + case ADC_EN_DTV_DEMODPLL: /* dtv demod */ if (adc_pll_chg & (ADC_EN_ATV_DEMOD | ADC_EN_TVAFE)) { ret = -4; @@ -871,10 +873,17 @@ int adc_set_pll_cntl(bool on, unsigned int module_sel, void *pDtvPara) /*reset*/ W_HIU_REG(HHI_ADC_PLL_CNTL3, 0xca6a2110); W_HIU_REG(HHI_ADC_PLL_CNTL, pDpara->adcpllctl); - if (pDpara->atsc) + if (pDpara->atsc) { W_HIU_REG(HHI_DEMOD_CLK_CNTL, 0x507); - else - W_HIU_REG(HHI_DEMOD_CLK_CNTL, 0x502); + } else { + /*bugzilla 139044*/ + if (tvafe_cpu_type() == CPU_TYPE_TXL) + W_HIU_REG(HHI_DEMOD_CLK_CNTL, + 0x301); + else + W_HIU_REG(HHI_DEMOD_CLK_CNTL, + 0x502); + } W_HIU_REG(HHI_ADC_PLL_CNTL3, 0x4a6a2110); diff --git a/drivers/amlogic/media/vin/tvin/tvafe/tvafe_vbi.c b/drivers/amlogic/media/vin/tvin/tvafe/tvafe_vbi.c index 21a3ee5df45b..c1b7f73374bf 100644 --- a/drivers/amlogic/media/vin/tvin/tvafe/tvafe_vbi.c +++ b/drivers/amlogic/media/vin/tvin/tvafe/tvafe_vbi.c @@ -31,6 +31,7 @@ #include #include #include +#include #include /* #include */ @@ -87,6 +88,7 @@ module_param(vbi_wakeup_interval, uint, 0664); static unsigned int vcnt = 1; static unsigned int wakeup_cnt; static unsigned int init_cc_data_flag; +static bool vbi_pr_en; static void vbi_hw_reset(struct vbi_dev_s *devp) { @@ -131,7 +133,7 @@ static void vbi_data_type_set(struct vbi_dev_s *devp) W_VBI_APB_REG(CVD2_VBI_DATA_TYPE_LINE23, vbi_data_type); W_VBI_APB_REG(CVD2_VBI_DATA_TYPE_LINE24, vbi_data_type); W_VBI_APB_REG(CVD2_VBI_DATA_TYPE_LINE25, vbi_data_type); - W_VBI_APB_REG(CVD2_VBI_DATA_TYPE_LINE26, vbi_data_type); + /*W_VBI_APB_REG(CVD2_VBI_DATA_TYPE_LINE26, vbi_data_type);*/ } static void vbi_dto_set(struct vbi_dev_s *devp) @@ -378,10 +380,12 @@ static irqreturn_t vbi_isr(int irq, void *dev_id) spin_unlock_irqrestore(&devp->vbi_isr_lock, flags); return IRQ_HANDLED; } + if (devp->vbi_start == false) { spin_unlock_irqrestore(&devp->vbi_isr_lock, flags); return IRQ_HANDLED; } + if (devp->tasklet_enable) tasklet_schedule(&devp->tsklt_slicer); spin_unlock_irqrestore(&devp->vbi_isr_lock, flags); @@ -501,7 +505,8 @@ static void force_set_vcnt(unsigned char *rptr) l_val = *rptr & 0xff; h_val = *(rptr+1) & 0xff; vcnt = (h_val << 8) | l_val; - tvafe_pr_info("force set vcnt:0x%x\n", vcnt); + if (vbi_pr_en) + tvafe_pr_info("force set vcnt:0x%x\n", vcnt); } static void set_vbi_new_vcnt(struct vbi_dev_s *devp, unsigned char *rptr) @@ -539,7 +544,8 @@ static void set_vbi_new_vcnt(struct vbi_dev_s *devp, unsigned char *rptr) } vcnt = (h_val << 8) | l_val; - tvafe_pr_info("pre vcnt=0x%x, current vcnt=0x%x\n", temp, vcnt); + if (vbi_pr_en) + tvafe_pr_info("pre vcnt=0x%x, current vcnt=0x%x\n", temp, vcnt); if (vcnt > 0xffff) vcnt = temp; } @@ -559,8 +565,8 @@ static unsigned char *search_vbi_new_addr(struct vbi_dev_s *devp) vaddr = devp->pac_addr_start + paddr - devp->mem_start; temp = (unsigned long)vaddr; vaddr = (unsigned char *)((temp >> 4) << 4); - - tvafe_pr_info("vbi search new addr\n"); + if (vbi_pr_en) + tvafe_pr_info("vbi search new addr\n"); return vaddr; } @@ -599,10 +605,12 @@ static int check_if_sync_cc_data(struct vbi_dev_s *devp, unsigned char *addr) field_data_flag = 0; set_vbi_new_vcnt(devp, new_addr); } - tvafe_pr_info("not find vbi data.\n"); + if (vbi_pr_en) + tvafe_pr_info("not find vbi data.\n"); return -1; } else if (addr > devp->pac_addr_end) { - tvafe_pr_info("vbi ret_addr error.\n"); + if (vbi_pr_en) + tvafe_pr_info("vbi ret_addr error.\n"); return -1; } @@ -634,7 +642,8 @@ static void vbi_slicer_task(unsigned long arg) ret = init_cc_data_sync(devp); if (!ret) return; - + if (vbi_dbg_en & 2) + tvafe_pr_info("pac_addr:%p\n", devp->pac_addr); if (devp->pac_addr > devp->pac_addr_end) devp->pac_addr = devp->pac_addr_start; @@ -1299,7 +1308,6 @@ static void vbi_dump_mem(char *path, struct vbi_dev_s *devp) { struct file *filp = NULL; loff_t pos = 0; - void *buf = NULL; mm_segment_t old_fs = get_fs(); set_fs(KERNEL_DS); @@ -1309,15 +1317,10 @@ static void vbi_dump_mem(char *path, struct vbi_dev_s *devp) tvafe_pr_info("create %s error.\n", path); return; } - buf = phys_to_virt(devp->mem_start); - if (buf == NULL) { - tvafe_pr_info("buf is null!!!.\n"); - return; - } - vfs_write(filp, buf, devp->mem_size, &pos); + vfs_write(filp, devp->pac_addr_start, devp->mem_size, &pos); tvafe_pr_info("write buffer addr:0x%p size: %2u to %s.\n", - buf, devp->mem_size, path); + devp->pac_addr_start, devp->mem_size, path); vfs_fsync(filp, 0); filp_close(filp, NULL); set_fs(old_fs); @@ -1378,7 +1381,7 @@ static ssize_t vbi_store(struct device *dev, struct vbi_dev_s *devp = dev_get_drvdata(dev); struct vbi_slicer_s *vbi_slicer; struct vbi_ringbuffer_s *vbi_buffer; - long val; + unsigned int val; int ret = 0; if (!buff || !devp) @@ -1418,19 +1421,29 @@ static ssize_t vbi_store(struct device *dev, vbi_buffer->pread, vbi_buffer->pwrite, vbi_buffer->data_wmode); tvafe_pr_info("dump satus done!!\n"); + } else if (!strncmp(parm[0], "vbi_pr_en", + strlen("vbi_pr_en"))) { + if (kstrtouint(parm[1], 10, &val) < 0) + return -EINVAL; + vbi_pr_en = val; + tvafe_pr_info("vbi_pr_en:%d\n", vbi_pr_en); } else if (!strncmp(parm[0], "enable_tasklet", strlen("enable_tasklet"))) { - if (kstrtol(parm[1], 10, &val) < 0) + if (kstrtouint(parm[1], 10, &val) < 0) return -EINVAL; devp->tasklet_enable = val; tvafe_pr_info("tasklet_enable:%d\n", devp->tasklet_enable); } else if (!strncmp(parm[0], "data_wmode", strlen("data_wmode"))) { - if (kstrtol(parm[1], 10, &val) < 0) + if (kstrtouint(parm[1], 10, &val) < 0) return -EINVAL; vbi_buffer->data_wmode = val; tvafe_pr_info("data_wmode:%d\n", vbi_buffer->data_wmode); } else if (!strncmp(parm[0], "start", strlen("start"))) { + W_APB_REG(ACD_REG_22, 0x07080000); + /* manuel reset vbi */ + W_APB_REG(ACD_REG_22, 0x87080000); + W_APB_REG(ACD_REG_22, 0x04080000); vbi_hw_init(devp); vbi_slicer_start(devp); /* enable data capture function */ @@ -1439,10 +1452,11 @@ static ssize_t vbi_store(struct device *dev, devp->vs_delay = VBI_VS_DELAY; tvafe_pr_info("start done!!!\n"); } else if (!strncmp(parm[0], "stop", strlen("stop"))) { - vbi_slicer_stop(vbi_slicer); /* disable data capture function */ devp->tasklet_enable = false; devp->vbi_start = false; + init_cc_data_flag = 0; + vbi_slicer_stop(vbi_slicer); /* manuel reset vbi */ /* vbi reset release, vbi agent enable*/ W_VBI_APB_REG(ACD_REG_22, 0x06080000); @@ -1450,19 +1464,20 @@ static ssize_t vbi_store(struct device *dev, tvafe_pr_info(" disable vbi function\n"); tvafe_pr_info("stop done!!!\n"); } else if (!strncmp(parm[0], "set_size", strlen("set_size"))) { - if (kstrtol(parm[1], 10, &val) < 0) + if (kstrtouint(parm[1], 10, &val) < 0) return -EINVAL; - vbi_set_buffer_size(devp, (unsigned int)val); + vbi_set_buffer_size(devp, val); tvafe_pr_info(" set buf size to %d\n", vbi_slicer->buffer.size); } else if (!strncmp(parm[0], "set_type", strlen("set_type"))) { - if (kstrtol(parm[1], 16, &val) < 0) + if (kstrtouint(parm[1], 16, &val) < 0) return -EINVAL; vbi_slicer->type = val; vbi_slicer_set(devp, vbi_slicer); tvafe_pr_info(" set slicer type to %d\n", vbi_slicer->type); } else if (!strncmp(parm[0], "open", strlen("open"))) { + tasklet_enable(&devp->tsklt_slicer); vbi_ringbuffer_init(vbi_buffer, NULL, VBI_DEFAULT_BUFFER_PACKAGE_NUM); devp->slicer->type = VBI_TYPE_NULL; @@ -1478,6 +1493,7 @@ static ssize_t vbi_store(struct device *dev, tvafe_pr_err("request_irq fail\n"); tvafe_pr_info(" open ok.\n"); } else if (!strncmp(parm[0], "release", strlen("release"))) { + tasklet_disable(&devp->tsklt_slicer); ret = vbi_slicer_free(devp, vbi_slicer); devp->tasklet_enable = false; devp->vbi_start = false; /*disable data capture function*/ @@ -1502,6 +1518,7 @@ static int vbi_probe(struct platform_device *pdev) int ret = 0; struct resource *res; struct vbi_dev_s *vbi_dev; + dma_addr_t vbi_dma_addr; /* allocate memory for the per-device structure */ vbi_dev = kzalloc(sizeof(struct vbi_dev_s), GFP_KERNEL); @@ -1509,7 +1526,7 @@ static int vbi_probe(struct platform_device *pdev) ret = -ENOMEM; goto fail_kzalloc_mem; } - memset(vbi_dev, 0, sizeof(struct vbi_dev_s)); + memset(vbi_dev, 0, sizeof(struct vbi_dev_s)); vbi_mem_start = 0; /* connect the file operations with cdev */ @@ -1536,34 +1553,27 @@ static int vbi_probe(struct platform_device *pdev) goto fail_create_dbg_file; } - /* get device memory */ - res = &vbi_memobj; - ret = of_reserved_mem_device_init(&pdev->dev); - if (ret == 0) - tvafe_pr_info("\n vbi memory resource done.\n"); - else - tvafe_pr_info("vbi: can't get memory resource\n"); - vbi_dev->mem_start = res->start; - vbi_dev->mem_size = res->end - res->start + 1; - if (vbi_dev->mem_size > DECODER_VBI_SIZE) - vbi_dev->mem_size = DECODER_VBI_SIZE; - tvafe_pr_info(": start_addr is:0x%x, size is:0x%x\n", - vbi_dev->mem_start, vbi_dev->mem_size); + /*vbi memory alloc*/ + vbi_dev->mem_size = DECODER_VBI_SIZE; + vbi_dev->pac_addr_start = dma_alloc_coherent(&pdev->dev, + vbi_dev->mem_size, &vbi_dma_addr, GFP_KERNEL); + vbi_dev->mem_start = (unsigned int)vbi_dma_addr; + if (vbi_dev->pac_addr_start == NULL) { + tvafe_pr_err(": dma_alloc_coherent failed!!!\n"); + goto fail_alloc_mem; + } + tvafe_pr_info("vbi: dma_alloc phy start_addr is:0x%x, size is:0x%x\n", + vbi_dev->mem_start, vbi_dev->mem_size); - /* remap the package vbi hardware address for our conversion */ - vbi_dev->pac_addr_start = phys_to_virt(vbi_dev->mem_start); - /*ioremap_nocache(vbi_dev->mem_start, vbi_dev->mem_size);*/ memset(vbi_dev->pac_addr_start, 0, vbi_dev->mem_size); vbi_dev->mem_size = vbi_dev->mem_size/2; vbi_dev->mem_size >>= 4; vbi_dev->mem_size <<= 4; vbi_mem_start = vbi_dev->mem_start; vbi_dev->pac_addr_end = vbi_dev->pac_addr_start + vbi_dev->mem_size - 1; - if (vbi_dev->pac_addr_start == NULL) - tvafe_pr_err(": ioremap error!!!\n"); - else - tvafe_pr_info(": vbi_dev->pac_addr_start=0x%p, end:0x%p, size:0x%x .......\n", - vbi_dev->pac_addr_start, vbi_dev->pac_addr_end, vbi_dev->mem_size); + tvafe_pr_info(": vbi_dev->pac_addr_start=0x%p, end:0x%p, size:0x%x\n", + vbi_dev->pac_addr_start, vbi_dev->pac_addr_end, + vbi_dev->mem_size); vbi_dev->pac_addr = vbi_dev->pac_addr_start; mutex_init(&vbi_dev->mutex); @@ -1632,7 +1642,9 @@ static int vbi_remove(struct platform_device *pdev) mutex_destroy(&vbi_dev->mutex); tasklet_kill(&vbi_dev->tsklt_slicer); if (vbi_dev->pac_addr_start) - iounmap(vbi_dev->pac_addr_start); + dma_free_coherent(vbi_dev->dev, vbi_dev->mem_size, + vbi_dev->pac_addr_start, + (dma_addr_t)&vbi_dev->mem_start); vfree(vbi_dev->slicer); device_destroy(vbi_clsp, MKDEV(MAJOR(vbi_id), 0)); cdev_del(&vbi_dev->cdev); diff --git a/drivers/amlogic/media/vin/tvin/tvin_format_table.c b/drivers/amlogic/media/vin/tvin/tvin_format_table.c index ff3ca0f8be3a..e952d031fd34 100644 --- a/drivers/amlogic/media/vin/tvin/tvin_format_table.c +++ b/drivers/amlogic/media/vin/tvin/tvin_format_table.c @@ -1494,7 +1494,7 @@ const unsigned int cvbs_acd_table[TVIN_SIG_FMT_CVBS_NTSC_50 - 0x00000000, 0x00000000, 0x00000000, 0x08000000, 0x02020000, 0x0209c832, 0x00000000, 0xfcf44396, 0x00000102, 0xe7f14e8e, 0x00140008, 0x20800000, 0x00275a60, 0x00001001, 0x10e0474f, - 0x00890359, 0x00170137, 0x00000000, 0x00070000, 0x00000000, + 0x00880358, 0x00130103, 0x00000000, 0x00070000, 0x00000000, 0x00000000, 0x00000050, 0x00000000, 0x000003ff, 0x00000000, 0x00000000, 0x00000000, 0x0004d206, 0x00000000, 0x030000f0, 0x0000000a, 0x0000523e, 0x0004114e, 0x000000f0, 0x00000001, @@ -1936,7 +1936,7 @@ const unsigned int rf_acd_table[TVIN_SIG_FMT_CVBS_NTSC_50 - 0x00000000, 0x00000000, 0x00000000, 0x08000000, 0x02020000, 0x0209c832, 0x00000000, 0xfcf44396, 0x00000102, 0xe7f14e8e, 0x00140008, 0x20800000, 0x00275a60, 0x00001001, 0x10e0474f, - 0x00890359, 0x00170137, 0x00000000, 0x00070000, 0x00000000, + 0x00880358, 0x00130103, 0x00000000, 0x00070000, 0x00000000, 0x00000000, 0x00000050, 0x00000000, 0x000003ff, 0x00000000, 0x00000000, 0x00000000, 0x0004d206, 0x00000000, 0x030000f0, 0x0000000a, 0x0000523e, 0x0004114e, 0x000000f0, 0x00000001, diff --git a/drivers/amlogic/media/vin/tvin/tvin_global.h b/drivers/amlogic/media/vin/tvin/tvin_global.h index c6d053b06416..78f4b4029f1a 100644 --- a/drivers/amlogic/media/vin/tvin/tvin_global.h +++ b/drivers/amlogic/media/vin/tvin/tvin_global.h @@ -116,6 +116,15 @@ static inline uint32_t R_APB_BIT(uint32_t reg, return val; } +static inline void W_VCBUS(uint32_t reg, const uint32_t value) +{ + aml_write_vcbus(reg, value); +} + +static inline uint32_t R_VCBUS(uint32_t reg) +{ + return aml_read_vcbus(reg); +} static inline void W_VCBUS_BIT(uint32_t reg, const uint32_t value, @@ -438,6 +447,19 @@ struct tvin_hdr_info_s { unsigned int hdr_check_cnt; }; +enum tvin_cn_type_e { + GRAPHICS, + PHOTO, + CINEMA, + GAME, +}; + +struct tvin_latency_s { + bool allm_mode; + bool it_content; + enum tvin_cn_type_e cn_type; +}; + struct tvin_sig_property_s { enum tvin_trans_fmt trans_fmt; enum tvin_color_fmt_e color_format; @@ -464,6 +486,7 @@ struct tvin_sig_property_s { bool low_latency;/*is low latency dolby mode*/ uint8_t fps; unsigned int skip_vf_num;/*skip pre vframe num*/ + struct tvin_latency_s latency; }; #define TVAFE_VF_POOL_SIZE 6 /* 8 */ diff --git a/drivers/amlogic/media/vin/tvin/vdin/Makefile b/drivers/amlogic/media/vin/tvin/vdin/Makefile index 7f0c556e4178..b8092e9aa0d4 100644 --- a/drivers/amlogic/media/vin/tvin/vdin/Makefile +++ b/drivers/amlogic/media/vin/tvin/vdin/Makefile @@ -1,6 +1,11 @@ # # Makefile for Vdin. # +ifeq ($(TARGET_BUILD_VARIANT),userdebug) +ccflags-y := -DDEBUG_SUPPORT +else +ccflags-y := -DDEBUG +endif obj-$(CONFIG_AMLOGIC_MEDIA_VDIN) = tvin_vdin.o tvin_vdin-objs += vdin_v4l2.o tvin_vdin-objs += vdin_vf.o diff --git a/drivers/amlogic/media/vin/tvin/vdin/vdin_afbce.c b/drivers/amlogic/media/vin/tvin/vdin/vdin_afbce.c index eaa9d734e4bb..14dd11f39557 100644 --- a/drivers/amlogic/media/vin/tvin/vdin/vdin_afbce.c +++ b/drivers/amlogic/media/vin/tvin/vdin/vdin_afbce.c @@ -69,18 +69,16 @@ unsigned int vdin_afbce_cma_alloc(struct vdin_dev_s *devp) char vdin_name[6]; unsigned int mem_size, h_size, v_size; int flags = CODEC_MM_FLAGS_CMA_FIRST|CODEC_MM_FLAGS_CMA_CLEAR| - CODEC_MM_FLAGS_CPU; + CODEC_MM_FLAGS_DMA; unsigned int max_buffer_num = min_buf_num; unsigned int i; - /*afbce head need 1036800 byte at most*/ - unsigned int afbce_head_size_byte = PAGE_SIZE * 300;/*1.2M*/ + /*head_size:3840*2160*3*9/32*/ + unsigned int afbce_head_size_byte = PAGE_SIZE * 1712; /*afbce map_table need 218700 byte at most*/ unsigned int afbce_table_size_byte = PAGE_SIZE * 60;/*0.3M*/ unsigned int afbce_mem_used; unsigned int frame_head_size; unsigned int mmu_used; - //unsigned long afbce_head_phy_addr; - //unsigned long afbce_table_phy_addr; unsigned long body_start_paddr; if (devp->rdma_enable) @@ -283,10 +281,9 @@ unsigned int vdin_afbce_cma_alloc(struct vdin_dev_s *devp) /* 1 block = 32 * 4 pixle = 128 pixel */ /* there is a header in one block, a header has 4 bytes */ /* set fm_head_paddr start */ - frame_head_size = roundup(devp->h_active * devp->v_active, 128); + frame_head_size = (int)roundup(devp->vfmem_size, 128); /*h_active * v_active / 128 * 4 = frame_head_size*/ - frame_head_size = devp->h_active * devp->v_active / 32; - frame_head_size = PAGE_ALIGN(frame_head_size); + frame_head_size = PAGE_ALIGN(frame_head_size / 32); devp->afbce_info->frame_head_size = frame_head_size; @@ -363,6 +360,7 @@ void vdin_afbce_cma_release(struct vdin_dev_s *devp) devp->cma_mem_alloc = 0; } +/*can not use RDMA, because vdin0/1 both use the register */ void vdin_write_mif_or_afbce(struct vdin_dev_s *devp, enum vdin_output_mif_e sel) { @@ -370,39 +368,117 @@ void vdin_write_mif_or_afbce(struct vdin_dev_s *devp, if (offset == 0) { if (sel == VDIN_OUTPUT_TO_MIF) { - W_VCBUS_BIT(VDIN_MISC_CTRL, 1, VDIN0_MIF_ENABLE_BIT, 1); - W_VCBUS_BIT(VDIN_MISC_CTRL, 1, VDIN0_OUT_MIF_BIT, 1); - W_VCBUS_BIT(VDIN_MISC_CTRL, 0, VDIN0_OUT_AFBCE_BIT, 1); + W_VCBUS_BIT(VDIN_MISC_CTRL, + 1, VDIN0_MIF_ENABLE_BIT, 1); + W_VCBUS_BIT(VDIN_MISC_CTRL, + 1, VDIN0_OUT_MIF_BIT, 1); + W_VCBUS_BIT(VDIN_MISC_CTRL, + 0, VDIN0_OUT_AFBCE_BIT, 1); } else if (sel == VDIN_OUTPUT_TO_AFBCE) { - W_VCBUS_BIT(VDIN_MISC_CTRL, 1, VDIN0_MIF_ENABLE_BIT, 1); - W_VCBUS_BIT(VDIN_MISC_CTRL, 0, VDIN0_OUT_MIF_BIT, 1); - W_VCBUS_BIT(VDIN_MISC_CTRL, 1, VDIN0_OUT_AFBCE_BIT, 1); + W_VCBUS_BIT(VDIN_MISC_CTRL, + 1, VDIN0_MIF_ENABLE_BIT, 1); + W_VCBUS_BIT(VDIN_MISC_CTRL, + 0, VDIN0_OUT_MIF_BIT, 1); + W_VCBUS_BIT(VDIN_MISC_CTRL, + 1, VDIN0_OUT_AFBCE_BIT, 1); } } else { if (sel == VDIN_OUTPUT_TO_MIF) { - W_VCBUS_BIT(VDIN_MISC_CTRL, 1, VDIN1_MIF_ENABLE_BIT, 1); - W_VCBUS_BIT(VDIN_MISC_CTRL, 1, VDIN1_OUT_MIF_BIT, 1); - W_VCBUS_BIT(VDIN_MISC_CTRL, 0, VDIN1_OUT_AFBCE_BIT, 1); + W_VCBUS_BIT(VDIN_MISC_CTRL, + 1, VDIN1_MIF_ENABLE_BIT, 1); + W_VCBUS_BIT(VDIN_MISC_CTRL, + 1, VDIN1_OUT_MIF_BIT, 1); + W_VCBUS_BIT(VDIN_MISC_CTRL, + 0, VDIN1_OUT_AFBCE_BIT, 1); } else if (sel == VDIN_OUTPUT_TO_AFBCE) { /*sel vdin1 afbce: not support in sw now, *just reserved interface */ - W_VCBUS_BIT(VDIN_MISC_CTRL, 1, VDIN1_MIF_ENABLE_BIT, 1); - W_VCBUS_BIT(VDIN_MISC_CTRL, 0, VDIN1_OUT_MIF_BIT, 1); - W_VCBUS_BIT(VDIN_MISC_CTRL, 1, VDIN1_OUT_AFBCE_BIT, 1); + W_VCBUS_BIT(VDIN_MISC_CTRL, + 1, VDIN1_MIF_ENABLE_BIT, 1); + W_VCBUS_BIT(VDIN_MISC_CTRL, + 0, VDIN1_OUT_MIF_BIT, 1); + W_VCBUS_BIT(VDIN_MISC_CTRL, + 1, VDIN1_OUT_AFBCE_BIT, 1); } } } - +/* static void afbce_wr(uint32_t reg, const uint32_t val) { wr(0, reg, val); } +*/ +#define VDIN_AFBCE_HOLD_LINE_NUM 4 +void vdin_afbce_update(struct vdin_dev_s *devp) +{ + int hold_line_num = VDIN_AFBCE_HOLD_LINE_NUM; + int reg_format_mode;/* 0:444 1:422 2:420 */ + int reg_fmt444_comb; + int sblk_num; + int uncmp_bits; + int uncmp_size; + + if (devp->index != 0) { + pr_info("cat not use afbce on vdin1 at the moment\n"); + return; + } + +#ifndef CONFIG_AMLOGIC_MEDIA_RDMA + pr_info("##############################################\n"); + pr_info("vdin afbce must use RDMA,but it not be opened\n"); + pr_info("##############################################\n"); +#endif + + if ((devp->prop.dest_cfmt == TVIN_YUV444) && (devp->h_active > 2048)) + reg_fmt444_comb = 1; + else + reg_fmt444_comb = 0; + + if ((devp->prop.dest_cfmt == TVIN_NV12) || + (devp->prop.dest_cfmt == TVIN_NV21)) { + reg_format_mode = 2; + sblk_num = 12; + } else if ((devp->prop.dest_cfmt == TVIN_YUV422) || + (devp->prop.dest_cfmt == TVIN_YUYV422) || + (devp->prop.dest_cfmt == TVIN_YVYU422) || + (devp->prop.dest_cfmt == TVIN_UYVY422) || + (devp->prop.dest_cfmt == TVIN_VYUY422)) { + reg_format_mode = 1; + sblk_num = 16; + } else { + reg_format_mode = 0; + sblk_num = 24; + } + uncmp_bits = devp->source_bitdepth; + + /* bit size of uncompression mode */ + uncmp_size = (((((16*uncmp_bits*sblk_num)+7)>>3)+31)/32)<<1; + /* + *pr_info("%s: dest_cfmt=%d, reg_format_mode=%d, uncmp_bits=%d, + * sblk_num=%d, uncmp_size=%d\n", + * __func__, devp->prop.dest_cfmt, reg_format_mode, + * uncmp_bits, sblk_num, uncmp_size); + */ + + rdma_write_reg(devp->rdma_handle, AFBCE_MODE, + (0 & 0x7) << 29 | (0 & 0x3) << 26 | (3 & 0x3) << 24 | + (hold_line_num & 0x7f) << 16 | + (2 & 0x3) << 14 | (reg_fmt444_comb & 0x1)); + + rdma_write_reg_bits(devp->rdma_handle, + AFBCE_MIF_SIZE, (uncmp_size & 0x1fff), 16, 5);/* uncmp_size */ + + rdma_write_reg(devp->rdma_handle, AFBCE_FORMAT, + (reg_format_mode & 0x3) << 8 | + (uncmp_bits & 0xf) << 4 | + (uncmp_bits & 0xf)); +} void vdin_afbce_config(struct vdin_dev_s *devp) { unsigned int offset = devp->addr_offset; - int hold_line_num = 4; + int hold_line_num = VDIN_AFBCE_HOLD_LINE_NUM; int lbuf_depth = 256; int lossy_luma_en = 0; int lossy_chrm_en = 0; @@ -412,9 +488,9 @@ void vdin_afbce_config(struct vdin_dev_s *devp) int sblk_num; int uncmp_bits; int uncmp_size; - int def_color_0 = 0; - int def_color_1 = 0; - int def_color_2 = 0; + int def_color_0 = 4095; + int def_color_1 = 2048; + int def_color_2 = 2048; int def_color_3 = 0; int hblksize_out = (devp->h_active + 31) >> 5; int vblksize_out = (devp->v_active + 3) >> 2; @@ -432,6 +508,12 @@ void vdin_afbce_config(struct vdin_dev_s *devp) return; } +#ifndef CONFIG_AMLOGIC_MEDIA_RDMA + pr_info("##############################################\n"); + pr_info("vdin afbce must use RDMA,but it not be opened\n"); + pr_info("##############################################\n"); +#endif + enc_win_bgn_h = 0; enc_win_end_h = devp->h_active - 1; enc_win_bgn_v = 0; @@ -467,103 +549,158 @@ void vdin_afbce_config(struct vdin_dev_s *devp) //bit size of uncompression mode uncmp_size = (((((16*uncmp_bits*sblk_num)+7)>>3)+31)/32)<<1; - W_VCBUS_BIT(VDIN_WRARB_REQEN_SLV, 0x1, 3, 1);//vpu arb axi_enable - W_VCBUS_BIT(VDIN_WRARB_REQEN_SLV, 0x1, 7, 1);//vpu arb axi_enable + rdma_write_reg_bits(devp->rdma_handle, + VDIN_WRARB_REQEN_SLV, 0x1, 3, 1);//vpu arb axi_enable + rdma_write_reg_bits(devp->rdma_handle, + VDIN_WRARB_REQEN_SLV, 0x1, 7, 1);//vpu arb axi_enable - afbce_wr(AFBCE_MODE, + rdma_write_reg(devp->rdma_handle, AFBCE_MODE, (0 & 0x7) << 29 | (0 & 0x3) << 26 | (3 & 0x3) << 24 | (hold_line_num & 0x7f) << 16 | (2 & 0x3) << 14 | (reg_fmt444_comb & 0x1)); - W_VCBUS_BIT(AFBCE_QUANT_ENABLE, (lossy_luma_en & 0x1), 0, 1);//loosy - W_VCBUS_BIT(AFBCE_QUANT_ENABLE, (lossy_chrm_en & 0x1), 4, 1);//loosy + rdma_write_reg_bits(devp->rdma_handle, + AFBCE_QUANT_ENABLE, (lossy_luma_en & 0x1), 0, 1);//loosy + rdma_write_reg_bits(devp->rdma_handle, + AFBCE_QUANT_ENABLE, (lossy_chrm_en & 0x1), 4, 1);//loosy - afbce_wr(AFBCE_SIZE_IN, + if (devp->afbce_lossy_en == 1) { + rdma_write_reg(devp->rdma_handle, + AFBCE_QUANT_ENABLE, 0xc11); + pr_info("afbce use lossy compression mode\n"); + } + + rdma_write_reg(devp->rdma_handle, AFBCE_SIZE_IN, ((devp->h_active & 0x1fff) << 16) | // hsize_in of afbc input ((devp->v_active & 0x1fff) << 0) // vsize_in of afbc input ); - afbce_wr(AFBCE_BLK_SIZE_IN, + rdma_write_reg(devp->rdma_handle, AFBCE_BLK_SIZE_IN, ((hblksize_out & 0x1fff) << 16) | // out blk hsize ((vblksize_out & 0x1fff) << 0) // out blk vsize ); //head addr of compressed data - afbce_wr(AFBCE_HEAD_BADDR, devp->afbce_info->fm_head_paddr[0]); + rdma_write_reg(devp->rdma_handle, AFBCE_HEAD_BADDR, + devp->afbce_info->fm_head_paddr[0]); - W_VCBUS_BIT(AFBCE_MIF_SIZE, (uncmp_size & 0x1fff), 16, 5);//uncmp_size + rdma_write_reg_bits(devp->rdma_handle, + AFBCE_MIF_SIZE, (uncmp_size & 0x1fff), 16, 5);//uncmp_size /* how to set reg when we use crop ? */ // scope of hsize_in ,should be a integer multipe of 32 // scope of vsize_in ,should be a integer multipe of 4 - afbce_wr(AFBCE_PIXEL_IN_HOR_SCOPE, + rdma_write_reg(devp->rdma_handle, AFBCE_PIXEL_IN_HOR_SCOPE, ((enc_win_end_h & 0x1fff) << 16) | ((enc_win_bgn_h & 0x1fff) << 0)); // scope of hsize_in ,should be a integer multipe of 32 // scope of vsize_in ,should be a integer multipe of 4 - afbce_wr(AFBCE_PIXEL_IN_VER_SCOPE, + rdma_write_reg(devp->rdma_handle, AFBCE_PIXEL_IN_VER_SCOPE, ((enc_win_end_v & 0x1fff) << 16) | ((enc_win_bgn_v & 0x1fff) << 0)); - afbce_wr(AFBCE_CONV_CTRL, lbuf_depth);//fix 256 + rdma_write_reg(devp->rdma_handle, + AFBCE_CONV_CTRL, lbuf_depth);//fix 256 - afbce_wr(AFBCE_MIF_HOR_SCOPE, + rdma_write_reg(devp->rdma_handle, AFBCE_MIF_HOR_SCOPE, ((blk_out_bgn_h & 0x3ff) << 16) | // scope of out blk hsize ((blk_out_end_h & 0xfff) << 0) // scope of out blk vsize ); - afbce_wr(AFBCE_MIF_VER_SCOPE, + rdma_write_reg(devp->rdma_handle, AFBCE_MIF_VER_SCOPE, ((blk_out_bgn_v & 0x3ff) << 16) | // scope of out blk hsize ((blk_out_end_v & 0xfff) << 0) // scope of out blk vsize ); - afbce_wr(AFBCE_FORMAT, + rdma_write_reg(devp->rdma_handle, AFBCE_FORMAT, (reg_format_mode & 0x3) << 8 | (uncmp_bits & 0xf) << 4 | (uncmp_bits & 0xf)); - afbce_wr(AFBCE_DEFCOLOR_1, + rdma_write_reg(devp->rdma_handle, AFBCE_DEFCOLOR_1, ((def_color_3 & 0xfff) << 12) | // def_color_a ((def_color_0 & 0xfff) << 0) // def_color_y ); - afbce_wr(AFBCE_DEFCOLOR_2, + rdma_write_reg(devp->rdma_handle, AFBCE_DEFCOLOR_2, ((def_color_2 & 0xfff) << 12) | // def_color_v ((def_color_1 & 0xfff) << 0) // def_color_u ); - //cur_mmu_used += Rd(AFBCE_MMU_NUM); //4k addr have used in every frame; + rdma_write_reg_bits(devp->rdma_handle, + AFBCE_MMU_RMIF_CTRL4, devp->afbce_info->table_paddr, 0, 32); + rdma_write_reg_bits(devp->rdma_handle, + AFBCE_MMU_RMIF_SCOPE_X, cur_mmu_used, 0, 12); - W_VCBUS_BIT(AFBCE_MMU_RMIF_CTRL4, devp->afbce_info->table_paddr, 0, 32); - W_VCBUS_BIT(AFBCE_MMU_RMIF_SCOPE_X, cur_mmu_used, 0, 12); - - W_VCBUS_BIT(AFBCE_ENABLE, 1, 8, 1);//enable afbce + rdma_write_reg_bits(devp->rdma_handle, + AFBCE_ENABLE, 1, 12, 1); //set afbce pulse mode + rdma_write_reg_bits(devp->rdma_handle, + AFBCE_ENABLE, 0, 8, 1);//disable afbce } void vdin_afbce_maptable_init(struct vdin_dev_s *devp) { unsigned int i, j; - unsigned int *ptable = NULL; + unsigned int highmem_flag = 0; + unsigned long ptable = 0; unsigned int *vtable = NULL; unsigned int body; unsigned int size; + void *p = NULL; size = roundup(devp->afbce_info->frame_body_size, 4096); - for (i = 0; i < devp->vfmem_max_cnt; i++) { - ptable = (unsigned int *) - (devp->afbce_info->fm_table_paddr[i]&0xffffffff); - if (devp->cma_config_flag == 0x101) - vtable = codec_mm_phys_to_virt((unsigned long)ptable); - else if (devp->cma_config_flag == 0) - vtable = phys_to_virt((unsigned long)ptable); + ptable = devp->afbce_info->fm_table_paddr[0]; + if (devp->cma_config_flag == 0x101) + highmem_flag = PageHighMem(phys_to_page(ptable)); + else + highmem_flag = PageHighMem(phys_to_page(ptable)); + for (i = 0; i < devp->vfmem_max_cnt; i++) { + ptable = devp->afbce_info->fm_table_paddr[i]; + if (highmem_flag == 0) { + if (devp->cma_config_flag == 0x101) + vtable = codec_mm_phys_to_virt(ptable); + else if (devp->cma_config_flag == 0) + vtable = phys_to_virt(ptable); + else + vtable = phys_to_virt(ptable); + } else { + vtable = (unsigned int *)vdin_vmap(ptable, + devp->afbce_info->frame_table_size); + if (vdin_dbg_en) { + pr_err("----vdin vmap v: %p, p: %lx, size: %d\n", + vtable, ptable, + devp->afbce_info->frame_table_size); + } + if (!vtable) { + pr_err("vmap fail, size: %d.\n", + devp->afbce_info->frame_table_size); + return; + } + + } + + p = vtable; body = devp->afbce_info->fm_body_paddr[i]&0xffffffff; for (j = 0; j < size; j += 4096) { *vtable = ((j + body) >> 12) & 0x000fffff; vtable++; } + + /* clean tail data. */ + memset(vtable, 0, devp->afbce_info->frame_table_size - + ((char *)vtable - (char *)p)); + + vdin_dma_flush(devp, p, + devp->afbce_info->frame_table_size, + DMA_TO_DEVICE); + + if (highmem_flag) + vdin_unmap_phyaddr(p); + + vtable = NULL; } } @@ -571,20 +708,61 @@ void vdin_afbce_set_next_frame(struct vdin_dev_s *devp, unsigned int rdma_enable, struct vf_entry *vfe) { unsigned char i; - unsigned int cur_mmu_used; i = vfe->af_num; - cur_mmu_used = devp->afbce_info->fm_table_paddr[i] / 4; + vfe->vf.compHeadAddr = devp->afbce_info->fm_head_paddr[i]; + vfe->vf.compBodyAddr = devp->afbce_info->fm_body_paddr[i]; -#ifdef CONFIG_AML_RDMA - if (rdma_enable) - rdma_write_reg_bits(devp->rdma_handle, - AFBCE_HEAD_BADDR, devp->afbce_info->fm_head_paddr[i]); - rdma_write_reg(devp->rdma_handle, - AFBCE_MMU_RMIF_SCOPE_X, cur_mmu_used, 0, 12); - else +#ifdef CONFIG_AMLOGIC_MEDIA_RDMA + if (rdma_enable) { + rdma_write_reg(devp->rdma_handle, AFBCE_HEAD_BADDR, + devp->afbce_info->fm_head_paddr[i]); + rdma_write_reg_bits(devp->rdma_handle, AFBCE_MMU_RMIF_CTRL4, + devp->afbce_info->fm_table_paddr[i], 0, 32); + rdma_write_reg_bits(devp->rdma_handle, AFBCE_ENABLE, 1, 0, 1); + } else #endif - afbce_wr(AFBCE_HEAD_BADDR, devp->afbce_info->fm_head_paddr[i]); - W_VCBUS_BIT(AFBCE_MMU_RMIF_SCOPE_X, cur_mmu_used, 0, 12); + { + pr_info("afbce must use RDMA.\n"); + } + + vdin_afbce_clear_writedown_flag(devp); } +void vdin_afbce_clear_writedown_flag(struct vdin_dev_s *devp) +{ + rdma_write_reg(devp->rdma_handle, AFBCE_CLR_FLAG, 1); +} + +/* return 1: write down*/ +int vdin_afbce_read_writedown_flag(void) +{ + int val1, val2; + + val1 = rd_bits(0, AFBCE_STA_FLAGT, 0, 1); + val2 = rd_bits(0, AFBCE_STA_FLAGT, 2, 2); + + if ((val1 == 1) || (val2 == 0)) + return 1; + else + return 0; +} + +void vdin_afbce_hw_disable(void) +{ + /*can not use RDMA*/ + W_VCBUS_BIT(AFBCE_ENABLE, 0, 8, 1);//disable afbce +} + +void vdin_afbce_hw_enable(struct vdin_dev_s *devp) +{ + //enable afbce + rdma_write_reg_bits(devp->rdma_handle, AFBCE_ENABLE, 1, 8, 1); +} + +void vdin_afbce_soft_reset(void) +{ + W_VCBUS_BIT(AFBCE_MODE, 0, 30, 1); + W_VCBUS_BIT(AFBCE_MODE, 1, 30, 1); + W_VCBUS_BIT(AFBCE_MODE, 0, 30, 1); +} diff --git a/drivers/amlogic/media/vin/tvin/vdin/vdin_afbce.h b/drivers/amlogic/media/vin/tvin/vdin/vdin_afbce.h index feb2d086eca4..08ad76fcf68c 100644 --- a/drivers/amlogic/media/vin/tvin/vdin/vdin_afbce.h +++ b/drivers/amlogic/media/vin/tvin/vdin/vdin_afbce.h @@ -304,10 +304,15 @@ extern void vdin_write_mif_or_afbce(struct vdin_dev_s *devp, enum vdin_output_mif_e sel); extern unsigned int vdin_afbce_cma_alloc(struct vdin_dev_s *devp); extern void vdin_afbce_cma_release(struct vdin_dev_s *devp); +extern void vdin_afbce_update(struct vdin_dev_s *devp); extern void vdin_afbce_config(struct vdin_dev_s *devp); extern void vdin_afbce_maptable_init(struct vdin_dev_s *devp); extern void vdin_afbce_set_next_frame(struct vdin_dev_s *devp, -unsigned int rdma_enable, struct vf_entry *vfe); - + unsigned int rdma_enable, struct vf_entry *vfe); +extern void vdin_afbce_clear_writedown_flag(struct vdin_dev_s *devp); +extern int vdin_afbce_read_writedown_flag(void); +extern void vdin_afbce_hw_disable(void); +extern void vdin_afbce_hw_enable(struct vdin_dev_s *devp); +extern void vdin_afbce_soft_reset(void); #endif diff --git a/drivers/amlogic/media/vin/tvin/vdin/vdin_canvas.h b/drivers/amlogic/media/vin/tvin/vdin/vdin_canvas.h index 66aababd2c2e..d97d7675a433 100644 --- a/drivers/amlogic/media/vin/tvin/vdin/vdin_canvas.h +++ b/drivers/amlogic/media/vin/tvin/vdin/vdin_canvas.h @@ -31,8 +31,8 @@ #define VDIN_MIN_SOURCE_BITDEPTH 8 -#define VDIN_YUV444_MAX_CMA_WIDTH 1920 -#define VDIN_YUV444_MAX_CMA_HEIGH 1080 +#define VDIN_YUV444_MAX_CMA_WIDTH 4096 +#define VDIN_YUV444_MAX_CMA_HEIGH 2160 extern const unsigned int vdin_canvas_ids[2][VDIN_CANVAS_MAX_CNT]; extern void vdin_canvas_init(struct vdin_dev_s *devp); diff --git a/drivers/amlogic/media/vin/tvin/vdin/vdin_ctl.c b/drivers/amlogic/media/vin/tvin/vdin/vdin_ctl.c index 97d58d375a3d..89820b29f765 100644 --- a/drivers/amlogic/media/vin/tvin/vdin/vdin_ctl.c +++ b/drivers/amlogic/media/vin/tvin/vdin/vdin_ctl.c @@ -22,6 +22,10 @@ #include #include #include +#include +#include +#include +#include #include #include #include @@ -159,6 +163,79 @@ static unsigned int vpu_reg_27af = 0x3; #define pr_info(fmt, ...) #endif +u8 *vdin_vmap(ulong addr, u32 size) +{ + u8 *vaddr = NULL; + struct page **pages = NULL; + u32 i, npages, offset = 0; + ulong phys, page_start; + /*pgprot_t pgprot = pgprot_noncached(PAGE_KERNEL);*/ + pgprot_t pgprot = PAGE_KERNEL; + + if (!PageHighMem(phys_to_page(addr))) + return phys_to_virt(addr); + + offset = offset_in_page(addr); + page_start = addr - offset; + npages = DIV_ROUND_UP(size + offset, PAGE_SIZE); + + pages = kmalloc_array(npages, sizeof(struct page *), GFP_KERNEL); + if (!pages) + return NULL; + + for (i = 0; i < npages; i++) { + phys = page_start + i * PAGE_SIZE; + pages[i] = pfn_to_page(phys >> PAGE_SHIFT); + } + + vaddr = vmap(pages, npages, VM_MAP, pgprot); + if (!vaddr) { + pr_err("the phy(%lx) vmaped fail, size: %d\n", + page_start, npages << PAGE_SHIFT); + kfree(pages); + return NULL; + } + + kfree(pages); + + if (vdin_dbg_en) { + pr_info("[vdin HIGH-MEM-MAP] %s, pa(%lx) to va(%p), size: %d\n", + __func__, page_start, vaddr, npages << PAGE_SHIFT); + } + + return vaddr + offset; +} + +void vdin_unmap_phyaddr(u8 *vaddr) +{ + void *addr = (void *)(PAGE_MASK & (ulong)vaddr); + + if (is_vmalloc_or_module_addr(vaddr)) { + if (vdin_dbg_en) + pr_info("----vdin unmap v: %p\n", addr); + vunmap(addr); + } +} + +void vdin_dma_flush(struct vdin_dev_s *devp, void *vaddr, + int size, enum dma_data_direction dir) +{ + ulong phy_addr; + + if (is_vmalloc_or_module_addr(vaddr)) { + phy_addr = page_to_phys(vmalloc_to_page(vaddr)) + + offset_in_page(vaddr); + if (phy_addr && PageHighMem(phys_to_page(phy_addr))) { + if (vdin_dbg_en) + pr_info("----vdin flush v: %p, p: %lx\n", + vaddr, phy_addr); + dma_sync_single_for_device(&devp->this_pdev->dev, + phy_addr, size, dir); + } + return; + } +} + /*reset reg mif value of vdin0: * VDIN_WR_CTRL \VDIN_COM_CTRL0\ VDIN_MISC_CTRL */ @@ -464,6 +541,8 @@ void vdin_get_format_convert(struct vdin_dev_s *devp) format_convert = VDIN_FORMAT_CONVERT_YUV_NV21; else if (devp->prop.dest_cfmt == TVIN_NV12) format_convert = VDIN_FORMAT_CONVERT_YUV_NV12; + else if (devp->prop.dest_cfmt == TVIN_YUV444) + format_convert = VDIN_FORMAT_CONVERT_YUV_YUV444; else format_convert = VDIN_FORMAT_CONVERT_YUV_YUV422; break; @@ -586,7 +665,9 @@ static void vdin_set_meas_mux(unsigned int offset, enum tvin_port_e port_, meas_mux = MEAS_MUX_656_B; else if ((is_meson_gxl_cpu() || is_meson_gxm_cpu() || is_meson_g12a_cpu() || is_meson_g12b_cpu() || - is_meson_tl1_cpu()) && (bt_path == BT_PATH_GPIO)) + is_meson_tl1_cpu() || is_meson_sm1_cpu() || + is_meson_tm2_cpu()) && + (bt_path == BT_PATH_GPIO)) meas_mux = MEAS_MUX_656; else pr_info("cpu not define or do not support bt656"); @@ -697,7 +778,9 @@ void vdin_set_top(unsigned int offset, VDI9_ASFIFO_CTRL_BIT, VDI9_ASFIFO_CTRL_WID); } else if ((is_meson_gxm_cpu() || is_meson_gxl_cpu() || is_meson_g12a_cpu() || is_meson_g12b_cpu() || - is_meson_tl1_cpu()) && (bt_path == BT_PATH_GPIO)) { + is_meson_tl1_cpu() || is_meson_sm1_cpu() || + is_meson_tm2_cpu()) && + (bt_path == BT_PATH_GPIO)) { vdin_mux = VDIN_MUX_656; wr_bits(offset, VDIN_ASFIFO_CTRL0, 0xe4, VDI1_ASFIFO_CTRL_BIT, VDI1_ASFIFO_CTRL_WID); @@ -745,18 +828,36 @@ void vdin_set_top(unsigned int offset, if (port != TVIN_PORT_VIU1) wr_bits(offset, VDIN_ASFIFO_CTRL3, 0xe4, VDI6_ASFIFO_CTRL_BIT, VDI6_ASFIFO_CTRL_WID); - else - wr_bits(offset, VDIN_ASFIFO_CTRL3, 0xf4, - VDI6_ASFIFO_CTRL_BIT, VDI6_ASFIFO_CTRL_WID); + else { + if (/*is_meson_gxlx2_cpu() || */is_meson_g12b_cpu() + || is_meson_tl1_cpu() || is_meson_sm1_cpu() || + is_meson_tm2_cpu()) + wr_bits(offset, VDIN_ASFIFO_CTRL3, 0xd4, + VDI6_ASFIFO_CTRL_BIT, + VDI6_ASFIFO_CTRL_WID); + else + wr_bits(offset, VDIN_ASFIFO_CTRL3, 0xf4, + VDI6_ASFIFO_CTRL_BIT, + VDI6_ASFIFO_CTRL_WID); + } break; case 0xc0: /* viu2 */ vdin_mux = VDIN_MUX_VIU_2; if (port != TVIN_PORT_VIU2) wr_bits(offset, VDIN_ASFIFO_CTRL3, 0xe4, VDI8_ASFIFO_CTRL_BIT, VDI8_ASFIFO_CTRL_WID); - else - wr_bits(offset, VDIN_ASFIFO_CTRL3, 0xf4, - VDI8_ASFIFO_CTRL_BIT, VDI8_ASFIFO_CTRL_WID); + else { + if (/*is_meson_gxlx2_cpu() || */is_meson_g12b_cpu() + || is_meson_tl1_cpu() || is_meson_sm1_cpu() || + is_meson_tm2_cpu()) + wr_bits(offset, VDIN_ASFIFO_CTRL3, 0xd4, + VDI6_ASFIFO_CTRL_BIT, + VDI6_ASFIFO_CTRL_WID); + else + wr_bits(offset, VDIN_ASFIFO_CTRL3, 0xf4, + VDI6_ASFIFO_CTRL_BIT, + VDI6_ASFIFO_CTRL_WID); + } break; case 0x100:/* mipi in mybe need modify base on truth */ vdin_mux = VDIN_MUX_MIPI; @@ -1453,9 +1554,10 @@ static void vdin_set_color_matrix0_g12a(unsigned int offset, VDIN_MATRIX_COEF_INDEX_BIT, VDIN_MATRIX_COEF_INDEX_WID); wr(offset, - VDIN_MATRIX_PRE_OFFSET0_1, matrix_tbl->pre_offset0_1); + VDIN_HDR2_MATRIXI_PRE_OFFSET0_1, + matrix_tbl->pre_offset0_1); wr(offset, - VDIN_MATRIX_PRE_OFFSET2, matrix_tbl->pre_offset2); + VDIN_HDR2_MATRIXI_PRE_OFFSET2, matrix_tbl->pre_offset2); wr(offset, VDIN_HDR2_MATRIXI_COEF00_01, matrix_tbl->coef00_01); wr(offset, VDIN_HDR2_MATRIXI_COEF02_10, matrix_tbl->coef02_10); wr(offset, VDIN_HDR2_MATRIXI_COEF11_12, matrix_tbl->coef11_12); @@ -1491,7 +1593,8 @@ void vdin_set_matrix(struct vdin_dev_s *devp) */ wr_bits(offset, VDIN_MATRIX_CTRL, 0, VDIN_MATRIX1_EN_BIT, VDIN_MATRIX1_EN_WID); - if (is_meson_g12a_cpu() || is_meson_g12b_cpu()) + if (is_meson_g12a_cpu() || is_meson_g12b_cpu() || + is_meson_sm1_cpu() || is_meson_tm2_cpu()) vdin_set_color_matrix0_g12a(devp->addr_offset, devp->fmt_info_p, devp->format_convert, @@ -1524,7 +1627,8 @@ void vdin_set_matrix(struct vdin_dev_s *devp) devp->prop.color_fmt_range, devp->prop.vdin_hdr_Flag, devp->color_range_mode); - if (is_meson_g12a_cpu() || is_meson_g12b_cpu()) + if (is_meson_g12a_cpu() || is_meson_g12b_cpu() || + is_meson_sm1_cpu() || is_meson_tm2_cpu()) vdin_set_color_matrix0_g12a(devp->addr_offset, devp->fmt_info_p, devp->format_convert, @@ -1559,7 +1663,8 @@ void vdin_set_matrixs(struct vdin_dev_s *devp, unsigned char id, { switch (id) { case 0: - if (is_meson_g12a_cpu() || is_meson_g12b_cpu()) + if (is_meson_g12a_cpu() || is_meson_g12b_cpu() || + is_meson_sm1_cpu() || is_meson_tm2_cpu()) vdin_set_color_matrix0_g12a(devp->addr_offset, devp->fmt_info_p, devp->format_convert, @@ -1609,7 +1714,8 @@ void vdin_set_prob_xy(unsigned int offset, devp->prop.color_fmt_range, devp->prop.vdin_hdr_Flag, devp->color_range_mode); - if (is_meson_g12a_cpu() || is_meson_g12b_cpu()) + if (is_meson_g12a_cpu() || is_meson_g12b_cpu() || + is_meson_sm1_cpu() || is_meson_tm2_cpu()) vdin_set_color_matrix0_g12a(devp->addr_offset, devp->fmt_info_p, devp->format_convert, @@ -1742,7 +1848,13 @@ static inline void vdin_set_hist_mux(struct vdin_dev_s *devp) /* use 11: form matrix1 din */ wr_bits(devp->addr_offset, VDIN_HIST_CTRL, 3, HIST_HIST_DIN_SEL_BIT, HIST_HIST_DIN_SEL_WID); + + /*for project get vdin1 hist*/ + //if (devp->index == 1) + // wr_bits(devp->addr_offset, VDIN_WR_CTRL2, 1, 8, 1); } + + /* urgent ctr config */ /*if vdin fifo over up_th,will trigger increase * urgent responds to vdin write, @@ -1934,7 +2046,7 @@ void vdin_set_wr_ctrl_vsync(struct vdin_dev_s *devp, hconv_mode = 2; swap_cbcr = 0; } -#ifdef CONFIG_AML_RDMA +#ifdef CONFIG_AMLOGIC_MEDIA_RDMA if (rdma_enable) { rdma_write_reg_bits(devp->rdma_handle, VDIN_WR_CTRL+devp->addr_offset, @@ -2028,9 +2140,10 @@ unsigned int vdin_get_total_v(unsigned int offset) void vdin_set_canvas_id(struct vdin_dev_s *devp, unsigned int rdma_enable, unsigned int canvas_id) { -#ifdef CONFIG_AML_RDMA +#ifdef CONFIG_AMLOGIC_MEDIA_RDMA if (rdma_enable) { - if (is_meson_g12a_cpu() || is_meson_g12b_cpu()) { + if (is_meson_g12a_cpu() || is_meson_g12b_cpu() || + is_meson_sm1_cpu()) { rdma_write_reg_bits(devp->rdma_handle, VDIN_COM_CTRL0+devp->addr_offset, 1, VDIN_FORCEGOLINE_EN_BIT, 1); @@ -2054,7 +2167,7 @@ unsigned int vdin_get_canvas_id(unsigned int offset) void vdin_set_chma_canvas_id(struct vdin_dev_s *devp, unsigned int rdma_enable, unsigned int canvas_id) { -#ifdef CONFIG_AML_RDMA +#ifdef CONFIG_AMLOGIC_MEDIA_RDMA if (rdma_enable) rdma_write_reg_bits(devp->rdma_handle, VDIN_WR_CTRL2+devp->addr_offset, @@ -2616,6 +2729,8 @@ void vdin_set_default_regmap(unsigned int offset) is_meson_gxtvbb_cpu() || is_meson_txl_cpu() || is_meson_txlx_cpu() || is_meson_tl1_cpu()) wr(offset, VDIN_LFIFO_CTRL, 0x00000f00); + else if (is_meson_tm2_cpu()) + wr(offset, VDIN_LFIFO_CTRL, 0xc0020f00); else wr(offset, VDIN_LFIFO_CTRL, 0x00000780); /* [15:14] clkgate.bbar = 0/(auto, off, on, on) */ @@ -3481,6 +3596,7 @@ void vdin_force_gofiled(struct vdin_dev_s *devp) void vdin_dolby_addr_alloc(struct vdin_dev_s *devp, unsigned int size) { unsigned int index, alloc_size; + int highmem_flag; alloc_size = dolby_size_byte*size; devp->dv.dv_dma_vaddr = dma_alloc_coherent(&devp->this_pdev->dev, @@ -3490,21 +3606,45 @@ void vdin_dolby_addr_alloc(struct vdin_dev_s *devp, unsigned int size) return; } memset(devp->dv.dv_dma_vaddr, 0, alloc_size); + if (devp->cma_config_flag & 0x100) + highmem_flag = PageHighMem(phys_to_page(devp->vfmem_start[0])); + else + highmem_flag = PageHighMem(phys_to_page(devp->mem_start)); + for (index = 0; index < size; index++) { devp->vfp->dv_buf_mem[index] = devp->dv.dv_dma_paddr + dolby_size_byte * index; devp->vfp->dv_buf_vmem[index] = devp->dv.dv_dma_vaddr + dolby_size_byte * index; - if ((devp->cma_config_flag & 0x100) && devp->cma_config_en) - devp->vfp->dv_buf_ori[index] = - phys_to_virt(devp->vfmem_start[index] + - devp->vfmem_size - - dolby_size_byte); - else - devp->vfp->dv_buf_ori[index] = - phys_to_virt(devp->mem_start + devp->mem_size - - dolby_size_byte * - (devp->canvas_max_num - index)); + + if (highmem_flag == 0) { + if ((devp->cma_config_flag & 0x100) + && devp->cma_config_en) + devp->vfp->dv_buf_ori[index] = + phys_to_virt(devp->vfmem_start[index] + + devp->vfmem_size - + dolby_size_byte); + else + devp->vfp->dv_buf_ori[index] = + phys_to_virt(devp->mem_start + + devp->mem_size - + dolby_size_byte * + (devp->canvas_max_num - index)); + } else { + if ((devp->cma_config_flag & 0x100) + && devp->cma_config_en) + devp->vfp->dv_buf_ori[index] = + vdin_vmap(devp->vfmem_start[index] + + devp->vfmem_size-dolby_size_byte, + dolby_size_byte); + else + devp->vfp->dv_buf_ori[index] = + vdin_vmap(devp->mem_start + + devp->mem_size - + dolby_size_byte * + (devp->canvas_max_num - index), + dolby_size_byte); + } pr_info("%s:dv_buf[%d]=0x%p(0x%x,0x%p)\n", __func__, index, devp->vfp->dv_buf_ori[index], devp->vfp->dv_buf_mem[index], @@ -3516,15 +3656,32 @@ void vdin_dolby_addr_alloc(struct vdin_dev_s *devp, unsigned int size) void vdin_dolby_addr_release(struct vdin_dev_s *devp, unsigned int size) { unsigned int alloc_size; + int highmem_flag; + int index; alloc_size = dolby_size_byte*size; if (devp->dv.dv_dma_vaddr) dma_free_coherent(&devp->this_pdev->dev, alloc_size, devp->dv.dv_dma_vaddr, devp->dv.dv_dma_paddr); devp->dv.dv_dma_vaddr = NULL; + + if (devp->cma_config_flag & 0x100) + highmem_flag = PageHighMem(phys_to_page(devp->vfmem_start[0])); + else + highmem_flag = PageHighMem(phys_to_page(devp->mem_start)); + + if (highmem_flag) { + for (index = 0; index < size; index++) { + if (devp->vfp->dv_buf_ori[index]) { + vdin_unmap_phyaddr( + devp->vfp->dv_buf_ori[index]); + devp->vfp->dv_buf_ori[index] = NULL; + } + } + } } -static void vdin_dolby_metadata_swap(char *buf) +static void vdin_dolby_metadata_swap(struct vdin_dev_s *devp, char *buf) { char ext; unsigned int i, j; @@ -3536,6 +3693,8 @@ static void vdin_dolby_metadata_swap(char *buf) buf[i*16+15-j] = ext; } } + + vdin_dma_flush(devp, buf, dolby_size_byte, DMA_TO_DEVICE); } #define swap32(num) \ @@ -3633,7 +3792,8 @@ void vdin_dolby_buffer_update(struct vdin_dev_s *devp, unsigned int index) for (count = 0; count < META_RETRY_MAX; count++) { if (dv_dbg_mask & DV_READ_MODE_AXI) { memcpy(p, devp->vfp->dv_buf_vmem[index], 128); - vdin_dolby_metadata_swap(c); + vdin_dma_flush(devp, p, 128, DMA_TO_DEVICE); + vdin_dolby_metadata_swap(devp, c); } else { wr(offset, VDIN_DOLBY_DSC_CTRL3, 0); wr(offset, VDIN_DOLBY_DSC_CTRL2, 0xd180c0d5); @@ -3646,7 +3806,9 @@ void vdin_dolby_buffer_update(struct vdin_dev_s *devp, unsigned int index) if ((i == 31) && (multimeta_flag == 0)) break; } + vdin_dma_flush(devp, p, 128, DMA_TO_DEVICE); } + meta_size = (c[3] << 8) | c[4]; crc = p[31]; crc_result = crc32(0, p, 124); @@ -4022,9 +4184,11 @@ u32 vdin_get_curr_field_type(struct vdin_dev_s *devp) } format_convert = devp->format_convert; if ((format_convert == VDIN_FORMAT_CONVERT_YUV_YUV444) || - (format_convert == VDIN_FORMAT_CONVERT_RGB_YUV444)) + (format_convert == VDIN_FORMAT_CONVERT_RGB_YUV444)) { type |= VIDTYPE_VIU_444; - else if ((format_convert == VDIN_FORMAT_CONVERT_YUV_YUV422) || + if (devp->afbce_mode == 1) + type |= VIDTYPE_COMB_MODE; + } else if ((format_convert == VDIN_FORMAT_CONVERT_YUV_YUV422) || (format_convert == VDIN_FORMAT_CONVERT_RGB_YUV422)) type |= VIDTYPE_VIU_422; else if (devp->prop.dest_cfmt == TVIN_NV21) { @@ -4035,6 +4199,14 @@ u32 vdin_get_curr_field_type(struct vdin_dev_s *devp) type &= (~VIDTYPE_VIU_SINGLE_PLANE); } + + if (devp->afbce_mode == 1) { + type |= VIDTYPE_COMPRESS; + type |= VIDTYPE_SCATTER; + if (devp->afbce_lossy_en == 1) + type |= VIDTYPE_COMPRESS_LOSS; + } + return type; } diff --git a/drivers/amlogic/media/vin/tvin/vdin/vdin_ctl.h b/drivers/amlogic/media/vin/tvin/vdin/vdin_ctl.h index 178c74a0a387..fcdf2974d439 100644 --- a/drivers/amlogic/media/vin/tvin/vdin/vdin_ctl.h +++ b/drivers/amlogic/media/vin/tvin/vdin/vdin_ctl.h @@ -17,7 +17,11 @@ #ifndef __TVIN_VDIN_CTL_H #define __TVIN_VDIN_CTL_H - +#include +#include +#include +#include +#include #include "vdin_drv.h" #define DV_SWAP_EN (1 << 0) @@ -111,10 +115,16 @@ struct ldim_max_s { #endif extern unsigned int game_mode; +extern bool vdin_dbg_en; /* ************************************************************************ */ /* ******** GLOBAL FUNCTION CLAIM ******** */ /* ************************************************************************ */ +extern u8 *vdin_vmap(ulong addr, u32 size); +extern void vdin_unmap_phyaddr(u8 *vaddr); +extern void vdin_dma_flush(struct vdin_dev_s *devp, void *vaddr, + int size, enum dma_data_direction dir); + extern void vdin_set_vframe_prop_info(struct vframe_s *vf, struct vdin_dev_s *devp); extern void LDIM_Initial_2(int pic_h, int pic_v, int BLK_Vnum, diff --git a/drivers/amlogic/media/vin/tvin/vdin/vdin_debug.c b/drivers/amlogic/media/vin/tvin/vdin/vdin_debug.c index cf16fb1f027e..cb3065f309b2 100644 --- a/drivers/amlogic/media/vin/tvin/vdin/vdin_debug.c +++ b/drivers/amlogic/media/vin/tvin/vdin/vdin_debug.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include /* Local Headers */ @@ -273,7 +274,11 @@ static void vdin_dump_one_buf_mem(char *path, struct vdin_dev_s *devp, struct file *filp = NULL; loff_t pos = 0; void *buf = NULL; - unsigned int i; + unsigned int i, j; + unsigned int span = 0, count = 0; + int highmem_flag; + unsigned long highaddr; + unsigned long phys; mm_segment_t old_fs = get_fs(); set_fs(KERNEL_DS); @@ -288,7 +293,22 @@ static void vdin_dump_one_buf_mem(char *path, struct vdin_dev_s *devp, pr_info("%s:no cma alloc mem!!!\n", __func__); return; } - if (buf_num < devp->canvas_max_num) { + + if (buf_num >= devp->canvas_max_num) { + vfs_fsync(filp, 0); + filp_close(filp, NULL); + set_fs(old_fs); + pr_info("buf_num > canvas_max_num, vdin exit dump\n"); + return; + } + + if (devp->cma_config_flag & 0x100) + highmem_flag = PageHighMem(phys_to_page(devp->vfmem_start[0])); + else + highmem_flag = PageHighMem(phys_to_page(devp->mem_start)); + + if (highmem_flag == 0) { + pr_info("low mem area\n"); if (devp->cma_config_flag == 0x1) buf = codec_mm_phys_to_virt(devp->mem_start + devp->canvas_max_size*buf_num); @@ -307,6 +327,34 @@ static void vdin_dump_one_buf_mem(char *path, struct vdin_dev_s *devp, /*vfs_write(filp, buf, devp->canvas_max_size, &pos);*/ pr_info("write buffer %2d of %2u to %s.\n", buf_num, devp->canvas_max_num, path); + } else { + pr_info("high mem area\n"); + count = devp->canvas_h; + span = devp->canvas_active_w; + + if (devp->cma_config_flag == 0x1) + phys = devp->mem_start + devp->canvas_max_size*buf_num; + else if (devp->cma_config_flag == 0x101) + phys = devp->vfmem_start[buf_num]; + else if (devp->cma_config_flag == 0x100) + phys = devp->vfmem_start[buf_num]; + else + phys = devp->mem_start + devp->canvas_max_size*buf_num; + + for (j = 0; j < count; j++) { + highaddr = phys + j * devp->canvas_w; + buf = vdin_vmap(highaddr, span); + if (!buf) { + pr_info("vdin_vmap error\n"); + return; + } + + vdin_dma_flush(devp, buf, span, DMA_FROM_DEVICE); + vfs_write(filp, buf, span, &pos); + vdin_unmap_phyaddr(buf); + } + pr_info("high-mem write buffer %2d of %2u to %s.\n", + buf_num, devp->canvas_max_num, path); } vfs_fsync(filp, 0); filp_close(filp, NULL); @@ -317,15 +365,20 @@ static void vdin_dump_mem(char *path, struct vdin_dev_s *devp) { struct file *filp = NULL; loff_t pos = 0; - loff_t i = 0, j = 0; - unsigned int mem_size = 0; + loff_t mem_size = 0; + unsigned int i = 0, j = 0; + unsigned int span = 0; + unsigned int count = 0; + unsigned long highaddr; + unsigned long phys; + int highmem_flag; void *buf = NULL; void *vfbuf[VDIN_CANVAS_MAX_CNT]; mm_segment_t old_fs = get_fs(); set_fs(KERNEL_DS); filp = filp_open(path, O_RDWR|O_CREAT, 0666); - mem_size = devp->canvas_active_w * devp->canvas_h; + mem_size = (loff_t)devp->canvas_active_w * devp->canvas_h; for (i = 0; i < VDIN_CANVAS_MAX_CNT; i++) vfbuf[i] = NULL; if (IS_ERR(filp)) { @@ -337,33 +390,79 @@ static void vdin_dump_mem(char *path, struct vdin_dev_s *devp) pr_info("%s:no cma alloc mem!!!\n", __func__); return; } - for (i = 0; i < devp->canvas_max_num; i++) { - pos = mem_size * i; - if (devp->cma_config_flag == 0x1) - buf = codec_mm_phys_to_virt(devp->mem_start + - devp->canvas_max_size*i); - else if (devp->cma_config_flag == 0x101) - vfbuf[i] = codec_mm_phys_to_virt( - devp->vfmem_start[i]); - else if (devp->cma_config_flag == 0x100) - vfbuf[i] = phys_to_virt(devp->vfmem_start[i]); - else - buf = phys_to_virt(devp->mem_start + - devp->canvas_max_size*i); - /*only write active data*/ - for (j = 0; j < devp->canvas_h; j++) { - if (devp->cma_config_flag & 0x100) { - vfs_write(filp, vfbuf[i], - devp->canvas_active_w, &pos); - vfbuf[i] += devp->canvas_w; - } else { - vfs_write(filp, buf, - devp->canvas_active_w, &pos); - buf += devp->canvas_w; + + if (devp->cma_config_flag & 0x100) + highmem_flag = PageHighMem(phys_to_page(devp->vfmem_start[0])); + else + highmem_flag = PageHighMem(phys_to_page(devp->mem_start)); + + if (highmem_flag == 0) { + /*low mem area*/ + pr_info("low mem area\n"); + for (i = 0; i < devp->canvas_max_num; i++) { + pos = mem_size * i; + if (devp->cma_config_flag == 0x1) + buf = codec_mm_phys_to_virt(devp->mem_start + + devp->canvas_max_size*i); + else if (devp->cma_config_flag == 0x101) + vfbuf[i] = codec_mm_phys_to_virt( + devp->vfmem_start[i]); + else if (devp->cma_config_flag == 0x100) + vfbuf[i] = phys_to_virt(devp->vfmem_start[i]); + else + buf = phys_to_virt(devp->mem_start + + devp->canvas_max_size*i); + /*only write active data*/ + for (j = 0; j < devp->canvas_h; j++) { + if (devp->cma_config_flag & 0x100) { + vfs_write(filp, vfbuf[i], + devp->canvas_active_w, &pos); + vfbuf[i] += devp->canvas_w; + } else { + vfs_write(filp, buf, + devp->canvas_active_w, &pos); + buf += devp->canvas_w; + } } + pr_info("write buffer %2d of %2u to %s.\n", + i, devp->canvas_max_num, path); + } + } else { + /*high mem area*/ + pr_info("high mem area\n"); + count = devp->canvas_h; + span = devp->canvas_active_w; + + for (i = 0; i < devp->canvas_max_num; i++) { + pos = mem_size * i; + if (devp->cma_config_flag == 0x1) { + phys = devp->mem_start + + devp->canvas_max_size*i; + } else if (devp->cma_config_flag == 0x101) + phys = devp->vfmem_start[i]; + else if (devp->cma_config_flag == 0x100) + phys = devp->vfmem_start[i]; + else { + phys = devp->mem_start + + devp->canvas_max_size*i; + } + + for (j = 0; j < count; j++) { + highaddr = phys + j * devp->canvas_w; + buf = vdin_vmap(highaddr, span); + if (!buf) { + pr_info("vdin_vmap error\n"); + return; + } + + vdin_dma_flush(devp, buf, span, + DMA_FROM_DEVICE); + vfs_write(filp, buf, span, &pos); + vdin_unmap_phyaddr(buf); + } + pr_info("high-mem write buffer %2d of %2u to %s.\n", + i, devp->canvas_max_num, path); } - pr_info("write buffer %lld of %2u to %s.\n", - i, devp->canvas_max_num, path); } vfs_fsync(filp, 0); filp_close(filp, NULL); @@ -378,6 +477,14 @@ static void vdin_dump_one_afbce_mem(char *path, struct vdin_dev_s *devp, void *buf_head = NULL; void *buf_table = NULL; void *buf_body = NULL; + unsigned long highaddr; + unsigned long phys; + int highmem_flag = 0; + unsigned int span = 0; + unsigned int remain = 0; + unsigned int count = 0; + unsigned int j = 0; + void *vbuf = NULL; unsigned char buff[100]; mm_segment_t old_fs = get_fs(); @@ -392,30 +499,52 @@ static void vdin_dump_one_afbce_mem(char *path, struct vdin_dev_s *devp, return; } - if (devp->cma_config_flag == 0x101) { - buf_head = codec_mm_phys_to_virt( - devp->afbce_info->fm_head_paddr[buf_num]); - buf_table = codec_mm_phys_to_virt( - devp->afbce_info->fm_table_paddr[buf_num]); - buf_body = codec_mm_phys_to_virt( - devp->afbce_info->fm_body_paddr[buf_num]); + highmem_flag = PageHighMem( + phys_to_page(devp->afbce_info->fm_body_paddr[0])); + + if (highmem_flag == 0) { + /*low mem area*/ + pr_info("low mem area\n"); + if (devp->cma_config_flag == 0x101) { + buf_head = codec_mm_phys_to_virt( + devp->afbce_info->fm_head_paddr[buf_num]); + buf_table = codec_mm_phys_to_virt( + devp->afbce_info->fm_table_paddr[buf_num]); + buf_body = codec_mm_phys_to_virt( + devp->afbce_info->fm_body_paddr[buf_num]); + + pr_info(".head_paddr=0x%lx,table_paddr=0x%lx,body_paddr=0x%lx\n", + devp->afbce_info->fm_head_paddr[buf_num], + (devp->afbce_info->fm_table_paddr[buf_num]), + devp->afbce_info->fm_body_paddr[buf_num]); + } else if (devp->cma_config_flag == 0) { + buf_head = phys_to_virt( + devp->afbce_info->fm_head_paddr[buf_num]); + buf_table = phys_to_virt( + devp->afbce_info->fm_table_paddr[buf_num]); + buf_body = phys_to_virt( + devp->afbce_info->fm_body_paddr[buf_num]); + + pr_info("head_paddr=0x%lx,table_paddr=0x%lx,body_paddr=0x%lx\n", + devp->afbce_info->fm_head_paddr[buf_num], + (devp->afbce_info->fm_table_paddr[buf_num]), + devp->afbce_info->fm_body_paddr[buf_num]); + } + } else { + /*high mem area*/ + pr_info("high mem area\n"); + buf_head = vdin_vmap( + devp->afbce_info->fm_head_paddr[buf_num], + devp->afbce_info->frame_head_size); + + buf_table = vdin_vmap( + devp->afbce_info->fm_table_paddr[buf_num], + devp->afbce_info->frame_table_size); pr_info(".head_paddr=0x%lx,table_paddr=0x%lx,body_paddr=0x%lx\n", devp->afbce_info->fm_head_paddr[buf_num], (devp->afbce_info->fm_table_paddr[buf_num]), devp->afbce_info->fm_body_paddr[buf_num]); - } else if (devp->cma_config_flag == 0) { - buf_head = phys_to_virt( - devp->afbce_info->fm_head_paddr[buf_num]); - buf_table = phys_to_virt( - devp->afbce_info->fm_table_paddr[buf_num]); - buf_body = phys_to_virt( - devp->afbce_info->fm_body_paddr[buf_num]); - - pr_info("head_paddr=0x%lx,table_paddr=0x%lx,body_paddr=0x%lx\n", - devp->afbce_info->fm_head_paddr[buf_num], - (devp->afbce_info->fm_table_paddr[buf_num]), - devp->afbce_info->fm_body_paddr[buf_num]); } set_fs(KERNEL_DS); @@ -429,7 +558,12 @@ static void vdin_dump_one_afbce_mem(char *path, struct vdin_dev_s *devp, return; } + vdin_dma_flush(devp, buf_head, + devp->afbce_info->frame_head_size, + DMA_FROM_DEVICE); vfs_write(filp, buf_head, devp->afbce_info->frame_head_size, &pos); + if (highmem_flag) + vdin_unmap_phyaddr(buf_head); pr_info("write buffer %2d of %2u head to %s.\n", buf_num, devp->canvas_max_num, buff); vfs_fsync(filp, 0); @@ -444,7 +578,12 @@ static void vdin_dump_one_afbce_mem(char *path, struct vdin_dev_s *devp, pr_info("create %s table error.\n", buff); return; } + vdin_dma_flush(devp, buf_table, + devp->afbce_info->frame_table_size, + DMA_FROM_DEVICE); vfs_write(filp, buf_table, devp->afbce_info->frame_table_size, &pos); + if (highmem_flag) + vdin_unmap_phyaddr(buf_table); pr_info("write buffer %2d of %2u table to %s.\n", buf_num, devp->canvas_max_num, buff); vfs_fsync(filp, 0); @@ -459,7 +598,42 @@ static void vdin_dump_one_afbce_mem(char *path, struct vdin_dev_s *devp, pr_info("create %s body error.\n", buff); return; } - vfs_write(filp, buf_body, devp->afbce_info->frame_body_size, &pos); + if (highmem_flag == 0) { + vfs_write(filp, buf_body, + devp->afbce_info->frame_body_size, &pos); + } else { + span = SZ_1M; + count = devp->afbce_info->frame_body_size/PAGE_ALIGN(span); + remain = devp->afbce_info->frame_body_size%PAGE_ALIGN(span); + phys = devp->afbce_info->fm_body_paddr[buf_num]; + + for (j = 0; j < count; j++) { + highaddr = phys + j * span; + vbuf = vdin_vmap(highaddr, span); + if (!vbuf) { + pr_info("vdin_vmap error\n"); + return; + } + + vdin_dma_flush(devp, vbuf, span, DMA_FROM_DEVICE); + vfs_write(filp, vbuf, span, &pos); + vdin_unmap_phyaddr(vbuf); + } + + if (remain) { + span = devp->afbce_info->frame_body_size - remain; + highaddr = phys + span; + vbuf = vdin_vmap(highaddr, remain); + if (!vbuf) { + pr_info("vdin_vmap1 error\n"); + return; + } + + vdin_dma_flush(devp, vbuf, remain, DMA_FROM_DEVICE); + vfs_write(filp, vbuf, remain, &pos); + vdin_unmap_phyaddr(vbuf); + } + } pr_info("write buffer %2d of %2u body to %s.\n", buf_num, devp->canvas_max_num, buff); vfs_fsync(filp, 0); @@ -468,119 +642,6 @@ static void vdin_dump_one_afbce_mem(char *path, struct vdin_dev_s *devp, set_fs(old_fs); } -static void vdin_dump_afbce_mem(char *path, struct vdin_dev_s *devp) -{ - struct file *filp = NULL; - loff_t pos = 0; - void *buf_head = NULL; - void *buf_table = NULL; - void *buf_body = NULL; - unsigned char buff[100]; - unsigned int i; - mm_segment_t old_fs = get_fs(); - - if ((devp->cma_config_flag & 0x1) && - (devp->cma_mem_alloc == 0)) { - pr_info("%s:no cma alloc mem!!!\n", __func__); - return; - } - - if (devp->cma_config_flag == 0x101) { - buf_head = codec_mm_phys_to_virt( - devp->afbce_info->head_paddr); - buf_table = codec_mm_phys_to_virt( - devp->afbce_info->table_paddr); - buf_body = codec_mm_phys_to_virt( - devp->afbce_info->fm_body_paddr[0]); - - pr_info(".head_paddr=0x%lx,table_paddr=0x%lx,body_paddr=0x%lx\n", - devp->afbce_info->head_paddr, - (devp->afbce_info->table_paddr), - devp->afbce_info->fm_body_paddr[0]); - } else if (devp->cma_config_flag == 0) { - buf_head = phys_to_virt( - devp->afbce_info->head_paddr); - buf_table = phys_to_virt( - devp->afbce_info->table_paddr); - buf_body = phys_to_virt( - devp->afbce_info->fm_body_paddr[0]); - - pr_info("head_paddr=0x%lx,table_paddr=0x%lx,body_paddr=0x%lx\n", - devp->afbce_info->head_paddr, - (devp->afbce_info->table_paddr), - devp->afbce_info->fm_body_paddr[0]); - } - - set_fs(KERNEL_DS); - - /* write header bin start */ - strcpy(buff, path); - strcat(buff, "_header.bin"); - filp = filp_open(buff, O_RDWR|O_CREAT, 0666); - if (IS_ERR(filp)) { - pr_info("create %s header error.\n", buff); - return; - } - - for (i = 0; i < devp->vfmem_max_cnt; i++) { - vfs_write(filp, buf_head, - devp->afbce_info->frame_head_size, &pos); - buf_head += devp->afbce_info->frame_head_size; - pr_info("write buffer %2d(0x%x bytes) of %2u head to %s.\n", - i, devp->afbce_info->frame_head_size, - devp->canvas_max_num, buff); - } - vfs_fsync(filp, 0); - filp_close(filp, NULL); - /* write header bin end */ - - /* write table bin start */ - pos = 0; - strcpy(buff, path); - strcat(buff, "_table.bin"); - filp = filp_open(buff, O_RDWR|O_CREAT, 0666); - if (IS_ERR(filp)) { - pr_info("create %s table error.\n", buff); - return; - } - - for (i = 0; i < devp->vfmem_max_cnt; i++) { - vfs_write(filp, buf_table, - devp->afbce_info->frame_table_size, &pos); - buf_table += devp->afbce_info->frame_table_size; - pr_info("write buffer %2d(0x%x bytes) of %2u table to %s.\n", - i, devp->afbce_info->frame_table_size, - devp->canvas_max_num, buff); - } - vfs_fsync(filp, 0); - filp_close(filp, NULL); - /* write table bin end */ - - /* write body bin start */ - pos = 0; - strcpy(buff, path); - strcat(buff, "_body.bin"); - filp = filp_open(buff, O_RDWR|O_CREAT, 0666); - if (IS_ERR(filp)) { - pr_info("create %s body error.\n", buff); - return; - } - - for (i = 0; i < devp->vfmem_max_cnt; i++) { - vfs_write(filp, buf_body, - devp->afbce_info->frame_body_size, &pos); - buf_body += devp->afbce_info->frame_body_size; - pr_info("write buffer %2d(0x%x bytes) of %2u body to %s.\n", - i, devp->afbce_info->frame_body_size, - devp->canvas_max_num, buff); - } - vfs_fsync(filp, 0); - filp_close(filp, NULL); - /* write body bin end */ - - set_fs(old_fs); -} - static void dump_other_mem(char *path, unsigned int start, unsigned int offset) { @@ -699,6 +760,7 @@ static void vdin_dump_state(struct vdin_dev_s *devp) pr_info("color_depth_support:0x%x\n", devp->color_depth_support); pr_info("cma_flag:0x%x\n", devp->cma_config_flag); pr_info("auto_cutwindow_en:%d\n", devp->auto_cutwindow_en); + pr_info("cutwindow_cfg:%d\n", devp->cutwindow_cfg); pr_info("auto_ratio_en:%d\n", devp->auto_ratio_en); pr_info("cma_mem_alloc:%d\n", devp->cma_mem_alloc); pr_info("cma_mem_size:0x%x\n", devp->cma_mem_size); @@ -745,7 +807,7 @@ static void vdin_dump_state(struct vdin_dev_s *devp) pr_info("vdin_irq_flag: %d, vdin_rest_flag: %d, irq_cnt: %d, rdma_irq_cnt: %d\n", devp->vdin_irq_flag, devp->vdin_reset_flag, devp->irq_cnt, devp->rdma_irq_cnt); - pr_info("rdma_enable : %d\n", devp->rdma_enable); + pr_info("game_mode : %d\n", devp->game_mode); pr_info("dolby_input : %d\n", devp->dv.dolby_input); if ((devp->cma_config_en != 1) || !(devp->cma_config_flag & 0x100)) pr_info("dolby_mem_start = %ld, dolby_mem_size = %d\n", @@ -766,6 +828,8 @@ static void vdin_dump_state(struct vdin_dev_s *devp) devp->dv.dv_flag, devp->dv.dv_config, devp->prop.dolby_vision); pr_info("size of struct vdin_dev_s: %d\n", devp->vdin_dev_ssize); + pr_info("afbce_flag: %d\n", devp->afbce_flag); + pr_info("afbce_mode: %d\n", devp->afbce_mode); if (devp->afbce_mode == 1) { for (i = 0; i < devp->vfmem_max_cnt; i++) { pr_info("head(%d) addr:0x%lx, size:0x%x\n", @@ -788,8 +852,11 @@ static void vdin_dump_state(struct vdin_dev_s *devp) i, devp->afbce_info->fm_body_paddr[i], devp->afbce_info->frame_body_size); } + if (is_meson_tl1_cpu()) { + pr_info("tl1 preview flag = %d\n", + tl1_vdin1_preview_flag); + } } - pr_info("Vdin driver version : %s\n", VDIN_VER); } @@ -936,6 +1003,140 @@ static void vdin_dump_histgram(struct vdin_dev_s *devp) } } +/*type: 1:nv21 2:yuv422 3:yuv444*/ +static void vdin_write_afbce_mem(struct vdin_dev_s *devp, char *type, + char *path) +{ + char md_path_head[100], md_path_body[100]; + unsigned int i, j; + int highmem_flag = 0; + unsigned int size = 0; + unsigned int span = 0; + unsigned int remain = 0; + unsigned int count = 0; + unsigned long highaddr; + unsigned long phys; + long val; + struct file *filp = NULL; + loff_t pos = 0; + mm_segment_t old_fs; + void *head_dts = NULL; + void *body_dts = NULL; + void *vbuf = NULL; + + if (kstrtol(type, 10, &val) < 0) + return; + if (!path) + return; + + if (!devp->curr_wr_vfe) { + devp->curr_wr_vfe = provider_vf_get(devp->vfp); + if (!devp->curr_wr_vfe) { + pr_info("no buffer to write.\n"); + return; + } + } + + sprintf(md_path_head, "%s_1header.bin", path); + sprintf(md_path_body, "%s_1body.bin", path); + + i = devp->curr_wr_vfe->af_num; + devp->curr_wr_vfe->vf.type = VIDTYPE_VIU_SINGLE_PLANE | + VIDTYPE_VIU_FIELD | VIDTYPE_COMPRESS | VIDTYPE_SCATTER; + switch (val) { + case 1: + devp->curr_wr_vfe->vf.type |= VIDTYPE_VIU_NV21; + break; + case 2: + devp->curr_wr_vfe->vf.type |= VIDTYPE_VIU_422; + break; + case 3: + devp->curr_wr_vfe->vf.type |= VIDTYPE_VIU_444; + break; + default: + devp->curr_wr_vfe->vf.type |= VIDTYPE_VIU_422; + break; + } + + devp->curr_wr_vfe->vf.compHeadAddr = devp->afbce_info->fm_head_paddr[i]; + devp->curr_wr_vfe->vf.compBodyAddr = devp->afbce_info->fm_body_paddr[i]; + + highmem_flag = PageHighMem( + phys_to_page(devp->afbce_info->fm_body_paddr[0])); + if (highmem_flag == 0) { + pr_info("low mem area\n"); + head_dts = codec_mm_phys_to_virt( + devp->afbce_info->fm_head_paddr[i]); + } else { + pr_info("high mem area\n"); + head_dts = vdin_vmap( + devp->afbce_info->fm_head_paddr[i], + devp->afbce_info->frame_head_size); + } + + old_fs = get_fs(); + set_fs(KERNEL_DS); + pr_info("head bin file path = %s\n", md_path_head); + filp = filp_open(md_path_head, O_RDONLY, 0); + if (IS_ERR(filp)) { + pr_info("read %s error.\n", md_path_head); + return; + } + + size = vfs_read(filp, head_dts, + devp->afbce_info->frame_head_size, &pos); + if (highmem_flag) + vdin_unmap_phyaddr(head_dts); + + vfs_fsync(filp, 0); + filp_close(filp, NULL); + set_fs(old_fs); + + pos = 0; + old_fs = get_fs(); + set_fs(KERNEL_DS); + pr_info("body bin file path = %s\n", md_path_body); + filp = filp_open(md_path_body, O_RDONLY, 0); + if (IS_ERR(filp)) { + pr_info("read %s error.\n", md_path_body); + return; + } + + if (highmem_flag == 0) { + body_dts = codec_mm_phys_to_virt( + devp->afbce_info->fm_body_paddr[i]); + + size = vfs_read(filp, body_dts, + devp->afbce_info->frame_body_size, &pos); + } else { + span = SZ_1M; + count = devp->afbce_info->frame_body_size/PAGE_ALIGN(span); + remain = devp->afbce_info->frame_body_size%PAGE_ALIGN(span); + phys = devp->afbce_info->fm_body_paddr[i]; + + + for (j = 0; j < count; j++) { + highaddr = phys + j * span; + vbuf = vdin_vmap(highaddr, span); + if (!vbuf) { + pr_info("vdin_vmap error\n"); + return; + } + vfs_read(filp, vbuf, span, &pos); + vdin_unmap_phyaddr(vbuf); + } + } + + vfs_fsync(filp, 0); + filp_close(filp, NULL); + set_fs(old_fs); + + provider_vf_put(devp->curr_wr_vfe, devp->vfp); + devp->curr_wr_vfe = NULL; + vf_notify_receiver(devp->name, VFRAME_EVENT_PROVIDER_VFRAME_READY, + NULL); +} + static void vdin_write_mem( struct vdin_dev_s *devp, char *type, char *path, char *md_path) @@ -946,8 +1147,10 @@ static void vdin_write_mem( mm_segment_t old_fs; void *dts = NULL; long val; - int index; + int index, j, span; + int highmem_flag, count; unsigned long addr; + unsigned long highaddr; struct vf_pool *p = devp->vfp; /* vtype = simple_strtol(type, NULL, 10); */ @@ -996,15 +1199,43 @@ static void vdin_write_mem( addr = canvas_get_addr(devp->curr_wr_vfe->vf.canvas0Addr); /* dts = ioremap(canvas_get_addr(devp->curr_wr_vfe->vf.canvas0Addr), */ /* real_size); */ - dts = phys_to_virt(addr); - size = vfs_read(filp, dts, devp->canvas_max_size, &pos); - pr_info("warning: %s read %u < %u\n", - __func__, size, devp->canvas_max_size); - vfs_fsync(filp, 0); - iounmap(dts); - filp_close(filp, NULL); - set_fs(old_fs); + if (devp->cma_config_flag & 0x100) + highmem_flag = PageHighMem(phys_to_page(devp->vfmem_start[0])); + else + highmem_flag = PageHighMem(phys_to_page(devp->mem_start)); + + if (highmem_flag == 0) { + pr_info("low mem area\n"); + dts = phys_to_virt(addr); + for (j = 0; j < devp->canvas_h; j++) { + vfs_read(filp, dts+(devp->canvas_w*j), + devp->canvas_active_w, &pos); + } + vfs_fsync(filp, 0); + iounmap(dts); + filp_close(filp, NULL); + set_fs(old_fs); + } else { + pr_info("high mem area\n"); + count = devp->canvas_h; + span = devp->canvas_active_w; + for (j = 0; j < count; j++) { + highaddr = addr + j * devp->canvas_w; + dts = vdin_vmap(highaddr, span); + if (!dts) { + pr_info("vdin_vmap error\n"); + return; + } + vfs_read(filp, dts, span, &pos); + vdin_dma_flush(devp, dts, span, DMA_TO_DEVICE); + vdin_unmap_phyaddr(dts); + } + vfs_fsync(filp, 0); + filp_close(filp, NULL); + set_fs(old_fs); + } + if (vtype == 8) { old_fs = get_fs(); set_fs(KERNEL_DS); @@ -1020,7 +1251,7 @@ static void vdin_write_mem( u8 *c = devp->vfp->dv_buf_ori[index]; pos = 0; - size = vfs_read(md_flip, + size = (unsigned int)vfs_read(md_flip, devp->vfp->dv_buf_ori[index], 4096, &pos); p->dv_buf_size[index] = size; @@ -1352,6 +1583,9 @@ start_chk: } else if (!strcmp(parm[1], "video")) { param.port = TVIN_PORT_VIU1_VIDEO; pr_info(" port is TVIN_PORT_VIU_VIDEO\n"); + } else if (!strcmp(parm[1], "viu_wb0_vpp")) { + param.port = TVIN_PORT_VIU1_WB0_VPP; + pr_info(" port is TVIN_PORT_VIU1_WB0_VPP\n"); } else if (!strcmp(parm[1], "viu_wb0_vd1")) { param.port = TVIN_PORT_VIU1_WB0_VD1; pr_info(" port is TVIN_PORT_VIU_WB0_VD1\n"); @@ -1367,6 +1601,9 @@ start_chk: } else if (!strcmp(parm[1], "viu_wb0_post_blend")) { param.port = TVIN_PORT_VIU1_WB0_POST_BLEND; pr_info(" port is TVIN_PORT_VIU_WB0_POST_BLEND\n"); + } else if (!strcmp(parm[1], "viu_wb1_vpp")) { + param.port = TVIN_PORT_VIU1_WB1_VPP; + pr_info(" port is TVIN_PORT_VIU1_WB1_VPP\n"); } else if (!strcmp(parm[1], "viu_wb1_vd1")) { param.port = TVIN_PORT_VIU1_WB1_VD1; pr_info(" port is TVIN_PORT_VIU_WB1_VD1\n"); @@ -1388,6 +1625,9 @@ start_chk: } else if (!strcmp(parm[1], "video2")) { param.port = TVIN_PORT_VIU2_VIDEO; pr_info(" port is TVIN_PORT_VIU_VIDEO\n"); + } else if (!strcmp(parm[1], "viu2_wb0_vpp")) { + param.port = TVIN_PORT_VIU2_WB0_VPP; + pr_info(" port is TVIN_PORT_VIU2_WB0_VPP\n"); } else if (!strcmp(parm[1], "viu2_wb0_vd1")) { param.port = TVIN_PORT_VIU2_WB0_VD1; pr_info(" port is TVIN_PORT_VIU_WB0_VD1\n"); @@ -1403,6 +1643,9 @@ start_chk: } else if (!strcmp(parm[1], "viu2_wb0_post_blend")) { param.port = TVIN_PORT_VIU2_WB0_POST_BLEND; pr_info(" port is TVIN_PORT_VIU_WB0_POST_BLEND\n"); + } else if (!strcmp(parm[1], "viu2_wb1_vpp")) { + param.port = TVIN_PORT_VIU2_WB1_VPP; + pr_info(" port is TVIN_PORT_VIU2_WB1_VPP\n"); } else if (!strcmp(parm[1], "viu2_wb1_vd1")) { param.port = TVIN_PORT_VIU2_WB1_VD1; pr_info(" port is TVIN_PORT_VIU_WB1_VD1\n"); @@ -1509,6 +1752,11 @@ start_chk: #endif } else if (!strcmp(parm[0], "force_recycle")) { devp->flags |= VDIN_FLAG_FORCE_RECYCLE; + } else if (!strcmp(parm[0], "read_pic_afbce")) { + if (parm[1] && parm[2]) + vdin_write_afbce_mem(devp, parm[1], parm[2]); + else + pr_err("miss parameters.\n"); } else if (!strcmp(parm[0], "read_pic")) { if (parm[1] && parm[2]) vdin_write_mem(devp, parm[1], parm[2], parm[3]); @@ -1875,7 +2123,34 @@ start_chk: buf_num = val; vdin_dump_one_afbce_mem(parm[1], devp, buf_num); } else if (parm[1] != NULL) { - vdin_dump_afbce_mem(parm[1], devp); + vdin_dump_one_afbce_mem(parm[1], devp, 0); + } + } else if (!strcmp(parm[0], "skip_frame_debug")) { + if (parm[1] != NULL) { + if (kstrtouint(parm[1], 10, &skip_frame_debug) == 0) + pr_info("set skip_frame_debug: %d\n", + skip_frame_debug); + } else { + pr_info("skip_frame_debug: %d\n", skip_frame_debug); + } + } else if (!strcmp(parm[0], "afbc_drop_cnt")) { + if (parm[1] != NULL) { + if (kstrtouint(parm[1], 10, + &vdin_afbc_force_drop_frame_cnt) == 0) + pr_info("set vdin_afbc_force_drop_frame_cnt: %d\n", + vdin_afbc_force_drop_frame_cnt); + } else { + pr_info("vdin_afbc_force_drop_frame_cnt: %d\n", + vdin_afbc_force_drop_frame_cnt); + } + } else if (!strcmp(parm[0], "max_ignore_cnt")) { + if (parm[1] != NULL) { + if (kstrtouint(parm[1], 10, &max_ignore_frame_cnt) == 0) + pr_info("set max_ignore_frame_cnt: %d\n", + max_ignore_frame_cnt); + } else { + pr_info("max_ignore_frame_cnt: %d\n", + max_ignore_frame_cnt); } } else { pr_info("unknown command\n"); diff --git a/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c b/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c index 74993dc3c561..d8bf617eeb5a 100644 --- a/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c +++ b/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c @@ -78,6 +78,16 @@ static unsigned int vdin_addr_offset[VDIN_MAX_DEVS] = {0, 0x80}; static struct vdin_dev_s *vdin_devp[VDIN_MAX_DEVS]; static unsigned long mem_start, mem_end; static unsigned int use_reserved_mem; +static unsigned int pr_times; + +/* afbce related */ +static int afbc_init_flag[VDIN_MAX_DEVS]; +unsigned int tl1_vdin1_preview_flag; +static unsigned int tl1_vdin1_data_readied; +static unsigned int tl1_vdin1_canvas_addr; +static unsigned int tl1_vdin1_height; +static unsigned int tl1_vdin1_width; +spinlock_t tl1_preview_lock; /* * canvas_config_mode * 0: canvas_config in driver probe @@ -86,13 +96,27 @@ static unsigned int use_reserved_mem; */ static int canvas_config_mode = 2; static bool work_mode_simple; -static int max_ignore_frames = 2; -static int ignore_frames; +static int phase_lock_flag; +static int max_ignore_frames[2] = {2, 1}; +/*game_mode_switch_frames:min num is 5 by 1080p60hz input test*/ +static int game_mode_switch_frames = 10; +static int game_mode_phlock_switch_frames = 60; +static int ignore_frames[2] = {0, 0}; static unsigned int dv_work_delby; + +static int tl1_vdin1_preview_ready_flag; +static unsigned int vdin_afbc_force_drop_frame = 1; +static struct vf_entry *vfe_drop_force; + +unsigned int vdin_afbc_force_drop_frame_cnt = 2; +unsigned int max_ignore_frame_cnt = 2; +unsigned int skip_frame_debug; + /* viu isr select: * enable viu_hw_irq for the bandwidth is enough on gxbb/gxtvbb and laters ic */ static bool viu_hw_irq = 1; +static bool de_fmt_flag; #ifdef DEBUG_SUPPORT module_param(canvas_config_mode, int, 0664); @@ -101,20 +125,21 @@ MODULE_PARM_DESC(canvas_config_mode, "canvas configure mode"); module_param(work_mode_simple, bool, 0664); MODULE_PARM_DESC(work_mode_simple, "enable/disable simple work mode"); -module_param(max_ignore_frames, int, 0664); -MODULE_PARM_DESC(max_ignore_frames, "ignore first frames"); - -module_param(ignore_frames, int, 0664); -MODULE_PARM_DESC(ignore_frames, "ignore first frames"); +module_param(viu_hw_irq, bool, 0664); +MODULE_PARM_DESC(viu_hw_irq, "viu_hw_irq"); module_param(dv_work_delby, uint, 0664); MODULE_PARM_DESC(dv_work_delby, "dv_work_delby"); -module_param(viu_hw_irq, bool, 0664); -MODULE_PARM_DESC(viu_hw_irq, "viu_hw_irq"); +module_param(game_mode_switch_frames, int, 0664); +MODULE_PARM_DESC(game_mode_switch_frames, "game mode switch frames"); + +module_param(game_mode_phlock_switch_frames, int, 0664); +MODULE_PARM_DESC(game_mode_phlock_switch_frames, + "game mode switch frames for phase_lock"); #endif -static bool vdin_dbg_en; +bool vdin_dbg_en; module_param(vdin_dbg_en, bool, 0664); MODULE_PARM_DESC(vdin_dbg_en, "enable/disable vdin debug information"); @@ -134,6 +159,8 @@ static unsigned int vdin_drop_cnt; module_param(vdin_drop_cnt, uint, 0664); MODULE_PARM_DESC(vdin_drop_cnt, "vdin_drop_cnt"); +struct vdin_hist_s vdin1_hist; +struct vdin_v4l2_param_s vdin_v4l2_param; static int irq_max_count; @@ -190,13 +217,18 @@ int vdin_open_fe(enum tvin_port_e port, int index, struct vdin_dev_s *devp) devp->frontend = fe; devp->parm.port = port; - /* for atv snow function */ - if ((port == TVIN_PORT_CVBS3) && - (devp->parm.info.fmt == TVIN_SIG_FMT_NULL)) - devp->parm.info.fmt = TVIN_SIG_FMT_CVBS_NTSC_M; - else - devp->parm.info.fmt = TVIN_SIG_FMT_NULL; - devp->parm.info.status = TVIN_SIG_STATUS_NULL; + /* don't change parm.info for tl1_vdin1_preview, + * for it should follow vdin0 parm.info + */ + if (tl1_vdin1_preview_flag == 0) { + /* for atv snow function */ + if ((port == TVIN_PORT_CVBS3) && + (devp->parm.info.fmt == TVIN_SIG_FMT_NULL)) + devp->parm.info.fmt = TVIN_SIG_FMT_CVBS_NTSC_M; + else + devp->parm.info.fmt = TVIN_SIG_FMT_NULL; + devp->parm.info.status = TVIN_SIG_STATUS_NULL; + } /* clear color para*/ memset(&devp->pre_prop, 0, sizeof(devp->pre_prop)); /* clear color para*/ @@ -213,8 +245,11 @@ int vdin_open_fe(enum tvin_port_e port, int index, struct vdin_dev_s *devp) if (devp->msr_clk != NULL) clk_prepare_enable(devp->msr_clk); - if (devp->frontend->dec_ops && devp->frontend->dec_ops->open) - ret = devp->frontend->dec_ops->open(devp->frontend, port); + if (tl1_vdin1_preview_flag == 0) { + if (devp->frontend->dec_ops && devp->frontend->dec_ops->open) + ret = + devp->frontend->dec_ops->open(devp->frontend, port); + } /* check open status */ if (ret) return 1; @@ -266,11 +301,30 @@ static void vdin_game_mode_check(struct vdin_dev_s *devp) (devp->parm.port != TVIN_PORT_CVBS3)) { if (devp->h_active > 720 && ((devp->parm.info.fps == 50) || (devp->parm.info.fps == 60))) - devp->game_mode = 3; + if (is_meson_tl1_cpu() || is_meson_tm2_cpu()) { + devp->game_mode = (VDIN_GAME_MODE_0 | + VDIN_GAME_MODE_1 | + VDIN_GAME_MODE_SWITCH_EN); + } else { + devp->game_mode = (VDIN_GAME_MODE_0 | + VDIN_GAME_MODE_1); + } else - devp->game_mode = 1; - } else + devp->game_mode = VDIN_GAME_MODE_0; + } else if (game_mode == 2)/*for debug force game mode*/ + devp->game_mode = (VDIN_GAME_MODE_0 | VDIN_GAME_MODE_1); + else if (game_mode == 3)/*for debug force game mode*/ + devp->game_mode = (VDIN_GAME_MODE_0 | VDIN_GAME_MODE_2); + else if (game_mode == 4)/*for debug force game mode*/ + devp->game_mode = VDIN_GAME_MODE_0; + else if (game_mode == 5)/*for debug force game mode*/ + devp->game_mode = (VDIN_GAME_MODE_0 | VDIN_GAME_MODE_1 | + VDIN_GAME_MODE_SWITCH_EN); + else devp->game_mode = 0; + + pr_info("%s: game_mode flag=%d, game_mode=%d\n", + __func__, game_mode, devp->game_mode); } /* *based on the bellow parameters: @@ -321,17 +375,24 @@ static void vdin_vf_init(struct vdin_dev_s *devp) /*if output fmt is nv21 or nv12 , * use the two continuous canvas for one field */ - if ((devp->prop.dest_cfmt == TVIN_NV12) || - (devp->prop.dest_cfmt == TVIN_NV21)) { - chromaid = + if (devp->afbce_mode == 0) { + if ((devp->prop.dest_cfmt == TVIN_NV12) || + (devp->prop.dest_cfmt == TVIN_NV21)) { + chromaid = (vdin_canvas_ids[index][(vf->index<<1)+1])<<8; - addr = - vdin_canvas_ids[index][vf->index<<1] | - chromaid; - } else - addr = vdin_canvas_ids[index][vf->index]; + addr = + vdin_canvas_ids[index][vf->index<<1] | + chromaid; + } else + addr = vdin_canvas_ids[index][vf->index]; - vf->canvas0Addr = vf->canvas1Addr = addr; + vf->canvas0Addr = vf->canvas1Addr = addr; + } else if (devp->afbce_mode == 1) { + vf->compHeadAddr = devp->afbce_info->fm_head_paddr[i]; + vf->compBodyAddr = devp->afbce_info->fm_body_paddr[i]; + vf->compWidth = devp->h_active; + vf->compHeight = devp->v_active; + } /* set source type & mode */ vdin_set_source_type(devp, vf); @@ -367,7 +428,7 @@ static void vdin_vf_init(struct vdin_dev_s *devp) } } -#ifdef CONFIG_AML_RDMA +#ifdef CONFIG_AMLOGIC_MEDIA_RDMA static void vdin_rdma_irq(void *arg) { struct vdin_dev_s *devp = arg; @@ -376,10 +437,7 @@ static void vdin_rdma_irq(void *arg) return; } -static struct rdma_op_s vdin_rdma_op = { - vdin_rdma_irq, - NULL -}; +static struct rdma_op_s vdin_rdma_op[VDIN_MAX_DEVS]; #endif /* @@ -408,10 +466,10 @@ void vdin_start_dec(struct vdin_dev_s *devp) pr_info("[vdin]%s null error.\n", __func__); return; } + if (devp->frontend && devp->frontend->sm_ops) { sm_ops = devp->frontend->sm_ops; sm_ops->get_sig_property(devp->frontend, &devp->prop); - if (!(devp->flags & VDIN_FLAG_V4L2_DEBUG)) devp->parm.info.cfmt = devp->prop.color_format; if ((devp->parm.dest_width != 0) || @@ -434,7 +492,6 @@ void vdin_start_dec(struct vdin_dev_s *devp) devp->prop.ve = devp->debug.cutwin.ve; } } - /*gxbb/gxl/gxm use clkb as vdin clk, *for clkb is low speed,wich is enough for 1080p process, *gxtvbb/txl use vpu clk for process 4k @@ -452,6 +509,21 @@ void vdin_start_dec(struct vdin_dev_s *devp) devp->canvas_config_mode = canvas_config_mode; /* h_active/v_active will be recalculated by bellow calling */ vdin_set_decimation(devp); + if (de_fmt_flag == 1 && + (devp->prop.vs != 0 || + devp->prop.ve != 0 || + devp->prop.hs != 0 || + devp->prop.he != 0)) { + devp->prop.vs = 0; + devp->prop.ve = 0; + devp->prop.hs = 0; + devp->prop.he = 0; + devp->prop.pre_vs = 0; + devp->prop.pre_ve = 0; + devp->prop.pre_hs = 0; + devp->prop.pre_he = 0; + pr_info("ioctl start dec,restore the cutwin param.\n"); + } vdin_set_cutwin(devp); vdin_set_hvscale(devp); if (cpu_after_eq(MESON_CPU_MAJOR_ID_GXTVBB)) @@ -460,11 +532,21 @@ void vdin_start_dec(struct vdin_dev_s *devp) if (get_cpu_type() >= MESON_CPU_MAJOR_ID_TXL) vdin_fix_nonstd_vsync(devp); - /*reverse / disable reverse write buffer*/ vdin_wr_reverse(devp->addr_offset, devp->parm.h_reverse, devp->parm.v_reverse); + + /* check if need enable afbce */ + if (devp->afbce_flag == 1) { + if ((devp->h_active > 1920) && (devp->v_active > 1080)) + devp->afbce_mode = 1; + else + devp->afbce_mode = 0; + pr_info("vdin%d afbce_mode: %d\n", + devp->index, devp->afbce_mode); + } + #ifdef CONFIG_CMA vdin_cma_malloc_mode(devp); if (devp->afbce_mode == 1) { @@ -481,6 +563,7 @@ void vdin_start_dec(struct vdin_dev_s *devp) } } #endif + /* h_active/v_active will be used by bellow calling */ if (devp->afbce_mode == 0) { if (canvas_config_mode == 1) @@ -491,6 +574,7 @@ void vdin_start_dec(struct vdin_dev_s *devp) vdin_afbce_maptable_init(devp); vdin_afbce_config(devp); } + #if 0 if ((devp->prop.dest_cfmt == TVIN_NV12) || (devp->prop.dest_cfmt == TVIN_NV21)) @@ -523,6 +607,7 @@ void vdin_start_dec(struct vdin_dev_s *devp) devp->abnormal_cnt = 0; devp->last_wr_vfe = NULL; irq_max_count = 0; + vdin_drop_cnt = 0; /* devp->stamp_valid = false; */ devp->stamp = 0; devp->cycle = 0; @@ -538,12 +623,10 @@ void vdin_start_dec(struct vdin_dev_s *devp) vdin_hw_enable(devp->addr_offset); vdin_set_all_regs(devp); - if (is_meson_tl1_cpu()) { - if (devp->afbce_mode == 0) - vdin_write_mif_or_afbce(devp, VDIN_OUTPUT_TO_MIF); - else if (devp->afbce_mode == 1) - vdin_write_mif_or_afbce(devp, VDIN_OUTPUT_TO_AFBCE); - } + if (devp->afbce_mode == 0) + vdin_write_mif_or_afbce(devp, VDIN_OUTPUT_TO_MIF); + else if (devp->afbce_mode == 1) + vdin_write_mif_or_afbce(devp, VDIN_OUTPUT_TO_AFBCE); if (!(devp->parm.flag & TVIN_PARM_FLAG_CAP) && (devp->frontend) && @@ -554,7 +637,7 @@ void vdin_start_dec(struct vdin_dev_s *devp) devp->frontend->dec_ops->start(devp->frontend, devp->parm.info.fmt); -#ifdef CONFIG_AML_RDMA +#ifdef CONFIG_AMLOGIC_MEDIA_RDMA /*it is better put after all reg init*/ if (devp->rdma_enable && devp->rdma_handle > 0) devp->flags |= VDIN_FLAG_RDMA_ENABLE; @@ -576,14 +659,6 @@ void vdin_start_dec(struct vdin_dev_s *devp) #endif vf_notify_receiver(devp->name, VFRAME_EVENT_PROVIDER_START, NULL); - if ((devp->parm.port != TVIN_PORT_VIU1) || - (viu_hw_irq != 0)) { - /*enable irq */ - enable_irq(devp->irq); - if (vdin_dbg_en) - pr_info("****[%s]enable_irq ifdef VDIN_V2****\n", - __func__); - } if (vdin_dbg_en) pr_info("****[%s]ok!****\n", __func__); @@ -599,10 +674,31 @@ void vdin_start_dec(struct vdin_dev_s *devp) #endif devp->irq_cnt = 0; devp->rdma_irq_cnt = 0; + devp->frame_cnt = 0; + phase_lock_flag = 0; + if (time_en) pr_info("vdin.%d start time: %ums, run time:%ums.\n", devp->index, jiffies_to_msecs(jiffies), jiffies_to_msecs(jiffies)-devp->start_time); + + if ((devp->afbce_mode == 1) && + (is_meson_tl1_cpu() || is_meson_tm2_cpu())) { + if ((devp->h_active >= 1920) && (devp->v_active >= 1080)) { + tl1_vdin1_preview_flag = 1; + tl1_vdin1_data_readied = 0; + tl1_vdin1_preview_ready_flag = 0; + pr_info("vdin.%d tl1_vdin1_preview state init\n", + devp->index); + } else { + tl1_vdin1_preview_flag = 0; + vdin_afbc_force_drop_frame = + vdin_afbc_force_drop_frame_cnt; + } + vfe_drop_force = NULL; + max_ignore_frames[devp->index] = max_ignore_frame_cnt; + vdin_afbc_force_drop_frame = vdin_afbc_force_drop_frame_cnt; + } } /* @@ -615,6 +711,9 @@ void vdin_start_dec(struct vdin_dev_s *devp) */ void vdin_stop_dec(struct vdin_dev_s *devp) { + int afbc_write_down_timeout = 500; /* 50ms to cover a 24Hz vsync */ + int i = 0; + /* avoid null pointer oops */ if (!devp || !devp->frontend) return; @@ -624,8 +723,26 @@ void vdin_stop_dec(struct vdin_dev_s *devp) return; } #endif + disable_irq_nosync(devp->irq); - vdin_hw_disable(devp->addr_offset); + afbc_init_flag[devp->index] = 0; + + if (devp->afbce_mode == 1) { + while (i++ < afbc_write_down_timeout) { + if (vdin_afbce_read_writedown_flag()) + break; + usleep_range(100, 105); + } + if (i >= afbc_write_down_timeout) { + pr_info("vdin.%d afbc write done timeout\n", + devp->index); + } + } + if (is_meson_tl1_cpu() && (tl1_vdin1_preview_flag == 1)) { + if (devp->index == 1) + tl1_vdin1_preview_flag = 0; + } + if (!(devp->parm.flag & TVIN_PARM_FLAG_CAP) && devp->frontend->dec_ops && devp->frontend->dec_ops->stop && @@ -633,6 +750,8 @@ void vdin_stop_dec(struct vdin_dev_s *devp) ((devp->flags & VDIN_FLAG_SNOW_FLAG) == 0))) devp->frontend->dec_ops->stop(devp->frontend, devp->parm.port); + vdin_hw_disable(devp->addr_offset); + vdin_set_default_regmap(devp->addr_offset); /*only for vdin0*/ if (devp->urgent_en && (devp->index == 0)) @@ -649,24 +768,32 @@ void vdin_stop_dec(struct vdin_dev_s *devp) #endif vf_unreg_provider(&devp->vprov); devp->dv.dv_config = 0; + + if (devp->afbce_mode == 1) { + vdin_afbce_hw_disable(); + vdin_afbce_soft_reset(); + } + +#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION + vdin_dolby_addr_release(devp, devp->vfp->size); +#endif + #ifdef CONFIG_CMA if (devp->afbce_mode == 1) vdin_afbce_cma_release(devp); else if (devp->afbce_mode == 0) vdin_cma_release(devp); #endif - vdin_dolby_addr_release(devp, devp->vfp->size); - - switch_vpu_mem_pd_vmod(devp->addr_offset?VPU_VIU_VDIN1:VPU_VIU_VDIN0, VPU_MEM_POWER_DOWN); memset(&devp->prop, 0, sizeof(struct tvin_sig_property_s)); -#ifdef CONFIG_AML_RDMA +#ifdef CONFIG_AMLOGIC_MEDIA_RDMA rdma_clear(devp->rdma_handle); #endif devp->flags &= (~VDIN_FLAG_RDMA_ENABLE); - ignore_frames = 0; + ignore_frames[devp->index] = 0; devp->cycle = 0; + /* clear color para*/ memset(&devp->prop, 0, sizeof(devp->prop)); if (time_en) @@ -694,6 +821,12 @@ int start_tvin_service(int no, struct vdin_parm_s *para) __func__, no); return -1; } + + if (tl1_vdin1_preview_flag == 1) { + pr_err("[vdin]%s vdin%d use for preview, return.\n", + __func__, no); + return -1; + } fmt = devp->parm.info.fmt; if (vdin_dbg_en) { pr_info("**[%s]cfmt:%d;dfmt:%d;dest_hactive:%d;", @@ -705,21 +838,24 @@ int start_tvin_service(int no, struct vdin_parm_s *para) pr_info("v_active:%d;scan_mode:%d**\n", para->v_active, para->scan_mode); } + + if (devp->index == 1) { + devp->parm.reserved |= para->reserved; + pr_info("vdin1 add reserved = 0x%lx\n", para->reserved); + pr_info("vdin1 all reserved = 0x%x\n", devp->parm.reserved); + } devp->start_time = jiffies_to_msecs(jiffies); if (devp->flags & VDIN_FLAG_DEC_STARTED) { pr_err("%s: port 0x%x, decode started already.\n", __func__, para->port); - ret = -EBUSY; - return ret; - } - if ((para->port != TVIN_PORT_VIU1) || - (viu_hw_irq != 0)) { - ret = request_irq(devp->irq, vdin_v4l2_isr, IRQF_SHARED, - devp->irq_name, (void *)devp); - devp->flags |= VDIN_FLAG_ISR_REQ; - /*disable vsync irq until vdin configured completely*/ - disable_irq_nosync(devp->irq); + if ((devp->parm.reserved & PARAM_STATE_SCREENCAP) && + (devp->parm.reserved & PARAM_STATE_HISTGRAM) && + (devp->index == 1)) + return 0; + else + return -EBUSY; } + vdin_clk_onoff(devp, true); /*config the vdin use default value*/ vdin_set_default_regmap(devp->addr_offset); @@ -801,6 +937,16 @@ int start_tvin_service(int no, struct vdin_parm_s *para) devp->flags |= VDIN_FLAG_DEC_OPENED; devp->flags |= VDIN_FLAG_DEC_STARTED; + if ((para->port != TVIN_PORT_VIU1) || + (viu_hw_irq != 0)) { + ret = request_irq(devp->irq, vdin_v4l2_isr, IRQF_SHARED, + devp->irq_name, (void *)devp); + if (ret != 0) { + pr_info("vdin_v4l2_isr request irq error.\n"); + return -1; + } + devp->flags |= VDIN_FLAG_ISR_REQ; + } return 0; } EXPORT_SYMBOL(start_tvin_service); @@ -816,6 +962,14 @@ int stop_tvin_service(int no) unsigned int end_time; devp = vdin_devp[no]; + if ((devp->parm.reserved & PARAM_STATE_HISTGRAM) && + (devp->parm.reserved & PARAM_STATE_SCREENCAP) && + (devp->index == 1)) { + pr_info("stop vdin v4l2 screencap.\n"); + devp->parm.reserved &= ~PARAM_STATE_SCREENCAP; + return 0; + } + if (!(devp->flags&VDIN_FLAG_DEC_STARTED)) { pr_err("%s:decode hasn't started.\n", __func__); return -EBUSY; @@ -1171,6 +1325,76 @@ static u64 func_div(u64 cur, u32 divid) return cur; } +static void vdin_hist_tgt(struct vdin_dev_s *devp, struct vframe_s *vf) +{ + int ave_luma; + int pix_sum; + ulong flags; + + spin_lock_irqsave(&devp->hist_lock, flags); + vdin1_hist.sum = vf->prop.hist.luma_sum; + pix_sum = vf->prop.hist.pixel_sum; + vdin1_hist.height = vf->prop.hist.height; + vdin1_hist.width = vf->prop.hist.width; + + if ((vdin1_hist.height == 0) || (vdin1_hist.width == 0)) { + spin_unlock_irqrestore(&devp->hist_lock, flags); + return; + } + + vdin1_hist.ave = + vdin1_hist.sum/(vdin1_hist.height * vdin1_hist.width); + + ave_luma = vdin1_hist.ave; + ave_luma = (ave_luma - 16) < 0 ? 0 : (ave_luma - 16); + vdin1_hist.ave = ave_luma*255/(235-16); + if (vdin1_hist.ave > 255) + vdin1_hist.ave = 255; + + spin_unlock_irqrestore(&devp->hist_lock, flags); +} + +static bool vdin_skip_frame_check(struct vdin_dev_s *devp) +{ + ulong flags = 0; + int skip_flag = 0; + + spin_lock_irqsave(&tl1_preview_lock, flags); + if (devp->afbce_mode == 0) { + spin_unlock_irqrestore(&tl1_preview_lock, flags); + return false; + } + + if (tl1_vdin1_preview_flag == 1) { + if (tl1_vdin1_preview_ready_flag == 0) { + skip_flag = 1; + } else { + if (vdin_afbc_force_drop_frame > 0) { + vdin_afbc_force_drop_frame--; + skip_flag = 1; + } + } + } else { + if (vdin_afbc_force_drop_frame > 0) { + vdin_afbc_force_drop_frame--; + skip_flag = 1; + } + } + + if (skip_flag) { + vfe_drop_force = receiver_vf_get(devp->vfp); + if (vfe_drop_force) + receiver_vf_put(&vfe_drop_force->vf, devp->vfp); + else + pr_info("vdin.%d: skip vf get error\n", devp->index); + spin_unlock_irqrestore(&tl1_preview_lock, flags); + return true; + } + + spin_unlock_irqrestore(&tl1_preview_lock, flags); + return false; +} + /* *VDIN_FLAG_RDMA_ENABLE=1 * provider_vf_put(devp->last_wr_vfe, devp->vfp); @@ -1179,7 +1403,7 @@ static u64 func_div(u64 cur, u32 divid) */ irqreturn_t vdin_isr(int irq, void *dev_id) { - ulong flags = 0; + ulong flags = 0, flags1 = 0; struct vdin_dev_s *devp = (struct vdin_dev_s *)dev_id; enum tvin_sm_status_e state; @@ -1209,6 +1433,10 @@ irqreturn_t vdin_isr(int irq, void *dev_id) if (!devp->frontend) { devp->vdin_irq_flag = 1; + if (skip_frame_debug) { + pr_info("vdin.%d: vdin_irq_flag=%d\n", + devp->index, devp->vdin_irq_flag); + } goto irq_handled; } @@ -1221,6 +1449,18 @@ irqreturn_t vdin_isr(int irq, void *dev_id) offset = devp->addr_offset; + if (devp->afbce_mode == 1) { + if (afbc_init_flag[devp->index] == 0) { + afbc_init_flag[devp->index] = 1; + /*set mem power on*/ + vdin_afbce_hw_enable(devp); + return IRQ_HANDLED; + } else if (afbc_init_flag[devp->index] == 1) { + afbc_init_flag[devp->index] = 2; + return IRQ_HANDLED; + } + } + isr_log(devp->vfp); devp->irq_cnt++; /* debug interrupt interval time @@ -1230,13 +1470,22 @@ irqreturn_t vdin_isr(int irq, void *dev_id) */ spin_lock_irqsave(&devp->isr_lock, flags); - /* W_VCBUS_BIT(VDIN_MISC_CTRL, 0, 0, 2); */ - devp->vdin_reset_flag = vdin_vsync_reset_mif(devp->index); + if (devp->afbce_mode == 1) { + /* no need reset mif under afbc mode */ + devp->vdin_reset_flag = 0; + } else { + /* W_VCBUS_BIT(VDIN_MISC_CTRL, 0, 0, 2); */ + devp->vdin_reset_flag = vdin_vsync_reset_mif(devp->index); + } if ((devp->flags & VDIN_FLAG_DEC_STOP_ISR) && (!(isr_flag & VDIN_BYPASS_STOP_CHECK))) { vdin_hw_disable(offset); devp->flags &= ~VDIN_FLAG_DEC_STOP_ISR; devp->vdin_irq_flag = 2; + if (skip_frame_debug) { + pr_info("vdin.%d: vdin_irq_flag=%d\n", + devp->index, devp->vdin_irq_flag); + } goto irq_handled; } @@ -1248,10 +1497,16 @@ irqreturn_t vdin_isr(int irq, void *dev_id) /*save the first field stamp*/ devp->stamp = stamp; devp->vdin_irq_flag = 3; + if (skip_frame_debug) { + pr_info("vdin.%d: vdin_irq_flag=%d\n", + devp->index, devp->vdin_irq_flag); + } goto irq_handled; } + /* use RDMA and not game mode */ if (devp->last_wr_vfe && (devp->flags&VDIN_FLAG_RDMA_ENABLE) && - !(devp->game_mode & (1 << 1))) { + !(devp->game_mode & VDIN_GAME_MODE_1) && + !(devp->game_mode & VDIN_GAME_MODE_2)) { /*dolby vision metadata process*/ if (dv_dbg_mask & DV_UPDATE_DATA_MODE_DELBY_WORK && devp->dv.dv_config) { @@ -1270,6 +1525,30 @@ irqreturn_t vdin_isr(int irq, void *dev_id) devp->dv.dv_crc_check = true; if ((devp->dv.dv_crc_check == true) || (!(dv_dbg_mask & DV_CRC_CHECK))) { + spin_lock_irqsave(&tl1_preview_lock, flags1); + if ((devp->index == 0) && + (tl1_vdin1_preview_flag == 1)) { + if (tl1_vdin1_data_readied == 1) { + tl1_vdin1_data_readied = 0; + devp->last_wr_vfe->vf.canvas0Addr = + tl1_vdin1_canvas_addr; + devp->last_wr_vfe->vf.height = + tl1_vdin1_height; + devp->last_wr_vfe->vf.width = + tl1_vdin1_width; + tl1_vdin1_preview_ready_flag = 1; + } else { + tl1_vdin1_preview_ready_flag = 0; + } + } else if ((devp->index == 1) && + (tl1_vdin1_preview_flag == 1)) { + tl1_vdin1_canvas_addr = + devp->last_wr_vfe->vf.canvas0Addr; + tl1_vdin1_height = devp->last_wr_vfe->vf.height; + tl1_vdin1_width = devp->last_wr_vfe->vf.width; + tl1_vdin1_data_readied = 1; + } + spin_unlock_irqrestore(&tl1_preview_lock, flags1); provider_vf_put(devp->last_wr_vfe, devp->vfp); if (time_en) { devp->last_wr_vfe->vf.ready_clock[1] = @@ -1281,6 +1560,10 @@ irqreturn_t vdin_isr(int irq, void *dev_id) } } else { devp->vdin_irq_flag = 15; + if (skip_frame_debug) { + pr_info("vdin.%d: vdin_irq_flag=%d\n", + devp->index, devp->vdin_irq_flag); + } vdin_drop_cnt++; goto irq_handled; } @@ -1289,21 +1572,45 @@ irqreturn_t vdin_isr(int irq, void *dev_id) vdin_vf_disp_mode_update(devp->last_wr_vfe, devp->vfp); devp->last_wr_vfe = NULL; + if ((devp->index == 1) && (tl1_vdin1_preview_flag == 1)) { + //if (vdin_dbg_en) + //pr_info("vdin1 preview dont notify receiver.\n"); + } else { #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION - if (((devp->dv.dolby_input & (1 << devp->index)) || - (devp->dv.dv_flag && is_dolby_vision_enable())) && - (devp->dv.dv_config == true)) - vf_notify_receiver("dv_vdin", - VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); - else + if (((devp->dv.dolby_input & (1 << devp->index)) || + (devp->dv.dv_flag && is_dolby_vision_enable())) + && (devp->dv.dv_config == true)) + vf_notify_receiver("dv_vdin", + VFRAME_EVENT_PROVIDER_VFRAME_READY, + NULL); + else { #endif - vf_notify_receiver(devp->name, - VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); + if (vdin_skip_frame_check(devp)) { + devp->vdin_irq_flag = 16; + if (skip_frame_debug) { + pr_info("vdin.%d: vdin_irq_flag=%d\n", + devp->index, + devp->vdin_irq_flag); + } + vdin_drop_cnt++; + } else { + vf_notify_receiver(devp->name, + VFRAME_EVENT_PROVIDER_VFRAME_READY, + NULL); + } +#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION + } +#endif + } } /*check vs is valid base on the time during continuous vs*/ if (vdin_check_cycle(devp) && (!(isr_flag & VDIN_BYPASS_CYC_CHECK)) && (!(devp->flags & VDIN_FLAG_SNOW_FLAG))) { devp->vdin_irq_flag = 4; + if (skip_frame_debug) { + pr_info("vdin.%d: vdin_irq_flag=%d\n", + devp->index, devp->vdin_irq_flag); + } vdin_drop_cnt++; goto irq_handled; } @@ -1329,6 +1636,10 @@ irqreturn_t vdin_isr(int irq, void *dev_id) (state != TVIN_SM_STATUS_STABLE)) && (!(devp->flags & VDIN_FLAG_SNOW_FLAG))) { devp->vdin_irq_flag = 6; + if (skip_frame_debug) { + pr_info("vdin.%d: vdin_irq_flag=%d\n", + devp->index, devp->vdin_irq_flag); + } vdin_drop_cnt++; goto irq_handled; } @@ -1343,6 +1654,10 @@ irqreturn_t vdin_isr(int irq, void *dev_id) VIDTYPE_INTERLACE_BOTTOM) ) { devp->vdin_irq_flag = 7; + if (skip_frame_debug) { + pr_info("vdin.%d: vdin_irq_flag=%d\n", + devp->index, devp->vdin_irq_flag); + } vdin_drop_cnt++; goto irq_handled; } @@ -1355,8 +1670,13 @@ irqreturn_t vdin_isr(int irq, void *dev_id) pre_prop = &devp->pre_prop; if ((prop->color_format != pre_prop->color_format) || (prop->vdin_hdr_Flag != pre_prop->vdin_hdr_Flag) || - (prop->color_fmt_range != pre_prop->color_fmt_range)) + (prop->color_fmt_range != pre_prop->color_fmt_range)) { vdin_set_matrix(devp); + if (skip_frame_debug) { + pr_info("vdin.%d color_format changed\n", + devp->index); + } + } if (prop->dest_cfmt != pre_prop->dest_cfmt) { vdin_set_bitdepth(devp); vdin_source_bitdepth_reinit(devp); @@ -1367,12 +1687,24 @@ irqreturn_t vdin_isr(int irq, void *dev_id) vdin_set_top(devp->addr_offset, devp->parm.port, devp->prop.color_format, devp->h_active, devp->bt_path); + if (devp->afbce_mode) + vdin_afbce_update(devp); + if (skip_frame_debug) { + pr_info("vdin.%d dest_cfmt changed: %d->%d\n", + devp->index, + pre_prop->dest_cfmt, prop->dest_cfmt); + } } pre_prop->color_format = prop->color_format; pre_prop->vdin_hdr_Flag = prop->vdin_hdr_Flag; pre_prop->color_fmt_range = prop->color_fmt_range; pre_prop->dest_cfmt = prop->dest_cfmt; - ignore_frames = 0; + ignore_frames[devp->index] = 0; + devp->vdin_irq_flag = 20; + if (skip_frame_debug) { + pr_info("vdin.%d: vdin_irq_flag=%d\n", + devp->index, devp->vdin_irq_flag); + } vdin_drop_cnt++; goto irq_handled; } @@ -1398,6 +1730,10 @@ irqreturn_t vdin_isr(int irq, void *dev_id) decops = devp->frontend->dec_ops; if (decops->decode_isr(devp->frontend, devp->hcnt64) == TVIN_BUF_SKIP) { devp->vdin_irq_flag = 8; + if (skip_frame_debug) { + pr_info("vdin.%d: vdin_irq_flag=%d\n", + devp->index, devp->vdin_irq_flag); + } vdin_drop_cnt++; goto irq_handled; } @@ -1406,10 +1742,13 @@ irqreturn_t vdin_isr(int irq, void *dev_id) curr_wr_vf->phase = sm_ops->get_secam_phase(devp->frontend) ? VFRAME_PHASE_DB : VFRAME_PHASE_DR; - - if (ignore_frames < max_ignore_frames) { - ignore_frames++; + if (ignore_frames[devp->index] < max_ignore_frames[devp->index]) { devp->vdin_irq_flag = 12; + if (skip_frame_debug) { + pr_info("vdin.%d: vdin_irq_flag=%d\n", + devp->index, devp->vdin_irq_flag); + } + ignore_frames[devp->index]++; vdin_drop_cnt++; goto irq_handled; } @@ -1417,34 +1756,57 @@ irqreturn_t vdin_isr(int irq, void *dev_id) if (sm_ops->check_frame_skip && sm_ops->check_frame_skip(devp->frontend)) { devp->vdin_irq_flag = 13; + if (skip_frame_debug) { + pr_info("vdin.%d: vdin_irq_flag=%d\n", + devp->index, devp->vdin_irq_flag); + } vdin_drop_cnt++; if (devp->flags&VDIN_FLAG_RDMA_ENABLE) - ignore_frames = 0; + ignore_frames[devp->index] = 0; goto irq_handled; } next_wr_vfe = provider_vf_peek(devp->vfp); if (!next_wr_vfe) { - devp->vdin_irq_flag = 14; - vdin_drop_cnt++; - vf_drop_cnt = vdin_drop_cnt;/*avoid do skip*/ - goto irq_handled; + /*add for force vdin buffer recycle*/ + if (devp->flags & VDIN_FLAG_FORCE_RECYCLE) { + next_wr_vfe = receiver_vf_get(devp->vfp); + if (next_wr_vfe) + receiver_vf_put(&next_wr_vfe->vf, devp->vfp); + else + pr_err("[vdin.%d]force recycle error,no buffer in ready list", + devp->index); + } else { + devp->vdin_irq_flag = 14; + if (skip_frame_debug) { + pr_info("vdin.%d: vdin_irq_flag=%d\n", + devp->index, devp->vdin_irq_flag); + } + vdin_drop_cnt++; + vf_drop_cnt = vdin_drop_cnt;/*avoid do skip*/ + goto irq_handled; + } } + + if ((devp->index == 1) && (tl1_vdin1_preview_flag == 1)) { + //if (vdin_dbg_en) + //pr_info("vdin1 preview dont notify receiver.\n"); + } else { #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION - if (((devp->dv.dolby_input & (1 << devp->index)) || - (devp->dv.dv_flag && is_dolby_vision_enable())) && - (devp->dv.dv_config == true)) - vdin2nr = vf_notify_receiver("dv_vdin", - VFRAME_EVENT_PROVIDER_QUREY_VDIN2NR, NULL); - else + if (((devp->dv.dolby_input & (1 << devp->index)) || + (devp->dv.dv_flag && is_dolby_vision_enable())) && + (devp->dv.dv_config == true)) + vdin2nr = vf_notify_receiver("dv_vdin", + VFRAME_EVENT_PROVIDER_QUREY_VDIN2NR, NULL); + else #endif - vdin2nr = vf_notify_receiver(devp->name, - VFRAME_EVENT_PROVIDER_QUREY_VDIN2NR, NULL); + vdin2nr = vf_notify_receiver(devp->name, + VFRAME_EVENT_PROVIDER_QUREY_VDIN2NR, NULL); + } /*if vdin-nr,di must get * vdin current field type which di pre will read */ - if ((vdin2nr || (devp->flags & VDIN_FLAG_RDMA_ENABLE)) && - !(devp->game_mode & (1 << 1))) + if (vdin2nr || (devp->flags & VDIN_FLAG_RDMA_ENABLE)) curr_wr_vf->type = devp->curr_field_type; else curr_wr_vf->type = last_field_type; @@ -1500,9 +1862,9 @@ irqreturn_t vdin_isr(int irq, void *dev_id) (devp->parm.port <= TVIN_PORT_CVBS3)) vdin_set_display_ratio(devp, curr_wr_vf); if ((devp->flags&VDIN_FLAG_RDMA_ENABLE) && - !(devp->game_mode & (1 << 1))) { + !(devp->game_mode & VDIN_GAME_MODE_1)) { devp->last_wr_vfe = curr_wr_vfe; - } else { + } else if (!(devp->game_mode & VDIN_GAME_MODE_2)) { /*dolby vision metadata process*/ if (dv_dbg_mask & DV_UPDATE_DATA_MODE_DELBY_WORK && devp->dv.dv_config) { @@ -1517,8 +1879,35 @@ irqreturn_t vdin_isr(int irq, void *dev_id) vdin_dolby_addr_update(devp, next_wr_vfe->vf.index); } else devp->dv.dv_crc_check = true; + if ((devp->dv.dv_crc_check == true) || (!(dv_dbg_mask & DV_CRC_CHECK))) { + spin_lock_irqsave(&tl1_preview_lock, flags1); + if ((devp->index == 0) && + (tl1_vdin1_preview_flag == 1)) { + if (tl1_vdin1_data_readied == 1) { + tl1_vdin1_data_readied = 0; + curr_wr_vfe->vf.canvas0Addr = + tl1_vdin1_canvas_addr; + curr_wr_vfe->vf.height = + tl1_vdin1_height; + curr_wr_vfe->vf.width = + tl1_vdin1_width; + tl1_vdin1_preview_ready_flag = 1; + } else { + tl1_vdin1_preview_ready_flag = 0; + } + } else if ((devp->index == 1) && + (tl1_vdin1_preview_flag == 1)) { + tl1_vdin1_canvas_addr = + curr_wr_vfe->vf.canvas0Addr; + tl1_vdin1_height = + curr_wr_vfe->vf.height; + tl1_vdin1_width = + curr_wr_vfe->vf.width; + tl1_vdin1_data_readied = 1; + } + spin_unlock_irqrestore(&tl1_preview_lock, flags1); provider_vf_put(curr_wr_vfe, devp->vfp); if (vdin_dbg_en) { curr_wr_vfe->vf.ready_clock[1] = sched_clock(); @@ -1529,6 +1918,10 @@ irqreturn_t vdin_isr(int irq, void *dev_id) } } else { devp->vdin_irq_flag = 15; + if (skip_frame_debug) { + pr_info("vdin.%d: vdin_irq_flag=%d\n", + devp->index, devp->vdin_irq_flag); + } vdin_drop_cnt++; goto irq_handled; } @@ -1536,21 +1929,63 @@ irqreturn_t vdin_isr(int irq, void *dev_id) if (devp->vfp->skip_vf_num > 0) vdin_vf_disp_mode_update(curr_wr_vfe, devp->vfp); } + /*switch to game mode 2 from game mode 1,otherwise may appear blink*/ + if (is_meson_tl1_cpu() || is_meson_tm2_cpu()) { + if (devp->game_mode & VDIN_GAME_MODE_SWITCH_EN) { + /* make sure phase lock for next few frames */ + if (vlock_get_phlock_flag()) + phase_lock_flag++; + if (phase_lock_flag >= game_mode_phlock_switch_frames) { + if (vdin_dbg_en) { + pr_info("switch game mode (%d-->5), frame_cnt=%d\n", + devp->game_mode, + devp->frame_cnt); + } + devp->game_mode = (VDIN_GAME_MODE_0 | + VDIN_GAME_MODE_2); + } + } +#if 0 + if (phase_lock_flag >= game_mode_phlock_switch_frames) { + if (!vlock_get_phlock_flag()) + phase_lock_flag = 0; + if (vdin_dbg_en) { + pr_info( + "switch game mode to %d, frame_cnt=%d\n", + devp->game_mode, devp->frame_cnt); + } + devp->game_mode = (VDIN_GAME_MODE_0 | VDIN_GAME_MODE_1 | + VDIN_GAME_MODE_SWITCH_EN); + } +#endif + } else { + if ((devp->frame_cnt >= game_mode_switch_frames) && + (devp->game_mode & VDIN_GAME_MODE_SWITCH_EN)) { + if (vdin_dbg_en) { + pr_info( + "switch game mode (%d-->5), frame_cnt=%d\n", + devp->game_mode, devp->frame_cnt); + } + devp->game_mode = (VDIN_GAME_MODE_0 | VDIN_GAME_MODE_2); + } + } + /* prepare for next input data */ next_wr_vfe = provider_vf_get(devp->vfp); - if (devp->afbce_mode == 0) + if (devp->afbce_mode == 0) { vdin_set_canvas_id(devp, (devp->flags&VDIN_FLAG_RDMA_ENABLE), (next_wr_vfe->vf.canvas0Addr&0xff)); - else if (devp->afbce_mode == 1) + + /* prepare for chroma canvas*/ + if ((devp->prop.dest_cfmt == TVIN_NV12) || + (devp->prop.dest_cfmt == TVIN_NV21)) + vdin_set_chma_canvas_id(devp, + (devp->flags&VDIN_FLAG_RDMA_ENABLE), + (next_wr_vfe->vf.canvas0Addr>>8)&0xff); + } else if (devp->afbce_mode == 1) { vdin_afbce_set_next_frame(devp, (devp->flags&VDIN_FLAG_RDMA_ENABLE), next_wr_vfe); - - /* prepare for chroma canvas*/ - if ((devp->prop.dest_cfmt == TVIN_NV12) || - (devp->prop.dest_cfmt == TVIN_NV21)) - vdin_set_chma_canvas_id(devp, - (devp->flags&VDIN_FLAG_RDMA_ENABLE), - (next_wr_vfe->vf.canvas0Addr>>8)&0xff); + } devp->curr_wr_vfe = next_wr_vfe; /* debug for video latency */ @@ -1558,27 +1993,105 @@ irqreturn_t vdin_isr(int irq, void *dev_id) next_wr_vfe->vf.ready_clock[0] = sched_clock(); if (!(devp->flags&VDIN_FLAG_RDMA_ENABLE) || - (devp->game_mode & (1 << 1))) { + (devp->game_mode & VDIN_GAME_MODE_1)) { + /* not RDMA, or game mode 1 */ + if ((devp->index == 1) && (tl1_vdin1_preview_flag == 1)) { + //if (vdin_dbg_en) + //pr_info("vdin1 preview dont notify receiver.\n"); + } else { #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION - if (((devp->dv.dolby_input & (1 << devp->index)) || - (devp->dv.dv_flag && is_dolby_vision_enable())) && - (devp->dv.dv_config == true)) - vf_notify_receiver("dv_vdin", - VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); - else + if (((devp->dv.dolby_input & (1 << devp->index)) || + (devp->dv.dv_flag && is_dolby_vision_enable())) + && (devp->dv.dv_config == true)) + vf_notify_receiver("dv_vdin", + VFRAME_EVENT_PROVIDER_VFRAME_READY, + NULL); + else { #endif - vf_notify_receiver(devp->name, - VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); + if (vdin_skip_frame_check(devp)) { + devp->vdin_irq_flag = 17; + if (skip_frame_debug) { + pr_info("vdin.%d: vdin_irq_flag=%d\n", + devp->index, + devp->vdin_irq_flag); + } + vdin_drop_cnt++; + } else { + vf_notify_receiver(devp->name, + VFRAME_EVENT_PROVIDER_VFRAME_READY, + NULL); + } +#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION + } +#endif + } + } else if (devp->game_mode & VDIN_GAME_MODE_2) { + /* game mode 2 */ + spin_lock_irqsave(&tl1_preview_lock, flags1); + if ((devp->index == 0) && + (tl1_vdin1_preview_flag == 1)) { + if (tl1_vdin1_data_readied == 1) { + tl1_vdin1_data_readied = 0; + next_wr_vfe->vf.canvas0Addr = + tl1_vdin1_canvas_addr; + next_wr_vfe->vf.height = + tl1_vdin1_height; + next_wr_vfe->vf.width = + tl1_vdin1_width; + tl1_vdin1_preview_ready_flag = 1; + } else { + tl1_vdin1_preview_ready_flag = 0; + } + } else if ((devp->index == 1) && + (tl1_vdin1_preview_flag == 1)) { + tl1_vdin1_canvas_addr = + next_wr_vfe->vf.canvas0Addr; + tl1_vdin1_height = + next_wr_vfe->vf.height; + tl1_vdin1_width = + next_wr_vfe->vf.width; + tl1_vdin1_data_readied = 1; + } + spin_unlock_irqrestore(&tl1_preview_lock, flags1); + provider_vf_put(next_wr_vfe, devp->vfp); + if ((devp->index == 1) && (tl1_vdin1_preview_flag == 1)) { + //if (vdin_dbg_en) + //pr_info("vdin1 preview dont notify receiver.\n"); + } else { + if (vdin_skip_frame_check(devp)) { + devp->vdin_irq_flag = 18; + if (skip_frame_debug) { + pr_info("vdin.%d: vdin_irq_flag=%d\n", + devp->index, + devp->vdin_irq_flag); + } + vdin_drop_cnt++; + } else { + vf_notify_receiver(devp->name, + VFRAME_EVENT_PROVIDER_VFRAME_READY, + NULL); + if (vdin_dbg_en) { + next_wr_vfe->vf.ready_clock[1] = + sched_clock(); + pr_info("vdin put latency %lld us.first %lld us\n", + func_div(next_wr_vfe->vf.ready_clock[1], + 1000), + func_div(next_wr_vfe->vf.ready_clock[0], + 1000)); + } + } + } } + devp->frame_cnt++; irq_handled: - /*hdmi skip policy should adapt to all drop vframe case*/ + /*hdmi skip policy should adapt to all drop front vframe case*/ if ((devp->vfp->skip_vf_num > 0) && (vf_drop_cnt < vdin_drop_cnt)) vdin_vf_disp_mode_skip(devp->vfp); spin_unlock_irqrestore(&devp->isr_lock, flags); -#ifdef CONFIG_AML_RDMA +#ifdef CONFIG_AMLOGIC_MEDIA_RDMA if (devp->flags & VDIN_FLAG_RDMA_ENABLE) rdma_config(devp->rdma_handle, (devp->rdma_enable&1) ? @@ -1680,6 +2193,7 @@ irqreturn_t vdin_v4l2_isr(int irq, void *dev_id) vdin_set_vframe_prop_info(curr_wr_vf, devp); vdin_backup_histgram(curr_wr_vf, devp); + vdin_hist_tgt(devp, curr_wr_vf); if (devp->frontend && devp->frontend->dec_ops) { decops = devp->frontend->dec_ops; @@ -1735,18 +2249,19 @@ irqreturn_t vdin_v4l2_isr(int irq, void *dev_id) /* prepare for next input data */ next_wr_vfe = provider_vf_get(devp->vfp); - if (devp->afbce_mode == 0) + if (devp->afbce_mode == 0) { vdin_set_canvas_id(devp, (devp->flags&VDIN_FLAG_RDMA_ENABLE), (next_wr_vfe->vf.canvas0Addr&0xff)); - else if (devp->afbce_mode == 1) - vdin_afbce_set_next_frame(devp, - (devp->flags&VDIN_FLAG_RDMA_ENABLE), next_wr_vfe); if ((devp->prop.dest_cfmt == TVIN_NV12) || (devp->prop.dest_cfmt == TVIN_NV21)) vdin_set_chma_canvas_id(devp, (devp->flags&VDIN_FLAG_RDMA_ENABLE), (next_wr_vfe->vf.canvas0Addr>>8)&0xff); + } else if (devp->afbce_mode == 1) { + vdin_afbce_set_next_frame(devp, + (devp->flags&VDIN_FLAG_RDMA_ENABLE), next_wr_vfe); + } devp->curr_wr_vfe = next_wr_vfe; vf_notify_receiver(devp->name, VFRAME_EVENT_PROVIDER_VFRAME_READY, @@ -1754,7 +2269,7 @@ irqreturn_t vdin_v4l2_isr(int irq, void *dev_id) irq_handled: spin_unlock_irqrestore(&devp->isr_lock, flags); -#ifdef CONFIG_AML_RDMA +#ifdef CONFIG_AMLOGIC_MEDIA_RDMA if (devp->flags & VDIN_FLAG_RDMA_ENABLE) rdma_config(devp->rdma_handle, (devp->rdma_enable&1) ? @@ -1823,6 +2338,9 @@ static int vdin_open(struct inode *inode, struct file *file) return 0; } + if ((is_meson_tl1_cpu() || is_meson_tm2_cpu())) + switch_vpu_mem_pd_vmod(VPU_AFBCE, VPU_MEM_POWER_ON); + devp->flags |= VDIN_FLAG_FS_OPENED; /* request irq */ @@ -1860,6 +2378,7 @@ static int vdin_open(struct inode *inode, struct file *file) static int vdin_release(struct inode *inode, struct file *file) { struct vdin_dev_s *devp = file->private_data; + struct vdin_dev_s *devp_vdin1 = vdin_devp[1]; if (!(devp->flags & VDIN_FLAG_FS_OPENED)) { if (vdin_dbg_en) @@ -1868,6 +2387,9 @@ static int vdin_release(struct inode *inode, struct file *file) return 0; } + if ((is_meson_tl1_cpu() || is_meson_tm2_cpu())) + switch_vpu_mem_pd_vmod(VPU_AFBCE, VPU_MEM_POWER_DOWN); + devp->flags &= (~VDIN_FLAG_FS_OPENED); if (devp->flags & VDIN_FLAG_DEC_STARTED) { devp->flags |= VDIN_FLAG_DEC_STOP_ISR; @@ -1890,6 +2412,28 @@ static int vdin_release(struct inode *inode, struct file *file) file->private_data = NULL; + if (tl1_vdin1_preview_flag == 1) { + tl1_vdin1_preview_flag = 0; + devp_vdin1->flags &= (~VDIN_FLAG_FS_OPENED); + if (devp_vdin1->flags & VDIN_FLAG_DEC_STARTED) { + devp_vdin1->flags |= VDIN_FLAG_DEC_STOP_ISR; + vdin_stop_dec(devp_vdin1); + /* init flag */ + devp_vdin1->flags &= ~VDIN_FLAG_DEC_STOP_ISR; + /* clear the flag of decode started */ + devp_vdin1->flags &= (~VDIN_FLAG_DEC_STARTED); + } + if (devp_vdin1->flags & VDIN_FLAG_DEC_OPENED) { + vdin_close_fe(devp_vdin1); + devp_vdin1->flags &= (~VDIN_FLAG_DEC_OPENED); + } + devp_vdin1->flags &= (~VDIN_FLAG_SNOW_FLAG); + + /* free irq */ + if (devp_vdin1->flags & VDIN_FLAG_ISR_REQ) + free_irq(devp_vdin1->irq, (void *)devp_vdin1); + devp_vdin1->flags &= (~VDIN_FLAG_ISR_REQ); + } /* reset the hardware limit to vertical [0-1079] */ /* WRITE_VCBUS_REG(VPP_PREBLEND_VD1_V_START_END, 0x00000437); */ /*if (vdin_dbg_en)*/ @@ -1914,7 +2458,11 @@ static long vdin_ioctl(struct file *file, unsigned int cmd, unsigned long arg) long ret = 0; int callmaster_status = 0; struct vdin_dev_s *devp = NULL; + struct vdin_dev_s *devp_vdin1 = NULL; void __user *argp = (void __user *)arg; + struct vdin_parm_s param; + ulong flags; + struct vdin_hist_s vdin1_hist_temp; /* Get the per-device structure that contains this cdev */ devp = file->private_data; @@ -1995,11 +2543,14 @@ static long vdin_ioctl(struct file *file, unsigned int cmd, unsigned long arg) break; } if ((devp->parm.info.fmt == TVIN_SIG_FMT_NULL) && - (devp->parm.port == TVIN_PORT_CVBS3)) + (devp->parm.port == TVIN_PORT_CVBS3)) { + de_fmt_flag = 1; fmt = devp->parm.info.fmt = TVIN_SIG_FMT_CVBS_NTSC_M; - else + } else { + de_fmt_flag = 0; fmt = devp->parm.info.fmt = parm.info.fmt; - devp->fmt_info_p = + } + devp->fmt_info_p = (struct tvin_format_s *)tvin_get_fmt_info(fmt); if (!devp->fmt_info_p) { pr_err("TVIN_IOC_START_DEC(%d) error, fmt is null\n", @@ -2009,11 +2560,86 @@ static long vdin_ioctl(struct file *file, unsigned int cmd, unsigned long arg) break; } vdin_start_dec(devp); + + if ((devp->parm.port != TVIN_PORT_VIU1) || + (viu_hw_irq != 0)) { + /*enable irq */ + enable_irq(devp->irq); + if (vdin_dbg_en) + pr_info("****[%s]enable_irq ifdef VDIN_V2****\n", + __func__); + } + devp->flags |= VDIN_FLAG_DEC_STARTED; if (vdin_dbg_en) pr_info("TVIN_IOC_START_DEC port %s, decode started ok\n\n", tvin_port_str(devp->parm.port)); mutex_unlock(&devp->fe_lock); + + devp_vdin1 = vdin_devp[1]; + mutex_lock(&devp_vdin1->fe_lock); + if ((tl1_vdin1_preview_flag == 1) && + !(devp_vdin1->flags & VDIN_FLAG_DEC_STARTED)) { + /*msleep(150);*/ + devp_vdin1->flags |= VDIN_FLAG_FS_OPENED; + + devp_vdin1->unstable_flag = false; + devp_vdin1->parm.info.fmt = fmt; + devp_vdin1->parm.port = devp->parm.port; + devp_vdin1->parm.info.status = TVIN_SIG_STATUS_STABLE; + devp_vdin1->fmt_info_p = (struct tvin_format_s *) + tvin_get_fmt_info(fmt); + + if (!(devp_vdin1->flags & VDIN_FLAG_DEC_OPENED)) { + /*init queue*/ + init_waitqueue_head(&devp_vdin1->queue); + + ret = vdin_open_fe(devp_vdin1->parm.port, + 0, devp_vdin1); + if (ret) { + pr_err("TVIN_IOC_OPEN(%d) failed to open port 0x%x\n", + devp_vdin1->index, + devp_vdin1->parm.port); + ret = -EFAULT; + mutex_unlock(&devp_vdin1->fe_lock); + break; + } + } + + devp_vdin1->flags |= VDIN_FLAG_DEC_OPENED; + devp_vdin1->flags |= VDIN_FLAG_FORCE_RECYCLE; + + devp_vdin1->debug.scaler4w = 1280; + devp_vdin1->debug.scaler4h = 720; + /* vdin1 follow vdin0 afbc dest_cfmt */ + devp_vdin1->debug.dest_cfmt = devp->prop.dest_cfmt; + devp_vdin1->flags |= VDIN_FLAG_MANUAL_CONVERSION; + + vdin_start_dec(devp_vdin1); + devp_vdin1->flags |= VDIN_FLAG_DEC_STARTED; + + if (!(devp_vdin1->flags & VDIN_FLAG_ISR_REQ)) { + ret = request_irq(devp_vdin1->irq, vdin_isr, + IRQF_SHARED, + devp_vdin1->irq_name, + (void *)devp_vdin1); + if (ret != 0) { + pr_info("tl1_vdin1_preview request irq error.\n"); + mutex_unlock(&devp_vdin1->fe_lock); + break; + } + devp_vdin1->flags |= VDIN_FLAG_ISR_REQ; + } else { + enable_irq(devp_vdin1->irq); + if (vdin_dbg_en) + pr_info("****[%s]enable_vdin1_irq****\n", + __func__); + } + + pr_info("TVIN_IOC_START_DEC port %s, vdin1 used for preview\n", + tvin_port_str(devp_vdin1->parm.port)); + } + mutex_unlock(&devp_vdin1->fe_lock); break; } case TVIN_IOC_STOP_DEC: { @@ -2040,6 +2666,30 @@ static long vdin_ioctl(struct file *file, unsigned int cmd, unsigned long arg) if (vdin_dbg_en) pr_info("TVIN_IOC_STOP_DEC(%d) port %s, decode stop ok\n\n", parm->index, tvin_port_str(parm->port)); + + if (tl1_vdin1_preview_flag == 1) { + devp_vdin1 = vdin_devp[1]; + msleep(20); + if (!(devp_vdin1->flags & VDIN_FLAG_DEC_STARTED)) { + pr_err("TVIN_IOC_STOP_DEC(%d) decode havn't started\n", + devp_vdin1->index); + ret = -EPERM; + mutex_unlock(&devp->fe_lock); + break; + } + devp_vdin1->flags |= VDIN_FLAG_DEC_STOP_ISR; + vdin_stop_dec(devp_vdin1); + /* init flag */ + devp_vdin1->flags &= ~VDIN_FLAG_DEC_STOP_ISR; + /* devp->flags &= ~VDIN_FLAG_FORCE_UNSTABLE; */ + /* clear the flag of decode started */ + devp_vdin1->flags &= (~VDIN_FLAG_DEC_STARTED); + if (vdin_dbg_en) + pr_info("vdin1 TVIN_IOC_STOP_DEC(%d) port %s stop ok\n\n", + parm->index, + tvin_port_str(parm->port)); + } + mutex_unlock(&devp->fe_lock); reset_tvin_smr(parm->index); break; @@ -2090,6 +2740,25 @@ static long vdin_ioctl(struct file *file, unsigned int cmd, unsigned long arg) pr_info("TVIN_IOC_CLOSE(%d) port %s closed ok\n\n", parm->index, tvin_port_str(port)); + + if (tl1_vdin1_preview_flag == 1) { + msleep(20); + devp_vdin1 = vdin_devp[1]; + tl1_vdin1_preview_flag = 0; + if (!(devp_vdin1->flags & VDIN_FLAG_DEC_OPENED)) { + pr_err("TVIN_IOC_CLOSE(%d) you have not opened port\n", + devp_vdin1->index); + ret = -EPERM; + mutex_unlock(&devp->fe_lock); + break; + } + vdin_close_fe(devp_vdin1); + devp_vdin1->flags &= (~VDIN_FLAG_DEC_OPENED); + if (vdin_dbg_en) + pr_info("vdin1 TVIN_IOC_CLOSE(%d) port %s closed ok\n\n", + parm->index, + tvin_port_str(port)); + } mutex_unlock(&devp->fe_lock); break; } @@ -2132,6 +2801,28 @@ static long vdin_ioctl(struct file *file, unsigned int cmd, unsigned long arg) mutex_unlock(&devp->fe_lock); break; } + case TVIN_IOC_G_FRONTEND_INFO: { + struct tvin_frontend_info_s info; + + if ((!devp) || (!devp->fmt_info_p) || (!devp->curr_wr_vfe)) { + ret = -EFAULT; + break; + } + + memset(&info, 0, sizeof(struct tvin_frontend_info_s)); + mutex_lock(&devp->fe_lock); + info.cfmt = devp->parm.info.cfmt; + info.fps = devp->parm.info.fps; + info.colordepth = devp->prop.colordepth; + info.scan_mode = devp->fmt_info_p->scan_mode; + info.height = devp->curr_wr_vfe->vf.height; + info.width = devp->curr_wr_vfe->vf.width; + if (copy_to_user(argp, &info, + sizeof(struct tvin_frontend_info_s))) + ret = -EFAULT; + mutex_unlock(&devp->fe_lock); + break; + } case TVIN_IOC_G_BUF_INFO: { struct tvin_buf_info_s buf_info; memset(&buf_info, 0, sizeof(buf_info)); @@ -2285,6 +2976,104 @@ static long vdin_ioctl(struct file *file, unsigned int cmd, unsigned long arg) devp->auto_ratio_en); } break; + case TVIN_IOC_GET_LATENCY_MODE: + mutex_unlock(&devp->fe_lock); + if (copy_to_user(argp, + &(devp->prop.latency), + sizeof(struct tvin_latency_s))) { + mutex_unlock(&devp->fe_lock); + ret = -EFAULT; + pr_info("TVIN_IOC_GET_ALLM_MODE err\n\n"); + break; + } + pr_info("allm mode-%d,IT=%d,CN=%d\n\n", + devp->prop.latency.allm_mode, + devp->prop.latency.it_content, + devp->prop.latency.cn_type); + mutex_unlock(&devp->fe_lock); + break; + case TVIN_IOC_G_VDIN_HIST: + if (devp->index == 0) { + pr_info("TVIN_IOC_G_VDIN_HIST cann't be used at vdin0\n"); + break; + } + + spin_lock_irqsave(&devp->hist_lock, flags); + vdin1_hist_temp.sum = vdin1_hist.sum; + vdin1_hist_temp.width = vdin1_hist.width; + vdin1_hist_temp.height = vdin1_hist.height; + vdin1_hist_temp.ave = vdin1_hist.ave; + spin_unlock_irqrestore(&devp->hist_lock, flags); + if (vdin_dbg_en) { + if (pr_times++ > 10) { + pr_times = 0; + pr_info("-:h=%d,w=%d,a=%d\n", + vdin1_hist_temp.height, + vdin1_hist_temp.width, + vdin1_hist_temp.ave); + } + } + + if ((vdin1_hist.height == 0) || (vdin1_hist.width == 0)) + ret = -EFAULT; + else if (copy_to_user(argp, + &vdin1_hist_temp, + sizeof(struct vdin_hist_s))) { + pr_info("vdin1_hist copy fail\n"); + ret = -EFAULT; + } + break; + case TVIN_IOC_S_VDIN_V4L2START: + if (devp->index == 0) { + pr_info("TVIN_IOC_S_VDIN_V4L2START cann't be used at vdin0\n"); + break; + } + if (devp->flags & VDIN_FLAG_ISR_REQ) + free_irq(devp->irq, (void *)devp); + + if (copy_from_user(&vdin_v4l2_param, argp, + sizeof(struct vdin_v4l2_param_s))) { + pr_info("vdin_v4l2_param copy fail\n"); + return -EFAULT; + } + memset(¶m, 0, sizeof(struct vdin_parm_s)); + if (is_meson_tl1_cpu() || is_meson_sm1_cpu() || + is_meson_tm2_cpu()) + param.port = TVIN_PORT_VIU1_WB0_VPP; + else + param.port = TVIN_PORT_VIU1; + param.reserved |= PARAM_STATE_HISTGRAM; + param.h_active = vdin_v4l2_param.width; + param.v_active = vdin_v4l2_param.height; + /* use 1280X720 for histgram*/ + if ((vdin_v4l2_param.width > 1280) && + (vdin_v4l2_param.height > 720)) { + devp->debug.scaler4w = 1280; + devp->debug.scaler4h = 720; + devp->debug.dest_cfmt = TVIN_YUV422; + devp->flags |= VDIN_FLAG_MANUAL_CONVERSION; + } + param.frame_rate = vdin_v4l2_param.fps; + param.cfmt = TVIN_YUV422; + param.dfmt = TVIN_YUV422; + param.scan_mode = TVIN_SCAN_MODE_PROGRESSIVE; + param.fmt = TVIN_SIG_FMT_MAX; + //devp->flags |= VDIN_FLAG_V4L2_DEBUG; + devp->hist_bar_enable = 1; + devp->index = 1; + start_tvin_service(devp->index, ¶m); + break; + + case TVIN_IOC_S_VDIN_V4L2STOP: + if (devp->index == 0) { + pr_info("TVIN_IOC_S_VDIN_V4L2STOP cann't be used at vdin0\n"); + break; + } + devp->parm.reserved &= ~PARAM_STATE_HISTGRAM; + devp->flags &= (~VDIN_FLAG_ISR_REQ); + devp->flags &= (~VDIN_FLAG_FS_OPENED); + stop_tvin_service(devp->index); + break; default: ret = -ENOIOCTLCMD; /* pr_info("%s %d is not supported command\n", __func__, cmd); */ @@ -2403,6 +3192,7 @@ static int vdin_drv_probe(struct platform_device *pdev) int ret = 0; struct vdin_dev_s *vdevp; struct resource *res; + unsigned int val; unsigned int urgent_en = 0; unsigned int bit_mode = VDIN_WR_COLOR_DEPTH_8BIT; /* const void *name; */ @@ -2423,9 +3213,10 @@ static int vdin_drv_probe(struct platform_device *pdev) } } vdin_devp[vdevp->index] = vdevp; -#ifdef CONFIG_AML_RDMA - vdin_rdma_op.arg = vdin_devp; - vdevp->rdma_handle = rdma_register(&vdin_rdma_op, +#ifdef CONFIG_AMLOGIC_MEDIA_RDMA + vdin_rdma_op[vdevp->index].irq_cb = vdin_rdma_irq; + vdin_rdma_op[vdevp->index].arg = vdevp; + vdevp->rdma_handle = rdma_register(&vdin_rdma_op[vdevp->index], NULL, RDMA_TABLE_SIZE); pr_info("%s:vdin.%d rdma hanld %d.\n", __func__, vdevp->index, vdevp->rdma_handle); @@ -2528,22 +3319,27 @@ static int vdin_drv_probe(struct platform_device *pdev) else vdevp->color_depth_mode = 0; + /* use for tl1 vdin1 preview */ + spin_lock_init(&tl1_preview_lock); /*set afbce mode*/ ret = of_property_read_u32(pdev->dev.of_node, - "afbce_bit_mode", &vdevp->afbce_mode); + "afbce_bit_mode", &val); if (ret) { - vdevp->afbce_mode = 0; - pr_info("no afbce mode found, use normal mode\n"); + vdevp->afbce_flag = 0; } else { - if ((is_meson_tl1_cpu()) && (vdevp->index == 0)) { + vdevp->afbce_flag = val & 0xf; + vdevp->afbce_lossy_en = (val>>4)&0xf; + if ((is_meson_tl1_cpu() || is_meson_tm2_cpu()) && + (vdevp->index == 0)) { /* just use afbce at vdin0 */ - pr_info("afbce mode = %d\n", vdevp->afbce_mode); + pr_info("afbce flag = %d\n", vdevp->afbce_flag); + pr_info("afbce loosy en = %d\n", vdevp->afbce_lossy_en); vdevp->afbce_info = devm_kzalloc(vdevp->dev, sizeof(struct vdin_afbce_s), GFP_KERNEL); if (!vdevp->afbce_info) goto fail_kzalloc_vdev; } else { - vdevp->afbce_mode = 0; + vdevp->afbce_flag = 0; pr_info("get afbce from dts, but chip cannot support\n"); } } @@ -2560,18 +3356,22 @@ static int vdin_drv_probe(struct platform_device *pdev) vdevp->flags &= (~VDIN_FLAG_FS_OPENED); mutex_init(&vdevp->fe_lock); spin_lock_init(&vdevp->isr_lock); + spin_lock_init(&vdevp->hist_lock); vdevp->frontend = NULL; /* @todo vdin_addr_offset */ if (is_meson_gxbb_cpu() && vdevp->index) vdin_addr_offset[vdevp->index] = 0x70; else if ((is_meson_g12a_cpu() || is_meson_g12b_cpu() || - is_meson_tl1_cpu()) && vdevp->index) + is_meson_tl1_cpu() || is_meson_sm1_cpu() || + is_meson_tm2_cpu()) && vdevp->index) vdin_addr_offset[vdevp->index] = 0x100; vdevp->addr_offset = vdin_addr_offset[vdevp->index]; vdevp->flags = 0; /*canvas align number*/ - if (is_meson_g12a_cpu() || is_meson_g12b_cpu() || is_meson_tl1_cpu()) + if (is_meson_g12a_cpu() || is_meson_g12b_cpu() || + is_meson_tl1_cpu() || is_meson_sm1_cpu() || + is_meson_tm2_cpu()) vdevp->canvas_align = 64; else vdevp->canvas_align = 32; @@ -2705,7 +3505,7 @@ static int vdin_drv_remove(struct platform_device *pdev) vdevp = platform_get_drvdata(pdev); ret = cancel_delayed_work(&vdevp->vlock_dwork); -#ifdef CONFIG_AML_RDMA +#ifdef CONFIG_AMLOGIC_MEDIA_RDMA rdma_unregister(vdevp->rdma_handle); #endif mutex_destroy(&vdevp->fe_lock); diff --git a/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.h b/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.h index 43e719ef8576..927c8c56cf8a 100644 --- a/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.h +++ b/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.h @@ -36,8 +36,8 @@ #include #include #include -#ifdef CONFIG_AML_RDMA -#include +#ifdef CONFIG_AMLOGIC_MEDIA_RDMA +#include #endif /* Local Headers */ @@ -45,7 +45,7 @@ #include "vdin_vf.h" #include "vdin_regs.h" -#define VDIN_VER "Ref.2018/11/07a" +#define VDIN_VER "Ref.2019/03/01" /*the counter of vdin*/ #define VDIN_MAX_DEVS 2 @@ -85,6 +85,12 @@ #define VDIN_BYPASS_VGA_CHECK 0x00000008 #define VDIN_CANVAS_MAX_CNT 9 +/*values of vdin game mode process flag */ +#define VDIN_GAME_MODE_0 (1 << 0) +#define VDIN_GAME_MODE_1 (1 << 1) +#define VDIN_GAME_MODE_2 (1 << 2) +#define VDIN_GAME_MODE_SWITCH_EN (1 << 3) + /*flag for flush vdin buff*/ #define VDIN_FLAG_BLACK_SCREEN_ON 1 #define VDIN_FLAG_BLACK_SCREEN_OFF 0 @@ -199,6 +205,7 @@ struct vdin_dev_s { struct timer_list timer; spinlock_t isr_lock; + spinlock_t hist_lock; struct mutex fe_lock; struct clk *msr_clk; unsigned int msr_clk_val; @@ -312,6 +319,8 @@ struct vdin_dev_s { *game_mode: *bit0:enable/disable *bit1:for true bypas and put vframe in advance one vsync + *bit2:for true bypas and put vframe in advance two vsync, + *vdin & vpp read/write same buffer may happen */ unsigned int game_mode; unsigned int rdma_enable; @@ -320,7 +329,9 @@ struct vdin_dev_s { * 1: use afbce non-mmu mode: head/body addr set by code * 2: use afbce mmu mode: head set by code, body addr assigning by hw */ + unsigned int afbce_flag; unsigned int afbce_mode; + unsigned int afbce_lossy_en; unsigned int canvas_config_mode; bool prehsc_en; bool vshrk_en; @@ -330,6 +341,7 @@ struct vdin_dev_s { /*use frame rate to cal duraton*/ unsigned int use_frame_rate; unsigned int irq_cnt; + unsigned int frame_cnt; unsigned int rdma_irq_cnt; unsigned int vdin_irq_flag; unsigned int vdin_reset_flag; @@ -339,6 +351,25 @@ struct vdin_dev_s { struct dentry *dbg_root; /*dbg_fs*/ }; +struct vdin_hist_s { + ulong sum; + int width; + int height; + int ave; +}; + +struct vdin_v4l2_param_s { + int width; + int height; + int fps; +}; + +extern unsigned int tl1_vdin1_preview_flag; +extern unsigned int vdin_afbc_preview_force_drop_frame_cnt; +extern unsigned int vdin_afbc_force_drop_frame_cnt; +extern unsigned int max_ignore_frame_cnt; +extern unsigned int skip_frame_debug; + extern struct vframe_provider_s *vf_get_provider_by_name( const char *provider_name); extern bool enable_reset; @@ -367,8 +398,6 @@ extern void ldim_get_matrix(int *data, int reg_sel); extern void ldim_set_matrix(int *data, int reg_sel); extern void tvafe_snow_config(unsigned int onoff); extern void tvafe_snow_config_clamp(unsigned int onoff); -extern void tvafe_snow_config_acd(void); -extern void tvafe_snow_config_acd_resume(void); extern void vdin_vf_reg(struct vdin_dev_s *devp); extern void vdin_vf_unreg(struct vdin_dev_s *devp); extern void vdin_pause_dec(struct vdin_dev_s *devp); @@ -378,5 +407,7 @@ extern bool is_dolby_vision_enable(void); extern void vdin_debugfs_init(struct vdin_dev_s *vdevp); extern void vdin_debugfs_exit(struct vdin_dev_s *vdevp); +extern bool vlock_get_phlock_flag(void); + #endif /* __TVIN_VDIN_DRV_H */ diff --git a/drivers/amlogic/media/vin/tvin/vdin/vdin_sm.c b/drivers/amlogic/media/vin/tvin/vdin/vdin_sm.c index 252a3ab0d2d2..1ac4fbe53744 100644 --- a/drivers/amlogic/media/vin/tvin/vdin/vdin_sm.c +++ b/drivers/amlogic/media/vin/tvin/vdin/vdin_sm.c @@ -92,9 +92,11 @@ static int atv_stable_fmt_check_enable; static int atv_prestable_out_cnt = 100; static int other_stable_out_cnt = EXIT_STABLE_MAX_CNT; static int other_unstable_out_cnt = BACK_STABLE_MAX_CNT; +static int manual_unstable_out_cnt = 30; static int other_unstable_in_cnt = UNSTABLE_MAX_CNT; static int nosig_in_cnt = NOSIG_MAX_CNT; static int nosig2_unstable_cnt = EXIT_NOSIG_MAX_CNT; +bool manual_flag; #ifdef DEBUG_SUPPORT module_param(back_nosig_max_cnt, int, 0664); @@ -332,11 +334,8 @@ void tvin_smr(struct vdin_dev_s *devp) ++sm_p->state_cnt; #ifdef CONFIG_AMLOGIC_MEDIA_TVIN_AFE if ((port == TVIN_PORT_CVBS3) && - (devp->flags & VDIN_FLAG_SNOW_FLAG)) { + (devp->flags & VDIN_FLAG_SNOW_FLAG)) tvafe_snow_config_clamp(1); - /*fix black side when config atv snow*/ - tvafe_snow_config_acd(); - } #endif if (sm_ops->nosig(devp->frontend)) { sm_p->exit_nosig_cnt = 0; @@ -411,6 +410,9 @@ void tvin_smr(struct vdin_dev_s *devp) (port == TVIN_PORT_CVBS0)) && (devp->flags & VDIN_FLAG_SNOW_FLAG)) unstb_in = sm_p->atv_unstable_out_cnt; + else if ((port == TVIN_PORT_CVBS3) && + manual_flag) + unstb_in = manual_unstable_out_cnt; else if ((port >= TVIN_PORT_HDMI0) && (port <= TVIN_PORT_HDMI7)) unstb_in = sm_p->hdmi_unstable_out_cnt; @@ -475,11 +477,8 @@ void tvin_smr(struct vdin_dev_s *devp) devp->unstable_flag = true; #ifdef CONFIG_AMLOGIC_MEDIA_TVIN_AFE if ((port == TVIN_PORT_CVBS3) && - (devp->flags & VDIN_FLAG_SNOW_FLAG)) { + (devp->flags & VDIN_FLAG_SNOW_FLAG)) tvafe_snow_config_clamp(0); - /*fix black side when config atv snow*/ - tvafe_snow_config_acd_resume(); - } #endif if (sm_ops->nosig(devp->frontend)) { nosig = true; diff --git a/drivers/amlogic/media/vin/tvin/vdin/vdin_sm.h b/drivers/amlogic/media/vin/tvin/vdin/vdin_sm.h index b3009111cc5b..92fdd32d3013 100644 --- a/drivers/amlogic/media/vin/tvin/vdin/vdin_sm.h +++ b/drivers/amlogic/media/vin/tvin/vdin/vdin_sm.h @@ -49,6 +49,9 @@ struct tvin_sm_s { int atv_stable_out_cnt; int hdmi_unstable_out_cnt; }; + +extern bool manual_flag; + void tvin_smr(struct vdin_dev_s *pdev); void tvin_smr_init(int index); void reset_tvin_smr(unsigned int index); diff --git a/drivers/amlogic/media/vin/tvin/vdin/vdin_vf.c b/drivers/amlogic/media/vin/tvin/vdin/vdin_vf.c index afd3446df7f0..6c01f41d583f 100644 --- a/drivers/amlogic/media/vin/tvin/vdin/vdin_vf.c +++ b/drivers/amlogic/media/vin/tvin/vdin/vdin_vf.c @@ -1018,7 +1018,10 @@ void vdin_vf_disp_mode_update(struct vf_entry *vfe, struct vf_pool *p) p->disp_index[0] = 0; vfe->vf.index_disp = p->disp_index[0]; - p->disp_mode[p->disp_index[p->skip_vf_num]] = VFRAME_DISP_MODE_OK; + if (p->disp_mode[p->disp_index[p->skip_vf_num]] != + VFRAME_DISP_MODE_SKIP) + p->disp_mode[p->disp_index[p->skip_vf_num]] = + VFRAME_DISP_MODE_OK; for (i = p->skip_vf_num - 1; i < VFRAME_DISP_MAX_NUM; i--) p->disp_mode[p->disp_index[i]] = VFRAME_DISP_MODE_UNKNOWN; } @@ -1030,8 +1033,7 @@ void vdin_vf_disp_mode_update(struct vf_entry *vfe, struct vf_pool *p) void vdin_vf_disp_mode_skip(struct vf_pool *p) { unsigned int i; - - for (i = p->skip_vf_num - 1; i < VFRAME_DISP_MAX_NUM; i--) - p->disp_mode[i] = VFRAME_DISP_MODE_SKIP; + for (i = 0; i <= p->skip_vf_num; i++) + p->disp_mode[p->disp_index[i]] = VFRAME_DISP_MODE_SKIP; } diff --git a/drivers/amlogic/media/vin/tvin/viu/viuin.c b/drivers/amlogic/media/vin/tvin/viu/viuin.c index 3fe16a66aaae..5da1da6ce8b2 100644 --- a/drivers/amlogic/media/vin/tvin/viu/viuin.c +++ b/drivers/amlogic/media/vin/tvin/viu/viuin.c @@ -178,8 +178,9 @@ static int viuin_open(struct tvin_frontend_s *fe, enum tvin_port_e port) /*open the venc to vdin path*/ switch (rd_bits_viu(VPU_VIU_VENC_MUX_CTRL, 0, 2)) { case 0: - if (is_meson_g12a_cpu() || is_meson_g12b_cpu() - || is_meson_tl1_cpu()) + if (is_meson_g12a_cpu() || is_meson_g12b_cpu() || + is_meson_tl1_cpu() || is_meson_sm1_cpu() || + is_meson_tm2_cpu()) viu_mux = 0x4; else viu_mux = 0x8; @@ -213,7 +214,9 @@ static int viuin_open(struct tvin_frontend_s *fe, enum tvin_port_e port) wr_viu(VPU_VIU2VDIN_HDN_CTRL, 0x40f00); } else wr_bits_viu(VPU_VIU2VDIN_HDN_CTRL, devp->parm.h_active, 0, 14); - if (is_meson_g12a_cpu() || is_meson_g12b_cpu() || is_meson_tl1_cpu()) { + if (is_meson_g12a_cpu() || is_meson_g12b_cpu() || + is_meson_tl1_cpu() || is_meson_sm1_cpu() || + is_meson_tm2_cpu()) { if (((port >= TVIN_PORT_VIU1_WB0_VD1) && (port <= TVIN_PORT_VIU1_WB0_POST_BLEND)) || ((port >= TVIN_PORT_VIU2_WB0_VD1) && @@ -308,8 +311,9 @@ static void viuin_close(struct tvin_frontend_s *fe) if (open_cnt) open_cnt--; if (open_cnt == 0) { - if (is_meson_g12a_cpu() || is_meson_g12b_cpu() - || is_meson_tl1_cpu()) { + if (is_meson_g12a_cpu() || is_meson_g12b_cpu() || + is_meson_tl1_cpu() || is_meson_sm1_cpu() || + is_meson_tm2_cpu()) { wr_viu(VPU_VIU_VDIN_IF_MUX_CTRL, 0); wr_viu(VPP_WRBAK_CTRL, 0); diff --git a/drivers/amlogic/media/vout/backlight/aml_bl.c b/drivers/amlogic/media/vout/backlight/aml_bl.c index a7286d475260..bec1f9996a15 100644 --- a/drivers/amlogic/media/vout/backlight/aml_bl.c +++ b/drivers/amlogic/media/vout/backlight/aml_bl.c @@ -68,8 +68,6 @@ MODULE_PARM_DESC(bl_level, "bl_level"); static unsigned int bl_level_uboot; static unsigned int brightness_bypass; -module_param(brightness_bypass, uint, 0664); -MODULE_PARM_DESC(brightness_bypass, "bl_brightness_bypass"); static unsigned char bl_pwm_bypass; /* debug flag */ static unsigned char bl_pwm_duty_free; /* debug flag */ @@ -332,14 +330,6 @@ static void bl_gpio_set(int index, int value) } } -static inline unsigned int bl_do_div(unsigned long num, unsigned int den) -{ - unsigned long long ret = num; - - do_div(ret, den); - return (unsigned int)ret; -} - /* ****************************************************** */ #define BL_PINMUX_MAX 8 static char *bl_pinmux_str[BL_PINMUX_MAX] = { @@ -972,7 +962,7 @@ static unsigned int bl_level_mapping(unsigned int level) static void bl_set_duty_pwm(struct bl_pwm_config_s *bl_pwm) { - unsigned long temp; + unsigned long long temp; if (bl_pwm_bypass) return; @@ -1040,7 +1030,7 @@ static void bl_set_level_pwm(struct bl_pwm_config_s *bl_pwm, unsigned int level) unsigned int max = bl_pwm->level_max; unsigned int pwm_max = bl_pwm->pwm_max; unsigned int pwm_min = bl_pwm->pwm_min; - unsigned long temp; + unsigned long long temp; if (bl_pwm_bypass) return; @@ -1131,7 +1121,6 @@ static void bl_set_level_ldim(unsigned int level) static void aml_bl_set_level(unsigned int level) { - unsigned int temp; struct bl_pwm_config_s *pwm0, *pwm1; if (aml_bl_check_driver()) @@ -1165,26 +1154,27 @@ static void aml_bl_set_level(unsigned int level) case BL_CTRL_PWM_COMBO: pwm0 = bl_drv->bconf->bl_pwm_combo0; pwm1 = bl_drv->bconf->bl_pwm_combo1; - if ((level >= pwm0->level_min) && - (level <= pwm0->level_max)) { - temp = (pwm0->level_min > pwm1->level_min) ? - pwm1->level_max : pwm1->level_min; - if (bl_debug_print_flag) { - BLPR("pwm0 region, level=%u, pwm1_level=%u\n", - level, temp); - } + + if (level >= pwm0->level_max) { + bl_set_level_pwm(pwm0, pwm0->level_max); + } else if ((level > pwm0->level_min) && + (level < pwm0->level_max)) { + if (bl_debug_print_flag) + BLPR("pwm0 region, level=%u\n", level); bl_set_level_pwm(pwm0, level); - bl_set_level_pwm(pwm1, temp); - } else if ((level >= pwm1->level_min) && - (level <= pwm1->level_max)) { - temp = (pwm1->level_min > pwm0->level_min) ? - pwm0->level_max : pwm0->level_min; - if (bl_debug_print_flag) { - BLPR("pwm1 region, level=%u, pwm0_level=%u\n", - level, temp); - } - bl_set_level_pwm(pwm0, temp); + } else { + bl_set_level_pwm(pwm0, pwm0->level_min); + } + + if (level >= pwm1->level_max) { + bl_set_level_pwm(pwm1, pwm1->level_max); + } else if ((level > pwm1->level_min) && + (level < pwm1->level_max)) { + if (bl_debug_print_flag) + BLPR("pwm1 region, level=%u,\n", level); bl_set_level_pwm(pwm1, level); + } else { + bl_set_level_pwm(pwm1, pwm1->level_min); } break; #ifdef CONFIG_AMLOGIC_LOCAL_DIMMING @@ -1213,6 +1203,30 @@ static unsigned int aml_bl_get_level(void) return bl_drv->level; } +static unsigned int aml_bl_update_brightness_level(unsigned int bl_level) +{ + mutex_lock(&bl_level_mutex); + if (bl_level > 255) { + BLPR("0-255 is the valid data\n"); + bl_level = 255; + } + + if (((bl_drv->state & BL_STATE_LCD_ON) == 0) || + ((bl_drv->state & BL_STATE_BL_POWER_ON) == 0)) + bl_level = 0; + + if (bl_level == 0) { + if (bl_drv->state & BL_STATE_BL_ON) + bl_power_off(); + } else { + aml_bl_set_level(bl_level); + if ((bl_drv->state & BL_STATE_BL_ON) == 0) + bl_power_on(); + } + mutex_unlock(&bl_level_mutex); + return 0; +} + static int aml_bl_update_status(struct backlight_device *bd) { int brightness = bd->props.brightness; @@ -1220,30 +1234,12 @@ static int aml_bl_update_status(struct backlight_device *bd) if (brightness_bypass) return 0; - mutex_lock(&bl_level_mutex); - if (brightness < 0) - brightness = 0; - else if (brightness > 255) - brightness = 255; - - if (((bl_drv->state & BL_STATE_LCD_ON) == 0) || - ((bl_drv->state & BL_STATE_BL_POWER_ON) == 0)) - brightness = 0; - + aml_bl_update_brightness_level(brightness); if (bl_debug_print_flag) { BLPR("%s: %u, real brightness: %u, state: 0x%x\n", __func__, bd->props.brightness, brightness, bl_drv->state); } - if (brightness == 0) { - if (bl_drv->state & BL_STATE_BL_ON) - bl_power_off(); - } else { - aml_bl_set_level(brightness); - if ((bl_drv->state & BL_STATE_BL_ON) == 0) - bl_power_on(); - } - mutex_unlock(&bl_level_mutex); return 0; } @@ -1287,7 +1283,7 @@ enum bl_pwm_port_e bl_pwm_str_to_pwm(const char *str) void bl_pwm_config_init(struct bl_pwm_config_s *bl_pwm) { unsigned int cnt; - unsigned long temp; + unsigned long long temp; if (bl_debug_print_flag) { BLPR("%s pwm_port %d: freq = %u\n", @@ -1530,7 +1526,8 @@ static int aml_bl_config_load_from_dts(struct bl_config_s *bconf, bconf->power_on_delay = bl_para[3]; bconf->power_off_delay = bl_para[4]; } - ret = of_property_read_u32(child, "bl_ldim_mode", &bl_para[0]); + ret = of_property_read_u32(child, "bl_ldim_region_row_col", + &bl_para[0]); if (ret == 0) bconf->ldim_flag = 1; @@ -1598,10 +1595,11 @@ static int aml_bl_config_load_from_dts(struct bl_config_s *bconf, ret = of_property_read_u32(child, "bl_pwm_en_sequence_reverse", &val); if (ret) { - BLPR("don't find bl_pwm_en_sequence_reverse\n"); bconf->en_sequence_reverse = 0; - } else + } else { bconf->en_sequence_reverse = val; + BLPR("find bl_pwm_en_sequence_reverse: %d\n", val); + } bl_pwm->pwm_duty = bl_pwm->pwm_duty_min; /* init pwm config */ @@ -2042,6 +2040,9 @@ static int aml_bl_pwm_channel_register(struct bl_config_s *bconf, struct device_node *child; struct bl_pwm_config_s *bl_pwm = NULL; + if (bl_debug_print_flag) + BLPR("%s\n", __func__); + ret = of_property_read_u32(blnode, "bl_pwm_config", &pwm_phandle); if (ret) { BLERR("not match bl_pwm_config node\n"); @@ -2105,8 +2106,6 @@ static int aml_bl_pwm_channel_register(struct bl_config_s *bconf, bl_pwm->pwm_data.port_index, bl_pwm->pwm_data.pwm); } - BLPR("%s ok\n", __func__); - return ret; } @@ -2288,12 +2287,34 @@ static struct notifier_block aml_bl_off_nb = { .priority = LCD_PRIORITY_POWER_BL_OFF, }; +static inline int aml_bl_pwm_vs_lcd_update(struct bl_pwm_config_s *bl_pwm) +{ + unsigned int cnt; + + if (bl_pwm == NULL) { + BLERR("%s: bl_pwm is null\n", __func__); + return 0; + } + + cnt = bl_vcbus_read(ENCL_VIDEO_MAX_LNCNT) + 1; + if (cnt != bl_pwm->pwm_cnt) { + bl_pwm_config_init(bl_pwm); + if (brightness_bypass) + bl_set_duty_pwm(bl_pwm); + else + aml_bl_update_status(bl_drv->bldev); + } + + return 0; +} + static int aml_bl_lcd_update_notifier(struct notifier_block *nb, unsigned long event, void *data) { struct bl_pwm_config_s *bl_pwm = NULL; #ifdef CONFIG_AMLOGIC_LOCAL_DIMMING struct aml_ldim_driver_s *ldim_drv = aml_ldim_get_driver(); + unsigned int *frame_rate; #endif /* If we aren't interested in this event, skip it immediately */ @@ -2308,13 +2329,8 @@ static int aml_bl_lcd_update_notifier(struct notifier_block *nb, case BL_CTRL_PWM: if (bl_drv->bconf->bl_pwm->pwm_port == BL_PWM_VS) { bl_pwm = bl_drv->bconf->bl_pwm; - if (bl_pwm) { - bl_pwm_config_init(bl_pwm); - if (brightness_bypass) - bl_set_duty_pwm(bl_pwm); - else - aml_bl_update_status(bl_drv->bldev); - } + if (bl_pwm) + aml_bl_pwm_vs_lcd_update(bl_pwm); } break; case BL_CTRL_PWM_COMBO: @@ -2322,16 +2338,16 @@ static int aml_bl_lcd_update_notifier(struct notifier_block *nb, bl_pwm = bl_drv->bconf->bl_pwm_combo0; else if (bl_drv->bconf->bl_pwm_combo1->pwm_port == BL_PWM_VS) bl_pwm = bl_drv->bconf->bl_pwm_combo1; - if (bl_pwm) { - bl_pwm_config_init(bl_pwm); - if (brightness_bypass) - bl_set_duty_pwm(bl_pwm); - else - aml_bl_update_status(bl_drv->bldev); - } + if (bl_pwm) + aml_bl_pwm_vs_lcd_update(bl_pwm); break; #ifdef CONFIG_AMLOGIC_LOCAL_DIMMING case BL_CTRL_LOCAL_DIMMING: + if (data) { + frame_rate = (unsigned int *)data; + ldim_drv->vsync_change_flag = + (unsigned char)(*frame_rate); + } if (ldim_drv->pwm_vs_update) ldim_drv->pwm_vs_update(); break; @@ -2529,7 +2545,7 @@ static ssize_t bl_status_read(struct class *class, return len; } -static ssize_t bl_debug_pwm_show(struct class *class, +static ssize_t bl_debug_pwm_info_show(struct class *class, struct class_attribute *attr, char *buf) { struct bl_config_s *bconf = bl_drv->bconf; @@ -2538,7 +2554,7 @@ static ssize_t bl_debug_pwm_show(struct class *class, unsigned int value; ssize_t len = 0; - len = sprintf(buf, "read backlight pwm state:\n"); + len = sprintf(buf, "read backlight pwm info:\n"); switch (bconf->method) { case BL_CTRL_PWM: len += sprintf(buf+len, @@ -2773,16 +2789,86 @@ static ssize_t bl_debug_pwm_show(struct class *class, return len; } -#define BL_DEBUG_PWM_FREQ 0 -#define BL_DEBUG_PWM_DUTY 1 -#define BL_DEBUG_PWM_POL 2 -#define BL_DEBUG_PWM_DUTY_MAX 3 -#define BL_DEBUG_PWM_DUTY_MIN 4 +static ssize_t bl_debug_pwm_show(struct class *class, + struct class_attribute *attr, char *buf) +{ + struct bl_config_s *bconf = bl_drv->bconf; + struct bl_pwm_config_s *bl_pwm; + ssize_t len = 0; + + switch (bconf->method) { + case BL_CTRL_PWM: + if (bconf->bl_pwm) { + bl_pwm = bconf->bl_pwm; + len += sprintf(buf+len, + "pwm: freq=%d, pol=%d, duty_max=%d, duty_min=%d, ", + bl_pwm->pwm_freq, bl_pwm->pwm_method, + bl_pwm->pwm_duty_max, bl_pwm->pwm_duty_min); + if (bl_pwm->pwm_duty_max > 100) { + len += sprintf(buf+len, + "duty_value=%d(%d%%)\n", + bl_pwm->pwm_duty, + bl_pwm->pwm_duty*100/255); + } else { + len += sprintf(buf+len, + "duty_value=%d%%\n", + bl_pwm->pwm_duty); + } + } + break; + case BL_CTRL_PWM_COMBO: + if (bconf->bl_pwm_combo0) { + bl_pwm = bconf->bl_pwm_combo0; + len += sprintf(buf+len, + "pwm_0: freq=%d, pol=%d, duty_max=%d, duty_min=%d, ", + bl_pwm->pwm_freq, bl_pwm->pwm_method, + bl_pwm->pwm_duty_max, bl_pwm->pwm_duty_min); + if (bl_pwm->pwm_duty_max > 100) { + len += sprintf(buf+len, + "duty_value=%d(%d%%)\n", + bl_pwm->pwm_duty, + bl_pwm->pwm_duty*100/255); + } else { + len += sprintf(buf+len, + "duty_value=%d%%\n", + bl_pwm->pwm_duty); + } + } + + if (bconf->bl_pwm_combo1) { + bl_pwm = bconf->bl_pwm_combo1; + len += sprintf(buf+len, + "pwm_1: freq=%d, pol=%d, duty_max=%d, duty_min=%d, ", + bl_pwm->pwm_freq, bl_pwm->pwm_method, + bl_pwm->pwm_duty_max, bl_pwm->pwm_duty_min); + if (bl_pwm->pwm_duty_max > 100) { + len += sprintf(buf+len, + "duty_value=%d(%d%%)\n", + bl_pwm->pwm_duty, + bl_pwm->pwm_duty*100/255); + } else { + len += sprintf(buf+len, + "duty_value=%d%%\n", + bl_pwm->pwm_duty); + } + } + break; + default: + break; + } + return len; +} + +#define BL_DEBUG_PWM_FREQ 0 +#define BL_DEBUG_PWM_DUTY 1 +#define BL_DEBUG_PWM_POL 2 +#define BL_DEBUG_PWM_DUTY_MAX 3 +#define BL_DEBUG_PWM_DUTY_MIN 4 static void bl_debug_pwm_set(unsigned int index, unsigned int value, int state) { struct bl_config_s *bconf = bl_drv->bconf; struct bl_pwm_config_s *bl_pwm = NULL; - unsigned long temp; + unsigned long long temp; unsigned int pwm_range, temp_duty; if (aml_bl_check_driver()) @@ -3107,9 +3193,58 @@ static ssize_t bl_debug_print_store(struct class *class, return count; } +static ssize_t bl_debug_brightness_bypass_show(struct class *class, + struct class_attribute *attr, char *buf) +{ + return sprintf(buf, "%d\n", brightness_bypass); +} + +static ssize_t bl_debug_brightness_bypass_store(struct class *class, + struct class_attribute *attr, const char *buf, size_t count) +{ + unsigned int ret; + + ret = kstrtouint(buf, 10, &brightness_bypass); + if (ret != 0) { + BLERR("invalid data\n"); + return -EINVAL; + } + return count; +} + +static ssize_t bl_debug_brightness_show(struct class *class, + struct class_attribute *attr, char *buf) +{ + return sprintf(buf, "%d\n", bl_drv->level); +} + +static ssize_t bl_debug_brightness_store(struct class *class, + struct class_attribute *attr, const char *buf, size_t count) +{ + unsigned int ret; + unsigned int brightness_level = 0; + + ret = kstrtouint(buf, 10, &brightness_level); + if (ret != 0) { + BLERR("invalid data\n"); + return -EINVAL; + } + + if (!brightness_bypass) + brightness_bypass = 1; + + ret = aml_bl_update_brightness_level(brightness_level); + if (ret == 0) + BLPR("brightness %d update ok\n", brightness_level); + else + BLERR("update fail\n"); + return count; +} + static struct class_attribute bl_debug_class_attrs[] = { __ATTR(help, 0444, bl_debug_help, NULL), __ATTR(status, 0444, bl_status_read, NULL), + __ATTR(pwm_info, 0644, bl_debug_pwm_info_show, NULL), __ATTR(pwm, 0644, bl_debug_pwm_show, bl_debug_pwm_store), __ATTR(power, 0644, bl_debug_power_show, bl_debug_power_store), __ATTR(step_on, 0644, bl_debug_step_on_show, bl_debug_step_on_store), @@ -3117,6 +3252,10 @@ static struct class_attribute bl_debug_class_attrs[] = { __ATTR(key_valid, 0444, bl_debug_key_valid_show, NULL), __ATTR(config_load, 0444, bl_debug_config_load_show, NULL), __ATTR(print, 0644, bl_debug_print_show, bl_debug_print_store), + __ATTR(brightness_bypass, 0644, bl_debug_brightness_bypass_show, + bl_debug_brightness_bypass_store), + __ATTR(brightness_level, 0644, bl_debug_brightness_show, + bl_debug_brightness_store), }; static int aml_bl_creat_class(void) @@ -3231,6 +3370,18 @@ static struct bl_data_s bl_data_tl1 = { .pwm_reg = pwm_reg_txlx, }; +static struct bl_data_s bl_data_sm1 = { + .chip_type = BL_CHIP_SM1, + .chip_name = "sm1", + .pwm_reg = pwm_reg_txlx, +}; + +static struct bl_data_s bl_data_tm2 = { + .chip_type = BL_CHIP_TM2, + .chip_name = "tm2", + .pwm_reg = pwm_reg_txlx, +}; + static const struct of_device_id bl_dt_match_table[] = { { .compatible = "amlogic, backlight-gxl", @@ -3264,6 +3415,14 @@ static const struct of_device_id bl_dt_match_table[] = { .compatible = "amlogic, backlight-tl1", .data = &bl_data_tl1, }, + { + .compatible = "amlogic, backlight-sm1", + .data = &bl_data_sm1, + }, + { + .compatible = "amlogic, backlight-tm2", + .data = &bl_data_tm2, + }, {}, }; #endif @@ -3384,7 +3543,7 @@ static int aml_bl_probe(struct platform_device *pdev) err: kfree(bl_drv); bl_drv = NULL; - return ret; + return 0; } static int __exit aml_bl_remove(struct platform_device *pdev) @@ -3392,6 +3551,9 @@ static int __exit aml_bl_remove(struct platform_device *pdev) int ret; /*struct aml_bl *bl_drv = platform_get_drvdata(pdev);*/ + if (bl_drv == NULL) + return 0; + aml_bl_remove_class(); ret = cancel_delayed_work_sync(&bl_drv->bl_delayed_work); diff --git a/drivers/amlogic/media/vout/backlight/aml_ldim/Makefile b/drivers/amlogic/media/vout/backlight/aml_ldim/Makefile index bc2132eb8332..1d695bb17d3a 100644 --- a/drivers/amlogic/media/vout/backlight/aml_ldim/Makefile +++ b/drivers/amlogic/media/vout/backlight/aml_ldim/Makefile @@ -3,6 +3,6 @@ # obj-$(CONFIG_AMLOGIC_LOCAL_DIMMING) = aml_ldim.o ldim_dev_drv.o ldim_spi.o \ ob3350_bl.o global_bl.o iw7027_bl.o -aml_ldim-objs := ldim_drv.o ldim_func.o +aml_ldim-objs := ldim_drv.o ldim_func.o ldim_hw.o diff --git a/drivers/amlogic/media/vout/backlight/aml_ldim/global_bl.c b/drivers/amlogic/media/vout/backlight/aml_ldim/global_bl.c index d2dcd99745b5..1a1856c3017c 100644 --- a/drivers/amlogic/media/vout/backlight/aml_ldim/global_bl.c +++ b/drivers/amlogic/media/vout/backlight/aml_ldim/global_bl.c @@ -44,7 +44,8 @@ static int global_hw_init_on(void) { struct aml_ldim_driver_s *ldim_drv = aml_ldim_get_driver(); - ldim_set_duty_pwm(&(ldim_drv->ldev_conf->pwm_config)); + ldim_set_duty_pwm(&(ldim_drv->ldev_conf->ldim_pwm_config)); + ldim_set_duty_pwm(&(ldim_drv->ldev_conf->analog_pwm_config)); ldim_drv->pinmux_ctrl(1); mdelay(2); ldim_gpio_set(ldim_drv->ldev_conf->en_gpio, @@ -61,7 +62,8 @@ static int global_hw_init_off(void) ldim_gpio_set(ldim_drv->ldev_conf->en_gpio, ldim_drv->ldev_conf->en_gpio_off); ldim_drv->pinmux_ctrl(0); - ldim_pwm_off(&(ldim_drv->ldev_conf->pwm_config)); + ldim_pwm_off(&(ldim_drv->ldev_conf->ldim_pwm_config)); + ldim_pwm_off(&(ldim_drv->ldev_conf->analog_pwm_config)); return 0; } @@ -88,12 +90,22 @@ static int global_smr(unsigned short *buf, unsigned char len) level = buf[0]; val = dim_min + ((level * (dim_max - dim_min)) / LD_DATA_MAX); - ldim_drv->ldev_conf->pwm_config.pwm_duty = val; - ldim_set_duty_pwm(&(ldim_drv->ldev_conf->pwm_config)); + ldim_drv->ldev_conf->ldim_pwm_config.pwm_duty = val; + ldim_set_duty_pwm(&(ldim_drv->ldev_conf->ldim_pwm_config)); return 0; } +static void global_dim_range_update(void) +{ + struct aml_ldim_driver_s *ldim_drv = aml_ldim_get_driver(); + struct ldim_dev_config_s *ldim_dev; + + ldim_dev = ldim_drv->ldev_conf; + ldim_dev->dim_max = ldim_dev->ldim_pwm_config.pwm_duty_max; + ldim_dev->dim_min = ldim_dev->ldim_pwm_config.pwm_duty_min; +} + static int global_power_on(void) { if (global_on_flag) { @@ -137,7 +149,7 @@ static ssize_t global_show(struct class *class, ldim_drv->ldev_conf->en_gpio_off, ldim_drv->ldev_conf->dim_max, ldim_drv->ldev_conf->dim_min, - ldim_drv->ldev_conf->pwm_config.pwm_duty); + ldim_drv->ldev_conf->ldim_pwm_config.pwm_duty); } return ret; @@ -150,6 +162,12 @@ static struct class_attribute global_class_attrs[] = { static int global_ldim_driver_update(struct aml_ldim_driver_s *ldim_drv) { + struct ldim_dev_config_s *ldim_dev = ldim_drv->ldev_conf; + + ldim_dev->ldim_pwm_config.pwm_duty_max = ldim_dev->dim_max; + ldim_dev->ldim_pwm_config.pwm_duty_min = ldim_dev->dim_min; + ldim_dev->dim_range_update = global_dim_range_update; + ldim_drv->device_power_on = global_power_on; ldim_drv->device_power_off = global_power_off; ldim_drv->device_bri_update = global_smr; diff --git a/drivers/amlogic/media/vout/backlight/aml_ldim/iw7027_bl.c b/drivers/amlogic/media/vout/backlight/aml_ldim/iw7027_bl.c index 187b7233316c..c1536128e3c0 100644 --- a/drivers/amlogic/media/vout/backlight/aml_ldim/iw7027_bl.c +++ b/drivers/amlogic/media/vout/backlight/aml_ldim/iw7027_bl.c @@ -46,9 +46,11 @@ #define IW7027_REG_CHIPID 0x7f #define IW7027_CHIPID 0x28 -#define IW7027_POWER_ON 0 -#define IW7027_POWER_RESET 1 +#define VSYNC_INFO_FREQUENT 30 + static int iw7027_on_flag; +static unsigned short vsync_cnt; +static unsigned short fault_cnt; static DEFINE_MUTEX(iw7027_spi_mutex); @@ -114,6 +116,37 @@ static int iw7027_wregs(struct spi_device *spi, unsigned char addr, return ret; } +static int iw7027_reg_write(unsigned char *buf, unsigned int len) +{ + int ret; + + if (len > 28) { + LDIMERR("%s: unsupport len: %d\n", __func__, len); + return -1; + } + + if (len > 1) + ret = iw7027_wreg(bl_iw7027->spi, buf[0], buf[1]); + else + ret = iw7027_wregs(bl_iw7027->spi, buf[0], &buf[1], (len - 1)); + + return ret; +} + +static int iw7027_reg_read(unsigned char *buf, unsigned int len) +{ + int ret; + + if (len > 1) { + LDIMERR("%s: unsupport len: %d\n", __func__, len); + return -1; + } + + ret = iw7027_rreg(bl_iw7027->spi, buf[0], &buf[0]); + + return ret; +} + static int ldim_power_cmd_dynamic_size(void) { unsigned char *table; @@ -247,8 +280,6 @@ static int iw7027_hw_init_on(void) unsigned char reg_chk, reg_duty_chk; struct aml_ldim_driver_s *ldim_drv = aml_ldim_get_driver(); - mutex_lock(&iw7027_spi_mutex); - /* step 1: system power_on */ ldim_gpio_set(ldim_drv->ldev_conf->en_gpio, ldim_drv->ldev_conf->en_gpio_on); @@ -273,7 +304,8 @@ static int iw7027_hw_init_on(void) iw7027_power_on_init(); /* step 5: supply stable vsync */ - ldim_set_duty_pwm(&(ldim_drv->ldev_conf->pwm_config)); + ldim_set_duty_pwm(&(ldim_drv->ldev_conf->ldim_pwm_config)); + ldim_set_duty_pwm(&(ldim_drv->ldev_conf->analog_pwm_config)); ldim_drv->pinmux_ctrl(1); /* step 6: delay for system clock and light bar PSU stable */ @@ -295,8 +327,6 @@ static int iw7027_hw_init_on(void) } LDIMPR("%s: calibration done: [%d] = %x\n", __func__, i, reg_duty_chk); - mutex_unlock(&iw7027_spi_mutex); - return 0; } @@ -304,14 +334,11 @@ static int iw7027_hw_init_off(void) { struct aml_ldim_driver_s *ldim_drv = aml_ldim_get_driver(); - mutex_lock(&iw7027_spi_mutex); - ldim_gpio_set(ldim_drv->ldev_conf->en_gpio, ldim_drv->ldev_conf->en_gpio_off); ldim_drv->pinmux_ctrl(0); - ldim_pwm_off(&(ldim_drv->ldev_conf->pwm_config)); - - mutex_unlock(&iw7027_spi_mutex); + ldim_pwm_off(&(ldim_drv->ldev_conf->ldim_pwm_config)); + ldim_pwm_off(&(ldim_drv->ldev_conf->analog_pwm_config)); return 0; } @@ -387,6 +414,48 @@ static int iw7027_spi_dump_dim(char *buf) return len; } +static int fault_cnt_save; +static int fault_check_cnt; +static int iw7027_fault_handler(unsigned int gpio) +{ + unsigned int val; + + if (gpio >= BL_GPIO_NUM_MAX) + return 0; + + if (fault_check_cnt++ > 200) { /* clear fault flag for a cycle */ + fault_check_cnt = 0; + fault_cnt = 0; + fault_cnt_save = 0; + } + + if (ldim_debug_print) { + if (vsync_cnt == 0) { + LDIMPR("%s: fault_cnt: %d, fault_check_cnt: %d\n", + __func__, fault_cnt, fault_check_cnt); + } + } + + val = ldim_gpio_get(gpio); + if (val == 0) + return 0; + + fault_cnt++; + if (fault_cnt_save != fault_cnt) { + fault_cnt_save = fault_cnt; + LDIMPR("%s: fault_cnt: %d\n", __func__, fault_cnt); + } + if (fault_cnt <= 10) { + iw7027_wreg(bl_iw7027->spi, 0x61, 0x0f); + } else { + iw7027_hw_init_on(); + fault_cnt = 0; + fault_cnt_save = 0; + } + + return -1; +} + static unsigned int dim_max, dim_min; static inline unsigned int iw7027_get_value(unsigned int level) { @@ -397,7 +466,6 @@ static inline unsigned int iw7027_get_value(unsigned int level) return val; } -static int smr_cnt; static int iw7027_smr(unsigned short *buf, unsigned char len) { int i; @@ -405,22 +473,22 @@ static int iw7027_smr(unsigned short *buf, unsigned char len) unsigned short *mapping, num; struct aml_ldim_driver_s *ldim_drv = aml_ldim_get_driver(); - if (smr_cnt++ >= 30) - smr_cnt = 0; + if (vsync_cnt++ >= VSYNC_INFO_FREQUENT) + vsync_cnt = 0; if (iw7027_on_flag == 0) { - if (smr_cnt == 0) + if (vsync_cnt == 0) LDIMPR("%s: on_flag=%d\n", __func__, iw7027_on_flag); return 0; } num = ldim_drv->ldev_conf->bl_regnum; if (len != num) { - if (smr_cnt == 0) + if (vsync_cnt == 0) LDIMERR("%s: data len %d invalid\n", __func__, len); return -1; } if (val_brightness == NULL) { - if (smr_cnt == 0) + if (vsync_cnt == 0) LDIMERR("%s: val_brightness is null\n", __func__); return -1; } @@ -431,9 +499,16 @@ static int iw7027_smr(unsigned short *buf, unsigned char len) dim_max = ldim_drv->ldev_conf->dim_max; dim_min = ldim_drv->ldev_conf->dim_min; + if (ldim_drv->vsync_change_flag == 50) { + iw7027_wreg(bl_iw7027->spi, 0x31, 0xd7); + ldim_drv->vsync_change_flag = 0; + } else if (ldim_drv->vsync_change_flag == 60) { + iw7027_wreg(bl_iw7027->spi, 0x31, 0xd3); + ldim_drv->vsync_change_flag = 0; + } if (bl_iw7027->test_mode) { if (test_brightness == NULL) { - if (smr_cnt == 0) + if (vsync_cnt == 0) LDIMERR("test_brightness is null\n"); return 0; } @@ -458,18 +533,51 @@ static int iw7027_smr(unsigned short *buf, unsigned char len) iw7027_wregs(bl_iw7027->spi, 0x40, val_brightness, (num * 2)); + if (ldim_drv->ldev_conf->fault_check) + iw7027_fault_handler(ldim_drv->ldev_conf->lamp_err_gpio); + mutex_unlock(&iw7027_spi_mutex); + return 0; } +static int iw7027_check(void) +{ + struct aml_ldim_driver_s *ldim_drv = aml_ldim_get_driver(); + int ret = 0; + + if (vsync_cnt++ >= VSYNC_INFO_FREQUENT) + vsync_cnt = 0; + + if (iw7027_on_flag == 0) { + if (vsync_cnt == 0) + LDIMPR("%s: on_flag=%d\n", __func__, iw7027_on_flag); + return 0; + } + + mutex_lock(&iw7027_spi_mutex); + + if (ldim_drv->ldev_conf->fault_check) + ret = iw7027_fault_handler(ldim_drv->ldev_conf->lamp_err_gpio); + + mutex_unlock(&iw7027_spi_mutex); + + return ret; +} + static int iw7027_power_on(void) { if (iw7027_on_flag) { LDIMPR("%s: iw7027 is already on, exit\n", __func__); return 0; } + + mutex_lock(&iw7027_spi_mutex); iw7027_hw_init_on(); iw7027_on_flag = 1; + vsync_cnt = 0; + fault_cnt = 0; + mutex_unlock(&iw7027_spi_mutex); LDIMPR("%s: ok\n", __func__); return 0; @@ -477,8 +585,10 @@ static int iw7027_power_on(void) static int iw7027_power_off(void) { + mutex_lock(&iw7027_spi_mutex); iw7027_on_flag = 0; iw7027_hw_init_off(); + mutex_unlock(&iw7027_spi_mutex); LDIMPR("%s: ok\n", __func__); return 0; @@ -492,11 +602,7 @@ static ssize_t iw7027_show(struct class *class, int ret = 0; int i; - if (!strcmp(attr->attr.name, "mode")) { - ret = sprintf(buf, "0x%02x\n", bl->spi->mode); - } else if (!strcmp(attr->attr.name, "speed")) { - ret = sprintf(buf, "%d\n", bl->spi->max_speed_hz); - } else if (!strcmp(attr->attr.name, "test")) { + if (!strcmp(attr->attr.name, "test")) { ret = sprintf(buf, "test mode=%d\n", bl->test_mode); } else if (!strcmp(attr->attr.name, "brightness")) { if (test_brightness == NULL) { @@ -511,13 +617,15 @@ static ssize_t iw7027_show(struct class *class, ret = sprintf(buf, "iw7027 status:\n" "dev_index = %d\n" "on_flag = %d\n" + "fault_cnt = %d\n" "en_on = %d\n" "en_off = %d\n" "cs_hold_delay = %d\n" "cs_clk_delay = %d\n" "dim_max = 0x%03x\n" "dim_min = 0x%03x\n", - ldim_drv->dev_index, iw7027_on_flag, + ldim_drv->dev_index, + iw7027_on_flag, fault_cnt, ldim_drv->ldev_conf->en_gpio_on, ldim_drv->ldev_conf->en_gpio_off, ldim_drv->ldev_conf->cs_hold_delay, @@ -542,23 +650,13 @@ static ssize_t iw7027_store(struct class *class, struct aml_ldim_driver_s *ldim_drv = aml_ldim_get_driver(); struct iw7027_s *bl = container_of(class, struct iw7027_s, cls); unsigned int val, val2; - unsigned char reg_addr, reg_val; + unsigned char reg_addr, reg_val, temp; int i; if (!strcmp(attr->attr.name, "init")) { + mutex_lock(&iw7027_spi_mutex); iw7027_hw_init_on(); - } else if (!strcmp(attr->attr.name, "mode")) { - i = kstrtouint(buf, 10, &val); - if (i == 1) - bl->spi->mode = val; - else - LDIMERR("%s: invalid args\n", __func__); - } else if (!strcmp(attr->attr.name, "speed")) { - i = kstrtouint(buf, 10, &val); - if (i == 1) - bl->spi->max_speed_hz = val*1000; - else - LDIMERR("%s: invalid args\n", __func__); + mutex_unlock(&iw7027_spi_mutex); } else if (!strcmp(attr->attr.name, "reg")) { if (buf[0] == 'w') { i = sscanf(buf, "w %x %x", &val, &val2); @@ -567,6 +665,10 @@ static ssize_t iw7027_store(struct class *class, reg_addr = (unsigned char)val; reg_val = (unsigned char)val2; iw7027_wreg(bl->spi, reg_addr, reg_val); + iw7027_rreg(bl->spi, reg_addr, &temp); + pr_info( + "reg 0x%02x = 0x%02x, readback 0x%02x\n", + reg_addr, reg_val, temp); mutex_unlock(&iw7027_spi_mutex); } else { LDIMERR("%s: invalid args\n", __func__); @@ -605,9 +707,7 @@ static ssize_t iw7027_store(struct class *class, } static struct class_attribute iw7027_class_attrs[] = { - __ATTR(init, 0644, iw7027_show, iw7027_store), - __ATTR(mode, 0644, iw7027_show, iw7027_store), - __ATTR(speed, 0644, iw7027_show, iw7027_store), + __ATTR(init, 0644, NULL, iw7027_store), __ATTR(reg, 0644, iw7027_show, iw7027_store), __ATTR(test, 0644, iw7027_show, iw7027_store), __ATTR(brightness, 0644, iw7027_show, iw7027_store), @@ -623,6 +723,10 @@ static int iw7027_ldim_driver_update(struct aml_ldim_driver_s *ldim_drv) ldim_drv->device_power_on = iw7027_power_on; ldim_drv->device_power_off = iw7027_power_off; ldim_drv->device_bri_update = iw7027_smr; + ldim_drv->device_bri_check = iw7027_check; + + ldim_drv->ldev_conf->dev_reg_write = iw7027_reg_write; + ldim_drv->ldev_conf->dev_reg_read = iw7027_reg_read; return 0; } @@ -636,6 +740,8 @@ int ldim_dev_iw7027_probe(struct aml_ldim_driver_s *ldim_drv) } iw7027_on_flag = 0; + vsync_cnt = 0; + fault_cnt = 0; bl_iw7027 = kzalloc(sizeof(struct iw7027_s), GFP_KERNEL); if (bl_iw7027 == NULL) { diff --git a/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_dev_drv.c b/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_dev_drv.c index b2c02250cf71..9dab744e1622 100644 --- a/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_dev_drv.c +++ b/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_dev_drv.c @@ -58,6 +58,7 @@ static struct spi_board_info ldim_spi_info = { static unsigned char *table_init_on_dft; static unsigned char *table_init_off_dft; static int ldim_dev_probe_flag; +static struct class ldim_dev_class; struct ldim_dev_config_s ldim_dev_config = { .type = LDIM_DEV_TYPE_NORMAL, @@ -77,14 +78,25 @@ struct ldim_dev_config_s ldim_dev_config = { .init_off = NULL, .init_on_cnt = 0, .init_off_cnt = 0, - .pwm_config = { + .ldim_pwm_config = { .pwm_method = BL_PWM_POSITIVE, .pwm_port = BL_PWM_MAX, .pwm_duty_max = 100, - .pwm_duty_min = 1, + .pwm_duty_min = 0, + }, + .analog_pwm_config = { + .pwm_method = BL_PWM_POSITIVE, + .pwm_port = BL_PWM_MAX, + .pwm_freq = 1000, + .pwm_duty_max = 100, + .pwm_duty_min = 10, }, .bl_regnum = 0, + + .dim_range_update = NULL, + .dev_reg_write = NULL, + .dev_reg_read = NULL, }; static void ldim_gpio_probe(int index) @@ -246,14 +258,13 @@ unsigned int ldim_gpio_get(int index) void ldim_set_duty_pwm(struct bl_pwm_config_s *bl_pwm) { - unsigned long temp; + unsigned long long temp; if (bl_pwm->pwm_port >= BL_PWM_MAX) return; temp = bl_pwm->pwm_cnt; - temp = (((temp * bl_pwm->pwm_duty) + 50) / 100); - bl_pwm->pwm_level = (unsigned int)temp; + bl_pwm->pwm_level = bl_do_div(((temp * bl_pwm->pwm_duty) + 50), 100); if (ldim_debug_print == 2) { LDIMPR( @@ -277,42 +288,53 @@ void ldim_pwm_off(struct bl_pwm_config_s *bl_pwm) static char *ldim_pinmux_str[] = { "ldim_pwm", /* 0 */ "ldim_pwm_vs", /* 1 */ - "ldim_pwm_off", /* 1 */ - "none", + "ldim_pwm_combo", /* 2 */ + "ldim_pwm_vs_combo", /* 3 */ + "ldim_pwm_off", /* 4 */ + "ldim_pwm_combo_off", /* 5 */ + "custome", }; static int ldim_pwm_pinmux_ctrl(int status) { struct aml_ldim_driver_s *ldim_drv = aml_ldim_get_driver(); struct bl_pwm_config_s *bl_pwm; + char *str; int ret = 0, index = 0xff; - if (strcmp(ldim_drv->ldev_conf->pinmux_name, "invalid") == 0) + if (ldim_drv->ldev_conf->ldim_pwm_config.pwm_port >= BL_PWM_MAX) return 0; - bl_pwm = &ldim_drv->ldev_conf->pwm_config; - if (bl_pwm->pwm_port >= BL_PWM_MAX) - return 0; - - if (bl_pwm->pwm_port == BL_PWM_VS) - index = (status) ? 1 : 2; - else - index = (status) ? 0 : 2; + if (status) { + bl_pwm = &ldim_drv->ldev_conf->ldim_pwm_config; + if (bl_pwm->pwm_port == BL_PWM_VS) + index = 1; + else + index = 0; + bl_pwm = &ldim_drv->ldev_conf->analog_pwm_config; + if (bl_pwm->pwm_port < BL_PWM_VS) + index += 2; + } else { + bl_pwm = &ldim_drv->ldev_conf->analog_pwm_config; + if (bl_pwm->pwm_port < BL_PWM_VS) + index = 5; + else + index = 4; + } + str = ldim_pinmux_str[index]; if (ldim_drv->pinmux_flag == index) { - LDIMPR("pinmux %s is already selected\n", - ldim_pinmux_str[index]); + LDIMPR("pinmux %s is already selected\n", str); return 0; } /* request pwm pinmux */ - ldim_drv->pin = devm_pinctrl_get_select(ldim_drv->dev, - ldim_pinmux_str[index]); + ldim_drv->pin = devm_pinctrl_get_select(ldim_drv->dev, str); if (IS_ERR(ldim_drv->pin)) { - LDIMERR("set pinmux %s error\n", ldim_pinmux_str[index]); + LDIMERR("set pinmux %s error\n", str); + ret = -1; } else { - LDIMPR("set pinmux %s: 0x%p\n", - ldim_pinmux_str[index], ldim_drv->pin); + LDIMPR("set pinmux %s: 0x%p\n", str, ldim_drv->pin); } ldim_drv->pinmux_flag = index; @@ -321,12 +343,21 @@ static int ldim_pwm_pinmux_ctrl(int status) static int ldim_pwm_vs_update(void) { - struct bl_pwm_config_s *bl_pwm = NULL; + struct bl_pwm_config_s *bl_pwm = &ldim_dev_config.ldim_pwm_config; + unsigned int cnt; int ret = 0; - bl_pwm = &ldim_dev_config.pwm_config; - bl_pwm_config_init(bl_pwm); - ldim_set_duty_pwm(bl_pwm); + if (bl_pwm->pwm_port != BL_PWM_VS) + return 0; + + if (ldim_debug_print) + LDIMPR("%s\n", __func__); + + cnt = bl_vcbus_read(ENCL_VIDEO_MAX_LNCNT) + 1; + if (cnt != bl_pwm->pwm_cnt) { + bl_pwm_config_init(bl_pwm); + ldim_set_duty_pwm(bl_pwm); + } return ret; } @@ -354,6 +385,10 @@ static void ldim_dev_init_table_dynamic_size_print( table = econf->init_off; max_len = econf->init_off_cnt; } + if (max_len == 0) { + kfree(str); + return; + } if (table == NULL) { LDIMERR("init_table %d is NULL\n", flag); kfree(str); @@ -431,6 +466,10 @@ static void ldim_dev_init_table_fixed_size_print( table = econf->init_off; max_len = econf->init_off_cnt; } + if (max_len == 0) { + kfree(str); + return; + } if (table == NULL) { LDIMERR("init_table %d is NULL\n", flag); kfree(str); @@ -466,15 +505,16 @@ static void ldim_dev_config_print(void) LDIMPR("%s:\n", __func__); pr_info("valid_flag = %d\n" - "dev_index = %d\n", + "dev_index = %d\n" + "vsync_change_flag = %d\n\n", ldim_drv->valid_flag, - ldim_drv->dev_index); + ldim_drv->dev_index, + ldim_drv->vsync_change_flag); if (ldim_drv->ldev_conf == NULL) { LDIMERR("%s: device config is null\n", __func__); return; } - bl_pwm = &ldim_drv->ldev_conf->pwm_config; pr_info("dev_name = %s\n" "type = %d\n" "en_gpio = %d\n" @@ -537,13 +577,14 @@ static void ldim_dev_config_print(void) default: break; } + bl_pwm = &ldim_drv->ldev_conf->ldim_pwm_config; if (bl_pwm->pwm_port < BL_PWM_MAX) { - pr_info("pwm_port: %d\n" - "pwm_pol: %d\n" - "pwm_freq: %d\n" - "pwm_cnt: %d\n" - "pwm_level: %d\n" - "pwm_duty: %d%%\n", + pr_info("lidm_pwm_port: %d\n" + "lidm_pwm_pol: %d\n" + "lidm_pwm_freq: %d\n" + "lidm_pwm_cnt: %d\n" + "lidm_pwm_level: %d\n" + "lidm_pwm_duty: %d%%\n", bl_pwm->pwm_port, bl_pwm->pwm_method, bl_pwm->pwm_freq, bl_pwm->pwm_cnt, bl_pwm->pwm_level, bl_pwm->pwm_duty); @@ -555,28 +596,28 @@ static void ldim_dev_config_print(void) case BL_PWM_E: case BL_PWM_F: if (IS_ERR_OR_NULL(bl_pwm->pwm_data.pwm)) { - pr_info("pwm invalid\n"); + pr_info("lidm_pwm invalid\n"); break; } - pr_info("pwm_pointer: %p\n", + pr_info("lidm_pwm_pointer: 0x%p\n", bl_pwm->pwm_data.pwm); pwm_get_state(bl_pwm->pwm_data.pwm, &pstate); - pr_info("pwm state:\n" - " period: %d\n" - " duty_cycle: %d\n" - " polarity: %d\n" - " enabled: %d\n", + pr_info("lidm_pwm state:\n" + " period: %d\n" + " duty_cycle: %d\n" + " polarity: %d\n" + " enabled: %d\n", pstate.period, pstate.duty_cycle, pstate.polarity, pstate.enabled); value = bl_cbus_read( bl_drv->data->pwm_reg[bl_pwm->pwm_port]); - pr_info("pwm_reg: 0x%08x\n", value); + pr_info("lidm_pwm_reg: 0x%08x\n", value); break; case BL_PWM_VS: - pr_info("pwm_reg0: 0x%08x\n" - "pwm_reg1: 0x%08x\n" - "pwm_reg2: 0x%08x\n" - "pwm_reg3: 0x%08x\n", + pr_info("lidm_pwm_reg0: 0x%08x\n" + "lidm_pwm_reg1: 0x%08x\n" + "lidm_pwm_reg2: 0x%08x\n" + "lidm_pwm_reg3: 0x%08x\n", bl_vcbus_read(VPU_VPU_PWM_V0), bl_vcbus_read(VPU_VPU_PWM_V1), bl_vcbus_read(VPU_VPU_PWM_V2), @@ -586,16 +627,59 @@ static void ldim_dev_config_print(void) break; } } - pr_info("pinmux_flag: %d\n" - "pinmux_pointer: 0x%p\n\n", + bl_pwm = &ldim_drv->ldev_conf->analog_pwm_config; + if (bl_pwm->pwm_port < BL_PWM_MAX) { + pr_info("\nanalog_pwm_port: %d\n" + "analog_pwm_pol: %d\n" + "analog_pwm_freq: %d\n" + "analog_pwm_cnt: %d\n" + "analog_pwm_level: %d\n" + "analog_pwm_duty: %d%%\n" + "analog_pwm_duty_max: %d%%\n" + "analog_pwm_duty_min: %d%%\n", + bl_pwm->pwm_port, bl_pwm->pwm_method, + bl_pwm->pwm_freq, bl_pwm->pwm_cnt, + bl_pwm->pwm_level, bl_pwm->pwm_duty, + bl_pwm->pwm_duty_max, bl_pwm->pwm_duty_min); + switch (bl_pwm->pwm_port) { + case BL_PWM_A: + case BL_PWM_B: + case BL_PWM_C: + case BL_PWM_D: + case BL_PWM_E: + case BL_PWM_F: + if (IS_ERR_OR_NULL(bl_pwm->pwm_data.pwm)) { + pr_info("analog_pwm invalid\n"); + break; + } + pr_info("analog_pwm_pointer: 0x%p\n", + bl_pwm->pwm_data.pwm); + pwm_get_state(bl_pwm->pwm_data.pwm, &pstate); + pr_info("analog_pwm state:\n" + " period: %d\n" + " duty_cycle: %d\n" + " polarity: %d\n" + " enabled: %d\n", + pstate.period, pstate.duty_cycle, + pstate.polarity, pstate.enabled); + value = bl_cbus_read( + bl_drv->data->pwm_reg[bl_pwm->pwm_port]); + pr_info("analog_pwm_reg: 0x%08x\n", value); + break; + default: + break; + } + } + pr_info("\npinmux_flag: %d\n" + "pinmux_pointer: 0x%p\n\n", ldim_drv->pinmux_flag, ldim_drv->pin); if (ldim_drv->ldev_conf->cmd_size > 0) { - pr_info("table_loaded: %d\n" - "cmd_size: %d\n" - "init_on_cnt: %d\n" - "init_off_cnt: %d\n", + pr_info("table_loaded: %d\n" + "cmd_size: %d\n" + "init_on_cnt: %d\n" + "init_off_cnt: %d\n", ldim_drv->ldev_conf->init_loaded, ldim_drv->ldev_conf->cmd_size, ldim_drv->ldev_conf->init_on_cnt, @@ -625,6 +709,9 @@ static int ldim_dev_pwm_channel_register(struct bl_pwm_config_s *bl_pwm, struct device_node *child; struct aml_ldim_driver_s *ldim_drv = aml_ldim_get_driver(); + if (ldim_debug_print) + LDIMPR("%s ok\n", __func__); + ret = of_property_read_u32(blnode, "ldim_pwm_config", &pwm_phandle); if (ret) { LDIMERR("not match ldim_pwm_config node\n"); @@ -672,8 +759,6 @@ static int ldim_dev_pwm_channel_register(struct bl_pwm_config_s *bl_pwm, bl_pwm->pwm_data.port_index, bl_pwm->pwm_data.pwm); } - LDIMPR("%s ok\n", __func__); - return ret; } @@ -880,6 +965,7 @@ static int ldim_dev_get_config_from_dts(struct device_node *np, int index) int i; int ret = 0; struct aml_ldim_driver_s *ldim_drv = aml_ldim_get_driver(); + struct bl_pwm_config_s *bl_pwm; temp = kcalloc(LD_BLKREGNUM, sizeof(unsigned int), GFP_KERNEL); if (temp == NULL) { @@ -905,48 +991,77 @@ static int ldim_dev_get_config_from_dts(struct device_node *np, int index) ret = of_property_read_string(child, "ldim_pwm_pinmux_sel", &str); if (ret) { - LDIMERR("failed to get ldim_pwm_name\n"); strcpy(ldim_dev_config.pinmux_name, "invalid"); } else { + LDIMPR("find custome ldim_pwm_pinmux_sel: %s\n", str); strcpy(ldim_dev_config.pinmux_name, str); } + /* ldim pwm config */ + bl_pwm = &ldim_dev_config.ldim_pwm_config; ret = of_property_read_string(child, "ldim_pwm_port", &str); if (ret) { LDIMERR("failed to get ldim_pwm_port\n"); - ldim_dev_config.pwm_config.pwm_port = BL_PWM_MAX; } else { - ldim_dev_config.pwm_config.pwm_port = bl_pwm_str_to_pwm(str); + bl_pwm->pwm_port = bl_pwm_str_to_pwm(str); + LDIMPR("ldim_pwm_port: %s(%u)\n", str, bl_pwm->pwm_port); } - LDIMPR("pwm_port: %s(%u)\n", str, ldim_dev_config.pwm_config.pwm_port); - - if (ldim_dev_config.pwm_config.pwm_port < BL_PWM_MAX) { + if (bl_pwm->pwm_port < BL_PWM_MAX) { ret = of_property_read_u32_array(child, "ldim_pwm_attr", temp, 3); if (ret) { LDIMERR("failed to get ldim_pwm_attr\n"); - ldim_dev_config.pwm_config.pwm_method = BL_PWM_POSITIVE; - if (ldim_dev_config.pwm_config.pwm_port == BL_PWM_VS) - ldim_dev_config.pwm_config.pwm_freq = 1; + bl_pwm->pwm_method = BL_PWM_POSITIVE; + if (bl_pwm->pwm_port == BL_PWM_VS) + bl_pwm->pwm_freq = 1; else - ldim_dev_config.pwm_config.pwm_freq = 60; - ldim_dev_config.pwm_config.pwm_duty = 50; + bl_pwm->pwm_freq = 60; + bl_pwm->pwm_duty = 50; } else { - ldim_dev_config.pwm_config.pwm_method = temp[0]; - ldim_dev_config.pwm_config.pwm_freq = temp[1]; - ldim_dev_config.pwm_config.pwm_duty = temp[2]; + bl_pwm->pwm_method = temp[0]; + bl_pwm->pwm_freq = temp[1]; + bl_pwm->pwm_duty = temp[2]; } - LDIMPR("get pwm pol = %d, freq = %d, duty = %d%%\n", - ldim_dev_config.pwm_config.pwm_method, - ldim_dev_config.pwm_config.pwm_freq, - ldim_dev_config.pwm_config.pwm_duty); + LDIMPR( + "get ldim_pwm pol = %d, freq = %d, default duty = %d%%\n", + bl_pwm->pwm_method, bl_pwm->pwm_freq, + bl_pwm->pwm_duty); - bl_pwm_config_init(&ldim_dev_config.pwm_config); + bl_pwm_config_init(bl_pwm); - if (ldim_dev_config.pwm_config.pwm_port < BL_PWM_VS) { - ldim_dev_pwm_channel_register( - &ldim_dev_config.pwm_config, np); + if (bl_pwm->pwm_port < BL_PWM_VS) + ldim_dev_pwm_channel_register(bl_pwm, np); + } + + /* analog pwm config */ + bl_pwm = &ldim_dev_config.analog_pwm_config; + ret = of_property_read_string(child, "analog_pwm_port", &str); + if (ret) + bl_pwm->pwm_port = BL_PWM_MAX; + else + bl_pwm->pwm_port = bl_pwm_str_to_pwm(str); + if (bl_pwm->pwm_port < BL_PWM_VS) { + LDIMPR("find analog_pwm_port: %s(%u)\n", str, bl_pwm->pwm_port); + ret = of_property_read_u32_array(child, "analog_pwm_attr", + temp, 5); + if (ret) { + LDIMERR("failed to get analog_pwm_attr\n"); + } else { + bl_pwm->pwm_method = temp[0]; + bl_pwm->pwm_freq = temp[1]; + bl_pwm->pwm_duty_max = temp[2]; + bl_pwm->pwm_duty_min = temp[3]; + bl_pwm->pwm_duty = temp[4]; } + LDIMPR( +"get analog_pwm pol = %d, freq = %d, duty_max = %d%%, duty_min = %d%%, default duty = %d%%\n", + bl_pwm->pwm_method, bl_pwm->pwm_freq, + bl_pwm->pwm_duty_max, bl_pwm->pwm_duty_min, + bl_pwm->pwm_duty); + + bl_pwm_config_init(bl_pwm); + + ldim_dev_pwm_channel_register(bl_pwm, np); } ret = of_property_read_u32_array(child, "en_gpio_on_off", temp, 3); @@ -1148,11 +1263,389 @@ ldim_get_config_err: return -1; } +static ssize_t ldim_dev_show(struct class *class, + struct class_attribute *attr, char *buf) +{ + int ret = 0; + + ldim_dev_config_print(); + + return ret; +} + +static ssize_t ldim_dev_pwm_ldim_show(struct class *class, + struct class_attribute *attr, char *buf) +{ + struct bl_pwm_config_s *bl_pwm; + ssize_t len = 0; + + bl_pwm = &ldim_dev_config.ldim_pwm_config; + if (bl_pwm->pwm_port < BL_PWM_MAX) { + len += sprintf(buf+len, + "ldim_pwm: freq=%d, pol=%d, duty_max=%d, duty_min=%d,", + bl_pwm->pwm_freq, bl_pwm->pwm_method, + bl_pwm->pwm_duty_max, bl_pwm->pwm_duty_min); + len += sprintf(buf+len, " duty_value=%d%%\n", bl_pwm->pwm_duty); + } + + return len; +} + +static ssize_t ldim_dev_pwm_ldim_store(struct class *class, + struct class_attribute *attr, const char *buf, size_t count) +{ + unsigned int ret; + unsigned int val = 0; + struct bl_pwm_config_s *bl_pwm; + + bl_pwm = &ldim_dev_config.ldim_pwm_config; + if (bl_pwm->pwm_port >= BL_PWM_MAX) + return count; + + switch (buf[0]) { + case 'f': /* frequency */ + ret = sscanf(buf, "freq %d", &val); + if (ret == 1) { + bl_pwm->pwm_freq = val; + bl_pwm_config_init(bl_pwm); + ldim_set_duty_pwm(bl_pwm); + if (ldim_debug_print) { + LDIMPR("set ldim_pwm (port %d): freq = %dHz\n", + bl_pwm->pwm_port, bl_pwm->pwm_freq); + } + } else { + LDIMERR("invalid parameters\n"); + } + break; + case 'd': /* duty */ + ret = sscanf(buf, "duty %d", &val); + if (ret == 1) { + bl_pwm->pwm_duty = val; + ldim_set_duty_pwm(bl_pwm); + if (ldim_debug_print) { + LDIMPR("set ldim_pwm (port %d): duty = %d%%\n", + bl_pwm->pwm_port, bl_pwm->pwm_duty); + } + } else { + LDIMERR("invalid parameters\n"); + } + break; + case 'p': /* polarity */ + ret = sscanf(buf, "pol %d", &val); + if (ret == 1) { + bl_pwm->pwm_method = val; + bl_pwm_config_init(bl_pwm); + ldim_set_duty_pwm(bl_pwm); + if (ldim_debug_print) { + LDIMPR("set ldim_pwm (port %d): method = %d\n", + bl_pwm->pwm_port, bl_pwm->pwm_method); + } + } else { + LDIMERR("invalid parameters\n"); + } + break; + case 'm': + if (buf[1] == 'a') { /* max */ + ret = sscanf(buf, "max %d", &val); + if (ret == 1) { + bl_pwm->pwm_duty_max = val; + if (ldim_dev_config.dim_range_update) + ldim_dev_config.dim_range_update(); + bl_pwm_config_init(bl_pwm); + ldim_set_duty_pwm(bl_pwm); + if (ldim_debug_print) { + LDIMPR( + "set ldim_pwm (port %d): duty_max = %d%%\n", + bl_pwm->pwm_port, + bl_pwm->pwm_duty_max); + } + } else { + LDIMERR("invalid parameters\n"); + } + } else if (buf[1] == 'i') { /* min */ + ret = sscanf(buf, "min %d", &val); + if (ret == 1) { + bl_pwm->pwm_duty_min = val; + if (ldim_dev_config.dim_range_update) + ldim_dev_config.dim_range_update(); + bl_pwm_config_init(bl_pwm); + ldim_set_duty_pwm(bl_pwm); + if (ldim_debug_print) { + LDIMPR( + "set ldim_pwm (port %d): duty_min = %d%%\n", + bl_pwm->pwm_port, + bl_pwm->pwm_duty_min); + } + } else { + LDIMERR("invalid parameters\n"); + } + } + break; + default: + LDIMERR("wrong command\n"); + break; + } + + return count; +} + +static ssize_t ldim_dev_pwm_analog_show(struct class *class, + struct class_attribute *attr, char *buf) +{ + struct bl_pwm_config_s *bl_pwm; + ssize_t len = 0; + + bl_pwm = &ldim_dev_config.analog_pwm_config; + if (bl_pwm->pwm_port < BL_PWM_VS) { + len += sprintf(buf+len, + "analog_pwm: freq=%d, pol=%d, duty_max=%d, duty_min=%d,", + bl_pwm->pwm_freq, bl_pwm->pwm_method, + bl_pwm->pwm_duty_max, bl_pwm->pwm_duty_min); + len += sprintf(buf+len, " duty_value=%d%%\n", bl_pwm->pwm_duty); + } + + return len; +} + +static ssize_t ldim_dev_pwm_analog_store(struct class *class, + struct class_attribute *attr, const char *buf, size_t count) +{ + unsigned int ret; + unsigned int val = 0; + struct bl_pwm_config_s *bl_pwm; + + bl_pwm = &ldim_dev_config.analog_pwm_config; + if (bl_pwm->pwm_port >= BL_PWM_VS) + return count; + + switch (buf[0]) { + case 'f': /* frequency */ + ret = sscanf(buf, "freq %d", &val); + if (ret == 1) { + bl_pwm->pwm_freq = val; + bl_pwm_config_init(bl_pwm); + ldim_set_duty_pwm(bl_pwm); + if (ldim_debug_print) { + LDIMPR("set ldim_pwm (port %d): freq = %dHz\n", + bl_pwm->pwm_port, bl_pwm->pwm_freq); + } + } else { + LDIMERR("invalid parameters\n"); + } + break; + case 'd': /* duty */ + ret = sscanf(buf, "duty %d", &val); + if (ret == 1) { + bl_pwm->pwm_duty = val; + ldim_set_duty_pwm(bl_pwm); + if (ldim_debug_print) { + LDIMPR("set ldim_pwm (port %d): duty = %d%%\n", + bl_pwm->pwm_port, bl_pwm->pwm_duty); + } + } else { + LDIMERR("invalid parameters\n"); + } + break; + case 'p': /* polarity */ + ret = sscanf(buf, "pol %d", &val); + if (ret == 1) { + bl_pwm->pwm_method = val; + bl_pwm_config_init(bl_pwm); + ldim_set_duty_pwm(bl_pwm); + if (ldim_debug_print) { + LDIMPR("set ldim_pwm (port %d): method = %d\n", + bl_pwm->pwm_port, bl_pwm->pwm_method); + } + } else { + LDIMERR("invalid parameters\n"); + } + break; + case 'm': + if (buf[1] == 'a') { /* max */ + ret = sscanf(buf, "max %d", &val); + if (ret == 1) { + bl_pwm->pwm_duty_max = val; + bl_pwm_config_init(bl_pwm); + ldim_set_duty_pwm(bl_pwm); + if (ldim_debug_print) { + LDIMPR( + "set ldim_pwm (port %d): duty_max = %d%%\n", + bl_pwm->pwm_port, + bl_pwm->pwm_duty_max); + } + } else { + LDIMERR("invalid parameters\n"); + } + } else if (buf[1] == 'i') { /* min */ + ret = sscanf(buf, "min %d", &val); + if (ret == 1) { + bl_pwm->pwm_duty_min = val; + bl_pwm_config_init(bl_pwm); + ldim_set_duty_pwm(bl_pwm); + if (ldim_debug_print) { + LDIMPR( + "set ldim_pwm (port %d): duty_min = %d%%\n", + bl_pwm->pwm_port, + bl_pwm->pwm_duty_min); + } + } else { + LDIMERR("invalid parameters\n"); + } + } + break; + default: + LDIMERR("wrong command\n"); + break; + } + + return count; +} + +static unsigned char ldim_dev_reg; +static unsigned char ldim_dev_reg_dump_cnt; +static ssize_t ldim_dev_reg_show(struct class *class, + struct class_attribute *attr, char *buf) +{ + unsigned char data; + ssize_t len = 0; + int ret; + + if (ldim_dev_config.dev_reg_read == NULL) + return sprintf(buf, "ldim dev_reg_read is null\n"); + + data = ldim_dev_reg; + ret = ldim_dev_config.dev_reg_read(&data, 1); + if (ret) { + len = sprintf(buf, "reg[0x%02x] read error\n", ldim_dev_reg); + } else { + len = sprintf(buf, "reg[0x%02x] = 0x%02x\n", + ldim_dev_reg, data); + } + + return len; +} + +static ssize_t ldim_dev_reg_store(struct class *class, + struct class_attribute *attr, const char *buf, size_t count) +{ + unsigned int reg = 0, val = 0; + unsigned char data[2]; + unsigned int ret; + + ret = sscanf(buf, "%x %x", ®, &val); + if (ret == 1) { + if (reg > 0xff) { + LDIMERR("invalid reg address: 0x%x\n", reg); + return count; + } + ldim_dev_reg = (unsigned char)reg; + } else if (ret == 2) { + if (ldim_dev_config.dev_reg_write == NULL) { + LDIMERR("ldim dev_reg_write is null\n"); + return count; + } + if (reg > 0xff) { + LDIMERR("invalid reg address: 0x%x\n", reg); + return count; + } + ldim_dev_reg = (unsigned char)reg; + data[0] = ldim_dev_reg; + data[1] = (unsigned char)val; + ldim_dev_config.dev_reg_write(data, 2); + LDIMPR("write reg[0x%02x] = 0x%02x\n", data[0], data[1]); + } else { + LDIMERR("invalid parameters\n"); + } + + return count; +} + +static ssize_t ldim_dev_reg_dump_show(struct class *class, + struct class_attribute *attr, char *buf) +{ + unsigned char *data; + ssize_t len = 0; + int i, ret; + + if (ldim_dev_config.dev_reg_read == NULL) + return sprintf(buf, "ldim dev_reg_read is null\n"); + + if (ldim_dev_reg_dump_cnt == 0) + return sprintf(buf, "ldim reg_dump_cnt is zero\n"); + + data = kcalloc(ldim_dev_reg_dump_cnt, + sizeof(unsigned char), GFP_KERNEL); + ret = ldim_dev_config.dev_reg_read(data, ldim_dev_reg_dump_cnt); + if (ret) { + len = sprintf(buf, "reg[0x%02x] read error\n", ldim_dev_reg); + } else { + len += sprintf(buf+len, "reg[0x%02x] = ", ldim_dev_reg); + for (i = 0; i < (ldim_dev_reg_dump_cnt - 1); i++) + len += sprintf(buf+len, "0x%02x,", data[i]); + len += sprintf(buf+len, "0x%02x\n", + data[ldim_dev_reg_dump_cnt - 1]); + } + kfree(data); + + return len; +} + +static ssize_t ldim_dev_reg_dump_store(struct class *class, + struct class_attribute *attr, const char *buf, size_t count) +{ + unsigned int reg = 0, cnt = 0; + unsigned int ret; + + ret = sscanf(buf, "%x %d", ®, &cnt); + if (ret == 2) { + if (reg > 0xff) { + LDIMERR("invalid reg address: 0x%x\n", reg); + return count; + } + if (cnt > 0xff) { + LDIMERR("invalid reg cnt: %d\n", cnt); + return count; + } + ldim_dev_reg = (unsigned char)reg; + ldim_dev_reg_dump_cnt = (unsigned char)cnt; + } else { + LDIMERR("invalid parameters\n"); + } + + return count; +} + +static struct class_attribute ldim_dev_class_attrs[] = { + __ATTR(status, 0644, ldim_dev_show, NULL), + __ATTR(pwm_ldim, 0644, ldim_dev_pwm_ldim_show, ldim_dev_pwm_ldim_store), + __ATTR(pwm_analog, 0644, ldim_dev_pwm_analog_show, + ldim_dev_pwm_analog_store), + __ATTR(reg, 0644, ldim_dev_reg_show, ldim_dev_reg_store), + __ATTR(reg_dump, 0644, ldim_dev_reg_dump_show, ldim_dev_reg_dump_store), + __ATTR_NULL +}; + +static void ldim_dev_class_create(void) +{ + int ret; + + ldim_dev_class.name = kzalloc(10, GFP_KERNEL); + if (ldim_dev_class.name == NULL) { + LDIMERR("%s: malloc failed\n", __func__); + return; + } + sprintf((char *)ldim_dev_class.name, "ldim_dev"); + ldim_dev_class.class_attrs = ldim_dev_class_attrs; + ret = class_register(&ldim_dev_class); + if (ret < 0) + LDIMERR("register ldim_dev_class failed\n"); +} + static int ldim_dev_add_driver(struct aml_ldim_driver_s *ldim_drv) { struct ldim_dev_config_s *ldev_conf = ldim_drv->ldev_conf; int index = ldim_drv->dev_index; - int ret = -1; + int ret = 0; switch (ldim_dev_config.type) { case LDIM_DEV_TYPE_SPI: @@ -1243,12 +1736,14 @@ static int ldim_dev_probe(struct platform_device *pdev) ldim_dev_get_config_from_dts(pdev->dev.of_node, ldim_drv->dev_index); + ldim_dev_class_create(); ldim_dev_add_driver(ldim_drv); + + /* init ldim function */ + if (ldim_drv->valid_flag) + ldim_drv->init(); + LDIMPR("%s OK\n", __func__); } - /* init ldim function */ - if (ldim_drv->valid_flag) - ldim_drv->init(); - LDIMPR("%s OK\n", __func__); return 0; } @@ -1257,10 +1752,11 @@ static int __exit ldim_dev_remove(struct platform_device *pdev) { struct aml_ldim_driver_s *ldim_drv = aml_ldim_get_driver(); - if (ldim_drv->dev_index != 0xff) + if (ldim_drv->dev_index != 0xff) { ldim_dev_remove_driver(ldim_drv); + LDIMPR("%s OK\n", __func__); + } - LDIMPR("%s OK\n", __func__); return 0; } diff --git a/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_drv.c b/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_drv.c index bb5e4e6cb46e..6cfe4d25df26 100644 --- a/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_drv.c +++ b/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_drv.c @@ -309,258 +309,22 @@ static void ldim_db_load_update(struct LDReg_s *mLDReg, ldim_db_para_print(mLDReg); } -static void ldim_stts_initial_txlx(unsigned int resolution) -{ - Wr_reg(LDIM_STTS_CTRL0, 7 << 2); - ldim_set_matrix_ycbcr2rgb(); - ldim_stts_en(resolution, 0, 0, 1, 1, 1, 0); -} - static void ldim_stts_initial(unsigned int pic_h, unsigned int pic_v, unsigned int BLK_Vnum, unsigned int BLK_Hnum) { - unsigned int resolution, resolution_region, blk_height, blk_width; - unsigned int row_start, col_start; - - BLK_Vnum = (BLK_Vnum == 0) ? 1 : BLK_Vnum; - BLK_Hnum = (BLK_Hnum == 0) ? 1 : BLK_Hnum; LDIMPR("%s: %d %d %d %d\n", __func__, pic_h, pic_v, BLK_Vnum, BLK_Hnum); ldim_fw_para.hist_col = BLK_Vnum; ldim_fw_para.hist_row = BLK_Hnum; - resolution = (((pic_h - 1) & 0xffff) << 16) | ((pic_v - 1) & 0xffff); - /*Wr_reg(VDIN0_HIST_CTRL, 0x10d);*/ - if (ldim_dev.ldim_op_func == NULL) { LDIMERR("%s: invalid ldim_op_func\n", __func__); return; } - if (ldim_dev.ldim_op_func->stts_init) - ldim_dev.ldim_op_func->stts_init(resolution); - - resolution_region = 0; - - blk_height = (pic_v - 8) / BLK_Vnum; - blk_width = (pic_h - 8) / BLK_Hnum; - row_start = (pic_v - (blk_height * BLK_Vnum)) >> 1; - col_start = (pic_h - (blk_width * BLK_Hnum)) >> 1; - ldim_set_region(0, blk_height, blk_width, - row_start, col_start, BLK_Hnum); -} - -static int LDIM_Update_Matrix(int NewBlMatrix[], int BlMatrixNum) -{ - int data; - - data = LDIM_RD_32Bits(REG_LD_MISC_CTRL0); - if (data & (1 << 12)) { /*bl_ram_mode=1;*/ - if (LDIM_RD_32Bits(REG_LD_BLMAT_RAM_MISC) & 0x10000) - /*Previous Matrix is not used*/ - goto Previous_Matrix; - else { - LDIM_WR_BASE_LUT_DRT(REG_LD_MATRIX_BASE, - NewBlMatrix, BlMatrixNum); - LDIM_WR_32Bits(REG_LD_BLMAT_RAM_MISC, - (BlMatrixNum & 0x1ff) | (1 << 16)); - /*set Matrix update ready*/ - - return 0; - } - } else { /*bl_ram_mode=0*/ - /*set ram_clk_sel=0, ram_bus_sel = 0*/ - data = data & (~(3 << 9)); - LDIM_WR_32Bits(REG_LD_MISC_CTRL0, data); - LDIM_WR_BASE_LUT_DRT(REG_LD_MATRIX_BASE, - NewBlMatrix, BlMatrixNum); - data = data | (3 << 9); /*set ram_clk_sel=1, ram_bus_sel = 1*/ - LDIM_WR_32Bits(REG_LD_MISC_CTRL0, data); - - return 0; + if (ldim_dev.ldim_op_func->stts_init) { + ldim_dev.ldim_op_func->stts_init(pic_h, pic_v, + BLK_Vnum, BLK_Hnum); } - -Previous_Matrix: - return 1; -} - -static void ldim_initial_txlx(unsigned int ldim_bl_en, - unsigned int ldim_hvcnt_bypass) -{ - unsigned int i; - unsigned int data; - unsigned int *arrayTmp; - - arrayTmp = kcalloc(1536, sizeof(unsigned int), GFP_KERNEL); - if (arrayTmp == NULL) { - LDIMERR("%s malloc error\n", __func__); - return; - } - - /* LD_FRM_SIZE */ - data = ((nPRM.reg_LD_pic_RowMax & 0xfff)<<16) | - (nPRM.reg_LD_pic_ColMax & 0xfff); - LDIM_WR_32Bits(REG_LD_FRM_SIZE, data); - - /* LD_RGB_MOD */ - data = ((0 & 0xfff) << 20) | - ((nPRM.reg_LD_RGBmapping_demo & 0x1) << 19) | - ((nPRM.reg_LD_X_LUT_interp_mode[2] & 0x1) << 18) | - ((nPRM.reg_LD_X_LUT_interp_mode[1] & 0x1) << 17) | - ((nPRM.reg_LD_X_LUT_interp_mode[0] & 0x1) << 16) | - ((0 & 0x1) << 15) | - ((nPRM.reg_LD_BkLit_LPFmod & 0x7) << 12) | - ((nPRM.reg_LD_Litshft & 0x7) << 8) | - ((nPRM.reg_LD_BackLit_Xtlk & 0x1) << 7) | - ((nPRM.reg_LD_BkLit_Intmod & 0x1) << 6) | - ((nPRM.reg_LD_BkLUT_Intmod & 0x1) << 5) | - ((nPRM.reg_LD_BkLit_curmod & 0x1) << 4) | - ((nPRM.reg_LD_BackLit_mode & 0x3)); - LDIM_WR_32Bits(REG_LD_RGB_MOD, data); - - /* LD_BLK_HVNUM */ - data = ((nPRM.reg_LD_Reflect_Vnum & 0x7) << 20) | - ((nPRM.reg_LD_Reflect_Hnum & 0x7) << 16) | - ((nPRM.reg_LD_BLK_Vnum & 0x3f) << 8) | - ((nPRM.reg_LD_BLK_Hnum & 0x3f)); - LDIM_WR_32Bits(REG_LD_BLK_HVNUM, data); - - /* LD_HVGAIN */ - data = ((nPRM.reg_LD_Vgain & 0xfff) << 16) | - (nPRM.reg_LD_Hgain & 0xfff); - LDIM_WR_32Bits(REG_LD_HVGAIN, data); - - /* LD_BKLIT_VLD */ - data = 0; - for (i = 0; i < 32; i++) - if (nPRM.reg_LD_BkLit_valid[i]) - data = data | (1 << i); - LDIM_WR_32Bits(REG_LD_BKLIT_VLD, data); - - /* LD_BKLIT_PARAM */ - data = ((nPRM.reg_LD_BkLit_Celnum & 0xff) << 16) | - (nPRM.reg_BL_matrix_AVG & 0xfff); - LDIM_WR_32Bits(REG_LD_BKLIT_PARAM, data); - - /* LD_LIT_GAIN_COMP */ - data = ((nPRM.reg_LD_Litgain & 0xfff) << 16) | - (nPRM.reg_BL_matrix_Compensate & 0xfff); - LDIM_WR_32Bits(REG_LD_LIT_GAIN_COMP, data); - - /* LD_FRM_RST_POS */ - data = (1 << 16) | (5); /* h=1,v=5 :ldim_param_frm_rst_pos */ - LDIM_WR_32Bits(REG_LD_FRM_RST_POS, data); - - /* LD_FRM_BL_START_POS */ - data = (1 << 16) | (6); /* ldim_param_frm_bl_start_pos; */ - LDIM_WR_32Bits(REG_LD_FRM_BL_START_POS, data); - - /* REG_LD_FRM_HBLAN_VHOLS */ - data = ((nPRM.reg_LD_LUT_VHo_LS & 0x7) << 16) | - ((6 & 0x1fff)) ; /*frm_hblank_num */ - LDIM_WR_32Bits(REG_LD_FRM_HBLAN_VHOLS, data); - - /* REG_LD_XLUT_DEMO_ROI_XPOS */ - data = ((nPRM.reg_LD_xlut_demo_roi_xend & 0x1fff) << 16) | - (nPRM.reg_LD_xlut_demo_roi_xstart & 0x1fff); - LDIM_WR_32Bits(REG_LD_XLUT_DEMO_ROI_XPOS, data); - - /* REG_LD_XLUT_DEMO_ROI_YPOS */ - data = ((nPRM.reg_LD_xlut_demo_roi_yend & 0x1fff) << 16) | - (nPRM.reg_LD_xlut_demo_roi_ystart & 0x1fff); - LDIM_WR_32Bits(REG_LD_XLUT_DEMO_ROI_YPOS, data); - - /* REG_LD_XLUT_DEMO_ROI_CTRL */ - data = ((nPRM.reg_LD_xlut_oroi_enable & 0x1) << 1) | - (nPRM.reg_LD_xlut_iroi_enable & 0x1); - LDIM_WR_32Bits(REG_LD_XLUT_DEMO_ROI_CTRL, data); - - /*LD_BLMAT_RAM_MISC*/ - LDIM_WR_32Bits(REG_LD_BLMAT_RAM_MISC, 384 & 0x1ff); - - /* X_idx: 12*16 */ - LDIM_WR_BASE_LUT(REG_LD_RGB_IDX_BASE, nPRM.X_idx[0], 16, 16); - - /* X_nrm[16]: 4 * 16 */ - LDIM_WR_BASE_LUT(REG_LD_RGB_NRMW_BASE_TXLX, nPRM.X_nrm[0], 4, 16); - - /*reg_LD_BLK_Hidx[33]: 14*33 */ - LDIM_WR_BASE_LUT(REG_LD_BLK_HIDX_BASE_TXLX, - nPRM.reg_LD_BLK_Hidx, 16, 33); - - /* reg_LD_BLK_Vidx[25]: 14*25 */ - LDIM_WR_BASE_LUT(REG_LD_BLK_VIDX_BASE_TXLX, - nPRM.reg_LD_BLK_Vidx, 16, 25); - - /* reg_LD_LUT_VHk_pos[32]/reg_LD_LUT_VHk_neg[32]: u8 */ - for (i = 0; i < 32; i++) - arrayTmp[i] = nPRM.reg_LD_LUT_VHk_pos[i]; - for (i = 0; i < 32; i++) - arrayTmp[32+i] = nPRM.reg_LD_LUT_VHk_neg[i]; - LDIM_WR_BASE_LUT(REG_LD_LUT_VHK_NEGPOS_BASE_TXLX, arrayTmp, 8, 64); - - /* reg_LD_LUT_VHo_pos[32]/reg_LD_LUT_VHo_neg[32]: s8 */ - for (i = 0; i < 32; i++) - arrayTmp[i] = nPRM.reg_LD_LUT_VHo_pos[i]; - for (i = 0; i < 32; i++) - arrayTmp[32+i] = nPRM.reg_LD_LUT_VHo_neg[i]; - LDIM_WR_BASE_LUT(REG_LD_LUT_VHO_NEGPOS_BASE_TXLX, arrayTmp, 8, 64); - - /* reg_LD_LUT_HHk[32]:u8 */ - LDIM_WR_BASE_LUT(REG_LD_LUT_HHK_BASE_TXLX, nPRM.reg_LD_LUT_HHk, 8, 32); - - /*reg_LD_Reflect_Hdgr[20],reg_LD_Reflect_Vdgr[20], - * reg_LD_Reflect_Xdgr[4] - */ - for (i = 0; i < 20; i++) - arrayTmp[i] = nPRM.reg_LD_Reflect_Hdgr[i]; - for (i = 0; i < 20; i++) - arrayTmp[20+i] = nPRM.reg_LD_Reflect_Vdgr[i]; - for (i = 0; i < 4; i++) - arrayTmp[40+i] = nPRM.reg_LD_Reflect_Xdgr[i]; - LDIM_WR_BASE_LUT(REG_LD_REFLECT_DGR_BASE_TXLX, arrayTmp, 8, 44); - - /*reg_LD_LUT_Hdg_LEXT[8]/reg_LD_LUT_Vdg_LEXT[8]/reg_LD_LUT_VHk_LEXT[8]*/ - for (i = 0; i < 8; i++) - arrayTmp[i] = (nPRM.reg_LD_LUT_Hdg_LEXT_TXLX[i] & 0x3ff) | - ((nPRM.reg_LD_LUT_VHk_LEXT_TXLX[i] & 0x3ff) << 10) | - ((nPRM.reg_LD_LUT_Vdg_LEXT_TXLX[i] & 0x3ff) << 20); - LDIM_WR_BASE_LUT_DRT(REG_LD_LUT_LEXT_BASE_TXLX, arrayTmp, 8); - - /*reg_LD_LUT_Hdg[8][32]: u10*8*32*/ - LDIM_WR_BASE_LUT(REG_LD_LUT_HDG_BASE_TXLX, - nPRM.reg_LD_LUT_Hdg_TXLX[0], 16, 8*32); - - /*reg_LD_LUT_Vdg[8][32]: u10*8*32*/ - LDIM_WR_BASE_LUT(REG_LD_LUT_VDG_BASE_TXLX, - nPRM.reg_LD_LUT_Vdg_TXLX[0], 16, 8*32); - - /*reg_LD_LUT_VHk[8][32]: u10*8*32*/ - LDIM_WR_BASE_LUT(REG_LD_LUT_VHK_BASE_TXLX, - nPRM.reg_LD_LUT_VHk_TXLX[0], 16, 8*32); - - /*reg_LD_LUT_Id[16][24]: u3*16*24=u3*384 */ - LDIM_WR_BASE_LUT(REG_LD_LUT_ID_BASE_TXLX, nPRM.reg_LD_LUT_Id, 4, 384); - - /*enable the CBUS configure the RAM*/ - /*LD_MISC_CTRL0 {reg_blmat_ram_mode, - *1'h0,ram_bus_sel,ram_clk_sel,ram_clk_gate_en, - *2'h0,reg_hvcnt_bypass,reg_demo_synmode,reg_ldbl_synmode, - *reg_ldim_bl_en,soft_bl_start,reg_soft_rst) - */ - data = LDIM_RD_32Bits(REG_LD_MISC_CTRL0); - data = (data & (~(3 << 9))) | (1 << 8); - LDIM_WR_32Bits(REG_LD_MISC_CTRL0, data); - - /*X_lut[3][16][16]*/ - LDIM_WR_BASE_LUT_DRT(REG_LD_RGB_LUT_BASE, nPRM.X_lut2[0][0], 3*16*16); - data = 0 | (0 << 1) | ((ldim_bl_en & 0x1) << 2) | - (ldim_hvcnt_bypass << 5) | (1 << 8) | - (3 << 9) | (1 << 12); - LDIM_WR_32Bits(REG_LD_MISC_CTRL0, data); - - LDIM_Update_Matrix(nPRM.BL_matrix, 16 * 24); - - kfree(arrayTmp); } static void LDIM_Initial(unsigned int pic_h, unsigned int pic_v, @@ -591,105 +355,23 @@ static void LDIM_Initial(unsigned int pic_h, unsigned int pic_v, LDIMERR("%s: invalid ldim_op_func\n", __func__); return; } - if (ldim_dev.ldim_op_func->ldim_init) - ldim_dev.ldim_op_func->ldim_init(ldim_bl_en, ldim_hvcnt_bypass); -} - -static void ldim_update_matrix(unsigned int mode) -{ - unsigned int data; - int bl_matrix[8] = {0}; - unsigned int reg_BL_matrix_Compensate = 0x0; - int bl_matrix_1[8] = {0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, - 0xfff, 0xfff}; - unsigned int reg_BL_matrix_Compensate_1 = 0xfff; - int bl_matrix_2[8] = {0xfff, 0xfff, 0xfff, 0x000, 0x000, 0xfff, - 0xfff, 0xfff}; - unsigned int reg_BL_matrix_Compensate_2 = 0xbff; - int bl_matrix_3[8] = {0, 0, 0, 0xfff, 0, 0, 0, 0}; - unsigned int reg_BL_matrix_Compensate_3 = 0x1ff; - int bl_matrix_4[8] = {0xfff, 0xfff, 0xfff, 0, 0xfff, 0xfff, - 0xfff, 0xfff}; - unsigned int reg_BL_matrix_Compensate_4 = 0xdff; - - data = LDIM_RD_32Bits(REG_LD_MISC_CTRL0); - data = data & (~(3<<4)); - LDIM_WR_32Bits(REG_LD_MISC_CTRL0, data); - - /* gMatrix_LUT: s12*100 ==> max to 8*8 enum ##r/w ram method*/ - if (mode == 0) { - LDIM_WR_BASE_LUT_DRT(REG_LD_MATRIX_BASE, - &bl_matrix[0], 8); - /* compensate */ - data = LDIM_RD_32Bits(REG_LD_LIT_GAIN_COMP); - data = data|(reg_BL_matrix_Compensate&0xfff); - LDIM_WR_32Bits(REG_LD_LIT_GAIN_COMP, data); - } else if (mode == 1) { - LDIM_WR_BASE_LUT_DRT(REG_LD_MATRIX_BASE, - &bl_matrix_1[0], 8); - /* compensate */ - data = LDIM_RD_32Bits(REG_LD_LIT_GAIN_COMP); - data = data | (reg_BL_matrix_Compensate_1 & 0xfff); - LDIM_WR_32Bits(REG_LD_LIT_GAIN_COMP, data); - } else if (mode == 2) { - LDIM_WR_BASE_LUT_DRT(REG_LD_MATRIX_BASE, - &bl_matrix_2[0], 8); - /* compensate */ - data = LDIM_RD_32Bits(REG_LD_LIT_GAIN_COMP); - data = data|(reg_BL_matrix_Compensate_2 & 0xfff); - LDIM_WR_32Bits(REG_LD_LIT_GAIN_COMP, data); - } else if (mode == 3) { - LDIM_WR_BASE_LUT_DRT(REG_LD_MATRIX_BASE, - &bl_matrix_3[0], 8); - /* compensate */ - data = LDIM_RD_32Bits(REG_LD_LIT_GAIN_COMP); - data = data | (reg_BL_matrix_Compensate_3 & 0xfff); - LDIM_WR_32Bits(REG_LD_LIT_GAIN_COMP, data); - } else if (mode == 4) { - LDIM_WR_BASE_LUT_DRT(REG_LD_MATRIX_BASE, - &bl_matrix_4[0], 8); - /* compensate */ - data = LDIM_RD_32Bits(REG_LD_LIT_GAIN_COMP); - data = data | (reg_BL_matrix_Compensate_4 & 0xfff); - LDIM_WR_32Bits(REG_LD_LIT_GAIN_COMP, data); + if (ldim_dev.ldim_op_func->ldim_init) { + ldim_dev.ldim_op_func->ldim_init(&nPRM, + ldim_bl_en, ldim_hvcnt_bypass); } - /* disable the CBUS configure the RAM */ - data = LDIM_RD_32Bits(REG_LD_MISC_CTRL0); - data = data | (3<<4); - LDIM_WR_32Bits(REG_LD_MISC_CTRL0, data); } -static void ldim_update_txlx(void) -{ - unsigned int data; - - if (ldim_avg_update_en) { - /* LD_BKLIT_PARAM */ - data = LDIM_RD_32Bits(REG_LD_BKLIT_PARAM); - data = (data&(~0xfff)) | (nPRM.reg_BL_matrix_AVG&0xfff); - LDIM_WR_32Bits(REG_LD_BKLIT_PARAM, data); - - /* compensate */ - data = LDIM_RD_32Bits(REG_LD_LIT_GAIN_COMP); - data = (data&(~0xfff)) | - (nPRM.reg_BL_matrix_Compensate & 0xfff); - LDIM_WR_32Bits(REG_LD_LIT_GAIN_COMP, data); - } - - if (ldim_matrix_update_en) - LDIM_Update_Matrix(nPRM.BL_matrix, ldim_blk_row*ldim_blk_col); - -} - -static void ldim_update_setting(void) +static void ldim_remap_update(void) { if (ldim_dev.ldim_op_func == NULL) { if (brightness_vs_cnt == 0) LDIMERR("%s: invalid ldim_op_func\n", __func__); return; } - if (ldim_dev.ldim_op_func->update_setting) - ldim_dev.ldim_op_func->update_setting(); + if (ldim_dev.ldim_op_func->remap_update) { + ldim_dev.ldim_op_func->remap_update(&nPRM, + ldim_avg_update_en, ldim_matrix_update_en); + } } static irqreturn_t ldim_vsync_isr(int irq, void *dev_id) @@ -706,7 +388,7 @@ static irqreturn_t ldim_vsync_isr(int irq, void *dev_id) if (ldim_func_en) { if (ldim_avg_update_en) - ldim_update_setting(); + ldim_remap_update(); if (ldim_hist_en) { /*schedule_work(&ldim_on_vs_work);*/ @@ -1293,7 +975,7 @@ static void ldim_get_matrix_info(void) } pr_info("current black_frm: %d\n", ldim_fw_para.black_frm); - pr_info("spi transfer_matrix:\n"); + pr_info("ldim_dev brightness transfer_matrix:\n"); for (i = 0; i < ldim_blk_row; i++) { len = 0; for (j = 0; j < ldim_blk_col; j++) { @@ -1662,7 +1344,8 @@ static int ldim_on_init(void) { int ret = 0; - LDIMPR("%s\n", __func__); + if (ldim_debug_print) + LDIMPR("%s\n", __func__); /* init ldim */ ldim_stts_initial(ldim_config.hsize, ldim_config.vsize, @@ -1745,6 +1428,7 @@ static struct aml_ldim_driver_s ldim_driver = { .valid_flag = 0, /* default invalid, active when bl_ctrl_method=ldim */ .dev_index = 0xff, .static_pic_flag = 0, + .vsync_change_flag = 0, .pinmux_flag = 0xff, .ldim_conf = &ldim_config, .ldev_conf = NULL, @@ -1774,6 +1458,45 @@ struct aml_ldim_driver_s *aml_ldim_get_driver(void) return &ldim_driver; } +/* ****************************************************** + * local dimming dummy function for virtual ldim dev + * ****************************************************** + */ +static int ldim_virtual_smr(unsigned short *buf, unsigned char len) +{ + return 0; +} + +static int ldim_virtual_power_on(void) +{ + return 0; +} + +static int ldim_virtual_power_off(void) +{ + return 0; +} + +static int ldim_virtual_driver_update(struct aml_ldim_driver_s *ldim_drv) +{ + ldim_drv->device_power_on = ldim_virtual_power_on; + ldim_drv->device_power_off = ldim_virtual_power_off; + ldim_drv->device_bri_update = ldim_virtual_smr; + + return 0; +} + +static int ldim_dev_add_virtual_driver(struct aml_ldim_driver_s *ldim_drv) +{ + LDIMPR("%s\n", __func__); + + ldim_virtual_driver_update(ldim_drv); + ldim_drv->init(); + + return 0; +} +/* ****************************************************** */ + static int ldim_open(struct inode *inode, struct file *file) { struct ldim_dev_s *devp; @@ -2355,16 +2078,6 @@ static ssize_t ldim_attr_store(struct class *cla, pr_info("reg_addr: 0x%x=0x%x, readback: 0x%x\n", reg_addr, reg_val, LDIM_RD_32Bits(reg_addr)); } - } else if (!strcmp(parm[0], "update_matrix")) { - unsigned int mode = 0; - - if (parm[1] != NULL) { - if (kstrtouint(parm[1], 10, &mode) < 0) - goto ldim_attr_store_err; - - ldim_update_matrix(mode); - pr_info("mode: %d\n", mode); - } } else if (!strcmp(parm[0], "bl_remap_curve")) { if (parm[1] != NULL) { if (!strcmp(parm[1], "r")) { @@ -2854,7 +2567,8 @@ static ssize_t ldim_attr_store(struct class *cla, ldim_fw_para.Dbprint_lv); } else if (!strcmp(parm[0], "info")) { pr_info("ldim_drv_ver: %s\n", LDIM_DRV_VER); - ldim_driver.config_print(); + if (ldim_driver.config_print) + ldim_driver.config_print(); pr_info("\nldim_blk_row = %d\n" "ldim_blk_col = %d\n" "ldim_hist_row = %d\n" @@ -2943,10 +2657,32 @@ static ssize_t ldim_func_en_store(struct class *class, return count; } +static ssize_t ldim_para_show(struct class *class, + struct class_attribute *attr, char *buf) +{ + int len = 0; + + len = sprintf(buf, "boost_gain=%d\n", ldim_fw_para.boost_gain); + + return len; +} + +static ssize_t ldim_dump_show(struct class *class, + struct class_attribute *attr, char *buf) +{ + int len = 0; + + len = ldim_hw_reg_dump(buf); + + return len; +} + static struct class_attribute aml_ldim_class_attrs[] = { __ATTR(attr, 0644, ldim_attr_show, ldim_attr_store), __ATTR(func_en, 0644, ldim_func_en_show, ldim_func_en_store), + __ATTR(para, 0644, ldim_para_show, NULL), + __ATTR(dump, 0644, ldim_dump_show, NULL), __ATTR_NULL, }; @@ -2999,7 +2735,8 @@ int aml_ldim_get_config_dts(struct device_node *child) LDIMERR("failed to get ldim_dev_index\n"); else ldim_driver.dev_index = (unsigned char)para[0]; - LDIMPR("get ldim_dev_index = %d\n", ldim_driver.dev_index); + if (ldim_driver.dev_index < 0xff) + LDIMPR("get ldim_dev_index = %d\n", ldim_driver.dev_index); return 0; } @@ -3031,7 +2768,8 @@ int aml_ldim_get_config_unifykey(unsigned char *buf) /* get ldim_dev_index 1byte*/ ldim_driver.dev_index = *(p + LCD_UKEY_BL_LDIM_DEV_INDEX); - LDIMPR("get dev_index = %d\n", ldim_driver.dev_index); + if (ldim_driver.dev_index < 0xff) + LDIMPR("get dev_index = %d\n", ldim_driver.dev_index); return 0; } @@ -3191,17 +2929,52 @@ ldim_malloc_err0: } static struct ldim_operate_func_s ldim_op_func_txlx = { - .update_setting = ldim_update_txlx, + .h_region_max = 24, + .v_region_max = 16, + .total_region_max = 384, + .remap_update = ldim_remap_update_txlx, .stts_init = ldim_stts_initial_txlx, .ldim_init = ldim_initial_txlx, }; static struct ldim_operate_func_s ldim_op_func_tl1 = { - .update_setting = NULL, - .stts_init = NULL, + .h_region_max = 31, + .v_region_max = 16, + .total_region_max = 128, + .remap_update = NULL, + .stts_init = ldim_stts_initial_tl1, .ldim_init = NULL, }; +static int ldim_region_num_check(struct ldim_operate_func_s *ldim_func) +{ + unsigned short temp; + + if (ldim_func == NULL) { + LDIMERR("%s: ldim_func is NULL\n", __func__); + return -1; + } + + if (ldim_config.row > ldim_func->v_region_max) { + LDIMERR("%s: blk row (%d) is out of support (%d)\n", + __func__, ldim_config.row, ldim_func->v_region_max); + return -1; + } + if (ldim_config.col > ldim_func->h_region_max) { + LDIMERR("%s: blk col (%d) is out of support (%d)\n", + __func__, ldim_config.col, ldim_func->h_region_max); + return -1; + } + temp = ldim_config.row * ldim_config.col; + if (temp > ldim_func->total_region_max) { + LDIMERR("%s: blk total region (%d) is out of support (%d)\n", + __func__, temp, ldim_func->total_region_max); + return -1; + } + + return 0; +} + int aml_ldim_probe(struct platform_device *pdev) { int ret = 0; @@ -3240,6 +3013,7 @@ int aml_ldim_probe(struct platform_device *pdev) /* ldim_op_func */ switch (bl_drv->data->chip_type) { case BL_CHIP_TL1: + case BL_CHIP_TM2: devp->ldim_op_func = &ldim_op_func_tl1; break; case BL_CHIP_TXLX: @@ -3249,6 +3023,9 @@ int aml_ldim_probe(struct platform_device *pdev) devp->ldim_op_func = NULL; break; } + ret = ldim_region_num_check(devp->ldim_op_func); + if (ret) + return -1; ret = aml_ldim_malloc(ldim_blk_row, ldim_blk_col); if (ret) { @@ -3319,12 +3096,18 @@ int aml_ldim_probe(struct platform_device *pdev) goto err; } ldim_vsync_irq = bl_drv->res_ldim_vsync_irq->start; - LDIMPR("ldim_vsync_irq: %d\n", ldim_vsync_irq); + if (ldim_debug_print) + LDIMPR("ldim_vsync_irq: %d\n", ldim_vsync_irq); if (request_irq(ldim_vsync_irq, ldim_vsync_isr, IRQF_SHARED, - "ldim_vsync", (void *)"ldim_vsync")) + "ldim_vsync", (void *)"ldim_vsync")) { LDIMERR("can't request ldim_vsync_irq\n"); - else - LDIMPR("request ldim_vsync_irq successful\n"); + } else { + if (ldim_debug_print) + LDIMPR("request ldim_vsync_irq successful\n"); + } + + if (bl_drv->bconf->method != BL_CTRL_LOCAL_DIMMING) + ldim_dev_add_virtual_driver(&ldim_driver); ldim_driver.valid_flag = 1; diff --git a/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_drv.h b/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_drv.h index dfd58f785a62..76c23ce4b7f6 100644 --- a/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_drv.h +++ b/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_drv.h @@ -24,7 +24,10 @@ /*20180730: algorithm clear up */ /*20180820: pq tooling support, espically optimize some alg parameters */ /*20181101: fix ldim_op_func null mistake, add new spi api support */ -#define LDIM_DRV_VER "20181101" +/*20181203: add 50/60hz change & iw7027 error handle support */ +/*20181220: add tl1 support*/ +/*20190103: add analog pwm support*/ +#define LDIM_DRV_VER "20190103" extern unsigned char ldim_debug_print; @@ -38,25 +41,36 @@ extern int LD_remap_lut[16][32]; /*========================================*/ struct ldim_operate_func_s { - void (*update_setting)(void); - void (*stts_init)(unsigned int resolution); - void (*ldim_init)(unsigned int bl_en, unsigned int hvcnt_bypass); + unsigned short h_region_max; + unsigned short v_region_max; + unsigned short total_region_max; + void (*remap_update)(struct LDReg_s *nPRM, + unsigned int avg_update_en, unsigned int matrix_update_en); + void (*stts_init)(unsigned int pic_h, unsigned int pic_v, + unsigned int blk_vnum, unsigned int blk_hnum); + void (*ldim_init)(struct LDReg_s *nPRM, + unsigned int bl_en, unsigned int hvcnt_bypass); }; /*========================================*/ extern int ldim_round(int ix, int ib); -extern void ldim_stts_en(unsigned int resolution, unsigned int pix_drop_mode, - unsigned int eol_en, unsigned int hist_mode, unsigned int lpf_en, - unsigned int rd_idx_auto_inc_mode, unsigned int one_ram_en); -extern void ldim_set_region(unsigned int resolution, unsigned int blk_height, - unsigned int blk_width, unsigned int row_start, unsigned int col_start, - unsigned int blk_hnum); extern void LD_ConLDReg(struct LDReg_s *Reg); extern void ld_fw_cfg_once(struct LDReg_s *nPRM); -extern void ldim_stts_read_region(unsigned int nrow, unsigned int ncol); +/* ldim hw */ +extern int ldim_hw_reg_dump(char *buf); +extern void ldim_stts_read_region(unsigned int nrow, unsigned int ncol); extern void ldim_set_matrix_ycbcr2rgb(void); extern void ldim_set_matrix_rgb2ycbcr(int mode); +extern void ldim_initial_txlx(struct LDReg_s *nPRM, + unsigned int ldim_bl_en, unsigned int ldim_hvcnt_bypass); +extern void ldim_stts_initial_txlx(unsigned int pic_h, unsigned int pic_v, + unsigned int blk_vnum, unsigned int blk_hnum); +extern void ldim_stts_initial_tl1(unsigned int pic_h, unsigned int pic_v, + unsigned int blk_vnum, unsigned int blk_hnum); +extern void ldim_remap_update_txlx(struct LDReg_s *nPRM, + unsigned int avg_update_en, unsigned int matrix_update_en); + #endif diff --git a/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_func.c b/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_func.c index 606cd542e203..613c6a728507 100644 --- a/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_func.c +++ b/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_func.c @@ -38,9 +38,6 @@ #define MIN(a, b) ((a < b) ? a:b) #endif -#define Wr(reg, val) Wr_reg(reg, val) -#define Rd(reg) Rd_reg(reg) - static int LD_BLK_Hidx[33] = { /* S14* 33 */ -1920, -1440, -960, -480, 0, 480, @@ -246,385 +243,6 @@ int ldim_round(int ix, int ib) return ld_rst; } -/***** local dimming stts functions begin *****/ -/*hist mode: 0: comp0 hist only, 1: Max(comp0,1,2) for hist, - *2: the hist of all comp0,1,2 are calculated - */ -/*lpf_en 1: 1,2,1 filter on before finding max& hist*/ -/*rd_idx_auto_inc_mode 0: no self increase, 1: read index increase after - *read a 25/48 block, 2: increases every read and lock sub-idx - */ -/*one_ram_en 1: one ram mode; 0:double ram mode*/ -void ldim_stts_en(unsigned int resolution, unsigned int pix_drop_mode, - unsigned int eol_en, unsigned int hist_mode, unsigned int lpf_en, - unsigned int rd_idx_auto_inc_mode, unsigned int one_ram_en) -{ - int data32; - - Wr(LDIM_STTS_GCLK_CTRL0, 0x0); - Wr(LDIM_STTS_WIDTHM1_HEIGHTM1, resolution); - - data32 = 0x80000000 | ((pix_drop_mode & 0x3) << 29); - data32 = data32 | ((eol_en & 0x1) << 28); - data32 = data32 | ((one_ram_en & 0x1) << 27); - data32 = data32 | ((hist_mode & 0x3) << 22); - data32 = data32 | ((lpf_en & 0x1) << 21); - data32 = data32 | ((rd_idx_auto_inc_mode & 0xff) << 14); - Wr(LDIM_STTS_HIST_REGION_IDX, data32); -} - -void ldim_set_region(unsigned int resolution, unsigned int blk_height, - unsigned int blk_width, unsigned int row_start, unsigned int col_start, - unsigned int blk_hnum) -{ - unsigned int hend0, hend1, hend2, hend3, hend4, hend5, - hend6, hend7, hend8, hend9, hend10, hend11, hend12, - hend13, hend14, hend15, hend16, hend17, hend18, - hend19, hend20, hend21, hend22, hend23; - unsigned int vend0, vend1, vend2, vend3, vend4, vend5, - vend6, vend7, vend8, vend9, vend10, vend11, - vend12, vend13, vend14, vend15; - unsigned int data32, k, h_index[24], v_index[16]; - - if (resolution == 0) { - h_index[0] = col_start + blk_width - 1; - for (k = 1; k < 24; k++) { - h_index[k] = h_index[k-1] + blk_width; - if (h_index[k] > 4095) - h_index[k] = 4095; /* clip U12 */ - } - v_index[0] = row_start + blk_height - 1; - for (k = 1; k < 16; k++) { - v_index[k] = v_index[k-1] + blk_height; - if (v_index[k] > 4095) - v_index[k] = 4095; /* clip U12 */ - } - hend0 = h_index[0];/*col_start + blk_width - 1;*/ - hend1 = h_index[1];/*hend0 + blk_width;*/ - hend2 = h_index[2];/*hend1 + blk_width;*/ - hend3 = h_index[3];/*hend2 + blk_width;*/ - hend4 = h_index[4];/*hend3 + blk_width;*/ - hend5 = h_index[5];/*hend4 + blk_width;*/ - hend6 = h_index[6];/*hend5 + blk_width;*/ - hend7 = h_index[7];/*hend6 + blk_width;*/ - hend8 = h_index[8];/*hend7 + blk_width;*/ - hend9 = h_index[9];/*hend8 + blk_width;*/ - hend10 = h_index[10];/*hend9 + blk_width ;*/ - hend11 = h_index[11];/*hend10 + blk_width;*/ - hend12 = h_index[12];/*hend11 + blk_width;*/ - hend13 = h_index[13];/*hend12 + blk_width;*/ - hend14 = h_index[14];/*hend13 + blk_width;*/ - hend15 = h_index[15];/*hend14 + blk_width;*/ - hend16 = h_index[16];/*hend15 + blk_width;*/ - hend17 = h_index[17];/*hend16 + blk_width;*/ - hend18 = h_index[18];/*hend17 + blk_width;*/ - hend19 = h_index[19];/*hend18 + blk_width;*/ - hend20 = h_index[20];/*hend19 + blk_width ;*/ - hend21 = h_index[21];/*hend20 + blk_width;*/ - hend22 = h_index[22];/*hend21 + blk_width;*/ - hend23 = h_index[23];/*hend22 + blk_width;*/ - vend0 = v_index[0];/*row_start + blk_height - 1;*/ - vend1 = v_index[1];/*vend0 + blk_height;*/ - vend2 = v_index[2];/*vend1 + blk_height;*/ - vend3 = v_index[3];/*vend2 + blk_height;*/ - vend4 = v_index[4];/*vend3 + blk_height;*/ - vend5 = v_index[5];/*vend4 + blk_height;*/ - vend6 = v_index[6];/*vend5 + blk_height;*/ - vend7 = v_index[7];/*vend6 + blk_height;*/ - vend8 = v_index[8];/*vend7 + blk_height;*/ - vend9 = v_index[9];/*vend8 + blk_height;*/ - vend10 = v_index[10];/*vend9 + blk_height;*/ - vend11 = v_index[11];/*vend10 + blk_height;*/ - vend12 = v_index[12];/*vend11 + blk_height;*/ - vend13 = v_index[13];/*vend12 + blk_height;*/ - vend14 = v_index[14];/*vend13 + blk_height;*/ - vend15 = v_index[15];/*vend14 + blk_height;*/ - - data32 = Rd(LDIM_STTS_HIST_REGION_IDX); - Wr(LDIM_STTS_HIST_REGION_IDX, 0xffe0ffff & data32); - Wr(LDIM_STTS_HIST_SET_REGION, ((((row_start & 0x1fff) << 16) - & 0xffff0000) | (col_start & 0x1fff))); - Wr(LDIM_STTS_HIST_SET_REGION, (((hend1 & 0x1fff) << 16) - | (hend0 & 0x1fff))); - Wr(LDIM_STTS_HIST_SET_REGION, (((vend1 & 0x1fff) << 16) - | (vend0 & 0x1fff))); - Wr(LDIM_STTS_HIST_SET_REGION, (((hend3 & 0x1fff) << 16) - | (hend2 & 0x1fff))); - Wr(LDIM_STTS_HIST_SET_REGION, (((vend3 & 0x1fff) << 16) - | (vend2 & 0x1fff))); - Wr(LDIM_STTS_HIST_SET_REGION, (((hend5 & 0x1fff) << 16) - | (hend4 & 0x1fff))); - Wr(LDIM_STTS_HIST_SET_REGION, (((vend5 & 0x1fff) << 16) - | (vend4 & 0x1fff))); - Wr(LDIM_STTS_HIST_SET_REGION, (((hend7 & 0x1fff) << 16) - | (hend6 & 0x1fff))); - Wr(LDIM_STTS_HIST_SET_REGION, (((vend7 & 0x1fff) << 16) - | (vend6 & 0x1fff))); - Wr(LDIM_STTS_HIST_SET_REGION, (((hend9 & 0x1fff) << 16) - | (hend8 & 0x1fff))); - Wr(LDIM_STTS_HIST_SET_REGION, (((vend9 & 0x1fff) << 16) - | (vend8 & 0x1fff))); - Wr(LDIM_STTS_HIST_SET_REGION, (((hend11 & 0x1fff) << 16) - | (hend10 & 0x1fff))); - Wr(LDIM_STTS_HIST_SET_REGION, (((vend11 & 0x1fff) << 16) - | (vend10 & 0x1fff))); - Wr(LDIM_STTS_HIST_SET_REGION, (((hend13 & 0x1fff) << 16) - | (hend12 & 0x1fff))); - Wr(LDIM_STTS_HIST_SET_REGION, (((vend13 & 0x1fff) << 16) - | (vend12 & 0x1fff))); - Wr(LDIM_STTS_HIST_SET_REGION, (((hend15 & 0x1fff) << 16) - | (hend14 & 0x1fff))); - Wr(LDIM_STTS_HIST_SET_REGION, (((vend15 & 0x1fff) << 16) - | (vend14 & 0x1fff))); - Wr(LDIM_STTS_HIST_SET_REGION, (((hend17 & 0x1fff) << 16) - | (hend16 & 0x1fff))); - Wr(LDIM_STTS_HIST_SET_REGION, (((hend19 & 0x1fff) << 16) - | (hend18 & 0x1fff))); - Wr(LDIM_STTS_HIST_SET_REGION, (((hend21 & 0x1fff) << 16) - | (hend20 & 0x1fff))); - Wr(LDIM_STTS_HIST_SET_REGION, (((hend23 & 0x1fff) << 16) - | (hend22 & 0x1fff))); - Wr(LDIM_STTS_HIST_SET_REGION, blk_hnum); /*h region number*/ - Wr(LDIM_STTS_HIST_SET_REGION, 0); /*line_n_int_num*/ - } else if (resolution == 1) { - data32 = Rd(LDIM_STTS_HIST_REGION_IDX); - Wr(LDIM_STTS_HIST_REGION_IDX, 0xfff0ffff & data32); - Wr(LDIM_STTS_HIST_SET_REGION, 0x0010010); - Wr(LDIM_STTS_HIST_SET_REGION, 0x1000080); - Wr(LDIM_STTS_HIST_SET_REGION, 0x0800040); - Wr(LDIM_STTS_HIST_SET_REGION, 0x2000180); - Wr(LDIM_STTS_HIST_SET_REGION, 0x10000c0); - Wr(LDIM_STTS_HIST_SET_REGION, 0x3000280); - Wr(LDIM_STTS_HIST_SET_REGION, 0x1800140); - Wr(LDIM_STTS_HIST_SET_REGION, 0x4000380); - Wr(LDIM_STTS_HIST_SET_REGION, 0x20001c0); - /*Wr(LDIM_STTS_HIST_SET_REGION, 0x4ff0480);*/ - /*Wr(LDIM_STTS_HIST_SET_REGION, 0x2cf0260);*/ - } else if (resolution == 2) { - data32 = Rd(LDIM_STTS_HIST_REGION_IDX); - Wr(LDIM_STTS_HIST_REGION_IDX, 0xfff0ffff & data32); - - Wr(LDIM_STTS_HIST_SET_REGION, 0x0000000);/*hv00*/ - Wr(LDIM_STTS_HIST_SET_REGION, 0x17f00bf);/*h01*/ - Wr(LDIM_STTS_HIST_SET_REGION, 0x0d7006b);/*v01*/ - Wr(LDIM_STTS_HIST_SET_REGION, 0x2ff023f);/*h23*/ - Wr(LDIM_STTS_HIST_SET_REGION, 0x1af0143);/*v23*/ - Wr(LDIM_STTS_HIST_SET_REGION, 0x47f03bf);/*h45*/ - Wr(LDIM_STTS_HIST_SET_REGION, 0x287021b);/*v45*/ - Wr(LDIM_STTS_HIST_SET_REGION, 0x5ff053f);/*h67*/ - Wr(LDIM_STTS_HIST_SET_REGION, 0x35f02f3);/*v67*/ - Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/*h89*/ - Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/*v89*/ - Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/*h1011*/ - Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/*v1011*/ - Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/*h1213*/ - Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/*v1213*/ - Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/*h1415*/ - Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/*v1415*/ - Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/*h1617*/ - Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/*h1819*/ - Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/*h2021*/ - Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/*h2223*/ - } else if (resolution == 3) { - data32 = Rd(LDIM_STTS_HIST_REGION_IDX); - Wr(LDIM_STTS_HIST_REGION_IDX, 0xfff0ffff & data32); - - Wr(LDIM_STTS_HIST_SET_REGION, 0x0000000); - Wr(LDIM_STTS_HIST_SET_REGION, 0x1df00ef); - Wr(LDIM_STTS_HIST_SET_REGION, 0x10d0086); - Wr(LDIM_STTS_HIST_SET_REGION, 0x3bf02cf); - Wr(LDIM_STTS_HIST_SET_REGION, 0x21b0194); - Wr(LDIM_STTS_HIST_SET_REGION, 0x59f04af); - Wr(LDIM_STTS_HIST_SET_REGION, 0x32902a2); - Wr(LDIM_STTS_HIST_SET_REGION, 0x77f068f); - Wr(LDIM_STTS_HIST_SET_REGION, 0x43703b0); - /*Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780);*/ - /*Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438);*/ - } else if (resolution == 4) { /* 5x6 */ - data32 = Rd(LDIM_STTS_HIST_REGION_IDX); - Wr(LDIM_STTS_HIST_REGION_IDX, 0xfff0ffff & data32); - - Wr(LDIM_STTS_HIST_SET_REGION, 0x0040001); - Wr(LDIM_STTS_HIST_SET_REGION, 0x27f0136); - Wr(LDIM_STTS_HIST_SET_REGION, 0x1af00d7); - Wr(LDIM_STTS_HIST_SET_REGION, 0x4ff03bf); - Wr(LDIM_STTS_HIST_SET_REGION, 0x35f0287); - Wr(LDIM_STTS_HIST_SET_REGION, 0x77f063f); - Wr(LDIM_STTS_HIST_SET_REGION, 0x4380437); - Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); - Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); - /*Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780);*/ - /*Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438);*/ - } else if (resolution == 5) { /* 8x2 */ - data32 = Rd(LDIM_STTS_HIST_REGION_IDX); - Wr(LDIM_STTS_HIST_REGION_IDX, 0xfff0ffff & data32); - - Wr(LDIM_STTS_HIST_SET_REGION, 0x0030002); - Wr(LDIM_STTS_HIST_SET_REGION, 0x31f02bb); - Wr(LDIM_STTS_HIST_SET_REGION, 0x0940031); - Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); - Wr(LDIM_STTS_HIST_SET_REGION, 0x233012b); - Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); - Wr(LDIM_STTS_HIST_SET_REGION, 0x30b0243); - Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); - Wr(LDIM_STTS_HIST_SET_REGION, 0x42d03d3); - /*Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780);*/ - /*Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438);*/ - } else if (resolution == 6) { /* 2x1 */ - data32 = Rd(LDIM_STTS_HIST_REGION_IDX); - Wr(LDIM_STTS_HIST_REGION_IDX, 0xfff0ffff & data32); - - Wr(LDIM_STTS_HIST_SET_REGION, 0x0030002); - Wr(LDIM_STTS_HIST_SET_REGION, 0x78002bb); - Wr(LDIM_STTS_HIST_SET_REGION, 0x0940031); - Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); - Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); - Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); - Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); - Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); - Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); - /*Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780);*/ - /*Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438);*/ - } else if (resolution == 7) { /* 2x2 */ - data32 = Rd(LDIM_STTS_HIST_REGION_IDX); - Wr(LDIM_STTS_HIST_REGION_IDX, 0xfff0ffff & data32); - - Wr(LDIM_STTS_HIST_SET_REGION, 0x0000000); - Wr(LDIM_STTS_HIST_SET_REGION, 0x77f03bf); - Wr(LDIM_STTS_HIST_SET_REGION, 0x437021b); - Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); - Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); - Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); - Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); - Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); - Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); - /*Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780);*/ - /*Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438);*/ - } else if (resolution == 8) { /* 3x5 */ - data32 = Rd(LDIM_STTS_HIST_REGION_IDX); - Wr(LDIM_STTS_HIST_REGION_IDX, 0xfff0ffff & data32); - - Wr(LDIM_STTS_HIST_SET_REGION, 0x0000000); - Wr(LDIM_STTS_HIST_SET_REGION, 0x2ff017f); - Wr(LDIM_STTS_HIST_SET_REGION, 0x2cf0167); - Wr(LDIM_STTS_HIST_SET_REGION, 0x5ff047f); - Wr(LDIM_STTS_HIST_SET_REGION, 0x4380437); - Wr(LDIM_STTS_HIST_SET_REGION, 0x780077f); - Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); - Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); - Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); - /*Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780);*/ - /*Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438);*/ - } else if (resolution == 9) { /* 4x3 */ - data32 = Rd(LDIM_STTS_HIST_REGION_IDX); - Wr(LDIM_STTS_HIST_REGION_IDX, 0xfff0ffff & data32); - - Wr(LDIM_STTS_HIST_SET_REGION, 0x0010001); - Wr(LDIM_STTS_HIST_SET_REGION, 0x4560333); - Wr(LDIM_STTS_HIST_SET_REGION, 0x2220180); - Wr(LDIM_STTS_HIST_SET_REGION, 0x7800666); - Wr(LDIM_STTS_HIST_SET_REGION, 0x4000338); - Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); - Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); - Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); - Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); - /*Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780);*/ - /*Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438);*/ - } else if (resolution == 10) { /* 6x8 */ - data32 = Rd(LDIM_STTS_HIST_REGION_IDX); - Wr(LDIM_STTS_HIST_REGION_IDX, 0xfff0ffff & data32); - - Wr(LDIM_STTS_HIST_SET_REGION, 0x0010001); - Wr(LDIM_STTS_HIST_SET_REGION, 0x2430167); - Wr(LDIM_STTS_HIST_SET_REGION, 0x2220180); - Wr(LDIM_STTS_HIST_SET_REGION, 0x4000350); - Wr(LDIM_STTS_HIST_SET_REGION, 0x4000338); - Wr(LDIM_STTS_HIST_SET_REGION, 0x6000510); - Wr(LDIM_STTS_HIST_SET_REGION, 0x4370410); - Wr(LDIM_STTS_HIST_SET_REGION, 0x77f0700); - Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); - /*Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780);*/ - /*Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438);*/ - } -} - -static unsigned int invalid_val_cnt; -void ldim_stts_read_region(unsigned int nrow, unsigned int ncol) -{ - unsigned int i, j, k; - unsigned int data32; - struct aml_ldim_driver_s *ldim_drv = aml_ldim_get_driver(); - - if (invalid_val_cnt > 0xfffffff) - invalid_val_cnt = 0; - - Wr(LDIM_STTS_HIST_REGION_IDX, Rd(LDIM_STTS_HIST_REGION_IDX) - & 0xffffc000); - data32 = Rd(LDIM_STTS_HIST_START_RD_REGION); - - for (i = 0; i < nrow; i++) { - for (j = 0; j < ncol; j++) { - data32 = Rd(LDIM_STTS_HIST_START_RD_REGION); - for (k = 0; k < 17; k++) { - if (k == 16) { - data32 = Rd(LDIM_STTS_HIST_READ_REGION); - ldim_drv->max_rgb[i * ncol + j] - = data32; - } else { - data32 = Rd(LDIM_STTS_HIST_READ_REGION); - ldim_drv->hist_matrix[i * ncol * 16 + - j * 16 + k] = data32; - } - if (!(data32 & 0x40000000)) - invalid_val_cnt++; - } - } - } -} - -/* VDIN_MATRIX_YUV601_RGB */ -/* -16 1.164 0 1.596 0 */ -/* -128 1.164 -0.391 -0.813 0 */ -/* -128 1.164 2.018 0 0 */ -/*{0x07c00600, 0x00000600, 0x04a80000, 0x066204a8, 0x1e701cbf, 0x04a80812, - * 0x00000000, 0x00000000, 0x00000000,}, - */ -void ldim_set_matrix_ycbcr2rgb(void) -{ - Wr_reg_bits(LDIM_STTS_CTRL0, 1, 2, 1); /* enable matrix */ - - Wr(LDIM_STTS_MATRIX_PRE_OFFSET0_1, 0x07c00600); - Wr(LDIM_STTS_MATRIX_PRE_OFFSET2, 0x00000600); - Wr(LDIM_STTS_MATRIX_COEF00_01, 0x04a80000); - Wr(LDIM_STTS_MATRIX_COEF02_10, 0x066204a8); - Wr(LDIM_STTS_MATRIX_COEF11_12, 0x1e701cbf); - Wr(LDIM_STTS_MATRIX_COEF20_21, 0x04a80812); - Wr(LDIM_STTS_MATRIX_COEF22, 0x00000000); - Wr(LDIM_STTS_MATRIX_OFFSET0_1, 0x00000000); - Wr(LDIM_STTS_MATRIX_OFFSET2, 0x00000000); -} - -void ldim_set_matrix_rgb2ycbcr(int mode) -{ - Wr_reg_bits(LDIM_STTS_CTRL0, 1, 2, 1); - if (mode == 0) {/*ycbcr not full range, 601 conversion*/ - Wr(LDIM_STTS_MATRIX_PRE_OFFSET0_1, 0x0); - Wr(LDIM_STTS_MATRIX_PRE_OFFSET2, 0x0); - /* 0.257 0.504 0.098 */ - /* -0.148 -0.291 0.439 */ - /* 0.439 -0.368 -0.071 */ - Wr(LDIM_STTS_MATRIX_COEF00_01, (0x107 << 16) | 0x204); - Wr(LDIM_STTS_MATRIX_COEF02_10, (0x64 << 16) | 0x1f68); - Wr(LDIM_STTS_MATRIX_COEF11_12, (0x1ed6 << 16) | 0x1c2); - Wr(LDIM_STTS_MATRIX_COEF20_21, (0x1c2 << 16) | 0x1e87); - Wr(LDIM_STTS_MATRIX_COEF22, 0x1fb7); - - Wr(LDIM_STTS_MATRIX_OFFSET2, 0x0200); - } else if (mode == 1) {/*ycbcr full range, 601 conversion*/ - /* todo */ - } -} - int Round(int iX, int iB) { int Rst = 0; diff --git a/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_hw.c b/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_hw.c new file mode 100644 index 000000000000..7d2dcc1f83b1 --- /dev/null +++ b/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_hw.c @@ -0,0 +1,1021 @@ +/* + * drivers/amlogic/media/vout/backlight/aml_ldim/ldim_hw.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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ldim_drv.h" +#include "ldim_reg.h" + +#define Wr(reg, val) Wr_reg(reg, val) +#define Rd(reg) Rd_reg(reg) + +static int LDIM_Update_Matrix(int NewBlMatrix[], int BlMatrixNum) +{ + int data; + + data = LDIM_RD_32Bits(REG_LD_MISC_CTRL0); + if (data & (1 << 12)) { /*bl_ram_mode=1;*/ + if (LDIM_RD_32Bits(REG_LD_BLMAT_RAM_MISC) & 0x10000) + /*Previous Matrix is not used*/ + goto Previous_Matrix; + else { + LDIM_WR_BASE_LUT_DRT(REG_LD_MATRIX_BASE, + NewBlMatrix, BlMatrixNum); + LDIM_WR_32Bits(REG_LD_BLMAT_RAM_MISC, + (BlMatrixNum & 0x1ff) | (1 << 16)); + /*set Matrix update ready*/ + + return 0; + } + } else { /*bl_ram_mode=0*/ + /*set ram_clk_sel=0, ram_bus_sel = 0*/ + data = data & (~(3 << 9)); + LDIM_WR_32Bits(REG_LD_MISC_CTRL0, data); + LDIM_WR_BASE_LUT_DRT(REG_LD_MATRIX_BASE, + NewBlMatrix, BlMatrixNum); + data = data | (3 << 9); /*set ram_clk_sel=1, ram_bus_sel = 1*/ + LDIM_WR_32Bits(REG_LD_MISC_CTRL0, data); + + return 0; + } + +Previous_Matrix: + return 1; +} + +void ldim_initial_txlx(struct LDReg_s *nPRM, + unsigned int ldim_bl_en, unsigned int ldim_hvcnt_bypass) +{ + unsigned int i; + unsigned int data; + unsigned int *arrayTmp; + + arrayTmp = kcalloc(1536, sizeof(unsigned int), GFP_KERNEL); + if (arrayTmp == NULL) { + LDIMERR("%s malloc error\n", __func__); + return; + } + + /* LD_FRM_SIZE */ + data = ((nPRM->reg_LD_pic_RowMax & 0xfff)<<16) | + (nPRM->reg_LD_pic_ColMax & 0xfff); + LDIM_WR_32Bits(REG_LD_FRM_SIZE, data); + + /* LD_RGB_MOD */ + data = ((0 & 0xfff) << 20) | + ((nPRM->reg_LD_RGBmapping_demo & 0x1) << 19) | + ((nPRM->reg_LD_X_LUT_interp_mode[2] & 0x1) << 18) | + ((nPRM->reg_LD_X_LUT_interp_mode[1] & 0x1) << 17) | + ((nPRM->reg_LD_X_LUT_interp_mode[0] & 0x1) << 16) | + ((0 & 0x1) << 15) | + ((nPRM->reg_LD_BkLit_LPFmod & 0x7) << 12) | + ((nPRM->reg_LD_Litshft & 0x7) << 8) | + ((nPRM->reg_LD_BackLit_Xtlk & 0x1) << 7) | + ((nPRM->reg_LD_BkLit_Intmod & 0x1) << 6) | + ((nPRM->reg_LD_BkLUT_Intmod & 0x1) << 5) | + ((nPRM->reg_LD_BkLit_curmod & 0x1) << 4) | + ((nPRM->reg_LD_BackLit_mode & 0x3)); + LDIM_WR_32Bits(REG_LD_RGB_MOD, data); + + /* LD_BLK_HVNUM */ + data = ((nPRM->reg_LD_Reflect_Vnum & 0x7) << 20) | + ((nPRM->reg_LD_Reflect_Hnum & 0x7) << 16) | + ((nPRM->reg_LD_BLK_Vnum & 0x3f) << 8) | + ((nPRM->reg_LD_BLK_Hnum & 0x3f)); + LDIM_WR_32Bits(REG_LD_BLK_HVNUM, data); + + /* LD_HVGAIN */ + data = ((nPRM->reg_LD_Vgain & 0xfff) << 16) | + (nPRM->reg_LD_Hgain & 0xfff); + LDIM_WR_32Bits(REG_LD_HVGAIN, data); + + /* LD_BKLIT_VLD */ + data = 0; + for (i = 0; i < 32; i++) + if (nPRM->reg_LD_BkLit_valid[i]) + data = data | (1 << i); + LDIM_WR_32Bits(REG_LD_BKLIT_VLD, data); + + /* LD_BKLIT_PARAM */ + data = ((nPRM->reg_LD_BkLit_Celnum & 0xff) << 16) | + (nPRM->reg_BL_matrix_AVG & 0xfff); + LDIM_WR_32Bits(REG_LD_BKLIT_PARAM, data); + + /* LD_LIT_GAIN_COMP */ + data = ((nPRM->reg_LD_Litgain & 0xfff) << 16) | + (nPRM->reg_BL_matrix_Compensate & 0xfff); + LDIM_WR_32Bits(REG_LD_LIT_GAIN_COMP, data); + + /* LD_FRM_RST_POS */ + data = (1 << 16) | (5); /* h=1,v=5 :ldim_param_frm_rst_pos */ + LDIM_WR_32Bits(REG_LD_FRM_RST_POS, data); + + /* LD_FRM_BL_START_POS */ + data = (1 << 16) | (6); /* ldim_param_frm_bl_start_pos; */ + LDIM_WR_32Bits(REG_LD_FRM_BL_START_POS, data); + + /* REG_LD_FRM_HBLAN_VHOLS */ + data = ((nPRM->reg_LD_LUT_VHo_LS & 0x7) << 16) | + ((6 & 0x1fff)) ; /*frm_hblank_num */ + LDIM_WR_32Bits(REG_LD_FRM_HBLAN_VHOLS, data); + + /* REG_LD_XLUT_DEMO_ROI_XPOS */ + data = ((nPRM->reg_LD_xlut_demo_roi_xend & 0x1fff) << 16) | + (nPRM->reg_LD_xlut_demo_roi_xstart & 0x1fff); + LDIM_WR_32Bits(REG_LD_XLUT_DEMO_ROI_XPOS, data); + + /* REG_LD_XLUT_DEMO_ROI_YPOS */ + data = ((nPRM->reg_LD_xlut_demo_roi_yend & 0x1fff) << 16) | + (nPRM->reg_LD_xlut_demo_roi_ystart & 0x1fff); + LDIM_WR_32Bits(REG_LD_XLUT_DEMO_ROI_YPOS, data); + + /* REG_LD_XLUT_DEMO_ROI_CTRL */ + data = ((nPRM->reg_LD_xlut_oroi_enable & 0x1) << 1) | + (nPRM->reg_LD_xlut_iroi_enable & 0x1); + LDIM_WR_32Bits(REG_LD_XLUT_DEMO_ROI_CTRL, data); + + /*LD_BLMAT_RAM_MISC*/ + LDIM_WR_32Bits(REG_LD_BLMAT_RAM_MISC, 384 & 0x1ff); + + /* X_idx: 12*16 */ + LDIM_WR_BASE_LUT(REG_LD_RGB_IDX_BASE, nPRM->X_idx[0], 16, 16); + + /* X_nrm[16]: 4 * 16 */ + LDIM_WR_BASE_LUT(REG_LD_RGB_NRMW_BASE_TXLX, nPRM->X_nrm[0], 4, 16); + + /*reg_LD_BLK_Hidx[33]: 14*33 */ + LDIM_WR_BASE_LUT(REG_LD_BLK_HIDX_BASE_TXLX, + nPRM->reg_LD_BLK_Hidx, 16, 33); + + /* reg_LD_BLK_Vidx[25]: 14*25 */ + LDIM_WR_BASE_LUT(REG_LD_BLK_VIDX_BASE_TXLX, + nPRM->reg_LD_BLK_Vidx, 16, 25); + + /* reg_LD_LUT_VHk_pos[32]/reg_LD_LUT_VHk_neg[32]: u8 */ + for (i = 0; i < 32; i++) + arrayTmp[i] = nPRM->reg_LD_LUT_VHk_pos[i]; + for (i = 0; i < 32; i++) + arrayTmp[32+i] = nPRM->reg_LD_LUT_VHk_neg[i]; + LDIM_WR_BASE_LUT(REG_LD_LUT_VHK_NEGPOS_BASE_TXLX, arrayTmp, 8, 64); + + /* reg_LD_LUT_VHo_pos[32]/reg_LD_LUT_VHo_neg[32]: s8 */ + for (i = 0; i < 32; i++) + arrayTmp[i] = nPRM->reg_LD_LUT_VHo_pos[i]; + for (i = 0; i < 32; i++) + arrayTmp[32+i] = nPRM->reg_LD_LUT_VHo_neg[i]; + LDIM_WR_BASE_LUT(REG_LD_LUT_VHO_NEGPOS_BASE_TXLX, arrayTmp, 8, 64); + + /* reg_LD_LUT_HHk[32]:u8 */ + LDIM_WR_BASE_LUT(REG_LD_LUT_HHK_BASE_TXLX, nPRM->reg_LD_LUT_HHk, 8, 32); + + /*reg_LD_Reflect_Hdgr[20],reg_LD_Reflect_Vdgr[20], + * reg_LD_Reflect_Xdgr[4] + */ + for (i = 0; i < 20; i++) + arrayTmp[i] = nPRM->reg_LD_Reflect_Hdgr[i]; + for (i = 0; i < 20; i++) + arrayTmp[20+i] = nPRM->reg_LD_Reflect_Vdgr[i]; + for (i = 0; i < 4; i++) + arrayTmp[40+i] = nPRM->reg_LD_Reflect_Xdgr[i]; + LDIM_WR_BASE_LUT(REG_LD_REFLECT_DGR_BASE_TXLX, arrayTmp, 8, 44); + + /*reg_LD_LUT_Hdg_LEXT[8]/reg_LD_LUT_Vdg_LEXT[8]/reg_LD_LUT_VHk_LEXT[8]*/ + for (i = 0; i < 8; i++) + arrayTmp[i] = (nPRM->reg_LD_LUT_Hdg_LEXT_TXLX[i] & 0x3ff) | + ((nPRM->reg_LD_LUT_VHk_LEXT_TXLX[i] & 0x3ff) << 10) | + ((nPRM->reg_LD_LUT_Vdg_LEXT_TXLX[i] & 0x3ff) << 20); + LDIM_WR_BASE_LUT_DRT(REG_LD_LUT_LEXT_BASE_TXLX, arrayTmp, 8); + + /*reg_LD_LUT_Hdg[8][32]: u10*8*32*/ + LDIM_WR_BASE_LUT(REG_LD_LUT_HDG_BASE_TXLX, + nPRM->reg_LD_LUT_Hdg_TXLX[0], 16, 8*32); + + /*reg_LD_LUT_Vdg[8][32]: u10*8*32*/ + LDIM_WR_BASE_LUT(REG_LD_LUT_VDG_BASE_TXLX, + nPRM->reg_LD_LUT_Vdg_TXLX[0], 16, 8*32); + + /*reg_LD_LUT_VHk[8][32]: u10*8*32*/ + LDIM_WR_BASE_LUT(REG_LD_LUT_VHK_BASE_TXLX, + nPRM->reg_LD_LUT_VHk_TXLX[0], 16, 8*32); + + /*reg_LD_LUT_Id[16][24]: u3*16*24=u3*384 */ + LDIM_WR_BASE_LUT(REG_LD_LUT_ID_BASE_TXLX, nPRM->reg_LD_LUT_Id, 4, 384); + + /*enable the CBUS configure the RAM*/ + /*LD_MISC_CTRL0 {reg_blmat_ram_mode, + *1'h0,ram_bus_sel,ram_clk_sel,ram_clk_gate_en, + *2'h0,reg_hvcnt_bypass,reg_demo_synmode,reg_ldbl_synmode, + *reg_ldim_bl_en,soft_bl_start,reg_soft_rst) + */ + data = LDIM_RD_32Bits(REG_LD_MISC_CTRL0); + data = (data & (~(3 << 9))) | (1 << 8); + LDIM_WR_32Bits(REG_LD_MISC_CTRL0, data); + + /*X_lut[3][16][16]*/ + LDIM_WR_BASE_LUT_DRT(REG_LD_RGB_LUT_BASE, nPRM->X_lut2[0][0], 3*16*16); + + data = 0 | (0 << 1) | ((ldim_bl_en & 0x1) << 2) | + (ldim_hvcnt_bypass << 5) | (1 << 8) | + (3 << 9) | (1 << 12); + LDIM_WR_32Bits(REG_LD_MISC_CTRL0, data); + + LDIM_Update_Matrix(nPRM->BL_matrix, 16 * 24); + + kfree(arrayTmp); +} + +static unsigned int ldim_hw_reg_dump_table[] = { + LDIM_STTS_GCLK_CTRL0, + LDIM_STTS_WIDTHM1_HEIGHTM1, + LDIM_STTS_CTRL0, + LDIM_STTS_HIST_REGION_IDX, +}; + +int ldim_hw_reg_dump(char *buf) +{ + unsigned int reg, data32; + int i, size, len = 0; + + size = sizeof(ldim_hw_reg_dump_table) / sizeof(unsigned int); + for (i = 0; i < size; i++) { + reg = ldim_hw_reg_dump_table[i]; + data32 = Rd(reg); + len += sprintf(buf+len, "0x%x = 0x%08x\n", reg, data32); + } + + data32 = Rd(LDIM_STTS_HIST_REGION_IDX); + Wr(LDIM_STTS_HIST_REGION_IDX, 0xffe0ffff & data32); + for (i = 0; i < 23; i++) { + reg = LDIM_STTS_HIST_SET_REGION; + data32 = Rd(reg); + len += sprintf(buf+len, "0x%x = 0x%08x\n", reg, data32); + } + + return len; +} + +/***** local dimming stts functions begin *****/ +/*hist mode: 0: comp0 hist only, 1: Max(comp0,1,2) for hist, + *2: the hist of all comp0,1,2 are calculated + */ +/*lpf_en 1: 1,2,1 filter on before finding max& hist*/ +/*rd_idx_auto_inc_mode 0: no self increase, 1: read index increase after + *read a 25/48 block, 2: increases every read and lock sub-idx + */ +/*one_ram_en 1: one ram mode; 0:double ram mode*/ +static void ldim_stts_en(unsigned int resolution, unsigned int pix_drop_mode, + unsigned int eol_en, unsigned int hist_mode, unsigned int lpf_en, + unsigned int rd_idx_auto_inc_mode, unsigned int one_ram_en) +{ + int data32; + + Wr(LDIM_STTS_GCLK_CTRL0, 0x0); + Wr(LDIM_STTS_WIDTHM1_HEIGHTM1, resolution); + + data32 = 0x80000000 | ((pix_drop_mode & 0x3) << 29); + data32 = data32 | ((eol_en & 0x1) << 28); + data32 = data32 | ((one_ram_en & 0x1) << 27); + data32 = data32 | ((hist_mode & 0x3) << 22); + data32 = data32 | ((lpf_en & 0x1) << 21); + data32 = data32 | ((rd_idx_auto_inc_mode & 0xff) << 14); + Wr(LDIM_STTS_HIST_REGION_IDX, data32); +} + +static void ldim_stts_set_region_txlx(unsigned int resolution, + unsigned int blk_height, unsigned int blk_width, + unsigned int row_start, unsigned int col_start, + unsigned int blk_hnum) +{ + unsigned int hend0, hend1, hend2, hend3, hend4, hend5, + hend6, hend7, hend8, hend9, hend10, hend11, hend12, + hend13, hend14, hend15, hend16, hend17, hend18, + hend19, hend20, hend21, hend22, hend23; + unsigned int vend0, vend1, vend2, vend3, vend4, vend5, + vend6, vend7, vend8, vend9, vend10, vend11, + vend12, vend13, vend14, vend15; + unsigned int data32, k, h_index[24], v_index[16]; + + if (resolution == 0) { + h_index[0] = col_start + blk_width - 1; + for (k = 1; k < 24; k++) { + h_index[k] = h_index[k-1] + blk_width; + if (h_index[k] > 4095) + h_index[k] = 4095; /* clip U12 */ + } + v_index[0] = row_start + blk_height - 1; + for (k = 1; k < 16; k++) { + v_index[k] = v_index[k-1] + blk_height; + if (v_index[k] > 4095) + v_index[k] = 4095; /* clip U12 */ + } + hend0 = h_index[0];/*col_start + blk_width - 1;*/ + hend1 = h_index[1];/*hend0 + blk_width;*/ + hend2 = h_index[2];/*hend1 + blk_width;*/ + hend3 = h_index[3];/*hend2 + blk_width;*/ + hend4 = h_index[4];/*hend3 + blk_width;*/ + hend5 = h_index[5];/*hend4 + blk_width;*/ + hend6 = h_index[6];/*hend5 + blk_width;*/ + hend7 = h_index[7];/*hend6 + blk_width;*/ + hend8 = h_index[8];/*hend7 + blk_width;*/ + hend9 = h_index[9];/*hend8 + blk_width;*/ + hend10 = h_index[10];/*hend9 + blk_width ;*/ + hend11 = h_index[11];/*hend10 + blk_width;*/ + hend12 = h_index[12];/*hend11 + blk_width;*/ + hend13 = h_index[13];/*hend12 + blk_width;*/ + hend14 = h_index[14];/*hend13 + blk_width;*/ + hend15 = h_index[15];/*hend14 + blk_width;*/ + hend16 = h_index[16];/*hend15 + blk_width;*/ + hend17 = h_index[17];/*hend16 + blk_width;*/ + hend18 = h_index[18];/*hend17 + blk_width;*/ + hend19 = h_index[19];/*hend18 + blk_width;*/ + hend20 = h_index[20];/*hend19 + blk_width ;*/ + hend21 = h_index[21];/*hend20 + blk_width;*/ + hend22 = h_index[22];/*hend21 + blk_width;*/ + hend23 = h_index[23];/*hend22 + blk_width;*/ + vend0 = v_index[0];/*row_start + blk_height - 1;*/ + vend1 = v_index[1];/*vend0 + blk_height;*/ + vend2 = v_index[2];/*vend1 + blk_height;*/ + vend3 = v_index[3];/*vend2 + blk_height;*/ + vend4 = v_index[4];/*vend3 + blk_height;*/ + vend5 = v_index[5];/*vend4 + blk_height;*/ + vend6 = v_index[6];/*vend5 + blk_height;*/ + vend7 = v_index[7];/*vend6 + blk_height;*/ + vend8 = v_index[8];/*vend7 + blk_height;*/ + vend9 = v_index[9];/*vend8 + blk_height;*/ + vend10 = v_index[10];/*vend9 + blk_height;*/ + vend11 = v_index[11];/*vend10 + blk_height;*/ + vend12 = v_index[12];/*vend11 + blk_height;*/ + vend13 = v_index[13];/*vend12 + blk_height;*/ + vend14 = v_index[14];/*vend13 + blk_height;*/ + vend15 = v_index[15];/*vend14 + blk_height;*/ + + data32 = Rd(LDIM_STTS_HIST_REGION_IDX); + Wr(LDIM_STTS_HIST_REGION_IDX, 0xffe0ffff & data32); + Wr(LDIM_STTS_HIST_SET_REGION, + ((((row_start & 0x1fff) << 16) & 0xffff0000) | + (col_start & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((hend1 & 0x1fff) << 16) + | (hend0 & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((vend1 & 0x1fff) << 16) + | (vend0 & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((hend3 & 0x1fff) << 16) + | (hend2 & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((vend3 & 0x1fff) << 16) + | (vend2 & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((hend5 & 0x1fff) << 16) + | (hend4 & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((vend5 & 0x1fff) << 16) + | (vend4 & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((hend7 & 0x1fff) << 16) + | (hend6 & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((vend7 & 0x1fff) << 16) + | (vend6 & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((hend9 & 0x1fff) << 16) + | (hend8 & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((vend9 & 0x1fff) << 16) + | (vend8 & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((hend11 & 0x1fff) << 16) + | (hend10 & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((vend11 & 0x1fff) << 16) + | (vend10 & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((hend13 & 0x1fff) << 16) + | (hend12 & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((vend13 & 0x1fff) << 16) + | (vend12 & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((hend15 & 0x1fff) << 16) + | (hend14 & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((vend15 & 0x1fff) << 16) + | (vend14 & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((hend17 & 0x1fff) << 16) + | (hend16 & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((hend19 & 0x1fff) << 16) + | (hend18 & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((hend21 & 0x1fff) << 16) + | (hend20 & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((hend23 & 0x1fff) << 16) + | (hend22 & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, blk_hnum); /*h region number*/ + Wr(LDIM_STTS_HIST_SET_REGION, 0); /*line_n_int_num*/ + } else if (resolution == 1) { + data32 = Rd(LDIM_STTS_HIST_REGION_IDX); + Wr(LDIM_STTS_HIST_REGION_IDX, 0xfff0ffff & data32); + Wr(LDIM_STTS_HIST_SET_REGION, 0x0010010); + Wr(LDIM_STTS_HIST_SET_REGION, 0x1000080); + Wr(LDIM_STTS_HIST_SET_REGION, 0x0800040); + Wr(LDIM_STTS_HIST_SET_REGION, 0x2000180); + Wr(LDIM_STTS_HIST_SET_REGION, 0x10000c0); + Wr(LDIM_STTS_HIST_SET_REGION, 0x3000280); + Wr(LDIM_STTS_HIST_SET_REGION, 0x1800140); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4000380); + Wr(LDIM_STTS_HIST_SET_REGION, 0x20001c0); + /*Wr(LDIM_STTS_HIST_SET_REGION, 0x4ff0480);*/ + /*Wr(LDIM_STTS_HIST_SET_REGION, 0x2cf0260);*/ + } else if (resolution == 2) { + data32 = Rd(LDIM_STTS_HIST_REGION_IDX); + Wr(LDIM_STTS_HIST_REGION_IDX, 0xfff0ffff & data32); + + Wr(LDIM_STTS_HIST_SET_REGION, 0x0000000);/*hv00*/ + Wr(LDIM_STTS_HIST_SET_REGION, 0x17f00bf);/*h01*/ + Wr(LDIM_STTS_HIST_SET_REGION, 0x0d7006b);/*v01*/ + Wr(LDIM_STTS_HIST_SET_REGION, 0x2ff023f);/*h23*/ + Wr(LDIM_STTS_HIST_SET_REGION, 0x1af0143);/*v23*/ + Wr(LDIM_STTS_HIST_SET_REGION, 0x47f03bf);/*h45*/ + Wr(LDIM_STTS_HIST_SET_REGION, 0x287021b);/*v45*/ + Wr(LDIM_STTS_HIST_SET_REGION, 0x5ff053f);/*h67*/ + Wr(LDIM_STTS_HIST_SET_REGION, 0x35f02f3);/*v67*/ + Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/*h89*/ + Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/*v89*/ + Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/*h1011*/ + Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/*v1011*/ + Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/*h1213*/ + Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/*v1213*/ + Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/*h1415*/ + Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/*v1415*/ + Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/*h1617*/ + Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/*h1819*/ + Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/*h2021*/ + Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/*h2223*/ + } else if (resolution == 3) { + data32 = Rd(LDIM_STTS_HIST_REGION_IDX); + Wr(LDIM_STTS_HIST_REGION_IDX, 0xfff0ffff & data32); + + Wr(LDIM_STTS_HIST_SET_REGION, 0x0000000); + Wr(LDIM_STTS_HIST_SET_REGION, 0x1df00ef); + Wr(LDIM_STTS_HIST_SET_REGION, 0x10d0086); + Wr(LDIM_STTS_HIST_SET_REGION, 0x3bf02cf); + Wr(LDIM_STTS_HIST_SET_REGION, 0x21b0194); + Wr(LDIM_STTS_HIST_SET_REGION, 0x59f04af); + Wr(LDIM_STTS_HIST_SET_REGION, 0x32902a2); + Wr(LDIM_STTS_HIST_SET_REGION, 0x77f068f); + Wr(LDIM_STTS_HIST_SET_REGION, 0x43703b0); + /*Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780);*/ + /*Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438);*/ + } else if (resolution == 4) { /* 5x6 */ + data32 = Rd(LDIM_STTS_HIST_REGION_IDX); + Wr(LDIM_STTS_HIST_REGION_IDX, 0xfff0ffff & data32); + + Wr(LDIM_STTS_HIST_SET_REGION, 0x0040001); + Wr(LDIM_STTS_HIST_SET_REGION, 0x27f0136); + Wr(LDIM_STTS_HIST_SET_REGION, 0x1af00d7); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4ff03bf); + Wr(LDIM_STTS_HIST_SET_REGION, 0x35f0287); + Wr(LDIM_STTS_HIST_SET_REGION, 0x77f063f); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4380437); + Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); + /*Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780);*/ + /*Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438);*/ + } else if (resolution == 5) { /* 8x2 */ + data32 = Rd(LDIM_STTS_HIST_REGION_IDX); + Wr(LDIM_STTS_HIST_REGION_IDX, 0xfff0ffff & data32); + + Wr(LDIM_STTS_HIST_SET_REGION, 0x0030002); + Wr(LDIM_STTS_HIST_SET_REGION, 0x31f02bb); + Wr(LDIM_STTS_HIST_SET_REGION, 0x0940031); + Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); + Wr(LDIM_STTS_HIST_SET_REGION, 0x233012b); + Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); + Wr(LDIM_STTS_HIST_SET_REGION, 0x30b0243); + Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); + Wr(LDIM_STTS_HIST_SET_REGION, 0x42d03d3); + /*Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780);*/ + /*Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438);*/ + } else if (resolution == 6) { /* 2x1 */ + data32 = Rd(LDIM_STTS_HIST_REGION_IDX); + Wr(LDIM_STTS_HIST_REGION_IDX, 0xfff0ffff & data32); + + Wr(LDIM_STTS_HIST_SET_REGION, 0x0030002); + Wr(LDIM_STTS_HIST_SET_REGION, 0x78002bb); + Wr(LDIM_STTS_HIST_SET_REGION, 0x0940031); + Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); + Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); + Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); + /*Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780);*/ + /*Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438);*/ + } else if (resolution == 7) { /* 2x2 */ + data32 = Rd(LDIM_STTS_HIST_REGION_IDX); + Wr(LDIM_STTS_HIST_REGION_IDX, 0xfff0ffff & data32); + + Wr(LDIM_STTS_HIST_SET_REGION, 0x0000000); + Wr(LDIM_STTS_HIST_SET_REGION, 0x77f03bf); + Wr(LDIM_STTS_HIST_SET_REGION, 0x437021b); + Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); + Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); + Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); + /*Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780);*/ + /*Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438);*/ + } else if (resolution == 8) { /* 3x5 */ + data32 = Rd(LDIM_STTS_HIST_REGION_IDX); + Wr(LDIM_STTS_HIST_REGION_IDX, 0xfff0ffff & data32); + + Wr(LDIM_STTS_HIST_SET_REGION, 0x0000000); + Wr(LDIM_STTS_HIST_SET_REGION, 0x2ff017f); + Wr(LDIM_STTS_HIST_SET_REGION, 0x2cf0167); + Wr(LDIM_STTS_HIST_SET_REGION, 0x5ff047f); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4380437); + Wr(LDIM_STTS_HIST_SET_REGION, 0x780077f); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); + Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); + /*Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780);*/ + /*Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438);*/ + } else if (resolution == 9) { /* 4x3 */ + data32 = Rd(LDIM_STTS_HIST_REGION_IDX); + Wr(LDIM_STTS_HIST_REGION_IDX, 0xfff0ffff & data32); + + Wr(LDIM_STTS_HIST_SET_REGION, 0x0010001); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4560333); + Wr(LDIM_STTS_HIST_SET_REGION, 0x2220180); + Wr(LDIM_STTS_HIST_SET_REGION, 0x7800666); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4000338); + Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); + Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); + /*Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780);*/ + /*Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438);*/ + } else if (resolution == 10) { /* 6x8 */ + data32 = Rd(LDIM_STTS_HIST_REGION_IDX); + Wr(LDIM_STTS_HIST_REGION_IDX, 0xfff0ffff & data32); + + Wr(LDIM_STTS_HIST_SET_REGION, 0x0010001); + Wr(LDIM_STTS_HIST_SET_REGION, 0x2430167); + Wr(LDIM_STTS_HIST_SET_REGION, 0x2220180); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4000350); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4000338); + Wr(LDIM_STTS_HIST_SET_REGION, 0x6000510); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4370410); + Wr(LDIM_STTS_HIST_SET_REGION, 0x77f0700); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); + /*Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780);*/ + /*Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438);*/ + } +} + +static void ldim_stts_set_region_tl1( + unsigned int resolution, + /* 0: auto calc by height/width/row_start/col_start + * 1: 720p + * 2: 1080p + */ + unsigned int height, unsigned int width, + unsigned int blk_height, unsigned int blk_width, + unsigned int row_start, unsigned int col_start, + unsigned int blk_vnum, unsigned int blk_hnum) +{ + unsigned int data32, h_region_num; + unsigned int heightm1, widthm1; + unsigned int lights_mode = 0; + unsigned int hend[24], vend[16], i; + + memset(hend, 0, (sizeof(unsigned int) * 24)); + memset(vend, 0, (sizeof(unsigned int) * 16)); + + /* 0:normal 1:>24 h region */ + if (blk_hnum > 24) + lights_mode = 1; + h_region_num = blk_hnum; + if (ldim_debug_print) { + pr_info("%s: lights_mode=%d, h_region_num=%d\n", + __func__, lights_mode, h_region_num); + } + + heightm1 = height - 1; + widthm1 = width - 1; + + if (resolution == 0) { + hend[0] = col_start + blk_width - 1; + for (i = 1; i < 24; i++) { + hend[i] = (hend[i-1] + blk_width >= widthm1) ? + hend[i-1] : (hend[i-1] + blk_width); + } + vend[0] = row_start + blk_height - 1; + for (i = 1; i < 16; i++) { + vend[i] = (vend[i-1] + blk_height >= heightm1) ? + vend[i-1] : (vend[i-1] + blk_height); + } + + if (lights_mode == 1) { /* 31 h region */ + vend[8] = (hend[23] + blk_width >= widthm1) ? + hend[23] : (hend[23] + blk_width); + for (i = 9; i < 16; i++) { + vend[i] = (vend[i-1] + blk_width >= widthm1) ? + vend[i-1] : (vend[i-1] + blk_width); + } + } + + Wr_reg_bits(LDIM_STTS_CTRL0, lights_mode, 22, 2); + data32 = Rd(LDIM_STTS_HIST_REGION_IDX); + Wr(LDIM_STTS_HIST_REGION_IDX, 0xffe0ffff & data32); + Wr(LDIM_STTS_HIST_SET_REGION, + ((((row_start & 0x1fff) << 16) & 0xffff0000) | + (col_start & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((hend[1] & 0x1fff) << 16) | + (hend[0] & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((vend[1] & 0x1fff) << 16) | + (vend[0] & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((hend[3] & 0x1fff) << 16) | + (hend[2] & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((vend[3] & 0x1fff) << 16) | + (vend[2] & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((hend[5] & 0x1fff) << 16) | + (hend[4] & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((vend[5] & 0x1fff) << 16) | + (vend[4] & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((hend[7] & 0x1fff) << 16) | + (hend[6] & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((vend[7] & 0x1fff) << 16) | + (vend[6] & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((hend[9] & 0x1fff) << 16) | + (hend[8] & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((vend[9] & 0x1fff) << 16) | + (vend[8] & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((hend[11] & 0x1fff) << 16) | + (hend[10] & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((vend[11] & 0x1fff) << 16) | + (vend[10] & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((hend[13] & 0x1fff) << 16) | + (hend[12] & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((vend[13] & 0x1fff) << 16) | + (vend[12] & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((hend[15] & 0x1fff) << 16) | + (hend[14] & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((vend[15] & 0x1fff) << 16) | + (vend[14] & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((hend[17] & 0x1fff) << 16) | + (hend[16] & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((hend[19] & 0x1fff) << 16) | + (hend[18] & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((hend[21] & 0x1fff) << 16) | + (hend[20] & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((hend[23] & 0x1fff) << 16) | + (hend[22] & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, h_region_num); /*h region number*/ + Wr(LDIM_STTS_HIST_SET_REGION, 0); /* line_n_int_num */ + } else if (resolution == 1) { + data32 = Rd(LDIM_STTS_HIST_REGION_IDX); + Wr(LDIM_STTS_HIST_REGION_IDX, 0xfff0ffff & data32); + + Wr(LDIM_STTS_HIST_SET_REGION, 0x0010010); + Wr(LDIM_STTS_HIST_SET_REGION, 0x1000080); + Wr(LDIM_STTS_HIST_SET_REGION, 0x0800040); + Wr(LDIM_STTS_HIST_SET_REGION, 0x2000180); + Wr(LDIM_STTS_HIST_SET_REGION, 0x10000c0); + Wr(LDIM_STTS_HIST_SET_REGION, 0x3000280); + Wr(LDIM_STTS_HIST_SET_REGION, 0x1800140); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4000380); + Wr(LDIM_STTS_HIST_SET_REGION, 0x20001c0); + /* Wr(LDIM_STTS_HIST_SET_REGION, 0x4ff0480); */ + /* Wr(LDIM_STTS_HIST_SET_REGION, 0x2cf0260); */ + } else if (resolution == 2) { + data32 = Rd(LDIM_STTS_HIST_REGION_IDX); + Wr(LDIM_STTS_HIST_REGION_IDX, 0xfff0ffff & data32); + + Wr(LDIM_STTS_HIST_SET_REGION, 0x0000000);/* hv00 */ + Wr(LDIM_STTS_HIST_SET_REGION, 0x17f00bf);/* h01 */ + Wr(LDIM_STTS_HIST_SET_REGION, 0x0d7006b);/* v01 */ + Wr(LDIM_STTS_HIST_SET_REGION, 0x2ff023f);/* h23 */ + Wr(LDIM_STTS_HIST_SET_REGION, 0x1af0143);/* v23 */ + Wr(LDIM_STTS_HIST_SET_REGION, 0x47f03bf);/* h45 */ + Wr(LDIM_STTS_HIST_SET_REGION, 0x287021b);/* v45 */ + Wr(LDIM_STTS_HIST_SET_REGION, 0x5ff053f);/* h67 */ + Wr(LDIM_STTS_HIST_SET_REGION, 0x35f02f3);/* v67 */ + Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/* h89 */ + Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/* v89 */ + Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/* h1011 */ + Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/* v1011 */ + Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/* h1213 */ + Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/* v1213 */ + Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/* h1415 */ + Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/* v1415 */ + Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/* h1617 */ + Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/* h1819 */ + Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/* h2021 */ + Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/* h2223 */ + } else if (resolution == 3) { + data32 = Rd(LDIM_STTS_HIST_REGION_IDX); + Wr(LDIM_STTS_HIST_REGION_IDX, 0xfff0ffff & data32); + + Wr(LDIM_STTS_HIST_SET_REGION, 0x0000000); + Wr(LDIM_STTS_HIST_SET_REGION, 0x1df00ef); + Wr(LDIM_STTS_HIST_SET_REGION, 0x10d0086); + Wr(LDIM_STTS_HIST_SET_REGION, 0x3bf02cf); + Wr(LDIM_STTS_HIST_SET_REGION, 0x21b0194); + Wr(LDIM_STTS_HIST_SET_REGION, 0x59f04af); + Wr(LDIM_STTS_HIST_SET_REGION, 0x32902a2); + Wr(LDIM_STTS_HIST_SET_REGION, 0x77f068f); + Wr(LDIM_STTS_HIST_SET_REGION, 0x43703b0); + /* Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); */ + /* Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); */ + } else if (resolution == 4) { /* 5x6 */ + data32 = Rd(LDIM_STTS_HIST_REGION_IDX); + Wr(LDIM_STTS_HIST_REGION_IDX, 0xfff0ffff & data32); + + Wr(LDIM_STTS_HIST_SET_REGION, 0x0040001); + Wr(LDIM_STTS_HIST_SET_REGION, 0x27f0136); + Wr(LDIM_STTS_HIST_SET_REGION, 0x1af00d7); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4ff03bf); + Wr(LDIM_STTS_HIST_SET_REGION, 0x35f0287); + Wr(LDIM_STTS_HIST_SET_REGION, 0x77f063f); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4380437); + Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); + /* Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); */ + /* Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); */ + } else if (resolution == 5) { /* 8x2 */ + data32 = Rd(LDIM_STTS_HIST_REGION_IDX); + Wr(LDIM_STTS_HIST_REGION_IDX, 0xfff0ffff & data32); + + Wr(LDIM_STTS_HIST_SET_REGION, 0x0030002); + Wr(LDIM_STTS_HIST_SET_REGION, 0x31f02bb); + Wr(LDIM_STTS_HIST_SET_REGION, 0x0940031); + Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); + Wr(LDIM_STTS_HIST_SET_REGION, 0x233012b); + Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); + Wr(LDIM_STTS_HIST_SET_REGION, 0x30b0243); + Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); + Wr(LDIM_STTS_HIST_SET_REGION, 0x42d03d3); + /* Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); */ + /* Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); */ + } else if (resolution == 6) { /* 2x1 */ + data32 = Rd(LDIM_STTS_HIST_REGION_IDX); + Wr(LDIM_STTS_HIST_REGION_IDX, 0xfff0ffff & data32); + + Wr(LDIM_STTS_HIST_SET_REGION, 0x0030002); + Wr(LDIM_STTS_HIST_SET_REGION, 0x78002bb); + Wr(LDIM_STTS_HIST_SET_REGION, 0x0940031); + Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); + Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); + Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); + /* Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); */ + /* Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); */ + } else if (resolution == 7) { /* 2x2 */ + data32 = Rd(LDIM_STTS_HIST_REGION_IDX); + Wr(LDIM_STTS_HIST_REGION_IDX, 0xfff0ffff & data32); + + Wr(LDIM_STTS_HIST_SET_REGION, 0x0000000); + Wr(LDIM_STTS_HIST_SET_REGION, 0x77f03bf); + Wr(LDIM_STTS_HIST_SET_REGION, 0x437021b); + Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); + Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); + Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); + /* Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); */ + /* Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); */ + } else if (resolution == 8) { /* 3x5 */ + data32 = Rd(LDIM_STTS_HIST_REGION_IDX); + Wr(LDIM_STTS_HIST_REGION_IDX, 0xfff0ffff & data32); + + Wr(LDIM_STTS_HIST_SET_REGION, 0x0000000); + Wr(LDIM_STTS_HIST_SET_REGION, 0x2ff017f); + Wr(LDIM_STTS_HIST_SET_REGION, 0x2cf0167); + Wr(LDIM_STTS_HIST_SET_REGION, 0x5ff047f); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4380437); + Wr(LDIM_STTS_HIST_SET_REGION, 0x780077f); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); + Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); + /* Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); */ + /* Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); */ + } else if (resolution == 9) { /* 4x3 */ + data32 = Rd(LDIM_STTS_HIST_REGION_IDX); + Wr(LDIM_STTS_HIST_REGION_IDX, 0xfff0ffff & data32); + + Wr(LDIM_STTS_HIST_SET_REGION, 0x0010001); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4560333); + Wr(LDIM_STTS_HIST_SET_REGION, 0x2220180); + Wr(LDIM_STTS_HIST_SET_REGION, 0x7800666); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4000338); + Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); + Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); + /* Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); */ + /* Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); */ + } else if (resolution == 10) { /* 6x8 */ + data32 = Rd(LDIM_STTS_HIST_REGION_IDX); + Wr(LDIM_STTS_HIST_REGION_IDX, 0xfff0ffff & data32); + + Wr(LDIM_STTS_HIST_SET_REGION, 0x0010001); + Wr(LDIM_STTS_HIST_SET_REGION, 0x2430167); + Wr(LDIM_STTS_HIST_SET_REGION, 0x2220180); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4000350); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4000338); + Wr(LDIM_STTS_HIST_SET_REGION, 0x6000510); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4370410); + Wr(LDIM_STTS_HIST_SET_REGION, 0x77f0700); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); + /* Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); */ + /* Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); */ + } +} + +void ldim_stts_initial_txlx(unsigned int pic_h, unsigned int pic_v, + unsigned int blk_vnum, unsigned int blk_hnum) +{ + unsigned int resolution, blk_height, blk_width; + unsigned int row_start, col_start; + + blk_vnum = (blk_vnum == 0) ? 1 : blk_vnum; + blk_hnum = (blk_hnum == 0) ? 1 : blk_hnum; + + resolution = (((pic_h - 1) & 0xffff) << 16) | ((pic_v - 1) & 0xffff); + /*Wr_reg(VDIN0_HIST_CTRL, 0x10d);*/ + + blk_height = (pic_v - 8) / blk_vnum; + blk_width = (pic_h - 8) / blk_hnum; + row_start = (pic_v - (blk_height * blk_vnum)) >> 1; + col_start = (pic_h - (blk_width * blk_hnum)) >> 1; + + Wr_reg(LDIM_STTS_CTRL0, 7 << 2); + ldim_set_matrix_ycbcr2rgb(); + ldim_stts_en(resolution, 0, 0, 1, 1, 1, 0); + + ldim_stts_set_region_txlx(0, blk_height, blk_width, + row_start, col_start, blk_hnum); +} + +void ldim_stts_initial_tl1(unsigned int pic_h, unsigned int pic_v, + unsigned int blk_vnum, unsigned int blk_hnum) +{ + unsigned int resolution, blk_height, blk_width; + unsigned int row_start, col_start; + + blk_vnum = (blk_vnum == 0) ? 1 : blk_vnum; + blk_hnum = (blk_hnum == 0) ? 1 : blk_hnum; + + resolution = (((pic_h - 1) & 0xffff) << 16) | ((pic_v - 1) & 0xffff); + /*Wr_reg(VDIN0_HIST_CTRL, 0x10d);*/ + + blk_height = (pic_v - 8) / blk_vnum; + blk_width = (pic_h - 8) / blk_hnum; + row_start = (pic_v - (blk_height * blk_vnum)) >> 1; + col_start = (pic_h - (blk_width * blk_hnum)) >> 1; + + ldim_stts_en(resolution, 0, 0, 1, 1, 1, 0); + ldim_set_matrix_ycbcr2rgb(); + /*0:di 1:vdin 2:null 3:postblend 4:vpp out 5:vd1 6:vd2 7:osd1*/ + Wr_reg_bits(LDIM_STTS_CTRL0, 3, 3, 3); + + ldim_stts_set_region_tl1(0, pic_v, pic_h, blk_height, blk_width, + row_start, col_start, blk_vnum, blk_hnum); +} + +static unsigned int invalid_val_cnt; +void ldim_stts_read_region(unsigned int nrow, unsigned int ncol) +{ + unsigned int i, j, k; + unsigned int data32; + struct aml_ldim_driver_s *ldim_drv = aml_ldim_get_driver(); + + if (invalid_val_cnt > 0xfffffff) + invalid_val_cnt = 0; + + Wr(LDIM_STTS_HIST_REGION_IDX, Rd(LDIM_STTS_HIST_REGION_IDX) + & 0xffffc000); + data32 = Rd(LDIM_STTS_HIST_START_RD_REGION); + + for (i = 0; i < nrow; i++) { + for (j = 0; j < ncol; j++) { + data32 = Rd(LDIM_STTS_HIST_START_RD_REGION); + for (k = 0; k < 17; k++) { + if (k == 16) { + data32 = Rd(LDIM_STTS_HIST_READ_REGION); + ldim_drv->max_rgb[i * ncol + j] + = data32; + } else { + data32 = Rd(LDIM_STTS_HIST_READ_REGION); + ldim_drv->hist_matrix[i * ncol * 16 + + j * 16 + k] = data32; + } + if (!(data32 & 0x40000000)) + invalid_val_cnt++; + } + } + } +} + +/* VDIN_MATRIX_YUV601_RGB */ +/* -16 1.164 0 1.596 0 */ +/* -128 1.164 -0.391 -0.813 0 */ +/* -128 1.164 2.018 0 0 */ +/*{0x07c00600, 0x00000600, 0x04a80000, 0x066204a8, 0x1e701cbf, 0x04a80812, + * 0x00000000, 0x00000000, 0x00000000,}, + */ +void ldim_set_matrix_ycbcr2rgb(void) +{ + Wr_reg_bits(LDIM_STTS_CTRL0, 1, 2, 1); /* enable matrix */ + + Wr(LDIM_STTS_MATRIX_PRE_OFFSET0_1, 0x07c00600); + Wr(LDIM_STTS_MATRIX_PRE_OFFSET2, 0x00000600); + Wr(LDIM_STTS_MATRIX_COEF00_01, 0x04a80000); + Wr(LDIM_STTS_MATRIX_COEF02_10, 0x066204a8); + Wr(LDIM_STTS_MATRIX_COEF11_12, 0x1e701cbf); + Wr(LDIM_STTS_MATRIX_COEF20_21, 0x04a80812); + Wr(LDIM_STTS_MATRIX_COEF22, 0x00000000); + Wr(LDIM_STTS_MATRIX_OFFSET0_1, 0x00000000); + Wr(LDIM_STTS_MATRIX_OFFSET2, 0x00000000); +} + +void ldim_set_matrix_rgb2ycbcr(int mode) +{ + Wr_reg_bits(LDIM_STTS_CTRL0, 1, 2, 1); + if (mode == 0) {/*ycbcr not full range, 601 conversion*/ + Wr(LDIM_STTS_MATRIX_PRE_OFFSET0_1, 0x0); + Wr(LDIM_STTS_MATRIX_PRE_OFFSET2, 0x0); + /* 0.257 0.504 0.098 */ + /* -0.148 -0.291 0.439 */ + /* 0.439 -0.368 -0.071 */ + Wr(LDIM_STTS_MATRIX_COEF00_01, (0x107 << 16) | 0x204); + Wr(LDIM_STTS_MATRIX_COEF02_10, (0x64 << 16) | 0x1f68); + Wr(LDIM_STTS_MATRIX_COEF11_12, (0x1ed6 << 16) | 0x1c2); + Wr(LDIM_STTS_MATRIX_COEF20_21, (0x1c2 << 16) | 0x1e87); + Wr(LDIM_STTS_MATRIX_COEF22, 0x1fb7); + + Wr(LDIM_STTS_MATRIX_OFFSET2, 0x0200); + } else if (mode == 1) {/*ycbcr full range, 601 conversion*/ + /* todo */ + } +} + +void ldim_remap_update_txlx(struct LDReg_s *nPRM, + unsigned int avg_update_en, unsigned int matrix_update_en) +{ + unsigned int data; + + if (avg_update_en) { + /* LD_BKLIT_PARAM */ + data = LDIM_RD_32Bits(REG_LD_BKLIT_PARAM); + data = (data & (~0xfff)) | (nPRM->reg_BL_matrix_AVG & 0xfff); + LDIM_WR_32Bits(REG_LD_BKLIT_PARAM, data); + + /* compensate */ + data = LDIM_RD_32Bits(REG_LD_LIT_GAIN_COMP); + data = (data & (~0xfff)) | + (nPRM->reg_BL_matrix_Compensate & 0xfff); + LDIM_WR_32Bits(REG_LD_LIT_GAIN_COMP, data); + } + + if (matrix_update_en) { + data = nPRM->reg_LD_BLK_Vnum * nPRM->reg_LD_BLK_Hnum; + LDIM_Update_Matrix(nPRM->BL_matrix, data); + } +} diff --git a/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_reg.h b/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_reg.h index 6fe28b425554..297dafa379c3 100644 --- a/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_reg.h +++ b/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_reg.h @@ -23,8 +23,8 @@ #define ASSIST_SPARE8_REG1 0x1f58 /*gxtvbb new add*/ -#define LDIM_STTS_CTRL0 0x1ac1 #define LDIM_STTS_GCLK_CTRL0 0x1ac0 +#define LDIM_STTS_CTRL0 0x1ac1 #define LDIM_STTS_WIDTHM1_HEIGHTM1 0x1ac2 #define LDIM_STTS_MATRIX_COEF00_01 0x1ac3 #define LDIM_STTS_MATRIX_COEF02_10 0x1ac4 diff --git a/drivers/amlogic/media/vout/backlight/aml_ldim/ob3350_bl.c b/drivers/amlogic/media/vout/backlight/aml_ldim/ob3350_bl.c index 4348321adf17..8efef8baaa2c 100644 --- a/drivers/amlogic/media/vout/backlight/aml_ldim/ob3350_bl.c +++ b/drivers/amlogic/media/vout/backlight/aml_ldim/ob3350_bl.c @@ -48,7 +48,8 @@ static int ob3350_hw_init_on(void) ldim_drv->ldev_conf->en_gpio_on); mdelay(2); - ldim_set_duty_pwm(&(ldim_drv->ldev_conf->pwm_config)); + ldim_set_duty_pwm(&(ldim_drv->ldev_conf->ldim_pwm_config)); + ldim_set_duty_pwm(&(ldim_drv->ldev_conf->analog_pwm_config)); ldim_drv->pinmux_ctrl(1); mdelay(20); @@ -62,7 +63,8 @@ static int ob3350_hw_init_off(void) ldim_gpio_set(ldim_drv->ldev_conf->en_gpio, ldim_drv->ldev_conf->en_gpio_off); ldim_drv->pinmux_ctrl(0); - ldim_pwm_off(&(ldim_drv->ldev_conf->pwm_config)); + ldim_pwm_off(&(ldim_drv->ldev_conf->ldim_pwm_config)); + ldim_pwm_off(&(ldim_drv->ldev_conf->analog_pwm_config)); return 0; } @@ -89,12 +91,22 @@ static int ob3350_smr(unsigned short *buf, unsigned char len) level = buf[0]; val = dim_min + ((level * (dim_max - dim_min)) / LD_DATA_MAX); - ldim_drv->ldev_conf->pwm_config.pwm_duty = val; - ldim_set_duty_pwm(&(ldim_drv->ldev_conf->pwm_config)); + ldim_drv->ldev_conf->ldim_pwm_config.pwm_duty = val; + ldim_set_duty_pwm(&(ldim_drv->ldev_conf->ldim_pwm_config)); return 0; } +static void ob3350_dim_range_update(void) +{ + struct aml_ldim_driver_s *ldim_drv = aml_ldim_get_driver(); + struct ldim_dev_config_s *ldim_dev; + + ldim_dev = ldim_drv->ldev_conf; + ldim_dev->dim_max = ldim_dev->ldim_pwm_config.pwm_duty_max; + ldim_dev->dim_min = ldim_dev->ldim_pwm_config.pwm_duty_min; +} + static int ob3350_power_on(void) { if (ob3350_on_flag) { @@ -138,7 +150,7 @@ static ssize_t ob3350_show(struct class *class, ldim_drv->ldev_conf->en_gpio_off, ldim_drv->ldev_conf->dim_max, ldim_drv->ldev_conf->dim_min, - ldim_drv->ldev_conf->pwm_config.pwm_duty); + ldim_drv->ldev_conf->ldim_pwm_config.pwm_duty); } return ret; @@ -151,6 +163,12 @@ static struct class_attribute ob3350_class_attrs[] = { static int ob3350_ldim_driver_update(struct aml_ldim_driver_s *ldim_drv) { + struct ldim_dev_config_s *ldim_dev = ldim_drv->ldev_conf; + + ldim_dev->ldim_pwm_config.pwm_duty_max = ldim_dev->dim_max; + ldim_dev->ldim_pwm_config.pwm_duty_min = ldim_dev->dim_min; + ldim_dev->dim_range_update = ob3350_dim_range_update; + ldim_drv->device_power_on = ob3350_power_on; ldim_drv->device_power_off = ob3350_power_off; ldim_drv->device_bri_update = ob3350_smr; diff --git a/drivers/amlogic/media/vout/cvbs/cvbs_out.c b/drivers/amlogic/media/vout/cvbs/cvbs_out.c index cf611fe41040..467535345c92 100644 --- a/drivers/amlogic/media/vout/cvbs/cvbs_out.c +++ b/drivers/amlogic/media/vout/cvbs/cvbs_out.c @@ -903,15 +903,13 @@ static void cvbs_performance_regs_dump(void) pr_info("vcbus [0x%x] = 0x%x\n", performance_regs_enci[i], cvbs_out_reg_read(performance_regs_enci[i])); } - if (cvbs_cpu_type() == CVBS_CPU_TYPE_G12A || - cvbs_cpu_type() == CVBS_CPU_TYPE_G12B) + if (cvbs_cpu_type() >= CVBS_CPU_TYPE_G12A) size = sizeof(performance_regs_vdac_g12a)/sizeof(unsigned int); else size = sizeof(performance_regs_vdac)/sizeof(unsigned int); pr_info("------------------------\n"); for (i = 0; i < size; i++) { - if (cvbs_cpu_type() == CVBS_CPU_TYPE_G12A || - cvbs_cpu_type() == CVBS_CPU_TYPE_G12B) + if (cvbs_cpu_type() >= CVBS_CPU_TYPE_G12A) pr_info("hiu [0x%x] = 0x%x\n", performance_regs_vdac_g12a[i], cvbs_out_hiu_read(performance_regs_vdac_g12a[i])); @@ -1208,9 +1206,8 @@ static void cvbs_debug_store(char *buf) cvbs_performance_config_dump(); break; case CMD_VP_SET_PLLPATH: - if (cvbs_cpu_type() != CVBS_CPU_TYPE_G12A && - cvbs_cpu_type() != CVBS_CPU_TYPE_G12B) { - print_info("ERR:Only g12a/b chip supported\n"); + if (cvbs_cpu_type() < CVBS_CPU_TYPE_G12A) { + print_info("ERR:Only after g12a/b chip supported\n"); break; } if (argc != 2) { @@ -1449,6 +1446,18 @@ struct meson_cvbsout_data meson_g12b_cvbsout_data = { .name = "meson-g12b-cvbsout", }; +struct meson_cvbsout_data meson_tl1_cvbsout_data = { + .cntl0_val = 0x906001, + .cpu_id = CVBS_CPU_TYPE_TL1, + .name = "meson-tl1-cvbsout", +}; + +struct meson_cvbsout_data meson_sm1_cvbsout_data = { + .cntl0_val = 0x8f6001, + .cpu_id = CVBS_CPU_TYPE_SM1, + .name = "meson-sm1-cvbsout", +}; + static const struct of_device_id meson_cvbsout_dt_match[] = { { .compatible = "amlogic, cvbsout-gxl", @@ -1465,6 +1474,12 @@ static const struct of_device_id meson_cvbsout_dt_match[] = { }, { .compatible = "amlogic, cvbsout-g12b", .data = &meson_g12b_cvbsout_data, + }, { + .compatible = "amlogic, cvbsout-tl1", + .data = &meson_tl1_cvbsout_data, + }, { + .compatible = "amlogic, cvbsout-sm1", + .data = &meson_sm1_cvbsout_data, }, {}, }; diff --git a/drivers/amlogic/media/vout/cvbs/cvbs_out.h b/drivers/amlogic/media/vout/cvbs/cvbs_out.h index 79f803caedaf..05f6961225e4 100644 --- a/drivers/amlogic/media/vout/cvbs/cvbs_out.h +++ b/drivers/amlogic/media/vout/cvbs/cvbs_out.h @@ -51,6 +51,8 @@ enum cvbs_cpu_type { CVBS_CPU_TYPE_TXLX = 3, CVBS_CPU_TYPE_G12A = 4, CVBS_CPU_TYPE_G12B = 5, + CVBS_CPU_TYPE_TL1 = 6, + CVBS_CPU_TYPE_SM1 = 7, }; struct meson_cvbsout_data { diff --git a/drivers/amlogic/media/vout/cvbs/enc_clk_config.c b/drivers/amlogic/media/vout/cvbs/enc_clk_config.c index 28b6fc871f51..379e19b2a850 100644 --- a/drivers/amlogic/media/vout/cvbs/enc_clk_config.c +++ b/drivers/amlogic/media/vout/cvbs/enc_clk_config.c @@ -183,7 +183,8 @@ void set_vmode_clk(void) cvbs_out_hiu_setb(HHI_VIID_CLK_CNTL, 0, VCLK2_EN, 1); udelay(5); } else if (cvbs_cpu_type() == CVBS_CPU_TYPE_G12A || - cvbs_cpu_type() == CVBS_CPU_TYPE_G12B) { + cvbs_cpu_type() == CVBS_CPU_TYPE_G12B || + cvbs_cpu_type() == CVBS_CPU_TYPE_SM1) { if (cvbs_clk_path & 0x1) { pr_info("config g12a gp0_pll\n"); cvbs_out_hiu_write(HHI_GP0_PLL_CNTL0, 0x180204f7); @@ -229,7 +230,8 @@ void set_vmode_clk(void) } if (cvbs_cpu_type() == CVBS_CPU_TYPE_G12A || - cvbs_cpu_type() == CVBS_CPU_TYPE_G12B) { + cvbs_cpu_type() == CVBS_CPU_TYPE_G12B || + cvbs_cpu_type() == CVBS_CPU_TYPE_SM1) { if (cvbs_clk_path & 0x2) cvbs_set_vid1_clk(cvbs_clk_path & 0x1); else @@ -248,7 +250,8 @@ void set_vmode_clk(void) void disable_vmode_clk(void) { if (cvbs_cpu_type() == CVBS_CPU_TYPE_G12A || - cvbs_cpu_type() == CVBS_CPU_TYPE_G12B) { + cvbs_cpu_type() == CVBS_CPU_TYPE_G12B || + cvbs_cpu_type() == CVBS_CPU_TYPE_SM1) { if (cvbs_clk_path & 0x2) disable_vid1_clk_out(); else diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_common/hdmi_parameters.c b/drivers/amlogic/media/vout/hdmitx/hdmi_common/hdmi_parameters.c index 43f1e2d79dd9..876dac585b21 100644 --- a/drivers/amlogic/media/vout/hdmitx/hdmi_common/hdmi_parameters.c +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_common/hdmi_parameters.c @@ -2753,6 +2753,24 @@ struct vinfo_s *hdmi_get_valid_vinfo(char *mode) /* the string of mode contains char NF */ memset(mode_, 0, sizeof(mode_)); strncpy(mode_, mode, sizeof(mode_)); + + /* skip "f", 1080fp60hz -> 1080p60hz for 3d */ + mode_[31] = '\0'; + if (strstr(mode_, "fp")) { + int i = 0; + + for (; mode_[i]; i++) { + if ((mode_[i] == 'f') && + (mode_[i + 1] == 'p')) { + do { + mode_[i] = mode_[i + 1]; + i++; + } while (mode_[i]); + break; + } + } + } + for (i = 0; i < sizeof(mode_); i++) if (mode_[i] == 10) mode_[i] = 0; @@ -3074,7 +3092,7 @@ struct hdmi_audio_fs_ncts aud_48k_para = { .n = 6864, .cts = 28125, .n_36bit = 9152, - .cts_36bit = 58250, + .cts_36bit = 56250, .n_48bit = 6864, .cts_48bit = 56250, }, @@ -3300,3 +3318,22 @@ unsigned int hdmi_get_csc_coef( return 1; } +bool is_hdmi14_4k(enum hdmi_vic vic) +{ + bool ret = 0; + + switch (vic) { + case HDMI_3840x2160p24_16x9: + case HDMI_3840x2160p25_16x9: + case HDMI_3840x2160p30_16x9: + case HDMI_4096x2160p24_256x135: + ret = 1; + break; + default: + ret = 0; + break; + } + + return ret; +} + diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_audio.c b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_audio.c index 1357960bec17..9ade063bdea1 100644 --- a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_audio.c +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_audio.c @@ -159,7 +159,7 @@ static void hdmi_tx_construct_aud_packet( AUD_DB[4] = 0; } } else if (audio_param->type == CT_DOLBY_D) { - pr_info(AUD "Audio Type: Dobly Digital +\n"); + pr_info(AUD "Audio Type: Dolby Digital +\n"); if (AUD_DB) { AUD_DB[0] = (FS_REFER_TO_STREAM<<4)|(CC_REFER_TO_STREAM); diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_edid.c b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_edid.c index 0a90ec50ec93..aa8ccb73c8b5 100644 --- a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_edid.c +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_edid.c @@ -319,9 +319,9 @@ int Edid_Parse_check_HDMI_VSDB(struct hdmitx_dev *hdev, if (temp_addr >= VSpecificBoundary) ret = -1; else { - if ((buff[BlockAddr + 1] != 0x03) || - (buff[BlockAddr + 2] != 0x0C) || - (buff[BlockAddr + 3] != 0x0)) + if ((buff[BlockAddr + 1] != GET_OUI_BYTE0(HDMI_IEEEOUI)) || + (buff[BlockAddr + 2] != GET_OUI_BYTE1(HDMI_IEEEOUI)) || + (buff[BlockAddr + 3] != GET_OUI_BYTE2(HDMI_IEEEOUI))) ret = -1; } return ret; @@ -1403,6 +1403,40 @@ static void hdmitx_edid_4k2k_parse(struct rx_cap *pRXCap, unsigned char *dat, } } +static void get_latency(struct rx_cap *pRXCap, unsigned char *val) +{ + if (val[0] == 0) + pRXCap->vLatency = LATENCY_INVALID_UNKNOWN; + else if (val[0] == 0xFF) + pRXCap->vLatency = LATENCY_NOT_SUPPORT; + else + pRXCap->vLatency = (val[0] - 1) * 2; + + if (val[1] == 0) + pRXCap->aLatency = LATENCY_INVALID_UNKNOWN; + else if (val[1] == 0xFF) + pRXCap->aLatency = LATENCY_NOT_SUPPORT; + else + pRXCap->aLatency = (val[1] - 1) * 2; +} + +static void get_ilatency(struct rx_cap *pRXCap, unsigned char *val) +{ + if (val[0] == 0) + pRXCap->i_vLatency = LATENCY_INVALID_UNKNOWN; + else if (val[0] == 0xFF) + pRXCap->i_vLatency = LATENCY_NOT_SUPPORT; + else + pRXCap->i_vLatency = val[0] * 2 - 1; + + if (val[1] == 0) + pRXCap->i_aLatency = LATENCY_INVALID_UNKNOWN; + else if (val[1] == 0xFF) + pRXCap->i_aLatency = LATENCY_NOT_SUPPORT; + else + pRXCap->i_aLatency = val[1] * 2 - 1; +} + static int hdmitx_edid_block_parse(struct hdmitx_dev *hdmitx_device, unsigned char *BlockBuf) { @@ -1443,7 +1477,7 @@ static int hdmitx_edid_block_parse(struct hdmitx_dev *hdmitx_device, pRXCap->RxAudioCap[idx + i].freq_cc = BlockBuf[offset + i * 3 + 1]&0x7f; pRXCap->RxAudioCap[idx + i].cc3 = - BlockBuf[offset + i * 3 + 2]&0x7; + BlockBuf[offset + i * 3 + 2]; } offset += count; break; @@ -1467,7 +1501,7 @@ static int hdmitx_edid_block_parse(struct hdmitx_dev *hdmitx_device, if ((BlockBuf[offset] == 0x03) && (BlockBuf[offset+1] == 0x0c) && (BlockBuf[offset+2] == 0x00)) { - pRXCap->IEEEOUI = 0x000c03; + pRXCap->ieeeoui = HDMI_IEEEOUI; pRXCap->ColorDeepSupport = (count > 5) ? BlockBuf[offset+5] : 0; set_vsdb_dc_cap(pRXCap); @@ -1477,10 +1511,22 @@ static int hdmitx_edid_block_parse(struct hdmitx_dev *hdmitx_device, if (count > 7) { tmp = BlockBuf[offset+7]; idx = offset + 8; - if (tmp & (1<<6)) + if (tmp & (1<<6)) { + unsigned char val[2]; + + val[0] = BlockBuf[idx]; + val[1] = BlockBuf[idx + 1]; + get_latency(pRXCap, val); idx += 2; - if (tmp & (1<<7)) + } + if (tmp & (1<<7)) { + unsigned char val[2]; + + val[0] = BlockBuf[idx]; + val[1] = BlockBuf[idx + 1]; + get_ilatency(pRXCap, val); idx += 2; + } if (tmp & (1<<5)) { idx += 1; /* valid 4k */ @@ -1502,7 +1548,7 @@ static int hdmitx_edid_block_parse(struct hdmitx_dev *hdmitx_device, } else if ((BlockBuf[offset] == 0xd8) && (BlockBuf[offset+1] == 0x5d) && (BlockBuf[offset+2] == 0xc4)) { - pRXCap->HF_IEEEOUI = 0xd85dc4; + pRXCap->hf_ieeeoui = HF_IEEEOUI; pRXCap->Max_TMDS_Clock2 = BlockBuf[offset+4]; pRXCap->scdc_present = !!(BlockBuf[offset+5] & (1 << 7)); @@ -1512,6 +1558,11 @@ static int hdmitx_edid_block_parse(struct hdmitx_dev *hdmitx_device, !!(BlockBuf[offset+5] & (1 << 3)); set_vsdb_dc_420_cap(&hdmitx_device->RXCap, &BlockBuf[offset]); + if (count > 7) { + unsigned char b7 = BlockBuf[offset+7]; + + pRXCap->allm = !!(b7 & (1 << 1)); + } } offset += count; /* ignore the remaind. */ @@ -1916,6 +1967,7 @@ next: } else dump_dtd_info(t); } + static void hdrinfo_to_vinfo(struct vinfo_s *info, struct rx_cap *pRXCap) { unsigned int k, l; @@ -1956,6 +2008,15 @@ static void hdrinfo_to_vinfo(struct vinfo_s *info, struct rx_cap *pRXCap) info->hdr_info.hdr_support); } +static void rxlatency_to_vinfo(struct vinfo_s *info, struct rx_cap *rx) +{ + if (!info || !rx) + return; + info->rx_latency.vLatency = rx->vLatency; + info->rx_latency.aLatency = rx->aLatency; + info->rx_latency.i_vLatency = rx->i_vLatency; + info->rx_latency.i_aLatency = rx->i_aLatency; +} int hdmitx_edid_parse(struct hdmitx_dev *hdmitx_device) { @@ -2042,18 +2103,18 @@ int hdmitx_edid_parse(struct hdmitx_dev *hdmitx_device) pr_info(EDID "edid blk0 checksum:%d ext_flag:%d\n", CheckSum, EDID_buf[0x7e]); if ((CheckSum & 0xff) == 0) - hdmitx_device->RXCap.IEEEOUI = 0; + hdmitx_device->RXCap.ieeeoui = 0; else - hdmitx_device->RXCap.IEEEOUI = 0x0c03; + hdmitx_device->RXCap.ieeeoui = HDMI_IEEEOUI; if (zero_numbers > 120) - hdmitx_device->RXCap.IEEEOUI = 0x0c03; + hdmitx_device->RXCap.ieeeoui = HDMI_IEEEOUI; return 0; /* do nothing. */ } /* Note: some DVI monitor have more than 1 block */ if ((BlockCount == 1) && (EDID_buf[0x81] == 1)) { - hdmitx_device->RXCap.IEEEOUI = 0; + hdmitx_device->RXCap.ieeeoui = 0; hdmitx_device->RXCap.VIC_count = 0x3; hdmitx_device->RXCap.VIC[0] = HDMI_720x480p60_16x9; hdmitx_device->RXCap.VIC[1] = HDMI_1280x720p60_16x9; @@ -2112,14 +2173,14 @@ int hdmitx_edid_parse(struct hdmitx_dev *hdmitx_device) } if (hdmitx_edid_search_IEEEOUI(&EDID_buf[128])) { - pRXCap->IEEEOUI = 0x0c03; + pRXCap->ieeeoui = HDMI_IEEEOUI; pr_info(EDID "find IEEEOUT\n"); } else { - pRXCap->IEEEOUI = 0x0; + pRXCap->ieeeoui = 0x0; pr_info(EDID "not find IEEEOUT\n"); } - if ((pRXCap->IEEEOUI != 0x0c03) || (pRXCap->IEEEOUI == 0x0) || + if ((pRXCap->ieeeoui != HDMI_IEEEOUI) || (pRXCap->ieeeoui == 0x0) || (pRXCap->VIC_count == 0)) hdmitx_edid_set_default_vic(hdmitx_device); @@ -2127,15 +2188,15 @@ int hdmitx_edid_parse(struct hdmitx_dev *hdmitx_device) /* valid EDID & no audio tag & no IEEEOUI */ if (edid_check_valid(&EDID_buf[0]) && !hdmitx_edid_search_IEEEOUI(&EDID_buf[128])) { - pRXCap->IEEEOUI = 0x0; + pRXCap->ieeeoui = 0x0; pr_info(EDID "sink is DVI device\n"); } else - pRXCap->IEEEOUI = 0x0c03; + pRXCap->ieeeoui = HDMI_IEEEOUI; if (edid_zero_data(EDID_buf)) - pRXCap->IEEEOUI = 0x0c03; + pRXCap->ieeeoui = HDMI_IEEEOUI; - if ((!pRXCap->AUD_count) && (!pRXCap->IEEEOUI)) + if ((!pRXCap->AUD_count) && (!pRXCap->ieeeoui)) hdmitx_edid_set_default_aud(hdmitx_device); edid_save_checkvalue(EDID_buf, BlockCount+1); @@ -2145,7 +2206,7 @@ int hdmitx_edid_parse(struct hdmitx_dev *hdmitx_device) hdmitx_device->tmp_buf[i] = 0; if (!hdmitx_edid_check_valid_blocks(&EDID_buf[0])) { - pRXCap->IEEEOUI = 0x0c03; + pRXCap->ieeeoui = HDMI_IEEEOUI; pr_info(EDID "Invalid edid, consider RX as HDMI device\n"); } /* update RX HDR information */ @@ -2153,8 +2214,10 @@ int hdmitx_edid_parse(struct hdmitx_dev *hdmitx_device) if (info) { if (!((strncmp(info->name, "480cvbs", 7) == 0) || (strncmp(info->name, "576cvbs", 7) == 0) || - (strncmp(info->name, "null", 4) == 0))) + (strncmp(info->name, "null", 4) == 0))) { hdrinfo_to_vinfo(info, pRXCap); + rxlatency_to_vinfo(info, pRXCap); + } } return 0; @@ -2271,6 +2334,29 @@ const char *hdmitx_edid_vic_to_string(enum hdmi_vic vic) return disp_str; } +static bool is_rx_support_y420(struct hdmitx_dev *hdev) +{ + enum hdmi_vic vic = HDMI_Unknown; + + vic = hdmitx_edid_get_VIC(hdev, "2160p60hz420", 0); + if (vic != HDMI_Unknown) + return 1; + + vic = hdmitx_edid_get_VIC(hdev, "2160p50hz420", 0); + if (vic != HDMI_Unknown) + return 1; + + vic = hdmitx_edid_get_VIC(hdev, "smpte60hz420", 0); + if (vic != HDMI_Unknown) + return 1; + + vic = hdmitx_edid_get_VIC(hdev, "smpte50hz420", 0); + if (vic != HDMI_Unknown) + return 1; + + return 0; +} + /* For some TV's EDID, there maybe exist some information ambiguous. * Such as EDID declears support 2160p60hz(Y444 8bit), but no valid * Max_TMDS_Clock2 to indicate that it can support 5.94G signal. @@ -2319,7 +2405,7 @@ bool hdmitx_edid_check_valid_mode(struct hdmitx_dev *hdev, pRXCap = &(hdev->RXCap); /* DVI case, only 8bit */ - if (pRXCap->IEEEOUI != 0x0c03) { + if (pRXCap->ieeeoui != HDMI_IEEEOUI) { if (para->cd != COLORDEPTH_24B) return 0; } @@ -2411,6 +2497,8 @@ bool hdmitx_edid_check_valid_mode(struct hdmitx_dev *hdev, return valid; } if (para->cs == COLORSPACE_YUV420) { + if (!is_rx_support_y420(hdev)) + return 0; if (pRXCap->dc_30bit_420) rx_y420_max_dc = COLORDEPTH_30B; if (pRXCap->dc_36bit_420) @@ -2480,7 +2568,7 @@ void hdmitx_edid_clear(struct hdmitx_dev *hdmitx_device) /* Note: in most cases, we think that rx is tv and the default * IEEEOUI is HDMI Identifier */ - pRXCap->IEEEOUI = 0x000c03; + pRXCap->ieeeoui = HDMI_IEEEOUI; hdmitx_device->vic_count = 0; hdmitx_device->hdmi_info.vsdb_phy_addr.a = 0; @@ -2660,17 +2748,66 @@ int hdmitx_edid_dump(struct hdmitx_dev *hdmitx_device, char *buffer, "Speaker Allocation: %x\n", pRXCap->RxSpeakerAllocation); pos += snprintf(buffer+pos, buffer_len-pos, "Vendor: 0x%x ( %s device)\n", - pRXCap->IEEEOUI, (pRXCap->IEEEOUI)?"HDMI":"DVI"); + pRXCap->ieeeoui, (pRXCap->ieeeoui)?"HDMI":"DVI"); pos += snprintf(buffer+pos, buffer_len-pos, "MaxTMDSClock1 %d MHz\n", pRXCap->Max_TMDS_Clock1 * 5); - if (pRXCap->HF_IEEEOUI) { + if (pRXCap->hf_ieeeoui) { pos += snprintf(buffer+pos, buffer_len-pos, "Vendor2: 0x%x\n", - pRXCap->HF_IEEEOUI); + pRXCap->hf_ieeeoui); pos += snprintf(buffer+pos, buffer_len-pos, "MaxTMDSClock2 %d MHz\n", pRXCap->Max_TMDS_Clock2 * 5); } + + if (pRXCap->allm) + pos += snprintf(buffer+pos, buffer_len-pos, "ALLM: %x\n", + pRXCap->allm); + + pos += snprintf(buffer+pos, buffer_len-pos, "vLatency: "); + if (pRXCap->vLatency == LATENCY_INVALID_UNKNOWN) + pos += snprintf(buffer+pos, buffer_len-pos, + " Invalid/Unknown\n"); + else if (pRXCap->vLatency == LATENCY_NOT_SUPPORT) + pos += snprintf(buffer+pos, buffer_len-pos, + " UnSupported\n"); + else + pos += snprintf(buffer+pos, buffer_len-pos, + " %d\n", pRXCap->vLatency); + + pos += snprintf(buffer+pos, buffer_len-pos, "aLatency: "); + if (pRXCap->aLatency == LATENCY_INVALID_UNKNOWN) + pos += snprintf(buffer+pos, buffer_len-pos, + " Invalid/Unknown\n"); + else if (pRXCap->aLatency == LATENCY_NOT_SUPPORT) + pos += snprintf(buffer+pos, buffer_len-pos, + " UnSupported\n"); + else + pos += snprintf(buffer+pos, buffer_len-pos, " %d\n", + pRXCap->aLatency); + + pos += snprintf(buffer+pos, buffer_len-pos, "i_vLatency: "); + if (pRXCap->i_vLatency == LATENCY_INVALID_UNKNOWN) + pos += snprintf(buffer+pos, buffer_len-pos, + " Invalid/Unknown\n"); + else if (pRXCap->i_vLatency == LATENCY_NOT_SUPPORT) + pos += snprintf(buffer+pos, buffer_len-pos, + " UnSupported\n"); + else + pos += snprintf(buffer+pos, buffer_len-pos, " %d\n", + pRXCap->i_vLatency); + + pos += snprintf(buffer+pos, buffer_len-pos, "i_aLatency: "); + if (pRXCap->i_aLatency == LATENCY_INVALID_UNKNOWN) + pos += snprintf(buffer+pos, buffer_len-pos, + " Invalid/Unknown\n"); + else if (pRXCap->i_aLatency == LATENCY_NOT_SUPPORT) + pos += snprintf(buffer+pos, buffer_len-pos, + " UnSupported\n"); + else + pos += snprintf(buffer+pos, buffer_len-pos, " %d\n", + pRXCap->i_aLatency); + if (pRXCap->colorimetry_data) pos += snprintf(buffer+pos, buffer_len-pos, "ColorMetry: 0x%x\n", pRXCap->colorimetry_data); diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_main.c b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_main.c index 2d79eb5ee214..b0d95c65b668 100644 --- a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_main.c +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_main.c @@ -58,6 +58,8 @@ #include #include #include "hw/tvenc_conf.h" +#include "hw/hdmi_tx_reg.h" +#include "hw/mach_reg.h" #include "hw/common.h" #include "hw/hw_clk.h" #include "hdmi_tx_hdcp.h" @@ -440,6 +442,16 @@ static void hdrinfo_to_vinfo(struct vinfo_s *info, struct hdmitx_dev *hdev) info->hdr_info.hdr_support); } +static void rxlatency_to_vinfo(struct vinfo_s *info, struct rx_cap *rx) +{ + if (!info || !rx) + return; + info->rx_latency.vLatency = rx->vLatency; + info->rx_latency.aLatency = rx->aLatency; + info->rx_latency.i_vLatency = rx->i_vLatency; + info->rx_latency.i_aLatency = rx->i_aLatency; +} + static int set_disp_mode_auto(void) { int ret = -1; @@ -449,6 +461,8 @@ static int set_disp_mode_auto(void) struct hdmi_format_para *para = NULL; unsigned char mode[32]; enum hdmi_vic vic = HDMI_Unknown; + enum hdmi_color_depth stream_cur_cd; + /* vic_ready got from IP */ enum hdmi_vic vic_ready = hdev->HWOp.GetState( hdev, STAT_VIDEO_VIC, 0); @@ -461,12 +475,21 @@ static int set_disp_mode_auto(void) if ((info == NULL) || (info->name == NULL)) return -1; + stream_cur_cd = hdev->para->cd; + + if (hdev->cur_video_param != NULL){ + pr_info("hdmitx: display colourdepth was %d in cur_param 0x%p (VIC: %d)\n",hdev->cur_video_param->color_depth * 2, + hdev->cur_video_param, hdev->cur_video_param->VIC); + } + pr_info(SYS "get current mode: %s\n", info->name); if (!((strncmp(info->name, "480cvbs", 7) == 0) || (strncmp(info->name, "576cvbs", 7) == 0) || - (strncmp(info->name, "null", 4) == 0))) + (strncmp(info->name, "null", 4) == 0))) { hdrinfo_to_vinfo(info, hdev); + rxlatency_to_vinfo(info, &hdev->RXCap); + } hdmi_physcial_size_update(hdev); @@ -486,9 +509,11 @@ static int set_disp_mode_auto(void) hdev->HWOp.CntlConfig(hdev, CONF_CLR_VSDB_PACKET, 0); hdev->HWOp.CntlMisc(hdev, MISC_TMDS_PHY_OP, TMDS_PHY_DISABLE); hdev->para = hdmi_get_fmt_name("invalid", hdev->fmt_attr); + para->cd = stream_cur_cd; return -1; } strncpy(mode, info->name, sizeof(mode)); + mode[31] = '\0'; if (strstr(mode, "fp")) { int i = 0; @@ -504,18 +529,56 @@ static int set_disp_mode_auto(void) } } - /* In the file hdmi_common/hdmi_parameters.c, - * the data array all_fmt_paras[] treat 2160p60hz and 2160p60hz420 - * as two different modes, such Scrambler - * So if node "attr" contains 420, need append 420 to mode. - */ - if (strstr(hdev->fmt_attr, "420")) { - if (!strstr(mode, "420")) - strncat(mode, "420", 3); + para = hdmi_get_fmt_name(mode, hdev->fmt_attr); + /* force 4k50/60Hz to 420 unless manually set */ + if (strstr(hdmitx_device.fmt_attr,"422") == NULL){ + switch ((para->vic) & 0xff) { + case HDMI_3840x2160p50_16x9: + case HDMI_3840x2160p60_16x9: + case HDMI_4096x2160p50_256x135: + case HDMI_4096x2160p60_256x135: + case HDMI_3840x2160p50_64x27: + case HDMI_3840x2160p60_64x27: + para->cs = COLORSPACE_YUV420; + break; + default: + break; + } + } + hdev->para = para; + + if (hdev->cur_video_param != NULL){ + if (strstr(hdmitx_device.fmt_attr,"bit") != NULL){ + hdev->cur_video_param->color_depth = para->cd; + pr_info("hdmitx: display colourdepth set by attr to %d in cur_param 0x%p (VIC: %d)\n",hdev->cur_video_param->color_depth * 2, + hdev->cur_video_param, hdev->cur_video_param->VIC); + } else { + hdev->cur_video_param->color_depth = COLORDEPTH_30B; + pr_info("hdmitx: display colourdepth is %d in cur_param 0x%p (VIC: %d)\n",hdev->cur_video_param->color_depth * 2, + hdev->cur_video_param, hdev->cur_video_param->VIC); + } + if (hdev->cur_video_param->color_depth > COLORDEPTH_24B){ + int dc_support = 0; + if (hdev->RXCap.ColorDeepSupport & 0x78 && hdev->para->cs != COLORSPACE_YUV420) + dc_support = 1; + else if ((hdev->RXCap.hf_ieeeoui) && + ((hdev->RXCap.dc_30bit_420 && hdev->cur_video_param->color_depth == COLORDEPTH_30B) || + (hdev->RXCap.dc_36bit_420 && hdev->cur_video_param->color_depth == COLORDEPTH_36B) || + (hdev->RXCap.dc_48bit_420 && hdev->cur_video_param->color_depth == COLORDEPTH_48B))) + dc_support = 1; + if (! dc_support){ + pr_warn("Bitdepth is set to %d bits but display does not support deep colour", + hdev->cur_video_param->color_depth * 2); + /* drop to 8 bit unless forced */ + if (strstr(hdmitx_device.fmt_attr,"bit") == NULL) + hdev->cur_video_param->color_depth = COLORDEPTH_24B; + } + } } - para = hdmi_get_fmt_name(mode, hdev->fmt_attr); - hdev->para = para; + /* and recover the original bitstream bitdepth */ + para->cd = stream_cur_cd; + vic = hdmitx_edid_get_VIC(hdev, mode, 1); if (strncmp(info->name, "2160p30hz", strlen("2160p30hz")) == 0) { vic = HDMI_4k2k_30; @@ -531,7 +594,7 @@ static int set_disp_mode_auto(void) else { /* nothing */ } - if ((vic_ready != HDMI_Unknown) && (vic_ready == vic)) { + if ((vic_ready != HDMI_Unknown) && (vic_ready == vic) && (strstr(hdmitx_device.fmt_attr,"now") == NULL)) { pr_info(SYS "[%s] ALREADY init VIC = %d\n", __func__, vic); #if defined(CONFIG_ARCH_MESON64_ODROID_COMMON) @@ -543,9 +606,9 @@ static int set_disp_mode_auto(void) hdev->HWOp.CntlConfig(hdev, CONF_HDMI_DVI_MODE, DVI_MODE); pr_info(SYS "change to DVI mode\n"); - } else if (hdev->RXCap.IEEEOUI == 0) { + } else if (hdev->RXCap.ieeeoui == 0) { #else - if (hdev->RXCap.IEEEOUI == 0) { + if (hdev->RXCap.ieeeoui == 0) { #endif /* DVI case judgement. In uboot, directly output HDMI * mode @@ -553,7 +616,7 @@ static int set_disp_mode_auto(void) hdev->HWOp.CntlConfig(hdev, CONF_HDMI_DVI_MODE, DVI_MODE); pr_info(SYS "change to DVI mode\n"); - } else if ((hdev->RXCap.IEEEOUI == 0xc03) && + } else if ((hdev->RXCap.ieeeoui == 0xc03) && (hdev->HWOp.CntlConfig(hdev, CONF_GET_HDMI_DVI_MODE, 0) == DVI_MODE)) { hdev->HWOp.CntlConfig(hdev, CONF_HDMI_DVI_MODE, @@ -568,6 +631,10 @@ static int set_disp_mode_auto(void) hdmitx_pre_display_init(); + + if (strstr(hdmitx_device.fmt_attr,"now") != NULL){ + memcpy(strstr(hdmitx_device.fmt_attr,"now"), " ", 3); + } hdev->cur_VIC = HDMI_Unknown; /* if vic is HDMI_Unknown, hdmitx_set_display will disable HDMI */ ret = hdmitx_set_display(hdev, vic); @@ -632,6 +699,10 @@ ssize_t store_attr(struct device *dev, { strncpy(hdmitx_device.fmt_attr, buf, sizeof(hdmitx_device.fmt_attr)); hdmitx_device.fmt_attr[15] = '\0'; + if (strstr(hdmitx_device.fmt_attr,"now")){ + set_disp_mode_auto(); + } +return count; return count; } /*aud_mode attr*/ @@ -1240,6 +1311,10 @@ static void hdr_work_func(struct work_struct *work) CONF_AVI_BT2020, hdev->colormetry); msleep(1500);/*delay 1.5s*/ + if (hdev->hdr_transfer_feature != T_BT709 || + hdev->hdr_color_feature != C_BT709) + return; + hdev->HWOp.SetPacket(HDMI_PACKET_DRM, NULL, NULL); hdev->hdmi_current_hdr_mode = 0; hdmitx_sdr_hdr_uevent(hdev); @@ -1357,9 +1432,6 @@ static void hdmitx_set_drm_pkt(struct master_display_info_s *data) hdev->hdmi_current_hdr_mode = 3; } - hdev->HWOp.CntlConfig(hdev, CONF_AVI_Q01, - RGB_RANGE_LIM); - switch (hdev->hdmi_current_hdr_mode) { case 1: /*standard HDR*/ @@ -1812,6 +1884,11 @@ static ssize_t show_config(struct device *dev, int pos = 0; unsigned char *conf; struct hdmitx_dev *hdev = &hdmitx_device; + char* pix_fmt[] = {"RGB","YUV422","YUV444","YUV420"}; + char* eotf[] = {"SDR","HDR","HDR10","HLG"}; + char* range[] = {"default","limited","full"}; + char* colourimetry[] = {"default", "BT.601", "BT.709", "xvYCC601","xvYCC709", + "sYCC601","Adobe_YCC601","Adobe_RGB","BT.2020c","BT.2020nc","P3 D65","P3 DCI"}; pos += snprintf(buf+pos, PAGE_SIZE, "cur_VIC: %d\n", hdev->cur_VIC); if (hdev->cur_video_param) @@ -1819,10 +1896,26 @@ static ssize_t show_config(struct device *dev, "cur_video_param->VIC=%d\n", hdev->cur_video_param->VIC); if (hdev->para) { - pos += snprintf(buf+pos, PAGE_SIZE, "cd = %d\n", - hdev->para->cd); - pos += snprintf(buf+pos, PAGE_SIZE, "cs = %d\n", - hdev->para->cs); + struct hdmi_format_para *para; + para = hdev->para; + + pos += snprintf(buf+pos, PAGE_SIZE, "VIC: %d %s\n", + hdmitx_device.cur_VIC, para->name); + pos += snprintf(buf + pos, PAGE_SIZE, "Colour depth: %d-bit\nColourspace: %s\nColour range: %s\nEOTF: %s\nYCC colour range: %s\n", + (((hdmitx_rd_reg(HDMITX_DWC_TX_INVID0) & 0x6) >> 1) + 4 ) * 2, + pix_fmt[(hdmitx_rd_reg(HDMITX_DWC_FC_AVICONF0) & 0x3)], + range[(hdmitx_rd_reg(HDMITX_DWC_FC_AVICONF2) & 0xc) >> 2], + eotf[(hdmitx_rd_reg(HDMITX_DWC_FC_DRM_PB00) & 7)], + range[((hdmitx_rd_reg(HDMITX_DWC_FC_AVICONF3) & 0xc) >> 2) + 1]); + if (((hdmitx_rd_reg(HDMITX_DWC_FC_AVICONF1) & 0xc0) >> 6) < 0x3) + pos += snprintf(buf + pos, PAGE_SIZE, "Colourimetry: %s\n", + colourimetry[(hdmitx_rd_reg(HDMITX_DWC_FC_AVICONF1) & 0xc0) >> 6]); + else + pos += snprintf(buf + pos, PAGE_SIZE, "Colourimetry: %s\n", + colourimetry[((hdmitx_rd_reg(HDMITX_DWC_FC_AVICONF2) & 0x70) >> 4) + 3]); + pos += snprintf(buf + pos, PAGE_SIZE, "PLL clock: 0x%08x, Vid clock div 0x%08x\n", + hd_read_reg(P_HHI_HDMI_PLL_CNTL), + hd_read_reg(P_HHI_VID_PLL_CLK_DIV)); } switch (hdev->tx_aud_cfg) { @@ -1896,7 +1989,7 @@ static ssize_t show_config(struct device *dev, conf = "One Bit Audio"; break; case CT_DOLBY_D: - conf = "Dobly Digital+"; + conf = "Dolby Digital+"; break; case CT_DTS_HD: conf = "DTS_HD"; @@ -2346,45 +2439,80 @@ static ssize_t show_disp_cap_3d(struct device *dev, return pos; } +static void _show_pcm_ch(struct rx_cap *pRXCap, int i, + int *ppos, char *buf) +{ + const char * const aud_sample_size[] = {"ReferToStreamHeader", + "16", "20", "24", NULL}; + int j = 0; + + for (j = 0; j < 3; j++) { + if (pRXCap->RxAudioCap[i].cc3 & (1 << j)) + *ppos += snprintf(buf + *ppos, PAGE_SIZE, "%s/", + aud_sample_size[j+1]); + } + *ppos += snprintf(buf + *ppos - 1, PAGE_SIZE, " bit\n"); +} + /**/ static ssize_t show_aud_cap(struct device *dev, struct device_attribute *attr, char *buf) { int i, pos = 0, j; - static const char * const aud_coding_type[] = { + static const char * const aud_ct[] = { "ReferToStreamHeader", "PCM", "AC-3", "MPEG1", "MP3", "MPEG2", "AAC", "DTS", "ATRAC", "OneBitAudio", - "Dobly_Digital+", "DTS-HD", "MAT", "DST", "WMA_Pro", + "Dolby_Digital+", "DTS-HD", "MAT", "DST", "WMA_Pro", "Reserved", NULL}; static const char * const aud_sampling_frequency[] = { "ReferToStreamHeader", "32", "44.1", "48", "88.2", "96", "176.4", "192", NULL}; - static const char * const aud_sample_size[] = {"ReferToStreamHeader", - "16", "20", "24", NULL}; - struct rx_cap *pRXCap = &(hdmitx_device.RXCap); pos += snprintf(buf + pos, PAGE_SIZE, "CodingType MaxChannels SamplingFreq SampleSize\n"); for (i = 0; i < pRXCap->AUD_count; i++) { - pos += snprintf(buf + pos, PAGE_SIZE, "%s, %d ch, ", - aud_coding_type[pRXCap->RxAudioCap[i]. - audio_format_code], + pos += snprintf(buf + pos, PAGE_SIZE, "%s", + aud_ct[pRXCap->RxAudioCap[i].audio_format_code]); + if ((pRXCap->RxAudioCap[i].audio_format_code == CT_DOLBY_D) && + (pRXCap->RxAudioCap[i].cc3 & 1)) + pos += snprintf(buf + pos, PAGE_SIZE, "/ATMOS"); + pos += snprintf(buf + pos, PAGE_SIZE, ", %d ch, ", pRXCap->RxAudioCap[i].channel_num_max + 1); for (j = 0; j < 7; j++) { if (pRXCap->RxAudioCap[i].freq_cc & (1 << j)) pos += snprintf(buf + pos, PAGE_SIZE, "%s/", aud_sampling_frequency[j+1]); } - pos += snprintf(buf + pos - 1, PAGE_SIZE, " kHz, ") - 1; - for (j = 0; j < 3; j++) { - if (pRXCap->RxAudioCap[i].cc3 & (1 << j)) - pos += snprintf(buf + pos, PAGE_SIZE, "%s/", - aud_sample_size[j+1]); + pos += snprintf(buf + pos - 1, PAGE_SIZE, " kHz, "); + switch (pRXCap->RxAudioCap[i].audio_format_code) { + case CT_PCM: + _show_pcm_ch(pRXCap, i, &pos, buf); + break; + case CT_AC_3: + case CT_MPEG1: + case CT_MP3: + case CT_MPEG2: + case CT_AAC: + case CT_DTS: + case CT_ATRAC: + case CT_ONE_BIT_AUDIO: + pos += snprintf(buf + pos, PAGE_SIZE, + "MaxBitRate %dkHz\n", + pRXCap->RxAudioCap[i].cc3 * 8); + break; + case CT_DOLBY_D: + case CT_DTS_HD: + case CT_MAT: + case CT_DST: + pos += snprintf(buf + pos, PAGE_SIZE, "DepVaule 0x%x\n", + pRXCap->RxAudioCap[i].cc3); + break; + case CT_WMA: + default: + break; } - pos += snprintf(buf + pos - 1, PAGE_SIZE, " bit\n") - 1; } - return pos; } @@ -2522,6 +2650,77 @@ static ssize_t store_valid_mode(struct device *dev, return count; } +static ssize_t show_allm_mode(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int pos = 0; + struct hdmitx_dev *hdev = &hdmitx_device; + struct rx_cap *pRXCap = &(hdmitx_device.RXCap); + + if (!pRXCap->allm) { /* Rx not support ALLM */ + pos += snprintf(buf + pos, PAGE_SIZE, "0\n\r"); + return pos; + } + + if (hdev->allm_mode == 1) + pos += snprintf(buf + pos, PAGE_SIZE, "game\n\r"); + else if (hdev->allm_mode == 2) + pos += snprintf(buf + pos, PAGE_SIZE, "graphics\n\r"); + else if (hdev->allm_mode == 3) + pos += snprintf(buf + pos, PAGE_SIZE, "photo\n\r"); + else if (hdev->allm_mode == 4) + pos += snprintf(buf + pos, PAGE_SIZE, "cinema\n\r"); + else + pos += snprintf(buf + pos, PAGE_SIZE, "0\n\r"); + + return pos; +} + +static ssize_t store_allm_mode(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct hdmitx_dev *hdev = &hdmitx_device; + struct rx_cap *pRXCap = &hdev->RXCap; + + pr_info("hdmitx: store allm_mode as %s\n", buf); + + if (!pRXCap->allm) /* Rx not support ALLM */ + return count; + +#define CMP_STR(str) (strncmp(buf, str, strlen(str)) == 0) + if (CMP_STR("0")) { + // disable ALLM + hdev->allm_mode = 0; + hdev->HWOp.CntlConfig(hdev, CONF_ALLM_MODE, CLEAR_ALLM_MODE); + hdmitx_construct_vsif(hdev, VT_ALLM, 0, NULL); + if (is_hdmi14_4k(hdev->cur_VIC)) + hdmitx_construct_vsif(hdev, VT_HDMI14_4K, 1, NULL); + return count; + } + if (CMP_STR("1") || CMP_STR("game") || CMP_STR("graphics") + || CMP_STR("photo") || CMP_STR("cinema")) { + hdmitx_construct_vsif(hdev, VT_ALLM, 1, NULL); + } + if (CMP_STR("1") || CMP_STR("game")) { + hdev->allm_mode = 1; + // enable the default GAME ALLM + hdev->HWOp.CntlConfig(hdev, CONF_ALLM_MODE, SET_ALLM_GAME); + } + if (CMP_STR("graphics")) { + hdev->allm_mode = 2; + hdev->HWOp.CntlConfig(hdev, CONF_ALLM_MODE, SET_ALLM_GRAPHICS); + } + if (CMP_STR("photo")) { + hdev->allm_mode = 3; + hdev->HWOp.CntlConfig(hdev, CONF_ALLM_MODE, SET_ALLM_PHOTO); + } + if (CMP_STR("cinema")) { + hdev->allm_mode = 4; + hdev->HWOp.CntlConfig(hdev, CONF_ALLM_MODE, SET_ALLM_CINEMA); + } + + return count; +} /**/ static ssize_t show_hdr_cap(struct device *dev, @@ -3407,6 +3606,7 @@ static DEVICE_ATTR(hdr_cap, 0444, show_hdr_cap, NULL); static DEVICE_ATTR(dv_cap, 0444, show_dv_cap, NULL); static DEVICE_ATTR(dc_cap, 0444, show_dc_cap, NULL); static DEVICE_ATTR(valid_mode, 0664, show_valid_mode, store_valid_mode); +static DEVICE_ATTR(allm_mode, 0664, show_allm_mode, store_allm_mode); static DEVICE_ATTR(aud_ch, 0664, show_aud_ch, store_aud_ch); static DEVICE_ATTR(avmute, 0664, show_avmute, store_avmute); static DEVICE_ATTR(swap, 0644, show_swap, store_swap); @@ -3480,6 +3680,16 @@ static enum vmode_e hdmitx_validate_vmode(char *mode) if (info) { hdmitx_vinfo = info; + hdmitx_vinfo->info_3d = NON_3D; + if (hdmitx_device.flag_3dfp) + hdmitx_vinfo->info_3d = FP_3D; + + if (hdmitx_device.flag_3dtb) + hdmitx_vinfo->info_3d = TB_3D; + + if (hdmitx_device.flag_3dss) + hdmitx_vinfo->info_3d = SS_3D; + hdmitx_vinfo->vout_device = &hdmitx_vdev; return VMODE_HDMI; } @@ -3777,7 +3987,6 @@ static void hdmitx_hpd_plugin_handler(struct work_struct *work) rx_repeat_hpd_state(1); hdmitx_get_edid(hdev); hdmi_physcial_size_update(hdev); - #if defined(CONFIG_ARCH_MESON64_ODROID_COMMON) if (odroid_voutmode() == VOUTMODE_HDMI) { pr_info(VID "Sink is HDMI device\n"); @@ -3789,14 +3998,14 @@ static void hdmitx_hpd_plugin_handler(struct work_struct *work) CONF_HDMI_DVI_MODE, DVI_MODE); } else #endif - { - if (hdev->RXCap.IEEEOUI != 0x000c03) - hdev->HWOp.CntlConfig(hdev, - CONF_HDMI_DVI_MODE, DVI_MODE); - else - hdev->HWOp.CntlConfig(hdev, - CONF_HDMI_DVI_MODE, HDMI_MODE); - } +{ + if (hdev->RXCap.ieeeoui != HDMI_IEEEOUI) + hdev->HWOp.CntlConfig(hdev, + CONF_HDMI_DVI_MODE, DVI_MODE); + else + hdev->HWOp.CntlConfig(hdev, + CONF_HDMI_DVI_MODE, HDMI_MODE); +} mutex_lock(&getedid_mutex); mutex_unlock(&getedid_mutex); @@ -3821,35 +4030,16 @@ static void hdmitx_hpd_plugin_handler(struct work_struct *work) mutex_unlock(&setclk_mutex); } -static void clear_hdr_info(struct hdmitx_dev *hdev) +static void clear_rx_vinfo(struct hdmitx_dev *hdev) { struct vinfo_s *info = hdmitx_get_current_vinfo(); - unsigned int i; if (info) { - info->hdr_info.hdr_support = 0; - for (i = 0; i < 4; i++) - memset(&(info->hdr_info.dynamic_info[i]), - 0, sizeof(struct hdr_dynamic)); - info->hdr_info.colorimetry_support = 0; - info->hdr_info.lumi_max = 0; - info->hdr_info.lumi_avg = 0; - info->hdr_info.lumi_min = 0; - pr_info(SYS "clear RX hdr info\n"); + memset(&info->hdr_info, 0, sizeof(info->hdr_info)); + memset(&info->rx_latency, 0, sizeof(info->rx_latency)); } } -static void hdmitx_aud_hpd_plug_handler(struct work_struct *work) -{ - int st; - struct hdmitx_dev *hdev = container_of((struct delayed_work *)work, - struct hdmitx_dev, work_aud_hpd_plug); - - st = hdev->HWOp.CntlMisc(hdev, MISC_HPD_GPI_ST, 0); - pr_info("hdmitx_aud_hpd_plug_handler state:%d\n", st); - extcon_set_state_sync(hdmitx_extcon_audio, EXTCON_DISP_HDMI, st); -} - static void hdmitx_hpd_plugout_handler(struct work_struct *work) { struct hdmitx_dev *hdev = container_of((struct delayed_work *)work, @@ -3882,7 +4072,7 @@ static void hdmitx_hpd_plugout_handler(struct work_struct *work) hdev->HWOp.CntlMisc(hdev, MISC_TMDS_PHY_OP, TMDS_PHY_DISABLE); hdev->hdmitx_event &= ~HDMI_TX_HPD_PLUGOUT; hdev->HWOp.CntlMisc(hdev, MISC_ESM_RESET, 0); - clear_hdr_info(hdev); + clear_rx_vinfo(hdev); rx_edid_physical_addr(0, 0, 0, 0); hdmitx_edid_clear(hdev); hdmi_physcial_size_update(hdev); @@ -3890,12 +4080,13 @@ static void hdmitx_hpd_plugout_handler(struct work_struct *work) hdev->hpd_state = 0; hdmitx_notify_hpd(hdev->hpd_state); extcon_set_state_sync(hdmitx_extcon_hdmi, EXTCON_DISP_HDMI, 0); + extcon_set_state_sync(hdmitx_extcon_audio, EXTCON_DISP_HDMI, 0); mutex_unlock(&setclk_mutex); } static void hdmitx_internal_intr_handler(struct work_struct *work) { - struct hdmitx_dev *hdev = container_of((struct work_struct *)work, + struct hdmitx_dev *hdev = container_of((struct delayed_work *)work, struct hdmitx_dev, work_internal_intr); hdev->HWOp.DebugFun(hdev, "dumpintr"); @@ -3948,9 +4139,7 @@ static int hdmi_task_handle(void *data) hdmitx_hpd_plugin_handler); INIT_DELAYED_WORK(&hdmitx_device->work_hpd_plugout, hdmitx_hpd_plugout_handler); - INIT_DELAYED_WORK(&hdmitx_device->work_aud_hpd_plug, - hdmitx_aud_hpd_plug_handler); - INIT_WORK(&hdmitx_device->work_internal_intr, + INIT_DELAYED_WORK(&hdmitx_device->work_internal_intr, hdmitx_internal_intr_handler); /* for rx sense feature */ @@ -4028,7 +4217,7 @@ static int get_dt_vend_init_data(struct device_node *np, pr_info(SYS "not find product desc\n"); return 0; } - +#if 0 static void hdmitx_init_fmt_attr(struct hdmitx_dev *hdev) { if (strlen(hdev->fmt_attr) >= 8) { @@ -4074,7 +4263,7 @@ static void hdmitx_init_fmt_attr(struct hdmitx_dev *hdev) } pr_info(SYS "fmt_attr %s\n", hdev->fmt_attr); } - +#endif /* for notify to cec */ static BLOCKING_NOTIFIER_HEAD(hdmitx_event_notify_list); int hdmitx_event_notifier_regist(struct notifier_block *nb) @@ -4275,6 +4464,10 @@ static int amhdmitx_device_init(struct hdmitx_dev *hdmi_dev) */ hdmitx_device.hpdmode = 1; + hdmitx_device.flag_3dfp = 0; + hdmitx_device.flag_3dss = 0; + hdmitx_device.flag_3dtb = 0; + if ((init_flag&INIT_FLAG_POWERDOWN) && (hdmitx_device.hpdmode == 2)) hdmitx_device.mux_hpd_if_pin_high_flag = 0; else @@ -4324,6 +4517,7 @@ static int amhdmitx_get_dt_info(struct platform_device *pdev) #ifdef CONFIG_OF if (pdev->dev.of_node) { + int dongle_mode = 0; memset(&hdmitx_device.config_data, 0, sizeof(struct hdmi_config_platform_data)); /* Get ic type information */ @@ -4335,6 +4529,14 @@ static int amhdmitx_get_dt_info(struct platform_device *pdev) pr_info(SYS "hdmitx_device.chip_type : %d\n", hdmitx_device.chip_type); + /* Get dongle_mode information */ + ret = of_property_read_u32(pdev->dev.of_node, "dongle_mode", + &dongle_mode); + hdmitx_device.dongle_mode = !!dongle_mode; + if (!ret) + pr_info(SYS "hdmitx_device.dongle_mode: %d\n", + hdmitx_device.dongle_mode); + ret = of_property_read_u32(pdev->dev.of_node, "repeater_tx", &val); if (!ret) @@ -4565,6 +4767,7 @@ static int amhdmitx_probe(struct platform_device *pdev) ret = device_create_file(dev, &dev_attr_support_3d); ret = device_create_file(dev, &dev_attr_dc_cap); ret = device_create_file(dev, &dev_attr_valid_mode); + ret = device_create_file(dev, &dev_attr_allm_mode); #ifdef CONFIG_AMLOGIC_LEGACY_EARLY_SUSPEND register_early_suspend(&hdmitx_early_suspend_handler); @@ -4588,7 +4791,7 @@ static int amhdmitx_probe(struct platform_device *pdev) HDMITX_Meson_Init(&hdmitx_device); /* update fmt_attr */ - hdmitx_init_fmt_attr(&hdmitx_device); + /*hdmitx_init_fmt_attr(&hdmitx_device); */ hdmitx_device.task = kthread_run(hdmi_task_handle, &hdmitx_device, "kthread_hdmi"); @@ -4634,6 +4837,7 @@ static int amhdmitx_remove(struct platform_device *pdev) device_remove_file(dev, &dev_attr_dv_cap); device_remove_file(dev, &dev_attr_dc_cap); device_remove_file(dev, &dev_attr_valid_mode); + device_remove_file(dev, &dev_attr_allm_mode); device_remove_file(dev, &dev_attr_hpd_state); device_remove_file(dev, &dev_attr_rhpd_state); device_remove_file(dev, &dev_attr_max_exceed); @@ -4837,6 +5041,7 @@ static int __init hdmitx_boot_para_setup(char *s) char *token; unsigned int token_len = 0; unsigned int token_offset = 0; + unsigned long list; unsigned int offset = 0; int size = strlen(s); @@ -4849,6 +5054,13 @@ static int __init hdmitx_boot_para_setup(char *s) if ((token_len == 3) && (strncmp(token, "off", token_len) == 0)) { init_flag |= INIT_FLAG_NOT_LOAD; + } else if (strncmp(token, "cec", 3) == 0) { + int ret; + ret = kstrtoul(token+3, 16, &list); + if ((list >= 0) && (list <= 0xff)) + hdmitx_device.cec_func_config = list; + pr_info("HDMI hdmi_cec_func_config:0x%x\n", + hdmitx_device.cec_func_config); } check_hdmiuboot_attr(token); } diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_video.c b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_video.c index b1ffd00dee56..26494535a3f2 100644 --- a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_video.c +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_video.c @@ -772,12 +772,12 @@ static void hdmi_tx_construct_avi_packet( *************************************/ /* - * HDMI Identifier = 0x000c03 + * HDMI Identifier = HDMI_IEEEOUI 0x000c03 * If not, treated as a DVI Device */ static int is_dvi_device(struct rx_cap *pRXCap) { - if (pRXCap->IEEEOUI != 0x000c03) + if (pRXCap->ieeeoui != HDMI_IEEEOUI) return 1; else return 0; @@ -804,6 +804,8 @@ int hdmitx_set_display(struct hdmitx_dev *hdev, enum hdmi_vic VideoCode) hdev->cur_VIC = vic; param = hdmi_get_video_param(VideoCode); + if (hdev->cur_video_param != NULL) + param->color_depth = hdev->cur_video_param->color_depth; hdev->cur_video_param = param; if (param) { param->color = param->color_prefer; @@ -812,12 +814,14 @@ int hdmitx_set_display(struct hdmitx_dev *hdev, enum hdmi_vic VideoCode) */ switch (hdev->RXCap.native_Mode & 0x30) { case 0x20:/*bit5==1, then support YCBCR444 + RGB*/ - case 0x30: param->color = COLORSPACE_YUV444; break; case 0x10:/*bit4==1, then support YCBCR422 + RGB*/ param->color = COLORSPACE_YUV422; break; + case 0x30: + param->color = hdev->para->cs; + break; default: param->color = COLORSPACE_RGB444; } @@ -878,6 +882,29 @@ int hdmitx_set_display(struct hdmitx_dev *hdev, enum hdmi_vic VideoCode) hdmi_set_vend_spec_infofram(hdev, 0); else ; + + switch (hdev->RXCap.allm ? hdev->allm_mode : 0) { + case 1: /* game */ + hdmitx_construct_vsif(hdev, VT_ALLM, 1, NULL); + hdev->HWOp.CntlConfig(hdev, CONF_ALLM_MODE, + SET_ALLM_GAME); + break; + case 2: /* graphics */ + hdev->HWOp.CntlConfig(hdev, CONF_ALLM_MODE, + SET_ALLM_GRAPHICS); + break; + case 3: /* photo */ + hdev->HWOp.CntlConfig(hdev, CONF_ALLM_MODE, + SET_ALLM_PHOTO); + break; + case 4: /* cinema */ + hdev->HWOp.CntlConfig(hdev, CONF_ALLM_MODE, + SET_ALLM_CINEMA); + break; + default: + break; + } + ret = 0; } } @@ -908,9 +935,9 @@ static void hdmi_set_vend_spec_infofram(struct hdmitx_dev *hdev, for (i = 0; i < 0x6; i++) VEN_DB[i] = 0; - VEN_DB[0] = 0x03; - VEN_DB[1] = 0x0c; - VEN_DB[2] = 0x00; + VEN_DB[0] = GET_OUI_BYTE0(HDMI_IEEEOUI); + VEN_DB[1] = GET_OUI_BYTE1(HDMI_IEEEOUI); + VEN_DB[2] = GET_OUI_BYTE2(HDMI_IEEEOUI); VEN_DB[3] = 0x00; /* 4k x 2k Spec P156 */ if (VideoCode == HDMI_4k2k_30) { @@ -944,9 +971,9 @@ int hdmi_set_3d(struct hdmitx_dev *hdev, int type, unsigned int param) else { for (i = 0; i < 0x6; i++) VEN_DB[i] = 0; - VEN_DB[0] = 0x03; - VEN_DB[1] = 0x0c; - VEN_DB[2] = 0x00; + VEN_DB[0] = GET_OUI_BYTE0(HDMI_IEEEOUI); + VEN_DB[1] = GET_OUI_BYTE1(HDMI_IEEEOUI); + VEN_DB[2] = GET_OUI_BYTE2(HDMI_IEEEOUI); VEN_DB[3] = 0x40; VEN_DB[4] = type<<4; VEN_DB[5] = param<<4; @@ -984,3 +1011,74 @@ static void hdmitx_set_spd_info(struct hdmitx_dev *hdev) SPD_DB[24] = 0x1; hdev->HWOp.SetPacket(HDMI_SOURCE_DESCRIPTION, SPD_DB, SPD_HB); } + +static void fill_hdmi4k_vsif_data(enum hdmi_vic vic, unsigned char *DB, + unsigned char *HB) +{ + if (!DB || !HB) + return; + + if (vic == HDMI_4k2k_30) + DB[4] = 0x1; + else if (vic == HDMI_4k2k_25) + DB[4] = 0x2; + else if (vic == HDMI_4k2k_24) + DB[4] = 0x3; + else if (vic == HDMI_4k2k_smpte_24) + DB[4] = 0x4; + else + return; + HB[0] = 0x81; + HB[1] = 0x01; + HB[2] = 0x5; + DB[3] = 0x20; +} + +int hdmitx_construct_vsif(struct hdmitx_dev *hdev, enum vsif_type type, + int on, void *param) +{ + unsigned char HB[3] = {0x81, 0x1, 0}; + unsigned char len = 0; /* HB[2] = len */ + unsigned char DB[27]; /* to be fulfilled */ + unsigned int ieeeoui = 0; + + if (!hdev || type >= VT_MAX) + return 0; + memset(DB, 0, sizeof(DB)); + + switch (type) { + case VT_DEFAULT: + break; + case VT_HDMI14_4K: + ieeeoui = HDMI_IEEEOUI; + len = 5; + if (is_hdmi14_4k(hdev->cur_VIC)) { + fill_hdmi4k_vsif_data(hdev->cur_VIC, DB, HB); + hdmitx_set_avi_vic(0); + } + break; + case VT_ALLM: + ieeeoui = HF_IEEEOUI; + len = 5; + DB[3] = 0x1; /* Fixed value */ + if (on) { + DB[4] |= 1 << 1; /* set bit1, ALLM_MODE */ + if (is_hdmi14_4k(hdev->cur_VIC)) + hdmitx_set_avi_vic(hdev->cur_VIC); + } else { + DB[4] &= ~(1 << 1); /* clear bit1, ALLM_MODE */ + /* still send out HS_VSIF, no set AVI.VIC = 0 */ + } + break; + default: + break; + } + + HB[2] = len; + DB[0] = GET_OUI_BYTE0(ieeeoui); + DB[1] = GET_OUI_BYTE1(ieeeoui); + DB[2] = GET_OUI_BYTE2(ieeeoui); + + hdev->HWOp.SetDataPacket(HDMI_PACKET_VEND, DB, HB); + return 1; +} diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/enc_cfg_hw.c b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/enc_cfg_hw.c index dd324960c65d..21f4e9cfd45a 100644 --- a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/enc_cfg_hw.c +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/enc_cfg_hw.c @@ -1245,7 +1245,7 @@ static const struct reg_s tvregs_3dfp_1080p60[] = { {P_ENCP_VIDEO_MODE, 0x4040,}, {P_ENCP_VIDEO_MODE_ADV, 0x18,}, - {P_ENCP_VIDEO_MAX_PXCNT, 0x897,}, + {P_ENCP_VIDEO_MAX_PXCNT, 0xABD,}, {P_ENCP_VIDEO_MAX_LNCNT, 0x8C9,}, {P_ENCP_VIDEO_HAVON_BEGIN, 0xC0,}, {P_ENCP_VIDEO_HAVON_END, 0x83F,}, @@ -1325,7 +1325,7 @@ static const struct reg_s tvregs_3dfp_1080p50[] = { {P_ENCP_VIDEO_MODE, 0x4040,}, {P_ENCP_VIDEO_MODE_ADV, 0x18,}, - {P_ENCP_VIDEO_MAX_PXCNT, 0xA4F,}, + {P_ENCP_VIDEO_MAX_PXCNT, 0xABD,}, {P_ENCP_VIDEO_MAX_LNCNT, 0x8C9,}, {P_ENCP_VIDEO_HAVON_BEGIN, 0xC0,}, {P_ENCP_VIDEO_HAVON_END, 0x83F,}, diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdmi_tx_hw.c b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdmi_tx_hw.c index 61bb649f3860..90e7641fdf5b 100644 --- a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdmi_tx_hw.c +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdmi_tx_hw.c @@ -68,6 +68,8 @@ struct ksv_lists_ { static struct ksv_lists_ tmp_ksv_lists; static void hdmitx_set_packet(int type, unsigned char *DB, unsigned char *HB); +static void hdmitx_set_datapacket(int type, unsigned char *DB, + unsigned char *HB); static void hdmitx_setaudioinfoframe(unsigned char *AUD_DB, unsigned char *CHAN_STAT_BUF); static int hdmitx_set_dispmode(struct hdmitx_dev *hdev); @@ -102,12 +104,8 @@ static int hdmitx_cntl_misc(struct hdmitx_dev *hdev, unsigned int cmd, /* store downstream ksv lists */ static char *rptx_ksvs; -static char rptx_ksv_prbuf[1271]; /* 127 * 5 * 2 + 1 */ MODULE_PARM_DESC(rptx_ksvs, "\n downstream ksvs\n"); module_param(rptx_ksvs, charp, 0444); -static int rptx_ksv_no; -static int rptx_ksvlist_retry; -static char rptx_ksv_buf[635]; #if defined(CONFIG_ARCH_MESON64_ODROID_COMMON) static int dvi_mode = VOUTMODE_NOINIT; @@ -150,6 +148,7 @@ int hdmitx_hpd_hw_op(enum hpd_op cmd) return hdmitx_hpd_hw_op_txlx(cmd); case MESON_CPU_ID_G12A: case MESON_CPU_ID_G12B: + case MESON_CPU_ID_SM1: return hdmitx_hpd_hw_op_g12a(cmd); default: break; @@ -173,6 +172,7 @@ int read_hpd_gpio(void) case MESON_CPU_ID_TXLX: case MESON_CPU_ID_G12A: case MESON_CPU_ID_G12B: + case MESON_CPU_ID_SM1: return read_hpd_gpio_txlx(); default: break; @@ -196,6 +196,7 @@ int hdmitx_ddc_hw_op(enum ddc_op cmd) case MESON_CPU_ID_TXLX: case MESON_CPU_ID_G12A: case MESON_CPU_ID_G12B: + case MESON_CPU_ID_SM1: return hdmitx_ddc_hw_op_txlx(cmd); default: break; @@ -277,6 +278,11 @@ static void config_avmute(unsigned int val) } } +void hdmitx_set_avi_vic(enum hdmi_vic vic) +{ + hdmitx_wr_reg(HDMITX_DWC_FC_AVIVID, vic); +} + static int read_avmute(void) { int val; @@ -419,6 +425,7 @@ static unsigned int hdmitx_get_format(void) case MESON_CPU_ID_TXLX: case MESON_CPU_ID_G12A: case MESON_CPU_ID_G12B: + case MESON_CPU_ID_SM1: ret = hdmitx_get_format_txlx(); break; case MESON_CPU_ID_GXBB: @@ -465,6 +472,7 @@ void hdmitx_sys_reset(void) case MESON_CPU_ID_TXLX: case MESON_CPU_ID_G12A: case MESON_CPU_ID_G12B: + case MESON_CPU_ID_SM1: hdmitx_sys_reset_txlx(); break; case MESON_CPU_ID_GXBB: @@ -582,6 +590,11 @@ static void hdmi_hwi_init(struct hdmitx_dev *hdev) hdmitx_set_reg_bits(HDMITX_TOP_CLK_CNTL, 1, 6, 1); /* Enable tmds_clk to HDCP2.2 IP */ hdmitx_set_reg_bits(HDMITX_TOP_CLK_CNTL, 1, 5, 1); + /* Enable axi_clk */ + hdmitx_set_reg_bits(HDMITX_TOP_CLK_CNTL, 1, 13, 1); + /* Enable axi_async_req_en_emp & axi_async_req_en_esm */ + hdmitx_set_reg_bits(HDMITX_TOP_AXI_ASYNC_CNTL0, 1, 0, 1); + hdmitx_set_reg_bits(HDMITX_TOP_AXI_ASYNC_CNTL0, 1, 16, 1); hdmitx_hpd_hw_op(HPD_INIT_DISABLE_PULLUP); hdmitx_hpd_hw_op(HPD_INIT_SET_FILTER); @@ -635,6 +648,7 @@ static void hdmi_hwi_init(struct hdmitx_dev *hdev) void HDMITX_Meson_Init(struct hdmitx_dev *hdev) { hdev->HWOp.SetPacket = hdmitx_set_packet; + hdev->HWOp.SetDataPacket = hdmitx_set_datapacket; hdev->HWOp.SetAudioInfoFrame = hdmitx_setaudioinfoframe; hdev->HWOp.SetDispMode = hdmitx_set_dispmode; hdev->HWOp.SetAudMode = hdmitx_set_audmode; @@ -664,9 +678,8 @@ static irqreturn_t intr_handler(int irq, void *dev) hdmitx_wr_reg(HDMITX_TOP_INTR_STAT_CLR, ~0); hdmitx_wr_reg(HDMITX_DWC_HDCP22REG_STAT, 0xff); - pr_info(SYS "irq %x\n", dat_top); - if (dat_dwc) - pr_info(SYS "irq %x\n", dat_dwc); + pr_info(SYS "irq %x %x\n", dat_top, dat_dwc); + if (hdev->hpd_lock == 1) { pr_info(HW "HDMI hpd locked\n"); goto next; @@ -688,8 +701,6 @@ static irqreturn_t intr_handler(int irq, void *dev) } /* HPD falling */ if (dat_top & (1 << 2)) { - queue_delayed_work(hdev->hdmi_wq, - &hdev->work_aud_hpd_plug, 2 * HZ); hdev->hdmitx_event |= HDMI_TX_HPD_PLUGOUT; hdev->hdmitx_event &= ~HDMI_TX_HPD_PLUGIN; hdev->rhpd_state = 0; @@ -699,7 +710,8 @@ static irqreturn_t intr_handler(int irq, void *dev) /* internal interrupt */ if (dat_top & (1 << 0)) { hdev->hdmitx_event |= HDMI_TX_INTERNAL_INTR; - queue_work(hdev->hdmi_wq, &hdev->work_internal_intr); + queue_delayed_work(hdev->hdmi_wq, + &hdev->work_internal_intr, HZ / 10); } if (dat_top & (1 << 3)) { unsigned int rd_nonce_mode = @@ -2010,14 +2022,19 @@ static void set_phy_by_mode(unsigned int mode) switch (hdev->chip_type) { case MESON_CPU_ID_G12A: case MESON_CPU_ID_G12B: + case MESON_CPU_ID_SM1: switch (mode) { case 1: /* 5.94/4.5/3.7Gbps */ hd_write_reg(P_HHI_HDMI_PHY_CNTL0, 0x37eb65c4); + if (hdev->dongle_mode) + hd_write_reg(P_HHI_HDMI_PHY_CNTL0, 0x37eb5584); hd_write_reg(P_HHI_HDMI_PHY_CNTL3, 0x2ab0ff3b); hd_write_reg(P_HHI_HDMI_PHY_CNTL5, 0x0000080b); break; case 2: /* 2.97Gbps */ - hd_write_reg(P_HHI_HDMI_PHY_CNTL0, 0x33eb6262); + hd_write_reg(P_HHI_HDMI_PHY_CNTL0, 0x33eb6272); + if (hdev->dongle_mode) + hd_write_reg(P_HHI_HDMI_PHY_CNTL0, 0x33eb4262); hd_write_reg(P_HHI_HDMI_PHY_CNTL3, 0x2ab0ff3b); hd_write_reg(P_HHI_HDMI_PHY_CNTL5, 0x00000003); break; @@ -2113,7 +2130,7 @@ do { \ case HDMI_4096x2160p25_256x135: case HDMI_4096x2160p30_256x135: if ((hdev->para->cs == COLORSPACE_YUV422) - || (hdev->para->cd == COLORDEPTH_24B)) + || (hdev->cur_video_param->color_depth == COLORDEPTH_24B)) set_phy_by_mode(2); else set_phy_by_mode(1); @@ -2131,7 +2148,7 @@ do { \ case HDMI_3840x2160p60_16x9_Y420: case HDMI_4096x2160p50_256x135_Y420: case HDMI_4096x2160p60_256x135_Y420: - if (hdev->para->cd == COLORDEPTH_24B) + if (hdev->cur_video_param->color_depth == COLORDEPTH_24B) set_phy_by_mode(2); else set_phy_by_mode(1); @@ -2139,7 +2156,7 @@ do { \ /* consider HPLL over 2Gbps */ case HDMI_2560x1600p60_8x5: case HDMI_2560x1440p60_16x9: - if (hdev->para->cd == COLORDEPTH_24B) + if (hdev->cur_video_param->color_depth == COLORDEPTH_24B) set_phy_by_mode(2); else set_phy_by_mode(1); @@ -2184,7 +2201,7 @@ static void hdmitx_set_scdc(struct hdmitx_dev *hdev) case HDMI_4096x2160p50_256x135: case HDMI_4096x2160p60_256x135: if ((hdev->para->cs == COLORSPACE_YUV420) - && (hdev->para->cd == COLORDEPTH_24B)) + && (hdev->cur_video_param->color_depth == COLORDEPTH_24B)) hdev->para->tmds_clk_div40 = 0; else hdev->para->tmds_clk_div40 = 1; @@ -2195,7 +2212,7 @@ static void hdmitx_set_scdc(struct hdmitx_dev *hdev) case HDMI_4096x2160p60_256x135_Y420: case HDMI_3840x2160p50_64x27_Y420: case HDMI_3840x2160p60_64x27_Y420: - if (hdev->para->cd == COLORDEPTH_24B) + if (hdev->cur_video_param->color_depth == COLORDEPTH_24B) hdev->para->tmds_clk_div40 = 0; else hdev->para->tmds_clk_div40 = 1; @@ -2210,7 +2227,7 @@ static void hdmitx_set_scdc(struct hdmitx_dev *hdev) case HDMI_3840x2160p30_64x27: case HDMI_4096x2160p30_256x135: if ((hdev->para->cs == COLORSPACE_YUV422) - || (hdev->para->cd == COLORDEPTH_24B)) + || (hdev->cur_video_param->color_depth == COLORDEPTH_24B)) hdev->para->tmds_clk_div40 = 0; else hdev->para->tmds_clk_div40 = 1; @@ -2444,6 +2461,40 @@ static void hdmitx_set_packet(int type, unsigned char *DB, unsigned char *HB) } } +static void hdmitx_set_datapacket(int type, unsigned char *DB, + unsigned char *HB) +{ + int i; +#if 0 + pr_info("HB: %02x %02x %02x\nDB:", HB[0], HB[1], HB[2]); + for (i = 0; (i < 24) && (i < HB[2]); i++) + pr_info(" %02x", DB[i]); + pr_info("\n"); +#endif + switch (type) { + case HDMI_PACKET_VEND: + if ((!DB) || (!HB)) { + hdmitx_set_reg_bits(HDMITX_DWC_FC_DATAUTO0, 0, 3, 1); + hdmitx_wr_reg(HDMITX_DWC_FC_VSDSIZE, 0x0); + return; + } + hdmitx_wr_reg(HDMITX_DWC_FC_VSDSIZE, HB[2]); + hdmitx_wr_reg(HDMITX_DWC_FC_VSDIEEEID0, DB[0]); + hdmitx_wr_reg(HDMITX_DWC_FC_VSDIEEEID1, DB[1]); + hdmitx_wr_reg(HDMITX_DWC_FC_VSDIEEEID2, DB[2]); + for (i = 0; (i < 24) && (i < HB[2]); i++) + hdmitx_wr_reg(HDMITX_DWC_FC_VSDPAYLOAD0 + i, DB[3 + i]); + /* Enable VSI packet */ + hdmitx_set_reg_bits(HDMITX_DWC_FC_DATAUTO0, 1, 3, 1); + hdmitx_wr_reg(HDMITX_DWC_FC_DATAUTO1, 0); + hdmitx_wr_reg(HDMITX_DWC_FC_DATAUTO2, 0x10); + hdmitx_set_reg_bits(HDMITX_DWC_FC_PACKET_TX_EN, 1, 4, 1); + break; + default: + break; + } +} + static void hdmitx_setaudioinfoframe(unsigned char *AUD_DB, unsigned char *CHAN_STAT_BUF) @@ -2619,14 +2670,6 @@ static void set_aud_acr_pkt(struct hdmitx_dev *hdev, else aud_n_para = hdmi_get_aud_n_paras(audio_param->sample_rate, hdev->para->cd, char_rate); - /* N must mutiples 4 for DD+ */ - switch (audio_param->type) { - case CT_DOLBY_D: - aud_n_para *= 4; - break; - default: - break; - } pr_info(HW "aud_n_para = %d\n", aud_n_para); /* ACR packet configuration */ @@ -2885,6 +2928,7 @@ static int hdmitx_cntl(struct hdmitx_dev *hdev, unsigned int cmd, switch (hdev->chip_type) { case MESON_CPU_ID_G12A: case MESON_CPU_ID_G12B: + case MESON_CPU_ID_SM1: hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL, 1, 29, 1); udelay(50); hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL, 0, 28, 1); @@ -3046,11 +3090,9 @@ do { \ #define DUMP_HDMITXREG_SECTION(start, end) \ do { \ - if (start > end) { \ - pr_info("Error start = 0x%lx > end = 0x%lx\n", start, end); \ + if (start > end) \ break; \ - } \ - pr_info("Start = 0x%lx End = 0x%lx\n", start, end); \ +\ for (addr = start; addr < end + 1; addr++) { \ val = hdmitx_rd_reg(addr); \ if (val) \ @@ -3062,7 +3104,12 @@ static void hdmitx_dump_intr(void) { unsigned int addr = 0, val = 0; - DUMP_HDMITXREG_SECTION(HDMITX_DWC_IH_FC_STAT0, HDMITX_DWC_IH_MUTE); + DUMP_HDMITXREG_SECTION(HDMITX_DWC_IH_FC_STAT0, + HDMITX_DWC_IH_I2CMPHY_STAT0); + DUMP_HDMITXREG_SECTION(HDMITX_DWC_IH_DECODE, HDMITX_DWC_IH_DECODE); + DUMP_HDMITXREG_SECTION(HDMITX_DWC_IH_MUTE_FC_STAT0, + HDMITX_DWC_IH_MUTE_I2CMPHY_STAT0); + DUMP_HDMITXREG_SECTION(HDMITX_DWC_IH_MUTE, HDMITX_DWC_IH_MUTE); } static void mode420_half_horizontal_para(void) @@ -3659,7 +3706,7 @@ static void hdmitx_dump_audio_info(void) conf = "One Bit Audio"; break; case CT_DOLBY_D: - conf = "Dobly Digital+"; + conf = "Dolby Digital+"; break; case CT_DTS_HD: conf = "DTS_HD"; @@ -4250,7 +4297,7 @@ static void hdmitx_debug(struct hdmitx_dev *hdev, const char *buf) pr_info("topo: %d\n", hdmitx_hdcp_opr(0xe)); return; } else if (strncmp(tmpbuf, "dumphdmireg", 11) == 0) { - unsigned char reg_val = 0; + unsigned int reg_val = 0; unsigned int reg_adr = 0; #define DUMP_HDMITX_SECTION(a, b) \ @@ -4275,8 +4322,10 @@ static void hdmitx_debug(struct hdmitx_dev *hdev, const char *buf) HDMITX_TOP_SEC_SCRATCH); DUMP_HDMITX_SECTION(HDMITX_DWC_DESIGN_ID, HDMITX_DWC_A_KSVMEMCTRL); +#if 0 DUMP_HDMITX_HDCP_SECTION(HDMITX_DWC_HDCP_BSTATUS_0, HDMITX_DWC_HDCP_REVOC_LIST_END); +#endif DUMP_HDMITX_HDCP_SECTION(HDMITX_DWC_HDCPREG_BKSV0, HDMITX_DWC_HDCPREG_BKSV4); DUMP_HDMITX_SECTION(HDMITX_DWC_HDCPREG_ANCONF, @@ -4368,6 +4417,7 @@ static void hdmitx_debug(struct hdmitx_dev *hdev, const char *buf) switch (hdev->chip_type) { case MESON_CPU_ID_G12A: case MESON_CPU_ID_G12B: + case MESON_CPU_ID_SM1: for (i = 0; i < 4; i++) { hd_write_reg(P_HHI_HDMI_PHY_CNTL1, 0x0390000f); hd_write_reg(P_HHI_HDMI_PHY_CNTL1, 0x0390000e); @@ -4842,6 +4892,7 @@ static int hdmitx_cntl_ddc(struct hdmitx_dev *hdev, unsigned int cmd, break; case DDC_HDCP_MUX_INIT: if (argv == 2) { + hd_write_reg(P_HHI_HDCP22_CLK_CNTL, 0x01000100); hdmitx_ddc_hw_op(DDC_MUX_DDC); hdmitx_set_reg_bits(HDMITX_DWC_MC_CLKDIS, 1, 6, 1); udelay(5); @@ -5046,6 +5097,28 @@ static int hdmitx_cntl_config(struct hdmitx_dev *hdev, unsigned int cmd, case CONF_AVI_YQ01: hdmitx_set_reg_bits(HDMITX_DWC_FC_AVICONF3, argv, 2, 2); break; + case CONF_ALLM_MODE: + if (argv == CLEAR_ALLM_MODE) { + hdmitx_set_reg_bits(HDMITX_DWC_FC_AVICONF2, 0, 7, 1); + hdmitx_set_reg_bits(HDMITX_DWC_FC_AVICONF3, 0, 0, 2); + break; + } + if (argv == GET_ALLM_MODE) { + if (hdmitx_rd_reg(HDMITX_DWC_FC_AVICONF2) & (1 << 7)) + ret = hdmitx_rd_reg(HDMITX_DWC_FC_AVICONF3) & 3; + else + ret = -1; + break; + } + /* set ALLM mode */ + hdmitx_set_reg_bits(HDMITX_DWC_FC_AVICONF2, 1, 7, 1); + hdmitx_set_reg_bits(HDMITX_DWC_FC_AVICONF3, argv & 3, 0, 2); + if (argv == SET_ALLM_PHOTO) { + // TODO + // Extended colorimetry field may be + // sYcc601, AdobeYcc601 or AdobeRGB + } + break; case CONF_EMP_NUMBER: hdmitx_set_reg_bits(HDMITX_TOP_EMP_CNTL0, argv, 16, 16); break; @@ -6171,10 +6244,10 @@ static void hdmitx_set_hw(struct hdmitx_dev *hdev) } pr_info(HW " config hdmitx IP vic = %d cd:%d cs: %d\n", vic, - hdev->para->cd, hdev->para->cs); + hdev->cur_video_param->color_depth, hdev->para->cs); config_hdmi20_tx(vic, hdev, - hdev->para->cd, + hdev->cur_video_param->color_depth, TX_INPUT_COLOR_FORMAT, hdev->para->cs); } diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdmi_tx_reg.h b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdmi_tx_reg.h index 596292525948..d5b95e8883c6 100644 --- a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdmi_tx_reg.h +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hdmi_tx_reg.h @@ -79,6 +79,10 @@ int hdmitx_hdcp_opr(unsigned int val); /* intr_maskn: MASK_N, one bit per interrupt source. * 1=Enable interrupt source; 0=Disable interrupt source. Default 0. + * [ 8] hdcp_topology_err + * [ 7] rxsense_fall + * [ 6] rxsense_rise + * [ 5] err_i2c_timeout * [ 4] hdcp22_rndnum_err * [ 3] nonce_rfrsh_rise * [ 2] hpd_fall_intr @@ -185,6 +189,7 @@ int hdmitx_hdcp_opr(unsigned int val); #define HDMITX_TOP_I2C_BUSY_CNT_STAT (TOP_OFFSET_MASK + 0x029) #define HDMITX_TOP_HDCP22_BSOD (TOP_SEC_OFFSET_MASK + 0x02A) #define HDMITX_TOP_DDC_CNTL (TOP_OFFSET_MASK + 0x02B) +#define HDMITX_TOP_DISABLE_NULL (TOP_OFFSET_MASK + 0x030) #define HDMITX_TOP_REVOCMEM_ADDR_S (TOP_OFFSET_MASK + 0x2000 >> 2) #define HDMITX_TOP_REVOCMEM_ADDR_E (TOP_OFFSET_MASK + 0x365E >> 2) @@ -921,6 +926,8 @@ int hdmitx_hdcp_opr(unsigned int val); /* [ 1] Rsvd for read-only ksv_mem_access */ /* [ 0] ksv_mem_request */ #define HDMITX_DWC_A_KSVMEMCTRL (DWC_OFFSET_MASK + 0x5016) +#define HDMITX_DWC_A_BSTATUS_HI (DWC_OFFSET_MASK + 0x5017) +#define HDMITX_DWC_A_BSTATUS_LO (DWC_OFFSET_MASK + 0x5018) #define HDMITX_DWC_HDCP_BSTATUS_0 (TOP_OFFSET_MASK + 0x2000) #define HDMITX_DWC_HDCP_BSTATUS_1 (TOP_OFFSET_MASK + 0x2001) diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hw_clk.c b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hw_clk.c index 7b4613a7c319..bf1dc31b9342 100644 --- a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hw_clk.c +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hw_clk.c @@ -165,6 +165,7 @@ void hdmitx_set_cts_hdcp22_clk(struct hdmitx_dev *hdev) case MESON_CPU_ID_GXM: case MESON_CPU_ID_G12A: case MESON_CPU_ID_G12B: + case MESON_CPU_ID_SM1: default: hd_write_reg(P_HHI_HDCP22_CLK_CNTL, 0x01000100); break; @@ -441,6 +442,7 @@ static void set_hpll_clk_out(unsigned int clk) break; case MESON_CPU_ID_G12A: case MESON_CPU_ID_G12B: + case MESON_CPU_ID_SM1: set_g12a_hpll_clk_out(frac_rate, clk); break; default: @@ -458,6 +460,7 @@ static void set_hpll_sspll(enum hdmi_vic vic) switch (hdev->chip_type) { case MESON_CPU_ID_G12A: case MESON_CPU_ID_G12B: + case MESON_CPU_ID_SM1: set_hpll_sspll_g12a(vic); break; case MESON_CPU_ID_GXBB: @@ -503,6 +506,7 @@ static void set_hpll_od1(unsigned int div) break; case MESON_CPU_ID_G12A: case MESON_CPU_ID_G12B: + case MESON_CPU_ID_SM1: set_hpll_od1_g12a(div); break; default: @@ -541,6 +545,7 @@ static void set_hpll_od2(unsigned int div) break; case MESON_CPU_ID_G12A: case MESON_CPU_ID_G12B: + case MESON_CPU_ID_SM1: set_hpll_od2_g12a(div); break; default: @@ -579,6 +584,7 @@ static void set_hpll_od3(unsigned int div) break; case MESON_CPU_ID_G12A: case MESON_CPU_ID_G12B: + case MESON_CPU_ID_SM1: set_hpll_od3_g12a(div); break; default: @@ -966,9 +972,19 @@ static void hdmitx_set_clk_(struct hdmitx_dev *hdev) struct hw_enc_clk_val_group *p_enc = NULL; enum hdmi_vic vic = hdev->cur_VIC; enum hdmi_color_space cs = hdev->para->cs; - enum hdmi_color_depth cd = hdev->para->cd; + enum hdmi_color_depth cd; struct hdmi_cea_timing *custom_timing; + if (hdev->cur_video_param->color_depth && hdev->cur_video_param->color_depth > 0) + cd = hdev->cur_video_param->color_depth; + else + cd = hdev->para->cd; + frac_rate = hdev->frac_rate_policy; + if (hdev->para->cs == COLORSPACE_YUV420) + vic |= 256; + pr_info("hdmitx: set clk: VIC = %d cd = %d cs = %d frac_rate = %d\n", vic, + cd, hdev->para->cs, frac_rate); + /* YUV 422 always use 24B mode */ if (cs == COLORSPACE_YUV422) cd = COLORDEPTH_24B; diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hw_g12a.c b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hw_g12a.c index 5179fcebf996..3f0e4df5d9e5 100644 --- a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hw_g12a.c +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hw_g12a.c @@ -164,12 +164,45 @@ static bool set_hpll_hclk_v3(unsigned int m, unsigned int frac_val) return ret; /* return hpll locked status */ } +#define IS_DONGLE_MODE(hdev) \ + ((hdev->dongle_mode) \ + && (hdev->para->cs == COLORSPACE_YUV422 \ + || hdev->para->cd == COLORDEPTH_24B) \ + && (hdev->cur_VIC == HDMI_1280x720p50_16x9 \ + || hdev->cur_VIC == HDMI_1280x720p60_16x9 \ + || hdev->cur_VIC == HDMI_1920x1080i60_16x9 \ + || hdev->cur_VIC == HDMI_1920x1080i50_16x9 \ + || hdev->cur_VIC == HDMI_1920x1080p60_16x9 \ + || hdev->cur_VIC == HDMI_1920x1080p50_16x9)) + +static void set_hpll_hclk_dongle_5940m(void) +{ + hd_write_reg(P_HHI_HDMI_PLL_CNTL0, 0x0b3a04f7); + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL0, 0x3, 28, 2); + hd_write_reg(P_HHI_HDMI_PLL_CNTL1, 0x10000); + hd_write_reg(P_HHI_HDMI_PLL_CNTL2, 0x00100140); + hd_write_reg(P_HHI_HDMI_PLL_CNTL3, 0x2a295c00); + hd_write_reg(P_HHI_HDMI_PLL_CNTL4, 0x65771290); + hd_write_reg(P_HHI_HDMI_PLL_CNTL5, 0x39272000); + hd_write_reg(P_HHI_HDMI_PLL_CNTL6, 0x50540000); + pr_info("HPLL: 0x%x\n", hd_read_reg(P_HHI_HDMI_PLL_CNTL0)); + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL0, 0x0, 29, 1); + pr_info("HPLL: 0x%x\n", hd_read_reg(P_HHI_HDMI_PLL_CNTL0)); + WAIT_FOR_PLL_LOCKED(P_HHI_HDMI_PLL_CNTL0); + pr_info("HPLL: 0x%x\n", hd_read_reg(P_HHI_HDMI_PLL_CNTL0)); +} + void set_g12a_hpll_clk_out(unsigned int frac_rate, unsigned int clk) { unsigned int m, m1, m2; + struct hdmitx_dev *hdev = get_hdmitx_device(); switch (clk) { case 5940000: + if (IS_DONGLE_MODE(hdev)) { + set_hpll_hclk_dongle_5940m(); + break; + } if (set_hpll_hclk_v1(0xf7, frac_rate ? 0x8148 : 0x10000)) break; else if (set_hpll_hclk_v2(0x7b, 0x18000)) @@ -616,6 +649,8 @@ int hdmitx_hpd_hw_op_g12a(enum hpd_op cmd) void set_hpll_sspll_g12a(enum hdmi_vic vic) { + struct hdmitx_dev *hdev = get_hdmitx_device(); + switch (vic) { case HDMI_1920x1080p60_16x9: case HDMI_1920x1080p50_16x9: @@ -632,6 +667,8 @@ void set_hpll_sspll_g12a(enum hdmi_vic vic) hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL2, 1, 8, 1); /* 2: 1000ppm 1: 500ppm */ hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL2, 2, 4, 4); + if (hdev->dongle_mode) + hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL2, 4, 4, 4); /* bit[15] hdmi_dpll_sdmnc_en */ hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL3, 0, 15, 1); hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL0, 0, 29, 1); diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/reg_ops.c b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/reg_ops.c index cb5f40b2e36f..7440ed5f1511 100644 --- a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/reg_ops.c +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/reg_ops.c @@ -165,6 +165,7 @@ void init_reg_map(unsigned int type) switch (type) { case MESON_CPU_ID_G12A: case MESON_CPU_ID_G12B: + case MESON_CPU_ID_SM1: map = reg_maps_g12a; for (i = 0; i < REG_IDX_END; i++) { map[i].p = ioremap(map[i].phy_addr, map[i].size); @@ -252,6 +253,7 @@ unsigned int hd_read_reg(unsigned int addr) case MESON_CPU_ID_GXM: case MESON_CPU_ID_G12A: case MESON_CPU_ID_G12B: + case MESON_CPU_ID_SM1: default: val = readl(TO_PMAP_ADDR(addr)); break; @@ -301,6 +303,7 @@ void hd_write_reg(unsigned int addr, unsigned int val) case MESON_CPU_ID_GXM: case MESON_CPU_ID_G12A: case MESON_CPU_ID_G12B: + case MESON_CPU_ID_SM1: default: writel(val, TO_PMAP_ADDR(addr)); break; diff --git a/drivers/amlogic/media/vout/lcd/Makefile b/drivers/amlogic/media/vout/lcd/Makefile index c5dab0196ad2..8b3baf15ebf1 100644 --- a/drivers/amlogic/media/vout/lcd/Makefile +++ b/drivers/amlogic/media/vout/lcd/Makefile @@ -1,6 +1,6 @@ obj-$(CONFIG_AMLOGIC_LCD) += lcd_vout.o lcd_reg.o lcd_common.o lcd_notify.o \ - lcd_debug.o lcd_clk_config.o lcd_unifykey.o \ - lcd_tcon.o + lcd_debug.o lcd_clk_config.o lcd_phy_config.o \ + lcd_unifykey.o lcd_tcon.o obj-$(CONFIG_AMLOGIC_LCD_TV) += lcd_tv/ obj-$(CONFIG_AMLOGIC_LCD_TABLET) += lcd_tablet/ obj-$(CONFIG_AMLOGIC_LCD_EXTERN) += lcd_extern/ diff --git a/drivers/amlogic/media/vout/lcd/lcd_clk_config.c b/drivers/amlogic/media/vout/lcd/lcd_clk_config.c index 98e693320662..10200e2549c1 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_clk_config.c +++ b/drivers/amlogic/media/vout/lcd/lcd_clk_config.c @@ -47,9 +47,11 @@ static struct lcd_clk_config_s clk_conf = { /* unit: kHz */ .pll_od1_sel = 0, .pll_od2_sel = 0, .pll_od3_sel = 0, - .pll_pi_div_sel = 0, /* for tcon */ + .pll_tcon_div_sel = 0, .pll_level = 0, .ss_level = 0, + .ss_freq = 0, + .ss_mode = 0, .div_sel = 0, .xd = 0, .pll_fout = 0, @@ -63,6 +65,7 @@ static struct lcd_clk_config_s clk_conf = { /* unit: kHz */ static struct lcd_clktree_s lcd_clktree = { .clk_gate_state = 0, + .clk_gate_optional_state = 0, /* by interface */ .encl_top_gate = NULL, .encl_int_gate = NULL, @@ -162,7 +165,7 @@ pll_lock_end_g12a: return ret; } -static void lcd_set_pll_ss_txl(unsigned int ss_level) +static void lcd_set_pll_ss_level_txl(unsigned int level) { unsigned int pll_ctrl3, pll_ctrl4; @@ -171,15 +174,13 @@ static void lcd_set_pll_ss_txl(unsigned int ss_level) pll_ctrl3 &= ~((0xf << 10) | (1 << 14)); pll_ctrl4 &= ~(0x3 << 2); - ss_level = (ss_level >= SS_LEVEL_MAX_TXL) ? 0 : ss_level; - pll_ctrl3 |= pll_ss_reg_txl[ss_level][0]; - pll_ctrl4 |= pll_ss_reg_txl[ss_level][1]; + pll_ctrl3 |= pll_ss_reg_txl[level][0]; + pll_ctrl4 |= pll_ss_reg_txl[level][1]; lcd_hiu_write(HHI_HDMI_PLL_CNTL3, pll_ctrl3); lcd_hiu_write(HHI_HDMI_PLL_CNTL4, pll_ctrl4); - LCDPR("set pll spread spectrum: %s\n", - lcd_pll_ss_table_txl[ss_level]); + LCDPR("set pll spread spectrum: %s\n", lcd_ss_level_table_txl[level]); } static void lcd_set_pll_txl(struct lcd_clk_config_s *cConf) @@ -216,10 +217,10 @@ static void lcd_set_pll_txl(struct lcd_clk_config_s *cConf) LCDERR("hpll lock failed\n"); if (cConf->ss_level > 0) - lcd_set_pll_ss_txl(cConf->ss_level); + lcd_set_pll_ss_level_txl(cConf->ss_level); } -static void lcd_set_pll_ss_txlx(unsigned int ss_level) +static void lcd_set_pll_ss_level_txlx(unsigned int level) { unsigned int pll_ctrl3, pll_ctrl4, pll_ctrl5; @@ -230,17 +231,15 @@ static void lcd_set_pll_ss_txlx(unsigned int ss_level) pll_ctrl4 &= ~(0x3 << 2); pll_ctrl5 &= ~(0x3 << 30); - ss_level = (ss_level >= SS_LEVEL_MAX_TXLX) ? 0 : ss_level; - pll_ctrl3 |= pll_ss_reg_txlx[ss_level][0]; - pll_ctrl4 |= pll_ss_reg_txlx[ss_level][1]; - pll_ctrl5 |= pll_ss_reg_txlx[ss_level][2]; + pll_ctrl3 |= pll_ss_reg_txlx[level][0]; + pll_ctrl4 |= pll_ss_reg_txlx[level][1]; + pll_ctrl5 |= pll_ss_reg_txlx[level][2]; lcd_hiu_write(HHI_HDMI_PLL_CNTL3, pll_ctrl3); lcd_hiu_write(HHI_HDMI_PLL_CNTL4, pll_ctrl4); lcd_hiu_write(HHI_HDMI_PLL_CNTL5, pll_ctrl5); - LCDPR("set pll spread spectrum: %s\n", - lcd_pll_ss_table_txlx[ss_level]); + LCDPR("set pll spread spectrum: %s\n", lcd_ss_level_table_txlx[level]); } static void lcd_set_pll_txlx(struct lcd_clk_config_s *cConf) @@ -274,7 +273,7 @@ static void lcd_set_pll_txlx(struct lcd_clk_config_s *cConf) LCDERR("hpll lock failed\n"); if (cConf->ss_level > 0) - lcd_set_pll_ss_txlx(cConf->ss_level); + lcd_set_pll_ss_level_txlx(cConf->ss_level); } static void lcd_set_pll_axg(struct lcd_clk_config_s *cConf) @@ -476,46 +475,103 @@ static void lcd_set_hpll_g12b(struct lcd_clk_config_s *cConf) LCDERR("hpll lock failed\n"); } -static void lcd_set_pll_ss_tl1(unsigned int ss_level) +static void lcd_set_pll_ss_level_tl1(unsigned int level) { - LCDPR("%s: todo\n", __func__); + unsigned int pll_ctrl2; + unsigned int dep_sel, str_m; + + pll_ctrl2 = lcd_hiu_read(HHI_TCON_PLL_CNTL2); + pll_ctrl2 &= ~((1 << 15) | (0xf << 16) | (0xf << 28)); + + if (level > 0) { + dep_sel = pll_ss_reg_tl1[level][0]; + str_m = pll_ss_reg_tl1[level][1]; + dep_sel = (dep_sel > 10) ? 10 : dep_sel; + str_m = (str_m > 10) ? 10 : str_m; + pll_ctrl2 |= ((1 << 15) | (dep_sel << 28) | (str_m << 16)); + } + lcd_hiu_write(HHI_TCON_PLL_CNTL2, pll_ctrl2); + + LCDPR("set pll spread spectrum: %s\n", lcd_ss_level_table_tl1[level]); +} + +static void lcd_set_pll_ss_advance_tl1(unsigned int freq, unsigned int mode) +{ + unsigned int pll_ctrl2; + + pll_ctrl2 = lcd_hiu_read(HHI_TCON_PLL_CNTL2); + pll_ctrl2 &= ~(0x7 << 24); /* ss_freq */ + pll_ctrl2 |= (freq << 24); + pll_ctrl2 &= ~(0x3 << 22); /* ss_mode */ + pll_ctrl2 |= (mode << 22); + lcd_hiu_write(HHI_TCON_PLL_CNTL2, pll_ctrl2); + + LCDPR("set pll spread spectrum: freq=%d, mode=%d\n", freq, mode); } static void lcd_set_pll_tl1(struct lcd_clk_config_s *cConf) { unsigned int pll_ctrl, pll_ctrl1; + unsigned int tcon_div[5][3] = { + /* div_mux, div2/4_sel, div4_bypass */ + {1, 0, 1}, /* div1 */ + {0, 0, 1}, /* div2 */ + {0, 1, 1}, /* div4 */ + {0, 0, 0}, /* div8 */ + {0, 1, 0}, /* div16 */ + }; + unsigned int tcon_div_sel = cConf->pll_tcon_div_sel; int ret; if (lcd_debug_print_flag == 2) LCDPR("%s\n", __func__); pll_ctrl = ((0x3 << 17) | /* gate ctrl */ - (1 << LCD_PLL_RST_TL1) | + (tcon_div[tcon_div_sel][2] << 16) | (cConf->pll_n << LCD_PLL_N_TL1) | (cConf->pll_m << LCD_PLL_M_TL1) | (cConf->pll_od3_sel << LCD_PLL_OD3_TL1) | (cConf->pll_od2_sel << LCD_PLL_OD2_TL1) | (cConf->pll_od1_sel << LCD_PLL_OD1_TL1)); - pll_ctrl1 = (1 << 28) | (1 << 23) | - ((1 << 20) | (cConf->pll_frac << 0)); + pll_ctrl1 = (1 << 28) | + (tcon_div[tcon_div_sel][0] << 22) | + (tcon_div[tcon_div_sel][1] << 21) | + ((1 << 20) | /* sdm_en */ + (cConf->pll_frac << 0)); lcd_hiu_write(HHI_TCON_PLL_CNTL0, pll_ctrl); + udelay(10); + lcd_hiu_setb(HHI_TCON_PLL_CNTL0, 1, LCD_PLL_RST_TL1, 1); + udelay(10); lcd_hiu_setb(HHI_TCON_PLL_CNTL0, 1, LCD_PLL_EN_TL1, 1); + udelay(10); lcd_hiu_write(HHI_TCON_PLL_CNTL1, pll_ctrl1); - lcd_hiu_write(HHI_TCON_PLL_CNTL2, 0x00001108); - lcd_hiu_write(HHI_TCON_PLL_CNTL3, 0x10058f30); - lcd_hiu_write(HHI_TCON_PLL_CNTL4, 0x010100c0); - lcd_hiu_write(HHI_TCON_PLL_CNTL4, 0x038300c0); + udelay(10); + lcd_hiu_write(HHI_TCON_PLL_CNTL2, 0x0000110c); + udelay(10); + lcd_hiu_write(HHI_TCON_PLL_CNTL3, 0x10051400); + udelay(10); + lcd_hiu_setb(HHI_TCON_PLL_CNTL4, 0x0100c0, 0, 24); + udelay(10); + lcd_hiu_setb(HHI_TCON_PLL_CNTL4, 0x8300c0, 0, 24); + udelay(10); lcd_hiu_setb(HHI_TCON_PLL_CNTL0, 1, 26, 1); + udelay(10); lcd_hiu_setb(HHI_TCON_PLL_CNTL0, 0, LCD_PLL_RST_TL1, 1); - lcd_hiu_write(HHI_TCON_PLL_CNTL2, 0x00003008); - lcd_hiu_write(HHI_TCON_PLL_CNTL4, 0x0b8300c0); + udelay(10); + lcd_hiu_write(HHI_TCON_PLL_CNTL2, 0x0000300c); ret = lcd_pll_wait_lock(HHI_TCON_PLL_CNTL0, LCD_PLL_LOCK_TL1); - if (ret) + if (ret) { LCDERR("hpll lock failed\n"); + } else { + udelay(100); + lcd_hiu_setb(HHI_TCON_PLL_CNTL2, 1, 5, 1); + } - if (cConf->ss_level > 0) - lcd_set_pll_ss_tl1(cConf->ss_level); + if (cConf->ss_level > 0) { + lcd_set_pll_ss_level_tl1(cConf->ss_level); + lcd_set_pll_ss_advance_tl1(cConf->ss_freq, cConf->ss_mode); + } } static void lcd_set_vid_pll_div(struct lcd_clk_config_s *cConf) @@ -554,7 +610,7 @@ static void lcd_set_vid_pll_div(struct lcd_clk_config_s *cConf) lcd_hiu_setb(HHI_VID_PLL_CLK_DIV, shift_sel, 16, 2); lcd_hiu_setb(HHI_VID_PLL_CLK_DIV, 1, 15, 1); - lcd_hiu_setb(HHI_VID_PLL_CLK_DIV, shift_val, 0, 14); + lcd_hiu_setb(HHI_VID_PLL_CLK_DIV, shift_val, 0, 15); lcd_hiu_setb(HHI_VID_PLL_CLK_DIV, 0, 15, 1); } /* Enable the final output clock */ @@ -604,34 +660,30 @@ static void lcd_set_dsi_phy_clk(int sel) static void lcd_set_tcon_clk(struct lcd_config_s *pconf) { -#if 0 - unsigned int val; + unsigned int freq, val; if (lcd_debug_print_flag == 2) LCDPR("%s\n", __func__); switch (pconf->lcd_basic.lcd_type) { - case LCD_LVDS: - lcd_hiu_write(HHI_DIF_TCON_CNTL0, 0x0); - lcd_hiu_write(HHI_DIF_TCON_CNTL0, 0x80000000); - lcd_hiu_write(HHI_DIF_TCON_CNTL1, 0x0); - lcd_hiu_write(HHI_DIF_TCON_CNTL2, 0x0); - break; case LCD_MLVDS: - val = pconf->lcd_control.mlvds_config->pi_clk_sel; - /*val = (~val) & 0x3ff;*/ - lcd_hiu_write(HHI_DIF_TCON_CNTL0, (val << 12)); - lcd_hiu_write(HHI_DIF_TCON_CNTL0, ((1 << 31) | (val << 12))); - val = pconf->lcd_control.mlvds_config->clk_phase & 0xfff; - lcd_hiu_write(HHI_DIF_TCON_CNTL1, val); - lcd_hiu_write(HHI_DIF_TCON_CNTL2, 0x0); + lcd_hiu_setb(HHI_TCON_PLL_CNTL1, (val & 0xf), 24, 4); + lcd_hiu_setb(HHI_TCON_PLL_CNTL4, ((val >> 4) & 0xf), 28, 4); + lcd_hiu_setb(HHI_TCON_PLL_CNTL4, ((val >> 8) & 0xf), 24, 4); - /* tcon_clk 50M */ - /*lcd_hiu_write(HHI_TCON_CLK_CNTL, - * (1 << 7) | (1 << 6) | (7 << 0)); - */ - if (!IS_ERR(lcd_clktree.tcon_clk)) { + /* tcon_clk */ + if (pconf->lcd_timing.lcd_clk >= 100000000) /* 25M */ + freq = 25000000; + else /* 12.5M */ + freq = 12500000; + if (!IS_ERR_OR_NULL(lcd_clktree.tcon_clk)) { + clk_set_rate(lcd_clktree.tcon_clk, freq); + clk_prepare_enable(lcd_clktree.tcon_clk); + } + break; + case LCD_P2P: + if (!IS_ERR_OR_NULL(lcd_clktree.tcon_clk)) { clk_set_rate(lcd_clktree.tcon_clk, 50000000); clk_prepare_enable(lcd_clktree.tcon_clk); } @@ -639,7 +691,6 @@ static void lcd_set_tcon_clk(struct lcd_config_s *pconf) default: break; } -#endif } /* **************************************************** @@ -747,6 +798,12 @@ static unsigned int clk_vid_pll_div_calc(unsigned int clk, else clk_ret = clk * 5 / 2; break; + case CLK_DIV_SEL_4p67: + if (dir == CLK_DIV_I2O) + clk_ret = clk * 3 / 14; + else + clk_ret = clk * 14 / 3; + break; default: clk_ret = clk; LCDERR("clk_div_sel: Invalid parameter\n"); @@ -850,8 +907,7 @@ static int check_pll_txl(struct lcd_clk_config_s *cConf, return done; } -static int check_pll_tl1_mlvds(struct lcd_clk_config_s *cConf, - unsigned int pll_fvco) +static int check_pll_vco(struct lcd_clk_config_s *cConf, unsigned int pll_fvco) { struct lcd_clk_data_s *data = cConf->data; unsigned int m, n; @@ -884,8 +940,7 @@ static int check_pll_tl1_mlvds(struct lcd_clk_config_s *cConf, } #define PLL_FVCO_ERR_MAX 2 /* kHz */ -static int check_pll_od_tl1_mlvds(struct lcd_clk_config_s *cConf, - unsigned int pll_fout) +static int check_pll_od(struct lcd_clk_config_s *cConf, unsigned int pll_fout) { struct lcd_clk_data_s *data = cConf->data; unsigned int od1_sel, od2_sel, od3_sel, od1, od2, od3; @@ -936,7 +991,8 @@ static void lcd_clk_generate_txl(struct lcd_config_s *pconf) { unsigned int pll_fout, pll_fvco, bit_rate; unsigned int clk_div_in, clk_div_out; - unsigned int clk_div_sel, xd, pi_div_sel; + unsigned int clk_div_sel, xd, tcon_div_sel = 0, phy_div = 1; + unsigned int od1, od2, od3; struct lcd_clk_config_s *cConf = get_lcd_clk_config(); int done; @@ -950,6 +1006,8 @@ static void lcd_clk_generate_txl(struct lcd_config_s *pconf) goto generate_clk_done_txl; } + bit_rate = pconf->lcd_timing.bit_rate / 1000; + if (pconf->lcd_timing.clk_auto == 2) cConf->pll_mode = 1; else @@ -1007,13 +1065,29 @@ static void lcd_clk_generate_txl(struct lcd_config_s *pconf) clk_div_sel, pll_fout); } done = check_pll_txl(cConf, pll_fout); - if (done) + if (done == 0) goto generate_clk_done_txl; + done = 0; + if (pconf->lcd_control.lvds_config->dual_port) + phy_div = 2; + else + phy_div = 1; + od1 = od_table[cConf->pll_od1_sel]; + od2 = od_table[cConf->pll_od2_sel]; + od3 = od_table[cConf->pll_od3_sel]; + for (tcon_div_sel = 0; tcon_div_sel < 5; tcon_div_sel++) { + if (tcon_div_table[tcon_div_sel] == + phy_div * od1 * od2 * od3) { + cConf->pll_tcon_div_sel = tcon_div_sel; + done = 1; + break; + } + } break; case LCD_VBYONE: cConf->div_sel_max = CLK_DIV_SEL_MAX; cConf->xd_max = CRT_VID_DIV_MAX; - pll_fout = pconf->lcd_control.vbyone_config->bit_rate / 1000; + pll_fout = bit_rate; clk_div_in = pll_fout; if (clk_div_in > cConf->data->div_in_fmax) goto generate_clk_done_txl; @@ -1040,54 +1114,111 @@ static void lcd_clk_generate_txl(struct lcd_config_s *pconf) cConf->div_sel); } done = check_pll_txl(cConf, pll_fout); + if (done == 0) + goto generate_clk_done_txl; + done = 0; + od1 = od_table[cConf->pll_od1_sel]; + od2 = od_table[cConf->pll_od2_sel]; + od3 = od_table[cConf->pll_od3_sel]; + for (tcon_div_sel = 0; tcon_div_sel < 5; tcon_div_sel++) { + if (tcon_div_table[tcon_div_sel] == od1 * od2 * od3) { + cConf->pll_tcon_div_sel = tcon_div_sel; + done = 1; + break; + } + } break; case LCD_MLVDS: - bit_rate = pconf->lcd_control.mlvds_config->bit_rate / 1000; - for (pi_div_sel = 0; pi_div_sel < 2; pi_div_sel++) { - pll_fvco = bit_rate * pi_div_table[pi_div_sel] * 4; - done = check_pll_tl1_mlvds(cConf, pll_fvco); - if (done) { - clk_div_sel = CLK_DIV_SEL_1; - cConf->xd_max = CRT_VID_DIV_MAX; - for (xd = 1; xd <= cConf->xd_max; xd++) { - clk_div_out = cConf->fout * xd; - if (clk_div_out > - cConf->data->div_out_fmax) - continue; - if (lcd_debug_print_flag == 2) { - LCDPR("fout=%d, xd=%d\n", - cConf->fout, xd); - LCDPR("clk_div_out=%d\n", - clk_div_out); - } + /* must go through div4 for clk phase */ + for (tcon_div_sel = 3; tcon_div_sel < 5; tcon_div_sel++) { + pll_fvco = bit_rate * tcon_div_table[tcon_div_sel]; + done = check_pll_vco(cConf, pll_fvco); + if (done == 0) + continue; + cConf->xd_max = CRT_VID_DIV_MAX; + for (xd = 1; xd <= cConf->xd_max; xd++) { + clk_div_out = cConf->fout * xd; + if (clk_div_out > cConf->data->div_out_fmax) + continue; + if (lcd_debug_print_flag == 2) { + LCDPR( + "fout=%d, xd=%d, clk_div_out=%d\n", + cConf->fout, xd, clk_div_out); + } + for (clk_div_sel = CLK_DIV_SEL_1; + clk_div_sel < CLK_DIV_SEL_MAX; + clk_div_sel++) { clk_div_in = clk_vid_pll_div_calc( - clk_div_out, - clk_div_sel, CLK_DIV_O2I); + clk_div_out, clk_div_sel, + CLK_DIV_O2I); if (clk_div_in > cConf->data->div_in_fmax) continue; cConf->xd = xd; cConf->div_sel = clk_div_sel; - cConf->pll_pi_div_sel = pi_div_sel; + cConf->pll_tcon_div_sel = tcon_div_sel; pll_fout = clk_div_in; if (lcd_debug_print_flag == 2) { LCDPR("clk_div_sel=%s(%d)\n", - lcd_clk_div_sel_table[ - clk_div_sel], + lcd_clk_div_sel_table[clk_div_sel], clk_div_sel); - LCDPR("pll_fout=%d\n", - pll_fout); - LCDPR("pi_clk_sel=%d\n", - pi_div_sel); + LCDPR( + "pll_fout=%d, tcon_div_sel=%d\n", + pll_fout, tcon_div_sel); } - done = check_pll_od_tl1_mlvds( - cConf, pll_fout); + done = check_pll_od(cConf, pll_fout); if (done) goto generate_clk_done_txl; } } } break; + case LCD_P2P: + for (tcon_div_sel = 0; tcon_div_sel < 5; tcon_div_sel++) { + pll_fvco = bit_rate * tcon_div_table[tcon_div_sel]; + done = check_pll_vco(cConf, pll_fvco); + if (done == 0) + continue; + cConf->xd_max = CRT_VID_DIV_MAX; + for (xd = 1; xd <= cConf->xd_max; xd++) { + clk_div_out = cConf->fout * xd; + if (clk_div_out > cConf->data->div_out_fmax) + continue; + if (lcd_debug_print_flag == 2) { + LCDPR( + "fout=%d, xd=%d, clk_div_out=%d\n", + cConf->fout, xd, clk_div_out); + } + for (clk_div_sel = CLK_DIV_SEL_1; + clk_div_sel < CLK_DIV_SEL_MAX; + clk_div_sel++) { + clk_div_in = clk_vid_pll_div_calc( + clk_div_out, clk_div_sel, + CLK_DIV_O2I); + if (clk_div_in > + cConf->data->div_in_fmax) + continue; + cConf->xd = xd; + cConf->div_sel = clk_div_sel; + cConf->pll_tcon_div_sel = tcon_div_sel; + pll_fout = clk_div_in; + if (lcd_debug_print_flag == 2) { + LCDPR("clk_div_sel=%s(%d)\n", + lcd_clk_div_sel_table[clk_div_sel], + clk_div_sel); + LCDPR( + "pll_fout=%d, tcon_div_sel=%d\n", + pll_fout, tcon_div_sel); + } + done = check_pll_od(cConf, pll_fout); + if (done) + goto generate_clk_done_txl; + } + } + } + if (done) + goto generate_clk_done_txl; + break; default: break; } @@ -1288,8 +1419,7 @@ static void lcd_clk_generate_axg(struct lcd_config_s *pconf) if (lcd_debug_print_flag == 2) LCDPR("fout=%d, xd=%d\n", cConf->fout, xd); - pconf->lcd_control.mipi_config->bit_rate = - pll_fout * 1000; + pconf->lcd_timing.bit_rate = pll_fout * 1000; pconf->lcd_control.mipi_config->clk_factor = xd; cConf->xd = xd; done = check_pll_axg(cConf, pll_fout); @@ -1423,8 +1553,7 @@ static void lcd_clk_generate_hpll_g12a(struct lcd_config_s *pconf) if (lcd_debug_print_flag == 2) LCDPR("fout=%d, xd=%d\n", cConf->fout, xd); - pconf->lcd_control.mipi_config->bit_rate = - pll_fout * 1000; + pconf->lcd_timing.bit_rate = pll_fout * 1000; pconf->lcd_control.mipi_config->clk_factor = xd; cConf->xd = xd; cConf->div_sel = clk_div_sel; @@ -1525,20 +1654,20 @@ static void lcd_clk_set_tl1(struct lcd_config_s *pconf) static void lcd_clk_gate_switch_dft(struct aml_lcd_drv_s *lcd_drv, int status) { if (status) { - if (IS_ERR(lcd_clktree.encl_top_gate)) + if (IS_ERR_OR_NULL(lcd_clktree.encl_top_gate)) LCDERR("%s: encl_top_gate\n", __func__); else clk_prepare_enable(lcd_clktree.encl_top_gate); - if (IS_ERR(lcd_clktree.encl_int_gate)) + if (IS_ERR_OR_NULL(lcd_clktree.encl_int_gate)) LCDERR("%s: encl_int_gata\n", __func__); else clk_prepare_enable(lcd_clktree.encl_int_gate); } else { - if (IS_ERR(lcd_clktree.encl_int_gate)) + if (IS_ERR_OR_NULL(lcd_clktree.encl_int_gate)) LCDERR("%s: encl_int_gata\n", __func__); else clk_disable_unprepare(lcd_clktree.encl_int_gate); - if (IS_ERR(lcd_clktree.encl_top_gate)) + if (IS_ERR_OR_NULL(lcd_clktree.encl_top_gate)) LCDERR("%s: encl_top_gata\n", __func__); else clk_disable_unprepare(lcd_clktree.encl_top_gate); @@ -1548,44 +1677,44 @@ static void lcd_clk_gate_switch_dft(struct aml_lcd_drv_s *lcd_drv, int status) static void lcd_clk_gate_switch_axg(struct aml_lcd_drv_s *lcd_drv, int status) { if (status) { - if (IS_ERR(lcd_clktree.dsi_host_gate)) + if (IS_ERR_OR_NULL(lcd_clktree.dsi_host_gate)) LCDERR("%s: dsi_host_gate\n", __func__); else clk_prepare_enable(lcd_clktree.dsi_host_gate); - if (IS_ERR(lcd_clktree.dsi_phy_gate)) + if (IS_ERR_OR_NULL(lcd_clktree.dsi_phy_gate)) LCDERR("%s: dsi_phy_gate\n", __func__); else clk_prepare_enable(lcd_clktree.dsi_phy_gate); - if (IS_ERR(lcd_clktree.dsi_meas)) + if (IS_ERR_OR_NULL(lcd_clktree.dsi_meas)) LCDERR("%s: dsi_meas\n", __func__); else clk_prepare_enable(lcd_clktree.dsi_meas); - if (IS_ERR(lcd_clktree.mipi_enable_gate)) + if (IS_ERR_OR_NULL(lcd_clktree.mipi_enable_gate)) LCDERR("%s: mipi_enable_gate\n", __func__); else clk_prepare_enable(lcd_clktree.mipi_enable_gate); - if (IS_ERR(lcd_clktree.mipi_bandgap_gate)) + if (IS_ERR_OR_NULL(lcd_clktree.mipi_bandgap_gate)) LCDERR("%s: mipi_bandgap_gate\n", __func__); else clk_prepare_enable(lcd_clktree.mipi_bandgap_gate); } else { - if (IS_ERR(lcd_clktree.dsi_host_gate)) + if (IS_ERR_OR_NULL(lcd_clktree.dsi_host_gate)) LCDERR("%s: dsi_host_gate\n", __func__); else clk_disable_unprepare(lcd_clktree.dsi_host_gate); - if (IS_ERR(lcd_clktree.dsi_phy_gate)) + if (IS_ERR_OR_NULL(lcd_clktree.dsi_phy_gate)) LCDERR("%s: dsi_phy_gate\n", __func__); else clk_disable_unprepare(lcd_clktree.dsi_phy_gate); - if (IS_ERR(lcd_clktree.dsi_meas)) + if (IS_ERR_OR_NULL(lcd_clktree.dsi_meas)) LCDERR("%s: dsi_meas\n", __func__); else clk_disable_unprepare(lcd_clktree.dsi_meas); - if (IS_ERR(lcd_clktree.mipi_enable_gate)) + if (IS_ERR_OR_NULL(lcd_clktree.mipi_enable_gate)) LCDERR("%s: mipi_enable_gate\n", __func__); else clk_disable_unprepare(lcd_clktree.mipi_enable_gate); - if (IS_ERR(lcd_clktree.mipi_bandgap_gate)) + if (IS_ERR_OR_NULL(lcd_clktree.mipi_bandgap_gate)) LCDERR("%s: mipi_bandgap_gate\n", __func__); else clk_disable_unprepare(lcd_clktree.mipi_bandgap_gate); @@ -1596,56 +1725,56 @@ static void lcd_clk_gate_switch_g12a(struct aml_lcd_drv_s *lcd_drv, int status) { if (status) { if (clk_conf.data->vclk_sel) { - if (IS_ERR(lcd_clktree.gp0_pll)) + if (IS_ERR_OR_NULL(lcd_clktree.gp0_pll)) LCDERR("%s: gp0_pll\n", __func__); else clk_prepare_enable(lcd_clktree.gp0_pll); } - if (IS_ERR(lcd_clktree.dsi_host_gate)) + if (IS_ERR_OR_NULL(lcd_clktree.dsi_host_gate)) LCDERR("%s: dsi_host_gate\n", __func__); else clk_prepare_enable(lcd_clktree.dsi_host_gate); - if (IS_ERR(lcd_clktree.dsi_phy_gate)) + if (IS_ERR_OR_NULL(lcd_clktree.dsi_phy_gate)) LCDERR("%s: dsi_phy_gate\n", __func__); else clk_prepare_enable(lcd_clktree.dsi_phy_gate); - if (IS_ERR(lcd_clktree.dsi_meas)) + if (IS_ERR_OR_NULL(lcd_clktree.dsi_meas)) LCDERR("%s: dsi_meas\n", __func__); else clk_prepare_enable(lcd_clktree.dsi_meas); - if (IS_ERR(lcd_clktree.encl_top_gate)) + if (IS_ERR_OR_NULL(lcd_clktree.encl_top_gate)) LCDERR("%s: encl_top_gate\n", __func__); else clk_prepare_enable(lcd_clktree.encl_top_gate); - if (IS_ERR(lcd_clktree.encl_int_gate)) + if (IS_ERR_OR_NULL(lcd_clktree.encl_int_gate)) LCDERR("%s: encl_int_gata\n", __func__); else clk_prepare_enable(lcd_clktree.encl_int_gate); } else { - if (IS_ERR(lcd_clktree.dsi_host_gate)) + if (IS_ERR_OR_NULL(lcd_clktree.dsi_host_gate)) LCDERR("%s: dsi_host_gate\n", __func__); else clk_disable_unprepare(lcd_clktree.dsi_host_gate); - if (IS_ERR(lcd_clktree.dsi_phy_gate)) + if (IS_ERR_OR_NULL(lcd_clktree.dsi_phy_gate)) LCDERR("%s: dsi_phy_gate\n", __func__); else clk_disable_unprepare(lcd_clktree.dsi_phy_gate); - if (IS_ERR(lcd_clktree.dsi_meas)) + if (IS_ERR_OR_NULL(lcd_clktree.dsi_meas)) LCDERR("%s: dsi_meas\n", __func__); else clk_disable_unprepare(lcd_clktree.dsi_meas); - if (IS_ERR(lcd_clktree.encl_int_gate)) + if (IS_ERR_OR_NULL(lcd_clktree.encl_int_gate)) LCDERR("%s: encl_int_gate\n", __func__); else clk_disable_unprepare(lcd_clktree.encl_int_gate); - if (IS_ERR(lcd_clktree.encl_top_gate)) + if (IS_ERR_OR_NULL(lcd_clktree.encl_top_gate)) LCDERR("%s: encl_top_gate\n", __func__); else clk_disable_unprepare(lcd_clktree.encl_top_gate); if (clk_conf.data->vclk_sel) { - if (IS_ERR(lcd_clktree.gp0_pll)) + if (IS_ERR_OR_NULL(lcd_clktree.gp0_pll)) LCDERR("%s: gp0_pll\n", __func__); else clk_disable_unprepare(lcd_clktree.gp0_pll); @@ -1653,28 +1782,22 @@ static void lcd_clk_gate_switch_g12a(struct aml_lcd_drv_s *lcd_drv, int status) } } -static void lcd_clk_gate_switch_tl1(struct aml_lcd_drv_s *lcd_drv, int status) +static void lcd_clk_gate_optional_switch_tl1(struct aml_lcd_drv_s *lcd_drv, + int status) { if (status) { - if (IS_ERR(lcd_clktree.encl_top_gate)) - LCDERR("%s: encl_top_gate\n", __func__); - else - clk_prepare_enable(lcd_clktree.encl_top_gate); - if (IS_ERR(lcd_clktree.encl_int_gate)) - LCDERR("%s: encl_int_gata\n", __func__); - else - clk_prepare_enable(lcd_clktree.encl_int_gate); switch (lcd_drv->lcd_config->lcd_basic.lcd_type) { case LCD_MLVDS: case LCD_P2P: - if (IS_ERR(lcd_clktree.tcon_gate)) + if (IS_ERR_OR_NULL(lcd_clktree.tcon_gate)) LCDERR("%s: tcon_gate\n", __func__); else clk_prepare_enable(lcd_clktree.tcon_gate); - if (IS_ERR(lcd_clktree.tcon_clk)) + if (IS_ERR_OR_NULL(lcd_clktree.tcon_clk)) LCDERR("%s: tcon_clk\n", __func__); else clk_prepare_enable(lcd_clktree.tcon_clk); + lcd_clktree.clk_gate_optional_state = 1; break; default: break; @@ -1683,26 +1806,19 @@ static void lcd_clk_gate_switch_tl1(struct aml_lcd_drv_s *lcd_drv, int status) switch (lcd_drv->lcd_config->lcd_basic.lcd_type) { case LCD_MLVDS: case LCD_P2P: - if (IS_ERR(lcd_clktree.tcon_clk)) + if (IS_ERR_OR_NULL(lcd_clktree.tcon_clk)) LCDERR("%s: tcon_clk\n", __func__); else clk_disable_unprepare(lcd_clktree.tcon_clk); - if (IS_ERR(lcd_clktree.tcon_gate)) + if (IS_ERR_OR_NULL(lcd_clktree.tcon_gate)) LCDERR("%s: tcon_gate\n", __func__); else clk_disable_unprepare(lcd_clktree.tcon_gate); + lcd_clktree.clk_gate_optional_state = 0; break; default: break; } - if (IS_ERR(lcd_clktree.encl_int_gate)) - LCDERR("%s: encl_int_gate\n", __func__); - else - clk_disable_unprepare(lcd_clktree.encl_int_gate); - if (IS_ERR(lcd_clktree.encl_top_gate)) - LCDERR("%s: encl_top_gate\n", __func__); - else - clk_disable_unprepare(lcd_clktree.encl_top_gate); } } @@ -1713,11 +1829,11 @@ static void lcd_clktree_probe_dft(void) lcd_clktree.clk_gate_state = 0; lcd_clktree.encl_top_gate = devm_clk_get(lcd_drv->dev, "encl_top_gate"); - if (IS_ERR(lcd_clktree.encl_top_gate)) + if (IS_ERR_OR_NULL(lcd_clktree.encl_top_gate)) LCDERR("%s: get encl_top_gate error\n", __func__); lcd_clktree.encl_int_gate = devm_clk_get(lcd_drv->dev, "encl_int_gate"); - if (IS_ERR(lcd_clktree.encl_int_gate)) + if (IS_ERR_OR_NULL(lcd_clktree.encl_int_gate)) LCDERR("%s: get encl_int_gate error\n", __func__); LCDPR("lcd_clktree_probe\n"); @@ -1730,25 +1846,25 @@ static void lcd_clktree_probe_axg(void) lcd_clktree.clk_gate_state = 0; lcd_clktree.dsi_host_gate = devm_clk_get(lcd_drv->dev, "dsi_host_gate"); - if (IS_ERR(lcd_clktree.dsi_host_gate)) + if (IS_ERR_OR_NULL(lcd_clktree.dsi_host_gate)) LCDERR("%s: clk dsi_host_gate\n", __func__); lcd_clktree.dsi_phy_gate = devm_clk_get(lcd_drv->dev, "dsi_phy_gate"); - if (IS_ERR(lcd_clktree.dsi_phy_gate)) + if (IS_ERR_OR_NULL(lcd_clktree.dsi_phy_gate)) LCDERR("%s: clk dsi_phy_gate\n", __func__); lcd_clktree.dsi_meas = devm_clk_get(lcd_drv->dev, "dsi_meas"); - if (IS_ERR(lcd_clktree.dsi_meas)) + if (IS_ERR_OR_NULL(lcd_clktree.dsi_meas)) LCDERR("%s: clk dsi_meas\n", __func__); lcd_clktree.mipi_enable_gate = devm_clk_get(lcd_drv->dev, "mipi_enable_gate"); - if (IS_ERR(lcd_clktree.mipi_enable_gate)) + if (IS_ERR_OR_NULL(lcd_clktree.mipi_enable_gate)) LCDERR("%s: clk mipi_enable_gate\n", __func__); lcd_clktree.mipi_bandgap_gate = devm_clk_get(lcd_drv->dev, "mipi_bandgap_gate"); - if (IS_ERR(lcd_clktree.mipi_bandgap_gate)) + if (IS_ERR_OR_NULL(lcd_clktree.mipi_bandgap_gate)) LCDERR("%s: clk mipi_bandgap_gate\n", __func__); LCDPR("lcd_clktree_probe\n"); @@ -1761,27 +1877,27 @@ static void lcd_clktree_probe_g12a(void) lcd_clktree.clk_gate_state = 0; lcd_clktree.dsi_host_gate = devm_clk_get(lcd_drv->dev, "dsi_host_gate"); - if (IS_ERR(lcd_clktree.dsi_host_gate)) + if (IS_ERR_OR_NULL(lcd_clktree.dsi_host_gate)) LCDERR("%s: clk dsi_host_gate\n", __func__); lcd_clktree.dsi_phy_gate = devm_clk_get(lcd_drv->dev, "dsi_phy_gate"); - if (IS_ERR(lcd_clktree.dsi_phy_gate)) + if (IS_ERR_OR_NULL(lcd_clktree.dsi_phy_gate)) LCDERR("%s: clk dsi_phy_gate\n", __func__); lcd_clktree.dsi_meas = devm_clk_get(lcd_drv->dev, "dsi_meas"); - if (IS_ERR(lcd_clktree.dsi_meas)) + if (IS_ERR_OR_NULL(lcd_clktree.dsi_meas)) LCDERR("%s: clk dsi_meas\n", __func__); lcd_clktree.encl_top_gate = devm_clk_get(lcd_drv->dev, "encl_top_gate"); - if (IS_ERR(lcd_clktree.encl_top_gate)) + if (IS_ERR_OR_NULL(lcd_clktree.encl_top_gate)) LCDERR("%s: clk encl_top_gate\n", __func__); lcd_clktree.encl_int_gate = devm_clk_get(lcd_drv->dev, "encl_int_gate"); - if (IS_ERR(lcd_clktree.encl_int_gate)) + if (IS_ERR_OR_NULL(lcd_clktree.encl_int_gate)) LCDERR("%s: clk encl_int_gate\n", __func__); lcd_clktree.gp0_pll = devm_clk_get(lcd_drv->dev, "gp0_pll"); - if (IS_ERR(lcd_clktree.gp0_pll)) + if (IS_ERR_OR_NULL(lcd_clktree.gp0_pll)) LCDERR("%s: clk gp0_pll\n", __func__); LCDPR("lcd_clktree_probe\n"); @@ -1795,34 +1911,27 @@ static void lcd_clktree_probe_tl1(void) lcd_clktree.clk_gate_state = 0; lcd_clktree.encl_top_gate = devm_clk_get(lcd_drv->dev, "encl_top_gate"); - if (IS_ERR(lcd_clktree.encl_top_gate)) + if (IS_ERR_OR_NULL(lcd_clktree.encl_top_gate)) LCDERR("%s: get encl_top_gate error\n", __func__); lcd_clktree.encl_int_gate = devm_clk_get(lcd_drv->dev, "encl_int_gate"); - if (IS_ERR(lcd_clktree.encl_int_gate)) + if (IS_ERR_OR_NULL(lcd_clktree.encl_int_gate)) LCDERR("%s: get encl_int_gate error\n", __func__); - switch (lcd_drv->lcd_config->lcd_basic.lcd_type) { - case LCD_MLVDS: - case LCD_P2P: - lcd_clktree.tcon_gate = devm_clk_get(lcd_drv->dev, "tcon_gate"); - if (IS_ERR(lcd_clktree.tcon_gate)) - LCDERR("%s: get tcon_gate error\n", __func__); + lcd_clktree.tcon_gate = devm_clk_get(lcd_drv->dev, "tcon_gate"); + if (IS_ERR_OR_NULL(lcd_clktree.tcon_gate)) + LCDERR("%s: get tcon_gate error\n", __func__); - temp_clk = devm_clk_get(lcd_drv->dev, "fclk_div5"); - if (IS_ERR(temp_clk)) { - LCDERR("%s: clk fclk_div5\n", __func__); - return; - } - lcd_clktree.tcon_clk = devm_clk_get(lcd_drv->dev, "clk_tcon"); - if (IS_ERR(lcd_clktree.tcon_clk)) - LCDERR("%s: clk clk_tcon\n", __func__); - else - clk_set_parent(lcd_clktree.tcon_clk, temp_clk); - break; - default: - break; + temp_clk = devm_clk_get(lcd_drv->dev, "fclk_div5"); + if (IS_ERR_OR_NULL(temp_clk)) { + LCDERR("%s: clk fclk_div5\n", __func__); + return; } + lcd_clktree.tcon_clk = devm_clk_get(lcd_drv->dev, "clk_tcon"); + if (IS_ERR_OR_NULL(lcd_clktree.tcon_clk)) + LCDERR("%s: clk clk_tcon\n", __func__); + else + clk_set_parent(lcd_clktree.tcon_clk, temp_clk); LCDPR("lcd_clktree_probe\n"); } @@ -1834,9 +1943,9 @@ static void lcd_clktree_remove_dft(void) if (lcd_debug_print_flag) LCDPR("lcd_clktree_remove\n"); - if (!IS_ERR(lcd_clktree.encl_top_gate)) + if (!IS_ERR_OR_NULL(lcd_clktree.encl_top_gate)) devm_clk_put(lcd_drv->dev, lcd_clktree.encl_top_gate); - if (!IS_ERR(lcd_clktree.encl_int_gate)) + if (!IS_ERR_OR_NULL(lcd_clktree.encl_int_gate)) devm_clk_put(lcd_drv->dev, lcd_clktree.encl_int_gate); } @@ -1847,17 +1956,17 @@ static void lcd_clktree_remove_axg(void) if (lcd_debug_print_flag) LCDPR("lcd_clktree_remove\n"); - if (!IS_ERR(lcd_clktree.mipi_bandgap_gate)) + if (!IS_ERR_OR_NULL(lcd_clktree.mipi_bandgap_gate)) devm_clk_put(lcd_drv->dev, lcd_clktree.mipi_bandgap_gate); - if (!IS_ERR(lcd_clktree.mipi_enable_gate)) + if (!IS_ERR_OR_NULL(lcd_clktree.mipi_enable_gate)) devm_clk_put(lcd_drv->dev, lcd_clktree.mipi_enable_gate); - if (!IS_ERR(lcd_clktree.dsi_meas)) + if (!IS_ERR_OR_NULL(lcd_clktree.dsi_meas)) devm_clk_put(lcd_drv->dev, lcd_clktree.dsi_meas); - if (!IS_ERR(lcd_clktree.dsi_phy_gate)) + if (!IS_ERR_OR_NULL(lcd_clktree.dsi_phy_gate)) devm_clk_put(lcd_drv->dev, lcd_clktree.dsi_phy_gate); - if (!IS_ERR(lcd_clktree.dsi_host_gate)) + if (!IS_ERR_OR_NULL(lcd_clktree.dsi_host_gate)) devm_clk_put(lcd_drv->dev, lcd_clktree.dsi_host_gate); - if (!IS_ERR(lcd_clktree.gp0_pll)) + if (!IS_ERR_OR_NULL(lcd_clktree.gp0_pll)) devm_clk_put(lcd_drv->dev, lcd_clktree.gp0_pll); } @@ -1868,15 +1977,15 @@ static void lcd_clktree_remove_g12a(void) if (lcd_debug_print_flag) LCDPR("lcd_clktree_remove\n"); - if (!IS_ERR(lcd_clktree.dsi_host_gate)) + if (!IS_ERR_OR_NULL(lcd_clktree.dsi_host_gate)) devm_clk_put(lcd_drv->dev, lcd_clktree.dsi_host_gate); - if (!IS_ERR(lcd_clktree.dsi_phy_gate)) + if (!IS_ERR_OR_NULL(lcd_clktree.dsi_phy_gate)) devm_clk_put(lcd_drv->dev, lcd_clktree.dsi_phy_gate); - if (!IS_ERR(lcd_clktree.dsi_meas)) + if (!IS_ERR_OR_NULL(lcd_clktree.dsi_meas)) devm_clk_put(lcd_drv->dev, lcd_clktree.dsi_meas); - if (!IS_ERR(lcd_clktree.encl_top_gate)) + if (!IS_ERR_OR_NULL(lcd_clktree.encl_top_gate)) devm_clk_put(lcd_drv->dev, lcd_clktree.encl_top_gate); - if (!IS_ERR(lcd_clktree.encl_int_gate)) + if (!IS_ERR_OR_NULL(lcd_clktree.encl_int_gate)) devm_clk_put(lcd_drv->dev, lcd_clktree.encl_int_gate); } @@ -1887,22 +1996,14 @@ static void lcd_clktree_remove_tl1(void) if (lcd_debug_print_flag) LCDPR("lcd_clktree_remove\n"); - if (!IS_ERR(lcd_clktree.encl_top_gate)) + if (!IS_ERR_OR_NULL(lcd_clktree.encl_top_gate)) devm_clk_put(lcd_drv->dev, lcd_clktree.encl_top_gate); - if (!IS_ERR(lcd_clktree.encl_int_gate)) + if (!IS_ERR_OR_NULL(lcd_clktree.encl_int_gate)) devm_clk_put(lcd_drv->dev, lcd_clktree.encl_int_gate); - - switch (lcd_drv->lcd_config->lcd_basic.lcd_type) { - case LCD_MLVDS: - case LCD_P2P: - if (!IS_ERR(lcd_clktree.tcon_clk)) - devm_clk_put(lcd_drv->dev, lcd_clktree.tcon_clk); - if (IS_ERR(lcd_clktree.tcon_gate)) - devm_clk_put(lcd_drv->dev, lcd_clktree.tcon_gate); - break; - default: - break; - } + if (!IS_ERR_OR_NULL(lcd_clktree.tcon_clk)) + devm_clk_put(lcd_drv->dev, lcd_clktree.tcon_clk); + if (IS_ERR_OR_NULL(lcd_clktree.tcon_gate)) + devm_clk_put(lcd_drv->dev, lcd_clktree.tcon_gate); } static void lcd_clk_config_init_print_dft(void) @@ -1926,7 +2027,9 @@ static void lcd_clk_config_init_print_dft(void) "div_in_fmax: %d\n" "div_out_fmax: %d\n" "xd_out_fmax: %d\n" - "ss_level_max: %d\n\n", + "ss_level_max: %d\n" + "ss_freq_max: %d\n" + "ss_mode_max: %d\n\n", data->pll_m_max, data->pll_m_min, data->pll_n_max, data->pll_n_min, data->pll_od_fb, data->pll_frac_range, @@ -1935,7 +2038,8 @@ static void lcd_clk_config_init_print_dft(void) data->pll_vco_fmax, data->pll_vco_fmin, data->pll_out_fmax, data->pll_out_fmin, data->div_in_fmax, data->div_out_fmax, - data->xd_out_fmax, data->ss_level_max); + data->xd_out_fmax, data->ss_level_max, + data->ss_freq_max, data->ss_mode_max); } static void lcd_clk_config_init_print_axg(void) @@ -1957,8 +2061,7 @@ static void lcd_clk_config_init_print_axg(void) "pll_vco_fmin: %d\n" "pll_out_fmax: %d\n" "pll_out_fmin: %d\n" - "xd_out_fmax: %d\n" - "ss_level_max: %d\n\n", + "xd_out_fmax: %d\n\n", data->vclk_sel, data->pll_m_max, data->pll_m_min, data->pll_n_max, data->pll_n_min, @@ -1967,7 +2070,7 @@ static void lcd_clk_config_init_print_axg(void) data->pll_ref_fmax, data->pll_ref_fmin, data->pll_vco_fmax, data->pll_vco_fmin, data->pll_out_fmax, data->pll_out_fmin, - data->xd_out_fmax, data->ss_level_max); + data->xd_out_fmax); } static int lcd_clk_config_print_dft(char *buf, int offset) @@ -1977,28 +2080,31 @@ static int lcd_clk_config_print_dft(char *buf, int offset) n = lcd_debug_info_len(len + offset); len += snprintf((buf+len), n, "lcd clk config:\n" - "pll_mode: %d\n" - "pll_m: %d\n" - "pll_n: %d\n" - "pll_frac: 0x%03x\n" - "pll_fvco: %dkHz\n" - "pll_od1: %d\n" - "pll_od2: %d\n" - "pll_od3: %d\n" - "pll_pi_div_sel: %d\n" - "pll_out: %dkHz\n" - "div_sel: %s(index %d)\n" - "xd: %d\n" - "fout: %dkHz\n" - "ss_level: %d\n\n", + "pll_mode: %d\n" + "pll_m: %d\n" + "pll_n: %d\n" + "pll_frac: 0x%03x\n" + "pll_fvco: %dkHz\n" + "pll_od1: %d\n" + "pll_od2: %d\n" + "pll_od3: %d\n" + "pll_tcon_div_sel: %d\n" + "pll_out: %dkHz\n" + "div_sel: %s(index %d)\n" + "xd: %d\n" + "fout: %dkHz\n" + "ss_level: %d\n" + "ss_freq: %d\n" + "ss_mode: %d\n\n", clk_conf.pll_mode, clk_conf.pll_m, clk_conf.pll_n, clk_conf.pll_frac, clk_conf.pll_fvco, clk_conf.pll_od1_sel, clk_conf.pll_od2_sel, - clk_conf.pll_od3_sel, clk_conf.pll_pi_div_sel, + clk_conf.pll_od3_sel, clk_conf.pll_tcon_div_sel, clk_conf.pll_fout, lcd_clk_div_sel_table[clk_conf.div_sel], clk_conf.div_sel, clk_conf.xd, - clk_conf.fout, clk_conf.ss_level); + clk_conf.fout, clk_conf.ss_level, + clk_conf.ss_freq, clk_conf.ss_mode); return len; } @@ -2017,12 +2123,11 @@ static int lcd_clk_config_print_axg(char *buf, int offset) "pll_od: %d\n" "pll_out: %dkHz\n" "xd: %d\n" - "fout: %dkHz\n" - "ss_level: %d\n\n", + "fout: %dkHz\n\n", clk_conf.pll_m, clk_conf.pll_n, clk_conf.pll_frac, clk_conf.pll_fvco, clk_conf.pll_od1_sel, clk_conf.pll_fout, - clk_conf.xd, clk_conf.fout, clk_conf.ss_level); + clk_conf.xd, clk_conf.fout); return len; } @@ -2043,13 +2148,12 @@ static int lcd_clk_config_print_g12a(char *buf, int offset) "pll_od: %d\n" "pll_out: %dkHz\n" "xd: %d\n" - "fout: %dkHz\n" - "ss_level: %d\n\n", + "fout: %dkHz\n\n", clk_conf.data->vclk_sel, clk_conf.pll_m, clk_conf.pll_n, clk_conf.pll_frac, clk_conf.pll_fvco, clk_conf.pll_od1_sel, clk_conf.pll_fout, - clk_conf.xd, clk_conf.fout, clk_conf.ss_level); + clk_conf.xd, clk_conf.fout); } else { len += snprintf((buf+len), n, "lcd clk config:\n" @@ -2064,8 +2168,7 @@ static int lcd_clk_config_print_g12a(char *buf, int offset) "pll_out: %dkHz\n" "div_sel: %s(index %d)\n" "xd: %d\n" - "fout: %dkHz\n" - "ss_level: %d\n\n", + "fout: %dkHz\n\n", clk_conf.data->vclk_sel, clk_conf.pll_m, clk_conf.pll_n, clk_conf.pll_frac, clk_conf.pll_fvco, @@ -2073,7 +2176,7 @@ static int lcd_clk_config_print_g12a(char *buf, int offset) clk_conf.pll_od3_sel, clk_conf.pll_fout, lcd_clk_div_sel_table[clk_conf.div_sel], clk_conf.div_sel, clk_conf.xd, - clk_conf.fout, clk_conf.ss_level); + clk_conf.fout); } return len; @@ -2094,43 +2197,130 @@ void lcd_clk_generate_parameter(struct lcd_config_s *pconf) clk_conf.data->clk_generate_parameter(pconf); } -static char lcd_ss_invalid_str[10] = {'i', 'n', 'v', 'a', 'l', 'i', 'd', '\0',}; -char *lcd_get_spread_spectrum(void) +int lcd_get_ss(char *buf) { - char *ss_str = lcd_ss_invalid_str; - unsigned int level; + unsigned int temp; + int len = 0; - level = clk_conf.ss_level; - if (clk_conf.data) { - level = (level >= clk_conf.data->ss_level_max) ? 0 : level; - if (clk_conf.data->pll_ss_table) - ss_str = clk_conf.data->pll_ss_table[level]; + if (clk_conf.data == NULL) { + len += sprintf(buf+len, "lcd clk config data is null\n"); + return len; + } + if (clk_conf.data->ss_level_max == 0) { + len += sprintf(buf+len, "lcd spread spectrum is invalid\n"); + return len; } - return ss_str; + temp = (clk_conf.ss_level >= clk_conf.data->ss_level_max) ? + 0 : clk_conf.ss_level; + if (clk_conf.data->ss_level_table) { + len += sprintf(buf+len, "ss_level: %s\n", + clk_conf.data->ss_level_table[temp]); + } + temp = (clk_conf.ss_freq >= clk_conf.data->ss_freq_max) ? + 0 : clk_conf.ss_freq; + if (clk_conf.data->ss_freq_table) { + len += sprintf(buf+len, "ss_freq: %s\n", + clk_conf.data->ss_freq_table[temp]); + } + temp = (clk_conf.ss_mode >= clk_conf.data->ss_mode_max) ? + 0 : clk_conf.ss_mode; + if (clk_conf.data->ss_mode_table) { + len += sprintf(buf+len, "ss_mode: %s\n", + clk_conf.data->ss_mode_table[temp]); + } + + return len; } -void lcd_set_spread_spectrum(unsigned int ss_level) +int lcd_set_ss(unsigned int level, unsigned int freq, unsigned int mode) { unsigned long flags = 0; + int ret = -1; spin_lock_irqsave(&lcd_clk_lock, flags); if (clk_conf.data == NULL) { LCDERR("%s: clk config data is null\n", __func__); - goto lcd_set_spread_spectrum_end; + goto lcd_set_ss_end; + } + if (level < 0xff) { + if (level >= clk_conf.data->ss_level_max) { + LCDERR("%s: ss_level %d is out of support (max %d)\n", + __func__, level, + (clk_conf.data->ss_level_max - 1)); + goto lcd_set_ss_end; + } + } + if (freq < 0xff) { + if (freq >= clk_conf.data->ss_freq_max) { + LCDERR("%s: ss_freq %d is out of support (max %d)\n", + __func__, freq, + (clk_conf.data->ss_freq_max - 1)); + goto lcd_set_ss_end; + } + } + if (mode < 0xff) { + if (mode >= clk_conf.data->ss_mode_max) { + LCDERR("%s: ss_mode %d is out of support (max %d)\n", + __func__, mode, + (clk_conf.data->ss_mode_max - 1)); + goto lcd_set_ss_end; + } } - clk_conf.ss_level = (ss_level >= clk_conf.data->ss_level_max) ? - 0 : ss_level; - if (clk_conf.data->set_spread_spectrum) - clk_conf.data->set_spread_spectrum(clk_conf.ss_level); + if (clk_conf.data->set_ss_level) { + if (level < 0xff) { + clk_conf.ss_level = level; + clk_conf.data->set_ss_level(level); + } + } -lcd_set_spread_spectrum_end: + ret = 0; + if (clk_conf.data->set_ss_advance) { + if ((freq == 0xff) && (mode == 0xff)) + goto lcd_set_ss_end; + if (freq < 0xff) + clk_conf.ss_freq = freq; + if (mode < 0xff) + clk_conf.ss_mode = mode; + clk_conf.data->set_ss_advance(clk_conf.ss_freq, + clk_conf.ss_mode); + } + +lcd_set_ss_end: spin_unlock_irqrestore(&lcd_clk_lock, flags); if (lcd_debug_print_flag) LCDPR("%s\n", __func__); + return ret; +} + +/* design for vlock, don't save ss_level to clk_config */ +int lcd_ss_enable(unsigned int flag) +{ + unsigned int level; + unsigned long flags = 0; + int ret = -1; + + spin_lock_irqsave(&lcd_clk_lock, flags); + + if (clk_conf.data == NULL) { + LCDERR("%s: clk config data is null\n", __func__); + goto lcd_ss_enable_end; + } + + if (clk_conf.data->set_ss_level) { + level = flag ? clk_conf.ss_level : 0; + clk_conf.data->set_ss_level(level); + } + +lcd_ss_enable_end: + spin_unlock_irqrestore(&lcd_clk_lock, flags); + + if (lcd_debug_print_flag) + LCDPR("%s\n", __func__); + return ret; } int lcd_encl_clk_msr(void) @@ -2178,6 +2368,68 @@ lcd_pll_reset_end: LCDPR("%s\n", __func__); } +void lcd_vlock_m_update(unsigned int vlock_m) +{ + struct lcd_clk_ctrl_s *table; + int i = 0; + unsigned long flags = 0; + + if (clk_conf.data == NULL) { + LCDERR("%s: clk config data is null\n", __func__); + return; + } + + if (clk_conf.data->pll_ctrl_table == NULL) + return; + + spin_lock_irqsave(&lcd_clk_lock, flags); + vlock_m &= 0xff; + if (lcd_debug_print_flag == 2) + LCDPR("%s,vlcok_m: 0x%x,", __func__, vlock_m); + + table = clk_conf.data->pll_ctrl_table; + while (i < LCD_CLK_CTRL_CNT_MAX) { + if (table[i].flag == LCD_CLK_CTRL_M) { + lcd_hiu_setb(table[i].reg, vlock_m, + table[i].bit, table[i].len); + break; + } + i++; + } + spin_unlock_irqrestore(&lcd_clk_lock, flags); +} + +void lcd_vlock_farc_update(unsigned int vlock_farc) +{ + struct lcd_clk_ctrl_s *table; + int i = 0; + unsigned long flags = 0; + + if (clk_conf.data == NULL) { + LCDERR("%s: clk config data is null\n", __func__); + return; + } + + if (clk_conf.data->pll_ctrl_table == NULL) + return; + + spin_lock_irqsave(&lcd_clk_lock, flags); + vlock_farc &= 0x1ffff; + if (lcd_debug_print_flag == 2) + LCDPR("%s,vlock_farc: 0x%x\n", __func__, vlock_farc); + + table = clk_conf.data->pll_ctrl_table; + while (i < LCD_CLK_CTRL_CNT_MAX) { + if (table[i].flag == LCD_CLK_CTRL_FRAC) { + lcd_hiu_setb(table[i].reg, vlock_farc, + table[i].bit, table[i].len); + break; + } + i++; + } + spin_unlock_irqrestore(&lcd_clk_lock, flags); +} + /* for frame rate change */ void lcd_clk_update(struct lcd_config_s *pconf) { @@ -2257,6 +2509,9 @@ void lcd_clk_disable(void) if (table[i].flag == LCD_CLK_CTRL_EN) { lcd_hiu_setb(table[i].reg, 0, table[i].bit, table[i].len); + } else if (table[i].flag == LCD_CLK_CTRL_RST) { + lcd_hiu_setb(table[i].reg, 1, + table[i].bit, table[i].len); } i++; } @@ -2265,37 +2520,63 @@ void lcd_clk_disable(void) LCDPR("%s\n", __func__); } +static void lcd_clk_gate_optional_switch(int status) +{ + struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); + + if (clk_conf.data == NULL) { + LCDERR("%s: clk config data is null\n", __func__); + return; + } + if (clk_conf.data->clk_gate_optional_switch == NULL) + return; + + if (status) { + if (lcd_clktree.clk_gate_optional_state) + LCDPR("clk_gate_optional is already on\n"); + else + clk_conf.data->clk_gate_optional_switch(lcd_drv, 1); + } else { + if (lcd_clktree.clk_gate_optional_state == 0) + LCDPR("clk_gate_optional is already off\n"); + else + clk_conf.data->clk_gate_optional_switch(lcd_drv, 0); + } +} + void lcd_clk_gate_switch(int status) { struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); + if (clk_conf.data == NULL) { + LCDERR("%s: clk config data is null\n", __func__); + return; + } + if (status) { if (lcd_clktree.clk_gate_state) { - LCDPR("clk gate is already on\n"); - return; - } + LCDPR("clk_gate is already on\n"); + } else { #ifdef CONFIG_AMLOGIC_VPU - switch_vpu_clk_gate_vmod(VPU_VENCL, VPU_CLK_GATE_ON); + switch_vpu_clk_gate_vmod(VPU_VENCL, VPU_CLK_GATE_ON); #endif - if (clk_conf.data) { if (clk_conf.data->clk_gate_switch) clk_conf.data->clk_gate_switch(lcd_drv, 1); + lcd_clktree.clk_gate_state = 1; } - lcd_clktree.clk_gate_state = 1; + lcd_clk_gate_optional_switch(1); } else { + lcd_clk_gate_optional_switch(0); if (lcd_clktree.clk_gate_state == 0) { - LCDPR("clk gate is already off\n"); - return; - } - - if (clk_conf.data) { + LCDPR("clk_gate is already off\n"); + } else { if (clk_conf.data->clk_gate_switch) clk_conf.data->clk_gate_switch(lcd_drv, 0); - } #ifdef CONFIG_AMLOGIC_VPU - switch_vpu_clk_gate_vmod(VPU_VENCL, VPU_CLK_GATE_OFF); + switch_vpu_clk_gate_vmod(VPU_VENCL, VPU_CLK_GATE_OFF); #endif - lcd_clktree.clk_gate_state = 0; + lcd_clktree.clk_gate_state = 0; + } } } @@ -2349,18 +2630,25 @@ static struct lcd_clk_data_s lcd_clk_data_gxl = { .div_in_fmax = CLK_DIV_IN_MAX_GXL, .div_out_fmax = CRT_VID_CLK_IN_MAX_GXL, .xd_out_fmax = ENCL_CLK_IN_MAX_GXL, - .ss_level_max = SS_LEVEL_MAX_GXL, .clk_path_valid = 0, .vclk_sel = 0, .pll_ctrl_table = pll_ctrl_table_txl, - .pll_ss_table = NULL, + + .ss_level_max = 0, + .ss_freq_max = 0, + .ss_mode_max = 0, + .ss_level_table = NULL, + .ss_freq_table = NULL, + .ss_mode_table = NULL, .clk_generate_parameter = lcd_clk_generate_txl, .pll_frac_generate = lcd_pll_frac_generate_txl, - .set_spread_spectrum = NULL, + .set_ss_level = NULL, + .set_ss_advance = NULL, .clk_set = lcd_clk_set_txl, .clk_gate_switch = lcd_clk_gate_switch_dft, + .clk_gate_optional_switch = NULL, .clktree_probe = lcd_clktree_probe_dft, .clktree_remove = lcd_clktree_remove_dft, .clk_config_init_print = lcd_clk_config_init_print_dft, @@ -2384,18 +2672,25 @@ static struct lcd_clk_data_s lcd_clk_data_txl = { .div_in_fmax = CLK_DIV_IN_MAX_TXL, .div_out_fmax = CRT_VID_CLK_IN_MAX_TXL, .xd_out_fmax = ENCL_CLK_IN_MAX_TXL, - .ss_level_max = SS_LEVEL_MAX_TXL, .clk_path_valid = 0, .vclk_sel = 0, .pll_ctrl_table = pll_ctrl_table_txl, - .pll_ss_table = lcd_pll_ss_table_txl, + + .ss_level_max = sizeof(lcd_ss_level_table_txl) / sizeof(char *), + .ss_freq_max = 0, + .ss_mode_max = 0, + .ss_level_table = lcd_ss_level_table_txl, + .ss_freq_table = NULL, + .ss_mode_table = NULL, .clk_generate_parameter = lcd_clk_generate_txl, .pll_frac_generate = lcd_pll_frac_generate_txl, - .set_spread_spectrum = lcd_set_pll_ss_txl, + .set_ss_level = lcd_set_pll_ss_level_txl, + .set_ss_advance = NULL, .clk_set = lcd_clk_set_txl, .clk_gate_switch = lcd_clk_gate_switch_dft, + .clk_gate_optional_switch = NULL, .clktree_probe = lcd_clktree_probe_dft, .clktree_remove = lcd_clktree_remove_dft, .clk_config_init_print = lcd_clk_config_init_print_dft, @@ -2419,18 +2714,25 @@ static struct lcd_clk_data_s lcd_clk_data_txlx = { .div_in_fmax = CLK_DIV_IN_MAX_TXLX, .div_out_fmax = CRT_VID_CLK_IN_MAX_TXLX, .xd_out_fmax = ENCL_CLK_IN_MAX_TXLX, - .ss_level_max = SS_LEVEL_MAX_TXLX, .clk_path_valid = 0, .vclk_sel = 0, .pll_ctrl_table = pll_ctrl_table_txl, - .pll_ss_table = lcd_pll_ss_table_txlx, + + .ss_level_max = sizeof(lcd_ss_level_table_txlx) / sizeof(char *), + .ss_freq_max = 0, + .ss_mode_max = 0, + .ss_level_table = lcd_ss_level_table_txlx, + .ss_freq_table = NULL, + .ss_mode_table = NULL, .clk_generate_parameter = lcd_clk_generate_txl, .pll_frac_generate = lcd_pll_frac_generate_txl, - .set_spread_spectrum = lcd_set_pll_ss_txlx, + .set_ss_level = lcd_set_pll_ss_level_txlx, + .set_ss_advance = NULL, .clk_set = lcd_clk_set_txlx, .clk_gate_switch = lcd_clk_gate_switch_dft, + .clk_gate_optional_switch = NULL, .clktree_probe = lcd_clktree_probe_dft, .clktree_remove = lcd_clktree_remove_dft, .clk_config_init_print = lcd_clk_config_init_print_dft, @@ -2454,18 +2756,25 @@ static struct lcd_clk_data_s lcd_clk_data_axg = { .div_in_fmax = 0, .div_out_fmax = CRT_VID_CLK_IN_MAX_AXG, .xd_out_fmax = ENCL_CLK_IN_MAX_AXG, - .ss_level_max = SS_LEVEL_MAX_AXG, .clk_path_valid = 0, .vclk_sel = 0, .pll_ctrl_table = pll_ctrl_table_axg, - .pll_ss_table = NULL, + + .ss_level_max = 0, + .ss_freq_max = 0, + .ss_mode_max = 0, + .ss_level_table = NULL, + .ss_freq_table = NULL, + .ss_mode_table = NULL, .clk_generate_parameter = lcd_clk_generate_axg, .pll_frac_generate = lcd_pll_frac_generate_axg, - .set_spread_spectrum = NULL, + .set_ss_level = NULL, + .set_ss_advance = NULL, .clk_set = lcd_clk_set_axg, .clk_gate_switch = lcd_clk_gate_switch_axg, + .clk_gate_optional_switch = NULL, .clktree_probe = lcd_clktree_probe_axg, .clktree_remove = lcd_clktree_remove_axg, .clk_config_init_print = lcd_clk_config_init_print_axg, @@ -2489,18 +2798,25 @@ static struct lcd_clk_data_s lcd_clk_data_g12a_path0 = { .div_in_fmax = 0, .div_out_fmax = CRT_VID_CLK_IN_MAX_G12A, .xd_out_fmax = ENCL_CLK_IN_MAX_G12A, - .ss_level_max = SS_LEVEL_MAX_HPLL_G12A, .clk_path_valid = 1, .vclk_sel = 0, .pll_ctrl_table = pll_ctrl_table_g12a_path0, - .pll_ss_table = NULL, + + .ss_level_max = 0, + .ss_freq_max = 0, + .ss_mode_max = 0, + .ss_level_table = NULL, + .ss_freq_table = NULL, + .ss_mode_table = NULL, .clk_generate_parameter = lcd_clk_generate_hpll_g12a, .pll_frac_generate = lcd_pll_frac_generate_txl, - .set_spread_spectrum = NULL, + .set_ss_level = NULL, + .set_ss_advance = NULL, .clk_set = lcd_clk_set_g12a_path0, .clk_gate_switch = lcd_clk_gate_switch_g12a, + .clk_gate_optional_switch = NULL, .clktree_probe = lcd_clktree_probe_g12a, .clktree_remove = lcd_clktree_remove_g12a, .clk_config_init_print = lcd_clk_config_init_print_axg, @@ -2524,18 +2840,25 @@ static struct lcd_clk_data_s lcd_clk_data_g12a_path1 = { .div_in_fmax = 0, .div_out_fmax = CRT_VID_CLK_IN_MAX_G12A, .xd_out_fmax = ENCL_CLK_IN_MAX_G12A, - .ss_level_max = SS_LEVEL_MAX_GP0_G12A, .clk_path_valid = 1, .vclk_sel = 1, .pll_ctrl_table = pll_ctrl_table_g12a_path1, - .pll_ss_table = NULL, + + .ss_level_max = 0, + .ss_freq_max = 0, + .ss_mode_max = 0, + .ss_level_table = NULL, + .ss_freq_table = NULL, + .ss_mode_table = NULL, .clk_generate_parameter = lcd_clk_generate_axg, .pll_frac_generate = lcd_pll_frac_generate_axg, - .set_spread_spectrum = NULL, + .set_ss_level = NULL, + .set_ss_advance = NULL, .clk_set = lcd_clk_set_g12a_path1, .clk_gate_switch = lcd_clk_gate_switch_g12a, + .clk_gate_optional_switch = NULL, .clktree_probe = lcd_clktree_probe_g12a, .clktree_remove = lcd_clktree_remove_g12a, .clk_config_init_print = lcd_clk_config_init_print_axg, @@ -2559,18 +2882,25 @@ static struct lcd_clk_data_s lcd_clk_data_g12b_path0 = { .div_in_fmax = 0, .div_out_fmax = CRT_VID_CLK_IN_MAX_G12A, .xd_out_fmax = ENCL_CLK_IN_MAX_G12A, - .ss_level_max = SS_LEVEL_MAX_HPLL_G12A, .clk_path_valid = 1, .vclk_sel = 0, .pll_ctrl_table = pll_ctrl_table_g12a_path0, - .pll_ss_table = NULL, + + .ss_level_max = 0, + .ss_freq_max = 0, + .ss_mode_max = 0, + .ss_level_table = NULL, + .ss_freq_table = NULL, + .ss_mode_table = NULL, .clk_generate_parameter = lcd_clk_generate_hpll_g12a, .pll_frac_generate = lcd_pll_frac_generate_txl, - .set_spread_spectrum = NULL, + .set_ss_level = NULL, + .set_ss_advance = NULL, .clk_set = lcd_clk_set_g12b_path0, .clk_gate_switch = lcd_clk_gate_switch_g12a, + .clk_gate_optional_switch = NULL, .clktree_probe = lcd_clktree_probe_g12a, .clktree_remove = lcd_clktree_remove_g12a, .clk_config_init_print = lcd_clk_config_init_print_axg, @@ -2594,18 +2924,25 @@ static struct lcd_clk_data_s lcd_clk_data_g12b_path1 = { .div_in_fmax = 0, .div_out_fmax = CRT_VID_CLK_IN_MAX_G12A, .xd_out_fmax = ENCL_CLK_IN_MAX_G12A, - .ss_level_max = SS_LEVEL_MAX_GP0_G12A, .clk_path_valid = 1, .vclk_sel = 1, .pll_ctrl_table = pll_ctrl_table_g12a_path1, - .pll_ss_table = NULL, + + .ss_level_max = 0, + .ss_freq_max = 0, + .ss_mode_max = 0, + .ss_level_table = NULL, + .ss_freq_table = NULL, + .ss_mode_table = NULL, .clk_generate_parameter = lcd_clk_generate_axg, .pll_frac_generate = lcd_pll_frac_generate_axg, - .set_spread_spectrum = NULL, + .set_ss_level = NULL, + .set_ss_advance = NULL, .clk_set = lcd_clk_set_g12b_path1, .clk_gate_switch = lcd_clk_gate_switch_g12a, + .clk_gate_optional_switch = NULL, .clktree_probe = lcd_clktree_probe_g12a, .clktree_remove = lcd_clktree_remove_g12a, .clk_config_init_print = lcd_clk_config_init_print_axg, @@ -2629,18 +2966,25 @@ static struct lcd_clk_data_s lcd_clk_data_tl1 = { .div_in_fmax = CLK_DIV_IN_MAX_TL1, .div_out_fmax = CRT_VID_CLK_IN_MAX_TL1, .xd_out_fmax = ENCL_CLK_IN_MAX_TL1, - .ss_level_max = SS_LEVEL_MAX_TL1, .clk_path_valid = 0, .vclk_sel = 0, .pll_ctrl_table = pll_ctrl_table_tl1, - .pll_ss_table = NULL, + + .ss_level_max = sizeof(lcd_ss_level_table_tl1) / sizeof(char *), + .ss_freq_max = sizeof(lcd_ss_freq_table_tl1) / sizeof(char *), + .ss_mode_max = sizeof(lcd_ss_mode_table_tl1) / sizeof(char *), + .ss_level_table = lcd_ss_level_table_tl1, + .ss_freq_table = lcd_ss_freq_table_tl1, + .ss_mode_table = lcd_ss_mode_table_tl1, .clk_generate_parameter = lcd_clk_generate_txl, .pll_frac_generate = lcd_pll_frac_generate_txl, - .set_spread_spectrum = NULL, + .set_ss_level = lcd_set_pll_ss_level_tl1, + .set_ss_advance = lcd_set_pll_ss_advance_tl1, .clk_set = lcd_clk_set_tl1, - .clk_gate_switch = lcd_clk_gate_switch_tl1, + .clk_gate_switch = lcd_clk_gate_switch_dft, + .clk_gate_optional_switch = lcd_clk_gate_optional_switch_tl1, .clktree_probe = lcd_clktree_probe_tl1, .clktree_remove = lcd_clktree_remove_tl1, .clk_config_init_print = lcd_clk_config_init_print_dft, @@ -2666,6 +3010,7 @@ static void lcd_clk_config_chip_init(struct lcd_clk_config_s *cConf) cConf->data = &lcd_clk_data_axg; break; case LCD_CHIP_G12A: + case LCD_CHIP_SM1: if (lcd_drv->lcd_clk_path) cConf->data = &lcd_clk_data_g12a_path1; else @@ -2678,6 +3023,7 @@ static void lcd_clk_config_chip_init(struct lcd_clk_config_s *cConf) cConf->data = &lcd_clk_data_g12b_path0; break; case LCD_CHIP_TL1: + case LCD_CHIP_TM2: cConf->data = &lcd_clk_data_tl1; break; default: @@ -2709,6 +3055,7 @@ int lcd_clk_path_change(int sel) switch (lcd_drv->data->chip_type) { case LCD_CHIP_G12A: case LCD_CHIP_G12B: + case LCD_CHIP_SM1: if (sel) cConf->data = &lcd_clk_data_g12a_path1; else diff --git a/drivers/amlogic/media/vout/lcd/lcd_clk_config.h b/drivers/amlogic/media/vout/lcd/lcd_clk_config.h index 8a52cdaaa407..487117d55f63 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_clk_config.h +++ b/drivers/amlogic/media/vout/lcd/lcd_clk_config.h @@ -27,7 +27,8 @@ */ #define LCD_CLK_CTRL_EN 0 #define LCD_CLK_CTRL_RST 1 -#define LCD_CLK_CTRL_FRAC 2 +#define LCD_CLK_CTRL_M 2 +#define LCD_CLK_CTRL_FRAC 3 #define LCD_CLK_CTRL_END 0xffff #define LCD_CLK_REG_END 0xffff @@ -57,18 +58,26 @@ struct lcd_clk_data_s { unsigned int div_in_fmax; unsigned int div_out_fmax; unsigned int xd_out_fmax; - unsigned int ss_level_max; unsigned char clk_path_valid; unsigned char vclk_sel; struct lcd_clk_ctrl_s *pll_ctrl_table; - char **pll_ss_table; + + unsigned int ss_level_max; + unsigned int ss_freq_max; + unsigned int ss_mode_max; + char **ss_level_table; + char **ss_freq_table; + char **ss_mode_table; void (*clk_generate_parameter)(struct lcd_config_s *pconf); void (*pll_frac_generate)(struct lcd_config_s *pconf); - void (*set_spread_spectrum)(unsigned int ss_level); + void (*set_ss_level)(unsigned int level); + void (*set_ss_advance)(unsigned int freq, unsigned int mode); void (*clk_set)(struct lcd_config_s *pconf); void (*clk_gate_switch)(struct aml_lcd_drv_s *lcd_drv, int status); + void (*clk_gate_optional_switch)(struct aml_lcd_drv_s *lcd_drv, + int status); void (*clktree_probe)(void); void (*clktree_remove)(void); void (*clk_config_init_print)(void); @@ -89,11 +98,13 @@ struct lcd_clk_config_s { /* unit: kHz */ unsigned int pll_od1_sel; unsigned int pll_od2_sel; unsigned int pll_od3_sel; - unsigned int pll_pi_div_sel; /* for tcon */ + unsigned int pll_tcon_div_sel; unsigned int pll_level; unsigned int pll_frac; unsigned int pll_fout; unsigned int ss_level; + unsigned int ss_freq; + unsigned int ss_mode; unsigned int div_sel; unsigned int xd; unsigned int div_sel_max; @@ -105,6 +116,7 @@ struct lcd_clk_config_s { /* unit: kHz */ struct lcd_clktree_s { unsigned char clk_gate_state; + unsigned char clk_gate_optional_state; struct clk *encl_top_gate; struct clk *encl_int_gate; @@ -127,8 +139,8 @@ extern struct lcd_clk_config_s *get_lcd_clk_config(void); extern int lcd_clk_config_print(char *buf, int offset); extern int lcd_encl_clk_msr(void); extern void lcd_pll_reset(void); -extern char *lcd_get_spread_spectrum(void); -extern void lcd_set_spread_spectrum(unsigned int ss_level); +extern int lcd_get_ss(char *buf); +extern int lcd_set_ss(unsigned int level, unsigned int freq, unsigned int mode); extern void lcd_clk_update(struct lcd_config_s *pconf); extern void lcd_clk_set(struct lcd_config_s *pconf); extern void lcd_clk_disable(void); diff --git a/drivers/amlogic/media/vout/lcd/lcd_clk_ctrl.h b/drivers/amlogic/media/vout/lcd/lcd_clk_ctrl.h index 928ba65cc68d..041d6b65a6ea 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_clk_ctrl.h +++ b/drivers/amlogic/media/vout/lcd/lcd_clk_ctrl.h @@ -232,20 +232,15 @@ /* video */ #define CLK_DIV_IN_MAX_TL1 (3100 * 1000) #define CRT_VID_CLK_IN_MAX_TL1 (3100 * 1000) -#define ENCL_CLK_IN_MAX_TL1 (400 * 1000) +#define ENCL_CLK_IN_MAX_TL1 (750 * 1000) /* ********************************** * Spread Spectrum * ********************************** */ -#define SS_LEVEL_MAX_GXL 0 -#define SS_LEVEL_MAX_AXG 0 -#define SS_LEVEL_MAX_GP0_G12A 0 -#define SS_LEVEL_MAX_HPLL_G12A 0 -#define SS_LEVEL_MAX_TXL 5 -static char *lcd_pll_ss_table_txl[] = { +static char *lcd_ss_level_table_txl[] = { "0, disable", "1, +/-0.3%", "2, +/-0.4%", @@ -253,8 +248,7 @@ static char *lcd_pll_ss_table_txl[] = { "4, +/-1.2%", }; -#define SS_LEVEL_MAX_TXLX 6 -static char *lcd_pll_ss_table_txlx[] = { +static char *lcd_ss_level_table_txlx[] = { "0, disable", "1, +/-0.3%", "2, +/-0.5%", @@ -263,7 +257,55 @@ static char *lcd_pll_ss_table_txlx[] = { "5, +/-3.0%", }; -#define SS_LEVEL_MAX_TL1 0 +static char *lcd_ss_level_table_tl1[] = { + "0, disable", + "1, 2000ppm", + "2, 4000ppm", + "3, 6000ppm", + "4, 8000ppm", + "5, 10000ppm", + "6, 12000ppm", + "7, 14000ppm", + "8, 16000ppm", + "9, 18000ppm", + "10, 20000ppm", + "11, 22000ppm", + "12, 24000ppm", + "13, 25000ppm", + "14, 28000ppm", + "15, 30000ppm", + "16, 32000ppm", + "17, 33000ppm", + "18, 36000ppm", + "19, 38500ppm", + "20, 40000ppm", + "21, 42000ppm", + "22, 44000ppm", + "23, 45000ppm", + "24, 48000ppm", + "25, 50000ppm", + "26, 50000ppm", + "27, 54000ppm", + "28, 55000ppm", + "29, 55000ppm", + "30, 60000ppm", +}; + +static char *lcd_ss_freq_table_tl1[] = { + "0, 29.5KHz", + "1, 31.5KHz", + "2, 50KHz", + "3, 75KHz", + "4, 100KHz", + "5, 150KHz", + "6, 200KHz", +}; + +static char *lcd_ss_mode_table_tl1[] = { + "0, center ss", + "1, up ss", + "2, down ss", +}; static unsigned int pll_ss_reg_txl[][2] = { @@ -275,7 +317,6 @@ static unsigned int pll_ss_reg_txl[][2] = { {((1 << 14) | (0xc << 10)), (0x3 << 2)}, /* 4: +/-1.2% */ }; - static unsigned int pll_ss_reg_txlx[][3] = { /* cntl3 cntl4 cntl5 */ { 0, 0, 0}, /* disable */ @@ -286,6 +327,57 @@ static unsigned int pll_ss_reg_txlx[][3] = { {((1 << 14) | (0xa << 10)), (0x3 << 2), (0x2 << 30)}, /* 5: +/-3.0% */ }; +static unsigned int pll_ss_reg_tl1[][2] = { + /* dep_sel, str_m */ +#if 0 + { 0, 0}, /* 0: disable */ + {10, 1}, /* 1: +/-0.25% */ + {10, 2}, /* 2: +/-0.50% */ + {10, 3}, /* 3: +/-0.75% */ + {10, 4}, /* 4: +/-1.00% */ + {10, 5}, /* 5: +/-1.25% */ + {10, 6}, /* 6: +/-1.50% */ + {10, 7}, /* 7: +/-1.75% */ + {10, 8}, /* 8: +/-2.00% */ + {10, 9}, /* 9: +/-2.25% */ + {10, 10}, /* 10: +/-2.50% */ + {11, 10}, /* 11: +/-2.75% */ + {12, 10}, /* 12: +/-3.00% */ +#else + { 0, 0}, /* 0: disable */ + { 4, 1}, /* 1: +/-0.1% */ + { 4, 2}, /* 2: +/-0.2% */ + { 4, 3}, /* 3: +/-0.3% */ + { 4, 4}, /* 4: +/-0.4% */ + { 4, 5}, /* 5: +/-0.5% */ + { 4, 6}, /* 6: +/-0.6% */ + { 4, 7}, /* 7: +/-0.7% */ + { 4, 8}, /* 8: +/-0.8% */ + { 4, 9}, /* 9: +/-0.9% */ + { 4, 10}, /* 10: +/-1.0% */ + { 11, 4}, /* 11: +/-1.1% */ + { 12, 4}, /* 12: +/-1.2% */ + { 10, 5}, /* 13: +/-1.25% */ + { 8, 7}, /* 14: +/-1.4% */ + { 6, 10}, /* 15: +/-1.5% */ + { 8, 8}, /* 16: +/-1.6% */ + { 11, 6}, /* 17: +/-1.65% */ + { 8, 9}, /* 18: +/-1.8% */ + { 11, 7}, /* 19: +/-1.925% */ + { 10, 8}, /* 20: +/-2.0% */ + { 12, 7}, /* 21: +/-2.1% */ + { 11, 8}, /* 22: +/-2.2% */ + { 9, 10}, /* 23: +/-2.25% */ + { 12, 8}, /* 24: +/-2.4% */ + { 10, 10}, /* 25: +/-2.5% */ + { 10, 10}, /* 26: +/-2.5% */ + { 12, 9}, /* 27: +/-2.7% */ + { 11, 10}, /* 28: +/-2.75% */ + { 11, 10}, /* 29: +/-2.75% */ + { 12, 10}, /* 30: +/-3.0% */ +#endif +}; + /* ********************************** * pll control * ********************************** @@ -294,6 +386,7 @@ struct lcd_clk_ctrl_s pll_ctrl_table_txl[] = { /* flag reg bit len*/ {LCD_CLK_CTRL_EN, HHI_HDMI_PLL_CNTL, LCD_PLL_EN_TXL, 1}, {LCD_CLK_CTRL_RST, HHI_HDMI_PLL_CNTL, LCD_PLL_RST_TXL, 1}, + {LCD_CLK_CTRL_M, HHI_HDMI_PLL_CNTL, LCD_PLL_M_TXL, 9}, {LCD_CLK_CTRL_FRAC, HHI_HDMI_PLL_CNTL2, 0, 12}, {LCD_CLK_CTRL_END, LCD_CLK_REG_END, 0, 0}, }; @@ -302,6 +395,7 @@ struct lcd_clk_ctrl_s pll_ctrl_table_axg[] = { /* flag reg bit len*/ {LCD_CLK_CTRL_EN, HHI_GP0_PLL_CNTL_AXG, LCD_PLL_EN_AXG, 1}, {LCD_CLK_CTRL_RST, HHI_GP0_PLL_CNTL_AXG, LCD_PLL_RST_AXG, 1}, + {LCD_CLK_CTRL_M, HHI_GP0_PLL_CNTL_AXG, LCD_PLL_M_AXG, 9}, {LCD_CLK_CTRL_FRAC, HHI_GP0_PLL_CNTL1_AXG, 0, 12}, {LCD_CLK_CTRL_END, LCD_CLK_REG_END, 0, 0}, }; @@ -310,6 +404,7 @@ struct lcd_clk_ctrl_s pll_ctrl_table_g12a_path0[] = { /* flag reg bit len*/ {LCD_CLK_CTRL_EN, HHI_HDMI_PLL_CNTL, LCD_PLL_EN_HPLL_G12A, 1}, {LCD_CLK_CTRL_RST, HHI_HDMI_PLL_CNTL, LCD_PLL_RST_HPLL_G12A, 1}, + {LCD_CLK_CTRL_M, HHI_HDMI_PLL_CNTL, LCD_PLL_M_HPLL_G12A, 8}, {LCD_CLK_CTRL_FRAC, HHI_HDMI_PLL_CNTL2, 0, 19}, {LCD_CLK_CTRL_END, LCD_CLK_REG_END, 0, 0}, }; @@ -318,6 +413,7 @@ struct lcd_clk_ctrl_s pll_ctrl_table_g12a_path1[] = { /* flag reg bit len*/ {LCD_CLK_CTRL_EN, HHI_GP0_PLL_CNTL0_G12A, LCD_PLL_EN_GP0_G12A, 1}, {LCD_CLK_CTRL_RST, HHI_GP0_PLL_CNTL0_G12A, LCD_PLL_RST_GP0_G12A, 1}, + {LCD_CLK_CTRL_M, HHI_GP0_PLL_CNTL0_G12A, LCD_PLL_M_GP0_G12A, 8}, {LCD_CLK_CTRL_FRAC, HHI_GP0_PLL_CNTL1_G12A, 0, 19}, {LCD_CLK_CTRL_END, LCD_CLK_REG_END, 0, 0}, }; @@ -326,6 +422,7 @@ struct lcd_clk_ctrl_s pll_ctrl_table_tl1[] = { /* flag reg bit len*/ {LCD_CLK_CTRL_EN, HHI_TCON_PLL_CNTL0, LCD_PLL_EN_TL1, 1}, {LCD_CLK_CTRL_RST, HHI_TCON_PLL_CNTL0, LCD_PLL_RST_TL1, 1}, + {LCD_CLK_CTRL_M, HHI_TCON_PLL_CNTL0, LCD_PLL_M_TL1, 8}, {LCD_CLK_CTRL_FRAC, HHI_TCON_PLL_CNTL1, 0, 17}, {LCD_CLK_CTRL_END, LCD_CLK_REG_END, 0, 0}, }; @@ -351,7 +448,7 @@ static const unsigned int od_table[6] = { 1, 2, 4, 8, 16, 32 }; -static const unsigned int pi_div_table[2] = {2, 4}; +static const unsigned int tcon_div_table[5] = {1, 2, 4, 8, 16}; static char *lcd_clk_div_sel_table[] = { "1", @@ -369,6 +466,7 @@ static char *lcd_clk_div_sel_table[] = { "14", "15", "2.5", + "4.67", "invalid", }; @@ -391,6 +489,7 @@ enum div_sel_e { CLK_DIV_SEL_14, /* 12 */ CLK_DIV_SEL_15, /* 13 */ CLK_DIV_SEL_2p5, /* 14 */ + CLK_DIV_SEL_4p67, /* 15 */ CLK_DIV_SEL_MAX, }; @@ -411,6 +510,7 @@ static unsigned int lcd_clk_div_table[][3] = { {CLK_DIV_SEL_14, 0x3f80, 1,}, {CLK_DIV_SEL_15, 0x7f80, 2,}, {CLK_DIV_SEL_2p5, 0x5294, 2,}, + {CLK_DIV_SEL_4p67, 0x0ccc, 1,}, {CLK_DIV_SEL_MAX, 0xffff, 0,}, }; diff --git a/drivers/amlogic/media/vout/lcd/lcd_common.c b/drivers/amlogic/media/vout/lcd/lcd_common.c index cbbcac6e6236..ca87abc9d3b0 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_common.c +++ b/drivers/amlogic/media/vout/lcd/lcd_common.c @@ -363,101 +363,42 @@ void lcd_vbyone_pinmux_set(int status) pconf->pinmux_flag = index; } +static char *lcd_tcon_pinmux_str[] = { + "tcon", + "tcon_off", + "none", +}; + void lcd_tcon_pinmux_set(int status) { struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); struct lcd_config_s *pconf; + unsigned int index; if (lcd_debug_print_flag) LCDPR("%s: %d\n", __func__, status); pconf = lcd_drv->lcd_config; - if (status) { - if (pconf->pinmux_flag == 0) { - pconf->pinmux_flag = 1; - /* request pinmux */ - pconf->pin = devm_pinctrl_get_select(lcd_drv->dev, - "tcon"); - if (IS_ERR(pconf->pin)) - LCDERR("set tcon pinmux error\n"); - } else { - LCDPR("tcon pinmux is already selected\n"); - } + index = (status) ? 0 : 1; + + if (pconf->pinmux_flag == index) { + LCDPR("pinmux %s is already selected\n", + lcd_tcon_pinmux_str[index]); + return; + } + + pconf->pin = devm_pinctrl_get_select(lcd_drv->dev, + lcd_tcon_pinmux_str[index]); + if (IS_ERR(pconf->pin)) { + LCDERR("set tcon pinmux %s error\n", + lcd_tcon_pinmux_str[index]); } else { - if (pconf->pinmux_flag) { - pconf->pinmux_flag = 0; - /* release pinmux */ - devm_pinctrl_put(pconf->pin); - } else { - LCDPR("tcon pinmux is already released\n"); + if (lcd_debug_print_flag) { + LCDPR("set tcon pinmux %s: %p\n", + lcd_tcon_pinmux_str[index], pconf->pin); } } -} - -unsigned int lcd_lvds_channel_on_value(struct lcd_config_s *pconf) -{ - unsigned int channel_on = 0; - - if (pconf->lcd_control.lvds_config->dual_port == 0) { - if (pconf->lcd_control.lvds_config->lane_reverse == 0) { - switch (pconf->lcd_basic.lcd_bits) { - case 6: - channel_on = 0xf; - break; - case 8: - channel_on = 0x1f; - break; - case 10: - default: - channel_on = 0x3f; - break; - } - } else { - switch (pconf->lcd_basic.lcd_bits) { - case 6: - channel_on = 0x3c; - break; - case 8: - channel_on = 0x3e; - break; - case 10: - default: - channel_on = 0x3f; - break; - } - } - if (pconf->lcd_control.lvds_config->port_swap == 1) - channel_on = (channel_on << 6); /* use channel B */ - } else { - if (pconf->lcd_control.lvds_config->lane_reverse == 0) { - switch (pconf->lcd_basic.lcd_bits) { - case 6: - channel_on = 0x3cf; - break; - case 8: - channel_on = 0x7df; - break; - case 10: - default: - channel_on = 0xfff; - break; - } - } else { - switch (pconf->lcd_basic.lcd_bits) { - case 6: - channel_on = 0xf3c; - break; - case 8: - channel_on = 0xfbe; - break; - case 10: - default: - channel_on = 0xfff; - break; - } - } - } - return channel_on; + pconf->pinmux_flag = index; } int lcd_power_load_from_dts(struct lcd_config_s *pconf, @@ -470,6 +411,9 @@ int lcd_power_load_from_dts(struct lcd_config_s *pconf, int i, j; unsigned int index; + if (lcd_debug_print_flag) + LCDPR("%s\n", __func__); + if (child == NULL) { LCDPR("error: failed to get %s\n", pconf->lcd_propname); return -1; @@ -506,6 +450,7 @@ int lcd_power_load_from_dts(struct lcd_config_s *pconf, index = lcd_power->power_on_step[i].index; switch (lcd_power->power_on_step[i].type) { case LCD_POWER_TYPE_CPU: + case LCD_POWER_TYPE_WAIT_GPIO: if (index < LCD_CPU_GPIO_NUM_MAX) lcd_cpu_gpio_probe(index); break; @@ -560,6 +505,7 @@ int lcd_power_load_from_dts(struct lcd_config_s *pconf, index = lcd_power->power_off_step[i].index; switch (lcd_power->power_off_step[i].type) { case LCD_POWER_TYPE_CPU: + case LCD_POWER_TYPE_WAIT_GPIO: if (index < LCD_CPU_GPIO_NUM_MAX) lcd_cpu_gpio_probe(index); break; @@ -605,8 +551,6 @@ int lcd_power_load_from_unifykey(struct lcd_config_s *pconf, /* power: (5byte * n) */ p = buf + len; - if (lcd_debug_print_flag) - LCDPR("power_on step:\n"); i = 0; while (i < LCD_PWR_STEP_MAX) { pconf->lcd_power->power_on_step_max = i; @@ -634,6 +578,7 @@ int lcd_power_load_from_unifykey(struct lcd_config_s *pconf, index = pconf->lcd_power->power_on_step[i].index; switch (pconf->lcd_power->power_on_step[i].type) { case LCD_POWER_TYPE_CPU: + case LCD_POWER_TYPE_WAIT_GPIO: if (index < LCD_CPU_GPIO_NUM_MAX) lcd_cpu_gpio_probe(index); break; @@ -686,6 +631,7 @@ int lcd_power_load_from_unifykey(struct lcd_config_s *pconf, index = pconf->lcd_power->power_off_step[j].index; switch (pconf->lcd_power->power_off_step[j].type) { case LCD_POWER_TYPE_CPU: + case LCD_POWER_TYPE_WAIT_GPIO: if (index < LCD_CPU_GPIO_NUM_MAX) lcd_cpu_gpio_probe(index); break; @@ -806,8 +752,8 @@ void lcd_timing_init_config(struct lcd_config_s *pconf) vsync_bp = pconf->lcd_timing.vsync_bp; vsync_width = pconf->lcd_timing.vsync_width; - de_hstart = h_period - h_active - 1; - de_vstart = v_period - v_active; + de_hstart = hsync_bp + hsync_width; + de_vstart = vsync_bp + vsync_width; pconf->lcd_timing.video_on_pixel = de_hstart - h_delay; pconf->lcd_timing.video_on_line = de_vstart; @@ -1064,9 +1010,24 @@ int lcd_vmode_change(struct lcd_config_s *pconf) } #endif +void lcd_clk_change(struct lcd_config_s *pconf) +{ + switch (pconf->lcd_timing.clk_change) { + case LCD_CLK_PLL_CHANGE: + lcd_clk_generate_parameter(pconf); + lcd_clk_set(pconf); + break; + case LCD_CLK_FRAC_UPDATE: + lcd_clk_update(pconf); + break; + default: + break; + } +} + void lcd_venc_change(struct lcd_config_s *pconf) { - unsigned int htotal, vtotal; + unsigned int htotal, vtotal, frame_rate; htotal = lcd_vcbus_read(ENCL_VIDEO_MAX_PXCNT) + 1; vtotal = lcd_vcbus_read(ENCL_VIDEO_MAX_LNCNT) + 1; @@ -1084,8 +1045,10 @@ void lcd_venc_change(struct lcd_config_s *pconf) pconf->lcd_basic.v_period); } - if (pconf->lcd_basic.v_period != vtotal) - aml_lcd_notifier_call_chain(LCD_EVENT_BACKLIGHT_UPDATE, NULL); + frame_rate = (pconf->lcd_timing.sync_duration_num * 100) / + pconf->lcd_timing.sync_duration_den; + frame_rate = (frame_rate + 50) / 100; + aml_lcd_notifier_call_chain(LCD_EVENT_BACKLIGHT_UPDATE, &frame_rate); } void lcd_if_enable_retry(struct lcd_config_s *pconf) diff --git a/drivers/amlogic/media/vout/lcd/lcd_common.h b/drivers/amlogic/media/vout/lcd/lcd_common.h index ce93c41ea5e3..1c571c1bb148 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_common.h +++ b/drivers/amlogic/media/vout/lcd/lcd_common.h @@ -33,57 +33,16 @@ /* 20180827: add pinmux off support */ /* 20180928: tl1 support, optimize clk config */ /* 20181012: tl1 support tcon */ -#define LCD_DRV_VERSION "20181012" +/* 20181212: tl1 update p2p config and pll setting */ +/* 20181225: update phy config */ +/* 20190108: tl1 support tablet mode */ +/* 20190115: tl1 tcon all interface support */ +/* 20190225: optimize unifykey read flow to avoid crash */ +/* 20190308: add more panel clk_ss_level step for tl1 */ +#define LCD_DRV_VERSION "20190308" #define VPP_OUT_SATURATE (1 << 0) -/* -------------------------- */ -/* lvsd phy parameters define */ -/* -------------------------- */ -#define LVDS_PHY_CNTL1_G9TV 0x606cca80 -#define LVDS_PHY_CNTL2_G9TV 0x0000006c -#define LVDS_PHY_CNTL3_G9TV 0x00000800 - -#define LVDS_PHY_CNTL1_TL1 0x6c60ca80 -#define LVDS_PHY_CNTL2_TL1 0x00000070 -#define LVDS_PHY_CNTL3_TL1 0x03ff0c00 -/* -------------------------- */ - -/* -------------------------- */ -/* vbyone phy parameters define */ -/* -------------------------- */ -#define VX1_PHY_CNTL1_G9TV 0x6e0ec900 -#define VX1_PHY_CNTL1_G9TV_PULLUP 0x6e0f4d00 -#define VX1_PHY_CNTL2_G9TV 0x0000007c -#define VX1_PHY_CNTL3_G9TV 0x00ff0800 -/* -------------------------- */ - -/* -------------------------- */ -/* minilvds phy parameters define */ -/* -------------------------- */ -#define MLVDS_PHY_CNTL1_TL1 0x6c60ca80 -#define MLVDS_PHY_CNTL2_TL1 0x00000070 -#define MLVDS_PHY_CNTL3_TL1 0x03ff0c00 - - -/* ******** mipi_dsi_phy ******** */ -/* bit[15:11] */ -#define MIPI_PHY_LANE_BIT 11 -#define MIPI_PHY_LANE_WIDTH 5 - -/* MIPI-DSI */ -#define DSI_LANE_0 (1 << 4) -#define DSI_LANE_1 (1 << 3) -#define DSI_LANE_CLK (1 << 2) -#define DSI_LANE_2 (1 << 1) -#define DSI_LANE_3 (1 << 0) -#define DSI_LANE_COUNT_1 (DSI_LANE_CLK | DSI_LANE_0) -#define DSI_LANE_COUNT_2 (DSI_LANE_CLK | DSI_LANE_0 | DSI_LANE_1) -#define DSI_LANE_COUNT_3 (DSI_LANE_CLK | DSI_LANE_0 |\ - DSI_LANE_1 | DSI_LANE_2) -#define DSI_LANE_COUNT_4 (DSI_LANE_CLK | DSI_LANE_0 |\ - DSI_LANE_1 | DSI_LANE_2 | DSI_LANE_3) - extern struct mutex lcd_vout_mutex; extern unsigned char lcd_resume_flag; extern int lcd_vout_serve_bypass; @@ -100,7 +59,7 @@ extern unsigned int lcd_cpu_gpio_get(unsigned int index); extern void lcd_ttl_pinmux_set(int status); extern void lcd_vbyone_pinmux_set(int status); extern void lcd_tcon_pinmux_set(int status); -extern unsigned int lcd_lvds_channel_on_value(struct lcd_config_s *pconf); + extern int lcd_power_load_from_dts(struct lcd_config_s *pconf, struct device_node *child); extern int lcd_power_load_from_unifykey(struct lcd_config_s *pconf, @@ -113,10 +72,20 @@ extern int lcd_vlock_param_load_from_unifykey(struct lcd_config_s *pconf, extern void lcd_optical_vinfo_update(void); extern void lcd_timing_init_config(struct lcd_config_s *pconf); extern int lcd_vmode_change(struct lcd_config_s *pconf); +extern void lcd_clk_change(struct lcd_config_s *pconf); extern void lcd_venc_change(struct lcd_config_s *pconf); extern void lcd_if_enable_retry(struct lcd_config_s *pconf); +/* lcd phy */ +extern void lcd_lvds_phy_set(struct lcd_config_s *pconf, int status); +extern void lcd_vbyone_phy_set(struct lcd_config_s *pconf, int status); +extern void lcd_mlvds_phy_set(struct lcd_config_s *pconf, int status); +extern void lcd_p2p_phy_set(struct lcd_config_s *pconf, int status); +extern void lcd_mipi_phy_set(struct lcd_config_s *pconf, int status); + /* lcd tcon */ +extern unsigned int lcd_tcon_reg_read(unsigned int addr); +extern void lcd_tcon_reg_write(unsigned int addr, unsigned int val); extern void lcd_tcon_reg_table_print(void); extern void lcd_tcon_reg_readback_print(void); extern int lcd_tcon_info_print(char *buf, int offset); diff --git a/drivers/amlogic/media/vout/lcd/lcd_debug.c b/drivers/amlogic/media/vout/lcd/lcd_debug.c index 83bf97be80a2..97dd57ccb16d 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_debug.c +++ b/drivers/amlogic/media/vout/lcd/lcd_debug.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -40,7 +41,7 @@ static struct lcd_debug_info_reg_s *lcd_debug_info_reg; static struct lcd_debug_info_if_s *lcd_debug_info_if; -#define PR_BUF_MAX 2048 +#define PR_BUF_MAX 4096 static void lcd_debug_parse_param(char *buf_orig, char **parm) { @@ -101,9 +102,14 @@ static const char *lcd_common_usage_str = { "\n" " echo > test ; show lcd bist pattern(1~7), 0=disable bist\n" "\n" -" echo w > reg ; write data to vcbus|hiu|cbus|periphs|mipi host|mipi phy reg\n" -" echo r > reg ; read vcbus|hiu|cbus|periphs|mipi host|mipi phy reg\n" -" echo d > reg ; dump vcbus|hiu|cbus|periphs|mipi host|mipi phy regs\n" +" echo level > ss ; set lcd clk spread spectrum level\n" +" echo freq > ss ; set lcd clk spread spectrum freq\n" +" echo mode > ss ; set lcd clk spread spectrum mode\n" +" cat ss ; show lcd clk spread spectrum information\n" +"\n" +" echo w > reg ; write data to vcbus|hiu|cbus|periphs|mipi host|mipi phy reg\n" +" echo r > reg ; read vcbus|hiu|cbus|periphs|mipi host|mipi phy reg\n" +" echo d > reg ; dump vcbus|hiu|cbus|periphs|mipi host|mipi phy regs\n" "\n" " echo <0|1> > print ; 0=disable debug print; 1=enable debug print\n" " cat print ; read current debug print flag\n" @@ -116,7 +122,8 @@ static const char *lcd_common_usage_str = { " echo ... > debug ; lcd common debug, use 'cat debug' for help\n" " cat debug ; print help information for debug command\n" "\n" -" echo > power ; set power on/off step delay(unit: ms)\n" +" echo <0|1> > power; lcd power control: 0=lcd power off, 1=lcd power on\n" +" echo > power_step ; set power on/off step delay(unit: ms)\n" " cat power ; print lcd power on/off step\n" "\n" " cat key_valid ; print lcd_key_valid setting\n" @@ -224,6 +231,7 @@ static int lcd_power_step_print(struct lcd_config_s *pconf, int status, switch (power_step->type) { case LCD_POWER_TYPE_CPU: case LCD_POWER_TYPE_PMU: + case LCD_POWER_TYPE_WAIT_GPIO: n = lcd_debug_info_len(len + offset); len += snprintf((buf+len), n, "%d: type=%d, index=%d, value=%d, delay=%d\n", @@ -252,7 +260,7 @@ static int lcd_power_step_print(struct lcd_config_s *pconf, int status, return len; } -static int lcd_power_info_print(char *buf, int offset) +static int lcd_power_step_info_print(char *buf, int offset) { struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); int len = 0; @@ -278,13 +286,13 @@ static int lcd_info_print_ttl(char *buf, int offset) n = lcd_debug_info_len(len + offset); len += snprintf((buf+len), n, "clk_pol %u\n" - "hvsync_valid %u\n" "de_valid %u\n" + "hvsync_valid %u\n" "rb_swap %u\n" "bit_swap %u\n\n", pconf->lcd_control.ttl_config->clk_pol, - ((pconf->lcd_control.ttl_config->sync_valid >> 0) & 1), ((pconf->lcd_control.ttl_config->sync_valid >> 1) & 1), + ((pconf->lcd_control.ttl_config->sync_valid >> 0) & 1), ((pconf->lcd_control.ttl_config->swap_ctrl >> 1) & 1), ((pconf->lcd_control.ttl_config->swap_ctrl >> 0) & 1)); @@ -356,7 +364,7 @@ static int lcd_info_print_vbyone(char *buf, int offset) vx1_conf->region_num, vx1_conf->byte_mode, vx1_conf->color_fmt, - vx1_conf->bit_rate, + pconf->lcd_timing.bit_rate, vx1_conf->phy_vswing, vx1_conf->phy_preem, vx1_conf->intr_en, @@ -420,7 +428,7 @@ static int lcd_info_print_mlvds(char *buf, int offset) n = lcd_debug_info_len(len + offset); len += snprintf((buf+len), n, "channel_num %d\n" - "channel_sel1 0x%08x\n" + "channel_sel0 0x%08x\n" "channel_sel1 0x%08x\n" "clk_phase 0x%04x\n" "pn_swap %u\n" @@ -437,7 +445,7 @@ static int lcd_info_print_mlvds(char *buf, int offset) pconf->lcd_control.mlvds_config->bit_swap, pconf->lcd_control.mlvds_config->phy_vswing, pconf->lcd_control.mlvds_config->phy_preem, - pconf->lcd_control.mlvds_config->bit_rate, + pconf->lcd_timing.bit_rate, pconf->lcd_control.mlvds_config->pi_clk_sel); len += lcd_tcon_info_print((buf+len), (len+offset)); @@ -462,26 +470,24 @@ static int lcd_info_print_p2p(char *buf, int offset) n = lcd_debug_info_len(len + offset); len += snprintf((buf+len), n, - "channel_num %d\n" + "p2p_type 0x%x\n" + "lane_num %d\n" + "channel_sel0 0x%08x\n" "channel_sel1 0x%08x\n" - "channel_sel1 0x%08x\n" - "clk_phase 0x%04x\n" "pn_swap %u\n" "bit_swap %u\n" - "phy_vswing 0x%x\n" - "phy_preem 0x%x\n" "bit_rate %dHz\n" - "pi_clk_sel 0x%03x\n\n", - pconf->lcd_control.p2p_config->channel_num, + "phy_vswing 0x%x\n" + "phy_preem 0x%x\n\n", + pconf->lcd_control.p2p_config->p2p_type, + pconf->lcd_control.p2p_config->lane_num, pconf->lcd_control.p2p_config->channel_sel0, pconf->lcd_control.p2p_config->channel_sel1, - pconf->lcd_control.p2p_config->clk_phase, pconf->lcd_control.p2p_config->pn_swap, pconf->lcd_control.p2p_config->bit_swap, + pconf->lcd_timing.bit_rate, pconf->lcd_control.p2p_config->phy_vswing, - pconf->lcd_control.p2p_config->phy_preem, - pconf->lcd_control.p2p_config->bit_rate, - pconf->lcd_control.p2p_config->pi_clk_sel); + pconf->lcd_control.p2p_config->phy_preem); len += lcd_tcon_info_print((buf+len), (len+offset)); @@ -510,12 +516,13 @@ static int lcd_info_print(char *buf, int offset) n = lcd_debug_info_len(len + offset); len += snprintf((buf+len), n, "driver version: %s\n" - "panel_type: %s, chip: %d, mode: %s, status: %d\n" + "panel_type: %s, chip: %d, mode: %s, status: %d, viu_sel: %d\n" "key_valid: %d, config_load: %d\n" "fr_auto_policy: %d\n", lcd_drv->version, pconf->lcd_propname, lcd_drv->data->chip_type, - lcd_mode_mode_to_str(lcd_drv->lcd_mode), lcd_drv->lcd_status, + lcd_mode_mode_to_str(lcd_drv->lcd_mode), + lcd_drv->lcd_status, lcd_drv->viu_sel, lcd_drv->lcd_key_valid, lcd_drv->lcd_config_load, lcd_drv->fr_auto_policy); @@ -591,6 +598,34 @@ static int lcd_info_print(char *buf, int offset) return len; } +static void lcd_reg_print_serializer(char *buf, int offset) +{ + struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); + unsigned int reg0, reg1; + int n, len = 0; + + switch (lcd_drv->data->chip_type) { + case LCD_CHIP_TL1: + reg0 = HHI_LVDS_TX_PHY_CNTL0_TL1; + reg1 = HHI_LVDS_TX_PHY_CNTL1_TL1; + break; + default: + reg0 = HHI_LVDS_TX_PHY_CNTL0; + reg1 = HHI_LVDS_TX_PHY_CNTL1; + break; + } + + n = lcd_debug_info_len(len + offset); + len += snprintf((buf+len), n, "\nserializer regs:\n"); + n = lcd_debug_info_len(len + offset); + len += snprintf((buf+len), n, + "HHI_LVDS_TX_PHY_CNTL0 [0x%04x] = 0x%08x\n", + reg0, lcd_hiu_read(reg0)); + len += snprintf((buf+len), n, + "HHI_LVDS_TX_PHY_CNTL1 [0x%04x] = 0x%08x\n", + reg1, lcd_hiu_read(reg1)); +} + static int lcd_reg_print_ttl(char *buf, int offset) { unsigned int reg; @@ -672,6 +707,8 @@ static int lcd_reg_print_lvds(char *buf, int offset) unsigned int reg; int n, len = 0; + lcd_reg_print_serializer((buf+len), (len+offset)); + n = lcd_debug_info_len(len + offset); len += snprintf((buf+len), n, "\nlvds regs:\n"); n = lcd_debug_info_len(len + offset); @@ -689,16 +726,6 @@ static int lcd_reg_print_lvds(char *buf, int offset) len += snprintf((buf+len), n, "LCD_PORT_SWAP [0x%04x] = 0x%08x\n", reg, lcd_vcbus_read(reg)); - n = lcd_debug_info_len(len + offset); - reg = HHI_LVDS_TX_PHY_CNTL0; - len += snprintf((buf+len), n, - "LVDS_PHY_CNTL0 [0x%04x] = 0x%08x\n", - reg, lcd_hiu_read(reg)); - n = lcd_debug_info_len(len + offset); - reg = HHI_LVDS_TX_PHY_CNTL1; - len += snprintf((buf+len), n, - "LVDS_PHY_CNTL1 [0x%04x] = 0x%08x\n", - reg, lcd_hiu_read(reg)); return len; } @@ -708,6 +735,8 @@ static int lcd_reg_print_vbyone(char *buf, int offset) unsigned int reg; int n, len = 0; + lcd_reg_print_serializer((buf+len), (len+offset)); + n = lcd_debug_info_len(len + offset); len += snprintf((buf+len), n, "\nvbyone regs:\n"); n = lcd_debug_info_len(len + offset); @@ -752,11 +781,6 @@ static int lcd_reg_print_vbyone(char *buf, int offset) len += snprintf((buf+len), n, "VX1_INTR_STATE [0x%04x] = 0x%08x\n", reg, lcd_vcbus_read(reg)); - n = lcd_debug_info_len(len + offset); - reg = HHI_LVDS_TX_PHY_CNTL0; - len += snprintf((buf+len), n, - "VX1_PHY_CNTL0 [0x%04x] = 0x%08x\n", - reg, lcd_hiu_read(reg)); return len; } @@ -847,6 +871,8 @@ static int lcd_reg_print_mlvds(char *buf, int offset) unsigned int reg; int n, len = 0; + lcd_reg_print_serializer((buf+len), (len+offset)); + n = lcd_debug_info_len(len + offset); len += snprintf((buf+len), n, "\nmlvds regs:\n"); @@ -945,9 +971,9 @@ static int lcd_reg_print_mlvds(char *buf, int offset) len += snprintf((buf+len), n, "TCON_INTR_MASKN [0x%04x] = 0x%08x\n", reg, lcd_tcon_read(reg)); - reg = TCON_INTR; + reg = TCON_INTR_RO; len += snprintf((buf+len), n, - "TCON_INTR [0x%04x] = 0x%08x\n", + "TCON_INTR_RO [0x%04x] = 0x%08x\n", reg, lcd_tcon_read(reg)); return len; @@ -958,29 +984,16 @@ static int lcd_reg_print_p2p(char *buf, int offset) unsigned int reg; int n, len = 0; + lcd_reg_print_serializer((buf+len), (len+offset)); + n = lcd_debug_info_len(len + offset); - len += snprintf((buf+len), n, "\nmlvds regs:\n"); + len += snprintf((buf+len), n, "\np2p regs:\n"); n = lcd_debug_info_len(len + offset); reg = HHI_TCON_CLK_CNTL; len += snprintf((buf+len), n, "HHI_TCON_CLK_CNTL [0x%04x] = 0x%08x\n", reg, lcd_hiu_read(reg)); - n = lcd_debug_info_len(len + offset); - reg = HHI_DIF_TCON_CNTL0; - len += snprintf((buf+len), n, - "HHI_DIF_TCON_CNTL0 [0x%04x] = 0x%08x\n", - reg, lcd_hiu_read(reg)); - n = lcd_debug_info_len(len + offset); - reg = HHI_DIF_TCON_CNTL1; - len += snprintf((buf+len), n, - "HHI_DIF_TCON_CNTL1 [0x%04x] = 0x%08x\n", - reg, lcd_hiu_read(reg)); - n = lcd_debug_info_len(len + offset); - reg = HHI_DIF_TCON_CNTL2; - len += snprintf((buf+len), n, - "HHI_DIF_TCON_CNTL2 [0x%04x] = 0x%08x\n", - reg, lcd_hiu_read(reg)); n = lcd_debug_info_len(len + offset); reg = TCON_TOP_CTRL; @@ -1056,9 +1069,9 @@ static int lcd_reg_print_p2p(char *buf, int offset) len += snprintf((buf+len), n, "TCON_INTR_MASKN [0x%04x] = 0x%08x\n", reg, lcd_tcon_read(reg)); - reg = TCON_INTR; + reg = TCON_INTR_RO; len += snprintf((buf+len), n, - "TCON_INTR [0x%04x] = 0x%08x\n", + "TCON_INTR_RO [0x%04x] = 0x%08x\n", reg, lcd_tcon_read(reg)); return len; @@ -1074,17 +1087,103 @@ static int lcd_reg_print_phy_analog(char *buf, int offset) n = lcd_debug_info_len(len + offset); reg = HHI_DIF_CSI_PHY_CNTL1; len += snprintf((buf+len), n, - "HHI_DIF_CSI_PHY_CNTL1 [0x%04x] = 0x%08x\n", + "HHI_DIF_CSI_PHY_CNTL1 [0x%02x] = 0x%08x\n", reg, lcd_hiu_read(reg)); n = lcd_debug_info_len(len + offset); reg = HHI_DIF_CSI_PHY_CNTL2; len += snprintf((buf+len), n, - "HHI_DIF_CSI_PHY_CNTL2 [0x%04x] = 0x%08x\n", + "HHI_DIF_CSI_PHY_CNTL2 [0x%02x] = 0x%08x\n", reg, lcd_hiu_read(reg)); n = lcd_debug_info_len(len + offset); reg = HHI_DIF_CSI_PHY_CNTL3; len += snprintf((buf+len), n, - "HHI_DIF_CSI_PHY_CNTL3 [0x%04x] = 0x%08x\n", + "HHI_DIF_CSI_PHY_CNTL3 [0x%02x] = 0x%08x\n", + reg, lcd_hiu_read(reg)); + + return len; +} + +static int lcd_reg_print_phy_analog_tl1(char *buf, int offset) +{ + unsigned int reg; + int n, len = 0; + + n = lcd_debug_info_len(len + offset); + len += snprintf((buf+len), n, "\nphy analog regs:\n"); + n = lcd_debug_info_len(len + offset); + reg = HHI_DIF_CSI_PHY_CNTL1; + len += snprintf((buf+len), n, + "HHI_DIF_CSI_PHY_CNTL1 [0x%02x] = 0x%08x\n", + reg, lcd_hiu_read(reg)); + n = lcd_debug_info_len(len + offset); + reg = HHI_DIF_CSI_PHY_CNTL2; + len += snprintf((buf+len), n, + "HHI_DIF_CSI_PHY_CNTL2 [0x%02x] = 0x%08x\n", + reg, lcd_hiu_read(reg)); + n = lcd_debug_info_len(len + offset); + reg = HHI_DIF_CSI_PHY_CNTL3; + len += snprintf((buf+len), n, + "HHI_DIF_CSI_PHY_CNTL3 [0x%02x] = 0x%08x\n", + reg, lcd_hiu_read(reg)); + n = lcd_debug_info_len(len + offset); + reg = HHI_DIF_CSI_PHY_CNTL4; + len += snprintf((buf+len), n, + "HHI_DIF_CSI_PHY_CNTL4 [0x%02x] = 0x%08x\n", + reg, lcd_hiu_read(reg)); + n = lcd_debug_info_len(len + offset); + reg = HHI_DIF_CSI_PHY_CNTL6; + len += snprintf((buf+len), n, + "HHI_DIF_CSI_PHY_CNTL6 [0x%02x] = 0x%08x\n", + reg, lcd_hiu_read(reg)); + n = lcd_debug_info_len(len + offset); + reg = HHI_DIF_CSI_PHY_CNTL7; + len += snprintf((buf+len), n, + "HHI_DIF_CSI_PHY_CNTL7 [0x%02x] = 0x%08x\n", + reg, lcd_hiu_read(reg)); + n = lcd_debug_info_len(len + offset); + reg = HHI_DIF_CSI_PHY_CNTL8; + len += snprintf((buf+len), n, + "HHI_DIF_CSI_PHY_CNTL8 [0x%02x] = 0x%08x\n", + reg, lcd_hiu_read(reg)); + n = lcd_debug_info_len(len + offset); + reg = HHI_DIF_CSI_PHY_CNTL9; + len += snprintf((buf+len), n, + "HHI_DIF_CSI_PHY_CNTL9 [0x%02x] = 0x%08x\n", + reg, lcd_hiu_read(reg)); + n = lcd_debug_info_len(len + offset); + reg = HHI_DIF_CSI_PHY_CNTL10; + len += snprintf((buf+len), n, + "HHI_DIF_CSI_PHY_CNTL10 [0x%02x] = 0x%08x\n", + reg, lcd_hiu_read(reg)); + n = lcd_debug_info_len(len + offset); + reg = HHI_DIF_CSI_PHY_CNTL11; + len += snprintf((buf+len), n, + "HHI_DIF_CSI_PHY_CNTL11 [0x%02x] = 0x%08x\n", + reg, lcd_hiu_read(reg)); + n = lcd_debug_info_len(len + offset); + reg = HHI_DIF_CSI_PHY_CNTL12; + len += snprintf((buf+len), n, + "HHI_DIF_CSI_PHY_CNTL12 [0x%02x] = 0x%08x\n", + reg, lcd_hiu_read(reg)); + n = lcd_debug_info_len(len + offset); + reg = HHI_DIF_CSI_PHY_CNTL13; + len += snprintf((buf+len), n, + "HHI_DIF_CSI_PHY_CNTL13 [0x%02x] = 0x%08x\n", + reg, lcd_hiu_read(reg)); + n = lcd_debug_info_len(len + offset); + reg = HHI_DIF_CSI_PHY_CNTL14; + len += snprintf((buf+len), n, + "HHI_DIF_CSI_PHY_CNTL14 [0x%02x] = 0x%08x\n", + reg, lcd_hiu_read(reg)); + n = lcd_debug_info_len(len + offset); + reg = HHI_DIF_CSI_PHY_CNTL15; + len += snprintf((buf+len), n, + "HHI_DIF_CSI_PHY_CNTL15 [0x%02x] = 0x%08x\n", + reg, lcd_hiu_read(reg)); + n = lcd_debug_info_len(len + offset); + reg = HHI_DIF_CSI_PHY_CNTL16; + len += snprintf((buf+len), n, + "HHI_DIF_CSI_PHY_CNTL16 [0x%02x] = 0x%08x\n", reg, lcd_hiu_read(reg)); return len; @@ -1100,17 +1199,17 @@ static int lcd_reg_print_mipi_phy_analog(char *buf, int offset) n = lcd_debug_info_len(len + offset); reg = HHI_MIPI_CNTL0; len += snprintf((buf+len), n, - "HHI_MIPI_CNTL0 [0x%04x] = 0x%08x\n", + "HHI_MIPI_CNTL0 [0x%02x] = 0x%08x\n", reg, lcd_hiu_read(reg)); n = lcd_debug_info_len(len + offset); reg = HHI_MIPI_CNTL1; len += snprintf((buf+len), n, - "HHI_MIPI_CNTL1 [0x%04x] = 0x%08x\n", + "HHI_MIPI_CNTL1 [0x%02x] = 0x%08x\n", reg, lcd_hiu_read(reg)); n = lcd_debug_info_len(len + offset); reg = HHI_MIPI_CNTL2; len += snprintf((buf+len), n, - "HHI_MIPI_CNTL2 [0x%04x] = 0x%08x\n", + "HHI_MIPI_CNTL2 [0x%02x] = 0x%08x\n", reg, lcd_hiu_read(reg)); return len; @@ -1136,7 +1235,7 @@ static int lcd_reg_print(char *buf, int offset) break; n = lcd_debug_info_len(len + offset); len += snprintf((buf+len), n, - "hiu [0x%08x] = 0x%08x\n", + "hiu [0x%02x] = 0x%08x\n", table[i], lcd_hiu_read(table[i])); i++; } @@ -1171,7 +1270,7 @@ static int lcd_reg_print(char *buf, int offset) if (table[i] == LCD_DEBUG_REG_END) break; len += snprintf((buf+len), n, - "PERIPHS_PIN_MUX [0x%08x] = 0x%08x\n", + "PERIPHS_PIN_MUX [0x%02x] = 0x%08x\n", table[i], lcd_periphs_read(table[i])); i++; } @@ -1394,6 +1493,8 @@ static void lcd_debug_clk_change(unsigned int pclk) struct lcd_config_s *pconf; unsigned int sync_duration; + vout_notifier_call_chain(VOUT_EVENT_MODE_CHANGE_PRE, + &lcd_drv->lcd_info->mode); pconf = lcd_drv->lcd_config; sync_duration = pclk / pconf->lcd_basic.h_period; sync_duration = sync_duration * 100 / pconf->lcd_basic.v_period; @@ -1564,7 +1665,7 @@ static ssize_t lcd_debug_store(struct class *class, lcd_info_print(print_buf, 0); lcd_debug_info_print(print_buf); memset(print_buf, 0, PR_BUF_MAX); - lcd_power_info_print(print_buf, 0); + lcd_power_step_info_print(print_buf, 0); lcd_debug_info_print(print_buf); kfree(print_buf); break; @@ -1616,7 +1717,7 @@ static ssize_t lcd_debug_store(struct class *class, lcd_info_print(print_buf, 0); lcd_debug_info_print(print_buf); memset(print_buf, 0, PR_BUF_MAX); - lcd_power_info_print(print_buf, 0); + lcd_power_step_info_print(print_buf, 0); lcd_debug_info_print(print_buf); memset(print_buf, 0, PR_BUF_MAX); lcd_reg_print(print_buf, 0); @@ -1959,24 +2060,21 @@ static ssize_t lcd_debug_change_store(struct class *class, break; case 'p': p2p_conf = pconf->lcd_control.p2p_config; - ret = sscanf(buf, "p2p %d %x %x %x %d %d", + ret = sscanf(buf, "p2p %x %d %x %x %d %d", &val[0], &val[1], &val[2], &val[3], &val[4], &val[5]); if (ret == 6) { - p2p_conf->channel_num = val[0]; - p2p_conf->channel_sel0 = val[1]; - p2p_conf->channel_sel1 = val[2]; - p2p_conf->clk_phase = val[3]; + p2p_conf->p2p_type = val[0]; + p2p_conf->lane_num = val[1]; + p2p_conf->channel_sel0 = val[2]; + p2p_conf->channel_sel1 = val[3]; p2p_conf->pn_swap = val[4]; p2p_conf->bit_swap = val[5]; - pr_info("change mlvds config:\n" - "channel_num=%d,\n" + pr_info("change p2p config:\n" + "p2p_type=0x%x, lane_num=%d,\n" "channel_sel0=0x%08x, channel_sel1=0x%08x,\n" - "clk_phase=0x%04x,\n" "pn_swap=%d, bit_swap=%d\n", - p2p_conf->channel_num, - p2p_conf->channel_sel0, - p2p_conf->channel_sel1, - p2p_conf->clk_phase, + p2p_conf->p2p_type, p2p_conf->lane_num, + p2p_conf->channel_sel0, p2p_conf->channel_sel1, p2p_conf->pn_swap, p2p_conf->bit_swap); lcd_debug_change_clk_change(pconf->lcd_timing.lcd_clk); pconf->change_flag = 1; @@ -2066,6 +2164,49 @@ static ssize_t lcd_debug_resume_store(struct class *class, static ssize_t lcd_debug_power_show(struct class *class, struct class_attribute *attr, char *buf) +{ + struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); + int state; + + if ((lcd_drv->lcd_status & LCD_STATUS_ON) == 0) { + state = 0; + } else { + if (lcd_drv->lcd_status & LCD_STATUS_IF_ON) + state = 1; + else + state = 0; + } + return sprintf(buf, "lcd power state: %d\n", state); +} + +static ssize_t lcd_debug_power_store(struct class *class, + struct class_attribute *attr, const char *buf, size_t count) +{ + struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); + int ret = 0; + unsigned int temp = 1; + + ret = kstrtouint(buf, 10, &temp); + if (ret) { + LCDERR("invalid data\n"); + return -EINVAL; + } + if (temp) { + mutex_lock(&lcd_drv->power_mutex); + aml_lcd_notifier_call_chain(LCD_EVENT_IF_POWER_ON, NULL); + lcd_if_enable_retry(lcd_drv->lcd_config); + mutex_unlock(&lcd_drv->power_mutex); + } else { + mutex_lock(&lcd_drv->power_mutex); + aml_lcd_notifier_call_chain(LCD_EVENT_IF_POWER_OFF, NULL); + mutex_unlock(&lcd_drv->power_mutex); + } + + return count; +} + +static ssize_t lcd_debug_power_step_show(struct class *class, + struct class_attribute *attr, char *buf) { char *print_buf; int n = 0; @@ -2074,7 +2215,7 @@ static ssize_t lcd_debug_power_show(struct class *class, if (print_buf == NULL) return sprintf(buf, "%s: buf malloc error\n", __func__); - lcd_power_info_print(print_buf, 0); + lcd_power_step_info_print(print_buf, 0); n = sprintf(buf, "%s\n", print_buf); kfree(print_buf); @@ -2082,41 +2223,63 @@ static ssize_t lcd_debug_power_show(struct class *class, return n; } -static ssize_t lcd_debug_power_store(struct class *class, +static ssize_t lcd_debug_power_step_store(struct class *class, struct class_attribute *attr, const char *buf, size_t count) { int ret = 0; - unsigned int i, delay; + unsigned int i; + unsigned int tmp[2]; struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); - struct lcd_power_ctrl_s *lcd_power; + struct lcd_power_ctrl_s *lcd_power_step; - lcd_power = lcd_drv->lcd_config->lcd_power; + lcd_power_step = lcd_drv->lcd_config->lcd_power; switch (buf[1]) { case 'n': /* on */ - ret = sscanf(buf, "on %d %d", &i, &delay); - if (ret == 2) { - if (i >= lcd_power->power_on_step_max) { + ret = sscanf(buf, "on %d %d %d", &i, &tmp[0], &tmp[1]); + if (ret == 3) { + if (i >= lcd_power_step->power_on_step_max) { + pr_info("invalid power_on step: %d, step_max: %d\n", + i, lcd_power_step->power_on_step_max); + return -EINVAL; + } + lcd_power_step->power_on_step[i].value = tmp[0]; + lcd_power_step->power_on_step[i].delay = tmp[1]; + pr_info( + "set power_on step %d value %d delay: %dms\n", + i, tmp[0], tmp[1]); + } else if (ret == 2) { + if (i >= lcd_power_step->power_on_step_max) { pr_info("invalid power_on step: %d\n", i); return -EINVAL; } - lcd_power->power_on_step[i].delay = delay; + lcd_power_step->power_on_step[i].delay = tmp[0]; pr_info("set power_on step %d delay: %dms\n", - i, delay); + i, tmp[0]); } else { pr_info("invalid data\n"); return -EINVAL; } break; case 'f': /* off */ - ret = sscanf(buf, "off %d %d", &i, &delay); - if (ret == 1) { - if (i >= lcd_power->power_off_step_max) { + ret = sscanf(buf, "off %d %d %d\n", &i, &tmp[0], &tmp[1]); + if (ret == 3) { + if (i >= lcd_power_step->power_off_step_max) { pr_info("invalid power_off step: %d\n", i); return -EINVAL; } - lcd_power->power_off_step[i].delay = delay; + lcd_power_step->power_off_step[i].value = tmp[0]; + lcd_power_step->power_off_step[i].delay = tmp[1]; + pr_info( + "set power_off step %d value %d delay: %dms\n", + i, tmp[0], tmp[1]); + } else if (ret == 2) { + if (i >= lcd_power_step->power_off_step_max) { + pr_info("invalid power_off step: %d\n", i); + return -EINVAL; + } + lcd_power_step->power_off_step[i].delay = tmp[0]; pr_info("set power_off step %d delay: %dms\n", - i, delay); + i, tmp[0]); } else { pr_info("invalid data\n"); return -EINVAL; @@ -2212,24 +2375,81 @@ static ssize_t lcd_debug_fr_policy_store(struct class *class, static ssize_t lcd_debug_ss_show(struct class *class, struct class_attribute *attr, char *buf) { - return sprintf(buf, "get lcd pll spread spectrum: %s\n", - lcd_get_spread_spectrum()); + int len; + + len = lcd_get_ss(buf); + return len; } static ssize_t lcd_debug_ss_store(struct class *class, struct class_attribute *attr, const char *buf, size_t count) { int ret = 0; - unsigned int temp = 0; + unsigned int value = 0, temp; struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); - ret = kstrtouint(buf, 10, &temp); - if (ret) { - pr_info("invalid data\n"); - return -EINVAL; + temp = lcd_drv->lcd_config->lcd_timing.ss_level; + switch (buf[0]) { + case 'l': + ret = sscanf(buf, "level %d", &value); + if (ret == 1) { + value &= 0xff; + ret = lcd_set_ss(value, 0xff, 0xff); + if (ret == 0) { + temp &= ~(0xff); + temp |= value; + lcd_drv->lcd_config->lcd_timing.ss_level = temp; + } + } else { + pr_info("invalid data\n"); + return -EINVAL; + } + break; + case 'f': + ret = sscanf(buf, "freq %d", &value); + if (ret == 1) { + value &= 0xf; + ret = lcd_set_ss(0xff, value, 0xff); + if (ret == 0) { + temp &= ~((0xf << LCD_CLK_SS_BIT_FREQ) << 8); + temp |= ((value << LCD_CLK_SS_BIT_FREQ) << 8); + lcd_drv->lcd_config->lcd_timing.ss_level = temp; + } + } else { + pr_info("invalid data\n"); + return -EINVAL; + } + break; + case 'm': + ret = sscanf(buf, "mode %d", &value); + if (ret == 1) { + value &= 0xf; + ret = lcd_set_ss(0xff, 0xff, value); + if (ret == 0) { + temp &= ~((0xf << LCD_CLK_SS_BIT_MODE) << 8); + temp |= ((value << LCD_CLK_SS_BIT_MODE) << 8); + lcd_drv->lcd_config->lcd_timing.ss_level = temp; + } + } else { + pr_info("invalid data\n"); + return -EINVAL; + } + break; + default: + ret = kstrtouint(buf, 16, &value); + if (ret) { + pr_info("invalid data\n"); + return -EINVAL; + } + value &= 0xffff; + temp = value >> 8; + ret = lcd_set_ss((value & 0xff), + ((temp >> LCD_CLK_SS_BIT_FREQ) & 0xf), + ((temp >> LCD_CLK_SS_BIT_MODE) & 0xf)); + if (ret == 0) + lcd_drv->lcd_config->lcd_timing.ss_level = value; + break; } - lcd_drv->lcd_config->lcd_timing.ss_level = temp; - lcd_set_spread_spectrum(temp); return count; } @@ -2352,9 +2572,9 @@ static ssize_t lcd_debug_mute_store(struct class *class, } static void lcd_debug_reg_write(unsigned int reg, unsigned int data, - unsigned int type) + unsigned int bus) { - switch (type) { + switch (bus) { case 0: /* vcbus */ lcd_vcbus_write(reg, data); pr_info("write vcbus [0x%04x] = 0x%08x, readback 0x%08x\n", @@ -2385,6 +2605,16 @@ static void lcd_debug_reg_write(unsigned int reg, unsigned int data, pr_info("write mipi_dsi_phy [0x%04x] = 0x%08x, readback 0x%08x\n", reg, data, dsi_phy_read(reg)); break; + case 6: /* tcon */ + lcd_tcon_reg_write(reg, data); + if (reg < TCON_TOP_BASE) { + pr_info("write tcon [0x%04x] = 0x%02x, readback 0x%02x\n", + reg, data, lcd_tcon_reg_read(reg)); + } else { + pr_info("write tcon [0x%04x] = 0x%08x, readback 0x%08x\n", + reg, data, lcd_tcon_reg_read(reg)); + } + break; default: break; } @@ -2417,6 +2647,15 @@ static void lcd_debug_reg_read(unsigned int reg, unsigned int bus) pr_info("read mipi_dsi_phy [0x%04x] = 0x%08x\n", reg, dsi_phy_read(reg)); break; + case 6: + if (reg < TCON_TOP_BASE) { + pr_info("read tcon [0x%04x] = 0x%02x\n", + reg, lcd_tcon_reg_read(reg)); + } else { + pr_info("read tcon [0x%04x] = 0x%08x\n", + reg, lcd_tcon_reg_read(reg)); + } + break; default: break; } @@ -2470,6 +2709,20 @@ static void lcd_debug_reg_dump(unsigned int reg, unsigned int num, (reg + i), dsi_phy_read(reg + i)); } break; + case 6: + pr_info("dump tcon regs:\n"); + if (reg < TCON_TOP_BASE) { + for (i = 0; i < num; i++) { + pr_info("[0x%04x] = 0x%02x\n", + (reg + i), lcd_tcon_reg_read(reg + i)); + } + } else { + for (i = 0; i < num; i++) { + pr_info("[0x%04x] = 0x%08x\n", + (reg + i), lcd_tcon_reg_read(reg + i)); + } + } + break; default: break; } @@ -2504,6 +2757,9 @@ static ssize_t lcd_debug_reg_store(struct class *class, ret = sscanf(buf, "wmp %x %x", ®32, &data32); bus = 5; } + } else if (buf[1] == 't') { + ret = sscanf(buf, "wt %x %x", ®32, &data32); + bus = 6; } if (ret == 2) { lcd_debug_reg_write(reg32, data32, bus); @@ -2533,6 +2789,9 @@ static ssize_t lcd_debug_reg_store(struct class *class, ret = sscanf(buf, "rmp %x", ®32); bus = 5; } + } else if (buf[1] == 't') { + ret = sscanf(buf, "rt %x", ®32); + bus = 6; } if (ret == 1) { lcd_debug_reg_read(reg32, bus); @@ -2562,6 +2821,9 @@ static ssize_t lcd_debug_reg_store(struct class *class, ret = sscanf(buf, "dmp %x %d", ®32, &data32); bus = 5; } + } else if (buf[1] == 't') { + ret = sscanf(buf, "dt %x %d", ®32, &data32); + bus = 6; } if (ret == 2) { lcd_debug_reg_dump(reg32, data32, bus); @@ -2725,7 +2987,7 @@ static ssize_t lcd_debug_dump_show(struct class *class, switch (lcd_debug_dump_state) { case LCD_DEBUG_DUMP_INFO: len = lcd_info_print(print_buf, 0); - lcd_power_info_print((print_buf+len), len); + lcd_power_step_info_print((print_buf+len), len); break; case LCD_DEBUG_DUMP_REG: lcd_reg_print(print_buf, 0); @@ -2806,7 +3068,10 @@ static struct class_attribute lcd_debug_class_attrs[] = { lcd_debug_enable_show, lcd_debug_enable_store), __ATTR(resume_type, 0644, lcd_debug_resume_show, lcd_debug_resume_store), - __ATTR(power, 0644, lcd_debug_power_show, lcd_debug_power_store), + __ATTR(power, 0644, lcd_debug_power_show, + lcd_debug_power_store), + __ATTR(power_step, 0644, lcd_debug_power_step_show, + lcd_debug_power_step_store), __ATTR(frame_rate, 0644, lcd_debug_frame_rate_show, lcd_debug_frame_rate_store), __ATTR(fr_policy, 0644, @@ -2927,10 +3192,11 @@ static const char *lcd_mlvds_debug_usage_str = { static const char *lcd_p2p_debug_usage_str = { "Usage:\n" -" echo > minilvds ; set minilvds config\n" +" echo > p2p ; set p2p config\n" "data format:\n" -" : minilvds 8 channels mapping in tx 10 channels\n" -" : bit[13:12]=clk01_pi_sel, bit[11:8]=pi2, bit[7:4]=pi1, bit[3:0]=pi0\n" +" : 0x0=ceds, 0x1=cmpi, 0x2=isp, 0x3=epi,\n" +" 0x10=chpi, 0x11=cspi, 0x12=usit\n" +" : 12 channels mapping\n" " : 0=normal, 1=swap p/n channels\n" " : 0=normal, 1=swap bit LSB/MSB\n" "\n" @@ -2961,37 +3227,128 @@ static const char *lcd_debug_tcon_usage_str = { static ssize_t lcd_ttl_debug_show(struct class *class, struct class_attribute *attr, char *buf) { - return sprintf(buf, "%s\n", lcd_ttl_debug_usage_str); + int len = 0; + + struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); + struct ttl_config_s *ttl_conf; + + ttl_conf = lcd_drv->lcd_config->lcd_control.ttl_config; + + len += sprintf(buf+len, + "ttl config: clk_pol=%d, de_valid=%d, hvsync_valid=%d,", + ttl_conf->clk_pol, + (ttl_conf->sync_valid >> 1) & 0x1, + (ttl_conf->sync_valid >> 0) & 0x1); + len += sprintf(buf+len, "rb_swap=%d, bit_swap=%d\n\n", + (ttl_conf->swap_ctrl >> 1) & 0x1, + (ttl_conf->swap_ctrl >> 0) & 0x1); + len += sprintf(buf+len, "%s\n", lcd_ttl_debug_usage_str); + + return len; } static ssize_t lcd_lvds_debug_show(struct class *class, struct class_attribute *attr, char *buf) { - return sprintf(buf, "%s\n", lcd_lvds_debug_usage_str); + int len = 0; + struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); + struct lvds_config_s *lvds_conf; + + lvds_conf = lcd_drv->lcd_config->lcd_control.lvds_config; + + len += sprintf(buf+len, "lvds config: repack=%d, dual_port=%d,", + lvds_conf->lvds_repack, lvds_conf->dual_port); + len += sprintf(buf+len, "pn_swap=%d, port_swap=%d, lane_reverse=%d\n\n", + lvds_conf->pn_swap, lvds_conf->port_swap, + lvds_conf->lane_reverse); + len += sprintf(buf+len, "%s\n", lcd_lvds_debug_usage_str); + + return len; } static ssize_t lcd_vx1_debug_show(struct class *class, struct class_attribute *attr, char *buf) { - return sprintf(buf, "%s\n", lcd_vbyone_debug_usage_str); + int len = 0; + struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); + struct vbyone_config_s *vx1_conf; + + vx1_conf = lcd_drv->lcd_config->lcd_control.vbyone_config; + + len += sprintf(buf+len, "vbyone config: lane_count=%d,", + vx1_conf->lane_count); + len += sprintf(buf+len, "region_num=%d, byte_mode=%d\n\n", + vx1_conf->region_num, vx1_conf->byte_mode); + len += sprintf(buf+len, "%s\n", lcd_vbyone_debug_usage_str); + + return len; } static ssize_t lcd_mipi_debug_show(struct class *class, struct class_attribute *attr, char *buf) { - return sprintf(buf, "%s\n", lcd_mipi_debug_usage_str); + int len = 0; + struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); + struct dsi_config_s *dsi_conf; + + dsi_conf = lcd_drv->lcd_config->lcd_control.mipi_config; + + len += sprintf(buf+len, "mipi_dsi config: lane_num=%d, ", + dsi_conf->lane_num); + len += sprintf(buf+len, "bit_rate_max=%dMhz, factor_numerator=%d, ", + dsi_conf->bit_rate_max, dsi_conf->factor_numerator); + len += sprintf(buf+len, + "operation_mode_init=%d, operation_mode_display=%d, ", + dsi_conf->operation_mode_init, + dsi_conf->operation_mode_display); + len += sprintf(buf+len, + "video_mode_type=%d, clk_always_hs=%d, phy_switch=%d\n\n", + dsi_conf->video_mode_type, dsi_conf->clk_always_hs, + dsi_conf->phy_switch); + len += sprintf(buf+len, "%s\n", lcd_mipi_debug_usage_str); + + return len; } static ssize_t lcd_mlvds_debug_show(struct class *class, struct class_attribute *attr, char *buf) { - return sprintf(buf, "%s\n", lcd_mlvds_debug_usage_str); + int len = 0; + struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); + struct mlvds_config_s *mlvds_conf; + + mlvds_conf = lcd_drv->lcd_config->lcd_control.mlvds_config; + + len += sprintf(buf+len, "minilvds config: channel_num=%d, ", + mlvds_conf->channel_num); + len += sprintf(buf+len, "channel_sel0=0x%08x, channel_sel1=0x%08x, ", + mlvds_conf->channel_sel0, mlvds_conf->channel_sel1); + len += sprintf(buf+len, "clk_phase=0x%04x, pn_swap=%d, bit_swap=%d\n\n", + mlvds_conf->clk_phase, + mlvds_conf->pn_swap, mlvds_conf->bit_swap); + len += sprintf(buf+len, "%s\n", lcd_mlvds_debug_usage_str); + + return len; } static ssize_t lcd_p2p_debug_show(struct class *class, struct class_attribute *attr, char *buf) { - return sprintf(buf, "%s\n", lcd_p2p_debug_usage_str); + int len = 0; + struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); + struct p2p_config_s *p2p_conf; + + p2p_conf = lcd_drv->lcd_config->lcd_control.p2p_config; + + len += sprintf(buf+len, "p2p config: p2p_type=0x%x, lane_num=%d, ", + p2p_conf->p2p_type, p2p_conf->lane_num); + len += sprintf(buf+len, "channel_sel0=0x%08x, channel_sel1=0x%08x, ", + p2p_conf->channel_sel0, p2p_conf->channel_sel1); + len += sprintf(buf+len, "pn_swap=%d, bit_swap=%d\n\n", + p2p_conf->pn_swap, p2p_conf->bit_swap); + len += sprintf(buf+len, "%s\n", lcd_p2p_debug_usage_str); + + return len; } static ssize_t lcd_tcon_debug_show(struct class *class, @@ -3013,7 +3370,7 @@ static ssize_t lcd_ttl_debug_store(struct class *class, &temp[0], &temp[1], &temp[2], &temp[3], &temp[4]); if (ret == 5) { pr_info("set ttl config:\n" - "clk_pol=%d, de_valid=%d, de_valid=%d\n" + "clk_pol=%d, de_valid=%d, hvsync_valid=%d\n" "rb_swap=%d, bit_swap=%d\n", temp[0], temp[1], temp[2], temp[3], temp[4]); ttl_conf->clk_pol = temp[0]; @@ -3235,20 +3592,17 @@ static ssize_t lcd_p2p_debug_store(struct class *class, struct p2p_config_s *p2p_conf; p2p_conf = lcd_drv->lcd_config->lcd_control.p2p_config; - ret = sscanf(buf, "%d %x %x %x %d %d", - &p2p_conf->channel_num, + ret = sscanf(buf, "%x %d %x %x %d %d", + &p2p_conf->p2p_type, &p2p_conf->lane_num, &p2p_conf->channel_sel0, &p2p_conf->channel_sel1, - &p2p_conf->clk_phase, &p2p_conf->pn_swap, &p2p_conf->bit_swap); if (ret == 6) { - pr_info("set minilvds config:\n" - "channel_num=%d,\n" + pr_info("set p2p config:\n" + "p2p_type=0x%x, lane_num=%d,\n" "channel_sel0=0x%08x, channel_sel1=0x%08x,\n" - "clk_phase=0x%04x,\n" "pn_swap=%d, bit_swap=%d\n", - p2p_conf->channel_num, + p2p_conf->p2p_type, p2p_conf->lane_num, p2p_conf->channel_sel0, p2p_conf->channel_sel1, - p2p_conf->clk_phase, p2p_conf->pn_swap, p2p_conf->bit_swap); lcd_debug_config_update(); } else { @@ -3263,61 +3617,32 @@ static void lcd_phy_config_update(unsigned int *para, int cnt) { struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); struct lcd_config_s *pconf; - struct lvds_config_s *lvdsconf; - int type; - unsigned int data32, vswing, preem, ext_pullup; - unsigned int rinner_table[] = {0xa, 0xa, 0x6, 0x4}; + struct lvds_config_s *lvds_conf; pconf = lcd_drv->lcd_config; - type = pconf->lcd_basic.lcd_type; - switch (type) { + switch (pconf->lcd_basic.lcd_type) { case LCD_LVDS: - lvdsconf = pconf->lcd_control.lvds_config; + lvds_conf = pconf->lcd_control.lvds_config; if (cnt == 4) { - if ((para[0] > 7) || (para[1] > 7) || - (para[2] > 3) || (para[3] > 7)) { - LCDERR("%s: wrong value:\n", __func__); - pr_info("vswing=%d, preem=%d\n", - para[0], para[1]); - pr_info("clk vswing=%d, preem=%d\n", - para[2], para[3]); - return; - } + lvds_conf->phy_vswing = para[0]; + lvds_conf->phy_preem = para[1]; + lvds_conf->phy_clk_vswing = para[2]; + lvds_conf->phy_clk_preem = para[3]; - lvdsconf->phy_vswing = para[0]; - lvdsconf->phy_preem = para[1]; - lvdsconf->phy_clk_vswing = para[2]; - lvdsconf->phy_clk_preem = para[3]; - - data32 = lcd_hiu_read(HHI_DIF_CSI_PHY_CNTL1); - data32 &= ~((0x7 << 26) | (0x7 << 0)); - data32 |= ((para[0] << 26) | (para[1] << 0)); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL1, data32); - data32 = lcd_hiu_read(HHI_DIF_CSI_PHY_CNTL3); - data32 &= ~((0x3 << 8) | (0x7 << 5)); - data32 |= ((para[2] << 8) | (para[3] << 5)); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL3, data32); + if (lcd_drv->lcd_status & LCD_STATUS_IF_ON) + lcd_lvds_phy_set(pconf, 1); LCDPR("%s:\n", __func__); pr_info("vswing=0x%x, preemphasis=0x%x\n", para[0], para[1]); - pr_info("clk_vswing=0x%x, clk_preem=0x%x\n", + pr_info("clk_vswing=0x%x, clk_preem=0x%x\n", para[2], para[3]); } else if (cnt == 2) { - if ((para[0] > 7) || (para[1] > 7)) { - LCDERR("%s: wrong value:\n", __func__); - pr_info("vswing=%d, preem=%d\n", - para[0], para[1]); - return; - } + lvds_conf->phy_vswing = para[0]; + lvds_conf->phy_preem = para[1]; - lvdsconf->phy_vswing = para[0]; - lvdsconf->phy_preem = para[1]; - - data32 = lcd_hiu_read(HHI_DIF_CSI_PHY_CNTL1); - data32 &= ~((0x7 << 26) | (0x7 << 0)); - data32 |= ((para[0] << 26) | (para[1] << 0)); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL1, data32); + if (lcd_drv->lcd_status & LCD_STATUS_IF_ON) + lcd_lvds_phy_set(pconf, 1); LCDPR("%s: vswing=0x%x, preemphasis=0x%x\n", __func__, para[0], para[1]); @@ -3328,33 +3653,11 @@ static void lcd_phy_config_update(unsigned int *para, int cnt) break; case LCD_VBYONE: if (cnt >= 2) { - ext_pullup = (para[0] >> 4) & 0x3; - vswing = para[0] & 0xf; - preem = para[1]; - if ((vswing > 7) || (preem > 7)) { - LCDERR("%s: wrong value:\n", __func__); - pr_info("vswing=%d, preemphasis=%d\n", - vswing, preem); - return; - } - pconf->lcd_control.vbyone_config->phy_vswing = para[0]; pconf->lcd_control.vbyone_config->phy_preem = para[1]; - data32 = lcd_hiu_read(HHI_DIF_CSI_PHY_CNTL1); - data32 &= ~((0x7 << 3) | (1 << 10) | - (1 << 15) | (1 << 16)); - data32 |= (vswing << 3); - if (ext_pullup) - data32 |= ((1 << 10) | (1 << 16)); - else - data32 |= (1 << 15); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL1, data32); - data32 = lcd_hiu_read(HHI_DIF_CSI_PHY_CNTL2); - data32 &= ~((0x7 << 20) | (0xf << 8)); - data32 |= ((preem << 20) | - (rinner_table[ext_pullup] << 8)); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL2, data32); + if (lcd_drv->lcd_status & LCD_STATUS_IF_ON) + lcd_vbyone_phy_set(pconf, 1); LCDPR("%s: vswing=0x%x, preemphasis=0x%x\n", __func__, para[0], para[1]); @@ -3365,34 +3668,11 @@ static void lcd_phy_config_update(unsigned int *para, int cnt) break; case LCD_MLVDS: if (cnt >= 2) { - if ((para[0] > 7) || (para[1] > 3)) { - LCDERR("%s: wrong value:\n", __func__); - pr_info("vswing=%d, preemphasis=%d\n", - para[0], para[1]); - return; - } - pconf->lcd_control.mlvds_config->phy_vswing = para[0]; pconf->lcd_control.mlvds_config->phy_preem = para[1]; - data32 = lcd_hiu_read(HHI_DIF_CSI_PHY_CNTL1); - data32 &= ~((0x7 << 3) | (0x7 << 0) | (0x3 << 23)); - data32 |= ((para[0] << 3) | (para[0] << 0) | - (para[1] << 23)); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL1, data32); - data32 = lcd_hiu_read(HHI_DIF_CSI_PHY_CNTL2); - data32 &= ~((0x3 << 14) | (0x3 << 12) | - (0x3 << 26) | (0x3 << 24)); - data32 |= ((para[1] << 14) | (para[1] << 12) | - (para[1] << 26) | (para[1] << 24)); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL2, data32); - data32 = lcd_hiu_read(HHI_DIF_CSI_PHY_CNTL3); - data32 &= ~((0x3 << 6) | (0x3 << 4) | - (0x3 << 2) | (0x3 << 0) | (0x3 << 30)); - data32 |= ((para[1] << 6) | (para[1] << 4) | - (para[1] << 2) | (para[1] << 0) | - (para[1] << 30)); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL3, data32); + if (lcd_drv->lcd_status & LCD_STATUS_IF_ON) + lcd_mlvds_phy_set(pconf, 1); LCDPR("%s: vswing=0x%x, preemphasis=0x%x\n", __func__, para[0], para[1]); @@ -3403,34 +3683,11 @@ static void lcd_phy_config_update(unsigned int *para, int cnt) break; case LCD_P2P: if (cnt >= 2) { - if ((para[0] > 7) || (para[1] > 3)) { - LCDERR("%s: wrong value:\n", __func__); - pr_info("vswing=%d, preemphasis=%d\n", - para[0], para[1]); - return; - } - pconf->lcd_control.p2p_config->phy_vswing = para[0]; pconf->lcd_control.p2p_config->phy_preem = para[1]; - data32 = lcd_hiu_read(HHI_DIF_CSI_PHY_CNTL1); - data32 &= ~((0x7 << 3) | (0x7 << 0) | (0x3 << 23)); - data32 |= ((para[0] << 3) | (para[0] << 0) | - (para[1] << 23)); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL1, data32); - data32 = lcd_hiu_read(HHI_DIF_CSI_PHY_CNTL2); - data32 &= ~((0x3 << 14) | (0x3 << 12) | - (0x3 << 26) | (0x3 << 24)); - data32 |= ((para[1] << 14) | (para[1] << 12) | - (para[1] << 26) | (para[1] << 24)); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL2, data32); - data32 = lcd_hiu_read(HHI_DIF_CSI_PHY_CNTL3); - data32 &= ~((0x3 << 6) | (0x3 << 4) | - (0x3 << 2) | (0x3 << 0) | (0x3 << 30)); - data32 |= ((para[1] << 6) | (para[1] << 4) | - (para[1] << 2) | (para[1] << 0) | - (para[1] << 30)); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL3, data32); + if (lcd_drv->lcd_status & LCD_STATUS_IF_ON) + lcd_p2p_phy_set(pconf, 1); LCDPR("%s: vswing=0x%x, preemphasis=0x%x\n", __func__, para[0], para[1]); @@ -3441,7 +3698,8 @@ static void lcd_phy_config_update(unsigned int *para, int cnt) break; default: LCDERR("%s: not support lcd_type: %s\n", - __func__, lcd_type_type_to_str(type)); + __func__, + lcd_type_type_to_str(pconf->lcd_basic.lcd_type)); break; } } @@ -3462,31 +3720,30 @@ static ssize_t lcd_phy_debug_show(struct class *class, preem = pconf->lcd_control.lvds_config->phy_preem; clk_vswing = pconf->lcd_control.lvds_config->phy_clk_vswing; clk_preem = pconf->lcd_control.lvds_config->phy_clk_preem; - len += sprintf(buf+len, "%s:\n", __func__); + len += sprintf(buf+len, "vswing=0x%x, preemphasis=0x%x\n", vswing, preem); - len += sprintf(buf+len, - "clk_vswing=0x%x, clk_preemphasis=0x%x\n", - clk_vswing, clk_preem); + if (lcd_drv->data->chip_type <= LCD_CHIP_TXLX) { + len += sprintf(buf+len, + "clk_vswing=0x%x, clk_preemphasis=0x%x\n", + clk_vswing, clk_preem); + } break; case LCD_VBYONE: vswing = pconf->lcd_control.vbyone_config->phy_vswing; preem = pconf->lcd_control.vbyone_config->phy_preem; - len += sprintf(buf+len, "%s:\n", __func__); len += sprintf(buf+len, "vswing=0x%x, preemphasis=0x%x\n", vswing, preem); break; case LCD_MLVDS: vswing = pconf->lcd_control.mlvds_config->phy_vswing; preem = pconf->lcd_control.mlvds_config->phy_preem; - len += sprintf(buf+len, "%s:\n", __func__); len += sprintf(buf+len, "vswing=0x%x, preemphasis=0x%x\n", vswing, preem); break; case LCD_P2P: vswing = pconf->lcd_control.p2p_config->phy_vswing; preem = pconf->lcd_control.p2p_config->phy_preem; - len += sprintf(buf+len, "%s:\n", __func__); len += sprintf(buf+len, "vswing=0x%x, preemphasis=0x%x\n", vswing, preem); break; @@ -3629,6 +3886,61 @@ static ssize_t lcd_tcon_debug_store(struct class *class, lcd_tcon_reg_save(parm[2], size); else pr_info("invalid save path\n"); + } else if (strcmp(parm[1], "rb") == 0) { + if (parm[2] != NULL) { + ret = kstrtouint(parm[2], 16, &temp); + if (ret) { + pr_info("invalid parameters\n"); + goto lcd_tcon_debug_store_err; + } + pr_info("read tcon byte [0x%04x] = 0x%02x\n", + temp, lcd_tcon_read_byte(temp)); + } + } else if (strcmp(parm[1], "wb") == 0) { + if (parm[3] != NULL) { + ret = kstrtouint(parm[2], 16, &temp); + if (ret) { + pr_info("invalid parameters\n"); + goto lcd_tcon_debug_store_err; + } + ret = kstrtouint(parm[3], 16, &val); + if (ret) { + pr_info("invalid parameters\n"); + goto lcd_tcon_debug_store_err; + } + data = (unsigned char)val; + lcd_tcon_write_byte(temp, data); + pr_info( + "write tcon byte [0x%04x] = 0x%02x, readback 0x%02x\n", + temp, data, lcd_tcon_read_byte(temp)); + } + } else if (strcmp(parm[1], "r") == 0) { + if (parm[2] != NULL) { + ret = kstrtouint(parm[2], 16, &temp); + if (ret) { + pr_info("invalid parameters\n"); + goto lcd_tcon_debug_store_err; + } + pr_info("read tcon [0x%04x] = 0x%08x\n", + temp, lcd_tcon_read(temp)); + } + } else if (strcmp(parm[1], "w") == 0) { + if (parm[3] != NULL) { + ret = kstrtouint(parm[2], 16, &temp); + if (ret) { + pr_info("invalid parameters\n"); + goto lcd_tcon_debug_store_err; + } + ret = kstrtouint(parm[3], 16, &val); + if (ret) { + pr_info("invalid parameters\n"); + goto lcd_tcon_debug_store_err; + } + lcd_tcon_write(temp, val); + pr_info( + "write tcon [0x%04x] = 0x%08x, readback 0x%08x\n", + temp, val, lcd_tcon_read(temp)); + } } } else if (strcmp(parm[0], "table") == 0) { if (parm[1] == NULL) { @@ -4184,10 +4496,20 @@ int lcd_debug_probe(void) switch (lcd_drv->data->chip_type) { case LCD_CHIP_TL1: + case LCD_CHIP_TM2: lcd_debug_info_reg = &lcd_debug_info_reg_tl1; + lcd_debug_info_if_lvds.reg_dump_phy = + lcd_reg_print_phy_analog_tl1; + lcd_debug_info_if_vbyone.reg_dump_phy = + lcd_reg_print_phy_analog_tl1; + lcd_debug_info_if_mlvds.reg_dump_phy = + lcd_reg_print_phy_analog_tl1; + lcd_debug_info_if_p2p.reg_dump_phy = + lcd_reg_print_phy_analog_tl1; break; case LCD_CHIP_G12A: case LCD_CHIP_G12B: + case LCD_CHIP_SM1: if (lcd_drv->lcd_clk_path) lcd_debug_info_reg = &lcd_debug_info_reg_g12a_clk_path1; else diff --git a/drivers/amlogic/media/vout/lcd/lcd_debug.h b/drivers/amlogic/media/vout/lcd/lcd_debug.h index 8c72d7b00ea3..af5bbf6612f3 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_debug.h +++ b/drivers/amlogic/media/vout/lcd/lcd_debug.h @@ -178,9 +178,9 @@ static unsigned int lcd_reg_dump_pinmux_txlx[] = { }; static unsigned int lcd_reg_dump_pinmux_tl1[] = { - PERIPHS_PIN_MUX_7, - PERIPHS_PIN_MUX_8, - PERIPHS_PIN_MUX_9, + PERIPHS_PIN_MUX_7_TL1, + PERIPHS_PIN_MUX_8_TL1, + PERIPHS_PIN_MUX_9_TL1, LCD_DEBUG_REG_END, }; diff --git a/drivers/amlogic/media/vout/lcd/lcd_phy_config.c b/drivers/amlogic/media/vout/lcd/lcd_phy_config.c new file mode 100644 index 000000000000..dd307f6ace62 --- /dev/null +++ b/drivers/amlogic/media/vout/lcd/lcd_phy_config.c @@ -0,0 +1,560 @@ +/* + * drivers/amlogic/media/vout/lcd/lcd_phy_config.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 +#include +#include +#include +#include +#include +#include +#include +#include +#include "lcd_reg.h" +#include "lcd_phy_config.h" +#include "lcd_common.h" + +static unsigned int lcd_lvds_channel_on_value(struct lcd_config_s *pconf) +{ + unsigned int channel_on = 0; + + if (pconf->lcd_control.lvds_config->dual_port == 0) { + if (pconf->lcd_control.lvds_config->lane_reverse == 0) { + switch (pconf->lcd_basic.lcd_bits) { + case 6: + channel_on = 0xf; + break; + case 8: + channel_on = 0x1f; + break; + case 10: + default: + channel_on = 0x3f; + break; + } + } else { + switch (pconf->lcd_basic.lcd_bits) { + case 6: + channel_on = 0x3c; + break; + case 8: + channel_on = 0x3e; + break; + case 10: + default: + channel_on = 0x3f; + break; + } + } + if (pconf->lcd_control.lvds_config->port_swap == 1) + channel_on = (channel_on << 6); /* use channel B */ + } else { + if (pconf->lcd_control.lvds_config->lane_reverse == 0) { + switch (pconf->lcd_basic.lcd_bits) { + case 6: + channel_on = 0x3cf; + break; + case 8: + channel_on = 0x7df; + break; + case 10: + default: + channel_on = 0xfff; + break; + } + } else { + switch (pconf->lcd_basic.lcd_bits) { + case 6: + channel_on = 0xf3c; + break; + case 8: + channel_on = 0xfbe; + break; + case 10: + default: + channel_on = 0xfff; + break; + } + } + } + return channel_on; +} + +void lcd_lvds_phy_set(struct lcd_config_s *pconf, int status) +{ + unsigned int vswing, preem, clk_vswing, clk_preem, channel_on; + unsigned int data32, size; + struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); + struct lvds_config_s *lvds_conf; + + if (lcd_debug_print_flag) + LCDPR("%s: %d\n", __func__, status); + + lvds_conf = pconf->lcd_control.lvds_config; + if (status) { + vswing = lvds_conf->phy_vswing & 0xf; + preem = lvds_conf->phy_preem & 0xf; + clk_vswing = lvds_conf->phy_clk_vswing & 0xf; + clk_preem = lvds_conf->phy_clk_preem & 0xf; + if (lcd_debug_print_flag) + LCDPR("vswing=0x%x, prrem=0x%x\n", vswing, preem); + + switch (lcd_drv->data->chip_type) { + case LCD_CHIP_TL1: + size = sizeof(lvds_vx1_p2p_phy_preem_tl1) / + sizeof(unsigned int); + if (preem >= size) { + LCDERR("%s: invalid preem=0x%x, use default\n", + __func__, preem); + preem = 0; + } + data32 = lvds_vx1_p2p_phy_preem_tl1[preem]; + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL14, + 0xff2027e0 | vswing); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL15, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL16, 0x80000000); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL8, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL1, data32); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL9, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL2, data32); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL10, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL3, data32); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL11, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL4, data32); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL12, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL6, data32); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL13, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL7, data32); + break; + default: + if (vswing > 7) { + LCDERR("%s: invalid vswing=0x%x, use default\n", + __func__, vswing); + vswing = LVDS_PHY_VSWING_DFT; + } + if (preem > 7) { + LCDERR("%s: invalid preem=0x%x, use default\n", + __func__, preem); + preem = LVDS_PHY_PREEM_DFT; + } + if (clk_vswing > 3) { + LCDERR( + "%s: invalid clk_vswing=0x%x, use default\n", + __func__, clk_vswing); + clk_vswing = LVDS_PHY_CLK_VSWING_DFT; + } + if (clk_preem > 7) { + LCDERR( + "%s: invalid clk_preem=0x%x, use default\n", + __func__, clk_preem); + clk_preem = LVDS_PHY_CLK_PREEM_DFT; + } + channel_on = lcd_lvds_channel_on_value(pconf); + + data32 = LVDS_PHY_CNTL1_G9TV | + (vswing << 26) | (preem << 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL1, data32); + data32 = LVDS_PHY_CNTL2_G9TV; + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL2, data32); + data32 = LVDS_PHY_CNTL3_G9TV | + (channel_on << 16) | + (clk_vswing << 8) | + (clk_preem << 5); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL3, data32); + break; + } + } else { + switch (lcd_drv->data->chip_type) { + case LCD_CHIP_TL1: + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL14, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL15, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL16, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL8, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL1, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL9, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL2, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL10, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL3, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL11, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL4, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL12, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL6, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL13, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL7, 0); + break; + default: + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL1, 0x0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL2, 0x0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL3, 0x0); + break; + } + } +} + +void lcd_vbyone_phy_set(struct lcd_config_s *pconf, int status) +{ + unsigned int vswing, preem, ext_pullup; + unsigned int data32, size; + unsigned int rinner_table[] = {0xa, 0xa, 0x6, 0x4}; + struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); + struct vbyone_config_s *vbyone_conf; + + if (lcd_debug_print_flag) + LCDPR("%s: %d\n", __func__, status); + + vbyone_conf = pconf->lcd_control.vbyone_config; + if (status) { + ext_pullup = (vbyone_conf->phy_vswing >> 4) & 0x3; + vswing = vbyone_conf->phy_vswing & 0xf; + preem = vbyone_conf->phy_preem & 0xf; + if (lcd_debug_print_flag) { + LCDPR("vswing=0x%x, prrem=0x%x\n", + vbyone_conf->phy_vswing, preem); + } + + switch (lcd_drv->data->chip_type) { + case LCD_CHIP_TL1: + size = sizeof(lvds_vx1_p2p_phy_preem_tl1) / + sizeof(unsigned int); + if (preem >= size) { + LCDERR("%s: invalid preem=0x%x, use default\n", + __func__, preem); + preem = 0x1; + } + data32 = lvds_vx1_p2p_phy_preem_tl1[preem]; + if (ext_pullup) { + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL14, + 0xff2027e0 | vswing); + } else { + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL14, + 0xf02027a0 | vswing); + } + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL15, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL16, 0x80000000); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL8, 0x40004); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL1, data32); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL9, 0x40004); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL2, data32); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL10, 0x40004); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL3, data32); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL11, 0x40004); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL4, data32); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL12, 0x40004); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL6, data32); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL13, 0x40004); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL7, data32); + break; + default: + if (vswing > 7) { + LCDERR("%s: invalid vswing=0x%x, use default\n", + __func__, vswing); + vswing = VX1_PHY_VSWING_DFT; + } + if (preem > 7) { + LCDERR("%s: invalid preem=0x%x, use default\n", + __func__, preem); + preem = VX1_PHY_PREEM_DFT; + } + if (ext_pullup) { + data32 = VX1_PHY_CNTL1_G9TV_PULLUP | + (vswing << 3); + } else { + data32 = VX1_PHY_CNTL1_G9TV | (vswing << 3); + } + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL1, data32); + data32 = VX1_PHY_CNTL2_G9TV | (preem << 20) | + (rinner_table[ext_pullup] << 8); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL2, data32); + data32 = VX1_PHY_CNTL3_G9TV; + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL3, data32); + break; + } + } else { + switch (lcd_drv->data->chip_type) { + case LCD_CHIP_TL1: + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL14, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL15, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL16, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL8, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL1, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL9, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL2, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL10, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL3, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL11, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL4, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL12, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL6, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL13, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL7, 0); + break; + default: + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL1, 0x0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL2, 0x0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL3, 0x0); + break; + } + } +} + +void lcd_mlvds_phy_set(struct lcd_config_s *pconf, int status) +{ + unsigned int vswing, preem; + unsigned int data32, size, cntl16; + struct mlvds_config_s *mlvds_conf; + + if (lcd_debug_print_flag) + LCDPR("%s: %d\n", __func__, status); + + mlvds_conf = pconf->lcd_control.mlvds_config; + if (status) { + vswing = mlvds_conf->phy_vswing & 0xf; + preem = mlvds_conf->phy_preem & 0xf; + if (lcd_debug_print_flag) + LCDPR("vswing=0x%x, prrem=0x%x\n", vswing, preem); + + size = sizeof(lvds_vx1_p2p_phy_preem_tl1) / + sizeof(unsigned int); + if (preem >= size) { + LCDERR("%s: invalid preem=0x%x, use default\n", + __func__, preem); + preem = 0; + } + data32 = lvds_vx1_p2p_phy_preem_tl1[preem]; + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL14, + 0xff2027e0 | vswing); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL15, 0); + cntl16 = (mlvds_conf->pi_clk_sel << 12); + cntl16 |= 0x80000000; + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL16, cntl16); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL8, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL1, data32); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL9, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL2, data32); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL10, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL3, data32); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL11, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL4, data32); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL12, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL6, data32); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL13, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL7, data32); + } else { + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL14, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL15, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL16, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL8, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL1, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL9, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL2, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL10, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL3, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL11, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL4, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL12, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL6, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL13, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL7, 0); + } +} + +void lcd_p2p_phy_set(struct lcd_config_s *pconf, int status) +{ + unsigned int vswing, preem; + unsigned int data32, size, cntl16; + struct p2p_config_s *p2p_conf; + + if (lcd_debug_print_flag) + LCDPR("%s: %d\n", __func__, status); + + p2p_conf = pconf->lcd_control.p2p_config; + if (status) { + vswing = p2p_conf->phy_vswing & 0xf; + preem = p2p_conf->phy_preem & 0xf; + if (lcd_debug_print_flag) + LCDPR("vswing=0x%x, prrem=0x%x\n", vswing, preem); + + switch (p2p_conf->p2p_type) { + case P2P_CEDS: + case P2P_CMPI: + case P2P_ISP: + case P2P_EPI: + size = sizeof(lvds_vx1_p2p_phy_preem_tl1) / + sizeof(unsigned int); + if (preem >= size) { + LCDERR("%s: invalid preem=0x%x, use default\n", + __func__, preem); + preem = 0x1; + } + data32 = lvds_vx1_p2p_phy_preem_tl1[preem]; + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL14, + 0xff2027a0 | vswing); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL15, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL16, 0x80000000); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL8, 0x40004); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL1, data32); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL9, 0x40004); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL2, data32); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL10, 0x40004); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL3, data32); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL11, 0x40004); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL4, data32); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL12, 0x40004); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL6, data32); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL13, 0x40004); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL7, data32); + break; + case P2P_CHPI: /* low common mode */ + case P2P_CSPI: + case P2P_USIT: + size = sizeof(p2p_low_common_phy_preem_tl1) / + sizeof(unsigned int); + if (preem >= size) { + LCDERR("%s: invalid preem=0x%x, use default\n", + __func__, preem); + preem = 0x1; + } + data32 = p2p_low_common_phy_preem_tl1[preem]; + cntl16 = 0x80000000; + if (p2p_conf->p2p_type == P2P_CHPI) { + /* weakly pull down */ + data32 &= ~((1 << 19) | (1 << 3)); + } + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL14, 0xfe60027f); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL15, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL16, cntl16); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL8, 0x40004); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL1, data32); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL9, 0x40004); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL2, data32); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL10, 0x40004); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL3, data32); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL11, 0x40004); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL4, data32); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL12, 0x40004); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL6, data32); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL13, 0x40004); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL7, data32); + break; + default: + LCDERR("%s: invalid p2p_type %d\n", + __func__, p2p_conf->p2p_type); + break; + } + } else { + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL14, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL15, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL16, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL8, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL1, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL9, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL2, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL10, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL3, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL11, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL4, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL12, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL6, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL13, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL7, 0); + } +} + +void lcd_mipi_phy_set(struct lcd_config_s *pconf, int status) +{ + unsigned int phy_reg, phy_bit, phy_width; + unsigned int lane_cnt; + struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); + + if (status) { + switch (lcd_drv->data->chip_type) { + case LCD_CHIP_G12A: + case LCD_CHIP_G12B: + /* HHI_MIPI_CNTL0 */ + /* DIF_REF_CTL1:31-16bit, DIF_REF_CTL0:15-0bit */ + lcd_hiu_write(HHI_MIPI_CNTL0, + (0xa487 << 16) | (0x8 << 0)); + + /* HHI_MIPI_CNTL1 */ + /* DIF_REF_CTL2:15-0bit; bandgap bit16 */ + lcd_hiu_write(HHI_MIPI_CNTL1, + (0x1 << 16) | (0x002e << 0)); + + /* HHI_MIPI_CNTL2 */ + /* DIF_TX_CTL1:31-16bit, DIF_TX_CTL0:15-0bit */ + lcd_hiu_write(HHI_MIPI_CNTL2, + (0x2680 << 16) | (0x45a << 0)); + break; + default: /* LCD_CHIP_AXG */ + /* HHI_MIPI_CNTL0 */ + /* DIF_REF_CTL1:31-16bit, DIF_REF_CTL0:15-0bit */ + lcd_hiu_setb(HHI_MIPI_CNTL0, 0x1b8, 16, 10); + lcd_hiu_setb(HHI_MIPI_CNTL0, 1, 26, 1); /* bandgap */ + lcd_hiu_setb(HHI_MIPI_CNTL0, 1, 29, 1); /* current */ + lcd_hiu_setb(HHI_MIPI_CNTL0, 1, 31, 1); + lcd_hiu_setb(HHI_MIPI_CNTL0, 0x8, 0, 16); + + /* HHI_MIPI_CNTL1 */ + /* DIF_REF_CTL2:15-0bit */ + lcd_hiu_write(HHI_MIPI_CNTL1, (0x001e << 0)); + + /* HHI_MIPI_CNTL2 */ + /* DIF_TX_CTL1:31-16bit, DIF_TX_CTL0:15-0bit */ + lcd_hiu_write(HHI_MIPI_CNTL2, + (0x26e0 << 16) | (0x459 << 0)); + break; + } + + phy_reg = HHI_MIPI_CNTL2; + phy_bit = MIPI_PHY_LANE_BIT; + phy_width = MIPI_PHY_LANE_WIDTH; + switch (pconf->lcd_control.mipi_config->lane_num) { + case 1: + lane_cnt = DSI_LANE_COUNT_1; + break; + case 2: + lane_cnt = DSI_LANE_COUNT_2; + break; + case 3: + lane_cnt = DSI_LANE_COUNT_3; + break; + case 4: + lane_cnt = DSI_LANE_COUNT_4; + break; + default: + lane_cnt = 0; + break; + } + lcd_hiu_setb(phy_reg, lane_cnt, phy_bit, phy_width); + } else { + switch (lcd_drv->data->chip_type) { + case LCD_CHIP_G12A: + case LCD_CHIP_G12B: + lcd_hiu_write(HHI_MIPI_CNTL0, 0); + lcd_hiu_write(HHI_MIPI_CNTL1, 0); + lcd_hiu_write(HHI_MIPI_CNTL2, 0); + break; + default:/* LCD_CHIP_AXG */ + lcd_hiu_setb(HHI_MIPI_CNTL0, 0, 16, 10); + lcd_hiu_setb(HHI_MIPI_CNTL0, 0, 31, 1); + lcd_hiu_setb(HHI_MIPI_CNTL0, 0, 0, 16); + lcd_hiu_write(HHI_MIPI_CNTL1, 0x6); + lcd_hiu_write(HHI_MIPI_CNTL2, 0x00200000); + break; + } + } +} diff --git a/drivers/amlogic/media/vout/lcd/lcd_phy_config.h b/drivers/amlogic/media/vout/lcd/lcd_phy_config.h new file mode 100644 index 000000000000..3ed875e5c38b --- /dev/null +++ b/drivers/amlogic/media/vout/lcd/lcd_phy_config.h @@ -0,0 +1,87 @@ +/* + * drivers/amlogic/media/vout/lcd/lcd_phy_config.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 __AML_LCD_PHY_CONFIG_H__ +#define __AML_LCD_PHY_CONFIG_H__ + +/* -------------------------- */ +/* lvsd phy parameters define */ +/* -------------------------- */ +#define LVDS_PHY_CNTL1_G9TV 0x606cca80 +#define LVDS_PHY_CNTL2_G9TV 0x0000006c +#define LVDS_PHY_CNTL3_G9TV 0x00000800 + +#define LVDS_PHY_CNTL1_TXHD 0x6c60ca80 +#define LVDS_PHY_CNTL2_TXHD 0x00000070 +#define LVDS_PHY_CNTL3_TXHD 0x03ff0c00 +/* -------------------------- */ + +/* -------------------------- */ +/* vbyone phy parameters define */ +/* -------------------------- */ +#define VX1_PHY_CNTL1_G9TV 0x6e0ec900 +#define VX1_PHY_CNTL1_G9TV_PULLUP 0x6e0f4d00 +#define VX1_PHY_CNTL2_G9TV 0x0000007c +#define VX1_PHY_CNTL3_G9TV 0x00ff0800 +/* -------------------------- */ + +/* -------------------------- */ +/* minilvds phy parameters define */ +/* -------------------------- */ +#define MLVDS_PHY_CNTL1_TXHD 0x6c60ca80 +#define MLVDS_PHY_CNTL2_TXHD 0x00000070 +#define MLVDS_PHY_CNTL3_TXHD 0x03ff0c00 +/* -------------------------- */ + +/* ******** MIPI_DSI_PHY ******** */ +/* bit[15:11] */ +#define MIPI_PHY_LANE_BIT 11 +#define MIPI_PHY_LANE_WIDTH 5 + +/* MIPI-DSI */ +#define DSI_LANE_0 (1 << 4) +#define DSI_LANE_1 (1 << 3) +#define DSI_LANE_CLK (1 << 2) +#define DSI_LANE_2 (1 << 1) +#define DSI_LANE_3 (1 << 0) +#define DSI_LANE_COUNT_1 (DSI_LANE_CLK | DSI_LANE_0) +#define DSI_LANE_COUNT_2 (DSI_LANE_CLK | DSI_LANE_0 | DSI_LANE_1) +#define DSI_LANE_COUNT_3 (DSI_LANE_CLK | DSI_LANE_0 |\ + DSI_LANE_1 | DSI_LANE_2) +#define DSI_LANE_COUNT_4 (DSI_LANE_CLK | DSI_LANE_0 |\ + DSI_LANE_1 | DSI_LANE_2 | DSI_LANE_3) + +static unsigned int lvds_vx1_p2p_phy_preem_tl1[] = { + 0x06020602, + 0x26022602, + 0x46024602, + 0x66026602, + 0x86028602, + 0xa602a602, + 0xf602f602, +}; + +static unsigned int p2p_low_common_phy_preem_tl1[] = { + 0x070b070b, + 0x170b170b, + 0x370b370b, + 0x770b770b, + 0xf70bf70b, + 0xff0bff0b, +}; + +#endif diff --git a/drivers/amlogic/media/vout/lcd/lcd_reg.c b/drivers/amlogic/media/vout/lcd/lcd_reg.c index 690bc666d051..2824b04914b0 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_reg.c +++ b/drivers/amlogic/media/vout/lcd/lcd_reg.c @@ -195,7 +195,7 @@ static inline void __iomem *check_lcd_tcon_reg(unsigned int _reg) reg_offset = LCD_REG_OFFSET(_reg); if (reg_offset >= lcd_reg_map[reg_bus].size) { - LCDERR("invalid dsi_phy reg offset: 0x%04x\n", _reg); + LCDERR("invalid tcon reg offset: 0x%04x\n", _reg); return NULL; } p = lcd_reg_map[reg_bus].p + reg_offset; @@ -214,7 +214,7 @@ static inline void __iomem *check_lcd_tcon_reg_byte(unsigned int _reg) reg_offset = LCD_REG_OFFSET_BYTE(_reg); if (reg_offset >= lcd_reg_map[reg_bus].size) { - LCDERR("invalid dsi_phy reg offset: 0x%04x\n", _reg); + LCDERR("invalid tcon reg offset: 0x%04x\n", _reg); return NULL; } p = lcd_reg_map[reg_bus].p + reg_offset; diff --git a/drivers/amlogic/media/vout/lcd/lcd_reg.h b/drivers/amlogic/media/vout/lcd/lcd_reg.h index b09f71d21d36..c3ca21e03af1 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_reg.h +++ b/drivers/amlogic/media/vout/lcd/lcd_reg.h @@ -58,6 +58,23 @@ #define PERIPHS_PIN_MUX_11 0x37 #define PERIPHS_PIN_MUX_12 0x38 +#define PERIPHS_PIN_MUX_0_TL1 0x0b0 +#define PERIPHS_PIN_MUX_1_TL1 0x0b1 +#define PERIPHS_PIN_MUX_2_TL1 0x0b2 +#define PERIPHS_PIN_MUX_3_TL1 0x0b3 +#define PERIPHS_PIN_MUX_4_TL1 0x0b4 +#define PERIPHS_PIN_MUX_5_TL1 0x0b5 +#define PERIPHS_PIN_MUX_6_TL1 0x0b6 +#define PERIPHS_PIN_MUX_7_TL1 0x0b7 +#define PERIPHS_PIN_MUX_8_TL1 0x0b8 +#define PERIPHS_PIN_MUX_9_TL1 0x0b9 +#define PERIPHS_PIN_MUX_A_TL1 0x0ba +#define PERIPHS_PIN_MUX_B_TL1 0x0bb +#define PERIPHS_PIN_MUX_C_TL1 0x0bc +#define PERIPHS_PIN_MUX_D_TL1 0x0bd +#define PERIPHS_PIN_MUX_E_TL1 0x0be +#define PERIPHS_PIN_MUX_F_TL1 0x0bf + /* HIU: HHI_CBUS_BASE = 0x10 */ #define HHI_GCLK_MPEG0 0x50 @@ -139,14 +156,13 @@ #define HHI_DSI_LVDS_EDP_CNTL0 0xd1 #define HHI_DSI_LVDS_EDP_CNTL1 0xd2 -#define HHI_DIF_CSI_PHY_CNTL0 0xd8 #define HHI_DIF_CSI_PHY_CNTL1 0xd9 #define HHI_DIF_CSI_PHY_CNTL2 0xda #define HHI_DIF_CSI_PHY_CNTL3 0xdb -#define HHI_DIF_CSI_PHY_CNTL4 0xdc -#define HHI_DIF_CSI_PHY_CNTL5 0xdd #define HHI_LVDS_TX_PHY_CNTL0 0xde #define HHI_LVDS_TX_PHY_CNTL1 0xdf +#define HHI_LVDS_TX_PHY_CNTL0_TL1 0x9a +#define HHI_LVDS_TX_PHY_CNTL1_TL1 0x9b #define HHI_VID2_PLL_CNTL 0xe0 #define HHI_VID2_PLL_CNTL2 0xe1 #define HHI_VID2_PLL_CNTL3 0xe2 @@ -155,6 +171,19 @@ #define HHI_VID2_PLL_CNTL6 0xe5 #define HHI_VID_LOCK_CLK_CNTL 0xf2 +#define HHI_DIF_CSI_PHY_CNTL10 0x8e +#define HHI_DIF_CSI_PHY_CNTL11 0x8f +#define HHI_DIF_CSI_PHY_CNTL12 0x90 +#define HHI_DIF_CSI_PHY_CNTL13 0x91 +#define HHI_DIF_CSI_PHY_CNTL14 0x92 +#define HHI_DIF_CSI_PHY_CNTL15 0x93 +#define HHI_DIF_CSI_PHY_CNTL16 0xde +#define HHI_DIF_CSI_PHY_CNTL4 0xe9 +#define HHI_DIF_CSI_PHY_CNTL6 0xea +#define HHI_DIF_CSI_PHY_CNTL7 0xeb +#define HHI_DIF_CSI_PHY_CNTL8 0xec +#define HHI_DIF_CSI_PHY_CNTL9 0xed + /* AXG use PLL 0xff63c000 */ #define HHI_GP0_PLL_CNTL_AXG 0x10 #define HHI_GP0_PLL_CNTL2_AXG 0x11 @@ -175,14 +204,14 @@ #define HHI_MIPIDSI_PHY_CLK_CNTL 0x95 -#define HHI_MIPI_CNTL0 0x00 -#define HHI_MIPI_CNTL1 0x01 -#define HHI_MIPI_CNTL2 0x02 +#define HHI_MIPI_CNTL0 0x00 +#define HHI_MIPI_CNTL1 0x01 +#define HHI_MIPI_CNTL2 0x02 #define HHI_DIF_TCON_CNTL0 0x3c #define HHI_DIF_TCON_CNTL1 0x3d #define HHI_DIF_TCON_CNTL2 0x3e -#define HHI_TCON_CLK_CNTL 0xf0 +#define HHI_TCON_CLK_CNTL 0x9c /* Global control: RESET_CBUS_BASE = 0x11 */ #define VERSION_CTRL 0x1100 @@ -711,6 +740,9 @@ * G5B10 Other */ #define LCD_MCU_DATA_1 0x14df +#define LVDS_CH_SWAP0 0x14e1 +#define LVDS_CH_SWAP1 0x14e2 +#define LVDS_CH_SWAP2 0x14e3 /* LVDS */ #define LVDS_GEN_CNTL 0x14e0 #define LVDS_PHY_CNTL0 0x14e1 @@ -822,7 +854,9 @@ #define VBO_TMCHK_VDE_STATE_H 0x14f7 #define VBO_INTR_STATE 0x14f8 #define VBO_INFILTER_CTRL 0x14f9 +#define VBO_INFILTER_TICK_PERIOD_L 0x14f9 #define VBO_INSGN_CTRL 0x14fa +#define VBO_INFILTER_TICK_PERIOD_H 0x1477 /* ******************************** * Video Interface: VENC_VCBUS_BASE = 0x1b @@ -909,8 +943,13 @@ #define ENCL_DACSEL_0 0x1cc9 #define ENCL_DACSEL_1 0x1cca +#define ENCL_VIDEO_H_PRE_DE_END 0x1ccf +#define ENCL_VIDEO_H_PRE_DE_BEGIN 0x1cd0 +#define ENCL_VIDEO_V_PRE_DE_ELINE 0x1cd1 +#define ENCL_VIDEO_V_PRE_DE_BLINE 0x1cd2 #define ENCL_INBUF_CNTL0 0x1cd3 #define ENCL_INBUF_CNTL1 0x1cd4 +#define ENCL_INBUF_CNT 0x1cd5 /* ******************************** * TCON TOP: TCON_TOP_BASE = 0x2000 @@ -920,6 +959,7 @@ #define TCON_CTRL_TIMING_BASE 0x01b0 +#define TCON_TOP_BASE 0x2000 #define TCON_TOP_CTRL 0x2000 #define TCON_RGB_IN_MUX 0x2001 #define TCON_OUT_CH_SEL0 0x2002 @@ -941,8 +981,13 @@ #define TCON_GPO_CTRL0 0x2015 #define TCON_GPO_CTRL1 0x2016 #define TCON_GPO_CTRL2 0x2017 +#define TCON_INTR_WR 0x2020 +#define TCON_INTR_CLR 0x2021 #define TCON_INTR_MASKN 0x2022 -#define TCON_INTR 0x2023 /* read only */ +#define TCON_INTR_RO 0x2023 /* read only */ + +#define P2P_CH_SWAP0 0x4200 +#define P2P_CH_SWAP1 0x4201 /* ******************************** * Video post-processing: VPP_VCBUS_BASE = 0x1d diff --git a/drivers/amlogic/media/vout/lcd/lcd_tablet/lcd_drv.c b/drivers/amlogic/media/vout/lcd/lcd_tablet/lcd_drv.c index d5d69bbde91a..16682e91c15f 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_tablet/lcd_drv.c +++ b/drivers/amlogic/media/vout/lcd/lcd_tablet/lcd_drv.c @@ -60,184 +60,6 @@ static int lcd_type_supported(struct lcd_config_s *pconf) return ret; } -static void lcd_lvds_phy_set(struct lcd_config_s *pconf, int status) -{ - unsigned int vswing, preem, clk_vswing, clk_preem, channel_on; - unsigned int data32; - - if (lcd_debug_print_flag) - LCDPR("%s: %d\n", __func__, status); - - if (status) { - vswing = pconf->lcd_control.lvds_config->phy_vswing; - preem = pconf->lcd_control.lvds_config->phy_preem; - clk_vswing = pconf->lcd_control.lvds_config->phy_clk_vswing; - clk_preem = pconf->lcd_control.lvds_config->phy_clk_preem; - if (vswing > 7) { - LCDERR("%s: wrong vswing_level=%d, use default\n", - __func__, vswing); - vswing = LVDS_PHY_VSWING_DFT; - } - channel_on = lcd_lvds_channel_on_value(pconf); - - if (preem > 7) { - LCDERR("%s: wrong preem=%d, use default\n", - __func__, preem); - preem = LVDS_PHY_PREEM_DFT; - } - if (clk_vswing > 3) { - LCDERR("%s: wrong clk_vswing=%d, use default\n", - __func__, clk_vswing); - clk_vswing = LVDS_PHY_CLK_VSWING_DFT; - } - if (clk_preem > 7) { - LCDERR("%s: wrong clk_preem=%d, use default\n", - __func__, clk_preem); - clk_preem = LVDS_PHY_CLK_PREEM_DFT; - } - - data32 = LVDS_PHY_CNTL1_G9TV | - (vswing << 26) | (preem << 0); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL1, data32); - data32 = LVDS_PHY_CNTL2_G9TV; - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL2, data32); - data32 = LVDS_PHY_CNTL3_G9TV | - (channel_on << 16) | - (clk_vswing << 8) | (clk_preem << 5); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL3, data32); - } else { - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL1, 0x0); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL2, 0x0); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL3, 0x0); - } -} - -static void lcd_vbyone_phy_set(struct lcd_config_s *pconf, int status) -{ - unsigned int vswing, preem, ext_pullup; - unsigned int data32; - unsigned int rinner_table[] = {0xa, 0xa, 0x6, 0x4}; - - if (lcd_debug_print_flag) - LCDPR("%s: %d\n", __func__, status); - - if (status) { - ext_pullup = (pconf->lcd_control.vbyone_config->phy_vswing >> 4) - & 0x3; - vswing = pconf->lcd_control.vbyone_config->phy_vswing & 0xf; - preem = pconf->lcd_control.vbyone_config->phy_preem; - if (vswing > 7) { - LCDERR("%s: wrong vswing_level=%d, use default\n", - __func__, vswing); - vswing = VX1_PHY_VSWING_DFT; - } - if (preem > 7) { - LCDERR("%s: wrong preemphasis_level=%d, use default\n", - __func__, preem); - preem = VX1_PHY_PREEM_DFT; - } - if (ext_pullup) - data32 = VX1_PHY_CNTL1_G9TV_PULLUP | (vswing << 3); - else - data32 = VX1_PHY_CNTL1_G9TV | (vswing << 3); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL1, data32); - data32 = VX1_PHY_CNTL2_G9TV | (preem << 20) | - (rinner_table[ext_pullup] << 8); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL2, data32); - data32 = VX1_PHY_CNTL3_G9TV; - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL3, data32); - } else { - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL1, 0x0); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL2, 0x0); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL3, 0x0); - } -} - -static void lcd_mipi_phy_set(struct lcd_config_s *pconf, int status) -{ - unsigned int phy_reg, phy_bit, phy_width; - unsigned int lane_cnt; - struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); - - if (status) { - switch (lcd_drv->data->chip_type) { - case LCD_CHIP_G12A: - case LCD_CHIP_G12B: - /* HHI_MIPI_CNTL0 */ - /* DIF_REF_CTL1:31-16bit, DIF_REF_CTL0:15-0bit */ - lcd_hiu_write(HHI_MIPI_CNTL0, - (0xa487 << 16) | (0x8 << 0)); - - /* HHI_MIPI_CNTL1 */ - /* DIF_REF_CTL2:15-0bit */ - lcd_hiu_write(HHI_MIPI_CNTL1, - (0x1 << 16) | (0x002e << 0)); - - /* HHI_MIPI_CNTL2 */ - /* DIF_TX_CTL1:31-16bit, DIF_TX_CTL0:15-0bit */ - lcd_hiu_write(HHI_MIPI_CNTL2, - (0x2680 << 16) | (0x45a << 0)); - break; - default: /* LCD_CHIP_AXG */ - /* HHI_MIPI_CNTL0 */ - /* DIF_REF_CTL1:31-16bit, DIF_REF_CTL0:15-0bit */ - lcd_hiu_setb(HHI_MIPI_CNTL0, 0x1b8, 16, 10); - lcd_hiu_setb(HHI_MIPI_CNTL0, 1, 26, 1); /* bandgap */ - lcd_hiu_setb(HHI_MIPI_CNTL0, 1, 29, 1); /* current */ - lcd_hiu_setb(HHI_MIPI_CNTL0, 1, 31, 1); - lcd_hiu_setb(HHI_MIPI_CNTL0, 0x8, 0, 16); - - /* HHI_MIPI_CNTL1 */ - /* DIF_REF_CTL2:15-0bit */ - lcd_hiu_write(HHI_MIPI_CNTL1, (0x001e << 0)); - - /* HHI_MIPI_CNTL2 */ - /* DIF_TX_CTL1:31-16bit, DIF_TX_CTL0:15-0bit */ - lcd_hiu_write(HHI_MIPI_CNTL2, - (0x26e0 << 16) | (0xfc59 << 0)); - break; - } - - phy_reg = HHI_MIPI_CNTL2; - phy_bit = MIPI_PHY_LANE_BIT; - phy_width = MIPI_PHY_LANE_WIDTH; - switch (pconf->lcd_control.mipi_config->lane_num) { - case 1: - lane_cnt = DSI_LANE_COUNT_1; - break; - case 2: - lane_cnt = DSI_LANE_COUNT_2; - break; - case 3: - lane_cnt = DSI_LANE_COUNT_3; - break; - case 4: - lane_cnt = DSI_LANE_COUNT_4; - break; - default: - lane_cnt = 0; - break; - } - lcd_hiu_setb(phy_reg, lane_cnt, phy_bit, phy_width); - } else { - switch (lcd_drv->data->chip_type) { - case LCD_CHIP_G12A: - case LCD_CHIP_G12B: - lcd_hiu_write(HHI_MIPI_CNTL0, 0); - lcd_hiu_write(HHI_MIPI_CNTL1, 0); - lcd_hiu_write(HHI_MIPI_CNTL2, 0); - break; - default:/* LCD_CHIP_AXG */ - lcd_hiu_setb(HHI_MIPI_CNTL0, 0, 16, 10); - lcd_hiu_setb(HHI_MIPI_CNTL0, 0, 31, 1); - lcd_hiu_setb(HHI_MIPI_CNTL0, 0, 0, 16); - lcd_hiu_write(HHI_MIPI_CNTL1, 0x6); - lcd_hiu_write(HHI_MIPI_CNTL2, 0x00200000); - break; - } - } -} - static void lcd_encl_tcon_set(struct lcd_config_s *pconf) { struct lcd_timing_s *tcon_adr = &pconf->lcd_timing; @@ -374,7 +196,8 @@ static void lcd_venc_set(struct lcd_config_s *pconf) switch (lcd_drv->data->chip_type) { case LCD_CHIP_TL1: - lcd_vcbus_write(ENCL_INBUF_CNTL1, (1 << 14) | (h_active - 1)); + /*[15:14]: 2'b10 or 2'b01*/ + lcd_vcbus_write(ENCL_INBUF_CNTL1, (2 << 14) | (h_active - 1)); lcd_vcbus_write(ENCL_INBUF_CNTL0, 0x200); break; default: @@ -409,7 +232,20 @@ static void lcd_ttl_control_set(struct lcd_config_s *pconf) static void lcd_lvds_clk_util_set(struct lcd_config_s *pconf) { + struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); unsigned int phy_div; + unsigned int reg_cntl0, reg_cntl1; + + switch (lcd_drv->data->chip_type) { + case LCD_CHIP_TL1: + reg_cntl0 = HHI_LVDS_TX_PHY_CNTL0_TL1; + reg_cntl1 = HHI_LVDS_TX_PHY_CNTL1_TL1; + break; + default: + reg_cntl0 = HHI_LVDS_TX_PHY_CNTL0; + reg_cntl1 = HHI_LVDS_TX_PHY_CNTL1; + break; + } if (pconf->lcd_control.lvds_config->dual_port) phy_div = 2; @@ -417,19 +253,27 @@ static void lcd_lvds_clk_util_set(struct lcd_config_s *pconf) phy_div = 1; /* set fifo_clk_sel: div 7 */ - lcd_hiu_write(HHI_LVDS_TX_PHY_CNTL0, (1 << 6)); + lcd_hiu_write(reg_cntl0, (1 << 6)); /* set cntl_ser_en: 8-channel to 1 */ - lcd_hiu_setb(HHI_LVDS_TX_PHY_CNTL0, 0xfff, 16, 12); + lcd_hiu_setb(reg_cntl0, 0xfff, 16, 12); + switch (lcd_drv->data->chip_type) { /* pn swap */ + case LCD_CHIP_TL1: + lcd_hiu_setb(reg_cntl0, 1, 2, 1); + break; + default: + break; + } /* decoupling fifo enable, gated clock enable */ - lcd_hiu_write(HHI_LVDS_TX_PHY_CNTL1, + lcd_hiu_write(reg_cntl1, (1 << 30) | ((phy_div - 1) << 25) | (1 << 24)); /* decoupling fifo write enable after fifo enable */ - lcd_hiu_setb(HHI_LVDS_TX_PHY_CNTL1, 1, 31, 1); + lcd_hiu_setb(reg_cntl1, 1, 31, 1); } static void lcd_lvds_control_set(struct lcd_config_s *pconf) { + struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); unsigned int bit_num = 1; unsigned int pn_swap, port_swap, lane_reverse; unsigned int dual_port, fifo_mode; @@ -480,10 +324,17 @@ static void lcd_lvds_control_set(struct lcd_config_s *pconf) (1 << 12) | /* g_select //0:R, 1:G, 2:B, 3:0 */ (2 << 14)); /* b_select //0:R, 1:G, 2:B, 3:0 */ - lcd_vcbus_setb(LCD_PORT_SWAP, port_swap, 12, 1); - - if (lane_reverse) - lcd_vcbus_setb(LVDS_GEN_CNTL, 0x03, 13, 2); + switch (lcd_drv->data->chip_type) { + case LCD_CHIP_TL1: + lcd_vcbus_write(P2P_CH_SWAP0, 0x76543210); + lcd_vcbus_write(P2P_CH_SWAP1, 0xba98); + break; + default: + lcd_vcbus_setb(LCD_PORT_SWAP, port_swap, 12, 1); + if (lane_reverse) + lcd_vcbus_setb(LVDS_GEN_CNTL, 0x03, 13, 2); + break; + } lcd_vcbus_write(LVDS_GEN_CNTL, (lcd_vcbus_read(LVDS_GEN_CNTL) | @@ -510,6 +361,19 @@ static void lcd_vbyone_clk_util_set(struct lcd_config_s *pconf) { unsigned int lcd_bits; unsigned int div_sel, phy_div; + struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); + unsigned int reg_cntl0, reg_cntl1; + + switch (lcd_drv->data->chip_type) { + case LCD_CHIP_TL1: + reg_cntl0 = HHI_LVDS_TX_PHY_CNTL0_TL1; + reg_cntl1 = HHI_LVDS_TX_PHY_CNTL1_TL1; + break; + default: + reg_cntl0 = HHI_LVDS_TX_PHY_CNTL0; + reg_cntl1 = HHI_LVDS_TX_PHY_CNTL1; + break; + } phy_div = pconf->lcd_control.vbyone_config->phy_div; lcd_bits = pconf->lcd_basic.lcd_bits; @@ -529,15 +393,22 @@ static void lcd_vbyone_clk_util_set(struct lcd_config_s *pconf) break; } /* set fifo_clk_sel */ - lcd_hiu_write(HHI_LVDS_TX_PHY_CNTL0, (div_sel << 6)); + lcd_hiu_write(reg_cntl0, (div_sel << 6)); /* set cntl_ser_en: 8-channel to 1 */ - lcd_hiu_setb(HHI_LVDS_TX_PHY_CNTL0, 0xfff, 16, 12); + lcd_hiu_setb(reg_cntl0, 0xfff, 16, 12); + switch (lcd_drv->data->chip_type) { /* pn swap */ + case LCD_CHIP_TL1: + lcd_hiu_setb(reg_cntl0, 1, 2, 1); + break; + default: + break; + } /* decoupling fifo enable, gated clock enable */ - lcd_hiu_write(HHI_LVDS_TX_PHY_CNTL1, + lcd_hiu_write(reg_cntl1, (1 << 30) | ((phy_div - 1) << 25) | (1 << 24)); /* decoupling fifo write enable after fifo enable */ - lcd_hiu_setb(HHI_LVDS_TX_PHY_CNTL1, 1, 31, 1); + lcd_hiu_setb(reg_cntl1, 1, 31, 1); } static int lcd_vbyone_lanes_set(int lane_num, int byte_mode, int region_num, @@ -646,6 +517,7 @@ static void lcd_vbyone_wait_timing_stable(void) static void lcd_vbyone_control_set(struct lcd_config_s *pconf) { + struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); int lane_count, byte_mode, region_num, hsize, vsize, color_fmt; int vin_color, vin_bpp; @@ -724,7 +596,21 @@ static void lcd_vbyone_control_set(struct lcd_config_s *pconf) /* lcd_vcbus_setb(LCD_PORT_SWAP, 1, 8, 1);//reverse lane output order */ /* Mux pads in combo-phy: 0 for dsi; 1 for lvds or vbyone; 2 for edp */ - lcd_hiu_write(HHI_DSI_LVDS_EDP_CNTL0, 0x1); + /*lcd_hiu_write(HHI_DSI_LVDS_EDP_CNTL0, 0x1);*/ + + switch (lcd_drv->data->chip_type) { + case LCD_CHIP_TL1: + lcd_vcbus_write(VBO_INFILTER_TICK_PERIOD_L, 0xff); + lcd_vcbus_write(VBO_INFILTER_TICK_PERIOD_H, 0x0); + lcd_vcbus_setb(VBO_INSGN_CTRL, 0x7, 8, 4); + lcd_vcbus_setb(VBO_INSGN_CTRL, 0x7, 12, 4); + break; + default: + lcd_vcbus_write(VBO_INFILTER_CTRL, 0xff77); + break; + } + lcd_vcbus_setb(VBO_INSGN_CTRL, 0, 2, 2); + lcd_vcbus_setb(VBO_CTRL_L, 1, 0, 1); /*force vencl clk enable, otherwise, it might auto turn off by mipi DSI @@ -737,6 +623,8 @@ static void lcd_vbyone_control_set(struct lcd_config_s *pconf) static void lcd_vbyone_disable(void) { lcd_vcbus_setb(VBO_CTRL_L, 0, 0, 1); + lcd_vcbus_setb(VBO_INSGN_CTRL, 0, 2, 1); + lcd_vcbus_setb(VBO_INSGN_CTRL, 0, 0, 1); } static void lcd_tablet_vbyone_wait_stable(void) @@ -751,7 +639,7 @@ static void lcd_tablet_vbyone_wait_stable(void) __func__, lcd_vcbus_read(VBO_STATUS_L), (5000 - i)); } -static void lcd_vx1_wait_hpd(void) +static void lcd_vbyone_wait_hpd(void) { int i = 0; @@ -764,12 +652,17 @@ static void lcd_vx1_wait_hpd(void) udelay(50); } mdelay(10); - if (lcd_vcbus_read(VBO_STATUS_L) & 0x40) + if (lcd_vcbus_read(VBO_STATUS_L) & 0x40) { LCDPR("%s: hpd=%d\n", __func__, ((lcd_vcbus_read(VBO_STATUS_L) >> 6) & 0x1)); - else + } else { LCDPR("%s: hpd=%d, i=%d\n", __func__, ((lcd_vcbus_read(VBO_STATUS_L) >> 6) & 0x1), i); + /* force low only actived for actual hpd is low */ + lcd_vcbus_setb(VBO_INSGN_CTRL, 1, 2, 2); + } + + usleep_range(10000, 10500); /* add 10ms delay for compatibility */ } static unsigned int vbyone_lane_num[] = { @@ -831,7 +724,7 @@ static void lcd_vbyone_config_set(struct lcd_config_s *pconf) bit_rate = bit_rate * 1000; /* Hz */ pconf->lcd_control.vbyone_config->phy_div = phy_div; - pconf->lcd_control.vbyone_config->bit_rate = bit_rate; + pconf->lcd_timing.bit_rate = bit_rate; if (lcd_debug_print_flag) { LCDPR("lane_count=%u, bit_rate = %uMHz, pclk=%u.%03uMhz\n", @@ -980,7 +873,7 @@ int lcd_tablet_driver_init(void) case LCD_VBYONE: lcd_vbyone_pinmux_set(1); lcd_vbyone_control_set(pconf); - lcd_vx1_wait_hpd(); + lcd_vbyone_wait_hpd(); lcd_vbyone_phy_set(pconf, 1); lcd_tablet_vbyone_wait_stable(); break; diff --git a/drivers/amlogic/media/vout/lcd/lcd_tablet/lcd_tablet.c b/drivers/amlogic/media/vout/lcd/lcd_tablet/lcd_tablet.c index 50814cce5054..4bf4862aa3b8 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_tablet/lcd_tablet.c +++ b/drivers/amlogic/media/vout/lcd/lcd_tablet/lcd_tablet.c @@ -131,7 +131,8 @@ static int lcd_vout_clr_state(int index) struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); lcd_vout_state &= ~(1 << index); - lcd_drv->viu_sel = LCD_VIU_SEL_NONE; + if (lcd_drv->viu_sel == index) + lcd_drv->viu_sel = LCD_VIU_SEL_NONE; return 0; } @@ -192,17 +193,7 @@ static int lcd_framerate_automation_set_mode(void) #endif /* change clk parameter */ - switch (lcd_drv->lcd_config->lcd_timing.clk_change) { - case LCD_CLK_PLL_CHANGE: - lcd_clk_generate_parameter(lcd_drv->lcd_config); - lcd_clk_set(lcd_drv->lcd_config); - break; - case LCD_CLK_FRAC_UPDATE: - lcd_clk_update(lcd_drv->lcd_config); - break; - default: - break; - } + lcd_clk_change(lcd_drv->lcd_config); lcd_tablet_config_post_update(lcd_drv->lcd_config); lcd_venc_change(lcd_drv->lcd_config); @@ -728,7 +719,7 @@ static int lcd_config_load_from_dts(struct lcd_config_s *pconf, pconf->lcd_timing.lcd_clk = 60; } else { pconf->lcd_timing.fr_adjust_type = (unsigned char)(para[0]); - pconf->lcd_timing.ss_level = (unsigned char)(para[1]); + pconf->lcd_timing.ss_level = para[1]; pconf->lcd_timing.clk_auto = (unsigned char)(para[2]); if (para[3] > 0) { pconf->lcd_timing.lcd_clk = para[3]; @@ -1001,6 +992,10 @@ static int lcd_config_load_from_unifykey(struct lcd_config_s *pconf) ((*(p + LCD_UKEY_PCLK + 1)) << 8) | ((*(p + LCD_UKEY_PCLK + 2)) << 16) | ((*(p + LCD_UKEY_PCLK + 3)) << 24)); + if (pconf->lcd_timing.lcd_clk == 0) { /* avoid 0 mistake */ + pconf->lcd_timing.lcd_clk = 60; + LCDERR("lcd_clk is 0, default to 60Hz\n"); + } pconf->lcd_basic.h_period_min = (*(p + LCD_UKEY_H_PERIOD_MIN) | ((*(p + LCD_UKEY_H_PERIOD_MIN + 1)) << 8)); pconf->lcd_basic.h_period_max = (*(p + LCD_UKEY_H_PERIOD_MAX) | @@ -1167,18 +1162,17 @@ static int lcd_config_load_from_unifykey(struct lcd_config_s *pconf) static void lcd_config_init(struct lcd_config_s *pconf) { struct lcd_clk_config_s *cconf = get_lcd_clk_config(); - unsigned int ss_level; - unsigned int clk; + unsigned int temp; unsigned int sync_duration, h_period, v_period; - clk = pconf->lcd_timing.lcd_clk; + temp = pconf->lcd_timing.lcd_clk; h_period = pconf->lcd_basic.h_period; v_period = pconf->lcd_basic.v_period; - if (clk < 200) { /* regard as frame_rate */ - sync_duration = clk * 100; - pconf->lcd_timing.lcd_clk = clk * h_period * v_period; + if (temp < 200) { /* regard as frame_rate */ + sync_duration = temp * 100; + pconf->lcd_timing.lcd_clk = temp * h_period * v_period; } else { /* regard as pixel clock */ - sync_duration = ((clk / h_period) * 100) / v_period; + sync_duration = ((temp / h_period) * 100) / v_period; } pconf->lcd_timing.sync_duration_num = sync_duration; pconf->lcd_timing.sync_duration_den = 100; @@ -1191,13 +1185,23 @@ static void lcd_config_init(struct lcd_config_s *pconf) lcd_tablet_config_update(pconf); lcd_clk_generate_parameter(pconf); - ss_level = pconf->lcd_timing.ss_level; if (cconf->data) { - cconf->ss_level = (ss_level >= cconf->data->ss_level_max) ? - 0 : ss_level; + temp = pconf->lcd_timing.ss_level & 0xff; + cconf->ss_level = (temp >= cconf->data->ss_level_max) ? + 0 : temp; + temp = (pconf->lcd_timing.ss_level >> 8) & 0xff; + temp = (temp >> LCD_CLK_SS_BIT_FREQ) & 0xf; + cconf->ss_freq = (temp >= cconf->data->ss_freq_max) ? + 0 : temp; + temp = (pconf->lcd_timing.ss_level >> 8) & 0xff; + temp = (temp >> LCD_CLK_SS_BIT_MODE) & 0xf; + cconf->ss_mode = (temp >= cconf->data->ss_mode_max) ? + 0 : temp; } else { LCDERR("%s: clk config data is null\n", __func__); cconf->ss_level = 0; + cconf->ss_freq = 0; + cconf->ss_mode = 0; } lcd_tablet_config_post_update(pconf); @@ -1247,6 +1251,8 @@ static void lcd_set_vinfo(unsigned int sync_duration) LCDPR("%s: sync_duration=%d\n", __func__, sync_duration); + vout_notifier_call_chain(VOUT_EVENT_MODE_CHANGE_PRE, + &lcd_drv->lcd_info->mode); /* update vinfo */ lcd_drv->lcd_info->sync_duration_num = sync_duration; lcd_drv->lcd_info->sync_duration_den = 100; @@ -1259,17 +1265,7 @@ static void lcd_set_vinfo(unsigned int sync_duration) #endif /* change clk parameter */ - switch (lcd_drv->lcd_config->lcd_timing.clk_change) { - case LCD_CLK_PLL_CHANGE: - lcd_clk_generate_parameter(lcd_drv->lcd_config); - lcd_clk_set(lcd_drv->lcd_config); - break; - case LCD_CLK_FRAC_UPDATE: - lcd_clk_update(lcd_drv->lcd_config); - break; - default: - break; - } + lcd_clk_change(lcd_drv->lcd_config); lcd_tablet_config_post_update(lcd_drv->lcd_config); lcd_venc_change(lcd_drv->lcd_config); diff --git a/drivers/amlogic/media/vout/lcd/lcd_tablet/mipi_dsi_util.c b/drivers/amlogic/media/vout/lcd/lcd_tablet/mipi_dsi_util.c index 49d701a50533..fdf006c3f95d 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_tablet/mipi_dsi_util.c +++ b/drivers/amlogic/media/vout/lcd/lcd_tablet/mipi_dsi_util.c @@ -152,11 +152,11 @@ static void mipi_dsi_init_table_print(struct dsi_config_s *dconf, int on_off) } } -static void mipi_dsi_dphy_print_info(struct dsi_config_s *dconf) +static void mipi_dsi_dphy_print_info(struct lcd_config_s *pconf) { unsigned int temp; - temp = ((1000000 * 100) / (dconf->bit_rate / 1000)) * 8; + temp = ((1000000 * 100) / (pconf->lcd_timing.bit_rate / 1000)) * 8; pr_info("MIPI DSI DPHY timing (unit: ns)\n" " UI: %d.%02d\n" " LP TESC: %d\n" @@ -217,7 +217,7 @@ static void mipi_dsi_host_print_info(struct lcd_config_s *pconf) struct dsi_config_s *dconf; dconf = pconf->lcd_control.mipi_config; - esc_clk = dconf->bit_rate / 8 / dsi_phy_config.lp_tesc; + esc_clk = pconf->lcd_timing.bit_rate / 8 / dsi_phy_config.lp_tesc; factor = dconf->factor_numerator; factor = ((factor * 1000 / dconf->factor_denominator) + 5) / 10; @@ -243,7 +243,8 @@ static void mipi_dsi_host_print_info(struct lcd_config_s *pconf) " data format: %s\n" " lp escape clock: %d.%03dMHz\n", dconf->lane_num, dconf->bit_rate_max, - (dconf->bit_rate / 1000000), (dconf->bit_rate % 1000000) / 1000, + (pconf->lcd_timing.bit_rate / 1000000), + (pconf->lcd_timing.bit_rate % 1000000) / 1000, factor, operation_mode_table[dconf->operation_mode_init], dconf->operation_mode_init, @@ -267,7 +268,7 @@ void mipi_dsi_print_info(struct lcd_config_s *pconf) { mipi_dsi_host_print_info(pconf); - mipi_dsi_dphy_print_info(pconf->lcd_control.mipi_config); + mipi_dsi_dphy_print_info(pconf); mipi_dsi_video_print_info(pconf->lcd_control.mipi_config); } @@ -1699,13 +1700,13 @@ static void mipi_dsi_non_burst_packet_config(struct lcd_config_s *pconf) hactive = pconf->lcd_basic.h_active; bit_rate_required = pconf->lcd_timing.lcd_clk * 3 * dsi_vconf.data_bits; bit_rate_required = bit_rate_required / lane_num; - if (dconf->bit_rate > bit_rate_required) + if (pconf->lcd_timing.bit_rate > bit_rate_required) multi_pkt_en = 1; else multi_pkt_en = 0; if (lcd_debug_print_flag) { LCDPR("non-burst: bit_rate_required=%d, bit_rate=%d\n", - bit_rate_required, dconf->bit_rate); + bit_rate_required, pconf->lcd_timing.bit_rate); } if (multi_pkt_en == 0) { @@ -2018,11 +2019,11 @@ void lcd_mipi_dsi_config_post(struct lcd_config_s *pconf) /* pclk lanebyteclk factor */ if (dconf->factor_numerator == 0) { - lanebyteclk = dconf->bit_rate / 8 / 1000; + lanebyteclk = pconf->lcd_timing.bit_rate / 8 / 1000; LCDPR("pixel_clk = %d.%03dMHz, bit_rate = %d.%03dMHz\n", (pclk / 1000), (pclk % 1000), - (dconf->bit_rate / 1000000), - ((dconf->bit_rate / 1000) % 1000)); + (pconf->lcd_timing.bit_rate / 1000000), + ((pconf->lcd_timing.bit_rate / 1000) % 1000)); #if 0 dconf->factor_numerator = pclk; dconf->factor_denominator = lanebyteclk; @@ -2042,7 +2043,7 @@ void lcd_mipi_dsi_config_post(struct lcd_config_s *pconf) mipi_dsi_vid_mode_config(pconf); /* phy config */ - mipi_dsi_phy_config(&dsi_phy_config, dconf->bit_rate); + mipi_dsi_phy_config(&dsi_phy_config, pconf->lcd_timing.bit_rate); } static void mipi_dsi_host_on(struct lcd_config_s *pconf) diff --git a/drivers/amlogic/media/vout/lcd/lcd_tcon.c b/drivers/amlogic/media/vout/lcd/lcd_tcon.c index b2e26713d24a..c8039f2499f9 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_tcon.c +++ b/drivers/amlogic/media/vout/lcd/lcd_tcon.c @@ -28,17 +28,27 @@ #include #include #include +#include +#include +#include #include #include #include "lcd_common.h" #include "lcd_reg.h" #include "lcd_tcon.h" +/*#include "tcon_ceds.h"*/ #define TCON_INTR_MASKN_VAL 0x0 /* default mask all */ -static struct reserved_mem tcon_fb_rmem = {.base = 0, .size = 0}; +static struct tcon_rmem_s tcon_rmem = { + .flag = 0, + .mem_vaddr = NULL, + .mem_paddr = 0, + .mem_size = 0, +}; static struct lcd_tcon_data_s *lcd_tcon_data; +static struct delayed_work lcd_tcon_delayed_work; static int lcd_tcon_valid_check(void) { @@ -54,6 +64,48 @@ static int lcd_tcon_valid_check(void) return 0; } +unsigned int lcd_tcon_reg_read(unsigned int addr) +{ + unsigned int val; + int ret; + + ret = lcd_tcon_valid_check(); + if (ret) + return 0; + + if (addr < TCON_TOP_BASE) { + if (lcd_tcon_data->core_reg_width == 8) + val = lcd_tcon_read_byte(addr); + else + val = lcd_tcon_read(addr); + } else { + val = lcd_tcon_read(addr); + } + + return val; +} + +void lcd_tcon_reg_write(unsigned int addr, unsigned int val) +{ + unsigned char temp; + int ret; + + ret = lcd_tcon_valid_check(); + if (ret) + return; + + if (addr < TCON_TOP_BASE) { + if (lcd_tcon_data->core_reg_width == 8) { + temp = (unsigned char)val; + lcd_tcon_write_byte(addr, temp); + } else { + lcd_tcon_write(addr, val); + } + } else { + lcd_tcon_write(addr, val); + } +} + static void lcd_tcon_od_check(unsigned char *table) { unsigned int reg, bit; @@ -66,7 +118,7 @@ static void lcd_tcon_od_check(unsigned char *table) if (((table[reg] >> bit) & 1) == 0) return; - if (lcd_tcon_data->axi_offset_addr == 0) { + if (tcon_rmem.flag == 0) { table[reg] &= ~(1 << bit); LCDPR("%s: invalid fb, disable od function\n", __func__); } @@ -111,32 +163,43 @@ void lcd_tcon_core_reg_update(void) } } -static int lcd_tcon_top_set_tl1(void) +static int lcd_tcon_top_set_tl1(struct lcd_config_s *pconf) { unsigned int axi_reg[3] = { TCON_AXI_OFST0, TCON_AXI_OFST1, TCON_AXI_OFST2 }; unsigned int addr[3] = {0, 0, 0}; - unsigned int size[3] = {0, 0, 0}; + unsigned int size[3] = {4162560, 4162560, 1960440}; int i; LCDPR("lcd tcon top set\n"); - if (lcd_tcon_data->axi_offset_addr == 0) { - LCDERR("%s: invalid axi_offset_addr\n", __func__); - } else { - addr[0] = lcd_tcon_data->axi_offset_addr; + if (tcon_rmem.flag) { + addr[0] = tcon_rmem.mem_paddr; addr[1] = addr[0] + size[0]; addr[2] = addr[1] + size[1]; for (i = 0; i < 3; i++) { lcd_tcon_write(axi_reg[i], addr[i]); - LCDPR("set tcon axi_offset_addr[%d]: 0x%08x\n", + LCDPR("set tcon axi_mem_paddr[%d]: 0x%08x\n", i, addr[i]); } + } else { + LCDERR("%s: invalid axi_mem\n", __func__); } lcd_tcon_write(TCON_CLK_CTRL, 0x001f); - lcd_tcon_write(TCON_TOP_CTRL, 0x8999); + if (pconf->lcd_basic.lcd_type == LCD_P2P) { + switch (pconf->lcd_control.p2p_config->p2p_type) { + case P2P_CHPI: + lcd_tcon_write(TCON_TOP_CTRL, 0x8199); + break; + default: + lcd_tcon_write(TCON_TOP_CTRL, 0x8999); + break; + } + } else { + lcd_tcon_write(TCON_TOP_CTRL, 0x8999); + } lcd_tcon_write(TCON_PLLLOCK_CNTL, 0x0037); lcd_tcon_write(TCON_RST_CTRL, 0x003f); lcd_tcon_write(TCON_RST_CTRL, 0x0000); @@ -146,8 +209,46 @@ static int lcd_tcon_top_set_tl1(void) return 0; } +static void lcd_tcon_chpi_bbc_init_tl1(int delay) +{ + unsigned int data32; + + udelay(delay); + lcd_hiu_setb(HHI_DIF_CSI_PHY_CNTL1, 1, 3, 1); + lcd_hiu_setb(HHI_DIF_CSI_PHY_CNTL1, 1, 19, 1); + lcd_hiu_setb(HHI_DIF_CSI_PHY_CNTL2, 1, 3, 1); + lcd_hiu_setb(HHI_DIF_CSI_PHY_CNTL2, 1, 19, 1); + lcd_hiu_setb(HHI_DIF_CSI_PHY_CNTL3, 1, 3, 1); + lcd_hiu_setb(HHI_DIF_CSI_PHY_CNTL3, 1, 19, 1); + lcd_hiu_setb(HHI_DIF_CSI_PHY_CNTL4, 1, 3, 1); + lcd_hiu_setb(HHI_DIF_CSI_PHY_CNTL4, 1, 19, 1); + lcd_hiu_setb(HHI_DIF_CSI_PHY_CNTL6, 1, 3, 1); + lcd_hiu_setb(HHI_DIF_CSI_PHY_CNTL6, 1, 19, 1); + lcd_hiu_setb(HHI_DIF_CSI_PHY_CNTL7, 1, 3, 1); + lcd_hiu_setb(HHI_DIF_CSI_PHY_CNTL7, 1, 19, 1); + LCDPR("%s: delay: %dus\n", __func__, delay); + + data32 = 0x06020602; + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL14, 0xff2027ef); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL15, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL16, 0x80000000); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL8, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL1, data32); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL9, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL2, data32); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL10, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL3, data32); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL11, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL4, data32); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL12, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL6, data32); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL13, 0); + lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL7, data32); +} + static int lcd_tcon_enable_tl1(struct lcd_config_s *pconf) { + unsigned int n = 10; int ret; ret = lcd_tcon_valid_check(); @@ -155,16 +256,23 @@ static int lcd_tcon_enable_tl1(struct lcd_config_s *pconf) return -1; /* step 1: tcon top */ - lcd_tcon_top_set_tl1(); + lcd_tcon_top_set_tl1(pconf); /* step 2: tcon_core_reg_update */ lcd_tcon_core_reg_update(); + if (pconf->lcd_basic.lcd_type == LCD_P2P) { + switch (pconf->lcd_control.p2p_config->p2p_type) { + case P2P_CHPI: + lcd_tcon_chpi_bbc_init_tl1(n); + break; + default: + break; + } + } /* step 3: tcon_top_output_set */ - lcd_tcon_write(TCON_OUT_CH_SEL1, 0xba98); /* out swap for ch8~11 */ - LCDPR("set tcon ch_sel: 0x%08x, 0x%08x\n", - lcd_tcon_read(TCON_OUT_CH_SEL0), - lcd_tcon_read(TCON_OUT_CH_SEL1)); + lcd_tcon_write(TCON_OUT_CH_SEL0, 0x76543210); + lcd_tcon_write(TCON_OUT_CH_SEL1, 0xba98); /* step 4: tcon_intr_mask */ lcd_tcon_write(TCON_INTR_MASKN, TCON_INTR_MASKN_VAL); @@ -180,7 +288,7 @@ static irqreturn_t lcd_tcon_isr(int irq, void *dev_id) if ((lcd_drv->lcd_status & LCD_STATUS_IF_ON) == 0) return IRQ_HANDLED; - temp = lcd_tcon_read(TCON_INTR); + temp = lcd_tcon_read(TCON_INTR_RO); if (temp & 0x2) { LCDPR("%s: tcon sw_reset triggered\n", __func__); lcd_tcon_core_reg_update(); @@ -200,13 +308,15 @@ static void lcd_tcon_intr_init(struct aml_lcd_drv_s *lcd_drv) return; } tcon_irq = lcd_drv->res_tcon_irq->start; - LCDPR("tcon_irq: %d\n", tcon_irq); + if (lcd_debug_print_flag) + LCDPR("tcon_irq: %d\n", tcon_irq); if (request_irq(tcon_irq, lcd_tcon_isr, IRQF_SHARED, "lcd_tcon", (void *)"lcd_tcon")) LCDERR("can't request lcd_tcon irq\n"); else { - LCDPR("request lcd_tcon successful\n"); + if (lcd_debug_print_flag) + LCDPR("request lcd_tcon irq successful\n"); } lcd_tcon_write(TCON_INTR_MASKN, TCON_INTR_MASKN_VAL); @@ -216,17 +326,7 @@ static int lcd_tcon_config(struct aml_lcd_drv_s *lcd_drv) { int key_len, reg_len, ret; - /* init reserved memory */ - ret = of_reserved_mem_device_init(lcd_drv->dev); - if ((ret != 0) && ((void *)tcon_fb_rmem.base == NULL)) { - LCDERR("failed to init tcon axi reserved memory\n"); - } else { - lcd_tcon_data->axi_offset_addr = - virt_to_phys((void *)tcon_fb_rmem.base); - } - LCDPR("tcon axi_offset_addr = 0x%08x\n", - lcd_tcon_data->axi_offset_addr); - +#if 1 /* get reg table from unifykey */ reg_len = lcd_tcon_data->reg_table_len; if (lcd_tcon_data->reg_table == NULL) { @@ -254,13 +354,43 @@ static int lcd_tcon_config(struct aml_lcd_drv_s *lcd_drv) __func__); return -1; } - LCDPR("tcon: load key len: %d\n", key_len); + LCDPR("tcon: load unifykey len: %d\n", key_len); +#else + reg_len = lcd_tcon_data->reg_table_len; + lcd_tcon_data->reg_table = uhd_tcon_setting_ceds_h10; + key_len = sizeof(uhd_tcon_setting_ceds_h10)/sizeof(unsigned char); + if (key_len != reg_len) { + lcd_tcon_data->reg_table = NULL; + LCDERR("%s: !!!!!!!!tcon unifykey load length error!!!!!!!!\n", + __func__); + return -1; + } + LCDPR("tcon: load default table len: %d\n", key_len); +#endif lcd_tcon_intr_init(lcd_drv); return 0; } +static void lcd_tcon_config_delayed(struct work_struct *work) +{ + struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); + int key_init_flag = 0; + int i = 0; + + key_init_flag = key_unify_get_init_flag(); + while (key_init_flag == 0) { + if (i++ >= LCD_UNIFYKEY_WAIT_TIMEOUT) + break; + msleep(20); + key_init_flag = key_unify_get_init_flag(); + } + LCDPR("tcon: key_init_flag=%d, i=%d\n", key_init_flag, i); + if (key_init_flag) + lcd_tcon_config(lcd_drv); +} + /* ********************************** * tcon function api * ********************************** @@ -353,10 +483,12 @@ int lcd_tcon_info_print(char *buf, int offset) "tcon info:\n" "core_reg_width: %d\n" "reg_table_len: %d\n" - "axi_offset_addr: 0x%08x\n\n", + "axi_mem paddr: 0x%lx\n" + "axi_mem size: 0x%x\n\n", lcd_tcon_data->core_reg_width, lcd_tcon_data->reg_table_len, - lcd_tcon_data->axi_offset_addr); + (unsigned long)tcon_rmem.mem_paddr, + tcon_rmem.mem_size); return len; } @@ -422,8 +554,8 @@ int lcd_tcon_od_set(int flag) } if (flag) { - if (lcd_tcon_data->axi_offset_addr == 0) { - LCDERR("%s: invalid fb, disable od function\n", + if (tcon_rmem.flag == 0) { + LCDERR("%s: invalid memory, disable od function\n", __func__); return -1; } @@ -458,11 +590,11 @@ int lcd_tcon_od_get(void) ret = lcd_tcon_valid_check(); if (ret) - return -1; + return 0; if (lcd_tcon_data->reg_core_od == REG_LCD_TCON_MAX) { LCDERR("%s: invalid od reg\n", __func__); - return -1; + return 0; } reg = lcd_tcon_data->reg_core_od; @@ -508,10 +640,11 @@ void lcd_tcon_disable(void) /* disable over_drive */ if (lcd_tcon_data->reg_core_od != REG_LCD_TCON_MAX) { reg = lcd_tcon_data->reg_core_od + TCON_CORE_REG_START; + bit = lcd_tcon_data->bit_od_en; if (lcd_tcon_data->core_reg_width == 8) - lcd_tcon_write_byte(reg, 0); + lcd_tcon_setb_byte(reg, 0, bit, 1); else - lcd_tcon_write(reg, 0); + lcd_tcon_setb(reg, 0, bit, 1); msleep(100); } @@ -550,14 +683,14 @@ static struct lcd_tcon_data_s tcon_data_tl1 = { .reg_top_ctrl = TCON_TOP_CTRL, .bit_en = BIT_TOP_EN_TL1, - .reg_core_od = REG_LCD_TCON_MAX, + .reg_core_od = REG_CORE_OD_TL1, .bit_od_en = BIT_OD_EN_TL1, - .reg_core_ctrl_timing_base = REG_CORE_CTRL_TIMING_BASE_TL1, + .reg_core_ctrl_timing_base = REG_LCD_TCON_MAX, .ctrl_timing_offset = CTRL_TIMING_OFFSET_TL1, .ctrl_timing_cnt = CTRL_TIMING_CNT_TL1, - .axi_offset_addr = 0, + .axi_mem_size = 0xc00000, .reg_table = NULL, .tcon_enable = lcd_tcon_enable_tl1, @@ -565,14 +698,16 @@ static struct lcd_tcon_data_s tcon_data_tl1 = { int lcd_tcon_probe(struct aml_lcd_drv_s *lcd_drv) { + int key_init_flag = 0; int ret = 0; + lcd_tcon_data = NULL; switch (lcd_drv->data->chip_type) { case LCD_CHIP_TL1: - lcd_tcon_data = &tcon_data_tl1; switch (lcd_drv->lcd_config->lcd_basic.lcd_type) { case LCD_MLVDS: case LCD_P2P: + lcd_tcon_data = &tcon_data_tl1; lcd_tcon_data->tcon_valid = 1; break; default: @@ -580,44 +715,103 @@ int lcd_tcon_probe(struct aml_lcd_drv_s *lcd_drv) } break; default: - lcd_tcon_data = NULL; break; } - ret = lcd_tcon_valid_check(); - if (ret) - return -1; + if (lcd_tcon_data == NULL) + return 0; - ret = lcd_tcon_config(lcd_drv); + /* init reserved memory */ + ret = of_reserved_mem_device_init(lcd_drv->dev); + if (ret) { + LCDERR("tcon: init reserved memory failed\n"); + } else { +#ifdef CONFIG_CMA + tcon_rmem.mem_vaddr = dma_alloc_coherent(lcd_drv->dev, + lcd_tcon_data->axi_mem_size, + &tcon_rmem.mem_paddr, + GFP_KERNEL); + if (tcon_rmem.mem_vaddr == NULL) { + LCDERR("tcon axi_mem alloc failed\n"); + tcon_rmem.mem_paddr = 0; + } else { + tcon_rmem.mem_size = lcd_tcon_data->axi_mem_size; + tcon_rmem.flag = 1; + LCDPR("tcon: axi_mem base:0x%lx, size:0x%x\n", + (unsigned long)tcon_rmem.mem_paddr, + tcon_rmem.mem_size); + } +#else + if ((void *)tcon_rmem.mem_paddr == NULL) { + LCDERR("tcon axi_mem alloc failed\n"); + } else { + tcon_rmem.flag = 1; + LCDPR("tcon: axi_mem base:0x%lx, size:0x%x\n", + (unsigned long)tcon_rmem.mem_paddr, + tcon_rmem.mem_size); + } +#endif + } + + INIT_DELAYED_WORK(&lcd_tcon_delayed_work, lcd_tcon_config_delayed); + + key_init_flag = key_unify_get_init_flag(); + if (key_init_flag) { + ret = lcd_tcon_config(lcd_drv); + } else { + if (lcd_drv->workqueue) { + queue_delayed_work(lcd_drv->workqueue, + &lcd_tcon_delayed_work, + msecs_to_jiffies(2000)); + } else { + schedule_delayed_work(&lcd_tcon_delayed_work, + msecs_to_jiffies(2000)); + } + } return ret; } -static int rmem_tcon_fb_device_init(struct reserved_mem *rmem, +int lcd_tcon_remove(struct aml_lcd_drv_s *lcd_drv) +{ + if (tcon_rmem.flag) { + LCDPR("tcon free memory: base:0x%lx, size:0x%x\n", + (unsigned long)tcon_rmem.mem_paddr, + tcon_rmem.mem_size); +#ifdef CONFIG_CMA + dma_free_coherent(lcd_drv->dev, tcon_rmem.mem_size, + tcon_rmem.mem_vaddr, + (dma_addr_t)&tcon_rmem.mem_paddr); +#else + /* to do */ +#endif + } + + if (lcd_tcon_data) { + /* lcd_tcon_data == NULL; */ + lcd_tcon_data->tcon_valid = 0; + } + + return 0; +} + +static int __init tcon_fb_device_init(struct reserved_mem *rmem, struct device *dev) { return 0; } -static const struct reserved_mem_ops rmem_tcon_fb_ops = { - .device_init = rmem_tcon_fb_device_init, +static const struct reserved_mem_ops tcon_fb_ops = { + .device_init = tcon_fb_device_init, }; -static int __init rmem_tcon_fb_setup(struct reserved_mem *rmem) +static int __init tcon_fb_setup(struct reserved_mem *rmem) { - /* - * phys_addr_t align = PAGE_SIZE; - * phys_addr_t mask = align - 1; - * if ((rmem->base & mask) || (rmem->size & mask)) { - * LCDERR("Reserved memory: incorrect alignment of region\n"); - * return -EINVAL; - * } - */ - tcon_fb_rmem.base = rmem->base; - tcon_fb_rmem.size = rmem->size; - rmem->ops = &rmem_tcon_fb_ops; - LCDPR("tcon: Reserved memory: created fb at 0x%p, size %ld MiB\n", - (void *)rmem->base, (unsigned long)rmem->size / SZ_1M); + tcon_rmem.mem_paddr = rmem->base; + tcon_rmem.mem_size = rmem->size; + rmem->ops = &tcon_fb_ops; + LCDPR("tcon: Reserved memory: created fb at 0x%lx, size %ld MiB\n", + (unsigned long)rmem->base, (unsigned long)rmem->size / SZ_1M); return 0; } -RESERVEDMEM_OF_DECLARE(fb, "amlogic, lcd_tcon-memory", rmem_tcon_fb_setup); +RESERVEDMEM_OF_DECLARE(fb, "amlogic, lcd_tcon-memory", tcon_fb_setup); diff --git a/drivers/amlogic/media/vout/lcd/lcd_tcon.h b/drivers/amlogic/media/vout/lcd/lcd_tcon.h index 8f210e623767..e557923d8cea 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_tcon.h +++ b/drivers/amlogic/media/vout/lcd/lcd_tcon.h @@ -17,6 +17,9 @@ #ifndef __AML_LCD_TCON_H__ #define __AML_LCD_TCON_H__ +#include +#include +#include #include #define REG_LCD_TCON_MAX 0xffff @@ -37,12 +40,19 @@ struct lcd_tcon_data_s { unsigned int ctrl_timing_offset; unsigned int ctrl_timing_cnt; - unsigned int axi_offset_addr; + unsigned int axi_mem_size; unsigned char *reg_table; int (*tcon_enable)(struct lcd_config_s *pconf); }; +struct tcon_rmem_s { + unsigned char flag; + void *mem_vaddr; + phys_addr_t mem_paddr; + unsigned int mem_size; +}; + /* ********************************** * tcon config * ********************************** @@ -54,8 +64,8 @@ struct lcd_tcon_data_s { #define BIT_TOP_EN_TL1 4 -#define REG_CORE_OD_TL1 0x5c -#define BIT_OD_EN_TL1 6 +#define REG_CORE_OD_TL1 0x247 +#define BIT_OD_EN_TL1 0 #define REG_CORE_CTRL_TIMING_BASE_TL1 0x1b #define CTRL_TIMING_OFFSET_TL1 12 #define CTRL_TIMING_CNT_TL1 0 diff --git a/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_drv.c b/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_drv.c index e2e8f9b13b00..d72795132f4a 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_drv.c +++ b/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_drv.c @@ -73,187 +73,24 @@ static int lcd_type_supported(struct lcd_config_s *pconf) return ret; } -static void lcd_vbyone_phy_set(struct lcd_config_s *pconf, int status) -{ - unsigned int vswing, preem, ext_pullup; - unsigned int data32; - unsigned int rinner_table[] = {0xa, 0xa, 0x6, 0x4}; - - if (lcd_debug_print_flag) - LCDPR("%s: %d\n", __func__, status); - - if (status) { - ext_pullup = (pconf->lcd_control.vbyone_config->phy_vswing >> 4) - & 0x3; - vswing = pconf->lcd_control.vbyone_config->phy_vswing & 0xf; - preem = pconf->lcd_control.vbyone_config->phy_preem; - if (vswing > 7) { - LCDERR("%s: wrong vswing_level=%d, use default\n", - __func__, vswing); - vswing = VX1_PHY_VSWING_DFT; - } - if (preem > 7) { - LCDERR("%s: wrong preemphasis_level=%d, use default\n", - __func__, preem); - preem = VX1_PHY_PREEM_DFT; - } - if (ext_pullup) - data32 = VX1_PHY_CNTL1_G9TV_PULLUP | (vswing << 3); - else - data32 = VX1_PHY_CNTL1_G9TV | (vswing << 3); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL1, data32); - data32 = VX1_PHY_CNTL2_G9TV | (preem << 20) | - (rinner_table[ext_pullup] << 8); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL2, data32); - data32 = VX1_PHY_CNTL3_G9TV; - /*lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL2, 0x00000a7c);*/ - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL3, data32); - } else { - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL1, 0x0); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL2, 0x0); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL3, 0x0); - } -} - -static void lcd_lvds_phy_set(struct lcd_config_s *pconf, int status) -{ - unsigned int vswing, preem, clk_vswing, clk_preem, channel_on; - unsigned int data32; - - if (lcd_debug_print_flag) - LCDPR("%s: %d\n", __func__, status); - - if (status) { - vswing = pconf->lcd_control.lvds_config->phy_vswing; - preem = pconf->lcd_control.lvds_config->phy_preem; - clk_vswing = pconf->lcd_control.lvds_config->phy_clk_vswing; - clk_preem = pconf->lcd_control.lvds_config->phy_clk_preem; - if (vswing > 7) { - LCDERR("%s: wrong vswing=%d, use default\n", - __func__, vswing); - vswing = LVDS_PHY_VSWING_DFT; - } - channel_on = lcd_lvds_channel_on_value(pconf); - - if (preem > 7) { - LCDERR("%s: wrong preem=%d, use default\n", - __func__, preem); - preem = LVDS_PHY_PREEM_DFT; - } - if (clk_vswing > 3) { - LCDERR("%s: wrong clk_vswing=%d, use default\n", - __func__, clk_vswing); - clk_vswing = LVDS_PHY_CLK_VSWING_DFT; - } - if (clk_preem > 7) { - LCDERR("%s: wrong clk_preem=%d, use default\n", - __func__, clk_preem); - clk_preem = LVDS_PHY_CLK_PREEM_DFT; - } - - data32 = LVDS_PHY_CNTL1_G9TV | - (vswing << 26) | (preem << 0); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL1, data32); - data32 = LVDS_PHY_CNTL2_G9TV; - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL2, data32); - data32 = LVDS_PHY_CNTL3_G9TV | - (channel_on << 16) | - (clk_vswing << 8) | (clk_preem << 5); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL3, data32); - } else { - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL1, 0x0); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL2, 0x0); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL3, 0x0); - } -} - -static void lcd_mlvds_phy_set(struct lcd_config_s *pconf, int status) -{ - unsigned int vswing, preem; - unsigned int data32; - - if (lcd_debug_print_flag) - LCDPR("%s: %d\n", __func__, status); - - if (status) { - vswing = pconf->lcd_control.mlvds_config->phy_vswing; - preem = pconf->lcd_control.mlvds_config->phy_preem; - if (vswing > 7) { - LCDERR("%s: wrong vswing_level=%d, use default\n", - __func__, vswing); - vswing = LVDS_PHY_VSWING_DFT; - } - if (preem > 3) { - LCDERR("%s: wrong preemphasis_level=%d, use default\n", - __func__, preem); - preem = LVDS_PHY_PREEM_DFT; - } - - data32 = MLVDS_PHY_CNTL1_TL1 | - (vswing << 3) | (vswing << 0) | (preem << 23); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL1, data32); - data32 = MLVDS_PHY_CNTL2_TL1 | - (preem << 14) | (preem << 12) | - (preem << 26) | (preem << 24); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL2, data32); - data32 = MLVDS_PHY_CNTL3_TL1 | - (preem << 6) | (preem << 4) | - (preem << 2) | (preem << 0) | (preem << 30); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL3, data32); - } else { - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL1, 0x0); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL2, 0x0); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL3, 0x0); - } -} - -static void lcd_p2p_phy_set(struct lcd_config_s *pconf, int status) -{ - unsigned int vswing, preem; - unsigned int data32; - - if (lcd_debug_print_flag) - LCDPR("%s: %d\n", __func__, status); - - if (status) { - vswing = pconf->lcd_control.p2p_config->phy_vswing; - preem = pconf->lcd_control.p2p_config->phy_preem; - if (vswing > 7) { - LCDERR("%s: wrong vswing_level=%d, use default\n", - __func__, vswing); - vswing = LVDS_PHY_VSWING_DFT; - } - if (preem > 3) { - LCDERR("%s: wrong preemphasis_level=%d, use default\n", - __func__, preem); - preem = LVDS_PHY_PREEM_DFT; - } - - data32 = MLVDS_PHY_CNTL1_TL1 | - (vswing << 3) | (vswing << 0) | (preem << 23); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL1, data32); - data32 = MLVDS_PHY_CNTL2_TL1 | - (preem << 14) | (preem << 12) | - (preem << 26) | (preem << 24); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL2, data32); - data32 = MLVDS_PHY_CNTL3_TL1 | - (preem << 6) | (preem << 4) | - (preem << 2) | (preem << 0) | (preem << 30); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL3, data32); - } else { - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL1, 0x0); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL2, 0x0); - lcd_hiu_write(HHI_DIF_CSI_PHY_CNTL3, 0x0); - } -} - static void lcd_encl_tcon_set(struct lcd_config_s *pconf) { + unsigned int lcd_bits; + lcd_vcbus_write(L_RGB_BASE_ADDR, 0); lcd_vcbus_write(L_RGB_COEFF_ADDR, 0x400); aml_lcd_notifier_call_chain(LCD_EVENT_GAMMA_UPDATE, NULL); - switch (pconf->lcd_basic.lcd_bits) { + switch (pconf->lcd_basic.lcd_type) { + case LCD_MLVDS: + case LCD_P2P: + lcd_bits = 10; + break; + default: + lcd_bits = pconf->lcd_basic.lcd_bits; + break; + } + switch (lcd_bits) { case 8: lcd_vcbus_write(L_DITH_CNTL_ADDR, 0x400); break; @@ -318,6 +155,20 @@ static void lcd_venc_set(struct lcd_config_s *pconf) lcd_vcbus_write(ENCL_VIDEO_HAVON_END, h_active - 1 + video_on_pixel); lcd_vcbus_write(ENCL_VIDEO_VAVON_BLINE, video_on_line); lcd_vcbus_write(ENCL_VIDEO_VAVON_ELINE, v_active - 1 + video_on_line); + switch (pconf->lcd_basic.lcd_type) { + case LCD_P2P: + lcd_vcbus_write(ENCL_VIDEO_V_PRE_DE_BLINE, + video_on_line - 1 - 4); + lcd_vcbus_write(ENCL_VIDEO_V_PRE_DE_ELINE, + video_on_line - 1); + lcd_vcbus_write(ENCL_VIDEO_H_PRE_DE_BEGIN, + video_on_pixel + PRE_DE_DELAY); + lcd_vcbus_write(ENCL_VIDEO_H_PRE_DE_END, + h_active - 1 + video_on_pixel + PRE_DE_DELAY); + break; + default: + break; + } lcd_vcbus_write(ENCL_VIDEO_HSO_BEGIN, pconf->lcd_timing.hs_hs_addr); lcd_vcbus_write(ENCL_VIDEO_HSO_END, pconf->lcd_timing.hs_he_addr); @@ -330,7 +181,8 @@ static void lcd_venc_set(struct lcd_config_s *pconf) switch (lcd_drv->data->chip_type) { case LCD_CHIP_TL1: - lcd_vcbus_write(ENCL_INBUF_CNTL1, (1 << 14) | (h_active - 1)); + /*[15:14]: 2'b10 or 2'b01*/ + lcd_vcbus_write(ENCL_INBUF_CNTL1, (2 << 14) | (h_active - 1)); lcd_vcbus_write(ENCL_INBUF_CNTL0, 0x200); break; default: @@ -352,7 +204,21 @@ static void lcd_venc_set(struct lcd_config_s *pconf) static void lcd_lvds_clk_util_set(struct lcd_config_s *pconf) { + struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); unsigned int phy_div; + unsigned int reg_cntl0, reg_cntl1; + + switch (lcd_drv->data->chip_type) { + case LCD_CHIP_TL1: + case LCD_CHIP_TM2: + reg_cntl0 = HHI_LVDS_TX_PHY_CNTL0_TL1; + reg_cntl1 = HHI_LVDS_TX_PHY_CNTL1_TL1; + break; + default: + reg_cntl0 = HHI_LVDS_TX_PHY_CNTL0; + reg_cntl1 = HHI_LVDS_TX_PHY_CNTL1; + break; + } if (pconf->lcd_control.lvds_config->dual_port) phy_div = 2; @@ -360,19 +226,28 @@ static void lcd_lvds_clk_util_set(struct lcd_config_s *pconf) phy_div = 1; /* set fifo_clk_sel: div 7 */ - lcd_hiu_write(HHI_LVDS_TX_PHY_CNTL0, (1 << 6)); + lcd_hiu_write(reg_cntl0, (1 << 6)); /* set cntl_ser_en: 8-channel to 1 */ - lcd_hiu_setb(HHI_LVDS_TX_PHY_CNTL0, 0xfff, 16, 12); + lcd_hiu_setb(reg_cntl0, 0xfff, 16, 12); + switch (lcd_drv->data->chip_type) { /* pn swap */ + case LCD_CHIP_TL1: + case LCD_CHIP_TM2: + lcd_hiu_setb(reg_cntl0, 1, 2, 1); + break; + default: + break; + } /* decoupling fifo enable, gated clock enable */ - lcd_hiu_write(HHI_LVDS_TX_PHY_CNTL1, + lcd_hiu_write(reg_cntl1, (1 << 30) | ((phy_div - 1) << 25) | (1 << 24)); /* decoupling fifo write enable after fifo enable */ - lcd_hiu_setb(HHI_LVDS_TX_PHY_CNTL1, 1, 31, 1); + lcd_hiu_setb(reg_cntl1, 1, 31, 1); } static void lcd_lvds_control_set(struct lcd_config_s *pconf) { + struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); unsigned int bit_num = 1; unsigned int pn_swap, port_swap, lane_reverse; unsigned int dual_port, fifo_mode; @@ -423,10 +298,17 @@ static void lcd_lvds_control_set(struct lcd_config_s *pconf) (1 << 12) | /* g_select //0:R, 1:G, 2:B, 3:0 */ (2 << 14)); /* b_select //0:R, 1:G, 2:B, 3:0 */ - lcd_vcbus_setb(LCD_PORT_SWAP, port_swap, 12, 1); - - if (lane_reverse) - lcd_vcbus_setb(LVDS_GEN_CNTL, 0x03, 13, 2); + switch (lcd_drv->data->chip_type) { + case LCD_CHIP_TL1: + lcd_vcbus_write(P2P_CH_SWAP0, 0x76543210); + lcd_vcbus_write(P2P_CH_SWAP1, 0xba98); + break; + default: + lcd_vcbus_setb(LCD_PORT_SWAP, port_swap, 12, 1); + if (lane_reverse) + lcd_vcbus_setb(LVDS_GEN_CNTL, 0x03, 13, 2); + break; + } lcd_vcbus_write(LVDS_GEN_CNTL, (lcd_vcbus_read(LVDS_GEN_CNTL) | (1 << 4) | (fifo_mode << 0))); @@ -439,13 +321,16 @@ static void lcd_lvds_disable(void) lcd_vcbus_setb(LVDS_GEN_CNTL, 0, 3, 1); /* disable lvds fifo */ } -static void lcd_mlvds_clk_util_set(struct lcd_config_s *pconf) +static void lcd_mlvds_control_set(struct lcd_config_s *pconf) { - unsigned int lcd_bits, div_sel; + unsigned int div_sel; + unsigned int channel_sel0, channel_sel1; - lcd_bits = pconf->lcd_basic.lcd_bits; + if (lcd_debug_print_flag) + LCDPR("%s\n", __func__); - switch (lcd_bits) { + /* phy_div: 0=div6, 1=div 7, 2=div8, 3=div10 */ + switch (pconf->lcd_basic.lcd_bits) { case 6: div_sel = 0; break; @@ -457,60 +342,22 @@ static void lcd_mlvds_clk_util_set(struct lcd_config_s *pconf) break; } - /* set fifo_clk_sel */ - lcd_hiu_write(HHI_LVDS_TX_PHY_CNTL0, (div_sel << 6)); - /* set cntl_ser_en: 8-channel to 1 */ - lcd_hiu_setb(HHI_LVDS_TX_PHY_CNTL0, 0xfff, 16, 12); + /* fifo_clk_sel[7:6]: 0=div6, 1=div 7, 2=div8, 3=div10 */ + lcd_hiu_write(HHI_LVDS_TX_PHY_CNTL0_TL1, (div_sel << 6)); + /* serializer_en[27:16] */ + lcd_hiu_setb(HHI_LVDS_TX_PHY_CNTL0_TL1, 0xfff, 16, 12); + /* pn swap[2] */ + lcd_hiu_setb(HHI_LVDS_TX_PHY_CNTL0_TL1, 1, 2, 1); - /* decoupling fifo enable, gated clock enable */ - lcd_hiu_write(HHI_LVDS_TX_PHY_CNTL1, - (1 << 30) | (0 << 25) | (1 << 24)); - /* decoupling fifo write enable after fifo enable */ - lcd_hiu_setb(HHI_LVDS_TX_PHY_CNTL1, 1, 31, 1); -} + /* fifo enable[30], phy_clock gating[24] */ + lcd_hiu_write(HHI_LVDS_TX_PHY_CNTL1_TL1, (1 << 30) | (1 << 24)); + /* fifo write enable[31] */ + lcd_hiu_setb(HHI_LVDS_TX_PHY_CNTL1_TL1, 1, 31, 1); -static void lcd_mlvds_control_set(struct lcd_config_s *pconf) -{ - unsigned int bit_num = 1; - - if (lcd_debug_print_flag) - LCDPR("%s\n", __func__); - - lcd_mlvds_clk_util_set(pconf); - - switch (pconf->lcd_basic.lcd_bits) { - case 10: - bit_num = 0; - break; - case 8: - bit_num = 1; - break; - case 6: - bit_num = 2; - break; - case 4: - bit_num = 3; - break; - default: - bit_num = 1; - break; - } - - lcd_vcbus_write(LVDS_PACK_CNTL_ADDR, - (1 << 0) | // repack //[1:0] - (0 << 3) | // reserve - (0 << 4) | // lsb first - (0 << 5) | // pn swap - (1 << 6) | // dual port - (0 << 7) | // use tcon control - (bit_num << 8) | // 0:10bits, 1:8bits, 2:6bits, 3:4bits. - (0 << 10) | //r_select //0:R, 1:G, 2:B, 3:0 - (1 << 12) | //g_select //0:R, 1:G, 2:B, 3:0 - (2 << 14)); //b_select //0:R, 1:G, 2:B, 3:0; - - lcd_vcbus_write(LVDS_GEN_CNTL, - (lcd_vcbus_read(LVDS_GEN_CNTL) | (1 << 4) | (0x3 << 0))); - lcd_vcbus_setb(LVDS_GEN_CNTL, 1, 3, 1); + channel_sel0 = pconf->lcd_control.mlvds_config->channel_sel0; + channel_sel1 = pconf->lcd_control.mlvds_config->channel_sel1; + lcd_vcbus_write(P2P_CH_SWAP0, channel_sel0); + lcd_vcbus_write(P2P_CH_SWAP1, channel_sel1); lcd_tcon_enable(pconf); } @@ -518,8 +365,6 @@ static void lcd_mlvds_control_set(struct lcd_config_s *pconf) static void lcd_mlvds_disable(void) { lcd_tcon_disable(); - - lcd_vcbus_setb(LVDS_GEN_CNTL, 0, 3, 1); /* disable lvds fifo */ } #if 0 @@ -548,6 +393,20 @@ static void lcd_vbyone_clk_util_set(struct lcd_config_s *pconf) { unsigned int lcd_bits; unsigned int div_sel, phy_div; + struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); + unsigned int reg_cntl0, reg_cntl1; + + switch (lcd_drv->data->chip_type) { + case LCD_CHIP_TL1: + case LCD_CHIP_TM2: + reg_cntl0 = HHI_LVDS_TX_PHY_CNTL0_TL1; + reg_cntl1 = HHI_LVDS_TX_PHY_CNTL1_TL1; + break; + default: + reg_cntl0 = HHI_LVDS_TX_PHY_CNTL0; + reg_cntl1 = HHI_LVDS_TX_PHY_CNTL1; + break; + } phy_div = pconf->lcd_control.vbyone_config->phy_div; lcd_bits = pconf->lcd_basic.lcd_bits; @@ -567,15 +426,23 @@ static void lcd_vbyone_clk_util_set(struct lcd_config_s *pconf) break; } /* set fifo_clk_sel */ - lcd_hiu_write(HHI_LVDS_TX_PHY_CNTL0, (div_sel << 6)); + lcd_hiu_write(reg_cntl0, (div_sel << 6)); /* set cntl_ser_en: 8-channel to 1 */ - lcd_hiu_setb(HHI_LVDS_TX_PHY_CNTL0, 0xfff, 16, 12); + lcd_hiu_setb(reg_cntl0, 0xfff, 16, 12); + switch (lcd_drv->data->chip_type) { /* pn swap */ + case LCD_CHIP_TL1: + case LCD_CHIP_TM2: + lcd_hiu_setb(reg_cntl0, 1, 2, 1); + break; + default: + break; + } /* decoupling fifo enable, gated clock enable */ - lcd_hiu_write(HHI_LVDS_TX_PHY_CNTL1, + lcd_hiu_write(reg_cntl1, (1 << 30) | ((phy_div - 1) << 25) | (1 << 24)); /* decoupling fifo write enable after fifo enable */ - lcd_hiu_setb(HHI_LVDS_TX_PHY_CNTL1, 1, 31, 1); + lcd_hiu_setb(reg_cntl1, 1, 31, 1); } static int lcd_vbyone_lanes_set(int lane_num, int byte_mode, int region_num, @@ -647,6 +514,31 @@ static int lcd_vbyone_lanes_set(int lane_num, int byte_mode, int region_num, return 0; } +static void lcd_vbyone_hw_filter(int flag) +{ + struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); + + switch (lcd_drv->data->chip_type) { + case LCD_CHIP_TL1: + case LCD_CHIP_TM2: + if (flag) { + lcd_vcbus_write(VBO_INFILTER_TICK_PERIOD_L, 0xffff); + lcd_vcbus_write(VBO_INFILTER_TICK_PERIOD_H, 0xf); + lcd_vcbus_setb(VBO_INSGN_CTRL, 0x7, 8, 4); + lcd_vcbus_setb(VBO_INSGN_CTRL, 0x7, 12, 4); + } else { + lcd_vcbus_write(VBO_INFILTER_TICK_PERIOD_L, 0xff); + lcd_vcbus_write(VBO_INFILTER_TICK_PERIOD_H, 0x0); + lcd_vcbus_setb(VBO_INSGN_CTRL, 0x7, 8, 4); + lcd_vcbus_setb(VBO_INSGN_CTRL, 0x7, 12, 4); + } + break; + default: + lcd_vcbus_write(VBO_INFILTER_CTRL, 0xff77); + break; + } +} + static void lcd_vbyone_sw_reset(void) { if (lcd_debug_print_flag) @@ -775,8 +667,9 @@ static void lcd_vbyone_control_set(struct lcd_config_s *pconf) /* lcd_vcbus_setb(LCD_PORT_SWAP, 1, 8, 1);//reverse lane output order */ /* Mux pads in combo-phy: 0 for dsi; 1 for lvds or vbyone; 2 for edp */ - lcd_hiu_write(HHI_DSI_LVDS_EDP_CNTL0, 0x1); - lcd_vcbus_write(VBO_INFILTER_CTRL, 0xff77); + /*lcd_hiu_write(HHI_DSI_LVDS_EDP_CNTL0, 0x1);*/ + + lcd_vbyone_hw_filter(0); lcd_vcbus_setb(VBO_INSGN_CTRL, 0, 2, 2); lcd_vcbus_setb(VBO_CTRL_L, 1, 0, 1); @@ -814,6 +707,7 @@ void lcd_vbyone_interrupt_enable(int flag) vx1_conf = lcd_drv->lcd_config->lcd_control.vbyone_config; if (flag) { + lcd_vbyone_hw_filter(1); if (vx1_conf->intr_en) { vx1_fsm_acq_st = 0; /* clear interrupt */ @@ -868,6 +762,7 @@ static void lcd_vbyone_interrupt_init(struct aml_lcd_drv_s *lcd_drv) /* release sw filter ctrl in uboot */ lcd_vcbus_setb(VBO_INSGN_CTRL, 0, 0, 1); + lcd_vbyone_hw_filter(1); /* set hold in FSM_ACQ */ if (vx1_conf->vsync_intr_en == 3) @@ -1102,19 +997,23 @@ static irqreturn_t lcd_vbyone_vsync_isr(int irq, void *dev_id) if (vsync_cnt < VSYNC_CNT_VX1_RESET) vsync_cnt++; else if (vsync_cnt == VSYNC_CNT_VX1_RESET) { + lcd_vbyone_hw_filter(0); lcd_vbyone_sw_reset(); vsync_cnt++; } else if ((vsync_cnt > VSYNC_CNT_VX1_RESET) && (vsync_cnt < VSYNC_CNT_VX1_STABLE)) { - if (lcd_vcbus_read(VBO_STATUS_L) & 0x20) + if (lcd_vcbus_read(VBO_STATUS_L) & 0x20) { vsync_cnt = VSYNC_CNT_VX1_STABLE; - else + lcd_vbyone_hw_filter(1); + } else { vsync_cnt++; + } } } else if (vx1_conf->vsync_intr_en == 2) { if (vsync_cnt >= 5) { vsync_cnt = 0; if (!(lcd_vcbus_read(VBO_STATUS_L) & 0x20)) { + lcd_vbyone_hw_filter(0); lcd_vbyone_sw_reset(); LCDPR("vx1 sw_reset 2\n"); while (lcd_vcbus_read(VBO_STATUS_L) & 0x4) @@ -1122,6 +1021,8 @@ static irqreturn_t lcd_vbyone_vsync_isr(int irq, void *dev_id) lcd_vcbus_setb(VBO_INTR_STATE_CTRL, 0, 15, 1); lcd_vcbus_setb(VBO_INTR_STATE_CTRL, 1, 15, 1); + } else { + lcd_vbyone_hw_filter(1); } } else vsync_cnt++; @@ -1284,6 +1185,7 @@ static irqreturn_t lcd_vbyone_interrupt_handler(int irq, void *dev_id) #if (VX1_FSM_ACQ_NEXT == VX1_FSM_ACQ_NEXT_RELEASE_HOLDER) lcd_vcbus_setb(VBO_FSM_HOLDER_L, 0xffff, 0, 16); #endif + lcd_vbyone_hw_filter(1); LCDPR("vx1 fsm stable\n"); } } @@ -1295,10 +1197,52 @@ static irqreturn_t lcd_vbyone_interrupt_handler(int irq, void *dev_id) static void lcd_p2p_control_set(struct lcd_config_s *pconf) { + struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); + unsigned int reg_cntl0, reg_cntl1; + unsigned int phy_div; + unsigned int channel_sel0, channel_sel1; + if (lcd_debug_print_flag) LCDPR("%s\n", __func__); - lcd_vbyone_control_set(pconf); + /* phy_div: 0=div6, 1=div 7, 2=div8, 3=div10 */ + switch (pconf->lcd_control.p2p_config->p2p_type) { + case P2P_CHPI: /* 8/10 coding */ + phy_div = 3; + break; + default: + phy_div = 2; + break; + } + + switch (lcd_drv->data->chip_type) { + case LCD_CHIP_TL1: + case LCD_CHIP_TM2: + reg_cntl0 = HHI_LVDS_TX_PHY_CNTL0_TL1; + reg_cntl1 = HHI_LVDS_TX_PHY_CNTL1_TL1; + break; + default: + reg_cntl0 = HHI_LVDS_TX_PHY_CNTL0; + reg_cntl1 = HHI_LVDS_TX_PHY_CNTL1; + break; + } + + /* fifo_clk_sel[7:6]: 0=div6, 1=div 7, 2=div8, 3=div10 */ + lcd_hiu_write(reg_cntl0, (phy_div << 6)); + /* serializer_en[27:16] */ + lcd_hiu_setb(reg_cntl0, 0xfff, 16, 12); + /* pn swap[2] */ + lcd_hiu_setb(reg_cntl0, 1, 2, 1); + + /* fifo enable[30], phy_clock gating[24] */ + lcd_hiu_write(reg_cntl1, (1 << 30) | (1 << 24)); + /* fifo write enable[31] */ + lcd_hiu_setb(reg_cntl1, 1, 31, 1); + + channel_sel0 = pconf->lcd_control.p2p_config->channel_sel0; + channel_sel1 = pconf->lcd_control.p2p_config->channel_sel1; + lcd_vcbus_write(P2P_CH_SWAP0, channel_sel0); + lcd_vcbus_write(P2P_CH_SWAP1, channel_sel1); lcd_tcon_enable(pconf); } @@ -1306,8 +1250,6 @@ static void lcd_p2p_control_set(struct lcd_config_s *pconf) static void lcd_p2p_disable(void) { lcd_tcon_disable(); - - lcd_vbyone_disable(); } static unsigned int vbyone_lane_num[] = { @@ -1370,7 +1312,7 @@ static void lcd_vbyone_config_set(struct lcd_config_s *pconf) bit_rate = bit_rate * 1000; /* Hz */ pconf->lcd_control.vbyone_config->phy_div = phy_div; - pconf->lcd_control.vbyone_config->bit_rate = bit_rate; + pconf->lcd_timing.bit_rate = bit_rate; if (lcd_debug_print_flag) { LCDPR("lane_count=%u, bit_rate = %uMHz, pclk=%u.%03uMhz\n", @@ -1383,7 +1325,7 @@ static void lcd_mlvds_config_set(struct lcd_config_s *pconf) { unsigned int bit_rate, pclk; unsigned int lcd_bits, channel_num; - unsigned int channel_sel0, channel_sel1, pi_clk_sel; + unsigned int channel_sel0, channel_sel1, pi_clk_sel = 0; unsigned int i, temp; if (lcd_debug_print_flag) @@ -1394,7 +1336,7 @@ static void lcd_mlvds_config_set(struct lcd_config_s *pconf) pclk = pconf->lcd_timing.lcd_clk / 1000; bit_rate = lcd_bits * 3 * pclk / channel_num; - pconf->lcd_control.mlvds_config->bit_rate = bit_rate * 1000; + pconf->lcd_timing.bit_rate = bit_rate * 1000; if (lcd_debug_print_flag) { LCDPR("channel_num=%u, bit_rate=%u.%03uMHz, pclk=%u.%03uMhz\n", @@ -1403,27 +1345,30 @@ static void lcd_mlvds_config_set(struct lcd_config_s *pconf) } /* pi_clk select */ - /* mlvds channel: //tx 10 channels - * 0: d0_a - * 1: d1_a - * 2: d2_a - * 3: clk_a - * 4: d0_b - * 5: d1_b - * 6: d2_b - * 7: clk_b - */ channel_sel0 = pconf->lcd_control.mlvds_config->channel_sel0; channel_sel1 = pconf->lcd_control.mlvds_config->channel_sel1; - pi_clk_sel = 0; + /* mlvds channel: //tx 12 channels + * 0: clk_a + * 1: d0_a + * 2: d1_a + * 3: d2_a + * 4: d3_a + * 5: d4_a + * 6: clk_b + * 7: d0_b + * 8: d1_b + * 9: d2_b + * 10: d3_b + * 11: d4_b + */ for (i = 0; i < 8; i++) { temp = (channel_sel0 >> (i*4)) & 0xf; - if ((temp == 3) || (temp == 7)) + if ((temp == 0) || (temp == 6)) pi_clk_sel |= (1 << i); } - for (i = 0; i < 2; i++) { + for (i = 0; i < 4; i++) { temp = (channel_sel1 >> (i*4)) & 0xf; - if ((temp == 3) || (temp == 7)) + if ((temp == 0) || (temp == 6)) pi_clk_sel |= (1 << (i + 8)); } pconf->lcd_control.mlvds_config->pi_clk_sel = pi_clk_sel; @@ -1434,6 +1379,41 @@ static void lcd_mlvds_config_set(struct lcd_config_s *pconf) } } +static void lcd_p2p_config_set(struct lcd_config_s *pconf) +{ + unsigned int bit_rate, pclk; + unsigned int lcd_bits, lane_num; + + if (lcd_debug_print_flag) + LCDPR("%s\n", __func__); + + lcd_bits = pconf->lcd_basic.lcd_bits; + lane_num = pconf->lcd_control.p2p_config->lane_num; + pclk = pconf->lcd_timing.lcd_clk / 1000; + switch (pconf->lcd_control.p2p_config->p2p_type) { + case P2P_CEDS: + if (pclk >= 600000) + bit_rate = pclk * 3 * lcd_bits / lane_num; + else + bit_rate = pclk * (3 * lcd_bits + 4) / lane_num; + break; + case P2P_CHPI: /* 8/10 coding */ + bit_rate = (pclk * 3 * lcd_bits * 10 / 8) / lane_num; + break; + default: + bit_rate = pclk * 3 * lcd_bits / lane_num; + break; + } + + pconf->lcd_timing.bit_rate = bit_rate * 1000; + + if (lcd_debug_print_flag) { + LCDPR("lane_num=%u, bit_rate=%u.%03uMHz, pclk=%u.%03uMhz\n", + lane_num, (bit_rate / 1000), (bit_rate % 1000), + (pclk / 1000), (pclk % 1000)); + } +} + void lcd_tv_clk_config_change(struct lcd_config_s *pconf) { #ifdef CONFIG_AMLOGIC_VPU @@ -1446,6 +1426,9 @@ void lcd_tv_clk_config_change(struct lcd_config_s *pconf) case LCD_MLVDS: lcd_mlvds_config_set(pconf); break; + case LCD_P2P: + lcd_p2p_config_set(pconf); + break; default: break; } @@ -1486,6 +1469,9 @@ void lcd_tv_config_update(struct lcd_config_s *pconf) case LCD_MLVDS: lcd_mlvds_config_set(pconf); break; + case LCD_P2P: + lcd_p2p_config_set(pconf); + break; default: break; } @@ -1582,9 +1568,9 @@ int lcd_tv_driver_init(void) lcd_mlvds_phy_set(pconf, 1); break; case LCD_P2P: - lcd_p2p_control_set(pconf); lcd_tcon_pinmux_set(1); lcd_p2p_phy_set(pconf, 1); + lcd_p2p_control_set(pconf); break; default: break; @@ -1663,17 +1649,7 @@ int lcd_tv_driver_change(void) lcd_vbyone_interrupt_enable(0); } - switch (pconf->lcd_timing.clk_change) { - case LCD_CLK_PLL_CHANGE: - lcd_clk_generate_parameter(pconf); - lcd_clk_set(pconf); - break; - case LCD_CLK_FRAC_UPDATE: - lcd_clk_update(pconf); - break; - default: - break; - } + lcd_clk_change(pconf); lcd_venc_change(pconf); if (pconf->lcd_basic.lcd_type == LCD_VBYONE) { diff --git a/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_tv.c b/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_tv.c index f309f02fadff..b692ed4f0454 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_tv.c +++ b/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_tv.c @@ -389,7 +389,8 @@ static int lcd_vout_clr_state(int index) struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); lcd_vout_state &= ~(1 << index); - lcd_drv->viu_sel = LCD_VIU_SEL_NONE; + if (lcd_drv->viu_sel == index) + lcd_drv->viu_sel = LCD_VIU_SEL_NONE; return 0; } @@ -445,17 +446,7 @@ static int lcd_framerate_automation_set_mode(void) if (lcd_drv->lcd_config->lcd_basic.lcd_type == LCD_VBYONE) lcd_vbyone_interrupt_enable(0); /* change clk parameter */ - switch (lcd_drv->lcd_config->lcd_timing.clk_change) { - case LCD_CLK_PLL_CHANGE: - lcd_clk_generate_parameter(lcd_drv->lcd_config); - lcd_clk_set(lcd_drv->lcd_config); - break; - case LCD_CLK_FRAC_UPDATE: - lcd_clk_update(lcd_drv->lcd_config); - break; - default: - break; - } + lcd_clk_change(lcd_drv->lcd_config); lcd_venc_change(lcd_drv->lcd_config); if (lcd_drv->lcd_config->lcd_basic.lcd_type == LCD_VBYONE) lcd_vbyone_wait_stable(); @@ -785,13 +776,17 @@ static int lcd_init_load_from_dts(struct lcd_config_s *pconf, struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); /* lock pinmux if lcd in on */ - switch (pconf->lcd_basic.lcd_type) { - case LCD_VBYONE: - if (lcd_drv->lcd_status & LCD_STATUS_IF_ON) + if (lcd_drv->lcd_status & LCD_STATUS_IF_ON) { + switch (pconf->lcd_basic.lcd_type) { + case LCD_VBYONE: lcd_vbyone_pinmux_set(1); - break; - default: - break; + break; + case LCD_P2P: + lcd_tcon_pinmux_set(1); + break; + default: + break; + } } return ret; @@ -806,6 +801,8 @@ static int lcd_config_load_from_dts(struct lcd_config_s *pconf, struct device_node *child; struct lvds_config_s *lvdsconf; struct vbyone_config_s *vx1_conf; + struct mlvds_config_s *mlvds_conf; + struct p2p_config_s *p2p_conf; child = of_get_child_by_name(dev->of_node, pconf->lcd_propname); if (child == NULL) { @@ -882,9 +879,9 @@ static int lcd_config_load_from_dts(struct lcd_config_s *pconf, pconf->lcd_timing.lcd_clk = 60; } else { pconf->lcd_timing.fr_adjust_type = (unsigned char)(para[0]); - pconf->lcd_timing.ss_level = (unsigned char)(para[1]); + pconf->lcd_timing.ss_level = para[1]; pconf->lcd_timing.clk_auto = (unsigned char)(para[2]); - pconf->lcd_timing.lcd_clk = (unsigned char)(para[3]); + pconf->lcd_timing.lcd_clk = para[3]; } switch (pconf->lcd_basic.lcd_type) { @@ -1010,6 +1007,64 @@ static int lcd_config_load_from_dts(struct lcd_config_s *pconf, } } break; + case LCD_MLVDS: + mlvds_conf = pconf->lcd_control.mlvds_config; + ret = of_property_read_u32_array(child, "minilvds_attr", + ¶[0], 6); + if (ret) { + LCDERR("failed to get minilvds_attr\n"); + } else { + mlvds_conf->channel_num = para[0]; + mlvds_conf->channel_sel0 = para[1]; + mlvds_conf->channel_sel1 = para[2]; + mlvds_conf->clk_phase = para[3]; + mlvds_conf->pn_swap = para[4]; + mlvds_conf->bit_swap = para[5]; + } + ret = of_property_read_u32_array(child, "phy_attr", + ¶[0], 2); + if (ret) { + if (lcd_debug_print_flag) + LCDPR("failed to get phy_attr\n"); + } else { + mlvds_conf->phy_vswing = para[0]; + mlvds_conf->phy_preem = para[1]; + if (lcd_debug_print_flag) { + LCDPR("phy vswing=0x%x, preem=0x%x\n", + mlvds_conf->phy_vswing, + mlvds_conf->phy_preem); + } + } + break; + case LCD_P2P: + p2p_conf = pconf->lcd_control.p2p_config; + ret = of_property_read_u32_array(child, "p2p_attr", + ¶[0], 6); + if (ret) { + LCDERR("failed to get p2p_attr\n"); + } else { + p2p_conf->p2p_type = para[0]; + p2p_conf->lane_num = para[1]; + p2p_conf->channel_sel0 = para[2]; + p2p_conf->channel_sel1 = para[3]; + p2p_conf->pn_swap = para[4]; + p2p_conf->bit_swap = para[5]; + } + ret = of_property_read_u32_array(child, "phy_attr", + ¶[0], 2); + if (ret) { + if (lcd_debug_print_flag) + LCDPR("failed to get phy_attr\n"); + } else { + p2p_conf->phy_vswing = para[0]; + p2p_conf->phy_preem = para[1]; + if (lcd_debug_print_flag) { + LCDPR("phy vswing=0x%x, preem=0x%x\n", + p2p_conf->phy_vswing, + p2p_conf->phy_preem); + } + } + break; default: LCDERR("invalid lcd type\n"); break; @@ -1030,6 +1085,8 @@ static int lcd_config_load_from_unifykey(struct lcd_config_s *pconf) struct aml_lcd_unifykey_header_s lcd_header; struct lvds_config_s *lvdsconf = pconf->lcd_control.lvds_config; struct vbyone_config_s *vx1_conf = pconf->lcd_control.vbyone_config; + struct mlvds_config_s *mlvds_conf = pconf->lcd_control.mlvds_config; + struct p2p_config_s *p2p_conf = pconf->lcd_control.p2p_config; int ret; para = kmalloc((sizeof(unsigned char) * LCD_UKEY_LCD_SIZE), GFP_KERNEL); @@ -1204,6 +1261,48 @@ static int lcd_config_load_from_unifykey(struct lcd_config_s *pconf) ((*(p + LCD_UKEY_IF_ATTR_7 + 1)) << 8)) & 0xff; lvdsconf->lane_reverse = 0; } + } else if (pconf->lcd_basic.lcd_type == LCD_MLVDS) { + mlvds_conf->channel_num = (*(p + LCD_UKEY_IF_ATTR_0) | + ((*(p + LCD_UKEY_IF_ATTR_0 + 1)) << 8)) & 0xff; + mlvds_conf->channel_sel0 = (*(p + LCD_UKEY_IF_ATTR_1) | + ((*(p + LCD_UKEY_IF_ATTR_1 + 1)) << 8) | + (*(p + LCD_UKEY_IF_ATTR_2) << 16) | + ((*(p + LCD_UKEY_IF_ATTR_2 + 1)) << 24)); + mlvds_conf->channel_sel1 = (*(p + LCD_UKEY_IF_ATTR_3) | + ((*(p + LCD_UKEY_IF_ATTR_3 + 1)) << 8) | + (*(p + LCD_UKEY_IF_ATTR_4) << 16) | + ((*(p + LCD_UKEY_IF_ATTR_4 + 1)) << 24)); + mlvds_conf->clk_phase = (*(p + LCD_UKEY_IF_ATTR_5) | + ((*(p + LCD_UKEY_IF_ATTR_5 + 1)) << 8)); + mlvds_conf->pn_swap = (*(p + LCD_UKEY_IF_ATTR_6) | + ((*(p + LCD_UKEY_IF_ATTR_6 + 1)) << 8)) & 0xff; + mlvds_conf->bit_swap = (*(p + LCD_UKEY_IF_ATTR_7) | + ((*(p + LCD_UKEY_IF_ATTR_7 + 1)) << 8)) & 0xff; + mlvds_conf->phy_vswing = (*(p + LCD_UKEY_IF_ATTR_8) | + ((*(p + LCD_UKEY_IF_ATTR_8 + 1)) << 8)) & 0xff; + mlvds_conf->phy_preem = (*(p + LCD_UKEY_IF_ATTR_9) | + ((*(p + LCD_UKEY_IF_ATTR_9 + 1)) << 8)) & 0xff; + } else if (pconf->lcd_basic.lcd_type == LCD_P2P) { + p2p_conf->p2p_type = (*(p + LCD_UKEY_IF_ATTR_0) | + ((*(p + LCD_UKEY_IF_ATTR_0 + 1)) << 8)); + p2p_conf->lane_num = (*(p + LCD_UKEY_IF_ATTR_1) | + ((*(p + LCD_UKEY_IF_ATTR_1 + 1)) << 8)); + p2p_conf->channel_sel0 = (*(p + LCD_UKEY_IF_ATTR_2) | + ((*(p + LCD_UKEY_IF_ATTR_2 + 1)) << 8) | + (*(p + LCD_UKEY_IF_ATTR_3) << 16) | + ((*(p + LCD_UKEY_IF_ATTR_3 + 1)) << 24)); + p2p_conf->channel_sel1 = (*(p + LCD_UKEY_IF_ATTR_4) | + ((*(p + LCD_UKEY_IF_ATTR_4 + 1)) << 8) | + (*(p + LCD_UKEY_IF_ATTR_5) << 16) | + ((*(p + LCD_UKEY_IF_ATTR_5 + 1)) << 24)); + p2p_conf->pn_swap = (*(p + LCD_UKEY_IF_ATTR_6) | + ((*(p + LCD_UKEY_IF_ATTR_6 + 1)) << 8)); + p2p_conf->bit_swap = (*(p + LCD_UKEY_IF_ATTR_7) | + ((*(p + LCD_UKEY_IF_ATTR_7 + 1)) << 8)); + p2p_conf->phy_vswing = (*(p + LCD_UKEY_IF_ATTR_8) | + ((*(p + LCD_UKEY_IF_ATTR_8 + 1)) << 8)); + p2p_conf->phy_preem = (*(p + LCD_UKEY_IF_ATTR_9) | + ((*(p + LCD_UKEY_IF_ATTR_9 + 1)) << 8)); } else LCDERR("unsupport lcd_type: %d\n", pconf->lcd_basic.lcd_type); @@ -1268,19 +1367,19 @@ static void lcd_vmode_init(struct lcd_config_s *pconf) static void lcd_config_init(struct lcd_config_s *pconf) { struct lcd_clk_config_s *cconf = get_lcd_clk_config(); - unsigned int ss_level; - unsigned int clk; + unsigned int temp; if (pconf->lcd_timing.lcd_clk == 0) /* default 0 for 60hz */ pconf->lcd_timing.lcd_clk = 60; else LCDPR("custome clk: %d\n", pconf->lcd_timing.lcd_clk); - clk = pconf->lcd_timing.lcd_clk; - if (clk < 200) { /* regard as frame_rate */ - pconf->lcd_timing.lcd_clk = clk * pconf->lcd_basic.h_period * + temp = pconf->lcd_timing.lcd_clk; + if (temp < 200) { /* regard as frame_rate */ + pconf->lcd_timing.lcd_clk = temp * pconf->lcd_basic.h_period * pconf->lcd_basic.v_period; - } else /* regard as pixel clock */ - pconf->lcd_timing.lcd_clk = clk; + } else { /* regard as pixel clock */ + pconf->lcd_timing.lcd_clk = temp; + } pconf->lcd_timing.lcd_clk_dft = pconf->lcd_timing.lcd_clk; pconf->lcd_timing.h_period_dft = pconf->lcd_basic.h_period; @@ -1290,13 +1389,23 @@ static void lcd_config_init(struct lcd_config_s *pconf) lcd_vmode_init(pconf); lcd_tv_config_update(pconf); lcd_clk_generate_parameter(pconf); - ss_level = pconf->lcd_timing.ss_level; if (cconf->data) { - cconf->ss_level = (ss_level >= cconf->data->ss_level_max) ? - 0 : ss_level; + temp = pconf->lcd_timing.ss_level & 0xff; + cconf->ss_level = (temp >= cconf->data->ss_level_max) ? + 0 : temp; + temp = (pconf->lcd_timing.ss_level >> 8) & 0xff; + temp = (temp >> LCD_CLK_SS_BIT_FREQ) & 0xf; + cconf->ss_freq = (temp >= cconf->data->ss_freq_max) ? + 0 : temp; + temp = (pconf->lcd_timing.ss_level >> 8) & 0xff; + temp = (temp >> LCD_CLK_SS_BIT_MODE) & 0xf; + cconf->ss_mode = (temp >= cconf->data->ss_mode_max) ? + 0 : temp; } else { LCDERR("%s: clk config data is null\n", __func__); cconf->ss_level = 0; + cconf->ss_freq = 0; + cconf->ss_mode = 0; } } @@ -1346,6 +1455,8 @@ static void lcd_set_vinfo(unsigned int sync_duration) LCDPR("%s: sync_duration=%d\n", __func__, sync_duration); + vout_notifier_call_chain(VOUT_EVENT_MODE_CHANGE_PRE, + &lcd_drv->lcd_info->mode); /* update vinfo */ lcd_drv->lcd_info->sync_duration_num = sync_duration; lcd_drv->lcd_info->sync_duration_den = 100; @@ -1360,17 +1471,7 @@ static void lcd_set_vinfo(unsigned int sync_duration) if (lcd_drv->lcd_config->lcd_basic.lcd_type == LCD_VBYONE) lcd_vbyone_interrupt_enable(0); /* change clk parameter */ - switch (lcd_drv->lcd_config->lcd_timing.clk_change) { - case LCD_CLK_PLL_CHANGE: - lcd_clk_generate_parameter(lcd_drv->lcd_config); - lcd_clk_set(lcd_drv->lcd_config); - break; - case LCD_CLK_FRAC_UPDATE: - lcd_clk_update(lcd_drv->lcd_config); - break; - default: - break; - } + lcd_clk_change(lcd_drv->lcd_config); lcd_venc_change(lcd_drv->lcd_config); if (lcd_drv->lcd_config->lcd_basic.lcd_type == LCD_VBYONE) lcd_vbyone_wait_stable(); diff --git a/drivers/amlogic/media/vout/lcd/lcd_vout.c b/drivers/amlogic/media/vout/lcd/lcd_vout.c index 14dce115d894..f6894f0314ba 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_vout.c +++ b/drivers/amlogic/media/vout/lcd/lcd_vout.c @@ -36,6 +36,7 @@ #ifdef CONFIG_OF #include #endif +#include #include #include #include @@ -47,6 +48,7 @@ #endif #include "lcd_reg.h" #include "lcd_common.h" +#include "lcd_clk_config.h" #define LCD_CDEV_NAME "lcd" @@ -102,7 +104,6 @@ static struct vbyone_config_s lcd_vbyone_config = { .byte_mode = 4, .color_fmt = 4, .phy_div = 1, - .bit_rate = 0, .phy_vswing = VX1_PHY_VSWING_DFT, .phy_preem = VX1_PHY_PREEM_DFT, .intr_en = 1, @@ -114,6 +115,30 @@ static struct vbyone_config_s lcd_vbyone_config = { .cdr_training_hold = VX1_CDR_TRAINING_HOLD_DFT, }; +static struct mlvds_config_s lcd_mlvds_config = { + .channel_num = 6, + .channel_sel0 = 0x76543210, + .channel_sel1 = 0, + .clk_phase = 0, + .pn_swap = 0, + .bit_swap = 0, + .phy_vswing = 0, + .phy_preem = 0, + + .pi_clk_sel = 0, +}; + +static struct p2p_config_s lcd_p2p_config = { + .p2p_type = P2P_MAX, + .lane_num = 12, + .channel_sel0 = 0x76543210, + .channel_sel1 = 0xba98, + .pn_swap = 0, + .bit_swap = 0, + .phy_vswing = 0, + .phy_preem = 0, +}; + static unsigned char dsi_init_on_table[DSI_INIT_ON_MAX] = {0xff, 0xff}; static unsigned char dsi_init_off_table[DSI_INIT_OFF_MAX] = {0xff, 0xff}; @@ -176,6 +201,7 @@ static struct lcd_config_s lcd_config_dft = { .clk_auto = 1, .ss_level = 0, .fr_adjust_type = 0, + .bit_rate = 0, }, .optical_info = { .hdr_support = 0, @@ -196,6 +222,8 @@ static struct lcd_config_s lcd_config_dft = { .ttl_config = &lcd_ttl_config, .lvds_config = &lcd_lvds_config, .vbyone_config = &lcd_vbyone_config, + .mlvds_config = &lcd_mlvds_config, + .p2p_config = &lcd_p2p_config, .mipi_config = &lcd_mipi_config, .vlock_param = vlock_param, }, @@ -231,7 +259,8 @@ static void lcd_power_ctrl(int status) #ifdef CONFIG_AMLOGIC_LCD_EXTERN struct aml_lcd_extern_driver_s *ext_drv; #endif - int i, index; + unsigned int i, index, wait, temp; + int value = -1; int ret = 0; LCDPR("%s: %d\n", __func__, status); @@ -246,8 +275,8 @@ static void lcd_power_ctrl(int status) break; if (lcd_debug_print_flag) { LCDPR("power_ctrl: %d, step %d\n", status, i); - LCDPR("type=%d, index=%d, value=%d, delay=%d\n", - power_step->type, power_step->index, + LCDPR("%s: type=%d, index=%d, value=%d, delay=%d\n", + __func__, power_step->type, power_step->index, power_step->value, power_step->delay); } switch (power_step->type) { @@ -260,7 +289,7 @@ static void lcd_power_ctrl(int status) break; case LCD_POWER_TYPE_SIGNAL: if (status) - ret = lcd_driver->driver_init(); + lcd_driver->driver_init(); else lcd_driver->driver_disable(); break; @@ -283,14 +312,42 @@ static void lcd_power_ctrl(int status) } break; #endif + case LCD_POWER_TYPE_WAIT_GPIO: + index = power_step->index; + lcd_cpu_gpio_set(index, LCD_GPIO_INPUT); + LCDPR("lcd_power_type_wait_gpio wait\n"); + for (wait = 0; wait < power_step->delay; wait++) { + value = lcd_cpu_gpio_get(index); + if (value == power_step->value) { + LCDPR("wait_gpio %d ok\n", value); + break; + } + mdelay(1); + } + if (wait == power_step->delay) + LCDERR("wait_gpio %d timeout!\n", value); + break; + case LCD_POWER_TYPE_CLK_SS: + temp = lcd_driver->lcd_config->lcd_timing.ss_level; + value = (power_step->value) & 0xff; + ret = lcd_set_ss(0xff, + (value >> LCD_CLK_SS_BIT_FREQ) & 0xf, + (value >> LCD_CLK_SS_BIT_MODE) & 0xf); + if (ret == 0) { + temp &= ~(0xff << 8); + temp |= (value << 8); + lcd_driver->lcd_config->lcd_timing.ss_level = + temp; + } + break; default: break; } - if (power_step->delay) + if ((power_step->type != LCD_POWER_TYPE_WAIT_GPIO) && + (power_step->delay > 0)) mdelay(power_step->delay); i++; } - if (lcd_debug_print_flag) LCDPR("%s: %d finished\n", __func__, status); } @@ -406,15 +463,41 @@ static void lcd_resume_work(struct work_struct *p_work) mutex_unlock(&lcd_driver->power_mutex); } +static struct delayed_work lcd_test_delayed_work; +static void lcd_auto_test_delayed(struct work_struct *work) +{ + LCDPR("%s\n", __func__); + mutex_lock(&lcd_driver->power_mutex); + aml_lcd_notifier_call_chain(LCD_EVENT_POWER_ON, NULL); + mutex_unlock(&lcd_driver->power_mutex); +} + +static void lcd_auto_test(unsigned char flag) +{ + lcd_driver->lcd_test_state = flag; + if (lcd_driver->workqueue) { + queue_delayed_work(lcd_driver->workqueue, + &lcd_test_delayed_work, + msecs_to_jiffies(20000)); + } else { + schedule_delayed_work(&lcd_test_delayed_work, + msecs_to_jiffies(20000)); + } +} + static int lcd_vsync_print_cnt; static inline void lcd_vsync_handler(void) { int flag; #ifdef CONFIG_AMLOGIC_LCD_TABLET - struct lcd_config_s *pconf = lcd_driver->lcd_config; + struct lcd_config_s *pconf; #endif + if (lcd_driver == NULL) + return; + #ifdef CONFIG_AMLOGIC_LCD_TABLET + pconf = lcd_driver->lcd_config; if (pconf->lcd_control.mipi_config->dread) { if (pconf->lcd_control.mipi_config->dread->flag) { lcd_mipi_test_read( @@ -460,6 +543,9 @@ static inline void lcd_vsync_handler(void) static irqreturn_t lcd_vsync_isr(int irq, void *dev_id) { + if (lcd_driver == NULL) + return IRQ_HANDLED; + if ((lcd_driver->lcd_status & LCD_STATUS_ENCL_ON) == 0) return IRQ_HANDLED; @@ -473,6 +559,9 @@ static irqreturn_t lcd_vsync_isr(int irq, void *dev_id) static irqreturn_t lcd_vsync2_isr(int irq, void *dev_id) { + if (lcd_driver == NULL) + return IRQ_HANDLED; + if ((lcd_driver->lcd_status & LCD_STATUS_ENCL_ON) == 0) return IRQ_HANDLED; @@ -506,6 +595,9 @@ static void lcd_wait_vsync(void) static void lcd_vsync_none_timer_handler(unsigned long arg) { + if (lcd_driver == NULL) + return; + if ((lcd_driver->lcd_status & LCD_STATUS_ENCL_ON) == 0) goto lcd_vsync_none_timer_handler_end; @@ -915,7 +1007,8 @@ static int lcd_fops_create(void) return -1; } - LCDPR("%s OK\n", __func__); + if (lcd_debug_print_flag) + LCDPR("%s OK\n", __func__); return 0; } @@ -928,6 +1021,57 @@ static void lcd_fops_remove(void) } /* ************************************************************* */ +static int lcd_vsync_irq_init(void) +{ + if (lcd_driver->res_vsync_irq) { + if (request_irq(lcd_driver->res_vsync_irq->start, + lcd_vsync_isr, IRQF_SHARED, + "lcd_vsync", (void *)"lcd_vsync")) { + LCDERR("can't request lcd_vsync_irq\n"); + } else { + if (lcd_debug_print_flag) + LCDPR("request lcd_vsync_irq successful\n"); + } + } + + if (lcd_driver->res_vsync2_irq) { + if (request_irq(lcd_driver->res_vsync2_irq->start, + lcd_vsync2_isr, IRQF_SHARED, + "lcd_vsync2", (void *)"lcd_vsync2")) { + LCDERR("can't request lcd_vsync2_irq\n"); + } else { + if (lcd_debug_print_flag) + LCDPR("request lcd_vsync2_irq successful\n"); + } + } + + /* add timer to monitor hpll frequency */ + init_timer(&lcd_vsync_none_timer); + /* lcd_vsync_none_timer.data = NULL; */ + lcd_vsync_none_timer.function = lcd_vsync_none_timer_handler; + lcd_vsync_none_timer.expires = jiffies + LCD_VSYNC_NONE_INTERVAL; + /*add_timer(&lcd_vsync_none_timer);*/ + /*LCDPR("add lcd_vsync_none_timer handler\n"); */ + + return 0; +} + +static void lcd_vsync_irq_remove(void) +{ + if (lcd_driver->res_vsync_irq) + free_irq(lcd_driver->res_vsync_irq->start, (void *)"lcd_vsync"); + + if (lcd_driver->res_vsync2_irq) { + free_irq(lcd_driver->res_vsync2_irq->start, + (void *)"lcd_vsync"); + } + + if (lcd_driver->vsync_none_timer_flag) { + del_timer_sync(&lcd_vsync_none_timer); + lcd_driver->vsync_none_timer_flag = 0; + } +} + static void lcd_init_vout(void) { switch (lcd_driver->lcd_mode) { @@ -964,16 +1108,23 @@ static int lcd_mode_probe(struct device *dev) LCDERR("invalid lcd mode: %d\n", lcd_driver->lcd_mode); break; } + lcd_tcon_probe(lcd_driver); + if (lcd_driver->lcd_status & LCD_STATUS_ENCL_ON) + lcd_clk_gate_switch(1); lcd_debug_probe(); lcd_fops_create(); lcd_notifier_register(); + lcd_vsync_irq_init(); /* add notifier for video sync_duration info refresh */ vout_notifier_call_chain(VOUT_EVENT_MODE_CHANGE, &lcd_driver->lcd_info->mode); + if (lcd_driver->lcd_auto_test) + lcd_auto_test(lcd_driver->lcd_auto_test); + return 0; } @@ -1010,16 +1161,22 @@ static void lcd_config_probe_delayed(struct work_struct *work) int i = 0; int ret; - if (lcd_driver->lcd_key_valid) { + key_init_flag = key_unify_get_init_flag(); + while (key_init_flag == 0) { + if (i++ >= LCD_UNIFYKEY_WAIT_TIMEOUT) + break; + msleep(LCD_UNIFYKEY_RETRY_INTERVAL); key_init_flag = key_unify_get_init_flag(); - while (key_init_flag == 0) { - if (i++ >= LCD_UNIFYKEY_WAIT_TIMEOUT) - break; - msleep(20); - key_init_flag = key_unify_get_init_flag(); - } - LCDPR("key_init_flag=%d, i=%d\n", key_init_flag, i); } + LCDPR("key_init_flag=%d, i=%d\n", key_init_flag, i); + + if (key_init_flag == 0) { + kfree(lcd_driver); + lcd_driver = NULL; + LCDERR("key is not ready, probe exit\n"); + return; + } + ret = lcd_mode_probe(lcd_driver->dev); if (ret) { kfree(lcd_driver); @@ -1112,29 +1269,14 @@ static int lcd_config_probe(struct platform_device *pdev) LCDPR("detect lcd_auto_test: %d\n", lcd_driver->lcd_auto_test); } - ret = of_property_read_string_index(lcd_driver->dev->of_node, - "interrupt-names", 0, &str); - if (ret == 0) { - lcd_driver->res_vsync_irq = platform_get_resource(pdev, - IORESOURCE_IRQ, 0); - } - ret = of_property_read_string_index(lcd_driver->dev->of_node, - "interrupt-names", 1, &str); - if (ret == 0) { - if (strcmp(str, "vbyone") == 0) { - lcd_driver->res_vx1_irq = - platform_get_resource(pdev, IORESOURCE_IRQ, 1); - } else if (strcmp(str, "vsync2") == 0) { - lcd_driver->res_vsync2_irq = - platform_get_resource(pdev, IORESOURCE_IRQ, 1); - } - } - ret = of_property_read_string_index(lcd_driver->dev->of_node, - "interrupt-names", 2, &str); - if (ret == 0) { - lcd_driver->res_tcon_irq = platform_get_resource(pdev, - IORESOURCE_IRQ, 2); - } + lcd_driver->res_vsync_irq = platform_get_resource_byname(pdev, + IORESOURCE_IRQ, "vsync"); + lcd_driver->res_vsync2_irq = platform_get_resource_byname(pdev, + IORESOURCE_IRQ, "vsync2"); + lcd_driver->res_vx1_irq = platform_get_resource_byname(pdev, + IORESOURCE_IRQ, "vbyone"); + lcd_driver->res_tcon_irq = platform_get_resource_byname(pdev, + IORESOURCE_IRQ, "tcon"); lcd_driver->lcd_info = &lcd_vinfo; lcd_driver->lcd_config = &lcd_config_dft; @@ -1173,55 +1315,6 @@ static int lcd_config_probe(struct platform_device *pdev) return 0; } -static int lcd_vsync_irq_init(void) -{ - if (lcd_driver->res_vsync_irq) { - if (request_irq(lcd_driver->res_vsync_irq->start, - lcd_vsync_isr, IRQF_SHARED, - "lcd_vsync", (void *)"lcd_vsync")) { - LCDERR("can't request lcd_vsync_irq\n"); - } else { - LCDPR("request lcd_vsync_irq successful\n"); - } - } - - if (lcd_driver->res_vsync2_irq) { - if (request_irq(lcd_driver->res_vsync2_irq->start, - lcd_vsync2_isr, IRQF_SHARED, - "lcd_vsync2", (void *)"lcd_vsync2")) { - LCDERR("can't request lcd_vsync2_irq\n"); - } else { - LCDPR("request lcd_vsync2_irq successful\n"); - } - } - - /* add timer to monitor hpll frequency */ - init_timer(&lcd_vsync_none_timer); - /* lcd_vsync_none_timer.data = NULL; */ - lcd_vsync_none_timer.function = lcd_vsync_none_timer_handler; - lcd_vsync_none_timer.expires = jiffies + LCD_VSYNC_NONE_INTERVAL; - /*add_timer(&lcd_vsync_none_timer);*/ - /*LCDPR("add lcd_vsync_none_timer handler\n"); */ - - return 0; -} - -static void lcd_vsync_irq_remove(void) -{ - if (lcd_driver->res_vsync_irq) - free_irq(lcd_driver->res_vsync_irq->start, (void *)"lcd_vsync"); - - if (lcd_driver->res_vsync2_irq) { - free_irq(lcd_driver->res_vsync2_irq->start, - (void *)"lcd_vsync"); - } - - if (lcd_driver->vsync_none_timer_flag) { - del_timer_sync(&lcd_vsync_none_timer); - lcd_driver->vsync_none_timer_flag = 0; - } -} - #ifdef CONFIG_OF static struct lcd_data_s lcd_data_gxl = { @@ -1272,6 +1365,18 @@ static struct lcd_data_s lcd_data_tl1 = { .reg_map_table = &lcd_reg_tl1[0], }; +static struct lcd_data_s lcd_data_sm1 = { + .chip_type = LCD_CHIP_SM1, + .chip_name = "sm1", + .reg_map_table = &lcd_reg_axg[0], +}; + +static struct lcd_data_s lcd_data_tm2 = { + .chip_type = LCD_CHIP_TM2, + .chip_name = "tm2", + .reg_map_table = &lcd_reg_tl1[0], +}; + static const struct of_device_id lcd_dt_match_table[] = { { .compatible = "amlogic, lcd-gxl", @@ -1305,32 +1410,18 @@ static const struct of_device_id lcd_dt_match_table[] = { .compatible = "amlogic, lcd-tl1", .data = &lcd_data_tl1, }, + { + .compatible = "amlogic, lcd-sm1", + .data = &lcd_data_sm1, + }, + { + .compatible = "amlogic, lcd-tm2", + .data = &lcd_data_tm2, + }, {}, }; #endif -static struct delayed_work lcd_test_delayed_work; -static void lcd_auto_test_delayed(struct work_struct *work) -{ - LCDPR("%s\n", __func__); - mutex_lock(&lcd_driver->power_mutex); - aml_lcd_notifier_call_chain(LCD_EVENT_POWER_ON, NULL); - mutex_unlock(&lcd_driver->power_mutex); -} - -static void lcd_auto_test(unsigned char flag) -{ - lcd_driver->lcd_test_state = flag; - if (lcd_driver->workqueue) { - queue_delayed_work(lcd_driver->workqueue, - &lcd_test_delayed_work, - msecs_to_jiffies(20000)); - } else { - schedule_delayed_work(&lcd_test_delayed_work, - msecs_to_jiffies(20000)); - } -} - static int lcd_probe(struct platform_device *pdev) { const struct of_device_id *match; @@ -1376,32 +1467,29 @@ static int lcd_probe(struct platform_device *pdev) lcd_ioremap(pdev); ret = lcd_config_probe(pdev); - lcd_vsync_irq_init(); LCDPR("%s %s\n", __func__, (ret ? "failed" : "ok")); - if (lcd_driver->lcd_auto_test) - lcd_auto_test(lcd_driver->lcd_auto_test); - return 0; } static int lcd_remove(struct platform_device *pdev) { + if (lcd_driver == NULL) + return 0; + cancel_delayed_work(&lcd_driver->lcd_probe_delayed_work); cancel_work_sync(&(lcd_driver->lcd_resume_work)); if (lcd_driver->workqueue) destroy_workqueue(lcd_driver->workqueue); - if (lcd_driver) { - lcd_vsync_irq_remove(); - lcd_fops_remove(); - lcd_debug_remove(); - lcd_config_remove(lcd_driver->dev); + lcd_vsync_irq_remove(); + lcd_fops_remove(); + lcd_debug_remove(); + lcd_config_remove(lcd_driver->dev); - kfree(lcd_driver); - lcd_driver = NULL; - } + kfree(lcd_driver); + lcd_driver = NULL; LCDPR("%s\n", __func__); return 0; @@ -1409,6 +1497,16 @@ static int lcd_remove(struct platform_device *pdev) static int lcd_resume(struct platform_device *pdev) { + if (lcd_debug_print_flag) + LCDPR("resume method: %d\n", get_resume_method()); + + if ((get_resume_method() == RTC_WAKEUP) || + (get_resume_method() == AUTO_WAKEUP) || + (get_resume_method() == UDEFINED_WAKEUP)) + return 0; + + if (lcd_driver == NULL) + return 0; if ((lcd_driver->lcd_status & LCD_STATUS_VMODE_ACTIVE) == 0) return 0; @@ -1435,6 +1533,9 @@ static int lcd_resume(struct platform_device *pdev) static int lcd_suspend(struct platform_device *pdev, pm_message_t state) { + if (lcd_driver == NULL) + return 0; + mutex_lock(&lcd_driver->power_mutex); if (lcd_driver->lcd_status & LCD_STATUS_ENCL_ON) { aml_lcd_notifier_call_chain(LCD_EVENT_POWER_OFF, NULL); @@ -1450,6 +1551,8 @@ static void lcd_shutdown(struct platform_device *pdev) if (lcd_debug_print_flag) LCDPR("%s\n", __func__); + if (lcd_driver == NULL) + return; if (lcd_driver->lcd_status & LCD_STATUS_ENCL_ON) aml_lcd_notifier_call_chain(LCD_EVENT_POWER_OFF, NULL); } diff --git a/drivers/amlogic/media/vout/lcd/tcon_ceds.h b/drivers/amlogic/media/vout/lcd/tcon_ceds.h new file mode 100644 index 000000000000..169cd79fd69a --- /dev/null +++ b/drivers/amlogic/media/vout/lcd/tcon_ceds.h @@ -0,0 +1,24019 @@ +/* + * drivers/amlogic/media/vout/lcd/tcon_ceds.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. + * + */ + +unsigned char uhd_tcon_setting_ceds_h10[] = { +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0xFF, +0x00, +0x00, +0x07, +0x00, +0xFF, +0x00, +0x07, +0x00, +0x00, +0xFF, +0x07, +0xFF, +0xFF, +0xFF, +0x07, +0x7F, +0x7F, +0x7F, +0x07, +0x00, +0x00, +0x00, +0x00, +0x63, +0x22, +0x51, +0xB0, +0x2D, +0x05, +0xA0, +0x50, +0x0A, +0x00, +0x80, +0x00, +0x80, +0x00, +0x00, +0x19, +0x00, +0x32, +0x01, +0x00, +0x05, +0x00, +0x12, +0x80, +0x0E, +0x00, +0x80, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x66, +0x66, +0x66, +0x66, +0x65, +0x66, +0x66, +0x66, +0x00, +0x00, +0x00, +0x01, +0x0D, +0x00, +0x87, +0x00, +0x00, +0x00, +0x00, +0x00, +0x55, +0x83, +0x80, +0x03, +0x28, +0x45, +0x00, +0x00, +0x28, +0x40, +0x00, +0x05, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x0B, +0x50, +0x1A, +0x70, +0x34, +0x00, +0x44, +0x00, +0x47, +0xF0, +0x48, +0x50, +0x4C, +0xE0, +0xB4, +0x33, +0x00, +0x3B, +0x00, +0x06, +0x01, +0x00, +0x02, +0x27, +0x52, +0xF0, +0x54, +0x00, +0x55, +0x10, +0x5C, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0xE8, +0x01, +0x5A, +0x00, +0x2A, +0xE8, +0x00, +0x02, +0x00, +0x02, +0x3D, +0xA3, +0xC2, +0x33, +0x82, +0xCA, +0x28, +0xC2, +0x2D, +0x22, +0xB1, +0xFB, +0x1F, +0xA1, +0x56, +0x11, +0x90, +0xBD, +0x02, +0xD0, +0x14, +0x20, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x08, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x3B, +0x00, +0x00, +0x00, +0x00, +0x00, +0x06, +0x3B, +0x01, +0x00, +0x00, +0x00, +0x00, +0x9F, +0x3B, +0x02, +0x00, +0x00, +0x53, +0x42, +0x31, +0x37, +0x30, +0x32, +0x38, +0xC2, +0x28, +0x15, +0x20, +0x00, +0x00, +0x00, +0x05, +0x00, +0x01, +0x86, +0x01, +0x87, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x13, +0x00, +0x1E, +0x00, +0x00, +0x71, +0x00, +0x3F, +0x00, +0x00, +0x00, +0x3F, +0xFF, +0xFF, +0xFF, +0x00, +0x3F, +0x00, +0x00, +0x00, +0x2A, +0x58, +0x58, +0x58, +0x2A, +0xC8, +0xC8, +0xC8, +0x2A, +0x00, +0x00, +0x00, +0x00, +0xCC, +0xCC, +0xCC, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x3F, +0x00, +0x00, +0x00, +0x00, +0x7F, +0x7F, +0x7F, +0x00, +0x3F, +0x3F, +0x3F, +0x15, +0xFF, +0xFF, +0xFF, +0x00, +0xFF, +0xFF, +0xFF, +0x3F, +0xFF, +0xFF, +0xFF, +0x00, +0x1F, +0x1F, +0x1F, +0xFF, +0x7F, +0x3F, +0x00, +0x00, +0x00, +0x46, +0x20, +0x00, +0xFF, +0x0C, +0xFF, +0x8F, +0x70, +0x76, +0x08, +0xFC, +0x40, +0x4C, +0x96, +0xCC, +0x01, +0xFF, +0x0A, +0x0A, +0x0A, +0x0C, +0x14, +0x47, +0x80, +0x08, +0x70, +0x2B, +0xB8, +0x08, +0x98, +0x08, +0x98, +0x08, +0x98, +0x89, +0x00, +0x0A, +0x00, +0x0F, +0x05, +0xDC, +0x03, +0x00, +0x0A, +0x3F, +0x1B, +0x0F, +0x1B, +0x00, +0x05, +0x03, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x32, +0x32, +0x32, +0x00, +0x00, +0x00, +0x02, +0x00, +0x00, +0x00, +0x7F, +0xFF, +0xFF, +0x61, +0x00, +0x01, +0x01, +0x02, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x40, +0x00, +0x01, +0x00, +0x00, +0x00, +0x00, +0x00, +0x64, +0x64, +0x64, +0x14, +0x00, +0x00, +0x10, +0x32, +0x54, +0x10, +0x32, +0x54, +0x00, +0x14, +0x14, +0x28, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x30, +0xE8, +0xFC, +0x03, +0x21, +0x49, +0xFF, +0xFF, +0xFF, +0x04, +0x20, +0xA0, +0x86, +0x01, +0x00, +0xA0, +0x86, +0x01, +0xD0, +0x38, +0x34, +0xC0, +0x38, +0x74, +0x01, +0xA0, +0xC7, +0x11, +0xC7, +0x27, +0x10, +0x20, +0xA0, +0xFF, +0x11, +0xFF, +0x0E, +0x10, +0x20, +0xA0, +0x38, +0x01, +0xC0, +0xA7, +0xF8, +0x20, +0xA0, +0x3F, +0x00, +0x3F, +0x3E, +0x80, +0x20, +0xA0, +0x07, +0x00, +0x07, +0x0B, +0xB8, +0x20, +0xE0, +0x07, +0x00, +0x07, +0x05, +0x14, +0x20, +0x20, +0xCC, +0xCC, +0xCC, +0xFD, +0xE8, +0x20, +0x21, +0xC7, +0x10, +0x00, +0x03, +0xE8, +0x20, +0x80, +0xC7, +0x11, +0xC7, +0x27, +0x10, +0x20, +0x20, +0xC7, +0x11, +0xC7, +0x27, +0x10, +0x20, +0xA0, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x34, +0x50, +0xFF, +0x30, +0xC7, +0x01, +0x10, +0x27, +0x02, +0x80, +0x00, +0x00, +0x00, +0x01, +0xC7, +0x01, +0xC7, +0x00, +0x01, +0x00, +0x00, +0x01, +0xC7, +0x27, +0x10, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x20, +0x22, +0x00, +0x10, +0x22, +0x22, +0x34, +0x22, +0x46, +0x58, +0x22, +0x6B, +0x7D, +0x22, +0x8F, +0xA2, +0x22, +0xB4, +0xC6, +0x22, +0xD8, +0xEB, +0x23, +0xFD, +0x0F, +0x33, +0x22, +0x34, +0x33, +0x46, +0x58, +0x33, +0x6B, +0x7D, +0x33, +0x8F, +0xA2, +0x33, +0xB4, +0xC6, +0x33, +0xD8, +0xEB, +0x34, +0xFD, +0x0F, +0x44, +0x21, +0x34, +0x40, +0x47, +0x00, +0x00, +0x00, +0x04, +0x40, +0x10, +0x01, +0x08, +0x80, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0xFF, +0x00, +0x00, +0xC0, +0x40, +0x00, +0xC0, +0x40, +0x00, +0x00, +0x00, +0x00, +0xC0, +0x40, +0x00, +0x00, +0x00, +0x00, +0xFF, +0x00, +0x00, +0xC0, +0x40, +0x00, +0xFF, +0x00, +0x00, +0xC0, +0x40, +0x00, +0x00, +0x00, +0x40, +0xC0, +0x00, +0x00, +0x00, +0x00, +0x40, +0xC0, +0x00, +0x00, +0xFF, +0x00, +0x00, +0xC0, +0x40, +0x00, +0xFF, +0x00, +0x00, +0x00, +0x00, +0x40, +0xC0, +0x00, +0x40, +0xC0, +0x00, +0x40, +0xC0, +0x00, +0x40, +0xC0, +0x00, +0x00, +0xFF, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x80, +0x80, +0x00, +0x00, +0xFF, +0x00, +0x00, +0xFF, +0x00, +0x00, +0xFF, +0x00, +0x00, +0xFF, +0x00, +0x00, +0x00, +0x00, +0x80, +0x80, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x8B, +0x33, +0xE1, +0x11, +0x0F, +0x00, +0x00, +0x00, +0x44, +0x01, +0x90, +0x04, +0xC0, +0x0B, +0x20, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x0F, +0xFF, +0x03, +0x14, +0x01, +0x41, +0x00, +0xA0, +0x00, +0xD6, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x80, +0x80, +0x80, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x38, +0xC2, +0x08, +0x08, +0x00, +0x08, +0x08, +0x00, +0x54, +0xAA, +0x55, +0x80, +0xFC, +0x00, +0x0E, +0x00, +0x80, +0x00, +0x08, +0x07, +0x80, +0x07, +0x80, +0x0E, +0x00, +0x20, +0x01, +0x1E, +0xF0, +0x1A, +0x00, +0x0C, +0x0D, +0xB7, +0x03, +0x94, +0x18, +0x00, +0x10, +0xF0, +0x07, +0x80, +0x20, +0x00, +0x66, +0x0B, +0x0B, +0x33, +0x0E, +0x1C, +0x2A, +0x38, +0x46, +0x54, +0x62, +0x69, +0x70, +0x77, +0x79, +0x7B, +0x7D, +0x7E, +0x02, +0x04, +0x00, +0x04, +0x00, +0x0D, +0x3E, +0x0E, +0x3C, +0x1F, +0x3A, +0x1F, +0x38, +0x1F, +0x78, +0x18, +0x78, +0x19, +0x76, +0x1A, +0x76, +0x1B, +0x74, +0x2C, +0x74, +0x2D, +0x74, +0x3D, +0x74, +0x6F, +0x00, +0x08, +0x11, +0x1A, +0x23, +0x2C, +0x2D, +0x3E, +0x10, +0x22, +0x33, +0x44, +0x55, +0x66, +0x87, +0x88, +0xCA, +0xF5, +0xF0, +0x80, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x80, +0x80, +0x00, +0x08, +0x07, +0x80, +0x07, +0x80, +0x82, +0x00, +0x01, +0x1E, +0x60, +0x1A, +0x0C, +0x0D, +0xB7, +0x03, +0x94, +0x18, +0x00, +0x10, +0xF0, +0x20, +0x00, +0x0B, +0x0B, +0x33, +0x0E, +0x1C, +0x2A, +0x38, +0x46, +0x54, +0x62, +0x69, +0x70, +0x77, +0x79, +0x7B, +0x7D, +0x7E, +0x02, +0x20, +0x00, +0x20, +0x00, +0x29, +0x3E, +0x31, +0x3C, +0x3B, +0x3A, +0x3B, +0x38, +0x3B, +0x38, +0x43, +0x38, +0x4B, +0x36, +0x53, +0x36, +0x5B, +0x34, +0x65, +0x34, +0x6D, +0x34, +0x6F, +0x74, +0x7D, +0x10, +0x22, +0x33, +0x44, +0x55, +0x66, +0x87, +0x88, +0x00, +0x10, +0x21, +0x32, +0x43, +0x54, +0x55, +0x76, +0x5A, +0x04, +0x28, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x28, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0xAA, +0x54, +0x46, +0xAA, +0x65, +0x54, +0xAA, +0x46, +0x65, +0xAA, +0x54, +0x46, +0xAA, +0x65, +0x54, +0xAA, +0x46, +0x65, +0xAA, +0x54, +0x46, +0xAA, +0x65, +0x54, +0xAA, +0x46, +0x65, +0xAA, +0x54, +0x46, +0xAA, +0x65, +0x54, +0xAA, +0x46, +0x65, +0xAA, +0x87, +0x79, +0xAA, +0x98, +0x87, +0xAA, +0x79, +0x98, +0xAA, +0x87, +0x79, +0xAA, +0x98, +0x87, +0xAA, +0x79, +0x98, +0xAA, +0x87, +0x79, +0xAA, +0x98, +0x87, +0xAA, +0x79, +0x98, +0xAA, +0x87, +0x79, +0xAA, +0x98, +0x87, +0xAA, +0x79, +0x98, +0x5F, +0xA0, +0x00, +0x07, +0x04, +0x0B, +0x33, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0xBA, +0x32, +0x28, +0x10, +0xE0, +0x81, +0x00, +0x00, +0x00, +0x00, +0x00, +0x10, +0xA5, +0x2D, +0x36, +0x2D, +0x36, +0x10, +0x00, +0x00, +0xD5, +0x5E, +0x00, +0x00, +0x00, +0x00, +0x00, +0x0A, +0x00, +0x00, +0xAA, +0x55, +0xAA, +0x44, +0x66, +0x88, +0x11, +0x33, +0x55, +0x00, +0x00, +0x00, +0xAA, +0xCC, +0xEE, +0x77, +0x99, +0xBB, +0x00, +0x00, +0x00, +0x88, +0xAA, +0xCC, +0x55, +0x77, +0x99, +0x00, +0x00, +0x00, +0xEE, +0x00, +0x22, +0xBB, +0xDD, +0xFF, +0x00, +0x00, +0x00, +0x66, +0x66, +0x66, +0xBB, +0xBB, +0xBB, +0x00, +0x00, +0x00, +0x66, +0xAA, +0xAA, +0xBB, +0xBB, +0xBB, +0x00, +0x00, +0x00, +0x01, +0x00, +0x00, +0x00, +0x00, +0x03, +0x30, +0x90, +0xC2, +0x22, +0x82, +0xE2, +0x42, +0xA2, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x6F, +0x01, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x3F, +0x00, +0x00, +0x3F, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x02, +0x00, +0x10, +0xEA, +0x06, +0x90, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x05, +0x00, +0x00, +0x00, +0x03, +0x90, +0xFF, +0xFF, +0x00, +0xF0, +0xE0, +0xD0, +0xC2, +0xC2, +0xC2, +0xC2, +0xC2, +0xC2, +0xC2, +0xC2, +0xC2, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x10, +0x32, +0x10, +0x32, +0x10, +0x32, +0x10, +0x32, +0x10, +0x32, +0x10, +0x32, +0x10, +0x32, +0x10, +0x32, +0x10, +0x32, +0x10, +0x32, +0x10, +0x32, +0x10, +0x32, +0x00, +0x10, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x64, +0x64, +0x64, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x65, +0xC1, +0x07, +0x10, +0xE0, +0x00, +0x04, +0x13, +0x40, +0x00, +0x60, +0x00, +0x00, +0x3F, +0xFF, +0x00, +0x00, +0x3F, +0xFF, +0x00, +0x00, +0x3F, +0xFF, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x20, +0x10, +0x04, +0x29, +0x00, +0x00, +0x08, +0x08, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x80, +0x40, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x80, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0xB9, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x05, +0x40, +0x40, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0xB0, +0x00, +0x00, +0x01, +0x01, +0x00, +0x01, +0x01, +0x00, +0x01, +0x01, +0x00, +0x01, +0x01, +0x00, +0x01, +0x01, +0x00, +0x01, +0x01, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x80, +0x8C, +0x00, +0x9B, +0x9B, +0x00, +0x9B, +0x9B, +0x00, +0x9B, +0x9B, +0x00, +0x9B, +0x9B, +0x00, +0x9B, +0x9B, +0x00, +0x9B, +0x9B, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x3E, +0x3E, +0x00, +0x3E, +0x3E, +0x00, +0x3E, +0x3E, +0x00, +0x3E, +0x3E, +0x00, +0x3E, +0x3E, +0x00, +0x3E, +0x3E, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0xFC, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x40, +0x00, +0x02, +0x03, +0x00, +0x00, +0x0C, +0x64, +0x08, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x01, +0x01, +0x00, +0x01, +0x01, +0x00, +0x01, +0x01, +0x00, +0x01, +0x01, +0x00, +0x00, +0x01, +0x01, +0x00, +0x01, +0x01, +0x20, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x03, +0x03, +0x03, +0x03, +0x03, +0x03, +0x03, +0x03, +0x03, +0x03, +0x03, +0x83, +0x1E, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x8C, +0x00, +0x0B, +0x0A, +0x09, +0x08, +0x07, +0x06, +0x05, +0x04, +0x03, +0x02, +0x01, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x10, +0x32, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x01, +0xA8, +0x61, +0xC4, +0x09, +0x03, +0x03, +0x7C, +0x13, +0x23, +0x33, +0x43, +0x53, +0x63, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x98, +0x3A, +0x31, +0x2F, +0x07, +0x27, +0x01, +0x00, +0x48, +0x00, +0x00, +0x49, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x70, +0x57, +0xA0, +0x3C, +0x00, +0x11, +0x22, +0x33, +0x44, +0x55, +0x00, +0x00, +0xFF, +0x00, +0xFA, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x44, +0x01, +0x89, +0x20, +0x01, +0x00, +0x06, +0xA0, +0x10, +0x40, +0x41, +0x24, +0x44, +0x01, +0x99, +0x30, +0x01, +0x00, +0x06, +0x20, +0x11, +0x40, +0x41, +0x24, +0x24, +0x01, +0x08, +0x80, +0x01, +0x00, +0x01, +0x80, +0x01, +0x0A, +0x40, +0x24, +0x24, +0x01, +0x01, +0x10, +0x01, +0x0A, +0x08, +0x01, +0x11, +0x40, +0x41, +0x24, +0x44, +0x01, +0x09, +0x40, +0x01, +0x00, +0x06, +0xA0, +0x10, +0x40, +0x41, +0x24, +0x44, +0x01, +0x19, +0x50, +0x01, +0x00, +0x06, +0xA0, +0x10, +0x40, +0x41, +0x24, +0x44, +0x01, +0x29, +0x60, +0x01, +0x00, +0x06, +0xA0, +0x10, +0x40, +0x41, +0x24, +0x44, +0x01, +0x39, +0x70, +0x01, +0x00, +0x06, +0xA0, +0x10, +0x40, +0x41, +0x24, +0x44, +0x01, +0x49, +0x80, +0x01, +0x00, +0x06, +0xA0, +0x10, +0x40, +0x41, +0x24, +0x44, +0x01, +0x59, +0x90, +0x01, +0x00, +0x06, +0xA0, +0x10, +0x40, +0x41, +0x24, +0x44, +0x01, +0x69, +0x00, +0x01, +0x00, +0x06, +0xA0, +0x10, +0x40, +0x41, +0x24, +0x44, +0x01, +0x79, +0x10, +0x01, +0x00, +0x06, +0xA0, +0x10, +0x40, +0x41, +0x24, +0x20, +0x0C, +0x00, +0x00, +0x5A, +0x00, +0x1C, +0x01, +0x13, +0x64, +0x00, +0x00, +0x31, +0x0C, +0x00, +0x00, +0x5A, +0x00, +0x1C, +0x01, +0x13, +0x64, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x04, +0x00, +0x00, +0x00, +0x01, +0x00, +0x01, +0x00, +0x87, +0x32, +0x20, +0x03, +0xF0, +0xB0, +0xF0, +0xF0, +0x70, +0x80, +0x00, +0x10, +0xC0, +0xD0, +0x20, +0x40, +0x50, +0x60, +0x90, +0xA0, +0x4F, +0x50, +0x61, +0xFF, +0x7F, +0x8F, +0x92, +0x13, +0x00, +0x0D, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x44, +0x50, +0x44, +0x44, +0x44, +0x44, +0x55, +0x00, +0x00, +0x00, +0xFF, +0xFF, +0x02, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x4E, +0x00, +0x00, +0x00, +0x00, +0x01, +0x20, +0x00, +0x03, +0x40, +0x00, +0x05, +0x60, +0x00, +0x07, +0x80, +0x00, +0x09, +0xA0, +0x00, +0x0B, +0xC0, +0x00, +0x0D, +0xE0, +0x00, +0x0F, +0x00, +0x01, +0x11, +0x20, +0x01, +0x13, +0x40, +0x01, +0x15, +0x60, +0x01, +0x17, +0x80, +0x01, +0x19, +0xA0, +0x01, +0x1B, +0xC0, +0x01, +0x1D, +0xE0, +0x01, +0x1F, +0x00, +0x02, +0x21, +0x20, +0x02, +0x23, +0x40, +0x02, +0x25, +0x60, +0x02, +0x27, +0x80, +0x02, +0x29, +0xA0, +0x02, +0x2B, +0xC0, +0x02, +0x2D, +0xE0, +0x02, +0x2F, +0x00, +0x03, +0x31, +0x20, +0x03, +0x33, +0x40, +0x03, +0x35, +0x60, +0x03, +0x37, +0x80, +0x03, +0x39, +0xA0, +0x03, +0x3B, +0xC0, +0x03, +0x3D, +0xE0, +0x03, +0x3F, +0x00, +0x04, +0x41, +0x20, +0x04, +0x43, +0x40, +0x04, +0x45, +0x60, +0x04, +0x47, +0x80, +0x04, +0x49, +0xA0, +0x04, +0x4B, +0xC0, +0x04, +0x4D, +0xE0, +0x04, +0x4F, +0x00, +0x05, +0x51, +0x20, +0x05, +0x53, +0x40, +0x05, +0x55, +0x60, +0x05, +0x57, +0x80, +0x05, +0x59, +0xA0, +0x05, +0x5B, +0xC0, +0x05, +0x5D, +0xE0, +0x05, +0x5F, +0x00, +0x06, +0x61, +0x20, +0x06, +0x63, +0x40, +0x06, +0x65, +0x60, +0x06, +0x67, +0x80, +0x06, +0x69, +0xA0, +0x06, +0x6B, +0xC0, +0x06, +0x6D, +0xE0, +0x06, +0x6F, +0x00, +0x07, +0x71, +0x20, +0x07, +0x73, +0x40, +0x07, +0x75, +0x60, +0x07, +0x77, +0x80, +0x07, +0x79, +0xA0, +0x07, +0x7B, +0xC0, +0x07, +0x7D, +0xE0, +0x07, +0x7F, +0x00, +0x08, +0x81, +0x20, +0x08, +0x83, +0x40, +0x08, +0x85, +0x60, +0x08, +0x87, +0x80, +0x08, +0x89, +0xA0, +0x08, +0x8B, +0xC0, +0x08, +0x8D, +0xE0, +0x08, +0x8F, +0x00, +0x09, +0x91, +0x20, +0x09, +0x93, +0x40, +0x09, +0x95, +0x60, +0x09, +0x97, +0x80, +0x09, +0x99, +0xA0, +0x09, +0x9B, +0xC0, +0x09, +0x9D, +0xE0, +0x09, +0x9F, +0x00, +0x0A, +0xA1, +0x20, +0x0A, +0xA3, +0x40, +0x0A, +0xA5, +0x60, +0x0A, +0xA7, +0x80, +0x0A, +0xA9, +0xA0, +0x0A, +0xAB, +0xC0, +0x0A, +0xAD, +0xE0, +0x0A, +0xAF, +0x00, +0x0B, +0xB1, +0x20, +0x0B, +0xB3, +0x40, +0x0B, +0xB5, +0x60, +0x0B, +0xB7, +0x80, +0x0B, +0xB9, +0xA0, +0x0B, +0xBB, +0xC0, +0x0B, +0xBD, +0xE0, +0x0B, +0xBF, +0x00, +0x0C, +0xC1, +0x20, +0x0C, +0xC3, +0x40, +0x0C, +0xC5, +0x60, +0x0C, +0xC7, +0x80, +0x0C, +0xC9, +0xA0, +0x0C, +0xCB, +0xC0, +0x0C, +0xCD, +0xE0, +0x0C, +0xCF, +0x00, +0x0D, +0xD1, +0x20, +0x0D, +0xD3, +0x40, +0x0D, +0xD5, +0x60, +0x0D, +0xD7, +0x80, +0x0D, +0xD9, +0xA0, +0x0D, +0xDB, +0xC0, +0x0D, +0xDD, +0xE0, +0x0D, +0xDF, +0x00, +0x0E, +0xE1, +0x20, +0x0E, +0xE3, +0x40, +0x0E, +0xE5, +0x60, +0x0E, +0xE7, +0x80, +0x0E, +0xE9, +0xA0, +0x0E, +0xEB, +0xC0, +0x0E, +0xED, +0xE0, +0x0E, +0xEF, +0x00, +0x0F, +0xF1, +0x20, +0x0F, +0xF3, +0x40, +0x0F, +0xF5, +0x60, +0x0F, +0xF7, +0x80, +0x0F, +0xF9, +0xA0, +0x0F, +0xFB, +0xC0, +0x0F, +0xFD, +0xE0, +0x0F, +0xFF, +0xFF, +0x0F, +0x00, +0x00, +0x00, +0x01, +0x20, +0x00, +0x03, +0x40, +0x00, +0x05, +0x60, +0x00, +0x07, +0x80, +0x00, +0x09, +0xA0, +0x00, +0x0B, +0xC0, +0x00, +0x0D, +0xE0, +0x00, +0x0F, +0x00, +0x01, +0x11, +0x20, +0x01, +0x13, +0x40, +0x01, +0x15, +0x60, +0x01, +0x17, +0x80, +0x01, +0x19, +0xA0, +0x01, +0x1B, +0xC0, +0x01, +0x1D, +0xE0, +0x01, +0x1F, +0x00, +0x02, +0x21, +0x20, +0x02, +0x23, +0x40, +0x02, +0x25, +0x60, +0x02, +0x27, +0x80, +0x02, +0x29, +0xA0, +0x02, +0x2B, +0xC0, +0x02, +0x2D, +0xE0, +0x02, +0x2F, +0x00, +0x03, +0x31, +0x20, +0x03, +0x33, +0x40, +0x03, +0x35, +0x60, +0x03, +0x37, +0x80, +0x03, +0x39, +0xA0, +0x03, +0x3B, +0xC0, +0x03, +0x3D, +0xE0, +0x03, +0x3F, +0x00, +0x04, +0x41, +0x20, +0x04, +0x43, +0x40, +0x04, +0x45, +0x60, +0x04, +0x47, +0x80, +0x04, +0x49, +0xA0, +0x04, +0x4B, +0xC0, +0x04, +0x4D, +0xE0, +0x04, +0x4F, +0x00, +0x05, +0x51, +0x20, +0x05, +0x53, +0x40, +0x05, +0x55, +0x60, +0x05, +0x57, +0x80, +0x05, +0x59, +0xA0, +0x05, +0x5B, +0xC0, +0x05, +0x5D, +0xE0, +0x05, +0x5F, +0x00, +0x06, +0x61, +0x20, +0x06, +0x63, +0x40, +0x06, +0x65, +0x60, +0x06, +0x67, +0x80, +0x06, +0x69, +0xA0, +0x06, +0x6B, +0xC0, +0x06, +0x6D, +0xE0, +0x06, +0x6F, +0x00, +0x07, +0x71, +0x20, +0x07, +0x73, +0x40, +0x07, +0x75, +0x60, +0x07, +0x77, +0x80, +0x07, +0x79, +0xA0, +0x07, +0x7B, +0xC0, +0x07, +0x7D, +0xE0, +0x07, +0x7F, +0x00, +0x08, +0x81, +0x20, +0x08, +0x83, +0x40, +0x08, +0x85, +0x60, +0x08, +0x87, +0x80, +0x08, +0x89, +0xA0, +0x08, +0x8B, +0xC0, +0x08, +0x8D, +0xE0, +0x08, +0x8F, +0x00, +0x09, +0x91, +0x20, +0x09, +0x93, +0x40, +0x09, +0x95, +0x60, +0x09, +0x97, +0x80, +0x09, +0x99, +0xA0, +0x09, +0x9B, +0xC0, +0x09, +0x9D, +0xE0, +0x09, +0x9F, +0x00, +0x0A, +0xA1, +0x20, +0x0A, +0xA3, +0x40, +0x0A, +0xA5, +0x60, +0x0A, +0xA7, +0x80, +0x0A, +0xA9, +0xA0, +0x0A, +0xAB, +0xC0, +0x0A, +0xAD, +0xE0, +0x0A, +0xAF, +0x00, +0x0B, +0xB1, +0x20, +0x0B, +0xB3, +0x40, +0x0B, +0xB5, +0x60, +0x0B, +0xB7, +0x80, +0x0B, +0xB9, +0xA0, +0x0B, +0xBB, +0xC0, +0x0B, +0xBD, +0xE0, +0x0B, +0xBF, +0x00, +0x0C, +0xC1, +0x20, +0x0C, +0xC3, +0x40, +0x0C, +0xC5, +0x60, +0x0C, +0xC7, +0x80, +0x0C, +0xC9, +0xA0, +0x0C, +0xCB, +0xC0, +0x0C, +0xCD, +0xE0, +0x0C, +0xCF, +0x00, +0x0D, +0xD1, +0x20, +0x0D, +0xD3, +0x40, +0x0D, +0xD5, +0x60, +0x0D, +0xD7, +0x80, +0x0D, +0xD9, +0xA0, +0x0D, +0xDB, +0xC0, +0x0D, +0xDD, +0xE0, +0x0D, +0xDF, +0x00, +0x0E, +0xE1, +0x20, +0x0E, +0xE3, +0x40, +0x0E, +0xE5, +0x60, +0x0E, +0xE7, +0x80, +0x0E, +0xE9, +0xA0, +0x0E, +0xEB, +0xC0, +0x0E, +0xED, +0xE0, +0x0E, +0xEF, +0x00, +0x0F, +0xF1, +0x20, +0x0F, +0xF3, +0x40, +0x0F, +0xF5, +0x60, +0x0F, +0xF7, +0x80, +0x0F, +0xF9, +0xA0, +0x0F, +0xFB, +0xC0, +0x0F, +0xFD, +0xE0, +0x0F, +0xFF, +0xFF, +0x0F, +0x00, +0x00, +0x00, +0x01, +0x20, +0x00, +0x03, +0x40, +0x00, +0x05, +0x60, +0x00, +0x07, +0x80, +0x00, +0x09, +0xA0, +0x00, +0x0B, +0xC0, +0x00, +0x0D, +0xE0, +0x00, +0x0F, +0x00, +0x01, +0x11, +0x20, +0x01, +0x13, +0x40, +0x01, +0x15, +0x60, +0x01, +0x17, +0x80, +0x01, +0x19, +0xA0, +0x01, +0x1B, +0xC0, +0x01, +0x1D, +0xE0, +0x01, +0x1F, +0x00, +0x02, +0x21, +0x20, +0x02, +0x23, +0x40, +0x02, +0x25, +0x60, +0x02, +0x27, +0x80, +0x02, +0x29, +0xA0, +0x02, +0x2B, +0xC0, +0x02, +0x2D, +0xE0, +0x02, +0x2F, +0x00, +0x03, +0x31, +0x20, +0x03, +0x33, +0x40, +0x03, +0x35, +0x60, +0x03, +0x37, +0x80, +0x03, +0x39, +0xA0, +0x03, +0x3B, +0xC0, +0x03, +0x3D, +0xE0, +0x03, +0x3F, +0x00, +0x04, +0x41, +0x20, +0x04, +0x43, +0x40, +0x04, +0x45, +0x60, +0x04, +0x47, +0x80, +0x04, +0x49, +0xA0, +0x04, +0x4B, +0xC0, +0x04, +0x4D, +0xE0, +0x04, +0x4F, +0x00, +0x05, +0x51, +0x20, +0x05, +0x53, +0x40, +0x05, +0x55, +0x60, +0x05, +0x57, +0x80, +0x05, +0x59, +0xA0, +0x05, +0x5B, +0xC0, +0x05, +0x5D, +0xE0, +0x05, +0x5F, +0x00, +0x06, +0x61, +0x20, +0x06, +0x63, +0x40, +0x06, +0x65, +0x60, +0x06, +0x67, +0x80, +0x06, +0x69, +0xA0, +0x06, +0x6B, +0xC0, +0x06, +0x6D, +0xE0, +0x06, +0x6F, +0x00, +0x07, +0x71, +0x20, +0x07, +0x73, +0x40, +0x07, +0x75, +0x60, +0x07, +0x77, +0x80, +0x07, +0x79, +0xA0, +0x07, +0x7B, +0xC0, +0x07, +0x7D, +0xE0, +0x07, +0x7F, +0x00, +0x08, +0x81, +0x20, +0x08, +0x83, +0x40, +0x08, +0x85, +0x60, +0x08, +0x87, +0x80, +0x08, +0x89, +0xA0, +0x08, +0x8B, +0xC0, +0x08, +0x8D, +0xE0, +0x08, +0x8F, +0x00, +0x09, +0x91, +0x20, +0x09, +0x93, +0x40, +0x09, +0x95, +0x60, +0x09, +0x97, +0x80, +0x09, +0x99, +0xA0, +0x09, +0x9B, +0xC0, +0x09, +0x9D, +0xE0, +0x09, +0x9F, +0x00, +0x0A, +0xA1, +0x20, +0x0A, +0xA3, +0x40, +0x0A, +0xA5, +0x60, +0x0A, +0xA7, +0x80, +0x0A, +0xA9, +0xA0, +0x0A, +0xAB, +0xC0, +0x0A, +0xAD, +0xE0, +0x0A, +0xAF, +0x00, +0x0B, +0xB1, +0x20, +0x0B, +0xB3, +0x40, +0x0B, +0xB5, +0x60, +0x0B, +0xB7, +0x80, +0x0B, +0xB9, +0xA0, +0x0B, +0xBB, +0xC0, +0x0B, +0xBD, +0xE0, +0x0B, +0xBF, +0x00, +0x0C, +0xC1, +0x20, +0x0C, +0xC3, +0x40, +0x0C, +0xC5, +0x60, +0x0C, +0xC7, +0x80, +0x0C, +0xC9, +0xA0, +0x0C, +0xCB, +0xC0, +0x0C, +0xCD, +0xE0, +0x0C, +0xCF, +0x00, +0x0D, +0xD1, +0x20, +0x0D, +0xD3, +0x40, +0x0D, +0xD5, +0x60, +0x0D, +0xD7, +0x80, +0x0D, +0xD9, +0xA0, +0x0D, +0xDB, +0xC0, +0x0D, +0xDD, +0xE0, +0x0D, +0xDF, +0x00, +0x0E, +0xE1, +0x20, +0x0E, +0xE3, +0x40, +0x0E, +0xE5, +0x60, +0x0E, +0xE7, +0x80, +0x0E, +0xE9, +0xA0, +0x0E, +0xEB, +0xC0, +0x0E, +0xED, +0xE0, +0x0E, +0xEF, +0x00, +0x0F, +0xF1, +0x20, +0x0F, +0xF3, +0x40, +0x0F, +0xF5, +0x60, +0x0F, +0xF7, +0x80, +0x0F, +0xF9, +0xA0, +0x0F, +0xFB, +0xC0, +0x0F, +0xFD, +0xE0, +0x0F, +0xFF, +0x00, +0x00, +0x00, +0x00, +0x00, +0x01, +0x20, +0x00, +0x03, +0x40, +0x00, +0x05, +0x60, +0x00, +0x07, +0x80, +0x00, +0x09, +0xA0, +0x00, +0x0B, +0xC0, +0x00, +0x0D, +0xE0, +0x00, +0x0F, +0x00, +0x01, +0x11, +0x20, +0x01, +0x13, +0x40, +0x01, +0x15, +0x60, +0x01, +0x17, +0x80, +0x01, +0x19, +0xA0, +0x01, +0x1B, +0xC0, +0x01, +0x1D, +0xE0, +0x01, +0x1F, +0x00, +0x02, +0x21, +0x20, +0x02, +0x23, +0x40, +0x02, +0x25, +0x60, +0x02, +0x27, +0x80, +0x02, +0x29, +0xA0, +0x02, +0x2B, +0xC0, +0x02, +0x2D, +0xE0, +0x02, +0x2F, +0x00, +0x03, +0x31, +0x20, +0x03, +0x33, +0x40, +0x03, +0x35, +0x60, +0x03, +0x37, +0x80, +0x03, +0x39, +0xA0, +0x03, +0x3B, +0xC0, +0x03, +0x3D, +0xE0, +0x03, +0x3F, +0x00, +0x04, +0x41, +0x20, +0x04, +0x43, +0x40, +0x04, +0x45, +0x60, +0x04, +0x47, +0x80, +0x04, +0x49, +0xA0, +0x04, +0x4B, +0xC0, +0x04, +0x4D, +0xE0, +0x04, +0x4F, +0x00, +0x05, +0x51, +0x20, +0x05, +0x53, +0x40, +0x05, +0x55, +0x60, +0x05, +0x57, +0x80, +0x05, +0x59, +0xA0, +0x05, +0x5B, +0xC0, +0x05, +0x5D, +0xE0, +0x05, +0x5F, +0x00, +0x06, +0x61, +0x20, +0x06, +0x63, +0x40, +0x06, +0x65, +0x60, +0x06, +0x67, +0x80, +0x06, +0x69, +0xA0, +0x06, +0x6B, +0xC0, +0x06, +0x6D, +0xE0, +0x06, +0x6F, +0x00, +0x07, +0x71, +0x20, +0x07, +0x73, +0x40, +0x07, +0x75, +0x60, +0x07, +0x77, +0x80, +0x07, +0x79, +0xA0, +0x07, +0x7B, +0xC0, +0x07, +0x7D, +0xE0, +0x07, +0x7F, +0x00, +0x08, +0x81, +0x20, +0x08, +0x83, +0x40, +0x08, +0x85, +0x60, +0x08, +0x87, +0x80, +0x08, +0x89, +0xA0, +0x08, +0x8B, +0xC0, +0x08, +0x8D, +0xE0, +0x08, +0x8F, +0x00, +0x09, +0x91, +0x20, +0x09, +0x93, +0x40, +0x09, +0x95, +0x60, +0x09, +0x97, +0x80, +0x09, +0x99, +0xA0, +0x09, +0x9B, +0xC0, +0x09, +0x9D, +0xE0, +0x09, +0x9F, +0x00, +0x0A, +0xA1, +0x20, +0x0A, +0xA3, +0x40, +0x0A, +0xA5, +0x60, +0x0A, +0xA7, +0x80, +0x0A, +0xA9, +0xA0, +0x0A, +0xAB, +0xC0, +0x0A, +0xAD, +0xE0, +0x0A, +0xAF, +0x00, +0x0B, +0xB1, +0x20, +0x0B, +0xB3, +0x40, +0x0B, +0xB5, +0x60, +0x0B, +0xB7, +0x80, +0x0B, +0xB9, +0xA0, +0x0B, +0xBB, +0xC0, +0x0B, +0xBD, +0xE0, +0x0B, +0xBF, +0x00, +0x0C, +0xC1, +0x20, +0x0C, +0xC3, +0x40, +0x0C, +0xC5, +0x60, +0x0C, +0xC7, +0x80, +0x0C, +0xC9, +0xA0, +0x0C, +0xCB, +0xC0, +0x0C, +0xCD, +0xE0, +0x0C, +0xCF, +0x00, +0x0D, +0xD1, +0x20, +0x0D, +0xD3, +0x40, +0x0D, +0xD5, +0x60, +0x0D, +0xD7, +0x80, +0x0D, +0xD9, +0xA0, +0x0D, +0xDB, +0xC0, +0x0D, +0xDD, +0xE0, +0x0D, +0xDF, +0x00, +0x0E, +0xE1, +0x20, +0x0E, +0xE3, +0x40, +0x0E, +0xE5, +0x60, +0x0E, +0xE7, +0x80, +0x0E, +0xE9, +0xA0, +0x0E, +0xEB, +0xC0, +0x0E, +0xED, +0xE0, +0x0E, +0xEF, +0x00, +0x0F, +0xF1, +0x20, +0x0F, +0xF3, +0x40, +0x0F, +0xF5, +0x60, +0x0F, +0xF7, +0x80, +0x0F, +0xF9, +0xA0, +0x0F, +0xFB, +0xC0, +0x0F, +0xFD, +0xE0, +0x0F, +0xFF, +0xFF, +0x0F, +0x00, +0x00, +0x00, +0x01, +0x20, +0x00, +0x03, +0x40, +0x00, +0x05, +0x60, +0x00, +0x07, +0x80, +0x00, +0x09, +0xA0, +0x00, +0x0B, +0xC0, +0x00, +0x0D, +0xE0, +0x00, +0x0F, +0x00, +0x01, +0x11, +0x20, +0x01, +0x13, +0x40, +0x01, +0x15, +0x60, +0x01, +0x17, +0x80, +0x01, +0x19, +0xA0, +0x01, +0x1B, +0xC0, +0x01, +0x1D, +0xE0, +0x01, +0x1F, +0x00, +0x02, +0x21, +0x20, +0x02, +0x23, +0x40, +0x02, +0x25, +0x60, +0x02, +0x27, +0x80, +0x02, +0x29, +0xA0, +0x02, +0x2B, +0xC0, +0x02, +0x2D, +0xE0, +0x02, +0x2F, +0x00, +0x03, +0x31, +0x20, +0x03, +0x33, +0x40, +0x03, +0x35, +0x60, +0x03, +0x37, +0x80, +0x03, +0x39, +0xA0, +0x03, +0x3B, +0xC0, +0x03, +0x3D, +0xE0, +0x03, +0x3F, +0x00, +0x04, +0x41, +0x20, +0x04, +0x43, +0x40, +0x04, +0x45, +0x60, +0x04, +0x47, +0x80, +0x04, +0x49, +0xA0, +0x04, +0x4B, +0xC0, +0x04, +0x4D, +0xE0, +0x04, +0x4F, +0x00, +0x05, +0x51, +0x20, +0x05, +0x53, +0x40, +0x05, +0x55, +0x60, +0x05, +0x57, +0x80, +0x05, +0x59, +0xA0, +0x05, +0x5B, +0xC0, +0x05, +0x5D, +0xE0, +0x05, +0x5F, +0x00, +0x06, +0x61, +0x20, +0x06, +0x63, +0x40, +0x06, +0x65, +0x60, +0x06, +0x67, +0x80, +0x06, +0x69, +0xA0, +0x06, +0x6B, +0xC0, +0x06, +0x6D, +0xE0, +0x06, +0x6F, +0x00, +0x07, +0x71, +0x20, +0x07, +0x73, +0x40, +0x07, +0x75, +0x60, +0x07, +0x77, +0x80, +0x07, +0x79, +0xA0, +0x07, +0x7B, +0xC0, +0x07, +0x7D, +0xE0, +0x07, +0x7F, +0x00, +0x08, +0x81, +0x20, +0x08, +0x83, +0x40, +0x08, +0x85, +0x60, +0x08, +0x87, +0x80, +0x08, +0x89, +0xA0, +0x08, +0x8B, +0xC0, +0x08, +0x8D, +0xE0, +0x08, +0x8F, +0x00, +0x09, +0x91, +0x20, +0x09, +0x93, +0x40, +0x09, +0x95, +0x60, +0x09, +0x97, +0x80, +0x09, +0x99, +0xA0, +0x09, +0x9B, +0xC0, +0x09, +0x9D, +0xE0, +0x09, +0x9F, +0x00, +0x0A, +0xA1, +0x20, +0x0A, +0xA3, +0x40, +0x0A, +0xA5, +0x60, +0x0A, +0xA7, +0x80, +0x0A, +0xA9, +0xA0, +0x0A, +0xAB, +0xC0, +0x0A, +0xAD, +0xE0, +0x0A, +0xAF, +0x00, +0x0B, +0xB1, +0x20, +0x0B, +0xB3, +0x40, +0x0B, +0xB5, +0x60, +0x0B, +0xB7, +0x80, +0x0B, +0xB9, +0xA0, +0x0B, +0xBB, +0xC0, +0x0B, +0xBD, +0xE0, +0x0B, +0xBF, +0x00, +0x0C, +0xC1, +0x20, +0x0C, +0xC3, +0x40, +0x0C, +0xC5, +0x60, +0x0C, +0xC7, +0x80, +0x0C, +0xC9, +0xA0, +0x0C, +0xCB, +0xC0, +0x0C, +0xCD, +0xE0, +0x0C, +0xCF, +0x00, +0x0D, +0xD1, +0x20, +0x0D, +0xD3, +0x40, +0x0D, +0xD5, +0x60, +0x0D, +0xD7, +0x80, +0x0D, +0xD9, +0xA0, +0x0D, +0xDB, +0xC0, +0x0D, +0xDD, +0xE0, +0x0D, +0xDF, +0x00, +0x0E, +0xE1, +0x20, +0x0E, +0xE3, +0x40, +0x0E, +0xE5, +0x60, +0x0E, +0xE7, +0x80, +0x0E, +0xE9, +0xA0, +0x0E, +0xEB, +0xC0, +0x0E, +0xED, +0xE0, +0x0E, +0xEF, +0x00, +0x0F, +0xF1, +0x20, +0x0F, +0xF3, +0x40, +0x0F, +0xF5, +0x60, +0x0F, +0xF7, +0x80, +0x0F, +0xF9, +0xA0, +0x0F, +0xFB, +0xC0, +0x0F, +0xFD, +0xE0, +0x0F, +0xFF, +0xFF, +0x0F, +0x00, +0x00, +0x00, +0x01, +0x20, +0x00, +0x03, +0x40, +0x00, +0x05, +0x60, +0x00, +0x07, +0x80, +0x00, +0x09, +0xA0, +0x00, +0x0B, +0xC0, +0x00, +0x0D, +0xE0, +0x00, +0x0F, +0x00, +0x01, +0x11, +0x20, +0x01, +0x13, +0x40, +0x01, +0x15, +0x60, +0x01, +0x17, +0x80, +0x01, +0x19, +0xA0, +0x01, +0x1B, +0xC0, +0x01, +0x1D, +0xE0, +0x01, +0x1F, +0x00, +0x02, +0x21, +0x20, +0x02, +0x23, +0x40, +0x02, +0x25, +0x60, +0x02, +0x27, +0x80, +0x02, +0x29, +0xA0, +0x02, +0x2B, +0xC0, +0x02, +0x2D, +0xE0, +0x02, +0x2F, +0x00, +0x03, +0x31, +0x20, +0x03, +0x33, +0x40, +0x03, +0x35, +0x60, +0x03, +0x37, +0x80, +0x03, +0x39, +0xA0, +0x03, +0x3B, +0xC0, +0x03, +0x3D, +0xE0, +0x03, +0x3F, +0x00, +0x04, +0x41, +0x20, +0x04, +0x43, +0x40, +0x04, +0x45, +0x60, +0x04, +0x47, +0x80, +0x04, +0x49, +0xA0, +0x04, +0x4B, +0xC0, +0x04, +0x4D, +0xE0, +0x04, +0x4F, +0x00, +0x05, +0x51, +0x20, +0x05, +0x53, +0x40, +0x05, +0x55, +0x60, +0x05, +0x57, +0x80, +0x05, +0x59, +0xA0, +0x05, +0x5B, +0xC0, +0x05, +0x5D, +0xE0, +0x05, +0x5F, +0x00, +0x06, +0x61, +0x20, +0x06, +0x63, +0x40, +0x06, +0x65, +0x60, +0x06, +0x67, +0x80, +0x06, +0x69, +0xA0, +0x06, +0x6B, +0xC0, +0x06, +0x6D, +0xE0, +0x06, +0x6F, +0x00, +0x07, +0x71, +0x20, +0x07, +0x73, +0x40, +0x07, +0x75, +0x60, +0x07, +0x77, +0x80, +0x07, +0x79, +0xA0, +0x07, +0x7B, +0xC0, +0x07, +0x7D, +0xE0, +0x07, +0x7F, +0x00, +0x08, +0x81, +0x20, +0x08, +0x83, +0x40, +0x08, +0x85, +0x60, +0x08, +0x87, +0x80, +0x08, +0x89, +0xA0, +0x08, +0x8B, +0xC0, +0x08, +0x8D, +0xE0, +0x08, +0x8F, +0x00, +0x09, +0x91, +0x20, +0x09, +0x93, +0x40, +0x09, +0x95, +0x60, +0x09, +0x97, +0x80, +0x09, +0x99, +0xA0, +0x09, +0x9B, +0xC0, +0x09, +0x9D, +0xE0, +0x09, +0x9F, +0x00, +0x0A, +0xA1, +0x20, +0x0A, +0xA3, +0x40, +0x0A, +0xA5, +0x60, +0x0A, +0xA7, +0x80, +0x0A, +0xA9, +0xA0, +0x0A, +0xAB, +0xC0, +0x0A, +0xAD, +0xE0, +0x0A, +0xAF, +0x00, +0x0B, +0xB1, +0x20, +0x0B, +0xB3, +0x40, +0x0B, +0xB5, +0x60, +0x0B, +0xB7, +0x80, +0x0B, +0xB9, +0xA0, +0x0B, +0xBB, +0xC0, +0x0B, +0xBD, +0xE0, +0x0B, +0xBF, +0x00, +0x0C, +0xC1, +0x20, +0x0C, +0xC3, +0x40, +0x0C, +0xC5, +0x60, +0x0C, +0xC7, +0x80, +0x0C, +0xC9, +0xA0, +0x0C, +0xCB, +0xC0, +0x0C, +0xCD, +0xE0, +0x0C, +0xCF, +0x00, +0x0D, +0xD1, +0x20, +0x0D, +0xD3, +0x40, +0x0D, +0xD5, +0x60, +0x0D, +0xD7, +0x80, +0x0D, +0xD9, +0xA0, +0x0D, +0xDB, +0xC0, +0x0D, +0xDD, +0xE0, +0x0D, +0xDF, +0x00, +0x0E, +0xE1, +0x20, +0x0E, +0xE3, +0x40, +0x0E, +0xE5, +0x60, +0x0E, +0xE7, +0x80, +0x0E, +0xE9, +0xA0, +0x0E, +0xEB, +0xC0, +0x0E, +0xED, +0xE0, +0x0E, +0xEF, +0x00, +0x0F, +0xF1, +0x20, +0x0F, +0xF3, +0x40, +0x0F, +0xF5, +0x60, +0x0F, +0xF7, +0x80, +0x0F, +0xF9, +0xA0, +0x0F, +0xFB, +0xC0, +0x0F, +0xFD, +0xE0, +0x0F, +0xFF, +0x00, +0x00, +0x00, +0x00, +0x00, +0x01, +0x20, +0x00, +0x03, +0x40, +0x00, +0x05, +0x60, +0x00, +0x07, +0x80, +0x00, +0x09, +0xA0, +0x00, +0x0B, +0xC0, +0x00, +0x0D, +0xE0, +0x00, +0x0F, +0x00, +0x01, +0x11, +0x20, +0x01, +0x13, +0x40, +0x01, +0x15, +0x60, +0x01, +0x17, +0x80, +0x01, +0x19, +0xA0, +0x01, +0x1B, +0xC0, +0x01, +0x1D, +0xE0, +0x01, +0x1F, +0x00, +0x02, +0x21, +0x20, +0x02, +0x23, +0x40, +0x02, +0x25, +0x60, +0x02, +0x27, +0x80, +0x02, +0x29, +0xA0, +0x02, +0x2B, +0xC0, +0x02, +0x2D, +0xE0, +0x02, +0x2F, +0x00, +0x03, +0x31, +0x20, +0x03, +0x33, +0x40, +0x03, +0x35, +0x60, +0x03, +0x37, +0x80, +0x03, +0x39, +0xA0, +0x03, +0x3B, +0xC0, +0x03, +0x3D, +0xE0, +0x03, +0x3F, +0x00, +0x04, +0x41, +0x20, +0x04, +0x43, +0x40, +0x04, +0x45, +0x60, +0x04, +0x47, +0x80, +0x04, +0x49, +0xA0, +0x04, +0x4B, +0xC0, +0x04, +0x4D, +0xE0, +0x04, +0x4F, +0x00, +0x05, +0x51, +0x20, +0x05, +0x53, +0x40, +0x05, +0x55, +0x60, +0x05, +0x57, +0x80, +0x05, +0x59, +0xA0, +0x05, +0x5B, +0xC0, +0x05, +0x5D, +0xE0, +0x05, +0x5F, +0x00, +0x06, +0x61, +0x20, +0x06, +0x63, +0x40, +0x06, +0x65, +0x60, +0x06, +0x67, +0x80, +0x06, +0x69, +0xA0, +0x06, +0x6B, +0xC0, +0x06, +0x6D, +0xE0, +0x06, +0x6F, +0x00, +0x07, +0x71, +0x20, +0x07, +0x73, +0x40, +0x07, +0x75, +0x60, +0x07, +0x77, +0x80, +0x07, +0x79, +0xA0, +0x07, +0x7B, +0xC0, +0x07, +0x7D, +0xE0, +0x07, +0x7F, +0x00, +0x08, +0x81, +0x20, +0x08, +0x83, +0x40, +0x08, +0x85, +0x60, +0x08, +0x87, +0x80, +0x08, +0x89, +0xA0, +0x08, +0x8B, +0xC0, +0x08, +0x8D, +0xE0, +0x08, +0x8F, +0x00, +0x09, +0x91, +0x20, +0x09, +0x93, +0x40, +0x09, +0x95, +0x60, +0x09, +0x97, +0x80, +0x09, +0x99, +0xA0, +0x09, +0x9B, +0xC0, +0x09, +0x9D, +0xE0, +0x09, +0x9F, +0x00, +0x0A, +0xA1, +0x20, +0x0A, +0xA3, +0x40, +0x0A, +0xA5, +0x60, +0x0A, +0xA7, +0x80, +0x0A, +0xA9, +0xA0, +0x0A, +0xAB, +0xC0, +0x0A, +0xAD, +0xE0, +0x0A, +0xAF, +0x00, +0x0B, +0xB1, +0x20, +0x0B, +0xB3, +0x40, +0x0B, +0xB5, +0x60, +0x0B, +0xB7, +0x80, +0x0B, +0xB9, +0xA0, +0x0B, +0xBB, +0xC0, +0x0B, +0xBD, +0xE0, +0x0B, +0xBF, +0x00, +0x0C, +0xC1, +0x20, +0x0C, +0xC3, +0x40, +0x0C, +0xC5, +0x60, +0x0C, +0xC7, +0x80, +0x0C, +0xC9, +0xA0, +0x0C, +0xCB, +0xC0, +0x0C, +0xCD, +0xE0, +0x0C, +0xCF, +0x00, +0x0D, +0xD1, +0x20, +0x0D, +0xD3, +0x40, +0x0D, +0xD5, +0x60, +0x0D, +0xD7, +0x80, +0x0D, +0xD9, +0xA0, +0x0D, +0xDB, +0xC0, +0x0D, +0xDD, +0xE0, +0x0D, +0xDF, +0x00, +0x0E, +0xE1, +0x20, +0x0E, +0xE3, +0x40, +0x0E, +0xE5, +0x60, +0x0E, +0xE7, +0x80, +0x0E, +0xE9, +0xA0, +0x0E, +0xEB, +0xC0, +0x0E, +0xED, +0xE0, +0x0E, +0xEF, +0x00, +0x0F, +0xF1, +0x20, +0x0F, +0xF3, +0x40, +0x0F, +0xF5, +0x60, +0x0F, +0xF7, +0x80, +0x0F, +0xF9, +0xA0, +0x0F, +0xFB, +0xC0, +0x0F, +0xFD, +0xE0, +0x0F, +0xFF, +0xFF, +0x0F, +0x00, +0x00, +0x00, +0x01, +0x20, +0x00, +0x03, +0x40, +0x00, +0x05, +0x60, +0x00, +0x07, +0x80, +0x00, +0x09, +0xA0, +0x00, +0x0B, +0xC0, +0x00, +0x0D, +0xE0, +0x00, +0x0F, +0x00, +0x01, +0x11, +0x20, +0x01, +0x13, +0x40, +0x01, +0x15, +0x60, +0x01, +0x17, +0x80, +0x01, +0x19, +0xA0, +0x01, +0x1B, +0xC0, +0x01, +0x1D, +0xE0, +0x01, +0x1F, +0x00, +0x02, +0x21, +0x20, +0x02, +0x23, +0x40, +0x02, +0x25, +0x60, +0x02, +0x27, +0x80, +0x02, +0x29, +0xA0, +0x02, +0x2B, +0xC0, +0x02, +0x2D, +0xE0, +0x02, +0x2F, +0x00, +0x03, +0x31, +0x20, +0x03, +0x33, +0x40, +0x03, +0x35, +0x60, +0x03, +0x37, +0x80, +0x03, +0x39, +0xA0, +0x03, +0x3B, +0xC0, +0x03, +0x3D, +0xE0, +0x03, +0x3F, +0x00, +0x04, +0x41, +0x20, +0x04, +0x43, +0x40, +0x04, +0x45, +0x60, +0x04, +0x47, +0x80, +0x04, +0x49, +0xA0, +0x04, +0x4B, +0xC0, +0x04, +0x4D, +0xE0, +0x04, +0x4F, +0x00, +0x05, +0x51, +0x20, +0x05, +0x53, +0x40, +0x05, +0x55, +0x60, +0x05, +0x57, +0x80, +0x05, +0x59, +0xA0, +0x05, +0x5B, +0xC0, +0x05, +0x5D, +0xE0, +0x05, +0x5F, +0x00, +0x06, +0x61, +0x20, +0x06, +0x63, +0x40, +0x06, +0x65, +0x60, +0x06, +0x67, +0x80, +0x06, +0x69, +0xA0, +0x06, +0x6B, +0xC0, +0x06, +0x6D, +0xE0, +0x06, +0x6F, +0x00, +0x07, +0x71, +0x20, +0x07, +0x73, +0x40, +0x07, +0x75, +0x60, +0x07, +0x77, +0x80, +0x07, +0x79, +0xA0, +0x07, +0x7B, +0xC0, +0x07, +0x7D, +0xE0, +0x07, +0x7F, +0x00, +0x08, +0x81, +0x20, +0x08, +0x83, +0x40, +0x08, +0x85, +0x60, +0x08, +0x87, +0x80, +0x08, +0x89, +0xA0, +0x08, +0x8B, +0xC0, +0x08, +0x8D, +0xE0, +0x08, +0x8F, +0x00, +0x09, +0x91, +0x20, +0x09, +0x93, +0x40, +0x09, +0x95, +0x60, +0x09, +0x97, +0x80, +0x09, +0x99, +0xA0, +0x09, +0x9B, +0xC0, +0x09, +0x9D, +0xE0, +0x09, +0x9F, +0x00, +0x0A, +0xA1, +0x20, +0x0A, +0xA3, +0x40, +0x0A, +0xA5, +0x60, +0x0A, +0xA7, +0x80, +0x0A, +0xA9, +0xA0, +0x0A, +0xAB, +0xC0, +0x0A, +0xAD, +0xE0, +0x0A, +0xAF, +0x00, +0x0B, +0xB1, +0x20, +0x0B, +0xB3, +0x40, +0x0B, +0xB5, +0x60, +0x0B, +0xB7, +0x80, +0x0B, +0xB9, +0xA0, +0x0B, +0xBB, +0xC0, +0x0B, +0xBD, +0xE0, +0x0B, +0xBF, +0x00, +0x0C, +0xC1, +0x20, +0x0C, +0xC3, +0x40, +0x0C, +0xC5, +0x60, +0x0C, +0xC7, +0x80, +0x0C, +0xC9, +0xA0, +0x0C, +0xCB, +0xC0, +0x0C, +0xCD, +0xE0, +0x0C, +0xCF, +0x00, +0x0D, +0xD1, +0x20, +0x0D, +0xD3, +0x40, +0x0D, +0xD5, +0x60, +0x0D, +0xD7, +0x80, +0x0D, +0xD9, +0xA0, +0x0D, +0xDB, +0xC0, +0x0D, +0xDD, +0xE0, +0x0D, +0xDF, +0x00, +0x0E, +0xE1, +0x20, +0x0E, +0xE3, +0x40, +0x0E, +0xE5, +0x60, +0x0E, +0xE7, +0x80, +0x0E, +0xE9, +0xA0, +0x0E, +0xEB, +0xC0, +0x0E, +0xED, +0xE0, +0x0E, +0xEF, +0x00, +0x0F, +0xF1, +0x20, +0x0F, +0xF3, +0x40, +0x0F, +0xF5, +0x60, +0x0F, +0xF7, +0x80, +0x0F, +0xF9, +0xA0, +0x0F, +0xFB, +0xC0, +0x0F, +0xFD, +0xE0, +0x0F, +0xFF, +0xFF, +0x0F, +0x00, +0x00, +0x00, +0x01, +0x20, +0x00, +0x03, +0x40, +0x00, +0x05, +0x60, +0x00, +0x07, +0x80, +0x00, +0x09, +0xA0, +0x00, +0x0B, +0xC0, +0x00, +0x0D, +0xE0, +0x00, +0x0F, +0x00, +0x01, +0x11, +0x20, +0x01, +0x13, +0x40, +0x01, +0x15, +0x60, +0x01, +0x17, +0x80, +0x01, +0x19, +0xA0, +0x01, +0x1B, +0xC0, +0x01, +0x1D, +0xE0, +0x01, +0x1F, +0x00, +0x02, +0x21, +0x20, +0x02, +0x23, +0x40, +0x02, +0x25, +0x60, +0x02, +0x27, +0x80, +0x02, +0x29, +0xA0, +0x02, +0x2B, +0xC0, +0x02, +0x2D, +0xE0, +0x02, +0x2F, +0x00, +0x03, +0x31, +0x20, +0x03, +0x33, +0x40, +0x03, +0x35, +0x60, +0x03, +0x37, +0x80, +0x03, +0x39, +0xA0, +0x03, +0x3B, +0xC0, +0x03, +0x3D, +0xE0, +0x03, +0x3F, +0x00, +0x04, +0x41, +0x20, +0x04, +0x43, +0x40, +0x04, +0x45, +0x60, +0x04, +0x47, +0x80, +0x04, +0x49, +0xA0, +0x04, +0x4B, +0xC0, +0x04, +0x4D, +0xE0, +0x04, +0x4F, +0x00, +0x05, +0x51, +0x20, +0x05, +0x53, +0x40, +0x05, +0x55, +0x60, +0x05, +0x57, +0x80, +0x05, +0x59, +0xA0, +0x05, +0x5B, +0xC0, +0x05, +0x5D, +0xE0, +0x05, +0x5F, +0x00, +0x06, +0x61, +0x20, +0x06, +0x63, +0x40, +0x06, +0x65, +0x60, +0x06, +0x67, +0x80, +0x06, +0x69, +0xA0, +0x06, +0x6B, +0xC0, +0x06, +0x6D, +0xE0, +0x06, +0x6F, +0x00, +0x07, +0x71, +0x20, +0x07, +0x73, +0x40, +0x07, +0x75, +0x60, +0x07, +0x77, +0x80, +0x07, +0x79, +0xA0, +0x07, +0x7B, +0xC0, +0x07, +0x7D, +0xE0, +0x07, +0x7F, +0x00, +0x08, +0x81, +0x20, +0x08, +0x83, +0x40, +0x08, +0x85, +0x60, +0x08, +0x87, +0x80, +0x08, +0x89, +0xA0, +0x08, +0x8B, +0xC0, +0x08, +0x8D, +0xE0, +0x08, +0x8F, +0x00, +0x09, +0x91, +0x20, +0x09, +0x93, +0x40, +0x09, +0x95, +0x60, +0x09, +0x97, +0x80, +0x09, +0x99, +0xA0, +0x09, +0x9B, +0xC0, +0x09, +0x9D, +0xE0, +0x09, +0x9F, +0x00, +0x0A, +0xA1, +0x20, +0x0A, +0xA3, +0x40, +0x0A, +0xA5, +0x60, +0x0A, +0xA7, +0x80, +0x0A, +0xA9, +0xA0, +0x0A, +0xAB, +0xC0, +0x0A, +0xAD, +0xE0, +0x0A, +0xAF, +0x00, +0x0B, +0xB1, +0x20, +0x0B, +0xB3, +0x40, +0x0B, +0xB5, +0x60, +0x0B, +0xB7, +0x80, +0x0B, +0xB9, +0xA0, +0x0B, +0xBB, +0xC0, +0x0B, +0xBD, +0xE0, +0x0B, +0xBF, +0x00, +0x0C, +0xC1, +0x20, +0x0C, +0xC3, +0x40, +0x0C, +0xC5, +0x60, +0x0C, +0xC7, +0x80, +0x0C, +0xC9, +0xA0, +0x0C, +0xCB, +0xC0, +0x0C, +0xCD, +0xE0, +0x0C, +0xCF, +0x00, +0x0D, +0xD1, +0x20, +0x0D, +0xD3, +0x40, +0x0D, +0xD5, +0x60, +0x0D, +0xD7, +0x80, +0x0D, +0xD9, +0xA0, +0x0D, +0xDB, +0xC0, +0x0D, +0xDD, +0xE0, +0x0D, +0xDF, +0x00, +0x0E, +0xE1, +0x20, +0x0E, +0xE3, +0x40, +0x0E, +0xE5, +0x60, +0x0E, +0xE7, +0x80, +0x0E, +0xE9, +0xA0, +0x0E, +0xEB, +0xC0, +0x0E, +0xED, +0xE0, +0x0E, +0xEF, +0x00, +0x0F, +0xF1, +0x20, +0x0F, +0xF3, +0x40, +0x0F, +0xF5, +0x60, +0x0F, +0xF7, +0x80, +0x0F, +0xF9, +0xA0, +0x0F, +0xFB, +0xC0, +0x0F, +0xFD, +0xE0, +0x0F, +0xFF, +0x00, +0x00, +0x00, +0x00, +0x00, +0x01, +0x20, +0x00, +0x03, +0x40, +0x00, +0x05, +0x60, +0x00, +0x07, +0x80, +0x00, +0x09, +0xA0, +0x00, +0x0B, +0xC0, +0x00, +0x0D, +0xE0, +0x00, +0x0F, +0x00, +0x01, +0x11, +0x20, +0x01, +0x13, +0x40, +0x01, +0x15, +0x60, +0x01, +0x17, +0x80, +0x01, +0x19, +0xA0, +0x01, +0x1B, +0xC0, +0x01, +0x1D, +0xE0, +0x01, +0x1F, +0x00, +0x02, +0x21, +0x20, +0x02, +0x23, +0x40, +0x02, +0x25, +0x60, +0x02, +0x27, +0x80, +0x02, +0x29, +0xA0, +0x02, +0x2B, +0xC0, +0x02, +0x2D, +0xE0, +0x02, +0x2F, +0x00, +0x03, +0x31, +0x20, +0x03, +0x33, +0x40, +0x03, +0x35, +0x60, +0x03, +0x37, +0x80, +0x03, +0x39, +0xA0, +0x03, +0x3B, +0xC0, +0x03, +0x3D, +0xE0, +0x03, +0x3F, +0x00, +0x04, +0x41, +0x20, +0x04, +0x43, +0x40, +0x04, +0x45, +0x60, +0x04, +0x47, +0x80, +0x04, +0x49, +0xA0, +0x04, +0x4B, +0xC0, +0x04, +0x4D, +0xE0, +0x04, +0x4F, +0x00, +0x05, +0x51, +0x20, +0x05, +0x53, +0x40, +0x05, +0x55, +0x60, +0x05, +0x57, +0x80, +0x05, +0x59, +0xA0, +0x05, +0x5B, +0xC0, +0x05, +0x5D, +0xE0, +0x05, +0x5F, +0x00, +0x06, +0x61, +0x20, +0x06, +0x63, +0x40, +0x06, +0x65, +0x60, +0x06, +0x67, +0x80, +0x06, +0x69, +0xA0, +0x06, +0x6B, +0xC0, +0x06, +0x6D, +0xE0, +0x06, +0x6F, +0x00, +0x07, +0x71, +0x20, +0x07, +0x73, +0x40, +0x07, +0x75, +0x60, +0x07, +0x77, +0x80, +0x07, +0x79, +0xA0, +0x07, +0x7B, +0xC0, +0x07, +0x7D, +0xE0, +0x07, +0x7F, +0x00, +0x08, +0x81, +0x20, +0x08, +0x83, +0x40, +0x08, +0x85, +0x60, +0x08, +0x87, +0x80, +0x08, +0x89, +0xA0, +0x08, +0x8B, +0xC0, +0x08, +0x8D, +0xE0, +0x08, +0x8F, +0x00, +0x09, +0x91, +0x20, +0x09, +0x93, +0x40, +0x09, +0x95, +0x60, +0x09, +0x97, +0x80, +0x09, +0x99, +0xA0, +0x09, +0x9B, +0xC0, +0x09, +0x9D, +0xE0, +0x09, +0x9F, +0x00, +0x0A, +0xA1, +0x20, +0x0A, +0xA3, +0x40, +0x0A, +0xA5, +0x60, +0x0A, +0xA7, +0x80, +0x0A, +0xA9, +0xA0, +0x0A, +0xAB, +0xC0, +0x0A, +0xAD, +0xE0, +0x0A, +0xAF, +0x00, +0x0B, +0xB1, +0x20, +0x0B, +0xB3, +0x40, +0x0B, +0xB5, +0x60, +0x0B, +0xB7, +0x80, +0x0B, +0xB9, +0xA0, +0x0B, +0xBB, +0xC0, +0x0B, +0xBD, +0xE0, +0x0B, +0xBF, +0x00, +0x0C, +0xC1, +0x20, +0x0C, +0xC3, +0x40, +0x0C, +0xC5, +0x60, +0x0C, +0xC7, +0x80, +0x0C, +0xC9, +0xA0, +0x0C, +0xCB, +0xC0, +0x0C, +0xCD, +0xE0, +0x0C, +0xCF, +0x00, +0x0D, +0xD1, +0x20, +0x0D, +0xD3, +0x40, +0x0D, +0xD5, +0x60, +0x0D, +0xD7, +0x80, +0x0D, +0xD9, +0xA0, +0x0D, +0xDB, +0xC0, +0x0D, +0xDD, +0xE0, +0x0D, +0xDF, +0x00, +0x0E, +0xE1, +0x20, +0x0E, +0xE3, +0x40, +0x0E, +0xE5, +0x60, +0x0E, +0xE7, +0x80, +0x0E, +0xE9, +0xA0, +0x0E, +0xEB, +0xC0, +0x0E, +0xED, +0xE0, +0x0E, +0xEF, +0x00, +0x0F, +0xF1, +0x20, +0x0F, +0xF3, +0x40, +0x0F, +0xF5, +0x60, +0x0F, +0xF7, +0x80, +0x0F, +0xF9, +0xA0, +0x0F, +0xFB, +0xC0, +0x0F, +0xFD, +0xE0, +0x0F, +0xFF, +0xFF, +0x0F, +0x00, +0x3C, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x04, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x08, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x0C, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x14, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x1C, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x20, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x28, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x38, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x40, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x48, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x50, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x58, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x68, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x70, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x78, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x80, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x88, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0x90, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xA0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xB0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xC0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD0, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xD8, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE0, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xE8, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF0, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0xF8, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x21, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0xFF, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x40, +0x40, +0x00, +0x00, +0x82, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0xFF, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x01, +0x20, +0x00, +0x03, +0x40, +0x00, +0x05, +0x60, +0x00, +0x07, +0x80, +0x00, +0x09, +0xA0, +0x00, +0x0B, +0xC0, +0x00, +0x0D, +0xE0, +0x00, +0x0F, +0x00, +0x01, +0x11, +0x20, +0x01, +0x13, +0x40, +0x01, +0x15, +0x60, +0x01, +0x17, +0x80, +0x01, +0x19, +0xA0, +0x01, +0x1B, +0xC0, +0x01, +0x1D, +0xE0, +0x01, +0x1F, +0x00, +0x02, +0x21, +0x20, +0x02, +0x23, +0x40, +0x02, +0x25, +0x60, +0x02, +0x27, +0x80, +0x02, +0x29, +0xA0, +0x02, +0x2B, +0xC0, +0x02, +0x2D, +0xE0, +0x02, +0x2F, +0x00, +0x03, +0x31, +0x20, +0x03, +0x33, +0x40, +0x03, +0x35, +0x60, +0x03, +0x37, +0x80, +0x03, +0x39, +0xA0, +0x03, +0x3B, +0xC0, +0x03, +0x3D, +0xE0, +0x03, +0x3F, +0x00, +0x04, +0x41, +0x20, +0x04, +0x43, +0x40, +0x04, +0x45, +0x60, +0x04, +0x47, +0x80, +0x04, +0x49, +0xA0, +0x04, +0x4B, +0xC0, +0x04, +0x4D, +0xE0, +0x04, +0x4F, +0x00, +0x05, +0x51, +0x20, +0x05, +0x53, +0x40, +0x05, +0x55, +0x60, +0x05, +0x57, +0x80, +0x05, +0x59, +0xA0, +0x05, +0x5B, +0xC0, +0x05, +0x5D, +0xE0, +0x05, +0x5F, +0x00, +0x06, +0x61, +0x20, +0x06, +0x63, +0x40, +0x06, +0x65, +0x60, +0x06, +0x67, +0x80, +0x06, +0x69, +0xA0, +0x06, +0x6B, +0xC0, +0x06, +0x6D, +0xE0, +0x06, +0x6F, +0x00, +0x07, +0x71, +0x20, +0x07, +0x73, +0x40, +0x07, +0x75, +0x60, +0x07, +0x77, +0x80, +0x07, +0x79, +0xA0, +0x07, +0x7B, +0xC0, +0x07, +0x7D, +0xE0, +0x07, +0x7F, +0x00, +0x08, +0x81, +0x20, +0x08, +0x83, +0x40, +0x08, +0x85, +0x60, +0x08, +0x87, +0x80, +0x08, +0x89, +0xA0, +0x08, +0x8B, +0xC0, +0x08, +0x8D, +0xE0, +0x08, +0x8F, +0x00, +0x09, +0x91, +0x20, +0x09, +0x93, +0x40, +0x09, +0x95, +0x60, +0x09, +0x97, +0x80, +0x09, +0x99, +0xA0, +0x09, +0x9B, +0xC0, +0x09, +0x9D, +0xE0, +0x09, +0x9F, +0x00, +0x0A, +0xA1, +0x20, +0x0A, +0xA3, +0x40, +0x0A, +0xA5, +0x60, +0x0A, +0xA7, +0x80, +0x0A, +0xA9, +0xA0, +0x0A, +0xAB, +0xC0, +0x0A, +0xAD, +0xE0, +0x0A, +0xAF, +0x00, +0x0B, +0xB1, +0x20, +0x0B, +0xB3, +0x40, +0x0B, +0xB5, +0x60, +0x0B, +0xB7, +0x80, +0x0B, +0xB9, +0xA0, +0x0B, +0xBB, +0xC0, +0x0B, +0xBD, +0xE0, +0x0B, +0xBF, +0x00, +0x0C, +0xC1, +0x20, +0x0C, +0xC3, +0x40, +0x0C, +0xC5, +0x60, +0x0C, +0xC7, +0x80, +0x0C, +0xC9, +0xA0, +0x0C, +0xCB, +0xC0, +0x0C, +0xCD, +0xE0, +0x0C, +0xCF, +0x00, +0x0D, +0xD1, +0x20, +0x0D, +0xD3, +0x40, +0x0D, +0xD5, +0x60, +0x0D, +0xD7, +0x80, +0x0D, +0xD9, +0xA0, +0x0D, +0xDB, +0xC0, +0x0D, +0xDD, +0xE0, +0x0D, +0xDF, +0x00, +0x0E, +0xE1, +0x20, +0x0E, +0xE3, +0x40, +0x0E, +0xE5, +0x60, +0x0E, +0xE7, +0x80, +0x0E, +0xE9, +0xA0, +0x0E, +0xEB, +0xC0, +0x0E, +0xED, +0xE0, +0x0E, +0xEF, +0x00, +0x0F, +0xF1, +0x20, +0x0F, +0xF3, +0x40, +0x0F, +0xF5, +0x60, +0x0F, +0xF7, +0x80, +0x0F, +0xF9, +0xA0, +0x0F, +0xFB, +0xC0, +0x0F, +0xFD, +0xE0, +0x0F, +0xFF, +0xFF, +0x0F, +0x00, +0x00, +0x00, +0x01, +0x20, +0x00, +0x03, +0x40, +0x00, +0x05, +0x60, +0x00, +0x07, +0x80, +0x00, +0x09, +0xA0, +0x00, +0x0B, +0xC0, +0x00, +0x0D, +0xE0, +0x00, +0x0F, +0x00, +0x01, +0x11, +0x20, +0x01, +0x13, +0x40, +0x01, +0x15, +0x60, +0x01, +0x17, +0x80, +0x01, +0x19, +0xA0, +0x01, +0x1B, +0xC0, +0x01, +0x1D, +0xE0, +0x01, +0x1F, +0x00, +0x02, +0x21, +0x20, +0x02, +0x23, +0x40, +0x02, +0x25, +0x60, +0x02, +0x27, +0x80, +0x02, +0x29, +0xA0, +0x02, +0x2B, +0xC0, +0x02, +0x2D, +0xE0, +0x02, +0x2F, +0x00, +0x03, +0x31, +0x20, +0x03, +0x33, +0x40, +0x03, +0x35, +0x60, +0x03, +0x37, +0x80, +0x03, +0x39, +0xA0, +0x03, +0x3B, +0xC0, +0x03, +0x3D, +0xE0, +0x03, +0x3F, +0x00, +0x04, +0x41, +0x20, +0x04, +0x43, +0x40, +0x04, +0x45, +0x60, +0x04, +0x47, +0x80, +0x04, +0x49, +0xA0, +0x04, +0x4B, +0xC0, +0x04, +0x4D, +0xE0, +0x04, +0x4F, +0x00, +0x05, +0x51, +0x20, +0x05, +0x53, +0x40, +0x05, +0x55, +0x60, +0x05, +0x57, +0x80, +0x05, +0x59, +0xA0, +0x05, +0x5B, +0xC0, +0x05, +0x5D, +0xE0, +0x05, +0x5F, +0x00, +0x06, +0x61, +0x20, +0x06, +0x63, +0x40, +0x06, +0x65, +0x60, +0x06, +0x67, +0x80, +0x06, +0x69, +0xA0, +0x06, +0x6B, +0xC0, +0x06, +0x6D, +0xE0, +0x06, +0x6F, +0x00, +0x07, +0x71, +0x20, +0x07, +0x73, +0x40, +0x07, +0x75, +0x60, +0x07, +0x77, +0x80, +0x07, +0x79, +0xA0, +0x07, +0x7B, +0xC0, +0x07, +0x7D, +0xE0, +0x07, +0x7F, +0x00, +0x08, +0x81, +0x20, +0x08, +0x83, +0x40, +0x08, +0x85, +0x60, +0x08, +0x87, +0x80, +0x08, +0x89, +0xA0, +0x08, +0x8B, +0xC0, +0x08, +0x8D, +0xE0, +0x08, +0x8F, +0x00, +0x09, +0x91, +0x20, +0x09, +0x93, +0x40, +0x09, +0x95, +0x60, +0x09, +0x97, +0x80, +0x09, +0x99, +0xA0, +0x09, +0x9B, +0xC0, +0x09, +0x9D, +0xE0, +0x09, +0x9F, +0x00, +0x0A, +0xA1, +0x20, +0x0A, +0xA3, +0x40, +0x0A, +0xA5, +0x60, +0x0A, +0xA7, +0x80, +0x0A, +0xA9, +0xA0, +0x0A, +0xAB, +0xC0, +0x0A, +0xAD, +0xE0, +0x0A, +0xAF, +0x00, +0x0B, +0xB1, +0x20, +0x0B, +0xB3, +0x40, +0x0B, +0xB5, +0x60, +0x0B, +0xB7, +0x80, +0x0B, +0xB9, +0xA0, +0x0B, +0xBB, +0xC0, +0x0B, +0xBD, +0xE0, +0x0B, +0xBF, +0x00, +0x0C, +0xC1, +0x20, +0x0C, +0xC3, +0x40, +0x0C, +0xC5, +0x60, +0x0C, +0xC7, +0x80, +0x0C, +0xC9, +0xA0, +0x0C, +0xCB, +0xC0, +0x0C, +0xCD, +0xE0, +0x0C, +0xCF, +0x00, +0x0D, +0xD1, +0x20, +0x0D, +0xD3, +0x40, +0x0D, +0xD5, +0x60, +0x0D, +0xD7, +0x80, +0x0D, +0xD9, +0xA0, +0x0D, +0xDB, +0xC0, +0x0D, +0xDD, +0xE0, +0x0D, +0xDF, +0x00, +0x0E, +0xE1, +0x20, +0x0E, +0xE3, +0x40, +0x0E, +0xE5, +0x60, +0x0E, +0xE7, +0x80, +0x0E, +0xE9, +0xA0, +0x0E, +0xEB, +0xC0, +0x0E, +0xED, +0xE0, +0x0E, +0xEF, +0x00, +0x0F, +0xF1, +0x20, +0x0F, +0xF3, +0x40, +0x0F, +0xF5, +0x60, +0x0F, +0xF7, +0x80, +0x0F, +0xF9, +0xA0, +0x0F, +0xFB, +0xC0, +0x0F, +0xFD, +0xE0, +0x0F, +0xFF, +0xFF, +0x0F, +0x00, +0x00, +0x00, +0x01, +0x20, +0x00, +0x03, +0x40, +0x00, +0x05, +0x60, +0x00, +0x07, +0x80, +0x00, +0x09, +0xA0, +0x00, +0x0B, +0xC0, +0x00, +0x0D, +0xE0, +0x00, +0x0F, +0x00, +0x01, +0x11, +0x20, +0x01, +0x13, +0x40, +0x01, +0x15, +0x60, +0x01, +0x17, +0x80, +0x01, +0x19, +0xA0, +0x01, +0x1B, +0xC0, +0x01, +0x1D, +0xE0, +0x01, +0x1F, +0x00, +0x02, +0x21, +0x20, +0x02, +0x23, +0x40, +0x02, +0x25, +0x60, +0x02, +0x27, +0x80, +0x02, +0x29, +0xA0, +0x02, +0x2B, +0xC0, +0x02, +0x2D, +0xE0, +0x02, +0x2F, +0x00, +0x03, +0x31, +0x20, +0x03, +0x33, +0x40, +0x03, +0x35, +0x60, +0x03, +0x37, +0x80, +0x03, +0x39, +0xA0, +0x03, +0x3B, +0xC0, +0x03, +0x3D, +0xE0, +0x03, +0x3F, +0x00, +0x04, +0x41, +0x20, +0x04, +0x43, +0x40, +0x04, +0x45, +0x60, +0x04, +0x47, +0x80, +0x04, +0x49, +0xA0, +0x04, +0x4B, +0xC0, +0x04, +0x4D, +0xE0, +0x04, +0x4F, +0x00, +0x05, +0x51, +0x20, +0x05, +0x53, +0x40, +0x05, +0x55, +0x60, +0x05, +0x57, +0x80, +0x05, +0x59, +0xA0, +0x05, +0x5B, +0xC0, +0x05, +0x5D, +0xE0, +0x05, +0x5F, +0x00, +0x06, +0x61, +0x20, +0x06, +0x63, +0x40, +0x06, +0x65, +0x60, +0x06, +0x67, +0x80, +0x06, +0x69, +0xA0, +0x06, +0x6B, +0xC0, +0x06, +0x6D, +0xE0, +0x06, +0x6F, +0x00, +0x07, +0x71, +0x20, +0x07, +0x73, +0x40, +0x07, +0x75, +0x60, +0x07, +0x77, +0x80, +0x07, +0x79, +0xA0, +0x07, +0x7B, +0xC0, +0x07, +0x7D, +0xE0, +0x07, +0x7F, +0x00, +0x08, +0x81, +0x20, +0x08, +0x83, +0x40, +0x08, +0x85, +0x60, +0x08, +0x87, +0x80, +0x08, +0x89, +0xA0, +0x08, +0x8B, +0xC0, +0x08, +0x8D, +0xE0, +0x08, +0x8F, +0x00, +0x09, +0x91, +0x20, +0x09, +0x93, +0x40, +0x09, +0x95, +0x60, +0x09, +0x97, +0x80, +0x09, +0x99, +0xA0, +0x09, +0x9B, +0xC0, +0x09, +0x9D, +0xE0, +0x09, +0x9F, +0x00, +0x0A, +0xA1, +0x20, +0x0A, +0xA3, +0x40, +0x0A, +0xA5, +0x60, +0x0A, +0xA7, +0x80, +0x0A, +0xA9, +0xA0, +0x0A, +0xAB, +0xC0, +0x0A, +0xAD, +0xE0, +0x0A, +0xAF, +0x00, +0x0B, +0xB1, +0x20, +0x0B, +0xB3, +0x40, +0x0B, +0xB5, +0x60, +0x0B, +0xB7, +0x80, +0x0B, +0xB9, +0xA0, +0x0B, +0xBB, +0xC0, +0x0B, +0xBD, +0xE0, +0x0B, +0xBF, +0x00, +0x0C, +0xC1, +0x20, +0x0C, +0xC3, +0x40, +0x0C, +0xC5, +0x60, +0x0C, +0xC7, +0x80, +0x0C, +0xC9, +0xA0, +0x0C, +0xCB, +0xC0, +0x0C, +0xCD, +0xE0, +0x0C, +0xCF, +0x00, +0x0D, +0xD1, +0x20, +0x0D, +0xD3, +0x40, +0x0D, +0xD5, +0x60, +0x0D, +0xD7, +0x80, +0x0D, +0xD9, +0xA0, +0x0D, +0xDB, +0xC0, +0x0D, +0xDD, +0xE0, +0x0D, +0xDF, +0x00, +0x0E, +0xE1, +0x20, +0x0E, +0xE3, +0x40, +0x0E, +0xE5, +0x60, +0x0E, +0xE7, +0x80, +0x0E, +0xE9, +0xA0, +0x0E, +0xEB, +0xC0, +0x0E, +0xED, +0xE0, +0x0E, +0xEF, +0x00, +0x0F, +0xF1, +0x20, +0x0F, +0xF3, +0x40, +0x0F, +0xF5, +0x60, +0x0F, +0xF7, +0x80, +0x0F, +0xF9, +0xA0, +0x0F, +0xFB, +0xC0, +0x0F, +0xFD, +0xE0, +0x0F, +0xFF, +0xFF, +0x0F, +0x00, +0x1E, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x01, +0x20, +0x00, +0x03, +0x40, +0x00, +0x05, +0x60, +0x00, +0x07, +0x80, +0x00, +0x09, +0xA0, +0x00, +0x0B, +0xC0, +0x00, +0x0D, +0xE0, +0x00, +0x0F, +0x00, +0x01, +0x11, +0x20, +0x01, +0x13, +0x40, +0x01, +0x15, +0x60, +0x01, +0x17, +0x80, +0x01, +0x19, +0xA0, +0x01, +0x1B, +0xC0, +0x01, +0x1D, +0xE0, +0x01, +0x1F, +0x00, +0x02, +0x21, +0x20, +0x02, +0x23, +0x40, +0x02, +0x25, +0x60, +0x02, +0x27, +0x80, +0x02, +0x29, +0xA0, +0x02, +0x2B, +0xC0, +0x02, +0x2D, +0xE0, +0x02, +0x2F, +0x00, +0x03, +0x31, +0x20, +0x03, +0x33, +0x40, +0x03, +0x35, +0x60, +0x03, +0x37, +0x80, +0x03, +0x39, +0xA0, +0x03, +0x3B, +0xC0, +0x03, +0x3D, +0xE0, +0x03, +0x3F, +0x00, +0x04, +0x41, +0x20, +0x04, +0x43, +0x40, +0x04, +0x45, +0x60, +0x04, +0x47, +0x80, +0x04, +0x49, +0xA0, +0x04, +0x4B, +0xC0, +0x04, +0x4D, +0xE0, +0x04, +0x4F, +0x00, +0x05, +0x51, +0x20, +0x05, +0x53, +0x40, +0x05, +0x55, +0x60, +0x05, +0x57, +0x80, +0x05, +0x59, +0xA0, +0x05, +0x5B, +0xC0, +0x05, +0x5D, +0xE0, +0x05, +0x5F, +0x00, +0x06, +0x61, +0x20, +0x06, +0x63, +0x40, +0x06, +0x65, +0x60, +0x06, +0x67, +0x80, +0x06, +0x69, +0xA0, +0x06, +0x6B, +0xC0, +0x06, +0x6D, +0xE0, +0x06, +0x6F, +0x00, +0x07, +0x71, +0x20, +0x07, +0x73, +0x40, +0x07, +0x75, +0x60, +0x07, +0x77, +0x80, +0x07, +0x79, +0xA0, +0x07, +0x7B, +0xC0, +0x07, +0x7D, +0xE0, +0x07, +0x7F, +0x00, +0x08, +0x81, +0x20, +0x08, +0x83, +0x40, +0x08, +0x85, +0x60, +0x08, +0x87, +0x80, +0x08, +0x89, +0xA0, +0x08, +0x8B, +0xC0, +0x08, +0x8D, +0xE0, +0x08, +0x8F, +0x00, +0x09, +0x91, +0x20, +0x09, +0x93, +0x40, +0x09, +0x95, +0x60, +0x09, +0x97, +0x80, +0x09, +0x99, +0xA0, +0x09, +0x9B, +0xC0, +0x09, +0x9D, +0xE0, +0x09, +0x9F, +0x00, +0x0A, +0xA1, +0x20, +0x0A, +0xA3, +0x40, +0x0A, +0xA5, +0x60, +0x0A, +0xA7, +0x80, +0x0A, +0xA9, +0xA0, +0x0A, +0xAB, +0xC0, +0x0A, +0xAD, +0xE0, +0x0A, +0xAF, +0x00, +0x0B, +0xB1, +0x20, +0x0B, +0xB3, +0x40, +0x0B, +0xB5, +0x60, +0x0B, +0xB7, +0x80, +0x0B, +0xB9, +0xA0, +0x0B, +0xBB, +0xC0, +0x0B, +0xBD, +0xE0, +0x0B, +0xBF, +0x00, +0x0C, +0xC1, +0x20, +0x0C, +0xC3, +0x40, +0x0C, +0xC5, +0x60, +0x0C, +0xC7, +0x80, +0x0C, +0xC9, +0xA0, +0x0C, +0xCB, +0xC0, +0x0C, +0xCD, +0xE0, +0x0C, +0xCF, +0x00, +0x0D, +0xD1, +0x20, +0x0D, +0xD3, +0x40, +0x0D, +0xD5, +0x60, +0x0D, +0xD7, +0x80, +0x0D, +0xD9, +0xA0, +0x0D, +0xDB, +0xC0, +0x0D, +0xDD, +0xE0, +0x0D, +0xDF, +0x00, +0x0E, +0xE1, +0x20, +0x0E, +0xE3, +0x40, +0x0E, +0xE5, +0x60, +0x0E, +0xE7, +0x80, +0x0E, +0xE9, +0xA0, +0x0E, +0xEB, +0xC0, +0x0E, +0xED, +0xE0, +0x0E, +0xEF, +0x00, +0x0F, +0xF1, +0x20, +0x0F, +0xF3, +0x40, +0x0F, +0xF5, +0x60, +0x0F, +0xF7, +0x80, +0x0F, +0xF9, +0xA0, +0x0F, +0xFB, +0xC0, +0x0F, +0xFD, +0xE0, +0x0F, +0xFF, +0xFF, +0x0F, +0x00, +0x00, +0x00, +0x01, +0x20, +0x00, +0x03, +0x40, +0x00, +0x05, +0x60, +0x00, +0x07, +0x80, +0x00, +0x09, +0xA0, +0x00, +0x0B, +0xC0, +0x00, +0x0D, +0xE0, +0x00, +0x0F, +0x00, +0x01, +0x11, +0x20, +0x01, +0x13, +0x40, +0x01, +0x15, +0x60, +0x01, +0x17, +0x80, +0x01, +0x19, +0xA0, +0x01, +0x1B, +0xC0, +0x01, +0x1D, +0xE0, +0x01, +0x1F, +0x00, +0x02, +0x21, +0x20, +0x02, +0x23, +0x40, +0x02, +0x25, +0x60, +0x02, +0x27, +0x80, +0x02, +0x29, +0xA0, +0x02, +0x2B, +0xC0, +0x02, +0x2D, +0xE0, +0x02, +0x2F, +0x00, +0x03, +0x31, +0x20, +0x03, +0x33, +0x40, +0x03, +0x35, +0x60, +0x03, +0x37, +0x80, +0x03, +0x39, +0xA0, +0x03, +0x3B, +0xC0, +0x03, +0x3D, +0xE0, +0x03, +0x3F, +0x00, +0x04, +0x41, +0x20, +0x04, +0x43, +0x40, +0x04, +0x45, +0x60, +0x04, +0x47, +0x80, +0x04, +0x49, +0xA0, +0x04, +0x4B, +0xC0, +0x04, +0x4D, +0xE0, +0x04, +0x4F, +0x00, +0x05, +0x51, +0x20, +0x05, +0x53, +0x40, +0x05, +0x55, +0x60, +0x05, +0x57, +0x80, +0x05, +0x59, +0xA0, +0x05, +0x5B, +0xC0, +0x05, +0x5D, +0xE0, +0x05, +0x5F, +0x00, +0x06, +0x61, +0x20, +0x06, +0x63, +0x40, +0x06, +0x65, +0x60, +0x06, +0x67, +0x80, +0x06, +0x69, +0xA0, +0x06, +0x6B, +0xC0, +0x06, +0x6D, +0xE0, +0x06, +0x6F, +0x00, +0x07, +0x71, +0x20, +0x07, +0x73, +0x40, +0x07, +0x75, +0x60, +0x07, +0x77, +0x80, +0x07, +0x79, +0xA0, +0x07, +0x7B, +0xC0, +0x07, +0x7D, +0xE0, +0x07, +0x7F, +0x00, +0x08, +0x81, +0x20, +0x08, +0x83, +0x40, +0x08, +0x85, +0x60, +0x08, +0x87, +0x80, +0x08, +0x89, +0xA0, +0x08, +0x8B, +0xC0, +0x08, +0x8D, +0xE0, +0x08, +0x8F, +0x00, +0x09, +0x91, +0x20, +0x09, +0x93, +0x40, +0x09, +0x95, +0x60, +0x09, +0x97, +0x80, +0x09, +0x99, +0xA0, +0x09, +0x9B, +0xC0, +0x09, +0x9D, +0xE0, +0x09, +0x9F, +0x00, +0x0A, +0xA1, +0x20, +0x0A, +0xA3, +0x40, +0x0A, +0xA5, +0x60, +0x0A, +0xA7, +0x80, +0x0A, +0xA9, +0xA0, +0x0A, +0xAB, +0xC0, +0x0A, +0xAD, +0xE0, +0x0A, +0xAF, +0x00, +0x0B, +0xB1, +0x20, +0x0B, +0xB3, +0x40, +0x0B, +0xB5, +0x60, +0x0B, +0xB7, +0x80, +0x0B, +0xB9, +0xA0, +0x0B, +0xBB, +0xC0, +0x0B, +0xBD, +0xE0, +0x0B, +0xBF, +0x00, +0x0C, +0xC1, +0x20, +0x0C, +0xC3, +0x40, +0x0C, +0xC5, +0x60, +0x0C, +0xC7, +0x80, +0x0C, +0xC9, +0xA0, +0x0C, +0xCB, +0xC0, +0x0C, +0xCD, +0xE0, +0x0C, +0xCF, +0x00, +0x0D, +0xD1, +0x20, +0x0D, +0xD3, +0x40, +0x0D, +0xD5, +0x60, +0x0D, +0xD7, +0x80, +0x0D, +0xD9, +0xA0, +0x0D, +0xDB, +0xC0, +0x0D, +0xDD, +0xE0, +0x0D, +0xDF, +0x00, +0x0E, +0xE1, +0x20, +0x0E, +0xE3, +0x40, +0x0E, +0xE5, +0x60, +0x0E, +0xE7, +0x80, +0x0E, +0xE9, +0xA0, +0x0E, +0xEB, +0xC0, +0x0E, +0xED, +0xE0, +0x0E, +0xEF, +0x00, +0x0F, +0xF1, +0x20, +0x0F, +0xF3, +0x40, +0x0F, +0xF5, +0x60, +0x0F, +0xF7, +0x80, +0x0F, +0xF9, +0xA0, +0x0F, +0xFB, +0xC0, +0x0F, +0xFD, +0xE0, +0x0F, +0xFF, +0xFF, +0x0F, +0x00, +0x00, +0x00, +0x01, +0x20, +0x00, +0x03, +0x40, +0x00, +0x05, +0x60, +0x00, +0x07, +0x80, +0x00, +0x09, +0xA0, +0x00, +0x0B, +0xC0, +0x00, +0x0D, +0xE0, +0x00, +0x0F, +0x00, +0x01, +0x11, +0x20, +0x01, +0x13, +0x40, +0x01, +0x15, +0x60, +0x01, +0x17, +0x80, +0x01, +0x19, +0xA0, +0x01, +0x1B, +0xC0, +0x01, +0x1D, +0xE0, +0x01, +0x1F, +0x00, +0x02, +0x21, +0x20, +0x02, +0x23, +0x40, +0x02, +0x25, +0x60, +0x02, +0x27, +0x80, +0x02, +0x29, +0xA0, +0x02, +0x2B, +0xC0, +0x02, +0x2D, +0xE0, +0x02, +0x2F, +0x00, +0x03, +0x31, +0x20, +0x03, +0x33, +0x40, +0x03, +0x35, +0x60, +0x03, +0x37, +0x80, +0x03, +0x39, +0xA0, +0x03, +0x3B, +0xC0, +0x03, +0x3D, +0xE0, +0x03, +0x3F, +0x00, +0x04, +0x41, +0x20, +0x04, +0x43, +0x40, +0x04, +0x45, +0x60, +0x04, +0x47, +0x80, +0x04, +0x49, +0xA0, +0x04, +0x4B, +0xC0, +0x04, +0x4D, +0xE0, +0x04, +0x4F, +0x00, +0x05, +0x51, +0x20, +0x05, +0x53, +0x40, +0x05, +0x55, +0x60, +0x05, +0x57, +0x80, +0x05, +0x59, +0xA0, +0x05, +0x5B, +0xC0, +0x05, +0x5D, +0xE0, +0x05, +0x5F, +0x00, +0x06, +0x61, +0x20, +0x06, +0x63, +0x40, +0x06, +0x65, +0x60, +0x06, +0x67, +0x80, +0x06, +0x69, +0xA0, +0x06, +0x6B, +0xC0, +0x06, +0x6D, +0xE0, +0x06, +0x6F, +0x00, +0x07, +0x71, +0x20, +0x07, +0x73, +0x40, +0x07, +0x75, +0x60, +0x07, +0x77, +0x80, +0x07, +0x79, +0xA0, +0x07, +0x7B, +0xC0, +0x07, +0x7D, +0xE0, +0x07, +0x7F, +0x00, +0x08, +0x81, +0x20, +0x08, +0x83, +0x40, +0x08, +0x85, +0x60, +0x08, +0x87, +0x80, +0x08, +0x89, +0xA0, +0x08, +0x8B, +0xC0, +0x08, +0x8D, +0xE0, +0x08, +0x8F, +0x00, +0x09, +0x91, +0x20, +0x09, +0x93, +0x40, +0x09, +0x95, +0x60, +0x09, +0x97, +0x80, +0x09, +0x99, +0xA0, +0x09, +0x9B, +0xC0, +0x09, +0x9D, +0xE0, +0x09, +0x9F, +0x00, +0x0A, +0xA1, +0x20, +0x0A, +0xA3, +0x40, +0x0A, +0xA5, +0x60, +0x0A, +0xA7, +0x80, +0x0A, +0xA9, +0xA0, +0x0A, +0xAB, +0xC0, +0x0A, +0xAD, +0xE0, +0x0A, +0xAF, +0x00, +0x0B, +0xB1, +0x20, +0x0B, +0xB3, +0x40, +0x0B, +0xB5, +0x60, +0x0B, +0xB7, +0x80, +0x0B, +0xB9, +0xA0, +0x0B, +0xBB, +0xC0, +0x0B, +0xBD, +0xE0, +0x0B, +0xBF, +0x00, +0x0C, +0xC1, +0x20, +0x0C, +0xC3, +0x40, +0x0C, +0xC5, +0x60, +0x0C, +0xC7, +0x80, +0x0C, +0xC9, +0xA0, +0x0C, +0xCB, +0xC0, +0x0C, +0xCD, +0xE0, +0x0C, +0xCF, +0x00, +0x0D, +0xD1, +0x20, +0x0D, +0xD3, +0x40, +0x0D, +0xD5, +0x60, +0x0D, +0xD7, +0x80, +0x0D, +0xD9, +0xA0, +0x0D, +0xDB, +0xC0, +0x0D, +0xDD, +0xE0, +0x0D, +0xDF, +0x00, +0x0E, +0xE1, +0x20, +0x0E, +0xE3, +0x40, +0x0E, +0xE5, +0x60, +0x0E, +0xE7, +0x80, +0x0E, +0xE9, +0xA0, +0x0E, +0xEB, +0xC0, +0x0E, +0xED, +0xE0, +0x0E, +0xEF, +0x00, +0x0F, +0xF1, +0x20, +0x0F, +0xF3, +0x40, +0x0F, +0xF5, +0x60, +0x0F, +0xF7, +0x80, +0x0F, +0xF9, +0xA0, +0x0F, +0xFB, +0xC0, +0x0F, +0xFD, +0xE0, +0x0F, +0xFF, +0xFF, +0x0F, +0x00, +0x00, +0x00, +0x01, +0x20, +0x00, +0x03, +0x40, +0x00, +0x05, +0x60, +0x00, +0x07, +0x80, +0x00, +0x09, +0xA0, +0x00, +0x0B, +0xC0, +0x00, +0x0D, +0xE0, +0x00, +0x0F, +0x00, +0x01, +0x11, +0x20, +0x01, +0x13, +0x40, +0x01, +0x15, +0x60, +0x01, +0x17, +0x80, +0x01, +0x19, +0xA0, +0x01, +0x1B, +0xC0, +0x01, +0x1D, +0xE0, +0x01, +0x1F, +0x00, +0x02, +0x21, +0x20, +0x02, +0x23, +0x40, +0x02, +0x25, +0x60, +0x02, +0x27, +0x80, +0x02, +0x29, +0xA0, +0x02, +0x2B, +0xC0, +0x02, +0x2D, +0xE0, +0x02, +0x2F, +0x00, +0x03, +0x31, +0x20, +0x03, +0x33, +0x40, +0x03, +0x35, +0x60, +0x03, +0x37, +0x80, +0x03, +0x39, +0xA0, +0x03, +0x3B, +0xC0, +0x03, +0x3D, +0xE0, +0x03, +0x3F, +0x00, +0x04, +0x41, +0x20, +0x04, +0x43, +0x40, +0x04, +0x45, +0x60, +0x04, +0x47, +0x80, +0x04, +0x49, +0xA0, +0x04, +0x4B, +0xC0, +0x04, +0x4D, +0xE0, +0x04, +0x4F, +0x00, +0x05, +0x51, +0x20, +0x05, +0x53, +0x40, +0x05, +0x55, +0x60, +0x05, +0x57, +0x80, +0x05, +0x59, +0xA0, +0x05, +0x5B, +0xC0, +0x05, +0x5D, +0xE0, +0x05, +0x5F, +0x00, +0x06, +0x61, +0x20, +0x06, +0x63, +0x40, +0x06, +0x65, +0x60, +0x06, +0x67, +0x80, +0x06, +0x69, +0xA0, +0x06, +0x6B, +0xC0, +0x06, +0x6D, +0xE0, +0x06, +0x6F, +0x00, +0x07, +0x71, +0x20, +0x07, +0x73, +0x40, +0x07, +0x75, +0x60, +0x07, +0x77, +0x80, +0x07, +0x79, +0xA0, +0x07, +0x7B, +0xC0, +0x07, +0x7D, +0xE0, +0x07, +0x7F, +0x00, +0x08, +0x81, +0x20, +0x08, +0x83, +0x40, +0x08, +0x85, +0x60, +0x08, +0x87, +0x80, +0x08, +0x89, +0xA0, +0x08, +0x8B, +0xC0, +0x08, +0x8D, +0xE0, +0x08, +0x8F, +0x00, +0x09, +0x91, +0x20, +0x09, +0x93, +0x40, +0x09, +0x95, +0x60, +0x09, +0x97, +0x80, +0x09, +0x99, +0xA0, +0x09, +0x9B, +0xC0, +0x09, +0x9D, +0xE0, +0x09, +0x9F, +0x00, +0x0A, +0xA1, +0x20, +0x0A, +0xA3, +0x40, +0x0A, +0xA5, +0x60, +0x0A, +0xA7, +0x80, +0x0A, +0xA9, +0xA0, +0x0A, +0xAB, +0xC0, +0x0A, +0xAD, +0xE0, +0x0A, +0xAF, +0x00, +0x0B, +0xB1, +0x20, +0x0B, +0xB3, +0x40, +0x0B, +0xB5, +0x60, +0x0B, +0xB7, +0x80, +0x0B, +0xB9, +0xA0, +0x0B, +0xBB, +0xC0, +0x0B, +0xBD, +0xE0, +0x0B, +0xBF, +0x00, +0x0C, +0xC1, +0x20, +0x0C, +0xC3, +0x40, +0x0C, +0xC5, +0x60, +0x0C, +0xC7, +0x80, +0x0C, +0xC9, +0xA0, +0x0C, +0xCB, +0xC0, +0x0C, +0xCD, +0xE0, +0x0C, +0xCF, +0x00, +0x0D, +0xD1, +0x20, +0x0D, +0xD3, +0x40, +0x0D, +0xD5, +0x60, +0x0D, +0xD7, +0x80, +0x0D, +0xD9, +0xA0, +0x0D, +0xDB, +0xC0, +0x0D, +0xDD, +0xE0, +0x0D, +0xDF, +0x00, +0x0E, +0xE1, +0x20, +0x0E, +0xE3, +0x40, +0x0E, +0xE5, +0x60, +0x0E, +0xE7, +0x80, +0x0E, +0xE9, +0xA0, +0x0E, +0xEB, +0xC0, +0x0E, +0xED, +0xE0, +0x0E, +0xEF, +0x00, +0x0F, +0xF1, +0x20, +0x0F, +0xF3, +0x40, +0x0F, +0xF5, +0x60, +0x0F, +0xF7, +0x80, +0x0F, +0xF9, +0xA0, +0x0F, +0xFB, +0xC0, +0x0F, +0xFD, +0xE0, +0x0F, +0xFF, +0xFF, +0x0F, +0x00, +0xD2, +0x00, +0x00, +0x00, +0x7F, +0x80, +0xE0, +0x00, +0x80, +0x7E, +0x00, +0xE0, +0x00, +0xE0, +0x80, +0x7E, +0xE0, +0x00, +0x7E, +0x80, +0x68, +0x80, +0x80, +0x10, +0x80, +0x69, +0x10, +0x80, +0x10, +0x80, +0x80, +0x68, +0x80, +0x10, +0x69, +0x80, +0x60, +0x84, +0x78, +0x80, +0x90, +0x61, +0x80, +0x78, +0x80, +0x78, +0x80, +0x60, +0x78, +0x80, +0x60, +0x84, +0x01, +0x96, +0x7C, +0x80, +0x96, +0x00, +0x80, +0x78, +0x80, +0x78, +0x96, +0x00, +0x6C, +0x80, +0x00, +0x96, +0x80, +0x70, +0x16, +0x88, +0x70, +0x80, +0x88, +0x56, +0x88, +0x56, +0x70, +0x80, +0x06, +0x88, +0x81, +0x70, +0x80, +0x60, +0x50, +0xE8, +0x70, +0x80, +0xE8, +0x10, +0xE8, +0x10, +0x60, +0x80, +0x50, +0xE8, +0x80, +0x60, +0x80, +0x48, +0x80, +0x70, +0x4C, +0x80, +0x70, +0x80, +0x70, +0x80, +0x4C, +0x81, +0x80, +0x70, +0x80, +0x48, +0x90, +0x68, +0x80, +0x66, +0x68, +0x94, +0x66, +0x80, +0x66, +0x80, +0x68, +0x95, +0x80, +0x66, +0x90, +0x68, +0x78, +0x80, +0x80, +0x00, +0x80, +0x78, +0x00, +0x80, +0x00, +0x80, +0x80, +0x78, +0x80, +0x00, +0x78, +0x80, +0x68, +0x80, +0x80, +0x76, +0x80, +0x68, +0x76, +0x81, +0x76, +0x80, +0x80, +0x68, +0x80, +0x76, +0x68, +0x80, +0x10, +0x80, +0x7E, +0x80, +0x84, +0x00, +0x80, +0x7E, +0x80, +0x7F, +0x94, +0x00, +0x7E, +0x80, +0x00, +0x90, +0x00, +0xF0, +0x68, +0x80, +0xF0, +0x04, +0x80, +0x68, +0x80, +0x69, +0xF0, +0x04, +0x68, +0x90, +0x00, +0xF0, +0xC0, +0x70, +0x61, +0x88, +0x70, +0x80, +0x88, +0x60, +0x88, +0x60, +0x70, +0x80, +0x61, +0x98, +0xC0, +0x70, +0x90, +0x66, +0x10, +0x88, +0x66, +0x80, +0x88, +0x50, +0x88, +0x50, +0x76, +0x80, +0x11, +0x88, +0x80, +0x76, +0xE6, +0x08, +0x80, +0x74, +0x08, +0xE6, +0x70, +0x81, +0x70, +0x80, +0x08, +0xE6, +0x80, +0x74, +0xE6, +0x08, +0x94, +0x48, +0x81, +0x60, +0x48, +0x90, +0x60, +0x80, +0x60, +0x80, +0x48, +0x90, +0x80, +0x60, +0x94, +0x48, +0x7F, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x7F, +0x80, +0xE0, +0x00, +0x80, +0x7E, +0x00, +0xE0, +0x00, +0xE0, +0x80, +0x7E, +0xE0, +0x00, +0x7E, +0x80, +0x68, +0x80, +0x80, +0x10, +0x80, +0x69, +0x10, +0x80, +0x10, +0x80, +0x80, +0x68, +0x80, +0x10, +0x69, +0x80, +0x60, +0x84, +0x78, +0x80, +0x90, +0x61, +0x80, +0x78, +0x80, +0x78, +0x80, +0x60, +0x78, +0x80, +0x60, +0x84, +0x01, +0x96, +0x7C, +0x80, +0x96, +0x00, +0x80, +0x78, +0x80, +0x78, +0x96, +0x00, +0x6C, +0x80, +0x00, +0x96, +0x80, +0x70, +0x16, +0x88, +0x70, +0x80, +0x88, +0x56, +0x88, +0x56, +0x70, +0x80, +0x06, +0x88, +0x81, +0x70, +0x80, +0x60, +0x50, +0xE8, +0x70, +0x80, +0xE8, +0x10, +0xE8, +0x10, +0x60, +0x80, +0x50, +0xE8, +0x80, +0x60, +0x80, +0x48, +0x80, +0x70, +0x4C, +0x80, +0x70, +0x80, +0x70, +0x80, +0x4C, +0x81, +0x80, +0x70, +0x80, +0x48, +0x90, +0x68, +0x80, +0x66, +0x68, +0x94, +0x66, +0x80, +0x66, +0x80, +0x68, +0x95, +0x80, +0x66, +0x90, +0x68, +0x78, +0x80, +0x80, +0x00, +0x80, +0x78, +0x00, +0x80, +0x00, +0x80, +0x80, +0x78, +0x80, +0x00, +0x78, +0x80, +0x68, +0x80, +0x80, +0x76, +0x80, +0x68, +0x76, +0x81, +0x76, +0x80, +0x80, +0x68, +0x80, +0x76, +0x68, +0x80, +0x10, +0x80, +0x7E, +0x80, +0x84, +0x00, +0x80, +0x7E, +0x80, +0x7F, +0x94, +0x00, +0x7E, +0x80, +0x00, +0x90, +0x00, +0xF0, +0x68, +0x80, +0xF0, +0x04, +0x80, +0x68, +0x80, +0x69, +0xF0, +0x04, +0x68, +0x90, +0x00, +0xF0, +0xC0, +0x70, +0x61, +0x88, +0x70, +0x80, +0x88, +0x60, +0x88, +0x60, +0x70, +0x80, +0x61, +0x98, +0xC0, +0x70, +0x90, +0x66, +0x10, +0x88, +0x66, +0x80, +0x88, +0x50, +0x88, +0x50, +0x76, +0x80, +0x11, +0x88, +0x80, +0x76, +0xE6, +0x08, +0x80, +0x74, +0x08, +0xE6, +0x70, +0x81, +0x70, +0x80, +0x08, +0xE6, +0x80, +0x74, +0xE6, +0x08, +0x94, +0x48, +0x81, +0x60, +0x48, +0x90, +0x60, +0x80, +0x60, +0x80, +0x48, +0x90, +0x80, +0x60, +0x94, +0x48, +0x7F, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x5B, +0x7C, +0x1A, +0x64, +0x1B, +0x3D, +0xE8, +0x71, +0x4E, +0xB4, +0x95, +0x2B, +0x8F, +0xA3, +0x64, +0x2A, +0x90, +0xE8, +0xB3, +0xEA, +0x5C, +0xFC, +0xD3, +0x60, +0xE1, +0x6F, +0x2C, +0xD7, +0x62, +0x7B, +0xD9, +0x72, +0x17, +0x47, +0x5E, +0x1D, +0x65, +0x40, +0xB8, +0x10, +0xA9, +0x95, +0x63, +0xC0, +0x3F, +0xF0, +0xB8, +0x93, +0xCA, +0x2D, +0xE4, +0x8E, +0xB8, +0x2D, +0x2B, +0x4E, +0xBF, +0x15, +0x9C, +0x2A, +0x19, +0x73, +0x6C, +0x30, +0x5D, +0x1A, +0x4D, +0xF1, +0x68, +0xE6, +0x3F, +0x50, +0xF8, +0x46, +0xDE, +0x27, +0xEA, +0x7F, +0xA2, +0x16, +0xC7, +0xC9, +0xB8, +0x93, +0x30, +0xFD, +0xA5, +0xC9, +0x85, +0xF0, +0x5D, +0x4C, +0x90, +0xA7, +0x20, +0x48, +0x38, +0xB1, +0xE7, +0xED, +0xF6, +0x92, +0x02, +0xDF, +0xB5, +0x70, +0x4E, +0xD6, +0x40, +0x2D, +0x5C, +0x91, +0x7C, +0x6F, +0x8F, +0x50, +0x39, +0x1A, +0x69, +0x4F, +0xB8, +0x49, +0x0A, +0x65, +0x4F, +0x20, +0x46, +0xA7, +0xEC, +0xD5, +0x81, +0xE7, +0x2D, +0xAC, +0x83, +0xCA, +0xE3, +0x7F, +0xEC, +0x1B, +0xA2, +0x79, +0x3C, +0x5D, +0x73, +0x85, +0x1B, +0x57, +0x16, +0xD4, +0x04, +0xD5, +0x86, +0xAF, +0x60, +0xC4, +0xE4, +0xBF, +0x90, +0xFB, +0x92, +0xB9, +0xC8, +0x8E, +0x30, +0x2B, +0xA2, +0xD7, +0x6D, +0x02, +0x51, +0xB9, +0x70, +0x46, +0x39, +0xB4, +0x8E, +0x51, +0x7D, +0x1B, +0xCA, +0x59, +0x83, +0x12, +0x3E, +0xAC, +0xF6, +0x38, +0x1A, +0x3E, +0xCA, +0xF2, +0xD6, +0x0A, +0x92, +0x35, +0x61, +0x08, +0x9D, +0x57, +0x3B, +0x4C, +0xD3, +0x0A, +0x1F, +0xE5, +0xC3, +0xAE, +0x29, +0xB4, +0xA6, +0x2C, +0xD7, +0xB8, +0x37, +0x29, +0x97, +0xC7, +0xF1, +0xE3, +0x08, +0xC9, +0xC1, +0x4D, +0x05, +0x02, +0xFB, +0x84, +0xC4, +0x31, +0x6E, +0x29, +0x4B, +0x58, +0x28, +0xE8, +0x6A, +0x5E, +0x16, +0xB1, +0x0B, +0xE9, +0xD6, +0xD3, +0xFA, +0x01, +0xDF, +0x72, +0xE4, +0x03, +0xFD, +0x79, +0x8A, +0x62, +0x3C, +0x65, +0x3C, +0x7F, +0x86, +0x59, +0x1B, +0xC7, +0x4A, +0x3F, +0x24, +0xBC, +0xFA, +0x04, +0x8D, +0xE2, +0xE1, +0x0F, +0x5A, +0xFA, +0x05, +0xC6, +0x17, +0xE4, +0x4D, +0xFB, +0xB9, +0x57, +0x7B, +0xA6, +0xD2, +0x95, +0x18, +0x8E, +0x94, +0xA8, +0x2E, +0x2C, +0xDA, +0xBF, +0x08, +0xE1, +0xA4, +0xE7, +0x9F, +0xC6, +0xCA, +0x64, +0x78, +0x07, +0xE3, +0x6C, +0x53, +0xB8, +0x18, +0xD5, +0x01, +0xF3, +0x83, +0x2B, +0x0D, +0xB2, +0xD7, +0x47, +0x8E, +0xF2, +0x9D, +0xAF, +0x59, +0x2A, +0x1F, +0xEA, +0x59, +0x91, +0xC6, +0xF3, +0xB4, +0x5A, +0xC0, +0xB6, +0xC4, +0x3E, +0xE7, +0x50, +0xA4, +0x4F, +0x82, +0xAB, +0x67, +0x01, +0x5E, +0xDA, +0x97, +0xB2, +0x61, +0x3D, +0x58, +0xE0, +0xC4, +0x26, +0xA2, +0xB6, +0xD8, +0x93, +0x81, +0x0C, +0xDC, +0x79, +0x07, +0x8D, +0x57, +0x39, +0x1C, +0xF3, +0xE4, +0x42, +0xDE, +0x69, +0xF5, +0x3F, +0xB1, +0x96, +0x04, +0xD1, +0x53, +0x2C, +0x7F, +0x0B, +0xB6, +0x51, +0x0D, +0x5C, +0xE5, +0xE4, +0x37, +0x83, +0xC1, +0x6E, +0x5A, +0x2A, +0x58, +0x62, +0xD6, +0xB1, +0x4F, +0x8A, +0xAF, +0x12, +0xDB, +0x94, +0xC0, +0x83, +0xAE, +0x9D, +0x40, +0xF5, +0xA7, +0x5E, +0x21, +0xB6, +0x37, +0x09, +0xE4, +0x51, +0xD7, +0xB5, +0xB6, +0x37, +0xC2, +0xD7, +0x94, +0x0D, +0x9F, +0xB3, +0x17, +0x2C, +0x60, +0xF8, +0x92, +0x8D, +0x1E, +0x1A, +0x6E, +0x58, +0x50, +0xFC, +0x29, +0x84, +0x4E, +0x16, +0x0F, +0xF5, +0xCA, +0x9C, +0x0A, +0xF3, +0x3E, +0x1D, +0xA3, +0x5E, +0xBA, +0xF7, +0xA6, +0x26, +0xD4, +0x17, +0xB2, +0xCB, +0xB6, +0x89, +0x40, +0xC8, +0x24, +0x93, +0x73, +0xC0, +0x79, +0xB2, +0x8D, +0x6E, +0xF9, +0xC3, +0x08, +0xF4, +0x71, +0xDB, +0x8A, +0x36, +0xA3, +0x19, +0x90, +0xC7, +0x2D, +0x48, +0xD5, +0x91, +0x04, +0xBF, +0x50, +0x2D, +0xB9, +0xF3, +0x57, +0xEA, +0x56, +0x1D, +0x8F, +0x2F, +0xC9, +0x40, +0xDE, +0x6C, +0x16, +0xB0, +0x8D, +0x34, +0xB1, +0xC7, +0x53, +0xC7, +0x24, +0x6D, +0x98, +0xB1, +0x2C, +0x4F, +0x2A, +0x98, +0x4A, +0x6E, +0xAC, +0xE3, +0xBF, +0x07, +0x5A, +0xA3, +0xE7, +0xC6, +0xE5, +0xB0, +0x2C, +0x83, +0xE4, +0x61, +0x90, +0xDA, +0xD7, +0x7C, +0x41, +0x39, +0x91, +0x8D, +0xD0, +0x75, +0x6C, +0xB8, +0x15, +0x92, +0x4B, +0xE0, +0x63, +0xE5, +0x4E, +0x50, +0x4A, +0x62, +0x7E, +0x30, +0xFB, +0x5F, +0xE2, +0x8B, +0x1F, +0x7F, +0xF3, +0x29, +0x86, +0xAF, +0xB1, +0x7C, +0xAD, +0x28, +0xB3, +0x1E, +0x60, +0xD6, +0x8C, +0x4E, +0xA3, +0xE5, +0x1A, +0xE6, +0xDC, +0x37, +0x4C, +0xEA, +0x25, +0x5C, +0x24, +0x90, +0xFE, +0xB6, +0x62, +0xA9, +0x16, +0xD8, +0x72, +0x93, +0xFB, +0x97, +0x79, +0x1E, +0x80, +0x25, +0xCE, +0x4B, +0xF0, +0x94, +0x16, +0x5D, +0xA0, +0xA2, +0xF0, +0xD6, +0xF5, +0xD1, +0x17, +0x8D, +0x78, +0xC3, +0x3E, +0x4B, +0x85, +0x13, +0x8B, +0x3F, +0xD7, +0x3A, +0xB8, +0x2F, +0x3C, +0x5B, +0xB4, +0x20, +0xE9, +0xD7, +0x6F, +0x27, +0x0F, +0xCE, +0x42, +0x96, +0x9D, +0x60, +0x18, +0x6F, +0xAC, +0x2B, +0xA7, +0xFA, +0x18, +0x4B, +0xF9, +0xEC, +0x48, +0x17, +0x59, +0xA5, +0xD8, +0xA0, +0x19, +0xB3, +0xC4, +0x20, +0x5D, +0x50, +0x73, +0xC4, +0x81, +0xB4, +0xCE, +0x78, +0x61, +0xB5, +0x0B, +0x82, +0x97, +0x0D, +0x97, +0xF2, +0xE6, +0x07, +0xD8, +0xB2, +0xFD, +0x0A, +0x47, +0x3B, +0xE0, +0x51, +0x3F, +0x8B, +0x2A, +0xC1, +0x74, +0x3E, +0xB5, +0xF3, +0x19, +0xAF, +0x7A, +0xC3, +0x8A, +0x29, +0xCF, +0xE7, +0x5D, +0x5B, +0x4E, +0x2C, +0x6D, +0x4C, +0x93, +0x19, +0x50, +0x6E, +0x80, +0x96, +0x1F, +0xB8, +0x30, +0x95, +0x94, +0x97, +0x10, +0xA7, +0xF2, +0xD4, +0x2E, +0xDA, +0x86, +0x6F, +0xD2, +0xC4, +0xA5, +0x61, +0xDB, +0x3C, +0x64, +0xAF, +0xA5, +0x98, +0x31, +0xC4, +0x05, +0x71, +0xE7, +0xB8, +0x23, +0x04, +0xC1, +0xEB, +0xDF, +0x23, +0x06, +0x3D, +0xCE, +0x48, +0x62, +0xAD, +0xC6, +0xF9, +0x5E, +0x5A, +0x5B, +0x7C, +0x1A, +0x64, +0x1B, +0x3D, +0xE8, +0x71, +0x4E, +0xB4, +0x95, +0x2B, +0x8F, +0xA3, +0x64, +0x2A, +0x90, +0xE8, +0xB3, +0xEA, +0x5C, +0xFC, +0xD3, +0x60, +0xE1, +0x6F, +0x2C, +0xD7, +0x62, +0x7B, +0xD9, +0x72, +0x17, +0x47, +0x5E, +0x1D, +0x65, +0x40, +0xB8, +0x10, +0xA9, +0x95, +0x63, +0xC0, +0x3F, +0xF0, +0xB8, +0x93, +0xCA, +0x2D, +0xE4, +0x8E, +0xB8, +0x2D, +0x2B, +0x4E, +0xBF, +0x15, +0x9C, +0x2A, +0x19, +0x73, +0x6C, +0x30, +0x5D, +0x1A, +0x4D, +0xF1, +0x68, +0xE6, +0x3F, +0x50, +0xF8, +0x46, +0xDE, +0x27, +0xEA, +0x7F, +0xA2, +0x16, +0xC7, +0xC9, +0xB8, +0x93, +0x30, +0xFD, +0xA5, +0xC9, +0x85, +0xF0, +0x5D, +0x4C, +0x90, +0xA7, +0x20, +0x48, +0x38, +0xB1, +0xE7, +0xED, +0xF6, +0x92, +0x02, +0xDF, +0xB5, +0x70, +0x4E, +0xD6, +0x40, +0x2D, +0x5C, +0x91, +0x7C, +0x6F, +0x8F, +0x50, +0x39, +0x1A, +0x69, +0x4F, +0xB8, +0x49, +0x0A, +0x65, +0x4F, +0x20, +0x46, +0xA7, +0xEC, +0xD5, +0x81, +0xE7, +0x2D, +0xAC, +0x83, +0xCA, +0xE3, +0x7F, +0xEC, +0x1B, +0xA2, +0x79, +0x3C, +0x5D, +0x73, +0x85, +0x1B, +0x57, +0x16, +0xD4, +0x04, +0xD5, +0x86, +0xAF, +0x60, +0xC4, +0xE4, +0xBF, +0x90, +0xFB, +0x92, +0xB9, +0xC8, +0x8E, +0x30, +0x2B, +0xA2, +0xD7, +0x6D, +0x02, +0x51, +0xB9, +0x70, +0x46, +0x39, +0xB4, +0x8E, +0x51, +0x7D, +0x1B, +0xCA, +0x59, +0x83, +0x12, +0x3E, +0xAC, +0xF6, +0x38, +0x1A, +0x3E, +0xCA, +0xF2, +0xD6, +0x0A, +0x92, +0x35, +0x61, +0x08, +0x9D, +0x57, +0x3B, +0x4C, +0xD3, +0x0A, +0x1F, +0xE5, +0xC3, +0xAE, +0x29, +0xB4, +0xA6, +0x2C, +0xD7, +0xB8, +0x37, +0x29, +0x97, +0xC7, +0xF1, +0xE3, +0x08, +0xC9, +0xC1, +0x4D, +0x05, +0x02, +0xFB, +0x84, +0xC4, +0x31, +0x6E, +0x29, +0x4B, +0x58, +0x28, +0xE8, +0x6A, +0x5E, +0x16, +0xB1, +0x0B, +0xE9, +0xD6, +0xD3, +0xFA, +0x01, +0xDF, +0x72, +0xE4, +0x03, +0xFD, +0x79, +0x8A, +0x62, +0x3C, +0x65, +0x3C, +0x7F, +0x86, +0x59, +0x1B, +0xC7, +0x4A, +0x3F, +0x24, +0xBC, +0xFA, +0x04, +0x8D, +0xE2, +0xE1, +0x0F, +0x5A, +0xFA, +0x05, +0xC6, +0x17, +0xE4, +0x4D, +0xFB, +0xB9, +0x57, +0x7B, +0xA6, +0xD2, +0x95, +0x18, +0x8E, +0x94, +0xA8, +0x2E, +0x2C, +0xDA, +0xBF, +0x08, +0xE1, +0xA4, +0xE7, +0x9F, +0xC6, +0xCA, +0x64, +0x78, +0x07, +0xE3, +0x6C, +0x53, +0xB8, +0x18, +0xD5, +0x01, +0xF3, +0x83, +0x2B, +0x0D, +0xB2, +0xD7, +0x47, +0x8E, +0xF2, +0x9D, +0xAF, +0x59, +0x2A, +0x1F, +0xEA, +0x59, +0x91, +0xC6, +0xF3, +0xB4, +0x5A, +0xC0, +0xB6, +0xC4, +0x3E, +0xE7, +0x50, +0xA4, +0x4F, +0x82, +0xAB, +0x67, +0x01, +0x5E, +0xDA, +0x97, +0xB2, +0x61, +0x3D, +0x58, +0xE0, +0xC4, +0x26, +0xA2, +0xB6, +0xD8, +0x93, +0x81, +0x0C, +0xDC, +0x79, +0x07, +0x8D, +0x57, +0x39, +0x1C, +0xF3, +0xE4, +0x42, +0xDE, +0x69, +0xF5, +0x3F, +0xB1, +0x96, +0x04, +0xD1, +0x53, +0x2C, +0x7F, +0x0B, +0xB6, +0x51, +0x0D, +0x5C, +0xE5, +0xE4, +0x37, +0x83, +0xC1, +0x6E, +0x5A, +0x2A, +0x58, +0x62, +0xD6, +0xB1, +0x4F, +0x8A, +0xAF, +0x12, +0xDB, +0x94, +0xC0, +0x83, +0xAE, +0x9D, +0x40, +0xF5, +0xA7, +0x5E, +0x21, +0xB6, +0x37, +0x09, +0xE4, +0x51, +0xD7, +0xB5, +0xB6, +0x37, +0xC2, +0xD7, +0x94, +0x0D, +0x9F, +0xB3, +0x17, +0x2C, +0x60, +0xF8, +0x92, +0x8D, +0x1E, +0x1A, +0x6E, +0x58, +0x50, +0xFC, +0x29, +0x84, +0x4E, +0x16, +0x0F, +0xF5, +0xCA, +0x9C, +0x0A, +0xF3, +0x3E, +0x1D, +0xA3, +0x5E, +0xBA, +0xF7, +0xA6, +0x26, +0xD4, +0x17, +0xB2, +0xCB, +0xB6, +0x89, +0x40, +0xC8, +0x24, +0x93, +0x73, +0xC0, +0x79, +0xB2, +0x8D, +0x6E, +0xF9, +0xC3, +0x08, +0xF4, +0x71, +0xDB, +0x8A, +0x36, +0xA3, +0x19, +0x90, +0xC7, +0x2D, +0x48, +0xD5, +0x91, +0x04, +0xBF, +0x50, +0x2D, +0xB9, +0xF3, +0x57, +0xEA, +0x56, +0x1D, +0x8F, +0x2F, +0xC9, +0x40, +0xDE, +0x6C, +0x16, +0xB0, +0x8D, +0x34, +0xB1, +0xC7, +0x53, +0xC7, +0x24, +0x6D, +0x98, +0xB1, +0x2C, +0x4F, +0x2A, +0x98, +0x4A, +0x6E, +0xAC, +0xE3, +0xBF, +0x07, +0x5A, +0xA3, +0xE7, +0xC6, +0xE5, +0xB0, +0x2C, +0x83, +0xE4, +0x61, +0x90, +0xDA, +0xD7, +0x7C, +0x41, +0x39, +0x91, +0x8D, +0xD0, +0x75, +0x6C, +0xB8, +0x15, +0x92, +0x4B, +0xE0, +0x63, +0xE5, +0x4E, +0x50, +0x4A, +0x62, +0x7E, +0x30, +0xFB, +0x5F, +0xE2, +0x8B, +0x1F, +0x7F, +0xF3, +0x29, +0x86, +0xAF, +0xB1, +0x7C, +0xAD, +0x28, +0xB3, +0x1E, +0x60, +0xD6, +0x8C, +0x4E, +0xA3, +0xE5, +0x1A, +0xE6, +0xDC, +0x37, +0x4C, +0xEA, +0x25, +0x5C, +0x24, +0x90, +0xFE, +0xB6, +0x62, +0xA9, +0x16, +0xD8, +0x72, +0x93, +0xFB, +0x97, +0x79, +0x1E, +0x80, +0x25, +0xCE, +0x4B, +0xF0, +0x94, +0x16, +0x5D, +0xA0, +0xA2, +0xF0, +0xD6, +0xF5, +0xD1, +0x17, +0x8D, +0x78, +0xC3, +0x3E, +0x4B, +0x85, +0x13, +0x8B, +0x3F, +0xD7, +0x3A, +0xB8, +0x2F, +0x3C, +0x5B, +0xB4, +0x20, +0xE9, +0xD7, +0x6F, +0x27, +0x0F, +0xCE, +0x42, +0x96, +0x9D, +0x60, +0x18, +0x6F, +0xAC, +0x2B, +0xA7, +0xFA, +0x18, +0x4B, +0xF9, +0xEC, +0x48, +0x17, +0x59, +0xA5, +0xD8, +0xA0, +0x19, +0xB3, +0xC4, +0x20, +0x5D, +0x50, +0x73, +0xC4, +0x81, +0xB4, +0xCE, +0x78, +0x61, +0xB5, +0x0B, +0x82, +0x97, +0x0D, +0x97, +0xF2, +0xE6, +0x07, +0xD8, +0xB2, +0xFD, +0x0A, +0x47, +0x3B, +0xE0, +0x51, +0x3F, +0x8B, +0x2A, +0xC1, +0x74, +0x3E, +0xB5, +0xF3, +0x19, +0xAF, +0x7A, +0xC3, +0x8A, +0x29, +0xCF, +0xE7, +0x5D, +0x5B, +0x4E, +0x2C, +0x6D, +0x4C, +0x93, +0x19, +0x50, +0x6E, +0x80, +0x96, +0x1F, +0xB8, +0x30, +0x95, +0x94, +0x97, +0x10, +0xA7, +0xF2, +0xD4, +0x2E, +0xDA, +0x86, +0x6F, +0xD2, +0xC4, +0xA5, +0x61, +0xDB, +0x3C, +0x64, +0xAF, +0xA5, +0x98, +0x31, +0xC4, +0x05, +0x71, +0xE7, +0xB8, +0x23, +0x04, +0xC1, +0xEB, +0xDF, +0x23, +0x06, +0x3D, +0xCE, +0x48, +0x62, +0xAD, +0xC6, +0xF9, +0x5E, +0x5A, +0xB4, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x02, +0x28, +0x02, +0x2D, +0x02, +0x2E, +0x02, +0x2F, +0x02, +0x32, +0x02, +0x33, +0x02, +0x26, +0x02, +0x31, +0x02, +0x30, +0x02, +0x2B, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0xA5, +0x00, +0x5F, +0x00, +0x19, +0x00, +0xF3, +0x00, +0x00, +0x00, +0x03, +0x00, +0x06, +0x00, +0x11, +0x00, +0xF8, +0x00, +0x38, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0xA5, +0x00, +0x5F, +0x00, +0x19, +0x00, +0xF3, +0x00, +0x00, +0x00, +0x03, +0x00, +0x06, +0x00, +0x11, +0x00, +0xF8, +0x00, +0x38, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0xA5, +0x00, +0x5F, +0x00, +0x19, +0x00, +0xF3, +0x00, +0x00, +0x00, +0x03, +0x00, +0x06, +0x00, +0x11, +0x00, +0xF8, +0x00, +0x38, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0xA5, +0x00, +0x5F, +0x00, +0x19, +0x00, +0xF3, +0x00, +0x00, +0x00, +0x03, +0x00, +0x06, +0x00, +0x11, +0x00, +0xF8, +0x00, +0x38, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0xA5, +0x00, +0x5F, +0x00, +0x19, +0x00, +0xF3, +0x00, +0x00, +0x00, +0x03, +0x00, +0x06, +0x00, +0x11, +0x00, +0xF8, +0x00, +0x38, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0xA5, +0x00, +0x5F, +0x00, +0x19, +0x00, +0xF3, +0x00, +0x00, +0x00, +0x03, +0x00, +0x06, +0x00, +0x11, +0x00, +0xF8, +0x00, +0x38, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0xA5, +0x00, +0x5F, +0x00, +0x19, +0x00, +0xF3, +0x00, +0x00, +0x00, +0x03, +0x00, +0x06, +0x00, +0x11, +0x00, +0xF8, +0x00, +0x38, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0xA5, +0x00, +0x5F, +0x00, +0x19, +0x00, +0xF3, +0x00, +0x00, +0x00, +0x03, +0x00, +0x06, +0x00, +0x11, +0x00, +0xF8, +0x00, +0x38, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0xA5, +0x00, +0x5F, +0x00, +0x19, +0x00, +0xF3, +0x00, +0x00, +0x00, +0x03, +0x00, +0x06, +0x00, +0x11, +0x00, +0xF8, +0x00, +0x38, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0xA5, +0x00, +0x5F, +0x00, +0x19, +0x00, +0xF3, +0x00, +0x00, +0x00, +0x03, +0x00, +0x06, +0x00, +0x11, +0x00, +0xF8, +0x00, +0x38, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0xA5, +0x00, +0x5F, +0x00, +0x19, +0x00, +0xF3, +0x00, +0x00, +0x00, +0x03, +0x00, +0x06, +0x00, +0x11, +0x00, +0xF8, +0x00, +0x38, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0xA5, +0x00, +0x5F, +0x00, +0x19, +0x00, +0xF3, +0x00, +0x00, +0x00, +0x03, +0x00, +0x06, +0x00, +0x11, +0x00, +0xF8, +0x00, +0x38, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x20, +0x40, +0x60, +0x00, +0x80, +0xA0, +0xC0, +0xE0, +0x00, +0x00, +0x20, +0x40, +0x60, +0x55, +0x80, +0xA0, +0xC0, +0xE0, +0x55, +0x00, +0x20, +0x40, +0x60, +0xAA, +0x80, +0xA0, +0xC0, +0xE0, +0xAA, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x36, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +}; diff --git a/drivers/amlogic/media/vout/vdac/vdac_dev.c b/drivers/amlogic/media/vout/vdac/vdac_dev.c index b5b3533c20ad..9c266930e374 100644 --- a/drivers/amlogic/media/vout/vdac/vdac_dev.c +++ b/drivers/amlogic/media/vout/vdac/vdac_dev.c @@ -589,6 +589,11 @@ struct meson_vdac_data meson_tl1_vdac_data = { .name = "meson-tl1-vdac", }; +struct meson_vdac_data meson_sm1_vdac_data = { + .cpu_id = VDAC_CPU_SM1, + .name = "meson-sm1-vdac", +}; + static const struct of_device_id meson_vdac_dt_match[] = { { .compatible = "amlogic, vdac-gxtvbb", @@ -620,6 +625,9 @@ static const struct of_device_id meson_vdac_dt_match[] = { }, { .compatible = "amlogic, vdac-tl1", .data = &meson_tl1_vdac_data, + }, { + .compatible = "amlogic, vdac-sm1", + .data = &meson_sm1_vdac_data, }, {}, }; @@ -701,14 +709,20 @@ static int __exit aml_vdac_remove(struct platform_device *pdev) static int amvdac_drv_suspend(struct platform_device *pdev, pm_message_t state) { - if (s_vdac_data->cpu_id == VDAC_CPU_TXL) + if (s_vdac_data->cpu_id == VDAC_CPU_TXL || + s_vdac_data->cpu_id == VDAC_CPU_TXLX) vdac_hiu_reg_write(HHI_VDAC_CNTL0, 0); + else if (s_vdac_data->cpu_id == VDAC_CPU_TL1) + vdac_hiu_reg_setb(HHI_VDAC_CNTL1_G12A, 1, 7, 1); pr_info("%s: suspend module\n", __func__); return 0; } static int amvdac_drv_resume(struct platform_device *pdev) { + /*0xbc[7] for bandgap enable: 0:enable,1:disable*/ + if (s_vdac_data->cpu_id == VDAC_CPU_TL1) + vdac_hiu_reg_setb(HHI_VDAC_CNTL1_G12A, 0, 7, 1); pr_info("%s: resume module\n", __func__); return 0; } @@ -720,8 +734,11 @@ static void amvdac_drv_shutdown(struct platform_device *pdev) pr_info("%s: shutdown module\n", __func__); cntl0 = 0x0; - if (is_meson_txl_cpu() || is_meson_txlx_cpu()) + if (s_vdac_data->cpu_id == VDAC_CPU_TXL || + s_vdac_data->cpu_id == VDAC_CPU_TXLX) cntl1 = 0x0; + else if (s_vdac_data->cpu_id == VDAC_CPU_TL1) + cntl1 = 0x80; else cntl1 = 0x8; vdac_set_ctrl0_ctrl1(cntl0, cntl1); diff --git a/drivers/amlogic/media/vout/vout_serve/vout_func.c b/drivers/amlogic/media/vout/vout_serve/vout_func.c index c8661b355196..0ea80a6fac8a 100644 --- a/drivers/amlogic/media/vout/vout_serve/vout_func.c +++ b/drivers/amlogic/media/vout/vout_serve/vout_func.c @@ -245,6 +245,19 @@ void vout_func_update_viu(int index) if (clk_bit < 0xff) vout_func_vcbus_setb(VPU_VENCX_CLK_CTRL, clk_sel, clk_bit, 1); + /* special setting for dummy mode */ + if (index == 1) { + if (vinfo->mode == VMODE_DUMMY_LCD) { + /* viu1 use encl_vsync */ + vout_func_vcbus_setb(VPU_VIU_VENC_MUX_CTRL, 0, 4, 2); + vout_func_vcbus_setb(VPU_VIU_VENC_MUX_CTRL, 1, 20, 1); + vout_func_vcbus_setb(VPP_WRBAK_CTRL, 1, 11, 1); + } else { + vout_func_vcbus_setb(VPU_VIU_VENC_MUX_CTRL, 0, 20, 1); + vout_func_vcbus_setb(VPP_WRBAK_CTRL, 0, 11, 1); + } + } + #if 0 VOUTPR("%s: %d, mux_sel=%d, clk_sel=%d\n", __func__, index, mux_sel, clk_sel); diff --git a/drivers/amlogic/media/vout/vout_serve/vout_func.h b/drivers/amlogic/media/vout/vout_serve/vout_func.h index a7e6d4c07e9b..3ad9a3395120 100644 --- a/drivers/amlogic/media/vout/vout_serve/vout_func.h +++ b/drivers/amlogic/media/vout/vout_serve/vout_func.h @@ -36,6 +36,7 @@ #define VPU_VENCX_CLK_CTRL 0x2785 #define VPP_POSTBLEND_H_SIZE 0x1d21 #define VPP2_POSTBLEND_H_SIZE 0x1921 +#define VPP_WRBAK_CTRL 0x1df9 struct vout_cdev_s { dev_t devno; diff --git a/drivers/amlogic/media/vout/vout_serve/vout_serve.c b/drivers/amlogic/media/vout/vout_serve/vout_serve.c index 8dd7ce6a489d..39fb58edafcd 100644 --- a/drivers/amlogic/media/vout/vout_serve/vout_serve.c +++ b/drivers/amlogic/media/vout/vout_serve/vout_serve.c @@ -131,6 +131,24 @@ static struct vinfo_s nulldisp_vinfo[] = { .viu_mux = VIU_MUX_MAX, .vout_device = NULL, }, + { + .name = "dummy_panel", + .mode = VMODE_DUMMY_LCD, + .width = 1920, + .height = 1080, + .field_height = 1080, + .aspect_ratio_num = 16, + .aspect_ratio_den = 9, + .sync_duration_num = 60, + .sync_duration_den = 1, + .video_clk = 148500000, + .htotal = 2200, + .vtotal = 1125, + .fr_adj_type = VOUT_FR_ADJ_NONE, + .viu_color_fmt = COLOR_FMT_RGB444, + .viu_mux = VIU_MUX_MAX, + .vout_device = NULL, + }, }; static struct vinfo_s *nulldisp_get_current_info(void) @@ -400,6 +418,43 @@ static ssize_t vout_mode_store(struct class *class, return count; } +static ssize_t vout_dummy_store(struct class *class, + struct class_attribute *attr, const char *buf, size_t count) +{ + unsigned int tmp[4], sync_duration; + enum vmode_e mode; + int ret; + + mutex_lock(&vout_serve_mutex); + mode = VMODE_DUMMY_LCD; + ret = sscanf(buf, "%d %d %d %d", &tmp[0], &tmp[1], &tmp[2], &tmp[3]); + if (ret == 2) { + vout_notifier_call_chain(VOUT_EVENT_MODE_CHANGE_PRE, &mode); + nulldisp_vinfo[2].width = tmp[0]; + nulldisp_vinfo[2].height = tmp[1]; + nulldisp_vinfo[2].field_height = tmp[1]; + VOUTPR("set dummy size: %d x %d\n", tmp[0], tmp[1]); + vout_notifier_call_chain(VOUT_EVENT_MODE_CHANGE, &mode); + } else if (ret == 4) { + vout_notifier_call_chain(VOUT_EVENT_MODE_CHANGE_PRE, &mode); + nulldisp_vinfo[2].width = tmp[0]; + nulldisp_vinfo[2].height = tmp[1]; + nulldisp_vinfo[2].field_height = tmp[1]; + nulldisp_vinfo[2].sync_duration_num = tmp[2]; + nulldisp_vinfo[2].sync_duration_den = tmp[3]; + sync_duration = (tmp[2] * 100) / tmp[3]; + VOUTPR("set dummy size: %d x %d, frame_rate: %d.%02dHz\n", + tmp[0], tmp[1], + (sync_duration / 100), (sync_duration % 100)); + vout_notifier_call_chain(VOUT_EVENT_MODE_CHANGE, &mode); + } else { + VOUTERR("invalid data\n"); + } + mutex_unlock(&vout_serve_mutex); + + return count; +} + static ssize_t vout_axis_show(struct class *class, struct class_attribute *attr, char *buf) { @@ -515,14 +570,16 @@ static ssize_t vout_vinfo_show(struct class *class, " fr_adj_type: %d\n" " video_clk: %d\n" " viu_color_fmt: %d\n" - " viu_mux: %d\n\n", + " viu_mux: %d\n" + " 3d_info: %d\n\n", info->name, info->mode, info->width, info->height, info->field_height, info->aspect_ratio_num, info->aspect_ratio_den, info->sync_duration_num, info->sync_duration_den, info->screen_real_width, info->screen_real_height, info->htotal, info->vtotal, info->fr_adj_type, - info->video_clk, info->viu_color_fmt, info->viu_mux); + info->video_clk, info->viu_color_fmt, info->viu_mux, + info->info_3d); len += sprintf(buf+len, "master_display_info:\n" " present_flag %d\n" " features 0x%x\n" @@ -573,11 +630,13 @@ static ssize_t vout_vinfo_show(struct class *class, info->hdr_info.hdr10plus_info.ieeeoui); len += sprintf(buf+len, " application_version: %x\n", info->hdr_info.hdr10plus_info.application_version); + return len; } static struct class_attribute vout_class_attrs[] = { __ATTR(mode, 0644, vout_mode_show, vout_mode_store), + __ATTR(dummy, 0644, NULL, vout_dummy_store), __ATTR(axis, 0644, vout_axis_show, vout_axis_store), __ATTR(fr_policy, 0644, vout_fr_policy_show, vout_fr_policy_store), diff --git a/drivers/amlogic/media_modules/Makefile b/drivers/amlogic/media_modules/Makefile index f2a514848876..018c8feff897 100644 --- a/drivers/amlogic/media_modules/Makefile +++ b/drivers/amlogic/media_modules/Makefile @@ -2,3 +2,4 @@ obj-y += common/ obj-y += frame_provider/ obj-y += frame_sink/ obj-y += stream_input/ +obj-y += amvdec_ports/ diff --git a/drivers/amlogic/media_modules/amvdec_ports/Makefile b/drivers/amlogic/media_modules/amvdec_ports/Makefile new file mode 100644 index 000000000000..5ce0a7fcc114 --- /dev/null +++ b/drivers/amlogic/media_modules/amvdec_ports/Makefile @@ -0,0 +1,11 @@ +obj-m += amvdec_ports.o +amvdec_ports-objs += aml_vcodec_dec_drv.o +amvdec_ports-objs += aml_vcodec_dec.o +amvdec_ports-objs += aml_vcodec_dec_pm.o +amvdec_ports-objs += aml_vcodec_util.o +amvdec_ports-objs += aml_vcodec_adapt.o +amvdec_ports-objs += aml_vcodec_vfm.o +amvdec_ports-objs += vdec_drv_if.o +amvdec_ports-objs += decoder/vdec_h264_if.o +amvdec_ports-objs += decoder/h264_parse.o +amvdec_ports-objs += decoder/h264_stream.o diff --git a/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_adapt.c b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_adapt.c new file mode 100644 index 000000000000..5a3f71b7016e --- /dev/null +++ b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_adapt.c @@ -0,0 +1,720 @@ +/* +* 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. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../stream_input/amports/adec.h" +#include "../stream_input/parser/streambuf.h" +#include "../stream_input/parser/streambuf_reg.h" +#include "../stream_input/parser/tsdemux.h" +#include "../stream_input/parser/psparser.h" +#include "../stream_input/parser/esparser.h" +#include "../frame_provider/decoder/utils/vdec.h" +#include "../common/media_clock/switch/amports_gate.h" +#include +#include "aml_vcodec_adapt.h" +#include + +#define DEFAULT_VIDEO_BUFFER_SIZE (1024 * 1024 * 3) +#define DEFAULT_VIDEO_BUFFER_SIZE_4K (1024 * 1024 * 6) +#define DEFAULT_VIDEO_BUFFER_SIZE_TVP (1024 * 1024 * 10) +#define DEFAULT_VIDEO_BUFFER_SIZE_4K_TVP (1024 * 1024 * 15) +#define DEFAULT_AUDIO_BUFFER_SIZE (1024*768*2) +#define DEFAULT_SUBTITLE_BUFFER_SIZE (1024*256) + +#define PTS_OUTSIDE (1) +#define SYNC_OUTSIDE (2) +#define USE_V4L_PORTS (0x80) + +//#define DATA_DEBUG + +static int def_4k_vstreambuf_sizeM = + (DEFAULT_VIDEO_BUFFER_SIZE_4K >> 20); +static int def_vstreambuf_sizeM = + (DEFAULT_VIDEO_BUFFER_SIZE >> 20); + +static int slow_input = 0; + +static int use_bufferlevelx10000 = 10000; +static unsigned int amstream_buf_num = BUF_MAX_NUM; + +static struct stream_buf_s bufs[BUF_MAX_NUM] = { + { + .reg_base = VLD_MEM_VIFIFO_REG_BASE, + .type = BUF_TYPE_VIDEO, + .buf_start = 0, + .buf_size = DEFAULT_VIDEO_BUFFER_SIZE, + .default_buf_size = DEFAULT_VIDEO_BUFFER_SIZE, + .first_tstamp = INVALID_PTS + }, + { + .reg_base = AIU_MEM_AIFIFO_REG_BASE, + .type = BUF_TYPE_AUDIO, + .buf_start = 0, + .buf_size = DEFAULT_AUDIO_BUFFER_SIZE, + .default_buf_size = DEFAULT_AUDIO_BUFFER_SIZE, + .first_tstamp = INVALID_PTS + }, + { + .reg_base = 0, + .type = BUF_TYPE_SUBTITLE, + .buf_start = 0, + .buf_size = DEFAULT_SUBTITLE_BUFFER_SIZE, + .default_buf_size = DEFAULT_SUBTITLE_BUFFER_SIZE, + .first_tstamp = INVALID_PTS + }, + { + .reg_base = 0, + .type = BUF_TYPE_USERDATA, + .buf_start = 0, + .buf_size = 0, + .first_tstamp = INVALID_PTS + }, + { + .reg_base = HEVC_STREAM_REG_BASE, + .type = BUF_TYPE_HEVC, + .buf_start = 0, + .buf_size = DEFAULT_VIDEO_BUFFER_SIZE_4K, + .default_buf_size = DEFAULT_VIDEO_BUFFER_SIZE_4K, + .first_tstamp = INVALID_PTS + }, +}; + +static void set_cfg_info(struct aml_vdec_adapt *vdec) +{ + unsigned long sync_mode = (PTS_OUTSIDE | SYNC_OUTSIDE | USE_V4L_PORTS); + + vdec->port.type |= (PORT_TYPE_VIDEO | PORT_TYPE_FRAME/* | PORT_TYPE_ES*/); + vdec->port.flag |= PORT_FLAG_VFORMAT; + vdec->dec_prop.format = vdec->format; + vdec->dec_prop.width = 1920; + vdec->dec_prop.height = 1080; + vdec->dec_prop.rate = 3200; + vdec->dec_prop.param = (void *)sync_mode; +} + +static void set_vdec_mode(struct vdec_s *vdec) +{ + //vdec->type = VDEC_TYPE_SINGLE; + vdec->type = VDEC_TYPE_FRAME_BLOCK; +} + +static void set_vdec_vfm(struct vdec_s *vdec) +{ + vdec->frame_base_video_path = FRAME_BASE_PATH_V4L_VIDEO; +} + +static int enable_hardware(struct stream_port_s *port) +{ + if (get_cpu_type() < MESON_CPU_MAJOR_ID_M6) + return -1; + + amports_switch_gate("demux", 1); + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M8) + amports_switch_gate("parser_top", 1); + + if (port->type & PORT_TYPE_VIDEO) { + amports_switch_gate("vdec", 1); + + if (has_hevc_vdec()) { + if (port->type & (PORT_TYPE_MPTS | PORT_TYPE_HEVC)) + vdec_poweron(VDEC_HEVC); + + if ((port->type & PORT_TYPE_HEVC) == 0) + vdec_poweron(VDEC_1); + } else { + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M8) + vdec_poweron(VDEC_1); + } + } + + return 0; +} + +static int disable_hardware(struct stream_port_s *port) +{ + if (get_cpu_type() < MESON_CPU_MAJOR_ID_M6) + return -1; + + if ((port->type & PORT_TYPE_VIDEO) + && get_cpu_type() >= MESON_CPU_MAJOR_ID_M8) { +#ifndef CONFIG_AMLOGIC_MEDIA_MULTI_DEC + if (has_hevc_vdec()) + vdec_poweroff(VDEC_HEVC); + + vdec_poweroff(VDEC_1); +#else + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_TXLX + && port->vformat == VFORMAT_H264 + && bufs[BUF_TYPE_VIDEO].for_4k) + vdec_poweroff(VDEC_HEVC); + + if ((port->vformat == VFORMAT_HEVC + || port->vformat == VFORMAT_VP9)) + vdec_poweroff(VDEC_HEVC); + else + vdec_poweroff(VDEC_1); +#endif + amports_switch_gate("vdec", 0); + } + + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M8) + amports_switch_gate("parser_top", 0); + + amports_switch_gate("demux", 0); + + return 0; +} + +static int reset_canuse_buferlevel(int levelx10000) +{ + int i; + struct stream_buf_s *p = NULL; + + if (levelx10000 >= 0 && levelx10000 <= 10000) + use_bufferlevelx10000 = levelx10000; + else + use_bufferlevelx10000 = 10000; + for (i = 0; i < amstream_buf_num; i++) { + p = &bufs[i]; + p->canusebuf_size = ((p->buf_size / 1024) * + use_bufferlevelx10000 / 10000) * 1024; + p->canusebuf_size += 1023; + p->canusebuf_size &= ~1023; + + if (p->canusebuf_size > p->buf_size) + p->canusebuf_size = p->buf_size; + } + + return 0; +} + +static void change_vbufsize(struct vdec_s *vdec, + struct stream_buf_s *pvbuf) +{ + if (pvbuf->buf_start != 0) { + pr_info("streambuf is alloced before\n"); + return; + } + + if (pvbuf->for_4k) { + pvbuf->buf_size = def_4k_vstreambuf_sizeM * SZ_1M; + + if (vdec->port_flag & PORT_FLAG_DRM) + pvbuf->buf_size = DEFAULT_VIDEO_BUFFER_SIZE_4K_TVP; + + if ((pvbuf->buf_size > 30 * SZ_1M) + && (codec_mm_get_total_size() < 220 * SZ_1M)) { + /*if less than 250M, used 20M for 4K & 265*/ + pvbuf->buf_size = pvbuf->buf_size >> 1; + } + } else if (pvbuf->buf_size > def_vstreambuf_sizeM * SZ_1M) { + if (vdec->port_flag & PORT_FLAG_DRM) + pvbuf->buf_size = DEFAULT_VIDEO_BUFFER_SIZE_TVP; + } else { + pvbuf->buf_size = def_vstreambuf_sizeM * SZ_1M; + if (vdec->port_flag & PORT_FLAG_DRM) + pvbuf->buf_size = DEFAULT_VIDEO_BUFFER_SIZE_TVP; + } + + reset_canuse_buferlevel(10000); +} + +static void user_buffer_init(void) +{ + struct stream_buf_s *pubuf = &bufs[BUF_TYPE_USERDATA]; + + pubuf->buf_size = 0; + pubuf->buf_start = 0; + pubuf->buf_wp = 0; + pubuf->buf_rp = 0; +} + +static void audio_component_release(struct stream_port_s *port, + struct stream_buf_s *pbuf, int release_num) +{ + switch (release_num) { + default: + case 0: + case 4: + esparser_release(pbuf); + case 3: + adec_release(port->vformat); + case 2: + stbuf_release(pbuf, false); + case 1: + ; + } +} + +static int audio_component_init(struct stream_port_s *port, + struct stream_buf_s *pbuf) +{ + int r; + + if ((port->flag & PORT_FLAG_AFORMAT) == 0) { + pr_err("aformat not set\n"); + return 0; + } + + r = stbuf_init(pbuf, NULL, false); + if (r < 0) + return r; + + r = adec_init(port); + if (r < 0) { + audio_component_release(port, pbuf, 2); + return r; + } + + if (port->type & PORT_TYPE_ES) { + r = esparser_init(pbuf, NULL); + if (r < 0) { + audio_component_release(port, pbuf, 3); + return r; + } + } + + pbuf->flag |= BUF_FLAG_IN_USE; + + return 0; +} + +static void video_component_release(struct stream_port_s *port, +struct stream_buf_s *pbuf, int release_num) +{ + struct aml_vdec_adapt *ada_ctx + = container_of(port, struct aml_vdec_adapt, port); + struct vdec_s *vdec = ada_ctx->vdec; + + struct vdec_s *slave = NULL; + bool is_multidec = !vdec_single(vdec); + + switch (release_num) { + default: + case 0: + case 4: { + if ((port->type & PORT_TYPE_FRAME) == 0) + esparser_release(pbuf); + } + + case 3: { + if (vdec->slave) + slave = vdec->slave; + vdec_release(vdec); + + if (slave) + vdec_release(slave); + vdec = NULL; + } + + case 2: { + if ((port->type & PORT_TYPE_FRAME) == 0) + stbuf_release(pbuf, is_multidec); + } + + case 1: + ; + } +} + +static int video_component_init(struct stream_port_s *port, + struct stream_buf_s *pbuf) +{ + int ret = -1; + struct aml_vdec_adapt *ada_ctx + = container_of(port, struct aml_vdec_adapt, port); + struct vdec_s *vdec = ada_ctx->vdec; + + if ((vdec->port_flag & PORT_FLAG_VFORMAT) == 0) { + pr_err("vformat not set\n"); + return -EPERM; + } + + if ((vdec->sys_info->height * vdec->sys_info->width) > 1920 * 1088 + || port->vformat == VFORMAT_H264_4K2K) { + pbuf->for_4k = 1; + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_TXLX + && port->vformat == VFORMAT_H264) + vdec_poweron(VDEC_HEVC); + } else + pbuf->for_4k = 0; + + if (port->type & PORT_TYPE_FRAME) { + ret = vdec_init(vdec, pbuf->for_4k); + if (ret < 0) { + pr_err("video_component_init %d, failed\n", __LINE__); + video_component_release(port, pbuf, 2); + return ret; + } + + return 0; + } + + change_vbufsize(vdec, pbuf); + + if (has_hevc_vdec()) { + if (port->type & PORT_TYPE_MPTS) { + if (pbuf->type == BUF_TYPE_HEVC) + vdec_poweroff(VDEC_1); + else + vdec_poweroff(VDEC_HEVC); + } + } + + ret = stbuf_init(pbuf, vdec, false); + if (ret < 0) { + pr_err("video_component_init %d, stbuf_init failed\n", __LINE__); + return ret; + } + + /* todo: set path based on port flag */ + ret = vdec_init(vdec, pbuf->for_4k); + if (ret < 0) { + pr_err("video_component_init %d, vdec_init failed\n", __LINE__); + video_component_release(port, pbuf, 2); + return ret; + } + + if (vdec_dual(vdec)) { + ret = vdec_init(vdec->slave, pbuf->for_4k); + if (ret < 0) { + pr_err("video_component_init %d, vdec_init failed\n", + __LINE__); + video_component_release(port, pbuf, 2); + return ret; + } + } + + if (port->type & PORT_TYPE_ES) { + ret = esparser_init(pbuf, vdec); + if (ret < 0) { + video_component_release(port, pbuf, 3); + pr_err("esparser_init() failed\n"); + return ret; + } + } + + pbuf->flag |= BUF_FLAG_IN_USE; + + vdec_connect(vdec); + + return 0; +} + +static int vdec_ports_release(struct stream_port_s *port) +{ + struct aml_vdec_adapt *ada_ctx + = container_of(port, struct aml_vdec_adapt, port); + struct vdec_s *vdec = ada_ctx->vdec; + + struct stream_buf_s *pvbuf = &bufs[BUF_TYPE_VIDEO]; + struct stream_buf_s *pabuf = &bufs[BUF_TYPE_AUDIO]; + //struct stream_buf_s *psbuf = &bufs[BUF_TYPE_SUBTITLE]; + struct vdec_s *slave = NULL; + + if (has_hevc_vdec()) { + if (port->vformat == VFORMAT_HEVC + || port->vformat == VFORMAT_VP9) + pvbuf = &bufs[BUF_TYPE_HEVC]; + } + + if (port->type & PORT_TYPE_MPTS) { + tsync_pcr_stop(); + tsdemux_release(); + } + + if (port->type & PORT_TYPE_MPPS) + psparser_release(); + + if (port->type & PORT_TYPE_VIDEO) + video_component_release(port, pvbuf, 0); + + if (port->type & PORT_TYPE_AUDIO) + audio_component_release(port, pabuf, 0); + + if (port->type & PORT_TYPE_SUB) + //sub_port_release(port, psbuf); + + if (vdec) { + if (vdec->slave) + slave = vdec->slave; + + vdec_release(vdec); + + if (slave) + vdec_release(slave); + vdec = NULL; + } + + port->pcr_inited = 0; + port->flag = 0; + + return 0; +} + +static int vdec_ports_init(struct aml_vdec_adapt *vdec_adapt) +{ + int ret = -1; + struct stream_buf_s *pvbuf = &bufs[BUF_TYPE_VIDEO]; + struct stream_buf_s *pabuf = &bufs[BUF_TYPE_AUDIO]; + //struct stream_buf_s *psbuf = &bufs[BUF_TYPE_SUBTITLE]; + struct stream_port_s *port = &vdec_adapt->port; + struct vdec_s *vdec = NULL; + + /* create the vdec instance.*/ + vdec = vdec_create(port, NULL); + if (IS_ERR_OR_NULL(vdec)) + return -1; + + /* set v4l2 ctx */ + vdec->private = vdec_adapt->ctx; + + vdec_adapt->vdec = vdec; + vdec->sys_info = &vdec_adapt->dec_prop; + vdec->sys_info_store = vdec_adapt->dec_prop; + vdec->vf_receiver_name = vdec_adapt->recv_name; + + /* set video format and sys info */ + vdec_set_format(vdec, vdec_adapt->dec_prop.format); + set_vdec_mode(vdec); + set_vdec_vfm(vdec); + + stbuf_fetch_init(); + + user_buffer_init(); + + if ((port->type & PORT_TYPE_AUDIO) + && (port->flag & PORT_FLAG_AFORMAT)) { + ret = audio_component_init(port, pabuf); + if (ret < 0) { + pr_err("audio_component_init failed\n"); + goto error1; + } + } + + if ((port->type & PORT_TYPE_VIDEO) + && (vdec->port_flag & PORT_FLAG_VFORMAT)) { + pvbuf->for_4k = 0; + if (has_hevc_vdec()) { + if (port->vformat == VFORMAT_HEVC + || port->vformat == VFORMAT_VP9) + pvbuf = &bufs[BUF_TYPE_HEVC]; + } + + ret = video_component_init(port, pvbuf); + if (ret < 0) { + pr_err("video_component_init failed\n"); + goto error2; + } + } + + /* connect vdec at the end after all HW initialization */ + if ((port->type & PORT_TYPE_VIDEO) + && (vdec->port_flag & PORT_FLAG_VFORMAT)) + vdec_connect(vdec); + + return 0; + +//error3: + //video_component_release(port, pvbuf, 0); +error2: + audio_component_release(port, pabuf, 0); +error1: + return ret; +} + +int video_decoder_init(struct aml_vdec_adapt *vdec) +{ + int ret = -1; + + /* sets configure data */ + set_cfg_info(vdec); + + /* init hw and gate*/ + ret = enable_hardware(&vdec->port); + if (ret < 0) { + pr_info("enable hw fail.\n"); + goto out; + } + + /* init the buffer work space and connect vdec.*/ + ret = vdec_ports_init(vdec); + if (ret < 0) { + pr_info("vdec ports init fail.\n"); + goto out; + } +out: + return ret; +} + +int video_decoder_release(struct aml_vdec_adapt *vdec) +{ + int ret = -1; + struct stream_port_s *port = &vdec->port; + + ret = vdec_ports_release(port); + if (ret < 0) { + pr_info("vdec ports release fail.\n"); + goto out; + } + + /* disable gates */ + ret = disable_hardware(port); + if (ret < 0) { + pr_info("disable hw fail.\n"); + goto out; + } +out: + return ret; +} + +int vdec_vbuf_write(struct aml_vdec_adapt *ada_ctx, + const char *buf, unsigned int count) +{ + int ret = -1; + int try_cnt = 100; + struct stream_port_s *port = &ada_ctx->port; + struct vdec_s *vdec = ada_ctx->vdec; + struct stream_buf_s *pbuf = NULL; + + if (has_hevc_vdec()) { + pbuf = (port->type & PORT_TYPE_HEVC) ? &bufs[BUF_TYPE_HEVC] : + &bufs[BUF_TYPE_VIDEO]; + } else + pbuf = &bufs[BUF_TYPE_VIDEO]; + + /*if (!(port_get_inited(priv))) { + r = video_decoder_init(priv); + if (r < 0) + return r; + }*/ + + do { + if (vdec->port_flag & PORT_FLAG_DRM) + ret = drm_write(ada_ctx->filp, pbuf, buf, count); + else + ret = esparser_write(ada_ctx->filp, pbuf, buf, count); + } while (ret == -EAGAIN && try_cnt--); + + if (slow_input) { + pr_info("slow_input: es codec write size %x\n", ret); + msleep(10); + } + +#ifdef DATA_DEBUG + /* dump to file */ + //dump_write(vbuf, size); + //pr_info("vbuf: %p, size: %u, ret: %d\n", vbuf, size, ret); +#endif + + return ret; +} + +int is_need_to_buf(struct aml_vdec_adapt *ada_ctx) +{ + struct vdec_s *vdec = ada_ctx->vdec; + + if (vdec->input.have_frame_num > 8) + return 0; + else + return 1; +} + +int vdec_vframe_write(struct aml_vdec_adapt *ada_ctx, + const char *buf, unsigned int count, unsigned long int timestamp) +{ + int ret = -1; + int try_cnt = 10; + struct vdec_s *vdec = ada_ctx->vdec; + + /* set timestamp */ + vdec_set_timestamp(vdec, timestamp); + + do { + ret = vdec_write_vframe(vdec, buf, count); + if (ret == -EAGAIN) { + /*vdec_input_level(&vdec->input);*/ + msleep(20); + } + } while (ret == -EAGAIN && try_cnt--); + + if (slow_input) { + pr_info("slow_input: frame codec write size %d\n", ret); + msleep(30); + } + +#ifdef DATA_DEBUG + /* dump to file */ + dump_write(buf, count); +#endif + aml_v4l2_debug(2, "[%d] write frames, vbuf: %p, size: %u, ret: %d, crc: %x", + ada_ctx->ctx->id, buf, count, ret, crc32(0, buf, count)); + + return ret; +} + +void aml_decoder_flush(struct aml_vdec_adapt *ada_ctx) +{ + struct vdec_s *vdec = ada_ctx->vdec; + + if (vdec) + vdec_set_eos(vdec, true); +} + +int aml_codec_reset(struct aml_vdec_adapt *ada_ctx) +{ + struct vdec_s *vdec = ada_ctx->vdec; + int ret = 0; + + if (vdec) { + vdec_set_eos(vdec, false); + ret = vdec_reset(vdec); + } + + return ret; +} + +bool is_input_ready(struct aml_vdec_adapt *ada_ctx) +{ + struct vdec_s *vdec = ada_ctx->vdec; + int state = VDEC_STATUS_UNINITIALIZED; + + if (vdec) { + state = vdec_get_status(vdec); + + if (state == VDEC_STATUS_CONNECTED + || state == VDEC_STATUS_ACTIVE) + return true; + } + + return false; +} diff --git a/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_adapt.h b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_adapt.h new file mode 100644 index 000000000000..da4553f50970 --- /dev/null +++ b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_adapt.h @@ -0,0 +1,65 @@ +/* +* 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. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ +#ifndef VDEC_ADAPT_H +#define VDEC_ADAPT_H + +#include +#include +#include "../stream_input/parser/streambuf.h" +#include "aml_vcodec_drv.h" + +struct aml_vdec_adapt { + enum vformat_e format; + void *vsi; + int32_t failure; + uint32_t inst_addr; + unsigned int signaled; + struct aml_vcodec_ctx *ctx; + struct platform_device *dev; + wait_queue_head_t wq; + struct file *filp; + struct vdec_s *vdec; + struct stream_port_s port; + struct dec_sysinfo dec_prop; + char *recv_name; +}; + +int video_decoder_init(struct aml_vdec_adapt *ada_ctx); + +int video_decoder_release(struct aml_vdec_adapt *ada_ctx); + +int vdec_vbuf_write(struct aml_vdec_adapt *ada_ctx, + const char *buf, unsigned int count); + +int vdec_vframe_write(struct aml_vdec_adapt *ada_ctx, + const char *buf, unsigned int count, unsigned long int timestamp); + +int is_need_to_buf(struct aml_vdec_adapt *ada_ctx); + +void aml_decoder_flush(struct aml_vdec_adapt *ada_ctx); + +int aml_codec_reset(struct aml_vdec_adapt *ada_ctx); + +extern void dump_write(const char __user *buf, size_t count); + +bool is_input_ready(struct aml_vdec_adapt *ada_ctx); + +#endif /* VDEC_ADAPT_H */ + diff --git a/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_dec.c b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_dec.c new file mode 100644 index 000000000000..20dd5d5346b4 --- /dev/null +++ b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_dec.c @@ -0,0 +1,1837 @@ +/* +* 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. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ +#include +#include +#include + +#include "aml_vcodec_drv.h" +#include "aml_vcodec_dec.h" +//#include "aml_vcodec_intr.h" +#include "aml_vcodec_util.h" +#include "vdec_drv_if.h" +#include "aml_vcodec_dec_pm.h" +#include +#include +#include +#include "aml_vcodec_adapt.h" + +#include "aml_vcodec_vfm.h" + +#define OUT_FMT_IDX 0 +#define CAP_FMT_IDX 1//3 + +#define AML_VDEC_MIN_W 64U +#define AML_VDEC_MIN_H 64U +#define DFT_CFG_WIDTH AML_VDEC_MIN_W +#define DFT_CFG_HEIGHT AML_VDEC_MIN_H + +//#define USEC_PER_SEC 1000000 + +#define call_void_memop(vb, op, args...) \ + do { \ + if ((vb)->vb2_queue->mem_ops->op) \ + (vb)->vb2_queue->mem_ops->op(args); \ + } while (0) + +static struct aml_video_fmt aml_video_formats[] = { + { + .fourcc = V4L2_PIX_FMT_H264, + .type = AML_FMT_DEC, + .num_planes = 1, + }, +/* { + .fourcc = V4L2_PIX_FMT_VP8, + .type = AML_FMT_DEC, + .num_planes = 1, + }, + { + .fourcc = V4L2_PIX_FMT_VP9, + .type = AML_FMT_DEC, + .num_planes = 1, + },*/ + { + .fourcc = V4L2_PIX_FMT_NV12, + .type = AML_FMT_FRAME, + .num_planes = 2, + }, +}; + +static const struct aml_codec_framesizes aml_vdec_framesizes[] = { + { + .fourcc = V4L2_PIX_FMT_H264, + .stepwise = { AML_VDEC_MIN_W, AML_VDEC_MAX_W, 16, + AML_VDEC_MIN_H, AML_VDEC_MAX_H, 16 }, + }, +/* { + .fourcc = V4L2_PIX_FMT_VP8, + .stepwise = { AML_VDEC_MIN_W, AML_VDEC_MAX_W, 16, + AML_VDEC_MIN_H, AML_VDEC_MAX_H, 16 }, + }, + { + .fourcc = V4L2_PIX_FMT_VP9, + .stepwise = { AML_VDEC_MIN_W, AML_VDEC_MAX_W, 16, + AML_VDEC_MIN_H, AML_VDEC_MAX_H, 16 }, + },*/ +}; + +#define NUM_SUPPORTED_FRAMESIZE ARRAY_SIZE(aml_vdec_framesizes) +#define NUM_FORMATS ARRAY_SIZE(aml_video_formats) + +static struct aml_video_fmt *aml_vdec_find_format(struct v4l2_format *f) +{ + struct aml_video_fmt *fmt; + unsigned int k; + + for (k = 0; k < NUM_FORMATS; k++) { + fmt = &aml_video_formats[k]; + if (fmt->fourcc == f->fmt.pix_mp.pixelformat) + return fmt; + } + + return NULL; +} + +static struct aml_q_data *aml_vdec_get_q_data(struct aml_vcodec_ctx *ctx, + enum v4l2_buf_type type) +{ + if (V4L2_TYPE_IS_OUTPUT(type)) + return &ctx->q_data[AML_Q_DATA_SRC]; + + return &ctx->q_data[AML_Q_DATA_DST]; +} + +static void aml_vdec_queue_res_chg_event(struct aml_vcodec_ctx *ctx) +{ + static const struct v4l2_event ev_src_ch = { + .type = V4L2_EVENT_SOURCE_CHANGE, + .u.src_change.changes = + V4L2_EVENT_SRC_CH_RESOLUTION, + }; + + aml_v4l2_debug(4, "[%d] %s()", ctx->id, __func__); + v4l2_event_queue_fh(&ctx->fh, &ev_src_ch); +} + +static void aml_vdec_flush_decoder(struct aml_vcodec_ctx *ctx) +{ + aml_v4l2_debug(3, "[%d] %s() [%d]", ctx->id, __func__, __LINE__); + + aml_decoder_flush(ctx->ada_ctx); +} + +static void aml_vdec_pic_info_update(struct aml_vcodec_ctx *ctx) +{ + unsigned int dpbsize = 0; + int ret; + + if (vdec_if_get_param(ctx, + GET_PARAM_PIC_INFO, + &ctx->last_decoded_picinfo)) { + aml_v4l2_err("[%d] Error!! Cannot get param : GET_PARAM_PICTURE_INFO ERR", + ctx->id); + return; + } + + if (ctx->last_decoded_picinfo.visible_width == 0 || + ctx->last_decoded_picinfo.visible_height == 0 || + ctx->last_decoded_picinfo.coded_width == 0 || + ctx->last_decoded_picinfo.coded_height == 0) { + aml_v4l2_err("Cannot get correct pic info"); + return; + } + + if ((ctx->last_decoded_picinfo.visible_width == ctx->picinfo.visible_width) || + (ctx->last_decoded_picinfo.visible_height == ctx->picinfo.visible_height)) + return; + + aml_v4l2_debug(4, + "[%d]-> new(%d,%d), old(%d,%d), real(%d,%d)", + ctx->id, ctx->last_decoded_picinfo.visible_width, + ctx->last_decoded_picinfo.visible_height, + ctx->picinfo.visible_width, ctx->picinfo.visible_height, + ctx->last_decoded_picinfo.coded_width, + ctx->last_decoded_picinfo.coded_width); + + ret = vdec_if_get_param(ctx, GET_PARAM_DPB_SIZE, &dpbsize); + if (dpbsize == 0) + aml_v4l2_err("[%d] Incorrect dpb size, ret=%d", ctx->id, ret); + + ctx->dpb_size = dpbsize; +} + +int get_fb_from_queue(struct aml_vcodec_ctx *ctx, struct vdec_fb **out_fb) +{ + struct vb2_buffer *dst_buf = NULL; + struct vdec_fb *pfb; + struct aml_video_dec_buf *dst_buf_info, *info; + struct vb2_v4l2_buffer *dst_vb2_v4l2; + int try_cnt = 10; + + aml_v4l2_debug(4, "[%d] %s() [%d]", ctx->id, __func__, __LINE__); + + do { + dst_buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx); + if (dst_buf) + break; + aml_v4l2_debug(3, "[%d] waitting enough dst buffers.", ctx->id); + msleep(20); + } while (try_cnt--); + + if (!dst_buf) + return -1; + + dst_vb2_v4l2 = container_of(dst_buf, struct vb2_v4l2_buffer, vb2_buf); + dst_buf_info = container_of(dst_vb2_v4l2, struct aml_video_dec_buf, vb); + + pfb = &dst_buf_info->frame_buffer; + //pfb->base_y.va = vb2_plane_vaddr(dst_buf, 0); + pfb->base_y.dma_addr = vb2_dma_contig_plane_dma_addr(dst_buf, 0); + pfb->base_y.va = phys_to_virt(dma_to_phys(v4l_get_dev_from_codec_mm(), pfb->base_y.dma_addr)); + pfb->base_y.size = ctx->picinfo.y_len_sz; + + //pfb->base_c.va = vb2_plane_vaddr(dst_buf, 1); + pfb->base_c.dma_addr = vb2_dma_contig_plane_dma_addr(dst_buf, 1); + pfb->base_c.va = phys_to_virt(dma_to_phys(v4l_get_dev_from_codec_mm(), pfb->base_c.dma_addr)); + pfb->base_c.size = ctx->picinfo.c_len_sz; + pfb->status = FB_ST_NORMAL; + + aml_v4l2_debug(4, "[%d] id=%d Framebuf pfb=%p VA=%p Y_DMA=%pad C_DMA=%pad y_size=%zx, c_size: %zx", + ctx->id, dst_buf->index, pfb, pfb->base_y.va, &pfb->base_y.dma_addr, + &pfb->base_c.dma_addr, pfb->base_y.size, pfb->base_c.size); + + //mutex_lock(&ctx->lock); + dst_buf_info->used = true; + //mutex_unlock(&ctx->lock); + + v4l2_m2m_dst_buf_remove(ctx->m2m_ctx); + + *out_fb = pfb; + + info = container_of(pfb, struct aml_video_dec_buf, frame_buffer); + + return 0; +} +EXPORT_SYMBOL(get_fb_from_queue); + +int put_fb_to_queue(struct aml_vcodec_ctx *ctx, struct vdec_fb *in_fb) +{ + struct aml_video_dec_buf *dstbuf; + + pr_info("[%d] %s() [%d]\n", ctx->id, __func__, __LINE__); + + if (in_fb == NULL) { + aml_v4l2_debug(4, "[%d] No free frame buffer", ctx->id); + return -1; + } + + aml_v4l2_debug(4, "[%d] tmp_frame_addr = 0x%p", ctx->id, in_fb); + + dstbuf = container_of(in_fb, struct aml_video_dec_buf, frame_buffer); + + mutex_lock(&ctx->lock); + + if (!dstbuf->used) + goto out; + + aml_v4l2_debug(4, + "[%d] status=%x queue id=%d to rdy_queue", + ctx->id, in_fb->status, + dstbuf->vb.vb2_buf.index); + + v4l2_m2m_buf_queue(ctx->m2m_ctx, &dstbuf->vb); + + dstbuf->used = false; +out: + mutex_unlock(&ctx->lock); + + return 0; + +} +EXPORT_SYMBOL(put_fb_to_queue); + +void trans_vframe_to_user(struct aml_vcodec_ctx *ctx, struct vdec_fb *fb) +{ + int cnt; + struct aml_video_dec_buf *dstbuf = NULL; + struct vframe_s *vf = (struct vframe_s *)fb->vf_handle; + + dstbuf = container_of(fb, struct aml_video_dec_buf, frame_buffer); + + aml_v4l2_debug(4,"%s() [%d], base_y: %zu, idx: %u\n", + __FUNCTION__, __LINE__, fb->base_y.size, dstbuf->vb.vb2_buf.index); + aml_v4l2_debug(4,"%s() [%d], base_c: %zu, idx: %u\n", + __FUNCTION__, __LINE__, fb->base_c.size, dstbuf->vb.vb2_buf.index); + + dstbuf->vb.vb2_buf.timestamp = vf->timestamp; + aml_v4l2_debug(4, "[%d] %s() [%d], timestamp: %llx", + ctx->id, __func__, __LINE__, vf->timestamp); + + vb2_set_plane_payload(&dstbuf->vb.vb2_buf, 0, fb->base_y.bytes_used); + vb2_set_plane_payload(&dstbuf->vb.vb2_buf, 1, fb->base_c.bytes_used); + + dstbuf->ready_to_display = true; + + aml_v4l2_debug(4, "[%d]status=%x queue id=%d to done_list %d", + ctx->id, fb->status, dstbuf->vb.vb2_buf.index, + dstbuf->queued_in_vb2); + + cnt = atomic_read(&dstbuf->vb.vb2_buf.vb2_queue->owned_by_drv_count); + aml_v4l2_debug(4, "[%d] %s() [%d], owned_by_drv_count: %d", + ctx->id, __func__, __LINE__, cnt); + aml_v4l2_debug(4, "[%d] %s() [%d], y_va: %p, vf_h: %lx", + ctx->id, __func__, __LINE__, dstbuf->frame_buffer.base_y.va, + dstbuf->frame_buffer.vf_handle); + + if (vf->flag == VFRAME_FLAG_EMPTY_FRAME_V4L) { + dstbuf->lastframe = true; + dstbuf->vb.flags = V4L2_BUF_FLAG_LAST; + vb2_set_plane_payload(&dstbuf->vb.vb2_buf, 0, 0); + vb2_set_plane_payload(&dstbuf->vb.vb2_buf, 1, 0); + ctx->has_receive_eos = true; + pr_info("[%d] recevie a empty frame.\n", ctx->id); + } + + v4l2_m2m_buf_done(&dstbuf->vb, VB2_BUF_STATE_DONE); + + mutex_lock(&ctx->state_lock); + if (ctx->state == AML_STATE_FLUSHING && + ctx->has_receive_eos) { + ctx->state = AML_STATE_FLUSHED; + aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_FLUSHED)", + ctx->id, __func__); + } + mutex_unlock(&ctx->state_lock); + + ctx->decoded_frame_cnt++; +} + +static int get_display_buffer(struct aml_vcodec_ctx *ctx, struct vdec_fb **out) +{ + int ret = -1; + + aml_v4l2_debug(4, "[%d] %s()", ctx->id, __func__); + + ret = vdec_if_get_param(ctx, GET_PARAM_DISP_FRAME_BUFFER, out); + if (ret) { + aml_v4l2_err("[%d] Cannot get param : GET_PARAM_DISP_FRAME_BUFFER", ctx->id); + return -1; + } + + if (!*out) { + aml_v4l2_debug(4, "[%d] No display frame buffer", ctx->id); + return -1; + } + + return ret; +} + +static int is_vdec_ready(struct aml_vcodec_ctx *ctx) +{ + struct aml_vcodec_dev *dev = ctx->dev; + + if (!is_input_ready(ctx->ada_ctx)) { + pr_err("[%d] %s() the decoder intput has not ready.\n", + ctx->id, __func__); + v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx); + return 0; + } + + if (ctx->state == AML_STATE_PROBE) { + int buf_ready_num; + + /* is there enough dst bufs for decoding? */ + buf_ready_num = v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx); + if (buf_ready_num < ctx->dpb_size) { + aml_v4l2_debug(4, "[%d] Not enough dst bufs, num: %d.\n", + ctx->id, buf_ready_num); + v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx); + v4l2_m2m_try_schedule(ctx->m2m_ctx); + msleep(60); + return 0; + } + + mutex_lock(&ctx->state_lock); + if (ctx->state == AML_STATE_PROBE) { + ctx->state = AML_STATE_READY; + aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_READY)", + ctx->id, __func__); + } + mutex_unlock(&ctx->state_lock); + } + + mutex_lock(&ctx->state_lock); + if (ctx->state == AML_STATE_READY) { + ctx->state = AML_STATE_ACTIVE; + aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_ACTIVE)", + ctx->id, __func__); + } + mutex_unlock(&ctx->state_lock); + + return 1; +} + +static void aml_vdec_worker(struct work_struct *work) +{ + struct aml_vcodec_ctx *ctx = + container_of(work, struct aml_vcodec_ctx, decode_work); + struct aml_vcodec_dev *dev = ctx->dev; + struct vb2_buffer *src_buf; + struct aml_vcodec_mem buf; + bool res_chg = false; + int ret; + struct aml_video_dec_buf *src_buf_info; + struct vb2_v4l2_buffer *src_vb2_v4l2; + + aml_v4l2_debug(4, "[%d] entry [%d] [%s]", ctx->id, __LINE__, __func__); + + aml_vdec_lock(ctx); + + if (ctx->state < AML_STATE_INIT || + ctx->state > AML_STATE_FLUSHED) { + v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx); + aml_vdec_unlock(ctx); + return; + } + + if (!is_vdec_ready(ctx)) { + pr_err("[%d] %s() the decoder has not ready.\n", + ctx->id, __func__); + aml_vdec_unlock(ctx); + return; + } + + src_buf = v4l2_m2m_next_src_buf(ctx->m2m_ctx); + if (src_buf == NULL) { + pr_err("[%d] src_buf empty!\n", ctx->id); + aml_vdec_unlock(ctx); + return; + } + + src_vb2_v4l2 = container_of(src_buf, struct vb2_v4l2_buffer, vb2_buf); + src_buf_info = container_of(src_vb2_v4l2, struct aml_video_dec_buf, vb); + + if (src_buf_info->lastframe) { + //the empty data use to flushed the decoder. + aml_v4l2_debug(3, "[%d] Got empty flush input buffer.", ctx->id); + + src_buf = v4l2_m2m_src_buf_remove(ctx->m2m_ctx); + v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx); + + /* sets eos data for vdec input. */ + aml_vdec_flush_decoder(ctx); + + mutex_lock(&ctx->state_lock); + if (ctx->state == AML_STATE_ACTIVE) { + ctx->state = AML_STATE_FLUSHING;// prepare flushing + aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_FLUSHING)", + ctx->id, __func__); + } + mutex_unlock(&ctx->state_lock); + + aml_vdec_unlock(ctx); + return; + } + + buf.va = vb2_plane_vaddr(src_buf, 0); + buf.dma_addr = vb2_dma_contig_plane_dma_addr(src_buf, 0); + //buf.va = phys_to_virt(dma_to_phys(v4l_get_dev_from_codec_mm(), buf.dma_addr)); + + buf.size = (size_t)src_buf->planes[0].bytesused; + if (!buf.va) { + v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx); + aml_v4l2_err("[%d] id=%d src_addr is NULL!!", + ctx->id, src_buf->index); + aml_vdec_unlock(ctx); + return; + } + aml_v4l2_debug(4, "[%d] Bitstream VA=%p DMA=%pad Size=%zx vb=%p", + ctx->id, buf.va, &buf.dma_addr, buf.size, src_buf); + + src_buf_info->used = true; + + //pr_err("%s() [%d], size: 0x%zx, crc: 0x%x\n", + //__func__, __LINE__, buf.size, crc32(0, buf.va, buf.size)); + + /* pts = (time / 10e6) * (90k / fps) */ + aml_v4l2_debug(4, "[%d] %s() timestamp: 0x%llx", ctx->id , __func__, + src_buf->timestamp); + + ret = vdec_if_decode(ctx, &buf, src_buf->timestamp, &res_chg); + if (ret > 0) { + /* + * we only return src buffer with VB2_BUF_STATE_DONE + * when decode success without resolution change + */ + src_buf = v4l2_m2m_src_buf_remove(ctx->m2m_ctx); + v4l2_m2m_buf_done(&src_buf_info->vb, VB2_BUF_STATE_DONE); + } else if (ret == -EAGAIN) { + v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx); + aml_vdec_unlock(ctx); + return; + } else { + src_buf = v4l2_m2m_src_buf_remove(ctx->m2m_ctx); + if (ret == -EIO) { + //mutex_lock(&ctx->lock); + src_buf_info->error = true; + //mutex_unlock(&ctx->lock); + } + v4l2_m2m_buf_done(&src_buf_info->vb, VB2_BUF_STATE_ERROR); + } + + if (!ret && res_chg) { + if (0) aml_vdec_pic_info_update(ctx); + /* + * On encountering a resolution change in the stream. + * The driver must first process and decode all + * remaining buffers from before the resolution change + * point, so call flush decode here + */ + if (0) aml_vdec_flush_decoder(ctx); + /* + * After all buffers containing decoded frames from + * before the resolution change point ready to be + * dequeued on the CAPTURE queue, the driver sends a + * V4L2_EVENT_SOURCE_CHANGE event for source change + * type V4L2_EVENT_SRC_CH_RESOLUTION + */ + if (0) aml_vdec_queue_res_chg_event(ctx); + } + + v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx); + aml_vdec_unlock(ctx); +} + +static void aml_reset_worker(struct work_struct *work) +{ + struct aml_vcodec_ctx *ctx = + container_of(work, struct aml_vcodec_ctx, reset_work); + struct aml_video_dec_buf *buf = NULL; + + aml_vdec_lock(ctx); + + if (ctx->state == AML_STATE_ABORT) { + pr_err("[%d] %s() the decoder will be exited.\n", + ctx->id, __func__); + aml_vdec_unlock(ctx); + return; + } + + /* fast enque capture buffers. */ + list_for_each_entry(buf, &ctx->capture_list, node) { + if (buf->que_in_m2m) + v4l2_m2m_buf_queue(ctx->m2m_ctx, &buf->vb); + } + + if (aml_codec_reset(ctx->ada_ctx)) { + ctx->state = AML_STATE_ABORT; + aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_ABORT)", + ctx->id, __func__); + aml_vdec_unlock(ctx); + return; + } + + mutex_lock(&ctx->state_lock); + if (ctx->state == AML_STATE_RESET) { + ctx->state = AML_STATE_READY; + aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_READY)", + ctx->id, __func__); + + v4l2_m2m_try_schedule(ctx->m2m_ctx); + } + mutex_unlock(&ctx->state_lock); + + aml_vdec_unlock(ctx); +} + +void try_to_capture(struct aml_vcodec_ctx *ctx) +{ + int ret = 0; + struct vdec_fb *fb = NULL; + + ret = get_display_buffer(ctx, &fb); + if (ret) { + aml_v4l2_debug(4, "[%d] %s() [%d], the que have no disp buf,ret: %d", + ctx->id, __func__, __LINE__, ret); + return; + } + + trans_vframe_to_user(ctx, fb); +} +EXPORT_SYMBOL_GPL(try_to_capture); + +static int vdec_thread(void *data) +{ + struct aml_vdec_thread *thread = + (struct aml_vdec_thread *) data; + struct aml_vcodec_ctx *ctx = + (struct aml_vcodec_ctx *) thread->priv; + + for (;;) { + aml_v4l2_debug(3, "[%d] %s() state: %d", ctx->id, + __func__, ctx->state); + + if (down_interruptible(&thread->sem)) + break; + + if (thread->stop) + break; + + thread->func(ctx); + } + + while (!kthread_should_stop()) { + set_current_state(TASK_INTERRUPTIBLE); + schedule(); + } + + return 0; +} + +void aml_thread_notify(struct aml_vcodec_ctx *ctx, + enum aml_thread_type type) +{ + struct aml_vdec_thread *thread = NULL; + + list_for_each_entry(thread, &ctx->vdec_thread_list, node) { + if (thread->task == NULL) + continue; + + if (thread->type == type) + up(&thread->sem); + } +} +EXPORT_SYMBOL_GPL(aml_thread_notify); + +int aml_thread_start(struct aml_vcodec_ctx *ctx, aml_thread_func func, + enum aml_thread_type type, const char *thread_name) +{ + struct aml_vdec_thread *thread; + int ret = 0; + + thread = kzalloc(sizeof(*thread), GFP_KERNEL); + if (thread == NULL) + return -ENOMEM; + + thread->type = type; + thread->func = func; + thread->priv = ctx; + sema_init(&thread->sem, 0); + + thread->task = kthread_run(vdec_thread, thread, "aml-%s", thread_name); + if (IS_ERR(thread->task)) { + ret = PTR_ERR(thread->task); + thread->task = NULL; + goto err; + } + + list_add(&thread->node, &ctx->vdec_thread_list); + + return 0; + +err: + kfree(thread); + + return ret; +} +EXPORT_SYMBOL_GPL(aml_thread_start); + +void aml_thread_stop(struct aml_vcodec_ctx *ctx) +{ + struct aml_vdec_thread *thread = NULL; + + while (!list_empty(&ctx->vdec_thread_list)) { + thread = list_entry(ctx->vdec_thread_list.next, + struct aml_vdec_thread, node); + list_del(&thread->node); + thread->stop = true; + up(&thread->sem); + kthread_stop(thread->task); + thread->task = NULL; + kfree(thread); + } +} +EXPORT_SYMBOL_GPL(aml_thread_stop); + +static int vidioc_try_decoder_cmd(struct file *file, void *priv, + struct v4l2_decoder_cmd *cmd) +{ + switch (cmd->cmd) { + case V4L2_DEC_CMD_STOP: + case V4L2_DEC_CMD_START: + if (cmd->flags != 0) { + aml_v4l2_err("cmd->flags=%u", cmd->flags); + return -EINVAL; + } + break; + default: + return -EINVAL; + } + return 0; +} + +static int vidioc_decoder_cmd(struct file *file, void *priv, + struct v4l2_decoder_cmd *cmd) +{ + struct aml_vcodec_ctx *ctx = fh_to_ctx(priv); + struct vb2_queue *src_vq, *dst_vq; + int ret; + + ret = vidioc_try_decoder_cmd(file, priv, cmd); + if (ret) + return ret; + + aml_v4l2_debug(3, "[%d] %s() [%d], cmd: %u", + ctx->id, __func__, __LINE__, cmd->cmd); + dst_vq = v4l2_m2m_get_vq(ctx->m2m_ctx, + V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); + switch (cmd->cmd) { + case V4L2_DEC_CMD_STOP: + + if (ctx->state != AML_STATE_ACTIVE) + return 0; + + src_vq = v4l2_m2m_get_vq(ctx->m2m_ctx, + V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); + if (!vb2_is_streaming(src_vq)) { + pr_err("[%d] Output stream is off. No need to flush.\n", ctx->id); + return 0; + } + + if (!vb2_is_streaming(dst_vq)) { + pr_err("[%d] Capture stream is off. No need to flush.\n", ctx->id); + return 0; + } + + /* flush src */ + v4l2_m2m_buf_queue(ctx->m2m_ctx, &ctx->empty_flush_buf->vb); + v4l2_m2m_try_schedule(ctx->m2m_ctx);//pay attention + + break; + + case V4L2_DEC_CMD_START: + aml_v4l2_debug(4, "[%d] CMD V4L2_DEC_CMD_START ", ctx->id); + vb2_clear_last_buffer_dequeued(dst_vq);//pay attention + break; + + default: + return -EINVAL; + } + + return 0; +} + +static int vidioc_decoder_streamon(struct file *file, void *priv, + enum v4l2_buf_type i) +{ + struct v4l2_fh *fh = file->private_data; + struct aml_vcodec_ctx *ctx = fh_to_ctx(fh); + struct aml_vcodec_dev *dev = ctx->dev; + struct vb2_queue *q; + int ret = 0; + + ret = v4l2_m2m_ioctl_streamon(file, priv, i); + + q = v4l2_m2m_get_vq(fh->m2m_ctx, i); + + mutex_lock(&ctx->state_lock); + if (ctx->state == AML_STATE_FLUSHED) { + if (!V4L2_TYPE_IS_OUTPUT(q->type)) { + ctx->state = AML_STATE_RESET; + aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_RESET)", + ctx->id, __func__); + queue_work(dev->reset_workqueue, &ctx->reset_work); + } + } + mutex_unlock(&ctx->state_lock); + + return ret; +} + +void aml_vdec_unlock(struct aml_vcodec_ctx *ctx) +{ + mutex_unlock(&ctx->dev->dec_mutex); +} + +void aml_vdec_lock(struct aml_vcodec_ctx *ctx) +{ + mutex_lock(&ctx->dev->dec_mutex); +} + +void aml_vcodec_dec_release(struct aml_vcodec_ctx *ctx) +{ + aml_vdec_lock(ctx); + + ctx->state = AML_STATE_ABORT; + aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_ABORT)", + ctx->id, __func__); + + vdec_if_deinit(ctx); + + aml_vdec_unlock(ctx); +} + +void aml_vcodec_dec_set_default_params(struct aml_vcodec_ctx *ctx) +{ + struct aml_q_data *q_data; + + ctx->m2m_ctx->q_lock = &ctx->dev->dev_mutex; + ctx->fh.m2m_ctx = ctx->m2m_ctx; + ctx->fh.ctrl_handler = &ctx->ctrl_hdl; + INIT_WORK(&ctx->decode_work, aml_vdec_worker); + INIT_WORK(&ctx->reset_work, aml_reset_worker); + ctx->colorspace = V4L2_COLORSPACE_REC709; + ctx->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; + ctx->quantization = V4L2_QUANTIZATION_DEFAULT; + ctx->xfer_func = V4L2_XFER_FUNC_DEFAULT; + ctx->dev->dec_capability = VCODEC_CAPABILITY_4K_DISABLED;//disable 4k + + q_data = &ctx->q_data[AML_Q_DATA_SRC]; + memset(q_data, 0, sizeof(struct aml_q_data)); + q_data->visible_width = DFT_CFG_WIDTH; + q_data->visible_height = DFT_CFG_HEIGHT; + q_data->fmt = &aml_video_formats[OUT_FMT_IDX]; + q_data->field = V4L2_FIELD_NONE; + + q_data->sizeimage[0] = (1024 * 1024);//DFT_CFG_WIDTH * DFT_CFG_HEIGHT; //1m + q_data->bytesperline[0] = 0; + + q_data = &ctx->q_data[AML_Q_DATA_DST]; + memset(q_data, 0, sizeof(struct aml_q_data)); + q_data->visible_width = DFT_CFG_WIDTH; + q_data->visible_height = DFT_CFG_HEIGHT; + q_data->coded_width = DFT_CFG_WIDTH; + q_data->coded_height = DFT_CFG_HEIGHT; + q_data->fmt = &aml_video_formats[CAP_FMT_IDX]; + q_data->field = V4L2_FIELD_NONE; + + v4l_bound_align_image(&q_data->coded_width, + AML_VDEC_MIN_W, + AML_VDEC_MAX_W, 4, + &q_data->coded_height, + AML_VDEC_MIN_H, + AML_VDEC_MAX_H, 5, 6); + + q_data->sizeimage[0] = q_data->coded_width * q_data->coded_height; + q_data->bytesperline[0] = q_data->coded_width; + q_data->sizeimage[1] = q_data->sizeimage[0] / 2; + q_data->bytesperline[1] = q_data->coded_width; + + ctx->state = AML_STATE_IDLE; + aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_IDLE)", + ctx->id, __func__); +} + +static int vidioc_vdec_qbuf(struct file *file, void *priv, + struct v4l2_buffer *buf) +{ + struct aml_vcodec_ctx *ctx = fh_to_ctx(priv); + + if (ctx->state == AML_STATE_ABORT) { + aml_v4l2_err("[%d] Call on QBUF after unrecoverable error", + ctx->id); + return -EIO; + } + + return v4l2_m2m_qbuf(file, ctx->m2m_ctx, buf); +} + +static int vidioc_vdec_dqbuf(struct file *file, void *priv, + struct v4l2_buffer *buf) +{ + struct aml_vcodec_ctx *ctx = fh_to_ctx(priv); + + if (ctx->state == AML_STATE_ABORT) { + aml_v4l2_err("[%d] Call on DQBUF after unrecoverable error", + ctx->id); + return -EIO; + } + + return v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf); +} + +static int vidioc_vdec_querycap(struct file *file, void *priv, + struct v4l2_capability *cap) +{ + strlcpy(cap->driver, AML_VCODEC_DEC_NAME, sizeof(cap->driver)); + strlcpy(cap->bus_info, AML_PLATFORM_STR, sizeof(cap->bus_info)); + strlcpy(cap->card, AML_PLATFORM_STR, sizeof(cap->card)); + + return 0; +} + +static int vidioc_vdec_subscribe_evt(struct v4l2_fh *fh, + const struct v4l2_event_subscription *sub) +{ + switch (sub->type) { + case V4L2_EVENT_EOS: + return v4l2_event_subscribe(fh, sub, 2, NULL); + case V4L2_EVENT_SOURCE_CHANGE: + return v4l2_src_change_event_subscribe(fh, sub); + default: + return v4l2_ctrl_subscribe_event(fh, sub); + } +} + +static int vidioc_try_fmt(struct v4l2_format *f, struct aml_video_fmt *fmt) +{ + struct v4l2_pix_format_mplane *pix_fmt_mp = &f->fmt.pix_mp; + int i; + + pix_fmt_mp->field = V4L2_FIELD_NONE; + + if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { + pix_fmt_mp->num_planes = 1; + pix_fmt_mp->plane_fmt[0].bytesperline = 0; + } else if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { + int tmp_w, tmp_h; + + pix_fmt_mp->height = clamp(pix_fmt_mp->height, + AML_VDEC_MIN_H, + AML_VDEC_MAX_H); + pix_fmt_mp->width = clamp(pix_fmt_mp->width, + AML_VDEC_MIN_W, + AML_VDEC_MAX_W); + + /* + * Find next closer width align 64, heign align 64, size align + * 64 rectangle + * Note: This only get default value, the real HW needed value + * only available when ctx in AML_STATE_PROBE state + */ + tmp_w = pix_fmt_mp->width; + tmp_h = pix_fmt_mp->height; + v4l_bound_align_image(&pix_fmt_mp->width, + AML_VDEC_MIN_W, + AML_VDEC_MAX_W, 6, + &pix_fmt_mp->height, + AML_VDEC_MIN_H, + AML_VDEC_MAX_H, 6, 9); + + if (pix_fmt_mp->width < tmp_w && + (pix_fmt_mp->width + 64) <= AML_VDEC_MAX_W) + pix_fmt_mp->width += 64; + if (pix_fmt_mp->height < tmp_h && + (pix_fmt_mp->height + 64) <= AML_VDEC_MAX_H) + pix_fmt_mp->height += 64; + + aml_v4l2_debug(4, + "before resize width=%d, height=%d, after resize width=%d, height=%d, sizeimage=%d", + tmp_w, tmp_h, pix_fmt_mp->width, + pix_fmt_mp->height, + pix_fmt_mp->width * pix_fmt_mp->height); + + pix_fmt_mp->num_planes = fmt->num_planes; + pix_fmt_mp->plane_fmt[0].sizeimage = + pix_fmt_mp->width * pix_fmt_mp->height; + pix_fmt_mp->plane_fmt[0].bytesperline = pix_fmt_mp->width; + + if (pix_fmt_mp->num_planes == 2) { + pix_fmt_mp->plane_fmt[1].sizeimage = + (pix_fmt_mp->width * pix_fmt_mp->height) / 2; + pix_fmt_mp->plane_fmt[1].bytesperline = + pix_fmt_mp->width; + } + } + + for (i = 0; i < pix_fmt_mp->num_planes; i++) + memset(&(pix_fmt_mp->plane_fmt[i].reserved[0]), 0x0, + sizeof(pix_fmt_mp->plane_fmt[0].reserved)); + + pix_fmt_mp->flags = 0; + memset(&pix_fmt_mp->reserved, 0x0, sizeof(pix_fmt_mp->reserved)); + return 0; +} + +static int vidioc_try_fmt_vid_cap_mplane(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct aml_video_fmt *fmt; + + fmt = aml_vdec_find_format(f); + if (!fmt) { + f->fmt.pix.pixelformat = aml_video_formats[CAP_FMT_IDX].fourcc; + fmt = aml_vdec_find_format(f); + } + + return vidioc_try_fmt(f, fmt); +} + +static int vidioc_try_fmt_vid_out_mplane(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct v4l2_pix_format_mplane *pix_fmt_mp = &f->fmt.pix_mp; + struct aml_video_fmt *fmt; + + fmt = aml_vdec_find_format(f); + if (!fmt) { + f->fmt.pix.pixelformat = aml_video_formats[OUT_FMT_IDX].fourcc; + fmt = aml_vdec_find_format(f); + } + + if (pix_fmt_mp->plane_fmt[0].sizeimage == 0) { + aml_v4l2_err("sizeimage of output format must be given"); + return -EINVAL; + } + + return vidioc_try_fmt(f, fmt); +} + +static int vidioc_vdec_g_selection(struct file *file, void *priv, + struct v4l2_selection *s) +{ + struct aml_vcodec_ctx *ctx = fh_to_ctx(priv); + struct aml_q_data *q_data; + + if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + q_data = &ctx->q_data[AML_Q_DATA_DST]; + + switch (s->target) { + case V4L2_SEL_TGT_COMPOSE_DEFAULT: + s->r.left = 0; + s->r.top = 0; + s->r.width = ctx->picinfo.visible_width; + s->r.height = ctx->picinfo.visible_height; + break; + case V4L2_SEL_TGT_COMPOSE_BOUNDS: + s->r.left = 0; + s->r.top = 0; + s->r.width = ctx->picinfo.coded_width; + s->r.height = ctx->picinfo.coded_height; + break; + case V4L2_SEL_TGT_COMPOSE: + if (vdec_if_get_param(ctx, GET_PARAM_CROP_INFO, &(s->r))) { + /* set to default value if header info not ready yet*/ + s->r.left = 0; + s->r.top = 0; + s->r.width = q_data->visible_width; + s->r.height = q_data->visible_height; + } + break; + default: + return -EINVAL; + } + + if (ctx->state < AML_STATE_PROBE) { + /* set to default value if header info not ready yet*/ + s->r.left = 0; + s->r.top = 0; + s->r.width = q_data->visible_width; + s->r.height = q_data->visible_height; + return 0; + } + + return 0; +} + +static int vidioc_vdec_s_selection(struct file *file, void *priv, + struct v4l2_selection *s) +{ + struct aml_vcodec_ctx *ctx = fh_to_ctx(priv); + + if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + switch (s->target) { + case V4L2_SEL_TGT_COMPOSE: + s->r.left = 0; + s->r.top = 0; + s->r.width = ctx->picinfo.visible_width; + s->r.height = ctx->picinfo.visible_height; + break; + default: + return -EINVAL; + } + + return 0; +} + +static int vidioc_vdec_s_fmt(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct aml_vcodec_ctx *ctx = fh_to_ctx(priv); + struct v4l2_pix_format_mplane *pix_mp; + struct aml_q_data *q_data; + int ret = 0; + struct aml_video_fmt *fmt; + + aml_v4l2_debug(4, "[%d] %s()", ctx->id, __func__); + + q_data = aml_vdec_get_q_data(ctx, f->type); + if (!q_data) + return -EINVAL; + + pix_mp = &f->fmt.pix_mp; + if ((f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) && + vb2_is_busy(&ctx->m2m_ctx->out_q_ctx.q)) { + aml_v4l2_err("[%d] out_q_ctx buffers already requested", ctx->id); + } + + if ((f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) && + vb2_is_busy(&ctx->m2m_ctx->cap_q_ctx.q)) { + aml_v4l2_err("[%d] cap_q_ctx buffers already requested", ctx->id); + } + + fmt = aml_vdec_find_format(f); + if (fmt == NULL) { + if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { + f->fmt.pix.pixelformat = + aml_video_formats[OUT_FMT_IDX].fourcc; + fmt = aml_vdec_find_format(f); + } else if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { + f->fmt.pix.pixelformat = + aml_video_formats[CAP_FMT_IDX].fourcc; + fmt = aml_vdec_find_format(f); + } + } + + q_data->fmt = fmt; + vidioc_try_fmt(f, q_data->fmt); + if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { + q_data->sizeimage[0] = pix_mp->plane_fmt[0].sizeimage; + q_data->coded_width = pix_mp->width; + q_data->coded_height = pix_mp->height; + + aml_v4l2_debug(4, "[%d] %s() [%d], w: %d, h: %d, size: %d", + ctx->id, __func__, __LINE__, pix_mp->width, pix_mp->height, + pix_mp->plane_fmt[0].sizeimage); + + ctx->colorspace = f->fmt.pix_mp.colorspace; + ctx->ycbcr_enc = f->fmt.pix_mp.ycbcr_enc; + ctx->quantization = f->fmt.pix_mp.quantization; + ctx->xfer_func = f->fmt.pix_mp.xfer_func; + + mutex_lock(&ctx->state_lock); + if (ctx->state == AML_STATE_IDLE) { + ret = vdec_if_init(ctx, q_data->fmt->fourcc); + if (ret) { + aml_v4l2_err("[%d]: vdec_if_init() fail ret=%d", + ctx->id, ret); + mutex_unlock(&ctx->state_lock); + return -EINVAL; + } + ctx->state = AML_STATE_INIT; + aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_INIT)", + ctx->id, __func__); + } + mutex_unlock(&ctx->state_lock); + } + + return 0; +} + +static int vidioc_enum_framesizes(struct file *file, void *priv, + struct v4l2_frmsizeenum *fsize) +{ + int i = 0; + struct aml_vcodec_ctx *ctx = fh_to_ctx(priv); + + if (fsize->index != 0) + return -EINVAL; + + for (i = 0; i < NUM_SUPPORTED_FRAMESIZE; ++i) { + if (fsize->pixel_format != aml_vdec_framesizes[i].fourcc) + continue; + + fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE; + fsize->stepwise = aml_vdec_framesizes[i].stepwise; + if (!(ctx->dev->dec_capability & + VCODEC_CAPABILITY_4K_DISABLED)) { + aml_v4l2_debug(4, "[%d] 4K is enabled", ctx->id); + fsize->stepwise.max_width = + VCODEC_DEC_4K_CODED_WIDTH; + fsize->stepwise.max_height = + VCODEC_DEC_4K_CODED_HEIGHT; + } + aml_v4l2_debug(4, "[%d] %x, %d %d %d %d %d %d", + ctx->id, ctx->dev->dec_capability, + fsize->stepwise.min_width, + fsize->stepwise.max_width, + fsize->stepwise.step_width, + fsize->stepwise.min_height, + fsize->stepwise.max_height, + fsize->stepwise.step_height); + return 0; + } + + return -EINVAL; +} + +static int vidioc_enum_fmt(struct v4l2_fmtdesc *f, bool output_queue) +{ + struct aml_video_fmt *fmt; + int i, j = 0; + + for (i = 0; i < NUM_FORMATS; i++) { + if (output_queue && (aml_video_formats[i].type != AML_FMT_DEC)) + continue; + if (!output_queue && + (aml_video_formats[i].type != AML_FMT_FRAME)) + continue; + + if (j == f->index) + break; + ++j; + } + + if (i == NUM_FORMATS) + return -EINVAL; + + fmt = &aml_video_formats[i]; + f->pixelformat = fmt->fourcc; + + return 0; +} + +static int vidioc_vdec_enum_fmt_vid_cap_mplane(struct file *file, void *pirv, + struct v4l2_fmtdesc *f) +{ + return vidioc_enum_fmt(f, false); +} + +static int vidioc_vdec_enum_fmt_vid_out_mplane(struct file *file, void *priv, + struct v4l2_fmtdesc *f) +{ + return vidioc_enum_fmt(f, true); +} + +static int vidioc_vdec_g_fmt(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct aml_vcodec_ctx *ctx = fh_to_ctx(priv); + struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp; + struct vb2_queue *vq; + struct aml_q_data *q_data; + + vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type); + if (!vq) { + aml_v4l2_err("[%d] no vb2 queue for type=%d", ctx->id, f->type); + return -EINVAL; + } + + q_data = aml_vdec_get_q_data(ctx, f->type); + + pix_mp->field = V4L2_FIELD_NONE; + pix_mp->colorspace = ctx->colorspace; + pix_mp->ycbcr_enc = ctx->ycbcr_enc; + pix_mp->quantization = ctx->quantization; + pix_mp->xfer_func = ctx->xfer_func; + + if ((f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) && + (ctx->state >= AML_STATE_PROBE)) { + /* Until STREAMOFF is called on the CAPTURE queue + * (acknowledging the event), the driver operates as if + * the resolution hasn't changed yet. + * So we just return picinfo yet, and update picinfo in + * stop_streaming hook function + */ + /* it is used for alloc the decode buffer size. */ + q_data->sizeimage[0] = ctx->picinfo.y_len_sz; + q_data->sizeimage[1] = ctx->picinfo.c_len_sz; + + /* it is used for alloc the EGL image buffer size. */ + q_data->coded_width = ctx->picinfo.coded_width; + q_data->coded_height = ctx->picinfo.coded_height; + + q_data->bytesperline[0] = ctx->picinfo.coded_width; + q_data->bytesperline[1] = ctx->picinfo.coded_height; + + /* + * Width and height are set to the dimensions + * of the movie, the buffer is bigger and + * further processing stages should crop to this + * rectangle. + */ + pix_mp->width = q_data->coded_width; + pix_mp->height = q_data->coded_height; + + /* + * Set pixelformat to the format in which mt vcodec + * outputs the decoded frame + */ + pix_mp->num_planes = q_data->fmt->num_planes; + pix_mp->pixelformat = q_data->fmt->fourcc; + pix_mp->plane_fmt[0].bytesperline = q_data->bytesperline[0]; + pix_mp->plane_fmt[0].sizeimage = q_data->sizeimage[0]; + pix_mp->plane_fmt[1].bytesperline = q_data->bytesperline[1]; + pix_mp->plane_fmt[1].sizeimage = q_data->sizeimage[1]; + } else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { + /* + * This is run on OUTPUT + * The buffer contains compressed image + * so width and height have no meaning. + * Assign value here to pass v4l2-compliance test + */ + pix_mp->width = q_data->visible_width; + pix_mp->height = q_data->visible_height; + pix_mp->plane_fmt[0].bytesperline = q_data->bytesperline[0]; + pix_mp->plane_fmt[0].sizeimage = q_data->sizeimage[0]; + pix_mp->pixelformat = q_data->fmt->fourcc; + pix_mp->num_planes = q_data->fmt->num_planes; + } else { + pix_mp->width = q_data->coded_width; + pix_mp->height = q_data->coded_height; + pix_mp->num_planes = q_data->fmt->num_planes; + pix_mp->pixelformat = q_data->fmt->fourcc; + pix_mp->plane_fmt[0].bytesperline = q_data->bytesperline[0]; + pix_mp->plane_fmt[0].sizeimage = q_data->sizeimage[0]; + pix_mp->plane_fmt[1].bytesperline = q_data->bytesperline[1]; + pix_mp->plane_fmt[1].sizeimage = q_data->sizeimage[1]; + + aml_v4l2_debug(4, "[%d] type=%d state=%d Format information could not be read, not ready yet!", + ctx->id, f->type, ctx->state); + } + + return 0; +} + +/*int vidioc_vdec_g_ctrl(struct file *file, void *fh, + struct v4l2_control *a) +{ + struct aml_vcodec_ctx *ctx = fh_to_ctx(fh); + + if (a->id == V4L2_CID_MIN_BUFFERS_FOR_CAPTURE) + a->value = 20; + + return 0; +}*/ + +static int vb2ops_vdec_queue_setup(struct vb2_queue *vq, + unsigned int *nbuffers, + unsigned int *nplanes, + unsigned int sizes[], struct device *alloc_devs[]) +{ + struct aml_vcodec_ctx *ctx = vb2_get_drv_priv(vq); + struct aml_q_data *q_data; + unsigned int i; + + q_data = aml_vdec_get_q_data(ctx, vq->type); + + if (q_data == NULL) { + aml_v4l2_err("[%d] vq->type=%d err", ctx->id, vq->type); + return -EINVAL; + } + + if (*nplanes) { + for (i = 0; i < *nplanes; i++) { + if (sizes[i] < q_data->sizeimage[i]) + return -EINVAL; + //alloc_devs[i] = &ctx->dev->plat_dev->dev; + alloc_devs[i] = v4l_get_dev_from_codec_mm();//alloc mm from the codec mm + } + } else { + if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) + *nplanes = 2; + else + *nplanes = 1; + + for (i = 0; i < *nplanes; i++) { + sizes[i] = q_data->sizeimage[i]; + //alloc_devs[i] = &ctx->dev->plat_dev->dev; + alloc_devs[i] = v4l_get_dev_from_codec_mm();//alloc mm from the codec mm + } + } + + pr_info("[%d] type: %d, plane: %d, buf cnt: %d, size: [Y: %u, C: %u]\n", + ctx->id, vq->type, *nplanes, *nbuffers, sizes[0], sizes[1]); + + return 0; +} + +static int vb2ops_vdec_buf_prepare(struct vb2_buffer *vb) +{ + struct aml_vcodec_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); + struct aml_q_data *q_data; + int i; + + aml_v4l2_debug(4, "[%d] (%d) id=%d", + ctx->id, vb->vb2_queue->type, vb->index); + + q_data = aml_vdec_get_q_data(ctx, vb->vb2_queue->type); + + for (i = 0; i < q_data->fmt->num_planes; i++) { + if (vb2_plane_size(vb, i) < q_data->sizeimage[i]) { + aml_v4l2_err("[%d] data will not fit into plane %d (%lu < %d)", + ctx->id, i, vb2_plane_size(vb, i), + q_data->sizeimage[i]); + } + } + + return 0; +} + +static void vb2ops_vdec_buf_queue(struct vb2_buffer *vb) +{ + struct aml_vcodec_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); + struct vb2_v4l2_buffer *vb2_v4l2 = NULL; + struct aml_video_dec_buf *buf = NULL; + struct aml_vcodec_mem src_mem; + unsigned int dpb = 0; + + vb2_v4l2 = to_vb2_v4l2_buffer(vb); + buf = container_of(vb2_v4l2, struct aml_video_dec_buf, vb); + + aml_v4l2_debug(3, "[%d] %s(), vb: %p, type: %d, idx: %d, state: %d, used: %d", + ctx->id, __func__, vb, vb->vb2_queue->type, + vb->index, vb->state, buf->used); + /* + * check if this buffer is ready to be used after decode + */ + if (!V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type)) { + aml_v4l2_debug(3, "[%d] %s() [%d], y_va: %p, vf_h: %lx, state: %d", ctx->id, + __func__, __LINE__, buf->frame_buffer.base_y.va, + buf->frame_buffer.vf_handle, buf->frame_buffer.status); + + if (!buf->que_in_m2m && buf->frame_buffer.status == FB_ST_NORMAL) { + aml_v4l2_debug(3, "[%d] enque capture buf idx %d, %p\n", + ctx->id, vb->index, vb); + v4l2_m2m_buf_queue(ctx->m2m_ctx, vb2_v4l2); + buf->que_in_m2m = true; + buf->queued_in_vb2 = true; + buf->queued_in_v4l2 = true; + buf->ready_to_display = false; + + /*save capture bufs to be used for resetting config.*/ + list_add(&buf->node, &ctx->capture_list); + } else if (buf->frame_buffer.status == FB_ST_DISPLAY) { + buf->queued_in_vb2 = false; + buf->queued_in_v4l2 = true; + buf->ready_to_display = false; + + /* recycle vf */ + video_vf_put(ctx->ada_ctx->recv_name, + &buf->frame_buffer, ctx->id); + } + return; + } + + v4l2_m2m_buf_queue(ctx->m2m_ctx, to_vb2_v4l2_buffer(vb)); + + if (ctx->state != AML_STATE_INIT) { + aml_v4l2_debug(4, "[%d] already init driver %d", + ctx->id, ctx->state); + return; + } + + vb2_v4l2 = to_vb2_v4l2_buffer(vb); + buf = container_of(vb2_v4l2, struct aml_video_dec_buf, vb); + if (buf->lastframe) { + /* This shouldn't happen. Just in case. */ + aml_v4l2_err("[%d] Invalid flush buffer.", ctx->id); + v4l2_m2m_src_buf_remove(ctx->m2m_ctx); + return; + } + + src_mem.va = vb2_plane_vaddr(vb, 0); + src_mem.dma_addr = vb2_dma_contig_plane_dma_addr(vb, 0); + src_mem.size = (size_t)vb->planes[0].bytesused; + if (vdec_if_probe(ctx, &src_mem, NULL)) + return; + + if (vdec_if_get_param(ctx, GET_PARAM_PIC_INFO, &ctx->picinfo)) { + pr_err("[%d] GET_PARAM_PICTURE_INFO err\n", ctx->id); + return; + } + + if (vdec_if_get_param(ctx, GET_PARAM_DPB_SIZE, &dpb)) { + pr_err("[%d] GET_PARAM_DPB_SIZE err\n", ctx->id); + return; + } + + ctx->dpb_size = dpb; + ctx->last_decoded_picinfo = ctx->picinfo; + aml_vdec_queue_res_chg_event(ctx); + + mutex_lock(&ctx->state_lock); + if (ctx->state == AML_STATE_INIT) { + ctx->state = AML_STATE_PROBE; + aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_PROBE)", + ctx->id, __func__); + } + mutex_unlock(&ctx->state_lock); +} + +static void vb2ops_vdec_buf_finish(struct vb2_buffer *vb) +{ + struct aml_vcodec_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); + struct vb2_v4l2_buffer *vb2_v4l2 = NULL; + struct aml_video_dec_buf *buf = NULL; + bool buf_error; + + vb2_v4l2 = container_of(vb, struct vb2_v4l2_buffer, vb2_buf); + buf = container_of(vb2_v4l2, struct aml_video_dec_buf, vb); + + //mutex_lock(&ctx->lock); + if (vb->vb2_queue->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { + buf->queued_in_v4l2 = false; + buf->queued_in_vb2 = false; + } + buf_error = buf->error; + //mutex_unlock(&ctx->lock); + + if (buf_error) { + aml_v4l2_err("[%d] Unrecoverable error on buffer.", ctx->id); + ctx->state = AML_STATE_ABORT; + aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_ABORT)", + ctx->id, __func__); + } +} + +static int vb2ops_vdec_buf_init(struct vb2_buffer *vb) +{ + struct aml_vcodec_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); + struct vb2_v4l2_buffer *vb2_v4l2 = container_of(vb, + struct vb2_v4l2_buffer, vb2_buf); + struct aml_video_dec_buf *buf = container_of(vb2_v4l2, + struct aml_video_dec_buf, vb); + unsigned int size, phy_addr = 0; + char *owner = __getname(); + + aml_v4l2_debug(4, "[%d] (%d) id=%d", + ctx->id, vb->vb2_queue->type, vb->index); + + if (vb->vb2_queue->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { + buf->used = false; + buf->ready_to_display = false; + buf->queued_in_v4l2 = false; + buf->frame_buffer.status = FB_ST_NORMAL; + } else { + buf->lastframe = false; + } + + /* codec_mm buffers count */ + if (V4L2_TYPE_IS_OUTPUT(vb->type)) { + size = vb->planes[0].length; + phy_addr = vb2_dma_contig_plane_dma_addr(vb, 0); + snprintf(owner, PATH_MAX, "%s-%d", "v4l-input", ctx->id); + strncpy(buf->mem_onwer, owner, sizeof(buf->mem_onwer)); + buf->mem_onwer[sizeof(buf->mem_onwer) - 1] = '\0'; + + buf->mem[0] = v4l_reqbufs_from_codec_mm(buf->mem_onwer, + phy_addr, size, vb->index); + aml_v4l2_debug(3, "[%d] IN alloc, addr: %x, size: %u, idx: %u", + ctx->id, phy_addr, size, vb->index); + } else { + size = vb->planes[0].length; + phy_addr = vb2_dma_contig_plane_dma_addr(vb, 0); + snprintf(owner, PATH_MAX, "%s-%d", "v4l-output", ctx->id); + strncpy(buf->mem_onwer, owner, sizeof(buf->mem_onwer)); + buf->mem_onwer[sizeof(buf->mem_onwer) - 1] = '\0'; + + buf->mem[0] = v4l_reqbufs_from_codec_mm(buf->mem_onwer, + phy_addr, size, vb->index); + aml_v4l2_debug(3, "[%d] OUT Y alloc, addr: %x, size: %u, idx: %u", + ctx->id, phy_addr, size, vb->index); + + size = vb->planes[1].length; + phy_addr = vb2_dma_contig_plane_dma_addr(vb, 1); + buf->mem[1] = v4l_reqbufs_from_codec_mm(buf->mem_onwer, + phy_addr, size, vb->index); + aml_v4l2_debug(3, "[%d] OUT C alloc, addr: %x, size: %u, idx: %u", + ctx->id, phy_addr, size, vb->index); + } + + __putname(owner); + + return 0; +} + +static void codec_mm_bufs_cnt_clean(struct vb2_queue *q) +{ + struct aml_vcodec_ctx *ctx = vb2_get_drv_priv(q); + struct vb2_v4l2_buffer *vb2_v4l2 = NULL; + struct aml_video_dec_buf *buf = NULL; + int i; + + for (i = 0; i < q->num_buffers; ++i) { + vb2_v4l2 = to_vb2_v4l2_buffer(q->bufs[i]); + buf = container_of(vb2_v4l2, struct aml_video_dec_buf, vb); + if (IS_ERR_OR_NULL(buf->mem[0])) + return; + + if (V4L2_TYPE_IS_OUTPUT(q->bufs[i]->type)) { + v4l_freebufs_back_to_codec_mm(buf->mem_onwer, buf->mem[0]); + + aml_v4l2_debug(3, "[%d] IN clean, addr: %lx, size: %u, idx: %u", + ctx->id, buf->mem[0]->phy_addr, buf->mem[0]->buffer_size, i); + buf->mem[0] = NULL; + continue; + } + + v4l_freebufs_back_to_codec_mm(buf->mem_onwer, buf->mem[0]); + v4l_freebufs_back_to_codec_mm(buf->mem_onwer, buf->mem[1]); + + aml_v4l2_debug(3, "[%d] OUT Y clean, addr: %lx, size: %u, idx: %u", + ctx->id, buf->mem[0]->phy_addr, buf->mem[0]->buffer_size, i); + aml_v4l2_debug(3, "[%d] OUT C clean, addr: %lx, size: %u, idx: %u", + ctx->id, buf->mem[1]->phy_addr, buf->mem[1]->buffer_size, i); + buf->mem[0] = NULL; + buf->mem[1] = NULL; + } +} + +static int vb2ops_vdec_start_streaming(struct vb2_queue *q, unsigned int count) +{ + struct aml_vcodec_ctx *ctx = vb2_get_drv_priv(q); + + ctx->has_receive_eos = false; + v4l2_m2m_set_dst_buffered(ctx->fh.m2m_ctx, true); + + return 0; +} + +static void vb2ops_vdec_stop_streaming(struct vb2_queue *q) +{ + struct aml_video_dec_buf *buf = NULL; + struct vb2_v4l2_buffer *vb2_v4l2 = NULL; + struct aml_vcodec_ctx *ctx = vb2_get_drv_priv(q); + int i; + + aml_v4l2_debug(3, "[%d] (%d) state=(%x) frame_cnt=%d", + ctx->id, q->type, ctx->state, ctx->decoded_frame_cnt); + + codec_mm_bufs_cnt_clean(q); + + if (V4L2_TYPE_IS_OUTPUT(q->type)) { + while (v4l2_m2m_src_buf_remove(ctx->m2m_ctx)); + return; + } + + while (v4l2_m2m_dst_buf_remove(ctx->m2m_ctx)); + + for (i = 0; i < q->num_buffers; ++i) { + if (q->bufs[i]->state == VB2_BUF_STATE_ACTIVE) { + q->bufs[i]->state = VB2_BUF_STATE_DEQUEUED; + atomic_dec(&q->owned_by_drv_count); + } + vb2_v4l2 = to_vb2_v4l2_buffer(q->bufs[i]); + buf = container_of(vb2_v4l2, struct aml_video_dec_buf, vb); + buf->frame_buffer.status = FB_ST_FREE; + } +} + +static void m2mops_vdec_device_run(void *priv) +{ + struct aml_vcodec_ctx *ctx = priv; + struct aml_vcodec_dev *dev = ctx->dev; + + aml_v4l2_debug(4, "[%d] %s() [%d]", ctx->id, __func__, __LINE__); + + queue_work(dev->decode_workqueue, &ctx->decode_work); +} + +void vdec_device_vf_run(struct aml_vcodec_ctx *ctx) +{ + aml_v4l2_debug(3, "[%d] %s() [%d]", ctx->id, __func__, __LINE__); + + if (ctx->state < AML_STATE_ACTIVE || + ctx->state > AML_STATE_FLUSHED) + return; + + aml_thread_notify(ctx, AML_THREAD_CAPTURE); +} + +static int m2mops_vdec_job_ready(void *m2m_priv) +{ + struct aml_vcodec_ctx *ctx = m2m_priv; + + aml_v4l2_debug(4, "[%d] %s(), state: %d", ctx->id, + __func__, ctx->state); + + if (ctx->state < AML_STATE_PROBE || + ctx->state > AML_STATE_FLUSHED) + return 0; + + return 1; +} + +static void m2mops_vdec_job_abort(void *priv) +{ + struct aml_vcodec_ctx *ctx = priv; + + aml_v4l2_debug(3, "[%d] %s() [%d]", ctx->id, __func__, __LINE__); + + ctx->state = AML_STATE_ABORT; + aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_ABORT)", + ctx->id, __func__); + + wake_up(&ctx->m2m_ctx->finished); +} + +static int aml_vdec_g_v_ctrl(struct v4l2_ctrl *ctrl) +{ + struct aml_vcodec_ctx *ctx = ctrl_to_ctx(ctrl); + int ret = 0; + + aml_v4l2_debug(4, "%s() [%d]", __func__, __LINE__); + + switch (ctrl->id) { + case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE: + if (ctx->state >= AML_STATE_PROBE) { + ctrl->val = ctx->dpb_size; + } else { + pr_err("Seqinfo not ready.\n"); + ctrl->val = 0; + } + break; + default: + ret = -EINVAL; + } + return ret; +} + +static const struct v4l2_ctrl_ops aml_vcodec_dec_ctrl_ops = { + .g_volatile_ctrl = aml_vdec_g_v_ctrl, +}; + +int aml_vcodec_dec_ctrls_setup(struct aml_vcodec_ctx *ctx) +{ + struct v4l2_ctrl *ctrl; + + v4l2_ctrl_handler_init(&ctx->ctrl_hdl, 1); + + ctrl = v4l2_ctrl_new_std(&ctx->ctrl_hdl, + &aml_vcodec_dec_ctrl_ops, + V4L2_CID_MIN_BUFFERS_FOR_CAPTURE, + 0, 32, 1, 1); + ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE; + + if (ctx->ctrl_hdl.error) { + aml_v4l2_err("[%d] Adding control failed %d", + ctx->id, ctx->ctrl_hdl.error); + return ctx->ctrl_hdl.error; + } + + v4l2_ctrl_handler_setup(&ctx->ctrl_hdl); + return 0; +} + +static void m2mops_vdec_lock(void *m2m_priv) +{ + struct aml_vcodec_ctx *ctx = m2m_priv; + + aml_v4l2_debug(4, "[%d] %s()", ctx->id, __func__); + mutex_lock(&ctx->dev->dev_mutex); +} + +static void m2mops_vdec_unlock(void *m2m_priv) +{ + struct aml_vcodec_ctx *ctx = m2m_priv; + + aml_v4l2_debug(4, "[%d] %s()", ctx->id, __func__); + mutex_unlock(&ctx->dev->dev_mutex); +} + +const struct v4l2_m2m_ops aml_vdec_m2m_ops = { + .device_run = m2mops_vdec_device_run, + .job_ready = m2mops_vdec_job_ready, + .job_abort = m2mops_vdec_job_abort, + .lock = m2mops_vdec_lock, + .unlock = m2mops_vdec_unlock, +}; + +static const struct vb2_ops aml_vdec_vb2_ops = { + .queue_setup = vb2ops_vdec_queue_setup, + .buf_prepare = vb2ops_vdec_buf_prepare, + .buf_queue = vb2ops_vdec_buf_queue, + .wait_prepare = vb2_ops_wait_prepare, + .wait_finish = vb2_ops_wait_finish, + .buf_init = vb2ops_vdec_buf_init, + .buf_finish = vb2ops_vdec_buf_finish, + .start_streaming = vb2ops_vdec_start_streaming, + .stop_streaming = vb2ops_vdec_stop_streaming, +}; + +const struct v4l2_ioctl_ops aml_vdec_ioctl_ops = { + .vidioc_streamon = vidioc_decoder_streamon, + .vidioc_streamoff = v4l2_m2m_ioctl_streamoff, + .vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs, + .vidioc_querybuf = v4l2_m2m_ioctl_querybuf, + .vidioc_expbuf = v4l2_m2m_ioctl_expbuf,//?? + //.vidioc_g_ctrl = vidioc_vdec_g_ctrl, + + .vidioc_qbuf = vidioc_vdec_qbuf, + .vidioc_dqbuf = vidioc_vdec_dqbuf, + + .vidioc_try_fmt_vid_cap_mplane = vidioc_try_fmt_vid_cap_mplane, + .vidioc_try_fmt_vid_out_mplane = vidioc_try_fmt_vid_out_mplane, + + .vidioc_s_fmt_vid_cap_mplane = vidioc_vdec_s_fmt, + .vidioc_s_fmt_vid_out_mplane = vidioc_vdec_s_fmt, + .vidioc_g_fmt_vid_cap_mplane = vidioc_vdec_g_fmt, + .vidioc_g_fmt_vid_out_mplane = vidioc_vdec_g_fmt, + + .vidioc_create_bufs = v4l2_m2m_ioctl_create_bufs, + + .vidioc_enum_fmt_vid_cap_mplane = vidioc_vdec_enum_fmt_vid_cap_mplane, + .vidioc_enum_fmt_vid_out_mplane = vidioc_vdec_enum_fmt_vid_out_mplane, + .vidioc_enum_framesizes = vidioc_enum_framesizes, + + .vidioc_querycap = vidioc_vdec_querycap, + .vidioc_subscribe_event = vidioc_vdec_subscribe_evt, + .vidioc_unsubscribe_event = v4l2_event_unsubscribe, + .vidioc_g_selection = vidioc_vdec_g_selection, + .vidioc_s_selection = vidioc_vdec_s_selection, + + .vidioc_decoder_cmd = vidioc_decoder_cmd, + .vidioc_try_decoder_cmd = vidioc_try_decoder_cmd, +}; + +int aml_vcodec_dec_queue_init(void *priv, struct vb2_queue *src_vq, + struct vb2_queue *dst_vq) +{ + struct aml_vcodec_ctx *ctx = priv; + int ret = 0; + + aml_v4l2_debug(4, "[%d] %s()", ctx->id, __func__); + + src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; + src_vq->io_modes = VB2_DMABUF | VB2_MMAP; + src_vq->drv_priv = ctx; + src_vq->buf_struct_size = sizeof(struct aml_video_dec_buf); + src_vq->ops = &aml_vdec_vb2_ops; + src_vq->mem_ops = &vb2_dma_contig_memops; + src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; + src_vq->lock = &ctx->dev->dev_mutex; + + ret = vb2_queue_init(src_vq); + if (ret) { + aml_v4l2_err("[%d] Failed to initialize videobuf2 queue(output)", ctx->id); + return ret; + } + dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + dst_vq->io_modes = VB2_DMABUF | VB2_MMAP | VB2_USERPTR; + dst_vq->drv_priv = ctx; + dst_vq->buf_struct_size = sizeof(struct aml_video_dec_buf); + dst_vq->ops = &aml_vdec_vb2_ops; + dst_vq->mem_ops = &vb2_dma_contig_memops; + dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; + dst_vq->lock = &ctx->dev->dev_mutex; + + ret = vb2_queue_init(dst_vq); + if (ret) { + vb2_queue_release(src_vq); + aml_v4l2_err("[%d] Failed to initialize videobuf2 queue(capture)", ctx->id); + } + + return ret; +} + diff --git a/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_dec.h b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_dec.h new file mode 100644 index 000000000000..6f884c4321ed --- /dev/null +++ b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_dec.h @@ -0,0 +1,109 @@ +/* +* 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. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ +#ifndef _AML_VCODEC_DEC_H_ +#define _AML_VCODEC_DEC_H_ + +#include +#include +#include + +#define VCODEC_CAPABILITY_4K_DISABLED 0x10 +#define VCODEC_DEC_4K_CODED_WIDTH 4096U +#define VCODEC_DEC_4K_CODED_HEIGHT 2304U +#define AML_VDEC_MAX_W 2048U +#define AML_VDEC_MAX_H 1088U + +#define AML_VDEC_IRQ_STATUS_DEC_SUCCESS 0x10000 +#define V4L2_BUF_FLAG_LAST 0x00100000 + +/** + * struct vdec_fb - decoder frame buffer + * @base_y : Y plane memory info + * @base_c : C plane memory info + * @status : frame buffer status (vdec_fb_status) + */ +struct vdec_fb { + unsigned long vf_handle; + struct aml_vcodec_mem base_y; + struct aml_vcodec_mem base_c; + unsigned int status; +}; + +/** + * struct aml_video_dec_buf - Private data related to each VB2 buffer. + * @b: VB2 buffer + * @list: link list + * @used: Capture buffer contain decoded frame data and keep in + * codec data structure + * @ready_to_display: Capture buffer not display yet + * @queued_in_vb2: Capture buffer is queue in vb2 + * @queued_in_v4l2: Capture buffer is in v4l2 driver, but not in vb2 + * queue yet + * @lastframe: Intput buffer is last buffer - EOS + * @error: An unrecoverable error occurs on this buffer. + * @frame_buffer: Decode status, and buffer information of Capture buffer + * + * Note : These status information help us track and debug buffer state + */ +struct aml_video_dec_buf { + struct vb2_v4l2_buffer vb; + struct list_head list; + + struct vdec_fb frame_buffer; + struct codec_mm_s *mem[2]; + char mem_onwer[32]; + struct list_head node; + bool used; + bool ready_to_display; + bool que_in_m2m; + bool queued_in_vb2; + bool queued_in_v4l2; + bool lastframe; + bool error; +}; + +extern const struct v4l2_ioctl_ops aml_vdec_ioctl_ops; +extern const struct v4l2_m2m_ops aml_vdec_m2m_ops; + + +/* + * aml_vdec_lock/aml_vdec_unlock are for ctx instance to + * get/release lock before/after access decoder hw. + * aml_vdec_lock get decoder hw lock and set curr_ctx + * to ctx instance that get lock + */ +void aml_vdec_unlock(struct aml_vcodec_ctx *ctx); +void aml_vdec_lock(struct aml_vcodec_ctx *ctx); +int aml_vcodec_dec_queue_init(void *priv, struct vb2_queue *src_vq, + struct vb2_queue *dst_vq); +void aml_vcodec_dec_set_default_params(struct aml_vcodec_ctx *ctx); +void aml_vcodec_dec_release(struct aml_vcodec_ctx *ctx); +int aml_vcodec_dec_ctrls_setup(struct aml_vcodec_ctx *ctx); + +void vdec_device_vf_run(struct aml_vcodec_ctx *ctx); + +void try_to_capture(struct aml_vcodec_ctx *ctx); +void aml_thread_notify(struct aml_vcodec_ctx *ctx, + enum aml_thread_type type); +int aml_thread_start(struct aml_vcodec_ctx *ctx, aml_thread_func func, + enum aml_thread_type type, const char *thread_name); +void aml_thread_stop(struct aml_vcodec_ctx *ctx); + +#endif /* _AML_VCODEC_DEC_H_ */ diff --git a/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_dec_drv.c b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_dec_drv.c new file mode 100644 index 000000000000..53b25c492605 --- /dev/null +++ b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_dec_drv.c @@ -0,0 +1,345 @@ +/* +* 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. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ + +#define DEBUG +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "aml_vcodec_drv.h" +#include "aml_vcodec_dec.h" +#include "aml_vcodec_dec_pm.h" +//#include "aml_vcodec_intr.h" +#include "aml_vcodec_util.h" +#include "aml_vcodec_vfm.h" + +#define VDEC_HW_ACTIVE 0x10 +#define VDEC_IRQ_CFG 0x11 +#define VDEC_IRQ_CLR 0x10 +#define VDEC_IRQ_CFG_REG 0xa4 + +module_param(aml_v4l2_dbg_level, int, 0644); +module_param(aml_vcodec_dbg, bool, 0644); + +static int fops_vcodec_open(struct file *file) +{ + struct aml_vcodec_dev *dev = video_drvdata(file); + struct aml_vcodec_ctx *ctx = NULL; + struct aml_video_dec_buf *aml_buf = NULL; + int ret = 0; + struct vb2_queue *src_vq; + + ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); + if (!ctx) + return -ENOMEM; + aml_buf = kzalloc(sizeof(*aml_buf), GFP_KERNEL); + if (!aml_buf) { + kfree(ctx); + return -ENOMEM; + } + + mutex_lock(&dev->dev_mutex); + ctx->empty_flush_buf = aml_buf; + ctx->id = dev->id_counter++; + v4l2_fh_init(&ctx->fh, video_devdata(file)); + file->private_data = &ctx->fh; + v4l2_fh_add(&ctx->fh); + INIT_LIST_HEAD(&ctx->list); + INIT_LIST_HEAD(&ctx->capture_list); + INIT_LIST_HEAD(&ctx->vdec_thread_list); + dev->filp = file; + ctx->dev = dev; + init_waitqueue_head(&ctx->queue); + mutex_init(&ctx->state_lock); + mutex_init(&ctx->lock); + init_waitqueue_head(&ctx->wq); + + ctx->type = AML_INST_DECODER; + ret = aml_vcodec_dec_ctrls_setup(ctx); + if (ret) { + aml_v4l2_err("Failed to setup vcodec controls"); + goto err_ctrls_setup; + } + ctx->m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev_dec, ctx, + &aml_vcodec_dec_queue_init); + if (IS_ERR((__force void *)ctx->m2m_ctx)) { + ret = PTR_ERR((__force void *)ctx->m2m_ctx); + aml_v4l2_err("Failed to v4l2_m2m_ctx_init() (%d)", ret); + goto err_m2m_ctx_init; + } + src_vq = v4l2_m2m_get_vq(ctx->m2m_ctx, + V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); + ctx->empty_flush_buf->vb.vb2_buf.vb2_queue = src_vq; + ctx->empty_flush_buf->lastframe = true; + aml_vcodec_dec_set_default_params(ctx); + + ret = aml_thread_start(ctx, try_to_capture, AML_THREAD_CAPTURE, "cap"); + if (ret) { + aml_v4l2_err("Failed to creat capture thread."); + goto err_creat_thread; + } + + list_add(&ctx->list, &dev->ctx_list); + + mutex_unlock(&dev->dev_mutex); + pr_info("[%d] %s decoder\n", ctx->id, dev_name(&dev->plat_dev->dev)); + + return ret; + + /* Deinit when failure occurred */ +err_creat_thread: + v4l2_m2m_ctx_release(ctx->m2m_ctx); +err_m2m_ctx_init: + v4l2_ctrl_handler_free(&ctx->ctrl_hdl); +err_ctrls_setup: + v4l2_fh_del(&ctx->fh); + v4l2_fh_exit(&ctx->fh); + kfree(ctx->empty_flush_buf); + kfree(ctx); + mutex_unlock(&dev->dev_mutex); + + return ret; +} + +static int fops_vcodec_release(struct file *file) +{ + struct aml_vcodec_dev *dev = video_drvdata(file); + struct aml_vcodec_ctx *ctx = fh_to_ctx(file->private_data); + + pr_info("[%d] release decoder\n", ctx->id); + mutex_lock(&dev->dev_mutex); + + /* + * Call v4l2_m2m_ctx_release before aml_vcodec_dec_release. First, it + * makes sure the worker thread is not running after vdec_if_deinit. + * Second, the decoder will be flushed and all the buffers will be + * returned in stop_streaming. + */ + aml_vcodec_dec_release(ctx); + v4l2_m2m_ctx_release(ctx->m2m_ctx); + + v4l2_fh_del(&ctx->fh); + v4l2_fh_exit(&ctx->fh); + v4l2_ctrl_handler_free(&ctx->ctrl_hdl); + + aml_thread_stop(ctx); + + list_del_init(&ctx->list); + kfree(ctx->empty_flush_buf); + kfree(ctx); + mutex_unlock(&dev->dev_mutex); + return 0; +} + +static const struct v4l2_file_operations aml_vcodec_fops = { + .owner = THIS_MODULE, + .open = fops_vcodec_open, + .release = fops_vcodec_release, + .poll = v4l2_m2m_fop_poll, + .unlocked_ioctl = video_ioctl2, + .mmap = v4l2_m2m_fop_mmap, +}; + +static int aml_vcodec_probe(struct platform_device *pdev) +{ + struct aml_vcodec_dev *dev; + struct video_device *vfd_dec; + int ret = 0; + + dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL); + if (!dev) + return -ENOMEM; + + INIT_LIST_HEAD(&dev->ctx_list); + dev->plat_dev = pdev; + + mutex_init(&dev->dec_mutex); + mutex_init(&dev->dev_mutex); + spin_lock_init(&dev->irqlock); + + snprintf(dev->v4l2_dev.name, sizeof(dev->v4l2_dev.name), "%s", + "[/AML_V4L2_VDEC]"); + + ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev); + if (ret) { + aml_v4l2_err("v4l2_device_register err=%d", ret); + goto err_res; + } + + init_waitqueue_head(&dev->queue); + + vfd_dec = video_device_alloc(); + if (!vfd_dec) { + aml_v4l2_err("Failed to allocate video device"); + ret = -ENOMEM; + goto err_dec_alloc; + } + + vfd_dec->fops = &aml_vcodec_fops; + vfd_dec->ioctl_ops = &aml_vdec_ioctl_ops; + vfd_dec->release = video_device_release; + vfd_dec->lock = &dev->dev_mutex; + vfd_dec->v4l2_dev = &dev->v4l2_dev; + vfd_dec->vfl_dir = VFL_DIR_M2M; + vfd_dec->device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | + V4L2_CAP_STREAMING; + + snprintf(vfd_dec->name, sizeof(vfd_dec->name), "%s", + AML_VCODEC_DEC_NAME); + video_set_drvdata(vfd_dec, dev); + dev->vfd_dec = vfd_dec; + platform_set_drvdata(pdev, dev); + + dev->m2m_dev_dec = v4l2_m2m_init(&aml_vdec_m2m_ops); + if (IS_ERR((__force void *)dev->m2m_dev_dec)) { + aml_v4l2_err("Failed to init mem2mem dec device"); + ret = PTR_ERR((__force void *)dev->m2m_dev_dec); + goto err_dec_mem_init; + } + + dev->decode_workqueue = + alloc_ordered_workqueue(AML_VCODEC_DEC_NAME, + WQ_MEM_RECLAIM | WQ_FREEZABLE); + if (!dev->decode_workqueue) { + aml_v4l2_err("Failed to create decode workqueue"); + ret = -EINVAL; + goto err_event_workq; + } + + dev->reset_workqueue = + alloc_ordered_workqueue("aml-vcodec-reset", + WQ_MEM_RECLAIM | WQ_FREEZABLE); + if (!dev->reset_workqueue) { + aml_v4l2_err("Failed to create decode workqueue"); + ret = -EINVAL; + destroy_workqueue(dev->decode_workqueue); + goto err_event_workq; + } + + //dev_set_name(&vdev->dev, "%s%d", name_base, vdev->num); + + ret = video_register_device(vfd_dec, VFL_TYPE_GRABBER, 26); + if (ret) { + pr_err("Failed to register video device\n"); + goto err_dec_reg; + } + + pr_info("decoder registered as /dev/video%d\n", vfd_dec->num); + + return 0; + +err_dec_reg: + destroy_workqueue(dev->reset_workqueue); + destroy_workqueue(dev->decode_workqueue); +err_event_workq: + v4l2_m2m_release(dev->m2m_dev_dec); +err_dec_mem_init: + video_unregister_device(vfd_dec); +err_dec_alloc: + v4l2_device_unregister(&dev->v4l2_dev); +err_res: + + return ret; +} + +static const struct of_device_id aml_vcodec_match[] = { + {.compatible = "amlogic, vcodec-dec",}, + {}, +}; + +MODULE_DEVICE_TABLE(of, aml_vcodec_match); + +static int aml_vcodec_dec_remove(struct platform_device *pdev) +{ + struct aml_vcodec_dev *dev = platform_get_drvdata(pdev); + + flush_workqueue(dev->reset_workqueue); + destroy_workqueue(dev->reset_workqueue); + + flush_workqueue(dev->decode_workqueue); + destroy_workqueue(dev->decode_workqueue); + + if (dev->m2m_dev_dec) + v4l2_m2m_release(dev->m2m_dev_dec); + + if (dev->vfd_dec) + video_unregister_device(dev->vfd_dec); + + v4l2_device_unregister(&dev->v4l2_dev); + + return 0; +} + +/*static void aml_vcodec_dev_release(struct device *dev) +{ +}*/ + +static struct platform_driver aml_vcodec_dec_driver = { + .probe = aml_vcodec_probe, + .remove = aml_vcodec_dec_remove, + .driver = { + .name = AML_VCODEC_DEC_NAME, + .of_match_table = aml_vcodec_match, + }, +}; + +/* +static struct platform_device aml_vcodec_dec_device = { + .name = AML_VCODEC_DEC_NAME, + .dev.release = aml_vcodec_dev_release, +};*/ + +module_platform_driver(aml_vcodec_dec_driver); + +/* +static int __init amvdec_ports_init(void) +{ + int ret; + + ret = platform_device_register(&aml_vcodec_dec_device); + if (ret) + return ret; + + ret = platform_driver_register(&aml_vcodec_dec_driver); + if (ret) + platform_device_unregister(&aml_vcodec_dec_device); + + return ret; +} + +static void __exit amvdec_ports_exit(void) +{ + platform_driver_unregister(&aml_vcodec_dec_driver); + platform_device_unregister(&aml_vcodec_dec_device); +} + +module_init(amvdec_ports_init); +module_exit(amvdec_ports_exit); +*/ + +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("AML video codec V4L2 decoder driver"); diff --git a/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_dec_pm.c b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_dec_pm.c new file mode 100644 index 000000000000..c801e871b397 --- /dev/null +++ b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_dec_pm.c @@ -0,0 +1,206 @@ +/* +* 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. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ +#include +#include +#include +#include + +#include "aml_vcodec_dec_pm.h" +#include "aml_vcodec_util.h" +//#include "aml_vpu.h" + +int aml_vcodec_init_dec_pm(struct aml_vcodec_dev *amldev) +{ + struct device_node *node; + struct platform_device *pdev; + struct aml_vcodec_pm *pm; + int ret = 0; + + pdev = amldev->plat_dev; + pm = &amldev->pm; + pm->amldev = amldev; + node = of_parse_phandle(pdev->dev.of_node, "larb", 0); + if (!node) { + aml_v4l2_err("of_parse_phandle larb fail!"); + return -1; + } + + pdev = of_find_device_by_node(node); + if (WARN_ON(!pdev)) { + of_node_put(node); + return -1; + } + pm->larbvdec = &pdev->dev; + pdev = amldev->plat_dev; + pm->dev = &pdev->dev; + + pm->vcodecpll = devm_clk_get(&pdev->dev, "vcodecpll"); + if (IS_ERR(pm->vcodecpll)) { + aml_v4l2_err("devm_clk_get vcodecpll fail"); + ret = PTR_ERR(pm->vcodecpll); + } + + pm->univpll_d2 = devm_clk_get(&pdev->dev, "univpll_d2"); + if (IS_ERR(pm->univpll_d2)) { + aml_v4l2_err("devm_clk_get univpll_d2 fail"); + ret = PTR_ERR(pm->univpll_d2); + } + + pm->clk_cci400_sel = devm_clk_get(&pdev->dev, "clk_cci400_sel"); + if (IS_ERR(pm->clk_cci400_sel)) { + aml_v4l2_err("devm_clk_get clk_cci400_sel fail"); + ret = PTR_ERR(pm->clk_cci400_sel); + } + + pm->vdec_sel = devm_clk_get(&pdev->dev, "vdec_sel"); + if (IS_ERR(pm->vdec_sel)) { + aml_v4l2_err("devm_clk_get vdec_sel fail"); + ret = PTR_ERR(pm->vdec_sel); + } + + pm->vdecpll = devm_clk_get(&pdev->dev, "vdecpll"); + if (IS_ERR(pm->vdecpll)) { + aml_v4l2_err("devm_clk_get vdecpll fail"); + ret = PTR_ERR(pm->vdecpll); + } + + pm->vencpll = devm_clk_get(&pdev->dev, "vencpll"); + if (IS_ERR(pm->vencpll)) { + aml_v4l2_err("devm_clk_get vencpll fail"); + ret = PTR_ERR(pm->vencpll); + } + + pm->venc_lt_sel = devm_clk_get(&pdev->dev, "venc_lt_sel"); + if (IS_ERR(pm->venc_lt_sel)) { + aml_v4l2_err("devm_clk_get venc_lt_sel fail"); + ret = PTR_ERR(pm->venc_lt_sel); + } + + pm->vdec_bus_clk_src = devm_clk_get(&pdev->dev, "vdec_bus_clk_src"); + if (IS_ERR(pm->vdec_bus_clk_src)) { + aml_v4l2_err("devm_clk_get vdec_bus_clk_src"); + ret = PTR_ERR(pm->vdec_bus_clk_src); + } + + pm_runtime_enable(&pdev->dev); + + return ret; +} + +void aml_vcodec_release_dec_pm(struct aml_vcodec_dev *dev) +{ + pm_runtime_disable(dev->pm.dev); +} + +void aml_vcodec_dec_pw_on(struct aml_vcodec_pm *pm) +{ + int ret; + + ret = pm_runtime_get_sync(pm->dev); + if (ret) + aml_v4l2_err("pm_runtime_get_sync fail %d", ret); +} + +void aml_vcodec_dec_pw_off(struct aml_vcodec_pm *pm) +{ + int ret; + + ret = pm_runtime_put_sync(pm->dev); + if (ret) + aml_v4l2_err("pm_runtime_put_sync fail %d", ret); +} + +void aml_vcodec_dec_clock_on(struct aml_vcodec_pm *pm) +{ + int ret; + + ret = clk_set_rate(pm->vcodecpll, 1482 * 1000000); + if (ret) + aml_v4l2_err("clk_set_rate vcodecpll fail %d", ret); + + ret = clk_set_rate(pm->vencpll, 800 * 1000000); + if (ret) + aml_v4l2_err("clk_set_rate vencpll fail %d", ret); + + ret = clk_prepare_enable(pm->vcodecpll); + if (ret) + aml_v4l2_err("clk_prepare_enable vcodecpll fail %d", ret); + + ret = clk_prepare_enable(pm->vencpll); + if (ret) + aml_v4l2_err("clk_prepare_enable vencpll fail %d", ret); + + ret = clk_prepare_enable(pm->vdec_bus_clk_src); + if (ret) + aml_v4l2_err("clk_prepare_enable vdec_bus_clk_src fail %d", + ret); + + ret = clk_prepare_enable(pm->venc_lt_sel); + if (ret) + aml_v4l2_err("clk_prepare_enable venc_lt_sel fail %d", ret); + + ret = clk_set_parent(pm->venc_lt_sel, pm->vdec_bus_clk_src); + if (ret) + aml_v4l2_err("clk_set_parent venc_lt_sel vdec_bus_clk_src fail %d", + ret); + + ret = clk_prepare_enable(pm->univpll_d2); + if (ret) + aml_v4l2_err("clk_prepare_enable univpll_d2 fail %d", ret); + + ret = clk_prepare_enable(pm->clk_cci400_sel); + if (ret) + aml_v4l2_err("clk_prepare_enable clk_cci400_sel fail %d", ret); + + ret = clk_set_parent(pm->clk_cci400_sel, pm->univpll_d2); + if (ret) + aml_v4l2_err("clk_set_parent clk_cci400_sel univpll_d2 fail %d", + ret); + + ret = clk_prepare_enable(pm->vdecpll); + if (ret) + aml_v4l2_err("clk_prepare_enable vdecpll fail %d", ret); + + ret = clk_prepare_enable(pm->vdec_sel); + if (ret) + aml_v4l2_err("clk_prepare_enable vdec_sel fail %d", ret); + + ret = clk_set_parent(pm->vdec_sel, pm->vdecpll); + if (ret) + aml_v4l2_err("clk_set_parent vdec_sel vdecpll fail %d", ret); + + //ret = aml_smi_larb_get(pm->larbvdec); + if (ret) + aml_v4l2_err("aml_smi_larb_get larbvdec fail %d", ret); + +} + +void aml_vcodec_dec_clock_off(struct aml_vcodec_pm *pm) +{ + //aml_smi_larb_put(pm->larbvdec); + clk_disable_unprepare(pm->vdec_sel); + clk_disable_unprepare(pm->vdecpll); + clk_disable_unprepare(pm->univpll_d2); + clk_disable_unprepare(pm->clk_cci400_sel); + clk_disable_unprepare(pm->venc_lt_sel); + clk_disable_unprepare(pm->vdec_bus_clk_src); + clk_disable_unprepare(pm->vencpll); + clk_disable_unprepare(pm->vcodecpll); +} diff --git a/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_dec_pm.h b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_dec_pm.h new file mode 100644 index 000000000000..ccdf313f0ca8 --- /dev/null +++ b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_dec_pm.h @@ -0,0 +1,34 @@ +/* +* 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. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ + +#ifndef _AML_VCODEC_DEC_PM_H_ +#define _AML_VCODEC_DEC_PM_H_ + +#include "aml_vcodec_drv.h" + +int aml_vcodec_init_dec_pm(struct aml_vcodec_dev *dev); +void aml_vcodec_release_dec_pm(struct aml_vcodec_dev *dev); + +void aml_vcodec_dec_pw_on(struct aml_vcodec_pm *pm); +void aml_vcodec_dec_pw_off(struct aml_vcodec_pm *pm); +void aml_vcodec_dec_clock_on(struct aml_vcodec_pm *pm); +void aml_vcodec_dec_clock_off(struct aml_vcodec_pm *pm); + +#endif /* _AML_VCODEC_DEC_PM_H_ */ diff --git a/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_drv.h b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_drv.h new file mode 100644 index 000000000000..4b638992af93 --- /dev/null +++ b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_drv.h @@ -0,0 +1,428 @@ +/* +* 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. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ +#ifndef _AML_VCODEC_DRV_H_ +#define _AML_VCODEC_DRV_H_ + +#include +#include +#include +#include +#include +#include +#include "aml_vcodec_util.h" + +#define AML_VCODEC_DRV_NAME "aml_vcodec_drv" +#define AML_VCODEC_DEC_NAME "aml-vcodec-dec" +#define AML_VCODEC_ENC_NAME "aml-vcodec-enc" +#define AML_PLATFORM_STR "platform:amlogic" + +#define AML_VCODEC_MAX_PLANES 3 +#define AML_V4L2_BENCHMARK 0 +#define WAIT_INTR_TIMEOUT_MS 1000 + +/** + * enum aml_hw_reg_idx - AML hw register base index + */ +enum aml_hw_reg_idx { + VDEC_SYS, + VDEC_MISC, + VDEC_LD, + VDEC_TOP, + VDEC_CM, + VDEC_AD, + VDEC_AV, + VDEC_PP, + VDEC_HWD, + VDEC_HWQ, + VDEC_HWB, + VDEC_HWG, + NUM_MAX_VDEC_REG_BASE, + /* h264 encoder */ + VENC_SYS = NUM_MAX_VDEC_REG_BASE, + /* vp8 encoder */ + VENC_LT_SYS, + NUM_MAX_VCODEC_REG_BASE +}; + +/** + * enum aml_instance_type - The type of an AML Vcodec instance. + */ +enum aml_instance_type { + AML_INST_DECODER = 0, + AML_INST_ENCODER = 1, +}; + +/** + * enum aml_instance_state - The state of an AML Vcodec instance. + * @AML_STATE_IDLE - default state when instance is created + * @AML_STATE_INIT - vcodec instance is initialized + * @AML_STATE_PROBE - vdec/venc had sps/pps header parsed/encoded + * @AML_STATE_ACTIVE - vdec is ready for work. + * @AML_STATE_FLUSHING - vdec is flushing. Only used by decoder + * @AML_STATE_FLUSHED - decoder has transacted the last frame. + * @AML_STATE_RESET - decoder has be reset after flush. + * @AML_STATE_ABORT - vcodec should be aborted + */ +enum aml_instance_state { + AML_STATE_IDLE, + AML_STATE_INIT, + AML_STATE_PROBE, + AML_STATE_READY, + AML_STATE_ACTIVE, + AML_STATE_FLUSHING, + AML_STATE_FLUSHED, + AML_STATE_RESET, + AML_STATE_ABORT, +}; + +/** + * struct aml_encode_param - General encoding parameters type + */ +enum aml_encode_param { + AML_ENCODE_PARAM_NONE = 0, + AML_ENCODE_PARAM_BITRATE = (1 << 0), + AML_ENCODE_PARAM_FRAMERATE = (1 << 1), + AML_ENCODE_PARAM_INTRA_PERIOD = (1 << 2), + AML_ENCODE_PARAM_FORCE_INTRA = (1 << 3), + AML_ENCODE_PARAM_GOP_SIZE = (1 << 4), +}; + +enum aml_fmt_type { + AML_FMT_DEC = 0, + AML_FMT_ENC = 1, + AML_FMT_FRAME = 2, +}; + +/** + * struct aml_video_fmt - Structure used to store information about pixelformats + */ +struct aml_video_fmt { + u32 fourcc; + enum aml_fmt_type type; + u32 num_planes; +}; + +/** + * struct aml_codec_framesizes - Structure used to store information about + * framesizes + */ +struct aml_codec_framesizes { + u32 fourcc; + struct v4l2_frmsize_stepwise stepwise; +}; + +/** + * struct aml_q_type - Type of queue + */ +enum aml_q_type { + AML_Q_DATA_SRC = 0, + AML_Q_DATA_DST = 1, +}; + +/** + * struct aml_q_data - Structure used to store information about queue + */ +struct aml_q_data { + unsigned int visible_width; + unsigned int visible_height; + unsigned int coded_width; + unsigned int coded_height; + enum v4l2_field field; + unsigned int bytesperline[AML_VCODEC_MAX_PLANES]; + unsigned int sizeimage[AML_VCODEC_MAX_PLANES]; + struct aml_video_fmt *fmt; +}; + +/** + * struct aml_enc_params - General encoding parameters + * @bitrate: target bitrate in bits per second + * @num_b_frame: number of b frames between p-frame + * @rc_frame: frame based rate control + * @rc_mb: macroblock based rate control + * @seq_hdr_mode: H.264 sequence header is encoded separately or joined + * with the first frame + * @intra_period: I frame period + * @gop_size: group of picture size, it's used as the intra frame period + * @framerate_num: frame rate numerator. ex: framerate_num=30 and + * framerate_denom=1 menas FPS is 30 + * @framerate_denom: frame rate denominator. ex: framerate_num=30 and + * framerate_denom=1 menas FPS is 30 + * @h264_max_qp: Max value for H.264 quantization parameter + * @h264_profile: V4L2 defined H.264 profile + * @h264_level: V4L2 defined H.264 level + * @force_intra: force/insert intra frame + */ +struct aml_enc_params { + unsigned int bitrate; + unsigned int num_b_frame; + unsigned int rc_frame; + unsigned int rc_mb; + unsigned int seq_hdr_mode; + unsigned int intra_period; + unsigned int gop_size; + unsigned int framerate_num; + unsigned int framerate_denom; + unsigned int h264_max_qp; + unsigned int h264_profile; + unsigned int h264_level; + unsigned int force_intra; +}; + +/** + * struct aml_vcodec_pm - Power management data structure + */ +struct aml_vcodec_pm { + struct clk *vdec_bus_clk_src; + struct clk *vencpll; + + struct clk *vcodecpll; + struct clk *univpll_d2; + struct clk *clk_cci400_sel; + struct clk *vdecpll; + struct clk *vdec_sel; + struct clk *vencpll_d2; + struct clk *venc_sel; + struct clk *univpll1_d2; + struct clk *venc_lt_sel; + struct device *larbvdec; + struct device *larbvenc; + struct device *larbvenclt; + struct device *dev; + struct aml_vcodec_dev *amldev; +}; + +/** + * struct vdec_pic_info - picture size information + * @visible_width: picture width + * @visible_height: picture height + * @coded_width: picture buffer width (64 aligned up from pic_w) + * @coded_height: picture buffer heiht (64 aligned up from pic_h) + * @y_bs_sz: Y bitstream size + * @c_bs_sz: CbCr bitstream size + * @y_len_sz: additional size required to store decompress information for y + * plane + * @c_len_sz: additional size required to store decompress information for cbcr + * plane + * E.g. suppose picture size is 176x144, + * buffer size will be aligned to 176x160. + */ +struct vdec_pic_info { + unsigned int visible_width; + unsigned int visible_height; + unsigned int coded_width; + unsigned int coded_height; + unsigned int y_bs_sz; + unsigned int c_bs_sz; + unsigned int y_len_sz; + unsigned int c_len_sz; +}; + +enum aml_thread_type { + AML_THREAD_OUTPUT, + AML_THREAD_CAPTURE, +}; + +typedef void (*aml_thread_func)(struct aml_vcodec_ctx *ctx); + +struct aml_vdec_thread { + struct list_head node; + spinlock_t lock; + struct semaphore sem; + struct task_struct *task; + enum aml_thread_type type; + void *priv; + int stop; + + aml_thread_func func; +}; + +/** + * struct aml_vcodec_ctx - Context (instance) private data. + * + * @type: type of the instance - decoder or encoder + * @dev: pointer to the aml_vcodec_dev of the device + * @list: link to ctx_list of aml_vcodec_dev + * @fh: struct v4l2_fh + * @m2m_ctx: pointer to the v4l2_m2m_ctx of the context + * @q_data: store information of input and output queue + * of the context + * @id: index of the context that this structure describes + * @state: state of the context + * @param_change: indicate encode parameter type + * @enc_params: encoding parameters + * @dec_if: hooked decoder driver interface + * @enc_if: hoooked encoder driver interface + * @drv_handle: driver handle for specific decode/encode instance + * + * @picinfo: store picture info after header parsing + * @dpb_size: store dpb count after header parsing + * @int_cond: variable used by the waitqueue + * @int_type: type of the last interrupt + * @queue: waitqueue that can be used to wait for this context to + * finish + * @irq_status: irq status + * + * @ctrl_hdl: handler for v4l2 framework + * @decode_work: worker for the decoding + * @encode_work: worker for the encoding + * @last_decoded_picinfo: pic information get from latest decode + * @empty_flush_buf: a fake size-0 capture buffer that indicates flush + * + * @colorspace: enum v4l2_colorspace; supplemental to pixelformat + * @ycbcr_enc: enum v4l2_ycbcr_encoding, Y'CbCr encoding + * @quantization: enum v4l2_quantization, colorspace quantization + * @xfer_func: enum v4l2_xfer_func, colorspace transfer function + * @lock: protect variables accessed by V4L2 threads and worker thread such as + * aml_video_dec_buf. + */ +struct aml_vcodec_ctx { + enum aml_instance_type type; + struct aml_vcodec_dev *dev; + struct list_head list; + + struct v4l2_fh fh; + struct v4l2_m2m_ctx *m2m_ctx; + struct aml_vdec_adapt *ada_ctx; + struct aml_q_data q_data[2]; + int id; + struct mutex state_lock; + enum aml_instance_state state; + enum aml_encode_param param_change; + struct aml_enc_params enc_params; + + const struct vdec_common_if *dec_if; + const struct venc_common_if *enc_if; + unsigned long drv_handle; + + struct vdec_pic_info picinfo; + int dpb_size; + + int int_cond; + int int_type; + wait_queue_head_t queue; + unsigned int irq_status; + + struct v4l2_ctrl_handler ctrl_hdl; + struct work_struct decode_work; + struct work_struct encode_work; + struct work_struct reset_work; + struct vdec_pic_info last_decoded_picinfo; + struct aml_video_dec_buf *empty_flush_buf; + + enum v4l2_colorspace colorspace; + enum v4l2_ycbcr_encoding ycbcr_enc; + enum v4l2_quantization quantization; + enum v4l2_xfer_func xfer_func; + + int decoded_frame_cnt; + struct mutex lock; + wait_queue_head_t wq; + bool has_receive_eos; + struct list_head capture_list; + struct list_head vdec_thread_list; +}; + +/** + * struct aml_vcodec_dev - driver data + * @v4l2_dev: V4L2 device to register video devices for. + * @vfd_dec: Video device for decoder + * @vfd_enc: Video device for encoder. + * + * @m2m_dev_dec: m2m device for decoder + * @m2m_dev_enc: m2m device for encoder. + * @plat_dev: platform device + * @vpu_plat_dev: aml vpu platform device + * @alloc_ctx: VB2 allocator context + * (for allocations without kernel mapping). + * @ctx_list: list of struct aml_vcodec_ctx + * @irqlock: protect data access by irq handler and work thread + * @curr_ctx: The context that is waiting for codec hardware + * + * @reg_base: Mapped address of AML Vcodec registers. + * + * @id_counter: used to identify current opened instance + * + * @encode_workqueue: encode work queue + * + * @int_cond: used to identify interrupt condition happen + * @int_type: used to identify what kind of interrupt condition happen + * @dev_mutex: video_device lock + * @queue: waitqueue for waiting for completion of device commands + * + * @dec_irq: decoder irq resource + * @enc_irq: h264 encoder irq resource + * @enc_lt_irq: vp8 encoder irq resource + * + * @dec_mutex: decoder hardware lock + * @enc_mutex: encoder hardware lock. + * + * @pm: power management control + * @dec_capability: used to identify decode capability, ex: 4k + * @enc_capability: used to identify encode capability + */ +struct aml_vcodec_dev { + struct v4l2_device v4l2_dev; + struct video_device *vfd_dec; + struct video_device *vfd_enc; + struct file *filp; + + struct v4l2_m2m_dev *m2m_dev_dec; + struct v4l2_m2m_dev *m2m_dev_enc; + struct platform_device *plat_dev; + struct platform_device *vpu_plat_dev;//?? + struct vb2_alloc_ctx *alloc_ctx;//?? + struct list_head ctx_list; + spinlock_t irqlock; + struct aml_vcodec_ctx *curr_ctx; + void __iomem *reg_base[NUM_MAX_VCODEC_REG_BASE]; + + unsigned long id_counter; + + struct workqueue_struct *decode_workqueue; + struct workqueue_struct *encode_workqueue; + struct workqueue_struct *reset_workqueue; + int int_cond; + int int_type; + struct mutex dev_mutex; + wait_queue_head_t queue; + + int dec_irq; + int enc_irq; + int enc_lt_irq; + + struct mutex dec_mutex; + struct mutex enc_mutex; + + struct aml_vcodec_pm pm; + unsigned int dec_capability; + unsigned int enc_capability; +}; + +static inline struct aml_vcodec_ctx *fh_to_ctx(struct v4l2_fh *fh) +{ + return container_of(fh, struct aml_vcodec_ctx, fh); +} + +static inline struct aml_vcodec_ctx *ctrl_to_ctx(struct v4l2_ctrl *ctrl) +{ + return container_of(ctrl->handler, struct aml_vcodec_ctx, ctrl_hdl); +} + +#endif /* _AML_VCODEC_DRV_H_ */ diff --git a/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_util.c b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_util.c new file mode 100644 index 000000000000..0026c6a2ad40 --- /dev/null +++ b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_util.c @@ -0,0 +1,122 @@ +/* +* 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. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ +#include + +#include "aml_vcodec_drv.h" +#include "aml_vcodec_util.h" +//#include "aml_vpu.h" + +/* For encoder, this will enable logs in venc/*/ +bool aml_vcodec_dbg; +EXPORT_SYMBOL(aml_vcodec_dbg); + +/* The log level of v4l2 encoder or decoder driver. + * That is, files under aml-vcodec/. + */ +int aml_v4l2_dbg_level; +EXPORT_SYMBOL(aml_v4l2_dbg_level); + +void __iomem *aml_vcodec_get_reg_addr(struct aml_vcodec_ctx *data, + unsigned int reg_idx) +{ + struct aml_vcodec_ctx *ctx = (struct aml_vcodec_ctx *)data; + + if (!data || reg_idx >= NUM_MAX_VCODEC_REG_BASE) { + aml_v4l2_err("Invalid arguments, reg_idx=%d", reg_idx); + return NULL; + } + return ctx->dev->reg_base[reg_idx]; +} +EXPORT_SYMBOL(aml_vcodec_get_reg_addr); + +int aml_vcodec_mem_alloc(struct aml_vcodec_ctx *data, + struct aml_vcodec_mem *mem) +{ + unsigned long size = mem->size; + struct aml_vcodec_ctx *ctx = (struct aml_vcodec_ctx *)data; + struct device *dev = &ctx->dev->plat_dev->dev; + + //mem->va = dma_alloc_coherent(dev, size, &mem->dma_addr, GFP_KERNEL); + mem->va = codec_mm_dma_alloc_coherent(dev_name(dev), size, + &mem->dma_addr, GFP_KERNEL, 0); + if (!mem->va) { + aml_v4l2_err("%s dma_alloc size=%ld failed!", dev_name(dev), + size); + return -ENOMEM; + } + + memset(mem->va, 0, size); + + aml_v4l2_debug(4, "[%d] - va = %p", ctx->id, mem->va); + aml_v4l2_debug(4, "[%d] - dma = 0x%lx", ctx->id, + (unsigned long)mem->dma_addr); + aml_v4l2_debug(4, "[%d] size = 0x%lx", ctx->id, size); + + return 0; +} +EXPORT_SYMBOL(aml_vcodec_mem_alloc); + +void aml_vcodec_mem_free(struct aml_vcodec_ctx *data, + struct aml_vcodec_mem *mem) +{ + unsigned long size = mem->size; + struct aml_vcodec_ctx *ctx = (struct aml_vcodec_ctx *)data; + struct device *dev = &ctx->dev->plat_dev->dev; + + if (!mem->va) { + aml_v4l2_err("%s dma_free size=%ld failed!", dev_name(dev), + size); + return; + } + + aml_v4l2_debug(4, "[%d] - va = %p", ctx->id, mem->va); + aml_v4l2_debug(4, "[%d] - dma = 0x%lx", ctx->id, + (unsigned long)mem->dma_addr); + aml_v4l2_debug(4, "[%d] size = 0x%lx", ctx->id, size); + + dma_free_coherent(dev, size, mem->va, mem->dma_addr); + mem->va = NULL; + mem->dma_addr = 0; + mem->size = 0; +} +EXPORT_SYMBOL(aml_vcodec_mem_free); + +void aml_vcodec_set_curr_ctx(struct aml_vcodec_dev *dev, + struct aml_vcodec_ctx *ctx) +{ + unsigned long flags; + + spin_lock_irqsave(&dev->irqlock, flags); + dev->curr_ctx = ctx; + spin_unlock_irqrestore(&dev->irqlock, flags); +} +EXPORT_SYMBOL(aml_vcodec_set_curr_ctx); + +struct aml_vcodec_ctx *aml_vcodec_get_curr_ctx(struct aml_vcodec_dev *dev) +{ + unsigned long flags; + struct aml_vcodec_ctx *ctx; + + spin_lock_irqsave(&dev->irqlock, flags); + ctx = dev->curr_ctx; + spin_unlock_irqrestore(&dev->irqlock, flags); + return ctx; +} +EXPORT_SYMBOL(aml_vcodec_get_curr_ctx); diff --git a/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_util.h b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_util.h new file mode 100644 index 000000000000..894cfb24b89c --- /dev/null +++ b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_util.h @@ -0,0 +1,94 @@ +/* +* 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. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ +#ifndef _AML_VCODEC_UTIL_H_ +#define _AML_VCODEC_UTIL_H_ + +#include +#include +#include + +#define DEBUG + +struct aml_vcodec_mem { + size_t size; + void *va; + dma_addr_t dma_addr; + unsigned int bytes_used; +}; + +struct aml_vcodec_ctx; +struct aml_vcodec_dev; + +extern int aml_v4l2_dbg_level; +extern bool aml_vcodec_dbg; + + +#if defined(DEBUG) + +#define aml_v4l2_debug(level, fmt, args...) \ + do { \ + if (aml_v4l2_dbg_level >= level) \ + pr_info(fmt "\n", ##args); \ + } while (0) + +#define aml_v4l2_debug_enter() aml_v4l2_debug(3, "+") +#define aml_v4l2_debug_leave() aml_v4l2_debug(3, "-") + +#define aml_vcodec_debug(h, fmt, args...) \ + do { \ + if (aml_vcodec_dbg) \ + pr_info("[%d]: %s() " fmt "\n", \ + ((struct aml_vcodec_ctx *)h->ctx)->id, \ + __func__, ##args); \ + } while (0) + +#define aml_vcodec_debug_enter(h) aml_vcodec_debug(h, "+") +#define aml_vcodec_debug_leave(h) aml_vcodec_debug(h, "-") + +#else + +#define aml_v4l2_debug(level, fmt, args...) +#define aml_v4l2_debug_enter() +#define aml_v4l2_debug_leave() + +#define aml_vcodec_debug(h, fmt, args...) +#define aml_vcodec_debug_enter(h) +#define aml_vcodec_debug_leave(h) + +#endif + +#define aml_v4l2_err(fmt, args...) \ + pr_err("[ERR]" fmt "\n", ##args) + +#define aml_vcodec_err(h, fmt, args...) \ + pr_err("[ERR][%d]" fmt "\n", \ + ((struct aml_vcodec_ctx *)h->ctx)->id, ##args) + +void __iomem *aml_vcodec_get_reg_addr(struct aml_vcodec_ctx *data, + unsigned int reg_idx); +int aml_vcodec_mem_alloc(struct aml_vcodec_ctx *data, + struct aml_vcodec_mem *mem); +void aml_vcodec_mem_free(struct aml_vcodec_ctx *data, + struct aml_vcodec_mem *mem); +void aml_vcodec_set_curr_ctx(struct aml_vcodec_dev *dev, + struct aml_vcodec_ctx *ctx); +struct aml_vcodec_ctx *aml_vcodec_get_curr_ctx(struct aml_vcodec_dev *dev); + +#endif /* _AML_VCODEC_UTIL_H_ */ diff --git a/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_vfm.c b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_vfm.c new file mode 100644 index 000000000000..c4dcf1e2741b --- /dev/null +++ b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_vfm.c @@ -0,0 +1,205 @@ +/* +* 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. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ +#include "aml_vcodec_vfm.h" +#include "aml_vcodec_vfq.h" +#include "aml_vcodec_util.h" +#include "aml_vcodec_adapt.h" +#include + +#define RECEIVER_NAME "v4l2-video" +#define PROVIDER_NAME "v4l2-video" + +static struct vframe_s *vdec_vf_peek(void *op_arg) +{ + struct vcodec_vfm_s *vfm = (struct vcodec_vfm_s *)op_arg; + + return vfq_peek(&vfm->vf_que); +} + +static struct vframe_s *vdec_vf_get(void *op_arg) +{ + struct vcodec_vfm_s *vfm = (struct vcodec_vfm_s *)op_arg; + + return vfq_pop(&vfm->vf_que); +} + +static void vdec_vf_put(struct vframe_s *vf, void *op_arg) +{ + struct vcodec_vfm_s *vfm = (struct vcodec_vfm_s *)op_arg; + + vf_put(vf, vfm->recv_name); + vf_notify_provider(vfm->recv_name, VFRAME_EVENT_RECEIVER_PUT, NULL); +} + +static int vdec_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 vdec_vf_states(struct vframe_states *states, void *op_arg) +{ + struct vcodec_vfm_s *vfm = (struct vcodec_vfm_s *)op_arg; + + states->vf_pool_size = POOL_SIZE; + states->buf_recycle_num = 0; + states->buf_free_num = POOL_SIZE - vfq_level(&vfm->vf_que); + states->buf_avail_num = vfq_level(&vfm->vf_que); + + return 0; +} + +void video_vf_put(char *receiver, struct vdec_fb *fb, int id) +{ + struct vframe_provider_s *vfp = vf_get_provider(receiver); + struct vframe_s *vf = (struct vframe_s *)fb->vf_handle; + + aml_v4l2_debug(2, "[%d] TO (%s) vf: %p, idx: %d", + id, vfp->name, vf, vf->index); + + if (vfp && vf) + vf_put(vf, receiver); +} + +static const struct vframe_operations_s vf_provider = { + .peek = vdec_vf_peek, + .get = vdec_vf_get, + .put = vdec_vf_put, + .event_cb = vdec_event_cb, + .vf_states = vdec_vf_states, +}; + +static int video_receiver_event_fun(int type, void *data, void *private_data) +{ + int ret = 0; + struct vframe_states states; + struct vcodec_vfm_s *vfm = (struct vcodec_vfm_s *)private_data; + + //aml_v4l2_debug(4, "[%d] type: %d, vfm: %p", vfm->ctx->id, type, vfm); + + switch (type) { + case VFRAME_EVENT_PROVIDER_UNREG: { + if (vf_get_receiver(vfm->prov_name)) { + aml_v4l2_debug(4, "[%d] unreg %s provider.", + vfm->ctx->id, vfm->prov_name); + vf_unreg_provider(&vfm->vf_prov); + } + + break; + } + + case VFRAME_EVENT_PROVIDER_START: { + if (vf_get_receiver(vfm->prov_name)) { + aml_v4l2_debug(4, "[%d] reg %s provider.", + vfm->ctx->id, vfm->prov_name); + vf_provider_init(&vfm->vf_prov, vfm->prov_name, + &vf_provider, vfm); + vf_reg_provider(&vfm->vf_prov); + vf_notify_receiver(vfm->prov_name, + VFRAME_EVENT_PROVIDER_START, NULL); + } + + vfq_init(&vfm->vf_que, POOL_SIZE + 1, &vfm->pool[0]); + + break; + } + + case VFRAME_EVENT_PROVIDER_QUREY_STATE: { + vdec_vf_states(&states, vfm); + if (states.buf_avail_num > 0) + ret = RECEIVER_ACTIVE; + break; + } + + case VFRAME_EVENT_PROVIDER_VFRAME_READY: { + if (vfq_level(&vfm->vf_que) > POOL_SIZE - 1) + ret = -1; + + if (!vf_peek(vfm->recv_name)) + ret = -1; + + vfm->vf = vf_get(vfm->recv_name); + if (!vfm->vf) + ret = -1; + + if (ret < 0) { + pr_err("[%d] receiver vf err.\n", vfm->ctx->id); + break; + } + + vfq_push(&vfm->vf_que, vfm->vf); + + /*vf_notify_receiver(vfm->prov_name, + VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL);*/ + + /* schedule capture work. */ + vdec_device_vf_run(vfm->ctx); + + aml_v4l2_debug(2, "[%d] FROM (%s) vf: %p, idx: %d", + vfm->ctx->id, vf_get_provider(vfm->recv_name)->name, + vfm->vf, vfm->vf->index); + break; + } + + default: + aml_v4l2_debug(4, "[%d] the vf event is %d", vfm->ctx->id, type); + } + + return ret; +} + +static const struct vframe_receiver_op_s vf_receiver = { + .event_cb = video_receiver_event_fun +}; + +struct vframe_s *peek_video_frame(struct vcodec_vfm_s *vfm) +{ + return vfq_peek(&vfm->vf_que); +} + +struct vframe_s *get_video_frame(struct vcodec_vfm_s *vfm) +{ + return vfq_pop(&vfm->vf_que); +} + +int vcodec_vfm_init(struct vcodec_vfm_s *vfm) +{ + snprintf(vfm->recv_name, VF_NAME_SIZE, "%s-%d", + RECEIVER_NAME, vfm->ctx->id); + snprintf(vfm->prov_name, VF_NAME_SIZE, "%s-%d", + PROVIDER_NAME, vfm->ctx->id); + + vfm->ada_ctx->recv_name = vfm->recv_name; + + vf_receiver_init(&vfm->vf_recv, vfm->recv_name, &vf_receiver, vfm); + vf_reg_receiver(&vfm->vf_recv); + + return 0; +} + +void vcodec_vfm_release(struct vcodec_vfm_s *vfm) +{ + vf_unreg_receiver(&vfm->vf_recv); +} + diff --git a/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_vfm.h b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_vfm.h new file mode 100644 index 000000000000..bcd88757f21f --- /dev/null +++ b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_vfm.h @@ -0,0 +1,57 @@ +/* +* 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. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ +#ifndef __AML_VCODEC_VFM_H_ +#define __AML_VCODEC_VFM_H_ + +#include "aml_vcodec_vfq.h" +#include "aml_vcodec_drv.h" +#include "aml_vcodec_dec.h" +#include +#include + +#define VF_NAME_SIZE (32) +#define POOL_SIZE (64) + +struct vcodec_vfm_s { + struct aml_vcodec_ctx *ctx; + struct aml_vdec_adapt *ada_ctx; + struct vfq_s vf_que; + struct vframe_s *vf; + struct vframe_s *pool[POOL_SIZE + 1]; + char recv_name[VF_NAME_SIZE]; + char prov_name[VF_NAME_SIZE]; + struct vframe_provider_s vf_prov; + struct vframe_receiver_s vf_recv; +}; + +int vcodec_vfm_init(struct vcodec_vfm_s *vfm); + +void vcodec_vfm_release(struct vcodec_vfm_s *vfm); + +struct vframe_s *peek_video_frame(struct vcodec_vfm_s *vfm); + +struct vframe_s *get_video_frame(struct vcodec_vfm_s *vfm); + +int get_fb_from_queue(struct aml_vcodec_ctx *ctx, struct vdec_fb **out_fb); +int put_fb_to_queue(struct aml_vcodec_ctx *ctx, struct vdec_fb *in_fb); + +void video_vf_put(char *receiver, struct vdec_fb *fb, int id); + +#endif /* __AML_VCODEC_VFM_H_ */ diff --git a/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_vfq.h b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_vfq.h new file mode 100644 index 000000000000..e19c53ca0a28 --- /dev/null +++ b/drivers/amlogic/media_modules/amvdec_ports/aml_vcodec_vfq.h @@ -0,0 +1,112 @@ +/* +* 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. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ +#ifndef __AML_VCODEC_VFQ_H_ +#define __AML_VCODEC_VFQ_H_ + +#include +#include + +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 = 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 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 /* __AML_VCODEC_VFQ_H_ */ + diff --git a/drivers/amlogic/media_modules/amvdec_ports/decoder/h264_parse.c b/drivers/amlogic/media_modules/amvdec_ports/decoder/h264_parse.c new file mode 100644 index 000000000000..1c3b73dfb7be --- /dev/null +++ b/drivers/amlogic/media_modules/amvdec_ports/decoder/h264_parse.c @@ -0,0 +1,389 @@ +/* + * drivers/amlogic/media_modules/amvdec_ports/decoder/h264_parse.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 +#include "h264_parse.h" +#include "h264_stream.h" + +static unsigned char h264_exp_golomb_bits[256] = { + 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, +}; + +static unsigned char ZZ_SCAN[16] = { + 0, 1, 4, 8, 5, 2, 3, 6, 9, 12, 13, 10, 7, 11, 14, 15 +}; + +static unsigned char ZZ_SCAN8[64] = { + 0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, + 12, 19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28, + 35, 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51, + 58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63 +}; + +unsigned int h264_u(struct h264_stream_t *s, unsigned int n) +{ + //if (n % 8 == 0) { + // return h264_stream_read_bytes(s, n / 8); + //} + return h264_stream_read_bits(s, n); +} + +unsigned int h264_ue(struct h264_stream_t *s) +{ + unsigned int bits, read; + unsigned char coded; + + bits = 0; + while (true) { + if (h264_stream_bytes_remaining(s) < 1) { + read = h264_stream_peek_bits(s, s->bit_pos) << + (8 - s->bit_pos); + break; + } + + read = h264_stream_peek_bits(s, 8); + if (bits > 16) + break; + + if (read) + break; + + h264_stream_read_bits(s, 8); + bits += 8; + } + + coded = h264_exp_golomb_bits[read]; + h264_stream_read_bits(s, coded); + bits += coded; + return h264_stream_read_bits(s, bits + 1) - 1; +} + +int h264_se(struct h264_stream_t *s) +{ + unsigned int ret; + + ret = h264_ue(s); + if (!(ret & 0x1)) { + ret >>= 1; + return (int)(-ret); + } + + return (ret + 1) >> 1; +} + +void h264_f(struct h264_stream_t *s, unsigned int n, unsigned int pattern) +{ + unsigned int val = h264_u(s, n); + + if (val != pattern) { + pr_err("fixed-pattern doesn't match. expected: %x actual: %x\n", + pattern, (unsigned int)val); + return; + } +} + +void h264_rbsp_trailing_bits(struct h264_stream_t *s) +{ + h264_f(s, 1, 1); + h264_f(s, s->bit_pos, 0); +} + +// syntax for scaling list matrix values +void Scaling_List(int *scalingList, int sizeOfScalingList, + bool *UseDefaultScalingMatrix, struct h264_stream_t *s) +{ + int j, scanj; + int delta_scale, lastScale, nextScale; + + lastScale = 8; + nextScale = 8; + + for (j = 0; j < sizeOfScalingList; j++) { + scanj = (sizeOfScalingList == 16) ? ZZ_SCAN[j] : ZZ_SCAN8[j]; + + if (nextScale != 0) { + delta_scale = h264_ue(s); + nextScale = (lastScale + delta_scale + 256) % 256; + *UseDefaultScalingMatrix = + (bool) (scanj == 0 && nextScale == 0); + } + + scalingList[scanj] = (nextScale == 0) ? lastScale : nextScale; + lastScale = scalingList[scanj]; + } +} + +void h264_sps_parse(struct h264_stream_t *s, struct h264_SPS_t *sps) +{ + unsigned int i, n_ScalingList; + + sps->profile_idc = h264_u(s, 8); + + if ((sps->profile_idc != BASELINE) && + (sps->profile_idc != MAIN) && + (sps->profile_idc != EXTENDED) && + (sps->profile_idc != FREXT_HP) && + (sps->profile_idc != FREXT_Hi10P) && + (sps->profile_idc != FREXT_Hi422) && + (sps->profile_idc != FREXT_Hi444) && + (sps->profile_idc != FREXT_CAVLC444) + && (sps->profile_idc != MVC_HIGH) + && (sps->profile_idc != STEREO_HIGH)) { + pr_err("Invalid Profile IDC (%d) encountered.\n", + sps->profile_idc); + return; + } + + sps->constrained_set0_flag = h264_u(s, 1); + sps->constrained_set1_flag = h264_u(s, 1); + sps->constrained_set2_flag = h264_u(s, 1); + h264_u(s, 5); // reserved_zero_5bits + sps->level_idc = h264_u(s, 8); + sps->seq_parameter_set_id = h264_ue(s); + + // Fidelity Range Extensions stuff + sps->chroma_format_idc = 1; + sps->bit_depth_luma_minus8 = 0; + sps->bit_depth_chroma_minus8 = 0; + sps->lossless_qpprime_flag = 0; + sps->separate_colour_plane_flag = 0; + + if ((sps->profile_idc == FREXT_HP) || + (sps->profile_idc == FREXT_Hi10P) || + (sps->profile_idc == FREXT_Hi422) || + (sps->profile_idc == FREXT_Hi444) || + (sps->profile_idc == FREXT_CAVLC444)) { + sps->chroma_format_idc = h264_ue(s); + + if (sps->chroma_format_idc == YUV444) + sps->separate_colour_plane_flag = h264_u(s, 1); + + sps->bit_depth_luma_minus8 = h264_ue(s); + sps->bit_depth_chroma_minus8 = h264_ue(s); + //checking; + if ((sps->bit_depth_luma_minus8 + 8 > sizeof(unsigned short) * 8) || + (sps->bit_depth_chroma_minus8 + 8 > sizeof(unsigned short) * 8)) { + pr_err("Source picture has higher bit depth than imgpel data type.\n"); + pr_err("Please recompile with larger data type for imgpel.\n"); + } + + sps->lossless_qpprime_flag = h264_u(s, 1); + sps->seq_scaling_matrix_present_flag = h264_u(s, 1); + if (sps->seq_scaling_matrix_present_flag) { + n_ScalingList = (sps->chroma_format_idc != YUV444) ? 8 : 12; + for (i = 0; i < n_ScalingList; i++) { + sps->seq_scaling_list_present_flag[i] = h264_u(s, 1); + if (sps->seq_scaling_list_present_flag[i]) { + if (i < 6) + Scaling_List(sps->ScalingList4x4[i], 16, + &sps->UseDefaultScalingMatrix4x4Flag[i], s); + else + Scaling_List(sps->ScalingList8x8[i - 6], + 64, &sps->UseDefaultScalingMatrix8x8Flag[i - 6], s); + } + } + } + } + + sps->log2_max_frame_num_minus4 = h264_ue(s); + sps->pic_order_cnt_type = h264_ue(s); + if (sps->pic_order_cnt_type == 0) { + sps->log2_max_pic_order_cnt_lsb_minus4 = h264_ue(s); + } else if (sps->pic_order_cnt_type == 1) { + sps->delta_pic_order_always_zero_flag = h264_se(s); + sps->offset_for_non_ref_pic = h264_se(s); + sps->offset_for_top_to_bottom_field = h264_se(s); + sps->num_ref_frames_in_poc_cycle = h264_se(s); + for (i = 0; i < sps->num_ref_frames_in_poc_cycle; ++i) + sps->offset_for_ref_frame[i] = h264_se(s); + } + + sps->num_ref_frames = h264_ue(s); + sps->gaps_in_frame_num_value_allowed_flag = h264_u(s, 1); + sps->pic_width_in_mbs_minus1 = h264_ue(s); + sps->pic_height_in_map_units_minus1 = h264_ue(s); + sps->frame_mbs_only_flag = h264_u(s, 1); + if (!sps->frame_mbs_only_flag) + sps->mb_adaptive_frame_field_flag = h264_u(s, 1); + + sps->direct_8x8_inference_flag = h264_u(s, 1); + sps->frame_cropping_flag = h264_u(s, 1); + if (sps->frame_cropping_flag) { + sps->frame_crop_left_offset = h264_ue(s); + sps->frame_crop_right_offset = h264_ue(s); + sps->frame_crop_top_offset = h264_ue(s); + sps->frame_crop_bottom_offset = h264_ue(s); + } + + sps->vui_parameters_present_flag = h264_u(s, 1); + //if (sps->vui_parameters_present_flag) { + // sps->vui_parameters = h264_vui_parameters(s); + //} + h264_rbsp_trailing_bits(s); +} + +void h264_pps_parse(struct h264_stream_t *s, struct h264_PPS_t *pps) +{ + pps->pic_parameter_set_id = h264_ue(s); + pps->seq_parameter_set_id = h264_ue(s); + pps->entropy_coding_mode_flag = h264_u(s, 1); + pps->pic_order_present_flag = h264_u(s, 1); + pps->num_slice_groups_minus1 = h264_ue(s); + if (pps->num_slice_groups_minus1 > 0) { + pps->slice_group_map_type = h264_ue(s); + if (pps->slice_group_map_type == 0) { + pps->run_length_minus1 = h264_ue(s); + } else if (pps->slice_group_map_type == 2) { + pps->top_left = h264_ue(s); + pps->bottom_right = h264_ue(s); + } else if (pps->slice_group_map_type == 3 || + pps->slice_group_map_type == 4 || + pps->slice_group_map_type == 5) { + pps->slice_group_change_direction_flag = h264_u(s, 1); + pps->slice_group_change_rate_minus1 = h264_ue(s); + } else if (pps->slice_group_map_type == 6) { + pps->pic_size_in_map_units_minus1 = h264_ue(s); + pps->slice_group_id = h264_ue(s); + } + } + pps->num_ref_idx_l0_active_minus1 = h264_ue(s); + pps->num_ref_idx_l1_active_minus1 = h264_ue(s); + pps->weighted_pred_flag = h264_u(s, 1); + pps->weighted_bipred_idc = h264_u(s, 2); + pps->pic_init_qp_minus26 = h264_se(s); + pps->pic_init_qs_minus26 = h264_se(s); + pps->chroma_qp_index_offset = h264_se(s); + pps->deblocking_filter_control_present_flag = h264_u(s, 1); + pps->constrained_intra_pred_flag = h264_u(s, 1); + pps->redundant_pic_cnt_present_flag = h264_u(s, 1); + h264_rbsp_trailing_bits(s); +} + +void h264_sps_info(struct h264_SPS_t *sps) +{ + int i; + + pr_info("sequence_parameter_set {\n"); + pr_info(" profile_idc: %d\n", sps->profile_idc); + pr_info(" constraint_set0_flag: %d\n", sps->constrained_set0_flag); + pr_info(" constraint_set1_flag: %d\n", sps->constrained_set1_flag); + pr_info(" constraint_set2_flag: %d\n", sps->constrained_set2_flag); + pr_info(" level_idc: %d\n", sps->level_idc); + pr_info(" seq_parameter_set_id: %d\n", sps->seq_parameter_set_id); + + pr_info(" log2_max_frame_num_minus4: %d\n", + sps->log2_max_frame_num_minus4); + pr_info(" pic_order_cnt_type: %d\n", sps->pic_order_cnt_type); + if (sps->pic_order_cnt_type == 0) { + pr_info(" log2_max_pic_order_cnt_lsb_minus4: %d\n", + sps->log2_max_pic_order_cnt_lsb_minus4); + } else if (sps->pic_order_cnt_type == 1) { + pr_info(" delta_pic_order_always_zero_flag: %d\n", + sps->delta_pic_order_always_zero_flag); + pr_info(" offset_for_non_ref_pic: %d\n", + sps->offset_for_non_ref_pic); + pr_info(" offset_for_top_to_bottom_field: %d\n", + sps->offset_for_top_to_bottom_field); + pr_info(" num_ref_frames_in_pic_order_cnt_cycle: %d\n", + sps->num_ref_frames_in_poc_cycle); + for (i = 0; i < sps->num_ref_frames_in_poc_cycle; ++i) { + pr_info(" offset_for_ref_frame[%d]: %d\n", i, + sps->offset_for_ref_frame[i]); + } + } + pr_info(" num_ref_frames: %d\n", sps->num_ref_frames); + pr_info(" gaps_in_frame_num_value_allowed_flag: %d\n", + sps->gaps_in_frame_num_value_allowed_flag); + pr_info(" pic_width_in_mbs_minus1: %d\n", + sps->pic_width_in_mbs_minus1); + pr_info(" pic_height_in_map_units_minus1: %d\n", + sps->pic_height_in_map_units_minus1); + pr_info(" frame_mbs_only_flag: %d\n", + sps->frame_mbs_only_flag); + pr_info(" mb_adaptive_frame_field_flag: %d\n", + sps->mb_adaptive_frame_field_flag); + pr_info(" direct_8x8_inference_flag: %d\n", + sps->direct_8x8_inference_flag); + pr_info(" frame_cropping_flag: %d\n", + sps->frame_cropping_flag); + if (sps->frame_cropping_flag) { + pr_info(" frame_crop_left_offset: %d\n", + sps->frame_crop_left_offset); + pr_info(" frame_crop_right_offset: %d\n", + sps->frame_crop_right_offset); + pr_info(" frame_crop_top_offset: %d\n", + sps->frame_crop_top_offset); + pr_info(" frame_crop_bottom_offset: %d\n", + sps->frame_crop_bottom_offset); + } + pr_info(" vui_parameters_present_flag: %d\n", + sps->vui_parameters_present_flag); + //if (sps->vui_parameters_present_flag) { + // h264_print_vui_parameters(sps->vui_parameters); + //} + + pr_info(" }\n"); +} + +void h264_pps_info(struct h264_PPS_t *pps) +{ + pr_info("pic_parameter_set {\n"); + pr_info(" pic_parameter_set_id: %d\n", + pps->pic_parameter_set_id); + pr_info(" seq_parameter_set_id: %d\n", + pps->seq_parameter_set_id); + pr_info(" entropy_coding_mode_flag: %d\n", + pps->entropy_coding_mode_flag); + pr_info(" pic_order_present_flag: %d\n", + pps->pic_order_present_flag); + pr_info(" num_slice_groups_minus1: %d\n", + pps->num_slice_groups_minus1); + // FIXME: Code for slice groups is missing here. + pr_info(" num_ref_idx_l0_active_minus1: %d\n", + pps->num_ref_idx_l0_active_minus1); + pr_info(" num_ref_idx_l1_active_minus1: %d\n", + pps->num_ref_idx_l1_active_minus1); + pr_info(" weighted_pred_flag: %d\n", pps->weighted_pred_flag); + pr_info(" weighted_bipred_idc: %d\n", pps->weighted_bipred_idc); + pr_info(" pic_init_qp_minus26: %d\n", pps->pic_init_qp_minus26); + pr_info(" pic_init_qs_minus26: %d\n", pps->pic_init_qs_minus26); + pr_info(" chroma_qp_index_offset: %d\n", + pps->chroma_qp_index_offset); + pr_info(" deblocking_filter_control_present_flag: %d\n", + pps->deblocking_filter_control_present_flag); + pr_info(" constrained_intra_pred_flag: %d\n", + pps->constrained_intra_pred_flag); + pr_info(" redundant_pic_cnt_present_flag: %d\n", + pps->redundant_pic_cnt_present_flag); + pr_info(" }\n"); +} + diff --git a/drivers/amlogic/media_modules/amvdec_ports/decoder/h264_parse.h b/drivers/amlogic/media_modules/amvdec_ports/decoder/h264_parse.h new file mode 100644 index 000000000000..e54e4d3665ff --- /dev/null +++ b/drivers/amlogic/media_modules/amvdec_ports/decoder/h264_parse.h @@ -0,0 +1,141 @@ +/* + * drivers/amlogic/media_modules/amvdec_ports/decoder/h264_parse.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 _H264_PARSE_H +#define _H264_PARSE_H + +#include "h264_stream.h" + +enum color_model { + CM_UNKNOWN = -1, + CM_YUV = 0, + CM_RGB = 1, + CM_XYZ = 2 +}; + +enum color_format { + CF_UNKNOWN = -1, //!< Unknown color format + YUV400 = 0, //!< Monochrome + YUV420 = 1, //!< 4:2:0 + YUV422 = 2, //!< 4:2:2 + YUV444 = 3 //!< 4:4:4 +}; + +enum pixel_format { + PF_UNKNOWN = -1, //!< Unknown color ordering + UYVY = 0, //!< UYVY + YUY2 = 1, //!< YUY2 + YUYV = 1, //!< YUYV + YVYU = 2, //!< YVYU + BGR = 3, //!< BGR + V210 = 4 //!< Video Clarity 422 format (10 bits) +}; + +//AVC Profile IDC definitions +enum profile_idc{ + NO_PROFILE = 0, //!< disable profile checking for experimental coding (enables FRExt, but disables MV) + FREXT_CAVLC444 = 44, //!< YUV 4:4:4/14 "CAVLC 4:4:4" + BASELINE = 66, //!< YUV 4:2:0/8 "Baseline" + MAIN = 77, //!< YUV 4:2:0/8 "Main" + EXTENDED = 88, //!< YUV 4:2:0/8 "Extended" + FREXT_HP = 100, //!< YUV 4:2:0/8 "High" + FREXT_Hi10P = 110, //!< YUV 4:2:0/10 "High 10" + FREXT_Hi422 = 122, //!< YUV 4:2:2/10 "High 4:2:2" + FREXT_Hi444 = 244, //!< YUV 4:4:4/14 "High 4:4:4" + MVC_HIGH = 118, //!< YUV 4:2:0/8 "Multiview High" + STEREO_HIGH = 128 //!< YUV 4:2:0/8 "Stereo High" +}; + +/* sequence parameter set */ +struct h264_SPS_t { + bool vailid; + unsigned int profile_idc; + bool constrained_set0_flag; + bool constrained_set1_flag; + bool constrained_set2_flag; + bool constrained_set3_flag; + unsigned int level_idc; + unsigned int seq_parameter_set_id; + unsigned int chroma_format_idc; + bool seq_scaling_matrix_present_flag; + int seq_scaling_list_present_flag[12]; + int ScalingList4x4[6][16]; + int ScalingList8x8[6][64]; + bool UseDefaultScalingMatrix4x4Flag[6]; + bool UseDefaultScalingMatrix8x8Flag[6]; + unsigned int bit_depth_luma_minus8; + unsigned int bit_depth_chroma_minus8; + unsigned int log2_max_frame_num_minus4; + unsigned int pic_order_cnt_type; + unsigned int log2_max_pic_order_cnt_lsb_minus4; + bool delta_pic_order_always_zero_flag; + int offset_for_non_ref_pic; + int offset_for_top_to_bottom_field; + unsigned int num_ref_frames_in_poc_cycle; + int offset_for_ref_frame[255]; + int num_ref_frames; + bool gaps_in_frame_num_value_allowed_flag; + unsigned int pic_width_in_mbs_minus1; + unsigned int pic_height_in_map_units_minus1; + bool frame_mbs_only_flag; + bool mb_adaptive_frame_field_flag; + bool direct_8x8_inference_flag; + bool frame_cropping_flag; + unsigned int frame_crop_left_offset; + unsigned int frame_crop_right_offset; + unsigned int frame_crop_top_offset; + unsigned int frame_crop_bottom_offset; + bool vui_parameters_present_flag; + //h264_vui_parameters_t *vui_parameters; + unsigned separate_colour_plane_flag; + int lossless_qpprime_flag; +}; + +/* pic parameter set */ +struct h264_PPS_t { + int pic_parameter_set_id; + int seq_parameter_set_id; + int entropy_coding_mode_flag; + int pic_order_present_flag; + int num_slice_groups_minus1; + int slice_group_map_type; + int run_length_minus1; + int top_left; + int bottom_right; + int slice_group_change_direction_flag; + int slice_group_change_rate_minus1; + int pic_size_in_map_units_minus1; + int slice_group_id; + int num_ref_idx_l0_active_minus1; + int num_ref_idx_l1_active_minus1; + int weighted_pred_flag; + int weighted_bipred_idc; + int pic_init_qp_minus26; + int pic_init_qs_minus26; + int chroma_qp_index_offset; + int deblocking_filter_control_present_flag; + int constrained_intra_pred_flag; + int redundant_pic_cnt_present_flag; +}; + +void h264_sps_parse(struct h264_stream_t *s, struct h264_SPS_t *sps); +void h264_pps_parse(struct h264_stream_t *s, struct h264_PPS_t *pps); + +void h264_sps_info(struct h264_SPS_t *sps); +void h264_pps_info(struct h264_PPS_t *pps); + +#endif //_H264_PARSE_H diff --git a/drivers/amlogic/media_modules/amvdec_ports/decoder/h264_stream.c b/drivers/amlogic/media_modules/amvdec_ports/decoder/h264_stream.c new file mode 100644 index 000000000000..3061568309fc --- /dev/null +++ b/drivers/amlogic/media_modules/amvdec_ports/decoder/h264_stream.c @@ -0,0 +1,111 @@ +/* + * drivers/amlogic/media_modules/amvdec_ports/decoder/h264_stream.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 +#include +#include "h264_stream.h" + +void h264_stream_set(struct h264_stream_t *s, unsigned char *data, int size) +{ + s->data = data; + s->size = size; + s->bit_pos = 7; + s->byte_pos = 0; +} + +unsigned int h264_stream_read_bits(struct h264_stream_t *s, unsigned int n) +{ + unsigned int ret = 0; + unsigned char b = 0; + int i; + + if (n == 0) + return 0; + + for (i = 0; i < n; ++i) { + if (h264_stream_bits_remaining(s) == 0) + ret <<= n - i - 1; + + b = s->data[s->byte_pos]; + if (n - i <= 32) + ret = ret << 1 | BITAT(b, s->bit_pos); + + if (s->bit_pos == 0) { + s->bit_pos = 7; + s->byte_pos++; + } else + s->bit_pos--; + } + + return ret; +} + +unsigned int h264_stream_peek_bits(struct h264_stream_t *s, unsigned int n) +{ + int prev_bit_pos = s->bit_pos; + int prev_byte_pos = s->byte_pos; + unsigned int ret = h264_stream_read_bits(s, n); + + s->bit_pos = prev_bit_pos; + s->byte_pos = prev_byte_pos; + + return ret; +} + +unsigned int h264_stream_read_bytes(struct h264_stream_t *s, unsigned int n) +{ + unsigned int ret = 0; + int i; + + if (n == 0) + return 0; + + for (i = 0; i < n; ++i) { + if (h264_stream_bytes_remaining(s) == 0) { + ret <<= (n - i - 1) * 8; + break; + } + + if (n - i <= 4) + ret = ret << 8 | s->data[s->byte_pos]; + + s->byte_pos++; + } + + return ret; +} + +unsigned int h264_stream_peek_bytes(struct h264_stream_t *s, unsigned int n) +{ + int prev_byte_pos = s->byte_pos; + unsigned int ret = h264_stream_read_bytes(s, n); + + s->byte_pos = prev_byte_pos; + + return ret; +} + +int h264_stream_bits_remaining(struct h264_stream_t *s) +{ + return (s->size - s->byte_pos) * 8 + s->bit_pos; +} + +int h264_stream_bytes_remaining(struct h264_stream_t *s) +{ + return s->size - s->byte_pos; +} + diff --git a/drivers/amlogic/media_modules/amvdec_ports/decoder/h264_stream.h b/drivers/amlogic/media_modules/amvdec_ports/decoder/h264_stream.h new file mode 100644 index 000000000000..d6d2eac88b93 --- /dev/null +++ b/drivers/amlogic/media_modules/amvdec_ports/decoder/h264_stream.h @@ -0,0 +1,39 @@ +/* + * drivers/amlogic/media_modules/amvdec_ports/decoder/h264_stream.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 _H264_STREAM_H +#define _H264_STREAM_H + +#include "utils.h" + +struct h264_stream_t { + unsigned char *data; + unsigned int size; + int bit_pos; + int byte_pos; +}; + +void h264_stream_set(struct h264_stream_t *s, unsigned char *data, int size); +unsigned int h264_stream_read_bits(struct h264_stream_t *s, unsigned int n); +unsigned int h264_stream_peek_bits(struct h264_stream_t *s, unsigned int n); +unsigned int h264_stream_read_bytes(struct h264_stream_t *s, unsigned int n); +unsigned int h264_stream_peek_bytes(struct h264_stream_t *s, unsigned int n); +int h264_stream_bits_remaining(struct h264_stream_t *s); +int h264_stream_bytes_remaining(struct h264_stream_t *s); + +#endif //_H264_STREAM_H + diff --git a/drivers/amlogic/media_modules/amvdec_ports/decoder/utils.h b/drivers/amlogic/media_modules/amvdec_ports/decoder/utils.h new file mode 100644 index 000000000000..26b155271916 --- /dev/null +++ b/drivers/amlogic/media_modules/amvdec_ports/decoder/utils.h @@ -0,0 +1,31 @@ +/* + * drivers/amlogic/media_modules/amvdec_ports/decoder/utils.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 _UTILS_H +#define _UTILS_H + +#define MAX(a, b) (((a) > (b)) ? (a) : (b)) +#define MIN(a, b) (((a) < (b)) ? (a) : (b)) +#define CLAMP(x, low, high) \ + (((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x))) +#define BITAT(x, n) ((x & (1 << n)) == (1 << n)) + +typedef unsigned char uint8_t; +typedef int int32_t; +typedef unsigned int uint32_t; + +#endif //_UTILS_H diff --git a/drivers/amlogic/media_modules/amvdec_ports/decoder/vdec_h264_if.c b/drivers/amlogic/media_modules/amvdec_ports/decoder/vdec_h264_if.c new file mode 100644 index 000000000000..0790ea955c6e --- /dev/null +++ b/drivers/amlogic/media_modules/amvdec_ports/decoder/vdec_h264_if.c @@ -0,0 +1,734 @@ +/* +* 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. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ +#include +#include +#include +#include +#include +#include "../vdec_drv_if.h" +#include "../aml_vcodec_util.h" +#include "../aml_vcodec_dec.h" +//#include "../aml_vcodec_intr.h" +#include "../aml_vcodec_adapt.h" +#include "../vdec_drv_base.h" +#include "../aml_vcodec_vfm.h" +#include "h264_stream.h" +#include "h264_parse.h" +#include + +/* h264 NALU type */ +#define NAL_NON_IDR_SLICE 0x01 +#define NAL_IDR_SLICE 0x05 +#define NAL_H264_SEI 0x06 +#define NAL_H264_SPS 0x07 +#define NAL_H264_PPS 0x08 + +#define NAL_TYPE(value) ((value) & 0x1F) + +#define BUF_PREDICTION_SZ (64 * 1024)//(32 * 1024) + +#define MB_UNIT_LEN 16 + +/* motion vector size (bytes) for every macro block */ +#define HW_MB_STORE_SZ 64 + +#define H264_MAX_FB_NUM 17 +#define HDR_PARSING_BUF_SZ 1024 + +#define HEADER_BUFFER_SIZE (32 * 1024) + +/** + * struct h264_fb - h264 decode frame buffer information + * @vdec_fb_va : virtual address of struct vdec_fb + * @y_fb_dma : dma address of Y frame buffer (luma) + * @c_fb_dma : dma address of C frame buffer (chroma) + * @poc : picture order count of frame buffer + * @reserved : for 8 bytes alignment + */ +struct h264_fb { + uint64_t vdec_fb_va; + uint64_t y_fb_dma; + uint64_t c_fb_dma; + int32_t poc; + uint32_t reserved; +}; + +/** + * struct h264_ring_fb_list - ring frame buffer list + * @fb_list : frame buffer arrary + * @read_idx : read index + * @write_idx : write index + * @count : buffer count in list + */ +struct h264_ring_fb_list { + struct h264_fb fb_list[H264_MAX_FB_NUM]; + unsigned int read_idx; + unsigned int write_idx; + unsigned int count; + unsigned int reserved; +}; + +/** + * struct vdec_h264_dec_info - decode information + * @dpb_sz : decoding picture buffer size + * @resolution_changed : resoltion change happen + * @realloc_mv_buf : flag to notify driver to re-allocate mv buffer + * @reserved : for 8 bytes alignment + * @bs_dma : Input bit-stream buffer dma address + * @y_fb_dma : Y frame buffer dma address + * @c_fb_dma : C frame buffer dma address + * @vdec_fb_va : VDEC frame buffer struct virtual address + */ +struct vdec_h264_dec_info { + uint32_t dpb_sz; + uint32_t resolution_changed; + uint32_t realloc_mv_buf; + uint32_t reserved; + uint64_t bs_dma; + uint64_t y_fb_dma; + uint64_t c_fb_dma; + uint64_t vdec_fb_va; +}; + +/** + * struct vdec_h264_vsi - shared memory for decode information exchange + * between VPU and Host. + * The memory is allocated by VPU then mapping to Host + * in vpu_dec_init() and freed in vpu_dec_deinit() + * by VPU. + * AP-W/R : AP is writer/reader on this item + * VPU-W/R: VPU is write/reader on this item + * @hdr_buf : Header parsing buffer (AP-W, VPU-R) + * @pred_buf_dma : HW working predication buffer dma address (AP-W, VPU-R) + * @mv_buf_dma : HW working motion vector buffer dma address (AP-W, VPU-R) + * @list_free : free frame buffer ring list (AP-W/R, VPU-W) + * @list_disp : display frame buffer ring list (AP-R, VPU-W) + * @dec : decode information (AP-R, VPU-W) + * @pic : picture information (AP-R, VPU-W) + * @crop : crop information (AP-R, VPU-W) + */ +struct vdec_h264_vsi { + unsigned char hdr_buf[HDR_PARSING_BUF_SZ]; + char *header_buf; + int sps_size; + int pps_size; + int sei_size; + int head_offset; + uint64_t pred_buf_dma; + uint64_t mv_buf_dma[H264_MAX_FB_NUM]; + struct h264_ring_fb_list list_free; + struct h264_ring_fb_list list_disp; + struct vdec_h264_dec_info dec; + struct vdec_pic_info pic; + struct v4l2_rect crop; +}; + +/** + * struct vdec_h264_inst - h264 decoder instance + * @num_nalu : how many nalus be decoded + * @ctx : point to aml_vcodec_ctx + * @pred_buf : HW working predication buffer + * @mv_buf : HW working motion vector buffer + * @vpu : VPU instance + * @vsi : VPU shared information + */ +struct vdec_h264_inst { + unsigned int num_nalu; + struct aml_vcodec_ctx *ctx; + struct aml_vcodec_mem pred_buf; + struct aml_vcodec_mem mv_buf[H264_MAX_FB_NUM]; + //struct vdec_vpu_inst vpu; + struct aml_vdec_adapt vdec; + struct vdec_h264_vsi *vsi; + struct vcodec_vfm_s vfm; +}; + +#define DUMP_FILE_NAME "/data/dump/dump.tmp" +static struct file *filp; +static loff_t file_pos; + +void dump_write(const char __user *buf, size_t count) +{ + mm_segment_t old_fs; + + if (!filp) + return; + + old_fs = get_fs(); + set_fs(KERNEL_DS); + + if (count != vfs_write(filp, buf, count, &file_pos)) + pr_err("Failed to write file\n"); + + set_fs(old_fs); +} + +void dump_init(void) +{ + filp = filp_open(DUMP_FILE_NAME, O_CREAT | O_RDWR, 0644); + if (IS_ERR(filp)) { + pr_err("open dump file failed\n"); + filp = NULL; + } +} + +void dump_deinit(void) +{ + if (filp) { + filp_close(filp, current->files); + filp = NULL; + file_pos = 0; + } +} + +void swap_uv(void *uv, int size) +{ + int i; + __u16 *p = uv; + + size /= 2; + + for (i = 0; i < size; i++, p++) + *p = __swab16(*p); +} + +static void get_pic_info(struct vdec_h264_inst *inst, + struct vdec_pic_info *pic) +{ + *pic = inst->vsi->pic; + + aml_vcodec_debug(inst, "pic(%d, %d), buf(%d, %d)", + pic->visible_width, pic->visible_height, + pic->coded_width, pic->coded_height); + aml_vcodec_debug(inst, "Y(%d, %d), C(%d, %d)", pic->y_bs_sz, + pic->y_len_sz, pic->c_bs_sz, pic->c_len_sz); +} + +static void get_crop_info(struct vdec_h264_inst *inst, struct v4l2_rect *cr) +{ + cr->left = inst->vsi->crop.left; + cr->top = inst->vsi->crop.top; + cr->width = inst->vsi->crop.width; + cr->height = inst->vsi->crop.height; + + aml_vcodec_debug(inst, "l=%d, t=%d, w=%d, h=%d", + cr->left, cr->top, cr->width, cr->height); +} + +static void get_dpb_size(struct vdec_h264_inst *inst, unsigned int *dpb_sz) +{ + *dpb_sz = inst->vsi->dec.dpb_sz; + aml_vcodec_debug(inst, "sz=%d", *dpb_sz); +} + +static int find_start_code(unsigned char *data, unsigned int data_sz) +{ + if (data_sz > 3 && data[0] == 0 && data[1] == 0 && data[2] == 1) + return 3; + + if (data_sz > 4 && data[0] == 0 && data[1] == 0 && data[2] == 0 && + data[3] == 1) + return 4; + + return -1; +} + +static int vdec_h264_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec) +{ + struct vdec_h264_inst *inst = NULL; + int ret = -1; + + inst = kzalloc(sizeof(*inst), GFP_KERNEL); + if (!inst) + return -ENOMEM; + + inst->ctx = ctx; + + inst->vdec.format = VFORMAT_H264; + inst->vdec.dev = ctx->dev->vpu_plat_dev; + inst->vdec.filp = ctx->dev->filp; + inst->vdec.ctx = ctx; + inst->vfm.ctx = ctx; + inst->vfm.ada_ctx = &inst->vdec; + + vcodec_vfm_init(&inst->vfm); + + ret = video_decoder_init(&inst->vdec); + if (ret) { + aml_vcodec_err(inst, "vdec_h264 init err=%d", ret); + goto error_free_inst; + } + + /* probe info from the stream */ + inst->vsi = kzalloc(sizeof(struct vdec_h264_vsi), GFP_KERNEL); + if (!inst->vsi) { + ret = -ENOMEM; + goto error_free_inst; + } + + /* alloc the header buffer to be used cache sps or spp etc.*/ + inst->vsi->header_buf = kzalloc(HEADER_BUFFER_SIZE, GFP_KERNEL); + if (!inst->vsi) { + ret = -ENOMEM; + goto error_free_vsi; + } + + inst->vsi->pic.visible_width = 1920; + inst->vsi->pic.visible_height = 1080; + inst->vsi->pic.coded_width = 1920; + inst->vsi->pic.coded_height = 1088; + inst->vsi->pic.y_bs_sz = 0; + inst->vsi->pic.y_len_sz = (1920 * 1088); + inst->vsi->pic.c_bs_sz = 0; + inst->vsi->pic.c_len_sz = (1920 * 1088 / 2); + + aml_vcodec_debug(inst, "H264 Instance >> %p", inst); + + ctx->ada_ctx = &inst->vdec; + *h_vdec = (unsigned long)inst; + + dump_init(); + + return 0; + +error_free_vsi: + kfree(inst->vsi); +error_free_inst: + kfree(inst); + *h_vdec = 0; + + return ret; +} + +static int refer_buffer_num(int level_idc, int poc_cnt, + int mb_width, int mb_height) +{ + int max_ref_num = 27; + int size, size_margin = 6; + int pic_size = mb_width * mb_height * 384; + + switch (level_idc) { + case 9: + size = 152064; + break; + case 10: + size = 152064; + break; + case 11: + size = 345600; + break; + case 12: + size = 912384; + break; + case 13: + size = 912384; + break; + case 20: + size = 912384; + break; + case 21: + size = 1824768; + break; + case 22: + size = 3110400; + break; + case 30: + size = 3110400; + break; + case 31: + size = 6912000; + break; + case 32: + size = 7864320; + break; + case 40: + size = 12582912; + break; + case 41: + size = 12582912; + break; + case 42: + size = 13369344; + break; + case 50: + size = 42393600; + break; + case 51: + case 52: + default: + size = 70778880; + break; + } + + size /= pic_size; + size = size + 1; /* need more buffers */ + + if (poc_cnt > size) + size = poc_cnt; + + size = size + size_margin; + if (size > max_ref_num) + size = max_ref_num; + + return size; +} + +static void fill_vdec_params(struct vdec_h264_inst *inst, struct h264_SPS_t *sps) +{ + struct vdec_pic_info *pic = &inst->vsi->pic; + struct vdec_h264_dec_info *dec = &inst->vsi->dec; + struct v4l2_rect *rect = &inst->vsi->crop; + unsigned int mb_w, mb_h, width, height; + unsigned int crop_unit_x = 0, crop_unit_y = 0; + unsigned int poc_cnt = 0; + + mb_w = sps->pic_width_in_mbs_minus1 + 1; + mb_h = sps->pic_height_in_map_units_minus1 + 1; + + width = mb_w << 4; // 16 + height = (2 - sps->frame_mbs_only_flag) * (mb_h << 4); + + if (sps->frame_cropping_flag) { + if (0 == sps->chroma_format_idc) {// monochrome + crop_unit_x = 1; + crop_unit_y = 2 - sps->frame_mbs_only_flag; + } else if (1 == sps->chroma_format_idc) {// 4:2:0 + crop_unit_x = 2; + crop_unit_y = 2 * (2 - sps->frame_mbs_only_flag); + } else if (2 == sps->chroma_format_idc) {// 4:2:2 + crop_unit_x = 2; + crop_unit_y = 2 - sps->frame_mbs_only_flag; + } else {// 3 == sps.chroma_format_idc // 4:4:4 + crop_unit_x = 1; + crop_unit_y = 2 - sps->frame_mbs_only_flag; + } + } + + width -= crop_unit_x * (sps->frame_crop_left_offset + + sps->frame_crop_right_offset); + height -= crop_unit_y * (sps->frame_crop_top_offset + + sps->frame_crop_bottom_offset); + + /* fill visible area size that be used for EGL. */ + pic->visible_width = width; + pic->visible_height = height; + + /* calc visible ares. */ + rect->left = 0; + rect->top = 0; + rect->width = pic->visible_width; + rect->height = pic->visible_height; + + /* config canvas size that be used for decoder. */ + pic->coded_width = ALIGN(mb_w, 4) << 4; + pic->coded_height = ALIGN(mb_h, 4) << 4; + pic->y_len_sz = pic->coded_width * pic->coded_height; + pic->c_len_sz = pic->y_len_sz >> 1; + + /* calc DPB size */ + poc_cnt = sps->pic_order_cnt_type; + if (!poc_cnt) + poc_cnt = (sps->log2_max_pic_order_cnt_lsb_minus4 + 4) << 1; + + dec->dpb_sz = refer_buffer_num(sps->level_idc, poc_cnt, mb_w, mb_h); + + pr_info("[%d] The stream infos, coded:(%d x %d), visible:(%d x %d), DPB: %d\n", + inst->ctx->id, pic->coded_width, pic->coded_height, + pic->visible_width, pic->visible_height, dec->dpb_sz); +} + +static int vdec_h264_probe(unsigned long h_vdec, + struct aml_vcodec_mem *bs, void *out) +{ + struct vdec_h264_inst *inst = + (struct vdec_h264_inst *)h_vdec; + struct h264_stream_t s; + struct h264_SPS_t *sps; + unsigned int nal_type; + int nal_idx; + int real_data_pos, real_data_size; + unsigned char *buf = (unsigned char *)bs->va; + unsigned int size = bs->size; + + nal_idx = find_start_code(buf, size); + if (nal_idx < 0) + return -1; + + nal_type = NAL_TYPE(buf[nal_idx]); + if (nal_type != NAL_H264_SPS) + return -1; + + /* start code plus nal type. */ + real_data_pos = nal_idx + 1; + real_data_size = size - real_data_pos; + + sps = kzalloc(sizeof(struct h264_SPS_t), GFP_KERNEL); + if (sps == NULL) + return -ENOMEM; + + h264_stream_set(&s, &buf[real_data_pos], real_data_size); + h264_sps_parse(&s, sps); + //h264_sps_info(sps); + + fill_vdec_params(inst, sps); + + kfree(sps); + + return 0; +} + +static void vdec_h264_deinit(unsigned long h_vdec) +{ + struct vdec_h264_inst *inst = (struct vdec_h264_inst *)h_vdec; + + if (!inst) + return; + + aml_vcodec_debug_enter(inst); + + video_decoder_release(&inst->vdec); + + vcodec_vfm_release(&inst->vfm); + + dump_deinit(); + + if (inst->vsi && inst->vsi->header_buf) + kfree(inst->vsi->header_buf); + + if (inst->vsi) + kfree(inst->vsi); + + kfree(inst); +} + +static int vdec_h264_get_fb(struct vdec_h264_inst *inst, struct vdec_fb **out) +{ + return get_fb_from_queue(inst->ctx, out); +} + +static void vdec_h264_get_vf(struct vdec_h264_inst *inst, struct vdec_fb **out) +{ + struct vframe_s *vf = NULL; + struct vdec_fb *fb = NULL; + + aml_vcodec_debug(inst, "%s() [%d], vfm: %p", + __func__, __LINE__, &inst->vfm); + + vf = peek_video_frame(&inst->vfm); + if (!vf) { + aml_vcodec_debug(inst, "there is no vframe."); + *out = NULL; + return; + } + + vf = get_video_frame(&inst->vfm); + if (!vf) { + aml_vcodec_debug(inst, "the vframe is avalid."); + *out = NULL; + return; + } + + aml_vcodec_debug(inst, "%s() [%d], vf: %p, v4l_mem_handle: %lx, idx: %d\n", + __func__, __LINE__, vf, vf->v4l_mem_handle, vf->index); + + fb = (struct vdec_fb *)vf->v4l_mem_handle; + fb->vf_handle = (unsigned long)vf; + fb->status = FB_ST_DISPLAY; + + *out = fb; + + //pr_info("%s, %d\n", __func__, fb->base_y.bytes_used); + //dump_write(fb->base_y.va, fb->base_y.bytes_used); + //dump_write(fb->base_c.va, fb->base_c.bytes_used); + + /* convert yuv format. */ + //swap_uv(fb->base_c.va, fb->base_c.size); + + aml_vcodec_debug(inst, "%s() [%d], va: %p, phy: %x, size: %zu", + __func__, __LINE__, fb->base_y.va, + (unsigned int)virt_to_phys(fb->base_y.va), fb->base_y.size); + aml_vcodec_debug(inst, "%s() [%d], va: %p, phy: %x, size: %zu", + __func__, __LINE__, fb->base_c.va, + (unsigned int)virt_to_phys(fb->base_c.va), fb->base_c.size); +} + +static int vdec_h264_decode(unsigned long h_vdec, struct aml_vcodec_mem *bs, + unsigned long int timestamp, bool *res_chg) +{ + struct vdec_h264_inst *inst = (struct vdec_h264_inst *)h_vdec; + struct aml_vdec_adapt *vdec = &inst->vdec; + int nal_start_idx = 0; + int err = 0; + unsigned int nal_start; + unsigned int nal_type; + unsigned char *buf; + unsigned int buf_sz; + int ret = 0; + + /* bs NULL means flush decoder */ + if (bs == NULL) + return 0;//vpu_dec_reset(vpu); + + buf = (unsigned char *)bs->va; + buf_sz = bs->size; + nal_start_idx = find_start_code(buf, buf_sz); + if (nal_start_idx < 0) + goto err_free_fb_out; + + nal_start = buf[nal_start_idx]; + nal_type = NAL_TYPE(buf[nal_start_idx]); + aml_vcodec_debug(inst, "NALU type: %d, size: %u", nal_type, buf_sz); + + if (nal_type == NAL_H264_SPS) { + if (inst->vsi->head_offset + buf_sz > HEADER_BUFFER_SIZE) { + err = -EILSEQ; + goto err_free_fb_out; + } + inst->vsi->sps_size = buf_sz; + memcpy(inst->vsi->header_buf + inst->vsi->head_offset, buf, buf_sz); + inst->vsi->head_offset += inst->vsi->sps_size; + } else if (nal_type == NAL_H264_PPS) { + //buf_sz -= nal_start_idx; + if (inst->vsi->head_offset + buf_sz > HEADER_BUFFER_SIZE) { + err = -EILSEQ; + goto err_free_fb_out; + } + inst->vsi->pps_size = buf_sz; + memcpy(inst->vsi->header_buf + inst->vsi->head_offset, buf, buf_sz); + inst->vsi->head_offset += inst->vsi->pps_size; + } else if (nal_type == NAL_H264_SEI) { + if (inst->vsi->head_offset + buf_sz > HEADER_BUFFER_SIZE) { + err = -EILSEQ; + goto err_free_fb_out; + } + inst->vsi->sei_size = buf_sz; + memcpy(inst->vsi->header_buf + inst->vsi->head_offset, buf, buf_sz); + inst->vsi->head_offset += inst->vsi->sei_size; + } else { + char *write_buf = vmalloc(inst->vsi->head_offset + buf_sz); + + memcpy(write_buf, inst->vsi->header_buf, inst->vsi->head_offset); + memcpy(write_buf + inst->vsi->head_offset, buf, buf_sz); + + ret = vdec_vframe_write(vdec, write_buf, + inst->vsi->head_offset + buf_sz, timestamp); + + aml_vcodec_debug(inst, "buf: %p, buf size: %u, write to: %d", + write_buf, inst->vsi->head_offset + buf_sz, ret); + + memset(inst->vsi->header_buf, 0, HEADER_BUFFER_SIZE); + inst->vsi->head_offset = 0; + inst->vsi->sps_size = 0; + inst->vsi->pps_size = 0; + inst->vsi->sei_size = 0; + + vfree(write_buf); + } + + //err = vpu_dec_start(vpu, data, 2); + /*if (err) + goto err_free_fb_out;*/ + +#if 0 + *res_chg = inst->vsi->dec.resolution_changed; + if (*res_chg) { + struct vdec_pic_info pic; + + aml_vcodec_debug(inst, "- resolution changed -"); + get_pic_info(inst, &pic); + + if (inst->vsi->dec.realloc_mv_buf) { + err = alloc_mv_buf(inst, &pic); + if (err) + goto err_free_fb_out; + } + } +#endif + if (nal_type == NAL_NON_IDR_SLICE || nal_type == NAL_IDR_SLICE) { + /* wait decoder done interrupt */ + //err = aml_vcodec_wait_for_done_ctx(inst->ctx, aml_INST_IRQ_RECEIVED, WAIT_INTR_TIMEOUT_MS); + /*if (err) + goto err_free_fb_out;*/ + + //vpu_dec_end(vpu); + } + return ret; + +err_free_fb_out: + //put_fb_to_free(inst, fb); + aml_vcodec_err(inst, "NALU[%d] err=%d", inst->num_nalu, err); + + return err; +} + +static int vdec_h264_get_param(unsigned long h_vdec, + enum vdec_get_param_type type, void *out) +{ + int ret = 0; + struct vdec_h264_inst *inst = (struct vdec_h264_inst *)h_vdec; + + if (!inst) { + pr_err("the h264 inst of dec is void."); + return -1; + } + + switch (type) { + case GET_PARAM_DISP_FRAME_BUFFER: + vdec_h264_get_vf(inst, out); + break; + + case GET_PARAM_FREE_FRAME_BUFFER: + ret = vdec_h264_get_fb(inst, out); + break; + + case GET_PARAM_PIC_INFO: + get_pic_info(inst, out); + break; + + case GET_PARAM_DPB_SIZE: + get_dpb_size(inst, out); + break; + + case GET_PARAM_CROP_INFO: + get_crop_info(inst, out); + break; + + default: + aml_vcodec_err(inst, "invalid get parameter type=%d", type); + ret = -EINVAL; + } + + return ret; +} + +static struct vdec_common_if vdec_h264_if = { + vdec_h264_init, + vdec_h264_probe, + vdec_h264_decode, + vdec_h264_get_param, + vdec_h264_deinit, +}; + +struct vdec_common_if *get_h264_dec_comm_if(void); + +struct vdec_common_if *get_h264_dec_comm_if(void) +{ + return &vdec_h264_if; +} diff --git a/drivers/amlogic/media_modules/amvdec_ports/test/Android.mk b/drivers/amlogic/media_modules/amvdec_ports/test/Android.mk new file mode 100644 index 000000000000..d9652fb23b4a --- /dev/null +++ b/drivers/amlogic/media_modules/amvdec_ports/test/Android.mk @@ -0,0 +1,23 @@ +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) +LOCAL_MODULE := vcode_m2m +LOCAL_MODULE_TAGS := optional +LOCAL_SRC_FILES := vcodec_m2m_test.c +LOCAL_ARM_MODE := arm + +LOCAL_C_INCLUDES := \ + $(JNI_H_INCLUDE) \ + $(BOARD_AML_VENDOR_PATH)/vendor/amlogic/external/ffmpeg + +LOCAL_SHARED_LIBRARIES := \ + libamffmpeg + +include $(BUILD_EXECUTABLE) + +include $(CLEAR_VARS) + +LOCAL_PREBUILT_LIBS:= \ +# libavcodec:ffmpeg/lib/libavcodec.so \ + +include $(BUILD_MULTI_PREBUILT) diff --git a/drivers/amlogic/media_modules/amvdec_ports/test/vcodec_m2m_test.c b/drivers/amlogic/media_modules/amvdec_ports/test/vcodec_m2m_test.c new file mode 100644 index 000000000000..5bed46c1644e --- /dev/null +++ b/drivers/amlogic/media_modules/amvdec_ports/test/vcodec_m2m_test.c @@ -0,0 +1,292 @@ +/* +* 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. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ +#include +#include +#include +#include +#include +#include +#include +#include + +#define INBUF_SIZE (4096) +#define DUMP_DIR "/mnt/video_frames" + +typedef struct VcodecCtx { + AVFormatContext *fmt_ctx; + AVStream *stream; + int nb_streams; + int vst_idx; + char *filename; + pthread_t tid; + pthread_mutex_t pthread_mutex; + pthread_cond_t pthread_cond; +} VcodecCtx; + +static void pgm_save(unsigned char *buf, int wrap, int xsize, int ysize, + char *filename) +{ + FILE *f; + int i; + + printf("wrap: %d, xsize: %d, ysize: %d, filename: %s\n", wrap, xsize, ysize, filename); + + f = fopen(filename,"w+"); + fprintf(f, "P5\n%d %d\n%d\n", xsize, ysize, 255); + + for (i = 0; i < ysize; i++) + fwrite(buf + i * wrap, 1, xsize, f); + fclose(f); +} + +static void decode(AVCodecContext *dec_ctx, AVFrame *frame, AVPacket *pkt, + const char *filename) +{ + char buf[1024]; + int ret; + + ret = avcodec_send_packet(dec_ctx, pkt); + if (ret < 0) { + fprintf(stderr, "Error sending a packet for decoding\n"); + return; + } + + while (ret >= 0) { + ret = avcodec_receive_frame(dec_ctx, frame); + if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) + return; + else if (ret < 0) { + fprintf(stderr, "Error during decoding, ret: %s\n", av_err2str(ret)); + break; + } + + //fprintf(stderr, "saving frame %3d\n", dec_ctx->frame_number); + fflush(stdout); + + /* the picture is allocated by the decoder. no need to free it */ + snprintf(buf, sizeof(buf), "%s/frame-%d", filename, dec_ctx->frame_number); + pgm_save(frame->data[0], frame->linesize[0], + frame->width, frame->height, buf); + } +} + +static void* read_thread(void *arg) +{ + int ret, err; + AVFormatContext *ic = NULL; + AVCodecContext *dec_ctx = NULL; + AVStream *stream = NULL; + AVCodec *codec = NULL; + AVPacket pkt1, *pkt = &pkt1; + AVFrame *frame = NULL; + int vst_idx = 0; + int has_video = 0; + unsigned int st_idx = 0; + VcodecCtx *vctx = arg; + + printf("entry read thread, tid: %ld.\n", vctx->tid); + + ic = avformat_alloc_context(); + if (!ic) { + fprintf(stderr, "Could not allocate avformat context.\n"); + return NULL; + } + + err = avformat_open_input(&ic, vctx->filename, NULL, NULL); + if (err < 0) { + fprintf(stderr, "Could not open avformat input.\n"); + return NULL; + } + + err = avformat_find_stream_info(ic, NULL); + if (err < 0) { + fprintf(stderr, "find stream info err.\n"); + return NULL; + } + + for (st_idx = 0; st_idx < ic->nb_streams; st_idx++) { + AVStream *st = ic->streams[st_idx]; + + enum AVMediaType type = st->codecpar->codec_type; + st->discard = AVDISCARD_ALL; + + if (type == AVMEDIA_TYPE_VIDEO) { + st->discard = AVDISCARD_NONE; + vctx->vst_idx = st_idx; + has_video = 1; + break; + } + } + + if (!has_video) { + fprintf(stderr, "no video stream.\n"); + return NULL; + } + + stream = ic->streams[vctx->vst_idx]; + + //codec = avcodec_find_decoder(stream->codecpar->codec_id); + codec = avcodec_find_decoder_by_name("h264_v4l2m2m"); + if (!codec) { + fprintf(stderr, "Unsupported codec with id %d for input stream %d\n", + stream->codecpar->codec_id, stream->index); + return NULL; + } + + dec_ctx = avcodec_alloc_context3(codec); + if (!dec_ctx) { + fprintf(stderr, "Could not allocate video codec context\n"); + return NULL; + } + + err = avcodec_parameters_to_context(dec_ctx, stream->codecpar); + if (err < 0) { + fprintf(stderr, "Could not set paras to context\n"); + return NULL; + } + + av_codec_set_pkt_timebase(dec_ctx, stream->time_base); + dec_ctx->framerate = stream->avg_frame_rate; + + if (avcodec_open2(dec_ctx, codec, NULL) < 0) { + fprintf(stderr, "Could not open codec for input stream %d\n", + stream->index); + return NULL; + } + + printf("fmt ctx: %p, stream: %p, video st idx: %d, num: %d\n", + ic, stream, vst_idx, ic->nb_streams); + printf("format: %s\n",ic->iformat->name); + + ic->flags |= AVFMT_FLAG_GENPTS; + ic->debug = 0xff; + + //if (ic->pb) + // ic->pb->eof_reached = 0; + + frame = av_frame_alloc(); + if (!frame) { + fprintf(stderr, "Could not allocate video frame\n"); + return NULL; + } + + for (;;) { + ret = av_read_frame(ic, pkt); + if (ret < 0) { + if (ret == AVERROR_EOF || avio_feof(ic->pb)) { + printf("read data end, ret: %d.\n", ret); + break; + } + + if (ic->pb && ic->pb->error) + break; + + printf("read data fail, ret: %d.\n", ret); + continue; + } + + if (pkt->stream_index == vctx->vst_idx) { + //packet_queue_put(&is->audioq, pkt); + printf("read video data size: %d.\n", pkt->size); + if (pkt->size) + decode(dec_ctx, frame, pkt, DUMP_DIR); + } else + av_packet_unref(pkt); + } + + /* flush the decoder */ + decode(dec_ctx, frame, NULL, DUMP_DIR); + + avcodec_free_context(&dec_ctx); + av_frame_free(&frame); + + if (ic) + avformat_close_input(&ic); + + printf("read thread exit.\n"); + + pthread_mutex_lock(&vctx->pthread_mutex); + pthread_cond_signal(&vctx->pthread_cond); + pthread_mutex_unlock(&vctx->pthread_mutex); + + return NULL; +} + + +static int open_input_file(const char *filename) +{ + int ret; + VcodecCtx *vctx; + pthread_t pid = pthread_self(); + + vctx = av_mallocz(sizeof(VcodecCtx)); + if (!vctx) + return -1; + + vctx->filename = av_strdup(filename); + if (!vctx->filename) + return -1; + + pthread_mutex_init(&vctx->pthread_mutex, NULL); + pthread_cond_init(&vctx->pthread_cond, NULL); + + ret = pthread_create(&vctx->tid, NULL, read_thread, (void *)vctx); + if (ret == 0) { + pthread_setname_np(pid, "read_thread"); + + pthread_mutex_lock(&vctx->pthread_mutex); + pthread_cond_wait(&vctx->pthread_cond, &vctx->pthread_mutex); + pthread_mutex_unlock(&vctx->pthread_mutex); + } + + printf("creat the read thread, ret: %d.\n", ret); + + return 0; +} + +int main(int argc, char **argv) +{ + int ret; + const char *filename, *outfilename; + + if (argc < 2) { + fprintf(stderr, "Usage: %s \n ==> %s/frame-123\n", argv[0], DUMP_DIR); + exit(0); + } + + filename = argv[1]; + outfilename = argv[2]; + + mkdir(DUMP_DIR, 0664); + + /*set debug level*/ + //av_log_set_level(AV_LOG_DEBUG); + + av_register_all(); + + ret = open_input_file(filename); + if (ret < 0) { + fprintf(stderr, "open input file fail.\n"); + goto out; + } + +out: + return ret < 0; +} diff --git a/drivers/amlogic/media_modules/amvdec_ports/vdec_drv_base.h b/drivers/amlogic/media_modules/amvdec_ports/vdec_drv_base.h new file mode 100644 index 000000000000..dfe5d27457df --- /dev/null +++ b/drivers/amlogic/media_modules/amvdec_ports/vdec_drv_base.h @@ -0,0 +1,64 @@ +/* +* 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. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ +#ifndef _VDEC_DRV_BASE_ +#define _VDEC_DRV_BASE_ + +#include "aml_vcodec_drv.h" + +#include "vdec_drv_if.h" + +struct vdec_common_if { + /** + * (*init)() - initialize decode driver + * @ctx : [in] aml v4l2 context + * @h_vdec : [out] driver handle + */ + int (*init)(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec); + + int (*probe)(unsigned long h_vdec, + struct aml_vcodec_mem *bs, void *out); + + /** + * (*decode)() - trigger decode + * @h_vdec : [in] driver handle + * @bs : [in] input bitstream + * @fb : [in] frame buffer to store decoded frame + * @res_chg : [out] resolution change happen + */ + int (*decode)(unsigned long h_vdec, struct aml_vcodec_mem *bs, + unsigned long int pts, bool *res_chg); + + /** + * (*get_param)() - get driver's parameter + * @h_vdec : [in] driver handle + * @type : [in] input parameter type + * @out : [out] buffer to store query result + */ + int (*get_param)(unsigned long h_vdec, + enum vdec_get_param_type type, void *out); + + /** + * (*deinit)() - deinitialize driver. + * @h_vdec : [in] driver handle to be deinit + */ + void (*deinit)(unsigned long h_vdec); +}; + +#endif diff --git a/drivers/amlogic/media_modules/amvdec_ports/vdec_drv_if.c b/drivers/amlogic/media_modules/amvdec_ports/vdec_drv_if.c new file mode 100644 index 000000000000..d981260b1361 --- /dev/null +++ b/drivers/amlogic/media_modules/amvdec_ports/vdec_drv_if.c @@ -0,0 +1,138 @@ +/* +* 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. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ +#include +#include +#include + +#include "vdec_drv_if.h" +#include "aml_vcodec_dec.h" +#include "vdec_drv_base.h" +#include "aml_vcodec_dec_pm.h" +//#include "aml_vpu.h" + +const struct vdec_common_if *get_h264_dec_comm_if(void); +const struct vdec_common_if *get_vp8_dec_comm_if(void); +const struct vdec_common_if *get_vp9_dec_comm_if(void); + +int vdec_if_init(struct aml_vcodec_ctx *ctx, unsigned int fourcc) +{ + int ret = 0; + + switch (fourcc) { + case V4L2_PIX_FMT_H264: + ctx->dec_if = get_h264_dec_comm_if(); + break; + /*case V4L2_PIX_FMT_VP8: + ctx->dec_if = get_vp8_dec_comm_if(); + break; + case V4L2_PIX_FMT_VP9: + ctx->dec_if = get_vp9_dec_comm_if(); + break;*/ + default: + return -EINVAL; + } + + aml_vdec_lock(ctx); + //aml_vcodec_dec_clock_on(&ctx->dev->pm);//debug_tmp + ret = ctx->dec_if->init(ctx, &ctx->drv_handle); + //aml_vcodec_dec_clock_off(&ctx->dev->pm); + aml_vdec_unlock(ctx); + + return ret; +} + +int vdec_if_probe(struct aml_vcodec_ctx *ctx, + struct aml_vcodec_mem *bs, void *out) +{ + int ret = 0; + + aml_vdec_lock(ctx); + ret = ctx->dec_if->probe(ctx->drv_handle, bs, out); + aml_vdec_unlock(ctx); + + return ret; +} + +int vdec_if_decode(struct aml_vcodec_ctx *ctx, struct aml_vcodec_mem *bs, + unsigned long int timestamp, bool *res_chg) +{ + int ret = 0; + + if (bs) { + if ((bs->dma_addr & 63) != 0) { + aml_v4l2_err("bs dma_addr should 64 byte align"); + return -EINVAL; + } + } + + /*if (fb) { + if (((fb->base_y.dma_addr & 511) != 0) || + ((fb->base_c.dma_addr & 511) != 0)) { + aml_v4l2_err("frame buffer dma_addr should 512 byte align"); + return -EINVAL; + } + }*/ + + if (ctx->drv_handle == 0) + return -EIO; + + //aml_vdec_lock(ctx); + + aml_vcodec_set_curr_ctx(ctx->dev, ctx); + //aml_vcodec_dec_clock_on(&ctx->dev->pm);//debug_tmp + //enable_irq(ctx->dev->dec_irq); + ret = ctx->dec_if->decode(ctx->drv_handle, bs, timestamp, res_chg); + //disable_irq(ctx->dev->dec_irq); + //aml_vcodec_dec_clock_off(&ctx->dev->pm); + aml_vcodec_set_curr_ctx(ctx->dev, NULL); + + //aml_vdec_unlock(ctx); + + return ret; +} + +int vdec_if_get_param(struct aml_vcodec_ctx *ctx, + enum vdec_get_param_type type, void *out) +{ + int ret = 0; + + if (ctx->drv_handle == 0) + return -EIO; + + //aml_vdec_lock(ctx); + ret = ctx->dec_if->get_param(ctx->drv_handle, type, out); + //aml_vdec_unlock(ctx); + + return ret; +} + +void vdec_if_deinit(struct aml_vcodec_ctx *ctx) +{ + if (ctx->drv_handle == 0) + return; + + //aml_vdec_lock(ctx); + //aml_vcodec_dec_clock_on(&ctx->dev->pm); + ctx->dec_if->deinit(ctx->drv_handle); + //aml_vcodec_dec_clock_off(&ctx->dev->pm); + //aml_vdec_unlock(ctx); + + ctx->drv_handle = 0; +} diff --git a/drivers/amlogic/media_modules/amvdec_ports/vdec_drv_if.h b/drivers/amlogic/media_modules/amvdec_ports/vdec_drv_if.h new file mode 100644 index 000000000000..c6f461a15ba7 --- /dev/null +++ b/drivers/amlogic/media_modules/amvdec_ports/vdec_drv_if.h @@ -0,0 +1,110 @@ +/* +* 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. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ +#ifndef _VDEC_DRV_IF_H_ +#define _VDEC_DRV_IF_H_ + +#include "aml_vcodec_drv.h" +#include "aml_vcodec_dec.h" +#include "aml_vcodec_util.h" + + +/** + * struct vdec_fb_status - decoder frame buffer status + * @FB_ST_NORMAL : initial state + * @FB_ST_DISPLAY : frmae buffer is ready to be displayed + * @FB_ST_FREE : frame buffer is not used by decoder any more + */ +enum vdec_fb_status { + FB_ST_NORMAL, + FB_ST_DISPLAY, + FB_ST_FREE +}; + +/* For GET_PARAM_DISP_FRAME_BUFFER and GET_PARAM_FREE_FRAME_BUFFER, + * the caller does not own the returned buffer. The buffer will not be + * released before vdec_if_deinit. + * GET_PARAM_DISP_FRAME_BUFFER : get next displayable frame buffer, + * struct vdec_fb** + * GET_PARAM_FREE_FRAME_BUFFER : get non-referenced framebuffer, vdec_fb** + * GET_PARAM_PIC_INFO : get picture info, struct vdec_pic_info* + * GET_PARAM_CROP_INFO : get crop info, struct v4l2_crop* + * GET_PARAM_DPB_SIZE : get dpb size, unsigned int* + */ +enum vdec_get_param_type { + GET_PARAM_DISP_FRAME_BUFFER, + GET_PARAM_FREE_FRAME_BUFFER, + GET_PARAM_PIC_INFO, + GET_PARAM_CROP_INFO, + GET_PARAM_DPB_SIZE +}; + +/** + * struct vdec_fb_node - decoder frame buffer node + * @list : list to hold this node + * @fb : point to frame buffer (vdec_fb), fb could point to frame buffer and + * working buffer this is for maintain buffers in different state + */ +struct vdec_fb_node { + struct list_head list; + struct vdec_fb *fb; +}; + +/** + * vdec_if_init() - initialize decode driver + * @ctx : [in] v4l2 context + * @fourcc : [in] video format fourcc, V4L2_PIX_FMT_H264/VP8/VP9.. + */ +int vdec_if_init(struct aml_vcodec_ctx *ctx, unsigned int fourcc); + +int vdec_if_probe(struct aml_vcodec_ctx *ctx, + struct aml_vcodec_mem *bs, void *out); + +/** + * vdec_if_deinit() - deinitialize decode driver + * @ctx : [in] v4l2 context + * + */ +void vdec_if_deinit(struct aml_vcodec_ctx *ctx); + +/** + * vdec_if_decode() - trigger decode + * @ctx : [in] v4l2 context + * @bs : [in] input bitstream + * @fb : [in] frame buffer to store decoded frame, when null menas parse + * header only + * @res_chg : [out] resolution change happens if current bs have different + * picture width/height + * Note: To flush the decoder when reaching EOF, set input bitstream as NULL. + * + * Return: 0 on success. -EIO on unrecoverable error. + */ +int vdec_if_decode(struct aml_vcodec_ctx *ctx, struct aml_vcodec_mem *bs, + unsigned long int timestamp, bool *res_chg); + +/** + * vdec_if_get_param() - get driver's parameter + * @ctx : [in] v4l2 context + * @type : [in] input parameter type + * @out : [out] buffer to store query result + */ +int vdec_if_get_param(struct aml_vcodec_ctx *ctx, enum vdec_get_param_type type, + void *out); + +#endif diff --git a/drivers/amlogic/media_modules/common/chips/chips.c b/drivers/amlogic/media_modules/common/chips/chips.c index a9912f498602..63d55ba9fe99 100644 --- a/drivers/amlogic/media_modules/common/chips/chips.c +++ b/drivers/amlogic/media_modules/common/chips/chips.c @@ -31,6 +31,7 @@ #include "chips.h" #include #include +#include "decoder_cpu_ver_info.h" #define VIDEO_FIRMWARE_FATHER_NAME "video" @@ -56,22 +57,25 @@ struct type_name { const char *name; }; static const struct type_name cpu_type_name[] = { - {MESON_CPU_MAJOR_ID_M6, "m6"}, - {MESON_CPU_MAJOR_ID_M6TV, "m6tv"}, - {MESON_CPU_MAJOR_ID_M6TVL, "m6tvl"}, - {MESON_CPU_MAJOR_ID_M8, "m8"}, - {MESON_CPU_MAJOR_ID_MTVD, "mtvd"}, - {MESON_CPU_MAJOR_ID_M8B, "m8b"}, - {MESON_CPU_MAJOR_ID_MG9TV, "mg9tv"}, - {MESON_CPU_MAJOR_ID_M8M2, "m8"}, - {MESON_CPU_MAJOR_ID_GXBB, "gxbb"}, - {MESON_CPU_MAJOR_ID_GXTVBB, "gxtvbb"}, - {MESON_CPU_MAJOR_ID_GXL, "gxl"}, - {MESON_CPU_MAJOR_ID_GXM, "gxm"}, - {MESON_CPU_MAJOR_ID_TXL, "txl"}, - {MESON_CPU_MAJOR_ID_TXLX, "txlx"}, - {MESON_CPU_MAJOR_ID_G12A, "g12a"}, - {MESON_CPU_MAJOR_ID_G12B, "g12b"}, + {AM_MESON_CPU_MAJOR_ID_M6, "m6"}, + {AM_MESON_CPU_MAJOR_ID_M6TV, "m6tv"}, + {AM_MESON_CPU_MAJOR_ID_M6TVL, "m6tvl"}, + {AM_MESON_CPU_MAJOR_ID_M8, "m8"}, + {AM_MESON_CPU_MAJOR_ID_MTVD, "mtvd"}, + {AM_MESON_CPU_MAJOR_ID_M8B, "m8b"}, + {AM_MESON_CPU_MAJOR_ID_MG9TV, "mg9tv"}, + {AM_MESON_CPU_MAJOR_ID_M8M2, "m8"}, + {AM_MESON_CPU_MAJOR_ID_GXBB, "gxbb"}, + {AM_MESON_CPU_MAJOR_ID_GXTVBB, "gxtvbb"}, + {AM_MESON_CPU_MAJOR_ID_GXL, "gxl"}, + {AM_MESON_CPU_MAJOR_ID_GXM, "gxm"}, + {AM_MESON_CPU_MAJOR_ID_TXL, "txl"}, + {AM_MESON_CPU_MAJOR_ID_TXLX, "txlx"}, + {AM_MESON_CPU_MAJOR_ID_G12A, "g12a"}, + {AM_MESON_CPU_MAJOR_ID_G12B, "g12b"}, + {AM_MESON_CPU_MAJOR_ID_SM1, "sm1"}, + {AM_MESON_CPU_MAJOR_ID_TL1, "tl1"}, + {AM_MESON_CPU_MAJOR_ID_TM2, "tm2"}, {0, NULL}, }; @@ -99,7 +103,7 @@ const char *get_cpu_type_name(void) return get_type_name(cpu_type_name, sizeof(cpu_type_name) / sizeof(struct type_name), - get_cpu_type()); + get_cpu_major_id()); } EXPORT_SYMBOL(get_cpu_type_name); diff --git a/drivers/amlogic/media_modules/common/chips/decoder_cpu_ver_info.c b/drivers/amlogic/media_modules/common/chips/decoder_cpu_ver_info.c new file mode 100644 index 000000000000..7818a21b4844 --- /dev/null +++ b/drivers/amlogic/media_modules/common/chips/decoder_cpu_ver_info.c @@ -0,0 +1,161 @@ +/* +* 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. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include "decoder_cpu_ver_info.h" + +#define DECODE_CPU_VER_ID_NODE_NAME "cpu_ver_name" +#define AM_SUCESS 0 +#define MAJOR_ID_START AM_MESON_CPU_MAJOR_ID_M6 + +static enum AM_MESON_CPU_MAJOR_ID cpu_ver_id = AM_MESON_CPU_MAJOR_ID_MAX; + +static enum AM_MESON_CPU_MAJOR_ID cpu_ver_info[AM_MESON_CPU_MAJOR_ID_MAX - MAJOR_ID_START]= +{ + AM_MESON_CPU_MAJOR_ID_M6, + AM_MESON_CPU_MAJOR_ID_M6TV, + AM_MESON_CPU_MAJOR_ID_M6TVL, + AM_MESON_CPU_MAJOR_ID_M8, + AM_MESON_CPU_MAJOR_ID_MTVD, + AM_MESON_CPU_MAJOR_ID_M8B, + AM_MESON_CPU_MAJOR_ID_MG9TV, + AM_MESON_CPU_MAJOR_ID_M8M2, + AM_MESON_CPU_MAJOR_ID_UNUSE, + AM_MESON_CPU_MAJOR_ID_GXBB, + AM_MESON_CPU_MAJOR_ID_GXTVBB, + AM_MESON_CPU_MAJOR_ID_GXL, + AM_MESON_CPU_MAJOR_ID_GXM, + AM_MESON_CPU_MAJOR_ID_TXL, + AM_MESON_CPU_MAJOR_ID_TXLX, + AM_MESON_CPU_MAJOR_ID_AXG, + AM_MESON_CPU_MAJOR_ID_GXLX, + AM_MESON_CPU_MAJOR_ID_TXHD, + AM_MESON_CPU_MAJOR_ID_G12A, + AM_MESON_CPU_MAJOR_ID_G12B, + AM_MESON_CPU_MAJOR_ID_GXLX2, + AM_MESON_CPU_MAJOR_ID_SM1, + AM_MESON_CPU_MAJOR_ID_RES_0x2c, + AM_MESON_CPU_MAJOR_ID_RES_0x2d, + AM_MESON_CPU_MAJOR_ID_TL1, + AM_MESON_CPU_MAJOR_ID_TM2, +}; + +static const struct of_device_id cpu_ver_of_match[] = { + { + .compatible = "amlogic, cpu-major-id-axg", + .data = &cpu_ver_info[AM_MESON_CPU_MAJOR_ID_AXG - MAJOR_ID_START], + }, + + { + .compatible = "amlogic, cpu-major-id-g12a", + .data = &cpu_ver_info[AM_MESON_CPU_MAJOR_ID_G12A - MAJOR_ID_START], + }, + + { + .compatible = "amlogic, cpu-major-id-gxl", + .data = &cpu_ver_info[AM_MESON_CPU_MAJOR_ID_GXL - MAJOR_ID_START], + }, + + { + .compatible = "amlogic, cpu-major-id-gxm", + .data = &cpu_ver_info[AM_MESON_CPU_MAJOR_ID_GXM - MAJOR_ID_START], + }, + + { + .compatible = "amlogic, cpu-major-id-txl", + .data = &cpu_ver_info[AM_MESON_CPU_MAJOR_ID_TXL - MAJOR_ID_START], + }, + + { + .compatible = "amlogic, cpu-major-id-txlx", + .data = &cpu_ver_info[AM_MESON_CPU_MAJOR_ID_TXLX - MAJOR_ID_START], + }, + + { + .compatible = "amlogic, cpu-major-id-sm1", + .data = &cpu_ver_info[AM_MESON_CPU_MAJOR_ID_SM1 - MAJOR_ID_START], + }, + + { + .compatible = "amlogic, cpu-major-id-tl1", + .data = &cpu_ver_info[AM_MESON_CPU_MAJOR_ID_TL1 - MAJOR_ID_START], + }, + { + .compatible = "amlogic, cpu-major-id-tm2", + .data = &cpu_ver_info[AM_MESON_CPU_MAJOR_ID_TM2 - MAJOR_ID_START], + }, + {}, +}; + +static bool get_cpu_id_from_dtb(enum AM_MESON_CPU_MAJOR_ID *pidType) +{ + struct device_node *pNode = NULL; + struct platform_device* pDev = NULL; + const struct of_device_id *pMatch = NULL; + + pNode = of_find_node_by_name(NULL, DECODE_CPU_VER_ID_NODE_NAME); + if (NULL == pNode) { + pr_err("No find node.\n"); + return -EINVAL; + } + + pDev = of_find_device_by_node(pNode); + if (NULL == pDev) + return -EINVAL; + + pMatch = of_match_device(cpu_ver_of_match, &pDev->dev); + if (NULL == pMatch) { + pr_err("No find of_match_device\n"); + return -EINVAL; + } + + *pidType = *(enum AM_MESON_CPU_MAJOR_ID *)pMatch->data; + + return AM_SUCESS; +} + +static void initial_cpu_id(void) +{ + enum AM_MESON_CPU_MAJOR_ID id_type = AM_MESON_CPU_MAJOR_ID_MAX; + + if (AM_SUCESS == get_cpu_id_from_dtb(&id_type)) + cpu_ver_id = id_type; + else + cpu_ver_id = (enum AM_MESON_CPU_MAJOR_ID)get_cpu_type(); + + if (AM_MESON_CPU_MAJOR_ID_G12B == cpu_ver_id) + if (is_meson_rev_b()) + cpu_ver_id = AM_MESON_CPU_MAJOR_ID_TL1; +} + +enum AM_MESON_CPU_MAJOR_ID get_cpu_major_id(void) +{ + if (AM_MESON_CPU_MAJOR_ID_MAX == cpu_ver_id) + initial_cpu_id(); + + return cpu_ver_id; +} +EXPORT_SYMBOL(get_cpu_major_id); diff --git a/drivers/amlogic/media_modules/common/chips/decoder_cpu_ver_info.h b/drivers/amlogic/media_modules/common/chips/decoder_cpu_ver_info.h new file mode 100644 index 000000000000..494f5f6fdbfd --- /dev/null +++ b/drivers/amlogic/media_modules/common/chips/decoder_cpu_ver_info.h @@ -0,0 +1,55 @@ +/* +* 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. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ +#ifndef DECODER_CPU_VER_INFO_H +#define DECODER_CPU_VER_INFO_H + +enum AM_MESON_CPU_MAJOR_ID +{ + AM_MESON_CPU_MAJOR_ID_M6 = 0x16, + AM_MESON_CPU_MAJOR_ID_M6TV = 0x17, + AM_MESON_CPU_MAJOR_ID_M6TVL = 0x18, + AM_MESON_CPU_MAJOR_ID_M8 = 0x19, + AM_MESON_CPU_MAJOR_ID_MTVD = 0x1A, + AM_MESON_CPU_MAJOR_ID_M8B = 0x1B, + AM_MESON_CPU_MAJOR_ID_MG9TV = 0x1C, + AM_MESON_CPU_MAJOR_ID_M8M2 = 0x1D, + AM_MESON_CPU_MAJOR_ID_UNUSE = 0x1E, + AM_MESON_CPU_MAJOR_ID_GXBB = 0x1F, + AM_MESON_CPU_MAJOR_ID_GXTVBB = 0x20, + AM_MESON_CPU_MAJOR_ID_GXL = 0x21, + AM_MESON_CPU_MAJOR_ID_GXM = 0x22, + AM_MESON_CPU_MAJOR_ID_TXL = 0x23, + AM_MESON_CPU_MAJOR_ID_TXLX = 0x24, + AM_MESON_CPU_MAJOR_ID_AXG = 0x25, + AM_MESON_CPU_MAJOR_ID_GXLX = 0x26, + AM_MESON_CPU_MAJOR_ID_TXHD = 0x27, + AM_MESON_CPU_MAJOR_ID_G12A = 0x28, + AM_MESON_CPU_MAJOR_ID_G12B = 0x29, + AM_MESON_CPU_MAJOR_ID_GXLX2 = 0x2a, + AM_MESON_CPU_MAJOR_ID_SM1 = 0x2b, + AM_MESON_CPU_MAJOR_ID_RES_0x2c, + AM_MESON_CPU_MAJOR_ID_RES_0x2d, + AM_MESON_CPU_MAJOR_ID_TL1 = 0x2e, + AM_MESON_CPU_MAJOR_ID_TM2 = 0x2f, + AM_MESON_CPU_MAJOR_ID_MAX, +}; + +enum AM_MESON_CPU_MAJOR_ID get_cpu_major_id(void); +#endif diff --git a/drivers/amlogic/media_modules/common/firmware/firmware_cfg.h b/drivers/amlogic/media_modules/common/firmware/firmware_cfg.h index 082d8f457535..e23ac2ad41dd 100644 --- a/drivers/amlogic/media_modules/common/firmware/firmware_cfg.h +++ b/drivers/amlogic/media_modules/common/firmware/firmware_cfg.h @@ -26,7 +26,7 @@ /*firmware for a special format, to replace the format in the package.*/ -{VIDEO_DECODE, VIDEO_FW_FILE, "h265.bin"}, -{VIDEO_DECODE, VIDEO_FW_FILE, "h264.bin"}, -{VIDEO_DECODE, VIDEO_FW_FILE, "h264_multi.bin"}, +/*{VIDEO_DECODE, VIDEO_FW_FILE, "h265.bin"},*/ +/*{VIDEO_DECODE, VIDEO_FW_FILE, "h264.bin"},*/ +/*{VIDEO_DECODE, VIDEO_FW_FILE, "h264_multi.bin"},*/ diff --git a/drivers/amlogic/media_modules/common/firmware/firmware_drv.c b/drivers/amlogic/media_modules/common/firmware/firmware_drv.c index 775f9352c728..f1ea44526448 100644 --- a/drivers/amlogic/media_modules/common/firmware/firmware_drv.c +++ b/drivers/amlogic/media_modules/common/firmware/firmware_drv.c @@ -14,7 +14,6 @@ * more details. * */ - #include #include #include @@ -38,9 +37,10 @@ #include #include #include +#include "../chips/decoder_cpu_ver_info.h" -/* major.minor.revision */ -#define PACK_VERS "v0.0.1" +/* major.minor */ +#define PACK_VERS "v0.1" #define CLASS_NAME "firmware_codec" #define DEV_NAME "firmware_vdec" @@ -79,15 +79,12 @@ int get_firmware_data(unsigned int format, char *buf) struct fw_mgr_s *mgr = g_mgr; struct fw_info_s *info; - if (tee_enabled()) { - pr_info ("tee load firmware fomat = %d\n",(u32)format); - ret = tee_load_video_fw((u32)format, 0); - if (ret == 0) - ret = 1; - else - ret = -1; - return ret; - } + pr_info("[%s], the fw (%s) will be loaded.\n", + tee_enabled() ? "TEE" : "LOCAL", + get_fw_format_name(format)); + + if (tee_enabled()) + return 0; mutex_lock(&mutex); @@ -120,7 +117,7 @@ int get_data_from_name(const char *name, char *buf) struct fw_info_s *info; char *fw_name = __getname(); - if (IS_ERR_OR_NULL(fw_name)) + if (fw_name == NULL) return -ENOMEM; strcat(fw_name, name); @@ -363,11 +360,12 @@ static ssize_t info_show(struct class *class, - sys_tz.tz_minuteswest * 60; time_to_tm(secs, 0, &tm); - pr_info("%s %-16s, %02d:%02d:%02d %d/%d/%ld, %s %-8s, %s %s\n", + pr_info("%s %-16s, %02d:%02d:%02d %d/%d/%ld, %s %-8s, %s %-8s, %s %s\n", "fmt:", info->data->head.format, tm.tm_hour, tm.tm_min, tm.tm_sec, tm.tm_mon + 1, tm.tm_mday, tm.tm_year + 1900, - "id:", info->data->head.commit, + "cmtid:", info->data->head.commit, + "chgid:", info->data->head.change_id, "mk:", info->data->head.maker); } out: @@ -394,7 +392,7 @@ static int fw_info_fill(void) char *path = __getname(); const char *name; - if (IS_ERR_OR_NULL(path)) + if (path == NULL) return -ENOMEM; for (i = 0; i < info_size; i++) { @@ -408,7 +406,7 @@ static int fw_info_fill(void) continue; files = kzalloc(sizeof(struct fw_files_s), GFP_KERNEL); - if (IS_ERR_OR_NULL(files)) { + if (files == NULL) { __putname(path); return -ENOMEM; } @@ -416,7 +414,9 @@ static int fw_info_fill(void) files->file_type = ucode_info[i].file_type; files->fw_type = ucode_info[i].fw_type; strncpy(files->path, path, sizeof(files->path)); + files->path[sizeof(files->path) - 1] = '\0'; strncpy(files->name, name, sizeof(files->name)); + files->name[sizeof(files->name) - 1] = '\0'; list_add(&files->node, &mgr->files_head); } @@ -448,7 +448,6 @@ static int fw_data_filter(struct firmware_s *fw, int cpu = fw_get_cpu(fw->head.cpu); if (mgr->cur_cpu < cpu) { - pr_info("the fw %s is not match.\n", fw_info->name); kfree(fw_info); kfree(fw); return -1; @@ -477,15 +476,18 @@ static int fw_data_filter(struct firmware_s *fw, /* the cpu ver is lower and needs to be filtered */ if (cpu < fw_get_cpu(info->data->head.cpu)) { - pr_info("the fw %s is not match.\n", - fw_info->name); + if (debug) + pr_info("keep the newer fw (%s) and ignore the older fw (%s).\n", + info->name, fw_info->name); kfree(fw_info); kfree(fw); return 1; } /* removes not match fw from info list */ - pr_info("the fw %s is not match.\n", info->name); + if (debug) + pr_info("drop the old fw (%s) will be load the newer fw (%s).\n", + info->name, fw_info->name); kfree(info->data); fw_del_info(info); } @@ -496,26 +498,30 @@ static int fw_data_filter(struct firmware_s *fw, static int fw_check_pack_version(char *buf) { struct package_s *pack = NULL; - int major, minor, rev, ver = 0; + int major, minor, major_fw, minor_fw, ver = 0; + int ret; pack = (struct package_s *) buf; - sscanf(PACK_VERS, "v%x.%x.%x", &major, &minor, &rev); - ver = (major << 24 | minor << 16 | rev); + ret = sscanf(PACK_VERS, "v%x.%x", &major, &minor); + if (ret != 2) + return -1; - pr_info("the package has %d fws totally.\n", pack->head.total); + ver = (major << 16 | minor); - major = pack->head.version >> 24; - minor = (pack->head.version >> 16) & 0xf; - rev = pack->head.version & 0xff; + if (debug) + pr_info("the package has %d fws totally.\n", pack->head.total); - if (ver < pack->head.version) { - pr_info("the pack ver v%d.%d.%d too higher to unsupport.\n", - major, minor, rev); + major_fw = (pack->head.version >> 16) & 0xff; + minor_fw = pack->head.version & 0xff; + + if (major < major_fw) { + pr_info("the pack ver v%d.%d too higher to unsupport.\n", + major_fw, minor_fw); return -1; } if (ver != pack->head.version) { - pr_info("the fw pack ver v%d.%d.%d is too lower.\n", major, minor, rev); + pr_info("the fw pack ver v%d.%d is too lower.\n", major_fw, minor_fw); pr_info("it may work abnormally so need to be update in time.\n"); } @@ -534,7 +540,7 @@ static int fw_package_parse(struct fw_files_s *files, int try_cnt = 100; char *path = __getname(); - if (IS_ERR_OR_NULL(path)) + if (path == NULL) return -ENOMEM; pack_data = ((struct package_s *)buf)->data; @@ -551,13 +557,13 @@ static int fw_package_parse(struct fw_files_s *files, continue; info = kzalloc(sizeof(struct fw_info_s), GFP_KERNEL); - if (IS_ERR_OR_NULL(info)) { + if (info == NULL) { ret = -ENOMEM; goto out; } data = kzalloc(FRIMWARE_SIZE, GFP_KERNEL); - if (IS_ERR_OR_NULL(data)) { + if (data == NULL) { kfree(info); ret = -ENOMEM; goto out; @@ -566,8 +572,10 @@ static int fw_package_parse(struct fw_files_s *files, info->file_type = files->file_type; strncpy(info->src_from, files->name, sizeof(info->src_from)); + info->src_from[sizeof(info->src_from) - 1] = '\0'; strncpy(info->name, pack_info->head.name, sizeof(info->name)); + info->name[sizeof(info->name) - 1] = '\0'; info->format = get_fw_format(pack_info->head.format); len = pack_info->head.length; @@ -604,21 +612,25 @@ static int fw_code_parse(struct fw_files_s *files, struct fw_info_s *info; info = kzalloc(sizeof(struct fw_info_s), GFP_KERNEL); - if (IS_ERR_OR_NULL(info)) + if (info == NULL) return -ENOMEM; info->data = kzalloc(FRIMWARE_SIZE, GFP_KERNEL); - if (IS_ERR_OR_NULL(info->data)) + if (info->data == NULL) { + kfree(info); return -ENOMEM; + } info->file_type = files->file_type; strncpy(info->src_from, files->name, sizeof(info->src_from)); + info->src_from[sizeof(info->src_from) - 1] = '\0'; memcpy(info->data, buf, size); if (!fw_data_check_sum(info->data)) { pr_info("check sum fail !\n"); kfree(info->data); + kfree(info); return -1; } @@ -647,7 +659,7 @@ static int fw_data_binding(void) int ret = 0, magic = 0; struct fw_mgr_s *mgr = g_mgr; struct fw_files_s *files, *tmp; - char *buf = vmalloc(BUFF_SIZE); + char *buf = NULL; int size; if (list_empty(&mgr->files_head)) { @@ -655,6 +667,7 @@ static int fw_data_binding(void) return 0; } + buf = vmalloc(BUFF_SIZE); if (IS_ERR_OR_NULL(buf)) return -ENOMEM; @@ -665,13 +678,9 @@ static int fw_data_binding(void) magic = fw_probe(buf); if (files->file_type == VIDEO_PACKAGE && magic == PACK) { - pr_info("start to parse fw package.\n"); - if (!fw_check_pack_version(buf)) ret = fw_package_parse(files, buf, size); } else if (files->file_type == VIDEO_FW_FILE && magic == CODE) { - pr_info("start to parse fw code.\n"); - ret = fw_code_parse(files, buf, size); } else { list_del(&files->node); @@ -711,7 +720,7 @@ static int fw_mgr_init(void) if (IS_ERR_OR_NULL(g_mgr)) return -ENOMEM; - g_mgr->cur_cpu = get_cpu_type(); + g_mgr->cur_cpu = get_cpu_major_id(); INIT_LIST_HEAD(&g_mgr->files_head); INIT_LIST_HEAD(&g_mgr->fw_head); spin_lock_init(&g_mgr->lock); diff --git a/drivers/amlogic/media_modules/common/firmware/firmware_priv.h b/drivers/amlogic/media_modules/common/firmware/firmware_priv.h index 811fdc6e0159..b8c4da876246 100644 --- a/drivers/amlogic/media_modules/common/firmware/firmware_priv.h +++ b/drivers/amlogic/media_modules/common/firmware/firmware_priv.h @@ -65,7 +65,8 @@ struct fw_head_s { char commit[16]; int data_size; unsigned int time; - char reserved[128]; + char change_id[16]; + char reserved[112]; }; struct firmware_s { diff --git a/drivers/amlogic/media_modules/common/firmware/firmware_type.c b/drivers/amlogic/media_modules/common/firmware/firmware_type.c index b2d9f17d6572..609ff6e8611d 100644 --- a/drivers/amlogic/media_modules/common/firmware/firmware_type.c +++ b/drivers/amlogic/media_modules/common/firmware/firmware_type.c @@ -1,12 +1,31 @@ +/* +* 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. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ #include "firmware_type.h" -#include +#include "../chips/decoder_cpu_ver_info.h" static const struct format_name_s format_name[] = { {VIDEO_DEC_MPEG12, "mpeg12"}, {VIDEO_DEC_MPEG12_MULTI, "mpeg12_multi"}, - {VIDEO_DEC_MPEG4_3, "divx311"}, - {VIDEO_DEC_MPEG4_4, "divx4x"}, - {VIDEO_DEC_MPEG4_4_MULTI, "divx4x_multi"}, + {VIDEO_DEC_MPEG4_3, "mpeg4_3"}, + {VIDEO_DEC_MPEG4_4, "mpeg4_4"}, + {VIDEO_DEC_MPEG4_4_MULTI, "mpeg4_4_multi"}, {VIDEO_DEC_MPEG4_5, "xvid"}, {VIDEO_DEC_MPEG4_5_MULTI, "xvid_multi"}, {VIDEO_DEC_H263, "h263"}, @@ -21,8 +40,6 @@ static const struct format_name_s format_name[] = { {VIDEO_DEC_AVS_GXM, "avs_gxm"}, {VIDEO_DEC_AVS_NOCABAC, "avs_no_cabac"}, {VIDEO_DEC_H264, "h264"}, - {VIDEO_DEC_H264_4k2K, "h264_4k2k"}, - {VIDEO_DEC_H264_4k2K_SINGLE, "h264_4k2k_single"}, {VIDEO_DEC_H264_MVC, "h264_mvc"}, {VIDEO_DEC_H264_MVC_GXM, "h264_mvc_gxm"}, {VIDEO_DEC_H264_MULTI, "h264_multi"}, @@ -30,6 +47,7 @@ static const struct format_name_s format_name[] = { {VIDEO_DEC_H264_MULTI_GXM, "h264_multi_gxm"}, {VIDEO_DEC_HEVC, "hevc"}, {VIDEO_DEC_HEVC_MMU, "hevc_mmu"}, + {VIDEO_DEC_HEVC_MMU_SWAP, "hevc_mmu_swap"}, {VIDEO_DEC_HEVC_G12A, "hevc_g12a"}, {VIDEO_DEC_VP9, "vp9"}, {VIDEO_DEC_VP9_MMU, "vp9_mmu"}, @@ -42,10 +60,19 @@ static const struct format_name_s format_name[] = { }; static const struct cpu_type_s cpu_type[] = { - {MESON_CPU_MAJOR_ID_GXL, "gxl"}, - {MESON_CPU_MAJOR_ID_GXM, "gxm"}, - {MESON_CPU_MAJOR_ID_G12A, "g12a"}, - {MESON_CPU_MAJOR_ID_G12B, "g12b"}, + {AM_MESON_CPU_MAJOR_ID_GXL, "gxl"}, + {AM_MESON_CPU_MAJOR_ID_GXM, "gxm"}, + {AM_MESON_CPU_MAJOR_ID_TXL, "txl"}, + {AM_MESON_CPU_MAJOR_ID_TXLX, "txlx"}, + {AM_MESON_CPU_MAJOR_ID_AXG, "axg"}, + {AM_MESON_CPU_MAJOR_ID_GXLX, "gxlx"}, + {AM_MESON_CPU_MAJOR_ID_TXHD, "txhd"}, + {AM_MESON_CPU_MAJOR_ID_G12A, "g12a"}, + {AM_MESON_CPU_MAJOR_ID_G12B, "g12b"}, + {AM_MESON_CPU_MAJOR_ID_GXLX2, "gxlx2"}, + {AM_MESON_CPU_MAJOR_ID_SM1, "sm1"}, + {AM_MESON_CPU_MAJOR_ID_TL1, "tl1"}, + {AM_MESON_CPU_MAJOR_ID_TM2, "tm2"}, }; const char *get_fw_format_name(unsigned int format) diff --git a/drivers/amlogic/media_modules/common/firmware/firmware_type.h b/drivers/amlogic/media_modules/common/firmware/firmware_type.h index f51956bbf561..6c1b3f7bcd7e 100644 --- a/drivers/amlogic/media_modules/common/firmware/firmware_type.h +++ b/drivers/amlogic/media_modules/common/firmware/firmware_type.h @@ -1,3 +1,22 @@ +/* +* 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. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ #ifndef __VIDEO_FIRMWARE_FORMAT_ #define __VIDEO_FIRMWARE_FORMAT_ @@ -44,7 +63,7 @@ #define VIDEO_DEC_MPEG4_4_MULTI TAG('M', '4', '4', 'M') #define VIDEO_DEC_MPEG4_5_MULTI TAG('M', '4', '5', 'M') #define VIDEO_DEC_H263_MULTI TAG('2', '6', '3', 'M') - +#define VIDEO_DEC_HEVC_MMU_SWAP TAG('2', '6', '5', 'S') /* ... */ #define FIRMWARE_MAX (UINT_MAX) @@ -69,7 +88,7 @@ struct cpu_type_s { const char *name; }; -const char *get_firmware_type_name(unsigned int format); +const char *get_fw_format_name(unsigned int format); unsigned int get_fw_format(const char *name); int fw_get_cpu(const char *name); diff --git a/drivers/amlogic/media_modules/common/media_clock/Makefile b/drivers/amlogic/media_modules/common/media_clock/Makefile index 994857a05219..975b5e57c452 100644 --- a/drivers/amlogic/media_modules/common/media_clock/Makefile +++ b/drivers/amlogic/media_modules/common/media_clock/Makefile @@ -3,3 +3,4 @@ media_clock-objs += ../chips/chips.o media_clock-objs += clk/clkg12.o media_clock-objs += clk/clk.o media_clock-objs += switch/amports_gate.o +media_clock-objs += ../chips/decoder_cpu_ver_info.o diff --git a/drivers/amlogic/media_modules/common/media_clock/clk/clk.c b/drivers/amlogic/media_modules/common/media_clock/clk/clk.c index 4ffaf12bfb46..b60a08d0805b 100644 --- a/drivers/amlogic/media_modules/common/media_clock/clk/clk.c +++ b/drivers/amlogic/media_modules/common/media_clock/clk/clk.c @@ -33,6 +33,7 @@ #include "../../chips/chips.h" #include "clk_priv.h" #include +#include "../../chips/decoder_cpu_ver_info.h" #define p_vdec() (get_current_vdec_chip()->clk_mgr[VDEC_1]) #define p_vdec2() (get_current_vdec_chip()->clk_mgr[VDEC_2]) @@ -336,7 +337,7 @@ int vdec_source_changed_for_clk_set(int format, int width, int height, int fps) || format == VFORMAT_AVS2) { ret_clk = hevc_clock_set(clk); clock_source_wxhxfps_saved[VDEC_HEVC] = width * height * fps; - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) { + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A) { ret_clk = hevc_back_clock_set(clk); clock_source_wxhxfps_saved[VDEC_HEVCB] = width * height * fps; } @@ -344,7 +345,7 @@ int vdec_source_changed_for_clk_set(int format, int width, int height, int fps) ret_clk = hcodec_clock_set(clk); clock_source_wxhxfps_saved[VDEC_HCODEC] = width * height * fps; } else if (format == VFORMAT_H264_4K2K && - get_cpu_type() == MESON_CPU_MAJOR_ID_M8) { + get_cpu_major_id() == AM_MESON_CPU_MAJOR_ID_M8) { ret_clk = vdec2_clock_set(clk); clock_source_wxhxfps_saved[VDEC_2] = width * height * fps; ret_clk = vdec_clock_set(clk); @@ -363,7 +364,7 @@ static int register_vdec_clk_mgr_per_cpu(int cputype, struct chip_vdec_clk_s *mgr; - if (cputype != get_cpu_type() || vdec_type >= VDEC_MAX) { + if (cputype != get_cpu_major_id() || vdec_type >= VDEC_MAX) { /* *pr_info("ignore vdec clk mgr for vdec[%d] cpu=%d\n", *vdec_type, cputype); @@ -414,7 +415,7 @@ static int register_vdec_clk_setting_per_cpu(int cputype, struct clk_set_setting *p_setting; - if (cputype != get_cpu_type()) { + if (cputype != get_cpu_major_id()) { /* *pr_info("ignore clk_set_setting for cpu=%d\n", *cputype); diff --git a/drivers/amlogic/media_modules/common/media_clock/clk/clk.h b/drivers/amlogic/media_modules/common/media_clock/clk/clk.h index 5fefcbc6c335..9e6c02588b8b 100644 --- a/drivers/amlogic/media_modules/common/media_clock/clk/clk.h +++ b/drivers/amlogic/media_modules/common/media_clock/clk/clk.h @@ -130,7 +130,7 @@ static int __init vdec_init_clk(void) #endif #ifdef VDEC_HAS_HEVC register_vdec_clk_mgr(cpus, VDEC_HEVC, &vdec_hevc_clk_mgr); - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) + if (get_cpu_major_id() >= MESON_CPU_MAJOR_ID_G12A) register_vdec_clk_mgr(cpus, VDEC_HEVCB, &vdec_hevc_back_clk_mgr); #endif #ifdef VDEC_HAS_VDEC_HCODEC diff --git a/drivers/amlogic/media_modules/common/media_clock/clk/clkg12.c b/drivers/amlogic/media_modules/common/media_clock/clk/clkg12.c index d7111eb63eca..f045bd320889 100644 --- a/drivers/amlogic/media_modules/common/media_clock/clk/clkg12.c +++ b/drivers/amlogic/media_modules/common/media_clock/clk/clkg12.c @@ -30,8 +30,11 @@ #include #include "../switch/amports_gate.h" +#include "../../chips/decoder_cpu_ver_info.h" + #define MHz (1000000) #define debug_print pr_info +#define TL1_HEVC_MAX_CLK (800) //#define NO_CLKTREE @@ -395,6 +398,11 @@ static struct clk_set_setting clks_for_formats[] = { 630}, {INT_MAX, 630}, } }, + {/*VFORMAT_AVS2*/ + {{1280*720*30, 100}, {1920*1080*30, 100}, + {1920*1080*60, 166}, {4096*2048*30, 333}, + {4096*2048*60, 630}, {INT_MAX, 630},} + }, }; @@ -492,12 +500,12 @@ static int vdec_clock_init(void) { gp_pll_user_vdec = gp_pll_user_register("vdec", 0, gp_pll_user_cb_vdec); - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXL) + if (get_cpu_major_id() >= MESON_CPU_MAJOR_ID_GXL) is_gp0_div2 = false; else is_gp0_div2 = true; - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXL) { + if (get_cpu_major_id() >= MESON_CPU_MAJOR_ID_GXL) { pr_info("used fix clk for vdec clk source!\n"); //update_vdec_clk_config_settings(1); } @@ -597,6 +605,16 @@ static int hevc_clock_init(void) return (gp_pll_user_hevc) ? 0 : -ENOMEM; } +static int hevc_back_clock_init(void) +{ + return 0; +} + +static int hevc_back_clock_set(int clk) +{ + return 0; +} + static int hevc_clock_set(int clk) { int use_gpll = 0; @@ -701,6 +719,10 @@ static int vdec_clock_set(int clk) clk = 667; } + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1 && + get_cpu_major_id() != AM_MESON_CPU_MAJOR_ID_TL1) + clk = 800; + if (set_frq_enable && vdec_frq) { pr_info("Set the vdec frq is %u MHz\n", vdec_frq); clk = vdec_frq; @@ -747,7 +769,10 @@ static int hevc_back_clock_set(int clk) if ((clk > 500 && clk != 667)) { if (clock_real_clk[VDEC_HEVCB] == 648) return 648; - clk = 667; + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) + clk = TL1_HEVC_MAX_CLK; + else + clk = 667; } if (set_frq_enable && hevcb_frq) { @@ -755,7 +780,7 @@ static int hevc_back_clock_set(int clk) clk = hevcb_frq; } - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_TXLX) { + if (get_cpu_major_id() >= MESON_CPU_MAJOR_ID_TXLX) { if ((READ_EFUSE_REG(EFUSE_LIC1) >> 28 & 0x1) && clk > 333) { pr_info("The hevcb clock limit to 333MHz.\n"); clk = 333; @@ -792,7 +817,10 @@ static int hevc_clock_set(int clk) if ((clk > 500 && clk != 667)) { if (clock_real_clk[VDEC_HEVC] == 648) return 648; - clk = 667; + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) + clk = TL1_HEVC_MAX_CLK; + else + clk = 667; } if (set_frq_enable && hevc_frq) { @@ -977,14 +1005,17 @@ static int vdec_clock_get(enum vdec_type_e core) #define VDEC_HAS_VDEC_HCODEC #define VDEC_HAS_CLK_SETTINGS #define CLK_FOR_CPU {\ - MESON_CPU_MAJOR_ID_GXBB,\ - MESON_CPU_MAJOR_ID_GXTVBB,\ - MESON_CPU_MAJOR_ID_GXL,\ - MESON_CPU_MAJOR_ID_GXM,\ - MESON_CPU_MAJOR_ID_TXL,\ - MESON_CPU_MAJOR_ID_TXLX,\ - MESON_CPU_MAJOR_ID_G12A,\ - MESON_CPU_MAJOR_ID_G12B,\ + AM_MESON_CPU_MAJOR_ID_GXBB,\ + AM_MESON_CPU_MAJOR_ID_GXTVBB,\ + AM_MESON_CPU_MAJOR_ID_GXL,\ + AM_MESON_CPU_MAJOR_ID_GXM,\ + AM_MESON_CPU_MAJOR_ID_TXL,\ + AM_MESON_CPU_MAJOR_ID_TXLX,\ + AM_MESON_CPU_MAJOR_ID_G12A,\ + AM_MESON_CPU_MAJOR_ID_G12B,\ + AM_MESON_CPU_MAJOR_ID_SM1,\ + AM_MESON_CPU_MAJOR_ID_TL1,\ + AM_MESON_CPU_MAJOR_ID_TM2,\ 0} #include "clk.h" diff --git a/drivers/amlogic/media_modules/common/media_clock/switch/amports_gate.c b/drivers/amlogic/media_modules/common/media_clock/switch/amports_gate.c index c6898217300e..beaea5388c05 100644 --- a/drivers/amlogic/media_modules/common/media_clock/switch/amports_gate.c +++ b/drivers/amlogic/media_modules/common/media_clock/switch/amports_gate.c @@ -191,14 +191,9 @@ int amports_clock_gate_init(struct device *dev) } EXPORT_SYMBOL(amports_clock_gate_init); -static int amports_switch_gate(struct gate_switch_node *gate_node, int enable) -{ - return 0; -} int amports_switch_gate(const char *name, int enable) { - amports_switch_gate(0, 0); return 0; } EXPORT_SYMBOL(amports_switch_gate); diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/avs/avs.c b/drivers/amlogic/media_modules/frame_provider/decoder/avs/avs.c index bb2ea4a504e7..ae50ec2989f8 100644 --- a/drivers/amlogic/media_modules/frame_provider/decoder/avs/avs.c +++ b/drivers/amlogic/media_modules/frame_provider/decoder/avs/avs.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -41,11 +42,15 @@ #include "../utils/decoder_mmu_box.h" #include "../utils/decoder_bmmu_box.h" #include "../utils/firmware.h" +#include "../../../common/chips/decoder_cpu_ver_info.h" +#include + + +#include #define DRIVER_NAME "amvdec_avs" #define MODULE_NAME "amvdec_avs" -#define ENABLE_USER_DATA #if 1/* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */ #define NV21 @@ -91,6 +96,11 @@ #define INT_AMVENCODER INT_MAILBOX_1A #endif + +#define DEC_CONTROL_FLAG_FORCE_2500_1080P_INTERLACE 0x0001 +static u32 dec_control = DEC_CONTROL_FLAG_FORCE_2500_1080P_INTERLACE; + + #define VPP_VD1_POSTBLEND (1 << 10) static int debug_flag; @@ -103,6 +113,7 @@ firmware_sel static int firmware_sel; static int disable_longcabac_trans = 1; +static int support_user_data = 1; int avs_get_debug_flag(void) { @@ -195,10 +206,10 @@ void *avsp_heap_adr; static uint long_cabac_busy; #endif -#ifdef ENABLE_USER_DATA + static void *user_data_buffer; static dma_addr_t user_data_buffer_phys; -#endif + static DECLARE_KFIFO(newframe_q, struct vframe_s *, VF_POOL_SIZE); static DECLARE_KFIFO(display_q, struct vframe_s *, VF_POOL_SIZE); static DECLARE_KFIFO(recycle_q, struct vframe_s *, VF_POOL_SIZE); @@ -303,7 +314,6 @@ static void set_frame_info(struct vframe_s *vf, unsigned int *duration) vf->flag = 0; } -#ifdef ENABLE_USER_DATA static struct work_struct userdata_push_work; /* @@ -402,7 +412,7 @@ static void UserDataHandler(void) schedule_work(&userdata_push_work); } } -#endif + #ifdef HANDLE_AVS_IRQ static irqreturn_t vavs_isr(int irq, void *dev_id) @@ -416,8 +426,9 @@ static void vavs_isr(void) u32 repeat_count; u32 picture_type; u32 buffer_index; - - unsigned int pts, pts_valid = 0, offset; + u32 frame_size; + bool force_interlaced_frame = false; + unsigned int pts, pts_valid = 0, offset = 0; u64 pts_us64; if (debug_flag & AVS_DEBUG_UCODE) { if (READ_VREG(AV_SCRATCH_E) != 0) { @@ -437,9 +448,9 @@ static void vavs_isr(void) } #endif -#ifdef ENABLE_USER_DATA + UserDataHandler(); -#endif + reg = READ_VREG(AVS_BUFFEROUT); if (reg) { @@ -450,6 +461,7 @@ static void vavs_isr(void) if (debug_flag & AVS_DEBUG_PRINT) pr_info("AVS OFFSET=%x\n", offset); if (pts_lookup_offset_us64(PTS_TYPE_VIDEO, offset, &pts, + &frame_size, 0, &pts_us64) == 0) { pts_valid = 1; #ifdef DEBUG_PTS @@ -484,6 +496,11 @@ static void vavs_isr(void) } #endif + if ((dec_control & DEC_CONTROL_FLAG_FORCE_2500_1080P_INTERLACE) + && frame_width == 1920 && frame_height == 1080) { + force_interlaced_frame = true; + } + if (throw_pb_flag && picture_type != I_PICTURE) { if (debug_flag & AVS_DEBUG_PRINT) { @@ -491,7 +508,7 @@ static void vavs_isr(void) picture_type); } WRITE_VREG(AVS_BUFFERIN, ~(1 << buffer_index)); - } else if (reg & INTERLACE_FLAG) { /* interlace */ + } else if (reg & INTERLACE_FLAG || force_interlaced_frame) { /* interlace */ throw_pb_flag = 0; if (debug_flag & AVS_DEBUG_PRINT) { @@ -544,10 +561,14 @@ static void vavs_isr(void) vf->signal_type = 0; vf->index = buffer_index; vf->duration_pulldown = 0; - vf->type = + if (force_interlaced_frame) { + vf->type = VIDTYPE_INTERLACE_TOP; + }else{ + vf->type = (reg & TOP_FIELD_FIRST_FLAG) ? VIDTYPE_INTERLACE_TOP : VIDTYPE_INTERLACE_BOTTOM; + } #ifdef NV21 vf->type |= VIDTYPE_VIU_NV21; #endif @@ -565,9 +586,10 @@ static void vavs_isr(void) decoder_bmmu_box_get_mem_handle( mm_blk_handle, buffer_index); - + decoder_do_frame_check(NULL, vf); kfifo_put(&display_q, (const struct vframe_s *)vf); + ATRACE_COUNTER(MODULE_NAME, vf->pts); vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); @@ -578,8 +600,11 @@ static void vavs_isr(void) } set_frame_info(vf, &dur); vf->bufWidth = 1920; - + if (force_interlaced_frame) + vf->pts = 0; + else vf->pts = next_pts; + if ((repeat_count > 1) && avi_flag) { /* vf->duration = vavs_amstream_dec_info.rate * * repeat_count >> 1; @@ -600,10 +625,14 @@ static void vavs_isr(void) vf->signal_type = 0; vf->index = buffer_index; vf->duration_pulldown = 0; - vf->type = - (reg & TOP_FIELD_FIRST_FLAG) ? - VIDTYPE_INTERLACE_BOTTOM : - VIDTYPE_INTERLACE_TOP; + if (force_interlaced_frame) { + vf->type = VIDTYPE_INTERLACE_BOTTOM; + } else { + vf->type = + (reg & TOP_FIELD_FIRST_FLAG) ? + VIDTYPE_INTERLACE_BOTTOM : + VIDTYPE_INTERLACE_TOP; + } #ifdef NV21 vf->type |= VIDTYPE_VIU_NV21; #endif @@ -619,6 +648,7 @@ static void vavs_isr(void) kfifo_put(&display_q, (const struct vframe_s *)vf); + ATRACE_COUNTER(MODULE_NAME, vf->pts); vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); @@ -694,8 +724,10 @@ static void vavs_isr(void) decoder_bmmu_box_get_mem_handle( mm_blk_handle, buffer_index); + decoder_do_frame_check(NULL, vf); kfifo_put(&display_q, (const struct vframe_s *)vf); + ATRACE_COUNTER(MODULE_NAME, vf->pts); vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); @@ -711,7 +743,6 @@ static void vavs_isr(void) */ WRITE_VREG(AVS_BUFFEROUT, 0); } - WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1); #ifdef HANDLE_AVS_IRQ @@ -777,6 +808,9 @@ static void vavs_vf_put(struct vframe_s *vf, void *op_arg) int vavs_dec_status(struct vdec_s *vdec, struct vdec_info *vstatus) { + if (!(stat & STAT_VDEC_RUN)) + return -1; + vstatus->frame_width = frame_width; vstatus->frame_height = frame_height; if (frame_dur != 0) @@ -824,6 +858,7 @@ static int vavs_canvas_init(void) u32 decbuf_size, decbuf_y_size, decbuf_uv_size; unsigned long buf_start; int need_alloc_buf_num; + u32 endian; vf_buf_num_used = vf_buf_num; if (buf_size <= 0x00400000) { @@ -874,37 +909,40 @@ static int vavs_canvas_init(void) continue; } #endif - + if (vdec->canvas_mode == CANVAS_BLKMODE_LINEAR) + endian = 7; + else + endian = 0; #ifdef NV21 - canvas_config(canvas_base + canvas_num * i + 0, + canvas_config_ex(canvas_base + canvas_num * i + 0, buf_start, canvas_width, canvas_height, CANVAS_ADDR_NOWRAP, - CANVAS_BLKMODE_32X32); - canvas_config(canvas_base + canvas_num * i + 1, + vdec->canvas_mode, endian); + canvas_config_ex(canvas_base + canvas_num * i + 1, buf_start + decbuf_y_size, canvas_width, canvas_height / 2, CANVAS_ADDR_NOWRAP, - CANVAS_BLKMODE_32X32); + vdec->canvas_mode, endian); #else - canvas_config(canvas_num * i + 0, + canvas_config_ex(canvas_num * i + 0, buf_start, canvas_width, canvas_height, CANVAS_ADDR_NOWRAP, - CANVAS_BLKMODE_32X32); - canvas_config(canvas_num * i + 1, + vdec->canvas_mode, endian); + canvas_config_ex(canvas_num * i + 1, buf_start + decbuf_y_size, canvas_width / 2, canvas_height / 2, CANVAS_ADDR_NOWRAP, - CANVAS_BLKMODE_32X32); - canvas_config(canvas_num * i + 2, + vdec->canvas_mode, endian); + canvas_config_ex(canvas_num * i + 2, buf_start + decbuf_y_size + decbuf_uv_size, canvas_width / 2, canvas_height / 2, CANVAS_ADDR_NOWRAP, - CANVAS_BLKMODE_32X32); + vdec->canvas_mode, endian); #endif if (debug_flag & AVS_DEBUG_PRINT) { pr_info("canvas config %d, addr %p\n", i, @@ -995,6 +1033,13 @@ void vavs_recover(void) WRITE_VREG(LONG_CABAC_SRC_ADDR, 0); } #endif + WRITE_VREG(AV_SCRATCH_N, (u32)(user_data_buffer_phys - buf_offset)); + pr_info("support_user_data = %d\n", support_user_data); + if (support_user_data) + WRITE_VREG(AV_SCRATCH_M, 1); + else + WRITE_VREG(AV_SCRATCH_M, 0); + WRITE_VREG(AV_SCRATCH_5, 0); } @@ -1101,10 +1146,12 @@ static int vavs_prot_init(void) } #endif -#ifdef ENABLE_USER_DATA WRITE_VREG(AV_SCRATCH_N, (u32)(user_data_buffer_phys - buf_offset)); - pr_debug("AV_SCRATCH_N = 0x%x\n", READ_VREG(AV_SCRATCH_N)); -#endif + pr_info("support_user_data = %d\n", support_user_data); + if (support_user_data) + WRITE_VREG(AV_SCRATCH_M, 1); + else + WRITE_VREG(AV_SCRATCH_M, 0); return r; } @@ -1195,13 +1242,14 @@ static void vavs_local_reset(void) recover_flag = 1; pr_info("error, local reset\n"); amvdec_stop(); + msleep(100); vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_RESET, NULL); vavs_local_init(); vavs_recover(); -#ifdef ENABLE_USER_DATA + reset_userdata_fifo(1); -#endif + amvdec_start(); recover_flag = 0; @@ -1259,8 +1307,6 @@ static void vavs_notify_work(struct work_struct *work) static void avs_set_clk(struct work_struct *work) { - if (frame_dur > 0 && saved_resolution != - frame_width * frame_height * (96000 / frame_dur)) { int fps = 96000 / frame_dur; saved_resolution = frame_width * frame_height * fps; @@ -1272,8 +1318,6 @@ static void avs_set_clk(struct work_struct *work) vdec_source_changed(VFORMAT_AVS, frame_width, frame_height, fps); } - - } } static void vavs_put_timer_func(unsigned long arg) @@ -1366,7 +1410,9 @@ static void vavs_put_timer_func(unsigned long arg) } - schedule_work(&set_clk_work); + if (frame_dur > 0 && saved_resolution != + frame_width * frame_height * (96000 / frame_dur)) + schedule_work(&set_clk_work); timer->expires = jiffies + PUT_INTERVAL; @@ -1488,7 +1534,7 @@ static void init_avsp_long_cabac_buf(void) static s32 vavs_init(void) { - int r, size = -1; + int ret, size = -1; char *buf = vmalloc(0x1000 * 16); if (IS_ERR_OR_NULL(buf)) @@ -1501,9 +1547,11 @@ static s32 vavs_init(void) amvdec_enable(); + vdec_enable_DMC(NULL); + vavs_local_init(); - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXM) + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXM) size = get_firmware_data(VIDEO_DEC_AVS, buf); else { if (firmware_sel == 1) @@ -1523,19 +1571,18 @@ static s32 vavs_init(void) return -1; } - if (size == 1) - pr_info("tee load ok\n"); - - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXM) - size = amvdec_loadmc_ex(VFORMAT_AVS, NULL, buf); + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXM) + ret = amvdec_loadmc_ex(VFORMAT_AVS, NULL, buf); else if (firmware_sel == 1) - size = amvdec_loadmc_ex(VFORMAT_AVS, "avs_no_cabac", buf); + ret = amvdec_loadmc_ex(VFORMAT_AVS, "avs_no_cabac", buf); else - size = amvdec_loadmc_ex(VFORMAT_AVS, NULL, buf); + ret = amvdec_loadmc_ex(VFORMAT_AVS, NULL, buf); - if (size < 0) { + if (ret < 0) { amvdec_disable(); vfree(buf); + pr_err("AVS: the %s fw loading failed, err: %x\n", + tee_enabled() ? "TEE" : "local", ret); return -EBUSY; } @@ -1544,9 +1591,9 @@ static s32 vavs_init(void) stat |= STAT_MC_LOAD; /* enable AMRISC side protocol */ - r = vavs_prot_init(); - if (r < 0) - return r; + ret = vavs_prot_init(); + if (ret < 0) + return ret; #ifdef HANDLE_AVS_IRQ if (vdec_request_irq(VDEC_IRQ_1, vavs_isr, @@ -1569,12 +1616,13 @@ static s32 vavs_init(void) #endif if (vavs_amstream_dec_info.rate != 0) { - if (!is_reset) + if (!is_reset) { vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_FR_HINT, (void *)((unsigned long) vavs_amstream_dec_info.rate)); - fr_hint_status = VDEC_HINTED; + fr_hint_status = VDEC_HINTED; + } } else fr_hint_status = VDEC_NEED_HINT; @@ -1592,7 +1640,8 @@ static s32 vavs_init(void) if (firmware_sel == 0) INIT_WORK(&long_cabac_wd_work, long_cabac_do_work); #endif - + vdec_source_changed(VFORMAT_AVS, + 1920, 1080, 30); amvdec_start(); stat |= STAT_VDEC_RUN; @@ -1608,7 +1657,7 @@ static int amvdec_avs_probe(struct platform_device *pdev) pr_info("amvdec_avs memory resource undefined.\n"); return -EFAULT; } - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXM || disable_longcabac_trans) + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXM || disable_longcabac_trans) firmware_sel = 1; if (firmware_sel == 1) { @@ -1637,7 +1686,7 @@ static int amvdec_avs_probe(struct platform_device *pdev) vavs_vdec_info_init(); -#ifdef ENABLE_USER_DATA + if (NULL == user_data_buffer) { user_data_buffer = dma_alloc_coherent(amports_get_dma_device(), @@ -1651,22 +1700,22 @@ static int amvdec_avs_probe(struct platform_device *pdev) pr_debug("user_data_buffer = 0x%p, user_data_buffer_phys = 0x%x\n", user_data_buffer, (u32)user_data_buffer_phys); } -#endif + INIT_WORK(&set_clk_work, avs_set_clk); + vdec = pdata; if (vavs_init() < 0) { pr_info("amvdec_avs init failed.\n"); kfree(gvs); gvs = NULL; - + pdata->dec_status = NULL; return -ENODEV; } - vdec = pdata; INIT_WORK(&fatal_error_wd_work, vavs_fatal_error_handler); atomic_set(&error_handler_run, 0); -#ifdef ENABLE_USER_DATA + INIT_WORK(&userdata_push_work, userdata_push_do_work); -#endif + INIT_WORK(¬ify_work, vavs_notify_work); return 0; @@ -1676,11 +1725,10 @@ static int amvdec_avs_remove(struct platform_device *pdev) { cancel_work_sync(&fatal_error_wd_work); atomic_set(&error_handler_run, 0); -#ifdef ENABLE_USER_DATA + cancel_work_sync(&userdata_push_work); -#endif + cancel_work_sync(¬ify_work); - cancel_work_sync(&set_clk_work); if (stat & STAT_VDEC_RUN) { amvdec_stop(); stat &= ~STAT_VDEC_RUN; @@ -1732,7 +1780,7 @@ static int amvdec_avs_remove(struct platform_device *pdev) } #endif if (stat & STAT_VF_HOOK) { - if (fr_hint_status == VDEC_HINTED && !is_reset) + if (fr_hint_status == VDEC_HINTED) vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_FR_END_HINT, NULL); fr_hint_status = VDEC_NO_NEED_HINT; @@ -1740,7 +1788,7 @@ static int amvdec_avs_remove(struct platform_device *pdev) stat &= ~STAT_VF_HOOK; } -#ifdef ENABLE_USER_DATA + if (user_data_buffer != NULL) { dma_free_coherent( amports_get_dma_device(), @@ -1750,8 +1798,10 @@ static int amvdec_avs_remove(struct platform_device *pdev) user_data_buffer = NULL; user_data_buffer_phys = 0; } -#endif + + amvdec_disable(); + vdec_disable_DMC(NULL); pic_type = 0; if (mm_blk_handle) { @@ -1767,6 +1817,7 @@ static int amvdec_avs_remove(struct platform_device *pdev) kfree(gvs); gvs = NULL; + cancel_work_sync(&set_clk_work); return 0; } @@ -1808,7 +1859,7 @@ static int __init amvdec_avs_driver_init_module(void) return -ENODEV; } - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXBB) + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXBB) amvdec_avs_profile.profile = "avs+"; vcodec_profile_register(&amvdec_avs_profile); @@ -1879,6 +1930,12 @@ MODULE_PARM_DESC(firmware_sel, "\n firmware_sel\n"); module_param(disable_longcabac_trans, uint, 0664); MODULE_PARM_DESC(disable_longcabac_trans, "\n disable_longcabac_trans\n"); +module_param(dec_control, uint, 0664); +MODULE_PARM_DESC(dec_control, "\n amvdec_vavs decoder control\n"); + +module_param(support_user_data, uint, 0664); +MODULE_PARM_DESC(support_user_data, "\n support_user_data\n"); + module_init(amvdec_avs_driver_init_module); module_exit(amvdec_avs_driver_remove_module); diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/avs/avs.h b/drivers/amlogic/media_modules/frame_provider/decoder/avs/avs.h index 93a04de603df..8277d202d3cd 100644 --- a/drivers/amlogic/media_modules/frame_provider/decoder/avs/avs.h +++ b/drivers/amlogic/media_modules/frame_provider/decoder/avs/avs.h @@ -1,3 +1,22 @@ +/* +* 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. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ #ifndef AVS_H_ #define AVS_H_ diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/avs/avsp_trans.c b/drivers/amlogic/media_modules/frame_provider/decoder/avs/avsp_trans.c index 2aca5ebe094d..b5dc44468278 100644 --- a/drivers/amlogic/media_modules/frame_provider/decoder/avs/avsp_trans.c +++ b/drivers/amlogic/media_modules/frame_provider/decoder/avs/avsp_trans.c @@ -1,3 +1,22 @@ +/* +* 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. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ #include #include #include diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/avs2/avs2_bufmgr.c b/drivers/amlogic/media_modules/frame_provider/decoder/avs2/avs2_bufmgr.c index df2adbb7d775..6862180a4f47 100644 --- a/drivers/amlogic/media_modules/frame_provider/decoder/avs2/avs2_bufmgr.c +++ b/drivers/amlogic/media_modules/frame_provider/decoder/avs2/avs2_bufmgr.c @@ -1,3 +1,22 @@ +/* +* 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. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ #include #include #include @@ -481,6 +500,14 @@ void Get_I_Picture_Header(struct avs2_decoder *avs2_dec) hd->curr_RPS.num_to_remove = get_param(rpm_param->p.num_to_remove_cur, "num of removed picture"); +#ifdef SANITY_CHECK + if (hd->curr_RPS.num_to_remove > 8) { + hd->curr_RPS.num_to_remove = 8; + pr_info("Warning, %s: num_to_remove %d beyond range, force to 8\n", + __func__, hd->curr_RPS.num_to_remove); + } +#endif + for (j = 0; j < hd->curr_RPS.num_to_remove; j++) { hd->curr_RPS.remove_pic[j] = get_param( @@ -663,6 +690,13 @@ void Get_PB_Picture_Header(struct avs2_decoder *avs2_dec) get_param( rpm_param->p.num_to_remove_cur, "num of removed picture"); +#ifdef SANITY_CHECK + if (hd->curr_RPS.num_to_remove > 8) { + hd->curr_RPS.num_to_remove = 8; + pr_info("Warning, %s: num_to_remove %d beyond range, force to 8\n", + __func__, hd->curr_RPS.num_to_remove); + } +#endif for (j = 0; j < hd->curr_RPS.num_to_remove; j++) { hd->curr_RPS.remove_pic[j] = @@ -1065,12 +1099,14 @@ void prepare_RefInfo(struct avs2_decoder *avs2_dec) (avs2_dec->fref[0]->imgtr_fwRefDistance <= img->tr || avs2_dec->fref[1]->imgtr_fwRefDistance >= img->tr)) { - pr_info("wrong reference configuration for B frame"); + pr_info("wrong reference configuration for B frame\n"); pr_info( "fref0 imgtr_fwRefDistance %d, fref1 imgtr_fwRefDistance %d, img->tr %d\n", avs2_dec->fref[0]->imgtr_fwRefDistance, avs2_dec->fref[1]->imgtr_fwRefDistance, img->tr); + hc->f_rec->error_mark = 1; + avs2_dec->bufmgr_error_flag = 1; return; /* exit(-1);*/ /*******************************************/ } @@ -1111,14 +1147,18 @@ void prepare_RefInfo(struct avs2_decoder *avs2_dec) && avs2_dec->fref[i]->bg_flag == 0 #ifndef NO_DISPLAY && avs2_dec->fref[i]->vf_ref == 0 - && avs2_dec->fref[i]->to_prepare_disp ==0 + && avs2_dec->fref[i]->to_prepare_disp == 0 #endif ) { break; } } - if (i == avs2_dec->ref_maxbuffer) + if (i == avs2_dec->ref_maxbuffer) { + pr_info( + "%s, warning, no enough buf\n", + __func__); i--; + } hc->f_rec = avs2_dec->fref[i]; hc->currentFrame = hc->f_rec->ref; @@ -1128,11 +1168,17 @@ void prepare_RefInfo(struct avs2_decoder *avs2_dec) hc->f_rec->temporal_id = hd->cur_layer; #endif hc->f_rec->is_output = 1; +#ifdef AML + hc->f_rec->error_mark = 0; + hc->f_rec->decoded_lcu = 0; + hc->f_rec->slice_type = img->type; +#endif hc->f_rec->refered_by_others = hd->curr_RPS.referd_by_others; if (is_avs2_print_bufmgr_detail()) pr_info( - "%s, set f_rec (cur_pic) <= fref[%d] img->tr %d coding_order %d\n", - __func__, i, img->tr, img->coding_order); + "%s, set f_rec (cur_pic) <= fref[%d] img->tr %d coding_order %d img_type %d\n", + __func__, i, img->tr, img->coding_order, + img->type); if (img->type != B_IMG) { for (j = 0; @@ -1181,24 +1227,24 @@ void prepare_RefInfo(struct avs2_decoder *avs2_dec) #if 1 /*rain*/ if (is_avs2_print_bufmgr_detail()) { - for (ii = 0; ii < avs2_dec->ref_maxbuffer; ii++) { - pr_info( + for (ii = 0; ii < avs2_dec->ref_maxbuffer; ii++) { + pr_info( "fref[%d]: index %d imgcoi_ref %d imgtr_fwRefDistance %d refered %d, is_out %d, bg %d, vf_ref %d ref_pos(%d,%d,%d,%d,%d,%d,%d)\n", ii, avs2_dec->fref[ii]->index, avs2_dec->fref[ii]->imgcoi_ref, avs2_dec->fref[ii]->imgtr_fwRefDistance, - avs2_dec->fref[ii]->refered_by_others, - avs2_dec->fref[ii]->is_output, - avs2_dec->fref[ii]->bg_flag, - avs2_dec->fref[ii]->vf_ref, - avs2_dec->fref[ii]->ref_poc[0], - avs2_dec->fref[ii]->ref_poc[1], - avs2_dec->fref[ii]->ref_poc[2], - avs2_dec->fref[ii]->ref_poc[3], - avs2_dec->fref[ii]->ref_poc[4], - avs2_dec->fref[ii]->ref_poc[5], - avs2_dec->fref[ii]->ref_poc[6] - ); + avs2_dec->fref[ii]->refered_by_others, + avs2_dec->fref[ii]->is_output, + avs2_dec->fref[ii]->bg_flag, + avs2_dec->fref[ii]->vf_ref, + avs2_dec->fref[ii]->ref_poc[0], + avs2_dec->fref[ii]->ref_poc[1], + avs2_dec->fref[ii]->ref_poc[2], + avs2_dec->fref[ii]->ref_poc[3], + avs2_dec->fref[ii]->ref_poc[4], + avs2_dec->fref[ii]->ref_poc[5], + avs2_dec->fref[ii]->ref_poc[6] + ); } } #endif @@ -1270,7 +1316,7 @@ void flushDPB(struct avs2_decoder *avs2_dec) for (j = 0; j < search_times; j++) { pos = -1; tmp_min = (1 << 20); - //search for min poi picture to display + /*search for min poi picture to display*/ for (i = 0; i < avs2_dec->outprint.buffer_num; i++) { if (avs2_dec->outprint.stdoutdata[i].tr < tmp_min) { pos = i; @@ -1281,20 +1327,23 @@ void flushDPB(struct avs2_decoder *avs2_dec) if (pos != -1) { hd->last_output = avs2_dec->outprint.stdoutdata[pos].tr; report_frame(avs2_dec, &avs2_dec->outprint, pos); - if (avs2_dec->outprint.stdoutdata[pos].typeb == BACKGROUND_IMG && avs2_dec->outprint.stdoutdata[pos].background_picture_output_flag == 0) { + if (avs2_dec->outprint.stdoutdata[pos].typeb + == BACKGROUND_IMG && + avs2_dec->outprint.stdoutdata[pos]. + background_picture_output_flag + == 0) { /*write_GB_frame(hd->p_out_background);*/ - } - else { - write_frame(avs2_dec, avs2_dec->outprint.stdoutdata[pos].tr); + } else { + write_frame(avs2_dec, + avs2_dec->outprint.stdoutdata[pos].tr); } delete_trbuffer(&avs2_dec->outprint, pos); } } - // clear dpb info - for (j = 0; j < REF_MAXBUFFER; j++) - { + /*clear dpb info*/ + for (j = 0; j < REF_MAXBUFFER; j++) { avs2_dec->fref[j]->imgtr_fwRefDistance = -256; avs2_dec->fref[j]->imgcoi_ref = -257; avs2_dec->fref[j]->temporal_id = -1; @@ -1310,19 +1359,19 @@ void cleanRefMVBufRef(int pos) { #if 0 int k, x, y; - //re-init mvbuf + /*re-init mvbuf*/ for (k = 0; k < 2; k++) { for (y = 0; y < img->height / MIN_BLOCK_SIZE; y++) { - for (x = 0; x < img->width / MIN_BLOCK_SIZE; x++) { + for (x = 0; x < img->width / MIN_BLOCK_SIZE; x++) fref[pos]->mvbuf[y][x][k] = 0; - } + } } - //re-init refbuf + /*re-init refbuf*/ for (y = 0; y < img->height / MIN_BLOCK_SIZE; y++) { - for (x = 0; x < img->width / MIN_BLOCK_SIZE ; x++) { + for (x = 0; x < img->width / MIN_BLOCK_SIZE ; x++) fref[pos]->refbuf[y][x] = -1; - } + } #endif } @@ -1510,6 +1559,7 @@ void write_frame(struct avs2_decoder *avs2_dec, int32_t pos) for (j = 0; j < avs2_dec->ref_maxbuffer; j++) { if (avs2_dec->fref[j]->imgtr_fwRefDistance == pos) { + avs2_dec->fref[j]->imgtr_fwRefDistance_bak = pos; avs2_dec->fref[j]->is_output = -1; avs2_dec->fref[j]->to_prepare_disp = avs2_dec->to_prepare_disp_count++; @@ -1523,7 +1573,8 @@ void write_frame(struct avs2_decoder *avs2_dec, int32_t pos) avs2_dec->fref[j]->temporal_id = -1; #endif if (is_avs2_print_bufmgr_detail()) - pr_info("%s, fref index %d\n", __func__, j); + pr_info("%s, fref index %d\n", + __func__, j); } break; } @@ -1689,6 +1740,7 @@ void avs2_prepare_header(struct avs2_decoder *avs2_dec, int32_t start_code) #endif img->number = 0; img->PrevPicDistanceLsb = 0; + avs2_dec->init_hw_flag = 0; } #endif @@ -1710,6 +1762,7 @@ void avs2_prepare_header(struct avs2_decoder *avs2_dec, int32_t start_code) #endif img->number = 0; img->PrevPicDistanceLsb = 0; + avs2_dec->init_hw_flag = 0; } #endif img->seq_header_indicate = 1; @@ -1772,6 +1825,8 @@ void avs2_prepare_header(struct avs2_decoder *avs2_dec, int32_t start_code) break; case SEQUENCE_END_CODE: + if (is_avs2_print_bufmgr_detail()) + pr_info("SEQUENCE_END_CODE\n"); #ifdef TO_CHECK #if SEQ_CHANGE_CHECKER if (seq_checker_buf != NULL) { @@ -1981,6 +2036,16 @@ int avs2_post_process(struct avs2_decoder *avs2_dec) /* delete the frame that will never be used*/ { int32_t i, j; + if (is_avs2_print_bufmgr_detail()) { + pr_info( + "%s, coding_order %d to remove %d buf: ", + __func__, + img->coding_order, + hd->curr_RPS.num_to_remove); + for (i = 0; i < hd->curr_RPS.num_to_remove; i++) + pr_info("%d ", hd->curr_RPS.remove_pic[i]); + pr_info("\n"); + } for (i = 0; i < hd->curr_RPS.num_to_remove; i++) { for (j = 0; j < avs2_dec->ref_maxbuffer; j++) { diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/avs2/avs2_global.h b/drivers/amlogic/media_modules/frame_provider/decoder/avs2/avs2_global.h index 7f9cca4971c7..e6c28cfddb6b 100644 --- a/drivers/amlogic/media_modules/frame_provider/decoder/avs2/avs2_global.h +++ b/drivers/amlogic/media_modules/frame_provider/decoder/avs2/avs2_global.h @@ -49,6 +49,7 @@ /* #include */ #define AML +#define SANITY_CHECK #undef NO_DISPLAY /* #include "define.h" */ @@ -792,10 +793,24 @@ struct avs2_frame_s { int vf_ref; int decode_idx; int slice_type; + int32_t imgtr_fwRefDistance_bak; + int32_t error_mark; + int32_t decoded_lcu; #endif #ifndef MV_USE_FIXED_BUF int mv_buf_index; #endif + + /* picture qos infomation*/ + int max_qp; + int avg_qp; + int min_qp; + int max_skip; + int avg_skip; + int min_skip; + int max_mv; + int min_mv; + int avg_mv; }; @@ -1585,6 +1600,17 @@ union param_u { uint16_t chroma_quant_param_delta_cb; uint16_t chroma_quant_param_delta_cr; uint16_t loop_filter_disable; + + uint16_t video_signal_type; + uint16_t color_description; + uint16_t display_primaries_x[3]; + uint16_t display_primaries_y[3]; + uint16_t white_point_x; + uint16_t white_point_y; + uint16_t max_display_mastering_luminance; + uint16_t min_display_mastering_luminance; + uint16_t max_content_light_level; + uint16_t max_picture_average_light_level; } p; struct { uint16_t padding[ALF_BEGIN - RPM_BEGIN]; @@ -1629,7 +1655,8 @@ struct avs2_decoder { int32_t lcu_y_num; int32_t lcu_total; int32_t ref_maxbuffer; - int32_t to_prepare_disp_count; + int32_t to_prepare_disp_count; + int8_t bufmgr_error_flag; #endif }; diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/avs2/vavs2.c b/drivers/amlogic/media_modules/frame_provider/decoder/avs2/vavs2.c index 16b3c29abefa..cc221610d586 100644 --- a/drivers/amlogic/media_modules/frame_provider/decoder/avs2/vavs2.c +++ b/drivers/amlogic/media_modules/frame_provider/decoder/avs2/vavs2.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -53,11 +54,14 @@ #include #include "../utils/config_parser.h" #include "../utils/firmware.h" +#include "../../../common/chips/decoder_cpu_ver_info.h" +#include +#include +#define I_ONLY_SUPPORT #define MIX_STREAM_SUPPORT -#define SUPPORT_4K2K - #define G12A_BRINGUP_DEBUG +#define CONSTRAIN_MAX_BUF_NUM #include "vavs2.h" #define HEVC_SHIFT_LENGTH_PROTECT 0x313a @@ -72,6 +76,7 @@ #define HEVC_SAO_MMU_VH0_ADDR 0x363a #define HEVC_SAO_MMU_STATUS 0x3639 + /* * AVS2_DEC_STATUS define */ @@ -109,6 +114,7 @@ /*cmd*/ #define AVS2_10B_DISCARD_NAL 0xf0 +#define AVS2_SEARCH_NEW_PIC 0xf1 #define AVS2_ACTION_ERROR 0xfe #define HEVC_ACTION_ERROR 0xfe #define AVS2_ACTION_DONE 0xff @@ -139,8 +145,67 @@ #define PARSER_CMD_SKIP_CFG_2 0x001b1910 + #define PARSER_CMD_NUMBER 37 +static unsigned short parser_cmd[PARSER_CMD_NUMBER] = { +0x0401, +0x8401, +0x0800, +0x0402, +0x9002, +0x1423, +0x8CC3, +0x1423, +0x8804, +0x9825, +0x0800, +0x04FE, +0x8406, +0x8411, +0x1800, +0x8408, +0x8409, +0x8C2A, +0x9C2B, +0x1C00, +0x840F, +0x8407, +0x8000, +0x8408, +0x2000, +0xA800, +0x8410, +0x04DE, +0x840C, +0x840D, +0xAC00, +0xA000, +0x08C0, +0x08E0, +0xA40E, +0xFC00, +0x7C00 +}; + +static int32_t g_WqMDefault4x4[16] = { + 64, 64, 64, 68, + 64, 64, 68, 72, + 64, 68, 76, 80, + 72, 76, 84, 96 +}; + + +static int32_t g_WqMDefault8x8[64] = { + 64, 64, 64, 64, 68, 68, 72, 76, + 64, 64, 64, 68, 72, 76, 84, 92, + 64, 64, 68, 72, 76, 80, 88, 100, + 64, 68, 72, 80, 84, 92, 100, 112, + 68, 72, 80, 84, 92, 104, 112, 128, + 76, 80, 84, 92, 104, 116, 132, 152, + 96, 100, 104, 116, 124, 140, 164, 188, + 104, 108, 116, 128, 152, 172, 192, 216 +}; /*#define HEVC_PIC_STRUCT_SUPPORT*/ /* to remove, fix build error */ @@ -148,18 +213,13 @@ #define MULTI_INSTANCE_SUPPORT /* #define ERROR_HANDLE_DEBUG */ -#if 0 /* MESON_CPU_TYPE == MESON_CPU_TYPE_MESON8B*/ -#undef SUPPORT_4K2K -#else -#define SUPPORT_4K2K -#endif #ifndef STAT_KTHREAD #define STAT_KTHREAD 0x40 #endif #ifdef MULTI_INSTANCE_SUPPORT -#define MAX_DECODE_INSTANCE_NUM 9 +#define MAX_DECODE_INSTANCE_NUM 12 #define MULTI_DRIVER_NAME "ammvdec_avs2" #define lock_buffer(dec, flags) \ @@ -178,7 +238,7 @@ static unsigned int input_empty[MAX_DECODE_INSTANCE_NUM]; static unsigned int not_run_ready[MAX_DECODE_INSTANCE_NUM]; #ifdef G12A_BRINGUP_DEBUG -static u32 decode_timeout_val; +static u32 decode_timeout_val = 200; #else static u32 decode_timeout_val = 200; #endif @@ -190,6 +250,9 @@ static u32 work_buf_size = 32 * 1024 * 1024; #endif static u32 mv_buf_margin; +static int pre_decode_buf_level = 0x1000; +static u32 again_threshold = 0x40; + /* DOUBLE_WRITE_MODE is enabled only when NV21 8 bit output is needed */ /* double_write_mode: 0, no double write @@ -258,13 +321,14 @@ static u32 video_signal_type; static u32 pts_unstable; static u32 on_no_keyframe_skiped; +static u32 force_video_signal_type; +static u32 enable_force_video_signal_type; +#define VIDEO_SIGNAL_TYPE_AVAILABLE_MASK 0x20000000 -#define PROB_SIZE (496 * 2 * 4) -#define PROB_BUF_SIZE (0x5000) -#define COUNT_BUF_SIZE (0x300 * 4 * 4) -/*compute_losless_comp_body_size(4096, 2304, 1) = 18874368(0x1200000)*/ -#define MAX_FRAME_4K_NUM 0x1200 -#define FRAME_MMU_MAP_SIZE (MAX_FRAME_4K_NUM * 4) +static const char * const video_format_names[] = { + "component", "PAL", "NTSC", "SECAM", + "MAC", "unspecified", "Reserved", "Reserved" +}; static inline int div_r32(int64_t m, int n) { @@ -272,8 +336,9 @@ static inline int div_r32(int64_t m, int n) return (int)(m/n) */ #ifndef CONFIG_ARM64 - do_div(m, n); - return (int)m; + int64_t qu = 0; + qu = div_s64(m, n); + return (int)qu; #else return (int)(m/n); #endif @@ -346,20 +411,25 @@ typedef unsigned short u16; #define AVS2_DBG_OUT_PTS 0x10 #define AVS2_DBG_PRINT_SOURCE_LINE 0x20 #define AVS2_DBG_PRINT_PARAM 0x40 +#define AVS2_DBG_PRINT_PIC_LIST 0x80 #define AVS2_DBG_SEND_PARAM_WITH_REG 0x100 #define AVS2_DBG_MERGE 0x200 #define AVS2_DBG_DBG_LF_PRINT 0x400 #define AVS2_DBG_REG 0x800 +#define AVS2_DBG_PIC_LEAK 0x1000 +#define AVS2_DBG_PIC_LEAK_WAIT 0x2000 +#define AVS2_DBG_HDR_INFO 0x4000 #define AVS2_DBG_DIS_LOC_ERROR_PROC 0x10000 #define AVS2_DBG_DIS_SYS_ERROR_PROC 0x20000 #define AVS2_DBG_DUMP_PIC_LIST 0x40000 #define AVS2_DBG_TRIG_SLICE_SEGMENT_PROC 0x80000 -#define AVS2_DBG_HW_RESET 0x100000 +#define AVS2_DBG_FORCE_UNCOMPRESS 0x100000 #define AVS2_DBG_LOAD_UCODE_FROM_FILE 0x200000 #define AVS2_DBG_FORCE_SEND_AGAIN 0x400000 #define AVS2_DBG_DUMP_DATA 0x800000 -#define AVS2_DBG_CACHE 0x1000000 -#define AVS2_DBG_CACHE_HIT_RATE 0x2000000 +#define AVS2_DBG_DUMP_LMEM_BUF 0x1000000 +#define AVS2_DBG_DUMP_RPM_BUF 0x2000000 +#define AVS2_DBG_CACHE 0x4000000 #define IGNORE_PARAM_FROM_CONFIG 0x8000000 /*MULTI_INSTANCE_SUPPORT*/ #define PRINT_FLAG_ERROR 0 @@ -368,11 +438,15 @@ typedef unsigned short u16; #define PRINT_FLAG_VDEC_DATA 0x80000000 #define PRINT_LINE() \ - if (debug & AVS2_DBG_PRINT_SOURCE_LINE)\ - pr_info("%s line %d\n", __func__, __LINE__) + do { \ + if (debug & AVS2_DBG_PRINT_SOURCE_LINE)\ + pr_info("%s line %d\n", __func__, __LINE__);\ + } while (0) static u32 debug; +static u32 debug_again; + bool is_avs2_print_param(void) { bool ret = false; @@ -433,6 +507,7 @@ static void WRITE_VREG_DBG2(unsigned adr, unsigned val) #ifdef AVS2_10B_MMU #define MMU_COMPRESS_HEADER_SIZE 0x48000 +#define MMU_COMPRESS_8K_HEADER_SIZE 0x48000*4 #endif #define INVALID_IDX -1 /* Invalid buffer index.*/ @@ -446,16 +521,16 @@ static void WRITE_VREG_DBG2(unsigned adr, unsigned val) #define FRAME_CONTEXTS (1 << FRAME_CONTEXTS_LOG2) /*buffer + header buffer + workspace*/ #ifdef MV_USE_FIXED_BUF -#define MAX_BMMU_BUFFER_NUM (FRAME_BUFFERS + HEADER_FRAME_BUFFERS + 1) +#define MAX_BMMU_BUFFER_NUM ((FRAME_BUFFERS + HEADER_FRAME_BUFFERS + 1)+1) #define VF_BUFFER_IDX(n) (n) -#define HEADER_BUFFER_IDX(n) (FRAME_BUFFERS + n) -#define WORK_SPACE_BUF_ID (FRAME_BUFFERS + HEADER_FRAME_BUFFERS) +#define HEADER_BUFFER_IDX(n) (FRAME_BUFFERS + n+1) +#define WORK_SPACE_BUF_ID (FRAME_BUFFERS + HEADER_FRAME_BUFFERS+1) #else -#define MAX_BMMU_BUFFER_NUM ((FRAME_BUFFERS * 2) + HEADER_FRAME_BUFFERS + 1) +#define MAX_BMMU_BUFFER_NUM (((FRAME_BUFFERS*2)+HEADER_FRAME_BUFFERS+1)+1) #define VF_BUFFER_IDX(n) (n) -#define HEADER_BUFFER_IDX(n) (FRAME_BUFFERS + n) -#define MV_BUFFER_IDX(n) ((FRAME_BUFFERS * 2) + n) -#define WORK_SPACE_BUF_ID ((FRAME_BUFFERS * 2) + HEADER_FRAME_BUFFERS) +#define HEADER_BUFFER_IDX(n) (FRAME_BUFFERS + n+1) +#define MV_BUFFER_IDX(n) ((FRAME_BUFFERS * 2) + n+1) +#define WORK_SPACE_BUF_ID ((FRAME_BUFFERS * 2) + HEADER_FRAME_BUFFERS+1) #endif /* static void set_canvas(struct AVS2Decoder_s *dec, @@ -554,10 +629,14 @@ struct AVS2Decoder_s { u32 frame_ar; int fatal_error; uint8_t init_flag; + uint8_t first_sc_checked; uint8_t process_busy; #define PROC_STATE_INIT 0 -#define PROC_STATE_DECODESLICE 1 -#define PROC_STATE_SENDAGAIN 2 +#define PROC_STATE_HEAD_DONE 1 +#define PROC_STATE_DECODING 2 +#define PROC_STATE_HEAD_AGAIN 3 +#define PROC_STATE_DECODE_AGAIN 4 +#define PROC_STATE_TEST1 5 uint8_t process_state; u32 ucode_pause_pos; @@ -594,6 +673,7 @@ struct AVS2Decoder_s { unsigned int losless_comp_body_size; u32 video_signal_type; + u32 video_ori_signal_type; int pts_mode; int last_lookup_pts; @@ -629,9 +709,11 @@ struct AVS2Decoder_s { int slice_idx; uint8_t wait_buf; uint8_t error_flag; + unsigned int bufmgr_error_count; /* bit 0, for decoding; bit 1, for displaying */ uint8_t ignore_bufmgr_error; + uint8_t skip_PB_before_I; int PB_skip_mode; int PB_skip_count_after_decoding; /*hw*/ @@ -658,7 +740,22 @@ struct AVS2Decoder_s { int32_t m_varIndTab[NO_VAR_BINS]; struct vframe_s vframe_dummy; - + /* start_decoding_flag, + bit 0, SEQ ready + bit 1, I ready + */ + unsigned char start_decoding_flag; + uint32_t mpred_abv_start_addr; + uint32_t mpred_abv_start_addr_bak; + u8 next_again_flag; + u32 pre_parser_wr_ptr; + int need_cache_size; + u64 sc_start_time; +#ifdef I_ONLY_SUPPORT + u32 i_only; +#endif + int frameinfo_enable; + struct vframe_qos_s vframe_qos; }; static int compute_losless_comp_body_size( @@ -702,6 +799,31 @@ static int avs2_print_cont(struct AVS2Decoder_s *dec, return 0; } +#define PROB_SIZE (496 * 2 * 4) +#define PROB_BUF_SIZE (0x5000) +#define COUNT_BUF_SIZE (0x300 * 4 * 4) +/*compute_losless_comp_body_size(4096, 2304, 1) = 18874368(0x1200000)*/ +#define MAX_FRAME_4K_NUM 0x1200 +#define MAX_FRAME_8K_NUM 0x4800 +#define MAX_SIZE_4K (4096 * 2304) +#define IS_8K_SIZE(w, h) (((w) * (h)) > MAX_SIZE_4K) + +static int get_frame_mmu_map_size(struct AVS2Decoder_s *dec) +{ + if ((get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) && + (IS_8K_SIZE(dec->init_pic_w, dec->init_pic_h))) + return (MAX_FRAME_8K_NUM * 4); + return (MAX_FRAME_4K_NUM * 4); +} + +static int get_compress_header_size(struct AVS2Decoder_s *dec) +{ + if ((get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) && + (IS_8K_SIZE(dec->init_pic_w, dec->init_pic_h))) + return MMU_COMPRESS_8K_HEADER_SIZE; + return MMU_COMPRESS_HEADER_SIZE; +} + static void reset_process_time(struct AVS2Decoder_s *dec) { if (dec->start_process_time) { @@ -720,14 +842,20 @@ static void start_process_time(struct AVS2Decoder_s *dec) dec->last_lcu_idx = 0; } +static void update_decoded_pic(struct AVS2Decoder_s *dec); + static void timeout_process(struct AVS2Decoder_s *dec) { + struct avs2_decoder *avs2_dec = &dec->avs2_dec; + struct avs2_frame_s *cur_pic = avs2_dec->hc.cur_pic; dec->timeout_num++; amhevc_stop(); avs2_print(dec, 0, "%s decoder timeout\n", __func__); - + if (cur_pic) + cur_pic->error_mark = 1; dec->dec_result = DEC_RESULT_DONE; + update_decoded_pic(dec); reset_process_time(dec); vdec_schedule_work(&dec->work); } @@ -788,7 +916,7 @@ static int get_double_write_ratio(struct AVS2Decoder_s *dec, return ratio; } -#define MAX_4K_NUM 0x1200 +//#define MAX_4K_NUM 0x1200 #ifdef AVS2_10B_MMU int avs2_alloc_mmu( struct AVS2Decoder_s *dec, @@ -800,13 +928,36 @@ int avs2_alloc_mmu( { int bit_depth_10 = (bit_depth == AVS2_BITS_10); int picture_size; - int cur_mmu_4k_number; + int cur_mmu_4k_number, max_frame_num; +#ifdef DYNAMIC_ALLOC_HEAD + unsigned long buf_addr; + struct avs2_frame_s *pic = dec->avs2_dec.hc.cur_pic; + if (pic->header_adr == 0) { + if (decoder_bmmu_box_alloc_buf_phy + (dec->bmmu_box, + HEADER_BUFFER_IDX(cur_buf_idx), + MMU_COMPRESS_HEADER_SIZE, + DRIVER_HEADER_NAME, + &buf_addr) < 0){ + avs2_print(dec, 0, + "%s malloc compress header failed %d\n", + DRIVER_HEADER_NAME, cur_buf_idx); + dec->fatal_error |= DECODER_FATAL_ERROR_NO_MEM; + return -1; + } else + pic->header_adr = buf_addr; + } +#endif picture_size = compute_losless_comp_body_size( dec, pic_width, pic_height, bit_depth_10); cur_mmu_4k_number = ((picture_size + (1 << 12) - 1) >> 12); - if (cur_mmu_4k_number > MAX_4K_NUM) { + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) + max_frame_num = MAX_FRAME_8K_NUM; + else + max_frame_num = MAX_FRAME_4K_NUM; + if (cur_mmu_4k_number > max_frame_num) { pr_err("over max !! cur_mmu_4k_number 0x%x width %d height %d\n", cur_mmu_4k_number, pic_width, pic_height); return -1; @@ -819,7 +970,8 @@ int avs2_alloc_mmu( } #endif -#ifndef MV_USE_FIXED_BUF +#if 0 +/*ndef MV_USE_FIXED_BUF*/ static void dealloc_mv_bufs(struct AVS2Decoder_s *dec) { int i; @@ -986,6 +1138,7 @@ static int get_free_buf_count(struct AVS2Decoder_s *dec) && avs2_dec->fref[i]->bg_flag == 0 #ifndef NO_DISPLAY && avs2_dec->fref[i]->vf_ref == 0 + && avs2_dec->fref[i]->to_prepare_disp == 0 #endif ) { count++; @@ -995,6 +1148,57 @@ static int get_free_buf_count(struct AVS2Decoder_s *dec) return count; } +#ifdef CONSTRAIN_MAX_BUF_NUM +static int get_vf_ref_only_buf_count(struct AVS2Decoder_s *dec) +{ + struct avs2_decoder *avs2_dec = &dec->avs2_dec; + int i; + int count = 0; + for (i = 0; i < avs2_dec->ref_maxbuffer; i++) { + if ((avs2_dec->fref[i]->imgcoi_ref < -256 +#if 0 + || abs(avs2_dec->fref[i]-> + imgtr_fwRefDistance - img->tr) >= 128 +#endif + ) && avs2_dec->fref[i]->is_output == -1 + && avs2_dec->fref[i]->bg_flag == 0 +#ifndef NO_DISPLAY + && avs2_dec->fref[i]->vf_ref > 0 + && avs2_dec->fref[i]->to_prepare_disp == 0 +#endif + ) { + count++; + } + } + + return count; +} + +static int get_used_buf_count(struct AVS2Decoder_s *dec) +{ + struct avs2_decoder *avs2_dec = &dec->avs2_dec; + int i; + int count = 0; + for (i = 0; i < avs2_dec->ref_maxbuffer; i++) { + if ((avs2_dec->fref[i]->imgcoi_ref >= -256 +#if 0 + || abs(avs2_dec->fref[i]-> + imgtr_fwRefDistance - img->tr) >= 128 +#endif + ) || avs2_dec->fref[i]->is_output != -1 + || avs2_dec->fref[i]->bg_flag != 0 +#ifndef NO_DISPLAY + || avs2_dec->fref[i]->vf_ref != 0 + || avs2_dec->fref[i]->to_prepare_disp != 0 +#endif + ) { + count++; + } + } + + return count; +} +#endif int avs2_bufmgr_init(struct AVS2Decoder_s *dec, struct BuffInfo_s *buf_spec_i, struct buff_s *mc_buf_i) { @@ -1021,6 +1225,7 @@ int avs2_bufmgr_init(struct AVS2Decoder_s *dec, struct BuffInfo_s *buf_spec_i, /*int m_uiMaxCUHeight = 1<<7;*/ dec->wait_buf = 0; dec->error_flag = 0; + dec->skip_PB_before_I = 0; dec->pts_mode = PTS_NORMAL; dec->last_pts = 0; @@ -1035,6 +1240,7 @@ int avs2_bufmgr_init(struct AVS2Decoder_s *dec, struct BuffInfo_s *buf_spec_i, dec->buf_num = 0; + dec->bufmgr_error_count = 0; return 0; } @@ -1074,19 +1280,23 @@ static u32 decode_pic_begin; static uint slice_parse_begin; static u32 step; #ifdef MIX_STREAM_SUPPORT -#ifdef SUPPORT_4K2K static u32 buf_alloc_width = 4096; static u32 buf_alloc_height = 2304; -#else -static u32 buf_alloc_width = 1920; -static u32 buf_alloc_height = 1088; -#endif + static u32 dynamic_buf_num_margin; #else static u32 buf_alloc_width; static u32 buf_alloc_height; static u32 dynamic_buf_num_margin = 7; #endif +#ifdef CONSTRAIN_MAX_BUF_NUM +static u32 run_ready_max_vf_only_num; +static u32 run_ready_display_q_num; + /*0: not check + 0xff: avs2_dec.ref_maxbuffer + */ +static u32 run_ready_max_buf_num = 0xff; +#endif static u32 buf_alloc_depth = 10; static u32 buf_alloc_size; /* @@ -1123,23 +1333,20 @@ static u32 max_decoding_time; error handling */ /*error_handle_policy: -bit 0: 0, auto skip error_skip_nal_count nals before error recovery; -1, skip error_skip_nal_count nals before error recovery; -bit 1 (valid only when bit0 == 1): -1, wait vps/sps/pps after error recovery; -bit 2 (valid only when bit0 == 0): -0, auto search after error recovery (avs2_recover() called); -1, manual search after error recovery -(change to auto search after get IDR: WRITE_VREG(NAL_SEARCH_CTL, 0x2)) - -bit 4: 0, set error_mark after reset/recover - 1, do not set error_mark after reset/recover -bit 5: 0, check total lcu for every picture - 1, do not check total lcu - +bit 0: search seq again if buffer mgr error occur + (buffer mgr error count need big than + re_search_seq_threshold) +bit 1: 1, display from I picture; + 0, display from any correct pic */ -static u32 error_handle_policy; +static u32 error_handle_policy = 1; +/* +re_search_seq_threshold: + bit 7~0: buffer mgr error research seq count + bit 15~8: frame count threshold +*/ +static u32 re_search_seq_threshold = 0x800; /*0x8;*/ /*static u32 parser_sei_enable = 1;*/ static u32 max_buf_num = (REF_BUFFER + 1); @@ -1150,7 +1357,7 @@ static DEFINE_MUTEX(vavs2_mutex); #define HEVC_DEC_STATUS_REG HEVC_ASSIST_SCRATCH_0 #define HEVC_RPM_BUFFER HEVC_ASSIST_SCRATCH_1 -#define HEVC_SHORT_TERM_RPS HEVC_ASSIST_SCRATCH_2 +#define AVS2_ALF_SWAP_BUFFER HEVC_ASSIST_SCRATCH_2 #define HEVC_RCS_BUFFER HEVC_ASSIST_SCRATCH_3 #define HEVC_SPS_BUFFER HEVC_ASSIST_SCRATCH_4 #define HEVC_PPS_BUFFER HEVC_ASSIST_SCRATCH_5 @@ -1197,17 +1404,22 @@ bit [17]: for NAL_SEI when bit0 is 0: bit [31:20]: used by ucode for debug purpose */ #define NAL_SEARCH_CTL HEVC_ASSIST_SCRATCH_I - /*set before start decoder*/ + /*DECODE_MODE: set before start decoder + bit 7~0: decode mode + bit 23~16: start_decoding_flag + bit [0] - SEQ_ready + bit [2:1] - I Picture Count + bit 31~24: chip feature + */ #define DECODE_MODE HEVC_ASSIST_SCRATCH_J #define DECODE_STOP_POS HEVC_ASSIST_SCRATCH_K - /*read only*/ #define CUR_NAL_UNIT_TYPE HEVC_ASSIST_SCRATCH_J -#define RPM_BUF_SIZE (0x400 * 2) -#define LMEM_BUF_SIZE (0x400 * 2) +#define RPM_BUF_SIZE (0x600 * 2) +#define LMEM_BUF_SIZE (0x600 * 2) -#define WORK_BUF_SPEC_NUM 2 +#define WORK_BUF_SPEC_NUM 3 static struct BuffInfo_s amvavs2_workbuff_spec[WORK_BUF_SPEC_NUM] = { { /* 8M bytes */ @@ -1392,6 +1604,92 @@ static struct BuffInfo_s amvavs2_workbuff_spec[WORK_BUF_SPEC_NUM] = { /* 4096x2304 , 0x120000 per buffer */ .buf_size = 0x120000 * FRAME_BUFFERS, }, +#endif + .rpm = { + .buf_size = RPM_BUF_SIZE, + }, + .lmem = { + .buf_size = 0x400 * 2, + } + }, + { + .max_width = 4096 * 2, + .max_height = 2304 * 2, + .ipp = { + /*IPP work space calculation : 4096 * (Y+CbCr+Flags) = 12k, + round to 16k*/ + .buf_size = 0x4000 * 2, + }, + .sao_abv = { + .buf_size = 0x30000 * 2, + }, + .sao_vb = { + .buf_size = 0x30000 * 2, + }, + .short_term_rps = { + /*SHORT_TERM_RPS - Max 64 set, 16 entry every set, + total 64x16x2 = 2048 bytes (0x800)*/ + .buf_size = 0x800, + }, + .rcs = { + /*RCS STORE AREA - Max 16 RCS, each has 32 bytes, + total 0x0400 bytes*/ + .buf_size = 0x400, + }, + .sps = { + /*SPS STORE AREA - Max 16 SPS, each has 0x80 bytes, + total 0x0800 bytes*/ + .buf_size = 0x800, + }, + .pps = { + /*PPS STORE AREA - Max 64 PPS, each has 0x80 bytes, total + 0x2000 bytes*/ + .buf_size = 0x2000, + }, + .sao_up = { + /*SAO UP STORE AREA - Max 640(10240/16) LCU, each has 16 bytes i + total 0x2800 bytes*/ + .buf_size = 0x2800 * 2, + }, + .swap_buf = { + /*256cyclex64bit = 2K bytes 0x800 (only 144 cycles valid)*/ + .buf_size = 0x800, + }, + .swap_buf2 = { + .buf_size = 0x800, + }, + .scalelut = { + /*support up to 32 SCALELUT 1024x32 = 32Kbytes (0x8000)*/ + .buf_size = 0x8000 * 2, + }, + .dblk_para = { + .buf_size = 0x40000 * 2, + }, + .dblk_data = { + .buf_size = 0x80000 * 2, + }, + .dblk_data2 = { + .buf_size = 0x80000 * 2, + }, +#ifdef AVS2_10B_MMU + .mmu_vbh = { + .buf_size = 0x5000 * 2, /*2*16*2304/4, 4K*/ + }, +#if 0 + .cm_header = { + /*0x44000 = ((1088*2*1024*4)/32/4)*(32/8)*/ + .buf_size = MMU_COMPRESS_8K_HEADER_SIZE * 17, + }, +#endif +#endif + .mpred_above = { + .buf_size = 0x8000 * 2, + }, +#ifdef MV_USE_FIXED_BUF + .mpred_mv = { + /*4k2k , 0x100000 per buffer*/ + .buf_size = 0x120000 * FRAME_BUFFERS * 4, + }, #endif .rpm = { .buf_size = RPM_BUF_SIZE, @@ -1582,7 +1880,8 @@ static void init_buff_spec(struct AVS2Decoder_s *dec, static void uninit_mmu_buffers(struct AVS2Decoder_s *dec) { -#ifndef MV_USE_FIXED_BUF +#if 0 +/*ndef MV_USE_FIXED_BUF*/ dealloc_mv_bufs(dec); #endif decoder_mmu_box_free(dec->mmu_box); @@ -1776,12 +2075,14 @@ static int config_pic(struct AVS2Decoder_s *dec, #endif #ifdef AVS2_10B_MMU +#ifndef DYNAMIC_ALLOC_HEAD pic->header_adr = decoder_bmmu_box_get_phy_addr( dec->bmmu_box, HEADER_BUFFER_IDX(pic->index)); avs2_print(dec, AVS2_DBG_BUFMGR_MORE, "buf_size %d, MMU header_adr %d: %ld\n", buf_size, pic->index, pic->header_adr); +#endif #endif i = pic->index; @@ -1820,7 +2121,7 @@ static int config_pic(struct AVS2Decoder_s *dec, dec->mc_buf->buf_end) y_adr = dec->mc_buf->buf_start + i * buf_size; else {*/ - if (buf_size > 0) { + if (buf_size > 0 && pic->cma_alloc_addr == 0) { ret = decoder_bmmu_box_alloc_buf_phy(dec->bmmu_box, VF_BUFFER_IDX(i), buf_size, DRIVER_NAME, @@ -1888,9 +2189,15 @@ static int config_pic(struct AVS2Decoder_s *dec, } #ifdef MV_USE_FIXED_BUF #ifdef G12A_BRINGUP_DEBUG - pic->mpred_mv_wr_start_addr = - dec->work_space_buf->mpred_mv.buf_start + + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) { + pic->mpred_mv_wr_start_addr = + dec->work_space_buf->mpred_mv.buf_start + + (pic->index * 0x120000 * 4); + } else { + pic->mpred_mv_wr_start_addr = + dec->work_space_buf->mpred_mv.buf_start + (pic->index * 0x120000); + } #else pic->mpred_mv_wr_start_addr = dec->work_space_buf->mpred_mv.buf_start + @@ -1937,12 +2244,25 @@ static void init_pic_list(struct AVS2Decoder_s *dec, struct avs2_decoder *avs2_dec = &dec->avs2_dec; struct avs2_frame_s *pic; #ifdef AVS2_10B_MMU + unsigned long buf_addr1; /*alloc AVS2 compress header first*/ + if (decoder_bmmu_box_alloc_buf_phy + (dec->bmmu_box, + HEADER_BUFFER_IDX(-1), get_compress_header_size(dec), + DRIVER_HEADER_NAME, + &buf_addr1) < 0){ + avs2_print(dec, 0, + "%s malloc compress header failed %d\n", + DRIVER_HEADER_NAME, -1); + dec->fatal_error |= DECODER_FATAL_ERROR_NO_MEM; + return; + } +#ifndef DYNAMIC_ALLOC_HEAD for (i = 0; i < dec->used_buf_num; i++) { unsigned long buf_addr; if (decoder_bmmu_box_alloc_buf_phy (dec->bmmu_box, - HEADER_BUFFER_IDX(i), MMU_COMPRESS_HEADER_SIZE, + HEADER_BUFFER_IDX(i), get_compress_header_size(dec), DRIVER_HEADER_NAME, &buf_addr) < 0){ avs2_print(dec, 0, @@ -1953,6 +2273,10 @@ static void init_pic_list(struct AVS2Decoder_s *dec, } } #endif +#endif + dec->frame_height = avs2_dec->img.height; + dec->frame_width = avs2_dec->img.width; + for (i = 0; i < dec->used_buf_num; i++) { if (i == (dec->used_buf_num - 1)) pic = avs2_dec->m_bg; @@ -1994,12 +2318,14 @@ static void init_pic_list_hw(struct AVS2Decoder_s *dec) struct avs2_decoder *avs2_dec = &dec->avs2_dec; struct avs2_frame_s *pic; /*WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CONF_ADDR, 0x0);*/ +#if 0 WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CONF_ADDR, (0x1 << 1) | (0x1 << 2)); #ifdef DUAL_CORE_64 WRITE_VREG(HEVC2_HEVCD_MPP_ANC2AXI_TBL_CONF_ADDR, (0x1 << 1) | (0x1 << 2)); +#endif #endif for (i = 0; i < dec->used_buf_num; i++) { if (i == (dec->used_buf_num - 1)) @@ -2008,11 +2334,21 @@ static void init_pic_list_hw(struct AVS2Decoder_s *dec) pic = avs2_dec->fref[i]; if (pic->index < 0) break; - #ifdef AVS2_10B_MMU /*WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CMD_ADDR, pic->header_adr | (pic->mc_canvas_y << 8)|0x1);*/ + WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CONF_ADDR, + (0x1 << 1) | (pic->index << 8)); + +#ifdef DUAL_CORE_64 + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXLX2) + WRITE_VREG(HEVC2_MPP_ANC2AXI_TBL_CONF_ADDR, + (0x1 << 1) | (pic->index << 8)); + else + WRITE_VREG(HEVC2_HEVCD_MPP_ANC2AXI_TBL_CONF_ADDR, + (0x1 << 1) | (pic->index << 8)); +#endif WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_DATA, pic->header_adr >> 5); #else /*WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CMD_ADDR, @@ -2060,33 +2396,32 @@ static void init_pic_list_hw(struct AVS2Decoder_s *dec) static void dump_pic_list(struct AVS2Decoder_s *dec) { -#if 0 + int ii; struct avs2_decoder *avs2_dec = &dec->avs2_dec; - int i; - for (i = 0; i < FRAME_BUFFERS; i++) { - struct avs2_frame_s *pic = - avs2_dec->fref[i]; - if (pic == NULL) - continue; - avs2_print(dec, - 0, - "Buf(%d) index %d mv_buf_index %d vf_ref %d dec_idx %d slice_type %d w/h %d/%d adr%ld\n", - i, - pic->index, -#ifndef MV_USE_FIXED_BUF - pic->mv_buf_index, -#else - -1, -#endif - pic->vf_ref, - pic->decode_idx, - pic->slice_type, - pic->pic_w, - pic->pic_h, - pic->cma_alloc_addr - ); + for (ii = 0; ii < avs2_dec->ref_maxbuffer; ii++) { + avs2_print(dec, 0, + "fref[%d]: index %d decode_id %d mvbuf %d imgcoi_ref %d imgtr_fwRefDistance %d refered %d, pre %d is_out %d, bg %d, vf_ref %d error %d lcu %d ref_pos(%d,%d,%d,%d,%d,%d,%d)\n", + ii, avs2_dec->fref[ii]->index, + avs2_dec->fref[ii]->decode_idx, + avs2_dec->fref[ii]->mv_buf_index, + avs2_dec->fref[ii]->imgcoi_ref, + avs2_dec->fref[ii]->imgtr_fwRefDistance, + avs2_dec->fref[ii]->refered_by_others, + avs2_dec->fref[ii]->to_prepare_disp, + avs2_dec->fref[ii]->is_output, + avs2_dec->fref[ii]->bg_flag, + avs2_dec->fref[ii]->vf_ref, + avs2_dec->fref[ii]->error_mark, + avs2_dec->fref[ii]->decoded_lcu, + avs2_dec->fref[ii]->ref_poc[0], + avs2_dec->fref[ii]->ref_poc[1], + avs2_dec->fref[ii]->ref_poc[2], + avs2_dec->fref[ii]->ref_poc[3], + avs2_dec->fref[ii]->ref_poc[4], + avs2_dec->fref[ii]->ref_poc[5], + avs2_dec->fref[ii]->ref_poc[6] + ); } -#endif return; } @@ -2095,6 +2430,8 @@ static int config_mc_buffer(struct AVS2Decoder_s *dec) int32_t i; struct avs2_decoder *avs2_dec = &dec->avs2_dec; struct avs2_frame_s *pic; + struct avs2_frame_s *cur_pic = avs2_dec->hc.cur_pic; + /*if (avs2_dec->img.type == I_IMG) return 0; */ @@ -2138,9 +2475,14 @@ static int config_mc_buffer(struct AVS2Decoder_s *dec) (pic->mc_canvas_u_v << 16) | (pic->mc_canvas_u_v << 8) | pic->mc_canvas_y); + + if (pic->error_mark) + cur_pic->error_mark = 1; + avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL, - "refid %x mc_canvas_u_v %x mc_canvas_y %x\n", - i, pic->mc_canvas_u_v, pic->mc_canvas_y); + "refid %x mc_canvas_u_v %x mc_canvas_y %x error_mark %x\n", + i, pic->mc_canvas_u_v, pic->mc_canvas_y, + pic->error_mark); } } else if (avs2_dec->img.type == F_IMG) { avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL, @@ -2155,9 +2497,14 @@ static int config_mc_buffer(struct AVS2Decoder_s *dec) (pic->mc_canvas_u_v << 16) | (pic->mc_canvas_u_v << 8) | pic->mc_canvas_y); + + if (pic->error_mark) + cur_pic->error_mark = 1; + avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL, - "refid %x mc_canvas_u_v %x mc_canvas_y %x\n", - i, pic->mc_canvas_u_v, pic->mc_canvas_y); + "refid %x mc_canvas_u_v %x mc_canvas_y %x error_mark %x\n", + i, pic->mc_canvas_u_v, pic->mc_canvas_y, + pic->error_mark); } WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR, (16 << 8) | (0<<1) | 1); @@ -2183,9 +2530,13 @@ static int config_mc_buffer(struct AVS2Decoder_s *dec) (pic->mc_canvas_u_v << 8) | pic->mc_canvas_y); + if (pic->error_mark) + cur_pic->error_mark = 1; + avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL, - "refid %x mc_canvas_u_v %x mc_canvas_y %x\n", - 1, pic->mc_canvas_u_v, pic->mc_canvas_y); + "refid %x mc_canvas_u_v %x mc_canvas_y %x error_mark %x\n", + 1, pic->mc_canvas_u_v, pic->mc_canvas_y, + pic->error_mark); pic = avs2_dec->fref[0]; WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR, @@ -2195,13 +2546,155 @@ static int config_mc_buffer(struct AVS2Decoder_s *dec) (pic->mc_canvas_u_v<<8) | pic->mc_canvas_y); + if (pic->error_mark) + cur_pic->error_mark = 1; + avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL, - "refid %x mc_canvas_u_v %x mc_canvas_y %x\n", - 0, pic->mc_canvas_u_v, pic->mc_canvas_y); + "refid %x mc_canvas_u_v %x mc_canvas_y %x error_mark %x\n", + 0, pic->mc_canvas_u_v, pic->mc_canvas_y, + pic->error_mark); } return 0; } +#if 0 +static void mcrcc_get_hitrate(void) +{ + u32 tmp; + u32 raw_mcr_cnt; + u32 hit_mcr_cnt; + u32 byp_mcr_cnt_nchoutwin; + u32 byp_mcr_cnt_nchcanv; + int hitrate; + if (debug & AVS2_DBG_CACHE) + pr_info("[cache_util.c] Entered mcrcc_get_hitrate...\n"); + WRITE_VREG(HEVCD_MCRCC_PERFMON_CTL, (unsigned int)(0x0<<1)); + raw_mcr_cnt = READ_VREG(HEVCD_MCRCC_PERFMON_DATA); + WRITE_VREG(HEVCD_MCRCC_PERFMON_CTL, (unsigned int)(0x1<<1)); + hit_mcr_cnt = READ_VREG(HEVCD_MCRCC_PERFMON_DATA); + WRITE_VREG(HEVCD_MCRCC_PERFMON_CTL, (unsigned int)(0x2<<1)); + byp_mcr_cnt_nchoutwin = READ_VREG(HEVCD_MCRCC_PERFMON_DATA); + WRITE_VREG(HEVCD_MCRCC_PERFMON_CTL, (unsigned int)(0x3<<1)); + byp_mcr_cnt_nchcanv = READ_VREG(HEVCD_MCRCC_PERFMON_DATA); + + if (debug & AVS2_DBG_CACHE) { + pr_info("raw_mcr_cnt_total: %d\n",raw_mcr_cnt); + pr_info("hit_mcr_cnt_total: %d\n",hit_mcr_cnt); + pr_info("byp_mcr_cnt_nchoutwin_total: %d\n",byp_mcr_cnt_nchoutwin); + pr_info("byp_mcr_cnt_nchcanv_total: %d\n",byp_mcr_cnt_nchcanv); + } + WRITE_VREG(HEVCD_MCRCC_PERFMON_CTL, (unsigned int)(0x4<<1)); + tmp = READ_VREG(HEVCD_MCRCC_PERFMON_DATA); + if (debug & AVS2_DBG_CACHE) + pr_info("miss_mcr_0_cnt_total: %d\n", tmp); + + WRITE_VREG(HEVCD_MCRCC_PERFMON_CTL, (unsigned int)(0x5<<1)); + tmp = READ_VREG(HEVCD_MCRCC_PERFMON_DATA); + if (debug & AVS2_DBG_CACHE) + pr_info("miss_mcr_1_cnt_total: %d\n", tmp); + + WRITE_VREG(HEVCD_MCRCC_PERFMON_CTL, (unsigned int)(0x6<<1)); + tmp = READ_VREG(HEVCD_MCRCC_PERFMON_DATA); + if (debug & AVS2_DBG_CACHE) + pr_info("hit_mcr_0_cnt_total: %d\n",tmp); + + WRITE_VREG(HEVCD_MCRCC_PERFMON_CTL, (unsigned int)(0x7<<1)); + tmp= READ_VREG(HEVCD_MCRCC_PERFMON_DATA); + if (debug & AVS2_DBG_CACHE) + pr_info("hit_mcr_1_cnt_total: %d\n",tmp); + + if (raw_mcr_cnt != 0) { + hitrate = (hit_mcr_cnt / raw_mcr_cnt) * 100; + if (debug & AVS2_DBG_CACHE) + pr_info("MCRCC_HIT_RATE : %d\n", hitrate); + hitrate = ((byp_mcr_cnt_nchoutwin + byp_mcr_cnt_nchcanv) + /raw_mcr_cnt) * 100; + if (debug & AVS2_DBG_CACHE) + pr_info("MCRCC_BYP_RATE : %d\n", hitrate); + } else if (debug & AVS2_DBG_CACHE) { + pr_info("MCRCC_HIT_RATE : na\n"); + pr_info("MCRCC_BYP_RATE : na\n"); + } + return; +} + + +static void decomp_get_hitrate(void) +{ + u32 raw_mcr_cnt; + u32 hit_mcr_cnt; + int hitrate; + + if (debug & AVS2_DBG_CACHE) + pr_info("[cache_util.c] Entered decomp_get_hitrate...\n"); + WRITE_VREG(HEVCD_MPP_DECOMP_PERFMON_CTL, (unsigned int)(0x0<<1)); + raw_mcr_cnt = READ_VREG(HEVCD_MPP_DECOMP_PERFMON_DATA); + WRITE_VREG(HEVCD_MPP_DECOMP_PERFMON_CTL, (unsigned int)(0x1<<1)); + hit_mcr_cnt = READ_VREG(HEVCD_MPP_DECOMP_PERFMON_DATA); + + if (debug & AVS2_DBG_CACHE) { + pr_info("hcache_raw_cnt_total: %d\n",raw_mcr_cnt); + pr_info("hcache_hit_cnt_total: %d\n",hit_mcr_cnt); + } + if (raw_mcr_cnt != 0) { + hitrate = (hit_mcr_cnt / raw_mcr_cnt) * 100; + if (debug & AVS2_DBG_CACHE) + pr_info("DECOMP_HCACHE_HIT_RATE : %d\n", hitrate); + } else { + if (debug & AVS2_DBG_CACHE) + pr_info("DECOMP_HCACHE_HIT_RATE : na\n"); + } + WRITE_VREG(HEVCD_MPP_DECOMP_PERFMON_CTL, (unsigned int)(0x2<<1)); + raw_mcr_cnt = READ_VREG(HEVCD_MPP_DECOMP_PERFMON_DATA); + WRITE_VREG(HEVCD_MPP_DECOMP_PERFMON_CTL, (unsigned int)(0x3<<1)); + hit_mcr_cnt = READ_VREG(HEVCD_MPP_DECOMP_PERFMON_DATA); + + if (debug & AVS2_DBG_CACHE) { + pr_info("dcache_raw_cnt_total: %d\n", raw_mcr_cnt); + pr_info("dcache_hit_cnt_total: %d\n", hit_mcr_cnt); + } + if (raw_mcr_cnt != 0) { + hitrate = (hit_mcr_cnt / raw_mcr_cnt) * 100; + if (debug & AVS2_DBG_CACHE) + pr_info("DECOMP_DCACHE_HIT_RATE : %d\n", hitrate); + } else if (debug & AVS2_DBG_CACHE) { + pr_info("DECOMP_DCACHE_HIT_RATE : na\n"); + } +return; +} + +static void decomp_get_comprate(void) +{ + u32 raw_ucomp_cnt; + u32 fast_comp_cnt; + u32 slow_comp_cnt; + int comprate; + + if (debug & AVS2_DBG_CACHE) + pr_info("[cache_util.c] Entered decomp_get_comprate...\n"); + WRITE_VREG(HEVCD_MPP_DECOMP_PERFMON_CTL, (unsigned int)(0x4<<1)); + fast_comp_cnt = READ_VREG(HEVCD_MPP_DECOMP_PERFMON_DATA); + WRITE_VREG(HEVCD_MPP_DECOMP_PERFMON_CTL, (unsigned int)(0x5<<1)); + slow_comp_cnt = READ_VREG(HEVCD_MPP_DECOMP_PERFMON_DATA); + WRITE_VREG(HEVCD_MPP_DECOMP_PERFMON_CTL, (unsigned int)(0x6<<1)); + raw_ucomp_cnt = READ_VREG(HEVCD_MPP_DECOMP_PERFMON_DATA); + if (debug & AVS2_DBG_CACHE) { + pr_info("decomp_fast_comp_total: %d\n", fast_comp_cnt); + pr_info("decomp_slow_comp_total: %d\n", slow_comp_cnt); + pr_info("decomp_raw_uncomp_total: %d\n", raw_ucomp_cnt); + } + + if (raw_ucomp_cnt != 0) { + comprate = ((fast_comp_cnt + slow_comp_cnt) + / raw_ucomp_cnt) * 100; + if (debug & AVS2_DBG_CACHE) + pr_info("DECOMP_COMP_RATIO : %d\n", comprate); + } else if (debug & AVS2_DBG_CACHE) { + pr_info("DECOMP_COMP_RATIO : na\n"); + } + return; +} +#endif static void config_mcrcc_axi_hw(struct AVS2Decoder_s *dec) { @@ -2216,13 +2709,13 @@ static void config_mcrcc_axi_hw(struct AVS2Decoder_s *dec) WRITE_VREG(HEVCD_MCRCC_CTL1, 0x0); return; } - - #if 0 - mcrcc_get_hitrate(); - decomp_get_hitrate(); - decomp_get_comprate(); - #endif - +/* + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) { + mcrcc_get_hitrate(); + decomp_get_hitrate(); + decomp_get_comprate(); + } +*/ if ((avs2_dec->img.type == B_IMG) || (avs2_dec->img.type == F_IMG)) { /*B-PIC or F_PIC*/ /*Programme canvas0 */ @@ -2353,7 +2846,7 @@ static void config_mpred_hw(struct AVS2Decoder_s *dec) avs2_dec->fref[0]->ref_poc[4], avs2_dec->fref[0]->ref_poc[5], avs2_dec->fref[0]->ref_poc[6] - ); + ); avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL, "pic_distance %d, imgtr_next_P %d\n", avs2_dec->img.pic_distance, avs2_dec->img.imgtr_next_P); @@ -2571,7 +3064,7 @@ static void config_sao_hw(struct AVS2Decoder_s *dec) data32 |= endian; /* Big-Endian per 64-bit */ data32 &= (~0x3); /*[1]:dw_disable [0]:cm_disable*/ #if 0 - if (get_cpu_type() < MESON_CPU_MAJOR_ID_G12A) { + if (get_cpu_major_id() < MESON_CPU_MAJOR_ID_G12A) { if (get_double_write_mode(dec) == 0) data32 |= 0x2; /*disable double write*/ #ifndef AVS2_10B_MMU @@ -2916,7 +3409,7 @@ static void avs2_config_work_space_hw(struct AVS2Decoder_s *dec) WRITE_VREG(HEVCD_IPP_LINEBUFF_BASE, buf_spec->ipp.buf_start); if ((debug & AVS2_DBG_SEND_PARAM_WITH_REG) == 0) WRITE_VREG(HEVC_RPM_BUFFER, (u32)dec->rpm_phy_addr); - WRITE_VREG(HEVC_SHORT_TERM_RPS, buf_spec->short_term_rps.buf_start); + WRITE_VREG(AVS2_ALF_SWAP_BUFFER, buf_spec->short_term_rps.buf_start); WRITE_VREG(HEVC_RCS_BUFFER, buf_spec->rcs.buf_start); WRITE_VREG(HEVC_SPS_BUFFER, buf_spec->sps.buf_start); WRITE_VREG(HEVC_PPS_BUFFER, buf_spec->pps.buf_start); @@ -2978,44 +3471,45 @@ static void avs2_config_work_space_hw(struct AVS2Decoder_s *dec) /* use HEVC_CM_HEADER_START_ADDR */ data32 = READ_VREG(HEVC_SAO_CTRL5); data32 |= (1<<10); +#if 1 + if (debug & AVS2_DBG_FORCE_UNCOMPRESS) + data32 |= 0x80; +#endif WRITE_VREG(HEVC_SAO_CTRL5, data32); #endif WRITE_VREG(LMEM_DUMP_ADR, (u32)dec->lmem_phy_addr); +#if 1 +/*MULTI_INSTANCE_SUPPORT*/ + /*new added in simulation???*/ + WRITE_VREG(HEVC_MPRED_ABV_START_ADDR, buf_spec->mpred_above.buf_start); +#endif +} +static void decomp_perfcount_reset(void) +{ + if (debug & AVS2_DBG_CACHE) + pr_info("[cache_util.c] Entered decomp_perfcount_reset...\n"); + WRITE_VREG(HEVCD_MPP_DECOMP_PERFMON_CTL, (unsigned int)0x1); + WRITE_VREG(HEVCD_MPP_DECOMP_PERFMON_CTL, (unsigned int)0x0); + return; +} + +static void mcrcc_perfcount_reset(void) +{ + if (debug & AVS2_DBG_CACHE) + pr_info("[cache_util.c] Entered mcrcc_perfcount_reset...\n"); + WRITE_VREG(HEVCD_MCRCC_PERFMON_CTL, (unsigned int)0x1); + WRITE_VREG(HEVCD_MCRCC_PERFMON_CTL, (unsigned int)0x0); + return; } static void avs2_init_decoder_hw(struct AVS2Decoder_s *dec) { unsigned int data32; + unsigned int decode_mode; int i; - const unsigned short parser_cmd[PARSER_CMD_NUMBER] = { - 0x0401, 0x8401, 0x0800, 0x0402, 0x9002, 0x1423, - 0x8CC3, 0x1423, 0x8804, 0x9825, 0x0800, 0x04FE, - 0x8406, 0x8411, 0x1800, 0x8408, 0x8409, 0x8C2A, - 0x9C2B, 0x1C00, 0x840F, 0x8407, 0x8000, 0x8408, - 0x2000, 0xA800, 0x8410, 0x04DE, 0x840C, 0x840D, - 0xAC00, 0xA000, 0x08C0, 0x08E0, 0xA40E, 0xFC00, - 0x7C00 - }; - const int32_t g_WqMDefault4x4[16] = { - 64, 64, 64, 68, - 64, 64, 68, 72, - 64, 68, 76, 80, - 72, 76, 84, 96 - }; - - const int32_t g_WqMDefault8x8[64] = { - 64, 64, 64, 64, 68, 68, 72, 76, - 64, 64, 64, 68, 72, 76, 84, 92, - 64, 64, 68, 72, 76, 80, 88, 100, - 64, 68, 72, 80, 84, 92, 100, 112, - 68, 72, 80, 84, 92, 104, 112, 128, - 76, 80, 84, 92, 104, 116, 132, 152, - 96, 100, 104, 116, 124, 140, 164, 188, - 104, 108, 116, 128, 152, 172, 192, 216 - }; /*if (debug & AVS2_DBG_BUFMGR_MORE) pr_info("%s\n", __func__);*/ @@ -3083,11 +3577,34 @@ static void avs2_init_decoder_hw(struct AVS2Decoder_s *dec) WRITE_VREG(HEVC_STREAM_SWAP_TEST, 0); #endif if (!dec->m_ins_flag) - WRITE_VREG(DECODE_MODE, DECODE_MODE_SINGLE); + decode_mode = DECODE_MODE_SINGLE; else if (vdec_frame_based(hw_to_vdec(dec))) - WRITE_VREG(DECODE_MODE, DECODE_MODE_MULTI_FRAMEBASE); + decode_mode = DECODE_MODE_MULTI_FRAMEBASE; else - WRITE_VREG(DECODE_MODE, DECODE_MODE_MULTI_STREAMBASE); + decode_mode = DECODE_MODE_MULTI_STREAMBASE; + if (dec->avs2_dec.bufmgr_error_flag && + (error_handle_policy & 0x1)) { + dec->bufmgr_error_count++; + dec->avs2_dec.bufmgr_error_flag = 0; + if (dec->bufmgr_error_count > + (re_search_seq_threshold & 0xff) + && dec->frame_count > + ((re_search_seq_threshold >> 8) & 0xff)) { + struct avs2_decoder *avs2_dec = &dec->avs2_dec; + dec->start_decoding_flag = 0; + avs2_dec->hd.vec_flag = 1; + dec->skip_PB_before_I = 1; + avs2_print(dec, 0, + "!!Bufmgr error, search seq again (0x%x %d %d)\n", + error_handle_policy, + dec->frame_count, + dec->bufmgr_error_count); + dec->bufmgr_error_count = 0; + } + } + decode_mode |= (dec->start_decoding_flag << 16); + + WRITE_VREG(DECODE_MODE, decode_mode); WRITE_VREG(HEVC_DECODE_SIZE, 0); WRITE_VREG(HEVC_DECODE_COUNT, 0); @@ -3107,6 +3624,22 @@ static void avs2_init_decoder_hw(struct AVS2Decoder_s *dec) (1 << 2) | /*parser_mpred_if_en*/ (1 << 0) /*parser_scaler_if_en*/ ); + +#ifdef MULTI_INSTANCE_SUPPORT + WRITE_VREG(HEVC_MPRED_INT_STATUS, (1<<31)); + + WRITE_VREG(HEVC_PARSER_RESULT_3, 0xffffffff); + + for (i = 0; i < 8; i++) + data32 = READ_VREG(HEVC_MPRED_ABV_START_ADDR); + + WRITE_VREG(DOS_SW_RESET3, (1<<18)); /* reset mpred */ + WRITE_VREG(DOS_SW_RESET3, 0); + WRITE_VREG(HEVC_MPRED_ABV_START_ADDR, data32); + WRITE_VREG(HEVC_MPRED_ABV_START_ADDR, data32); + WRITE_VREG(HEVC_MPRED_ABV_START_ADDR, data32); +#endif + /*End of Multi-instance*/ /*Changed to Start MPRED in microcode*/ /* pr_info("[test.c] Start MPRED\n"); @@ -3157,13 +3690,18 @@ static void avs2_init_decoder_hw(struct AVS2Decoder_s *dec) else if (get_double_write_mode(dec) == 0x10) data32 |= (0x1 << 9); /*double write only*/ else - data32 |= ((0x1 << 8) |(0x1 << 9)); + data32 |= ((0x1 << 8) | (0x1 << 9)); WRITE_VREG(HEVC_DBLK_CFGB, data32); WRITE_VREG(HEVC_DBLK_CFG0, (1 << 0)); /* [0] rst_sync*/ avs2_print(dec, AVS2_DBG_BUFMGR_MORE, "Bitstream level Init for DBLK .Done.\n"); + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) { + mcrcc_perfcount_reset(); + decomp_perfcount_reset(); + } + return; } @@ -3217,7 +3755,7 @@ static void config_avs2_clk_forced_on(void) -static struct AVS2Decoder_s *gHevc; +static struct AVS2Decoder_s gAVS2Decoder; static void avs2_local_uninit(struct AVS2Decoder_s *dec) { @@ -3231,10 +3769,10 @@ static void avs2_local_uninit(struct AVS2Decoder_s *dec) dec->rpm_addr = NULL; } if (dec->lmem_addr) { - if (dec->lmem_phy_addr) - dma_free_coherent(amports_get_dma_device(), - LMEM_BUF_SIZE, dec->lmem_addr, - dec->lmem_phy_addr); + if (dec->lmem_phy_addr) + dma_free_coherent(amports_get_dma_device(), + LMEM_BUF_SIZE, dec->lmem_addr, + dec->lmem_phy_addr); dec->lmem_addr = NULL; } @@ -3242,7 +3780,7 @@ static void avs2_local_uninit(struct AVS2Decoder_s *dec) if (dec->frame_mmu_map_addr) { if (dec->frame_mmu_map_phy_addr) dma_free_coherent(amports_get_dma_device(), - FRAME_MMU_MAP_SIZE, dec->frame_mmu_map_addr, + get_frame_mmu_map_size(dec), dec->frame_mmu_map_addr, dec->frame_mmu_map_phy_addr); dec->frame_mmu_map_addr = NULL; } @@ -3260,17 +3798,18 @@ static int avs2_local_init(struct AVS2Decoder_s *dec) struct BuffInfo_s *cur_buf_info = NULL; cur_buf_info = &dec->work_space_buf_store; -#ifdef SUPPORT_4K2K - if (vdec_is_support_4k()) - memcpy(cur_buf_info, &amvavs2_workbuff_spec[1], /* 4k */ - sizeof(struct BuffInfo_s)); - else + + if (vdec_is_support_4k()) { + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) + memcpy(cur_buf_info, &amvavs2_workbuff_spec[2], /* 8k */ + sizeof(struct BuffInfo_s)); + else + memcpy(cur_buf_info, &amvavs2_workbuff_spec[1], /* 4k */ + sizeof(struct BuffInfo_s)); + } else memcpy(cur_buf_info, &amvavs2_workbuff_spec[0],/* 1080p */ sizeof(struct BuffInfo_s)); -#else - memcpy(cur_buf_info, &amvavs2_workbuff_spec[0], /* 1080p work space */ - sizeof(struct BuffInfo_s)); -#endif + cur_buf_info->start_adr = dec->buf_start; #ifndef AVS2_10B_MMU dec->mc_buf_spec.buf_end = dec->buf_start + dec->buf_size; @@ -3300,6 +3839,9 @@ static int avs2_local_init(struct AVS2Decoder_s *dec) && (buf_alloc_width > 1920 && buf_alloc_height > 1088)) { buf_alloc_width = 1920; buf_alloc_height = 1088; + } else if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) { + buf_alloc_width = 8192; + buf_alloc_height = 4608; } dec->init_pic_w = buf_alloc_width ? buf_alloc_width : (dec->vavs2_amstream_dec_info.width ? @@ -3309,7 +3851,8 @@ static int avs2_local_init(struct AVS2Decoder_s *dec) (dec->vavs2_amstream_dec_info.height ? dec->vavs2_amstream_dec_info.height : dec->work_space_buf->max_height); -#ifndef MV_USE_FIXED_BUF +#if 0 +/*ndef MV_USE_FIXED_BUF*/ if (init_mv_buf_list(dec) < 0) { pr_err("%s: init_mv_buf_list fail\n", __func__); return -1; @@ -3346,6 +3889,9 @@ static int avs2_local_init(struct AVS2Decoder_s *dec) kfree(dec->rpm_addr); dec->rpm_addr = NULL; return -1; + } else { + avs2_print(dec, AVS2_DBG_BUFMGR, + "rpm_phy_addr %x\n", (u32) dec->rpm_phy_addr); } dec->rpm_ptr = dec->rpm_addr; @@ -3357,7 +3903,10 @@ static int avs2_local_init(struct AVS2Decoder_s *dec) if (dec->lmem_addr == NULL) { pr_err("%s: failed to alloc lmem buffer\n", __func__); return -1; - } + } else + avs2_print(dec, AVS2_DBG_BUFMGR, + "%s, lmem_phy_addr %x\n", + __func__, (u32)dec->lmem_phy_addr); /* dec->lmem_phy_addr = dma_map_single(amports_get_dma_device(), dec->lmem_addr, LMEM_BUF_SIZE, DMA_BIDIRECTIONAL); @@ -3374,13 +3923,13 @@ static int avs2_local_init(struct AVS2Decoder_s *dec) #ifdef AVS2_10B_MMU dec->frame_mmu_map_addr = dma_alloc_coherent(amports_get_dma_device(), - FRAME_MMU_MAP_SIZE, + get_frame_mmu_map_size(dec), &dec->frame_mmu_map_phy_addr, GFP_KERNEL); if (dec->frame_mmu_map_addr == NULL) { pr_err("%s: failed to alloc count_buffer\n", __func__); return -1; } - memset(dec->frame_mmu_map_addr, 0, COUNT_BUF_SIZE); + memset(dec->frame_mmu_map_addr, 0, get_frame_mmu_map_size(dec)); /* dec->frame_mmu_map_phy_addr = dma_map_single(amports_get_dma_device(), dec->frame_mmu_map_addr, FRAME_MMU_MAP_SIZE, DMA_BIDIRECTIONAL); if (dma_mapping_error(amports_get_dma_device(), @@ -3423,6 +3972,7 @@ static void set_canvas(struct AVS2Decoder_s *dec, int canvas_w = ALIGN(pic->pic_w, 64)/4; int canvas_h = ALIGN(pic->pic_h, 32)/4; int blkmode = mem_map_mode; + struct vdec_s *vdec = hw_to_vdec(dec); /*CANVAS_BLKMODE_64X32*/ if (pic->double_write_mode) { canvas_w = pic->pic_w / @@ -3438,8 +3988,15 @@ static void set_canvas(struct AVS2Decoder_s *dec, canvas_w = ALIGN(canvas_w, 64); canvas_h = ALIGN(canvas_h, 32); - pic->y_canvas_index = 128 + pic->index * 2; - pic->uv_canvas_index = 128 + pic->index * 2 + 1; + if (vdec->parallel_dec == 1) { + if (pic->y_canvas_index == -1) + pic->y_canvas_index = vdec->get_canvas_ex(CORE_MASK_HEVC, vdec->id); + if (pic->uv_canvas_index == -1) + pic->uv_canvas_index = vdec->get_canvas_ex(CORE_MASK_HEVC, vdec->id); + } else { + pic->y_canvas_index = 128 + pic->index * 2; + pic->uv_canvas_index = 128 + pic->index * 2 + 1; + } canvas_config_ex(pic->y_canvas_index, pic->dw_y_adr, canvas_w, canvas_h, @@ -3470,8 +4027,15 @@ static void set_canvas(struct AVS2Decoder_s *dec, #endif } else { #ifndef AVS2_10B_MMU - pic->y_canvas_index = 128 + pic->index; - pic->uv_canvas_index = 128 + pic->index; + if (vdec->parallel_dec == 1) { + if (pic->y_canvas_index == -1) + pic->y_canvas_index = vdec->get_canvas_ex(CORE_MASK_HEVC, vdec->id); + if (pic->uv_canvas_index == -1) + pic->uv_canvas_index = vdec->get_canvas_ex(CORE_MASK_HEVC, vdec->id); + } else { + pic->y_canvas_index = 128 + pic->index; + pic->uv_canvas_index = 128 + pic->index; + } canvas_config_ex(pic->y_canvas_index, pic->mc_y_adr, canvas_w, canvas_h, @@ -3577,20 +4141,36 @@ static struct vframe_s *vavs2_vf_get(void *op_arg) if (kfifo_get(&dec->display_q, &vf)) { uint8_t index = vf->index & 0xff; - - if (index >= 0 && index < dec->used_buf_num) { + if (index >= 0 && index < dec->used_buf_num) { struct avs2_frame_s *pic = get_pic_by_index(dec, index); - dec->vf_get_count++; + if (pic == NULL && + (debug & AVS2_DBG_PIC_LEAK)) { + int i; + avs2_print(dec, 0, + "%s error index 0x%x pic not exist\n", + __func__, index); + dump_pic_list(dec); + for (i = 0; i < 10; i++) { + pic = get_pic_by_index(dec, index); + pr_info("pic = %p\n", pic); + } + + if (debug & AVS2_DBG_PIC_LEAK) + debug |= AVS2_DBG_PIC_LEAK_WAIT; + return NULL; + } + dec->vf_get_count++; + if (pic) avs2_print(dec, AVS2_DBG_BUFMGR, - "%s index 0x%x pos %d getcount %d type 0x%x w/h %d/%d, pts %d, %lld\n", - __func__, index, - pic->imgtr_fwRefDistance, - dec->vf_get_count, - vf->type, - vf->width, vf->height, - vf->pts, - vf->pts_us64); - return vf; + "%s index 0x%x pos %d getcount %d type 0x%x w/h %d/%d, pts %d, %lld\n", + __func__, index, + pic->imgtr_fwRefDistance_bak, + dec->vf_get_count, + vf->type, + vf->width, vf->height, + vf->pts, + vf->pts_us64); + return vf; } } return NULL; @@ -3667,11 +4247,72 @@ static struct avs2_frame_s *get_disp_pic(struct AVS2Decoder_s *dec) } + + +static void fill_frame_info(struct AVS2Decoder_s *dec, + struct avs2_frame_s *pic, unsigned int framesize, unsigned int pts) +{ + struct vframe_qos_s *vframe_qos = &dec->vframe_qos; + + if (pic->slice_type == I_IMG) + vframe_qos->type = 1; + else if (pic->slice_type == P_IMG) + vframe_qos->type = 2; + else if (pic->slice_type == B_IMG) + vframe_qos->type = 3; +/* +#define SHOW_QOS_INFO +*/ + vframe_qos->size = framesize; + vframe_qos->pts = pts; +#ifdef SHOW_QOS_INFO + avs2_print(dec, 0, "slice:%d\n", pic->slice_type); +#endif + + + vframe_qos->max_mv = pic->max_mv; + vframe_qos->avg_mv = pic->avg_mv; + vframe_qos->min_mv = pic->min_mv; +#ifdef SHOW_QOS_INFO + avs2_print(dec, 0, "mv: max:%d, avg:%d, min:%d\n", + vframe_qos->max_mv, + vframe_qos->avg_mv, + vframe_qos->min_mv); +#endif + + vframe_qos->max_qp = pic->max_qp; + vframe_qos->avg_qp = pic->avg_qp; + vframe_qos->min_qp = pic->min_qp; +#ifdef SHOW_QOS_INFO + avs2_print(dec, 0, "qp: max:%d, avg:%d, min:%d\n", + vframe_qos->max_qp, + vframe_qos->avg_qp, + vframe_qos->min_qp); +#endif + + vframe_qos->max_skip = pic->max_skip; + vframe_qos->avg_skip = pic->avg_skip; + vframe_qos->min_skip = pic->min_skip; +#ifdef SHOW_QOS_INFO + avs2_print(dec, 0, "skip: max:%d, avg:%d, min:%d\n", + vframe_qos->max_skip, + vframe_qos->avg_skip, + vframe_qos->min_skip); +#endif + + vframe_qos->num++; + + if (dec->frameinfo_enable) + vdec_fill_frame_info(vframe_qos, 1); +} + static void set_vframe(struct AVS2Decoder_s *dec, struct vframe_s *vf, struct avs2_frame_s *pic, u8 dummy) { unsigned long flags; int stream_offset; + unsigned int frame_size; + int pts_discontinue; stream_offset = pic->stream_offset; avs2_print(dec, AVS2_DBG_BUFMGR, "%s index = %d pos = %d\r\n", @@ -3693,7 +4334,8 @@ static void set_vframe(struct AVS2Decoder_s *dec, /* if (pts_lookup_offset(PTS_TYPE_VIDEO, stream_offset, &vf->pts, 0) != 0) { */ if (pts_lookup_offset_us64 - (PTS_TYPE_VIDEO, stream_offset, &vf->pts, 0, + (PTS_TYPE_VIDEO, stream_offset, + &vf->pts, &frame_size, 0, &vf->pts_us64) != 0) { #ifdef DEBUG_PTS dec->pts_missed++; @@ -3708,6 +4350,8 @@ static void set_vframe(struct AVS2Decoder_s *dec, if (pts_unstable) dec->pts_mode = PTS_NONE_REF_USE_DURATION; + fill_frame_info(dec, pic, frame_size, vf->pts); + if ((dec->pts_mode == PTS_NORMAL) && (vf->pts != 0) && dec->get_frame_dur) { int pts_diff = (int)vf->pts - dec->last_lookup_pts; @@ -3734,11 +4378,16 @@ static void set_vframe(struct AVS2Decoder_s *dec, } } + pts_discontinue = + (abs(dec->last_pts - vf->pts) >= + tsync_vpts_discontinuity_margin()); + if (vf->pts != 0) dec->last_lookup_pts = vf->pts; -#if 0 +#if 1 if ((dec->pts_mode == PTS_NONE_REF_USE_DURATION) - && (slice_type != KEY_FRAME)) + && ((pic->slice_type != I_IMG) || (!pts_discontinue && + !first_pts_checkin_complete(PTS_TYPE_AUDIO)))) vf->pts = dec->last_pts + DUR2PTS(dec->frame_dur); #endif dec->last_pts = vf->pts; @@ -3746,9 +4395,10 @@ static void set_vframe(struct AVS2Decoder_s *dec, if (vf->pts_us64 != 0) dec->last_lookup_pts_us64 = vf->pts_us64; -#if 0 +#if 1 if ((dec->pts_mode == PTS_NONE_REF_USE_DURATION) - && (slice_type != KEY_FRAME)) { + && ((pic->slice_type != I_IMG) || (!pts_discontinue && + !first_pts_checkin_complete(PTS_TYPE_AUDIO)))) { vf->pts_us64 = dec->last_pts_us64 + (DUR2PTS(dec->frame_dur) * 100 / 9); @@ -3757,17 +4407,16 @@ static void set_vframe(struct AVS2Decoder_s *dec, dec->last_pts_us64 = vf->pts_us64; avs2_print(dec, AVS2_DBG_OUT_PTS, "avs2 dec out pts: vf->pts=%d, vf->pts_us64 = %lld\n", - vf->pts, vf->pts_us64); + vf->pts, vf->pts_us64); + } - } + vf->index = 0xff00 | pic->index; - vf->index = 0xff00 | pic->index; - - if (pic->double_write_mode & 0x10) { - /* double write only */ - vf->compBodyAddr = 0; - vf->compHeadAddr = 0; - } else { + if (pic->double_write_mode & 0x10) { + /* double write only */ + vf->compBodyAddr = 0; + vf->compHeadAddr = 0; + } else { #ifdef AVS2_10B_MMU vf->compBodyAddr = 0; vf->compHeadAddr = pic->header_adr; @@ -3777,109 +4426,109 @@ static void set_vframe(struct AVS2Decoder_s *dec, pic->comp_body_size; /*head adr*/ #endif - } - if (pic->double_write_mode) { - vf->type = VIDTYPE_PROGRESSIVE | - VIDTYPE_VIU_FIELD; - vf->type |= VIDTYPE_VIU_NV21; - if (pic->double_write_mode == 3) { - vf->type |= VIDTYPE_COMPRESS; + } + if (pic->double_write_mode) { + vf->type = VIDTYPE_PROGRESSIVE | + VIDTYPE_VIU_FIELD; + vf->type |= VIDTYPE_VIU_NV21; + if (pic->double_write_mode == 3) { + vf->type |= VIDTYPE_COMPRESS; +#ifdef AVS2_10B_MMU + vf->type |= VIDTYPE_SCATTER; +#endif + } +#ifdef MULTI_INSTANCE_SUPPORT + if (dec->m_ins_flag) { + vf->canvas0Addr = vf->canvas1Addr = -1; + vf->plane_num = 2; + vf->canvas0_config[0] = + pic->canvas_config[0]; + vf->canvas0_config[1] = + pic->canvas_config[1]; + + vf->canvas1_config[0] = + pic->canvas_config[0]; + vf->canvas1_config[1] = + pic->canvas_config[1]; + + } else +#endif + vf->canvas0Addr = vf->canvas1Addr = + spec2canvas(pic); + } else { + vf->canvas0Addr = vf->canvas1Addr = 0; + vf->type = VIDTYPE_COMPRESS | VIDTYPE_VIU_FIELD; #ifdef AVS2_10B_MMU vf->type |= VIDTYPE_SCATTER; #endif } -#ifdef MULTI_INSTANCE_SUPPORT - if (dec->m_ins_flag) { - vf->canvas0Addr = vf->canvas1Addr = -1; - vf->plane_num = 2; - vf->canvas0_config[0] = - pic->canvas_config[0]; - vf->canvas0_config[1] = - pic->canvas_config[1]; - vf->canvas1_config[0] = - pic->canvas_config[0]; - vf->canvas1_config[1] = - pic->canvas_config[1]; + switch (pic->bit_depth) { + case AVS2_BITS_8: + vf->bitdepth = BITDEPTH_Y8 | + BITDEPTH_U8 | BITDEPTH_V8; + break; + case AVS2_BITS_10: + case AVS2_BITS_12: + vf->bitdepth = BITDEPTH_Y10 | + BITDEPTH_U10 | BITDEPTH_V10; + break; + default: + vf->bitdepth = BITDEPTH_Y10 | + BITDEPTH_U10 | BITDEPTH_V10; + break; + } + if ((vf->type & VIDTYPE_COMPRESS) == 0) + vf->bitdepth = + BITDEPTH_Y8 | BITDEPTH_U8 | BITDEPTH_V8; + if (pic->bit_depth == AVS2_BITS_8) + vf->bitdepth |= BITDEPTH_SAVING_MODE; - } else -#endif - vf->canvas0Addr = vf->canvas1Addr = - spec2canvas(pic); - } else { - vf->canvas0Addr = vf->canvas1Addr = 0; - vf->type = VIDTYPE_COMPRESS | VIDTYPE_VIU_FIELD; + set_frame_info(dec, vf); + /* if((vf->width!=pic->width)| + (vf->height!=pic->height)) */ + /* pr_info("aaa: %d/%d, %d/%d\n", + vf->width,vf->height, pic->width, + pic->height); */ + vf->width = pic->pic_w / + get_double_write_ratio(dec, + pic->double_write_mode); + vf->height = pic->pic_h / + get_double_write_ratio(dec, + pic->double_write_mode); + if (force_w_h != 0) { + vf->width = (force_w_h >> 16) & 0xffff; + vf->height = force_w_h & 0xffff; + } + vf->compWidth = pic->pic_w; + vf->compHeight = pic->pic_h; + if (force_fps & 0x100) { + u32 rate = force_fps & 0xff; + if (rate) + vf->duration = 96000/rate; + else + vf->duration = 0; + } #ifdef AVS2_10B_MMU - vf->type |= VIDTYPE_SCATTER; -#endif - } - - switch (pic->bit_depth) { - case AVS2_BITS_8: - vf->bitdepth = BITDEPTH_Y8 | - BITDEPTH_U8 | BITDEPTH_V8; - break; - case AVS2_BITS_10: - case AVS2_BITS_12: - vf->bitdepth = BITDEPTH_Y10 | - BITDEPTH_U10 | BITDEPTH_V10; - break; - default: - vf->bitdepth = BITDEPTH_Y10 | - BITDEPTH_U10 | BITDEPTH_V10; - break; - } - if ((vf->type & VIDTYPE_COMPRESS) == 0) - vf->bitdepth = - BITDEPTH_Y8 | BITDEPTH_U8 | BITDEPTH_V8; - if (pic->bit_depth == AVS2_BITS_8) - vf->bitdepth |= BITDEPTH_SAVING_MODE; - - set_frame_info(dec, vf); - /* if((vf->width!=pic->width)| - (vf->height!=pic->height)) */ - /* pr_info("aaa: %d/%d, %d/%d\n", - vf->width,vf->height, pic->width, - pic->height); */ - vf->width = pic->pic_w / - get_double_write_ratio(dec, - pic->double_write_mode); - vf->height = pic->pic_h / - get_double_write_ratio(dec, - pic->double_write_mode); - if (force_w_h != 0) { - vf->width = (force_w_h >> 16) & 0xffff; - vf->height = force_w_h & 0xffff; - } - vf->compWidth = pic->pic_w; - vf->compHeight = pic->pic_h; - if (force_fps & 0x100) { - u32 rate = force_fps & 0xff; - if (rate) - vf->duration = 96000/rate; - else - vf->duration = 0; - } -#ifdef AVS2_10B_MMU - if (vf->type & VIDTYPE_SCATTER) { - vf->mem_handle = decoder_mmu_box_get_mem_handle( - dec->mmu_box, - pic->index); - vf->mem_head_handle = decoder_bmmu_box_get_mem_handle( - dec->bmmu_box, - HEADER_BUFFER_IDX(pic->index)); - } else { + if (vf->type & VIDTYPE_SCATTER) { + vf->mem_handle = decoder_mmu_box_get_mem_handle( + dec->mmu_box, + pic->index); + vf->mem_head_handle = decoder_bmmu_box_get_mem_handle( + dec->bmmu_box, + HEADER_BUFFER_IDX(pic->index)); + } else { + vf->mem_handle = decoder_bmmu_box_get_mem_handle( + dec->bmmu_box, + VF_BUFFER_IDX(pic->index)); + vf->mem_head_handle = decoder_bmmu_box_get_mem_handle( + dec->bmmu_box, + HEADER_BUFFER_IDX(pic->index)); + } +#else vf->mem_handle = decoder_bmmu_box_get_mem_handle( dec->bmmu_box, VF_BUFFER_IDX(pic->index)); - vf->mem_head_handle = decoder_bmmu_box_get_mem_handle( - dec->bmmu_box, - HEADER_BUFFER_IDX(pic->index)); - } -#else - vf->mem_handle = decoder_bmmu_box_get_mem_handle( - dec->bmmu_box, - VF_BUFFER_IDX(pic->index)); #endif if (!dummy) { @@ -3890,6 +4539,7 @@ static void set_vframe(struct AVS2Decoder_s *dec, dec->vf_pre_count++; } + static int avs2_prepare_display_buf(struct AVS2Decoder_s *dec) { #ifndef NO_DISPLAY @@ -3906,6 +4556,24 @@ static int avs2_prepare_display_buf(struct AVS2Decoder_s *dec) continue; } + if (pic->error_mark) { + avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL, + "!!!error pic, skip\n", + 0); + continue; + } + + if (dec->start_decoding_flag != 0) { + if (dec->skip_PB_before_I && + pic->slice_type != I_IMG) { + avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL, + "!!!slice type %d (not I) skip\n", + 0, pic->slice_type); + continue; + } + dec->skip_PB_before_I = 0; + } + if (kfifo_get(&dec->newframe_q, &vf) == 0) { pr_info("fatal error, no available buffer slot."); return -1; @@ -3913,14 +4581,16 @@ static int avs2_prepare_display_buf(struct AVS2Decoder_s *dec) if (vf) { set_vframe(dec, vf, pic, 0); - + decoder_do_frame_check(hw_to_vdec(dec), vf); kfifo_put(&dec->display_q, (const struct vframe_s *)vf); + ATRACE_COUNTER(MODULE_NAME, vf->pts); #ifndef CONFIG_AMLOGIC_MEDIA_MULTI_DEC /*count info*/ gvs->frame_dur = dec->frame_dur; vdec_count_info(gvs, 0, stream_offset); #endif + hw_to_vdec(dec)->vdec_fps_detec(hw_to_vdec(dec)->id); vf_notify_receiver(dec->provider_name, VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); } @@ -3993,13 +4663,15 @@ static void dec_again_process(struct AVS2Decoder_s *dec) amhevc_stop(); dec->dec_result = DEC_RESULT_AGAIN; if (dec->process_state == - PROC_STATE_DECODESLICE) { + PROC_STATE_DECODING) { dec->process_state = - PROC_STATE_SENDAGAIN; -#ifdef AVS2_10B_MMU - avs2_recycle_mmu_buf(dec); -#endif + PROC_STATE_DECODE_AGAIN; + } else if (dec->process_state == + PROC_STATE_HEAD_DONE) { + dec->process_state = + PROC_STATE_HEAD_AGAIN; } + dec->next_again_flag = 1; reset_process_time(dec); vdec_schedule_work(&dec->work); } @@ -4014,6 +4686,517 @@ static uint32_t log2i(uint32_t val) return ret; } +static void check_pic_error(struct AVS2Decoder_s *dec, + struct avs2_frame_s *pic) +{ + if (pic->decoded_lcu == 0) { + pic->decoded_lcu = + (READ_VREG(HEVC_PARSER_LCU_START) + & 0xffffff) + 1; + } + if (pic->decoded_lcu != dec->avs2_dec.lcu_total) { + avs2_print(dec, AVS2_DBG_BUFMGR, + "%s error pic(index %d imgtr_fwRefDistance %d) decoded lcu %d (total %d)\n", + __func__, pic->index, pic->imgtr_fwRefDistance, + pic->decoded_lcu, dec->avs2_dec.lcu_total); + pic->error_mark = 1; + } else { + avs2_print(dec, AVS2_DBG_BUFMGR_MORE, + "%s pic(index %d imgtr_fwRefDistance %d) decoded lcu %d (total %d)\n", + __func__, pic->index, pic->imgtr_fwRefDistance, + pic->decoded_lcu, dec->avs2_dec.lcu_total); + + } +} +static void update_decoded_pic(struct AVS2Decoder_s *dec) +{ + struct avs2_frame_s *pic = dec->avs2_dec.hc.cur_pic; + if (pic) { + dec->avs2_dec.hc.cur_pic->decoded_lcu = + (READ_VREG(HEVC_PARSER_LCU_START) + & 0xffffff) + 1; + avs2_print(dec, AVS2_DBG_BUFMGR_MORE, + "%s pic(index %d imgtr_fwRefDistance %d) decoded lcu %d (total %d)\n", + __func__, pic->index, pic->imgtr_fwRefDistance, + pic->decoded_lcu, dec->avs2_dec.lcu_total); + } +} +/* +[SE] [BUG][BUG-171463][chuanqi.wang]: get frame rate by video sequeue*/ +static int get_frame_rate(union param_u *params, struct AVS2Decoder_s *dec) +{ + int tmp = 0; + + switch (params->p.frame_rate_code) { + case 1: + case 2: + tmp = 24; + break; + case 3: + tmp = 25; + break; + case 4: + case 5: + tmp = 30; + break; + case 6: + tmp = 50; + break; + case 7: + case 8: + tmp = 60; + break; + case 9: + tmp = 100; + break; + case 10: + tmp = 120; + break; + default: + tmp = 25; + break; + } + + if (!params->p.progressive_sequence) + tmp = tmp / 2; + dec->frame_dur = div_u64(96000ULL, tmp); + dec->get_frame_dur = true; + /*avs2_print(dec, 0, "avs2 frame_dur:%d,progressive:%d\n", dec->frame_dur, params->p.progressive_sequence);*/ + return 0; +} + + +#define HEVC_MV_INFO 0x310d +#define HEVC_QP_INFO 0x3137 +#define HEVC_SKIP_INFO 0x3136 + +/* only when we decoded one field or one frame, +we can call this function to get qos info*/ +static void get_picture_qos_info(struct AVS2Decoder_s *dec) +{ + struct avs2_frame_s *picture = dec->avs2_dec.hc.cur_pic; + if (!picture) { + avs2_print(dec, AVS2_DBG_BUFMGR_MORE, + "%s decode picture is none exist\n"); + + return; + } + +/* +#define DEBUG_QOS +*/ + + if (get_cpu_major_id() < AM_MESON_CPU_MAJOR_ID_G12A) { + unsigned char a[3]; + unsigned char i, j, t; + unsigned long data; + + data = READ_VREG(HEVC_MV_INFO); + if (picture->slice_type == I_IMG) + data = 0; + a[0] = data & 0xff; + a[1] = (data >> 8) & 0xff; + a[2] = (data >> 16) & 0xff; + + for (i = 0; i < 3; i++) + for (j = i+1; j < 3; j++) { + if (a[j] < a[i]) { + t = a[j]; + a[j] = a[i]; + a[i] = t; + } else if (a[j] == a[i]) { + a[i]++; + t = a[j]; + a[j] = a[i]; + a[i] = t; + } + } + picture->max_mv = a[2]; + picture->avg_mv = a[1]; + picture->min_mv = a[0]; +#ifdef DEBUG_QOS + avs2_print(dec, 0, "mv data %x a[0]= %x a[1]= %x a[2]= %x\n", + data, a[0], a[1], a[2]); +#endif + + data = READ_VREG(HEVC_QP_INFO); + a[0] = data & 0x1f; + a[1] = (data >> 8) & 0x3f; + a[2] = (data >> 16) & 0x7f; + + for (i = 0; i < 3; i++) + for (j = i+1; j < 3; j++) { + if (a[j] < a[i]) { + t = a[j]; + a[j] = a[i]; + a[i] = t; + } else if (a[j] == a[i]) { + a[i]++; + t = a[j]; + a[j] = a[i]; + a[i] = t; + } + } + picture->max_qp = a[2]; + picture->avg_qp = a[1]; + picture->min_qp = a[0]; +#ifdef DEBUG_QOS + avs2_print(dec, 0, "qp data %x a[0]= %x a[1]= %x a[2]= %x\n", + data, a[0], a[1], a[2]); +#endif + + data = READ_VREG(HEVC_SKIP_INFO); + a[0] = data & 0x1f; + a[1] = (data >> 8) & 0x3f; + a[2] = (data >> 16) & 0x7f; + + for (i = 0; i < 3; i++) + for (j = i+1; j < 3; j++) { + if (a[j] < a[i]) { + t = a[j]; + a[j] = a[i]; + a[i] = t; + } else if (a[j] == a[i]) { + a[i]++; + t = a[j]; + a[j] = a[i]; + a[i] = t; + } + } + picture->max_skip = a[2]; + picture->avg_skip = a[1]; + picture->min_skip = a[0]; + +#ifdef DEBUG_QOS + avs2_print(dec, 0, + "skip data %x a[0]= %x a[1]= %x a[2]= %x\n", + data, a[0], a[1], a[2]); +#endif + } else { + uint32_t blk88_y_count; + uint32_t blk88_c_count; + uint32_t blk22_mv_count; + uint32_t rdata32; + int32_t mv_hi; + int32_t mv_lo; + uint32_t rdata32_l; + uint32_t mvx_L0_hi; + uint32_t mvy_L0_hi; + uint32_t mvx_L1_hi; + uint32_t mvy_L1_hi; + int64_t value; + uint64_t temp_value; +#ifdef DEBUG_QOS + int pic_number = 0; +#endif + + picture->max_mv = 0; + picture->avg_mv = 0; + picture->min_mv = 0; + + picture->max_skip = 0; + picture->avg_skip = 0; + picture->min_skip = 0; + + picture->max_qp = 0; + picture->avg_qp = 0; + picture->min_qp = 0; + + + +#ifdef DEBUG_QOS + avs2_print(dec, 0, "slice_type:%d, poc:%d\n", + picture->slice_type, + pic_number); +#endif + /* set rd_idx to 0 */ + WRITE_VREG(HEVC_PIC_QUALITY_CTRL, 0); + + blk88_y_count = READ_VREG(HEVC_PIC_QUALITY_DATA); + if (blk88_y_count == 0) { +#ifdef DEBUG_QOS + avs2_print(dec, 0, + "[Picture %d Quality] NO Data yet.\n", + pic_number); +#endif + /* reset all counts */ + WRITE_VREG(HEVC_PIC_QUALITY_CTRL, (1<<8)); + return; + } + /* qp_y_sum */ + rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA); +#ifdef DEBUG_QOS + avs2_print(dec, 0, + "[Picture %d Quality] Y QP AVG : %d (%d/%d)\n", + pic_number, rdata32/blk88_y_count, + rdata32, blk88_y_count); +#endif + picture->avg_qp = rdata32/blk88_y_count; + /* intra_y_count */ + rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA); +#ifdef DEBUG_QOS + avs2_print(dec, 0, + "[Picture %d Quality] Y intra rate : %d%c (%d)\n", + pic_number, rdata32*100/blk88_y_count, + '%', rdata32); +#endif + /* skipped_y_count */ + rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA); +#ifdef DEBUG_QOS + avs2_print(dec, 0, + "[Picture %d Quality] Y skipped rate : %d%c (%d)\n", + pic_number, rdata32*100/blk88_y_count, + '%', rdata32); +#endif + picture->avg_skip = rdata32*100/blk88_y_count; + /* coeff_non_zero_y_count */ + rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA); +#ifdef DEBUG_QOS + avs2_print(dec, 0, + "[Picture %d Quality] Y ZERO_Coeff rate : %d%c (%d)\n", + pic_number, (100 - rdata32*100/(blk88_y_count*1)), + '%', rdata32); +#endif + /* blk66_c_count */ + blk88_c_count = READ_VREG(HEVC_PIC_QUALITY_DATA); + if (blk88_c_count == 0) { +#ifdef DEBUG_QOS + avs2_print(dec, 0, + "[Picture %d Quality] NO Data yet.\n", + pic_number); +#endif + /* reset all counts */ + WRITE_VREG(HEVC_PIC_QUALITY_CTRL, (1<<8)); + return; + } + /* qp_c_sum */ + rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA); +#ifdef DEBUG_QOS + avs2_print(dec, 0, + "[Picture %d Quality] C QP AVG : %d (%d/%d)\n", + pic_number, rdata32/blk88_c_count, + rdata32, blk88_c_count); +#endif + /* intra_c_count */ + rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA); +#ifdef DEBUG_QOS + avs2_print(dec, 0, + "[Picture %d Quality] C intra rate : %d%c (%d)\n", + pic_number, rdata32*100/blk88_c_count, + '%', rdata32); +#endif + /* skipped_cu_c_count */ + rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA); +#ifdef DEBUG_QOS + avs2_print(dec, 0, + "[Picture %d Quality] C skipped rate : %d%c (%d)\n", + pic_number, rdata32*100/blk88_c_count, + '%', rdata32); +#endif + /* coeff_non_zero_c_count */ + rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA); +#ifdef DEBUG_QOS + avs2_print(dec, 0, + "[Picture %d Quality] C ZERO_Coeff rate : %d%c (%d)\n", + pic_number, (100 - rdata32*100/(blk88_c_count*1)), + '%', rdata32); +#endif + + /* 1'h0, qp_c_max[6:0], 1'h0, qp_c_min[6:0], + 1'h0, qp_y_max[6:0], 1'h0, qp_y_min[6:0] */ + rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA); +#ifdef DEBUG_QOS + avs2_print(dec, 0, "[Picture %d Quality] Y QP min : %d\n", + pic_number, (rdata32>>0)&0xff); +#endif + picture->min_qp = (rdata32>>0)&0xff; + +#ifdef DEBUG_QOS + avs2_print(dec, 0, "[Picture %d Quality] Y QP max : %d\n", + pic_number, (rdata32>>8)&0xff); +#endif + picture->max_qp = (rdata32>>8)&0xff; + +#ifdef DEBUG_QOS + avs2_print(dec, 0, "[Picture %d Quality] C QP min : %d\n", + pic_number, (rdata32>>16)&0xff); + avs2_print(dec, 0, "[Picture %d Quality] C QP max : %d\n", + pic_number, (rdata32>>24)&0xff); +#endif + + /* blk22_mv_count */ + blk22_mv_count = READ_VREG(HEVC_PIC_QUALITY_DATA); + if (blk22_mv_count == 0) { +#ifdef DEBUG_QOS + avs2_print(dec, 0, + "[Picture %d Quality] NO MV Data yet.\n", + pic_number); +#endif + /* reset all counts */ + WRITE_VREG(HEVC_PIC_QUALITY_CTRL, (1<<8)); + return; + } + /* mvy_L1_count[39:32], mvx_L1_count[39:32], + mvy_L0_count[39:32], mvx_L0_count[39:32] */ + rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA); + /* should all be 0x00 or 0xff */ +#ifdef DEBUG_QOS + avs2_print(dec, 0, + "[Picture %d Quality] MV AVG High Bits: 0x%X\n", + pic_number, rdata32); +#endif + mvx_L0_hi = ((rdata32>>0)&0xff); + mvy_L0_hi = ((rdata32>>8)&0xff); + mvx_L1_hi = ((rdata32>>16)&0xff); + mvy_L1_hi = ((rdata32>>24)&0xff); + + /* mvx_L0_count[31:0] */ + rdata32_l = READ_VREG(HEVC_PIC_QUALITY_DATA); + temp_value = mvx_L0_hi; + temp_value = (temp_value << 32) | rdata32_l; + + if (mvx_L0_hi & 0x80) + value = 0xFFFFFFF000000000 | temp_value; + else + value = temp_value; + value = div_s64(value, blk22_mv_count); +#ifdef DEBUG_QOS + avs2_print(dec, 0, + "[Picture %d Quality] MVX_L0 AVG : %d (%lld/%d)\n", + pic_number, (int)value, + value, blk22_mv_count); +#endif + picture->avg_mv = value; + + /* mvy_L0_count[31:0] */ + rdata32_l = READ_VREG(HEVC_PIC_QUALITY_DATA); + temp_value = mvy_L0_hi; + temp_value = (temp_value << 32) | rdata32_l; + + if (mvy_L0_hi & 0x80) + value = 0xFFFFFFF000000000 | temp_value; + else + value = temp_value; +#ifdef DEBUG_QOS + avs2_print(dec, 0, + "[Picture %d Quality] MVY_L0 AVG : %d (%lld/%d)\n", + pic_number, rdata32_l/blk22_mv_count, + value, blk22_mv_count); +#endif + + /* mvx_L1_count[31:0] */ + rdata32_l = READ_VREG(HEVC_PIC_QUALITY_DATA); + temp_value = mvx_L1_hi; + temp_value = (temp_value << 32) | rdata32_l; + if (mvx_L1_hi & 0x80) + value = 0xFFFFFFF000000000 | temp_value; + else + value = temp_value; +#ifdef DEBUG_QOS + avs2_print(dec, 0, + "[Picture %d Quality] MVX_L1 AVG : %d (%lld/%d)\n", + pic_number, rdata32_l/blk22_mv_count, + value, blk22_mv_count); +#endif + + /* mvy_L1_count[31:0] */ + rdata32_l = READ_VREG(HEVC_PIC_QUALITY_DATA); + temp_value = mvy_L1_hi; + temp_value = (temp_value << 32) | rdata32_l; + if (mvy_L1_hi & 0x80) + value = 0xFFFFFFF000000000 | temp_value; + else + value = temp_value; +#ifdef DEBUG_QOS + avs2_print(dec, 0, + "[Picture %d Quality] MVY_L1 AVG : %d (%lld/%d)\n", + pic_number, rdata32_l/blk22_mv_count, + value, blk22_mv_count); +#endif + + /* {mvx_L0_max, mvx_L0_min} // format : {sign, abs[14:0]} */ + rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA); + mv_hi = (rdata32>>16)&0xffff; + if (mv_hi & 0x8000) + mv_hi = 0x8000 - mv_hi; +#ifdef DEBUG_QOS + avs2_print(dec, 0, "[Picture %d Quality] MVX_L0 MAX : %d\n", + pic_number, mv_hi); +#endif + picture->max_mv = mv_hi; + + mv_lo = (rdata32>>0)&0xffff; + if (mv_lo & 0x8000) + mv_lo = 0x8000 - mv_lo; +#ifdef DEBUG_QOS + avs2_print(dec, 0, "[Picture %d Quality] MVX_L0 MIN : %d\n", + pic_number, mv_lo); +#endif + picture->min_mv = mv_lo; + + /* {mvy_L0_max, mvy_L0_min} */ + rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA); + mv_hi = (rdata32>>16)&0xffff; + if (mv_hi & 0x8000) + mv_hi = 0x8000 - mv_hi; +#ifdef DEBUG_QOS + avs2_print(dec, 0, "[Picture %d Quality] MVY_L0 MAX : %d\n", + pic_number, mv_hi); +#endif + + mv_lo = (rdata32>>0)&0xffff; + if (mv_lo & 0x8000) + mv_lo = 0x8000 - mv_lo; +#ifdef DEBUG_QOS + avs2_print(dec, 0, "[Picture %d Quality] MVY_L0 MIN : %d\n", + pic_number, mv_lo); +#endif + + /* {mvx_L1_max, mvx_L1_min} */ + rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA); + mv_hi = (rdata32>>16)&0xffff; + if (mv_hi & 0x8000) + mv_hi = 0x8000 - mv_hi; +#ifdef DEBUG_QOS + avs2_print(dec, 0, "[Picture %d Quality] MVX_L1 MAX : %d\n", + pic_number, mv_hi); +#endif + + mv_lo = (rdata32>>0)&0xffff; + if (mv_lo & 0x8000) + mv_lo = 0x8000 - mv_lo; +#ifdef DEBUG_QOS + avs2_print(dec, 0, "[Picture %d Quality] MVX_L1 MIN : %d\n", + pic_number, mv_lo); +#endif + + /* {mvy_L1_max, mvy_L1_min} */ + rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA); + mv_hi = (rdata32>>16)&0xffff; + if (mv_hi & 0x8000) + mv_hi = 0x8000 - mv_hi; +#ifdef DEBUG_QOS + avs2_print(dec, 0, "[Picture %d Quality] MVY_L1 MAX : %d\n", + pic_number, mv_hi); +#endif + mv_lo = (rdata32>>0)&0xffff; + if (mv_lo & 0x8000) + mv_lo = 0x8000 - mv_lo; +#ifdef DEBUG_QOS + avs2_print(dec, 0, "[Picture %d Quality] MVY_L1 MIN : %d\n", + pic_number, mv_lo); +#endif + + rdata32 = READ_VREG(HEVC_PIC_QUALITY_CTRL); +#ifdef DEBUG_QOS + avs2_print(dec, 0, + "[Picture %d Quality] After Read : VDEC_PIC_QUALITY_CTRL : 0x%x\n", + pic_number, rdata32); +#endif + /* reset all counts */ + WRITE_VREG(HEVC_PIC_QUALITY_CTRL, (1<<8)); + } +} + static irqreturn_t vavs2_isr_thread_fn(int irq, void *data) { struct AVS2Decoder_s *dec = (struct AVS2Decoder_s *)data; @@ -4024,46 +5207,64 @@ static irqreturn_t vavs2_isr_thread_fn(int irq, void *data) /*if (dec->wait_buf) pr_info("set wait_buf to 0\r\n"); */ + avs2_print(dec, AVS2_DBG_BUFMGR_MORE, - "%s %x\n", __func__, dec_status); + "%s decode_status 0x%x process_state %d lcu 0x%x\n", + __func__, dec_status, dec->process_state, + READ_VREG(HEVC_PARSER_LCU_START)); + #ifndef G12A_BRINGUP_DEBUG if (dec->eos) { PRINT_LINE(); - dec->process_busy = 0; - return IRQ_HANDLED; + goto irq_handled_exit; } #endif dec->wait_buf = 0; - if ((dec_status == HEVC_NAL_DECODE_DONE) || - (dec_status == AVS2_DECODE_TIMEOUT) || - (dec_status == AVS2_DECODE_BUFEMPTY) - ) { + if (dec_status == AVS2_DECODE_BUFEMPTY) { PRINT_LINE(); if (dec->m_ins_flag) { reset_process_time(dec); if (!vdec_frame_based(hw_to_vdec(dec))) dec_again_process(dec); else { - dec->dec_result = DEC_RESULT_GET_DATA; + dec->dec_result = DEC_RESULT_DONE; + reset_process_time(dec); + amhevc_stop(); vdec_schedule_work(&dec->work); } } - dec->process_busy = 0; - return IRQ_HANDLED; + goto irq_handled_exit; } else if (dec_status == HEVC_DECPIC_DATA_DONE) { PRINT_LINE(); + dec->start_decoding_flag |= 0x3; if (dec->m_ins_flag) { + update_decoded_pic(dec); + get_picture_qos_info(dec); reset_process_time(dec); dec->dec_result = DEC_RESULT_DONE; amhevc_stop(); +#if 0 /*def AVS2_10B_MMU*/ + if (dec->m_ins_flag) { + /*avs2_recycle_mmu_buf_tail(dec);*/ + dec->used_4k_num = + (READ_VREG(HEVC_SAO_MMU_STATUS) >> 16); + } +#endif + +#if 0 + /*keep hardware state*/ + WRITE_VREG(HEVC_MPRED_INT_STATUS, (1<<31)); + WRITE_VREG(HEVC_PARSER_RESULT_3, 0xffffffff); + dec->mpred_abv_start_addr = + READ_VREG(HEVC_MPRED_ABV_START_ADDR); + /**/ +#endif vdec_schedule_work(&dec->work); } - - dec->process_busy = 0; - return IRQ_HANDLED; + goto irq_handled_exit; } PRINT_LINE(); - +#if 0 if (dec_status == AVS2_EOS) { if (dec->m_ins_flag) reset_process_time(dec); @@ -4077,14 +5278,16 @@ static irqreturn_t vavs2_isr_thread_fn(int irq, void *data) avs2_print(dec, AVS2_DBG_BUFMGR, "send AVS2_10B_DISCARD_NAL\r\n"); WRITE_VREG(HEVC_DEC_STATUS_REG, AVS2_10B_DISCARD_NAL); - dec->process_busy = 0; if (dec->m_ins_flag) { + update_decoded_pic(dec); dec->dec_result = DEC_RESULT_DONE; amhevc_stop(); vdec_schedule_work(&dec->work); } - return IRQ_HANDLED; - } else if (dec_status == AVS2_DECODE_OVER_SIZE) { + goto irq_handled_exit; + } else +#endif + if (dec_status == AVS2_DECODE_OVER_SIZE) { avs2_print(dec, 0, "avs2 decode oversize !!\n"); debug |= (AVS2_DBG_DIS_LOC_ERROR_PROC | @@ -4092,33 +5295,79 @@ static irqreturn_t vavs2_isr_thread_fn(int irq, void *data) dec->fatal_error |= DECODER_FATAL_ERROR_SIZE_OVERFLOW; if (dec->m_ins_flag) reset_process_time(dec); - dec->process_busy = 0; - return IRQ_HANDLED; + goto irq_handled_exit; } PRINT_LINE(); if (dec->m_ins_flag) reset_process_time(dec); - if ((dec_status == AVS2_HEAD_PIC_I_READY) - || (dec_status == AVS2_HEAD_PIC_PB_READY)) { + if (dec_status == AVS2_HEAD_SEQ_READY) + start_code = SEQUENCE_HEADER_CODE; + else if (dec_status == AVS2_HEAD_PIC_I_READY) + start_code = I_PICTURE_START_CODE; + else if (dec_status == AVS2_HEAD_PIC_PB_READY) + start_code = PB_PICTURE_START_CODE; + else if (dec_status == AVS2_STARTCODE_SEARCH_DONE) + /*SEQUENCE_END_CODE, VIDEO_EDIT_CODE*/ + start_code = READ_VREG(CUR_NAL_UNIT_TYPE); + + if (dec->process_state == + PROC_STATE_HEAD_AGAIN + ) { + if ((start_code == I_PICTURE_START_CODE) + || (start_code == PB_PICTURE_START_CODE)) { + avs2_print(dec, 0, + "PROC_STATE_HEAD_AGAIN error, start_code 0x%x!!!\r\n", + start_code); + goto irq_handled_exit; + } else { + avs2_print(dec, AVS2_DBG_BUFMGR, + "PROC_STATE_HEAD_AGAIN, start_code 0x%x\r\n", + start_code); + dec->process_state = PROC_STATE_HEAD_DONE; + WRITE_VREG(HEVC_DEC_STATUS_REG, AVS2_ACTION_DONE); + goto irq_handled_exit; + } + } else if (dec->process_state == + PROC_STATE_DECODE_AGAIN) { + if ((start_code == I_PICTURE_START_CODE) + || (start_code == PB_PICTURE_START_CODE)) { + avs2_print(dec, AVS2_DBG_BUFMGR, + "PROC_STATE_DECODE_AGAIN=> decode_slice, start_code 0x%x\r\n", + start_code); + goto decode_slice; + } else { + avs2_print(dec, 0, + "PROC_STATE_DECODE_AGAIN, start_code 0x%x!!!\r\n", + start_code); + WRITE_VREG(HEVC_DEC_STATUS_REG, AVS2_ACTION_DONE); + goto irq_handled_exit; + } + } + + if ((start_code == I_PICTURE_START_CODE) + || (start_code == PB_PICTURE_START_CODE) + || (start_code == SEQUENCE_END_CODE) + || (start_code == VIDEO_EDIT_CODE)) { PRINT_LINE(); - if (dec->avs2_dec.hc.cur_pic != NULL && - dec->process_state != PROC_STATE_SENDAGAIN) { + if (dec->avs2_dec.hc.cur_pic != NULL) { int32_t ii; #ifdef AVS2_10B_MMU avs2_recycle_mmu_buf_tail(dec); #endif + check_pic_error(dec, dec->avs2_dec.hc.cur_pic); avs2_post_process(&dec->avs2_dec); + + if (debug & AVS2_DBG_PRINT_PIC_LIST) + dump_pic_list(dec); + avs2_prepare_display_buf(dec); dec->avs2_dec.hc.cur_pic = NULL; -#ifdef AVS2_10B_MMU for (ii = 0; ii < dec->avs2_dec.ref_maxbuffer; ii++) { if (dec->avs2_dec.fref[ii]-> - refered_by_others == 0 && - dec->avs2_dec.fref[ii]-> bg_flag == 0 && dec->avs2_dec.fref[ii]-> is_output == -1 && @@ -4126,16 +5375,43 @@ static irqreturn_t vavs2_isr_thread_fn(int irq, void *data) mmu_alloc_flag && dec->avs2_dec.fref[ii]-> vf_ref == 0) { - dec->avs2_dec.fref[ii]-> - mmu_alloc_flag = 0; - /*release_buffer_4k( - dec->avs2_dec.fref[ii]->index);*/ - decoder_mmu_box_free_idx(dec->mmu_box, - dec->avs2_dec.fref[ii]->index); + struct avs2_frame_s *pic = + dec->avs2_dec.fref[ii]; + if (dec->avs2_dec.fref[ii]-> + refered_by_others == 0) { +#ifdef AVS2_10B_MMU + dec->avs2_dec.fref[ii]-> + mmu_alloc_flag = 0; + /*release_buffer_4k( + dec->avs2_dec.fref[ii]->index);*/ + decoder_mmu_box_free_idx(dec->mmu_box, + dec->avs2_dec.fref[ii]->index); +#ifdef DYNAMIC_ALLOC_HEAD + decoder_bmmu_box_free_idx( + dec->bmmu_box, + HEADER_BUFFER_IDX(pic->index)); + pic->header_adr = 0; +#endif +#endif +#ifndef MV_USE_FIXED_BUF + decoder_bmmu_box_free_idx( + dec->bmmu_box, + MV_BUFFER_IDX(pic->index)); + pic->mpred_mv_wr_start_addr = 0; +#endif + } + decoder_bmmu_box_free_idx( + dec->bmmu_box, + VF_BUFFER_IDX(pic->index)); + dec->cma_alloc_addr = 0; } } -#endif } + } + + if ((dec_status == AVS2_HEAD_PIC_I_READY) + || (dec_status == AVS2_HEAD_PIC_PB_READY)) { + PRINT_LINE(); if (debug & AVS2_DBG_SEND_PARAM_WITH_REG) { get_rpm_param( @@ -4155,48 +5431,215 @@ static irqreturn_t vavs2_isr_thread_fn(int irq, void *data) dec->rpm_ptr[i + 3 - ii]; } } +#ifdef SANITY_CHECK + if (dec->avs2_dec.param.p.num_of_ref_cur > + dec->avs2_dec.ref_maxbuffer) { + pr_info("Warning: Wrong num_of_ref_cur %d, force to %d\n", + dec->avs2_dec.param.p.num_of_ref_cur, + dec->avs2_dec.ref_maxbuffer); + dec->avs2_dec.param.p.num_of_ref_cur = + dec->avs2_dec.ref_maxbuffer; + } +#endif PRINT_LINE(); debug_buffer_mgr_more(dec); + get_frame_rate(&dec->avs2_dec.param, dec); + if (dec->avs2_dec.param.p.video_signal_type + & (1<<30)) { + union param_u *pPara; + + avs2_print(dec, 0, + "avs2 HDR meta data present\n"); + pPara = &dec->avs2_dec.param; + + /*clean this flag*/ + pPara->p.video_signal_type + &= ~(1<<30); + + dec->vf_dp.present_flag = 1; + + dec->vf_dp.white_point[0] + = pPara->p.white_point_x; + avs2_print(dec, AVS2_DBG_HDR_INFO, + "white_point[0]:0x%x\n", + dec->vf_dp.white_point[0]); + + dec->vf_dp.white_point[1] + = pPara->p.white_point_y; + avs2_print(dec, AVS2_DBG_HDR_INFO, + "white_point[1]:0x%x\n", + dec->vf_dp.white_point[1]); + + for (i = 0; i < 3; i++) { + dec->vf_dp.primaries[i][0] + = pPara->p.display_primaries_x[i]; + avs2_print(dec, AVS2_DBG_HDR_INFO, + "primaries[%d][0]:0x%x\n", + i, + dec->vf_dp.primaries[i][0]); + } + + for (i = 0; i < 3; i++) { + dec->vf_dp.primaries[i][1] + = pPara->p.display_primaries_y[i]; + avs2_print(dec, AVS2_DBG_HDR_INFO, + "primaries[%d][1]:0x%x\n", + i, + dec->vf_dp.primaries[i][1]); + } + + dec->vf_dp.luminance[0] + = pPara->p.max_display_mastering_luminance; + avs2_print(dec, AVS2_DBG_HDR_INFO, + "luminance[0]:0x%x\n", + dec->vf_dp.luminance[0]); + + dec->vf_dp.luminance[1] + = pPara->p.min_display_mastering_luminance; + avs2_print(dec, AVS2_DBG_HDR_INFO, + "luminance[1]:0x%x\n", + dec->vf_dp.luminance[1]); + + + dec->vf_dp.content_light_level.present_flag + = 1; + dec->vf_dp.content_light_level.max_content + = pPara->p.max_content_light_level; + avs2_print(dec, AVS2_DBG_HDR_INFO, + "max_content:0x%x\n", + dec->vf_dp.content_light_level.max_content); + + dec->vf_dp.content_light_level.max_pic_average + = pPara->p.max_picture_average_light_level; + + avs2_print(dec, AVS2_DBG_HDR_INFO, + "max_pic_average:0x%x\n", + dec->vf_dp.content_light_level.max_pic_average); + } + + + if (dec->video_ori_signal_type != + ((dec->avs2_dec.param.p.video_signal_type << 16) + | dec->avs2_dec.param.p.color_description)) { + u32 v = dec->avs2_dec.param.p.video_signal_type; + u32 c = dec->avs2_dec.param.p.color_description; + u32 convert_c = c; + + if (v & 0x2000) { + avs2_print(dec, 0, + "video_signal_type present:\n"); + avs2_print(dec, 0, + " %s %s\n", + video_format_names[(v >> 10) & 7], + ((v >> 9) & 1) ? + "full_range" : "limited"); + if (v & 0x100) { + u32 transfer; + u32 maxtrix; + + avs2_print(dec, 0, + "color_description present:\n"); + avs2_print(dec, 0, + "color_primarie = %d\n", + v & 0xff); + avs2_print(dec, 0, + "transfer_characteristic = %d\n", + (c >> 8) & 0xff); + avs2_print(dec, 0, + " matrix_coefficient = %d\n", + c & 0xff); + + transfer = (c >> 8) & 0xFF; + if (transfer >= 15) + avs2_print(dec, 0, + "unsupport transfer_characteristic\n"); + else if (transfer == 14) + transfer = 18; /* HLG */ + else if (transfer == 13) + transfer = 32; + else if (transfer == 12) + transfer = 16; + else if (transfer == 11) + transfer = 15; + + maxtrix = c & 0xFF; + if (maxtrix >= 10) + avs2_print(dec, 0, + "unsupport matrix_coefficient\n"); + else if (maxtrix == 9) + maxtrix = 10; + else if (maxtrix == 8) + maxtrix = 9; + + convert_c = (transfer << 8) | (maxtrix); + + avs2_print(dec, 0, + " convered c:0x%x\n", + convert_c); + } + } + + if (enable_force_video_signal_type) + dec->video_signal_type + = force_video_signal_type; + else { + dec->video_signal_type + = (v << 16) | convert_c; + + dec->video_ori_signal_type + = (v << 16) | c; + } + + video_signal_type = dec->video_signal_type; + } } - - if (dec_status == AVS2_HEAD_SEQ_READY) - start_code = SEQUENCE_HEADER_CODE; - else if (dec_status == AVS2_HEAD_PIC_I_READY) - start_code = I_PICTURE_START_CODE; - else if (dec_status == AVS2_HEAD_PIC_PB_READY) - start_code = PB_PICTURE_START_CODE; - else if (dec_status == AVS2_HEAD_SEQ_END_READY) - start_code = SEQUENCE_END_CODE; - else if (dec_status == AVS2_STARTCODE_SEARCH_DONE) - start_code = READ_VREG(CUR_NAL_UNIT_TYPE); - +#if 0 + if ((debug_again & 0x4) && + dec->process_state == + PROC_STATE_INIT) { + if (start_code == PB_PICTURE_START_CODE) { + dec->process_state = PROC_STATE_TEST1; + dec_again_process(dec); + goto irq_handled_exit; + } + } +#endif PRINT_LINE(); avs2_prepare_header(&dec->avs2_dec, start_code); if (start_code == SEQUENCE_HEADER_CODE || - start_code == VIDEO_EDIT_CODE) + start_code == VIDEO_EDIT_CODE || + start_code == SEQUENCE_END_CODE) { + if (dec->m_ins_flag && + vdec_frame_based(hw_to_vdec(dec))) + dec->start_decoding_flag |= 0x1; + dec->process_state = PROC_STATE_HEAD_DONE; WRITE_VREG(HEVC_DEC_STATUS_REG, AVS2_ACTION_DONE); - else if (start_code == I_PICTURE_START_CODE || + } else if (start_code == I_PICTURE_START_CODE || start_code == PB_PICTURE_START_CODE) { ret = 0; - if (dec->process_state != PROC_STATE_SENDAGAIN) { - if (dec->pic_list_init_flag == 0) { - int32_t lcu_size_log2 = - log2i(dec->avs2_dec.param.p.lcu_size); + if (dec->pic_list_init_flag == 0) { + int32_t lcu_size_log2 = + log2i(dec->avs2_dec.param.p.lcu_size); - avs2_init_global_buffers(&dec->avs2_dec); - /*avs2_dec->m_bg->index is - set to dec->used_buf_num - 1*/ - init_pic_list(dec, lcu_size_log2); - init_pic_list_hw(dec); - } - ret = avs2_process_header(&dec->avs2_dec); - if (!dec->m_ins_flag) - dec->slice_idx++; + avs2_init_global_buffers(&dec->avs2_dec); + /*avs2_dec->m_bg->index is + set to dec->used_buf_num - 1*/ + init_pic_list(dec, lcu_size_log2); + init_pic_list_hw(dec); } + ret = avs2_process_header(&dec->avs2_dec); + if (!dec->m_ins_flag) + dec->slice_idx++; + PRINT_LINE(); +#ifdef I_ONLY_SUPPORT + if ((start_code == PB_PICTURE_START_CODE) && + (dec->i_only & 0x2)) + ret = -2; +#endif #ifdef AVS2_10B_MMU if (ret >= 0) { ret = avs2_alloc_mmu(dec, @@ -4215,12 +5658,34 @@ static irqreturn_t vavs2_isr_thread_fn(int irq, void *data) ret); } #endif + +#ifndef MV_USE_FIXED_BUF + if (ret >= 0 && + dec->avs2_dec.hc.cur_pic-> + mpred_mv_wr_start_addr == 0) { + unsigned long buf_addr; + unsigned mv_buf_size = 0x120000; + int i = dec->avs2_dec.hc.cur_pic->index; + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) + mv_buf_size = 0x120000 * 4; + if (decoder_bmmu_box_alloc_buf_phy + (dec->bmmu_box, + MV_BUFFER_IDX(i), + mv_buf_size, + DRIVER_NAME, + &buf_addr) < 0) + ret = -1; + else + dec->avs2_dec.hc.cur_pic-> + mpred_mv_wr_start_addr + = buf_addr; + } +#endif if (ret < 0) { avs2_print(dec, AVS2_DBG_BUFMGR, "avs2_bufmgr_process=> %d, AVS2_10B_DISCARD_NAL\r\n", ret); WRITE_VREG(HEVC_DEC_STATUS_REG, AVS2_10B_DISCARD_NAL); - dec->process_busy = 0; #ifdef AVS2_10B_MMU avs2_recycle_mmu_buf(dec); #endif @@ -4230,35 +5695,36 @@ static irqreturn_t vavs2_isr_thread_fn(int irq, void *data) vdec_schedule_work(&dec->work); } - return IRQ_HANDLED; + goto irq_handled_exit; } else { PRINT_LINE(); + dec->avs2_dec.hc.cur_pic->stream_offset = + READ_VREG(HEVC_SHIFT_BYTE_COUNT); /* struct PIC_BUFFER_CONFIG_s *cur_pic = &cm->cur_frame->buf; cur_pic->decode_idx = dec->frame_count; */ - if (dec->process_state != PROC_STATE_SENDAGAIN) { - if (!dec->m_ins_flag) { - dec->frame_count++; - decode_frame_count[dec->index] - = dec->frame_count; - } - /*MULTI_INSTANCE_SUPPORT*/ - if (dec->chunk) { - dec->avs2_dec.hc.cur_pic->pts = - dec->chunk->pts; - dec->avs2_dec.hc.cur_pic->pts64 = - dec->chunk->pts64; - } - /**/ + if (!dec->m_ins_flag) { + dec->frame_count++; + decode_frame_count[dec->index] + = dec->frame_count; } + /*MULTI_INSTANCE_SUPPORT*/ + if (dec->chunk) { + dec->avs2_dec.hc.cur_pic->pts = + dec->chunk->pts; + dec->avs2_dec.hc.cur_pic->pts64 = + dec->chunk->pts64; + } + /**/ dec->avs2_dec.hc.cur_pic->bit_depth = dec->avs2_dec.input.sample_bit_depth; dec->avs2_dec.hc.cur_pic->double_write_mode = get_double_write_mode(dec); - +decode_slice: PRINT_LINE(); + config_mc_buffer(dec); config_mcrcc_axi_hw(dec); config_mpred_hw(dec); @@ -4276,17 +5742,26 @@ static irqreturn_t vavs2_isr_thread_fn(int irq, void *data) dec->avs2_dec.fref[4]->imgtr_fwRefDistance, dec->avs2_dec.img.tr); + if ((debug_again & 0x2) && + dec->process_state == + PROC_STATE_INIT) { + dec->process_state = PROC_STATE_DECODING; + dec_again_process(dec); + goto irq_handled_exit; + } + + dec->process_state = PROC_STATE_DECODING; + WRITE_VREG(HEVC_DEC_STATUS_REG, AVS2_ACTION_DONE); } - dec->process_busy = 0; - dec->process_state = PROC_STATE_DECODESLICE; if (dec->m_ins_flag) start_process_time(dec); } - dec->process_busy = 0; +irq_handled_exit: PRINT_LINE(); + dec->process_busy = 0; return IRQ_HANDLED; } @@ -4296,6 +5771,7 @@ static irqreturn_t vavs2_isr(int irq, void *data) unsigned int dec_status; struct AVS2Decoder_s *dec = (struct AVS2Decoder_s *)data; uint debug_tag; + WRITE_VREG(HEVC_ASSIST_MBOX0_CLR_REG, 1); dec_status = READ_VREG(HEVC_DEC_STATUS_REG); @@ -4506,25 +5982,6 @@ static void vavs2_put_timer_func(unsigned long arg) dec->ucode_pause_pos = 0; WRITE_HREG(DEBUG_REG1, 0); } - if (debug & AVS2_DBG_FORCE_SEND_AGAIN) { - pr_info( - "Force Send Again\r\n"); - debug &= ~AVS2_DBG_FORCE_SEND_AGAIN; - reset_process_time(dec); - dec->dec_result = DEC_RESULT_AGAIN; - if (dec->process_state == - PROC_STATE_DECODESLICE) { -#ifdef AVS2_10B_MMU - avs2_recycle_mmu_buf(dec); -#endif - dec->process_state = - PROC_STATE_SENDAGAIN; - } - amhevc_stop(); - - vdec_schedule_work(&dec->work); - } - if (debug & AVS2_DBG_DUMP_DATA) { debug &= ~AVS2_DBG_DUMP_DATA; avs2_print(dec, 0, @@ -4544,6 +6001,50 @@ static void vavs2_put_timer_func(unsigned long arg) WRITE_VREG(HEVC_ASSIST_MBOX0_IRQ_REG, 0x1); debug &= ~AVS2_DBG_TRIG_SLICE_SEGMENT_PROC; } + if (debug & AVS2_DBG_DUMP_RPM_BUF) { + int i; + dma_sync_single_for_cpu( + amports_get_dma_device(), + dec->rpm_phy_addr, + RPM_BUF_SIZE, + DMA_FROM_DEVICE); + + pr_info("RPM:\n"); + for (i = 0; i < RPM_BUF_SIZE; i += 4) { + int ii; + if ((i & 0xf) == 0) + pr_info("%03x: ", i); + for (ii = 0; ii < 4; ii++) { + pr_info("%04x ", + dec->lmem_ptr[i + 3 - ii]); + } + if (((i + ii) & 0xf) == 0) + pr_info("\n"); + } + debug &= ~AVS2_DBG_DUMP_RPM_BUF; + } + if (debug & AVS2_DBG_DUMP_LMEM_BUF) { + int i; + dma_sync_single_for_cpu( + amports_get_dma_device(), + dec->lmem_phy_addr, + LMEM_BUF_SIZE, + DMA_FROM_DEVICE); + + pr_info("LMEM:\n"); + for (i = 0; i < LMEM_BUF_SIZE; i += 4) { + int ii; + if ((i & 0xf) == 0) + pr_info("%03x: ", i); + for (ii = 0; ii < 4; ii++) { + pr_info("%04x ", + dec->lmem_ptr[i + 3 - ii]); + } + if (((i + ii) & 0xf) == 0) + pr_info("\n"); + } + debug &= ~AVS2_DBG_DUMP_LMEM_BUF; + } /*if (debug & AVS2_DBG_HW_RESET) { }*/ @@ -4578,7 +6079,7 @@ static void vavs2_put_timer_func(unsigned long arg) if (dbg_cmd != 0) { if (dbg_cmd == 1) { u32 disp_laddr; - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXBB && + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXBB && get_double_write_mode(dec) == 0) { disp_laddr = READ_VCBUS_REG(AFBC_BODY_BADDR) << 4; @@ -4614,8 +6115,13 @@ int vavs2_dec_status(struct vdec_s *vdec, struct vdec_info *vstatus) { struct AVS2Decoder_s *dec = (struct AVS2Decoder_s *)vdec->private; - vstatus->frame_width = frame_width; - vstatus->frame_height = frame_height; + + if (!dec) + return -1; + + vstatus->frame_width = dec->frame_width; + vstatus->frame_height = dec->frame_height; + if (dec->frame_dur != 0) vstatus->frame_rate = 96000 / dec->frame_dur; else @@ -4714,6 +6220,21 @@ static void vavs2_prot_init(struct AVS2Decoder_s *dec) } +#ifdef I_ONLY_SUPPORT +static int vavs2_set_trickmode(struct vdec_s *vdec, unsigned long trickmode) +{ + struct AVS2Decoder_s *dec = + (struct AVS2Decoder_s *)vdec->private; + if (i_only_flag & 0x100) + return 0; + if (trickmode == TRICKMODE_I) + dec->i_only = 0x3; + else if (trickmode == TRICKMODE_NONE) + dec->i_only = 0x0; + return 0; +} +#endif + static int vavs2_local_init(struct AVS2Decoder_s *dec) { int i; @@ -4751,7 +6272,15 @@ TODO:FOR VERSION if (dec->frame_dur == 0) dec->frame_dur = 96000 / 24; - +#ifdef I_ONLY_SUPPORT + if (i_only_flag & 0x100) + dec->i_only = i_only_flag & 0xff; + else if ((unsigned long) dec->vavs2_amstream_dec_info.param + & 0x08) + dec->i_only = 0x7; + else + dec->i_only = 0x0; +#endif INIT_KFIFO(dec->display_q); INIT_KFIFO(dec->newframe_q); @@ -4771,7 +6300,7 @@ TODO:FOR VERSION static s32 vavs2_init(struct vdec_s *vdec) { - int size = -1; + int ret = -1, size = -1; int fw_size = 0x1000 * 16; struct firmware_s *fw = NULL; struct AVS2Decoder_s *dec = (struct AVS2Decoder_s *)vdec->private; @@ -4784,20 +6313,14 @@ static s32 vavs2_init(struct vdec_s *vdec) fw = vmalloc(sizeof(struct firmware_s) + fw_size); if (IS_ERR_OR_NULL(fw)) return -ENOMEM; -#ifdef MULTI_INSTANCE_SUPPORT - if (tee_enabled()) { - size = 1; - pr_debug ("laod\n"); - } else -#endif + size = get_firmware_data(VIDEO_DEC_AVS2_MMU, fw->data); if (size < 0) { pr_err("get firmware fail.\n"); vfree(fw); return -1; } - avs2_print(dec, AVS2_DBG_BUFMGR, - "firmware size %d\n", size); + fw->len = fw_size; if (dec->m_ins_flag) { @@ -4815,20 +6338,20 @@ static s32 vavs2_init(struct vdec_s *vdec) return 0; } - + hevc_enable_DMC(hw_to_vdec(dec)); amhevc_enable(); - if (size == 1) - pr_info ("tee load ok\n"); - if (amhevc_loadmc_ex(VFORMAT_AVS2, NULL, fw->data) < 0) { + ret = amhevc_loadmc_ex(VFORMAT_AVS2, NULL, fw->data); + if (ret < 0) { amhevc_disable(); vfree(fw); + pr_err("AVS2: the %s fw loading failed, err: %x\n", + tee_enabled() ? "TEE" : "local", ret); return -EBUSY; } - avs2_print(dec, AVS2_DBG_BUFMGR, - "firmware size %d\n", size); vfree(fw); + dec->stat |= STAT_MC_LOAD; /* enable AMRISC side protocol */ @@ -4870,12 +6393,6 @@ static s32 vavs2_init(struct vdec_s *vdec) dec->stat |= STAT_TIMER_ARM; /* dec->stat |= STAT_KTHREAD; */ - - amhevc_start(); - - dec->stat |= STAT_VDEC_RUN; - - dec->init_flag = 1; dec->process_busy = 0; avs2_print(dec, AVS2_DBG_BUFMGR_MORE, "%d, vavs2_init, RP=0x%x\n", @@ -4886,7 +6403,7 @@ static s32 vavs2_init(struct vdec_s *vdec) static int vmavs2_stop(struct AVS2Decoder_s *dec) { dec->init_flag = 0; - + dec->first_sc_checked = 0; if (dec->stat & STAT_TIMER_ARM) { del_timer_sync(&dec->timer); dec->stat &= ~STAT_TIMER_ARM; @@ -4905,6 +6422,10 @@ static int vmavs2_stop(struct AVS2Decoder_s *dec) reset_process_time(dec); cancel_work_sync(&dec->work); uninit_mmu_buffers(dec); + if (dec->fw) { + vfree(dec->fw); + dec->fw = NULL; + } return 0; } @@ -4914,7 +6435,7 @@ static int vavs2_stop(struct AVS2Decoder_s *dec) { dec->init_flag = 0; - + dec->first_sc_checked = 0; if (dec->stat & STAT_VDEC_RUN) { amhevc_stop(); dec->stat &= ~STAT_VDEC_RUN; @@ -4948,8 +6469,6 @@ static int vavs2_stop(struct AVS2Decoder_s *dec) else amhevc_disable(); uninit_mmu_buffers(dec); - vfree(dec->fw); - dec->fw = NULL; return 0; } @@ -4958,11 +6477,14 @@ static int amvdec_avs2_mmu_init(struct AVS2Decoder_s *dec) { int tvp_flag = vdec_secure(hw_to_vdec(dec)) ? CODEC_MM_FLAGS_TVP : 0; + int buf_size = 48; #ifdef AVS2_10B_MMU + dec->need_cache_size = buf_size * SZ_1M; + dec->sc_start_time = get_jiffies_64(); dec->mmu_box = decoder_mmu_box_alloc_box(DRIVER_NAME, dec->index, FRAME_BUFFERS, - 48 * SZ_1M, + dec->need_cache_size, tvp_flag ); if (!dec->mmu_box) { @@ -4989,23 +6511,17 @@ static int amvdec_avs2_probe(struct platform_device *pdev) { struct vdec_s *pdata = *(struct vdec_s **)pdev->dev.platform_data; struct BUF_s BUF[MAX_BUF_NUM]; - struct AVS2Decoder_s *dec; + struct AVS2Decoder_s *dec = &gAVS2Decoder; int ret; pr_info("%s\n", __func__); mutex_lock(&vavs2_mutex); - dec = vmalloc(sizeof(struct AVS2Decoder_s)); - if (dec == NULL) { - pr_info("failed to vamlloc amvdec_avs2 dec struct\n"); - return -ENOMEM; - } - gHevc = dec; memcpy(&BUF[0], &dec->m_BUF[0], sizeof(struct BUF_s) * MAX_BUF_NUM); memset(dec, 0, sizeof(struct AVS2Decoder_s)); memcpy(&dec->m_BUF[0], &BUF[0], sizeof(struct BUF_s) * MAX_BUF_NUM); dec->init_flag = 0; - + dec->first_sc_checked = 0; dec->eos = 0; dec->start_process_time = 0; dec->timeout_num = 0; @@ -5014,7 +6530,6 @@ static int amvdec_avs2_probe(struct platform_device *pdev) if (pdata == NULL) { avs2_print(dec, 0, "\namvdec_avs2 memory resource undefined.\n"); - vfree(dec); mutex_unlock(&vavs2_mutex); return -EFAULT; } @@ -5023,7 +6538,6 @@ static int amvdec_avs2_probe(struct platform_device *pdev) platform_set_drvdata(pdev, pdata); if (amvdec_avs2_mmu_init(dec) < 0) { - vfree(dec); mutex_unlock(&vavs2_mutex); pr_err("avs2 alloc bmmu box failed!!\n"); return -1; @@ -5033,7 +6547,6 @@ static int amvdec_avs2_probe(struct platform_device *pdev) work_buf_size, DRIVER_NAME, &pdata->mem_start); if (ret < 0) { uninit_mmu_buffers(dec); - vfree(dec); mutex_unlock(&vavs2_mutex); return ret; } @@ -5048,9 +6561,11 @@ static int amvdec_avs2_probe(struct platform_device *pdev) pdata->mem_start, dec->buf_size); } - if (pdata->sys_info) + if (pdata->sys_info) { dec->vavs2_amstream_dec_info = *pdata->sys_info; - else { + dec->frame_width = dec->vavs2_amstream_dec_info.width; + dec->frame_height = dec->vavs2_amstream_dec_info.height; + } else { dec->vavs2_amstream_dec_info.width = 0; dec->vavs2_amstream_dec_info.height = 0; dec->vavs2_amstream_dec_info.rate = 30; @@ -5059,13 +6574,13 @@ static int amvdec_avs2_probe(struct platform_device *pdev) pdata->private = dec; pdata->dec_status = vavs2_dec_status; - pdata->set_isreset = vavs2_set_isreset; + /*pdata->set_isreset = vavs2_set_isreset;*/ is_reset = 0; if (vavs2_init(pdata) < 0) { pr_info("\namvdec_avs2 init failed.\n"); avs2_local_uninit(dec); uninit_mmu_buffers(dec); - vfree(dec); + pdata->dec_status = NULL; mutex_unlock(&vavs2_mutex); return -ENODEV; } @@ -5079,7 +6594,7 @@ static int amvdec_avs2_probe(struct platform_device *pdev) static int amvdec_avs2_remove(struct platform_device *pdev) { - struct AVS2Decoder_s *dec = gHevc; + struct AVS2Decoder_s *dec = &gAVS2Decoder; if (debug) pr_info("amvdec_avs2_remove\n"); @@ -5096,8 +6611,6 @@ static int amvdec_avs2_remove(struct platform_device *pdev) dec->pts_missed, dec->pts_hit, dec->frame_dur); #endif - vfree(dec); - mutex_unlock(&vavs2_mutex); return 0; @@ -5127,20 +6640,37 @@ static unsigned char get_data_check_sum { int jj; int sum = 0; - u8 *data = ((u8 *)dec->chunk->block->start_virt) + - dec->chunk->offset; + u8 *data = NULL; + + if (!dec->chunk->block->is_mapped) + data = codec_mm_vmap(dec->chunk->block->start + + dec->chunk->offset, size); + else + data = ((u8 *)dec->chunk->block->start_virt) + + dec->chunk->offset; + for (jj = 0; jj < size; jj++) sum += data[jj]; + + if (!dec->chunk->block->is_mapped) + codec_mm_unmap_phyaddr(data); return sum; } static void dump_data(struct AVS2Decoder_s *dec, int size) { int jj; - u8 *data = ((u8 *)dec->chunk->block->start_virt) + - dec->chunk->offset; + u8 *data = NULL; int padding_size = dec->chunk->offset & (VDEC_FIFO_ALIGN - 1); + + if (!dec->chunk->block->is_mapped) + data = codec_mm_vmap(dec->chunk->block->start + + dec->chunk->offset, size); + else + data = ((u8 *)dec->chunk->block->start_virt) + + dec->chunk->offset; + avs2_print(dec, 0, "padding: "); for (jj = padding_size; jj > 0; jj--) avs2_print_cont(dec, @@ -5165,6 +6695,9 @@ static void dump_data(struct AVS2Decoder_s *dec, int size) avs2_print(dec, 0, "\n"); + + if (!dec->chunk->block->is_mapped) + codec_mm_unmap_phyaddr(data); } static void avs2_work(struct work_struct *work) @@ -5290,6 +6823,7 @@ static void avs2_work(struct work_struct *work) "%s: end of stream\n", __func__); dec->eos = 1; + check_pic_error(dec, dec->avs2_dec.hc.cur_pic); avs2_post_process(&dec->avs2_dec); avs2_prepare_display_buf(dec); vdec_vframe_dirty(hw_to_vdec(dec), dec->chunk); @@ -5315,7 +6849,10 @@ static void avs2_work(struct work_struct *work) dec->stat &= ~STAT_TIMER_ARM; } /* mark itself has all HW resource released and input released */ - vdec_core_finish_run(vdec, CORE_MASK_VDEC_1 | CORE_MASK_HEVC); + if (vdec->parallel_dec ==1) + vdec_core_finish_run(vdec, CORE_MASK_HEVC); + else + vdec_core_finish_run(vdec, CORE_MASK_VDEC_1 | CORE_MASK_HEVC); if (dec->vdec_cb) dec->vdec_cb(hw_to_vdec(dec), dec->vdec_cb_arg); @@ -5332,21 +6869,89 @@ static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask) { struct AVS2Decoder_s *dec = (struct AVS2Decoder_s *)vdec->private; - bool ret = 0; + int tvp = vdec_secure(hw_to_vdec(dec)) ? + CODEC_MM_FLAGS_TVP : 0; + unsigned long ret = 0; avs2_print(dec, PRINT_FLAG_VDEC_DETAIL, "%s\r\n", __func__); + if (debug & AVS2_DBG_PIC_LEAK_WAIT) + return ret; + if (dec->eos) return ret; + if (!dec->first_sc_checked) { + int size = decoder_mmu_box_sc_check(dec->mmu_box, tvp); + dec->first_sc_checked = 1; + avs2_print(dec, 0, "vavs2 cached=%d need_size=%d speed= %d ms\n", + size, (dec->need_cache_size >> PAGE_SHIFT), + (int)(get_jiffies_64() - dec->sc_start_time) * 1000/HZ); + } + + if (dec->next_again_flag && + (!vdec_frame_based(vdec))) { + u32 parser_wr_ptr = + READ_PARSER_REG(PARSER_VIDEO_WP); + if (parser_wr_ptr >= dec->pre_parser_wr_ptr && + (parser_wr_ptr - dec->pre_parser_wr_ptr) < + again_threshold) { + int r = vdec_sync_input(vdec); + avs2_print(dec, + PRINT_FLAG_VDEC_DETAIL, "%s buf lelvel:%x\n", __func__, r); + return 0; + } + } +/* + if (vdec_stream_based(vdec) && (dec->pic_list_init_flag == 0) + && pre_decode_buf_level != 0) { + u32 rp, wp, level; + + rp = READ_PARSER_REG(PARSER_VIDEO_RP); + wp = READ_PARSER_REG(PARSER_VIDEO_WP); + if (wp < rp) + level = vdec->input.size + wp - rp; + else + level = wp - rp; + + if (level < pre_decode_buf_level) + return 0; + } +*/ if ((dec->pic_list_init_flag == 0) || get_free_buf_count(dec) >= run_ready_min_buf_num) ret = 1; +#ifdef CONSTRAIN_MAX_BUF_NUM + if (dec->pic_list_init_flag) { + if (run_ready_max_vf_only_num > 0 && + get_vf_ref_only_buf_count(dec) >= + run_ready_max_vf_only_num + ) + ret = 0; + if (run_ready_display_q_num > 0 && + kfifo_len(&dec->display_q) >= + run_ready_display_q_num) + ret = 0; + + if (run_ready_max_buf_num == 0xff && + get_used_buf_count(dec) >= + dec->avs2_dec.ref_maxbuffer) + ret = 0; + else if (run_ready_max_buf_num && + get_used_buf_count(dec) >= + run_ready_max_buf_num) + ret = 0; + } +#endif if (ret) not_run_ready[dec->index] = 0; else not_run_ready[dec->index]++; - return ret ? (CORE_MASK_VDEC_1 | CORE_MASK_HEVC) : 0; + + if (vdec->parallel_dec == 1) + return ret ? CORE_MASK_HEVC : 0; + else + return ret ? (CORE_MASK_VDEC_1 | CORE_MASK_HEVC) : 0; } static void run(struct vdec_s *vdec, unsigned long mask, @@ -5361,6 +6966,9 @@ static void run(struct vdec_s *vdec, unsigned long mask, dec->vdec_cb = callback; /* dec->chunk = vdec_prepare_input(vdec); */ hevc_reset_core(vdec); + dec->pre_parser_wr_ptr = + READ_PARSER_REG(PARSER_VIDEO_WP); + dec->next_again_flag = 0; r = vdec_prepare_input(vdec, &dec->chunk); if (r < 0) { @@ -5386,23 +6994,31 @@ static void run(struct vdec_s *vdec, unsigned long mask, dec->frame_count, r, dec->chunk ? dec->chunk->size : 0, dec->chunk ? dec->chunk->offset : 0, - (vdec_frame_based(vdec) && + dec->chunk ? ((vdec_frame_based(vdec) && (debug & PRINT_FLAG_VDEC_STATUS)) ? - get_data_check_sum(dec, r) : 0, + get_data_check_sum(dec, r) : 0) : 0, READ_VREG(HEVC_STREAM_START_ADDR), READ_VREG(HEVC_STREAM_END_ADDR), READ_VREG(HEVC_STREAM_LEVEL), READ_VREG(HEVC_STREAM_WR_PTR), READ_VREG(HEVC_STREAM_RD_PTR), dec->start_shift_bytes); - if (vdec_frame_based(vdec)) { - u8 *data = ((u8 *)dec->chunk->block->start_virt) + - dec->chunk->offset; + if (vdec_frame_based(vdec) && dec->chunk) { + u8 *data = NULL; + if (!dec->chunk->block->is_mapped) + data = codec_mm_vmap(dec->chunk->block->start + + dec->chunk->offset, 8); + else + data = ((u8 *)dec->chunk->block->start_virt) + + dec->chunk->offset; + avs2_print_cont(dec, 0, "data adr %p:", data); for (ii = 0; ii < 8; ii++) avs2_print_cont(dec, 0, "%02x ", data[ii]); + if (!dec->chunk->block->is_mapped) + codec_mm_unmap_phyaddr(data); } avs2_print_cont(dec, 0, "\r\n"); } @@ -5416,9 +7032,13 @@ static void run(struct vdec_s *vdec, unsigned long mask, amhevc_disable(); avs2_print(dec, 0, "%s: Error amvdec_loadmc fail\n", __func__); + dec->dec_result = DEC_RESULT_FORCE_EXIT; + vdec_schedule_work(&dec->work); return; - } else + } else { vdec->mc_loaded = 1; + vdec->mc_type = VFORMAT_AVS2; + } if (avs2_hw_ctx_restore(dec) < 0) { @@ -5428,9 +7048,9 @@ static void run(struct vdec_s *vdec, unsigned long mask, vdec_enable_input(vdec); - WRITE_VREG(HEVC_DEC_STATUS_REG, AVS2_ACTION_DONE); + WRITE_VREG(HEVC_DEC_STATUS_REG, AVS2_SEARCH_NEW_PIC); - if (vdec_frame_based(vdec)) { + if (vdec_frame_based(vdec) && dec->chunk) { if (debug & PRINT_FLAG_VDEC_DATA) dump_data(dec, dec->chunk->size); @@ -5594,9 +7214,13 @@ static void avs2_dump_state(struct vdec_s *vdec) int jj; if (dec->chunk && dec->chunk->block && dec->chunk->size > 0) { - u8 *data = - ((u8 *)dec->chunk->block->start_virt) + - dec->chunk->offset; + u8 *data = NULL; + if (!dec->chunk->block->is_mapped) + data = codec_mm_vmap(dec->chunk->block->start + + dec->chunk->offset, dec->chunk->size); + else + data = ((u8 *)dec->chunk->block->start_virt) + + dec->chunk->offset; avs2_print(dec, 0, "frame data size 0x%x\n", dec->chunk->size); @@ -5610,6 +7234,9 @@ static void avs2_dump_state(struct vdec_s *vdec) avs2_print_cont(dec, 0, "\n"); } + + if (!dec->chunk->block->is_mapped) + codec_mm_unmap_phyaddr(data); } } @@ -5639,9 +7266,18 @@ static int ammvdec_avs2_probe(struct platform_device *pdev) pr_info("\nammvdec_avs2 device data allocation failed\n"); return -ENOMEM; } + if (pdata->parallel_dec == 1) { + int i; + for (i = 0; i < AVS2_MAX_BUFFER_NUM; i++) { + dec->avs2_dec.frm_pool[i].y_canvas_index = -1; + dec->avs2_dec.frm_pool[i].uv_canvas_index = -1; + } + } pdata->private = dec; pdata->dec_status = vavs2_dec_status; - /* pdata->set_trickmode = set_trickmode; */ +#ifdef I_ONLY_SUPPORT + pdata->set_trickmode = vavs2_set_trickmode; +#endif pdata->run_ready = run_ready; pdata->run = run; pdata->reset = reset; @@ -5649,18 +7285,18 @@ static int ammvdec_avs2_probe(struct platform_device *pdev) pdata->threaded_irq_handler = avs2_threaded_irq_cb; pdata->dump_state = avs2_dump_state; - - memcpy(&BUF[0], &dec->m_BUF[0], sizeof(struct BUF_s) * MAX_BUF_NUM); memset(dec, 0, sizeof(struct AVS2Decoder_s)); memcpy(&dec->m_BUF[0], &BUF[0], sizeof(struct BUF_s) * MAX_BUF_NUM); dec->index = pdev->id; + dec->m_ins_flag = 1; - if (pdata->use_vfm_path) + if (pdata->use_vfm_path) { snprintf(pdata->vf_provider_name, VDEC_PROVIDER_NAME_SIZE, VFM_DEC_PROVIDER_NAME); - else + dec->frameinfo_enable = 1; + } else snprintf(pdata->vf_provider_name, VDEC_PROVIDER_NAME_SIZE, MULTI_INSTANCE_PROVIDER_NAME ".%02x", pdev->id & 0xff); @@ -5672,7 +7308,8 @@ static int ammvdec_avs2_probe(struct platform_device *pdev) dec->platform_dev = pdev; dec->video_signal_type = 0; - if (get_cpu_type() < MESON_CPU_MAJOR_ID_TXLX) + dec->video_ori_signal_type = 0; + if (get_cpu_major_id() < AM_MESON_CPU_MAJOR_ID_TXLX) dec->stat |= VP9_TRIGGER_FRAME_ENABLE; #if 1 if ((debug & IGNORE_PARAM_FROM_CONFIG) == 0 && @@ -5755,9 +7392,8 @@ static int ammvdec_avs2_probe(struct platform_device *pdev) dec->buf_start = dec->cma_alloc_addr; dec->buf_size = work_buf_size; #endif - dec->m_ins_flag = 1; - dec->init_flag = 0; + dec->first_sc_checked = 0; dec->fatal_error = 0; dec->show_frame_num = 0; if (pdata == NULL) { @@ -5774,9 +7410,11 @@ static int ammvdec_avs2_probe(struct platform_device *pdev) dec->buf_size); } - if (pdata->sys_info) + if (pdata->sys_info) { dec->vavs2_amstream_dec_info = *pdata->sys_info; - else { + dec->frame_width = dec->vavs2_amstream_dec_info.width; + dec->frame_height = dec->vavs2_amstream_dec_info.height; + } else { dec->vavs2_amstream_dec_info.width = 0; dec->vavs2_amstream_dec_info.height = 0; dec->vavs2_amstream_dec_info.rate = 30; @@ -5789,14 +7427,18 @@ static int ammvdec_avs2_probe(struct platform_device *pdev) uninit_mmu_buffers(dec); /* devm_kfree(&pdev->dev, (void *)dec); */ vfree((void *)dec); + pdata->dec_status = NULL; return -ENODEV; } vdec_set_prepare_level(pdata, start_decode_buf_level); hevc_source_changed(VFORMAT_AVS2, 4096, 2048, 60); - - vdec_core_request(pdata, CORE_MASK_VDEC_1 | CORE_MASK_HEVC + if (pdata->parallel_dec == 1) + vdec_core_request(pdata, CORE_MASK_HEVC); + else { + vdec_core_request(pdata, CORE_MASK_VDEC_1 | CORE_MASK_HEVC | CORE_MASK_COMBINE); + } return 0; } @@ -5805,14 +7447,26 @@ static int ammvdec_avs2_remove(struct platform_device *pdev) { struct AVS2Decoder_s *dec = (struct AVS2Decoder_s *) (((struct vdec_s *)(platform_get_drvdata(pdev)))->private); + struct vdec_s *pdata = *(struct vdec_s **)pdev->dev.platform_data; + int i; + if (debug) pr_info("amvdec_avs2_remove\n"); vmavs2_stop(dec); - vdec_core_release(hw_to_vdec(dec), CORE_MASK_HEVC); + if (pdata->parallel_dec == 1) + vdec_core_release(hw_to_vdec(dec), CORE_MASK_HEVC); + else + vdec_core_release(hw_to_vdec(dec), CORE_MASK_HEVC); vdec_set_status(hw_to_vdec(dec), VDEC_STATUS_DISCONNECTED); + if (pdata->parallel_dec == 1) { + for (i = 0; i < AVS2_MAX_BUFFER_NUM; i++) { + pdata->free_canvas_ex(dec->avs2_dec.frm_pool[i].y_canvas_index, pdata->id); + pdata->free_canvas_ex(dec->avs2_dec.frm_pool[i].uv_canvas_index, pdata->id); + } + } #ifdef DEBUG_PTS @@ -5880,14 +7534,15 @@ static int __init amvdec_avs2_driver_init_module(void) #ifdef AVS2_10B_MMU struct BuffInfo_s *p_buf_info; -#ifdef SUPPORT_4K2K - if (vdec_is_support_4k()) - p_buf_info = &amvavs2_workbuff_spec[1]; - else + + if (vdec_is_support_4k()) { + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) + p_buf_info = &amvavs2_workbuff_spec[2]; + else + p_buf_info = &amvavs2_workbuff_spec[1]; + } else p_buf_info = &amvavs2_workbuff_spec[0]; -#else - p_buf_info = &amvavs2_workbuff_spec[0]; -#endif + init_buff_spec(NULL, p_buf_info); work_buf_size = (p_buf_info->end_adr - p_buf_info->start_adr @@ -5896,8 +7551,6 @@ static int __init amvdec_avs2_driver_init_module(void) #endif pr_debug("amvdec_avs2 module init\n"); - error_handle_policy = 0; - #ifdef ERROR_HANDLE_DEBUG dbg_nal_skip_flag = 0; dbg_nal_skip_count = 0; @@ -5915,19 +7568,22 @@ static int __init amvdec_avs2_driver_init_module(void) return -ENODEV; } - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXL - /*&& get_cpu_type() != MESON_CPU_MAJOR_ID_GXLX*/) { + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) { + amvdec_avs2_profile.profile = + "8k, 10bit, dwrite, compressed"; + vcodec_profile_register(&amvdec_avs2_profile); + } else if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A) { if (vdec_is_support_4k()) amvdec_avs2_profile.profile = "4k, 10bit, dwrite, compressed"; else amvdec_avs2_profile.profile = "10bit, dwrite, compressed"; + vcodec_profile_register(&amvdec_avs2_profile); } else { amvdec_avs2_profile.name = "avs2_unsupport"; } - vcodec_profile_register(&amvdec_avs2_profile); INIT_REG_NODE_CONFIGS("media.decoder", &avs2_node, "avs2", avs2_configs, CONFIG_FOR_RW); @@ -5958,6 +7614,9 @@ MODULE_PARM_DESC(frame_height, "\n amvdec_avs2 frame_height\n"); module_param(debug, uint, 0664); MODULE_PARM_DESC(debug, "\n amvdec_avs2 debug\n"); +module_param(debug_again, uint, 0664); +MODULE_PARM_DESC(debug_again, "\n amvdec_avs2 debug_again\n"); + module_param(radr, uint, 0664); MODULE_PARM_DESC(radr, "\nradr\n"); @@ -5991,6 +7650,9 @@ MODULE_PARM_DESC(i_only_flag, "\n amvdec_avs2 i_only_flag\n"); module_param(error_handle_policy, uint, 0664); MODULE_PARM_DESC(error_handle_policy, "\n amvdec_avs2 error_handle_policy\n"); +module_param(re_search_seq_threshold, uint, 0664); +MODULE_PARM_DESC(re_search_seq_threshold, "\n amvdec_avs2 re_search_seq_threshold\n"); + module_param(buf_alloc_width, uint, 0664); MODULE_PARM_DESC(buf_alloc_width, "\n buf_alloc_width\n"); @@ -6015,6 +7677,17 @@ MODULE_PARM_DESC(max_buf_num, "\n max_buf_num\n"); module_param(dynamic_buf_num_margin, uint, 0664); MODULE_PARM_DESC(dynamic_buf_num_margin, "\n dynamic_buf_num_margin\n"); +#ifdef CONSTRAIN_MAX_BUF_NUM +module_param(run_ready_max_vf_only_num, uint, 0664); +MODULE_PARM_DESC(run_ready_max_vf_only_num, "\n run_ready_max_vf_only_num\n"); + +module_param(run_ready_display_q_num, uint, 0664); +MODULE_PARM_DESC(run_ready_display_q_num, "\n run_ready_display_q_num\n"); + +module_param(run_ready_max_buf_num, uint, 0664); +MODULE_PARM_DESC(run_ready_max_buf_num, "\n run_ready_max_buf_num\n"); +#endif + module_param(mv_buf_margin, uint, 0664); MODULE_PARM_DESC(mv_buf_margin, "\n mv_buf_margin\n"); @@ -6071,6 +7744,16 @@ module_param_array(input_empty, uint, module_param_array(not_run_ready, uint, &max_decode_instance_num, 0664); +module_param(video_signal_type, uint, 0664); +MODULE_PARM_DESC(video_signal_type, "\n amvdec_avs2 video_signal_type\n"); + +module_param(force_video_signal_type, uint, 0664); +MODULE_PARM_DESC(force_video_signal_type, "\n amvdec_avs2 force_video_signal_type\n"); + +module_param(enable_force_video_signal_type, uint, 0664); +MODULE_PARM_DESC(enable_force_video_signal_type, "\n amvdec_avs2 enable_force_video_signal_type\n"); + + module_param(udebug_flag, uint, 0664); MODULE_PARM_DESC(udebug_flag, "\n amvdec_h265 udebug_flag\n"); @@ -6083,6 +7766,14 @@ MODULE_PARM_DESC(udebug_pause_val, "\n udebug_pause_val\n"); module_param(udebug_pause_decode_idx, uint, 0664); MODULE_PARM_DESC(udebug_pause_decode_idx, "\n udebug_pause_decode_idx\n"); +module_param(pre_decode_buf_level, int, 0664); +MODULE_PARM_DESC(pre_decode_buf_level, + "\n amvdec_avs2 pre_decode_buf_level\n"); + +module_param(again_threshold, uint, 0664); +MODULE_PARM_DESC(again_threshold, "\n again_threshold\n"); + + module_param(force_disp_pic_index, int, 0664); MODULE_PARM_DESC(force_disp_pic_index, "\n amvdec_h265 force_disp_pic_index\n"); diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/h264/vh264.c b/drivers/amlogic/media_modules/frame_provider/decoder/h264/vh264.c index 40c7bbdc8dd2..0e594ea41b80 100644 --- a/drivers/amlogic/media_modules/frame_provider/decoder/h264/vh264.c +++ b/drivers/amlogic/media_modules/frame_provider/decoder/h264/vh264.c @@ -54,11 +54,18 @@ #include #include "../utils/firmware.h" #include +#include "../../../common/chips/decoder_cpu_ver_info.h" +#include + + +#include + #define DRIVER_NAME "amvdec_h264" #define MODULE_NAME "amvdec_h264" #define MEM_NAME "codec_264" #define HANDLE_H264_IRQ +#define ENABLE_SEI_ITU_T35 #if 0 /* currently, only iptv supports this function*/ @@ -77,7 +84,7 @@ #define PTS2DUR(x) ((x)*96/90) #define DUR2PTS_REM(x) (x*90 - DUR2PTS(x)*96) #define FIX_FRAME_RATE_CHECK_IDRFRAME_NUM 2 -#define VDEC_CLOCK_ADJUST_FRAME 50 +#define VDEC_CLOCK_ADJUST_FRAME 30 static inline bool close_to(int a, int b, int m) { @@ -241,13 +248,19 @@ static u32 max_refer_buf = 1; static u32 decoder_force_reset; static unsigned int no_idr_error_count; static unsigned int no_idr_error_max = 60; +static unsigned int canvas_mode; + #ifdef SUPPORT_BAD_MACRO_BLOCK_REDUNDANCY /* 0~128*/ static u32 bad_block_scale; #endif +static u32 enable_userdata_debug; -static unsigned int enable_switch_fense = 1; +static unsigned int enable_switch_fense = 0; #define EN_SWITCH_FENCE() (enable_switch_fense && !is_4k) +static struct vframe_qos_s s_vframe_qos; +static int frame_count; + #if 0 static u32 vh264_no_disp_wd_count; #endif @@ -270,7 +283,7 @@ static bool check_pts_discontinue; static u32 wait_buffer_counter; static u32 video_signal_from_vui; -static uint error_recovery_mode; +static uint error_recovery_mode = 1; static uint error_recovery_mode_in = 3; static uint error_recovery_mode_use = 3; @@ -294,13 +307,36 @@ static struct work_struct notify_work; static struct work_struct set_clk_work; static struct work_struct userdata_push_work; +struct h264_qos_data_node_t { + struct list_head list; + uint32_t b_offset; + int poc; + /* picture qos infomation*/ + int max_qp; + int avg_qp; + int min_qp; + int max_skip; + int avg_skip; + int min_skip; + int max_mv; + int min_mv; + int avg_mv; +}; +/*qos data records list waiting for match with picture that be display*/ +static struct list_head picture_qos_list; +/*free qos data records list*/ +static struct list_head free_qos_nodes_list; +#define MAX_FREE_QOS_NODES 64 +static struct h264_qos_data_node_t free_nodes[MAX_FREE_QOS_NODES]; +static struct work_struct qos_work; static struct dec_sysinfo vh264_amstream_dec_info; static dma_addr_t mc_dma_handle; static void *mc_cpu_addr; static u32 first_offset; static u32 first_pts; +static u32 first_frame_size; static u64 first_pts64; static bool first_pts_cached; static void *sei_data_buffer; @@ -327,6 +363,7 @@ static bool block_display_q; static int vh264_stop(int mode); static s32 vh264_init(void); + #define DFS_HIGH_THEASHOLD 3 static bool pts_discontinue; @@ -335,6 +372,8 @@ static struct ge2d_context_s *ge2d_videoh264_context; static struct vdec_info *gvs; +static struct vdec_s *vdec_h264; + static int ge2d_videoh264task_init(void) { if (ge2d_videoh264_context == NULL) @@ -410,7 +449,7 @@ static int ge2d_canvas_dup(struct canvas_s *srcy, struct canvas_s *srcu, return -1; } - stretchblt_noalpha(ge2d_videoh264_context, 0, 0, srcy->width, + stretchblt_noalpha_noblk(ge2d_videoh264_context, 0, 0, srcy->width, srcy->height, 0, 0, srcy->width, srcy->height); return 0; @@ -425,16 +464,19 @@ static inline int fifo_level(void) void spec_set_canvas(struct buffer_spec_s *spec, unsigned int width, unsigned int height) { - canvas_config(spec->y_canvas_index, + int endian; + + endian = (canvas_mode == CANVAS_BLKMODE_LINEAR)?7:0; + canvas_config_ex(spec->y_canvas_index, spec->y_addr, width, height, - CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_32X32); + CANVAS_ADDR_NOWRAP, canvas_mode, endian); + + canvas_config_ex(spec->u_canvas_index, + spec->u_addr, + width, height / 2, + CANVAS_ADDR_NOWRAP, canvas_mode, endian); - canvas_config(spec->u_canvas_index, - spec->u_addr, - width, height / 2, - CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_32X32); - return; } static void vh264_notify_work(struct work_struct *work) @@ -478,6 +520,7 @@ static void prepare_display_q(void) if (kfifo_get(&delay_display_q, &vf)) { kfifo_put(&display_q, (const struct vframe_s *)vf); + ATRACE_COUNTER(MODULE_NAME, vf->pts); vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); } @@ -570,7 +613,10 @@ static tvin_trans_fmt_t convert_3d_format(u32 type) #endif -#ifdef DEBUG_CC_USER_DATA + +#define DUMP_CC_AS_ASCII + +#ifdef DUMP_CC_AS_ASCII static int vbi_to_ascii(int c) { if (c < 0) @@ -584,7 +630,7 @@ static int vbi_to_ascii(int c) return c; } -static void dump_cc_ascii(const uint8_t *buf, int poc) +static void dump_cc_ascii(const uint8_t *buf, unsigned int vpts, int poc) { int cc_flag; int cc_count; @@ -621,72 +667,56 @@ static void dump_cc_ascii(const uint8_t *buf, int poc) break; } } - switch (index) { - case 8: - pr_info("push poc:%d : %c %c %c %c %c %c %c %c\n", - poc, - szAscii[0], szAscii[1], szAscii[2], szAscii[3], - szAscii[4], szAscii[5], szAscii[6], szAscii[7]); - break; - case 7: - pr_info("push poc:%d : %c %c %c %c %c %c %c\n", - poc, - szAscii[0], szAscii[1], szAscii[2], szAscii[3], - szAscii[4], szAscii[5], szAscii[6]); - break; - case 6: - pr_info("push poc:%d : %c %c %c %c %c %c\n", poc, - szAscii[0], szAscii[1], szAscii[2], szAscii[3], - szAscii[4], szAscii[5]); - break; - case 5: - pr_info("push poc:%d : %c %c %c %c %c\n", poc, - szAscii[0], szAscii[1], szAscii[2], szAscii[3], - szAscii[4]); - break; - case 4: - pr_info("push poc:%d : %c %c %c %c\n", poc, - szAscii[0], szAscii[1], szAscii[2], szAscii[3]); - break; - case 3: - pr_info("push poc:%d : %c %c %c\n", poc, - szAscii[0], szAscii[1], szAscii[2]); - break; - case 2: - pr_info("push poc:%d : %c %c\n", poc, - szAscii[0], szAscii[1]); - break; - case 1: - pr_info("push poc:%d : %c\n", poc, szAscii[0]); - break; - default: - pr_info("push poc:%d and no CC data: index = %d\n", - poc, index); - break; + + if (index > 0 && index <= 8) { + char pr_buf[128]; + int len; + + sprintf(pr_buf, "push vpts:0x%x, poc:%d :", vpts, poc); + len = strlen(pr_buf); + for (i=0;i= 16) { + int i; + + for (i=0;i<16;i++) + sprintf(buf+i*3, "%02x ", pdata[i]); + + pr_info("%s\n", buf); + nLeft -= 16; + pdata += 16; + } while (nLeft >= 8) { - pr_info("%02x %02x %02x %02x %02x %02x %02x %02x\n", - pdata[0], pdata[1], pdata[2], pdata[3], - pdata[4], pdata[5], pdata[6], pdata[7]); + int i; + for (i=0;idata_buf = userdata_buf; + p_userdata_mgr->buf_len = buf_len; + p_userdata_mgr->data_buf_end = userdata_buf + buf_len; + } +} + +void vh264_destroy_userdata_manager(void) +{ + if (p_userdata_mgr) { + vfree(p_userdata_mgr); + p_userdata_mgr = NULL; + } +} + +/* +#define DUMP_USER_DATA +*/ +#ifdef DUMP_USER_DATA + +#define MAX_USER_DATA_SIZE 3145728 +static void *user_data_buf; +static unsigned char *pbuf_start; +static int total_len; +static int bskip; +static int n_userdata_id; + + +static void print_mem_data(unsigned char *pdata, + int len, + unsigned int flag, + unsigned int duration, + unsigned int vpts, + unsigned int vpts_valid, + int rec_id) +{ + int nLeft; + + nLeft = len; +#if 0 + pr_info("%d len = %d, flag = %d, duration = %d, vpts = 0x%x, vpts_valid = %d\n", + rec_id, len, flag, + duration, vpts, vpts_valid); +#endif + pr_info("%d len = %d, flag = %d, vpts = 0x%x\n", + rec_id, len, flag, vpts); + + + while (nLeft >= 16) { + pr_info("%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", + pdata[0], pdata[1], pdata[2], pdata[3], + pdata[4], pdata[5], pdata[6], pdata[7], + pdata[8], pdata[9], pdata[10], pdata[11], + pdata[12], pdata[13], pdata[14], pdata[15]); + nLeft -= 16; + pdata += 16; + } + + + while (nLeft > 0) { + pr_info("%02x %02x %02x %02x %02x %02x %02x %02x\n", + pdata[0], pdata[1], pdata[2], pdata[3], + pdata[4], pdata[5], pdata[6], pdata[7]); + nLeft -= 8; + pdata += 8; + } +} + + +static void dump_data(u8 *pdata, + unsigned int user_data_length, + unsigned int flag, + unsigned int duration, + unsigned int vpts, + unsigned int vpts_valid, + int rec_id) +{ + unsigned char szBuf[256]; + + + memset(szBuf, 0, 256); + memcpy(szBuf, pdata, user_data_length); +/* + aml_swap_data(szBuf, user_data_length); +*/ + + print_mem_data(szBuf, user_data_length, + flag, duration, vpts, + vpts_valid, rec_id); + +#ifdef DEBUG_CC_DUMP_ASCII + dump_cc_ascii(szBuf+7); +#endif +} + +static void push_to_buf(u8 *pdata, int len, struct userdata_meta_info_t *pmeta) +{ + u32 *pLen; + int info_cnt; + u8 *pbuf_end; + + if (!user_data_buf) + return; + + if (bskip) { + pr_info("over size, skip\n"); + return; + } + info_cnt = 0; + pLen = (u32 *)pbuf_start; + + *pLen = len; + pbuf_start += sizeof(u32); + info_cnt++; + pLen++; + + *pLen = pmeta->duration; + pbuf_start += sizeof(u32); + info_cnt++; + pLen++; + + *pLen = pmeta->flags; + pbuf_start += sizeof(u32); + info_cnt++; + pLen++; + + *pLen = pmeta->vpts; + pbuf_start += sizeof(u32); + info_cnt++; + pLen++; + + *pLen = pmeta->vpts_valid; + pbuf_start += sizeof(u32); + info_cnt++; + pLen++; + + + *pLen = n_userdata_id; + pbuf_start += sizeof(u32); + info_cnt++; + pLen++; + + + + pbuf_end = (u8 *)sei_data_buffer + USER_DATA_SIZE; + if (pdata + len > pbuf_end) { + int first_section_len; + + first_section_len = pbuf_end - pdata; + memcpy(pbuf_start, pdata, first_section_len); + pdata = (u8 *)sei_data_buffer; + pbuf_start += first_section_len; + memcpy(pbuf_start, pdata, len - first_section_len); + pbuf_start += len - first_section_len; + } else { + memcpy(pbuf_start, pdata, len); + pbuf_start += len; + } + + total_len += len + info_cnt * sizeof(u32); + if (total_len >= MAX_USER_DATA_SIZE-4096) + bskip = 1; +} + + +static void dump_userdata_info( + void *puser_data, + int len, + struct userdata_meta_info_t *pmeta) +{ + u8 *pstart; + + pstart = (u8 *)puser_data; + + + push_to_buf(pstart, len, pmeta); +} + +static void show_user_data_buf(void) +{ + u8 *pbuf; + int len; + unsigned int flag; + unsigned int duration; + unsigned int vpts; + unsigned int vpts_valid; + int rec_id; + + pr_info("show user data buf\n"); + pbuf = user_data_buf; + + while (pbuf < pbuf_start) { + u32 *pLen; + + pLen = (u32 *)pbuf; + + len = *pLen; + pLen++; + pbuf += sizeof(u32); + + duration = *pLen; + pLen++; + pbuf += sizeof(u32); + + flag = *pLen; + pLen++; + pbuf += sizeof(u32); + + vpts = *pLen; + pLen++; + pbuf += sizeof(u32); + + vpts_valid = *pLen; + pLen++; + pbuf += sizeof(u32); + + rec_id = *pLen; + pLen++; + pbuf += sizeof(u32); + + dump_data(pbuf, len, flag, duration, vpts, vpts_valid, rec_id); + pbuf += len; + msleep(30); + } +} + +static int vh264_init_userdata_dump(void) +{ + user_data_buf = kmalloc(MAX_USER_DATA_SIZE, GFP_KERNEL); + if (user_data_buf) + return 1; + else + return 0; +} + +static void vh264_dump_userdata(void) +{ + if (user_data_buf) { + show_user_data_buf(); + kfree(user_data_buf); + user_data_buf = NULL; + } +} + +static void vh264_reset_user_data_buf(void) +{ + total_len = 0; + pbuf_start = user_data_buf; + bskip = 0; + n_userdata_id = 0; } #endif +static void vh264_add_userdata(struct userdata_meta_info_t meta_info, int wp) +{ + struct vh264_userdata_recored_t *p_userdata_rec; + int data_length; + + mutex_lock(&userdata_mutex); + + if (p_userdata_mgr) { + if (wp > p_userdata_mgr->last_wp) + data_length = wp - p_userdata_mgr->last_wp; + else + data_length = wp + p_userdata_mgr->buf_len - + p_userdata_mgr->last_wp; + + if (data_length & 0x7) + data_length = (((data_length + 8) >> 3) << 3); +#if 0 + pr_info("wakeup_push: ri:%d, wi:%d, data_len:%d, last_wp:%d, wp:%d, id = %d\n", + p_userdata_mgr->read_index, + p_userdata_mgr->write_index, + data_length, + p_userdata_mgr->last_wp, + wp, + n_userdata_id); +#endif + p_userdata_rec = p_userdata_mgr->records + + p_userdata_mgr->write_index; + p_userdata_rec->meta_info = meta_info; + p_userdata_rec->rec_start = p_userdata_mgr->last_wp; + p_userdata_rec->rec_len = data_length; + p_userdata_mgr->last_wp = wp; + +#ifdef DUMP_USER_DATA + dump_userdata_info(p_userdata_mgr->data_buf + + p_userdata_rec->rec_start, + data_length, + &meta_info); + n_userdata_id++; +#endif + + p_userdata_mgr->write_index++; + if (p_userdata_mgr->write_index >= USERDATA_FIFO_NUM) + p_userdata_mgr->write_index = 0; + } + mutex_unlock(&userdata_mutex); + + vdec_wakeup_userdata_poll(vdec_h264); +} + +static int vh264_user_data_read(struct vdec_s *vdec, + struct userdata_param_t *puserdata_para) +{ + int rec_ri, rec_wi; + int rec_len; + u8 *rec_data_start; + u8 *pdest_buf; + struct vh264_userdata_recored_t *p_userdata_rec; + u32 data_size; + u32 res; + int copy_ok = 1; + + + pdest_buf = puserdata_para->pbuf_addr; + + + mutex_lock(&userdata_mutex); + + if (!p_userdata_mgr) { + mutex_unlock(&userdata_mutex); + return 0; + } +/* + pr_info("ri = %d, wi = %d\n", + p_userdata_mgr->read_index, + p_userdata_mgr->write_index); +*/ + rec_ri = p_userdata_mgr->read_index; + rec_wi = p_userdata_mgr->write_index; + + if (rec_ri == rec_wi) { + mutex_unlock(&userdata_mutex); + return 0; + } + + p_userdata_rec = p_userdata_mgr->records + rec_ri; + + rec_len = p_userdata_rec->rec_len; + rec_data_start = p_userdata_rec->rec_start + p_userdata_mgr->data_buf; +/* + pr_info("rec_len:%d, rec_start:%d, buf_len:%d\n", + p_userdata_rec->rec_len, + p_userdata_rec->rec_start, + puserdata_para->buf_len); +*/ + if (rec_len <= puserdata_para->buf_len) { + /* dvb user data buffer is enought to copy the whole recored. */ + data_size = rec_len; + if (rec_data_start + data_size + > p_userdata_mgr->data_buf_end) { + int first_section_len; + + first_section_len = p_userdata_mgr->buf_len - + p_userdata_rec->rec_start; + res = (u32)copy_to_user((void *)pdest_buf, + (void *)rec_data_start, + first_section_len); + if (res) { + pr_info("p1 read not end res=%d, request=%d\n", + res, first_section_len); + copy_ok = 0; + + p_userdata_rec->rec_len -= + first_section_len - res; + p_userdata_rec->rec_start += + first_section_len - res; + puserdata_para->data_size = + first_section_len - res; + } else { + res = (u32)copy_to_user( + (void *)(pdest_buf+first_section_len), + (void *)p_userdata_mgr->data_buf, + data_size - first_section_len); + if (res) { + pr_info("p2 read not end res=%d, request=%d\n", + res, data_size); + copy_ok = 0; + } + p_userdata_rec->rec_len -= + data_size - res; + p_userdata_rec->rec_start = + data_size - first_section_len - res; + puserdata_para->data_size = + data_size - res; + } + } else { + res = (u32)copy_to_user((void *)pdest_buf, + (void *)rec_data_start, + data_size); + if (res) { + pr_info("p3 read not end res=%d, request=%d\n", + res, data_size); + copy_ok = 0; + } + p_userdata_rec->rec_len -= data_size - res; + p_userdata_rec->rec_start += data_size - res; + puserdata_para->data_size = data_size - res; + } + + if (copy_ok) { + p_userdata_mgr->read_index++; + if (p_userdata_mgr->read_index >= USERDATA_FIFO_NUM) + p_userdata_mgr->read_index = 0; + } + } else { + /* dvb user data buffer is not enought + to copy the whole recored. */ + data_size = puserdata_para->buf_len; + if (rec_data_start + data_size + > p_userdata_mgr->data_buf_end) { + int first_section_len; + + first_section_len = p_userdata_mgr->buf_len + - p_userdata_rec->rec_start; + res = (u32)copy_to_user((void *)pdest_buf, + (void *)rec_data_start, + first_section_len); + if (res) { + pr_info("p4 read not end res=%d, request=%d\n", + res, first_section_len); + copy_ok = 0; + p_userdata_rec->rec_len -= + first_section_len - res; + p_userdata_rec->rec_start += + first_section_len - res; + puserdata_para->data_size = + first_section_len - res; + } else { + /* first secton copy is ok*/ + res = (u32)copy_to_user( + (void *)(pdest_buf+first_section_len), + (void *)p_userdata_mgr->data_buf, + data_size - first_section_len); + if (res) { + pr_info("p5 read not end res=%d, request=%d\n", + res, + data_size - first_section_len); + copy_ok = 0; + } + + p_userdata_rec->rec_len -= data_size - res; + p_userdata_rec->rec_start = + data_size - first_section_len - res; + puserdata_para->data_size = data_size - res; + } + } else { + res = (u32)copy_to_user((void *)pdest_buf, + (void *)rec_data_start, + data_size); + if (res) { + pr_info("p6 read not end res=%d, request=%d\n", + res, data_size); + copy_ok = 0; + } + + p_userdata_rec->rec_len -= data_size - res; + p_userdata_rec->rec_start += data_size - res; + puserdata_para->data_size = data_size - res; + } + + if (copy_ok) { + p_userdata_mgr->read_index++; + if (p_userdata_mgr->read_index + >= USERDATA_FIFO_NUM) + p_userdata_mgr->read_index = 0; + } + + } + puserdata_para->meta_info = p_userdata_rec->meta_info; + + if (p_userdata_mgr->read_index <= p_userdata_mgr->write_index) + puserdata_para->meta_info.records_in_que = + p_userdata_mgr->write_index - + p_userdata_mgr->read_index; + else + puserdata_para->meta_info.records_in_que = + p_userdata_mgr->write_index + + USERDATA_FIFO_NUM - + p_userdata_mgr->read_index; + + puserdata_para->version = (0<<24|0<<16|0<<8|1); + + mutex_unlock(&userdata_mutex); + + return 1; +} + +static void vh264_wakeup_userdata_poll(struct vdec_s *vdec) +{ + amstream_wakeup_userdata_poll(vdec); +} + +static void vh264_reset_userdata_fifo(struct vdec_s *vdec, int bInit) +{ + mutex_lock(&userdata_mutex); + + if (p_userdata_mgr) { + pr_info("h264_reset_userdata_fifo: bInit: %d, ri: %d, wi: %d\n", + bInit, p_userdata_mgr->read_index, + p_userdata_mgr->write_index); + p_userdata_mgr->read_index = 0; + p_userdata_mgr->write_index = 0; + + if (bInit) + p_userdata_mgr->last_wp = 0; + } + + mutex_unlock(&userdata_mutex); +} + +static void h264_reset_qos_mgr(void) +{ + int i; + + pr_info("h264_reset_qos_mgr\n"); + + INIT_LIST_HEAD(&free_qos_nodes_list); + INIT_LIST_HEAD(&picture_qos_list); + + for (i = 0; i < MAX_FREE_QOS_NODES; i++) { + free_nodes[i].b_offset = 0xFFFFFFFF; + + list_add_tail(&free_nodes[i].list, + &free_qos_nodes_list); + } +} + + +static void load_qos_data(int pic_number, uint32_t b_offset) +{ + uint32_t blk88_y_count; + uint32_t blk88_c_count; + uint32_t blk22_mv_count; + uint32_t rdata32; + int32_t mv_hi; + int32_t mv_lo; + uint32_t rdata32_l; + uint32_t mvx_L0_hi; + uint32_t mvy_L0_hi; + uint32_t mvx_L1_hi; + uint32_t mvy_L1_hi; + int64_t value; + uint64_t temp_value; +/* +#define DEBUG_QOS +*/ +#define SUPPORT_NODE + +#ifdef SUPPORT_NODE + struct h264_qos_data_node_t *node; + struct h264_qos_data_node_t *tmp; + int bFoundNode = 0; + + node = NULL; + if (!list_empty(&picture_qos_list)) { + list_for_each_entry_safe(node, tmp, &picture_qos_list, list) { + if (node->b_offset == b_offset) { + bFoundNode = 1; + break; + } + } + } + /* + pr_info("bFoundNode = %d, node:0x%p\n", bFoundNode, node); + */ + if (!bFoundNode) { + if (!list_empty(&free_qos_nodes_list)) { + node = list_entry( + free_qos_nodes_list.next, + struct h264_qos_data_node_t, + list); + /* + pr_info("get a node:0x%p\n", node); + */ + } else { + pr_info("there is no qos data node avaible\n"); + + return; + } + } + + node->b_offset = b_offset; + node->poc = pic_number; + + node->max_mv = 0; + node->avg_mv = 0; + node->min_mv = 0; + + node->max_skip = 0; + node->avg_skip = 0; + node->min_skip = 0; + + node->max_qp = 0; + node->avg_qp = 0; + node->min_qp = 0; +#endif + + + + + + + /* set rd_idx to 0 */ + WRITE_VREG(VDEC_PIC_QUALITY_CTRL, 0); + blk88_y_count = READ_VREG(VDEC_PIC_QUALITY_DATA); + if (blk88_y_count == 0) { +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] NO Data yet.\n", + pic_number); +#endif + /* reset all counts */ + WRITE_VREG(VDEC_PIC_QUALITY_CTRL, (1<<8)); + +#ifdef SUPPORT_NODE + list_move(&node->list, &picture_qos_list); +#endif + return; + } + /* qp_y_sum */ + rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA); +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] Y QP AVG : %d (%d/%d)\n", + pic_number, rdata32/blk88_y_count, + rdata32, blk88_y_count); +#endif +#ifdef SUPPORT_NODE + node->avg_qp = rdata32/blk88_y_count; +#endif + + /* intra_y_count */ + rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA); +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] Y intra rate : %d%c (%d)\n", + pic_number, rdata32*100/blk88_y_count, + '%', rdata32); +#endif + /* skipped_y_count */ + rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA); +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] Y skipped rate : %d%c (%d)\n", + pic_number, rdata32*100/blk88_y_count, + '%', rdata32); +#endif +#ifdef SUPPORT_NODE + node->avg_skip = rdata32*100/blk88_y_count; +#endif + /* coeff_non_zero_y_count */ + rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA); +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] Y ZERO_Coeff rate : %d%c (%d)\n", + pic_number, (100 - rdata32*100/(blk88_y_count*1)), + '%', rdata32); +#endif + /* blk66_c_count */ + blk88_c_count = READ_VREG(VDEC_PIC_QUALITY_DATA); + if (blk88_c_count == 0) { +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] NO Data yet.\n", + pic_number); +#endif + /* reset all counts */ + WRITE_VREG(VDEC_PIC_QUALITY_CTRL, (1<<8)); + +#ifdef SUPPORT_NODE + list_move(&node->list, &picture_qos_list); +#endif + return; + } + /* qp_c_sum */ + rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA); +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] C QP AVG : %d (%d/%d)\n", + pic_number, rdata32/blk88_c_count, + rdata32, blk88_c_count); +#endif + /* intra_c_count */ + rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA); +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] C intra rate : %d%c (%d)\n", + pic_number, rdata32*100/blk88_c_count, + '%', rdata32); +#endif + /* skipped_cu_c_count */ + rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA); +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] C skipped rate : %d%c (%d)\n", + pic_number, rdata32*100/blk88_c_count, + '%', rdata32); +#endif + /* coeff_non_zero_c_count */ + rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA); +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] C ZERO_Coeff rate : %d%c (%d)\n", + pic_number, (100 - rdata32*100/(blk88_c_count*1)), + '%', rdata32); +#endif + + /* 1'h0, qp_c_max[6:0], 1'h0, qp_c_min[6:0], + 1'h0, qp_y_max[6:0], 1'h0, qp_y_min[6:0] */ + rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA); +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] Y QP min : %d\n", + pic_number, (rdata32>>0)&0xff); +#endif +#ifdef SUPPORT_NODE + node->min_qp = (rdata32>>0)&0xff; +#endif + +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] Y QP max : %d\n", + pic_number, (rdata32>>8)&0xff); +#endif +#ifdef SUPPORT_NODE + node->max_qp = (rdata32>>8)&0xff; +#endif + +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] C QP min : %d\n", + pic_number, (rdata32>>16)&0xff); + pr_info(" [Picture %d Quality] C QP max : %d\n", + pic_number, (rdata32>>24)&0xff); +#endif + + /* blk22_mv_count */ + blk22_mv_count = READ_VREG(VDEC_PIC_QUALITY_DATA); + if (blk22_mv_count == 0) { +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] NO MV Data yet.\n", + pic_number); +#endif + /* reset all counts */ + WRITE_VREG(VDEC_PIC_QUALITY_CTRL, (1<<8)); +#ifdef SUPPORT_NODE + list_move(&node->list, &picture_qos_list); +#endif + return; + } + /* mvy_L1_count[39:32], mvx_L1_count[39:32], + mvy_L0_count[39:32], mvx_L0_count[39:32] */ + rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA); + /* should all be 0x00 or 0xff */ +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] MV AVG High Bits: 0x%X\n", + pic_number, rdata32); +#endif + mvx_L0_hi = ((rdata32>>0)&0xff); + mvy_L0_hi = ((rdata32>>8)&0xff); + mvx_L1_hi = ((rdata32>>16)&0xff); + mvy_L1_hi = ((rdata32>>24)&0xff); + + /* mvx_L0_count[31:0] */ + rdata32_l = READ_VREG(VDEC_PIC_QUALITY_DATA); + temp_value = mvx_L0_hi; + temp_value = (temp_value << 32) | rdata32_l; + + if (mvx_L0_hi & 0x80) + value = 0xFFFFFFF000000000 | temp_value; + else + value = temp_value; + value = div_s64(value, blk22_mv_count); +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] MVX_L0 AVG : %d (%lld/%d)\n", + pic_number, (int)(value), + value, blk22_mv_count); +#endif +#ifdef SUPPORT_NODE + node->avg_mv = value; +#endif + + /* mvy_L0_count[31:0] */ + rdata32_l = READ_VREG(VDEC_PIC_QUALITY_DATA); + temp_value = mvy_L0_hi; + temp_value = (temp_value << 32) | rdata32_l; + + if (mvy_L0_hi & 0x80) + value = 0xFFFFFFF000000000 | temp_value; + else + value = temp_value; +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] MVY_L0 AVG : %d (%lld/%d)\n", + pic_number, rdata32_l/blk22_mv_count, + value, blk22_mv_count); +#endif + + /* mvx_L1_count[31:0] */ + rdata32_l = READ_VREG(VDEC_PIC_QUALITY_DATA); + temp_value = mvx_L1_hi; + temp_value = (temp_value << 32) | rdata32_l; + if (mvx_L1_hi & 0x80) + value = 0xFFFFFFF000000000 | temp_value; + else + value = temp_value; +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] MVX_L1 AVG : %d (%lld/%d)\n", + pic_number, rdata32_l/blk22_mv_count, + value, blk22_mv_count); +#endif + + /* mvy_L1_count[31:0] */ + rdata32_l = READ_VREG(VDEC_PIC_QUALITY_DATA); + temp_value = mvy_L1_hi; + temp_value = (temp_value << 32) | rdata32_l; + if (mvy_L1_hi & 0x80) + value = 0xFFFFFFF000000000 | temp_value; + else + value = temp_value; +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] MVY_L1 AVG : %d (%lld/%d)\n", + pic_number, rdata32_l/blk22_mv_count, + value, blk22_mv_count); +#endif + + /* {mvx_L0_max, mvx_L0_min} // format : {sign, abs[14:0]} */ + rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA); + mv_hi = (rdata32>>16)&0xffff; + if (mv_hi & 0x8000) + mv_hi = 0x8000 - mv_hi; +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] MVX_L0 MAX : %d\n", + pic_number, mv_hi); +#endif +#ifdef SUPPORT_NODE + node->max_mv = mv_hi; +#endif + + mv_lo = (rdata32>>0)&0xffff; + if (mv_lo & 0x8000) + mv_lo = 0x8000 - mv_lo; +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] MVX_L0 MIN : %d\n", + pic_number, mv_lo); +#endif +#ifdef SUPPORT_NODE + node->min_mv = mv_lo; +#endif + + /* {mvy_L0_max, mvy_L0_min} */ + rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA); + mv_hi = (rdata32>>16)&0xffff; + if (mv_hi & 0x8000) + mv_hi = 0x8000 - mv_hi; +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] MVY_L0 MAX : %d\n", + pic_number, mv_hi); +#endif + + mv_lo = (rdata32>>0)&0xffff; + if (mv_lo & 0x8000) + mv_lo = 0x8000 - mv_lo; +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] MVY_L0 MIN : %d\n", + pic_number, mv_lo); +#endif + + /* {mvx_L1_max, mvx_L1_min} */ + rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA); + mv_hi = (rdata32>>16)&0xffff; + if (mv_hi & 0x8000) + mv_hi = 0x8000 - mv_hi; +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] MVX_L1 MAX : %d\n", + pic_number, mv_hi); +#endif + + mv_lo = (rdata32>>0)&0xffff; + if (mv_lo & 0x8000) + mv_lo = 0x8000 - mv_lo; +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] MVX_L1 MIN : %d\n", + pic_number, mv_lo); +#endif + + /* {mvy_L1_max, mvy_L1_min} */ + rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA); + mv_hi = (rdata32>>16)&0xffff; + if (mv_hi & 0x8000) + mv_hi = 0x8000 - mv_hi; +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] MVY_L1 MAX : %d\n", + pic_number, mv_hi); +#endif + mv_lo = (rdata32>>0)&0xffff; + if (mv_lo & 0x8000) + mv_lo = 0x8000 - mv_lo; +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] MVY_L1 MIN : %d\n", + pic_number, mv_lo); +#endif + + rdata32 = READ_VREG(VDEC_PIC_QUALITY_CTRL); +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] After Read : VDEC_PIC_QUALITY_CTRL : 0x%x\n", + pic_number, rdata32); +#endif + /* reset all counts */ + WRITE_VREG(VDEC_PIC_QUALITY_CTRL, (1<<8)); +#ifdef SUPPORT_NODE + list_move(&node->list, &picture_qos_list); +#endif +} + +void search_qos_node(struct vframe_qos_s *picture_qos, uint32_t b_offset) +{ + struct h264_qos_data_node_t *node; + struct h264_qos_data_node_t *tmp; + + if (!list_empty(&picture_qos_list)) { + list_for_each_entry_safe(node, tmp, &picture_qos_list, list) { + if (node->b_offset == b_offset) { + + picture_qos->avg_mv = node->avg_mv; + picture_qos->min_mv = node->min_mv; + picture_qos->max_mv = node->max_mv; + + picture_qos->avg_skip = node->avg_skip; + picture_qos->min_skip = node->min_skip; + picture_qos->max_skip = node->max_skip; + + picture_qos->avg_qp = node->avg_qp; + picture_qos->min_qp = node->min_qp; + picture_qos->max_qp = node->max_qp; + +#if 0 + pr_info("POC:%d, mv: max:%d, avg:%d, min:%d\n" + "qp: max:%d, avg:%d, min:%d\n" + "skip: max:%d, avg:%d, min:%d\n", + node->poc, + picture_qos->max_mv, + picture_qos->avg_mv, + picture_qos->min_mv, + picture_qos->max_qp, + picture_qos->avg_qp, + picture_qos->min_qp, + picture_qos->max_skip, + picture_qos->avg_skip, + picture_qos->min_skip); +#endif + node->b_offset = 0xFFFFFFFF; + list_move(&node->list, &free_qos_nodes_list); + + break; + } + } + } +} + +static void qos_do_work(struct work_struct *work) +{ + uint32_t poc; + uint32_t bOffset; + + + poc = READ_VREG(AV_SCRATCH_M); + bOffset = READ_VREG(AV_SCRATCH_L); +/* + pr_info("poc:%d, bOffset:0x%x\n", poc, bOffset); +*/ + load_qos_data(poc, bOffset); + + + WRITE_VREG(AV_SCRATCH_0, 0); +} static void userdata_push_do_work(struct work_struct *work) { unsigned int sei_itu35_flags; unsigned int sei_itu35_wp; unsigned int sei_itu35_data_length; - struct userdata_poc_info_t user_data_poc; + struct userdata_meta_info_t meta_info; + u32 offset, pts; + u64 pts_us64 = 0; + u32 slice_type; + u32 reg; + u32 poc_number; + u32 picture_struct; + + memset(&meta_info, 0, sizeof(meta_info)); + + meta_info.duration = frame_dur; + + reg = READ_VREG(AV_SCRATCH_M); + poc_number = reg & 0x7FFFFFF; + if ((poc_number >> 16) == 0x7FF) + poc_number = (reg & 0x7FFFFFF) - 0x8000000; + + slice_type = (reg >> 29) & 0x7; + switch (slice_type) { + case SLICE_TYPE_I: + meta_info.flags |= 1<<7; + break; + case SLICE_TYPE_P: + meta_info.flags |= 3<<7; + break; + case SLICE_TYPE_B: + meta_info.flags |= 2<<7; + break; + } + meta_info.poc_number = poc_number; + picture_struct = (reg >> 27) & 0x3; + + meta_info.flags |= (VFORMAT_H264 << 3) | (picture_struct << 12); + + + offset = READ_VREG(AV_SCRATCH_L); + + if (pts_pickout_offset_us64 + (PTS_TYPE_VIDEO, offset, &pts, 0, &pts_us64) != 0) { + pr_info("pts pick outfailed, offset:0x%x\n", offset); + pts = -1; + meta_info.vpts_valid = 0; + } else + meta_info.vpts_valid = 1; + meta_info.vpts = pts; +/* + pr_info("offset:0x%x, vpts:0x%x, slice:%d, poc:%d\n", + offset, pts, slice_type, + poc_number); +*/ sei_itu35_flags = READ_VREG(AV_SCRATCH_J); sei_itu35_wp = (sei_itu35_flags >> 16) & 0xffff; sei_itu35_data_length = sei_itu35_flags & 0x7fff; -#if 0 - pr_info("pocinfo 0x%x, top poc %d, wp 0x%x, length %d\n", - READ_VREG(AV_SCRATCH_L), - READ_VREG(AV_SCRATCH_M), - sei_itu35_wp, sei_itu35_data_length); -#endif - user_data_poc.poc_info = READ_VREG(AV_SCRATCH_L); - user_data_poc.poc_number = READ_VREG(AV_SCRATCH_M); -#ifdef DEBUG_CC_USER_DATA - dump_data(sei_itu35_wp, sei_itu35_data_length, - user_data_poc.poc_number); -#endif + if (enable_userdata_debug) + udr_dump_data(sei_itu35_wp, + sei_itu35_data_length, + pts, poc_number); + + + vh264_add_userdata(meta_info, sei_itu35_wp); + WRITE_VREG(AV_SCRATCH_J, 0); - wakeup_userdata_poll(user_data_poc, sei_itu35_wp, - (unsigned long)sei_data_buffer, - USER_DATA_SIZE, sei_itu35_data_length); } @@ -898,7 +1969,7 @@ static void vh264_set_params(struct work_struct *work) int max_dpb_size, actual_dpb_size, max_reference_size; int i, mb_mv_byte, ret; unsigned long addr; - unsigned int post_canvas, buf_size; + unsigned int post_canvas, buf_size, endian; unsigned int frame_mbs_only_flag; unsigned int chroma_format_idc, chroma444, video_signal; unsigned int crop_infor, crop_bottom, crop_right, level_idc; @@ -910,7 +1981,12 @@ static void vh264_set_params(struct work_struct *work) post_canvas = get_post_canvas(); clk_adj_frame_count = 0; /* set to max decoder clock rate at the beginning */ - vdec_source_changed(VFORMAT_H264, 3840, 2160, 60); + + if (vdec_is_support_4k()) + vdec_source_changed(VFORMAT_H264, 3840, 2160, 60); + else + vdec_source_changed(VFORMAT_H264, 1920, 1080, 29); + timing_info_present_flag = 0; mb_width = READ_VREG(AV_SCRATCH_1); seq_info = READ_VREG(AV_SCRATCH_2); @@ -950,11 +2026,12 @@ static void vh264_set_params(struct work_struct *work) if (ucode_type == UCODE_IP_ONLY_PARAM) mb_mv_byte = 96; mb_width = mb_width & 0xff; - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXTVBB) { + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXTVBB) { if (!mb_width && mb_total) mb_width = 256; } - mb_height = mb_total / mb_width; + if (mb_width) + mb_height = mb_total / mb_width; last_duration = 0; /* AV_SCRATCH_2 * bit 15: frame_mbs_only_flag @@ -1032,7 +2109,7 @@ static void vh264_set_params(struct work_struct *work) if (max_dpb_size < max_reference_size) max_dpb_size = max_reference_size; if (max_dpb_size > 15 - && get_cpu_type() >= MESON_CPU_MAJOR_ID_GXTVBB + && get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXTVBB && (codec_mm_get_total_size() < 80 * SZ_1M)) { actual_dpb_size = max_reference_size + dpb_size_adj; @@ -1112,16 +2189,17 @@ static void vh264_set_params(struct work_struct *work) buffer_spec[i].v_canvas_width = mb_width << 4; buffer_spec[i].v_canvas_height = mb_height << 4; - canvas_config(128 + i * 2, + endian = (canvas_mode == CANVAS_BLKMODE_LINEAR)?7:0; + canvas_config_ex(128 + i * 2, buffer_spec[i].y_addr, mb_width << 4, mb_height << 4, CANVAS_ADDR_NOWRAP, - CANVAS_BLKMODE_32X32); - canvas_config(128 + i * 2 + 1, + canvas_mode, endian); + canvas_config_ex(128 + i * 2 + 1, buffer_spec[i].u_addr, mb_width << 4, mb_height << 3, CANVAS_ADDR_NOWRAP, - CANVAS_BLKMODE_32X32); + canvas_mode, endian); WRITE_VREG(ANC0_CANVAS_ADDR + i, spec2canvas(&buffer_spec[i])); } else { @@ -1485,9 +2563,12 @@ static void vh264_isr(void) unsigned int cpu_cmd; unsigned int pts, pts_lookup_save, pts_valid_save, pts_valid = 0; unsigned int pts_us64_valid = 0; + unsigned int framesize; u64 pts_us64; bool force_interlaced_frame = false; +#ifdef ENABLE_SEI_ITU_T35 unsigned int sei_itu35_flags; +#endif static const unsigned int idr_num = FIX_FRAME_RATE_CHECK_IDRFRAME_NUM; static const unsigned int flg_1080_itl = @@ -1621,7 +2702,7 @@ static void vh264_isr(void) return IRQ_HANDLED; } - if (clk_adj_frame_count < VDEC_CLOCK_ADJUST_FRAME) + if (clk_adj_frame_count < (VDEC_CLOCK_ADJUST_FRAME + 1)) clk_adj_frame_count++; set_frame_info(vf); @@ -1667,6 +2748,7 @@ static void vh264_isr(void) && (first_pts_cached))) { pts = first_pts; pts_us64 = first_pts64; + framesize = first_frame_size; first_pts_cached = false; pts_valid = 1; pts_us64_valid = 1; @@ -1674,8 +2756,8 @@ static void vh264_isr(void) pts_hit++; #endif } else if (pts_lookup_offset_us64 - (PTS_TYPE_VIDEO, b_offset, &pts, 0, - &pts_us64) == 0) { + (PTS_TYPE_VIDEO, b_offset, &pts, + &framesize, 0, &pts_us64) == 0) { pts_valid = 1; pts_us64_valid = 1; #ifdef DEBUG_PTS @@ -1684,11 +2766,100 @@ static void vh264_isr(void) } else { pts_valid = 0; pts_us64_valid = 0; + framesize = 0; #ifdef DEBUG_PTS pts_missed++; #endif } + if (idr_flag) + s_vframe_qos.type = 4; + else if (slice_type == SLICE_TYPE_I) + s_vframe_qos.type = 1; + else if (slice_type == SLICE_TYPE_P) + s_vframe_qos.type = 2; + else if (slice_type == SLICE_TYPE_B || slice_type == 8) + s_vframe_qos.type = 3; + + s_vframe_qos.size = framesize; + + if (pts_valid) + s_vframe_qos.pts = pts; + else + s_vframe_qos.pts = last_pts + DUR2PTS(frame_dur); +#ifndef ENABLE_SEI_ITU_T35 + if (get_cpu_major_id() < AM_MESON_CPU_MAJOR_ID_G12A) { + u32 reg_data; + if (i) { + reg_data = READ_VREG(AV_SCRATCH_N); + s_vframe_qos.max_mv + = (reg_data >> 16) & 0xffff; + s_vframe_qos.avg_mv + = (reg_data >> 8) & 0xff; + s_vframe_qos.min_mv + = reg_data & 0xff; + reg_data = READ_VREG(AV_SCRATCH_L); + s_vframe_qos.max_qp + = (reg_data >> 16) & 0xff; + s_vframe_qos.avg_qp + = (reg_data >> 8) & 0xff; + s_vframe_qos.min_qp + = reg_data & 0xff; + reg_data = READ_VREG(AV_SCRATCH_M); + s_vframe_qos.max_skip + = (reg_data >> 16) & 0xff; + s_vframe_qos.avg_skip + = (reg_data >> 8) & 0xff; + s_vframe_qos.min_skip + = reg_data & 0xff; + } else { + reg_data = READ_VREG(AV_SCRATCH_J); + s_vframe_qos.max_mv + = (reg_data >> 16) & 0xffff; + s_vframe_qos.avg_mv + = (reg_data >> 8) & 0xff; + s_vframe_qos.min_mv + = reg_data & 0xff; + reg_data = READ_VREG(AV_SCRATCH_I); + s_vframe_qos.max_qp + = (reg_data >> 16) & 0xff; + s_vframe_qos.avg_qp + = (reg_data >> 8) & 0xff; + s_vframe_qos.min_qp + = reg_data & 0xff; + reg_data = READ_VREG(AV_SCRATCH_K); + s_vframe_qos.max_skip + = (reg_data >> 16) & 0xff; + s_vframe_qos.avg_skip + = (reg_data >> 8) & 0xff; + s_vframe_qos.min_skip + = reg_data & 0xff; + } + if (decoder_debug_flag&0x2) { + pr_info("max_mv %d avg_mv %d min_mv %d slice_type %d offset %x i = %d\n", + s_vframe_qos.max_mv, + s_vframe_qos.avg_mv, + s_vframe_qos.min_mv, + slice_type, + b_offset, + i); + pr_info("max_qp %d avg_qp %d min_qp %d\n", + s_vframe_qos.max_qp, + s_vframe_qos.avg_qp, + s_vframe_qos.min_qp); + pr_info("max_skip %d avg_skip %d min_skip %d\n", + s_vframe_qos.max_skip, + s_vframe_qos.avg_skip, + s_vframe_qos.min_skip); + } + } else + search_qos_node(&s_vframe_qos, b_offset); +#endif + frame_count++; + + s_vframe_qos.num = frame_count; + vdec_fill_frame_info(&s_vframe_qos, 1); + /* on second IDR frame,check the diff between pts * compute from duration and pts from lookup , * if large than frame_dur,we think it is uncorrect. @@ -1747,7 +2918,8 @@ static void vh264_isr(void) h264_pts_count++; } else { - if (!idr_flag) + /* non-idr or non-I frame will set pts_valid */ + if (!idr_flag && !(slice_type == SLICE_TYPE_I)) pts_valid = 0; } @@ -1898,6 +3070,7 @@ static void vh264_isr(void) decoder_bmmu_box_get_mem_handle( mm_blk_handle, VF_BUFFER_IDX(buffer_index)); + decoder_do_frame_check(NULL, vf); if ((error_recovery_mode_use & 2) && error) { kfifo_put(&recycle_q, (const struct vframe_s *)vf); @@ -1948,6 +3121,7 @@ static void vh264_isr(void) decoder_bmmu_box_get_mem_handle( mm_blk_handle, VF_BUFFER_IDX(buffer_index)); + decoder_do_frame_check(NULL, vf); if ((error_recovery_mode_use & 2) && error) { kfifo_put(&recycle_q, (const struct vframe_s *)vf); @@ -2046,12 +3220,14 @@ static void vh264_isr(void) } else if ((cpu_cmd & 0xff) == 9) { first_offset = READ_VREG(AV_SCRATCH_1); if (pts_lookup_offset_us64 - (PTS_TYPE_VIDEO, first_offset, &first_pts, 0, + (PTS_TYPE_VIDEO, first_offset, &first_pts, + &first_frame_size, 0, &first_pts64) == 0) first_pts_cached = true; WRITE_VREG(AV_SCRATCH_0, 0); } else if ((cpu_cmd & 0xff) == 0xa) { int b_offset; + unsigned int frame_size; b_offset = READ_VREG(AV_SCRATCH_2); buffer_index = READ_VREG(AV_SCRATCH_1); @@ -2065,7 +3241,8 @@ static void vh264_isr(void) return IRQ_HANDLED; } if (pts_lookup_offset_us64 (PTS_TYPE_VIDEO, b_offset, - &pts, 0, &pts_us64) != 0) + &pts, &frame_size, + 0, &pts_us64) != 0) vf->pts_us64 = vf->pts = 0; else { vf->pts_us64 = pts_us64; @@ -2088,15 +3265,19 @@ static void vh264_isr(void) p_last_vf = vf; pts_discontinue = false; iponly_early_mode = 1; + decoder_do_frame_check(NULL, vf); kfifo_put(&delay_display_q, (const struct vframe_s *)vf); WRITE_VREG(AV_SCRATCH_0, 0); + } else if ((cpu_cmd & 0xff) == 0xB) { + schedule_work(&qos_work); } - +#ifdef ENABLE_SEI_ITU_T35 sei_itu35_flags = READ_VREG(AV_SCRATCH_J); if (sei_itu35_flags & (1 << 15)) { /* data ready */ schedule_work(&userdata_push_work); } +#endif #ifdef HANDLE_H264_IRQ return IRQ_HANDLED; #else @@ -2106,10 +3287,6 @@ static void vh264_isr(void) static void vh264_set_clk(struct work_struct *work) { - if (ucode_type != UCODE_IP_ONLY_PARAM && - (clk_adj_frame_count > VDEC_CLOCK_ADJUST_FRAME) && - frame_dur > 0 && saved_resolution != - frame_width * frame_height * (96000 / frame_dur)) { int fps = 96000 / frame_dur; if (frame_dur < 10) /*dur is too small ,think it errors fps*/ @@ -2117,7 +3294,6 @@ static void vh264_set_clk(struct work_struct *work) saved_resolution = frame_width * frame_height * fps; vdec_source_changed(VFORMAT_H264, frame_width, frame_height, fps); - } } static void vh264_put_timer_func(unsigned long arg) @@ -2207,7 +3383,7 @@ static void vh264_put_timer_func(unsigned long arg) struct vframe_s *vf; if (kfifo_get(&recycle_q, &vf)) { - if ((vf->index >= 0) && (vf->index < VF_BUF_NUM)) { + if (vf->index < VF_BUF_NUM) { if (--vfbuf_use[vf->index] == 0) { if (READ_VREG(AV_SCRATCH_7) == 0) { WRITE_VREG(AV_SCRATCH_7, @@ -2230,8 +3406,7 @@ static void vh264_put_timer_func(unsigned long arg) struct vframe_s *vf; if (kfifo_get(&recycle_q, &vf)) { - if ((vf->index >= 0 && - (vf->index < VF_BUF_NUM))) { + if (vf->index < VF_BUF_NUM) { vf->index = VF_BUF_NUM; kfifo_put(&newframe_q, (const struct vframe_s *)vf); @@ -2246,7 +3421,11 @@ static void vh264_put_timer_func(unsigned long arg) stream_switching_done(); } - schedule_work(&set_clk_work); + if (ucode_type != UCODE_IP_ONLY_PARAM && + (clk_adj_frame_count > VDEC_CLOCK_ADJUST_FRAME) && + frame_dur > 0 && saved_resolution != + frame_width * frame_height * (96000 / frame_dur)) + schedule_work(&set_clk_work); exit: timer->expires = jiffies + PUT_INTERVAL; @@ -2256,6 +3435,12 @@ exit: int vh264_dec_status(struct vdec_s *vdec, struct vdec_info *vstatus) { + u32 ratio_control; + u32 ar; + + if (!(stat & STAT_VDEC_RUN)) + return -1; + vstatus->frame_width = frame_width; vstatus->frame_height = frame_height; if (frame_dur != 0) @@ -2276,6 +3461,13 @@ int vh264_dec_status(struct vdec_s *vdec, struct vdec_info *vstatus) vstatus->total_data = gvs->total_data; vstatus->samp_cnt = gvs->samp_cnt; vstatus->offset = gvs->offset; + ar = min_t(u32, + h264_ar, + DISP_RATIO_ASPECT_RATIO_MAX); + ratio_control = + ar << DISP_RATIO_ASPECT_RATIO_BIT; + vstatus->ratio_control = ratio_control; + snprintf(vstatus->vdec_name, sizeof(vstatus->vdec_name), "%s", DRIVER_NAME); @@ -2394,7 +3586,7 @@ static void vh264_prot_init(void) WRITE_VREG(AV_SCRATCH_I, (u32)(sei_data_buffer_phys - buf_offset)); WRITE_VREG(AV_SCRATCH_J, 0); /* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */ - if ((get_cpu_type() >= MESON_CPU_MAJOR_ID_M8) && !is_meson_mtvd_cpu()) { + if ((get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M8) && !is_meson_mtvd_cpu()) { /* pr_info("vh264 meson8 prot init\n"); */ WRITE_VREG(MDEC_PIC_DC_THRESH, 0x404038aa); } @@ -2444,7 +3636,7 @@ static int vh264_local_init(void) pr_debug("sync_outside=%d, use_idr_framerate=%d\n", sync_outside, use_idr_framerate); - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXTVBB) + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXTVBB) size = V_BUF_ADDR_OFFSET_NEW; else size = V_BUF_ADDR_OFFSET; @@ -2513,7 +3705,8 @@ static int vh264_local_init(void) pts_discontinue = false; no_idr_error_count = 0; - reset_userdata_fifo(1); + vh264_reset_userdata_fifo(vdec_h264, 1); + h264_reset_qos_mgr(); if (enable_switch_fense) { for (i = 0; i < ARRAY_SIZE(fense_buffer_spec); i++) { @@ -2561,6 +3754,8 @@ static s32 vh264_init(void) iponly_early_mode = 0; saved_idc_level = 0; + frame_count = 0; + memset(&s_vframe_qos, 0, sizeof(s_vframe_qos)); /*init vdec status*/ ret = vh264_vdec_info_init(); if (0 != ret) @@ -2573,9 +3768,12 @@ static s32 vh264_init(void) amvdec_enable(); if (!firmwareloaded && tee_enabled()) { - if (tee_load_video_fw((u32)VIDEO_DEC_H264, 0) != 0) { + ret = amvdec_loadmc_ex(VFORMAT_H264, NULL, NULL); + if (ret < 0) { amvdec_disable(); - return -1; + pr_err("H264: the %s fw loading failed, err: %x\n", + tee_enabled() ? "TEE" : "local", ret); + return ret; } } else { /* -- ucode loading (amrisc and swap code) */ @@ -2649,14 +3847,13 @@ static s32 vh264_init(void) } firmwareloaded = 1; } else { - int ret = -1, size = -1; + int ret = -1; char *buf = vmalloc(0x1000 * 16); if (IS_ERR_OR_NULL(buf)) return -ENOMEM; - size = get_firmware_data(VIDEO_DEC_H264, buf); - if (size < 0) { + if (get_firmware_data(VIDEO_DEC_H264, buf) < 0) { pr_err("get firmware fail."); vfree(buf); return -1; @@ -2677,7 +3874,6 @@ static s32 vh264_init(void) vfree(buf); if (ret < 0) { - pr_err("h264 load orignal firmware error %d.\n", ret); amvdec_disable(); if (mc_cpu_addr) { dma_free_coherent(amports_get_dma_device(), @@ -2685,6 +3881,8 @@ static s32 vh264_init(void) mc_dma_handle); mc_cpu_addr = NULL; } + pr_err("H264: the %s fw loading failed, err: %x\n", + tee_enabled() ? "TEE" : "local", ret); return -EBUSY; } } @@ -2720,11 +3918,12 @@ static s32 vh264_init(void) #endif if (frame_dur != 0) { - if (!is_reset) + if (!is_reset) { vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_FR_HINT, (void *)((unsigned long)frame_dur)); - fr_hint_status = VDEC_HINTED; + fr_hint_status = VDEC_HINTED; + } } else fr_hint_status = VDEC_NEED_HINT; @@ -2776,7 +3975,7 @@ static int vh264_stop(int mode) if (stat & STAT_VF_HOOK) { if (mode == MODE_FULL) { - if (fr_hint_status == VDEC_HINTED && !is_reset) + if (fr_hint_status == VDEC_HINTED) vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_FR_END_HINT, NULL); @@ -2814,9 +4013,27 @@ static int vh264_stop(int mode) return 0; } +static void wait_vh264_search_done(void) +{ + u32 vld_rp = READ_VREG(VLD_MEM_VIFIFO_RP); + int count = 0; + do { + usleep_range(100, 500); + if (vld_rp == READ_VREG(VLD_MEM_VIFIFO_RP)) + break; + if (count > 2000) { + pr_info("%s, timeout count %d vld_rp 0x%x VLD_MEM_VIFIFO_RP 0x%x\n", + __func__, count, vld_rp, READ_VREG(VLD_MEM_VIFIFO_RP)); + break; + } else + vld_rp = READ_VREG(VLD_MEM_VIFIFO_RP); + count++; + } while (1); +} + + static void error_do_work(struct work_struct *work) { - mutex_lock(&vh264_mutex); /* * we need to lock vh264_stop/vh264_init. @@ -2827,8 +4044,9 @@ static void error_do_work(struct work_struct *work) if (atomic_read(&vh264_active)) { amvdec_stop(); do { - msleep(20); + msleep(50); } while (vh264_stream_switching_state != SWITCHING_STATE_OFF); + wait_vh264_search_done(); vh264_reset = 1; #ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER vh264_ppmgr_reset(); @@ -2839,14 +4057,10 @@ static void error_do_work(struct work_struct *work) vf_reg_provider(&vh264_vf_prov); #endif - msleep(30); vh264_prot_init(); - amvdec_start(); vh264_reset = 0; } - - mutex_unlock(&vh264_mutex); } static void stream_switching_done(void) @@ -2907,6 +4121,7 @@ static void stream_switching_do(struct work_struct *work) if (kfifo_get(&delay_display_q, &vf)) { kfifo_put(&display_q, (const struct vframe_s *)vf); + ATRACE_COUNTER(MODULE_NAME, vf->pts); vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); } else @@ -2988,7 +4203,7 @@ static void stream_switching_do(struct work_struct *work) /* send clone to receiver */ kfifo_put(&display_q, (const struct vframe_s *)&fense_vf[i]); - + ATRACE_COUNTER(MODULE_NAME, fense_vf[i].pts); /* early recycle frames for last session */ if (delay) vh264_vf_put(vf, NULL); @@ -3018,6 +4233,7 @@ static int amvdec_h264_probe(struct platform_device *pdev) mutex_unlock(&vh264_mutex); return -EFAULT; } + canvas_mode = pdata->canvas_mode; tvp_flag = vdec_secure(pdata) ? CODEC_MM_FLAGS_TVP : 0; if (pdata->sys_info) vh264_amstream_dec_info = *pdata->sys_info; @@ -3040,15 +4256,29 @@ static int amvdec_h264_probe(struct platform_device *pdev) pdata->dec_status = vh264_dec_status; pdata->set_trickmode = vh264_set_trickmode; pdata->set_isreset = vh264_set_isreset; - is_reset = 0; + pdata->user_data_read = vh264_user_data_read; + pdata->reset_userdata_fifo = vh264_reset_userdata_fifo; + pdata->wakeup_userdata_poll = vh264_wakeup_userdata_poll; + + is_reset = 0; + clk_adj_frame_count = 0; if (vh264_init() < 0) { pr_info("\namvdec_h264 init failed.\n"); kfree(gvs); gvs = NULL; + pdata->dec_status = NULL; mutex_unlock(&vh264_mutex); return -ENODEV; } + vdec_h264 = pdata; + vh264_crate_userdata_manager(sei_data_buffer, USER_DATA_SIZE); + vh264_reset_userdata_fifo(vdec_h264, 1); + +#ifdef DUMP_USER_DATA + vh264_init_userdata_dump(); + vh264_reset_user_data_buf(); +#endif INIT_WORK(&error_wd_work, error_do_work); INIT_WORK(&stream_switching_work, stream_switching_do); @@ -3056,6 +4286,9 @@ static int amvdec_h264_probe(struct platform_device *pdev) INIT_WORK(¬ify_work, vh264_notify_work); INIT_WORK(&set_clk_work, vh264_set_clk); INIT_WORK(&userdata_push_work, userdata_push_do_work); + INIT_WORK(&qos_work, qos_do_work); + + atomic_set(&vh264_active, 1); @@ -3071,12 +4304,17 @@ static int amvdec_h264_remove(struct platform_device *pdev) cancel_work_sync(&error_wd_work); cancel_work_sync(&stream_switching_work); cancel_work_sync(¬ify_work); - cancel_work_sync(&set_clk_work); cancel_work_sync(&userdata_push_work); + cancel_work_sync(&qos_work); + - mutex_lock(&vh264_mutex); vh264_stop(MODE_FULL); + wait_vh264_search_done(); vdec_source_changed(VFORMAT_H264, 0, 0, 0); +#ifdef DUMP_USER_DATA + vh264_dump_userdata(); +#endif + vh264_destroy_userdata_manager(); atomic_set(&vh264_active, 0); #ifdef DEBUG_PTS pr_info @@ -3087,6 +4325,7 @@ static int amvdec_h264_remove(struct platform_device *pdev) #endif kfree(gvs); gvs = NULL; + cancel_work_sync(&set_clk_work); mutex_unlock(&vh264_mutex); return 0; } @@ -3140,7 +4379,7 @@ static int __init amvdec_h264_driver_init_module(void) pr_err("failed to register amvdec_h264 driver\n"); return -ENODEV; } - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXTVBB + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXTVBB && (codec_mm_get_total_size() > 80 * SZ_1M)) { amvdec_h264_profile.profile = "4k"; } @@ -3169,6 +4408,9 @@ module_param(sync_outside, uint, 0664); MODULE_PARM_DESC(sync_outside, "\n amvdec_h264 sync_outside\n"); module_param(dec_control, uint, 0664); MODULE_PARM_DESC(dec_control, "\n amvdec_h264 decoder control\n"); +module_param(frame_count, uint, 0664); +MODULE_PARM_DESC(frame_count, + "\n amvdec_h264 decoded total count\n"); module_param(fatal_error_reset, uint, 0664); MODULE_PARM_DESC(fatal_error_reset, "\n amvdec_h264 decoder reset when fatal error happens\n"); @@ -3208,6 +4450,11 @@ MODULE_PARM_DESC(bad_block_scale, "\n print bad_block_scale\n"); #endif +module_param(enable_userdata_debug, uint, 0664); +MODULE_PARM_DESC(enable_userdata_debug, + "\n enable_userdata_debug\n"); + + module_init(amvdec_h264_driver_init_module); module_exit(amvdec_h264_driver_remove_module); diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/h264/vh264_4k2k.c b/drivers/amlogic/media_modules/frame_provider/decoder/h264/vh264_4k2k.c index 9363bcf9c377..b0d0a950841d 100644 --- a/drivers/amlogic/media_modules/frame_provider/decoder/h264/vh264_4k2k.c +++ b/drivers/amlogic/media_modules/frame_provider/decoder/h264/vh264_4k2k.c @@ -37,6 +37,10 @@ #include #include #include "../utils/firmware.h" +#include +#include "../../../common/chips/decoder_cpu_ver_info.h" + + #define MEM_NAME "codec_264_4k" @@ -55,6 +59,9 @@ #include #include +#include + + #if 0 /* MESON_CPU_TYPE == MESON_CPU_TYPE_MESON6TVD */ #define DOUBLE_WRITE #endif @@ -70,7 +77,6 @@ #define VF_BUFFER_IDX(n) (2 + n) #define DECODER_WORK_SPACE_SIZE 0x800000 - #if 1 /* MESON_CPU_TYPE == MESON_CPU_TYPE_MESONG9TV */ #define H264_4K2K_SINGLE_CORE 1 #else @@ -110,7 +116,7 @@ static u32 saved_resolution; static struct timer_list recycle_timer; static u32 stat; static u32 error_watchdog_count; -static uint error_recovery_mode; +static uint error_recovery_mode = 1; static u32 sync_outside; static u32 vh264_4k2k_rotation; static u32 first_i_received; @@ -678,6 +684,7 @@ static irqreturn_t vh264_4k2k_isr(int irq, void *dev_id) unsigned int stream_offset; struct vframe_s *vf = NULL; int ret = READ_VREG(MAILBOX_COMMAND); + u32 frame_size; switch (ret & 0xff) { case CMD_ALLOC_VIEW: @@ -714,6 +721,7 @@ static irqreturn_t vh264_4k2k_isr(int irq, void *dev_id) ret = pts_lookup_offset_us64(PTS_TYPE_VIDEO, stream_offset, &vf->pts, + &frame_size, 0, &vf->pts_us64); if (ret != 0) @@ -760,6 +768,7 @@ static irqreturn_t vh264_4k2k_isr(int irq, void *dev_id) VF_BUFFER_IDX(display_buff_id)); kfifo_put(&display_q, (const struct vframe_s *)vf); + ATRACE_COUNTER(MODULE_NAME, vf->pts); vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_VFRAME_READY, @@ -942,8 +951,7 @@ static void vh264_4k2k_put_timer_func(unsigned long arg) struct vframe_s *vf; if (kfifo_get(&recycle_q, &vf)) { - if ((vf->index >= 0) - && (vf->index < DECODE_BUFFER_NUM_MAX) + if ((vf->index < DECODE_BUFFER_NUM_MAX) && (--vfbuf_use[vf->index] == 0)) { WRITE_VREG(BUFFER_RECYCLE, vf->index + 1); vf->index = DECODE_BUFFER_NUM_MAX; @@ -1408,7 +1416,7 @@ static s32 vh264_4k2k_init(void) int ret = -1, size = -1; char *buf = vmalloc(0x1000 * 16); - if (IS_ERR_OR_NULL(buf)) + if (buf == NULL) return -ENOMEM; pr_info("\nvh264_4k2k_init\n"); @@ -1418,8 +1426,10 @@ static s32 vh264_4k2k_init(void) stat |= STAT_TIMER_INIT; ret = vh264_4k2k_local_init(); - if (ret < 0) + if (ret < 0) { + vfree(buf); return ret; + } amvdec_enable(); /* -- ucode loading (amrisc and swap code) */ @@ -1438,7 +1448,6 @@ static s32 vh264_4k2k_init(void) if (H264_4K2K_SINGLE_CORE) size = get_firmware_data(VIDEO_DEC_H264_4k2K_SINGLE, buf); - else size = get_firmware_data(VIDEO_DEC_H264_4k2K, buf); @@ -1448,11 +1457,18 @@ static s32 vh264_4k2k_init(void) return -1; } - if (amvdec_loadmc_ex(VFORMAT_H264_4K2K, NULL, buf) < 0) { + if (H264_4K2K_SINGLE_CORE) + ret = amvdec_loadmc_ex(VFORMAT_H264_4K2K, "single_core", buf); + else + ret = amvdec_loadmc_ex(VFORMAT_H264_4K2K, NULL, buf); + + if (ret < 0) { amvdec_disable(); dma_free_coherent(amports_get_dma_device(), MC_TOTAL_SIZE, mc_cpu_addr, mc_dma_handle); mc_cpu_addr = NULL; + pr_err("H264_4K2K: the %s fw loading failed, err: %x\n", + tee_enabled() ? "TEE" : "local", ret); return -EBUSY; } @@ -1478,19 +1494,6 @@ static s32 vh264_4k2k_init(void) /*slice*/ memcpy((u8 *) mc_cpu_addr + 0x3000, buf + 0x4000, 0x3000); - if (ret < 0) { - amvdec_disable(); - if (!H264_4K2K_SINGLE_CORE) - amvdec2_disable(); - pr_info("vh264_4k2k load firmware error.\n"); - if (mc_cpu_addr) { - dma_free_coherent(amports_get_dma_device(), - MC_TOTAL_SIZE, mc_cpu_addr, mc_dma_handle); - mc_cpu_addr = NULL; - } - - return -EBUSY; - } stat |= STAT_MC_LOAD; /* enable AMRISC side protocol */ @@ -1776,7 +1779,7 @@ static int __init amvdec_h264_4k2k_driver_init_module(void) pr_err("failed to register amvdec_h264_4k2k driver\n"); return -ENODEV; } - if (get_cpu_type() < MESON_CPU_MAJOR_ID_GXTVBB) + if (get_cpu_major_id() < AM_MESON_CPU_MAJOR_ID_GXTVBB) vcodec_profile_register(&amvdec_h264_4k2k_profile); INIT_REG_NODE_CONFIGS("media.decoder", &h264_4k2k_node, "h264_4k2k", h264_4k2k_configs, CONFIG_FOR_RW); diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/h264/vh264_mvc.c b/drivers/amlogic/media_modules/frame_provider/decoder/h264/vh264_mvc.c index 9ca073f99326..5181a459bd2a 100644 --- a/drivers/amlogic/media_modules/frame_provider/decoder/h264/vh264_mvc.c +++ b/drivers/amlogic/media_modules/frame_provider/decoder/h264/vh264_mvc.c @@ -476,15 +476,14 @@ static struct vframe_s *vh264mvc_vf_get(void *op_arg) INCPTR(get_ptr); - if (vf) { - if (frame_width == 0) - frame_width = vh264mvc_amstream_dec_info.width; - if (frame_height == 0) - frame_height = vh264mvc_amstream_dec_info.height; + if (frame_width == 0) + frame_width = vh264mvc_amstream_dec_info.width; + if (frame_height == 0) + frame_height = vh264mvc_amstream_dec_info.height; + + vf->width = frame_width; + vf->height = frame_height; - vf->width = frame_width; - vf->height = frame_height; - } if ((no_dropping_cnt < DROPPING_FIRST_WAIT) && (vf->frame_dirty == 0)) no_dropping_cnt++; return vf; @@ -892,6 +891,7 @@ static void vh264mvc_isr(void) struct vframe_s *vf; unsigned int pts, pts_valid = 0; u64 pts_us64; + u32 frame_size; int ret = READ_VREG(MAILBOX_COMMAND); /* pr_info("vh264mvc_isr, cmd =%x\n", ret); */ switch (ret & 0xff) { @@ -1003,6 +1003,11 @@ static void vh264mvc_isr(void) VF_BUFFER_IDX(display_buff_id)); } else if (display_view_id == 1) { + vf->mem_head_handle = + decoder_bmmu_box_get_mem_handle( + mm_blk_handle, + VF_BUFFER_IDX(display_buff_id)); + vf->mem_handle = decoder_bmmu_box_get_mem_handle( mm_blk_handle, @@ -1020,6 +1025,7 @@ static void vh264mvc_isr(void) if (pts_lookup_offset_us64 (PTS_TYPE_VIDEO, vfpool_idx[slot].stream_offset, &pts, + &frame_size, 0x10000, &pts_us64) == 0) pts_valid = 1; else @@ -1376,8 +1382,10 @@ static int vh264mvc_local_init(void) vfpool_idx[i].view1_drop = 0; vfpool_idx[i].used = 0; } - for (i = 0; i < VF_POOL_SIZE; i++) + for (i = 0; i < VF_POOL_SIZE; i++) { memset(&vfpool[i], 0, sizeof(struct vframe_s)); + vfpool[i].index = i; + } init_vf_buf(); if (mm_blk_handle) { @@ -1402,10 +1410,10 @@ static int vh264mvc_local_init(void) static s32 vh264mvc_init(void) { - int ret = -1, size = -1; + int ret = -1; char *buf = vmalloc(0x1000 * 16); - if (IS_ERR_OR_NULL(buf)) + if (buf == NULL) return -ENOMEM; pr_info("\nvh264mvc_init\n"); @@ -1414,20 +1422,26 @@ static s32 vh264mvc_init(void) stat |= STAT_TIMER_INIT; ret = vh264mvc_vdec_info_init(); - if (0 != ret) + if (0 != ret) { + vfree(buf); return -ret; + } ret = vh264mvc_local_init(); - if (ret < 0) + if (ret < 0) { + vfree(buf); return ret; + } amvdec_enable(); if (tee_enabled()) { - pr_info("the video fw from the teeload.\n"); - ret = tee_load_video_fw((u32)VIDEO_DEC_H264_MVC, 0); + ret = amvdec_loadmc_ex(VFORMAT_H264MVC, NULL, buf); if (ret != 0) { amvdec_disable(); + vfree(buf); + pr_err("H264_MVC: the %s fw loading failed, err: %x\n", + tee_enabled() ? "TEE" : "local", ret); return -1; } } else { @@ -1443,8 +1457,7 @@ static s32 vh264mvc_init(void) WRITE_VREG(UCODE_START_ADDR, mc_dma_handle); - size = get_firmware_data(VIDEO_DEC_H264_MVC, buf); - if (size < 0) { + if (get_firmware_data(VIDEO_DEC_H264_MVC, buf) < 0) { pr_err("get firmware fail."); vfree(buf); return -1; @@ -1459,8 +1472,6 @@ static s32 vh264mvc_init(void) /*slice*/ memcpy((u8 *) mc_cpu_addr + 0x3000, buf + 0x4000, 0x3000); - vfree(buf); - if (ret < 0) { amvdec_disable(); @@ -1471,6 +1482,8 @@ static s32 vh264mvc_init(void) return -EBUSY; } } + vfree(buf); + stat |= STAT_MC_LOAD; /* enable AMRISC side protocol */ @@ -1704,13 +1717,13 @@ module_param(view_mode, uint, 0664); MODULE_PARM_DESC(view_mode, "\n amvdec_h264mvc view mode\n"); module_param(dbg_cmd, uint, 0664); -MODULE_PARM_DESC(dbg_mode, "\n amvdec_h264mvc cmd mode\n"); +MODULE_PARM_DESC(dbg_cmd, "\n amvdec_h264mvc cmd mode\n"); module_param(drop_rate, uint, 0664); -MODULE_PARM_DESC(dbg_mode, "\n amvdec_h264mvc drop rate\n"); +MODULE_PARM_DESC(drop_rate, "\n amvdec_h264mvc drop rate\n"); module_param(drop_thread_hold, uint, 0664); -MODULE_PARM_DESC(dbg_mode, "\n amvdec_h264mvc drop thread hold\n"); +MODULE_PARM_DESC(drop_thread_hold, "\n amvdec_h264mvc drop thread hold\n"); module_init(amvdec_h264mvc_driver_init_module); module_exit(amvdec_h264mvc_driver_remove_module); diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/h264_multi/h264_dpb.c b/drivers/amlogic/media_modules/frame_provider/decoder/h264_multi/h264_dpb.c index 3ec89d64509d..8008310f56e2 100644 --- a/drivers/amlogic/media_modules/frame_provider/decoder/h264_multi/h264_dpb.c +++ b/drivers/amlogic/media_modules/frame_provider/decoder/h264_multi/h264_dpb.c @@ -1,3 +1,22 @@ +/* +* 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. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ #define DEBUG #include #include @@ -9,6 +28,8 @@ #include "h264_dpb.h" +#define FRAME_NUM_MAX_SIZE 0x10000 + #undef pr_info #define pr_info printk int dpb_print(int index, int debug_flag, const char *fmt, ...) @@ -364,6 +385,18 @@ void slice_prepare(struct h264_dpb_stru *p_H264_Dpb, pSlice->structure = (p_H264_Dpb-> dpb_param.l.data[NEW_PICTURE_STRUCTURE] == 3) ? FRAME : p_H264_Dpb->dpb_param.l.data[NEW_PICTURE_STRUCTURE]; + if (pSlice->structure == FRAME) { + pSlice->field_pic_flag = 0; + pSlice->bottom_field_flag = 0; + } else { + pSlice->field_pic_flag = 1; + if (pSlice->structure == TOP_FIELD) + pSlice->bottom_field_flag = 0; + else + pSlice->bottom_field_flag = 1; + } + pSlice->pic_struct = p_H264_Dpb->dpb_param.l.data[PICTURE_STRUCT]; + sps->num_ref_frames = p_H264_Dpb-> dpb_param.l.data[MAX_REFERENCE_FRAME_NUM]; sps->profile_idc = @@ -516,6 +549,14 @@ void slice_prepare(struct h264_dpb_stru *p_H264_Dpb, p_H264_Dpb->dpb_param.l.data[NUM_UNITS_IN_TICK]; p_H264_Dpb->time_scale = p_H264_Dpb->dpb_param.l.data[TIME_SCALE] | (p_H264_Dpb->dpb_param.l.data[TIME_SCALE + 1] << 16); + + p_H264_Dpb->bitstream_restriction_flag = + (p_H264_Dpb->dpb_param.l.data[SPS_FLAGS2] >> 3) & 0x1; + p_H264_Dpb->num_reorder_frames = + p_H264_Dpb->dpb_param.l.data[NUM_REORDER_FRAMES]; + p_H264_Dpb->max_dec_frame_buffering = + p_H264_Dpb->dpb_param.l.data[MAX_BUFFER_FRAME]; + /**/ dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, "%s return\n", __func__); @@ -1016,6 +1057,14 @@ static void init_picture(struct h264_dpb_stru *p_H264_Dpb, currSlice->picture_structure_mmco); } + if (currSlice->pic_struct >= 3) + dec_picture->pic_struct = currSlice->pic_struct + 2; + else if (currSlice->pic_struct == 1) + dec_picture->pic_struct = PIC_TOP_BOT; + else if (currSlice->pic_struct >= 2) + dec_picture->pic_struct = PIC_BOT_TOP; + else + dec_picture->pic_struct = PIC_INVALID; } void dump_pic(struct h264_dpb_stru *p_H264_Dpb) @@ -1460,30 +1509,33 @@ static void dpb_combine_field(struct h264_dpb_stru *p_H264_Dpb, fs->frame->buf_spec_num = fs->top_field->buf_spec_num; fs->frame->colocated_buf_index = fs->top_field->colocated_buf_index; fs->frame->data_flag = fs->top_field->data_flag; + fs->frame->slice_type = fs->top_field->slice_type; if (fs->bottom_field) fs->frame->data_flag |= (fs->bottom_field->data_flag & 0xf0); #endif + if (fs->bottom_field) { + fs->poc = fs->frame->poc = fs->frame->frame_poc = imin( + fs->top_field->poc, fs->bottom_field->poc); - fs->poc = fs->frame->poc = fs->frame->frame_poc = imin( - fs->top_field->poc, fs->bottom_field->poc); + fs->bottom_field->frame_poc = fs->top_field->frame_poc = fs->frame->poc; - fs->bottom_field->frame_poc = fs->top_field->frame_poc = fs->frame->poc; + fs->bottom_field->top_poc = fs->frame->top_poc = fs->top_field->poc; + fs->top_field->bottom_poc = fs->frame->bottom_poc = + fs->bottom_field->poc; - fs->bottom_field->top_poc = fs->frame->top_poc = fs->top_field->poc; - fs->top_field->bottom_poc = fs->frame->bottom_poc = - fs->bottom_field->poc; - - fs->frame->used_for_reference = (fs->top_field->used_for_reference && - fs->bottom_field->used_for_reference); - fs->frame->is_long_term = (fs->top_field->is_long_term && - fs->bottom_field->is_long_term); + fs->frame->used_for_reference = (fs->top_field->used_for_reference && + fs->bottom_field->used_for_reference); + fs->frame->is_long_term = (fs->top_field->is_long_term && + fs->bottom_field->is_long_term); + } if (fs->frame->is_long_term) fs->frame->long_term_frame_idx = fs->long_term_frame_idx; fs->frame->top_field = fs->top_field; - fs->frame->bottom_field = fs->bottom_field; + if (fs->bottom_field) + fs->frame->bottom_field = fs->bottom_field; fs->frame->frame = fs->frame; fs->frame->coded_frame = 0; @@ -1500,12 +1552,13 @@ static void dpb_combine_field(struct h264_dpb_stru *p_H264_Dpb, fs->frame->frame_crop_right_offset = fs->top_field->frame_crop_right_offset; } - - fs->top_field->frame = fs->bottom_field->frame = fs->frame; - fs->top_field->top_field = fs->top_field; - fs->top_field->bottom_field = fs->bottom_field; - fs->bottom_field->top_field = fs->top_field; - fs->bottom_field->bottom_field = fs->bottom_field; + if (fs->bottom_field) { + fs->top_field->frame = fs->bottom_field->frame = fs->frame; + fs->top_field->top_field = fs->top_field; + fs->top_field->bottom_field = fs->bottom_field; + fs->bottom_field->top_field = fs->top_field; + fs->bottom_field->bottom_field = fs->bottom_field; + } /**/ #if (MVC_EXTENSION_ENABLE) @@ -1561,10 +1614,13 @@ static void insert_picture_in_dpb(struct h264_dpb_stru *p_H264_Dpb, fs->buf_spec_num = p->buf_spec_num; fs->colocated_buf_index = p->colocated_buf_index; #endif + p->slice_type = p_H264_Dpb->mSlice.slice_type; switch (p->structure) { case FRAME: fs->frame = p; fs->is_used = 3; + fs->slice_type = p->slice_type; + fs->frame_size = p->frame_size; if (p->used_for_reference) { fs->is_reference = 3; fs->is_orig_reference = 3; @@ -1591,6 +1647,12 @@ static void insert_picture_in_dpb(struct h264_dpb_stru *p_H264_Dpb, fs->top_field = p; fs->is_used |= 1; fs->layer_id = p->layer_id; + if (fs->frame_size == 0) { + fs->slice_type = p->slice_type; +// fs->pts = p->pts; +// fs->pts64 = p->pts64; + } + fs->frame_size += p->frame_size; #if (MVC_EXTENSION_ENABLE) fs->view_id = p->view_id; fs->inter_view_flag[0] = p->inter_view_flag; @@ -1617,6 +1679,12 @@ static void insert_picture_in_dpb(struct h264_dpb_stru *p_H264_Dpb, fs->bottom_field = p; fs->is_used |= 2; fs->layer_id = p->layer_id; + if (fs->frame_size == 0) { + fs->slice_type = p->slice_type; +// fs->pts = p->pts; +// fs->pts64 = p->pts64; + } + fs->frame_size += p->frame_size; #if (MVC_EXTENSION_ENABLE) fs->view_id = p->view_id; fs->inter_view_flag[1] = p->inter_view_flag; @@ -1646,6 +1714,19 @@ static void insert_picture_in_dpb(struct h264_dpb_stru *p_H264_Dpb, fs->is_output = p->is_output; fs->pre_output = p->pre_output; + /* picture qos infomation*/ + fs->max_mv = p->max_mv; + fs->avg_mv = p->avg_mv; + fs->min_mv = p->min_mv; + + fs->max_qp = p->max_qp; + fs->avg_qp = p->avg_qp; + fs->min_qp = p->min_qp; + + fs->max_skip = p->max_skip; + fs->avg_skip = p->avg_skip; + fs->min_skip = p->min_skip; + if (fs->is_used == 3) { calculate_frame_no(p_Vid, p); #if 0 @@ -1657,6 +1738,7 @@ static void insert_picture_in_dpb(struct h264_dpb_stru *p_H264_Dpb, fs->pts = p->pts; fs->pts64 = p->pts64; + fs->timestamp = p->timestamp; } void reset_frame_store(struct h264_dpb_stru *p_H264_Dpb, @@ -1927,7 +2009,7 @@ static void remove_frame_from_dpb(struct h264_dpb_stru *p_H264_Dpb, int pos) fs->is_long_term = 0; fs->is_reference = 0; fs->is_orig_reference = 0; - + fs->frame_size = 0; /* move empty framestore to end of buffer */ tmp = p_Dpb->fs[pos]; @@ -2114,7 +2196,8 @@ static void get_smallest_poc(struct DecodedPictureBuffer *p_Dpb, int *poc, /* rain */ if ((*poc > p_Dpb->fs[i]->poc) && (!p_Dpb->fs[i]->is_output) && - (!p_Dpb->fs[i]->pre_output)) { + (!p_Dpb->fs[i]->pre_output) && + (p_Dpb->fs[i]->is_used == 3)) { #else if ((*poc > p_Dpb->fs[i]->poc) && (!p_Dpb->fs[i]->is_output)) { #endif @@ -2134,8 +2217,18 @@ int output_frames(struct h264_dpb_stru *p_H264_Dpb, unsigned char flush_flag) if (!flush_flag) { for (i = 0; i < p_Dpb->used_size; i++) { if ((!p_Dpb->fs[i]->is_output) && - (!p_Dpb->fs[i]->pre_output)) { + (!p_Dpb->fs[i]->pre_output) && (p_Dpb->fs[i]->is_used == 3)) { none_displayed_num++; + if ((p_H264_Dpb->first_insert_frame == FirstInsertFrm_IDLE) + && (p_Dpb->fs[i]->is_used == 3) + && (p_Dpb->last_output_poc == INT_MIN)) { + p_H264_Dpb->first_insert_frame = FirstInsertFrm_OUT; + p_H264_Dpb->first_output_poc = p_Dpb->fs[i]->poc; + fast_output_flag = 1; + dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, + "%s first insert frame i %d poc %d frame_num %x\n", + __func__, i, p_Dpb->fs[i]->poc, p_Dpb->fs[i]->frame_num); + } /*check poc even/odd*/ if (p_H264_Dpb->poc_even_odd_flag == 0 && p_H264_Dpb->decode_pic_count >= 3) @@ -2147,10 +2240,6 @@ int output_frames(struct h264_dpb_stru *p_H264_Dpb, unsigned char flush_flag) if ((p_H264_Dpb->fast_output_enable & 0x1) && (p_Dpb->fs[i]->data_flag & IDR_FLAG)) fast_output_flag = 1; - if (p_H264_Dpb->fast_output_enable & 0x6 - && p_H264_Dpb->poc_even_odd_flag - && p_Dpb->last_output_poc == INT_MIN) - fast_output_flag = 1; if ((p_H264_Dpb->fast_output_enable & 0x2) && ((p_Dpb->fs[i]->poc - p_Dpb->last_output_poc) @@ -2158,6 +2247,7 @@ int output_frames(struct h264_dpb_stru *p_H264_Dpb, unsigned char flush_flag) fast_output_flag = 1; if ((p_H264_Dpb->fast_output_enable & 0x4) && (p_H264_Dpb->poc_even_odd_flag == 2) && + (p_Dpb->fs[i]->is_used == 3) && ((p_Dpb->fs[i]->poc - p_Dpb->last_output_poc) == 2)) @@ -2179,6 +2269,19 @@ int output_frames(struct h264_dpb_stru *p_H264_Dpb, unsigned char flush_flag) if (is_used_for_reference(p_Dpb->fs[pos])) return 0; #endif + if (p_H264_Dpb->first_insert_frame == FirstInsertFrm_OUT) { + dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, + "%s pos %d pos->poc %d first_output_poc %d \n", + __func__, pos, p_Dpb->fs[pos]->poc, p_H264_Dpb->first_output_poc); + + if (p_Dpb->fs[pos]->poc < p_H264_Dpb->first_output_poc) + p_Dpb->fs[pos]->data_flag |= NODISP_FLAG; + else if (p_Dpb->last_output_poc != INT_MIN) + p_H264_Dpb->first_insert_frame = FirstInsertFrm_SKIPDONE; + + dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL, + "%s first_insert_frame %d \n", __func__, p_H264_Dpb->first_insert_frame); + } if (prepare_display_buf(p_H264_Dpb->vdec, p_Dpb->fs[pos]) >= 0) p_Dpb->fs[pos]->pre_output = 1; else { @@ -2828,12 +2931,12 @@ static void unmark1(struct DecodedPictureBuffer *p_Dpb, unsigned int curr_frame_num, int i) { if (p_Dpb->last_picture) { - if ((p_Dpb->last_picture != p_Dpb->fs_ltref[i]) || - p_Dpb->last_picture->frame_num != curr_frame_num) { + /*if ((p_Dpb->last_picture != p_Dpb->fs_ltref[i]) || + p_Dpb->last_picture->frame_num != curr_frame_num) {*/ unmark_for_long_term_reference(p_Dpb->fs_ltref[i]); - } else { + /*} else { unmark_for_long_term_reference(p_Dpb->fs_ltref[i]); - } + }*/ } } @@ -3500,6 +3603,14 @@ int store_picture_in_dpb(struct h264_dpb_stru *p_H264_Dpb, update_ltref_list(p_Dpb); check_num_ref(p_Dpb); + if (p_H264_Dpb->fast_output_enable == H264_OUTPUT_MODE_FAST) + i = 1; + else + i = 0; + if (i || (p_H264_Dpb->first_insert_frame < FirstInsertFrm_SKIPDONE)) { + while (output_frames(p_H264_Dpb, i)) + ; + } dump_dpb(p_Dpb, 0); p_Dpb->first_pic_done = 1; /*by rain*/ @@ -4904,7 +5015,8 @@ static struct StorablePicture *get_long_term_pic(struct Slice *currSlice, for (i = 0; i < p_Dpb->ltref_frames_in_buffer; i++) { if (currSlice->structure == FRAME) { if (p_Dpb->fs_ltref[i]->is_reference == 3) - if ((p_Dpb->fs_ltref[i]->frame-> + if ((p_Dpb->fs_ltref[i]->frame) && + (p_Dpb->fs_ltref[i]->frame-> is_long_term) && (p_Dpb->fs_ltref[i]->frame-> long_term_pic_num == @@ -4912,13 +5024,16 @@ static struct StorablePicture *get_long_term_pic(struct Slice *currSlice, return p_Dpb->fs_ltref[i]->frame; } else { if (p_Dpb->fs_ltref[i]->is_reference & 1) - if ((p_Dpb->fs_ltref[i]->top_field-> + if ((p_Dpb->fs_ltref[i]->top_field) && + (p_Dpb->fs_ltref[i]->top_field-> is_long_term) && (p_Dpb->fs_ltref[i]->top_field-> long_term_pic_num == LongtermPicNum)) return p_Dpb->fs_ltref[i]->top_field; + if (p_Dpb->fs_ltref[i]->is_reference & 2) - if ((p_Dpb->fs_ltref[i]->bottom_field-> + if ((p_Dpb->fs_ltref[i]->bottom_field) && + (p_Dpb->fs_ltref[i]->bottom_field-> is_long_term) && (p_Dpb->fs_ltref[i]->bottom_field-> long_term_pic_num == @@ -5602,6 +5717,7 @@ int h264_slice_header_process(struct h264_dpb_stru *p_H264_Dpb) p_Vid->pre_frame_num, p_Vid->max_frame_num); if (p_Vid->recovery_point == 0 && + p_Vid->max_frame_num <= FRAME_NUM_MAX_SIZE && currSlice->frame_num != p_Vid->pre_frame_num && currSlice->frame_num != (p_Vid->pre_frame_num + 1) % p_Vid->max_frame_num) { @@ -5735,6 +5851,9 @@ int dpb_check_ref_list_error( int i; /*int j;*/ struct Slice *currSlice = &p_H264_Dpb->mSlice; + /* in first output, ignore ref check */ + if (p_H264_Dpb->first_insert_frame < FirstInsertFrm_SKIPDONE) + return 0; if ((currSlice->slice_type != I_SLICE) && (currSlice->slice_type != SI_SLICE)) { for (i = 0; i < currSlice->listXsize[0]; i++) { diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/h264_multi/h264_dpb.h b/drivers/amlogic/media_modules/frame_provider/decoder/h264_multi/h264_dpb.h index dc3824f451a5..222113f7eb1b 100644 --- a/drivers/amlogic/media_modules/frame_provider/decoder/h264_multi/h264_dpb.h +++ b/drivers/amlogic/media_modules/frame_provider/decoder/h264_multi/h264_dpb.h @@ -1,3 +1,22 @@ +/* +* 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. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ #ifndef H264_DPB_H_ #define H264_DPB_H_ @@ -19,15 +38,27 @@ #define RRINT_FLAG_RPM 0x0400 #define DEBUG_DISABLE_RUNREADY_RMBUF 0x0800 #define PRINT_FLAG_DUMP_BUFSPEC 0x1000 +#define PRINT_FLAG_V4L_DETAIL 0x8000 #define DISABLE_ERROR_HANDLE 0x10000 #define DEBUG_DUMP_STAT 0x80000 +#define PIC_SINGLE_FRAME 0 +#define PIC_TOP_BOT_TOP 1 +#define PIC_BOT_TOP_BOT 2 +#define PIC_DOUBLE_FRAME 3 +#define PIC_TRIPLE_FRAME 4 +#define PIC_TOP_BOT 5 +#define PIC_BOT_TOP 6 +#define PIC_INVALID 7 #define MVC_EXTENSION_ENABLE 0 #define PRINTREFLIST 0 #define MAX_LIST_SIZE 33 +#define H264_OUTPUT_MODE_NORMAL 0x4 +#define H264_OUTPUT_MODE_FAST 0x8 + #define FALSE 0 #define H264_SLICE_HEAD_DONE 0x01 @@ -47,10 +78,17 @@ #define H264_SEARCH_BUFEMPTY 0x22 #define H264_DECODE_OVER_SIZE 0x23 +#define VIDEO_SIGNAL_LOW 0x26 +#define VIDEO_SIGNAL_HIGHT 0x27 + + #define H264_FIND_NEXT_PIC_NAL 0x50 #define H264_FIND_NEXT_DVEL_NAL 0x51 #define H264_AUX_DATA_READY 0x52 +#define H264_SEI_DATA_READY 0x53 +#define H264_SEI_DATA_DONE 0x54 + /* 0x8x, search state*/ #define H264_STATE_SEARCH_AFTER_SPS 0x80 #define H264_STATE_SEARCH_AFTER_PPS 0x81 @@ -100,8 +138,19 @@ union param { #define BUFFER_SIZE_HI 0X69 #define CROPPING_LEFT_RIGHT 0X6A #define CROPPING_TOP_BOTTOM 0X6B +#if 1 + /* sps_flags2: + *bit 3, bitstream_restriction_flag + *bit 2, pic_struct_present_flag + *bit 1, vcl_hrd_parameters_present_flag + *bit 0, nal_hrd_parameters_present_flag + */ +#define SPS_FLAGS2 0x6c +#define NUM_REORDER_FRAMES 0x6d +#else #define POC_SELECT_NEED_SWAP 0X6C #define POC_SELECT_SWAP 0X6D +#endif #define MAX_BUFFER_FRAME 0X6E #define NON_CONFORMING_STREAM 0X70 @@ -398,6 +447,13 @@ enum ProfileIDC { STEREO_HIGH = 128 /*!< YUV 4:2:0/8 "Stereo High"*/ }; +enum FirstInsertFrm_State { + FirstInsertFrm_IDLE = 0, + FirstInsertFrm_OUT = 1, + FirstInsertFrm_SKIPDONE = 2, +}; + + struct SPSParameters { unsigned int profile_idc; int pic_order_cnt_type; @@ -470,6 +526,7 @@ struct Slice { unsigned char dec_ref_pic_marking_buffer_valid; struct DecRefPicMarking_s dec_ref_pic_marking_buffer[DEC_REF_PIC_MARKING_BUFFER_NUM_MAX]; + int pic_struct; }; struct OldSliceParams { @@ -646,7 +703,21 @@ struct StorablePicture { u32 pts; u64 pts64; + u64 timestamp; unsigned char data_flag; + int pic_struct; + + /* picture qos infomation*/ + int frame_size; + int max_qp; + int avg_qp; + int min_qp; + int max_skip; + int avg_skip; + int min_skip; + int max_mv; + int min_mv; + int avg_mv; }; struct FrameStore { @@ -709,6 +780,22 @@ struct FrameStore { u32 pts; u64 pts64; + u64 timestamp; + + + /* picture qos infomation*/ + int slice_type; + int frame_size; + + int max_qp; + int avg_qp; + int min_qp; + int max_skip; + int avg_skip; + int min_skip; + int max_mv; + int min_mv; + int avg_mv; }; @@ -790,10 +877,15 @@ struct h264_dpb_stru { unsigned int aspect_ratio_idc; unsigned int aspect_ratio_sar_width; unsigned int aspect_ratio_sar_height; + u8 bitstream_restriction_flag; + u16 num_reorder_frames; + u16 max_dec_frame_buffering; unsigned int dec_dpb_status; unsigned char buf_alloc_fail; unsigned int dpb_error_flag; + unsigned int first_insert_frame; + int first_output_poc; }; diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/h264_multi/vmh264.c b/drivers/amlogic/media_modules/frame_provider/decoder/h264_multi/vmh264.c index 690c04c3ba35..08d5421564ed 100644 --- a/drivers/amlogic/media_modules/frame_provider/decoder/h264_multi/vmh264.c +++ b/drivers/amlogic/media_modules/frame_provider/decoder/h264_multi/vmh264.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -57,10 +58,16 @@ #include #include #include "../utils/config_parser.h" +#include "../../../amvdec_ports/vdec_drv_base.h" +#include "../../../common/chips/decoder_cpu_ver_info.h" +#include + +#include + #undef pr_info #define pr_info printk - +#define VDEC_DW #define DEBUG_UCODE #define MEM_NAME "codec_m264" #define MULTI_INSTANCE_FRAMEWORK @@ -74,6 +81,7 @@ #define CHECK_INTERVAL (HZ/100) +#define SEI_DATA_SIZE (8*1024) #define SEI_ITU_DATA_SIZE (4*1024) #define RATE_MEASURE_NUM 8 @@ -108,7 +116,10 @@ #define H264_DEV_NUM 9 +#define CONSTRAIN_MAX_BUF_NUM + #define H264_MMU +#define VIDEO_SIGNAL_TYPE_AVAILABLE_MASK 0x20000000 static int mmu_enable; static int force_enable_mmu = 1; unsigned int h264_debug_flag; /* 0xa0000000; */ @@ -126,6 +137,8 @@ static unsigned int fixed_frame_rate_mode; static unsigned int error_recovery_mode_in; static int start_decode_buf_level = 0x8000; static int pre_decode_buf_level = 0x1000; +static int stream_mode_start_num = 4; + #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION /*to make reorder size difference of bl and el not too big*/ static unsigned int reorder_dpb_size_margin_dv = 16; @@ -133,6 +146,18 @@ static unsigned int reorder_dpb_size_margin_dv = 16; static unsigned int reorder_dpb_size_margin = 6; static unsigned int reference_buf_margin = 4; +#ifdef CONSTRAIN_MAX_BUF_NUM +static u32 run_ready_max_vf_only_num; +static u32 run_ready_display_q_num; + /*0: not check + 0xff: mDPB.size + */ +static u32 run_ready_max_buf_num = 0xff; +#endif + +#define VDEC_ASSIST_CANVAS_BLK32 0x5 + + static unsigned int max_alloc_buf_count; static unsigned int decode_timeout_val = 100; static unsigned int errordata_timeout_val = 50; @@ -184,11 +209,16 @@ static unsigned int max_get_frame_interval[H264_DEV_NUM]; static unsigned int run_count[H264_DEV_NUM]; static unsigned int input_empty[H264_DEV_NUM]; static unsigned int not_run_ready[H264_DEV_NUM]; - /* bit[3:0]: - *0, run ; 1, pause; 3, step - *bit[4]: - *1, schedule run - */ +static unsigned int ref_frame_mark_flag[H264_DEV_NUM] = +{1, 1, 1, 1, 1, 1, 1, 1, 1}; + +#define VDEC_CLOCK_ADJUST_FRAME 30 +static unsigned int clk_adj_frame_count; + +/* + *bit[3:0]: 0, run ; 1, pause; 3, step + *bit[4]: 1, schedule run + */ static unsigned int step[H264_DEV_NUM]; #define AUX_BUF_ALIGN(adr) ((adr + 0xf) & (~0xf)) @@ -230,7 +260,8 @@ static unsigned int i_only_flag; bit[12] i_only when error happen */ -static unsigned int error_proc_policy = 0x1f36; /*0x1f14*/ +static unsigned int error_proc_policy = 0xf36; /*0x1f14*/ + /* error_skip_count: @@ -249,7 +280,7 @@ static unsigned int force_sliding_margin; bit[15:8]: the max count of skip frames after first I 3, start playing from IDR */ -static unsigned int first_i_policy = (15 << 8) | 2; +static unsigned int first_i_policy = 1; /* fast_output_enable: @@ -257,13 +288,13 @@ static unsigned int first_i_policy = (15 << 8) | 2; bit [1], output frame if the current poc is 1 big than the previous poc bit [2], if even poc only, output frame ifthe cuurent poc is 2 big than the previous poc + bit [3], ip only */ -static unsigned int fast_output_enable = 4; +static unsigned int fast_output_enable = H264_OUTPUT_MODE_NORMAL; static unsigned int enable_itu_t35 = 1; -//static unsigned int frmbase_cont_bitlevel = 0x40;//DEBUG_TMP -static unsigned int frmbase_cont_bitlevel; +static unsigned int frmbase_cont_bitlevel = 0x40; static unsigned int frmbase_cont_bitlevel2 = 0x1; @@ -278,9 +309,13 @@ static unsigned int frmbase_cont_bitlevel2 = 0x1; 3, (1/4):(1/4) ratio, with both compressed frame included 4, (1/2):(1/2) ratio 0x10, double write only + 0x10000: vdec dw horizotal 1/2 + 0x20000: vdec dw horizotal/vertical 1/2 */ static u32 double_write_mode; +#define IS_VDEC_DW(hw) (hw->double_write_mode >> 16 & 0xf) + static void vmh264_dump_state(struct vdec_s *vdec); #define is_in_parsing_state(status) \ @@ -320,17 +355,9 @@ static inline bool close_to(int a, int b, int m) /*#define V_BUF_ADDR_OFFSET (0x13e000)*/ u32 V_BUF_ADDR_OFFSET = 0x200000; #define DCAC_READ_MARGIN (64 * 1024) -#define PIC_SINGLE_FRAME 0 -#define PIC_TOP_BOT_TOP 1 -#define PIC_BOT_TOP_BOT 2 -#define PIC_DOUBLE_FRAME 3 -#define PIC_TRIPLE_FRAME 4 -#define PIC_TOP_BOT 5 -#define PIC_BOT_TOP 6 -#define PIC_INVALID 7 + #define EXTEND_SAR 0xff - #define BUFSPEC_POOL_SIZE 64 #define VF_POOL_SIZE 64 #define VF_POOL_NUM 2 @@ -339,7 +366,7 @@ u32 V_BUF_ADDR_OFFSET = 0x200000; #define BMMU_REF_IDX (BUFSPEC_POOL_SIZE) #define BMMU_DPB_IDX (BUFSPEC_POOL_SIZE + 1) #define BMMU_EXTIF_IDX (BUFSPEC_POOL_SIZE + 2) -#define EXTIF_BUF_SIZE 0x10000 +#define EXTIF_BUF_SIZE (0x10000 * 2) #define HEADER_BUFFER_IDX(n) (n) #define VF_BUFFER_IDX(n) (n) @@ -386,6 +413,21 @@ struct buffer_spec_s { int u_canvas_index; int v_canvas_index; +#ifdef VDEC_DW + unsigned int vdec_dw_y_addr; + unsigned int vdec_dw_u_addr; + unsigned int vdec_dw_v_addr; + + int vdec_dw_y_canvas_index; + int vdec_dw_u_canvas_index; + int vdec_dw_v_canvas_index; +#ifdef NV21 + struct canvas_config_s vdec_dw_canvas_config[2]; +#else + struct canvas_config_s vdec_dw_canvas_config[3]; +#endif +#endif + #ifdef NV21 struct canvas_config_s canvas_config[2]; #else @@ -412,6 +454,13 @@ struct buffer_spec_s { #define AUX_DATA_BUF(pic) (hw->buffer_spec[pic->buf_spec_num].aux_data_buf) #define DEL_EXIST(h, p) (h->buffer_spec[p->buf_spec_num].dv_enhance_exist) + +#define vdec_dw_spec2canvas(x) \ + (((x)->vdec_dw_v_canvas_index << 16) | \ + ((x)->vdec_dw_u_canvas_index << 8) | \ + ((x)->vdec_dw_y_canvas_index << 0)) + + #define spec2canvas(x) \ (((x)->v_canvas_index << 16) | \ ((x)->u_canvas_index << 8) | \ @@ -428,9 +477,9 @@ static int vh264_vf_states(struct vframe_states *states, void *); static int vh264_event_cb(int type, void *data, void *private_data); static void vh264_work(struct work_struct *work); static void vh264_notify_work(struct work_struct *work); -static void user_data_push_work(struct work_struct *work); #ifdef MH264_USERDATA_ENABLE static void user_data_ready_notify_work(struct work_struct *work); +static void vmh264_wakeup_userdata_poll(struct vdec_s *vdec); #endif static const char vh264_dec_id[] = "vh264-dev"; @@ -558,6 +607,11 @@ struct vdec_h264_hw_s { u32 suffix_aux_size; void *aux_addr; dma_addr_t aux_phy_addr; + + /* buffer for store all sei data */ + void *sei_data_buf; + u32 sei_data_len; + /* buffer for storing one itu35 recored */ void *sei_itu_data_buf; u32 sei_itu_data_len; @@ -565,8 +619,6 @@ struct vdec_h264_hw_s { /* recycle buffer for user data storing all itu35 records */ void *sei_user_data_buffer; u32 sei_user_data_wp; - int sei_poc; - struct work_struct user_data_work; #ifdef MH264_USERDATA_ENABLE struct work_struct user_data_ready_work; #endif @@ -604,6 +656,7 @@ struct vdec_h264_hw_s { struct vframe_s switching_fense_vf; struct h264_dpb_stru dpb; u8 init_flag; + u8 first_sc_checked; u8 has_i_frame; u8 config_bufmgr_done; u32 max_reference_size; @@ -641,6 +694,9 @@ struct vdec_h264_hw_s { u32 video_signal_from_vui; /*to do .. */ u32 timing_info_present_flag; u32 fixed_frame_rate_flag; + u32 bitstream_restriction_flag; + u32 num_reorder_frames; + u32 max_dec_frame_buffering; u32 iframe_count; u32 aspect_ratio_info; u32 num_units_in_tick; @@ -653,6 +709,7 @@ struct vdec_h264_hw_s { u32 h264_pts_count; u32 duration_from_pts_done; u32 pts_unstable; + u32 unstable_pts; u32 last_checkout_pts; u32 max_refer_buf; @@ -760,11 +817,21 @@ struct vdec_h264_hw_s { /*user data*/ struct mutex userdata_mutex; struct mh264_userdata_info_t userdata_info; - struct list_head frame_uds; /*user data records list waiting for vpts*/ - struct list_head free_uds_wait_nodes; /*free user data records list*/ - struct mh264_ud_record_wait_node_t free_nodes[MAX_FREE_USERDATA_NODES]; + struct mh264_userdata_record_t ud_record; int wait_for_udr_send; #endif + u32 no_mem_count; + u32 canvas_mode; + bool is_used_v4l; + void *v4l2_ctx; + wait_queue_head_t wait_q; + u32 reg_g_status; + struct mutex chunks_mutex; + int need_cache_size; + u64 sc_start_time; + u8 frmbase_cont_flag; + struct vframe_qos_s vframe_qos; + int frameinfo_enable; }; static u32 again_threshold = 0x40; @@ -796,6 +863,7 @@ static void h264_clear_dpb(struct vdec_h264_hw_s *hw); #define HEVC_SAO_MMU_STATUS 0x3639 #define HEVCD_MPP_ANC2AXI_TBL_DATA 0x3464 + #define HEVC_CM_HEADER_START_ADDR 0x3628 #define HEVC_CM_BODY_START_ADDR 0x3626 #define HEVC_CM_BODY_LENGTH 0x3627 @@ -804,7 +872,9 @@ static void h264_clear_dpb(struct vdec_h264_hw_s *hw); #define HEVC_SAO_CTRL9 0x362d #define HEVCD_MPP_DECOMP_CTL3 0x34c4 #define HEVCD_MPP_VDEC_MCR_CTL 0x34c8 - +#define HEVC_DBLK_CFGB 0x350b +#define HEVC_CM_CORE_STATUS 0x3640 +#define HEVC_ASSIST_MMU_MAP_ADDR 0x3009 #define H265_DW_NO_SCALE #define H265_MEM_MAP_MODE 0 /*0:linear 1:32x32 2:64x32*/ @@ -812,16 +882,30 @@ static void h264_clear_dpb(struct vdec_h264_hw_s *hw); #define MAX_FRAME_4K_NUM 0x1200 #define FRAME_MMU_MAP_SIZE (MAX_FRAME_4K_NUM * 4) - /* 0:linear 1:32x32 2:64x32 ; m8baby test1902 */ static u32 mem_map_mode = H265_MEM_MAP_MODE; +#define MAX_SIZE_8K (8192 * 4608) +#define MAX_SIZE_4K (4096 * 2304) + +static int is_oversize(int w, int h) +{ + int max = (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1)? + MAX_SIZE_8K : MAX_SIZE_4K; + + if (w < 0 || h < 0) + return true; + + if (h != 0 && (w > max / h)) + return true; + + return false; +} + static int compute_losless_comp_body_size(int width, int height, int bit_depth_10); static int compute_losless_comp_header_size(int width, int height); - - static int hevc_alloc_mmu(struct vdec_h264_hw_s *hw, int pic_idx, int pic_width, int pic_height, u16 bit_depth, unsigned int *mmu_index_adr) { @@ -839,6 +923,13 @@ static int hevc_alloc_mmu(struct vdec_h264_hw_s *hw, int pic_idx, PRINT_FLAG_MMU_DETAIL, "alloc_mmu new_fb_idx %d picture_size %d cur_mmu_4k_number %d\n", cur_buf_idx, picture_size, cur_mmu_4k_number); + + if (cur_mmu_4k_number > MAX_FRAME_4K_NUM) { + pr_err("hevc_alloc_mmu cur_mmu_4k_number %d unsupport\n", + cur_mmu_4k_number); + return -1; + } + return decoder_mmu_box_alloc_idx( hw->mmu_box, cur_buf_idx, @@ -892,14 +983,10 @@ static int compute_losless_comp_header_size(int width, int height) return hsize; } - - static int get_double_write_ratio(struct vdec_h264_hw_s *hw) { int ratio = 1; - int dw_mode; - - dw_mode = hw->double_write_mode; + int dw_mode = hw->double_write_mode; if ((dw_mode == 2) || (dw_mode == 3)) ratio = 4; @@ -916,11 +1003,12 @@ static int get_dw_size(struct vdec_h264_hw_s *hw, u32 *pdw_buffer_size_u_v_h) int dw_buf_size; u32 dw_buffer_size_u_v; u32 dw_buffer_size_u_v_h; + int dw_mode = hw->double_write_mode; pic_width = hw->frame_width; pic_height = hw->frame_height; - if (hw->double_write_mode) { + if (dw_mode) { int pic_width_dw = pic_width / get_double_write_ratio(hw); int pic_height_dw = pic_height / @@ -958,6 +1046,7 @@ static void hevc_mcr_config_canv2axitbl(struct vdec_h264_hw_s *hw, int restore) int dw_size = 0; u32 dw_buffer_size_u_v_h; u32 blkmode = mem_map_mode; + int dw_mode = hw->double_write_mode; canvas_addr = ANC0_CANVAS_ADDR; for (i = 0; i < num_buff; i++) @@ -1000,7 +1089,7 @@ static void hevc_mcr_config_canv2axitbl(struct vdec_h264_hw_s *hw, int restore) "%s : canvas: %d axiaddr:%x size 0x%x\n", __func__, i, (u32)maddr, size); - if (hw->double_write_mode) { + if (dw_mode) { u32 addr; int canvas_w; int canvas_h; @@ -1074,6 +1163,8 @@ static void hevc_mcr_config_mc_ref(struct vdec_h264_hw_s *hw) /*REFLIST[0]*/ for (i = 0; i < (unsigned int)(pSlice->listXsize[0]); i++) { struct StorablePicture *ref = pSlice->listX[0][i]; + if (ref == NULL) + return; WRITE_VREG(CURR_CANVAS_CTRL, ref->buf_spec_num<<24); ref_canv = READ_VREG(CURR_CANVAS_CTRL)&0xffffff; WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR, @@ -1083,6 +1174,8 @@ static void hevc_mcr_config_mc_ref(struct vdec_h264_hw_s *hw) /*REFLIST[1]*/ for (i = 0; i < (unsigned int)(pSlice->listXsize[1]); i++) { struct StorablePicture *ref = pSlice->listX[1][i]; + if (ref == NULL) + return; WRITE_VREG(CURR_CANVAS_CTRL, ref->buf_spec_num<<24); ref_canv = READ_VREG(CURR_CANVAS_CTRL)&0xffffff; WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR, @@ -1108,6 +1201,8 @@ static void hevc_mcr_config_mcrcc(struct vdec_h264_hw_s *hw) } if (slice_type == B_SLICE) { ref = pSlice->listX[0][0]; + if (ref == NULL) + return; WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR, ((ref->buf_spec_num & 0x3f) << 8)); rdata32 = READ_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR); @@ -1116,6 +1211,8 @@ static void hevc_mcr_config_mcrcc(struct vdec_h264_hw_s *hw) WRITE_VREG(HEVCD_MCRCC_CTL2, rdata32); ref = pSlice->listX[1][0]; + if (ref == NULL) + return; WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR, ((ref->buf_spec_num & 0x3f) << 8)); rdata32_2 = READ_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR); @@ -1123,6 +1220,8 @@ static void hevc_mcr_config_mcrcc(struct vdec_h264_hw_s *hw) rdata32_2 = rdata32_2 | (rdata32_2 << 16); if (rdata32 == rdata32_2) { ref = pSlice->listX[1][1]; + if (ref == NULL) + return; WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR, ((ref->buf_spec_num & 0x3f) << 8)); rdata32_2 = READ_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR); @@ -1132,6 +1231,8 @@ static void hevc_mcr_config_mcrcc(struct vdec_h264_hw_s *hw) WRITE_VREG(HEVCD_MCRCC_CTL3, rdata32_2); } else { /*P-PIC*/ ref = pSlice->listX[0][0]; + if (ref == NULL) + return; WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR, ((ref->buf_spec_num & 0x3f) << 8)); rdata32 = READ_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR); @@ -1140,6 +1241,8 @@ static void hevc_mcr_config_mcrcc(struct vdec_h264_hw_s *hw) WRITE_VREG(HEVCD_MCRCC_CTL2, rdata32); ref = pSlice->listX[0][1]; + if (ref == NULL) + return; WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR, ((ref->buf_spec_num & 0x3f) << 8)); rdata32 = READ_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR); @@ -1151,6 +1254,7 @@ static void hevc_mcr_config_mcrcc(struct vdec_h264_hw_s *hw) return; } + static void hevc_mcr_sao_global_hw_init(struct vdec_h264_hw_s *hw, u32 width, u32 height) { u32 data32; @@ -1158,6 +1262,7 @@ static void hevc_mcr_sao_global_hw_init(struct vdec_h264_hw_s *hw, u32 lcu_total; u32 mc_buffer_size_u_v; u32 mc_buffer_size_u_v_h; + int dw_mode = hw->double_write_mode; lcu_x_num = (width + 15) >> 4; lcu_y_num = (height + 15) >> 4; @@ -1208,6 +1313,15 @@ static void hevc_mcr_sao_global_hw_init(struct vdec_h264_hw_s *hw, /* ipp_enable*/ WRITE_VREG(HEVCD_IPP_TOP_CNTL, 0x1 << 1); + if (get_cpu_major_id() >= MESON_CPU_MAJOR_ID_G12A) { + WRITE_VREG(HEVC_DBLK_CFG1, 0x2); // set ctusize==16 + WRITE_VREG(HEVC_DBLK_CFG2, ((height & 0xffff)<<16) | (width & 0xffff)); + if (dw_mode) + WRITE_VREG(HEVC_DBLK_CFGB, 0x40405703); + else + WRITE_VREG(HEVC_DBLK_CFGB, 0x40405503); + } + data32 = READ_VREG(HEVC_SAO_CTRL0); data32 &= (~0xf); data32 |= 0x4; @@ -1229,7 +1343,7 @@ static void hevc_mcr_sao_global_hw_init(struct vdec_h264_hw_s *hw, data32 &= (~0xff0); data32 |= endian; /* Big-Endian per 64-bit */ - if (hw->mmu_enable && hw->double_write_mode) + if (hw->mmu_enable && dw_mode) data32 |= ((mem_map_mode << 12)); else data32 |= ((mem_map_mode << 12)|2); @@ -1238,13 +1352,13 @@ static void hevc_mcr_sao_global_hw_init(struct vdec_h264_hw_s *hw, #ifdef H265_DW_NO_SCALE WRITE_VREG(HEVC_SAO_CTRL5, READ_VREG(HEVC_SAO_CTRL5) & ~(0xff << 16)); - if (hw->mmu_enable && hw->double_write_mode) { + if (hw->mmu_enable && dw_mode) { data32 = READ_VREG(HEVC_SAO_CTRL5); data32 &= (~(0xff << 16)); - if (hw->double_write_mode == 2 || - hw->double_write_mode == 3) + if (dw_mode == 2 || + dw_mode == 3) data32 |= (0xff<<16); - else if (hw->double_write_mode == 4) + else if (dw_mode == 4) data32 |= (0x33<<16); WRITE_VREG(HEVC_SAO_CTRL5, data32); } @@ -1293,6 +1407,7 @@ static void hevc_sao_set_pic_buffer(struct vdec_h264_hw_s *hw, u32 dw_u_v_adr; u32 canvas_addr; int ret; + int dw_mode = hw->double_write_mode; if (hw->is_new_pic != 1) return; @@ -1312,7 +1427,7 @@ static void hevc_sao_set_pic_buffer(struct vdec_h264_hw_s *hw, WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CONF_ADDR, 0x1); - if (hw->double_write_mode) { + if (dw_mode) { dw_y_adr = hw->buffer_spec[pic->buf_spec_num].dw_y_adr; dw_u_v_adr = hw->buffer_spec[pic->buf_spec_num].dw_u_v_adr; } else { @@ -1320,7 +1435,7 @@ static void hevc_sao_set_pic_buffer(struct vdec_h264_hw_s *hw, dw_u_v_adr = 0; } #ifdef H265_LOSLESS_COMPRESS_MODE - if (hw->double_write_mode) + if (dw_mode) WRITE_VREG(HEVC_SAO_Y_START_ADDR, dw_y_adr); WRITE_VREG(HEVC_CM_BODY_START_ADDR, mc_y_adr); #ifdef H264_MMU @@ -1336,12 +1451,12 @@ static void hevc_sao_set_pic_buffer(struct vdec_h264_hw_s *hw, #ifndef H265_LOSLESS_COMPRESS_MODE WRITE_VREG(HEVC_SAO_C_START_ADDR, mc_u_v_adr); #else - if (hw->double_write_mode) + if (dw_mode) WRITE_VREG(HEVC_SAO_C_START_ADDR, dw_u_v_adr); #endif #ifndef LOSLESS_COMPRESS_MODE - if (hw->double_write_mode) { + if (dw_mode) { WRITE_VREG(HEVC_SAO_Y_WPTR, mc_y_adr); WRITE_VREG(HEVC_SAO_C_WPTR, mc_u_v_adr); } @@ -1351,7 +1466,7 @@ static void hevc_sao_set_pic_buffer(struct vdec_h264_hw_s *hw, #endif ret = hevc_alloc_mmu(hw, pic->buf_spec_num, - hw->frame_width, hw->frame_height, 0x0, + (hw->mb_width << 4), (hw->mb_height << 4), 0x0, hw->frame_mmu_map_addr); if (ret != 0) { dpb_print(DECODE_ID(hw), @@ -1362,14 +1477,20 @@ static void hevc_sao_set_pic_buffer(struct vdec_h264_hw_s *hw, } /*Reset SAO + Enable SAO slice_start*/ + if (hw->mmu_enable && get_cpu_major_id() >= MESON_CPU_MAJOR_ID_G12A) + WRITE_VREG(HEVC_DBLK_CFG0, 0x1); // reset buffer32x4 in lpf for every picture WRITE_VREG(HEVC_SAO_INT_STATUS, READ_VREG(HEVC_SAO_INT_STATUS) | 0x1 << 28); WRITE_VREG(HEVC_SAO_INT_STATUS, READ_VREG(HEVC_SAO_INT_STATUS) | 0x1 << 31); /*pr_info("hevc_sao_set_pic_buffer:mc_y_adr: %x\n", mc_y_adr);*/ /*Send coommand to hevc-code to supply 4k buffers to sao*/ - WRITE_VREG(H265_SAO_4K_SET_BASE, (u32)hw->frame_mmu_map_phy_addr); - WRITE_VREG(H265_SAO_4K_SET_COUNT, MAX_FRAME_4K_NUM); + + if (get_cpu_major_id() < MESON_CPU_MAJOR_ID_G12A) { + WRITE_VREG(H265_SAO_4K_SET_BASE, (u32)hw->frame_mmu_map_phy_addr); + WRITE_VREG(H265_SAO_4K_SET_COUNT, MAX_FRAME_4K_NUM); + } else + WRITE_VREG(HEVC_ASSIST_MMU_MAP_ADDR, (u32)hw->frame_mmu_map_phy_addr); WRITE_VREG(SYS_COMMAND, H265_PUT_SAO_4K_SET); hw->frame_busy = 1; return; @@ -1399,6 +1520,14 @@ static void hevc_set_frame_done(struct vdec_h264_hw_s *hw) break; } } + timeout = jiffies + HZ; + while (READ_VREG(HEVC_CM_CORE_STATUS) & 0x1) { + if (time_after(jiffies, timeout)) { + dpb_print(DECODE_ID(hw), + PRINT_FLAG_MMU_DETAIL, " %s cm_core..timeout!\n", __func__); + break; + } + } WRITE_VREG(HEVC_SAO_INT_STATUS, 0x1); hw->frame_done = 1; return; @@ -1431,15 +1560,17 @@ static void hevc_sao_wait_done(struct vdec_h264_hw_s *hw) } } timeout = jiffies + HZ; - if ((hw->frame_busy == 1) && (hw->frame_done == 1)) { + if ((hw->frame_busy == 1) && (hw->frame_done == 1) ) { + if (get_cpu_major_id() < MESON_CPU_MAJOR_ID_G12A) { WRITE_VREG(SYS_COMMAND, H265_ABORT_SAO_4K_SET); - while ((READ_VREG(SYS_COMMAND) & 0xff) != - H265_ABORT_SAO_4K_SET_DONE) { - if (time_after(jiffies, timeout)) { - dpb_print(DECODE_ID(hw), - PRINT_FLAG_MMU_DETAIL, - "wait h265_abort_sao_4k_set_done timeout!\n"); - break; + while ((READ_VREG(SYS_COMMAND) & 0xff) != + H265_ABORT_SAO_4K_SET_DONE) { + if (time_after(jiffies, timeout)) { + dpb_print(DECODE_ID(hw), + PRINT_FLAG_MMU_DETAIL, + "wait h265_abort_sao_4k_set_done timeout!\n"); + break; + } } } amhevc_stop(); @@ -1499,8 +1630,16 @@ static int alloc_one_buf_spec(struct vdec_h264_hw_s *hw, int i) return -1; } else { - int buf_size = (hw->mb_total << 8) + (hw->mb_total << 7); + int buf_size = (hw->mb_total << 8) + (hw->mb_total << 7); int addr; +#ifdef VDEC_DW + int orig_buf_size; + orig_buf_size = buf_size; + if (IS_VDEC_DW(hw) == 1) + buf_size += (hw->mb_total << 7) + (hw->mb_total << 6); + else if (IS_VDEC_DW(hw) == 2) + buf_size += (hw->mb_total << 6) + (hw->mb_total << 6); +#endif if (hw->buffer_spec[i].cma_alloc_addr) return 0; @@ -1508,12 +1647,20 @@ static int alloc_one_buf_spec(struct vdec_h264_hw_s *hw, int i) PAGE_ALIGN(buf_size), DRIVER_NAME, &hw->buffer_spec[i].cma_alloc_addr) < 0) { hw->buffer_spec[i].cma_alloc_addr = 0; + if (hw->no_mem_count++ > 3) { + hw->stat |= DECODER_FATAL_ERROR_NO_MEM; + hw->reset_bufmgr_flag = 1; + } dpb_print(DECODE_ID(hw), 0, "%s, fail to alloc buf for bufspec%d, try later\n", __func__, i ); return -1; + } else { + hw->no_mem_count = 0; + hw->stat &= ~DECODER_FATAL_ERROR_NO_MEM; } + hw->buffer_spec[i].buf_adr = hw->buffer_spec[i].cma_alloc_addr; addr = hw->buffer_spec[i].buf_adr; @@ -1521,55 +1668,295 @@ static int alloc_one_buf_spec(struct vdec_h264_hw_s *hw, int i) hw->buffer_spec[i].y_addr = addr; addr += hw->mb_total << 8; - hw->buffer_spec[i].u_addr = addr; hw->buffer_spec[i].v_addr = addr; addr += hw->mb_total << 7; hw->buffer_spec[i].canvas_config[0].phy_addr = - hw->buffer_spec[i].y_addr; + hw->buffer_spec[i].y_addr; hw->buffer_spec[i].canvas_config[0].width = - hw->mb_width << 4; + hw->mb_width << 4; hw->buffer_spec[i].canvas_config[0].height = - hw->mb_height << 4; + hw->mb_height << 4; hw->buffer_spec[i].canvas_config[0].block_mode = + hw->canvas_mode; + + hw->buffer_spec[i].canvas_config[1].phy_addr = + hw->buffer_spec[i].u_addr; + hw->buffer_spec[i].canvas_config[1].width = + hw->mb_width << 4; + hw->buffer_spec[i].canvas_config[1].height = + hw->mb_height << 3; + hw->buffer_spec[i].canvas_config[1].block_mode = + hw->canvas_mode; + dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS, + "%s, alloc buf for bufspec%d\n", + __func__, i + ); +#ifdef VDEC_DW + + if (!IS_VDEC_DW(hw)) + return 0; + else if (IS_VDEC_DW(hw) == 1) { + addr = hw->buffer_spec[i].cma_alloc_addr + orig_buf_size; + hw->buffer_spec[i].vdec_dw_y_addr = addr; + addr += hw->mb_total << 7; + hw->buffer_spec[i].vdec_dw_u_addr = addr; + hw->buffer_spec[i].vdec_dw_v_addr = addr; + addr += hw->mb_total << 6; + + hw->buffer_spec[i].vdec_dw_canvas_config[0].phy_addr = + hw->buffer_spec[i].vdec_dw_y_addr; + hw->buffer_spec[i].vdec_dw_canvas_config[0].width = + hw->mb_width << 3; + hw->buffer_spec[i].vdec_dw_canvas_config[0].height = + hw->mb_height << 4; + hw->buffer_spec[i].vdec_dw_canvas_config[0].block_mode = CANVAS_BLKMODE_32X32; - hw->buffer_spec[i].canvas_config[1].phy_addr = - hw->buffer_spec[i].u_addr; - hw->buffer_spec[i].canvas_config[1].width = - hw->mb_width << 4; - hw->buffer_spec[i].canvas_config[1].height = + hw->buffer_spec[i].vdec_dw_canvas_config[1].phy_addr = + hw->buffer_spec[i].vdec_dw_u_addr; + hw->buffer_spec[i].vdec_dw_canvas_config[1].width = + hw->mb_width << 3; + hw->buffer_spec[i].vdec_dw_canvas_config[1].height = hw->mb_height << 3; - hw->buffer_spec[i].canvas_config[1].block_mode = + hw->buffer_spec[i].vdec_dw_canvas_config[1].block_mode = CANVAS_BLKMODE_32X32; - dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS, - "%s, alloc buf for bufspec%d\n", - __func__, i - ); + }else { + addr = hw->buffer_spec[i].cma_alloc_addr + orig_buf_size; + hw->buffer_spec[i].vdec_dw_y_addr = addr; + addr += hw->mb_total << 6; + hw->buffer_spec[i].vdec_dw_u_addr = addr; + hw->buffer_spec[i].vdec_dw_v_addr = addr; + addr += hw->mb_total << 5; + + hw->buffer_spec[i].vdec_dw_canvas_config[0].phy_addr = + hw->buffer_spec[i].vdec_dw_y_addr; + hw->buffer_spec[i].vdec_dw_canvas_config[0].width = + hw->mb_width << 3; + hw->buffer_spec[i].vdec_dw_canvas_config[0].height = + hw->mb_height << 3; + hw->buffer_spec[i].vdec_dw_canvas_config[0].block_mode = + CANVAS_BLKMODE_32X32; + + hw->buffer_spec[i].vdec_dw_canvas_config[1].phy_addr = + hw->buffer_spec[i].vdec_dw_u_addr; + hw->buffer_spec[i].vdec_dw_canvas_config[1].width = + hw->mb_width << 3; + hw->buffer_spec[i].vdec_dw_canvas_config[1].height = + hw->mb_height << 2; + hw->buffer_spec[i].vdec_dw_canvas_config[1].block_mode = + CANVAS_BLKMODE_32X32; + } + dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS, + "%s, vdec_dw: alloc buf for bufspec%d\n", + __func__, i + ); +#endif } return 0; } +static int v4l_get_fb(struct aml_vcodec_ctx *ctx, struct vdec_fb **out) +{ + int ret = 0; + + ret = ctx->dec_if->get_param(ctx->drv_handle, + GET_PARAM_FREE_FRAME_BUFFER, out); + if (ret) + pr_err("get frame buffer failed.\n"); + + return ret; +} + +static int alloc_one_buf_spec_from_queue(struct vdec_h264_hw_s *hw, int idx) +{ + int ret = 0; + struct aml_vcodec_ctx *ctx = NULL; + struct buffer_spec_s *bs = &hw->buffer_spec[idx]; + struct canvas_config_s *y_canvas_cfg = NULL; + struct canvas_config_s *c_canvas_cfg = NULL; + struct vdec_fb *fb = NULL; + unsigned int y_addr, c_addr; + + if (IS_ERR_OR_NULL(hw->v4l2_ctx)) { + pr_err("the v4l context has err.\n"); + return -1; + } + + if (bs->cma_alloc_addr) + return 0; + + ctx = (struct aml_vcodec_ctx *)(hw->v4l2_ctx); + dpb_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL, + "[%d] %s(), buf size: %d\n", ctx->id, __func__, + (hw->mb_total << 8) + (hw->mb_total << 7)); + + ret = v4l_get_fb(hw->v4l2_ctx, &fb); + if (ret) { + pr_err("[%d] get fb fail.\n", ctx->id); + return ret; + } + + bs->cma_alloc_addr = (unsigned long)fb; + dpb_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL, + "[%d] %s(), cma alloc addr: 0x%x\n", + ctx->id, __func__, bs->cma_alloc_addr); + + y_addr = virt_to_phys(fb->base_y.va); + c_addr = virt_to_phys(fb->base_c.va); + + dpb_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL, + "[%d] %s(), y_addr: %x, va: %p\n", + ctx->id, __func__, y_addr, fb->base_y.va); + dpb_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL, + "[%d] %s(), c_addr: %x, va: %p\n", + ctx->id, __func__, c_addr, fb->base_c.va); + + bs->y_addr = y_addr; + bs->u_addr = c_addr; + bs->v_addr = c_addr; + + y_canvas_cfg = &bs->canvas_config[0]; + c_canvas_cfg = &bs->canvas_config[1]; + + y_canvas_cfg->phy_addr = y_addr; + y_canvas_cfg->width = hw->mb_width << 4; + y_canvas_cfg->height = hw->mb_height << 4; + y_canvas_cfg->block_mode = CANVAS_BLKMODE_LINEAR; + fb->base_y.bytes_used = y_canvas_cfg->width * y_canvas_cfg->height; + dpb_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL, + "[%d] %s(), y_w: %d, y_h: %d\n", ctx->id, __func__, + y_canvas_cfg->width,y_canvas_cfg->height); + + c_canvas_cfg->phy_addr = c_addr; + c_canvas_cfg->width = hw->mb_width << 4; + c_canvas_cfg->height = hw->mb_height << 3; + c_canvas_cfg->block_mode = CANVAS_BLKMODE_LINEAR; + fb->base_c.bytes_used = c_canvas_cfg->width * c_canvas_cfg->height; + dpb_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL, + "[%d] %s(), c_w: %d, c_h: %d\n", ctx->id, __func__, + c_canvas_cfg->width, c_canvas_cfg->height); + + dpb_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL, + "[%d] %s(), alloc buf for bufspec%d\n", ctx->id, __func__, idx); + + return ret; +} + static void config_decode_canvas(struct vdec_h264_hw_s *hw, int i) { - canvas_config(hw->buffer_spec[i]. + int endian = 0; + int blkmode = ((hw->canvas_mode == CANVAS_BLKMODE_LINEAR) || + hw->is_used_v4l) ? CANVAS_BLKMODE_LINEAR : + CANVAS_BLKMODE_32X32; + if (blkmode == CANVAS_BLKMODE_LINEAR) + endian = 7; + + canvas_config_ex(hw->buffer_spec[i]. y_canvas_index, hw->buffer_spec[i].y_addr, hw->mb_width << 4, hw->mb_height << 4, CANVAS_ADDR_NOWRAP, - CANVAS_BLKMODE_32X32); + blkmode, + endian); + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A) { + WRITE_VREG(VDEC_ASSIST_CANVAS_BLK32, + (1 << 11) | /* canvas_blk32_wr */ + (blkmode << 10) | /* canvas_blk32*/ + (1 << 8) | /* canvas_index_wr*/ + (hw->buffer_spec[i].y_canvas_index << 0) /* canvas index*/ + ); + } - canvas_config(hw->buffer_spec[i]. + canvas_config_ex(hw->buffer_spec[i]. u_canvas_index, hw->buffer_spec[i].u_addr, hw->mb_width << 4, hw->mb_height << 3, CANVAS_ADDR_NOWRAP, - CANVAS_BLKMODE_32X32); + blkmode, + endian); + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A) { + WRITE_VREG(VDEC_ASSIST_CANVAS_BLK32, + (1 << 11) | + (blkmode << 10) | + (1 << 8) | + (hw->buffer_spec[i].u_canvas_index << 0)); + } WRITE_VREG(ANC0_CANVAS_ADDR + hw->buffer_spec[i].canvas_pos, spec2canvas(&hw->buffer_spec[i])); + + +#ifdef VDEC_DW + if (!IS_VDEC_DW(hw)) + return; + else if (IS_VDEC_DW(hw) == 1) { + canvas_config_ex(hw->buffer_spec[i]. + vdec_dw_y_canvas_index, + hw->buffer_spec[i].vdec_dw_y_addr, + hw->mb_width << 3, + hw->mb_height << 4, + CANVAS_ADDR_NOWRAP, + blkmode, + hw->is_used_v4l ? 7 : 0); + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A) { + WRITE_VREG(VDEC_ASSIST_CANVAS_BLK32, + (1 << 11) | + (blkmode << 10) | + (1 << 8) | + (hw->buffer_spec[i].vdec_dw_y_canvas_index << 0)); + } + canvas_config_ex(hw->buffer_spec[i]. + vdec_dw_u_canvas_index, + hw->buffer_spec[i].vdec_dw_u_addr, + hw->mb_width << 3, + hw->mb_height << 3, + CANVAS_ADDR_NOWRAP, + blkmode, + hw->is_used_v4l ? 7 : 0); + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A) { + WRITE_VREG(VDEC_ASSIST_CANVAS_BLK32, + (1 << 11) | + (blkmode << 10) | + (1 << 8) | + (hw->buffer_spec[i].vdec_dw_u_canvas_index << 0)); + } + } else { + canvas_config_ex(hw->buffer_spec[i]. + vdec_dw_y_canvas_index, + hw->buffer_spec[i].vdec_dw_y_addr, + hw->mb_width << 3, + hw->mb_height << 3, + CANVAS_ADDR_NOWRAP, + blkmode, + hw->is_used_v4l ? 7 : 0); + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A) { + WRITE_VREG(VDEC_ASSIST_CANVAS_BLK32, + (1 << 11) | + (blkmode << 10) | + (1 << 8) | + (hw->buffer_spec[i].vdec_dw_y_canvas_index << 0)); + } + + canvas_config_ex(hw->buffer_spec[i]. + vdec_dw_u_canvas_index, + hw->buffer_spec[i].vdec_dw_u_addr, + hw->mb_width << 3, + hw->mb_height << 2, + CANVAS_ADDR_NOWRAP, + blkmode, + hw->is_used_v4l ? 7 : 0); + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A) { + WRITE_VREG(VDEC_ASSIST_CANVAS_BLK32, + (1 << 11) | + (blkmode << 10) | + (1 << 8) | + (hw->buffer_spec[i].vdec_dw_u_canvas_index << 0)); + } + } +#endif } static void config_decode_canvas_ex(struct vdec_h264_hw_s *hw, int i) @@ -1664,13 +2051,13 @@ int get_free_buf_idx(struct vdec_s *vdec) int release_buf_spec_num(struct vdec_s *vdec, int buf_spec_num) { - u32 cur_buf_idx; + /*u32 cur_buf_idx;*/ unsigned long flags; struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)vdec->private; dpb_print(DECODE_ID(hw), PRINT_FLAG_MMU_DETAIL, "%s buf_spec_num %d used %d\n", __func__, buf_spec_num, - hw->buffer_spec[buf_spec_num].used); + buf_spec_num > 0 ? hw->buffer_spec[buf_spec_num].used : 0); if (buf_spec_num >= 0 && buf_spec_num < BUFSPEC_POOL_SIZE ) { @@ -1678,10 +2065,10 @@ int release_buf_spec_num(struct vdec_s *vdec, int buf_spec_num) hw->buffer_spec[buf_spec_num].used = 0; spin_unlock_irqrestore(&hw->bufspec_lock, flags); if (hw->mmu_enable) { - WRITE_VREG(CURR_CANVAS_CTRL, buf_spec_num<<24); + /*WRITE_VREG(CURR_CANVAS_CTRL, buf_spec_num<<24); cur_buf_idx = READ_VREG(CURR_CANVAS_CTRL); - cur_buf_idx = cur_buf_idx&0xff; - decoder_mmu_box_free_idx(hw->mmu_box, cur_buf_idx); + cur_buf_idx = cur_buf_idx&0xff;*/ + decoder_mmu_box_free_idx(hw->mmu_box, buf_spec_num); } release_aux_data(hw, buf_spec_num); } @@ -1696,6 +2083,8 @@ static void config_buf_specs(struct vdec_s *vdec) int i, j; unsigned long flags; struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)vdec->private; + int mode = IS_VDEC_DW(hw) ? 2 : 1; + spin_lock_irqsave(&hw->bufspec_lock, flags); for (i = 0, j = 0; j < hw->dpb.mDPB.size @@ -1704,16 +2093,53 @@ static void config_buf_specs(struct vdec_s *vdec) int canvas; if (hw->buffer_spec[i].used != -1) continue; - canvas = vdec->get_canvas(j, 2); - hw->buffer_spec[i].y_canvas_index = canvas_y(canvas); - hw->buffer_spec[i].u_canvas_index = canvas_u(canvas); - hw->buffer_spec[i].v_canvas_index = canvas_v(canvas); - hw->buffer_spec[i].used = 0; + if (vdec->parallel_dec == 1) { + if (hw->buffer_spec[i].y_canvas_index == -1) + hw->buffer_spec[i].y_canvas_index = vdec->get_canvas_ex(CORE_MASK_VDEC_1, vdec->id); + if (hw->buffer_spec[i].u_canvas_index == -1) { + hw->buffer_spec[i].u_canvas_index = vdec->get_canvas_ex(CORE_MASK_VDEC_1, vdec->id); + hw->buffer_spec[i].v_canvas_index = hw->buffer_spec[i].u_canvas_index; + } +#ifdef VDEC_DW + if (IS_VDEC_DW(hw)) { + if (hw->buffer_spec[i].vdec_dw_y_canvas_index == -1) + hw->buffer_spec[i].vdec_dw_y_canvas_index = + vdec->get_canvas_ex(CORE_MASK_VDEC_1, vdec->id); + if (hw->buffer_spec[i].vdec_dw_u_canvas_index == -1) { + hw->buffer_spec[i].vdec_dw_u_canvas_index = + vdec->get_canvas_ex(CORE_MASK_VDEC_1, vdec->id); + hw->buffer_spec[i].vdec_dw_v_canvas_index = + hw->buffer_spec[i].vdec_dw_u_canvas_index; + } + } +#endif + } else { + canvas = vdec->get_canvas(j * mode, 2); + hw->buffer_spec[i].y_canvas_index = canvas_y(canvas); + hw->buffer_spec[i].u_canvas_index = canvas_u(canvas); + hw->buffer_spec[i].v_canvas_index = canvas_v(canvas); + dpb_print(DECODE_ID(hw), + PRINT_FLAG_DPB_DETAIL, + "config canvas (%d) %x for bufspec %d\r\n", + j, canvas, i); +#ifdef VDEC_DW + if (IS_VDEC_DW(hw)) { + canvas = vdec->get_canvas(j * mode + 1, 2); + hw->buffer_spec[i].vdec_dw_y_canvas_index = canvas_y(canvas); + hw->buffer_spec[i].vdec_dw_u_canvas_index = canvas_u(canvas); + hw->buffer_spec[i].vdec_dw_v_canvas_index = canvas_v(canvas); + dpb_print(DECODE_ID(hw), + PRINT_FLAG_DPB_DETAIL, + "vdec_dw: config canvas (%d) %x for bufspec %d\r\n", + j, canvas, i); + } +#endif + } + hw->buffer_spec[i].used = 0; hw->buffer_spec[i].canvas_pos = j; - /*pr_info("config canvas (%d) %x for bufspec %d\r\n", - j, canvas, i);*/ + j++; } spin_unlock_irqrestore(&hw->bufspec_lock, flags); @@ -1724,25 +2150,64 @@ static void config_buf_specs_ex(struct vdec_s *vdec) int i, j; unsigned long flags; struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)vdec->private; + int mode = IS_VDEC_DW(hw) ? 2 : 1; + spin_lock_irqsave(&hw->bufspec_lock, flags); for (i = 0, j = 0; j < hw->dpb.mDPB.size && i < BUFSPEC_POOL_SIZE; i++) { - int canvas; + int canvas = 0; if (hw->buffer_spec[i].used != -1) continue; - canvas = vdec->get_canvas(j, 2); - hw->buffer_spec[i].y_canvas_index = canvas_y(canvas); - hw->buffer_spec[i].u_canvas_index = canvas_u(canvas); - hw->buffer_spec[i].v_canvas_index = canvas_v(canvas); + if (vdec->parallel_dec == 1) { + if (hw->buffer_spec[i].y_canvas_index == -1) + hw->buffer_spec[i].y_canvas_index = vdec->get_canvas_ex(CORE_MASK_VDEC_1, vdec->id); + if (hw->buffer_spec[i].u_canvas_index == -1) { + hw->buffer_spec[i].u_canvas_index = vdec->get_canvas_ex(CORE_MASK_VDEC_1, vdec->id); + hw->buffer_spec[i].v_canvas_index = hw->buffer_spec[i].u_canvas_index; + } +#ifdef VDEC_DW + if (IS_VDEC_DW(hw)) { + if (hw->buffer_spec[i].vdec_dw_y_canvas_index == -1) + hw->buffer_spec[i].vdec_dw_y_canvas_index = + vdec->get_canvas_ex(CORE_MASK_VDEC_1, vdec->id); + if (hw->buffer_spec[i].vdec_dw_u_canvas_index == -1) { + hw->buffer_spec[i].vdec_dw_u_canvas_index = + vdec->get_canvas_ex(CORE_MASK_VDEC_1, vdec->id); + hw->buffer_spec[i].vdec_dw_v_canvas_index = + hw->buffer_spec[i].vdec_dw_u_canvas_index; + } + } +#endif + } else { + canvas = vdec->get_canvas(j* mode, 2); + hw->buffer_spec[i].y_canvas_index = canvas_y(canvas); + hw->buffer_spec[i].u_canvas_index = canvas_u(canvas); + hw->buffer_spec[i].v_canvas_index = canvas_v(canvas); + + dpb_print(DECODE_ID(hw), + PRINT_FLAG_DPB_DETAIL, + "config canvas (%d) %x for bufspec %d\r\n", + j, canvas, i); +#ifdef VDEC_DW + if (IS_VDEC_DW(hw)) { + canvas = vdec->get_canvas(j*mode + 1, 2); + hw->buffer_spec[i].vdec_dw_y_canvas_index = canvas_y(canvas); + hw->buffer_spec[i].vdec_dw_u_canvas_index = canvas_u(canvas); + hw->buffer_spec[i].vdec_dw_v_canvas_index = canvas_v(canvas); + dpb_print(DECODE_ID(hw), + PRINT_FLAG_DPB_DETAIL, + "vdec_dw: config canvas (%d) %x for bufspec %d\r\n", + j, canvas, i); + } +#endif + } + hw->buffer_spec[i].used = 0; hw->buffer_spec[i].alloc_header_addr = 0; - hw->buffer_spec[i].canvas_pos = j; - pr_info("config canvas (%d) %x for bufspec %d\r\n", - j, canvas, i); j++; } spin_unlock_irqrestore(&hw->bufspec_lock, flags); @@ -1773,9 +2238,11 @@ static void dealloc_buf_specs(struct vdec_h264_hw_s *hw, if (!hw->mmu_enable) { if (hw->buffer_spec[i].cma_alloc_addr) { - decoder_bmmu_box_free_idx( - hw->bmmu_box, - i); + if (!hw->is_used_v4l) { + decoder_bmmu_box_free_idx( + hw->bmmu_box, + i); + } spin_lock_irqsave (&hw->bufspec_lock, flags); hw->buffer_spec[i].cma_alloc_addr = 0; @@ -1837,7 +2304,10 @@ unsigned char have_free_buf_spec(struct vdec_s *vdec) dealloc_buf_specs(hw, 0); if (max_alloc_buf_count == 0 || allocated_count < max_alloc_buf_count) { - if (alloc_one_buf_spec(hw, index) >= 0) + if (hw->is_used_v4l) { + if (alloc_one_buf_spec_from_queue(hw, index) >= 0) + ret = 1; + } else if (alloc_one_buf_spec(hw, index) >= 0) ret = 1; } mutex_unlock(&vmh264_mutex); @@ -1910,6 +2380,63 @@ static int check_force_interlace(struct vdec_h264_hw_s *hw, return bForceInterlace; } +static void fill_frame_info(struct vdec_h264_hw_s *hw, struct FrameStore *frame) +{ + struct vframe_qos_s *vframe_qos = &hw->vframe_qos; + if (frame->slice_type == I_SLICE) + vframe_qos->type = 1; + else if (frame->slice_type == P_SLICE) + vframe_qos->type = 2; + else if (frame->slice_type == B_SLICE) + vframe_qos->type = 3; + + vframe_qos->size = frame->frame_size; + vframe_qos->pts = frame->pts64; + + vframe_qos->max_mv = frame->max_mv; + vframe_qos->avg_mv = frame->avg_mv; + vframe_qos->min_mv = frame->min_mv; +/* + pr_info("mv: max:%d, avg:%d, min:%d\n", + vframe_qos->max_mv, + vframe_qos->avg_mv, + vframe_qos->min_mv); +*/ + + vframe_qos->max_qp = frame->max_qp; + vframe_qos->avg_qp = frame->avg_qp; + vframe_qos->min_qp = frame->min_qp; +/* + pr_info("qp: max:%d, avg:%d, min:%d\n", + vframe_qos->max_qp, + vframe_qos->avg_qp, + vframe_qos->min_qp); +*/ + + vframe_qos->max_skip = frame->max_skip; + vframe_qos->avg_skip = frame->avg_skip; + vframe_qos->min_skip = frame->min_skip; +/* + pr_info("skip: max:%d, avg:%d, min:%d\n", + vframe_qos->max_skip, + vframe_qos->avg_skip, + vframe_qos->min_skip); +*/ + vframe_qos->num++; + if (hw->frameinfo_enable) + vdec_fill_frame_info(vframe_qos, 1); +} + +static int is_iframe(struct FrameStore *frame) { + + if (frame->frame && frame->frame->slice_type == I_SLICE) { + return 1; + } + return 0; +} + + + int prepare_display_buf(struct vdec_s *vdec, struct FrameStore *frame) { struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)vdec->private; @@ -1948,9 +2475,17 @@ int prepare_display_buf(struct vdec_s *vdec, struct FrameStore *frame) __func__, buffer_index, frame->data_flag & ERROR_FLAG, frame->poc, hw->data_flag & ERROR_FLAG, error_proc_policy); + if (frame->frame == NULL && + ((frame->is_used == 1 && frame->top_field) + || (frame->is_used == 2 && frame->bottom_field))) { + dpb_print(DECODE_ID(hw), PRINT_FLAG_ERRORFLAG_DBG, + "%s Error frame_num %d used %d\n", + frame->frame_num, frame->is_used); + frame->data_flag |= ERROR_FLAG; + } + if ((frame->data_flag & NODISP_FLAG) || (frame->data_flag & NULL_FLAG) || - (frame->data_flag & ERROR_FLAG) || ((!hw->send_error_frame_flag) && (frame->data_flag & ERROR_FLAG)) || ((hw->i_only & 0x1) && @@ -1960,6 +2495,7 @@ int prepare_display_buf(struct vdec_s *vdec, struct FrameStore *frame) return 0; /*do not return -1, otherwise flush_dpb() will not flush all dbp frames*/ } + display_frame_count[DECODE_ID(hw)]++; if (dpb_is_debug(DECODE_ID(hw), @@ -1984,6 +2520,7 @@ int prepare_display_buf(struct vdec_s *vdec, struct FrameStore *frame) if (bForceInterlace) vf_count = 2; hw->buffer_spec[buffer_index].vf_ref = 0; + fill_frame_info(hw, frame); for (i = 0; i < vf_count; i++) { if (kfifo_get(&hw->newframe_q, &vf) == 0 || vf == NULL) { @@ -1993,9 +2530,27 @@ int prepare_display_buf(struct vdec_s *vdec, struct FrameStore *frame) return -1; } vf->duration_pulldown = 0; - vf->pts = frame->pts; - vf->pts_us64 = frame->pts64; - vf->index = VF_INDEX(frame->index, buffer_index); + if (!(is_iframe(frame)) && hw->unstable_pts) { + vf->pts = 0; + vf->pts_us64 = 0; + vf->timestamp = 0; + vf->index = VF_INDEX(frame->index, buffer_index); + } else { + vf->pts = frame->pts; + vf->pts_us64 = frame->pts64; + vf->timestamp = frame->timestamp; + vf->index = VF_INDEX(frame->index, buffer_index); + } + + if (hw->is_used_v4l) { + vf->v4l_mem_handle + = hw->buffer_spec[buffer_index].cma_alloc_addr; + dpb_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL, + "[%d] %s(), v4l mem handle: 0x%x\n", + ((struct aml_vcodec_ctx *)(hw->v4l2_ctx))->id, + __func__, vf->v4l_mem_handle); + } + if (hw->mmu_enable) { if (hw->double_write_mode & 0x10) { /* double write only */ @@ -2040,6 +2595,7 @@ int prepare_display_buf(struct vdec_s *vdec, struct FrameStore *frame) VIDTYPE_COMPRESS | VIDTYPE_VIU_FIELD; vf->canvas0Addr = vf->canvas1Addr = 0; } + vf->bitdepth = BITDEPTH_Y8 | BITDEPTH_U8 | BITDEPTH_V8; @@ -2048,8 +2604,15 @@ int prepare_display_buf(struct vdec_s *vdec, struct FrameStore *frame) } else { vf->type = VIDTYPE_PROGRESSIVE | VIDTYPE_VIU_FIELD | VIDTYPE_VIU_NV21; + vf->canvas0Addr = vf->canvas1Addr = spec2canvas(&hw->buffer_spec[buffer_index]); +#ifdef VDEC_DW + if (IS_VDEC_DW(hw)) + vf->canvas0Addr = vf->canvas1Addr = + vdec_dw_spec2canvas(&hw->buffer_spec[buffer_index]); +#endif + } set_frame_info(hw, vf, buffer_index); @@ -2094,8 +2657,21 @@ int prepare_display_buf(struct vdec_s *vdec, struct FrameStore *frame) vf->duration = vf->duration/2; } + if (i == 0) { + if (hw->mmu_enable) + decoder_do_frame_check(hw_to_vdec(hw), vf); + else + decoder_do_frame_check(hw_to_vdec(hw), vf); + } + + vf->ratio_control |= (0x3FF << DISP_RATIO_ASPECT_RATIO_BIT); + vf->sar_width = vf->width; + vf->sar_height = vf->height; + kfifo_put(&hw->display_q, (const struct vframe_s *)vf); + ATRACE_COUNTER(MODULE_NAME, vf->pts); hw->vf_pre_count++; + vdec->vdec_fps_detec(vdec->id); vf_notify_receiver(vdec->vf_provider_name, VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); } @@ -2106,6 +2682,42 @@ int prepare_display_buf(struct vdec_s *vdec, struct FrameStore *frame) return 0; } +int notify_v4l_eos(struct vdec_s *vdec) +{ + struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)vdec->private; + struct aml_vcodec_ctx *ctx = (struct aml_vcodec_ctx *)(hw->v4l2_ctx); + struct vframe_s *vf = NULL; + struct vdec_fb *fb = NULL; + + if (hw->is_used_v4l && hw->eos) { + if (kfifo_get(&hw->newframe_q, &vf) == 0 || vf == NULL) { + dpb_print(DECODE_ID(hw), PRINT_FLAG_ERROR, + "%s fatal error, no available buffer slot.\n", + __func__); + return -1; + } + + if (v4l_get_fb(hw->v4l2_ctx, &fb)) { + pr_err("[%d] get fb fail.\n", ctx->id); + return -1; + } + + vf->timestamp = ULONG_MAX; + vf->v4l_mem_handle = (unsigned long)fb; + vf->flag = VFRAME_FLAG_EMPTY_FRAME_V4L; + + kfifo_put(&hw->display_q, (const struct vframe_s *)vf); + + ATRACE_COUNTER(MODULE_NAME, vf->pts); + vf_notify_receiver(vdec->vf_provider_name, + VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); + + pr_info("[%d] H264 EOS notify.\n", ctx->id); + } + + return 0; +} + /****************** * Hardware config */ @@ -2421,6 +3033,7 @@ int config_decode_buf(struct vdec_h264_hw_s *hw, struct StorablePicture *pic) struct Slice *pSlice = &(p_H264_Dpb->mSlice); unsigned int colocate_adr_offset; unsigned int val; + #ifdef ONE_COLOCATE_BUF_PER_DECODE_BUF int colocate_buf_index; #endif @@ -2471,12 +3084,23 @@ int config_decode_buf(struct vdec_h264_hw_s *hw, struct StorablePicture *pic) canvas_pos); print_pic_info(DECODE_ID(hw), "cur", pic, pSlice->slice_type); +#ifdef VDEC_DW + if (IS_VDEC_DW(hw) && pic->mb_aff_frame_flag) + WRITE_VREG(MDEC_DOUBLEW_CFG0, + ( READ_VREG(MDEC_DOUBLEW_CFG0) & (~(1 << 30)))); +#endif WRITE_VREG(CURR_CANVAS_CTRL, canvas_pos << 24); + canvas_adr = READ_VREG(CURR_CANVAS_CTRL) & 0xffffff; + if (!hw->mmu_enable) { - canvas_adr = READ_VREG(CURR_CANVAS_CTRL) & 0xffffff; WRITE_VREG(REC_CANVAS_ADDR, canvas_adr); WRITE_VREG(DBKR_CANVAS_ADDR, canvas_adr); WRITE_VREG(DBKW_CANVAS_ADDR, canvas_adr); +#ifdef VDEC_DW + WRITE_VREG(MDEC_DOUBLEW_CFG1, + (hw->buffer_spec[canvas_pos].vdec_dw_y_canvas_index + | (hw->buffer_spec[canvas_pos].vdec_dw_u_canvas_index << 8))); +#endif } else hevc_sao_set_pic_buffer(hw, pic); @@ -2545,14 +3169,14 @@ int config_decode_buf(struct vdec_h264_hw_s *hw, struct StorablePicture *pic) /* bit[6:5] - frame/field info, * 01 - top, 10 - bottom, 11 - frame */ -#ifdef ERROR_CHECK + #ifdef ERROR_CHECK if (ref == NULL) { hw->data_flag |= ERROR_FLAG; pic->data_flag |= ERROR_FLAG; dpb_print(DECODE_ID(hw), PRINT_FLAG_ERRORFLAG_DBG, " ref list0 NULL\n"); return -1; } - if (ref->data_flag & ERROR_FLAG) { + if ((ref->data_flag & ERROR_FLAG) && ref_frame_mark_flag[DECODE_ID(hw)]) { hw->data_flag |= ERROR_FLAG; pic->data_flag |= ERROR_FLAG; dpb_print(DECODE_ID(hw), PRINT_FLAG_ERRORFLAG_DBG, " ref error mark1 \n"); @@ -2568,6 +3192,7 @@ int config_decode_buf(struct vdec_h264_hw_s *hw, struct StorablePicture *pic) cfg = 0x2; else /* FRAME */ cfg = 0x3; + one_ref_cfg = (canvas_pos & 0x1f) | (cfg << 5); ref_reg_val <<= 8; ref_reg_val |= one_ref_cfg; @@ -2613,14 +3238,15 @@ int config_decode_buf(struct vdec_h264_hw_s *hw, struct StorablePicture *pic) /* bit[6:5] - frame/field info, * 01 - top, 10 - bottom, 11 - frame */ -#ifdef ERROR_CHECK + + #ifdef ERROR_CHECK if (ref == NULL) { hw->data_flag |= ERROR_FLAG; pic->data_flag |= ERROR_FLAG; dpb_print(DECODE_ID(hw), PRINT_FLAG_ERRORFLAG_DBG, " ref error list1 NULL\n"); return -2; } - if (ref->data_flag & ERROR_FLAG) { + if ((ref->data_flag & ERROR_FLAG) && (ref_frame_mark_flag[DECODE_ID(hw)])) { pic->data_flag |= ERROR_FLAG; hw->data_flag |= ERROR_FLAG; dpb_print(DECODE_ID(hw), PRINT_FLAG_ERRORFLAG_DBG, " ref error mark2\n"); @@ -3070,6 +3696,7 @@ static void vh264_vf_put(struct vframe_s *vf, void *op_arg) struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)vdec->private; int buf_spec_num; int frame_index; + if (vf == (&hw->vframe_dummy)) return; if (vf->index == -1) { @@ -3174,6 +3801,7 @@ static int vh264_event_cb(int type, void *data, void *op_arg) static void set_frame_info(struct vdec_h264_hw_s *hw, struct vframe_s *vf, u32 index) { + struct canvas_config_s *p_canvas_config; int force_rate = input_frame_based(hw_to_vdec(hw)) ? force_rate_framebase : force_rate_streambase; dpb_print(DECODE_ID(hw), PRINT_FLAG_DPB_DETAIL, @@ -3201,16 +3829,427 @@ static void set_frame_info(struct vdec_h264_hw_s *hw, struct vframe_s *vf, #else vf->plane_num = 3; #endif - vf->canvas0_config[0] = hw->buffer_spec[index].canvas_config[0]; - vf->canvas0_config[1] = hw->buffer_spec[index].canvas_config[1]; + + if (IS_VDEC_DW(hw)) { + vf->width = (hw->frame_width /2); + if (IS_VDEC_DW(hw) == 2) + vf->height = (hw->frame_height /2); + p_canvas_config = &hw->buffer_spec[index].vdec_dw_canvas_config[0]; + } else + p_canvas_config = &hw->buffer_spec[index].canvas_config[0]; + + vf->canvas0_config[0] = p_canvas_config[0]; + vf->canvas0_config[1] = p_canvas_config[1]; #ifndef NV21 - vf->canvas0_config[2] = hw->buffer_spec[index].canvas_config[2]; + vf->canvas0_config[2] = p_canvas_config[2]; #endif - vf->canvas1_config[0] = hw->buffer_spec[index].canvas_config[0]; - vf->canvas1_config[1] = hw->buffer_spec[index].canvas_config[1]; + vf->canvas1_config[0] = p_canvas_config[0]; + vf->canvas1_config[1] = p_canvas_config[1]; #ifndef NV21 - vf->canvas1_config[2] = hw->buffer_spec[index].canvas_config[2]; + vf->canvas1_config[2] = p_canvas_config[2]; #endif + /* signal_type */ + if (hw->video_signal_from_vui & VIDEO_SIGNAL_TYPE_AVAILABLE_MASK) + vf->signal_type = hw->video_signal_from_vui; + else + vf->signal_type = 0; + +} + +static void get_picture_qos_info(struct StorablePicture *picture) +{ + if (get_cpu_major_id() < AM_MESON_CPU_MAJOR_ID_G12A) { + unsigned char a[3]; + unsigned char i, j, t; + unsigned long data; + + get_random_bytes(&data, sizeof(unsigned long)); + if (picture->slice_type == I_SLICE) + data = 0; + a[0] = data & 0xff; + a[1] = (data >> 8) & 0xff; + a[2] = (data >> 16) & 0xff; + + for (i = 0; i < 3; i++) + for (j = i+1; j < 3; j++) { + if (a[j] < a[i]) { + t = a[j]; + a[j] = a[i]; + a[i] = t; + } else if (a[j] == a[i]) { + a[i]++; + t = a[j]; + a[j] = a[i]; + a[i] = t; + } + } + picture->max_mv = a[2]; + picture->avg_mv = a[1]; + picture->min_mv = a[0]; + /* + pr_info("mv data %x a[0]= %x a[1]= %x a[2]= %x\n", + data, a[0], a[1], a[2]); + */ + + get_random_bytes(&data, sizeof(unsigned long)); + a[0] = data & 0x1f; + a[1] = (data >> 8) & 0x3f; + a[2] = (data >> 16) & 0x7f; + + for (i = 0; i < 3; i++) + for (j = i+1; j < 3; j++) { + if (a[j] < a[i]) { + t = a[j]; + a[j] = a[i]; + a[i] = t; + } else if (a[j] == a[i]) { + a[i]++; + t = a[j]; + a[j] = a[i]; + a[i] = t; + } + } + picture->max_qp = a[2]; + picture->avg_qp = a[1]; + picture->min_qp = a[0]; + /* + pr_info("qp data %x a[0]= %x a[1]= %x a[2]= %x\n", + data, a[0], a[1], a[2]); + */ + + get_random_bytes(&data, sizeof(unsigned long)); + a[0] = data & 0x1f; + a[1] = (data >> 8) & 0x3f; + a[2] = (data >> 16) & 0x7f; + + for (i = 0; i < 3; i++) + for (j = i+1; j < 3; j++) { + if (a[j] < a[i]) { + t = a[j]; + a[j] = a[i]; + a[i] = t; + } else if (a[j] == a[i]) { + a[i]++; + t = a[j]; + a[j] = a[i]; + a[i] = t; + } + } + picture->max_skip = a[2]; + picture->avg_skip = a[1]; + picture->min_skip = a[0]; + + + /* + pr_info("skip data %x a[0]= %x a[1]= %x a[2]= %x\n", + data,a[0], a[1], a[2]); + */ + } else { + uint32_t blk88_y_count; + uint32_t blk88_c_count; + uint32_t blk22_mv_count; + uint32_t rdata32; + int32_t mv_hi; + int32_t mv_lo; + uint32_t rdata32_l; + uint32_t mvx_L0_hi; + uint32_t mvy_L0_hi; + uint32_t mvx_L1_hi; + uint32_t mvy_L1_hi; + int64_t value; + uint64_t temp_value; +/* +#define DEBUG_QOS +*/ +#ifdef DEBUG_QOS + int pic_number = picture->poc; +#endif + + picture->max_mv = 0; + picture->avg_mv = 0; + picture->min_mv = 0; + + picture->max_skip = 0; + picture->avg_skip = 0; + picture->min_skip = 0; + + picture->max_qp = 0; + picture->avg_qp = 0; + picture->min_qp = 0; + + + + + + /* set rd_idx to 0 */ + WRITE_VREG(VDEC_PIC_QUALITY_CTRL, 0); + blk88_y_count = READ_VREG(VDEC_PIC_QUALITY_DATA); + if (blk88_y_count == 0) { +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] NO Data yet.\n", + pic_number); +#endif + /* reset all counts */ + WRITE_VREG(VDEC_PIC_QUALITY_CTRL, (1<<8)); + return; + } + /* qp_y_sum */ + rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA); +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] Y QP AVG : %d (%d/%d)\n", + pic_number, rdata32/blk88_y_count, + rdata32, blk88_y_count); +#endif + picture->avg_qp = rdata32/blk88_y_count; + /* intra_y_count */ + rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA); +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] Y intra rate : %d%c (%d)\n", + pic_number, rdata32*100/blk88_y_count, + '%', rdata32); +#endif + /* skipped_y_count */ + rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA); +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] Y skipped rate : %d%c (%d)\n", + pic_number, rdata32*100/blk88_y_count, + '%', rdata32); +#endif + picture->avg_skip = rdata32*100/blk88_y_count; + /* coeff_non_zero_y_count */ + rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA); +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] Y ZERO_Coeff rate : %d%c (%d)\n", + pic_number, (100 - rdata32*100/(blk88_y_count*1)), + '%', rdata32); +#endif + /* blk66_c_count */ + blk88_c_count = READ_VREG(VDEC_PIC_QUALITY_DATA); + if (blk88_c_count == 0) { +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] NO Data yet.\n", + pic_number); +#endif + /* reset all counts */ + WRITE_VREG(VDEC_PIC_QUALITY_CTRL, (1<<8)); + return; + } + /* qp_c_sum */ + rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA); +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] C QP AVG : %d (%d/%d)\n", + pic_number, rdata32/blk88_c_count, + rdata32, blk88_c_count); +#endif + /* intra_c_count */ + rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA); +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] C intra rate : %d%c (%d)\n", + pic_number, rdata32*100/blk88_c_count, + '%', rdata32); +#endif + /* skipped_cu_c_count */ + rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA); +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] C skipped rate : %d%c (%d)\n", + pic_number, rdata32*100/blk88_c_count, + '%', rdata32); +#endif + /* coeff_non_zero_c_count */ + rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA); +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] C ZERO_Coeff rate : %d%c (%d)\n", + pic_number, (100 - rdata32*100/(blk88_c_count*1)), + '%', rdata32); +#endif + + /* 1'h0, qp_c_max[6:0], 1'h0, qp_c_min[6:0], + 1'h0, qp_y_max[6:0], 1'h0, qp_y_min[6:0] */ + rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA); +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] Y QP min : %d\n", + pic_number, (rdata32>>0)&0xff); +#endif + picture->min_qp = (rdata32>>0)&0xff; + +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] Y QP max : %d\n", + pic_number, (rdata32>>8)&0xff); +#endif + picture->max_qp = (rdata32>>8)&0xff; + +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] C QP min : %d\n", + pic_number, (rdata32>>16)&0xff); + pr_info(" [Picture %d Quality] C QP max : %d\n", + pic_number, (rdata32>>24)&0xff); +#endif + + /* blk22_mv_count */ + blk22_mv_count = READ_VREG(VDEC_PIC_QUALITY_DATA); + if (blk22_mv_count == 0) { +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] NO MV Data yet.\n", + pic_number); +#endif + /* reset all counts */ + WRITE_VREG(VDEC_PIC_QUALITY_CTRL, (1<<8)); + return; + } + /* mvy_L1_count[39:32], mvx_L1_count[39:32], + mvy_L0_count[39:32], mvx_L0_count[39:32] */ + rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA); + /* should all be 0x00 or 0xff */ +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] MV AVG High Bits: 0x%X\n", + pic_number, rdata32); +#endif + mvx_L0_hi = ((rdata32>>0)&0xff); + mvy_L0_hi = ((rdata32>>8)&0xff); + mvx_L1_hi = ((rdata32>>16)&0xff); + mvy_L1_hi = ((rdata32>>24)&0xff); + + /* mvx_L0_count[31:0] */ + rdata32_l = READ_VREG(VDEC_PIC_QUALITY_DATA); + temp_value = mvx_L0_hi; + temp_value = (temp_value << 32) | rdata32_l; + + if (mvx_L0_hi & 0x80) + value = 0xFFFFFFF000000000 | temp_value; + else + value = temp_value; + value = div_s64(value, blk22_mv_count); +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] MVX_L0 AVG : %d (%lld/%d)\n", + pic_number, (int)(value), + value, blk22_mv_count); +#endif + picture->avg_mv = value; + + /* mvy_L0_count[31:0] */ + rdata32_l = READ_VREG(VDEC_PIC_QUALITY_DATA); + temp_value = mvy_L0_hi; + temp_value = (temp_value << 32) | rdata32_l; + + if (mvy_L0_hi & 0x80) + value = 0xFFFFFFF000000000 | temp_value; + else + value = temp_value; +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] MVY_L0 AVG : %d (%lld/%d)\n", + pic_number, rdata32_l/blk22_mv_count, + value, blk22_mv_count); +#endif + + /* mvx_L1_count[31:0] */ + rdata32_l = READ_VREG(VDEC_PIC_QUALITY_DATA); + temp_value = mvx_L1_hi; + temp_value = (temp_value << 32) | rdata32_l; + if (mvx_L1_hi & 0x80) + value = 0xFFFFFFF000000000 | temp_value; + else + value = temp_value; +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] MVX_L1 AVG : %d (%lld/%d)\n", + pic_number, rdata32_l/blk22_mv_count, + value, blk22_mv_count); +#endif + + /* mvy_L1_count[31:0] */ + rdata32_l = READ_VREG(VDEC_PIC_QUALITY_DATA); + temp_value = mvy_L1_hi; + temp_value = (temp_value << 32) | rdata32_l; + if (mvy_L1_hi & 0x80) + value = 0xFFFFFFF000000000 | temp_value; + else + value = temp_value; +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] MVY_L1 AVG : %d (%lld/%d)\n", + pic_number, rdata32_l/blk22_mv_count, + value, blk22_mv_count); +#endif + + /* {mvx_L0_max, mvx_L0_min} // format : {sign, abs[14:0]} */ + rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA); + mv_hi = (rdata32>>16)&0xffff; + if (mv_hi & 0x8000) + mv_hi = 0x8000 - mv_hi; +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] MVX_L0 MAX : %d\n", + pic_number, mv_hi); +#endif + picture->max_mv = mv_hi; + + mv_lo = (rdata32>>0)&0xffff; + if (mv_lo & 0x8000) + mv_lo = 0x8000 - mv_lo; +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] MVX_L0 MIN : %d\n", + pic_number, mv_lo); +#endif + picture->min_mv = mv_lo; + + /* {mvy_L0_max, mvy_L0_min} */ + rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA); + mv_hi = (rdata32>>16)&0xffff; + if (mv_hi & 0x8000) + mv_hi = 0x8000 - mv_hi; +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] MVY_L0 MAX : %d\n", + pic_number, mv_hi); +#endif + + mv_lo = (rdata32>>0)&0xffff; + if (mv_lo & 0x8000) + mv_lo = 0x8000 - mv_lo; +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] MVY_L0 MIN : %d\n", + pic_number, mv_lo); +#endif + + /* {mvx_L1_max, mvx_L1_min} */ + rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA); + mv_hi = (rdata32>>16)&0xffff; + if (mv_hi & 0x8000) + mv_hi = 0x8000 - mv_hi; +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] MVX_L1 MAX : %d\n", + pic_number, mv_hi); +#endif + + mv_lo = (rdata32>>0)&0xffff; + if (mv_lo & 0x8000) + mv_lo = 0x8000 - mv_lo; +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] MVX_L1 MIN : %d\n", + pic_number, mv_lo); +#endif + + /* {mvy_L1_max, mvy_L1_min} */ + rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA); + mv_hi = (rdata32>>16)&0xffff; + if (mv_hi & 0x8000) + mv_hi = 0x8000 - mv_hi; +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] MVY_L1 MAX : %d\n", + pic_number, mv_hi); +#endif + mv_lo = (rdata32>>0)&0xffff; + if (mv_lo & 0x8000) + mv_lo = 0x8000 - mv_lo; +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] MVY_L1 MIN : %d\n", + pic_number, mv_lo); +#endif + + rdata32 = READ_VREG(VDEC_PIC_QUALITY_CTRL); +#ifdef DEBUG_QOS + pr_info(" [Picture %d Quality] After Read : VDEC_PIC_QUALITY_CTRL : 0x%x\n", + pic_number, rdata32); +#endif + /* reset all counts */ + WRITE_VREG(VDEC_PIC_QUALITY_CTRL, (1<<8)); + } } static int get_max_dec_frame_buf_size(int level_idc, @@ -3292,7 +4331,8 @@ static void vh264_config_canvs_for_mmu(struct vdec_h264_hw_s *hw) if (hw->decode_pic_count == 0) { for (j = 0; j < hw->dpb.mDPB.size; j++) { i = get_buf_spec_by_canvas_pos(hw, j); - config_decode_canvas_ex(hw, i); + if (i >= 0) + config_decode_canvas_ex(hw, i); } } mutex_unlock(&vmh264_mutex); @@ -3305,7 +4345,7 @@ static int vh264_set_params(struct vdec_h264_hw_s *hw, int i, j; int mb_width, mb_total; int max_reference_size, level_idc; - int mb_height; + int mb_height = 0; unsigned long flags; /*int mb_mv_byte;*/ struct vdec_s *vdec = hw_to_vdec(hw); @@ -3330,11 +4370,10 @@ static int vh264_set_params(struct vdec_h264_hw_s *hw, mb_total = (seq_info2 >> 8) & 0xffff; if (!mb_width && mb_total) /*for 4k2k*/ mb_width = 256; - mb_height = mb_total/mb_width; - if (mb_width > 0x110 || - mb_height > 0xa0 || - mb_width <= 0 || - mb_height <= 0) { + if (mb_width) + mb_height = mb_total/mb_width; + if (mb_width <= 0 || mb_height <= 0 || + is_oversize(mb_width << 4, mb_height << 4)) { dpb_print(DECODE_ID(hw), 0, "!!!wrong seq_info2 0x%x mb_width/mb_height (0x%x/0x%x) %x\r\n", seq_info2, @@ -3413,7 +4452,7 @@ static int vh264_set_params(struct vdec_h264_hw_s *hw, (unsigned int)((8 << chroma444) - 1)); } dpb_print(DECODE_ID(hw), 0, - "frame_mbs_only_flag %d, crop_bottom %d, frame_height %d, ", + "frame_mbs_only_flag %d, crop_bottom %d, frame_height %d,\n", frame_mbs_only_flag, crop_bottom, hw->frame_height); dpb_print(DECODE_ID(hw), 0, "mb_height %d,crop_right %d, frame_width %d, mb_width %d\n", @@ -3423,13 +4462,17 @@ static int vh264_set_params(struct vdec_h264_hw_s *hw, if (hw->frame_height == 1088) hw->frame_height = 1080; #endif - - mb_width = (mb_width+3) & 0xfffffffc; - mb_height = (mb_height+3) & 0xfffffffc; + if (!hw->mmu_enable) { + mb_width = (mb_width+3) & 0xfffffffc; + mb_height = (mb_height+3) & 0xfffffffc; + } mb_total = mb_width * mb_height; + hw->mb_width = mb_width; + hw->mb_height = mb_height; + hw->mb_total = mb_total; if (hw->mmu_enable) hevc_mcr_sao_global_hw_init(hw, - hw->frame_width, hw->frame_height); + (hw->mb_width << 4), (hw->mb_height << 4)); reg_val = param4; level_idc = reg_val & 0xff; @@ -3440,13 +4483,25 @@ static int vh264_set_params(struct vdec_h264_hw_s *hw, level_idc, max_reference_size); p_H264_Dpb->colocated_buf_size = mb_total * 96; - hw->mb_total = mb_total; - hw->mb_width = mb_width; - hw->mb_height = mb_height; - hw->dpb.reorder_pic_num = get_max_dec_frame_buf_size(level_idc, max_reference_size, mb_width, mb_height); + + dpb_print(DECODE_ID(hw), 0, + "restriction_flag=%d, max_dec_frame_buffering=%d, reorder_pic_num=%d\n", + hw->bitstream_restriction_flag, + hw->max_dec_frame_buffering, + hw->dpb.reorder_pic_num); + + if ((hw->bitstream_restriction_flag) && + (hw->max_dec_frame_buffering < + hw->dpb.reorder_pic_num)) { + hw->dpb.reorder_pic_num = hw->max_dec_frame_buffering; + dpb_print(DECODE_ID(hw), 0, + "set reorder_pic_num to %d\n", + hw->dpb.reorder_pic_num); + } + active_buffer_spec_num = hw->dpb.reorder_pic_num + used_reorder_dpb_size_margin; @@ -3477,10 +4532,19 @@ static int vh264_set_params(struct vdec_h264_hw_s *hw, if (!hw->mmu_enable) { config_buf_specs(vdec); i = get_buf_spec_by_canvas_pos(hw, 0); - if (alloc_one_buf_spec(hw, i) >= 0) - config_decode_canvas(hw, i); - else - ret = -1; + + if (hw->is_used_v4l) { + if (i != -1) { + ret = alloc_one_buf_spec_from_queue(hw, i); + if (!ret) + config_decode_canvas(hw, i); + } + } else { + if ((i != -1) && alloc_one_buf_spec(hw, i) >= 0) + config_decode_canvas(hw, i); + else + ret = -1; + } } else { if (hw->double_write_mode) { config_buf_specs_ex(vdec); @@ -3548,11 +4612,23 @@ static int vh264_set_params(struct vdec_h264_hw_s *hw, if (!hw->mmu_enable) { mutex_lock(&vmh264_mutex); if (ret >= 0 && hw->decode_pic_count == 0) { + int buf_cnt; /* h264_reconfig: alloc later*/ - for (j = 1; j < hw->dpb.mDPB.size; j++) { + buf_cnt = hw->dpb.mDPB.size; + + for (j = 1; j < buf_cnt; j++) { i = get_buf_spec_by_canvas_pos(hw, j); - if (alloc_one_buf_spec(hw, i) < 0) + + if (hw->is_used_v4l) { + if (alloc_one_buf_spec_from_queue + (hw, i) < 0) { + if (j++ != buf_cnt) + ret = -1; + break; + } + } else if (alloc_one_buf_spec(hw, i) < 0) break; + config_decode_canvas(hw, i); } } @@ -3578,6 +4654,19 @@ static void vui_config(struct vdec_h264_hw_s *hw) hw->time_scale = p_H264_Dpb->time_scale; hw->timing_info_present_flag = p_H264_Dpb->vui_status & 0x2; + hw->bitstream_restriction_flag = + p_H264_Dpb->bitstream_restriction_flag; + hw->num_reorder_frames = + p_H264_Dpb->num_reorder_frames; + hw->max_dec_frame_buffering = + p_H264_Dpb->max_dec_frame_buffering; + + dpb_print(DECODE_ID(hw), PRINT_FLAG_DPB_DETAIL, + "vui_config: pdb %d, %d, %d\n", + p_H264_Dpb->bitstream_restriction_flag, + p_H264_Dpb->num_reorder_frames, + p_H264_Dpb->max_dec_frame_buffering); + hw->fixed_frame_rate_flag = 0; if (hw->timing_info_present_flag) { hw->fixed_frame_rate_flag = @@ -3763,9 +4852,12 @@ static void vui_config(struct vdec_h264_hw_s *hw) static void bufmgr_recover(struct vdec_h264_hw_s *hw) { struct h264_dpb_stru *p_H264_Dpb = &hw->dpb; + bufmgr_h264_remove_unused_frame(p_H264_Dpb, 2); - if (error_proc_policy & 0x20) - hw->reset_bufmgr_flag = 1; + if (error_proc_policy & 0x20) { + if (!hw->is_used_v4l) + hw->reset_bufmgr_flag = 1; + } } void bufmgr_force_recover(struct h264_dpb_stru *p_H264_Dpb) @@ -3779,6 +4871,32 @@ void bufmgr_force_recover(struct h264_dpb_stru *p_H264_Dpb) hw->reset_bufmgr_flag = 1; } +#ifdef CONSTRAIN_MAX_BUF_NUM +static int get_vf_ref_only_buf_count(struct vdec_h264_hw_s *hw) +{ + int i; + int count = 0; + for (i = 0; i < BUFSPEC_POOL_SIZE; i++) { + if (is_buf_spec_in_disp_q(hw, i) && + hw->buffer_spec[i].vf_ref > 0) + count++; + } + return count; +} + +static int get_used_buf_count(struct vdec_h264_hw_s *hw) +{ + int i; + int count = 0; + for (i = 0; i < BUFSPEC_POOL_SIZE; i++) { + if (is_buf_spec_in_use(hw, i)) + count++; + } + return count; +} +#endif + + static bool is_buffer_available(struct vdec_s *vdec) { bool buffer_available = 1; @@ -3788,7 +4906,7 @@ static bool is_buffer_available(struct vdec_s *vdec) if ((kfifo_len(&hw->newframe_q) <= 0) || ((hw->config_bufmgr_done) && (!have_free_buf_spec(vdec))) || ((p_H264_Dpb->mDPB.init_done) && - (p_H264_Dpb->mDPB.used_size == p_H264_Dpb->mDPB.size) && + (p_H264_Dpb->mDPB.used_size >= (p_H264_Dpb->mDPB.size -1)) && (is_there_unused_frame_from_dpb(&p_H264_Dpb->mDPB) == 0))) { dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_DETAIL, "%s, empty, newq(%d), free_spec(%d), initdon(%d), used_size(%d/%d), unused_fr_dpb(%d)\n", @@ -3854,6 +4972,211 @@ static bool is_buffer_available(struct vdec_s *vdec) return buffer_available; } +#define AUX_TAG_SEI 0x2 + +#define SEI_BUFFERING_PERIOD 0 +#define SEI_PicTiming 1 +#define SEI_USER_DATA 4 +#define SEI_RECOVERY_POINT 6 + +/* + ************************************************************************* + * Function:Reads bits from the bitstream buffer + * Input: + byte buffer[] + containing sei message data bits + int totbitoffset + bit offset from start of partition + int bytecount + total bytes in bitstream + int numbits + number of bits to read + * Output: + int *info + * Return: + -1: failed + > 0: the count of bit read + * Attention: + ************************************************************************* + */ + +static int get_bits(unsigned char buffer[], + int totbitoffset, + int *info, + int bytecount, + int numbits) +{ + register int inf; + long byteoffset; + int bitoffset; + + int bitcounter = numbits; + + byteoffset = totbitoffset / 8; + bitoffset = 7 - (totbitoffset % 8); + + inf = 0; + while (numbits) { + inf <<= 1; + inf |= (buffer[byteoffset] & (0x01 << bitoffset)) >> bitoffset; + numbits--; + bitoffset--; + if (bitoffset < 0) { + byteoffset++; + bitoffset += 8; + if (byteoffset > bytecount) + return -1; + } + } + + *info = inf; + + + return bitcounter; +} + +static int parse_one_sei_record(struct vdec_h264_hw_s *hw, + u8 *sei_data_buf, + u8 *sei_data_buf_end) +{ + int payload_type; + int payload_size; + u8 *p_sei; + int temp; + int bit_offset; + int read_size; + struct h264_dpb_stru *p_H264_Dpb = &hw->dpb; + + p_sei = sei_data_buf; + read_size = 0; + payload_type = 0; + do { + if (p_sei >= sei_data_buf_end) + return read_size; + + payload_type += *p_sei; + read_size++; + } while (*p_sei++ == 255); + + + payload_size = 0; + do { + if (p_sei >= sei_data_buf_end) + return read_size; + + payload_size += *p_sei; + read_size++; + } while (*p_sei++ == 255); + + + if (p_sei + payload_size > sei_data_buf_end) { + dpb_print(DECODE_ID(hw), 0, + "%s: payload_type = %d, payload_size = %d is over\n", + __func__, payload_type, payload_size); + return read_size; + } + bit_offset = 0; + + if (payload_size <= 0) { + dpb_print(DECODE_ID(hw), 0, + "%s warning: this is a null sei message for payload_type = %d\n", + __func__, payload_type); + return read_size; + } + switch (payload_type) { + case SEI_BUFFERING_PERIOD: + break; + case SEI_PicTiming: + if (p_H264_Dpb->vui_status & 0xc) { + int cpb_removal_delay; + int dpb_output_delay; + u32 delay_len; + + delay_len = p_H264_Dpb->dpb_param.l.data[DELAY_LENGTH]; + cpb_removal_delay + = (delay_len & 0x1F) + 1; + dpb_output_delay + = ((delay_len >> 5) & 0x1F) + 1; + + get_bits(p_sei, bit_offset, + &temp, payload_size, + dpb_output_delay+cpb_removal_delay); + bit_offset += dpb_output_delay+cpb_removal_delay; + } + if (p_H264_Dpb->vui_status & 0x10) { + get_bits(p_sei, bit_offset, &temp, payload_size, 4); + bit_offset += 4; + p_H264_Dpb->dpb_param.l.data[PICTURE_STRUCT] = temp; + } + break; + case SEI_USER_DATA: + if (enable_itu_t35) { + int i; + int j; + int data_len; + u8 *user_data_buf; + + user_data_buf + = hw->sei_itu_data_buf + hw->sei_itu_data_len; + /* user data length should be align with 8 bytes, + if not, then padding with zero*/ + for (i = 0; i < payload_size; i += 8) { + for (j = 0; j < 8; j++) { + int index; + + index = i+7-j; + if (index >= payload_size) + user_data_buf[i+j] = 0; + else + user_data_buf[i+j] + = p_sei[i+7-j]; + } + } + + data_len = payload_size; + if (payload_size % 8) + data_len = ((payload_size + 8) >> 3) << 3; + + hw->sei_itu_data_len += data_len; + /* + dpb_print(DECODE_ID(hw), 0, + "%s: user data, and len = %d:\n", + __func__, hw->sei_itu_data_len); + */ + } + break; + case SEI_RECOVERY_POINT: + p_H264_Dpb->dpb_param.l.data[RECOVERY_POINT] = 1; + break; + } + + return read_size + payload_size; +} + +static void parse_sei_data(struct vdec_h264_hw_s *hw, + u8 *sei_data_buf, + int len) +{ + char *p_sei; + char *p_sei_end; + int parsed_size; + int read_size; + + + p_sei = sei_data_buf; + p_sei_end = p_sei + len; + parsed_size = 0; + while (parsed_size < len) { + read_size = parse_one_sei_record(hw, p_sei, p_sei_end); + p_sei += read_size; + parsed_size += read_size; + if (*p_sei == 0x80) { + p_sei++; + parsed_size++; + } + } +} + static void check_decoded_pic_error(struct vdec_h264_hw_s *hw) { struct h264_dpb_stru *p_H264_Dpb = &hw->dpb; @@ -3909,12 +5232,67 @@ static irqreturn_t vh264_isr_thread_fn(struct vdec_s *vdec, int irq) int ret; if (dec_dpb_status == H264_CONFIG_REQUEST) { +#if 1 + unsigned short *p = (unsigned short *)hw->lmem_addr; + dma_sync_single_for_cpu( + amports_get_dma_device(), + hw->lmem_addr_remap, + PAGE_SIZE, + DMA_FROM_DEVICE); + for (i = 0; i < (RPM_END-RPM_BEGIN); i += 4) { + int ii; + for (ii = 0; ii < 4; ii++) { + p_H264_Dpb->dpb_param.l.data[i+ii] = + p[i+3-ii]; + if (dpb_is_debug(DECODE_ID(hw), + RRINT_FLAG_RPM)) { + if (((i + ii) & 0xf) == 0) + dpb_print(DECODE_ID(hw), + 0, "%04x:", + i); + dpb_print_cont(DECODE_ID(hw), + 0, "%04x ", + p[i+3-ii]); + if (((i + ii + 1) & 0xf) == 0) + dpb_print_cont( + DECODE_ID(hw), + 0, "\r\n"); + } + } + } + + p_H264_Dpb->bitstream_restriction_flag = + (p_H264_Dpb->dpb_param.l.data[SPS_FLAGS2] >> 3) & 0x1; + p_H264_Dpb->num_reorder_frames = + p_H264_Dpb->dpb_param.l.data[NUM_REORDER_FRAMES]; + p_H264_Dpb->max_dec_frame_buffering = + p_H264_Dpb->dpb_param.l.data[MAX_BUFFER_FRAME]; + + dpb_print(DECODE_ID(hw), PRINT_FLAG_DPB_DETAIL, + "H264_CONFIG_REQUEST: pdb %d, %d, %d\n", + p_H264_Dpb->bitstream_restriction_flag, + p_H264_Dpb->num_reorder_frames, + p_H264_Dpb->max_dec_frame_buffering); + hw->bitstream_restriction_flag = + p_H264_Dpb->bitstream_restriction_flag; + hw->num_reorder_frames = + p_H264_Dpb->num_reorder_frames; + hw->max_dec_frame_buffering = + p_H264_Dpb->max_dec_frame_buffering; +#endif + WRITE_VREG(DPB_STATUS_REG, H264_ACTION_CONFIG_DONE); reset_process_time(hw); + hw->reg_iqidct_control = READ_VREG(IQIDCT_CONTROL); hw->dec_result = DEC_RESULT_CONFIG_PARAM; vdec_schedule_work(&hw->work); } else if (dec_dpb_status == H264_SLICE_HEAD_DONE) { + u16 data_hight; + u16 data_low; + u32 video_signal; + int slice_header_process_status = 0; + int I_flag; /*unsigned char is_idr;*/ unsigned short *p = (unsigned short *)hw->lmem_addr; reset_process_time(hw); @@ -3998,6 +5376,26 @@ static irqreturn_t vh264_isr_thread_fn(struct vdec_s *vdec, int irq) } } #endif + data_low = p_H264_Dpb->dpb_param.l.data[VIDEO_SIGNAL_LOW]; + data_hight = p_H264_Dpb->dpb_param.l.data[VIDEO_SIGNAL_HIGHT]; + + video_signal = (data_hight << 16) | data_low; + hw->video_signal_from_vui = + ((video_signal & 0xffff) << 8) | + ((video_signal & 0xff0000) >> 16) | + ((video_signal & 0x3f000000)); + + + /*dpb_print(DECODE_ID(hw), + 0, + "video_signal_from_vui:0x%x, " + "data_low:0x%x, data_hight:0x%x\n", + hw->video_signal_from_vui, + data_low, + data_hight);*/ + + parse_sei_data(hw, hw->sei_data_buf, hw->sei_data_len); + if (hw->config_bufmgr_done == 0) { hw->dec_result = DEC_RESULT_DONE; vdec_schedule_work(&hw->work); @@ -4053,6 +5451,13 @@ static irqreturn_t vh264_isr_thread_fn(struct vdec_s *vdec, int irq) val(p_H264_Dpb->dpb_param.dpb.frame_pic_order_cnt), val(p_H264_Dpb->dpb_param.dpb.top_field_pic_order_cnt), val(p_H264_Dpb->dpb_param.dpb.top_field_pic_order_cnt)); + I_flag = (p_H264_Dpb->dpb_param.l.data[SLICE_TYPE] == I_Slice) + ? I_FLAG : 0; + if ((hw->i_only & 0x2) && (!(I_flag & I_FLAG)) && + (p_H264_Dpb->mSlice.structure == FRAME)) { + hw->data_flag = NULL_FLAG; + goto pic_done_proc; + } slice_header_process_status = h264_slice_header_process(p_H264_Dpb); @@ -4064,33 +5469,17 @@ static irqreturn_t vh264_isr_thread_fn(struct vdec_s *vdec, int irq) if (p_H264_Dpb->mVideo.dec_picture) { int cfg_ret = 0; - if (hw->sei_itu_data_len) { - hw->sei_poc = - p_H264_Dpb->mVideo.dec_picture->poc; - schedule_work(&hw->user_data_work); - } if (slice_header_process_status == 1) { - /* for baseline , set fast_output mode */ - if ((p_H264_Dpb->mSPS.profile_idc == BASELINE) - || ((((unsigned long) - hw->vh264_amstream_dec_info.param) & 0x8) - && (!hw->i_only))) - p_H264_Dpb->fast_output_enable = 4; + if ((p_H264_Dpb->mSPS.profile_idc == BASELINE) || + (((unsigned long)(hw->vh264_amstream_dec_info + .param)) & 0x8)) { + p_H264_Dpb->fast_output_enable = + H264_OUTPUT_MODE_FAST; + } else p_H264_Dpb->fast_output_enable = fast_output_enable; - hw->data_flag = - (p_H264_Dpb-> - dpb_param.l.data[SLICE_TYPE] - == I_Slice) - ? I_FLAG : 0; - if ((hw->i_only & 0x2) && - (!(hw->data_flag & I_FLAG)) && - (p_H264_Dpb->mSlice.structure - == FRAME)) { - hw->data_flag = NULL_FLAG; - goto pic_done_proc; - } + hw->data_flag = I_flag; if ((p_H264_Dpb-> dpb_param.dpb.NAL_info_mmco & 0x1f) == 5) @@ -4126,6 +5515,7 @@ static irqreturn_t vh264_isr_thread_fn(struct vdec_s *vdec, int irq) p->data_flag |= MAYBE_ERROR_FLAG; } } + if (error_proc_policy & 0x400) { int ret = dpb_check_ref_list_error(p_H264_Dpb); if (ret != 0) { @@ -4134,6 +5524,7 @@ static irqreturn_t vh264_isr_thread_fn(struct vdec_s *vdec, int irq) ret, hw->decode_pic_count+1, hw->skip_frame_count); + flush_dpb(p_H264_Dpb); hw->data_flag |= ERROR_FLAG; p_H264_Dpb->mVideo.dec_picture->data_flag |= ERROR_FLAG; if ((error_proc_policy & 0x80) @@ -4193,7 +5584,23 @@ static irqreturn_t vh264_isr_thread_fn(struct vdec_s *vdec, int irq) } else if (dec_dpb_status == H264_PIC_DATA_DONE) { pic_done_proc: reset_process_time(hw); + + if (input_frame_based(vdec) && + frmbase_cont_bitlevel != 0 && + READ_VREG(VIFF_BIT_CNT) > + frmbase_cont_bitlevel) { + /*handle the case: multi pictures in one packet*/ + dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS, + "%s H264_PIC_DATA_DONE decode slice count %d, continue (bitcnt 0x%x)\n", + __func__, + hw->decode_pic_count, + READ_VREG(VIFF_BIT_CNT)); + hw->frmbase_cont_flag = 1; + } else + hw->frmbase_cont_flag = 0; + if (p_H264_Dpb->mVideo.dec_picture) { + get_picture_qos_info(p_H264_Dpb->mVideo.dec_picture); #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION DEL_EXIST(hw, p_H264_Dpb->mVideo.dec_picture) = 0; @@ -4207,11 +5614,14 @@ pic_done_proc: = 1; } #endif + mutex_lock(&hw->chunks_mutex); if (hw->chunk) { p_H264_Dpb->mVideo.dec_picture->pts = hw->chunk->pts; p_H264_Dpb->mVideo.dec_picture->pts64 = hw->chunk->pts64; + p_H264_Dpb->mVideo.dec_picture->timestamp = + hw->chunk->timestamp; #ifdef MH264_USERDATA_ENABLE vmh264_udc_fill_vpts(hw, p_H264_Dpb->mSlice.slice_type, @@ -4233,7 +5643,8 @@ pic_done_proc: u32 offset = pic->offset_delimiter_lo | (pic->offset_delimiter_hi << 16); if (pts_lookup_offset_us64(PTS_TYPE_VIDEO, - offset, &pic->pts, 0, &pic->pts64)) { + offset, &pic->pts, &pic->frame_size, + 0, &pic->pts64)) { pic->pts = 0; pic->pts64 = 0; #ifdef MH264_USERDATA_ENABLE @@ -4249,6 +5660,7 @@ pic_done_proc: #endif } } + mutex_unlock(&hw->chunks_mutex); check_decoded_pic_error(hw); #ifdef ERROR_HANDLE_TEST if ((hw->data_flag & ERROR_FLAG) @@ -4309,16 +5721,7 @@ pic_done_proc: } } } - if (input_frame_based(vdec) && - frmbase_cont_bitlevel != 0 && - READ_VREG(VIFF_BIT_CNT) > - frmbase_cont_bitlevel) { - /*handle the case: multi pictures in one packet*/ - dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS, - "%s H264_PIC_DATA_DONE decode slice count %d, continue (bitcnt 0x%x)\n", - __func__, - hw->decode_pic_count, - READ_VREG(VIFF_BIT_CNT)); + if (hw->frmbase_cont_flag) { /*do not DEC_RESULT_GET_DATA*/ hw->get_data_count = 0x7fffffff; WRITE_VREG(DPB_STATUS_REG, H264_ACTION_SEARCH_HEAD); @@ -4357,6 +5760,8 @@ pic_done_proc: #endif if (!hw->wait_for_udr_send) { hw->dec_result = DEC_RESULT_DONE; + dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS, + "%s wait_for_udr_send\n", __func__); vdec_schedule_work(&hw->work); } #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION @@ -4406,6 +5811,8 @@ pic_done_proc: hw->switch_dvlayer_flag = 0; hw->got_valid_nal = 1; #endif + dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS, + "%s H264_AUX_DATA_READY\n", __func__); hw->dec_result = DEC_RESULT_DONE; vdec_schedule_work(&hw->work); } else if (/*(dec_dpb_status == H264_DATA_REQUEST) ||*/ @@ -4414,8 +5821,8 @@ pic_done_proc: (dec_dpb_status == H264_DECODE_TIMEOUT)) { empty_proc: reset_process_time(hw); - - release_cur_decoding_buf(hw); + if (!hw->frmbase_cont_flag) + release_cur_decoding_buf(hw); if (input_frame_based(vdec) || (READ_VREG(VLD_MEM_VIFIFO_LEVEL) > 0x200)) { @@ -4446,8 +5853,8 @@ empty_proc: hw->decode_timeout_num++; else if (dec_dpb_status == H264_DECODE_BUFEMPTY) hw->decode_dataempty_num++; - - hw->data_flag |= ERROR_FLAG; + if (!hw->frmbase_cont_flag) + hw->data_flag |= ERROR_FLAG; vdec_schedule_work(&hw->work); } else { @@ -4466,6 +5873,7 @@ send_again: "%s H264_DATA_REQUEST (%d)\n", __func__, hw->get_data_count); hw->dec_result = DEC_RESULT_GET_DATA; + hw->reg_iqidct_control = READ_VREG(IQIDCT_CONTROL); hw->get_data_start_time = jiffies; hw->get_data_count++; if (hw->get_data_count >= frame_max_data_packet) @@ -4483,47 +5891,72 @@ send_again: hw->dec_result = DEC_RESULT_DONE; vdec_schedule_work(&hw->work); return IRQ_HANDLED; - } - - if (READ_VREG(AV_SCRATCH_G) == 1) { - hw->sei_itu_data_len = + } else if (dec_dpb_status == H264_SEI_DATA_READY) { + int aux_data_len; + aux_data_len = (READ_VREG(H264_AUX_DATA_SIZE) >> 16) << 4; - if (hw->sei_itu_data_len > SEI_ITU_DATA_SIZE * 2) { + + if (aux_data_len > SEI_DATA_SIZE) { dpb_print(DECODE_ID(hw), PRINT_FLAG_ERROR, - "itu data size more than 4K: %d, discarded it\n", + "sei data size more than 4K: %d, discarded it\n", hw->sei_itu_data_len); hw->sei_itu_data_len = 0; } - if (hw->sei_itu_data_len != 0) { + if (aux_data_len != 0) { u8 *trans_data_buf; u8 *sei_data_buf; - u32 temp; - u32 *pswap_data; + u8 swap_byte; dma_sync_single_for_cpu( - amports_get_dma_device(), - hw->aux_phy_addr, - hw->prefix_aux_size + hw->suffix_aux_size, - DMA_FROM_DEVICE); + amports_get_dma_device(), + hw->aux_phy_addr, + hw->prefix_aux_size + hw->suffix_aux_size, + DMA_FROM_DEVICE); #if 0 dump_aux_buf(hw); #endif - trans_data_buf = (u8 *)hw->aux_addr; - sei_data_buf = (u8 *)hw->sei_itu_data_buf; - for (i = 0; i < hw->sei_itu_data_len/2; i++) - sei_data_buf[i] = trans_data_buf[i*2]; - hw->sei_itu_data_len = hw->sei_itu_data_len / 2; - pswap_data = (u32 *)hw->sei_itu_data_buf; - for (i = 0; i < hw->sei_itu_data_len/4; i = i+2) { - temp = pswap_data[i]; - pswap_data[i] = pswap_data[i+1]; - pswap_data[i+1] = temp; + if (trans_data_buf[7] == AUX_TAG_SEI) { + int left_len; + + sei_data_buf = (u8 *)hw->sei_data_buf + + hw->sei_data_len; + left_len = SEI_DATA_SIZE - hw->sei_data_len; + if (aux_data_len/2 <= left_len) { + for (i = 0; i < aux_data_len/2; i++) + sei_data_buf[i] + = trans_data_buf[i*2]; + + aux_data_len = aux_data_len / 2; + for (i = 0; i < aux_data_len; i = i+4) { + swap_byte = sei_data_buf[i]; + sei_data_buf[i] + = sei_data_buf[i+3]; + sei_data_buf[i+3] = swap_byte; + + swap_byte = sei_data_buf[i+1]; + sei_data_buf[i+1] + = sei_data_buf[i+2]; + sei_data_buf[i+2] = swap_byte; + } + + for (i = aux_data_len-1; i >= 0; i--) + if (sei_data_buf[i] != 0) + break; + + hw->sei_data_len += i+1; + } else + dpb_print(DECODE_ID(hw), + PRINT_FLAG_ERROR, + "sei data size %d and more than left space: %d, discarded it\n", + hw->sei_itu_data_len, + left_len); } } - WRITE_VREG(AV_SCRATCH_G, 0); + WRITE_VREG(DPB_STATUS_REG, H264_SEI_DATA_DONE); + return IRQ_HANDLED; } @@ -4600,11 +6033,9 @@ static irqreturn_t vh264_isr(struct vdec_s *vdec, int irq) WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1); - if (!hw) { - dpb_print(DECODE_ID(hw), PRINT_FLAG_ERROR, - "decoder is not running\n"); + if (!hw) return IRQ_HANDLED; - } + if (hw->eos) return IRQ_HANDLED; @@ -4684,12 +6115,14 @@ static void vmh264_dump_state(struct vdec_s *vdec) dpb_print(DECODE_ID(hw), 0, "====== %s\n", __func__); dpb_print(DECODE_ID(hw), 0, - "width/height (%d/%d), reorder_pic_num %d dpb size(bufspec count) %d max_reference_size(collocate count) %d\n", + "width/height (%d/%d), reorder_pic_num %d dpb size(bufspec count) %d max_reference_size(collocate count) %d i_only %d send_err %d\n", hw->frame_width, hw->frame_height, hw->dpb.reorder_pic_num, hw->dpb.mDPB.size, - hw->max_reference_size + hw->max_reference_size, + hw->i_only, + hw->send_error_frame_flag ); dpb_print(DECODE_ID(hw), 0, @@ -4718,7 +6151,7 @@ static void vmh264_dump_state(struct vdec_s *vdec) } dpb_print(DECODE_ID(hw), 0, - "%s, newq(%d/%d), dispq(%d/%d) vf prepare/get/put (%d/%d/%d), free_spec(%d), initdon(%d), used_size(%d/%d), unused_fr_dpb(%d)\n", + "%s, newq(%d/%d), dispq(%d/%d) vf prepare/get/put (%d/%d/%d), free_spec(%d), initdon(%d), used_size(%d/%d), unused_fr_dpb(%d) fast_output_enable %x\n", __func__, kfifo_len(&hw->newframe_q), VF_POOL_SIZE, @@ -4730,7 +6163,8 @@ static void vmh264_dump_state(struct vdec_s *vdec) have_free_buf_spec(vdec), p_H264_Dpb->mDPB.init_done, p_H264_Dpb->mDPB.used_size, p_H264_Dpb->mDPB.size, - is_there_unused_frame_from_dpb(&p_H264_Dpb->mDPB) + is_there_unused_frame_from_dpb(&p_H264_Dpb->mDPB), + p_H264_Dpb->fast_output_enable ); dump_dpb(&p_H264_Dpb->mDPB, 1); @@ -4778,9 +6212,15 @@ static void vmh264_dump_state(struct vdec_s *vdec) int jj; if (hw->chunk && hw->chunk->block && hw->chunk->size > 0) { - u8 *data = - ((u8 *)hw->chunk->block->start_virt) + - hw->chunk->offset; + u8 *data = NULL; + + if (!hw->chunk->block->is_mapped) + data = codec_mm_vmap(hw->chunk->block->start + + hw->chunk->offset, hw->chunk->size); + else + data = ((u8 *)hw->chunk->block->start_virt) + + hw->chunk->offset; + dpb_print(DECODE_ID(hw), 0, "frame data size 0x%x\n", hw->chunk->size); @@ -4797,6 +6237,9 @@ static void vmh264_dump_state(struct vdec_s *vdec) PRINT_FRAMEBASE_DATA, "\n"); } + + if (!hw->chunk->block->is_mapped) + codec_mm_unmap_phyaddr(data); } } } @@ -4891,7 +6334,12 @@ static void check_timer_func(unsigned long arg) static int dec_status(struct vdec_s *vdec, struct vdec_info *vstatus) { + u32 ar; struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)vdec->private; + + if (!hw) + return -1; + vstatus->frame_width = hw->frame_width; vstatus->frame_height = hw->frame_height; if (hw->frame_dur != 0) @@ -4900,6 +6348,12 @@ static int dec_status(struct vdec_s *vdec, struct vdec_info *vstatus) vstatus->frame_rate = -1; vstatus->error_count = 0; vstatus->status = hw->stat; + ar = min_t(u32, + hw->h264_ar, + DISP_RATIO_ASPECT_RATIO_MAX); + vstatus->ratio_control = + ar << DISP_RATIO_ASPECT_RATIO_BIT; + snprintf(vstatus->vdec_name, sizeof(vstatus->vdec_name), "%s-%02d", DRIVER_NAME, hw->id); @@ -4972,13 +6426,19 @@ static int vh264_hw_ctx_restore(struct vdec_h264_hw_s *hw) SET_VREG_MASK(MDEC_PIC_DC_CTRL, 1<<17); #endif + /* cbcr_merge_swap_en */ + if (hw->is_used_v4l) + SET_VREG_MASK(MDEC_PIC_DC_CTRL, 1 << 16); + SET_VREG_MASK(MDEC_PIC_DC_CTRL, 0xbf << 24); CLEAR_VREG_MASK(MDEC_PIC_DC_CTRL, 0xbf << 24); CLEAR_VREG_MASK(MDEC_PIC_DC_CTRL, 1 << 31); if (hw->mmu_enable) { SET_VREG_MASK(MDEC_PIC_DC_MUX_CTRL, 1<<31); - WRITE_VREG(MDEC_EXTIF_CFG1, 0x80000000); + /* sw reset to extif hardware */ + SET_VREG_MASK(MDEC_EXTIF_CFG1, 1<<30); + CLEAR_VREG_MASK(MDEC_EXTIF_CFG1, 1<<30); } else { CLEAR_VREG_MASK(MDEC_PIC_DC_MUX_CTRL, 1 << 31); WRITE_VREG(MDEC_EXTIF_CFG1, 0); @@ -4989,6 +6449,16 @@ static int vh264_hw_ctx_restore(struct vdec_h264_hw_s *hw) /* pr_info("vh264 meson8 prot init\n"); */ WRITE_VREG(MDEC_PIC_DC_THRESH, 0x404038aa); #endif + +#ifdef VDEC_DW + if (IS_VDEC_DW(hw)) { + u32 data = ((1 << 30) |(1 << 0) |(1 << 8)); + + if (IS_VDEC_DW(hw) == 2) + data |= (1 << 9); + WRITE_VREG(MDEC_DOUBLEW_CFG0, data); /* Double Write Enable*/ + } +#endif if (hw->dpb.mDPB.size > 0) { WRITE_VREG(AV_SCRATCH_7, (hw->max_reference_size << 24) | (hw->dpb.mDPB.size << 16) | @@ -5068,6 +6538,7 @@ static void vh264_local_init(struct vdec_h264_hw_s *hw) { int i; hw->init_flag = 0; + hw->first_sc_checked= 0; hw->eos = 0; hw->valve_count = 0; hw->config_bufmgr_done = 0; @@ -5084,7 +6555,7 @@ static void vh264_local_init(struct vdec_h264_hw_s *hw) hw->reg_rv_ai_mb_count = 0; hw->vld_dec_control = 0; hw->decode_timeout_count = 0; - + hw->no_mem_count = 0; hw->vh264_ratio = hw->vh264_amstream_dec_info.ratio; /* vh264_ratio = 0x100; */ @@ -5110,13 +6581,23 @@ static void vh264_local_init(struct vdec_h264_hw_s *hw) hw->frame_dur = 96000/30; } - pr_info - ("H264 sysinfo: %dx%d duration=%d, pts_outside=%d\n", - hw->frame_width, hw->frame_height, hw->frame_dur, hw->pts_outside); - pr_debug("sync_outside=%d, use_idr_framerate=%d\n", - hw->sync_outside, hw->use_idr_framerate); + hw->unstable_pts = (((unsigned long) hw->vh264_amstream_dec_info.param & 0x40) >> 6); + + hw->is_used_v4l = (((unsigned long) + hw->vh264_amstream_dec_info.param & 0x80) >> 7); + + if (hw->is_used_v4l) + mem_map_mode = CANVAS_BLKMODE_LINEAR; + + pr_info("H264 sysinfo: %dx%d duration=%d, pts_outside=%d\n", + hw->frame_width, hw->frame_height, hw->frame_dur, hw->pts_outside); + pr_debug("sync_outside=%d, use_idr_framerate=%d, is_used_v4l: %d\n", + hw->sync_outside, hw->use_idr_framerate, hw->is_used_v4l); + if (i_only_flag & 0x100) hw->i_only = i_only_flag & 0xff; + if (hw->i_only) + hw->dpb.first_insert_frame = FirstInsertFrm_SKIPDONE; if ((unsigned long) hw->vh264_amstream_dec_info.param & 0x08) @@ -5144,11 +6625,18 @@ static void vh264_local_init(struct vdec_h264_hw_s *hw) hw->vh264_stream_switching_state = SWITCHING_STATE_OFF; hw->hevc_cur_buf_idx = 0xffff; + init_waitqueue_head(&hw->wait_q); + return; } static s32 vh264_init(struct vdec_h264_hw_s *hw) { + int size = -1; + int fw_size = 0x1000 * 16; + int fw_mmu_size = 0x1000 * 16; + struct firmware_s *fw = NULL, *fw_mmu = NULL; + /* int trickmode_fffb = 0; */ /* pr_info("\nvh264_init\n"); */ @@ -5165,10 +6653,10 @@ static s32 vh264_init(struct vdec_h264_hw_s *hw) hw->stat |= STAT_TIMER_ARM; hw->stat |= STAT_ISR_REG; + mutex_init(&hw->chunks_mutex); vh264_local_init(hw); INIT_WORK(&hw->work, vh264_work); INIT_WORK(&hw->notify_work, vh264_notify_work); - INIT_WORK(&hw->user_data_work, user_data_push_work); #ifdef MH264_USERDATA_ENABLE INIT_WORK(&hw->user_data_ready_work, user_data_ready_notify_work); #endif @@ -5190,11 +6678,38 @@ static s32 vh264_init(struct vdec_h264_hw_s *hw) return -ENOMEM; } } - if (!tee_enabled()) { - int ret = 0, size = -1; - int fw_size = 0x1000 * 16; - struct firmware_s *fw = NULL; + fw = vmalloc(sizeof(struct firmware_s) + fw_size); + if (IS_ERR_OR_NULL(fw)) + return -ENOMEM; + + size = get_firmware_data(VIDEO_DEC_H264_MULTI, fw->data); + if (size < 0) { + pr_err("get firmware fail.\n"); + vfree(fw); + return -1; + } + + fw->len = size; + hw->fw = fw; + + if (hw->mmu_enable) { + fw_mmu = vmalloc(sizeof(struct firmware_s) + fw_mmu_size); + if (IS_ERR_OR_NULL(fw_mmu)) + return -ENOMEM; + + size = get_firmware_data(VIDEO_DEC_H264_MULTI_MMU, fw_mmu->data); + if (size < 0) { + pr_err("get mmu fw fail.\n"); + vfree(fw_mmu); + return -1; + } + + fw_mmu->len = size; + hw->fw_mmu = fw_mmu; + } + + if (!tee_enabled()) { /* -- ucode loading (amrisc and swap code) */ hw->mc_cpu_addr = dma_alloc_coherent(amports_get_dma_device(), MC_TOTAL_SIZE, @@ -5212,23 +6727,6 @@ static s32 vh264_init(struct vdec_h264_hw_s *hw) (void *)hw->mc_dma_handle, hw->mc_cpu_addr); */ - - pr_debug("start load orignal firmware ...\n"); - - fw = vmalloc(sizeof(struct firmware_s) + fw_size); - if (IS_ERR_OR_NULL(fw)) - return -ENOMEM; - - size = get_firmware_data(VIDEO_DEC_H264_MULTI, fw->data); - if (size < 0) { - pr_err("get firmware fail.\n"); - vfree(fw); - return -1; - } - - fw->len = size; - hw->fw = fw; - /*ret = amvdec_loadmc_ex(VFORMAT_H264, NULL, buf);*/ /*header*/ @@ -5255,48 +6753,8 @@ static s32 vh264_init(struct vdec_h264_hw_s *hw) /*slice*/ memcpy((u8 *) hw->mc_cpu_addr + MC_OFFSET_MAIN + 0x3000, fw->data + 0x5000, 0x1000); - - if (hw->mmu_enable) { - int fw_mmu_size = 0x1000 * 16; - struct firmware_s *fw_mmu = NULL; - - pr_debug("start load mmu fw ...\n"); - - fw_mmu = vmalloc(sizeof(struct firmware_s) + fw_mmu_size); - if (IS_ERR_OR_NULL(fw_mmu)) - return -ENOMEM; - - size = get_firmware_data(VIDEO_DEC_H264_MULTI_MMU, - fw_mmu->data); - if (size < 0) { - pr_err("get mmu fw fail.\n"); - vfree(fw_mmu); - return -1; - } - - ret = amhevc_loadmc_ex(VFORMAT_HEVC, - NULL, fw_mmu->data); - - fw_mmu->len = size; - hw->fw_mmu = fw_mmu; - } - - if (ret < 0) { - dpb_print(DECODE_ID(hw), PRINT_FLAG_ERROR, - "264 load orignal firmware error.\n"); - amvdec_disable(); - if (hw->mmu_enable) - amhevc_disable(); - if (hw->mc_cpu_addr) { - dma_free_coherent(amports_get_dma_device(), - MC_TOTAL_SIZE, hw->mc_cpu_addr, - hw->mc_dma_handle); - hw->mc_cpu_addr = NULL; - } - return -EBUSY; - } - } + #if 1 /* #ifdef BUFFER_MGR_IN_C */ hw->lmem_addr = __get_free_page(GFP_KERNEL); if (!hw->lmem_addr) { @@ -5342,10 +6800,21 @@ static s32 vh264_init(struct vdec_h264_hw_s *hw) hw->aux_addr = NULL; return -1; } + hw->sei_data_buf = kmalloc(SEI_DATA_SIZE, GFP_KERNEL); + if (hw->sei_data_buf == NULL) { + pr_err("%s: failed to alloc sei itu data buffer\n", + __func__); + return -1; + } hw->sei_itu_data_buf = kmalloc(SEI_ITU_DATA_SIZE, GFP_KERNEL); if (hw->sei_itu_data_buf == NULL) { pr_err("%s: failed to alloc sei itu data buffer\n", __func__); + kfree(hw->aux_addr); + hw->aux_addr = NULL; + kfree(hw->sei_data_buf); + hw->sei_data_buf = NULL; + return -1; } @@ -5355,6 +6824,13 @@ static s32 vh264_init(struct vdec_h264_hw_s *hw) if (!hw->sei_user_data_buffer) { pr_info("%s: Can not allocate sei_data_buffer\n", __func__); + kfree(hw->aux_addr); + hw->aux_addr = NULL; + kfree(hw->sei_data_buf); + hw->sei_data_buf = NULL; + kfree(hw->sei_itu_data_buf); + hw->sei_itu_data_buf = NULL; + return -1; } hw->sei_user_data_wp = 0; @@ -5376,10 +6852,11 @@ static int vh264_stop(struct vdec_h264_hw_s *hw) amvdec_stop(); hw->stat &= ~STAT_VDEC_RUN; } - +#ifdef VDEC_DW + WRITE_VREG(MDEC_DOUBLEW_CFG0, 0); +#endif cancel_work_sync(&hw->work); cancel_work_sync(&hw->notify_work); - cancel_work_sync(&hw->user_data_work); #ifdef MH264_USERDATA_ENABLE cancel_work_sync(&hw->user_data_ready_work); #endif @@ -5421,6 +6898,10 @@ static int vh264_stop(struct vdec_h264_hw_s *hw) kfree(hw->aux_addr); hw->aux_addr = NULL; } + if (hw->sei_data_buf != NULL) { + kfree(hw->sei_data_buf); + hw->sei_data_buf = NULL; + } if (hw->sei_itu_data_buf != NULL) { kfree(hw->sei_itu_data_buf); hw->sei_itu_data_buf = NULL; @@ -5445,6 +6926,25 @@ static int vh264_stop(struct vdec_h264_hw_s *hw) return 0; } +static void wait_vmh264_search_done(struct vdec_h264_hw_s *hw) +{ + u32 vld_rp = READ_VREG(VLD_MEM_VIFIFO_RP); + int count = 0; + do { + usleep_range(100, 500); + if (vld_rp == READ_VREG(VLD_MEM_VIFIFO_RP)) + break; + if (count > 2000) { + dpb_print(DECODE_ID(hw), + PRINT_FLAG_ERROR, "%s timeout count %d vld_rp 0x%x VLD_MEM_VIFIFO_RP 0x%x\n", + __func__, count, vld_rp, READ_VREG(VLD_MEM_VIFIFO_RP)); + break; + } else + vld_rp = READ_VREG(VLD_MEM_VIFIFO_RP); + count++; + } while (1); +} + static void vh264_notify_work(struct work_struct *work) { struct vdec_h264_hw_s *hw = container_of(work, @@ -5463,15 +6963,9 @@ static void vh264_notify_work(struct work_struct *work) #ifdef MH264_USERDATA_ENABLE static void vmh264_reset_udr_mgr(struct vdec_h264_hw_s *hw) { - int i; hw->wait_for_udr_send = 0; - - INIT_LIST_HEAD(&hw->free_uds_wait_nodes); - INIT_LIST_HEAD(&hw->frame_uds); - - for (i = 0; i < MAX_FREE_USERDATA_NODES; i++) - list_add_tail(&hw->free_nodes[i].list, - &hw->free_uds_wait_nodes); + hw->sei_itu_data_len = 0; + memset(&hw->ud_record, 0, sizeof(hw->ud_record)); } static void vmh264_crate_userdata_manager( @@ -5532,8 +7026,8 @@ static void print_data(unsigned char *pdata, rec_id, len, flag, duration, vpts, vpts_valid, poc_number); #endif - pr_info("%d len = %d, flag = %d, vpts = 0x%x, poc = %d\n", - rec_id, len, flag, vpts, poc); + pr_info("%d len = %d, flag = %d, vpts = 0x%x\n", + rec_id, len, flag, vpts); if (len == 96) { int i; @@ -5775,70 +7269,77 @@ static void vmh264_reset_user_data_buf(void) } #endif -static void vmh264_input_udc_waitqueue(struct vdec_h264_hw_s *hw, - struct userdata_meta_info_t meta_info, - int wp) -{ - struct mh264_ud_record_wait_node_t *node; - struct mh264_userdata_record_t *p_userdata_rec; - int data_length; - - node = list_entry( - hw->free_uds_wait_nodes.next, - struct mh264_ud_record_wait_node_t, - list); - - if (node) { - if (wp > hw->userdata_info.last_wp) - data_length = wp - hw->userdata_info.last_wp; - else - data_length = wp + hw->userdata_info.buf_len - - hw->userdata_info.last_wp; - - if (data_length & 0x7) - data_length = (((data_length + 8) >> 3) << 3); -#if 0 - pr_info("wakeup_push: ri:%d, wi:%d, data_len:%d, last_wp:%d, wp:%d, id = %d\n", - lg_p_mpeg12_userdata_info->read_index, - lg_p_mpeg12_userdata_info->write_index, - data_length, - lg_p_mpeg12_userdata_info->last_wp, - wp, - n_userdata_id); -#endif - p_userdata_rec = &node->ud_record; - p_userdata_rec->meta_info = meta_info; - p_userdata_rec->rec_start = hw->userdata_info.last_wp; - p_userdata_rec->rec_len = data_length; -#if 0 - dump_userdata_record(hw, p_userdata_rec); -#endif - list_move(&node->list, &hw->frame_uds); - } - hw->userdata_info.last_wp = wp; -} static void vmh264_udc_fill_vpts(struct vdec_h264_hw_s *hw, int frame_type, u32 vpts, u32 vpts_valid) { - struct mh264_ud_record_wait_node_t *node; - struct mh264_ud_record_wait_node_t *tmp; - struct mh264_userdata_record_t *pud_record; struct h264_dpb_stru *p_H264_Dpb = &hw->dpb; - if (!list_empty(&hw->frame_uds)) { - list_for_each_entry_safe(node, tmp, &hw->frame_uds, list) { - pud_record = &node->ud_record; - pud_record->meta_info.vpts = vpts; - pud_record->meta_info.vpts_valid = vpts_valid; - pud_record->meta_info.poc_number = - p_H264_Dpb->mVideo.dec_picture->poc; - } - hw->wait_for_udr_send = 1; - schedule_work(&hw->user_data_ready_work); + unsigned char *pdata; + u8 *pmax_sei_data_buffer; + u8 *sei_data_buf; + int i; + int wp; + int data_length; + struct mh264_userdata_record_t *p_userdata_rec; + + +#ifdef MH264_USERDATA_ENABLE + struct userdata_meta_info_t meta_info; + memset(&meta_info, 0, sizeof(meta_info)); +#endif + + if (hw->sei_itu_data_len <= 0) + return; + + pdata = (u8 *)hw->sei_user_data_buffer + hw->sei_user_data_wp; + pmax_sei_data_buffer = (u8 *)hw->sei_user_data_buffer + USER_DATA_SIZE; + sei_data_buf = (u8 *)hw->sei_itu_data_buf; + for (i = 0; i < hw->sei_itu_data_len; i++) { + *pdata++ = sei_data_buf[i]; + if (pdata >= pmax_sei_data_buffer) + pdata = (u8 *)hw->sei_user_data_buffer; } + + hw->sei_user_data_wp = (hw->sei_user_data_wp + + hw->sei_itu_data_len) % USER_DATA_SIZE; + hw->sei_itu_data_len = 0; + +#ifdef MH264_USERDATA_ENABLE + meta_info.duration = hw->frame_dur; + meta_info.flags |= (VFORMAT_H264 << 3); + + meta_info.vpts = vpts; + meta_info.vpts_valid = vpts_valid; + meta_info.poc_number = + p_H264_Dpb->mVideo.dec_picture->poc; + + + wp = hw->sei_user_data_wp; + + if (hw->sei_user_data_wp > hw->userdata_info.last_wp) + data_length = wp - hw->userdata_info.last_wp; + else + data_length = wp + hw->userdata_info.buf_len + - hw->userdata_info.last_wp; + + if (data_length & 0x7) + data_length = (((data_length + 8) >> 3) << 3); + + p_userdata_rec = &hw->ud_record; + p_userdata_rec->meta_info = meta_info; + p_userdata_rec->rec_start = hw->userdata_info.last_wp; + p_userdata_rec->rec_len = data_length; + hw->userdata_info.last_wp = wp; + + p_userdata_rec->meta_info.flags |= + p_H264_Dpb->mVideo.dec_picture->pic_struct << 12; + + hw->wait_for_udr_send = 1; + schedule_work(&hw->user_data_ready_work); +#endif } @@ -5847,30 +7348,30 @@ static void user_data_ready_notify_work(struct work_struct *work) struct vdec_h264_hw_s *hw = container_of(work, struct vdec_h264_hw_s, user_data_ready_work); - struct mh264_ud_record_wait_node_t *node; - struct mh264_ud_record_wait_node_t *tmp; - list_for_each_entry_safe(node, tmp, &hw->frame_uds, list) { - mutex_lock(&hw->userdata_mutex); + mutex_lock(&hw->userdata_mutex); - hw->userdata_info.records[hw->userdata_info.write_index] - = node->ud_record; - hw->userdata_info.write_index++; - if (hw->userdata_info.write_index >= USERDATA_FIFO_NUM) - hw->userdata_info.write_index = 0; + hw->userdata_info.records[hw->userdata_info.write_index] + = hw->ud_record; + hw->userdata_info.write_index++; + if (hw->userdata_info.write_index >= USERDATA_FIFO_NUM) + hw->userdata_info.write_index = 0; - mutex_unlock(&hw->userdata_mutex); + mutex_unlock(&hw->userdata_mutex); - list_move(&node->list, &hw->free_uds_wait_nodes); #ifdef DUMP_USERDATA_RECORD - dump_userdata_record(hw, &node->ud_record); + dump_userdata_record(hw, &hw->ud_record); #endif - vdec_wakeup_userdata_poll(hw_to_vdec(hw)); - } + vdec_wakeup_userdata_poll(hw_to_vdec(hw)); hw->wait_for_udr_send = 0; - hw->dec_result = DEC_RESULT_DONE; - vdec_schedule_work(&hw->work); + if (!hw->frmbase_cont_flag) { + hw->dec_result = DEC_RESULT_DONE; + dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS, + "%s\n", __func__); + + vdec_schedule_work(&hw->work); + } } static int vmh264_user_data_read(struct vdec_s *vdec, @@ -5888,7 +7389,8 @@ static int vmh264_user_data_read(struct vdec_s *vdec, hw = (struct vdec_h264_hw_s *)vdec->private; - pdest_buf = (void *)(puserdata_para->pbuf_addr); + pdest_buf = puserdata_para->pbuf_addr; + mutex_lock(&hw->userdata_mutex); /* @@ -6039,9 +7541,7 @@ static int vmh264_user_data_read(struct vdec_s *vdec, } } - res = (u32)copy_to_user((void *)&puserdata_para->meta_info, - (void *)&p_userdata_rec->meta_info, - sizeof(p_userdata_rec->meta_info)); + puserdata_para->meta_info = p_userdata_rec->meta_info; if (hw->userdata_info.read_index <= hw->userdata_info.write_index) puserdata_para->meta_info.records_in_que = @@ -6068,7 +7568,7 @@ static void vmh264_reset_userdata_fifo(struct vdec_s *vdec, int bInit) if (hw) { mutex_lock(&hw->userdata_mutex); - pr_info("vmpeg12_reset_userdata_fifo: bInit: %d, ri: %d, wi: %d\n", + pr_info("vmh264_reset_userdata_fifo: bInit: %d, ri: %d, wi: %d\n", bInit, hw->userdata_info.read_index, hw->userdata_info.write_index); @@ -6080,52 +7580,15 @@ static void vmh264_reset_userdata_fifo(struct vdec_s *vdec, int bInit) mutex_unlock(&hw->userdata_mutex); } } -#endif -static void user_data_push_work(struct work_struct *work) +static void vmh264_wakeup_userdata_poll(struct vdec_s *vdec) { - struct vdec_h264_hw_s *hw = container_of(work, - struct vdec_h264_hw_s, user_data_work); - - struct userdata_poc_info_t user_data_poc; - unsigned char *pdata; - u8 *pmax_sei_data_buffer; - u8 *sei_data_buf; - int i; -#ifdef MH264_USERDATA_ENABLE - struct userdata_meta_info_t meta_info; - memset(&meta_info, 0, sizeof(meta_info)); -#endif - - pdata = (u8 *)hw->sei_user_data_buffer + hw->sei_user_data_wp; - pmax_sei_data_buffer = (u8 *)hw->sei_user_data_buffer + USER_DATA_SIZE; - sei_data_buf = (u8 *)hw->sei_itu_data_buf; - for (i = 0; i < hw->sei_itu_data_len; i++) { - *pdata++ = sei_data_buf[i]; - if (pdata >= pmax_sei_data_buffer) - pdata = (u8 *)hw->sei_user_data_buffer; - } - - hw->sei_user_data_wp = (hw->sei_user_data_wp - + hw->sei_itu_data_len) % USER_DATA_SIZE; - user_data_poc.poc_number = hw->sei_poc; - - hw->sei_itu_data_len = 0; - -#ifdef MH264_USERDATA_ENABLE - meta_info.duration = hw->frame_dur; - meta_info.flags |= (VFORMAT_H264 << 3); - - - vmh264_input_udc_waitqueue(hw, meta_info, hw->sei_user_data_wp); - -#endif -/* - pr_info("sei_itu35_wp = %d, poc = %d\n", - hw->sei_user_data_wp, hw->sei_poc); -*/ + amstream_wakeup_userdata_poll(vdec); } +#endif + + static void vh264_work(struct work_struct *work) { struct vdec_h264_hw_s *hw = container_of(work, @@ -6178,7 +7641,10 @@ static void vh264_work(struct work_struct *work) READ_VREG(VLD_MEM_VIFIFO_LEVEL), READ_VREG(VLD_MEM_VIFIFO_WP), READ_VREG(VLD_MEM_VIFIFO_RP)); + mutex_lock(&hw->chunks_mutex); vdec_vframe_dirty(vdec, hw->chunk); + hw->chunk = NULL; + mutex_unlock(&hw->chunks_mutex); vdec_clean_input(vdec); } if ((hw->dec_result == DEC_RESULT_GET_DATA_RETRY) && @@ -6211,9 +7677,17 @@ static void vh264_work(struct work_struct *work) if (dpb_is_debug(DECODE_ID(hw), PRINT_FRAMEBASE_DATA)) { int jj; - u8 *data = - ((u8 *)hw->chunk->block->start_virt) + - hw->chunk->offset; + u8 *data = NULL; + + if (!hw->chunk->block->is_mapped) + data = codec_mm_vmap( + hw->chunk->block->start + + hw->chunk->offset, r); + else + data = ((u8 *) + hw->chunk->block->start_virt) + + hw->chunk->offset; + for (jj = 0; jj < r; jj++) { if ((jj & 0xf) == 0) dpb_print(DECODE_ID(hw), @@ -6227,6 +7701,9 @@ static void vh264_work(struct work_struct *work) PRINT_FRAMEBASE_DATA, "\n"); } + + if (!hw->chunk->block->is_mapped) + codec_mm_unmap_phyaddr(data); } WRITE_VREG(POWER_CTL_VLD, READ_VREG(POWER_CTL_VLD) | @@ -6271,6 +7748,13 @@ result_done: } decode_frame_count[DECODE_ID(hw)]++; amvdec_stop(); + if (!vdec_is_support_4k()) { + if (clk_adj_frame_count < VDEC_CLOCK_ADJUST_FRAME) { + clk_adj_frame_count++; + if (clk_adj_frame_count == VDEC_CLOCK_ADJUST_FRAME) + vdec_source_changed(VFORMAT_H264, 3840, 2160, 60); + } + } dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS, "%s dec_result %d %x %x %x\n", __func__, @@ -6278,7 +7762,10 @@ result_done: READ_VREG(VLD_MEM_VIFIFO_LEVEL), READ_VREG(VLD_MEM_VIFIFO_WP), READ_VREG(VLD_MEM_VIFIFO_RP)); + mutex_lock(&hw->chunks_mutex); vdec_vframe_dirty(hw_to_vdec(hw), hw->chunk); + hw->chunk = NULL; + mutex_unlock(&hw->chunks_mutex); } else if (hw->dec_result == DEC_RESULT_AGAIN) { /* stream base: stream buf empty or timeout @@ -6300,7 +7787,13 @@ result_done: amhevc_stop(); hw->eos = 1; flush_dpb(p_H264_Dpb); + if (hw->is_used_v4l) + notify_v4l_eos(hw_to_vdec(hw)); + mutex_lock(&hw->chunks_mutex); vdec_vframe_dirty(hw_to_vdec(hw), hw->chunk); + hw->chunk = NULL; + mutex_unlock(&hw->chunks_mutex); + vdec_clean_input(vdec); } else if (hw->dec_result == DEC_RESULT_FORCE_EXIT) { dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS, "%s: force exit\n", @@ -6318,8 +7811,8 @@ result_done: del_timer_sync(&hw->check_timer); hw->stat &= ~STAT_TIMER_ARM; + wait_vmh264_search_done(hw); /* mark itself has all HW resource released and input released */ - vdec_set_status(hw_to_vdec(hw), VDEC_STATUS_CONNECTED); #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION if (hw->switch_dvlayer_flag) { @@ -6332,8 +7825,15 @@ result_done: #endif /* mark itself has all HW resource released and input released */ - vdec_core_finish_run(vdec, CORE_MASK_VDEC_1 | CORE_MASK_HEVC); + if (vdec->parallel_dec == 1) { + if (hw->mmu_enable == 0) + vdec_core_finish_run(vdec, CORE_MASK_VDEC_1); + else + vdec_core_finish_run(vdec, CORE_MASK_VDEC_1 | CORE_MASK_HEVC); + } else + vdec_core_finish_run(vdec, CORE_MASK_VDEC_1 | CORE_MASK_HEVC); + wake_up_interruptible(&hw->wait_q); if (hw->vdec_cb) hw->vdec_cb(hw_to_vdec(hw), hw->vdec_cb_arg); } @@ -6343,7 +7843,17 @@ static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask) bool ret = 0; struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)vdec->private; + int tvp = vdec_secure(hw_to_vdec(hw)) ? + CODEC_MM_FLAGS_TVP : 0; + if (!hw->first_sc_checked && hw->mmu_enable) { + int size = decoder_mmu_box_sc_check(hw->mmu_box, tvp); + hw->first_sc_checked =1; + dpb_print(DECODE_ID(hw), 0, + "vmh264 cached=%d need_size=%d speed= %d ms\n", + size, (hw->need_cache_size >> PAGE_SHIFT), + (int)(get_jiffies_64() - hw->sc_start_time) * 1000/HZ); + } if (vdec_stream_based(vdec) && (hw->init_flag == 0) && pre_decode_buf_level != 0) { @@ -6367,6 +7877,9 @@ static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask) if (hw->eos) return 0; + if (hw->stat & DECODER_FATAL_ERROR_NO_MEM) + return 0; + if (disp_vframe_valve_level && kfifo_len(&hw->display_q) >= disp_vframe_valve_level) { @@ -6382,8 +7895,12 @@ static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask) READ_PARSER_REG(PARSER_VIDEO_WP); if (parser_wr_ptr >= hw->pre_parser_wr_ptr && (parser_wr_ptr - hw->pre_parser_wr_ptr) < - again_threshold) + again_threshold) { + int r = vdec_sync_input(vdec); + dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_DETAIL, + "%s buf lelvel:%x\n", __func__, r); return 0; + } } if (h264_debug_flag & 0x20000000) { @@ -6392,11 +7909,40 @@ static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask) } else ret = is_buffer_available(vdec); +#ifdef CONSTRAIN_MAX_BUF_NUM + if (hw->dpb.mDPB.size > 0) { /*make sure initilized*/ + if (run_ready_max_vf_only_num > 0 && + get_vf_ref_only_buf_count(hw) >= + run_ready_max_vf_only_num + ) + ret = 0; + if (run_ready_display_q_num > 0 && + kfifo_len(&hw->display_q) >= + run_ready_display_q_num) + ret = 0; + /*avoid more buffers consumed when + switching resolution*/ + if (run_ready_max_buf_num == 0xff && + get_used_buf_count(hw) >= + hw->dpb.mDPB.size) + ret = 0; + else if (run_ready_max_buf_num && + get_used_buf_count(hw) >= + run_ready_max_buf_num) + ret = 0; + } +#endif if (ret) not_run_ready[DECODE_ID(hw)] = 0; else not_run_ready[DECODE_ID(hw)]++; - return ret ? (CORE_MASK_VDEC_1 | CORE_MASK_HEVC) : 0; + if (vdec->parallel_dec == 1) { + if (hw->mmu_enable == 0) + return ret ? (CORE_MASK_VDEC_1) : 0; + else + return ret ? (CORE_MASK_VDEC_1 | CORE_MASK_HEVC) : 0; + } else + return ret ? (CORE_MASK_VDEC_1 | CORE_MASK_HEVC) : 0; } static unsigned char get_data_check_sum @@ -6404,10 +7950,20 @@ static unsigned char get_data_check_sum { int jj; int sum = 0; - u8 *data = ((u8 *)hw->chunk->block->start_virt) + - hw->chunk->offset; + u8 *data = NULL; + + if (!hw->chunk->block->is_mapped) + data = codec_mm_vmap(hw->chunk->block->start + + hw->chunk->offset, size); + else + data = ((u8 *)hw->chunk->block->start_virt) + + hw->chunk->offset; + for (jj = 0; jj < size; jj++) sum += data[jj]; + + if (!hw->chunk->block->is_mapped) + codec_mm_unmap_phyaddr(data); return sum; } @@ -6417,9 +7973,10 @@ static void run(struct vdec_s *vdec, unsigned long mask, struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)vdec->private; struct h264_dpb_stru *p_H264_Dpb = &hw->dpb; - int size; + int size, ret = -1; run_count[DECODE_ID(hw)]++; + vdec_reset_core(vdec); if (hw->mmu_enable) hevc_reset_core(vdec); hw->vdec_cb_arg = arg; @@ -6478,9 +8035,16 @@ static void run(struct vdec_s *vdec, unsigned long mask, READ_VREG(VLD_MEM_VIFIFO_WP)); #endif - if (input_frame_based(vdec)) { - u8 *data = ((u8 *)hw->chunk->block->start_virt) + - hw->chunk->offset; + if (input_frame_based(vdec) && !vdec_secure(vdec)) { + u8 *data = NULL; + + if (!hw->chunk->block->is_mapped) + data = codec_mm_vmap(hw->chunk->block->start + + hw->chunk->offset, size); + else + data = ((u8 *)hw->chunk->block->start_virt) + + hw->chunk->offset; + if (dpb_is_debug(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS) ) { @@ -6496,9 +8060,7 @@ static void run(struct vdec_s *vdec, unsigned long mask, PRINT_FRAMEBASE_DATA) ) { int jj; - u8 *data = - ((u8 *)hw->chunk->block->start_virt) + - hw->chunk->offset; + for (jj = 0; jj < size; jj++) { if ((jj & 0xf) == 0) dpb_print(DECODE_ID(hw), @@ -6514,6 +8076,8 @@ static void run(struct vdec_s *vdec, unsigned long mask, } } + if (!hw->chunk->block->is_mapped) + codec_mm_unmap_phyaddr(data); } else dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS, "%s: %x %x %x %x %x size 0x%x\n", @@ -6526,42 +8090,46 @@ static void run(struct vdec_s *vdec, unsigned long mask, size); start_process_time(hw); - - if (tee_enabled()) { - if (tee_load_video_fw(VIDEO_DEC_H264_MULTI, 0) != 0) { - amvdec_enable_flag = false; - amvdec_disable(); - dpb_print(DECODE_ID(hw), 0, "%s: Error amvdec_vdec_loadmc fail\n", __func__); - return; - } - if (hw->mmu_enable) { - if (tee_load_video_fw(VIDEO_DEC_H264_MULTI_MMU, - OPTEE_VDEC_HEVC) < 0) { - amvdec_enable_flag = false; - amhevc_disable(); - dpb_print(DECODE_ID(hw), 0, "tee mmu fw load fail\n"); - return; - } - } - + if (vdec->mc_loaded) { + /*firmware have load before, + and not changes to another. + ignore reload. + */ + WRITE_VREG(AV_SCRATCH_G, hw->reg_g_status); } else { - if (amvdec_vdec_loadmc_ex(vdec, NULL, hw->fw->data) < 0) { + + ret = amvdec_vdec_loadmc_ex(VFORMAT_H264, "mh264", vdec, hw->fw->data); + if (ret < 0) { amvdec_enable_flag = false; amvdec_disable(); - dpb_print(DECODE_ID(hw), 0, "%s: Error amvdec_vdec_loadmc fail\n", __func__); + + dpb_print(DECODE_ID(hw), PRINT_FLAG_ERROR, + "MH264 the %s fw loading failed, err: %x\n", + tee_enabled() ? "TEE" : "local", ret); + hw->dec_result = DEC_RESULT_FORCE_EXIT; + vdec_schedule_work(&hw->work); return; } + vdec->mc_type = VFORMAT_H264; + hw->reg_g_status = READ_VREG(AV_SCRATCH_G); if (hw->mmu_enable) { - if (amhevc_loadmc_ex(VFORMAT_HEVC, - NULL, hw->fw_mmu->data) < 0) { + ret = amhevc_loadmc_ex(VFORMAT_H264, "mh264_mmu", + hw->fw_mmu->data); + if (ret < 0) { amvdec_enable_flag = false; amhevc_disable(); - dpb_print(DECODE_ID(hw), 0, "mmu fw load fail\n"); + + dpb_print(DECODE_ID(hw), PRINT_FLAG_ERROR, + "MH264_MMU the %s fw loading failed, err: %x\n", + tee_enabled() ? "TEE" : "local", ret); + hw->dec_result = DEC_RESULT_FORCE_EXIT; + vdec_schedule_work(&hw->work); return; } + vdec->mc_type = ((1 << 16) | VFORMAT_H264); } + vdec->mc_loaded = 1; } - vmh264_reset_udr_mgr(hw); if (vh264_hw_ctx_restore(hw) < 0) { @@ -6569,7 +8137,9 @@ static void run(struct vdec_s *vdec, unsigned long mask, return; } if (input_frame_based(vdec)) { - int decode_size = hw->chunk->size + + int decode_size = 0; + + decode_size = hw->chunk->size + (hw->chunk->offset & (VDEC_FIFO_ALIGN - 1)); WRITE_VREG(H264_DECODE_INFO, (1<<13)); WRITE_VREG(H264_DECODE_SIZE, decode_size); @@ -6585,6 +8155,7 @@ static void run(struct vdec_s *vdec, unsigned long mask, config_decode_mode(hw); vdec_enable_input(vdec); WRITE_VREG(NAL_SEARCH_CTL, 0); + hw->sei_data_len = 0; if (enable_itu_t35) WRITE_VREG(NAL_SEARCH_CTL, READ_VREG(NAL_SEARCH_CTL) | 0x1); if (!hw->init_flag) { @@ -6599,13 +8170,20 @@ static void run(struct vdec_s *vdec, unsigned long mask, WRITE_VREG(AV_SCRATCH_K, udebug_flag); mod_timer(&hw->check_timer, jiffies + CHECK_INTERVAL); + if (get_cpu_major_id() >= MESON_CPU_MAJOR_ID_G12A) { + + if (hw->mmu_enable) + SET_VREG_MASK(VDEC_ASSIST_MMC_CTRL1, 1 << 3); + else + CLEAR_VREG_MASK(VDEC_ASSIST_MMC_CTRL1, 1 << 3); + } amvdec_start(); if (hw->mmu_enable /*&& !hw->frame_busy && !hw->frame_done*/) { WRITE_VREG(HEVC_ASSIST_SCRATCH_0, 0x0); amhevc_start(); if (hw->config_bufmgr_done) { hevc_mcr_sao_global_hw_init(hw, - hw->frame_width, hw->frame_height); + (hw->mb_width << 4), (hw->mb_height << 4)); hevc_mcr_config_canv2axitbl(hw, 1); } } @@ -6619,7 +8197,26 @@ static void run(struct vdec_s *vdec, unsigned long mask, static void reset(struct vdec_s *vdec) { - pr_info("ammvdec_h264: reset.\n"); + struct vdec_h264_hw_s *hw = + (struct vdec_h264_hw_s *)vdec->private; + + cancel_work_sync(&hw->work); + cancel_work_sync(&hw->notify_work); + if (hw->stat & STAT_VDEC_RUN) { + amhevc_stop(); + hw->stat &= ~STAT_VDEC_RUN; + } + + if (hw->stat & STAT_TIMER_ARM) { + del_timer_sync(&hw->check_timer); + hw->stat &= ~STAT_TIMER_ARM; + } + hw->eos = 0; + hw->decode_pic_count = 0; + hw->dec_result = DEC_RESULT_NONE; + reset_process_time(hw); + h264_reset_bufmgr(vdec); + dpb_print(DECODE_ID(hw), 0, "%s\n", __func__); } static void h264_reconfig(struct vdec_h264_hw_s *hw) @@ -6693,6 +8290,7 @@ static void h264_clear_dpb(struct vdec_h264_hw_s *hw) static void h264_reset_bufmgr(struct vdec_s *vdec) { int i; + ulong timeout; struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)vdec->private; #if 0 struct h264_dpb_stru *p_H264_Dpb = &hw->dpb; @@ -6750,6 +8348,13 @@ static void h264_reset_bufmgr(struct vdec_s *vdec) __func__, hw->decode_pic_count+1, hw->skip_frame_count); + timeout = jiffies + HZ; + while (kfifo_len(&hw->display_q) > 0) { + if (time_after(jiffies, timeout)) + break; + schedule(); + } + for (i = 0; i < VF_POOL_SIZE; i++) hw->vfpool[hw->cur_pool][i].index = -1; /* VF_BUF_NUM; */ @@ -6794,14 +8399,17 @@ int ammvdec_h264_mmu_init(struct vdec_h264_hw_s *hw) int ret = -1; int tvp_flag = vdec_secure(hw_to_vdec(hw)) ? CODEC_MM_FLAGS_TVP : 0; + int buf_size = 64; pr_debug("ammvdec_h264_mmu_init tvp = 0x%x mmu_enable %d\n", tvp_flag, hw->mmu_enable); + hw->need_cache_size = buf_size * SZ_1M; + hw->sc_start_time = get_jiffies_64(); if (hw->mmu_enable && !hw->mmu_box) { hw->mmu_box = decoder_mmu_box_alloc_box(DRIVER_NAME, hw->id, MMU_MAX_BUFFERS, - 64 * SZ_1M, + hw->need_cache_size, tvp_flag); if (!hw->mmu_box) { pr_err("h264 4k alloc mmu box failed!!\n"); @@ -6856,38 +8464,66 @@ static int ammvdec_h264_probe(struct platform_device *pdev) } hw->id = pdev->id; hw->platform_dev = pdev; + + /* the ctx from v4l2 driver. */ + hw->v4l2_ctx = pdata->private; + + hw->canvas_mode = pdata->canvas_mode; + platform_set_drvdata(pdev, pdata); hw->mmu_enable = 0; if (force_enable_mmu && pdata->sys_info && - (get_cpu_type() >= MESON_CPU_MAJOR_ID_TXLX) && - (get_cpu_type() != MESON_CPU_MAJOR_ID_GXLX) && - (get_cpu_type() != MESON_CPU_MAJOR_ID_G12A) && - (get_cpu_type() != MESON_CPU_MAJOR_ID_G12B) && + (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_TXLX) && + (get_cpu_major_id() != AM_MESON_CPU_MAJOR_ID_GXLX) && (pdata->sys_info->height * pdata->sys_info->width > 1920 * 1088)) hw->mmu_enable = 1; + + if (hw->mmu_enable && + (pdata->frame_base_video_path == FRAME_BASE_PATH_IONVIDEO)) { + hw->mmu_enable = 0; + pr_info("ionvideo needs disable mmu, path= %d \n", + pdata->frame_base_video_path); + } + if (ammvdec_h264_mmu_init(hw)) { h264_free_hw_stru(&pdev->dev, (void *)hw); pr_info("\nammvdec_h264 mmu alloc failed!\n"); return -ENOMEM; } - if (hw->mmu_enable) { - if (pdata->config && pdata->config_len) { - /*use ptr config for doubel_write_mode, etc*/ - if (get_config_int(pdata->config, - "mh264_double_write_mode", &config_val) == 0) - hw->double_write_mode = config_val; - else - hw->double_write_mode = double_write_mode; - } else + if (pdata->config_len) { + /*use ptr config for doubel_write_mode, etc*/ + if (get_config_int(pdata->config, + "mh264_double_write_mode", &config_val) == 0) + hw->double_write_mode = config_val; + else hw->double_write_mode = double_write_mode; } else - hw->double_write_mode = 0; + hw->double_write_mode = double_write_mode; + + if (hw->mmu_enable) + hw->double_write_mode &= 0xffff; + + if (pdata->parallel_dec == 1) { + int i; + for (i = 0; i < BUFSPEC_POOL_SIZE; i++) { + hw->buffer_spec[i].y_canvas_index = -1; + hw->buffer_spec[i].u_canvas_index = -1; + hw->buffer_spec[i].v_canvas_index = -1; +#ifdef VDEC_DW + if (IS_VDEC_DW(hw)) { + hw->buffer_spec[i].vdec_dw_y_canvas_index = -1; + hw->buffer_spec[i].vdec_dw_u_canvas_index = -1; + hw->buffer_spec[i].vdec_dw_v_canvas_index = -1; + } +#endif + } + } dpb_print(DECODE_ID(hw), 0, - "%s mmu_enable %d double_write_mode %d\n", + "%s mmu_enable %d double_write_mode 0x%x\n", __func__, hw->mmu_enable, hw->double_write_mode); pdata->private = hw; @@ -6901,15 +8537,19 @@ static int ammvdec_h264_probe(struct platform_device *pdev) pdata->dump_state = vmh264_dump_state; #ifdef MH264_USERDATA_ENABLE + pdata->wakeup_userdata_poll = vmh264_wakeup_userdata_poll; pdata->user_data_read = vmh264_user_data_read; pdata->reset_userdata_fifo = vmh264_reset_userdata_fifo; #else + pdata->wakeup_userdata_poll = NULL; pdata->user_data_read = NULL; pdata->reset_userdata_fifo = NULL; #endif - if (pdata->use_vfm_path) + if (pdata->use_vfm_path) { snprintf(pdata->vf_provider_name, VDEC_PROVIDER_NAME_SIZE, VFM_DEC_PROVIDER_NAME); + hw->frameinfo_enable = 1; + } #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION else if (vdec_dual(pdata)) { if (dv_toggle_prov_name) /*debug purpose*/ @@ -6944,25 +8584,43 @@ static int ammvdec_h264_probe(struct platform_device *pdev) if (decoder_bmmu_box_alloc_buf_phy(hw->bmmu_box, BMMU_DPB_IDX, V_BUF_ADDR_OFFSET, DRIVER_NAME, &hw->cma_alloc_addr) < 0) { h264_free_hw_stru(&pdev->dev, (void *)hw); + pdata->dec_status = NULL; return -ENOMEM; } hw->buf_offset = hw->cma_alloc_addr - DEF_BUF_START_ADDR + DCAC_READ_MARGIN; - if (hw->mmu_enable) + if (hw->mmu_enable) { + u32 extif_size = EXTIF_BUF_SIZE; + if (get_cpu_major_id() >= MESON_CPU_MAJOR_ID_G12A) + extif_size <<= 1; if (decoder_bmmu_box_alloc_buf_phy(hw->bmmu_box, BMMU_EXTIF_IDX, - EXTIF_BUF_SIZE, DRIVER_NAME, &hw->extif_addr) < 0) { + extif_size, DRIVER_NAME, &hw->extif_addr) < 0) { h264_free_hw_stru(&pdev->dev, (void *)hw); + pdata->dec_status = NULL; return -ENOMEM; } + } if (!vdec_secure(pdata)) { #if 1 /*init internal buf*/ tmpbuf = (char *)codec_mm_phys_to_virt(hw->cma_alloc_addr); - memset(tmpbuf, 0, V_BUF_ADDR_OFFSET); - dma_sync_single_for_device(amports_get_dma_device(), - hw->cma_alloc_addr, - V_BUF_ADDR_OFFSET, DMA_TO_DEVICE); + if (tmpbuf) { + memset(tmpbuf, 0, V_BUF_ADDR_OFFSET); + codec_mm_dma_flush(tmpbuf, + V_BUF_ADDR_OFFSET, + DMA_TO_DEVICE); + } else { + tmpbuf = codec_mm_vmap(hw->cma_alloc_addr, + V_BUF_ADDR_OFFSET); + if (tmpbuf) { + memset(tmpbuf, 0, V_BUF_ADDR_OFFSET); + codec_mm_dma_flush(tmpbuf, + V_BUF_ADDR_OFFSET, + DMA_TO_DEVICE); + codec_mm_unmap_phyaddr(tmpbuf); + } + } #else /*init sps/pps internal buf 64k*/ tmpbuf = (char *)codec_mm_phys_to_virt(hw->cma_alloc_addr @@ -6999,13 +8657,17 @@ static int ammvdec_h264_probe(struct platform_device *pdev) pr_debug("ammvdec_h264 mem-addr=%lx,buff_offset=%x,buf_start=%lx\n", pdata->mem_start, hw->buf_offset, hw->cma_alloc_addr); - - vdec_source_changed(VFORMAT_H264, 3840, 2160, 60); + if (vdec_is_support_4k() || + (clk_adj_frame_count > (VDEC_CLOCK_ADJUST_FRAME - 1))) + vdec_source_changed(VFORMAT_H264, 3840, 2160, 60); + else + vdec_source_changed(VFORMAT_H264, 1920, 1080, 29); if (vh264_init(hw) < 0) { pr_info("\nammvdec_h264 init failed.\n"); ammvdec_h264_mmu_release(hw); h264_free_hw_stru(&pdev->dev, (void *)hw); + pdata->dec_status = NULL; return -ENODEV; } #ifdef MH264_USERDATA_ENABLE @@ -7015,9 +8677,16 @@ static int ammvdec_h264_probe(struct platform_device *pdev) #endif vdec_set_prepare_level(pdata, start_decode_buf_level); - - vdec_core_request(pdata, CORE_MASK_VDEC_1 | CORE_MASK_HEVC - | CORE_MASK_COMBINE); + if (pdata->parallel_dec == 1) { + if (hw->mmu_enable == 0) + vdec_core_request(pdata, CORE_MASK_VDEC_1); + else { + vdec_core_request(pdata, CORE_MASK_VDEC_1 | CORE_MASK_HEVC + | CORE_MASK_COMBINE); + } + } else + vdec_core_request(pdata, CORE_MASK_VDEC_1 | CORE_MASK_HEVC + | CORE_MASK_COMBINE); atomic_set(&hw->vh264_active, 1); @@ -7031,6 +8700,18 @@ static int ammvdec_h264_remove(struct platform_device *pdev) (((struct vdec_s *)(platform_get_drvdata(pdev)))->private); int i; + struct vdec_s *vdec = hw_to_vdec(hw); + + if (vdec->next_status == VDEC_STATUS_DISCONNECTED + && (vdec->status == VDEC_STATUS_ACTIVE)) { + pr_info("%s force exit %d\n", __func__, __LINE__); + hw->dec_result = DEC_RESULT_FORCE_EXIT; + vdec_schedule_work(&hw->work); + wait_event_interruptible_timeout(hw->wait_q, + (vdec->status == VDEC_STATUS_CONNECTED), + msecs_to_jiffies(50)); /* wait for work done */ + } + for (i = 0; i < BUFSPEC_POOL_SIZE; i++) release_aux_data(hw, i); @@ -7051,12 +8732,32 @@ static int ammvdec_h264_remove(struct platform_device *pdev) /* vdec_source_changed(VFORMAT_H264, 0, 0, 0); */ atomic_set(&hw->vh264_active, 0); - - vdec_core_release(hw_to_vdec(hw), CORE_MASK_VDEC_1 | CORE_MASK_HEVC); + if (vdec->parallel_dec == 1) { + if (hw->mmu_enable == 0) + vdec_core_release(vdec, CORE_MASK_VDEC_1); + else + vdec_core_release(vdec, CORE_MASK_VDEC_1 | CORE_MASK_HEVC | + CORE_MASK_COMBINE); + } else + vdec_core_release(hw_to_vdec(hw), CORE_MASK_VDEC_1 | CORE_MASK_HEVC); vdec_set_status(hw_to_vdec(hw), VDEC_STATUS_DISCONNECTED); + if (vdec->parallel_dec == 1) { + for (i = 0; i < BUFSPEC_POOL_SIZE; i++) { + vdec->free_canvas_ex(hw->buffer_spec[i].y_canvas_index, vdec->id); + vdec->free_canvas_ex(hw->buffer_spec[i].u_canvas_index, vdec->id); + vdec->free_canvas_ex(hw->buffer_spec[i].v_canvas_index, vdec->id); + if (IS_VDEC_DW(hw)) { + vdec->free_canvas_ex(hw->buffer_spec[i].vdec_dw_y_canvas_index, vdec->id); + vdec->free_canvas_ex(hw->buffer_spec[i].vdec_dw_u_canvas_index, vdec->id); + vdec->free_canvas_ex(hw->buffer_spec[i].vdec_dw_v_canvas_index, vdec->id); + } + } + } ammvdec_h264_mmu_release(hw); h264_free_hw_stru(&pdev->dev, (void *)hw); + clk_adj_frame_count = 0; + return 0; } @@ -7116,10 +8817,10 @@ static int __init ammvdec_h264_driver_init_module(void) } if (vdec_is_support_4k()) { - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_TXLX) { + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_TXLX) { ammvdec_h264_profile.profile = "4k, dwrite, compressed"; - } else if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXTVBB) { + } else if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXTVBB) { ammvdec_h264_profile.profile = "4k"; } } @@ -7138,7 +8839,6 @@ static void __exit ammvdec_h264_driver_remove_module(void) } /****************************************/ - module_param(h264_debug_flag, uint, 0664); MODULE_PARM_DESC(h264_debug_flag, "\n ammvdec_h264 h264_debug_flag\n"); @@ -7176,6 +8876,17 @@ MODULE_PARM_DESC(reorder_dpb_size_margin_dv, module_param(reference_buf_margin, uint, 0664); MODULE_PARM_DESC(reference_buf_margin, "\n ammvdec_h264 reference_buf_margin\n"); +#ifdef CONSTRAIN_MAX_BUF_NUM +module_param(run_ready_max_vf_only_num, uint, 0664); +MODULE_PARM_DESC(run_ready_max_vf_only_num, "\n run_ready_max_vf_only_num\n"); + +module_param(run_ready_display_q_num, uint, 0664); +MODULE_PARM_DESC(run_ready_display_q_num, "\n run_ready_display_q_num\n"); + +module_param(run_ready_max_buf_num, uint, 0664); +MODULE_PARM_DESC(run_ready_max_buf_num, "\n run_ready_max_buf_num\n"); +#endif + module_param(radr, uint, 0664); MODULE_PARM_DESC(radr, "\nradr\n"); @@ -7245,7 +8956,7 @@ MODULE_PARM_DESC(frmbase_cont_bitlevel2, "\n amvdec_h264 frmbase_cont_bitlevel\n"); module_param(udebug_flag, uint, 0664); -MODULE_PARM_DESC(udebug_flag, "\n amvdec_h265 udebug_flag\n"); +MODULE_PARM_DESC(udebug_flag, "\n amvdec_mh264 udebug_flag\n"); module_param(udebug_pause_pos, uint, 0664); MODULE_PARM_DESC(udebug_pause_pos, "\n udebug_pause_pos\n"); @@ -7274,6 +8985,8 @@ MODULE_PARM_DESC(force_enable_mmu, "\n force_enable_mmu\n"); module_param(again_threshold, uint, 0664); MODULE_PARM_DESC(again_threshold, "\n again_threshold\n"); +module_param(stream_mode_start_num, uint, 0664); +MODULE_PARM_DESC(stream_mode_start_num, "\n stream_mode_start_num\n"); /* module_param(trigger_task, uint, 0664); @@ -7299,6 +9012,8 @@ module_param_array(max_get_frame_interval, uint, module_param_array(step, uint, &max_decode_instance_num, 0664); +module_param_array(ref_frame_mark_flag, uint, &max_decode_instance_num, 0664); + module_param(disp_vframe_valve_level, uint, 0664); MODULE_PARM_DESC(disp_vframe_valve_level, "\n disp_vframe_valve_level\n"); diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/h265/vh265.c b/drivers/amlogic/media_modules/frame_provider/decoder/h265/vh265.c index e566b9949bde..618c13340744 100644 --- a/drivers/amlogic/media_modules/frame_provider/decoder/h265/vh265.c +++ b/drivers/amlogic/media_modules/frame_provider/decoder/h265/vh265.c @@ -45,6 +45,14 @@ #include "../utils/decoder_bmmu_box.h" #include "../utils/config_parser.h" #include "../utils/firmware.h" +#include "../../../common/chips/decoder_cpu_ver_info.h" +#include + +#define CONSTRAIN_MAX_BUF_NUM + +#define SWAP_HEVC_UCODE +#define DETREFILL_ENABLE + #define AGAIN_HAS_THRESHOLD /*#define TEST_NO_BUF*/ /*#define HEVC_PIC_STRUCT_SUPPORT*/ @@ -54,11 +62,17 @@ /* .buf_size = 0x100000*16, //4k2k , 0x100000 per buffer */ /* 4096x2304 , 0x120000 per buffer */ -#define MPRED_MV_BUF_SIZE 0x120000 +#define MPRED_8K_MV_BUF_SIZE (0x120000*4) +#define MPRED_4K_MV_BUF_SIZE (0x120000) +#define MPRED_MV_BUF_SIZE (0x40000) #define MMU_COMPRESS_HEADER_SIZE 0x48000 +#define MMU_COMPRESS_8K_HEADER_SIZE (0x48000*4) + #define MAX_FRAME_4K_NUM 0x1200 -#define FRAME_MMU_MAP_SIZE (MAX_FRAME_4K_NUM * 4) +#define MAX_FRAME_8K_NUM (0x1200*4) + +//#define FRAME_MMU_MAP_SIZE (MAX_FRAME_4K_NUM * 4) #define H265_MMU_MAP_BUFFER HEVC_ASSIST_SCRATCH_7 #define HEVC_ASSIST_MMU_MAP_ADDR 0x3009 @@ -70,7 +84,7 @@ #define HEVC_DBLK_CFGB 0x350b #define HEVCD_MPP_DECOMP_AXIURG_CTL 0x34c7 - +#define SWAP_HEVC_OFFSET (3 * 0x1000) #define MEM_NAME "codec_265" /* #include */ @@ -84,11 +98,6 @@ #define SEND_LMEM_WITH_RPM #define SUPPORT_10BIT /* #define ERROR_HANDLE_DEBUG */ -#if 0/*MESON_CPU_TYPE == MESON_CPU_TYPE_MESON8B*/ -#undef SUPPORT_4K2K -#else -#define SUPPORT_4K2K -#endif #ifndef STAT_KTHREAD #define STAT_KTHREAD 0x40 @@ -112,8 +121,14 @@ #define PTS_MODE_SWITCHING_RECOVERY_THREASHOLD 3 #define DUR2PTS(x) ((x)*90/96) -#define MAX_SIZE (4096 + 2304) -#define OVER_SIZE(w, h) (MAX_SIZE < (w + h)) + +#define MAX_SIZE_8K (8192 * 4608) +#define MAX_SIZE_4K (4096 * 2304) + +#define IS_8K_SIZE(w, h) (((w) * (h)) > MAX_SIZE_4K) +#define IS_4K_SIZE(w, h) (((w) * (h)) > (1920*1088)) + +#define SEI_UserDataITU_T_T35 4 static struct semaphore h265_sema; @@ -228,6 +243,7 @@ static u32 force_fps; static u32 pts_unstable; #define H265_DEBUG_BUFMGR 0x01 #define H265_DEBUG_BUFMGR_MORE 0x02 +#define H265_DEBUG_DETAIL 0x04 #define H265_DEBUG_REG 0x08 #define H265_DEBUG_MAN_SEARCH_NAL 0x10 #define H265_DEBUG_MAN_SKIP_NAL 0x20 @@ -240,6 +256,7 @@ static u32 pts_unstable; #define H265_DEBUG_DUMP_PIC_LIST 0x1000 #define H265_DEBUG_PRINT_SEI 0x2000 #define H265_DEBUG_PIC_STRUCT 0x4000 +#define H265_DEBUG_HAS_AUX_IN_SLICE 0x8000 #define H265_DEBUG_DIS_LOC_ERROR_PROC 0x10000 #define H265_DEBUG_DIS_SYS_ERROR_PROC 0x20000 #define H265_NO_CHANG_DEBUG_FLAG_IN_CODE 0x40000 @@ -273,6 +290,10 @@ static u32 pts_unstable; #define MV_BUFFER_IDX(n) (BUF_POOL_SIZE + 1 + n) #endif +#define HEVC_MV_INFO 0x310d +#define HEVC_QP_INFO 0x3137 +#define HEVC_SKIP_INFO 0x3136 + const u32 h265_version = 201602101; static u32 debug_mask = 0xffffffff; static u32 log_mask; @@ -318,7 +339,16 @@ static uint slice_parse_begin; static u32 step; static bool is_reset; -static u32 dynamic_buf_num_margin = 7; +#ifdef CONSTRAIN_MAX_BUF_NUM +static u32 run_ready_max_vf_only_num; +static u32 run_ready_display_q_num; + /*0: not check + 0xff: work_pic_num + */ +static u32 run_ready_max_buf_num = 0xff; +#endif + +static u32 dynamic_buf_num_margin = 8; static u32 buf_alloc_width; static u32 buf_alloc_height; @@ -368,6 +398,8 @@ bit 0, fast output first I picture */ static u32 fast_output_enable = 1; +static u32 frmbase_cont_bitlevel = 0x60; + /* use_cma: 1, use both reserver memory and cma for buffers 2, only use cma for buffers @@ -429,6 +461,7 @@ static u32 mmu_enable_force; static u32 work_buf_size; static unsigned int force_disp_pic_index; static unsigned int disp_vframe_valve_level; +static int pre_decode_buf_level = 0x1000; #ifdef MULTI_INSTANCE_SUPPORT static unsigned int max_decode_instance_num @@ -440,6 +473,8 @@ static unsigned int max_get_frame_interval[MAX_DECODE_INSTANCE_NUM]; static unsigned int run_count[MAX_DECODE_INSTANCE_NUM]; static unsigned int input_empty[MAX_DECODE_INSTANCE_NUM]; static unsigned int not_run_ready[MAX_DECODE_INSTANCE_NUM]; +static unsigned int ref_frame_mark_flag[MAX_DECODE_INSTANCE_NUM] = +{1, 1, 1, 1, 1, 1, 1, 1, 1}; #ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC static unsigned char get_idx(struct hevc_state_s *hevc); @@ -449,6 +484,8 @@ static unsigned char get_idx(struct hevc_state_s *hevc); static u32 dv_toggle_prov_name; static u32 dv_debug; + +static u32 force_bypass_dvenl; #endif #endif @@ -603,6 +640,7 @@ enum NalUnitType { #define HEVC_SEI_DAT 0xc #define HEVC_SEI_DAT_DONE 0xd #define HEVC_NAL_DECODE_DONE 0xe +#define HEVC_OVER_DECODE 0xf #define HEVC_DATA_REQUEST 0x12 @@ -652,8 +690,8 @@ enum NalUnitType { #define HEVC_SPS_BUFFER HEVC_ASSIST_SCRATCH_4 #define HEVC_PPS_BUFFER HEVC_ASSIST_SCRATCH_5 #define HEVC_SAO_UP HEVC_ASSIST_SCRATCH_6 -/*#define HEVC_STREAM_SWAP_BUFFER HEVC_ASSIST_SCRATCH_7 -#define HEVC_STREAM_SWAP_BUFFER2 HEVC_ASSIST_SCRATCH_8*/ +#define HEVC_STREAM_SWAP_BUFFER HEVC_ASSIST_SCRATCH_7 +#define HEVC_STREAM_SWAP_BUFFER2 HEVC_ASSIST_SCRATCH_8 #define HEVC_sao_mem_unit HEVC_ASSIST_SCRATCH_9 #define HEVC_SAO_ABV HEVC_ASSIST_SCRATCH_A #define HEVC_sao_vb_size HEVC_ASSIST_SCRATCH_B @@ -802,6 +840,7 @@ union param_u { unsigned short aspect_ratio_idc; unsigned short sar_width; unsigned short sar_height; + unsigned short sps_max_dec_pic_buffering_minus1_0; } p; }; @@ -843,7 +882,7 @@ struct BuffInfo_s { struct buff_s rpm; struct buff_s lmem; }; -#define WORK_BUF_SPEC_NUM 2 +#define WORK_BUF_SPEC_NUM 3 static struct BuffInfo_s amvh265_workbuff_spec[WORK_BUF_SPEC_NUM] = { { /* 8M bytes */ @@ -1036,7 +1075,7 @@ static struct BuffInfo_s amvh265_workbuff_spec[WORK_BUF_SPEC_NUM] = { /* .buf_size = 0x100000*16, //4k2k , 0x100000 per buffer */ /* 4096x2304 , 0x120000 per buffer */ - .buf_size = MPRED_MV_BUF_SIZE * MAX_REF_PIC_NUM, + .buf_size = MPRED_4K_MV_BUF_SIZE * MAX_REF_PIC_NUM, }, #endif .rpm = { @@ -1045,6 +1084,78 @@ static struct BuffInfo_s amvh265_workbuff_spec[WORK_BUF_SPEC_NUM] = { .lmem = { .buf_size = 0x500 * 2, } + }, + + { + .max_width = 4096*2, + .max_height = 2048*2, + .ipp = { + // IPP work space calculation : 4096 * (Y+CbCr+Flags) = 12k, round to 16k + .buf_size = 0x4000*2, + }, + .sao_abv = { + .buf_size = 0x30000*2, + }, + .sao_vb = { + .buf_size = 0x30000*2, + }, + .short_term_rps = { + // SHORT_TERM_RPS - Max 64 set, 16 entry every set, total 64x16x2 = 2048 bytes (0x800) + .buf_size = 0x800, + }, + .vps = { + // VPS STORE AREA - Max 16 VPS, each has 0x80 bytes, total 0x0800 bytes + .buf_size = 0x800, + }, + .sps = { + // SPS STORE AREA - Max 16 SPS, each has 0x80 bytes, total 0x0800 bytes + .buf_size = 0x800, + }, + .pps = { + // PPS STORE AREA - Max 64 PPS, each has 0x80 bytes, total 0x2000 bytes + .buf_size = 0x2000, + }, + .sao_up = { + // SAO UP STORE AREA - Max 640(10240/16) LCU, each has 16 bytes total 0x2800 bytes + .buf_size = 0x2800*2, + }, + .swap_buf = { + // 256cyclex64bit = 2K bytes 0x800 (only 144 cycles valid) + .buf_size = 0x800, + }, + .swap_buf2 = { + .buf_size = 0x800, + }, + .scalelut = { + // support up to 32 SCALELUT 1024x32 = 32Kbytes (0x8000) + .buf_size = 0x8000*2, + }, + .dblk_para = {.buf_size = 0x40000*2, }, // dblk parameter + .dblk_data = {.buf_size = 0x80000*2, }, // dblk data for left/top + .dblk_data2 = {.buf_size = 0x80000*2, }, // dblk data for adapter + .mmu_vbh = { + .buf_size = 0x5000*2, //2*16*2304/4, 4K + }, +#if 0 + .cm_header = { + .buf_size = MMU_COMPRESS_8K_HEADER_SIZE * + MAX_REF_PIC_NUM, // 0x44000 = ((1088*2*1024*4)/32/4)*(32/8) + }, +#endif + .mpred_above = { + .buf_size = 0x8000*2, + }, +#ifdef MV_USE_FIXED_BUF + .mpred_mv = { + .buf_size = MPRED_8K_MV_BUF_SIZE * MAX_REF_PIC_NUM, //4k2k , 0x120000 per buffer + }, +#endif + .rpm = { + .buf_size = RPM_BUF_SIZE, + }, + .lmem = { + .buf_size = 0x500 * 2, + }, } }; @@ -1252,6 +1363,24 @@ struct PIC_s { u32 sar_width; u32 sar_height; u32 double_write_mode; + u32 video_signal_type; + unsigned short conformance_window_flag; + unsigned short conf_win_left_offset; + unsigned short conf_win_right_offset; + unsigned short conf_win_top_offset; + unsigned short conf_win_bottom_offset; + unsigned short chroma_format_idc; + + /* picture qos infomation*/ + int max_qp; + int avg_qp; + int min_qp; + int max_skip; + int avg_skip; + int min_skip; + int max_mv; + int min_mv; + int avg_mv; } /*PIC_t */; #define MAX_TILE_COL_NUM 10 @@ -1268,6 +1397,7 @@ struct tile_s { #define SEI_MASTER_DISPLAY_COLOR_MASK 0x00000001 #define SEI_CONTENT_LIGHT_LEVEL_MASK 0x00000002 +#define SEI_HDR10PLUS_MASK 0x00000004 #define VF_POOL_SIZE 32 @@ -1312,6 +1442,8 @@ struct hevc_state_s { #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION unsigned char switch_dvlayer_flag; unsigned char no_switch_dvlayer_count; + unsigned char bypass_dvenl_enable; + unsigned char bypass_dvenl; #endif unsigned char start_parser_type; /*start_decoding_flag: @@ -1321,6 +1453,7 @@ struct hevc_state_s { unsigned char eos; int pic_decoded_lcu_idx; u8 over_decode; + u8 empty_flag; #endif struct vframe_s vframe_dummy; char *provider_name; @@ -1335,6 +1468,7 @@ struct hevc_state_s { struct BuffInfo_s work_space_buf_store; struct BuffInfo_s *work_space_buf; + u8 aux_data_dirty; u32 prefix_aux_size; u32 suffix_aux_size; void *aux_addr; @@ -1480,6 +1614,7 @@ struct hevc_state_s { u32 bit_depth_luma; u32 bit_depth_chroma; u32 video_signal_type; + u32 video_signal_type_debug; u32 saved_resolution; bool get_frame_dur; u32 error_watchdog_count; @@ -1492,6 +1627,7 @@ struct hevc_state_s { #endif struct dec_sysinfo vh265_amstream_dec_info; unsigned char init_flag; + unsigned char first_sc_checked; unsigned char uninit_list; u32 start_decoding_time; @@ -1528,6 +1664,7 @@ struct hevc_state_s { int double_write_mode; int dynamic_buf_num_margin; int start_action; + int save_buffer_mode; #endif u32 i_only; struct list_head log_list; @@ -1537,6 +1674,17 @@ struct hevc_state_s { u32 vf_pre_count; u32 vf_get_count; u32 vf_put_count; +#ifdef SWAP_HEVC_UCODE + dma_addr_t mc_dma_handle; + void *mc_cpu_addr; + int swap_size; + ulong swap_addr; +#endif +#ifdef DETREFILL_ENABLE + dma_addr_t detbuf_adr; + u16 *detbuf_adr_virt; + u8 delrefill_check; +#endif u8 head_error_flag; int valve_count; struct firmware_s *fw; @@ -1546,6 +1694,18 @@ struct hevc_state_s { u8 next_again_flag; u32 pre_parser_wr_ptr; #endif + u32 ratio_control; + u32 first_pic_flag; + u32 decode_size; + struct mutex chunks_mutex; + int need_cache_size; + u64 sc_start_time; + u32 skip_first_nal; + bool is_swap; + bool is_4k; + + int frameinfo_enable; + struct vframe_qos_s vframe_qos; } /*hevc_stru_t */; #ifdef AGAIN_HAS_THRESHOLD @@ -1555,6 +1715,29 @@ u32 again_threshold = 0x40; #define get_lmem_params(hevc, ladr) \ hevc->lmem_ptr[ladr - (ladr & 0x3) + 3 - (ladr & 0x3)] + +static int get_frame_mmu_map_size(void) +{ + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) + return (MAX_FRAME_8K_NUM * 4); + + return (MAX_FRAME_4K_NUM * 4); +} + +static int is_oversize(int w, int h) +{ + int max = (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1)? + MAX_SIZE_8K : MAX_SIZE_4K; + + if (w < 0 || h < 0) + return true; + + if (h != 0 && (w > max / h)) + return true; + + return false; +} + void check_head_error(struct hevc_state_s *hevc) { #define pcm_enabled_flag 0x040 @@ -1683,7 +1866,7 @@ static unsigned char is_skip_decoding(struct hevc_state_s *hevc, static int get_pic_poc(struct hevc_state_s *hevc, unsigned int idx) { - if (idx != 0xff && idx >= 0 + if (idx != 0xff && idx < MAX_REF_PIC_NUM && hevc->m_PIC[idx]) return hevc->m_PIC[idx]->POC; @@ -1711,7 +1894,7 @@ static int get_dynamic_buf_num_margin(struct hevc_state_s *hevc) static int get_double_write_mode(struct hevc_state_s *hevc) { u32 valid_dw_mode = get_valid_double_write_mode(hevc); - u32 dw; + u32 dw = hevc->double_write_mode; if (valid_dw_mode == 0x100) { int w = hevc->pic_w; int h = hevc->pic_h; @@ -1751,13 +1934,11 @@ static int hevc_print(struct hevc_state_s *hevc, #define HEVC_PRINT_BUF 256 unsigned char buf[HEVC_PRINT_BUF]; int len = 0; -#ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC if (hevc == NULL || (flag == 0) || ((debug_mask & (1 << hevc->index)) && (debug & flag))) { -#endif va_list args; va_start(args, fmt); @@ -1766,9 +1947,7 @@ static int hevc_print(struct hevc_state_s *hevc, vsnprintf(buf + len, HEVC_PRINT_BUF - len, fmt, args); pr_debug("%s", buf); va_end(args); -#ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC } -#endif return 0; } @@ -1939,6 +2118,7 @@ static void hevc_init_stru(struct hevc_state_s *hevc, hevc->sei_present_flag = 0; hevc->valve_count = 0; + hevc->first_pic_flag = 0; #ifdef MULTI_INSTANCE_SUPPORT hevc->decoded_poc = INVALID_POC; hevc->start_process_time = 0; @@ -1953,6 +2133,10 @@ static void hevc_init_stru(struct hevc_state_s *hevc, hevc->rps_set_id = 0; backup_decode_state(hevc); #endif +#ifdef DETREFILL_ENABLE + hevc->detbuf_adr = 0; + hevc->detbuf_adr_virt = NULL; +#endif } static int prepare_display_buf(struct hevc_state_s *hevc, struct PIC_s *pic); @@ -1960,6 +2144,384 @@ static int H265_alloc_mmu(struct hevc_state_s *hevc, struct PIC_s *new_pic, unsigned short bit_depth, unsigned int *mmu_index_adr); +#ifdef DETREFILL_ENABLE +#define DETREFILL_BUF_SIZE (4 * 0x4000) +#define HEVC_SAO_DBG_MODE0 0x361e +#define HEVC_SAO_DBG_MODE1 0x361f +#define HEVC_SAO_CTRL10 0x362e +#define HEVC_SAO_CTRL11 0x362f +static int init_detrefill_buf(struct hevc_state_s *hevc) +{ + if (hevc->detbuf_adr_virt) + return 0; + + hevc->detbuf_adr_virt = + (void *)dma_alloc_coherent(amports_get_dma_device(), + DETREFILL_BUF_SIZE, &hevc->detbuf_adr, + GFP_KERNEL); + + if (hevc->detbuf_adr_virt == NULL) { + pr_err("%s: failed to alloc ETREFILL_BUF\n", __func__); + return -1; + } + return 0; +} + +static void uninit_detrefill_buf(struct hevc_state_s *hevc) +{ + if (hevc->detbuf_adr_virt) { + dma_free_coherent(amports_get_dma_device(), + DETREFILL_BUF_SIZE, hevc->detbuf_adr_virt, + hevc->detbuf_adr); + + hevc->detbuf_adr_virt = NULL; + hevc->detbuf_adr = 0; + } +} + +/* + * convert uncompressed frame buffer data from/to ddr + */ +static void convUnc8x4blk(uint16_t* blk8x4Luma, + uint16_t* blk8x4Cb, uint16_t* blk8x4Cr, uint16_t* cmBodyBuf, int32_t direction) +{ + if (direction == 0) { + blk8x4Luma[3 + 0 * 8] = ((cmBodyBuf[0] >> 0)) & 0x3ff; + blk8x4Luma[3 + 1 * 8] = ((cmBodyBuf[1] << 6) + | (cmBodyBuf[0] >> 10)) & 0x3ff; + blk8x4Luma[3 + 2 * 8] = ((cmBodyBuf[1] >> 4)) & 0x3ff; + blk8x4Luma[3 + 3 * 8] = ((cmBodyBuf[2] << 2) + | (cmBodyBuf[1] >> 14)) & 0x3ff; + blk8x4Luma[7 + 0 * 8] = ((cmBodyBuf[3] << 8) + | (cmBodyBuf[2] >> 8)) & 0x3ff; + blk8x4Luma[7 + 1 * 8] = ((cmBodyBuf[3] >> 2)) & 0x3ff; + blk8x4Luma[7 + 2 * 8] = ((cmBodyBuf[4] << 4) + | (cmBodyBuf[3] >> 12)) & 0x3ff; + blk8x4Luma[7 + 3 * 8] = ((cmBodyBuf[4] >> 6)) & 0x3ff; + blk8x4Cb [0 + 0 * 4] = ((cmBodyBuf[5] >> 0)) & 0x3ff; + blk8x4Cr [0 + 0 * 4] = ((cmBodyBuf[6] << 6) + | (cmBodyBuf[5] >> 10)) & 0x3ff; + blk8x4Cb [0 + 1 * 4] = ((cmBodyBuf[6] >> 4)) & 0x3ff; + blk8x4Cr [0 + 1 * 4] = ((cmBodyBuf[7] << 2) + | (cmBodyBuf[6] >> 14)) & 0x3ff; + + blk8x4Luma[0 + 0 * 8] = ((cmBodyBuf[0 + 8] >> 0)) & 0x3ff; + blk8x4Luma[1 + 0 * 8] = ((cmBodyBuf[1 + 8] << 6) | + (cmBodyBuf[0 + 8] >> 10)) & 0x3ff; + blk8x4Luma[2 + 0 * 8] = ((cmBodyBuf[1 + 8] >> 4)) & 0x3ff; + blk8x4Luma[0 + 1 * 8] = ((cmBodyBuf[2 + 8] << 2) | + (cmBodyBuf[1 + 8] >> 14)) & 0x3ff; + blk8x4Luma[1 + 1 * 8] = ((cmBodyBuf[3 + 8] << 8) | + (cmBodyBuf[2 + 8] >> 8)) & 0x3ff; + blk8x4Luma[2 + 1 * 8] = ((cmBodyBuf[3 + 8] >> 2)) & 0x3ff; + blk8x4Luma[0 + 2 * 8] = ((cmBodyBuf[4 + 8] << 4) | + (cmBodyBuf[3 + 8] >> 12)) & 0x3ff; + blk8x4Luma[1 + 2 * 8] = ((cmBodyBuf[4 + 8] >> 6)) & 0x3ff; + blk8x4Luma[2 + 2 * 8] = ((cmBodyBuf[5 + 8] >> 0)) & 0x3ff; + blk8x4Luma[0 + 3 * 8] = ((cmBodyBuf[6 + 8] << 6) | + (cmBodyBuf[5 + 8] >> 10)) & 0x3ff; + blk8x4Luma[1 + 3 * 8] = ((cmBodyBuf[6 + 8] >> 4)) & 0x3ff; + blk8x4Luma[2 + 3 * 8] = ((cmBodyBuf[7 + 8] << 2) | + (cmBodyBuf[6 + 8] >> 14)) & 0x3ff; + + blk8x4Luma[4 + 0 * 8] = ((cmBodyBuf[0 + 16] >> 0)) & 0x3ff; + blk8x4Luma[5 + 0 * 8] = ((cmBodyBuf[1 + 16] << 6) | + (cmBodyBuf[0 + 16] >> 10)) & 0x3ff; + blk8x4Luma[6 + 0 * 8] = ((cmBodyBuf[1 + 16] >> 4)) & 0x3ff; + blk8x4Luma[4 + 1 * 8] = ((cmBodyBuf[2 + 16] << 2) | + (cmBodyBuf[1 + 16] >> 14)) & 0x3ff; + blk8x4Luma[5 + 1 * 8] = ((cmBodyBuf[3 + 16] << 8) | + (cmBodyBuf[2 + 16] >> 8)) & 0x3ff; + blk8x4Luma[6 + 1 * 8] = ((cmBodyBuf[3 + 16] >> 2)) & 0x3ff; + blk8x4Luma[4 + 2 * 8] = ((cmBodyBuf[4 + 16] << 4) | + (cmBodyBuf[3 + 16] >> 12)) & 0x3ff; + blk8x4Luma[5 + 2 * 8] = ((cmBodyBuf[4 + 16] >> 6)) & 0x3ff; + blk8x4Luma[6 + 2 * 8] = ((cmBodyBuf[5 + 16] >> 0)) & 0x3ff; + blk8x4Luma[4 + 3 * 8] = ((cmBodyBuf[6 + 16] << 6) | + (cmBodyBuf[5 + 16] >> 10)) & 0x3ff; + blk8x4Luma[5 + 3 * 8] = ((cmBodyBuf[6 + 16] >> 4)) & 0x3ff; + blk8x4Luma[6 + 3 * 8] = ((cmBodyBuf[7 + 16] << 2) | + (cmBodyBuf[6 + 16] >> 14)) & 0x3ff; + + blk8x4Cb[1 + 0 * 4] = ((cmBodyBuf[0 + 24] >> 0)) & 0x3ff; + blk8x4Cr[1 + 0 * 4] = ((cmBodyBuf[1 + 24] << 6) | + (cmBodyBuf[0 + 24] >> 10)) & 0x3ff; + blk8x4Cb[2 + 0 * 4] = ((cmBodyBuf[1 + 24] >> 4)) & 0x3ff; + blk8x4Cr[2 + 0 * 4] = ((cmBodyBuf[2 + 24] << 2) | + (cmBodyBuf[1 + 24] >> 14)) & 0x3ff; + blk8x4Cb[3 + 0 * 4] = ((cmBodyBuf[3 + 24] << 8) | + (cmBodyBuf[2 + 24] >> 8)) & 0x3ff; + blk8x4Cr[3 + 0 * 4] = ((cmBodyBuf[3 + 24] >> 2)) & 0x3ff; + blk8x4Cb[1 + 1 * 4] = ((cmBodyBuf[4 + 24] << 4) | + (cmBodyBuf[3 + 24] >> 12)) & 0x3ff; + blk8x4Cr[1 + 1 * 4] = ((cmBodyBuf[4 + 24] >> 6)) & 0x3ff; + blk8x4Cb[2 + 1 * 4] = ((cmBodyBuf[5 + 24] >> 0)) & 0x3ff; + blk8x4Cr[2 + 1 * 4] = ((cmBodyBuf[6 + 24] << 6) | + (cmBodyBuf[5 + 24] >> 10)) & 0x3ff; + blk8x4Cb[3 + 1 * 4] = ((cmBodyBuf[6 + 24] >> 4)) & 0x3ff; + blk8x4Cr[3 + 1 * 4] = ((cmBodyBuf[7 + 24] << 2) | + (cmBodyBuf[6 + 24] >> 14)) & 0x3ff; + } else { + cmBodyBuf[0 + 8 * 0] = (blk8x4Luma[3 + 1 * 8] << 10) | + blk8x4Luma[3 + 0 * 8]; + cmBodyBuf[1 + 8 * 0] = (blk8x4Luma[3 + 3 * 8] << 14) | + (blk8x4Luma[3 + 2 * 8] << 4) | (blk8x4Luma[3 + 1 * 8] >> 6); + cmBodyBuf[2 + 8 * 0] = (blk8x4Luma[7 + 0 * 8] << 8) | + (blk8x4Luma[3 + 3 * 8] >> 2); + cmBodyBuf[3 + 8 * 0] = (blk8x4Luma[7 + 2 * 8] << 12) | + (blk8x4Luma[7 + 1 * 8] << 2) | (blk8x4Luma[7 + 0 * 8] >>8); + cmBodyBuf[4 + 8 * 0] = (blk8x4Luma[7 + 3 * 8] << 6) | + (blk8x4Luma[7 + 2 * 8] >>4); + cmBodyBuf[5 + 8 * 0] = (blk8x4Cr[0 + 0 * 4] << 10) | + blk8x4Cb[0 + 0 * 4]; + cmBodyBuf[6 + 8 * 0] = (blk8x4Cr[0 + 1 * 4] << 14) | + (blk8x4Cb[0 + 1 * 4] << 4) | (blk8x4Cr[0 + 0 * 4] >> 6); + cmBodyBuf[7 + 8 * 0] = (0<< 8) | (blk8x4Cr[0 + 1 * 4] >> 2); + + cmBodyBuf[0 + 8 * 1] = (blk8x4Luma[1 + 0 * 8] << 10) | + blk8x4Luma[0 + 0 * 8]; + cmBodyBuf[1 + 8 * 1] = (blk8x4Luma[0 + 1 * 8] << 14) | + (blk8x4Luma[2 + 0 * 8] << 4) | (blk8x4Luma[1 + 0 * 8] >> 6); + cmBodyBuf[2 + 8 * 1] = (blk8x4Luma[1 + 1 * 8] << 8) | + (blk8x4Luma[0 + 1 * 8] >> 2); + cmBodyBuf[3 + 8 * 1] = (blk8x4Luma[0 + 2 * 8] << 12) | + (blk8x4Luma[2 + 1 * 8] << 2) | (blk8x4Luma[1 + 1 * 8] >>8); + cmBodyBuf[4 + 8 * 1] = (blk8x4Luma[1 + 2 * 8] << 6) | + (blk8x4Luma[0 + 2 * 8] >>4); + cmBodyBuf[5 + 8 * 1] = (blk8x4Luma[0 + 3 * 8] << 10) | + blk8x4Luma[2 + 2 * 8]; + cmBodyBuf[6 + 8 * 1] = (blk8x4Luma[2 + 3 * 8] << 14) | + (blk8x4Luma[1 + 3 * 8] << 4) | (blk8x4Luma[0 + 3 * 8] >> 6); + cmBodyBuf[7 + 8 * 1] = (0<< 8) | (blk8x4Luma[2 + 3 * 8] >> 2); + + cmBodyBuf[0 + 8 * 2] = (blk8x4Luma[5 + 0 * 8] << 10) | + blk8x4Luma[4 + 0 * 8]; + cmBodyBuf[1 + 8 * 2] = (blk8x4Luma[4 + 1 * 8] << 14) | + (blk8x4Luma[6 + 0 * 8] << 4) | (blk8x4Luma[5 + 0 * 8] >> 6); + cmBodyBuf[2 + 8 * 2] = (blk8x4Luma[5 + 1 * 8] << 8) | + (blk8x4Luma[4 + 1 * 8] >> 2); + cmBodyBuf[3 + 8 * 2] = (blk8x4Luma[4 + 2 * 8] << 12) | + (blk8x4Luma[6 + 1 * 8] << 2) | (blk8x4Luma[5 + 1 * 8] >>8); + cmBodyBuf[4 + 8 * 2] = (blk8x4Luma[5 + 2 * 8] << 6) | + (blk8x4Luma[4 + 2 * 8] >>4); + cmBodyBuf[5 + 8 * 2] = (blk8x4Luma[4 + 3 * 8] << 10) | + blk8x4Luma[6 + 2 * 8]; + cmBodyBuf[6 + 8 * 2] = (blk8x4Luma[6 + 3 * 8] << 14) | + (blk8x4Luma[5 + 3 * 8] << 4) | (blk8x4Luma[4 + 3 * 8] >> 6); + cmBodyBuf[7 + 8 * 2] = (0<< 8) | (blk8x4Luma[6 + 3 * 8] >> 2); + + cmBodyBuf[0 + 8 * 3] = (blk8x4Cr[1 + 0 * 4] << 10) | + blk8x4Cb[1 + 0 * 4]; + cmBodyBuf[1 + 8 * 3] = (blk8x4Cr[2 + 0 * 4] << 14) | + (blk8x4Cb[2 + 0 * 4] << 4) | (blk8x4Cr[1 + 0 * 4] >> 6); + cmBodyBuf[2 + 8 * 3] = (blk8x4Cb[3 + 0 * 4] << 8) | + (blk8x4Cr[2 + 0 * 4] >> 2); + cmBodyBuf[3 + 8 * 3] = (blk8x4Cb[1 + 1 * 4] << 12) | + (blk8x4Cr[3 + 0 * 4] << 2) | (blk8x4Cb[3 + 0 * 4] >>8); + cmBodyBuf[4 + 8 * 3] = (blk8x4Cr[1 + 1 * 4] << 6) | + (blk8x4Cb[1 + 1 * 4] >>4); + cmBodyBuf[5 + 8 * 3] = (blk8x4Cr[2 + 1 * 4] << 10) | + blk8x4Cb[2 + 1 * 4]; + cmBodyBuf[6 + 8 * 3] = (blk8x4Cr[3 + 1 * 4] << 14) | + (blk8x4Cb[3 + 1 * 4] << 4) | (blk8x4Cr[2 + 1 * 4] >> 6); + cmBodyBuf[7 + 8 * 3] = (0 << 8) | (blk8x4Cr[3 + 1 * 4] >> 2); + } +} + +static void corrRefillWithAmrisc ( + struct hevc_state_s *hevc, + uint32_t cmHeaderBaseAddr, + uint32_t picWidth, + uint32_t ctuPosition) +{ + int32_t i; + uint16_t ctux = (ctuPosition>>16) & 0xffff; + uint16_t ctuy = (ctuPosition>> 0) & 0xffff; + int32_t aboveCtuAvailable = (ctuy) ? 1 : 0; + + uint16_t cmBodyBuf[32 * 18]; + + uint32_t pic_width_x64_pre = picWidth + 0x3f; + uint32_t pic_width_x64 = pic_width_x64_pre >> 6; + uint32_t stride64x64 = pic_width_x64 * 128; + uint32_t addr_offset64x64_abv = stride64x64 * + (aboveCtuAvailable ? ctuy - 1 : ctuy) + 128 * ctux; + uint32_t addr_offset64x64_cur = stride64x64*ctuy + 128 * ctux; + uint32_t cmHeaderAddrAbv = cmHeaderBaseAddr + addr_offset64x64_abv; + uint32_t cmHeaderAddrCur = cmHeaderBaseAddr + addr_offset64x64_cur; + unsigned int tmpData32; + + uint16_t blkBuf0Y[32]; + uint16_t blkBuf0Cb[8]; + uint16_t blkBuf0Cr[8]; + uint16_t blkBuf1Y[32]; + uint16_t blkBuf1Cb[8]; + uint16_t blkBuf1Cr[8]; + int32_t blkBufCnt = 0; + + int32_t blkIdx; + + WRITE_VREG(HEVC_SAO_CTRL10, cmHeaderAddrAbv); + WRITE_VREG(HEVC_SAO_CTRL11, cmHeaderAddrCur); + WRITE_VREG(HEVC_SAO_DBG_MODE0, hevc->detbuf_adr); + WRITE_VREG(HEVC_SAO_DBG_MODE1, 2); + + for (i = 0; i < 32 * 18; i++) + cmBodyBuf[i] = 0; + + hevc_print(hevc, H265_DEBUG_BUFMGR_MORE, + "%s, %d\n", __func__, __LINE__); + do { + tmpData32 = READ_VREG(HEVC_SAO_DBG_MODE1); + } while (tmpData32); + hevc_print(hevc, H265_DEBUG_BUFMGR_MORE, + "%s, %d\n", __func__, __LINE__); + + hevc_print(hevc, H265_DEBUG_DETAIL, + "cmBodyBuf from detbuf:\n"); + for (i = 0; i < 32 * 18; i++) { + cmBodyBuf[i] = hevc->detbuf_adr_virt[i]; + if (get_dbg_flag(hevc) & + H265_DEBUG_DETAIL) { + if ((i & 0xf) == 0) + hevc_print_cont(hevc, 0, "\n"); + hevc_print_cont(hevc, 0, "%02x ", cmBodyBuf[i]); + } + } + hevc_print_cont(hevc, H265_DEBUG_DETAIL, "\n"); + + for (i = 0; i < 32; i++) + blkBuf0Y[i] = 0; + for (i = 0; i < 8; i++) + blkBuf0Cb[i] = 0; + for (i = 0; i < 8; i++) + blkBuf0Cr[i] = 0; + for (i = 0; i < 32; i++) + blkBuf1Y[i] = 0; + for (i = 0; i < 8; i++) + blkBuf1Cb[i] = 0; + for (i = 0; i < 8; i++) + blkBuf1Cr[i] = 0; + + for (blkIdx = 0; blkIdx < 18; blkIdx++) { + int32_t inAboveCtu = (blkIdx<2) ? 1 : 0; + int32_t restoreEnable = (blkIdx>0) ? 1 : 0; + uint16_t* blkY = (blkBufCnt==0) ? blkBuf0Y : blkBuf1Y ; + uint16_t* blkCb = (blkBufCnt==0) ? blkBuf0Cb : blkBuf1Cb; + uint16_t* blkCr = (blkBufCnt==0) ? blkBuf0Cr : blkBuf1Cr; + uint16_t* cmBodyBufNow = cmBodyBuf + (blkIdx * 32); + + if (!aboveCtuAvailable && inAboveCtu) + continue; + + /* detRefillBuf --> 8x4block*/ + convUnc8x4blk(blkY, blkCb, blkCr, cmBodyBufNow, 0); + + if (restoreEnable) { + blkY[3 + 0 * 8] = blkY[2 + 0 * 8] + 2; + blkY[4 + 0 * 8] = blkY[1 + 0 * 8] + 3; + blkY[5 + 0 * 8] = blkY[0 + 0 * 8] + 1; + blkY[6 + 0 * 8] = blkY[0 + 0 * 8] + 2; + blkY[7 + 0 * 8] = blkY[1 + 0 * 8] + 2; + blkY[3 + 1 * 8] = blkY[2 + 1 * 8] + 1; + blkY[4 + 1 * 8] = blkY[1 + 1 * 8] + 2; + blkY[5 + 1 * 8] = blkY[0 + 1 * 8] + 2; + blkY[6 + 1 * 8] = blkY[0 + 1 * 8] + 2; + blkY[7 + 1 * 8] = blkY[1 + 1 * 8] + 3; + blkY[3 + 2 * 8] = blkY[2 + 2 * 8] + 3; + blkY[4 + 2 * 8] = blkY[1 + 2 * 8] + 1; + blkY[5 + 2 * 8] = blkY[0 + 2 * 8] + 3; + blkY[6 + 2 * 8] = blkY[0 + 2 * 8] + 3; + blkY[7 + 2 * 8] = blkY[1 + 2 * 8] + 3; + blkY[3 + 3 * 8] = blkY[2 + 3 * 8] + 0; + blkY[4 + 3 * 8] = blkY[1 + 3 * 8] + 0; + blkY[5 + 3 * 8] = blkY[0 + 3 * 8] + 1; + blkY[6 + 3 * 8] = blkY[0 + 3 * 8] + 2; + blkY[7 + 3 * 8] = blkY[1 + 3 * 8] + 1; + blkCb[1 + 0 * 4] = blkCb[0 + 0 * 4]; + blkCb[2 + 0 * 4] = blkCb[0 + 0 * 4]; + blkCb[3 + 0 * 4] = blkCb[0 + 0 * 4]; + blkCb[1 + 1 * 4] = blkCb[0 + 1 * 4]; + blkCb[2 + 1 * 4] = blkCb[0 + 1 * 4]; + blkCb[3 + 1 * 4] = blkCb[0 + 1 * 4]; + blkCr[1 + 0 * 4] = blkCr[0 + 0 * 4]; + blkCr[2 + 0 * 4] = blkCr[0 + 0 * 4]; + blkCr[3 + 0 * 4] = blkCr[0 + 0 * 4]; + blkCr[1 + 1 * 4] = blkCr[0 + 1 * 4]; + blkCr[2 + 1 * 4] = blkCr[0 + 1 * 4]; + blkCr[3 + 1 * 4] = blkCr[0 + 1 * 4]; + + /*Store data back to DDR*/ + convUnc8x4blk(blkY, blkCb, blkCr, cmBodyBufNow, 1); + } + + blkBufCnt = (blkBufCnt==1) ? 0 : blkBufCnt + 1; + } + + hevc_print(hevc, H265_DEBUG_DETAIL, + "cmBodyBuf to detbuf:\n"); + for (i = 0; i < 32 * 18; i++) { + hevc->detbuf_adr_virt[i] = cmBodyBuf[i]; + if (get_dbg_flag(hevc) & + H265_DEBUG_DETAIL) { + if ((i & 0xf) == 0) + hevc_print_cont(hevc, 0, "\n"); + hevc_print_cont(hevc, 0, "%02x ", cmBodyBuf[i]); + } + } + hevc_print_cont(hevc, H265_DEBUG_DETAIL, "\n"); + + WRITE_VREG(HEVC_SAO_DBG_MODE1, 3); + hevc_print(hevc, H265_DEBUG_BUFMGR_MORE, + "%s, %d\n", __func__, __LINE__); + do { + tmpData32 = READ_VREG(HEVC_SAO_DBG_MODE1); + } while (tmpData32); + hevc_print(hevc, H265_DEBUG_BUFMGR_MORE, + "%s, %d\n", __func__, __LINE__); +} + +static void delrefill(struct hevc_state_s *hevc) +{ + /* + * corrRefill + */ + /*HEVC_SAO_DBG_MODE0: picGlobalVariable + [31:30]error number + [29:20]error2([9:7]tilex[6:0]ctuy) + [19:10]error1 [9:0]error0*/ + uint32_t detResult = READ_VREG(HEVC_ASSIST_SCRATCH_3); + uint32_t errorIdx; + uint32_t errorNum = (detResult>>30); + + if (detResult) { + hevc_print(hevc, H265_DEBUG_BUFMGR, + "[corrRefillWithAmrisc] detResult=%08x\n", detResult); + for (errorIdx = 0; errorIdx < errorNum; errorIdx++) { + uint32_t errorPos = errorIdx * 10; + uint32_t errorResult = (detResult >> errorPos) & 0x3ff; + uint32_t tilex = (errorResult >> 7) - 1; + uint16_t ctux = hevc->m_tile[0][tilex].start_cu_x + + hevc->m_tile[0][tilex].width - 1; + uint16_t ctuy = (uint16_t)(errorResult & 0x7f); + uint32_t ctuPosition = (ctux<< 16) + ctuy; + hevc_print(hevc, H265_DEBUG_BUFMGR, + "Idx:%d tilex:%d ctu(%d(0x%x), %d(0x%x))\n", + errorIdx,tilex,ctux,ctux, ctuy,ctuy); + corrRefillWithAmrisc( + hevc, + (uint32_t)hevc->cur_pic->header_adr, + hevc->pic_w, + ctuPosition); + } + + WRITE_VREG(HEVC_ASSIST_SCRATCH_3, 0); /*clear status*/ + WRITE_VREG(HEVC_SAO_DBG_MODE0, 0); + WRITE_VREG(HEVC_SAO_DBG_MODE1, 1); + } +} +#endif + static void get_rpm_param(union param_u *params) { int i; @@ -2044,10 +2606,8 @@ static unsigned int log2i(unsigned int val) } static int init_buf_spec(struct hevc_state_s *hevc); - static void uninit_mmu_buffers(struct hevc_state_s *hevc) { - if (hevc->mmu_box) decoder_mmu_box_free(hevc->mmu_box); hevc->mmu_box = NULL; @@ -2069,8 +2629,10 @@ static int init_mmu_buffers(struct hevc_state_s *hevc) hevc_print(hevc, 0, "%s max_w %d max_h %d\n", __func__, hevc->max_pic_w, hevc->max_pic_h); } - - if (hevc->mmu_enable) { + hevc->need_cache_size = buf_size * SZ_1M; + hevc->sc_start_time = get_jiffies_64(); + if (hevc->mmu_enable + && ((get_double_write_mode(hevc) & 0x10) == 0)) { hevc->mmu_box = decoder_mmu_box_alloc_box(DRIVER_NAME, hevc->index, MAX_REF_PIC_NUM, @@ -2082,6 +2644,7 @@ static int init_mmu_buffers(struct hevc_state_s *hevc) return -1; } } + hevc->bmmu_box = decoder_bmmu_box_alloc_box(DRIVER_NAME, hevc->index, BMMU_MAX_BUFFERS, @@ -2164,19 +2727,28 @@ static int alloc_mv_buf(struct hevc_state_s *hevc, int i) static int get_mv_buf(struct hevc_state_s *hevc, struct PIC_s *pic) { #ifdef MV_USE_FIXED_BUF - if (pic && pic->index >= 0) - pic->mpred_mv_wr_start_addr = - hevc->work_space_buf->mpred_mv.buf_start - + (pic->index * MPRED_MV_BUF_SIZE); + if (pic && pic->index >= 0) { + if (IS_8K_SIZE(pic->width, pic->height)) { + pic->mpred_mv_wr_start_addr = + hevc->work_space_buf->mpred_mv.buf_start + + (pic->index * MPRED_8K_MV_BUF_SIZE); + } else { + pic->mpred_mv_wr_start_addr = + hevc->work_space_buf->mpred_mv.buf_start + + (pic->index * MPRED_4K_MV_BUF_SIZE); + } + } return 0; #else int i; int ret = -1; int new_size; - if (pic->width > 1920 || pic->height > 1088) - new_size = MPRED_MV_BUF_SIZE + 0x10000; /*0x120000*/ + if (IS_8K_SIZE(pic->width, pic->height)) + new_size = MPRED_8K_MV_BUF_SIZE + 0x10000; + else if (IS_4K_SIZE(pic->width, pic->height)) + new_size = MPRED_4K_MV_BUF_SIZE + 0x10000; /*0x120000*/ else - new_size = 0x40000 + 0x10000; + new_size = MPRED_MV_BUF_SIZE + 0x10000; if (new_size != hevc->mv_buf_size) { dealloc_mv_bufs(hevc); hevc->mv_buf_size = new_size; @@ -2270,11 +2842,15 @@ static int cal_current_buf_size(struct hevc_state_s *hevc, int dw_mode = get_double_write_mode(hevc); - if (hevc->mmu_enable) - buf_size = - ((MMU_COMPRESS_HEADER_SIZE + 0xffff) >> 16) - << 16; - else + if (hevc->mmu_enable) { + if ((get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) && + (IS_8K_SIZE(hevc->pic_w, hevc->pic_h))) + buf_size = ((MMU_COMPRESS_8K_HEADER_SIZE + 0xffff) >> 16) + << 16; + else + buf_size = ((MMU_COMPRESS_HEADER_SIZE + 0xffff) >> 16) + << 16; + } else buf_size = 0; if (dw_mode) { @@ -2426,9 +3002,22 @@ static void dealloc_pic_buf(struct hevc_state_s *hevc, static int get_work_pic_num(struct hevc_state_s *hevc) { int used_buf_num = 0; + int sps_pic_buf_diff = 0; + if (get_dynamic_buf_num_margin(hevc) > 0) { - used_buf_num = hevc->sps_num_reorder_pics_0 - + get_dynamic_buf_num_margin(hevc); + if ((!hevc->sps_num_reorder_pics_0) && + (hevc->param.p.sps_max_dec_pic_buffering_minus1_0)) { + /* the range of sps_num_reorder_pics_0 is in + [0, sps_max_dec_pic_buffering_minus1_0] */ + used_buf_num = get_dynamic_buf_num_margin(hevc) + + hevc->param.p.sps_max_dec_pic_buffering_minus1_0; + } else + used_buf_num = hevc->sps_num_reorder_pics_0 + + get_dynamic_buf_num_margin(hevc); + + sps_pic_buf_diff = hevc->param.p.sps_max_dec_pic_buffering_minus1_0 + - hevc->sps_num_reorder_pics_0; + #ifdef MULTI_INSTANCE_SUPPORT /* need one more for multi instance, as @@ -2441,6 +3030,16 @@ static int get_work_pic_num(struct hevc_state_s *hevc) } else used_buf_num = max_buf_num; + if (hevc->save_buffer_mode) + hevc_print(hevc, 0, + "save buf _mode : dynamic_buf_num_margin %d ----> %d \n", + dynamic_buf_num_margin, hevc->dynamic_buf_num_margin); + + if (sps_pic_buf_diff >= 4) + { + used_buf_num += 1; + } + if (used_buf_num > MAX_BUF_NUM) used_buf_num = MAX_BUF_NUM; return used_buf_num; @@ -2488,7 +3087,13 @@ static int config_pic(struct hevc_state_s *hevc, struct PIC_s *pic) if (hevc->mmu_enable) { pic->header_adr = hevc->m_BUF[i].start_adr; - y_adr = hevc->m_BUF[i].start_adr + MMU_COMPRESS_HEADER_SIZE; + if ((get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) && + (IS_8K_SIZE(hevc->pic_w, hevc->pic_h))) + y_adr = hevc->m_BUF[i].start_adr + + MMU_COMPRESS_8K_HEADER_SIZE; + else + y_adr = hevc->m_BUF[i].start_adr + + MMU_COMPRESS_HEADER_SIZE; } else y_adr = hevc->m_BUF[i].start_adr; @@ -2546,7 +3151,7 @@ static void init_pic_list(struct hevc_state_s *hevc) int i; int init_buf_num = get_work_pic_num(hevc); int dw_mode = get_double_write_mode(hevc); - + struct vdec_s *vdec = hw_to_vdec(hevc); /*alloc decoder buf*/ for (i = 0; i < init_buf_num; i++) { if (alloc_buf(hevc) < 0) { @@ -2574,6 +3179,10 @@ static void init_pic_list(struct hevc_state_s *hevc) pic->index = i; pic->BUF_index = -1; pic->mv_buf_index = -1; + if (vdec->parallel_dec == 1) { + pic->y_canvas_index = -1; + pic->uv_canvas_index = -1; + } if (config_pic(hevc, pic) < 0) { if (get_dbg_flag(hevc)) hevc_print(hevc, 0, @@ -2602,12 +3211,17 @@ static void init_pic_list(struct hevc_state_s *hevc) hevc->m_PIC[i] = pic; pic->index = -1; pic->BUF_index = -1; + if (vdec->parallel_dec == 1) { + pic->y_canvas_index = -1; + pic->uv_canvas_index = -1; + } } } static void uninit_pic_list(struct hevc_state_s *hevc) { + struct vdec_s *vdec = hw_to_vdec(hevc); int i; #ifndef MV_USE_FIXED_BUF dealloc_mv_bufs(hevc); @@ -2616,6 +3230,10 @@ static void uninit_pic_list(struct hevc_state_s *hevc) struct PIC_s *pic = hevc->m_PIC[i]; if (pic) { + if (vdec->parallel_dec == 1) { + vdec->free_canvas_ex(pic->y_canvas_index, vdec->id); + vdec->free_canvas_ex(pic->uv_canvas_index, vdec->id); + } release_aux_data(hevc, pic); vfree(pic); hevc->m_PIC[i] = NULL; @@ -2689,7 +3307,7 @@ static void init_pic_list_hw(struct hevc_state_s *hevc) int i; int cur_pic_num = MAX_REF_PIC_NUM; int dw_mode = get_double_write_mode(hevc); - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXL) + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXL) WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CONF_ADDR, (0x1 << 1) | (0x1 << 2)); else @@ -2701,8 +3319,8 @@ static void init_pic_list_hw(struct hevc_state_s *hevc) cur_pic_num = i; break; } - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXL) { - if (hevc->mmu_enable) + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXL) { + if (hevc->mmu_enable && ((dw_mode & 0x10) == 0)) WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_DATA, hevc->m_PIC[i]->header_adr>>5); else @@ -2713,11 +3331,7 @@ static void init_pic_list_hw(struct hevc_state_s *hevc) hevc->m_PIC[i]->mc_y_adr | (hevc->m_PIC[i]->mc_canvas_y << 8) | 0x1); if (dw_mode & 0x10) { - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXL) { - if (hevc->mmu_enable) - WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_DATA, - hevc->m_PIC[i]->header_adr>>5); - else + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXL) { WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_DATA, hevc->m_PIC[i]->mc_u_v_adr >> 5); } @@ -2731,8 +3345,8 @@ static void init_pic_list_hw(struct hevc_state_s *hevc) if (cur_pic_num == 0) return; for (; i < MAX_REF_PIC_NUM; i++) { - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXL) { - if (hevc->mmu_enable) + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXL) { + if (hevc->mmu_enable && ((dw_mode & 0x10) == 0)) WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_DATA, hevc->m_PIC[cur_pic_num-1]->header_adr>>5); else @@ -2818,6 +3432,18 @@ static void clear_referenced_flag(struct hevc_state_s *hevc) } } +static void clear_poc_flag(struct hevc_state_s *hevc) +{ + int i; + struct PIC_s *pic; + for (i = 0; i < MAX_REF_PIC_NUM; i++) { + pic = hevc->m_PIC[i]; + if (pic == NULL || pic->index == -1) + continue; + pic->POC = INVALID_POC; + } +} + static struct PIC_s *output_pic(struct hevc_state_s *hevc, unsigned char flush_flag) { @@ -2911,6 +3537,10 @@ static struct PIC_s *output_pic(struct hevc_state_s *hevc, pic_display = NULL; } } + if (pic_display && (hevc->vf_pre_count == 1) && (hevc->first_pic_flag == 1)) { + pic_display = NULL; + hevc->first_pic_flag = 0; + } return pic_display; } @@ -2940,7 +3570,7 @@ static int config_mc_buffer(struct hevc_state_s *hevc, struct PIC_s *cur_pic) pic->width, pic->height); cur_pic->error_mark = 1; } - if (pic->error_mark) + if (pic->error_mark && (ref_frame_mark_flag[hevc->index])) cur_pic->error_mark = 1; WRITE_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR, (pic->mc_canvas_u_v << 16) @@ -2975,6 +3605,7 @@ static int config_mc_buffer(struct hevc_state_s *hevc, struct PIC_s *cur_pic) "config_mc_buffer RefNum_L1\n"); WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR, (16 << 8) | (0 << 1) | 1); + for (i = 0; i < cur_pic->RefNum_L1; i++) { pic = get_ref_pic_by_POC(hevc, @@ -2991,7 +3622,7 @@ static int config_mc_buffer(struct hevc_state_s *hevc, struct PIC_s *cur_pic) cur_pic->error_mark = 1; } - if (pic->error_mark) + if (pic->error_mark && (ref_frame_mark_flag[hevc->index])) cur_pic->error_mark = 1; WRITE_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR, (pic->mc_canvas_u_v << 16) @@ -3032,6 +3663,7 @@ static void apply_ref_pic_set(struct hevc_state_s *hevc, int cur_poc, unsigned char is_referenced; /* hevc_print(hevc, 0, "%s cur_poc %d\n", __func__, cur_poc); */ + for (ii = 0; ii < MAX_REF_PIC_NUM; ii++) { pic = hevc->m_PIC[ii]; if (pic == NULL || @@ -3270,6 +3902,26 @@ static void update_tile_info(struct hevc_state_s *hevc, int pic_width_cu, int start_cu_x, start_cu_y; int sao_vb_size = (sao_mem_unit + (2 << 4)) * pic_height_cu; int sao_abv_size = sao_mem_unit * pic_width_cu; +#ifdef DETREFILL_ENABLE + if (hevc->is_swap && get_cpu_major_id() <= AM_MESON_CPU_MAJOR_ID_GXM) { + int tmpRefillLcuSize = 1 << + (params->p.log2_min_coding_block_size_minus3 + + 3 + params->p.log2_diff_max_min_coding_block_size); + hevc_print(hevc, H265_DEBUG_BUFMGR_MORE, + "%x, %x, %x, %x\n", + params->p.slice_segment_address, + params->p.bit_depth, + params->p.tiles_enabled_flag, + tmpRefillLcuSize); + if (params->p.slice_segment_address == 0 && + params->p.bit_depth != 0 && + (params->p.tiles_enabled_flag & 1) && + tmpRefillLcuSize == 64) + hevc->delrefill_check = 1; + else + hevc->delrefill_check = 0; + } +#endif hevc->tile_enabled = params->p.tiles_enabled_flag & 1; if (params->p.tiles_enabled_flag & 1) { @@ -3476,7 +4128,7 @@ static void hevc_config_work_space_hw(struct hevc_state_s *hevc) struct BuffInfo_s *buf_spec = hevc->work_space_buf; if (get_dbg_flag(hevc)) - hevc_print(hevc, 0, + hevc_print(hevc, H265_DEBUG_BUFMGR_MORE, "%s %x %x %x %x %x %x %x %x %x %x %x %x %x\n", __func__, buf_spec->ipp.buf_start, @@ -3501,7 +4153,7 @@ static void hevc_config_work_space_hw(struct hevc_state_s *hevc) WRITE_VREG(HEVC_PPS_BUFFER, buf_spec->pps.buf_start); WRITE_VREG(HEVC_SAO_UP, buf_spec->sao_up.buf_start); if (hevc->mmu_enable) { - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) { + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A) { WRITE_VREG(HEVC_ASSIST_MMU_MAP_ADDR, hevc->frame_mmu_map_phy_addr); hevc_print(hevc, H265_DEBUG_BUFMGR_MORE, "write HEVC_ASSIST_MMU_MAP_ADDR\n"); @@ -3544,7 +4196,7 @@ static void hevc_init_decoder_hw(struct hevc_state_s *hevc, unsigned int data32; int i; #if 0 - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) { + if (get_cpu_major_id() >= MESON_CPU_MAJOR_ID_G12A) { /* Set MCR fetch priorities*/ data32 = 0x1 | (0x1 << 2) | (0x1 <<3) | (24 << 4) | (32 << 11) | (24 << 18) | (32 << 25); @@ -3589,7 +4241,7 @@ static void hevc_init_decoder_hw(struct hevc_state_s *hevc, if (!hevc->m_ins_flag) { data32 = READ_VREG(HEVC_STREAM_CONTROL); data32 = data32 | (1 << 0); /* stream_fetch_enable */ - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A) data32 |= (0xf << 25); /*arwlen_axi_max*/ WRITE_VREG(HEVC_STREAM_CONTROL, data32); } @@ -3919,13 +4571,24 @@ static void config_title_hw(struct hevc_state_s *hevc, int sao_vb_size, WRITE_VREG(HEVC_SAO_VB, hevc->work_space_buf->sao_vb.buf_start); } +static u32 init_aux_size; +static int aux_data_is_avaible(struct hevc_state_s *hevc) +{ + u32 reg_val; + + reg_val = READ_VREG(HEVC_AUX_DATA_SIZE); + if (reg_val != 0 && reg_val != init_aux_size) + return 1; + else + return 0; +} + static void config_aux_buf(struct hevc_state_s *hevc) { WRITE_VREG(HEVC_AUX_ADR, hevc->aux_phy_addr); - WRITE_VREG(HEVC_AUX_DATA_SIZE, - ((hevc->prefix_aux_size >> 4) << 16) | - (hevc->suffix_aux_size >> 4) - ); + init_aux_size = ((hevc->prefix_aux_size >> 4) << 16) | + (hevc->suffix_aux_size >> 4); + WRITE_VREG(HEVC_AUX_DATA_SIZE, init_aux_size); } static void config_mpred_hw(struct hevc_state_s *hevc) @@ -4227,9 +4890,13 @@ static void config_sao_hw(struct hevc_state_s *hevc, union param_u *params) #endif /* DBLK CONFIG HERE */ if (hevc->new_pic) { - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) { - data32 = (0x57 << 8) | /* 1st/2nd write both enable*/ - (0x0 << 0); /* h265 video format*/ + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A) { + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) + data32 = (0xff << 8) | (0x0 << 0); + else + data32 = (0x57 << 8) | /* 1st/2nd write both enable*/ + (0x0 << 0); /* h265 video format*/ + if (hevc->pic_w >= 1280) data32 |= (0x1 << 4); /*dblk pipeline mode=1 for performance*/ data32 &= (~0x300); /*[8]:first write enable (compress) [9]:double write enable (uncompress)*/ @@ -4244,7 +4911,6 @@ static void config_sao_hw(struct hevc_state_s *hevc, union param_u *params) hevc_print(hevc, H265_DEBUG_BUFMGR_MORE, "[DBLK DEBUG] HEVC1 CFGB : 0x%x\n", data32); } - data32 = (hevc->pic_w | hevc->pic_h << 16); WRITE_VREG(HEVC_DBLK_CFG2, data32); @@ -4266,7 +4932,7 @@ static void config_sao_hw(struct hevc_state_s *hevc, union param_u *params) WRITE_VREG(HEVC_DBLK_CFG1, data32); - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) { + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A) { /*if (debug & 0x80) {*/ data32 = 1 << 28; /* Debug only: sts1 chooses dblk_main*/ WRITE_VREG(HEVC_DBLK_STS1 + 4, data32); /* 0x3510 */ @@ -4274,7 +4940,7 @@ static void config_sao_hw(struct hevc_state_s *hevc, union param_u *params) "[DBLK DEBUG] HEVC1 STS1 : 0x%x\n", data32); /*}*/ - } + } } #if 0 data32 = READ_VREG(HEVC_SAO_CTRL1); @@ -4309,15 +4975,32 @@ static void config_sao_hw(struct hevc_state_s *hevc, union param_u *params) data32 &= (~0xff0); /* data32 |= 0x670; // Big-Endian per 64-bit */ data32 |= endian; /* Big-Endian per 64-bit */ - if (get_cpu_type() < MESON_CPU_MAJOR_ID_G12A) { + if (get_cpu_major_id() < AM_MESON_CPU_MAJOR_ID_G12A) { data32 &= (~0x3); /*[1]:dw_disable [0]:cm_disable*/ if (get_double_write_mode(hevc) == 0) data32 |= 0x2; /*disable double write*/ - else if (!hevc->mmu_enable && (get_double_write_mode(hevc) & 0x10)) + else if (get_double_write_mode(hevc) & 0x10) data32 |= 0x1; /*disable cm*/ - } - WRITE_VREG(HEVC_SAO_CTRL1, data32); + } else { + unsigned int data; + data = (0x57 << 8) | /* 1st/2nd write both enable*/ + (0x0 << 0); /* h265 video format*/ + if (hevc->pic_w >= 1280) + data |= (0x1 << 4); /*dblk pipeline mode=1 for performance*/ + data &= (~0x300); /*[8]:first write enable (compress) [9]:double write enable (uncompress)*/ + if (get_double_write_mode(hevc) == 0) + data |= (0x1 << 8); /*enable first write*/ + else if (get_double_write_mode(hevc) & 0x10) + data |= (0x1 << 9); /*double write only*/ + else + data |= ((0x1 << 8) |(0x1 << 9)); + WRITE_VREG(HEVC_DBLK_CFGB, data); + hevc_print(hevc, H265_DEBUG_BUFMGR_MORE, + "[DBLK DEBUG] HEVC1 CFGB : 0x%x\n", data); + } + + WRITE_VREG(HEVC_SAO_CTRL1, data32); if (get_double_write_mode(hevc) & 0x10) { /* [23:22] dw_v1_ctrl *[21:20] dw_v0_ctrl @@ -4573,6 +5256,7 @@ static struct PIC_s *get_new_pic(struct hevc_state_s *hevc, rpm_param->p.bit_depth, hevc->frame_mmu_map_addr); if (ret != 0) { + put_mv_buf(hevc, new_pic); hevc_print(hevc, 0, "can't alloc need mmu1,idx %d ret =%d\n", new_pic->decode_idx, @@ -4600,6 +5284,21 @@ static struct PIC_s *get_new_pic(struct hevc_state_s *hevc, hevc->bit_depth_luma; new_pic->bit_depth_chroma = hevc->bit_depth_chroma; + new_pic->video_signal_type = + hevc->video_signal_type; + + new_pic->conformance_window_flag = + hevc->param.p.conformance_window_flag; + new_pic->conf_win_left_offset = + hevc->param.p.conf_win_left_offset; + new_pic->conf_win_right_offset = + hevc->param.p.conf_win_right_offset; + new_pic->conf_win_top_offset = + hevc->param.p.conf_win_top_offset; + new_pic->conf_win_bottom_offset = + hevc->param.p.conf_win_bottom_offset; + new_pic->chroma_format_idc = + hevc->param.p.chroma_format_idc; hevc_print(hevc, H265_DEBUG_BUFMGR_MORE, "%s: index %d, buf_idx %d, decode_idx %d, POC %d\n", @@ -4713,8 +5412,20 @@ static void set_aux_data(struct hevc_state_s *hevc, READ_VREG(HEVC_AUX_DATA_SIZE); unsigned int aux_count = 0; int aux_size = 0; - if (pic == NULL) + if (pic == NULL || 0 == aux_data_is_avaible(hevc)) return; + + if (hevc->aux_data_dirty || + hevc->m_ins_flag == 0) { + dma_sync_single_for_cpu( + amports_get_dma_device(), + hevc->aux_phy_addr, + hevc->prefix_aux_size + hevc->suffix_aux_size, + DMA_FROM_DEVICE); + + hevc->aux_data_dirty = 0; + } + if (suffix_flag) { aux_adr = (unsigned short *) (hevc->aux_addr + @@ -4735,8 +5446,8 @@ static void set_aux_data(struct hevc_state_s *hevc, } if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR_MORE) { hevc_print(hevc, 0, - "%s:old size %d count %d,suf %d dv_flag %d\r\n", - __func__, pic->aux_data_size, + "%s:pic 0x%p old size %d count %d,suf %d dv_flag %d\r\n", + __func__, pic, pic->aux_data_size, aux_count, suffix_flag, dv_meta_flag); } if (aux_size > 0 && aux_count > 0) { @@ -4902,7 +5613,8 @@ static inline void hevc_pre_pic(struct hevc_state_s *hevc, hevc->ignore_bufmgr_error |= 0x2; } } - if (hevc->mmu_enable) { + if (hevc->mmu_enable + && ((hevc->double_write_mode & 0x10) == 0)) { if (!hevc->m_ins_flag) { hevc->used_4k_num = READ_VREG(HEVC_SAO_MMU_STATUS) >> 16; @@ -5039,6 +5751,15 @@ static void check_pic_decoded_error_pre(struct hevc_state_s *hevc, hevc_print(hevc, 0, "head has error, set error_mark\n"); } + + if ((error_handle_policy & 0x80) == 0) { + if (hevc->over_decode && hevc->cur_pic) { + hevc_print(hevc, 0, + "over decode, set error_mark\n"); + hevc->cur_pic->error_mark = 1; + } + } + hevc->lcu_x_num_pre = hevc->lcu_x_num; hevc->lcu_y_num_pre = hevc->lcu_y_num; } @@ -5092,6 +5813,431 @@ static void check_pic_decoded_error(struct hevc_state_s *hevc, } } +/* only when we decoded one field or one frame, +we can call this function to get qos info*/ +static void get_picture_qos_info(struct hevc_state_s *hevc) +{ + struct PIC_s *picture = hevc->cur_pic; + +/* +#define DEBUG_QOS +*/ + + if (!hevc->cur_pic) + return; + + if (get_cpu_major_id() < AM_MESON_CPU_MAJOR_ID_G12A) { + unsigned char a[3]; + unsigned char i, j, t; + unsigned long data; + + data = READ_VREG(HEVC_MV_INFO); + if (picture->slice_type == I_SLICE) + data = 0; + a[0] = data & 0xff; + a[1] = (data >> 8) & 0xff; + a[2] = (data >> 16) & 0xff; + + for (i = 0; i < 3; i++) + for (j = i+1; j < 3; j++) { + if (a[j] < a[i]) { + t = a[j]; + a[j] = a[i]; + a[i] = t; + } else if (a[j] == a[i]) { + a[i]++; + t = a[j]; + a[j] = a[i]; + a[i] = t; + } + } + picture->max_mv = a[2]; + picture->avg_mv = a[1]; + picture->min_mv = a[0]; +#ifdef DEBUG_QOS + hevc_print(hevc, 0, "mv data %x a[0]= %x a[1]= %x a[2]= %x\n", + data, a[0], a[1], a[2]); +#endif + + data = READ_VREG(HEVC_QP_INFO); + a[0] = data & 0x1f; + a[1] = (data >> 8) & 0x3f; + a[2] = (data >> 16) & 0x7f; + + for (i = 0; i < 3; i++) + for (j = i+1; j < 3; j++) { + if (a[j] < a[i]) { + t = a[j]; + a[j] = a[i]; + a[i] = t; + } else if (a[j] == a[i]) { + a[i]++; + t = a[j]; + a[j] = a[i]; + a[i] = t; + } + } + picture->max_qp = a[2]; + picture->avg_qp = a[1]; + picture->min_qp = a[0]; +#ifdef DEBUG_QOS + hevc_print(hevc, 0, "qp data %x a[0]= %x a[1]= %x a[2]= %x\n", + data, a[0], a[1], a[2]); +#endif + + data = READ_VREG(HEVC_SKIP_INFO); + a[0] = data & 0x1f; + a[1] = (data >> 8) & 0x3f; + a[2] = (data >> 16) & 0x7f; + + for (i = 0; i < 3; i++) + for (j = i+1; j < 3; j++) { + if (a[j] < a[i]) { + t = a[j]; + a[j] = a[i]; + a[i] = t; + } else if (a[j] == a[i]) { + a[i]++; + t = a[j]; + a[j] = a[i]; + a[i] = t; + } + } + picture->max_skip = a[2]; + picture->avg_skip = a[1]; + picture->min_skip = a[0]; + +#ifdef DEBUG_QOS + hevc_print(hevc, 0, + "skip data %x a[0]= %x a[1]= %x a[2]= %x\n", + data, a[0], a[1], a[2]); +#endif + } else { + uint32_t blk88_y_count; + uint32_t blk88_c_count; + uint32_t blk22_mv_count; + uint32_t rdata32; + int32_t mv_hi; + int32_t mv_lo; + uint32_t rdata32_l; + uint32_t mvx_L0_hi; + uint32_t mvy_L0_hi; + uint32_t mvx_L1_hi; + uint32_t mvy_L1_hi; + int64_t value; + uint64_t temp_value; +#ifdef DEBUG_QOS + int pic_number = picture->POC; +#endif + + picture->max_mv = 0; + picture->avg_mv = 0; + picture->min_mv = 0; + + picture->max_skip = 0; + picture->avg_skip = 0; + picture->min_skip = 0; + + picture->max_qp = 0; + picture->avg_qp = 0; + picture->min_qp = 0; + + + +#ifdef DEBUG_QOS + hevc_print(hevc, 0, "slice_type:%d, poc:%d\n", + picture->slice_type, + picture->POC); +#endif + /* set rd_idx to 0 */ + WRITE_VREG(HEVC_PIC_QUALITY_CTRL, 0); + + blk88_y_count = READ_VREG(HEVC_PIC_QUALITY_DATA); + if (blk88_y_count == 0) { +#ifdef DEBUG_QOS + hevc_print(hevc, 0, + "[Picture %d Quality] NO Data yet.\n", + pic_number); +#endif + /* reset all counts */ + WRITE_VREG(HEVC_PIC_QUALITY_CTRL, (1<<8)); + return; + } + /* qp_y_sum */ + rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA); +#ifdef DEBUG_QOS + hevc_print(hevc, 0, + "[Picture %d Quality] Y QP AVG : %d (%d/%d)\n", + pic_number, rdata32/blk88_y_count, + rdata32, blk88_y_count); +#endif + picture->avg_qp = rdata32/blk88_y_count; + /* intra_y_count */ + rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA); +#ifdef DEBUG_QOS + hevc_print(hevc, 0, + "[Picture %d Quality] Y intra rate : %d%c (%d)\n", + pic_number, rdata32*100/blk88_y_count, + '%', rdata32); +#endif + /* skipped_y_count */ + rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA); +#ifdef DEBUG_QOS + hevc_print(hevc, 0, + "[Picture %d Quality] Y skipped rate : %d%c (%d)\n", + pic_number, rdata32*100/blk88_y_count, + '%', rdata32); +#endif + picture->avg_skip = rdata32*100/blk88_y_count; + /* coeff_non_zero_y_count */ + rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA); +#ifdef DEBUG_QOS + hevc_print(hevc, 0, + "[Picture %d Quality] Y ZERO_Coeff rate : %d%c (%d)\n", + pic_number, (100 - rdata32*100/(blk88_y_count*1)), + '%', rdata32); +#endif + /* blk66_c_count */ + blk88_c_count = READ_VREG(HEVC_PIC_QUALITY_DATA); + if (blk88_c_count == 0) { +#ifdef DEBUG_QOS + hevc_print(hevc, 0, + "[Picture %d Quality] NO Data yet.\n", + pic_number); +#endif + /* reset all counts */ + WRITE_VREG(HEVC_PIC_QUALITY_CTRL, (1<<8)); + return; + } + /* qp_c_sum */ + rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA); +#ifdef DEBUG_QOS + hevc_print(hevc, 0, + "[Picture %d Quality] C QP AVG : %d (%d/%d)\n", + pic_number, rdata32/blk88_c_count, + rdata32, blk88_c_count); +#endif + /* intra_c_count */ + rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA); +#ifdef DEBUG_QOS + hevc_print(hevc, 0, + "[Picture %d Quality] C intra rate : %d%c (%d)\n", + pic_number, rdata32*100/blk88_c_count, + '%', rdata32); +#endif + /* skipped_cu_c_count */ + rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA); +#ifdef DEBUG_QOS + hevc_print(hevc, 0, + "[Picture %d Quality] C skipped rate : %d%c (%d)\n", + pic_number, rdata32*100/blk88_c_count, + '%', rdata32); +#endif + /* coeff_non_zero_c_count */ + rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA); +#ifdef DEBUG_QOS + hevc_print(hevc, 0, + "[Picture %d Quality] C ZERO_Coeff rate : %d%c (%d)\n", + pic_number, (100 - rdata32*100/(blk88_c_count*1)), + '%', rdata32); +#endif + + /* 1'h0, qp_c_max[6:0], 1'h0, qp_c_min[6:0], + 1'h0, qp_y_max[6:0], 1'h0, qp_y_min[6:0] */ + rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA); +#ifdef DEBUG_QOS + hevc_print(hevc, 0, "[Picture %d Quality] Y QP min : %d\n", + pic_number, (rdata32>>0)&0xff); +#endif + picture->min_qp = (rdata32>>0)&0xff; + +#ifdef DEBUG_QOS + hevc_print(hevc, 0, "[Picture %d Quality] Y QP max : %d\n", + pic_number, (rdata32>>8)&0xff); +#endif + picture->max_qp = (rdata32>>8)&0xff; + +#ifdef DEBUG_QOS + hevc_print(hevc, 0, "[Picture %d Quality] C QP min : %d\n", + pic_number, (rdata32>>16)&0xff); + hevc_print(hevc, 0, "[Picture %d Quality] C QP max : %d\n", + pic_number, (rdata32>>24)&0xff); +#endif + + /* blk22_mv_count */ + blk22_mv_count = READ_VREG(HEVC_PIC_QUALITY_DATA); + if (blk22_mv_count == 0) { +#ifdef DEBUG_QOS + hevc_print(hevc, 0, + "[Picture %d Quality] NO MV Data yet.\n", + pic_number); +#endif + /* reset all counts */ + WRITE_VREG(HEVC_PIC_QUALITY_CTRL, (1<<8)); + return; + } + /* mvy_L1_count[39:32], mvx_L1_count[39:32], + mvy_L0_count[39:32], mvx_L0_count[39:32] */ + rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA); + /* should all be 0x00 or 0xff */ +#ifdef DEBUG_QOS + hevc_print(hevc, 0, + "[Picture %d Quality] MV AVG High Bits: 0x%X\n", + pic_number, rdata32); +#endif + mvx_L0_hi = ((rdata32>>0)&0xff); + mvy_L0_hi = ((rdata32>>8)&0xff); + mvx_L1_hi = ((rdata32>>16)&0xff); + mvy_L1_hi = ((rdata32>>24)&0xff); + + /* mvx_L0_count[31:0] */ + rdata32_l = READ_VREG(HEVC_PIC_QUALITY_DATA); + temp_value = mvx_L0_hi; + temp_value = (temp_value << 32) | rdata32_l; + + if (mvx_L0_hi & 0x80) + value = 0xFFFFFFF000000000 | temp_value; + else + value = temp_value; + value = div_s64(value, blk22_mv_count); +#ifdef DEBUG_QOS + hevc_print(hevc, 0, + "[Picture %d Quality] MVX_L0 AVG : %d (%lld/%d)\n", + pic_number, (int)value, + value, blk22_mv_count); +#endif + picture->avg_mv = value; + + /* mvy_L0_count[31:0] */ + rdata32_l = READ_VREG(HEVC_PIC_QUALITY_DATA); + temp_value = mvy_L0_hi; + temp_value = (temp_value << 32) | rdata32_l; + + if (mvy_L0_hi & 0x80) + value = 0xFFFFFFF000000000 | temp_value; + else + value = temp_value; +#ifdef DEBUG_QOS + hevc_print(hevc, 0, + "[Picture %d Quality] MVY_L0 AVG : %d (%lld/%d)\n", + pic_number, rdata32_l/blk22_mv_count, + value, blk22_mv_count); +#endif + + /* mvx_L1_count[31:0] */ + rdata32_l = READ_VREG(HEVC_PIC_QUALITY_DATA); + temp_value = mvx_L1_hi; + temp_value = (temp_value << 32) | rdata32_l; + if (mvx_L1_hi & 0x80) + value = 0xFFFFFFF000000000 | temp_value; + else + value = temp_value; +#ifdef DEBUG_QOS + hevc_print(hevc, 0, + "[Picture %d Quality] MVX_L1 AVG : %d (%lld/%d)\n", + pic_number, rdata32_l/blk22_mv_count, + value, blk22_mv_count); +#endif + + /* mvy_L1_count[31:0] */ + rdata32_l = READ_VREG(HEVC_PIC_QUALITY_DATA); + temp_value = mvy_L1_hi; + temp_value = (temp_value << 32) | rdata32_l; + if (mvy_L1_hi & 0x80) + value = 0xFFFFFFF000000000 | temp_value; + else + value = temp_value; +#ifdef DEBUG_QOS + hevc_print(hevc, 0, + "[Picture %d Quality] MVY_L1 AVG : %d (%lld/%d)\n", + pic_number, rdata32_l/blk22_mv_count, + value, blk22_mv_count); +#endif + + /* {mvx_L0_max, mvx_L0_min} // format : {sign, abs[14:0]} */ + rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA); + mv_hi = (rdata32>>16)&0xffff; + if (mv_hi & 0x8000) + mv_hi = 0x8000 - mv_hi; +#ifdef DEBUG_QOS + hevc_print(hevc, 0, "[Picture %d Quality] MVX_L0 MAX : %d\n", + pic_number, mv_hi); +#endif + picture->max_mv = mv_hi; + + mv_lo = (rdata32>>0)&0xffff; + if (mv_lo & 0x8000) + mv_lo = 0x8000 - mv_lo; +#ifdef DEBUG_QOS + hevc_print(hevc, 0, "[Picture %d Quality] MVX_L0 MIN : %d\n", + pic_number, mv_lo); +#endif + picture->min_mv = mv_lo; + + /* {mvy_L0_max, mvy_L0_min} */ + rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA); + mv_hi = (rdata32>>16)&0xffff; + if (mv_hi & 0x8000) + mv_hi = 0x8000 - mv_hi; +#ifdef DEBUG_QOS + hevc_print(hevc, 0, "[Picture %d Quality] MVY_L0 MAX : %d\n", + pic_number, mv_hi); +#endif + + mv_lo = (rdata32>>0)&0xffff; + if (mv_lo & 0x8000) + mv_lo = 0x8000 - mv_lo; +#ifdef DEBUG_QOS + hevc_print(hevc, 0, "[Picture %d Quality] MVY_L0 MIN : %d\n", + pic_number, mv_lo); +#endif + + /* {mvx_L1_max, mvx_L1_min} */ + rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA); + mv_hi = (rdata32>>16)&0xffff; + if (mv_hi & 0x8000) + mv_hi = 0x8000 - mv_hi; +#ifdef DEBUG_QOS + hevc_print(hevc, 0, "[Picture %d Quality] MVX_L1 MAX : %d\n", + pic_number, mv_hi); +#endif + + mv_lo = (rdata32>>0)&0xffff; + if (mv_lo & 0x8000) + mv_lo = 0x8000 - mv_lo; +#ifdef DEBUG_QOS + hevc_print(hevc, 0, "[Picture %d Quality] MVX_L1 MIN : %d\n", + pic_number, mv_lo); +#endif + + /* {mvy_L1_max, mvy_L1_min} */ + rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA); + mv_hi = (rdata32>>16)&0xffff; + if (mv_hi & 0x8000) + mv_hi = 0x8000 - mv_hi; +#ifdef DEBUG_QOS + hevc_print(hevc, 0, "[Picture %d Quality] MVY_L1 MAX : %d\n", + pic_number, mv_hi); +#endif + mv_lo = (rdata32>>0)&0xffff; + if (mv_lo & 0x8000) + mv_lo = 0x8000 - mv_lo; +#ifdef DEBUG_QOS + hevc_print(hevc, 0, "[Picture %d Quality] MVY_L1 MIN : %d\n", + pic_number, mv_lo); +#endif + + rdata32 = READ_VREG(HEVC_PIC_QUALITY_CTRL); +#ifdef DEBUG_QOS + hevc_print(hevc, 0, + "[Picture %d Quality] After Read : VDEC_PIC_QUALITY_CTRL : 0x%x\n", + pic_number, rdata32); +#endif + /* reset all counts */ + WRITE_VREG(HEVC_PIC_QUALITY_CTRL, (1<<8)); + } +} + static int hevc_slice_segment_header_process(struct hevc_state_s *hevc, union param_u *rpm_param, int decode_pic_begin) @@ -5168,7 +6314,7 @@ static int hevc_slice_segment_header_process(struct hevc_state_s *hevc, #endif } - if (OVER_SIZE(hevc->pic_w, hevc->pic_h)) { + if (is_oversize(hevc->pic_w, hevc->pic_h)) { hevc_print(hevc, 0, "over size : %u x %u.\n", hevc->pic_w, hevc->pic_h); if ((!hevc->m_ins_flag) && @@ -5351,6 +6497,10 @@ static int hevc_slice_segment_header_process(struct hevc_state_s *hevc, hevc->pic_list_init_flag = 3; } } + if (!hevc->m_ins_flag) { + if (hevc->cur_pic) + get_picture_qos_info(hevc); + } hevc->first_pic_after_recover = 0; if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR_MORE) dump_pic_list(hevc); @@ -5380,7 +6530,11 @@ static int hevc_slice_segment_header_process(struct hevc_state_s *hevc, } if (vdec->master == NULL && vdec->slave == NULL) - set_aux_data(hevc, hevc->cur_pic, 1, 0); + set_aux_data(hevc, + hevc->cur_pic, 1, 0); /*suffix*/ + if (hevc->bypass_dvenl && !dolby_meta_with_el) + set_aux_data(hevc, + hevc->cur_pic, 0, 1); /*dv meta only*/ #else set_aux_data(hevc, hevc->cur_pic, 1, 0); #endif @@ -5394,6 +6548,8 @@ static int hevc_slice_segment_header_process(struct hevc_state_s *hevc, } #ifdef MULTI_INSTANCE_SUPPORT hevc->decoding_pic = hevc->cur_pic; + if (!hevc->m_ins_flag) + hevc->over_decode = 0; #endif #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION hevc->cur_pic->dv_enhance_exist = 0; @@ -5403,7 +6559,12 @@ static int hevc_slice_segment_header_process(struct hevc_state_s *hevc, hevc->curr_POC); if (vdec->master == NULL && vdec->slave == NULL) - set_aux_data(hevc, hevc->cur_pic, 0, 0); + set_aux_data(hevc, + hevc->cur_pic, 0, 0); /*prefix*/ + + if (hevc->bypass_dvenl && !dolby_meta_with_el) + set_aux_data(hevc, + hevc->cur_pic, 0, 2); /*pre sei only*/ #else set_aux_data(hevc, hevc->cur_pic, 0, 0); #endif @@ -5416,16 +6577,18 @@ static int hevc_slice_segment_header_process(struct hevc_state_s *hevc, return -1; } } else { + if (get_dbg_flag(hevc) & H265_DEBUG_HAS_AUX_IN_SLICE) { #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION - if (vdec->master == NULL && - vdec->slave == NULL) { + if (vdec->master == NULL && + vdec->slave == NULL) { + set_aux_data(hevc, hevc->cur_pic, 1, 0); + set_aux_data(hevc, hevc->cur_pic, 0, 0); + } +#else set_aux_data(hevc, hevc->cur_pic, 1, 0); set_aux_data(hevc, hevc->cur_pic, 0, 0); - } -#else - set_aux_data(hevc, hevc->cur_pic, 1, 0); - set_aux_data(hevc, hevc->cur_pic, 0, 0); #endif + } if (hevc->pic_list_init_flag != 3 || hevc->cur_pic == NULL) { /* make it dec from the first slice segment */ @@ -5441,6 +6604,9 @@ static int hevc_slice_segment_header_process(struct hevc_state_s *hevc, if (hevc->cur_pic == NULL) return -1; + if (!hevc->m_ins_flag) + hevc->over_decode = 0; + #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION hevc->cur_pic->dv_enhance_exist = 0; if (vdec->master == NULL && @@ -5707,11 +6873,12 @@ static int H265_alloc_mmu(struct hevc_state_s *hevc, struct PIC_s *new_pic, int bit_depth_10 = (bit_depth != 0x00); int picture_size; int cur_mmu_4k_number; - int ret; + int ret, max_frame_num; picture_size = compute_losless_comp_body_size(hevc, new_pic->width, new_pic->height, !bit_depth_10); cur_mmu_4k_number = ((picture_size+(1<<12)-1) >> 12); - + if (hevc->double_write_mode & 0x10) + return 0; /*hevc_print(hevc, 0, "alloc_mmu cur_idx : %d picture_size : %d mmu_4k_number : %d\r\n", cur_buf_idx, picture_size, cur_mmu_4k_number);*/ @@ -5719,7 +6886,11 @@ static int H265_alloc_mmu(struct hevc_state_s *hevc, struct PIC_s *new_pic, decoder_mmu_box_free_idx(hevc->mmu_box, new_pic->index); new_pic->scatter_alloc = 0; } - if (cur_mmu_4k_number > MAX_FRAME_4K_NUM) { + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) + max_frame_num = MAX_FRAME_8K_NUM; + else + max_frame_num = MAX_FRAME_4K_NUM; + if (cur_mmu_4k_number > max_frame_num) { hevc_print(hevc, 0, "over max !! 0x%x width %d height %d\n", cur_mmu_4k_number, new_pic->width, @@ -5750,7 +6921,9 @@ static void release_pic_mmu_buf(struct hevc_state_s *hevc, __func__, pic->index, pic->scatter_alloc); - if (hevc->mmu_enable && pic->scatter_alloc) + if (hevc->mmu_enable + && ((hevc->double_write_mode & 0x10) == 0) + && pic->scatter_alloc) decoder_mmu_box_free_idx(hevc->mmu_box, pic->index); pic->scatter_alloc = 0; } @@ -5769,6 +6942,21 @@ static void hevc_local_uninit(struct hevc_state_s *hevc) hevc->rpm_ptr = NULL; hevc->lmem_ptr = NULL; +#ifdef SWAP_HEVC_UCODE + if (hevc->is_swap && get_cpu_major_id() <= AM_MESON_CPU_MAJOR_ID_GXM) { + if (hevc->mc_cpu_addr != NULL) { + dma_free_coherent(amports_get_dma_device(), + hevc->swap_size, hevc->mc_cpu_addr, + hevc->mc_dma_handle); + hevc->mc_cpu_addr = NULL; + } + + } +#endif +#ifdef DETREFILL_ENABLE + if (hevc->is_swap && get_cpu_major_id() <= AM_MESON_CPU_MAJOR_ID_GXM) + uninit_detrefill_buf(hevc); +#endif if (hevc->aux_addr) { dma_unmap_single(amports_get_dma_device(), hevc->aux_phy_addr, @@ -5793,7 +6981,7 @@ static void hevc_local_uninit(struct hevc_state_s *hevc) if (hevc->mmu_enable && hevc->frame_mmu_map_addr) { if (hevc->frame_mmu_map_phy_addr) dma_free_coherent(amports_get_dma_device(), - FRAME_MMU_MAP_SIZE, hevc->frame_mmu_map_addr, + get_frame_mmu_map_size(), hevc->frame_mmu_map_addr, hevc->frame_mmu_map_phy_addr); hevc->frame_mmu_map_addr = NULL; @@ -5811,17 +6999,18 @@ static int hevc_local_init(struct hevc_state_s *hevc) memset(&hevc->param, 0, sizeof(union param_u)); cur_buf_info = &hevc->work_space_buf_store; -#ifdef SUPPORT_4K2K - if (vdec_is_support_4k()) - memcpy(cur_buf_info, &amvh265_workbuff_spec[1], /* 4k */ - sizeof(struct BuffInfo_s)); - else + + if (vdec_is_support_4k()) { + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) + memcpy(cur_buf_info, &amvh265_workbuff_spec[2], /* 4k */ + sizeof(struct BuffInfo_s)); + else + memcpy(cur_buf_info, &amvh265_workbuff_spec[1], /* 4k */ + sizeof(struct BuffInfo_s)); + } else memcpy(cur_buf_info, &amvh265_workbuff_spec[0], /* 1080p */ sizeof(struct BuffInfo_s)); -#else - memcpy(cur_buf_info, &amvh265_workbuff_spec[0], /* 1080p work space */ - sizeof(struct BuffInfo_s)); -#endif + cur_buf_info->start_adr = hevc->buf_start; init_buff_spec(hevc, cur_buf_info); @@ -5830,6 +7019,7 @@ static int hevc_local_init(struct hevc_state_s *hevc) hevc->bit_depth_luma = 8; hevc->bit_depth_chroma = 8; hevc->video_signal_type = 0; + hevc->video_signal_type_debug = 0; bit_depth_luma = hevc->bit_depth_luma; bit_depth_chroma = hevc->bit_depth_chroma; video_signal_type = hevc->video_signal_type; @@ -5897,13 +7087,13 @@ static int hevc_local_init(struct hevc_state_s *hevc) if (hevc->mmu_enable) { hevc->frame_mmu_map_addr = dma_alloc_coherent(amports_get_dma_device(), - FRAME_MMU_MAP_SIZE, + get_frame_mmu_map_size(), &hevc->frame_mmu_map_phy_addr, GFP_KERNEL); if (hevc->frame_mmu_map_addr == NULL) { pr_err("%s: failed to alloc count_buffer\n", __func__); return -1; } - memset(hevc->frame_mmu_map_addr, 0, FRAME_MMU_MAP_SIZE); + memset(hevc->frame_mmu_map_addr, 0, get_frame_mmu_map_size()); } ret = 0; return ret; @@ -5934,6 +7124,7 @@ static int hevc_local_init(struct hevc_state_s *hevc) static void set_canvas(struct hevc_state_s *hevc, struct PIC_s *pic) { + struct vdec_s *vdec = hw_to_vdec(hevc); int canvas_w = ALIGN(pic->width, 64)/4; int canvas_h = ALIGN(pic->height, 32)/4; int blkmode = mem_map_mode; @@ -5952,8 +7143,15 @@ static void set_canvas(struct hevc_state_s *hevc, struct PIC_s *pic) canvas_w = ALIGN(canvas_w, 64); canvas_h = ALIGN(canvas_h, 32); - pic->y_canvas_index = 128 + pic->index * 2; - pic->uv_canvas_index = 128 + pic->index * 2 + 1; + if (vdec->parallel_dec == 1) { + if (pic->y_canvas_index == -1) + pic->y_canvas_index = vdec->get_canvas_ex(CORE_MASK_HEVC, vdec->id); + if (pic->uv_canvas_index == -1) + pic->uv_canvas_index = vdec->get_canvas_ex(CORE_MASK_HEVC, vdec->id); + } else { + pic->y_canvas_index = 128 + pic->index * 2; + pic->uv_canvas_index = 128 + pic->index * 2 + 1; + } canvas_config_ex(pic->y_canvas_index, pic->dw_y_adr, canvas_w, canvas_h, @@ -5985,8 +7183,14 @@ static void set_canvas(struct hevc_state_s *hevc, struct PIC_s *pic) } else { if (!hevc->mmu_enable) { /* to change after 10bit VPU is ready ... */ - pic->y_canvas_index = 128 + pic->index; - pic->uv_canvas_index = 128 + pic->index; + if (vdec->parallel_dec == 1) { + if (pic->y_canvas_index == -1) + pic->y_canvas_index = vdec->get_canvas_ex(CORE_MASK_HEVC, vdec->id); + pic->uv_canvas_index = pic->y_canvas_index; + } else { + pic->y_canvas_index = 128 + pic->index; + pic->uv_canvas_index = 128 + pic->index; + } canvas_config_ex(pic->y_canvas_index, pic->mc_y_adr, canvas_w, canvas_h, @@ -5997,8 +7201,16 @@ static void set_canvas(struct hevc_state_s *hevc, struct PIC_s *pic) } } #else - pic->y_canvas_index = 128 + pic->index * 2; - pic->uv_canvas_index = 128 + pic->index * 2 + 1; + if (vdec->parallel_dec == 1) { + if (pic->y_canvas_index == -1) + pic->y_canvas_index = vdec->get_canvas_ex(CORE_MASK_HEVC, vdec->id); + if (pic->uv_canvas_index == -1) + pic->uv_canvas_index = vdec->get_canvas_ex(CORE_MASK_HEVC, vdec->id); + } else { + pic->y_canvas_index = 128 + pic->index * 2; + pic->uv_canvas_index = 128 + pic->index * 2 + 1; + } + canvas_config_ex(pic->y_canvas_index, pic->mc_y_adr, canvas_w, canvas_h, CANVAS_ADDR_NOWRAP, blkmode, 0x7); @@ -6064,6 +7276,17 @@ static int parse_sei(struct hevc_state_s *hevc, "parse result pic_struct = %d\n", hevc->curr_pic_struct); } + break; + case SEI_UserDataITU_T_T35: + p_sei = p; + if (p_sei[0] == 0xB5 + && p_sei[1] == 0x00 + && p_sei[2] == 0x3C + && p_sei[3] == 0x00 + && p_sei[4] == 0x01 + && p_sei[5] == 0x04) + hevc->sei_present_flag |= SEI_HDR10PLUS_MASK; + break; case SEI_MasteringDisplayColorVolume: /*hevc_print(hevc, 0, @@ -6112,8 +7335,9 @@ static int parse_sei(struct hevc_state_s *hevc, hevc->luminance[1]);*/ break; case SEI_ContentLightLevel: - hevc_print(hevc, 0, - "sei type: max content light level %d, size %d\n", + if (get_dbg_flag(hevc) & H265_DEBUG_PRINT_SEI) + hevc_print(hevc, 0, + "sei type: max content light level %d, size %d\n", payload_type, payload_size); /* content_light_level */ p_sei = p; @@ -6125,8 +7349,9 @@ static int parse_sei(struct hevc_state_s *hevc, p_sei += 2; hevc->sei_present_flag |= SEI_CONTENT_LIGHT_LEVEL_MASK; - hevc_print(hevc, 0, - "\tmax cll = %04x, max_pa_cll = %04x\n", + if (get_dbg_flag(hevc) & H265_DEBUG_PRINT_SEI) + hevc_print(hevc, 0, + "\tmax cll = %04x, max_pa_cll = %04x\n", hevc->content_light_level[0], hevc->content_light_level[1]); break; @@ -6229,11 +7454,6 @@ static void set_frame_info(struct hevc_state_s *hevc, struct vframe_s *vf, ar = min_t(u32, hevc->frame_ar, DISP_RATIO_ASPECT_RATIO_MAX); vf->ratio_control = (ar << DISP_RATIO_ASPECT_RATIO_BIT); - /* signal_type */ - if (hevc->video_signal_type & VIDEO_SIGNAL_TYPE_AVAILABLE_MASK) - vf->signal_type = hevc->video_signal_type; - else - vf->signal_type = 0; if (((pic->aspect_ratio_idc == 255) && pic->sar_width && @@ -6249,6 +7469,7 @@ static void set_frame_info(struct hevc_state_s *hevc, struct vframe_s *vf, DISP_RATIO_ASPECT_RATIO_MAX); vf->ratio_control = (ar << DISP_RATIO_ASPECT_RATIO_BIT); } + hevc->ratio_control = vf->ratio_control; if (pic->aux_data_buf && pic->aux_data_size) { /* parser sei */ @@ -6271,6 +7492,19 @@ static void set_frame_info(struct hevc_state_s *hevc, struct vframe_s *vf, p += size; } } + if (hevc->video_signal_type & VIDEO_SIGNAL_TYPE_AVAILABLE_MASK) { + vf->signal_type = pic->video_signal_type; + if (hevc->sei_present_flag & SEI_HDR10PLUS_MASK) { + u32 data; + data = vf->signal_type; + data = data & 0xFFFF00FF; + data = data | (0x30<<8); + vf->signal_type = data; + } + } + else + vf->signal_type = 0; + hevc->video_signal_type_debug = vf->signal_type; /* master_display_colour */ if (hevc->sei_present_flag & SEI_MASTER_DISPLAY_COLOR_MASK) { @@ -6443,13 +7677,32 @@ static struct vframe_s *vh265_vf_get(void *op_arg) struct vframe_s *next_vf; if (get_dbg_flag(hevc) & H265_DEBUG_PIC_STRUCT) hevc_print(hevc, 0, - "%s(type %d index 0x%x poc %d/%d) pts(%d,%d) dur %d\n", - __func__, vf->type, vf->index, + "%s(vf 0x%p type %d index 0x%x poc %d/%d) pts(%d,%d) dur %d\n", + __func__, vf, vf->type, vf->index, get_pic_poc(hevc, vf->index & 0xff), get_pic_poc(hevc, (vf->index >> 8) & 0xff), vf->pts, vf->pts_us64, vf->duration); - +#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION + if (get_dbg_flag(hevc) & H265_DEBUG_DV) { + struct PIC_s *pic = hevc->m_PIC[vf->index & 0xff]; + if (pic->aux_data_buf && pic->aux_data_size > 0) { + int i; + struct PIC_s *pic = + hevc->m_PIC[vf->index & 0xff]; + hevc_print(hevc, 0, + "pic 0x%p aux size %d:\n", + pic, pic->aux_data_size); + for (i = 0; i < pic->aux_data_size; i++) { + hevc_print_cont(hevc, 0, + "%02x ", pic->aux_data_buf[i]); + if (((i + 1) & 0xf) == 0) + hevc_print_cont(hevc, 0, "\n"); + } + hevc_print_cont(hevc, 0, "\n"); + } + } +#endif hevc->show_frame_num++; hevc->vf_get_count++; @@ -6486,7 +7739,7 @@ static void vh265_vf_put(struct vframe_s *vf, void *op_arg) kfifo_put(&hevc->newframe_q, (const struct vframe_s *)vf); spin_lock_irqsave(&lock, flags); - if (index_top != 0xff && index_top >= 0 + if (index_top != 0xff && index_top < MAX_REF_PIC_NUM && hevc->m_PIC[index_top]) { if (hevc->m_PIC[index_top]->vf_ref > 0) { @@ -6502,7 +7755,7 @@ static void vh265_vf_put(struct vframe_s *vf, void *op_arg) } } - if (index_bot != 0xff && index_bot >= 0 + if (index_bot != 0xff && index_bot < MAX_REF_PIC_NUM && hevc->m_PIC[index_bot]) { if (hevc->m_PIC[index_bot]->vf_ref > 0) { @@ -6554,17 +7807,22 @@ static int vh265_event_cb(int type, void *data, void *op_arg) req->aux_size = 0; if (req->bot_flag) index = (req->vf->index >> 8) & 0xff; - if (index != 0xff && index >= 0 + if (index != 0xff && index < MAX_REF_PIC_NUM && hevc->m_PIC[index]) { req->aux_buf = hevc->m_PIC[index]->aux_data_buf; req->aux_size = hevc->m_PIC[index]->aux_data_size; #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION - req->dv_enhance_exist = - hevc->m_PIC[index]->dv_enhance_exist; + if (hevc->bypass_dvenl && !dolby_meta_with_el) + req->dv_enhance_exist = false; + else + req->dv_enhance_exist = + hevc->m_PIC[index]->dv_enhance_exist; hevc_print(hevc, H265_DEBUG_DV, - "query dv_enhance_exist for pic (poc %d) flag => %d\n", - hevc->m_PIC[index]->POC, req->dv_enhance_exist); + "query dv_enhance_exist for pic (vf 0x%p, poc %d index %d) flag => %d, aux sizd 0x%x\n", + req->vf, + hevc->m_PIC[index]->POC, index, + req->dv_enhance_exist, req->aux_size); #else req->dv_enhance_exist = 0; #endif @@ -6575,8 +7833,17 @@ static int vh265_event_cb(int type, void *data, void *op_arg) hevc_print(hevc, 0, "%s(type 0x%x vf index 0x%x)=>size 0x%x\n", __func__, type, index, req->aux_size); - } +#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION + } else if (type & VFRAME_EVENT_RECEIVER_DOLBY_BYPASS_EL) { + if ((force_bypass_dvenl & 0x80000000) == 0) { + hevc_print(hevc, 0, + "%s: VFRAME_EVENT_RECEIVER_DOLBY_BYPASS_EL\n", + __func__); + hevc->bypass_dvenl_enable = 1; + } +#endif + } return 0; } @@ -6606,6 +7873,7 @@ static int process_pending_vframe(struct hevc_state_s *hevc, __func__, vf->index); hevc->vf_pre_count++; kfifo_put(&hevc->display_q, (const struct vframe_s *)vf); + ATRACE_COUNTER(MODULE_NAME, vf->pts); } if (kfifo_peek(&hevc->pending_q, &vf)) { @@ -6627,6 +7895,7 @@ static int process_pending_vframe(struct hevc_state_s *hevc, hevc->vf_pre_count++; kfifo_put(&hevc->display_q, (const struct vframe_s *)vf); + ATRACE_COUNTER(MODULE_NAME, vf->pts); } } else if ((!pair_frame_top_flag) && (((vf->index >> 8) & 0xff) == 0xff)) { @@ -6644,6 +7913,7 @@ static int process_pending_vframe(struct hevc_state_s *hevc, pair_pic->vf_ref++; kfifo_put(&hevc->display_q, (const struct vframe_s *)vf); + ATRACE_COUNTER(MODULE_NAME, vf->pts); hevc->vf_pre_count++; if (get_dbg_flag(hevc) & H265_DEBUG_PIC_STRUCT) hevc_print(hevc, 0, @@ -6666,6 +7936,7 @@ static int process_pending_vframe(struct hevc_state_s *hevc, pair_pic->vf_ref++; kfifo_put(&hevc->display_q, (const struct vframe_s *)vf); + ATRACE_COUNTER(MODULE_NAME, vf->pts); hevc->vf_pre_count++; if (get_dbg_flag(hevc) & H265_DEBUG_PIC_STRUCT) hevc_print(hevc, 0, @@ -6701,6 +7972,65 @@ static void update_vf_memhandle(struct hevc_state_s *hevc, } return; } + +static void fill_frame_info(struct hevc_state_s *hevc, + struct PIC_s *pic, unsigned int framesize, unsigned int pts) +{ + struct vframe_qos_s *vframe_qos = &hevc->vframe_qos; + if (hevc->m_nalUnitType == NAL_UNIT_CODED_SLICE_IDR) + vframe_qos->type = 4; + else if (pic->slice_type == I_SLICE) + vframe_qos->type = 1; + else if (pic->slice_type == P_SLICE) + vframe_qos->type = 2; + else if (pic->slice_type == B_SLICE) + vframe_qos->type = 3; +/* +#define SHOW_QOS_INFO +*/ + vframe_qos->size = framesize; + vframe_qos->pts = pts; +#ifdef SHOW_QOS_INFO + hevc_print(hevc, 0, "slice:%d, poc:%d\n", pic->slice_type, pic->POC); +#endif + + + vframe_qos->max_mv = pic->max_mv; + vframe_qos->avg_mv = pic->avg_mv; + vframe_qos->min_mv = pic->min_mv; +#ifdef SHOW_QOS_INFO + hevc_print(hevc, 0, "mv: max:%d, avg:%d, min:%d\n", + vframe_qos->max_mv, + vframe_qos->avg_mv, + vframe_qos->min_mv); +#endif + + vframe_qos->max_qp = pic->max_qp; + vframe_qos->avg_qp = pic->avg_qp; + vframe_qos->min_qp = pic->min_qp; +#ifdef SHOW_QOS_INFO + hevc_print(hevc, 0, "qp: max:%d, avg:%d, min:%d\n", + vframe_qos->max_qp, + vframe_qos->avg_qp, + vframe_qos->min_qp); +#endif + + vframe_qos->max_skip = pic->max_skip; + vframe_qos->avg_skip = pic->avg_skip; + vframe_qos->min_skip = pic->min_skip; +#ifdef SHOW_QOS_INFO + hevc_print(hevc, 0, "skip: max:%d, avg:%d, min:%d\n", + vframe_qos->max_skip, + vframe_qos->avg_skip, + vframe_qos->min_skip); +#endif + + vframe_qos->num++; + + if (hevc->frameinfo_enable) + vdec_fill_frame_info(vframe_qos, 1); +} + static int prepare_display_buf(struct hevc_state_s *hevc, struct PIC_s *pic) { #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION @@ -6709,6 +8039,8 @@ static int prepare_display_buf(struct hevc_state_s *hevc, struct PIC_s *pic) struct vframe_s *vf = NULL; int stream_offset = pic->stream_offset; unsigned short slice_type = pic->slice_type; + u32 frame_size; + if (force_disp_pic_index & 0x100) { /*recycle directly*/ pic->output_ready = 0; @@ -6742,7 +8074,8 @@ static int prepare_display_buf(struct hevc_state_s *hevc, struct PIC_s *pic) "call pts_lookup_offset_us64(0x%x)\n", stream_offset); if (pts_lookup_offset_us64 - (PTS_TYPE_VIDEO, stream_offset, &vf->pts, 0, + (PTS_TYPE_VIDEO, stream_offset, &vf->pts, + &frame_size, 0, &vf->pts_us64) != 0) { #ifdef DEBUG_PTS hevc->pts_missed++; @@ -6767,6 +8100,8 @@ static int prepare_display_buf(struct hevc_state_s *hevc, struct PIC_s *pic) if (pts_unstable && (hevc->frame_dur > 0)) hevc->pts_mode = PTS_NONE_REF_USE_DURATION; + fill_frame_info(hevc, pic, frame_size, vf->pts); + if ((hevc->pts_mode == PTS_NORMAL) && (vf->pts != 0) && hevc->get_frame_dur) { int pts_diff = (int)vf->pts - hevc->last_lookup_pts; @@ -6853,7 +8188,8 @@ static int prepare_display_buf(struct hevc_state_s *hevc, struct PIC_s *pic) if (pic->double_write_mode) { vf->type = VIDTYPE_PROGRESSIVE | VIDTYPE_VIU_FIELD; vf->type |= VIDTYPE_VIU_NV21; - if (pic->double_write_mode == 3) { + if ((pic->double_write_mode == 3) && + (!(IS_8K_SIZE(pic->width, pic->height)))) { vf->type |= VIDTYPE_COMPRESS; if (hevc->mmu_enable) vf->type |= VIDTYPE_SCATTER; @@ -6948,12 +8284,12 @@ static int prepare_display_buf(struct hevc_state_s *hevc, struct PIC_s *pic) * need move below code to get_new_pic(), * hevc->xxx can only be used by current decoded pic */ - if (hevc->param.p.conformance_window_flag && + if (pic->conformance_window_flag && (get_dbg_flag(hevc) & H265_DEBUG_IGNORE_CONFORMANCE_WINDOW) == 0) { unsigned int SubWidthC, SubHeightC; - switch (hevc->param.p.chroma_format_idc) { + switch (pic->chroma_format_idc) { case 1: SubWidthC = 2; SubHeightC = 2; @@ -6968,27 +8304,27 @@ static int prepare_display_buf(struct hevc_state_s *hevc, struct PIC_s *pic) break; } vf->width -= SubWidthC * - (hevc->param.p.conf_win_left_offset + - hevc->param.p.conf_win_right_offset); + (pic->conf_win_left_offset + + pic->conf_win_right_offset); vf->height -= SubHeightC * - (hevc->param.p.conf_win_top_offset + - hevc->param.p.conf_win_bottom_offset); + (pic->conf_win_top_offset + + pic->conf_win_bottom_offset); vf->compWidth -= SubWidthC * - (hevc->param.p.conf_win_left_offset + - hevc->param.p.conf_win_right_offset); + (pic->conf_win_left_offset + + pic->conf_win_right_offset); vf->compHeight -= SubHeightC * - (hevc->param.p.conf_win_top_offset + - hevc->param.p.conf_win_bottom_offset); + (pic->conf_win_top_offset + + pic->conf_win_bottom_offset); if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR) hevc_print(hevc, 0, "conformance_window %d, %d, %d, %d, %d => cropped width %d, height %d com_w %d com_h %d\n", - hevc->param.p.chroma_format_idc, - hevc->param.p.conf_win_left_offset, - hevc->param.p.conf_win_right_offset, - hevc->param.p.conf_win_top_offset, - hevc->param.p.conf_win_bottom_offset, + pic->chroma_format_idc, + pic->conf_win_left_offset, + pic->conf_win_right_offset, + pic->conf_win_top_offset, + pic->conf_win_bottom_offset, vf->width, vf->height, vf->compWidth, vf->compHeight); } @@ -7029,9 +8365,11 @@ static int prepare_display_buf(struct hevc_state_s *hevc, struct PIC_s *pic) hevc->vf_pre_count++; kfifo_put(&hevc->display_q, (const struct vframe_s *)vf); + ATRACE_COUNTER(MODULE_NAME, vf->pts); hevc->vf_pre_count++; kfifo_put(&hevc->display_q, (const struct vframe_s *)vf2); + ATRACE_COUNTER(MODULE_NAME, vf2->pts); } else if (pic->pic_struct == 5 || pic->pic_struct == 6) { struct vframe_s *vf2, *vf3; @@ -7075,12 +8413,15 @@ static int prepare_display_buf(struct hevc_state_s *hevc, struct PIC_s *pic) hevc->vf_pre_count++; kfifo_put(&hevc->display_q, (const struct vframe_s *)vf); + ATRACE_COUNTER(MODULE_NAME, vf->pts); hevc->vf_pre_count++; kfifo_put(&hevc->display_q, (const struct vframe_s *)vf2); + ATRACE_COUNTER(MODULE_NAME, vf2->pts); hevc->vf_pre_count++; kfifo_put(&hevc->display_q, (const struct vframe_s *)vf3); + ATRACE_COUNTER(MODULE_NAME, vf3->pts); } else if (pic->pic_struct == 9 || pic->pic_struct == 10) { @@ -7184,12 +8525,15 @@ static int prepare_display_buf(struct hevc_state_s *hevc, struct PIC_s *pic) hevc->vf_pre_count++; kfifo_put(&hevc->display_q, (const struct vframe_s *)vf); + ATRACE_COUNTER(MODULE_NAME, vf->pts); } #else vf->type_original = vf->type; pic->vf_ref = 1; hevc->vf_pre_count++; + decoder_do_frame_check(hw_to_vdec(hevc), vf); kfifo_put(&hevc->display_q, (const struct vframe_s *)vf); + ATRACE_COUNTER(MODULE_NAME, vf->pts); if (get_dbg_flag(hevc) & H265_DEBUG_PIC_STRUCT) hevc_print(hevc, 0, @@ -7204,6 +8548,7 @@ static int prepare_display_buf(struct hevc_state_s *hevc, struct PIC_s *pic) /*count info*/ vdec_count_info(gvs, 0, stream_offset); #endif + hw_to_vdec(hevc)->vdec_fps_detec(hw_to_vdec(hevc)->id); vf_notify_receiver(hevc->provider_name, VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); } @@ -7436,6 +8781,13 @@ static int hevc_recover(struct hevc_state_s *hevc) hevc_print(hevc, 0, "%s HEVC_SHIFT_BYTE_COUNT=0x%x\n", __func__, READ_VREG(HEVC_SHIFT_BYTE_COUNT)); +#ifdef SWAP_HEVC_UCODE + if (!tee_enabled() && hevc->is_swap && + get_cpu_major_id() <= AM_MESON_CPU_MAJOR_ID_GXM) { + WRITE_VREG(HEVC_STREAM_SWAP_BUFFER2, hevc->mc_dma_handle); + /*pr_info("write swap buffer %x\n", (u32)(hevc->mc_dma_handle));*/ + } +#endif amhevc_start(); /* skip, search next start code */ @@ -7508,11 +8860,7 @@ static void dump_aux_buf(struct hevc_state_s *hevc) static void dolby_get_meta(struct hevc_state_s *hevc) { struct vdec_s *vdec = hw_to_vdec(hevc); - dma_sync_single_for_cpu( - amports_get_dma_device(), - hevc->aux_phy_addr, - hevc->prefix_aux_size + hevc->suffix_aux_size, - DMA_FROM_DEVICE); + if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR_MORE) dump_aux_buf(hevc); @@ -7657,6 +9005,7 @@ static irqreturn_t vh265_isr_thread_fn(int irq, void *data) hevc->shift_byte_count_lo = i; } #ifdef MULTI_INSTANCE_SUPPORT + mutex_lock(&hevc->chunks_mutex); if ((dec_status == HEVC_DECPIC_DATA_DONE || dec_status == HEVC_FIND_NEXT_PIC_NAL || dec_status == HEVC_FIND_NEXT_DVEL_NAL) @@ -7664,12 +9013,14 @@ static irqreturn_t vh265_isr_thread_fn(int irq, void *data) hevc->cur_pic->pts = hevc->chunk->pts; hevc->cur_pic->pts64 = hevc->chunk->pts64; } + mutex_unlock(&hevc->chunks_mutex); if (dec_status == HEVC_DECODE_BUFEMPTY || dec_status == HEVC_DECODE_BUFEMPTY2) { if (hevc->m_ins_flag) { read_decode_info(hevc); if (vdec_frame_based(hw_to_vdec(hevc))) { + hevc->empty_flag = 1; goto pic_done; } else { if ( @@ -7695,6 +9046,7 @@ static irqreturn_t vh265_isr_thread_fn(int irq, void *data) read_decode_info(hevc); if (vdec_frame_based(hw_to_vdec(hevc))) { /*hevc->dec_result = DEC_RESULT_GET_DATA;*/ + hevc->empty_flag = 1; goto pic_done; } else { hevc->dec_result = DEC_RESULT_AGAIN; @@ -7709,15 +9061,143 @@ static irqreturn_t vh265_isr_thread_fn(int irq, void *data) return IRQ_HANDLED; } else if (dec_status == HEVC_DECPIC_DATA_DONE) { if (hevc->m_ins_flag) { + struct PIC_s *pic; + struct PIC_s *pic_display; + int decoded_poc; +#ifdef DETREFILL_ENABLE + if (hevc->is_swap && + get_cpu_major_id() <= AM_MESON_CPU_MAJOR_ID_GXM) { + if (hevc->detbuf_adr_virt && hevc->delrefill_check + && READ_VREG(HEVC_SAO_DBG_MODE0)) + hevc->delrefill_check = 2; + } +#endif + hevc->empty_flag = 0; pic_done: - read_decode_info(hevc); + if (input_frame_based(hw_to_vdec(hevc)) && + frmbase_cont_bitlevel != 0 && + (hevc->decode_size > READ_VREG(HEVC_SHIFT_BYTE_COUNT)) && + (hevc->decode_size - (READ_VREG(HEVC_SHIFT_BYTE_COUNT)) + > frmbase_cont_bitlevel)) { + /*handle the case: multi pictures in one packet*/ + hevc_print(hevc, PRINT_FLAG_VDEC_STATUS, + "%s has more data index= %d, size=0x%x shiftcnt=0x%x)\n", + __func__, + hevc->decode_idx, hevc->decode_size, + READ_VREG(HEVC_SHIFT_BYTE_COUNT)); + WRITE_VREG(HEVC_DEC_STATUS_REG, HEVC_ACTION_DONE); + start_process_time(hevc); + return IRQ_HANDLED; + } + read_decode_info(hevc); + get_picture_qos_info(hevc); +#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION + hevc->start_parser_type = 0; + hevc->switch_dvlayer_flag = 0; +#endif hevc->decoded_poc = hevc->curr_POC; hevc->decoding_pic = NULL; hevc->dec_result = DEC_RESULT_DONE; +#ifdef DETREFILL_ENABLE + if (hevc->is_swap && + get_cpu_major_id() <= AM_MESON_CPU_MAJOR_ID_GXM) + if (hevc->delrefill_check != 2) +#endif + amhevc_stop(); reset_process_time(hevc); + + if (hevc->vf_pre_count == 0) { + decoded_poc = hevc->curr_POC; + pic = get_pic_by_POC(hevc, decoded_poc); + if (pic && (pic->POC != INVALID_POC)) { + /*PB skip control */ + if (pic->error_mark == 0 + && hevc->PB_skip_mode == 1) { + /* start decoding after + * first I + */ + hevc->ignore_bufmgr_error |= 0x1; + } + if (hevc->ignore_bufmgr_error & 1) { + if (hevc->PB_skip_count_after_decoding > 0) { + hevc->PB_skip_count_after_decoding--; + } else { + /* start displaying */ + hevc->ignore_bufmgr_error |= 0x2; + } + } + if (hevc->mmu_enable + && ((hevc->double_write_mode & 0x10) == 0)) { + if (!hevc->m_ins_flag) { + hevc->used_4k_num = + READ_VREG(HEVC_SAO_MMU_STATUS) >> 16; + + if ((!is_skip_decoding(hevc, pic)) && + (hevc->used_4k_num >= 0) && + (hevc->cur_pic->scatter_alloc + == 1)) { + hevc_print(hevc, + H265_DEBUG_BUFMGR_MORE, + "%s pic index %d scatter_alloc %d page_start %d\n", + "decoder_mmu_box_free_idx_tail", + hevc->cur_pic->index, + hevc->cur_pic->scatter_alloc, + hevc->used_4k_num); + decoder_mmu_box_free_idx_tail( + hevc->mmu_box, + hevc->cur_pic->index, + hevc->used_4k_num); + hevc->cur_pic->scatter_alloc + = 2; + } + hevc->used_4k_num = -1; + } + } + + pic->output_mark = 1; + pic->recon_mark = 1; + } + + pic_display = output_pic(hevc, 1); + + if (pic_display) { + if ((pic_display->error_mark && + ((hevc->ignore_bufmgr_error & + 0x2) == 0)) + || (get_dbg_flag(hevc) & + H265_DEBUG_DISPLAY_CUR_FRAME) + || (get_dbg_flag(hevc) & + H265_DEBUG_NO_DISPLAY)) { + pic_display->output_ready = 0; + if (get_dbg_flag(hevc) & + H265_DEBUG_BUFMGR) { + hevc_print(hevc, 0, + "[BM] Display: POC %d, ", + pic_display->POC); + hevc_print_cont(hevc, 0, + "decoding index %d ==> ", + pic_display-> + decode_idx); + hevc_print_cont(hevc, 0, + "Debug or err,recycle it\n"); + } + } else { + if (pic_display-> + slice_type != 2) { + pic_display->output_ready = 0; + } else { + prepare_display_buf + (hevc, + pic_display); + hevc->first_pic_flag = 1; + } + } + } + } + vdec_schedule_work(&hevc->work); } @@ -7798,7 +9278,7 @@ pic_done: hevc->dec_result = DEC_RESULT_DONE; amhevc_stop(); reset_process_time(hevc); - if (READ_VREG(HEVC_AUX_DATA_SIZE) != 0) + if (aux_data_is_avaible(hevc)) dolby_get_meta(hevc); vdec_schedule_work(&hevc->work); @@ -7844,7 +9324,7 @@ pic_done: hevc_print(hevc, 0, "get NAL_UNIT_EOS, flush output\n"); #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION if ((vdec->master || vdec->slave) && - READ_VREG(HEVC_AUX_DATA_SIZE) != 0) { + aux_data_is_avaible(hevc)) { if (hevc->decoding_pic) dolby_get_meta(hevc); } @@ -7856,6 +9336,7 @@ pic_done: /* add to fix RAP_B_Bossen_1 */ hevc->m_pocRandomAccess = MAX_INT; flush_output(hevc, pic); + clear_poc_flag(hevc); WRITE_VREG(HEVC_DEC_STATUS_REG, HEVC_DISCARD_NAL); /* Interrupt Amrisc to excute */ WRITE_VREG(HEVC_MCPU_INTR_REQ, AMRISC_MAIN_REQ); @@ -8076,7 +9557,7 @@ pic_done: vdec->master == NULL && vdec->slave == NULL && #endif - READ_VREG(HEVC_AUX_DATA_SIZE) != 0 + aux_data_is_avaible(hevc) ) { dma_sync_single_for_cpu( amports_get_dma_device(), @@ -8188,10 +9669,16 @@ pic_done: hevc->lcu_size = 1 << (log + 3 + log_s); hevc->lcu_size_log2 = log2i(hevc->lcu_size); if (hevc->pic_w == 0 || hevc->pic_h == 0 - || hevc->lcu_size == 0) { + || hevc->lcu_size == 0 + || is_oversize(hevc->pic_w, hevc->pic_h) + || (!hevc->skip_first_nal && + (hevc->pic_h == 96) && (hevc->pic_w == 160))) { /* skip search next start code */ WRITE_VREG(HEVC_WAIT_FLAG, READ_VREG(HEVC_WAIT_FLAG) & (~0x2)); + if ( !hevc->skip_first_nal && + (hevc->pic_h == 96) && (hevc->pic_w == 160)) + hevc->skip_first_nal = 1; hevc->skip_flag = 1; WRITE_VREG(HEVC_DEC_STATUS_REG, HEVC_ACTION_DONE); /* Interrupt Amrisc to excute */ @@ -8404,6 +9891,16 @@ static irqreturn_t vh265_isr(int irq, void *data) if (hevc->pic_list_init_flag == 1) return IRQ_HANDLED; + if (!hevc->m_ins_flag) { + if (dec_status == HEVC_OVER_DECODE) { + hevc->over_decode = 1; + hevc_print(hevc, 0, + "isr: over decode\n"), + WRITE_VREG(HEVC_DEC_STATUS_REG, 0); + return IRQ_HANDLED; + } + } + return IRQ_WAKE_THREAD; } @@ -8414,16 +9911,16 @@ static void vh265_set_clk(struct work_struct *work) struct hevc_state_s, work); if (hevc->m_ins_flag == 0 && - hevc->get_frame_dur && hevc->show_frame_num > 60 && - hevc->frame_dur > 0 && hevc->saved_resolution != - hevc->frame_width * hevc->frame_height * - (96000 / hevc->frame_dur)) { - int fps = 96000 / hevc->frame_dur; - - if (hevc_source_changed(VFORMAT_HEVC, - hevc->frame_width, hevc->frame_height, fps) > 0) - hevc->saved_resolution = hevc->frame_width * - hevc->frame_height * fps; + hevc->get_frame_dur && hevc->show_frame_num > 60 && + hevc->frame_dur > 0 && hevc->saved_resolution != + hevc->frame_width * hevc->frame_height * + (96000 / hevc->frame_dur)) { + int fps = 96000 / hevc->frame_dur; + + if (hevc_source_changed(VFORMAT_HEVC, + hevc->frame_width, hevc->frame_height, fps) > 0) + hevc->saved_resolution = hevc->frame_width * + hevc->frame_height * fps; } } @@ -8622,7 +10119,7 @@ static void vh265_check_timer_func(unsigned long arg) if (dbg_cmd == 1) { u32 disp_laddr; - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXBB && + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXBB && get_double_write_mode(hevc) == 0) { disp_laddr = READ_VCBUS_REG(AFBC_BODY_BADDR) << 4; @@ -8640,7 +10137,11 @@ static void vh265_check_timer_func(unsigned long arg) dbg_cmd = 0; } /*don't changed at start.*/ - if (hevc->m_ins_flag == 0) + if (hevc->m_ins_flag == 0 && + hevc->get_frame_dur && hevc->show_frame_num > 60 && + hevc->frame_dur > 0 && hevc->saved_resolution != + hevc->frame_width * hevc->frame_height * + (96000 / hevc->frame_dur)) schedule_work(&hevc->set_clk_work); mod_timer(timer, jiffies + PUT_INTERVAL); @@ -8675,20 +10176,17 @@ static int h265_task_handle(void *data) hevc_print(hevc, 0, "uninit list\n"); hevc->uninit_list = 0; #ifdef USE_UNINIT_SEMA - if (use_cma && hevc->init_flag) { + if (use_cma) { up(&hevc->h265_uninit_done_sema); + while (!kthread_should_stop()) + msleep(1); break; } #endif } } - while (!kthread_should_stop()) { - msleep(1); - } - return 0; - } void vh265_free_cmabuf(void) @@ -8717,6 +10215,9 @@ int vh265_dec_status(struct vdec_info *vstatus) #else struct hevc_state_s *hevc = gHevc; #endif + if (!hevc) + return -1; + vstatus->frame_width = hevc->frame_width; vstatus->frame_height = hevc->frame_height; if (hevc->frame_dur != 0) @@ -8742,6 +10243,7 @@ int vh265_dec_status(struct vdec_info *vstatus) snprintf(vstatus->vdec_name, sizeof(vstatus->vdec_name), "%s", DRIVER_NAME); #endif + vstatus->ratio_control = hevc->ratio_control; return 0; } @@ -8794,11 +10296,25 @@ static void config_decode_mode(struct hevc_state_s *hevc) decode_mode = DECODE_MODE_MULTI_FRAMEBASE; #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION - else if (vdec->slave) - decode_mode = - (hevc->start_parser_type << 8) - | DECODE_MODE_MULTI_DVBAL; - else if (vdec->master) + else if (vdec->slave) { + if (force_bypass_dvenl & 0x80000000) + hevc->bypass_dvenl = force_bypass_dvenl & 0x1; + else + hevc->bypass_dvenl = hevc->bypass_dvenl_enable; + if (dolby_meta_with_el && hevc->bypass_dvenl) { + hevc->bypass_dvenl = 0; + hevc_print(hevc, 0, + "NOT support bypass_dvenl when meta_with_el\n"); + } + if (hevc->bypass_dvenl) + decode_mode = + (hevc->start_parser_type << 8) + | DECODE_MODE_MULTI_STREAMBASE; + else + decode_mode = + (hevc->start_parser_type << 8) + | DECODE_MODE_MULTI_DVBAL; + } else if (vdec->master) decode_mode = (hevc->start_parser_type << 8) | DECODE_MODE_MULTI_DVENL; @@ -8878,6 +10394,20 @@ static void vh265_prot_init(struct hevc_state_s *hevc) config_decode_mode(hevc); config_aux_buf(hevc); +#ifdef SWAP_HEVC_UCODE + if (!tee_enabled() && hevc->is_swap && + get_cpu_major_id() <= AM_MESON_CPU_MAJOR_ID_GXM) { + WRITE_VREG(HEVC_STREAM_SWAP_BUFFER2, hevc->mc_dma_handle); + /*pr_info("write swap buffer %x\n", (u32)(hevc->mc_dma_handle));*/ + } +#endif +#ifdef DETREFILL_ENABLE + if (hevc->is_swap && + get_cpu_major_id() <= AM_MESON_CPU_MAJOR_ID_GXM) { + WRITE_VREG(HEVC_SAO_DBG_MODE0, 0); + WRITE_VREG(HEVC_SAO_DBG_MODE1, 0); + } +#endif } static int vh265_local_init(struct hevc_state_s *hevc) @@ -8894,12 +10424,23 @@ static int vh265_local_init(struct hevc_state_s *hevc) hevc->get_frame_dur = false; hevc->frame_width = hevc->vh265_amstream_dec_info.width; hevc->frame_height = hevc->vh265_amstream_dec_info.height; - if (OVER_SIZE(hevc->frame_width, hevc->frame_height)) { + if (is_oversize(hevc->frame_width, hevc->frame_height)) { pr_info("over size : %u x %u.\n", hevc->frame_width, hevc->frame_height); hevc->fatal_error |= DECODER_FATAL_ERROR_SIZE_OVERFLOW; return ret; } + + if (hevc->max_pic_w && hevc->max_pic_h) { + hevc->is_4k = !(hevc->max_pic_w && hevc->max_pic_h) || + ((hevc->max_pic_w * hevc->max_pic_h) > + 1920 * 1088) ? true : false; + } else { + hevc->is_4k = !(hevc->frame_width && hevc->frame_height) || + ((hevc->frame_width * hevc->frame_height) > + 1920 * 1088) ? true : false; + } + hevc->frame_dur = (hevc->vh265_amstream_dec_info.rate == 0) ? 3600 : hevc->vh265_amstream_dec_info.rate; @@ -8967,29 +10508,35 @@ static s32 vh265_init(struct hevc_state_s *hevc) if (vh265_local_init(hevc) < 0) return -EBUSY; + mutex_init(&hevc->chunks_mutex); INIT_WORK(&hevc->notify_work, vh265_notify_work); INIT_WORK(&hevc->set_clk_work, vh265_set_clk); + fw = vmalloc(sizeof(struct firmware_s) + fw_size); if (IS_ERR_OR_NULL(fw)) return -ENOMEM; -#ifdef MULTI_INSTANCE_SUPPORT - if (tee_enabled()) - size = 1; - else -#endif - if (hevc->mmu_enable) { - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) { - size = get_firmware_data(VIDEO_DEC_HEVC, fw->data); - hevc_print(hevc, 0, "vh265 ucode loaded!\n"); - } else { + if (hevc->mmu_enable) + if (get_cpu_major_id() > AM_MESON_CPU_MAJOR_ID_GXM) size = get_firmware_data(VIDEO_DEC_HEVC_MMU, fw->data); - hevc_print(hevc, 0, "vh265 mmu ucode loaded!\n"); + else { + if (!hevc->is_4k) { + /* if an older version of the fw was loaded, */ + /* needs try to load noswap fw because the */ + /* old fw package dose not contain the swap fw.*/ + size = get_firmware_data( + VIDEO_DEC_HEVC_MMU_SWAP, fw->data); + if (size < 0) + size = get_firmware_data( + VIDEO_DEC_HEVC_MMU, fw->data); + else if (size) + hevc->is_swap = true; + } else + size = get_firmware_data(VIDEO_DEC_HEVC_MMU, + fw->data); } - } else { + else size = get_firmware_data(VIDEO_DEC_HEVC, fw->data); - hevc_print(hevc, 0, "vh265 ucode loaded!\n"); - } if (size < 0) { pr_err("get firmware fail.\n"); @@ -8999,6 +10546,31 @@ static s32 vh265_init(struct hevc_state_s *hevc) fw->len = size; +#ifdef SWAP_HEVC_UCODE + if (!tee_enabled() && hevc->is_swap && + get_cpu_major_id() <= AM_MESON_CPU_MAJOR_ID_GXM) { + if (hevc->mmu_enable) { + hevc->swap_size = (4 * (4 * SZ_1K)); /*max 4 swap code, each 0x400*/ + hevc->mc_cpu_addr = + dma_alloc_coherent(amports_get_dma_device(), + hevc->swap_size, + &hevc->mc_dma_handle, GFP_KERNEL); + if (!hevc->mc_cpu_addr) { + amhevc_disable(); + pr_info("vh265 mmu swap ucode loaded fail.\n"); + return -ENOMEM; + } + + memcpy((u8 *) hevc->mc_cpu_addr, fw->data + SWAP_HEVC_OFFSET, + hevc->swap_size); + + hevc_print(hevc, 0, + "vh265 mmu ucode swap loaded %x\n", + hevc->mc_dma_handle); + } + } +#endif + #ifdef MULTI_INSTANCE_SUPPORT if (hevc->m_ins_flag) { hevc->timer.data = (ulong) hevc; @@ -9020,24 +10592,36 @@ static s32 vh265_init(struct hevc_state_s *hevc) return 0; } #endif + hevc_enable_DMC(hw_to_vdec(hevc)); amhevc_enable(); - if (size == 1) { - pr_info ("tee load ok"); - - if (hevc->mmu_enable) { - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) - ret = tee_load_video_fw((u32)VIDEO_DEC_HEVC, 0); - else - ret = tee_load_video_fw((u32)VIDEO_DEC_HEVC_MMU, 0); - } else - ret = tee_load_video_fw((u32)VIDEO_DEC_HEVC, 0); - } else + if (hevc->mmu_enable) + if (get_cpu_major_id() > AM_MESON_CPU_MAJOR_ID_GXM) + ret = amhevc_loadmc_ex(VFORMAT_HEVC, "h265_mmu", fw->data); + else { + if (!hevc->is_4k) { + /* if an older version of the fw was loaded, */ + /* needs try to load noswap fw because the */ + /* old fw package dose not contain the swap fw. */ + ret = amhevc_loadmc_ex(VFORMAT_HEVC, + "hevc_mmu_swap", fw->data); + if (ret < 0) + ret = amhevc_loadmc_ex(VFORMAT_HEVC, + "h265_mmu", fw->data); + else + hevc->is_swap = true; + } else + ret = amhevc_loadmc_ex(VFORMAT_HEVC, + "h265_mmu", fw->data); + } + else ret = amhevc_loadmc_ex(VFORMAT_HEVC, NULL, fw->data); if (ret < 0) { amhevc_disable(); vfree(fw); + pr_err("H265: the %s fw loading failed, err: %x\n", + tee_enabled() ? "TEE" : "local", ret); return -EBUSY; } @@ -9045,6 +10629,11 @@ static s32 vh265_init(struct hevc_state_s *hevc) hevc->stat |= STAT_MC_LOAD; +#ifdef DETREFILL_ENABLE + if (hevc->is_swap && + get_cpu_major_id() <= AM_MESON_CPU_MAJOR_ID_GXM) + init_detrefill_buf(hevc); +#endif /* enable AMRISC side protocol */ vh265_prot_init(hevc); @@ -9067,12 +10656,13 @@ static s32 vh265_init(struct hevc_state_s *hevc) vf_notify_receiver(hevc->provider_name, VFRAME_EVENT_PROVIDER_START, NULL); if (hevc->frame_dur != 0) { - if (!is_reset) + if (!is_reset) { vf_notify_receiver(hevc->provider_name, VFRAME_EVENT_PROVIDER_FR_HINT, (void *) ((unsigned long)hevc->frame_dur)); - fr_hint_status = VDEC_HINTED; + fr_hint_status = VDEC_HINTED; + } } else fr_hint_status = VDEC_NEED_HINT; #else @@ -9143,17 +10733,21 @@ static s32 vh265_init(struct hevc_state_s *hevc) (1 << 3)); /* 3 */ } #endif - amhevc_start(); +#ifdef SWAP_HEVC_UCODE + if (!tee_enabled() && hevc->is_swap && + get_cpu_major_id() <= AM_MESON_CPU_MAJOR_ID_GXM) { + WRITE_VREG(HEVC_STREAM_SWAP_BUFFER2, hevc->mc_dma_handle); + /*pr_info("write swap buffer %x\n", (u32)(hevc->mc_dma_handle));*/ + } +#endif - hevc->stat |= STAT_VDEC_RUN; #ifndef MULTI_INSTANCE_SUPPORT set_vdec_func(&vh265_dec_status); #endif + amhevc_start(); + hevc->stat |= STAT_VDEC_RUN; hevc->init_flag = 1; - if (hevc->mmu_enable) - error_handle_threshold = 300; - else - error_handle_threshold = 30; + error_handle_threshold = 30; /* pr_info("%d, vh265_init, RP=0x%x\n", * __LINE__, READ_VREG(HEVC_STREAM_RD_PTR)); */ @@ -9195,7 +10789,7 @@ static int vh265_stop(struct hevc_state_s *hevc) } if (hevc->stat & STAT_VF_HOOK) { - if (fr_hint_status == VDEC_HINTED && !is_reset) { + if (fr_hint_status == VDEC_HINTED) { vf_notify_receiver(hevc->provider_name, VFRAME_EVENT_PROVIDER_FR_END_HINT, NULL); @@ -9211,12 +10805,10 @@ static int vh265_stop(struct hevc_state_s *hevc) hevc->uninit_list = 1; up(&h265_sema); #ifdef USE_UNINIT_SEMA - if (hevc->init_flag) { - down(&hevc->h265_uninit_done_sema); - if (!IS_ERR(h265_task)) { - kthread_stop(h265_task); - h265_task = NULL; - } + down(&hevc->h265_uninit_done_sema); + if (!IS_ERR(h265_task)) { + kthread_stop(h265_task); + h265_task = NULL; } #else while (hevc->uninit_list) /* wait uninit complete */ @@ -9225,6 +10817,7 @@ static int vh265_stop(struct hevc_state_s *hevc) } hevc->init_flag = 0; + hevc->first_sc_checked = 0; cancel_work_sync(&hevc->notify_work); cancel_work_sync(&hevc->set_clk_work); uninit_mmu_buffers(hevc); @@ -9278,6 +10871,43 @@ static void timeout_process(struct hevc_state_s *hevc) vdec_schedule_work(&hevc->work); } +#ifdef CONSTRAIN_MAX_BUF_NUM +static int get_vf_ref_only_buf_count(struct hevc_state_s *hevc) +{ + struct PIC_s *pic; + int i; + int count = 0; + for (i = 0; i < MAX_REF_PIC_NUM; i++) { + pic = hevc->m_PIC[i]; + if (pic == NULL || pic->index == -1) + continue; + if (pic->output_mark == 0 && pic->referenced == 0 + && pic->output_ready == 1) + count++; + } + + return count; +} + +static int get_used_buf_count(struct hevc_state_s *hevc) +{ + struct PIC_s *pic; + int i; + int count = 0; + for (i = 0; i < MAX_REF_PIC_NUM; i++) { + pic = hevc->m_PIC[i]; + if (pic == NULL || pic->index == -1) + continue; + if (pic->output_mark != 0 || pic->referenced != 0 + || pic->output_ready != 0) + count++; + } + + return count; +} +#endif + + static unsigned char is_new_pic_available(struct hevc_state_s *hevc) { struct PIC_s *new_pic = NULL; @@ -9346,6 +10976,7 @@ static int vmh265_stop(struct hevc_state_s *hevc) #endif } hevc->init_flag = 0; + hevc->first_sc_checked = 0; cancel_work_sync(&hevc->work); cancel_work_sync(&hevc->notify_work); cancel_work_sync(&hevc->set_clk_work); @@ -9363,10 +10994,20 @@ static unsigned char get_data_check_sum { int jj; int sum = 0; - u8 *data = ((u8 *)hevc->chunk->block->start_virt) + - hevc->chunk->offset; + u8 *data = NULL; + + if (!hevc->chunk->block->is_mapped) + data = codec_mm_vmap(hevc->chunk->block->start + + hevc->chunk->offset, size); + else + data = ((u8 *)hevc->chunk->block->start_virt) + + hevc->chunk->offset; + for (jj = 0; jj < size; jj++) sum += data[jj]; + + if (!hevc->chunk->block->is_mapped) + codec_mm_unmap_phyaddr(data); return sum; } @@ -9492,7 +11133,10 @@ static void vh265_work(struct work_struct *work) READ_VREG(HEVC_STREAM_WR_PTR), READ_VREG(HEVC_STREAM_RD_PTR), READ_VREG(HEVC_MPC_E)); + mutex_lock(&hevc->chunks_mutex); vdec_vframe_dirty(vdec, hevc->chunk); + hevc->chunk = NULL; + mutex_unlock(&hevc->chunks_mutex); vdec_clean_input(vdec); } @@ -9521,9 +11165,17 @@ static void vh265_work(struct work_struct *work) if (get_dbg_flag(hevc) & PRINT_FRAMEBASE_DATA) { int jj; - u8 *data = - ((u8 *)hevc->chunk->block->start_virt) + - hevc->chunk->offset; + u8 *data = NULL; + + if (!hevc->chunk->block->is_mapped) + data = codec_mm_vmap( + hevc->chunk->block->start + + hevc->chunk->offset, r); + else + data = ((u8 *) + hevc->chunk->block->start_virt) + + hevc->chunk->offset; + for (jj = 0; jj < r; jj++) { if ((jj & 0xf) == 0) hevc_print(hevc, @@ -9537,6 +11189,9 @@ static void vh265_work(struct work_struct *work) PRINT_FRAMEBASE_DATA, "\n"); } + + if (!hevc->chunk->block->is_mapped) + codec_mm_unmap_phyaddr(data); } decode_size = hevc->chunk->size + @@ -9566,7 +11221,16 @@ static void vh265_work(struct work_struct *work) /* if (!hevc->ctx_valid) hevc->ctx_valid = 1; */ decode_frame_count[hevc->index]++; - if (hevc->mmu_enable) { +#ifdef DETREFILL_ENABLE + if (hevc->is_swap && + get_cpu_major_id() <= AM_MESON_CPU_MAJOR_ID_GXM) { + if (hevc->delrefill_check == 2) { + delrefill(hevc); + amhevc_stop(); + } + } +#endif + if (hevc->mmu_enable && ((hevc->double_write_mode & 0x10) == 0)) { hevc->used_4k_num = READ_VREG(HEVC_SAO_MMU_STATUS) >> 16; if (hevc->used_4k_num >= 0 && @@ -9589,11 +11253,15 @@ static void vh265_work(struct work_struct *work) hevc->pic_decoded_lcu_idx = READ_VREG(HEVC_PARSER_LCU_START) & 0xffffff; - hevc->over_decode = - (READ_VREG(HEVC_SHIFT_STATUS) >> 15) & 0x1; - if (hevc->over_decode) - hevc_print(hevc, 0, - "!!!Over decode\n"); + + if (vdec->master == NULL && vdec->slave == NULL && + hevc->empty_flag == 0) { + hevc->over_decode = + (READ_VREG(HEVC_SHIFT_STATUS) >> 15) & 0x1; + if (hevc->over_decode) + hevc_print(hevc, 0, + "!!!Over decode\n"); + } if (is_log_enable(hevc)) add_log(hevc, @@ -9672,7 +11340,10 @@ static void vh265_work(struct work_struct *work) hevc->shift_byte_count_lo; } #endif + mutex_lock(&hevc->chunks_mutex); vdec_vframe_dirty(hw_to_vdec(hevc), hevc->chunk); + hevc->chunk = NULL; + mutex_unlock(&hevc->chunks_mutex); } else if (hevc->dec_result == DEC_RESULT_AGAIN) { /* stream base: stream buf empty or timeout @@ -9691,7 +11362,7 @@ static void vh265_work(struct work_struct *work) hevc->eos = 1; #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION if ((vdec->master || vdec->slave) && - READ_VREG(HEVC_AUX_DATA_SIZE) != 0) + aux_data_is_avaible(hevc)) dolby_get_meta(hevc); #endif check_pic_decoded_error(hevc, @@ -9722,7 +11393,10 @@ static void vh265_work(struct work_struct *work) hevc->shift_byte_count_lo; } #endif + mutex_lock(&hevc->chunks_mutex); vdec_vframe_dirty(hw_to_vdec(hevc), hevc->chunk); + hevc->chunk = NULL; + mutex_unlock(&hevc->chunks_mutex); } else if (hevc->dec_result == DEC_RESULT_FORCE_EXIT) { hevc_print(hevc, PRINT_FLAG_VDEC_STATUS, "%s: force exit\n", @@ -9762,8 +11436,10 @@ static void vh265_work(struct work_struct *work) #endif /* mark itself has all HW resource released and input released */ - vdec_core_finish_run(vdec, CORE_MASK_VDEC_1 | CORE_MASK_HEVC); - + if (vdec->parallel_dec == 1) + vdec_core_finish_run(vdec, CORE_MASK_HEVC); + else + vdec_core_finish_run(vdec, CORE_MASK_VDEC_1 | CORE_MASK_HEVC); if (hevc->vdec_cb) hevc->vdec_cb(hw_to_vdec(hevc), hevc->vdec_cb_arg); @@ -9775,11 +11451,12 @@ static int vh265_hw_ctx_restore(struct hevc_state_s *hevc) vh265_prot_init(hevc); return 0; } - static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask) { struct hevc_state_s *hevc = (struct hevc_state_s *)vdec->private; + int tvp = vdec_secure(hw_to_vdec(hevc)) ? + CODEC_MM_FLAGS_TVP : 0; bool ret = 0; if (step == 0x12) return 0; @@ -9788,6 +11465,29 @@ static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask) if (hevc->eos) return 0; + if (!hevc->first_sc_checked && hevc->mmu_enable) { + int size = decoder_mmu_box_sc_check(hevc->mmu_box, tvp); + hevc->first_sc_checked =1; + hevc_print(hevc, 0, + "vh265 cached=%d need_size=%d speed= %d ms\n", + size, (hevc->need_cache_size >> PAGE_SHIFT), + (int)(get_jiffies_64() - hevc->sc_start_time) * 1000/HZ); + } + if (vdec_stream_based(vdec) && (hevc->init_flag == 0) + && pre_decode_buf_level != 0) { + u32 rp, wp, level; + + rp = READ_PARSER_REG(PARSER_VIDEO_RP); + wp = READ_PARSER_REG(PARSER_VIDEO_WP); + if (wp < rp) + level = vdec->input.size + wp - rp; + else + level = wp - rp; + + if (level < pre_decode_buf_level) + return 0; + } + #ifdef AGAIN_HAS_THRESHOLD if (hevc->next_again_flag && (!vdec_frame_based(vdec))) { @@ -9795,8 +11495,12 @@ static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask) READ_PARSER_REG(PARSER_VIDEO_WP); if (parser_wr_ptr >= hevc->pre_parser_wr_ptr && (parser_wr_ptr - hevc->pre_parser_wr_ptr) < - again_threshold) + again_threshold) { + int r = vdec_sync_input(vdec); + hevc_print(hevc, + PRINT_FLAG_VDEC_DETAIL, "%s buf lelvel:%x\n", __func__, r); return 0; + } } #endif @@ -9816,11 +11520,40 @@ static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask) PRINT_FLAG_VDEC_DETAIL, "%s=>%d\r\n", __func__, ret); } + +#ifdef CONSTRAIN_MAX_BUF_NUM + if (hevc->pic_list_init_flag == 3) { + if (run_ready_max_vf_only_num > 0 && + get_vf_ref_only_buf_count(hevc) >= + run_ready_max_vf_only_num + ) + ret = 0; + if (run_ready_display_q_num > 0 && + kfifo_len(&hevc->display_q) >= + run_ready_display_q_num) + ret = 0; + + /*avoid more buffers consumed when + switching resolution*/ + if (run_ready_max_buf_num == 0xff && + get_used_buf_count(hevc) >= + get_work_pic_num(hevc)) + ret = 0; + else if (run_ready_max_buf_num && + get_used_buf_count(hevc) >= + run_ready_max_buf_num) + ret = 0; + } +#endif + if (ret) not_run_ready[hevc->index] = 0; else not_run_ready[hevc->index]++; - return ret ? (CORE_MASK_VDEC_1 | CORE_MASK_HEVC) : 0; + if (vdec->parallel_dec == 1) + return ret ? (CORE_MASK_HEVC) : 0; + else + return ret ? (CORE_MASK_VDEC_1 | CORE_MASK_HEVC) : 0; } static void run(struct vdec_s *vdec, unsigned long mask, @@ -9834,7 +11567,7 @@ static void run(struct vdec_s *vdec, unsigned long mask, run_count[hevc->index]++; hevc->vdec_cb_arg = arg; hevc->vdec_cb = callback; - + hevc->aux_data_dirty = 1; hevc_reset_core(vdec); #ifdef AGAIN_HAS_THRESHOLD @@ -9846,7 +11579,6 @@ static void run(struct vdec_s *vdec, unsigned long mask, if (r < 0) { input_empty[hevc->index]++; hevc->dec_result = DEC_RESULT_AGAIN; - hevc_print(hevc, PRINT_FLAG_VDEC_DETAIL, "ammvdec_vh265: Insufficient data\n"); @@ -9855,7 +11587,6 @@ static void run(struct vdec_s *vdec, unsigned long mask, } input_empty[hevc->index] = 0; hevc->dec_result = DEC_RESULT_NONE; - if (vdec_frame_based(vdec) && ((get_dbg_flag(hevc) & PRINT_FLAG_VDEC_STATUS) || is_log_enable(hevc))) @@ -9883,8 +11614,15 @@ static void run(struct vdec_s *vdec, unsigned long mask, if ((get_dbg_flag(hevc) & PRINT_FRAMEBASE_DATA) && input_frame_based(vdec)) { int jj; - u8 *data = ((u8 *)hevc->chunk->block->start_virt) + - hevc->chunk->offset; + u8 *data = NULL; + + if (!hevc->chunk->block->is_mapped) + data = codec_mm_vmap(hevc->chunk->block->start + + hevc->chunk->offset, r); + else + data = ((u8 *)hevc->chunk->block->start_virt) + + hevc->chunk->offset; + for (jj = 0; jj < r; jj++) { if ((jj & 0xf) == 0) hevc_print(hevc, PRINT_FRAMEBASE_DATA, @@ -9895,32 +11633,72 @@ static void run(struct vdec_s *vdec, unsigned long mask, hevc_print_cont(hevc, PRINT_FRAMEBASE_DATA, "\n"); } - } - if (hevc->mmu_enable) { - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) - loadr = amhevc_vdec_loadmc_ex(vdec, - "vh265_mc", hevc->fw->data); + if (!hevc->chunk->block->is_mapped) + codec_mm_unmap_phyaddr(data); + } + if (vdec->mc_loaded) { + /*firmware have load before, + and not changes to another. + ignore reload. + */ + if (tee_enabled() && hevc->is_swap && + get_cpu_major_id() <= AM_MESON_CPU_MAJOR_ID_GXM) + WRITE_VREG(HEVC_STREAM_SWAP_BUFFER2, hevc->swap_addr); + } else { + if (hevc->mmu_enable) + if (get_cpu_major_id() > AM_MESON_CPU_MAJOR_ID_GXM) + loadr = amhevc_vdec_loadmc_ex(VFORMAT_HEVC, vdec, + "h265_mmu", hevc->fw->data); + else { + if (!hevc->is_4k) { + /* if an older version of the fw was loaded, */ + /* needs try to load noswap fw because the */ + /* old fw package dose not contain the swap fw.*/ + loadr = amhevc_vdec_loadmc_ex( + VFORMAT_HEVC, vdec, + "hevc_mmu_swap", + hevc->fw->data); + if (loadr < 0) + loadr = amhevc_vdec_loadmc_ex( + VFORMAT_HEVC, vdec, + "h265_mmu", + hevc->fw->data); + else + hevc->is_swap = true; + } else + loadr = amhevc_vdec_loadmc_ex( + VFORMAT_HEVC, vdec, + "h265_mmu", hevc->fw->data); + } else - loadr = amhevc_vdec_loadmc_ex(vdec, - "vh265_mc_mmu", hevc->fw->data); - } else - loadr = amhevc_vdec_loadmc_ex(vdec, - "vh265_mc", hevc->fw->data); + loadr = amhevc_vdec_loadmc_ex(VFORMAT_HEVC, vdec, + NULL, hevc->fw->data); - if (loadr < 0) { - amhevc_disable(); - hevc_print(hevc, 0, - "%s: Error amvdec_loadmc fail\n", - __func__); - return; + if (loadr < 0) { + amhevc_disable(); + hevc_print(hevc, 0, "H265: the %s fw loading failed, err: %x\n", + tee_enabled() ? "TEE" : "local", loadr); + hevc->dec_result = DEC_RESULT_FORCE_EXIT; + vdec_schedule_work(&hevc->work); + return; + } + + if (tee_enabled() && hevc->is_swap && + get_cpu_major_id() <= AM_MESON_CPU_MAJOR_ID_GXM) + hevc->swap_addr = READ_VREG(HEVC_STREAM_SWAP_BUFFER2); +#ifdef DETREFILL_ENABLE + if (hevc->is_swap && + get_cpu_major_id() <= AM_MESON_CPU_MAJOR_ID_GXM) + init_detrefill_buf(hevc); +#endif + vdec->mc_loaded = 1; + vdec->mc_type = VFORMAT_HEVC; } - if (vh265_hw_ctx_restore(hevc) < 0) { vdec_schedule_work(&hevc->work); return; } - vdec_enable_input(vdec); WRITE_VREG(HEVC_DEC_STATUS_REG, HEVC_ACTION_DONE); @@ -9929,6 +11707,7 @@ static void run(struct vdec_s *vdec, unsigned long mask, WRITE_VREG(HEVC_SHIFT_BYTE_COUNT, 0); r = hevc->chunk->size + (hevc->chunk->offset & (VDEC_FIFO_ALIGN - 1)); + hevc->decode_size = r; } #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION else { @@ -10007,14 +11786,16 @@ static int amvdec_h265_probe(struct platform_device *pdev) hevc_print(hevc, 0, "%s\r\n", __func__); mutex_lock(&vh265_mutex); - if ((get_cpu_type() >= MESON_CPU_MAJOR_ID_GXTVBB) && + if ((get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXTVBB) && (parser_sei_enable & 0x100) == 0) parser_sei_enable = 7; /*old 1*/ hevc->m_ins_flag = 0; hevc->init_flag = 0; + hevc->first_sc_checked = 0; hevc->uninit_list = 0; hevc->fatal_error = 0; hevc->show_frame_num = 0; + hevc->frameinfo_enable = 1; #ifdef MULTI_INSTANCE_SUPPORT hevc->platform_dev = pdev; platform_set_drvdata(pdev, pdata); @@ -10028,7 +11809,7 @@ static int amvdec_h265_probe(struct platform_device *pdev) return -EFAULT; } if (mmu_enable_force == 0) { - if (get_cpu_type() < MESON_CPU_MAJOR_ID_GXL + if (get_cpu_major_id() < AM_MESON_CPU_MAJOR_ID_GXL || double_write_mode == 0x10) hevc->mmu_enable = 0; else @@ -10046,7 +11827,6 @@ static int amvdec_h265_probe(struct platform_device *pdev) work_buf_size, DRIVER_NAME, &hevc->buf_start); if (ret < 0) { uninit_mmu_buffers(hevc); - devm_kfree(&pdev->dev, (void *)hevc); vfree(hevc); mutex_unlock(&vh265_mutex); return ret; @@ -10091,6 +11871,7 @@ static int amvdec_h265_probe(struct platform_device *pdev) hevc_local_uninit(hevc); uninit_mmu_buffers(hevc); vfree(hevc); + pdata->dec_status = NULL; mutex_unlock(&vh265_mutex); return -ENODEV; } @@ -10154,11 +11935,13 @@ static void vh265_dump_state(struct vdec_s *vdec) "====== %s\n", __func__); hevc_print(hevc, 0, - "width/height (%d/%d), reorder_pic_num %d buf count(bufspec size) %d\n", + "width/height (%d/%d), reorder_pic_num %d buf count(bufspec size) %d, video_signal_type 0x%x, is_swap %d\n", hevc->frame_width, hevc->frame_height, hevc->sps_num_reorder_pics_0, - get_work_pic_num(hevc) + get_work_pic_num(hevc), + hevc->video_signal_type_debug, + hevc->is_swap ); hevc_print(hevc, 0, @@ -10270,9 +12053,13 @@ static void vh265_dump_state(struct vdec_s *vdec) int jj; if (hevc->chunk && hevc->chunk->block && hevc->chunk->size > 0) { - u8 *data = - ((u8 *)hevc->chunk->block->start_virt) + - hevc->chunk->offset; + u8 *data = NULL; + if (!hevc->chunk->block->is_mapped) + data = codec_mm_vmap(hevc->chunk->block->start + + hevc->chunk->offset, hevc->chunk->size); + else + data = ((u8 *)hevc->chunk->block->start_virt) + + hevc->chunk->offset; hevc_print(hevc, 0, "frame data size 0x%x\n", hevc->chunk->size); @@ -10289,11 +12076,15 @@ static void vh265_dump_state(struct vdec_s *vdec) PRINT_FRAMEBASE_DATA, "\n"); } + + if (!hevc->chunk->block->is_mapped) + codec_mm_unmap_phyaddr(data); } } } + static int ammvdec_h265_probe(struct platform_device *pdev) { @@ -10327,11 +12118,14 @@ static int ammvdec_h265_probe(struct platform_device *pdev) pdata->dump_state = vh265_dump_state; hevc->index = pdev->id; + hevc->m_ins_flag = 1; - if (pdata->use_vfm_path) + if (pdata->use_vfm_path) { snprintf(pdata->vf_provider_name, VDEC_PROVIDER_NAME_SIZE, VFM_DEC_PROVIDER_NAME); + hevc->frameinfo_enable = 1; + } #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION else if (vdec_dual(pdata)) { struct hevc_state_s *hevc_pair = NULL; @@ -10382,6 +12176,12 @@ static int ammvdec_h265_probe(struct platform_device *pdev) else hevc->double_write_mode = double_write_mode; + if (get_config_int(pdata->config, "save_buffer_mode", + &config_val) == 0) + hevc->save_buffer_mode = config_val; + else + hevc->save_buffer_mode = 0; + /*use ptr config for max_pic_w, etc*/ if (get_config_int(pdata->config, "hevc_buf_width", &config_val) == 0) { @@ -10394,16 +12194,22 @@ static int ammvdec_h265_probe(struct platform_device *pdev) #endif } else { - hevc->vh265_amstream_dec_info.width = 0; - hevc->vh265_amstream_dec_info.height = 0; - hevc->vh265_amstream_dec_info.rate = 30; - hevc->dynamic_buf_num_margin = dynamic_buf_num_margin; + if (pdata->sys_info) + hevc->vh265_amstream_dec_info = *pdata->sys_info; + else { + hevc->vh265_amstream_dec_info.width = 0; + hevc->vh265_amstream_dec_info.height = 0; + hevc->vh265_amstream_dec_info.rate = 30; + } hevc->double_write_mode = double_write_mode; } + if (hevc->save_buffer_mode && dynamic_buf_num_margin > 2) + hevc->dynamic_buf_num_margin = dynamic_buf_num_margin -2; + else + hevc->dynamic_buf_num_margin = dynamic_buf_num_margin; if (mmu_enable_force == 0) { - if (get_cpu_type() < MESON_CPU_MAJOR_ID_GXL - || hevc->double_write_mode == 0x10) + if (get_cpu_major_id() < AM_MESON_CPU_MAJOR_ID_GXL) hevc->mmu_enable = 0; else hevc->mmu_enable = 1; @@ -10416,6 +12222,7 @@ static int ammvdec_h265_probe(struct platform_device *pdev) /* devm_kfree(&pdev->dev, (void *)hevc);*/ if (hevc) vfree((void *)hevc); + pdata->dec_status = NULL; return -EFAULT; } #if 0 @@ -10431,28 +12238,21 @@ static int ammvdec_h265_probe(struct platform_device *pdev) /* devm_kfree(&pdev->dev, (void *)hevc); */ if (hevc) vfree((void *)hevc); + pdata->dec_status = NULL; mutex_unlock(&vh265_mutex); return ret; } hevc->buf_size = work_buf_size; #endif - if ((get_cpu_type() >= MESON_CPU_MAJOR_ID_GXTVBB) && + if ((get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXTVBB) && (parser_sei_enable & 0x100) == 0) parser_sei_enable = 7; - hevc->m_ins_flag = 1; hevc->init_flag = 0; + hevc->first_sc_checked = 0; hevc->uninit_list = 0; hevc->fatal_error = 0; hevc->show_frame_num = 0; - if (pdata == NULL) { - hevc_print(hevc, 0, - "\namvdec_h265 memory resource undefined.\n"); - uninit_mmu_buffers(hevc); - /* devm_kfree(&pdev->dev, (void *)hevc); */ - if (hevc) - vfree((void *)hevc); - return -EFAULT; - } + /* *hevc->mc_buf_spec.buf_end = pdata->mem_end + 1; *for (i = 0; i < WORK_BUF_SPEC_NUM; i++) @@ -10481,6 +12281,7 @@ static int ammvdec_h265_probe(struct platform_device *pdev) /* devm_kfree(&pdev->dev, (void *)hevc); */ if (hevc) vfree((void *)hevc); + pdata->dec_status = NULL; return -ENODEV; } @@ -10489,9 +12290,11 @@ static int ammvdec_h265_probe(struct platform_device *pdev) /*set the max clk for smooth playing...*/ hevc_source_changed(VFORMAT_HEVC, 3840, 2160, 60); - - vdec_core_request(pdata, CORE_MASK_VDEC_1 | CORE_MASK_HEVC - | CORE_MASK_COMBINE); + if (pdata->parallel_dec == 1) + vdec_core_request(pdata, CORE_MASK_HEVC); + else + vdec_core_request(pdata, CORE_MASK_VDEC_1 | CORE_MASK_HEVC + | CORE_MASK_COMBINE); return 0; } @@ -10501,6 +12304,10 @@ static int ammvdec_h265_remove(struct platform_device *pdev) struct hevc_state_s *hevc = (struct hevc_state_s *) (((struct vdec_s *)(platform_get_drvdata(pdev)))->private); + struct vdec_s *vdec = hw_to_vdec(hevc); + + if (hevc == NULL) + return 0; if (get_dbg_flag(hevc)) hevc_print(hevc, 0, "%s\r\n", __func__); @@ -10508,12 +12315,14 @@ static int ammvdec_h265_remove(struct platform_device *pdev) vmh265_stop(hevc); /* vdec_source_changed(VFORMAT_H264, 0, 0, 0); */ - - vdec_core_release(hw_to_vdec(hevc), CORE_MASK_HEVC); + if (vdec->parallel_dec == 1) + vdec_core_release(hw_to_vdec(hevc), CORE_MASK_HEVC); + else + vdec_core_release(hw_to_vdec(hevc), CORE_MASK_HEVC); vdec_set_status(hw_to_vdec(hevc), VDEC_STATUS_DISCONNECTED); - if (hevc) - vfree((void *)hevc); + + vfree((void *)hevc); return 0; } @@ -10594,14 +12403,15 @@ static struct mconfig_node decoder_265_node; static int __init amvdec_h265_driver_init_module(void) { struct BuffInfo_s *p_buf_info; -#ifdef SUPPORT_4K2K - if (vdec_is_support_4k()) - p_buf_info = &amvh265_workbuff_spec[1]; - else + + if (vdec_is_support_4k()) { + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) + p_buf_info = &amvh265_workbuff_spec[2]; + else + p_buf_info = &amvh265_workbuff_spec[1]; + } else p_buf_info = &amvh265_workbuff_spec[0]; -#else - p_buf_info = &amvh265_workbuff_spec[0]; -#endif + init_buff_spec(NULL, p_buf_info); work_buf_size = (p_buf_info->end_adr - p_buf_info->start_adr @@ -10638,10 +12448,13 @@ static int __init amvdec_h265_driver_init_module(void) if (is_meson_m8m2_cpu()) { /* m8m2 support 4k */ amvdec_h265_profile.profile = "4k"; - } else if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXBB) { + } else if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) { amvdec_h265_profile.profile = - "4k, 9bit, 10bit, dwrite, compressed"; - } else if (get_cpu_type() >= MESON_CPU_MAJOR_ID_MG9TV) + "8k, 8bit, 10bit, dwrite, compressed"; + }else if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXBB) { + amvdec_h265_profile.profile = + "4k, 8bit, 10bit, dwrite, compressed"; + } else if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_MG9TV) amvdec_h265_profile.profile = "4k"; } #endif @@ -10776,6 +12589,17 @@ MODULE_PARM_DESC(max_buf_num, "\n max_buf_num\n"); module_param(buf_alloc_size, uint, 0664); MODULE_PARM_DESC(buf_alloc_size, "\n buf_alloc_size\n"); +#ifdef CONSTRAIN_MAX_BUF_NUM +module_param(run_ready_max_vf_only_num, uint, 0664); +MODULE_PARM_DESC(run_ready_max_vf_only_num, "\n run_ready_max_vf_only_num\n"); + +module_param(run_ready_display_q_num, uint, 0664); +MODULE_PARM_DESC(run_ready_display_q_num, "\n run_ready_display_q_num\n"); + +module_param(run_ready_max_buf_num, uint, 0664); +MODULE_PARM_DESC(run_ready_max_buf_num, "\n run_ready_max_buf_num\n"); +#endif + #if 0 module_param(re_config_pic_flag, uint, 0664); MODULE_PARM_DESC(re_config_pic_flag, "\n re_config_pic_flag\n"); @@ -10864,6 +12688,10 @@ module_param_array(input_empty, uint, module_param_array(not_run_ready, uint, &max_decode_instance_num, 0664); + +module_param_array(ref_frame_mark_flag, uint, + &max_decode_instance_num, 0664); + #endif #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION module_param(dv_toggle_prov_name, uint, 0664); @@ -10871,6 +12699,9 @@ MODULE_PARM_DESC(dv_toggle_prov_name, "\n dv_toggle_prov_name\n"); module_param(dv_debug, uint, 0664); MODULE_PARM_DESC(dv_debug, "\n dv_debug\n"); + +module_param(force_bypass_dvenl, uint, 0664); +MODULE_PARM_DESC(force_bypass_dvenl, "\n force_bypass_dvenl\n"); #endif #ifdef AGAIN_HAS_THRESHOLD @@ -10882,6 +12713,9 @@ module_param(force_disp_pic_index, int, 0664); MODULE_PARM_DESC(force_disp_pic_index, "\n amvdec_h265 force_disp_pic_index\n"); +module_param(frmbase_cont_bitlevel, uint, 0664); +MODULE_PARM_DESC(frmbase_cont_bitlevel, "\n frmbase_cont_bitlevel\n"); + module_param(udebug_flag, uint, 0664); MODULE_PARM_DESC(udebug_flag, "\n amvdec_h265 udebug_flag\n"); @@ -10891,6 +12725,9 @@ MODULE_PARM_DESC(udebug_pause_pos, "\n udebug_pause_pos\n"); module_param(udebug_pause_val, uint, 0664); MODULE_PARM_DESC(udebug_pause_val, "\n udebug_pause_val\n"); +module_param(pre_decode_buf_level, int, 0664); +MODULE_PARM_DESC(pre_decode_buf_level, "\n ammvdec_h264 pre_decode_buf_level\n"); + module_param(udebug_pause_decode_idx, uint, 0664); MODULE_PARM_DESC(udebug_pause_decode_idx, "\n udebug_pause_decode_idx\n"); diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/mjpeg/vmjpeg.c b/drivers/amlogic/media_modules/frame_provider/decoder/mjpeg/vmjpeg.c index b5af67a2ffe4..1c69a5a41fd9 100644 --- a/drivers/amlogic/media_modules/frame_provider/decoder/mjpeg/vmjpeg.c +++ b/drivers/amlogic/media_modules/frame_provider/decoder/mjpeg/vmjpeg.c @@ -36,6 +36,10 @@ #include "../utils/decoder_bmmu_box.h" #include #include +#include + +#include + #ifdef CONFIG_AM_VDEC_MJPEG_LOG #define AMLOG @@ -166,6 +170,7 @@ static irqreturn_t vmjpeg_isr(int irq, void *dev_id) u32 reg, offset, pts, pts_valid = 0; struct vframe_s *vf = NULL; u64 pts_us64; + u32 frame_size; WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1); @@ -175,7 +180,8 @@ static irqreturn_t vmjpeg_isr(int irq, void *dev_id) offset = READ_VREG(MREG_FRAME_OFFSET); if (pts_lookup_offset_us64 - (PTS_TYPE_VIDEO, offset, &pts, 0, &pts_us64) == 0) + (PTS_TYPE_VIDEO, offset, &pts, + &frame_size, 0, &pts_us64) == 0) pts_valid = 1; if ((reg & PICINFO_INTERLACE) == 0) { @@ -218,6 +224,7 @@ static irqreturn_t vmjpeg_isr(int irq, void *dev_id) vdec_count_info(gvs, 0, offset); kfifo_put(&display_q, (const struct vframe_s *)vf); + ATRACE_COUNTER(MODULE_NAME, vf->pts); vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_VFRAME_READY, @@ -275,6 +282,7 @@ static irqreturn_t vmjpeg_isr(int irq, void *dev_id) vfbuf_use[index]++; kfifo_put(&display_q, (const struct vframe_s *)vf); + ATRACE_COUNTER(MODULE_NAME, vf->pts); #else /* send whole frame by weaving top & bottom field */ #ifdef NV21 @@ -303,6 +311,7 @@ static irqreturn_t vmjpeg_isr(int irq, void *dev_id) vdec_count_info(gvs, 0, offset); kfifo_put(&display_q, (const struct vframe_s *)vf); + ATRACE_COUNTER(MODULE_NAME, vf->pts); vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_VFRAME_READY, @@ -398,8 +407,7 @@ static void vmjpeg_put_timer_func(unsigned long arg) struct vframe_s *vf; if (kfifo_get(&recycle_q, &vf)) { - if ((vf->index >= 0) - && (vf->index < DECODE_BUFFER_NUM_MAX) + if ((vf->index < DECODE_BUFFER_NUM_MAX) && (--vfbuf_use[vf->index] == 0)) { WRITE_VREG(MREG_TO_AMRISC, vf->index + 1); vf->index = DECODE_BUFFER_NUM_MAX; @@ -418,6 +426,9 @@ static void vmjpeg_put_timer_func(unsigned long arg) int vmjpeg_dec_status(struct vdec_s *vdec, struct vdec_info *vstatus) { + if (!(stat & STAT_VDEC_RUN)) + return -1; + vstatus->frame_width = frame_width; vstatus->frame_height = frame_height; if (0 != frame_dur) @@ -746,11 +757,12 @@ static s32 vmjpeg_init(void) return -1; } - if (size == 1) - pr_info ("tee load ok"); - else if (amvdec_loadmc_ex(VFORMAT_MJPEG, NULL, buf) < 0) { + ret = amvdec_loadmc_ex(VFORMAT_MJPEG, NULL, buf); + if (ret < 0) { amvdec_disable(); vfree(buf); + pr_err("MJPEG: the %s fw loading failed, err: %x\n", + tee_enabled() ? "TEE" : "local", ret); return -EBUSY; } @@ -840,6 +852,7 @@ static int amvdec_mjpeg_probe(struct platform_device *pdev) mutex_unlock(&vmjpeg_mutex); kfree(gvs); gvs = NULL; + pdata->dec_status = NULL; return -ENODEV; } diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/mjpeg/vmjpeg_multi.c b/drivers/amlogic/media_modules/frame_provider/decoder/mjpeg/vmjpeg_multi.c index a0b449324efe..38c08e1e113a 100644 --- a/drivers/amlogic/media_modules/frame_provider/decoder/mjpeg/vmjpeg_multi.c +++ b/drivers/amlogic/media_modules/frame_provider/decoder/mjpeg/vmjpeg_multi.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -43,6 +44,9 @@ #include #include "../utils/firmware.h" +#include + + #define MEM_NAME "codec_mmjpeg" #define DRIVER_NAME "ammvdec_mjpeg" @@ -59,7 +63,10 @@ #define MREG_TO_AMRISC AV_SCRATCH_8 #define MREG_FROM_AMRISC AV_SCRATCH_9 #define MREG_FRAME_OFFSET AV_SCRATCH_A -#define DEC_STATUS_REG AV_SCRATCH_J +#define DEC_STATUS_REG AV_SCRATCH_F +#define MREG_PIC_WIDTH AV_SCRATCH_B +#define MREG_PIC_HEIGHT AV_SCRATCH_C +#define DECODE_STOP_POS AV_SCRATCH_K #define PICINFO_BUF_IDX_MASK 0x0007 #define PICINFO_AVI1 0x0080 @@ -73,8 +80,15 @@ #define DEFAULT_MEM_SIZE (32*SZ_1M) static int debug_enable; +static u32 udebug_flag; #define DECODE_ID(hw) (hw_to_vdec(hw)->id) +static unsigned int radr; +static unsigned int rval; +#define VMJPEG_DEV_NUM 9 +static unsigned int max_decode_instance_num = VMJPEG_DEV_NUM; +static unsigned int max_process_time[VMJPEG_DEV_NUM]; +static unsigned int decode_timeout_val = 200; static struct vframe_s *vmjpeg_vf_peek(void *); static struct vframe_s *vmjpeg_vf_get(void *); static void vmjpeg_vf_put(struct vframe_s *, void *); @@ -82,6 +96,36 @@ static int vmjpeg_vf_states(struct vframe_states *states, void *); static int vmjpeg_event_cb(int type, void *data, void *private_data); static void vmjpeg_work(struct work_struct *work); static int pre_decode_buf_level = 0x800; +#undef pr_info +#define pr_info printk +unsigned int mmjpeg_debug_mask = 0xff; +#define PRINT_FLAG_ERROR 0x0 +#define PRINT_FLAG_RUN_FLOW 0X0001 +#define PRINT_FLAG_TIMEINFO 0x0002 +#define PRINT_FLAG_UCODE_DETAIL 0x0004 +#define PRINT_FLAG_VLD_DETAIL 0x0008 +#define PRINT_FLAG_DEC_DETAIL 0x0010 +#define PRINT_FLAG_BUFFER_DETAIL 0x0020 +#define PRINT_FLAG_RESTORE 0x0040 +#define PRINT_FRAME_NUM 0x0080 +#define PRINT_FLAG_FORCE_DONE 0x0100 +#define PRINT_FRAMEBASE_DATA 0x0400 +int mmjpeg_debug_print(int index, int debug_flag, const char *fmt, ...) +{ + if (((debug_enable & debug_flag) && + ((1 << index) & mmjpeg_debug_mask)) + || (debug_flag == PRINT_FLAG_ERROR)) { + unsigned char buf[512]; + int len = 0; + va_list args; + va_start(args, fmt); + len = sprintf(buf, "%d: ", index); + vsnprintf(buf + len, 512-len, fmt, args); + pr_info("%s", buf); + va_end(args); + } + return 0; +} static const char vmjpeg_dec_id[] = "vmmjpeg-dev"; @@ -152,15 +196,33 @@ struct vdec_mjpeg_hw_s { void *vdec_cb_arg; struct firmware_s *fw; struct timer_list check_timer; - unsigned decode_timeout_count; + u32 decode_timeout_count; + u32 start_process_time; + u32 last_vld_level; u8 eos; - u32 frame_num, put_num; + u32 frame_num; + u32 put_num; + u32 run_count; + u32 not_run_ready; + u32 input_empty; + u32 peek_num; + u32 get_num; }; +static void reset_process_time(struct vdec_mjpeg_hw_s *hw); static void set_frame_info(struct vdec_mjpeg_hw_s *hw, struct vframe_s *vf) { - vf->width = hw->frame_width; - vf->height = hw->frame_height; + u32 temp; + temp = READ_VREG(MREG_PIC_WIDTH); + if (temp > 1920) + vf->width = hw->frame_width = 1920; + else if (temp > 0) + vf->width = hw->frame_width = temp; + temp = READ_VREG(MREG_PIC_HEIGHT); + if (temp > 1088) + vf->height = hw->frame_height = 1088; + else if (temp > 0) + vf->height = hw->frame_height = temp; vf->duration = hw->frame_dur; vf->ratio_control = 0; vf->duration_pulldown = 0; @@ -185,16 +247,23 @@ static irqreturn_t vmjpeg_isr(struct vdec_s *vdec, int irq) struct vframe_s *vf = NULL; u32 index, offset = 0, pts; u64 pts_us64; - - if (debug_enable & 0x1) - pr_info("%s: %d\n", __func__, __LINE__); - - WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1); + u32 frame_size; if (!hw) return IRQ_HANDLED; + if (hw->eos) return IRQ_HANDLED; + reset_process_time(hw); + WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1); + if (READ_VREG(AV_SCRATCH_D) != 0 && + (debug_enable & PRINT_FLAG_UCODE_DETAIL)) { + pr_info("dbg%x: %x\n", READ_VREG(AV_SCRATCH_D), + READ_VREG(AV_SCRATCH_E)); + WRITE_VREG(AV_SCRATCH_D, 0); + return IRQ_HANDLED; + } + reg = READ_VREG(MREG_FROM_AMRISC); index = READ_VREG(AV_SCRATCH_5); @@ -222,7 +291,8 @@ static irqreturn_t vmjpeg_isr(struct vdec_s *vdec, int irq) } else { offset = READ_VREG(MREG_FRAME_OFFSET); if (pts_lookup_offset_us64 - (PTS_TYPE_VIDEO, offset, &pts, 3000, + (PTS_TYPE_VIDEO, offset, &pts, + &frame_size, 3000, &pts_us64) == 0) { vf->pts = pts; vf->pts_us64 = pts_us64; @@ -235,15 +305,20 @@ static irqreturn_t vmjpeg_isr(struct vdec_s *vdec, int irq) hw->vfbuf_use[index]++; kfifo_put(&hw->display_q, (const struct vframe_s *)vf); - + ATRACE_COUNTER(MODULE_NAME, vf->pts); hw->frame_num++; + mmjpeg_debug_print(DECODE_ID(hw), PRINT_FRAME_NUM, + "%s:frame num:%d,pts=%d,pts64=%lld. dur=%d\n", + __func__, hw->frame_num, + vf->pts, vf->pts_us64, vf->duration); + vdec->vdec_fps_detec(vdec->id); vf_notify_receiver(vdec->vf_provider_name, VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); hw->dec_result = DEC_RESULT_DONE; - schedule_work(&hw->work); + vdec_schedule_work(&hw->work); return IRQ_HANDLED; } @@ -256,7 +331,7 @@ static struct vframe_s *vmjpeg_vf_peek(void *op_arg) if (!hw) return NULL; - + hw->peek_num++; if (kfifo_peek(&hw->display_q, &vf)) return vf; @@ -271,7 +346,7 @@ static struct vframe_s *vmjpeg_vf_get(void *op_arg) if (!hw) return NULL; - + hw->get_num++; if (kfifo_get(&hw->display_q, &vf)) return vf; @@ -282,7 +357,8 @@ static void vmjpeg_vf_put(struct vframe_s *vf, void *op_arg) { struct vdec_s *vdec = op_arg; struct vdec_mjpeg_hw_s *hw = (struct vdec_mjpeg_hw_s *)vdec->private; - + mmjpeg_debug_print(DECODE_ID(hw), PRINT_FRAME_NUM, + "%s:put_num:%d\n", __func__, hw->put_num); hw->vfbuf_use[vf->index]--; kfifo_put(&hw->newframe_q, (const struct vframe_s *)vf); hw->put_num++; @@ -314,6 +390,10 @@ static int vmjpeg_vf_states(struct vframe_states *states, void *op_arg) static int vmjpeg_dec_status(struct vdec_s *vdec, struct vdec_info *vstatus) { struct vdec_mjpeg_hw_s *hw = (struct vdec_mjpeg_hw_s *)vdec->private; + + if (!hw) + return -1; + vstatus->frame_width = hw->frame_width; vstatus->frame_height = hw->frame_height; if (0 != hw->frame_dur) @@ -345,7 +425,7 @@ static void vmjpeg_canvas_init(struct vdec_s *vdec) for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) { int canvas; - canvas = vdec->get_canvas(i, 3); + ret = decoder_bmmu_box_alloc_buf_phy(hw->mm_blk_handle, i, decbuf_size, DRIVER_NAME, &buf_start); @@ -364,9 +444,19 @@ static void vmjpeg_canvas_init(struct vdec_s *vdec) addr += decbuf_uv_size; hw->buffer_spec[i].v_addr = addr; - hw->buffer_spec[i].y_canvas_index = canvas_y(canvas); - hw->buffer_spec[i].u_canvas_index = canvas_u(canvas); - hw->buffer_spec[i].v_canvas_index = canvas_v(canvas); + if (vdec->parallel_dec == 1) { + if (hw->buffer_spec[i].y_canvas_index == -1) + hw->buffer_spec[i].y_canvas_index = vdec->get_canvas_ex(CORE_MASK_VDEC_1, vdec->id); + if (hw->buffer_spec[i].u_canvas_index == -1) + hw->buffer_spec[i].u_canvas_index = vdec->get_canvas_ex(CORE_MASK_VDEC_1, vdec->id); + if (hw->buffer_spec[i].v_canvas_index == -1) + hw->buffer_spec[i].v_canvas_index = vdec->get_canvas_ex(CORE_MASK_VDEC_1, vdec->id); + } else { + canvas = vdec->get_canvas(i, 3); + hw->buffer_spec[i].y_canvas_index = canvas_y(canvas); + hw->buffer_spec[i].u_canvas_index = canvas_u(canvas); + hw->buffer_spec[i].v_canvas_index = canvas_v(canvas); + } canvas_config(hw->buffer_spec[i].y_canvas_index, hw->buffer_spec[i].y_addr, @@ -499,12 +589,129 @@ static void init_scaler(void) WRITE_VREG(PSCALE_RST, 0x0); } +static void vmjpeg_dump_state(struct vdec_s *vdec) +{ + struct vdec_mjpeg_hw_s *hw = + (struct vdec_mjpeg_hw_s *)(vdec->private); + mmjpeg_debug_print(DECODE_ID(hw), 0, + "====== %s\n", __func__); + mmjpeg_debug_print(DECODE_ID(hw), 0, + "width/height (%d/%d)\n", + hw->frame_width, + hw->frame_height + ); + mmjpeg_debug_print(DECODE_ID(hw), 0, + "is_framebase(%d), eos %d, state 0x%x, dec_result 0x%x dec_frm %d put_frm %d run %d not_run_ready %d input_empty %d\n", + input_frame_based(vdec), + hw->eos, + hw->stat, + hw->dec_result, + hw->frame_num, + hw->put_num, + hw->run_count, + hw->not_run_ready, + hw->input_empty + ); + if (vf_get_receiver(vdec->vf_provider_name)) { + enum receviver_start_e state = + vf_notify_receiver(vdec->vf_provider_name, + VFRAME_EVENT_PROVIDER_QUREY_STATE, + NULL); + mmjpeg_debug_print(DECODE_ID(hw), 0, + "\nreceiver(%s) state %d\n", + vdec->vf_provider_name, + state); + } + mmjpeg_debug_print(DECODE_ID(hw), 0, + "%s, newq(%d/%d), dispq(%d/%d) vf peek/get/put (%d/%d/%d)\n", + __func__, + kfifo_len(&hw->newframe_q), + VF_POOL_SIZE, + kfifo_len(&hw->display_q), + VF_POOL_SIZE, + hw->peek_num, + hw->get_num, + hw->put_num + ); + mmjpeg_debug_print(DECODE_ID(hw), 0, + "VIFF_BIT_CNT=0x%x\n", + READ_VREG(VIFF_BIT_CNT)); + mmjpeg_debug_print(DECODE_ID(hw), 0, + "VLD_MEM_VIFIFO_LEVEL=0x%x\n", + READ_VREG(VLD_MEM_VIFIFO_LEVEL)); + mmjpeg_debug_print(DECODE_ID(hw), 0, + "VLD_MEM_VIFIFO_WP=0x%x\n", + READ_VREG(VLD_MEM_VIFIFO_WP)); + mmjpeg_debug_print(DECODE_ID(hw), 0, + "VLD_MEM_VIFIFO_RP=0x%x\n", + READ_VREG(VLD_MEM_VIFIFO_RP)); + mmjpeg_debug_print(DECODE_ID(hw), 0, + "PARSER_VIDEO_RP=0x%x\n", + READ_PARSER_REG(PARSER_VIDEO_RP)); + mmjpeg_debug_print(DECODE_ID(hw), 0, + "PARSER_VIDEO_WP=0x%x\n", + READ_PARSER_REG(PARSER_VIDEO_WP)); + if (input_frame_based(vdec) && + debug_enable & PRINT_FRAMEBASE_DATA + ) { + int jj; + if (hw->chunk && hw->chunk->block && + hw->chunk->size > 0) { + u8 *data = NULL; + + if (!hw->chunk->block->is_mapped) + data = codec_mm_vmap(hw->chunk->block->start + + hw->chunk->offset, hw->chunk->size); + else + data = ((u8 *)hw->chunk->block->start_virt) + + hw->chunk->offset; + + mmjpeg_debug_print(DECODE_ID(hw), 0, + "frame data size 0x%x\n", + hw->chunk->size); + for (jj = 0; jj < hw->chunk->size; jj++) { + if ((jj & 0xf) == 0) + mmjpeg_debug_print(DECODE_ID(hw), + PRINT_FRAMEBASE_DATA, + "%06x:", jj); + mmjpeg_debug_print(DECODE_ID(hw), + PRINT_FRAMEBASE_DATA, + "%02x ", data[jj]); + if (((jj + 1) & 0xf) == 0) + mmjpeg_debug_print(DECODE_ID(hw), + PRINT_FRAMEBASE_DATA, + "\n"); + } + + if (!hw->chunk->block->is_mapped) + codec_mm_unmap_phyaddr(data); + } + } +} +static void reset_process_time(struct vdec_mjpeg_hw_s *hw) +{ + if (hw->start_process_time) { + unsigned process_time = + 1000 * (jiffies - hw->start_process_time) / HZ; + hw->start_process_time = 0; + if (process_time > max_process_time[DECODE_ID(hw)]) + max_process_time[DECODE_ID(hw)] = process_time; + } +} + +static void start_process_time(struct vdec_mjpeg_hw_s *hw) +{ + hw->decode_timeout_count = 2; + hw->start_process_time = jiffies; +} + static void timeout_process(struct vdec_mjpeg_hw_s *hw) { amvdec_stop(); - pr_info("%s decoder timeout\n", __func__); + mmjpeg_debug_print(DECODE_ID(hw), PRINT_FLAG_ERROR, + "%s decoder timeout\n", __func__); hw->dec_result = DEC_RESULT_DONE; - + reset_process_time(hw); vdec_schedule_work(&hw->work); } @@ -512,31 +719,43 @@ static void check_timer_func(unsigned long arg) { struct vdec_mjpeg_hw_s *hw = (struct vdec_mjpeg_hw_s *)arg; struct vdec_s *vdec = hw_to_vdec(hw); - if ((debug_enable & 0x2) != 0) { - pr_info("%s: status:nstatus=%d:%d\n", + int timeout_val = decode_timeout_val; + + mmjpeg_debug_print(DECODE_ID(hw), PRINT_FLAG_VLD_DETAIL, + "%s: status:nstatus=%d:%d\n", __func__, vdec->status, vdec->next_status); - pr_info("%s: %d,buftl=%x:%x:%x:%x\n", + mmjpeg_debug_print(DECODE_ID(hw), PRINT_FLAG_VLD_DETAIL, + "%s: %d,buftl=%x:%x:%x:%x\n", __func__, __LINE__, READ_VREG(VLD_MEM_VIFIFO_BUF_CNTL), READ_PARSER_REG(PARSER_VIDEO_WP), READ_VREG(VLD_MEM_VIFIFO_LEVEL), READ_VREG(VLD_MEM_VIFIFO_WP)); - } - if ((debug_enable & 0x100) != 0) { - hw->dec_result = DEC_RESULT_DONE; - vdec_schedule_work(&hw->work); - pr_info("vdec %d is forced to be disconnected\n", - debug_enable & 0xff); - debug_enable = 0; - return; + + if (radr != 0) { + if (rval != 0) { + WRITE_VREG(radr, rval); + pr_info("WRITE_VREG(%x,%x)\n", radr, rval); + } else + pr_info("READ_VREG(%x)=%x\n", radr, READ_VREG(radr)); + rval = 0; + radr = 0; } - if (input_stream_based(vdec) - && READ_VREG(VLD_MEM_VIFIFO_LEVEL) <= 0x80) { - if (hw->decode_timeout_count > 0) - hw->decode_timeout_count--; - if (hw->decode_timeout_count == 0) - timeout_process(hw); + if ((debug_enable == 0) && + (input_frame_based(vdec) || + (READ_VREG(VLD_MEM_VIFIFO_LEVEL) > 0x100)) && + (timeout_val > 0) && + (hw->start_process_time > 0) && + ((1000 * (jiffies - hw->start_process_time) / HZ) + > timeout_val)) { + if (hw->last_vld_level == READ_VREG(VLD_MEM_VIFIFO_LEVEL)) { + if (hw->decode_timeout_count > 0) + hw->decode_timeout_count--; + if (hw->decode_timeout_count == 0) + timeout_process(hw); + } + hw->last_vld_level = READ_VREG(VLD_MEM_VIFIFO_LEVEL); } if (READ_VREG(DEC_STATUS_REG) == DEC_DECODE_TIMEOUT) { @@ -556,6 +775,7 @@ static void check_timer_func(unsigned long arg) } mod_timer(&hw->check_timer, jiffies + CHECK_INTERVAL); } + static void vmjpeg_hw_ctx_restore(struct vdec_s *vdec, int index) { struct vdec_mjpeg_hw_s *hw = @@ -601,10 +821,7 @@ static s32 vmjpeg_init(struct vdec_s *vdec) fw = vmalloc(sizeof(struct firmware_s) + fw_size); if (IS_ERR_OR_NULL(fw)) return -ENOMEM; - if (tee_enabled()) { - size = 1; - pr_debug (" tee load\n"); - } else + size = get_firmware_data(VIDEO_DEC_MJPEG_MULTI, fw->data); if (size < 0) { pr_err("get firmware fail."); @@ -617,12 +834,18 @@ static s32 vmjpeg_init(struct vdec_s *vdec) hw->frame_width = hw->vmjpeg_amstream_dec_info.width; hw->frame_height = hw->vmjpeg_amstream_dec_info.height; - hw->frame_dur = hw->vmjpeg_amstream_dec_info.rate; + hw->frame_dur = ((hw->vmjpeg_amstream_dec_info.rate) ? + hw->vmjpeg_amstream_dec_info.rate : 3840); hw->saved_resolution = 0; hw->eos = 0; hw->init_flag = 0; hw->frame_num = 0; hw->put_num = 0; + hw->run_count = 0; + hw->not_run_ready = 0; + hw->input_empty = 0; + hw->peek_num = 0; + hw->get_num = 0; for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) hw->vfbuf_use[i] = 0; @@ -656,16 +879,20 @@ static s32 vmjpeg_init(struct vdec_s *vdec) hw->check_timer.expires = jiffies + CHECK_INTERVAL; /*add_timer(&hw->check_timer);*/ hw->stat |= STAT_TIMER_ARM; + hw->stat |= STAT_ISR_REG; + WRITE_VREG(DECODE_STOP_POS, udebug_flag); INIT_WORK(&hw->work, vmjpeg_work); - + pr_info("w:h=%d:%d\n", hw->frame_width, hw->frame_height); return 0; } -static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask) +static unsigned long run_ready(struct vdec_s *vdec, + unsigned long mask) { struct vdec_mjpeg_hw_s *hw = (struct vdec_mjpeg_hw_s *)vdec->private; + hw->not_run_ready++; if (hw->eos) return 0; if (vdec_stream_based(vdec) && (hw->init_flag == 0) @@ -682,7 +909,11 @@ static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask) if (level < pre_decode_buf_level) return 0; } - return CORE_MASK_VDEC_1 | CORE_MASK_HEVC; + hw->not_run_ready = 0; + if (vdec->parallel_dec == 1) + return CORE_MASK_VDEC_1; + else + return CORE_MASK_VDEC_1 | CORE_MASK_HEVC; } static void run(struct vdec_s *vdec, unsigned long mask, @@ -690,11 +921,13 @@ static void run(struct vdec_s *vdec, unsigned long mask, { struct vdec_mjpeg_hw_s *hw = (struct vdec_mjpeg_hw_s *)vdec->private; - int i,ret = -1; + int i, ret; hw->vdec_cb_arg = arg; hw->vdec_cb = callback; + hw->run_count++; + vdec_reset_core(vdec); for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) { if (hw->vfbuf_use[i] == 0) break; @@ -702,29 +935,42 @@ static void run(struct vdec_s *vdec, unsigned long mask, if (i == DECODE_BUFFER_NUM_MAX) { hw->dec_result = DEC_RESULT_AGAIN; - schedule_work(&hw->work); + vdec_schedule_work(&hw->work); return; } ret = vdec_prepare_input(vdec, &hw->chunk); - if (ret < 0) { - if (debug_enable & 0x1) { - pr_info("%s: %d,r=%d,buftl=%x:%x:%x\n", + if (ret <= 0) { + hw->input_empty++; + mmjpeg_debug_print(DECODE_ID(hw), PRINT_FLAG_RUN_FLOW, + "%s: %d,r=%d,buftl=%x:%x:%x\n", __func__, __LINE__, ret, READ_VREG(VLD_MEM_VIFIFO_BUF_CNTL), READ_PARSER_REG(PARSER_VIDEO_WP), READ_VREG(VLD_MEM_VIFIFO_WP)); - } + hw->dec_result = DEC_RESULT_AGAIN; - schedule_work(&hw->work); + vdec_schedule_work(&hw->work); return; } - + hw->input_empty = 0; hw->dec_result = DEC_RESULT_NONE; - - if (amvdec_vdec_loadmc_ex(vdec, "vmmjpeg_mc",hw->fw->data) < 0) { - pr_err("%s: Error amvdec_loadmc fail\n", __func__); - return; + if (vdec->mc_loaded) { + /*firmware have load before, + and not changes to another. + ignore reload. + */ + } else { + ret = amvdec_vdec_loadmc_ex(VFORMAT_MJPEG, "mmjpeg", vdec, hw->fw->data); + if (ret < 0) { + pr_err("[%d] MMJPEG: the %s fw loading failed, err: %x\n", + vdec->id, tee_enabled() ? "TEE" : "local", ret); + hw->dec_result = DEC_RESULT_FORCE_EXIT; + vdec_schedule_work(&hw->work); + return; + } + vdec->mc_loaded = 1; + vdec->mc_type = VFORMAT_MJPEG; } /* if (amvdec_vdec_loadmc_buf_ex(vdec, hw->fw->data, hw->fw->len) < 0) { pr_err("%s: Error amvdec_loadmc fail\n", __func__); @@ -736,42 +982,65 @@ static void run(struct vdec_s *vdec, unsigned long mask, vdec_enable_input(vdec); mod_timer(&hw->check_timer, jiffies + CHECK_INTERVAL); #endif + hw->stat |= STAT_MC_LOAD; + start_process_time(hw); + hw->last_vld_level = 0; + mod_timer(&hw->check_timer, jiffies + CHECK_INTERVAL); amvdec_start(); vdec_enable_input(vdec); - mod_timer(&hw->check_timer, jiffies + CHECK_INTERVAL); - hw->decode_timeout_count = 2; + hw->stat |= STAT_VDEC_RUN; hw->init_flag = 1; - if (debug_enable&0x1) { - pr_info("%s (0x%x 0x%x 0x%x) vldcrl 0x%x bitcnt 0x%x powerctl 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", - __func__, - READ_VREG(VLD_MEM_VIFIFO_LEVEL), - READ_VREG(VLD_MEM_VIFIFO_WP), - READ_VREG(VLD_MEM_VIFIFO_RP), - READ_VREG(VLD_DECODE_CONTROL), - READ_VREG(VIFF_BIT_CNT), - READ_VREG(POWER_CTL_VLD), - READ_VREG(VLD_MEM_VIFIFO_START_PTR), - READ_VREG(VLD_MEM_VIFIFO_CURR_PTR), - READ_VREG(VLD_MEM_VIFIFO_CONTROL), - READ_VREG(VLD_MEM_VIFIFO_BUF_CNTL), - READ_VREG(VLD_MEM_VIFIFO_END_PTR)); + mmjpeg_debug_print(DECODE_ID(hw), PRINT_FLAG_RUN_FLOW, + "%s (0x%x 0x%x 0x%x) vldcrl 0x%x bitcnt 0x%x powerctl 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", + __func__, + READ_VREG(VLD_MEM_VIFIFO_LEVEL), + READ_VREG(VLD_MEM_VIFIFO_WP), + READ_VREG(VLD_MEM_VIFIFO_RP), + READ_VREG(VLD_DECODE_CONTROL), + READ_VREG(VIFF_BIT_CNT), + READ_VREG(POWER_CTL_VLD), + READ_VREG(VLD_MEM_VIFIFO_START_PTR), + READ_VREG(VLD_MEM_VIFIFO_CURR_PTR), + READ_VREG(VLD_MEM_VIFIFO_CONTROL), + READ_VREG(VLD_MEM_VIFIFO_BUF_CNTL), + READ_VREG(VLD_MEM_VIFIFO_END_PTR)); +} +static void wait_vmjpeg_search_done(struct vdec_mjpeg_hw_s *hw) +{ + u32 vld_rp = READ_VREG(VLD_MEM_VIFIFO_RP); + int count = 0; - } + do { + usleep_range(100, 500); + if (vld_rp == READ_VREG(VLD_MEM_VIFIFO_RP)) + break; + if (count > 1000) { + mmjpeg_debug_print(DECODE_ID(hw), 0, + "%s, count %d vld_rp 0x%x VLD_MEM_VIFIFO_RP 0x%x\n", + __func__, count, vld_rp, READ_VREG(VLD_MEM_VIFIFO_RP)); + break; + } else + vld_rp = READ_VREG(VLD_MEM_VIFIFO_RP); + count++; + } while (1); } static void vmjpeg_work(struct work_struct *work) { struct vdec_mjpeg_hw_s *hw = container_of(work, struct vdec_mjpeg_hw_s, work); - if (debug_enable & 0x2) - pr_info("%s: result=%d,len=%d:%d\n", + struct vdec_s *vdec = hw_to_vdec(hw); + + mmjpeg_debug_print(DECODE_ID(hw), PRINT_FLAG_BUFFER_DETAIL, + "%s: result=%d,len=%d:%d\n", __func__, hw->dec_result, kfifo_len(&hw->newframe_q), kfifo_len(&hw->display_q)); - if (hw->dec_result == DEC_RESULT_DONE) + if (hw->dec_result == DEC_RESULT_DONE) { vdec_vframe_dirty(hw_to_vdec(hw), hw->chunk); - else if (hw->dec_result == DEC_RESULT_AGAIN) { + hw->chunk = NULL; + } else if (hw->dec_result == DEC_RESULT_AGAIN) { /* stream base: stream buf empty or timeout frame base: vdec_prepare_input fail @@ -784,20 +1053,37 @@ static void vmjpeg_work(struct work_struct *work) return; } } else if (hw->dec_result == DEC_RESULT_FORCE_EXIT) { - pr_info("%s: force exit\n", - __func__); + pr_info("%s: force exit\n", __func__); + if (hw->stat & STAT_ISR_REG) { + amvdec_stop(); + /*disable mbox interrupt */ + WRITE_VREG(ASSIST_MBOX1_MASK, 0); + vdec_free_irq(VDEC_IRQ_1, (void *)hw); + hw->stat &= ~STAT_ISR_REG; + } } else if (hw->dec_result == DEC_RESULT_EOS) { - /*pr_info("%s: end of stream\n", - __func__);*/ - if (READ_VREG(VLD_MEM_VIFIFO_LEVEL) < 0x100) - hw->eos = 1; + pr_info("%s: end of stream\n", __func__); + if (hw->stat & STAT_VDEC_RUN) { + amvdec_stop(); + hw->stat &= ~STAT_VDEC_RUN; + } + hw->eos = 1; vdec_vframe_dirty(hw_to_vdec(hw), hw->chunk); + hw->chunk = NULL; + vdec_clean_input(hw_to_vdec(hw)); } - amvdec_stop(); + if (hw->stat & STAT_VDEC_RUN) { + amvdec_stop(); + hw->stat &= ~STAT_VDEC_RUN; + } + wait_vmjpeg_search_done(hw); /* mark itself has all HW resource released and input released */ - vdec_set_status(hw_to_vdec(hw), VDEC_STATUS_CONNECTED); - vdec_core_finish_run(hw_to_vdec(hw), CORE_MASK_VDEC_1 + if (vdec->parallel_dec == 1) + vdec_core_finish_run(hw_to_vdec(hw), CORE_MASK_VDEC_1); + else { + vdec_core_finish_run(hw_to_vdec(hw), CORE_MASK_VDEC_1 | CORE_MASK_HEVC); + } del_timer_sync(&hw->check_timer); hw->stat &= ~STAT_TIMER_ARM; @@ -805,18 +1091,54 @@ static void vmjpeg_work(struct work_struct *work) hw->vdec_cb(hw_to_vdec(hw), hw->vdec_cb_arg); } -static int amvdec_mjpeg_probe(struct platform_device *pdev) +static int vmjpeg_stop(struct vdec_mjpeg_hw_s *hw) +{ + pr_info("%s ...count = %d\n", __func__, hw->frame_num); + + if (hw->stat & STAT_VDEC_RUN) { + amvdec_stop(); + pr_info("%s amvdec_stop\n", __func__); + hw->stat &= ~STAT_VDEC_RUN; + } + + if (hw->stat & STAT_ISR_REG) { + vdec_free_irq(VDEC_IRQ_1, (void *)hw); + hw->stat &= ~STAT_ISR_REG; + } + + if (hw->stat & STAT_TIMER_ARM) { + del_timer_sync(&hw->check_timer); + hw->stat &= ~STAT_TIMER_ARM; + } + cancel_work_sync(&hw->work); + hw->init_flag = 0; + + if (hw->mm_blk_handle) { + decoder_bmmu_box_free(hw->mm_blk_handle); + hw->mm_blk_handle = NULL; + } + + if (hw->fw) { + vfree(hw->fw); + hw->fw = NULL; + } + + return 0; +} + +static int ammvdec_mjpeg_probe(struct platform_device *pdev) { struct vdec_s *pdata = *(struct vdec_s **)pdev->dev.platform_data; struct vdec_mjpeg_hw_s *hw = NULL; if (pdata == NULL) { - pr_info("amvdec_mjpeg memory resource undefined.\n"); + pr_info("ammvdec_mjpeg memory resource undefined.\n"); return -EFAULT; } hw = (struct vdec_mjpeg_hw_s *)devm_kzalloc(&pdev->dev, sizeof(struct vdec_mjpeg_hw_s), GFP_KERNEL); + hw = vzalloc(sizeof(struct vdec_mjpeg_hw_s)); if (hw == NULL) { pr_info("\nammvdec_mjpeg device data allocation failed\n"); return -ENOMEM; @@ -828,7 +1150,16 @@ static int amvdec_mjpeg_probe(struct platform_device *pdev) pdata->run = run; pdata->run_ready = run_ready; pdata->irq_handler = vmjpeg_isr; + pdata->dump_state = vmjpeg_dump_state; + if (pdata->parallel_dec == 1) { + int i; + for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) { + hw->buffer_spec[i].y_canvas_index = -1; + hw->buffer_spec[i].u_canvas_index = -1; + hw->buffer_spec[i].v_canvas_index = -1; + } + } if (pdata->use_vfm_path) snprintf(pdata->vf_provider_name, VDEC_PROVIDER_NAME_SIZE, @@ -847,48 +1178,62 @@ static int amvdec_mjpeg_probe(struct platform_device *pdev) if (pdata->sys_info) hw->vmjpeg_amstream_dec_info = *pdata->sys_info; + vdec_source_changed(VFORMAT_MJPEG, + 1920, 1080, 60); if (vmjpeg_init(pdata) < 0) { - pr_info("amvdec_mjpeg init failed.\n"); + pr_info("ammvdec_mjpeg init failed.\n"); + if (hw) { + vfree(hw); + hw = NULL; + } + pdata->dec_status = NULL; return -ENODEV; } - - vdec_core_request(pdata, CORE_MASK_VDEC_1 | CORE_MASK_HEVC + if (pdata->parallel_dec == 1) + vdec_core_request(pdata, CORE_MASK_VDEC_1); + else { + vdec_core_request(pdata, CORE_MASK_VDEC_1 | CORE_MASK_HEVC | CORE_MASK_COMBINE); + } return 0; } -static int amvdec_mjpeg_remove(struct platform_device *pdev) +static int ammvdec_mjpeg_remove(struct platform_device *pdev) { struct vdec_mjpeg_hw_s *hw = (struct vdec_mjpeg_hw_s *) (((struct vdec_s *)(platform_get_drvdata(pdev)))->private); + struct vdec_s *vdec = hw_to_vdec(hw); + int i; + vmjpeg_stop(hw); - if (hw->stat & STAT_TIMER_ARM) { - del_timer_sync(&hw->check_timer); - hw->stat &= ~STAT_TIMER_ARM; - } - cancel_work_sync(&hw->work); - if (hw->mm_blk_handle) { - decoder_bmmu_box_free(hw->mm_blk_handle); - hw->mm_blk_handle = NULL; - } - - vfree(hw->fw); - hw->fw = NULL; - - vdec_core_release(hw_to_vdec(hw), CORE_MASK_VDEC_1 | CORE_MASK_HEVC); + if (vdec->parallel_dec == 1) + vdec_core_release(hw_to_vdec(hw), CORE_MASK_VDEC_1); + else + vdec_core_release(hw_to_vdec(hw), CORE_MASK_VDEC_1 | CORE_MASK_HEVC); vdec_set_status(hw_to_vdec(hw), VDEC_STATUS_DISCONNECTED); - + if (vdec->parallel_dec == 1) { + for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) { + vdec->free_canvas_ex(hw->buffer_spec[i].y_canvas_index, vdec->id); + vdec->free_canvas_ex(hw->buffer_spec[i].u_canvas_index, vdec->id); + vdec->free_canvas_ex(hw->buffer_spec[i].v_canvas_index, vdec->id); + } + } + if (hw) { + vfree(hw); + hw = NULL; + } + pr_info("%s\n", __func__); return 0; } /****************************************/ -static struct platform_driver amvdec_mjpeg_driver = { - .probe = amvdec_mjpeg_probe, - .remove = amvdec_mjpeg_remove, +static struct platform_driver ammvdec_mjpeg_driver = { + .probe = ammvdec_mjpeg_probe, + .remove = ammvdec_mjpeg_remove, #ifdef CONFIG_PM .suspend = amvdec_suspend, .resume = amvdec_resume, @@ -898,24 +1243,24 @@ static struct platform_driver amvdec_mjpeg_driver = { } }; -static struct codec_profile_t amvdec_mjpeg_profile = { +static struct codec_profile_t ammvdec_mjpeg_profile = { .name = "mmjpeg", .profile = "" }; -static int __init amvdec_mjpeg_driver_init_module(void) +static int __init ammvdec_mjpeg_driver_init_module(void) { - if (platform_driver_register(&amvdec_mjpeg_driver)) { - pr_err("failed to register amvdec_mjpeg driver\n"); + if (platform_driver_register(&ammvdec_mjpeg_driver)) { + pr_err("failed to register ammvdec_mjpeg driver\n"); return -ENODEV; } - vcodec_profile_register(&amvdec_mjpeg_profile); + vcodec_profile_register(&ammvdec_mjpeg_profile); return 0; } -static void __exit amvdec_mjpeg_driver_remove_module(void) +static void __exit ammvdec_mjpeg_driver_remove_module(void) { - platform_driver_unregister(&amvdec_mjpeg_driver); + platform_driver_unregister(&ammvdec_mjpeg_driver); } /****************************************/ @@ -924,8 +1269,23 @@ MODULE_PARM_DESC(debug_enable, "\n debug enable\n"); module_param(pre_decode_buf_level, int, 0664); MODULE_PARM_DESC(pre_decode_buf_level, "\n ammvdec_h264 pre_decode_buf_level\n"); -module_init(amvdec_mjpeg_driver_init_module); -module_exit(amvdec_mjpeg_driver_remove_module); +module_param(udebug_flag, uint, 0664); +MODULE_PARM_DESC(udebug_flag, "\n amvdec_mmpeg12 udebug_flag\n"); + + +module_param(decode_timeout_val, uint, 0664); +MODULE_PARM_DESC(decode_timeout_val, "\n ammvdec_mjpeg decode_timeout_val\n"); + +module_param_array(max_process_time, uint, &max_decode_instance_num, 0664); + +module_param(radr, uint, 0664); +MODULE_PARM_DESC(radr, "\nradr\n"); + +module_param(rval, uint, 0664); +MODULE_PARM_DESC(rval, "\nrval\n"); + +module_init(ammvdec_mjpeg_driver_init_module); +module_exit(ammvdec_mjpeg_driver_remove_module); MODULE_DESCRIPTION("AMLOGIC MJMPEG Video Decoder Driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/mpeg12/Makefile b/drivers/amlogic/media_modules/frame_provider/decoder/mpeg12/Makefile index 9a07229b0cb0..34f78c477e30 100644 --- a/drivers/amlogic/media_modules/frame_provider/decoder/mpeg12/Makefile +++ b/drivers/amlogic/media_modules/frame_provider/decoder/mpeg12/Makefile @@ -1,2 +1,5 @@ obj-$(CONFIG_AMLOGIC_MEDIA_VDEC_MPEG12) += amvdec_mpeg12.o amvdec_mpeg12-objs += vmpeg12.o + +obj-$(CONFIG_AMLOGIC_MEDIA_VDEC_MPEG2_MULTI) += amvdec_mmpeg12.o +amvdec_mmpeg12-objs += vmpeg12_multi.o diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/mpeg12/vmpeg12.c b/drivers/amlogic/media_modules/frame_provider/decoder/mpeg12/vmpeg12.c index 2e3a90edea7c..ab54188c87e5 100644 --- a/drivers/amlogic/media_modules/frame_provider/decoder/mpeg12/vmpeg12.c +++ b/drivers/amlogic/media_modules/frame_provider/decoder/mpeg12/vmpeg12.c @@ -41,6 +41,10 @@ #include "../utils/decoder_bmmu_box.h" #include #include +#include + +#include + #ifdef CONFIG_AM_VDEC_MPEG12_LOG #define AMLOG @@ -56,6 +60,7 @@ MODULE_AMLOG(LOG_LEVEL_ERROR, 0, LOG_LEVEL_DESC, LOG_DEFAULT_MASK_DESC); #include "../utils/amvdec.h" #include "../utils/vdec.h" #include "../utils/firmware.h" +#include "../../../common/chips/decoder_cpu_ver_info.h" #define DRIVER_NAME "amvdec_mpeg12" #define MODULE_NAME "amvdec_mpeg12" @@ -171,6 +176,7 @@ static int ccbuf_phyAddress_is_remaped_nocache; static u32 lastpts; static u32 fr_hint_status; static u32 last_offset; +static u32 ratio_control; static DEFINE_SPINLOCK(lock); @@ -194,6 +200,10 @@ static struct work_struct reset_work; static struct work_struct set_clk_work; static bool is_reset; +static DEFINE_MUTEX(userdata_mutex); + +static void vmpeg12_create_userdata_manager(u8 *userdata_buf, int buf_len); + struct mpeg12_userdata_recored_t { struct userdata_meta_info_t meta_info; u32 rec_start; @@ -286,6 +296,8 @@ static void set_frame_info(struct vframe_s *vf) else vf->ratio_control = 0; + ratio_control = vf->ratio_control; + amlog_level_if(first, LOG_LEVEL_INFO, "mpeg2dec: w(%d), h(%d), dur(%d), dur-ES(%d)\n", frame_width, frame_height, frame_dur, @@ -756,8 +768,8 @@ static void userdata_push_do_work(struct work_struct *work) DMA_FROM_DEVICE); } - - if (p_userdata_mgr) { + mutex_lock(&userdata_mutex); + if (p_userdata_mgr && ccbuf_phyAddress_virt) { int new_wp; new_wp = reg & 0xffff; @@ -769,6 +781,7 @@ static void userdata_push_do_work(struct work_struct *work) memcpy(head_info, pdata, 8); } else memset(head_info, 0, 8); + mutex_unlock(&userdata_mutex); aml_swap_data(head_info, 8); wp = (head_info[0] << 8 | head_info[1]); @@ -854,6 +867,7 @@ static irqreturn_t vmpeg12_isr(int irq, void *dev_id) u32 reg, info, seqinfo, offset, pts, pts_valid = 0; struct vframe_s *vf; u64 pts_us64 = 0; + u32 frame_size; WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1); @@ -870,7 +884,8 @@ static irqreturn_t vmpeg12_isr(int irq, void *dev_id) first_i_frame_ready = 1; if ((pts_lookup_offset_us64 - (PTS_TYPE_VIDEO, offset, &pts, 0, &pts_us64) == 0) + (PTS_TYPE_VIDEO, offset, &pts, + &frame_size, 0, &pts_us64) == 0) && (((info & PICINFO_TYPE_MASK) == PICINFO_TYPE_I) || ((info & PICINFO_TYPE_MASK) == PICINFO_TYPE_P))) @@ -928,7 +943,9 @@ static irqreturn_t vmpeg12_isr(int irq, void *dev_id) } set_frame_info(vf); - vf->signal_type = 0; + /*pr_info("video signal type:0x%x\n", + READ_VREG(AV_SCRATCH_H));*/ + vf->signal_type = READ_VREG(AV_SCRATCH_H); vf->index = index; #ifdef NV21 vf->type = @@ -986,6 +1003,7 @@ static irqreturn_t vmpeg12_isr(int irq, void *dev_id) index); kfifo_put(&display_q, (const struct vframe_s *)vf); + ATRACE_COUNTER(MODULE_NAME, vf->pts); vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); @@ -1071,6 +1089,7 @@ static irqreturn_t vmpeg12_isr(int irq, void *dev_id) index); kfifo_put(&display_q, (const struct vframe_s *)vf); + ATRACE_COUNTER(MODULE_NAME, vf->pts); vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); @@ -1123,6 +1142,7 @@ static irqreturn_t vmpeg12_isr(int irq, void *dev_id) index); kfifo_put(&display_q, (const struct vframe_s *)vf); + ATRACE_COUNTER(MODULE_NAME, vf->pts); vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); @@ -1163,6 +1183,7 @@ static irqreturn_t vmpeg12_isr(int irq, void *dev_id) } else { kfifo_put(&display_q, (const struct vframe_s *)vf); + ATRACE_COUNTER(MODULE_NAME, vf->pts); vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); @@ -1254,6 +1275,7 @@ static void vmpeg12_ppmgr_reset(void) #endif static void vmpeg12_reset_userdata_fifo(struct vdec_s *vdec, int bInit); +static void vmpeg12_wakeup_userdata_poll(struct vdec_s *vdec); static void reset_do_work(struct work_struct *work) { @@ -1267,6 +1289,7 @@ static void reset_do_work(struct work_struct *work) vf_reg_provider(&vmpeg_vf_prov); #endif vmpeg12_prot_init(); + vmpeg12_create_userdata_manager(ccbuf_phyAddress_virt, CCBUF_SIZE); vmpeg12_reset_userdata_fifo(vdec, 1); #ifdef DUMP_USER_DATA last_wp = 0; @@ -1277,8 +1300,7 @@ static void reset_do_work(struct work_struct *work) static void vmpeg12_set_clk(struct work_struct *work) { - if (frame_dur > 0 && saved_resolution != - frame_width * frame_height * (96000 / frame_dur)) { + { int fps = 96000 / frame_dur; saved_resolution = frame_width * frame_height * fps; @@ -1342,7 +1364,9 @@ static void vmpeg_put_timer_func(unsigned long arg) } } - schedule_work(&set_clk_work); + if (frame_dur > 0 && saved_resolution != + frame_width * frame_height * (96000 / frame_dur)) + schedule_work(&set_clk_work); timer->expires = jiffies + PUT_INTERVAL; @@ -1351,6 +1375,9 @@ static void vmpeg_put_timer_func(unsigned long arg) int vmpeg12_dec_status(struct vdec_s *vdec, struct vdec_info *vstatus) { + if (!(stat & STAT_VDEC_RUN)) + return -1; + vstatus->frame_width = frame_width; vstatus->frame_height = frame_height; if (frame_dur != 0) @@ -1369,6 +1396,7 @@ int vmpeg12_dec_status(struct vdec_s *vdec, struct vdec_info *vstatus) vstatus->total_data = gvs->total_data; vstatus->samp_cnt = gvs->samp_cnt; vstatus->offset = gvs->offset; + vstatus->ratio_control = ratio_control; snprintf(vstatus->vdec_name, sizeof(vstatus->vdec_name), "%s", DRIVER_NAME); @@ -1381,10 +1409,10 @@ int vmpeg12_set_isreset(struct vdec_s *vdec, int isreset) return 0; } -static DEFINE_MUTEX(userdata_mutex); -void vmpeg12_crate_userdata_manager(u8 *userdata_buf, int buf_len) + +static void vmpeg12_create_userdata_manager(u8 *userdata_buf, int buf_len) { mutex_lock(&userdata_mutex); @@ -1400,7 +1428,7 @@ void vmpeg12_crate_userdata_manager(u8 *userdata_buf, int buf_len) mutex_unlock(&userdata_mutex); } -void vmpeg12_destroy_userdata_manager(void) +static void vmpeg12_destroy_userdata_manager(void) { mutex_lock(&userdata_mutex); @@ -1473,13 +1501,12 @@ static int vmpeg12_user_data_read(struct vdec_s *vdec, u8 *rec_data_start; u8 *pdest_buf; struct mpeg12_userdata_recored_t *p_userdata_rec; - - u32 data_size; u32 res; int copy_ok = 1; - pdest_buf = (void *)(puserdata_para->pbuf_addr); + pdest_buf = puserdata_para->pbuf_addr; + mutex_lock(&userdata_mutex); if (!p_userdata_mgr) { @@ -1630,9 +1657,8 @@ static int vmpeg12_user_data_read(struct vdec_s *vdec, } } - res = (u32)copy_to_user((void *)&puserdata_para->meta_info, - (void *)&p_userdata_rec->meta_info, - sizeof(p_userdata_rec->meta_info)); + + puserdata_para->meta_info = p_userdata_rec->meta_info; if (p_userdata_mgr->read_index <= p_userdata_mgr->write_index) puserdata_para->meta_info.records_in_que = @@ -1668,6 +1694,11 @@ static void vmpeg12_reset_userdata_fifo(struct vdec_s *vdec, int bInit) mutex_unlock(&userdata_mutex); } +static void vmpeg12_wakeup_userdata_poll(struct vdec_s *vdec) +{ + amstream_wakeup_userdata_poll(vdec); +} + static int vmpeg12_vdec_info_init(void) { gvs = kzalloc(sizeof(struct vdec_info), GFP_KERNEL); @@ -1721,12 +1752,13 @@ static int vmpeg12_canvas_init(void) = (u32)buf_start; ccbuf_phyAddress_virt - = codec_mm_phys_to_virt(ccbuf_phyAddress); + = codec_mm_phys_to_virt( + ccbuf_phyAddress); if (!ccbuf_phyAddress_virt) { ccbuf_phyAddress_virt - = ioremap_nocache( - ccbuf_phyAddress, - CCBUF_SIZE); + = codec_mm_vmap( + ccbuf_phyAddress, + CCBUF_SIZE); ccbuf_phyAddress_is_remaped_nocache = 1; } } @@ -1767,13 +1799,13 @@ static int vmpeg12_canvas_init(void) static int vmpeg12_prot_init(void) { int ret; - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M6) { + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M6) { int save_reg = READ_VREG(POWER_CTL_VLD); WRITE_VREG(DOS_SW_RESET0, (1 << 7) | (1 << 6) | (1 << 4)); WRITE_VREG(DOS_SW_RESET0, 0); - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M8) { + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M8) { READ_VREG(DOS_SW_RESET0); READ_VREG(DOS_SW_RESET0); @@ -1875,10 +1907,20 @@ static void vmpeg12_local_init(void) for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) vfbuf_use[i] = 0; - if (mm_blk_handle) { + mutex_lock(&userdata_mutex); + if (p_userdata_mgr) { + vfree(p_userdata_mgr); + p_userdata_mgr = NULL; + } + if (ccbuf_phyAddress_is_remaped_nocache) + codec_mm_unmap_phyaddr(ccbuf_phyAddress_virt); + ccbuf_phyAddress_virt = NULL; + ccbuf_phyAddress = 0; + ccbuf_phyAddress_is_remaped_nocache = 0; decoder_bmmu_box_free(mm_blk_handle); mm_blk_handle = NULL; + mutex_unlock(&userdata_mutex); } mm_blk_handle = decoder_bmmu_box_alloc_box( @@ -1921,11 +1963,12 @@ static s32 vmpeg12_init(void) return -1; } - if (size == 1) - pr_info ("tee load ok"); - else if (amvdec_loadmc_ex(VFORMAT_MPEG12, NULL, buf) < 0) { + ret = amvdec_loadmc_ex(VFORMAT_MPEG12, "mpeg12", buf); + if (ret < 0) { amvdec_disable(); vfree(buf); + pr_err("MPEG12: the %s fw loading failed, err: %x\n", + tee_enabled() ? "TEE" : "local", ret); return -EBUSY; } @@ -1957,13 +2000,14 @@ static s32 vmpeg12_init(void) vf_reg_provider(&vmpeg_vf_prov); #endif if (vmpeg12_amstream_dec_info.rate != 0) { - if (!is_reset) + if (!is_reset) { vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_FR_HINT, (void *) ((unsigned long) vmpeg12_amstream_dec_info.rate)); - fr_hint_status = VDEC_HINTED; + fr_hint_status = VDEC_HINTED; + } } else fr_hint_status = VDEC_NEED_HINT; @@ -2015,7 +2059,7 @@ static int amvdec_mpeg12_probe(struct platform_device *pdev) pdata->user_data_read = vmpeg12_user_data_read; pdata->reset_userdata_fifo = vmpeg12_reset_userdata_fifo; - + pdata->wakeup_userdata_poll = vmpeg12_wakeup_userdata_poll; is_reset = 0; vmpeg12_vdec_info_init(); @@ -2025,14 +2069,14 @@ static int amvdec_mpeg12_probe(struct platform_device *pdev) amlog_level(LOG_LEVEL_ERROR, "amvdec_mpeg12 init failed.\n"); kfree(gvs); gvs = NULL; - + pdata->dec_status = NULL; return -ENODEV; } vdec = pdata; #ifdef DUMP_USER_DATA amvdec_mpeg12_init_userdata_dump(); #endif - vmpeg12_crate_userdata_manager(ccbuf_phyAddress_virt, CCBUF_SIZE); + vmpeg12_create_userdata_manager(ccbuf_phyAddress_virt, CCBUF_SIZE); INIT_WORK(&userdata_push_work, userdata_push_do_work); INIT_WORK(¬ify_work, vmpeg12_notify_work); @@ -2055,7 +2099,6 @@ static int amvdec_mpeg12_remove(struct platform_device *pdev) cancel_work_sync(&userdata_push_work); cancel_work_sync(¬ify_work); cancel_work_sync(&reset_work); - cancel_work_sync(&set_clk_work); if (stat & STAT_VDEC_RUN) { amvdec_stop(); @@ -2072,8 +2115,9 @@ static int amvdec_mpeg12_remove(struct platform_device *pdev) stat &= ~STAT_TIMER_ARM; } + cancel_work_sync(&set_clk_work); if (stat & STAT_VF_HOOK) { - if (fr_hint_status == VDEC_HINTED && !is_reset) + if (fr_hint_status == VDEC_HINTED) vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_FR_END_HINT, NULL); fr_hint_status = VDEC_NO_NEED_HINT; @@ -2084,7 +2128,7 @@ static int amvdec_mpeg12_remove(struct platform_device *pdev) amvdec_disable(); if (ccbuf_phyAddress_is_remaped_nocache) - iounmap(ccbuf_phyAddress_virt); + codec_mm_unmap_phyaddr(ccbuf_phyAddress_virt); ccbuf_phyAddress_virt = NULL; ccbuf_phyAddress = 0; diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/mpeg12/vmpeg12_multi.c b/drivers/amlogic/media_modules/frame_provider/decoder/mpeg12/vmpeg12_multi.c new file mode 100644 index 000000000000..a8962ddd9f70 --- /dev/null +++ b/drivers/amlogic/media_modules/frame_provider/decoder/mpeg12/vmpeg12_multi.c @@ -0,0 +1,2854 @@ +/* + * drivers/amlogic/amports/vmpeg12.c + * + * Copyright (C) 2015 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include "../../../stream_input/amports/amports_priv.h" + +#include "../utils/vdec_input.h" +#include "../utils/vdec.h" +#include "../utils/amvdec.h" +#include "../utils/decoder_mmu_box.h" +#include "../utils/decoder_bmmu_box.h" +#include +#include +#include "../utils/firmware.h" + + +#define MEM_NAME "codec_mmpeg12" +#define CHECK_INTERVAL (HZ/100) + +#define DRIVER_NAME "ammvdec_mpeg12" +#define MODULE_NAME "ammvdec_mpeg12" +#define MREG_REF0 AV_SCRATCH_2 +#define MREG_REF1 AV_SCRATCH_3 +/* protocol registers */ +#define MREG_SEQ_INFO AV_SCRATCH_4 +#define MREG_PIC_INFO AV_SCRATCH_5 +#define MREG_PIC_WIDTH AV_SCRATCH_6 +#define MREG_PIC_HEIGHT AV_SCRATCH_7 +#define MREG_INPUT AV_SCRATCH_8 /*input_type*/ +#define MREG_BUFFEROUT AV_SCRATCH_9 /*FROM_AMRISC_REG*/ + +#define MREG_CMD AV_SCRATCH_A +#define MREG_CO_MV_START AV_SCRATCH_B +#define MREG_ERROR_COUNT AV_SCRATCH_C +#define MREG_FRAME_OFFSET AV_SCRATCH_D +#define MREG_WAIT_BUFFER AV_SCRATCH_E +#define MREG_FATAL_ERROR AV_SCRATCH_F + +#define PICINFO_ERROR 0x80000000 +#define PICINFO_TYPE_MASK 0x00030000 +#define PICINFO_TYPE_I 0x00000000 +#define PICINFO_TYPE_P 0x00010000 +#define PICINFO_TYPE_B 0x00020000 + +#define GET_SLICE_TYPE(type) ("IPB###"[(type&PICINFO_TYPE_MASK)>>16]) +#define PICINFO_PROG 0x8000 +#define PICINFO_RPT_FIRST 0x4000 +#define PICINFO_TOP_FIRST 0x2000 +#define PICINFO_FRAME 0x1000 +#define TOP_FIELD 0x1000 +#define BOTTOM_FIELD 0x2000 +#define FRAME_PICTURE 0x3000 +#define FRAME_PICTURE_MASK 0x3000 + +#define SEQINFO_EXT_AVAILABLE 0x80000000 +#define SEQINFO_PROG 0x00010000 +#define CCBUF_SIZE (5*1024) + +#define VF_POOL_SIZE 32 +#define DECODE_BUFFER_NUM_MAX 8 +#define PUT_INTERVAL (HZ/100) +#define WORKSPACE_SIZE (4*SZ_64K) /*swap&ccbuf&matirx&MV*/ +#define CTX_LMEM_SWAP_OFFSET 0 +#define CTX_CCBUF_OFFSET 0x800 +#define CTX_QUANT_MATRIX_OFFSET (CTX_CCBUF_OFFSET + 5*1024) +#define CTX_CO_MV_OFFSET (CTX_QUANT_MATRIX_OFFSET + 1*1024) +#define CTX_DECBUF_OFFSET (CTX_CO_MV_OFFSET + 0x11000) + +#define MAX_BMMU_BUFFER_NUM (DECODE_BUFFER_NUM_MAX + 1) +#define DEFAULT_MEM_SIZE (32*SZ_1M) +static u32 buf_size = 32 * 1024 * 1024; +static int pre_decode_buf_level = 0x800; +static u32 dec_control; +static u32 error_frame_skip_level; +static u32 stat; +static u32 udebug_flag; +static unsigned int radr; +static unsigned int rval; + +#define VMPEG12_DEV_NUM 9 +static unsigned int max_decode_instance_num = VMPEG12_DEV_NUM; +static unsigned int max_process_time[VMPEG12_DEV_NUM]; +static unsigned int decode_timeout_val = 100; +#define INCPTR(p) ptr_atomic_wrap_inc(&p) + +#define DEC_CONTROL_FLAG_FORCE_2500_720_576_INTERLACE 0x0002 +#define DEC_CONTROL_FLAG_FORCE_3000_704_480_INTERLACE 0x0004 +#define DEC_CONTROL_FLAG_FORCE_2500_704_576_INTERLACE 0x0008 +#define DEC_CONTROL_FLAG_FORCE_2500_544_576_INTERLACE 0x0010 +#define DEC_CONTROL_FLAG_FORCE_2500_480_576_INTERLACE 0x0020 +#define DEC_CONTROL_INTERNAL_MASK 0x0fff +#define DEC_CONTROL_FLAG_FORCE_SEQ_INTERLACE 0x1000 + +#define INTERLACE_SEQ_ALWAYS + +#if 1/* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */ +#define NV21 +#endif + +#define AGAIN_HAS_THRESHOLD + +#ifdef AGAIN_HAS_THRESHOLD +u32 again_threshold = 0x40; +#endif + +/* +#define DUMP_USER_DATA +*/ + +enum { + FRAME_REPEAT_TOP, + FRAME_REPEAT_BOT, + FRAME_REPEAT_NONE +}; +#define DEC_RESULT_NONE 0 +#define DEC_RESULT_DONE 1 +#define DEC_RESULT_AGAIN 2 +#define DEC_RESULT_ERROR 3 +#define DEC_RESULT_FORCE_EXIT 4 +#define DEC_RESULT_EOS 5 +#define DEC_RESULT_GET_DATA 6 +#define DEC_RESULT_GET_DATA_RETRY 7 + +#define DEC_DECODE_TIMEOUT 0x21 +#define DECODE_ID(hw) (hw_to_vdec(hw)->id) +#define DECODE_STOP_POS AV_SCRATCH_K + +static struct vframe_s *vmpeg_vf_peek(void *); +static struct vframe_s *vmpeg_vf_get(void *); +static void vmpeg_vf_put(struct vframe_s *, void *); +static int vmpeg_vf_states(struct vframe_states *states, void *); +static int vmpeg_event_cb(int type, void *data, void *private_data); + +struct mmpeg2_userdata_record_t { + struct userdata_meta_info_t meta_info; + u32 rec_start; + u32 rec_len; +}; + +#define USERDATA_FIFO_NUM 256 +#define MAX_FREE_USERDATA_NODES 5 + +struct mmpeg2_userdata_info_t { + struct mmpeg2_userdata_record_t records[USERDATA_FIFO_NUM]; + u8 *data_buf; + u8 *data_buf_end; + u32 buf_len; + u32 read_index; + u32 write_index; + u32 last_wp; +}; +#define MAX_UD_RECORDS 5 + +struct vdec_mpeg12_hw_s { + spinlock_t lock; + struct platform_device *platform_dev; + DECLARE_KFIFO(newframe_q, struct vframe_s *, VF_POOL_SIZE); + DECLARE_KFIFO(display_q, struct vframe_s *, VF_POOL_SIZE); + struct vframe_s vfpool[VF_POOL_SIZE]; + s32 vfbuf_use[DECODE_BUFFER_NUM_MAX]; + u32 frame_width; + u32 frame_height; + u32 frame_dur; + u32 frame_prog; + u32 seqinfo; + u32 ctx_valid; + u32 dec_control; + void *mm_blk_handle; + struct vframe_chunk_s *chunk; + u32 stat; + u8 init_flag; + unsigned long buf_start; + u32 buf_size; + u32 reg_pic_width; + u32 reg_pic_height; + u32 reg_mpeg1_2_reg; + u32 reg_pic_head_info; + u32 reg_f_code_reg; + u32 reg_slice_ver_pos_pic_type; + u32 reg_vcop_ctrl_reg; + u32 reg_mb_info; + u32 reg_signal_type; + u32 frame_num; + struct timer_list check_timer; + u32 decode_timeout_count; + u32 start_process_time; + u32 last_vld_level; + u32 eos; + u32 buffer_info[DECODE_BUFFER_NUM_MAX]; + u32 pts[DECODE_BUFFER_NUM_MAX]; + u64 pts64[DECODE_BUFFER_NUM_MAX]; + bool pts_valid[DECODE_BUFFER_NUM_MAX]; + u32 canvas_spec[DECODE_BUFFER_NUM_MAX]; + struct canvas_config_s canvas_config[DECODE_BUFFER_NUM_MAX][2]; + struct dec_sysinfo vmpeg12_amstream_dec_info; + + s32 refs[2]; + int dec_result; + struct work_struct work; + struct work_struct notify_work; + void (*vdec_cb)(struct vdec_s *, void *); + void *vdec_cb_arg; + unsigned long ccbuf_phyAddress; + void *ccbuf_phyAddress_virt; + unsigned long ccbuf_phyAddress_is_remaped_nocache; + u32 frame_rpt_state; +/* for error handling */ + s32 frame_force_skip_flag; + s32 error_frame_skip_level; + s32 wait_buffer_counter; + u32 first_i_frame_ready; + u32 run_count; + u32 not_run_ready; + u32 input_empty; + u32 put_num; + u32 peek_num; + u32 get_num; + u32 drop_frame_count; + u32 buffer_not_ready; + u32 ratio_control; + int frameinfo_enable; + struct firmware_s *fw; + u32 canvas_mode; +#ifdef AGAIN_HAS_THRESHOLD + u32 pre_parser_wr_ptr; + u8 next_again_flag; +#endif + struct work_struct userdata_push_work; + struct mutex userdata_mutex; + struct mmpeg2_userdata_info_t userdata_info; + struct mmpeg2_userdata_record_t ud_record[MAX_UD_RECORDS]; + int cur_ud_idx; + u8 *user_data_buffer; + int wait_for_udr_send; + u32 ucode_cc_last_wp; + u32 notify_ucode_cc_last_wp; + u32 notify_data_cc_last_wp; + +#ifdef DUMP_USER_DATA +#define MAX_USER_DATA_SIZE 1572864 + void *user_data_dump_buf; + unsigned char *pdump_buf_cur_start; + int total_len; + int bskip; + int n_userdata_id; + u32 reference[MAX_UD_RECORDS]; +#endif +}; +static void vmpeg12_local_init(struct vdec_mpeg12_hw_s *hw); +static int vmpeg12_hw_ctx_restore(struct vdec_mpeg12_hw_s *hw); +static void reset_process_time(struct vdec_mpeg12_hw_s *hw); +static struct vdec_info gvs; +static int debug_enable; +/*static struct work_struct userdata_push_work;*/ +#undef pr_info +#define pr_info printk +unsigned int mpeg12_debug_mask = 0xff; +/*static int counter_max = 5;*/ + +#define PRINT_FLAG_ERROR 0x0 +#define PRINT_FLAG_RUN_FLOW 0X0001 +#define PRINT_FLAG_TIMEINFO 0x0002 +#define PRINT_FLAG_UCODE_DETAIL 0x0004 +#define PRINT_FLAG_VLD_DETAIL 0x0008 +#define PRINT_FLAG_DEC_DETAIL 0x0010 +#define PRINT_FLAG_BUFFER_DETAIL 0x0020 +#define PRINT_FLAG_RESTORE 0x0040 +#define PRINT_FRAME_NUM 0x0080 +#define PRINT_FLAG_FORCE_DONE 0x0100 +#define PRINT_FLAG_COUNTER 0X0200 +#define PRINT_FRAMEBASE_DATA 0x0400 +#define PRINT_FLAG_VDEC_STATUS 0x0800 +#define PRINT_FLAG_PARA_DATA 0x1000 +#define PRINT_FLAG_USERDATA_DETAIL 0x2000 + + + +int debug_print(int index, int debug_flag, const char *fmt, ...) +{ + if (((debug_enable & debug_flag) && + ((1 << index) & mpeg12_debug_mask)) + || (debug_flag == PRINT_FLAG_ERROR)) { + unsigned char buf[512]; + int len = 0; + va_list args; + va_start(args, fmt); + len = sprintf(buf, "%d: ", index); + vsnprintf(buf + len, 512-len, fmt, args); + pr_info("%s", buf); + va_end(args); + } + return 0; +} + + +/*static bool is_reset;*/ +#define PROVIDER_NAME "vdec.mpeg12" +static const struct vframe_operations_s vf_provider_ops = { + .peek = vmpeg_vf_peek, + .get = vmpeg_vf_get, + .put = vmpeg_vf_put, + .event_cb = vmpeg_event_cb, + .vf_states = vmpeg_vf_states, +}; + + +static const u32 frame_rate_tab[16] = { + 96000 / 30, 96000000 / 23976, 96000 / 24, 96000 / 25, + 9600000 / 2997, 96000 / 30, 96000 / 50, 9600000 / 5994, + 96000 / 60, + /* > 8 reserved, use 24 */ + 96000 / 24, 96000 / 24, 96000 / 24, 96000 / 24, + 96000 / 24, 96000 / 24, 96000 / 24 +}; + + +static u32 find_buffer(struct vdec_mpeg12_hw_s *hw) +{ + u32 i; + + for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) { + if (hw->vfbuf_use[i] == 0) + return i; + } + + return DECODE_BUFFER_NUM_MAX; +} + +static u32 spec_to_index(struct vdec_mpeg12_hw_s *hw, u32 spec) +{ + u32 i; + + for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) { + if (hw->canvas_spec[i] == spec) + return i; + } + + return DECODE_BUFFER_NUM_MAX; +} + +static void set_frame_info(struct vdec_mpeg12_hw_s *hw, struct vframe_s *vf) +{ + unsigned ar_bits; + u32 temp; + u32 buffer_index = vf->index; +#ifdef CONFIG_AM_VDEC_MPEG12_LOG + bool first = (hw->frame_width == 0) && (hw->frame_height == 0); +#endif + + temp = READ_VREG(MREG_PIC_WIDTH); + if (temp > 1920 || temp == 0) + vf->width = hw->frame_width = 1920; + else + vf->width = hw->frame_width = temp; + + temp = READ_VREG(MREG_PIC_HEIGHT); + if (temp > 1088 || temp == 0) + vf->height = hw->frame_height = 1088; + else + vf->height = hw->frame_height = temp; + + if (hw->frame_dur > 0) + vf->duration = hw->frame_dur; + else { + vf->duration = hw->frame_dur = + frame_rate_tab[(READ_VREG(MREG_SEQ_INFO) >> 4) & 0xf]; + schedule_work(&hw->notify_work); + } + + ar_bits = READ_VREG(MREG_SEQ_INFO) & 0xf; + + if (ar_bits == 0x2) + vf->ratio_control = 0xc0 << DISP_RATIO_ASPECT_RATIO_BIT; + + else if (ar_bits == 0x3) + vf->ratio_control = 0x90 << DISP_RATIO_ASPECT_RATIO_BIT; + + else if (ar_bits == 0x4) + vf->ratio_control = 0x74 << DISP_RATIO_ASPECT_RATIO_BIT; + else + vf->ratio_control = 0; + + hw->ratio_control = vf->ratio_control; + + vf->canvas0Addr = vf->canvas1Addr = -1; + vf->plane_num = 2; + + vf->canvas0_config[0] = hw->canvas_config[buffer_index][0]; + vf->canvas0_config[1] = hw->canvas_config[buffer_index][1]; + + vf->canvas1_config[0] = hw->canvas_config[buffer_index][0]; + vf->canvas1_config[1] = hw->canvas_config[buffer_index][1]; + + + debug_print(DECODE_ID(hw), PRINT_FLAG_PARA_DATA, + "mpeg2dec: w(%d), h(%d), dur(%d), dur-ES(%d)\n", + hw->frame_width, hw->frame_height, hw->frame_dur, + frame_rate_tab[(READ_VREG(MREG_SEQ_INFO) >> 4) & 0xf]); +} + +static bool error_skip(struct vdec_mpeg12_hw_s *hw, + u32 info, struct vframe_s *vf) +{ + if (hw->error_frame_skip_level) { + /* skip error frame */ + if ((info & PICINFO_ERROR) || (hw->frame_force_skip_flag)) { + if ((info & PICINFO_ERROR) == 0) { + if ((info & PICINFO_TYPE_MASK) == + PICINFO_TYPE_I) + hw->frame_force_skip_flag = 0; + } else { + if (hw->error_frame_skip_level >= 2) + hw->frame_force_skip_flag = 1; + } + if ((info & PICINFO_ERROR) + || (hw->frame_force_skip_flag)) + return true; + } + } + return false; +} + +static inline void vmpeg12_save_hw_context(struct vdec_mpeg12_hw_s *hw) +{ + hw->seqinfo = READ_VREG(MREG_SEQ_INFO); + hw->reg_pic_width = READ_VREG(MREG_PIC_WIDTH); + hw->reg_pic_height = READ_VREG(MREG_PIC_HEIGHT); + hw->reg_mpeg1_2_reg = READ_VREG(MPEG1_2_REG); + hw->reg_pic_head_info = READ_VREG(PIC_HEAD_INFO); + hw->reg_f_code_reg = READ_VREG(F_CODE_REG); + hw->reg_slice_ver_pos_pic_type = READ_VREG(SLICE_VER_POS_PIC_TYPE); + hw->reg_vcop_ctrl_reg = READ_VREG(VCOP_CTRL_REG); + hw->reg_mb_info = READ_VREG(MB_INFO); + hw->reg_signal_type = READ_VREG(AV_SCRATCH_H); + debug_print(DECODE_ID(hw), PRINT_FLAG_PARA_DATA, + "signal_type = %x", hw->reg_signal_type); +} + +static void vmmpeg2_reset_udr_mgr(struct vdec_mpeg12_hw_s *hw) +{ + hw->wait_for_udr_send = 0; + hw->cur_ud_idx = 0; + memset(&hw->ud_record, 0, sizeof(hw->ud_record)); +} + +static void vmmpeg2_crate_userdata_manager( + struct vdec_mpeg12_hw_s *hw, + u8 *userdata_buf, + int buf_len) +{ + if (hw) { + mutex_init(&hw->userdata_mutex); + + memset(&hw->userdata_info, 0, + sizeof(struct mmpeg2_userdata_info_t)); + hw->userdata_info.data_buf = userdata_buf; + hw->userdata_info.buf_len = buf_len; + hw->userdata_info.data_buf_end = userdata_buf + buf_len; + + vmmpeg2_reset_udr_mgr(hw); + } +} + +static void vmmpeg2_destroy_userdata_manager(struct vdec_mpeg12_hw_s *hw) +{ + if (hw) + memset(&hw->userdata_info, + 0, + sizeof(struct mmpeg2_userdata_info_t)); +} + +static void aml_swap_data(uint8_t *user_data, int ud_size) +{ + int swap_blocks, i, j, k, m; + unsigned char c_temp; + + /* swap byte order */ + swap_blocks = ud_size / 8; + for (i = 0; i < swap_blocks; i++) { + j = i * 8; + k = j + 7; + for (m = 0; m < 4; m++) { + c_temp = user_data[j]; + user_data[j++] = user_data[k]; + user_data[k--] = c_temp; + } + } +} + +#ifdef DUMP_USER_DATA +static void push_to_buf(struct vdec_mpeg12_hw_s *hw, + u8 *pdata, + int len, + struct userdata_meta_info_t *pmeta, + u32 reference) +{ + u32 *pLen; + int info_cnt; + u8 *pbuf_end; + + if (!hw->user_data_dump_buf) + return; + + if (hw->bskip) { + pr_info("over size, skip\n"); + return; + } + info_cnt = 0; + pLen = (u32 *)hw->pdump_buf_cur_start; + + *pLen = len; + hw->pdump_buf_cur_start += sizeof(u32); + info_cnt++; + pLen++; + + *pLen = pmeta->duration; + hw->pdump_buf_cur_start += sizeof(u32); + info_cnt++; + pLen++; + + *pLen = pmeta->flags; + hw->pdump_buf_cur_start += sizeof(u32); + info_cnt++; + pLen++; + + *pLen = pmeta->vpts; + hw->pdump_buf_cur_start += sizeof(u32); + info_cnt++; + pLen++; + + *pLen = pmeta->vpts_valid; + hw->pdump_buf_cur_start += sizeof(u32); + info_cnt++; + pLen++; + + + *pLen = hw->n_userdata_id; + hw->pdump_buf_cur_start += sizeof(u32); + info_cnt++; + pLen++; + + *pLen = reference; + hw->pdump_buf_cur_start += sizeof(u32); + info_cnt++; + pLen++; + + pbuf_end = hw->userdata_info.data_buf_end; + if (pdata + len > pbuf_end) { + int first_section_len; + + first_section_len = pbuf_end - pdata; + memcpy(hw->pdump_buf_cur_start, pdata, first_section_len); + pdata = (u8 *)hw->userdata_info.data_buf; + hw->pdump_buf_cur_start += first_section_len; + memcpy(hw->pdump_buf_cur_start, pdata, len - first_section_len); + hw->pdump_buf_cur_start += len - first_section_len; + } else { + memcpy(hw->pdump_buf_cur_start, pdata, len); + hw->pdump_buf_cur_start += len; + } + + hw->total_len += len + info_cnt * sizeof(u32); + if (hw->total_len >= MAX_USER_DATA_SIZE-4096) + hw->bskip = 1; +} + +static void dump_userdata_info(struct vdec_mpeg12_hw_s *hw, + void *puser_data, + int len, + struct userdata_meta_info_t *pmeta, + u32 reference) +{ + u8 *pstart; + + pstart = (u8 *)puser_data; + +#ifdef DUMP_HEAD_INFO_DATA + push_to_buf(hw, pstart, len, pmeta, reference); +#else + push_to_buf(hw, pstart+8, len - 8, pmeta, reference); +#endif +} + + +static void print_data(unsigned char *pdata, + int len, + unsigned int flag, + unsigned int duration, + unsigned int vpts, + unsigned int vpts_valid, + int rec_id, + u32 reference) +{ + int nLeft; + + nLeft = len; + + pr_info("%d len:%d, flag:0x%x, dur:%d, vpts:0x%x, valid:%d, refer:%d\n", + rec_id, len, flag, + duration, vpts, vpts_valid, + reference); + while (nLeft >= 16) { + pr_info("%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", + pdata[0], pdata[1], pdata[2], pdata[3], + pdata[4], pdata[5], pdata[6], pdata[7], + pdata[8], pdata[9], pdata[10], pdata[11], + pdata[12], pdata[13], pdata[14], pdata[15]); + nLeft -= 16; + pdata += 16; + } + + + while (nLeft > 0) { + pr_info("%02x %02x %02x %02x %02x %02x %02x %02x\n", + pdata[0], pdata[1], pdata[2], pdata[3], + pdata[4], pdata[5], pdata[6], pdata[7]); + nLeft -= 8; + pdata += 8; + } +} + +static void dump_data(u8 *pdata, + unsigned int user_data_length, + unsigned int flag, + unsigned int duration, + unsigned int vpts, + unsigned int vpts_valid, + int rec_id, + u32 reference) +{ + unsigned char szBuf[256]; + + + memset(szBuf, 0, 256); + memcpy(szBuf, pdata, user_data_length); + + aml_swap_data(szBuf, user_data_length); + + print_data(szBuf, + user_data_length, + flag, + duration, + vpts, + vpts_valid, + rec_id, + reference); +} + + +static void show_user_data_buf(struct vdec_mpeg12_hw_s *hw) +{ + u8 *pbuf; + int len; + unsigned int flag; + unsigned int duration; + unsigned int vpts; + unsigned int vpts_valid; + int rec_id; + u32 reference; + + pr_info("show user data buf\n"); + pbuf = hw->user_data_dump_buf; + + while (pbuf < hw->pdump_buf_cur_start) { + u32 *pLen; + + pLen = (u32 *)pbuf; + + len = *pLen; + pLen++; + pbuf += sizeof(u32); + + duration = *pLen; + pLen++; + pbuf += sizeof(u32); + + flag = *pLen; + pLen++; + pbuf += sizeof(u32); + + vpts = *pLen; + pLen++; + pbuf += sizeof(u32); + + vpts_valid = *pLen; + pLen++; + pbuf += sizeof(u32); + + rec_id = *pLen; + pLen++; + pbuf += sizeof(u32); + + reference = *pLen; + pLen++; + pbuf += sizeof(u32); + + + dump_data(pbuf, len, flag, duration, + vpts, vpts_valid, rec_id, reference); + pbuf += len; + msleep(30); + } +} + +static int amvdec_mmpeg12_init_userdata_dump(struct vdec_mpeg12_hw_s *hw) +{ + hw->user_data_dump_buf = kmalloc(MAX_USER_DATA_SIZE, GFP_KERNEL); + if (hw->user_data_dump_buf) + return 1; + else + return 0; +} + +static void amvdec_mmpeg12_uninit_userdata_dump(struct vdec_mpeg12_hw_s *hw) +{ + if (hw->user_data_dump_buf) { + show_user_data_buf(hw); + kfree(hw->user_data_dump_buf); + hw->user_data_dump_buf = NULL; + } +} + +static void reset_user_data_buf(struct vdec_mpeg12_hw_s *hw) +{ + hw->total_len = 0; + hw->pdump_buf_cur_start = hw->user_data_dump_buf; + hw->bskip = 0; + hw->n_userdata_id = 0; +} +#endif + +static void user_data_ready_notify(struct vdec_mpeg12_hw_s *hw, + u32 pts, u32 pts_valid) +{ + struct mmpeg2_userdata_record_t *p_userdata_rec; + int i; + + if (hw->wait_for_udr_send) { + for (i = 0; i < hw->cur_ud_idx; i++) { + mutex_lock(&hw->userdata_mutex); + + + p_userdata_rec = hw->userdata_info.records + + hw->userdata_info.write_index; + + hw->ud_record[i].meta_info.vpts_valid = pts_valid; + hw->ud_record[i].meta_info.vpts = pts; + + *p_userdata_rec = hw->ud_record[i]; +#ifdef DUMP_USER_DATA + dump_userdata_info(hw, + hw->userdata_info.data_buf + p_userdata_rec->rec_start, + p_userdata_rec->rec_len, + &p_userdata_rec->meta_info, + hw->reference[i]); + hw->n_userdata_id++; +#endif +/* + pr_info("notify: rec_start:%d, rec_len:%d, wi:%d, reference:%d\n", + p_userdata_rec->rec_start, + p_userdata_rec->rec_len, + hw->userdata_info.write_index, + hw->reference[i]); +*/ + hw->userdata_info.write_index++; + if (hw->userdata_info.write_index >= USERDATA_FIFO_NUM) + hw->userdata_info.write_index = 0; + + mutex_unlock(&hw->userdata_mutex); + + + vdec_wakeup_userdata_poll(hw_to_vdec(hw)); + } + hw->wait_for_udr_send = 0; + hw->cur_ud_idx = 0; + } + hw->notify_ucode_cc_last_wp = hw->ucode_cc_last_wp; + hw->notify_data_cc_last_wp = hw->userdata_info.last_wp; +} + +static int vmmpeg2_user_data_read(struct vdec_s *vdec, + struct userdata_param_t *puserdata_para) +{ + struct vdec_mpeg12_hw_s *hw = NULL; + int rec_ri, rec_wi; + int rec_len; + u8 *rec_data_start; + u8 *pdest_buf; + struct mmpeg2_userdata_record_t *p_userdata_rec; + u32 data_size; + u32 res; + int copy_ok = 1; + + hw = (struct vdec_mpeg12_hw_s *)vdec->private; + + pdest_buf = puserdata_para->pbuf_addr; + + mutex_lock(&hw->userdata_mutex); + +/* + pr_info("ri = %d, wi = %d\n", + hw->userdata_info.read_index, + hw->userdata_info.write_index); +*/ + rec_ri = hw->userdata_info.read_index; + rec_wi = hw->userdata_info.write_index; + + if (rec_ri == rec_wi) { + mutex_unlock(&hw->userdata_mutex); + return 0; + } + + p_userdata_rec = hw->userdata_info.records + rec_ri; + + rec_len = p_userdata_rec->rec_len; + rec_data_start = p_userdata_rec->rec_start + hw->userdata_info.data_buf; +/* + pr_info("ri:%d, wi:%d, rec_len:%d, rec_start:%d, buf_len:%d\n", + rec_ri, rec_wi, + p_userdata_rec->rec_len, + p_userdata_rec->rec_start, + puserdata_para->buf_len); +*/ + if (rec_len <= puserdata_para->buf_len) { + /* dvb user data buffer is enought to + copy the whole recored. */ + data_size = rec_len; + if (rec_data_start + data_size + > hw->userdata_info.data_buf_end) { + int first_section_len; + + first_section_len = hw->userdata_info.buf_len - + p_userdata_rec->rec_start; + res = (u32)copy_to_user((void *)pdest_buf, + (void *)rec_data_start, + first_section_len); + if (res) { + pr_info("p1 read not end res=%d, request=%d\n", + res, first_section_len); + copy_ok = 0; + + p_userdata_rec->rec_len -= + first_section_len - res; + p_userdata_rec->rec_start += + first_section_len - res; + puserdata_para->data_size = + first_section_len - res; + } else { + res = (u32)copy_to_user( + (void *)(pdest_buf+first_section_len), + (void *)hw->userdata_info.data_buf, + data_size - first_section_len); + if (res) { + pr_info("p2 read not end res=%d, request=%d\n", + res, data_size); + copy_ok = 0; + } + p_userdata_rec->rec_len -= + data_size - res; + p_userdata_rec->rec_start = + data_size - first_section_len - res; + puserdata_para->data_size = + data_size - res; + } + } else { + res = (u32)copy_to_user((void *)pdest_buf, + (void *)rec_data_start, + data_size); + if (res) { + pr_info("p3 read not end res=%d, request=%d\n", + res, data_size); + copy_ok = 0; + } + p_userdata_rec->rec_len -= data_size - res; + p_userdata_rec->rec_start += data_size - res; + puserdata_para->data_size = data_size - res; + } + + if (copy_ok) { + hw->userdata_info.read_index++; + if (hw->userdata_info.read_index >= USERDATA_FIFO_NUM) + hw->userdata_info.read_index = 0; + } + } else { + /* dvb user data buffer is not enought + to copy the whole recored. */ + data_size = puserdata_para->buf_len; + if (rec_data_start + data_size + > hw->userdata_info.data_buf_end) { + int first_section_len; + + first_section_len = hw->userdata_info.buf_len - + p_userdata_rec->rec_start; + res = (u32)copy_to_user((void *)pdest_buf, + (void *)rec_data_start, + first_section_len); + if (res) { + pr_info("p4 read not end res=%d, request=%d\n", + res, first_section_len); + copy_ok = 0; + p_userdata_rec->rec_len -= + first_section_len - res; + p_userdata_rec->rec_start += + first_section_len - res; + puserdata_para->data_size = + first_section_len - res; + } else { + /* first secton copy is ok*/ + res = (u32)copy_to_user( + (void *)(pdest_buf+first_section_len), + (void *)hw->userdata_info.data_buf, + data_size - first_section_len); + if (res) { + pr_info("p5 read not end res=%d, request=%d\n", + res, + data_size - first_section_len); + copy_ok = 0; + } + + p_userdata_rec->rec_len -= + data_size - res; + p_userdata_rec->rec_start = + data_size - first_section_len - res; + puserdata_para->data_size = + data_size - res; + } + } else { + res = (u32)copy_to_user((void *)pdest_buf, + (void *)rec_data_start, + data_size); + if (res) { + pr_info("p6 read not end res=%d, request=%d\n", + res, data_size); + copy_ok = 0; + } + + p_userdata_rec->rec_len -= data_size - res; + p_userdata_rec->rec_start += data_size - res; + puserdata_para->data_size = data_size - res; + } + + if (copy_ok) { + hw->userdata_info.read_index++; + if (hw->userdata_info.read_index >= USERDATA_FIFO_NUM) + hw->userdata_info.read_index = 0; + } + + } + puserdata_para->meta_info = p_userdata_rec->meta_info; + + if (hw->userdata_info.read_index <= hw->userdata_info.write_index) + puserdata_para->meta_info.records_in_que = + hw->userdata_info.write_index - + hw->userdata_info.read_index; + else + puserdata_para->meta_info.records_in_que = + hw->userdata_info.write_index + + USERDATA_FIFO_NUM - + hw->userdata_info.read_index; + + puserdata_para->version = (0<<24|0<<16|0<<8|1); + + mutex_unlock(&hw->userdata_mutex); + + + return 1; +} + +static void vmmpeg2_reset_userdata_fifo(struct vdec_s *vdec, int bInit) +{ + struct vdec_mpeg12_hw_s *hw = NULL; + + hw = (struct vdec_mpeg12_hw_s *)vdec->private; + + if (hw) { + mutex_lock(&hw->userdata_mutex); + pr_info("vmh264_reset_userdata_fifo: bInit: %d, ri: %d, wi: %d\n", + bInit, + hw->userdata_info.read_index, + hw->userdata_info.write_index); + hw->userdata_info.read_index = 0; + hw->userdata_info.write_index = 0; + + if (bInit) + hw->userdata_info.last_wp = 0; + mutex_unlock(&hw->userdata_mutex); + } +} + +static void vmmpeg2_wakeup_userdata_poll(struct vdec_s *vdec) +{ + amstream_wakeup_userdata_poll(vdec); +} + +/* +#define PRINT_HEAD_INFO +*/ +static void userdata_push_do_work(struct work_struct *work) +{ + u32 reg; + u8 *pdata; + u8 *psrc_data; + u8 head_info[8]; + struct userdata_meta_info_t meta_info; + u32 wp; + u32 index; + u32 picture_struct; + u32 reference; + u32 picture_type; + u32 temp; + u32 data_length; + u32 data_start; + int i; + u32 offset; + u32 cur_wp; +#ifdef PRINT_HEAD_INFO + u8 *ptype_str; +#endif + struct mmpeg2_userdata_record_t *pcur_ud_rec; + + struct vdec_mpeg12_hw_s *hw = container_of(work, + struct vdec_mpeg12_hw_s, userdata_push_work); + + memset(&meta_info, 0, sizeof(meta_info)); + + meta_info.duration = hw->frame_dur; + + + reg = READ_VREG(AV_SCRATCH_J); + meta_info.flags = ((reg >> 30) << 1); + meta_info.flags |= (VFORMAT_MPEG12 << 3); + /* check top_field_first flag */ + if ((reg >> 28) & 0x1) { + meta_info.flags |= (1 << 10); + meta_info.flags |= (((reg >> 29) & 0x1) << 11); + } + + cur_wp = reg & 0x7fff; + if (cur_wp == hw->ucode_cc_last_wp) { + debug_print(DECODE_ID(hw), 0, + "Null user data package: wp = %d\n", cur_wp); + WRITE_VREG(AV_SCRATCH_J, 0); + return; + } + + if (hw->cur_ud_idx >= MAX_UD_RECORDS) { + debug_print(DECODE_ID(hw), 0, + "UD Records over: %d, skip it\n", MAX_UD_RECORDS); + WRITE_VREG(AV_SCRATCH_J, 0); + return; + } + + if (cur_wp < hw->ucode_cc_last_wp) + hw->ucode_cc_last_wp = 0; + + offset = READ_VREG(AV_SCRATCH_I); + + codec_mm_dma_flush( + hw->ccbuf_phyAddress_virt, + CCBUF_SIZE, + DMA_FROM_DEVICE); + + mutex_lock(&hw->userdata_mutex); + if (hw->ccbuf_phyAddress_virt) { + pdata = (u8 *)hw->ccbuf_phyAddress_virt + hw->ucode_cc_last_wp; + memcpy(head_info, pdata, 8); + } else + memset(head_info, 0, 8); + mutex_unlock(&hw->userdata_mutex); + aml_swap_data(head_info, 8); + + wp = (head_info[0] << 8 | head_info[1]); + index = (head_info[2] << 8 | head_info[3]); + + picture_struct = (head_info[6] << 8 | head_info[7]); + temp = (head_info[4] << 8 | head_info[5]); + reference = temp & 0x3FF; + picture_type = (temp >> 10) & 0x7; + + if (debug_enable & PRINT_FLAG_USERDATA_DETAIL) + pr_info("index:%d, wp:%d, ref:%d, type:%d, struct:0x%x, u_last_wp:0x%x\n", + index, wp, reference, + picture_type, picture_struct, + hw->ucode_cc_last_wp); + + switch (picture_type) { + case 1: + /* pr_info("I type, pos:%d\n", + (meta_info.flags>>1)&0x3); */ + meta_info.flags |= (1<<7); +#ifdef PRINT_HEAD_INFO + ptype_str = " I"; +#endif + break; + case 2: + /* pr_info("P type, pos:%d\n", + (meta_info.flags>>1)&0x3); */ + meta_info.flags |= (2<<7); +#ifdef PRINT_HEAD_INFO + ptype_str = " P"; +#endif + break; + case 3: + /* pr_info("B type, pos:%d\n", + (meta_info.flags>>1)&0x3); */ + meta_info.flags |= (3<<7); +#ifdef PRINT_HEAD_INFO + ptype_str = " B"; +#endif + break; + case 4: + /* pr_info("D type, pos:%d\n", + (meta_info.flags>>1)&0x3); */ + meta_info.flags |= (4<<7); +#ifdef PRINT_HEAD_INFO + ptype_str = " D"; +#endif + break; + default: + /* pr_info("Unknown type:0x%x, pos:%d\n", + pheader->picture_coding_type, + (meta_info.flags>>1)&0x3); */ +#ifdef PRINT_HEAD_INFO + ptype_str = " U"; +#endif + break; + } +#ifdef PRINT_HEAD_INFO + pr_info("ref:%d, type:%s, ext:%d, first:%d, data_length:%d\n", + reference, ptype_str, + (reg >> 30), + (reg >> 28)&0x3, + reg & 0xffff); +#endif + data_length = cur_wp - hw->ucode_cc_last_wp; + data_start = reg & 0xffff; + psrc_data = (u8 *)hw->ccbuf_phyAddress_virt + hw->ucode_cc_last_wp; + + pdata = hw->userdata_info.data_buf + hw->userdata_info.last_wp; + for (i = 0; i < data_length; i++) { + *pdata++ = *psrc_data++; + if (pdata >= hw->userdata_info.data_buf_end) + pdata = hw->userdata_info.data_buf; + } + pcur_ud_rec = hw->ud_record + hw->cur_ud_idx; + + pcur_ud_rec->meta_info = meta_info; + pcur_ud_rec->rec_start = hw->userdata_info.last_wp; + pcur_ud_rec->rec_len = data_length; + + hw->userdata_info.last_wp += data_length; + if (hw->userdata_info.last_wp >= USER_DATA_SIZE) + hw->userdata_info.last_wp -= USER_DATA_SIZE; + + hw->wait_for_udr_send = 1; + + hw->ucode_cc_last_wp = cur_wp; + + if (debug_enable & PRINT_FLAG_USERDATA_DETAIL) + pr_info("cur_wp:%d, rec_start:%d, rec_len:%d\n", + cur_wp, + pcur_ud_rec->rec_start, + pcur_ud_rec->rec_len); + +#ifdef DUMP_USER_DATA + hw->reference[hw->cur_ud_idx] = reference; +#endif + + hw->cur_ud_idx++; + WRITE_VREG(AV_SCRATCH_J, 0); + +} + + +void userdata_pushed_drop(struct vdec_mpeg12_hw_s *hw) +{ + hw->userdata_info.last_wp = hw->notify_data_cc_last_wp; + hw->ucode_cc_last_wp = hw->notify_ucode_cc_last_wp; + hw->cur_ud_idx = 0; + hw->wait_for_udr_send = 0; + +} + + +static irqreturn_t vmpeg12_isr_thread_fn(struct vdec_s *vdec, int irq) +{ + u32 reg, info, seqinfo, offset, pts, pts_valid = 0; + struct vframe_s *vf = NULL; + u32 index; + u64 pts_us64 = 0; + u32 frame_size; + struct vdec_mpeg12_hw_s *hw = + (struct vdec_mpeg12_hw_s *)(vdec->private); + + if (READ_VREG(AV_SCRATCH_M) != 0 && + (debug_enable & PRINT_FLAG_UCODE_DETAIL)) { + + debug_print(DECODE_ID(hw), PRINT_FLAG_DEC_DETAIL, + "dbg %x: %x, level %x, wp %x, rp %x, cnt %x\n", + READ_VREG(AV_SCRATCH_M), READ_VREG(AV_SCRATCH_N), + READ_VREG(VLD_MEM_VIFIFO_LEVEL), + READ_VREG(VLD_MEM_VIFIFO_WP), + READ_VREG(VLD_MEM_VIFIFO_RP), + READ_VREG(VIFF_BIT_CNT)); + WRITE_VREG(AV_SCRATCH_M, 0); + return IRQ_HANDLED; + } + + reg = READ_VREG(AV_SCRATCH_J); + if (reg & (1<<16)) { + vdec_schedule_work(&hw->userdata_push_work); + return IRQ_HANDLED; + } + + reg = READ_VREG(MREG_BUFFEROUT); + + if (reg == 2) { + /*timeout when decoding next frame*/ + + debug_print(DECODE_ID(hw), PRINT_FLAG_VLD_DETAIL, + "ammvdec_mpeg12: Insufficient data\n"); + debug_print(DECODE_ID(hw), PRINT_FLAG_VLD_DETAIL, + "level=%x, vtl=%x,bcnt=%d\n", + READ_VREG(VLD_MEM_VIFIFO_LEVEL), + READ_VREG(VLD_MEM_VIFIFO_CONTROL), + READ_VREG(VIFF_BIT_CNT)); + if (input_frame_based(vdec)) + vmpeg12_save_hw_context(hw); + else { + hw->dec_result = DEC_RESULT_AGAIN; + vdec_schedule_work(&hw->work); + userdata_pushed_drop(hw); + } + return IRQ_HANDLED; + } else { + reset_process_time(hw); + info = READ_VREG(MREG_PIC_INFO); + offset = READ_VREG(MREG_FRAME_OFFSET); + index = spec_to_index(hw, READ_VREG(REC_CANVAS_ADDR)); + seqinfo = READ_VREG(MREG_SEQ_INFO); + if ((info & PICINFO_PROG) == 0 && + (info & FRAME_PICTURE_MASK) != FRAME_PICTURE) + hw->first_i_frame_ready = 1; /* for field struct case*/ + debug_print(DECODE_ID(hw), PRINT_FLAG_DEC_DETAIL, + "struct: %d %x\n", (info & PICINFO_FRAME), info); + if (index >= DECODE_BUFFER_NUM_MAX) { + + debug_print(DECODE_ID(hw), PRINT_FLAG_ERROR, + "invalid buffer index,index=%d\n", + index); + hw->dec_result = DEC_RESULT_ERROR; + vdec_schedule_work(&hw->work); + return IRQ_HANDLED; + } + + hw->dec_result = DEC_RESULT_DONE; + + /*debug_print(DECODE_ID(hw), PRINT_FLAG_TIMEINFO, + "ammvdec_mpeg12: error = 0x%x, offset = 0x%x\n", + info & PICINFO_ERROR, offset);*/ + + if (((info & PICINFO_TYPE_MASK) == PICINFO_TYPE_I)) { + if (hw->chunk) { + hw->pts_valid[index] = hw->chunk->pts_valid; + hw->pts[index] = hw->chunk->pts; + hw->pts64[index] = hw->chunk->pts64; + debug_print(DECODE_ID(hw), PRINT_FLAG_TIMEINFO, + "!!!cpts=%d,pts64=%lld,size=%d,offset=%d\n", + hw->pts[index], hw->pts64[index], + hw->chunk->size, hw->chunk->offset); + } else { + if (pts_lookup_offset_us64(PTS_TYPE_VIDEO, + offset, &pts, &frame_size, + 0, &pts_us64) == 0) { + hw->pts_valid[index] = true; + hw->pts[index] = pts; + hw->pts64[index] = pts_us64; + } else { + hw->pts_valid[index] = false; + } + } + } else { + hw->pts_valid[index] = false; + } + /*if (frame_prog == 0) */ + { + hw->frame_prog = info & PICINFO_PROG; + if ((seqinfo & SEQINFO_EXT_AVAILABLE) + && (!(seqinfo & SEQINFO_PROG))) + hw->frame_prog = 0; + } + if ((hw->dec_control & + DEC_CONTROL_FLAG_FORCE_2500_720_576_INTERLACE) && + (hw->frame_width == 720) && + (hw->frame_height == 576) && + (hw->frame_dur == 3840)) { + hw->frame_prog = 0; + } else if ((hw->dec_control + & DEC_CONTROL_FLAG_FORCE_3000_704_480_INTERLACE) && + (hw->frame_width == 704) && + (hw->frame_height == 480) && + (hw->frame_dur == 3200)) { + hw->frame_prog = 0; + } else if ((hw->dec_control + & DEC_CONTROL_FLAG_FORCE_2500_704_576_INTERLACE) && + (hw->frame_width == 704) && + (hw->frame_height == 576) && + (hw->frame_dur == 3840)) { + hw->frame_prog = 0; + } else if ((hw->dec_control + & DEC_CONTROL_FLAG_FORCE_2500_544_576_INTERLACE) && + (hw->frame_width == 544) && + (hw->frame_height == 576) && + (hw->frame_dur == 3840)) { + hw->frame_prog = 0; + } else if ((hw->dec_control + & DEC_CONTROL_FLAG_FORCE_2500_480_576_INTERLACE) && + (hw->frame_width == 480) && + (hw->frame_height == 576) && + (hw->frame_dur == 3840)) { + hw->frame_prog = 0; + } else if (hw->dec_control + & DEC_CONTROL_FLAG_FORCE_SEQ_INTERLACE) { + hw->frame_prog = 0; + } + + hw->buffer_info[index] = info; + + debug_print(DECODE_ID(hw), PRINT_FLAG_DEC_DETAIL, + "ammvdec_mpeg12: decoded buffer %d, frame_type %c\n", + index, GET_SLICE_TYPE(info)); + + /* Buffer management + todo: add sequence-end flush */ + if (((info & PICINFO_TYPE_MASK) == PICINFO_TYPE_I) || + ((info & PICINFO_TYPE_MASK) == PICINFO_TYPE_P)) { + hw->vfbuf_use[index]++; + if (hw->refs[1] == -1) { + hw->refs[1] = index; + index = DECODE_BUFFER_NUM_MAX; + } else if (hw->refs[0] == -1) { + hw->refs[0] = hw->refs[1]; + hw->refs[1] = index; + index = hw->refs[0]; + } else { + hw->vfbuf_use[hw->refs[0]]--; + hw->refs[0] = hw->refs[1]; + hw->refs[1] = index; + index = hw->refs[0]; + } + } else { + /* if this is a B frame, then drop + (depending on if there are two reference frames) + or display immediately*/ + if (hw->refs[0] == -1) + index = DECODE_BUFFER_NUM_MAX; + + } + + vmpeg12_save_hw_context(hw); + + if (index >= DECODE_BUFFER_NUM_MAX) { + debug_print(DECODE_ID(hw), 0, + "invalid buffer index,index=%d\n", index); + hw->dec_result = DEC_RESULT_ERROR; + vdec_schedule_work(&hw->work); + return IRQ_HANDLED; + } + + info = hw->buffer_info[index]; + pts_valid = hw->pts_valid[index]; + pts = hw->pts[index]; + pts_us64 = hw->pts64[index]; + + user_data_ready_notify(hw, pts, pts_valid); + + if ((hw->first_i_frame_ready == 0) && + ((info & PICINFO_TYPE_MASK) == PICINFO_TYPE_I) && + ((info & PICINFO_ERROR) == 0)) + hw->first_i_frame_ready = 1; + debug_print(DECODE_ID(hw), PRINT_FLAG_RUN_FLOW, + "ammvdec_mpeg12: display buffer %d, frame_type %c\n", + index, GET_SLICE_TYPE(info)); + if (hw->frame_prog & PICINFO_PROG) { + + seqinfo = READ_VREG(MREG_SEQ_INFO); + + if (kfifo_get(&hw->newframe_q, &vf) == 0) { + debug_print(DECODE_ID(hw), PRINT_FLAG_ERROR, + "fatal error, no available buffer slot."); + hw->dec_result = DEC_RESULT_ERROR; + vdec_schedule_work(&hw->work); + + return IRQ_HANDLED; + } + + vf->index = index; + set_frame_info(hw, vf); + vf->signal_type = hw->reg_signal_type; + +#ifdef NV21 + vf->type = + VIDTYPE_PROGRESSIVE | VIDTYPE_VIU_FIELD | + VIDTYPE_VIU_NV21; +#else + vf->type = VIDTYPE_PROGRESSIVE | VIDTYPE_VIU_FIELD; +#endif + if ((hw->seqinfo & SEQINFO_EXT_AVAILABLE) + && (hw->seqinfo & SEQINFO_PROG)) { + if (info & PICINFO_RPT_FIRST) { + if (info & PICINFO_TOP_FIRST) { + vf->duration = + vf->duration * 3; + /* repeat three times */ + } else { + vf->duration = + vf->duration * 2; + /* repeat two times */ + } + } + vf->duration_pulldown = 0; + /* no pull down */ + + } else { + vf->duration_pulldown = + (info & PICINFO_RPT_FIRST) ? + vf->duration >> 1 : 0; + } + + vf->duration += vf->duration_pulldown; + + vf->orientation = 0; + vf->pts = (pts_valid) ? pts : 0; + vf->pts_us64 = (pts_valid) ? pts_us64 : 0; + vf->type_original = vf->type; + hw->vfbuf_use[index]++; + + if ((error_skip(hw, info, vf)) || + ((hw->first_i_frame_ready == 0) + && ((PICINFO_TYPE_MASK & info) != + PICINFO_TYPE_I))) { + hw->drop_frame_count++; + hw->vfbuf_use[index]--; + kfifo_put(&hw->newframe_q, + (const struct vframe_s *)vf); + + } else { + debug_print(DECODE_ID(hw), PRINT_FLAG_TIMEINFO, + "cpts=%d,pts64=%lld\n", + vf->pts, vf->pts_us64); + decoder_do_frame_check(hw_to_vdec(hw), vf); + kfifo_put(&hw->display_q, + (const struct vframe_s *)vf); + hw->frame_num++; + vdec->vdec_fps_detec(vdec->id); + vf_notify_receiver(vdec->vf_provider_name, + VFRAME_EVENT_PROVIDER_VFRAME_READY, + NULL); + } + } +/*interlace temp*/ + else { + int first_field_type = (info & PICINFO_TOP_FIRST) ? + VIDTYPE_INTERLACE_TOP : + VIDTYPE_INTERLACE_BOTTOM; + +#ifdef INTERLACE_SEQ_ALWAYS + /* once an interlaced sequence exist, + always force interlaced type */ + /* to make DI easy. */ + hw->dec_control |= DEC_CONTROL_FLAG_FORCE_SEQ_INTERLACE; +#endif + + hw->frame_rpt_state = FRAME_REPEAT_NONE; + + if (kfifo_get(&hw->newframe_q, &vf) == 0) { + debug_print(DECODE_ID(hw), PRINT_FLAG_ERROR, + "fatal error, no available buffer slot."); + vdec_schedule_work(&hw->work); + return IRQ_HANDLED; + } + + hw->vfbuf_use[index] += 2; + vf->signal_type = hw->reg_signal_type; + vf->index = index; + set_frame_info(hw, vf); + vf->type = + (first_field_type == VIDTYPE_INTERLACE_TOP) ? + VIDTYPE_INTERLACE_TOP : + VIDTYPE_INTERLACE_BOTTOM; +#ifdef NV21 + vf->type |= VIDTYPE_VIU_NV21; +#endif + if (info & PICINFO_RPT_FIRST) + vf->duration /= 3; + else + vf->duration >>= 1; + vf->duration_pulldown = (info & PICINFO_RPT_FIRST) ? + vf->duration >> 1 : 0; + vf->duration += vf->duration_pulldown; + vf->orientation = 0; + vf->pts = (pts_valid) ? pts : 0; + vf->pts_us64 = (pts_valid) ? pts_us64 : 0; + + if ((error_skip(hw, info, vf)) || + ((hw->first_i_frame_ready == 0) + && ((PICINFO_TYPE_MASK & info) != + PICINFO_TYPE_I))) { + hw->vfbuf_use[index]--; + hw->drop_frame_count++; + kfifo_put(&hw->newframe_q, + (const struct vframe_s *)vf); + } else { + debug_print(DECODE_ID(hw), PRINT_FLAG_TIMEINFO, + "cpts0=%d,pts64=%lld,dur=%d, index %d , use %d\n", + vf->pts, vf->pts_us64, vf->duration, + vf->index, hw->vfbuf_use[index]); + decoder_do_frame_check(hw_to_vdec(hw), vf); + kfifo_put(&hw->display_q, + (const struct vframe_s *)vf); + hw->frame_num++; + vdec->vdec_fps_detec(vdec->id); + vf_notify_receiver(vdec->vf_provider_name, + VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); + } + + if (kfifo_get(&hw->newframe_q, &vf) == 0) { + debug_print(DECODE_ID(hw), PRINT_FLAG_ERROR, + "ammvdec_mpeg12: fatal error, no available buffer slot."); + + hw->vfbuf_use[index]--; + + vdec_schedule_work(&hw->work); + + return IRQ_HANDLED; + } + vf->signal_type = hw->reg_signal_type; + vf->index = index; + set_frame_info(hw, vf); + vf->type = (first_field_type == + VIDTYPE_INTERLACE_TOP) ? + VIDTYPE_INTERLACE_BOTTOM : + VIDTYPE_INTERLACE_TOP; +#ifdef NV21 + vf->type |= VIDTYPE_VIU_NV21; +#endif + if (info & PICINFO_RPT_FIRST) + vf->duration /= 3; + else + vf->duration >>= 1; + vf->duration_pulldown = (info & PICINFO_RPT_FIRST) ? + vf->duration >> 1 : 0; + vf->duration += vf->duration_pulldown; + vf->orientation = 0; + vf->pts = 0; + vf->pts_us64 = 0; + vf->type_original = vf->type; + + if ((error_skip(hw, info, vf)) || + ((hw->first_i_frame_ready == 0) + && ((PICINFO_TYPE_MASK & info) != + PICINFO_TYPE_I))) { + hw->drop_frame_count++; + hw->vfbuf_use[index]--; + + kfifo_put(&hw->newframe_q, + (const struct vframe_s *)vf); + } else { + debug_print(DECODE_ID(hw), PRINT_FLAG_TIMEINFO, + "cpts1=%d,pts64=%lld,dur=%d index %d, used %d\n", + vf->pts, vf->pts_us64, vf->duration, vf->index, + hw->vfbuf_use[index]); + kfifo_put(&hw->display_q, + (const struct vframe_s *)vf); + hw->frame_num++; + vdec->vdec_fps_detec(vdec->id); + vf_notify_receiver(vdec->vf_provider_name, + VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); + } + + if (info & PICINFO_RPT_FIRST) { + if (kfifo_get(&hw->newframe_q, &vf) == 0) { + debug_print(DECODE_ID(hw), + PRINT_FLAG_ERROR, + "error, no available buffer slot."); + return IRQ_HANDLED; + } + hw->vfbuf_use[index]++; + vf->index = index; + set_frame_info(hw, vf); + vf->type = (first_field_type == + VIDTYPE_INTERLACE_TOP) ? + VIDTYPE_INTERLACE_TOP : + VIDTYPE_INTERLACE_BOTTOM; +#ifdef NV21 + vf->type |= VIDTYPE_VIU_NV21; +#endif + vf->duration /= 3; + vf->duration_pulldown = + (info & PICINFO_RPT_FIRST) ? + vf->duration >> 1 : 0; + vf->duration += vf->duration_pulldown; + vf->orientation = 0; + + vf->pts = 0; + vf->pts_us64 = 0; + if ((error_skip(hw, info, vf)) || + ((hw->first_i_frame_ready == 0) + && ((PICINFO_TYPE_MASK & info) + != PICINFO_TYPE_I))) { + hw->vfbuf_use[index]--; + hw->drop_frame_count++; + kfifo_put(&hw->newframe_q, + (const struct vframe_s *)vf); + } else { + hw->frame_num++; + debug_print(DECODE_ID(hw), + PRINT_FLAG_TIMEINFO, + "cpts2=%d,pts64=%lld,dur=%d index %d, used %d\n", + vf->pts, vf->pts_us64, vf->duration, + vf->index, hw->vfbuf_use[index]); + kfifo_put(&hw->display_q, + (const struct vframe_s *)vf); + vdec->vdec_fps_detec(vdec->id); + vf_notify_receiver( + vdec->vf_provider_name, + VFRAME_EVENT_PROVIDER_VFRAME_READY, + NULL); + } + } + } + vdec_schedule_work(&hw->work); + + debug_print(DECODE_ID(hw), PRINT_FRAME_NUM, + "frame_num=%d\n", hw->frame_num); + if (hw->frame_num == 1) + debug_print(DECODE_ID(hw), PRINT_FRAME_NUM, + "frame_num==1\n"); + if (hw->frame_num == 1000) + debug_print(DECODE_ID(hw), PRINT_FRAME_NUM, + "frame_num==1000\n"); + } + + return IRQ_HANDLED; +} +static irqreturn_t vmpeg12_isr(struct vdec_s *vdec, int irq) +{ + u32 info, offset; + struct vdec_mpeg12_hw_s *hw = + (struct vdec_mpeg12_hw_s *)(vdec->private); + if (hw->eos) + return IRQ_HANDLED; + info = READ_VREG(MREG_PIC_INFO); + offset = READ_VREG(MREG_FRAME_OFFSET); + + vdec_count_info(&gvs, info & PICINFO_ERROR, offset); + + WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1); + + return IRQ_WAKE_THREAD; +} + +static void vmpeg12_notify_work(struct work_struct *work) +{ + struct vdec_mpeg12_hw_s *hw = container_of(work, + struct vdec_mpeg12_hw_s, notify_work); + struct vdec_s *vdec = hw_to_vdec(hw); + + if (vdec->fr_hint_state == VDEC_NEED_HINT) { + vf_notify_receiver(vdec->vf_provider_name, + VFRAME_EVENT_PROVIDER_FR_HINT, + (void *)((unsigned long)hw->frame_dur)); + vdec->fr_hint_state = VDEC_HINTED; + } +} + +static void wait_vmmpeg12_search_done(struct vdec_mpeg12_hw_s *hw) +{ + u32 vld_rp = READ_VREG(VLD_MEM_VIFIFO_RP); + int count = 0; + + do { + usleep_range(100, 500); + if (vld_rp == READ_VREG(VLD_MEM_VIFIFO_RP)) + break; + if (count > 1000) { + debug_print(DECODE_ID(hw), 0, + "%s, count %d vld_rp 0x%x VLD_MEM_VIFIFO_RP 0x%x\n", + __func__, count, vld_rp, READ_VREG(VLD_MEM_VIFIFO_RP)); + break; + } else + vld_rp = READ_VREG(VLD_MEM_VIFIFO_RP); + count++; + } while (1); +} + +static void vmpeg12_work(struct work_struct *work) +{ + struct vdec_mpeg12_hw_s *hw = + container_of(work, struct vdec_mpeg12_hw_s, work); + struct vdec_s *vdec = hw_to_vdec(hw); + if (hw->dec_result != DEC_RESULT_DONE) + debug_print(DECODE_ID(hw), PRINT_FLAG_RUN_FLOW, + "ammvdec_mpeg12: vmpeg_work,result=%d,status=%d\n", + hw->dec_result, hw_to_vdec(hw)->next_status); + + if (hw->dec_result == DEC_RESULT_DONE) { + if (!hw->ctx_valid) + hw->ctx_valid = 1; + vdec_vframe_dirty(hw_to_vdec(hw), hw->chunk); + hw->chunk = NULL; + } else if (hw->dec_result == DEC_RESULT_AGAIN + && (hw_to_vdec(hw)->next_status != + VDEC_STATUS_DISCONNECTED)) { + /* + stream base: stream buf empty or timeout + frame base: vdec_prepare_input fail + */ + if (!vdec_has_more_input(hw_to_vdec(hw))) { + hw->dec_result = DEC_RESULT_EOS; + vdec_schedule_work(&hw->work); + return; + } +#ifdef AGAIN_HAS_THRESHOLD + hw->next_again_flag = 1; +#endif + } else if (hw->dec_result == DEC_RESULT_GET_DATA + && (hw_to_vdec(hw)->next_status != + VDEC_STATUS_DISCONNECTED)) { + if (!vdec_has_more_input(hw_to_vdec(hw))) { + hw->dec_result = DEC_RESULT_EOS; + vdec_schedule_work(&hw->work); + return; + } + debug_print(DECODE_ID(hw), PRINT_FLAG_VLD_DETAIL, + "%s DEC_RESULT_GET_DATA %x %x %x\n", + __func__, + READ_VREG(VLD_MEM_VIFIFO_LEVEL), + READ_VREG(VLD_MEM_VIFIFO_WP), + READ_VREG(VLD_MEM_VIFIFO_RP)); + vdec_vframe_dirty(hw_to_vdec(hw), hw->chunk); + hw->chunk = NULL; + vdec_clean_input(hw_to_vdec(hw)); + return; + } else if (hw->dec_result == DEC_RESULT_FORCE_EXIT) { + debug_print(DECODE_ID(hw), PRINT_FLAG_ERROR, + "%s: force exit\n", __func__); + if (hw->stat & STAT_ISR_REG) { + amvdec_stop(); + /*disable mbox interrupt */ + WRITE_VREG(ASSIST_MBOX1_MASK, 0); + vdec_free_irq(VDEC_IRQ_1, (void *)hw); + hw->stat &= ~STAT_ISR_REG; + } + } else if (hw->dec_result == DEC_RESULT_EOS) { + pr_info("%s: end of stream\n", __func__); + if (hw->stat & STAT_VDEC_RUN) { + amvdec_stop(); + hw->stat &= ~STAT_VDEC_RUN; + } + hw->eos = 1; + vdec_vframe_dirty(hw_to_vdec(hw), hw->chunk); + hw->chunk = NULL; + vdec_clean_input(hw_to_vdec(hw)); + } + if (hw->stat & STAT_VDEC_RUN) { + amvdec_stop(); + hw->stat &= ~STAT_VDEC_RUN; + } + wait_vmmpeg12_search_done(hw); + if (vdec->parallel_dec == 1) + vdec_core_finish_run(hw_to_vdec(hw), CORE_MASK_VDEC_1); + else + vdec_core_finish_run(hw_to_vdec(hw), CORE_MASK_VDEC_1 | CORE_MASK_HEVC); + del_timer_sync(&hw->check_timer); + hw->stat &= ~STAT_TIMER_ARM; + + if (hw->vdec_cb) { + hw->vdec_cb(hw_to_vdec(hw), hw->vdec_cb_arg); + debug_print(DECODE_ID(hw), 0x80000, + "%s:\n", __func__); + } +} + +static struct vframe_s *vmpeg_vf_peek(void *op_arg) +{ + struct vframe_s *vf; + struct vdec_s *vdec = op_arg; + struct vdec_mpeg12_hw_s *hw = + (struct vdec_mpeg12_hw_s *)vdec->private; + hw->peek_num++; + if (kfifo_peek(&hw->display_q, &vf)) + return vf; + + return NULL; +} + +static struct vframe_s *vmpeg_vf_get(void *op_arg) +{ + struct vframe_s *vf; + struct vdec_s *vdec = op_arg; + struct vdec_mpeg12_hw_s *hw = + (struct vdec_mpeg12_hw_s *)vdec->private; + + hw->get_num++; + if (kfifo_get(&hw->display_q, &vf)) + return vf; + + return NULL; +} + +static void vmpeg_vf_put(struct vframe_s *vf, void *op_arg) +{ + struct vdec_s *vdec = op_arg; + struct vdec_mpeg12_hw_s *hw = + (struct vdec_mpeg12_hw_s *)vdec->private; + + hw->vfbuf_use[vf->index]--; + hw->put_num++; + kfifo_put(&hw->newframe_q, (const struct vframe_s *)vf); +} + +static int vmpeg_event_cb(int type, void *data, void *private_data) +{ + return 0; +} + +static int vmpeg_vf_states(struct vframe_states *states, void *op_arg) +{ + unsigned long flags; + struct vdec_s *vdec = op_arg; + struct vdec_mpeg12_hw_s *hw = + (struct vdec_mpeg12_hw_s *)vdec->private; + + spin_lock_irqsave(&hw->lock, flags); + + states->vf_pool_size = VF_POOL_SIZE; + states->buf_free_num = kfifo_len(&hw->newframe_q); + states->buf_avail_num = kfifo_len(&hw->display_q); + states->buf_recycle_num = 0; + + spin_unlock_irqrestore(&hw->lock, flags); + return 0; +} +static int vmmpeg12_dec_status(struct vdec_s *vdec, struct vdec_info *vstatus) +{ + struct vdec_mpeg12_hw_s *hw = + (struct vdec_mpeg12_hw_s *)vdec->private; + + if (!hw) + return -1; + + vstatus->frame_width = hw->frame_width; + vstatus->frame_height = hw->frame_height; + if (hw->frame_dur != 0) + vstatus->frame_rate = 96000 / hw->frame_dur; + else + vstatus->frame_rate = -1; + vstatus->error_count = READ_VREG(AV_SCRATCH_C); + vstatus->status = hw->stat; + vstatus->bit_rate = gvs.bit_rate; + vstatus->frame_dur = hw->frame_dur; + vstatus->frame_data = gvs.frame_data; + vstatus->total_data = gvs.total_data; + vstatus->frame_count = gvs.frame_count; + vstatus->error_frame_count = gvs.error_frame_count; + vstatus->drop_frame_count = hw->drop_frame_count; + vstatus->total_data = gvs.total_data; + vstatus->samp_cnt = gvs.samp_cnt; + vstatus->offset = gvs.offset; + vstatus->ratio_control = hw->ratio_control; + snprintf(vstatus->vdec_name, sizeof(vstatus->vdec_name), + "%s", DRIVER_NAME); + + return 0; +} + + + +/****************************************/ +static void vmpeg12_canvas_init(struct vdec_mpeg12_hw_s *hw) +{ + int i, ret; + u32 canvas_width, canvas_height; + u32 decbuf_size, decbuf_y_size, decbuf_uv_size; + unsigned long decbuf_start; + /*u32 disp_addr = 0xffffffff;*/ + struct vdec_s *vdec = hw_to_vdec(hw); + + if (buf_size <= 0x00400000) { + /* SD only */ + canvas_width = 768; + canvas_height = 576; + decbuf_y_size = 0x80000; + decbuf_uv_size = 0x20000; + decbuf_size = 0x100000; + } else { + /* HD & SD */ + canvas_width = 1920; + canvas_height = 1088; + decbuf_y_size = 0x200000; + decbuf_uv_size = 0x80000; + decbuf_size = 0x300000; + } + + for (i = 0; i < MAX_BMMU_BUFFER_NUM; i++) { + + unsigned canvas; + if (i == (MAX_BMMU_BUFFER_NUM - 1)) /* SWAP&CCBUF&MATIRX&MV */ + decbuf_size = WORKSPACE_SIZE; + ret = decoder_bmmu_box_alloc_buf_phy(hw->mm_blk_handle, i, + decbuf_size, DRIVER_NAME, &decbuf_start); + if (ret < 0) { + pr_err("mmu alloc failed! size 0x%d idx %d\n", + decbuf_size, i); + return; + } + + if (i == (MAX_BMMU_BUFFER_NUM - 1)) { + if (hw->ccbuf_phyAddress_is_remaped_nocache) + codec_mm_unmap_phyaddr(hw->ccbuf_phyAddress_virt); + hw->ccbuf_phyAddress_virt = NULL; + hw->ccbuf_phyAddress = 0; + hw->ccbuf_phyAddress_is_remaped_nocache = 0; + + hw->buf_start = decbuf_start; + hw->ccbuf_phyAddress = hw->buf_start + CTX_CCBUF_OFFSET; + hw->ccbuf_phyAddress_virt + = codec_mm_phys_to_virt( + hw->ccbuf_phyAddress); + if (!hw->ccbuf_phyAddress_virt) { + hw->ccbuf_phyAddress_virt + = codec_mm_vmap( + hw->ccbuf_phyAddress, + CCBUF_SIZE); + hw->ccbuf_phyAddress_is_remaped_nocache = 1; + } + + WRITE_VREG(MREG_CO_MV_START, hw->buf_start); + } else { + if (vdec->parallel_dec == 1) { + unsigned tmp; + if (canvas_u(hw->canvas_spec[i]) == 0xff) { + tmp = + vdec->get_canvas_ex(CORE_MASK_VDEC_1, vdec->id); + hw->canvas_spec[i] &= ~(0xffff << 8); + hw->canvas_spec[i] |= tmp << 8; + hw->canvas_spec[i] |= tmp << 16; + } + if (canvas_y(hw->canvas_spec[i]) == 0xff) { + tmp = + vdec->get_canvas_ex(CORE_MASK_VDEC_1, vdec->id); + hw->canvas_spec[i] &= ~0xff; + hw->canvas_spec[i] |= tmp; + } + canvas = hw->canvas_spec[i]; + } else { + canvas = vdec->get_canvas(i, 2); + hw->canvas_spec[i] = canvas; + } + + hw->canvas_config[i][0].phy_addr = + decbuf_start; + hw->canvas_config[i][0].width = + canvas_width; + hw->canvas_config[i][0].height = + canvas_height; + hw->canvas_config[i][0].block_mode = + hw->canvas_mode; + hw->canvas_config[i][0].endian = + (hw->canvas_mode == CANVAS_BLKMODE_LINEAR)?7:0; + + canvas_config_config(canvas_y(canvas), + &hw->canvas_config[i][0]); + + hw->canvas_config[i][1].phy_addr = + decbuf_start + decbuf_y_size; + hw->canvas_config[i][1].width = + canvas_width; + hw->canvas_config[i][1].height = + canvas_height / 2; + hw->canvas_config[i][1].block_mode = + hw->canvas_mode; + hw->canvas_config[i][0].endian = + (hw->canvas_mode == CANVAS_BLKMODE_LINEAR)?7:0; + + canvas_config_config(canvas_u(canvas), + &hw->canvas_config[i][1]); + } + } + return; +} + +static void vmpeg2_dump_state(struct vdec_s *vdec) +{ + struct vdec_mpeg12_hw_s *hw = + (struct vdec_mpeg12_hw_s *)(vdec->private); + u32 i; + debug_print(DECODE_ID(hw), 0, + "====== %s\n", __func__); + debug_print(DECODE_ID(hw), 0, + "width/height (%d/%d),i_first %d\n", + hw->frame_width, + hw->frame_height, + hw->first_i_frame_ready + ); + debug_print(DECODE_ID(hw), 0, + "is_framebase(%d), eos %d, state 0x%x, dec_result 0x%x dec_frm %d put_frm %d run %d not_run_ready %d,input_empty %d\n", + input_frame_based(vdec), + hw->eos, + hw->stat, + hw->dec_result, + hw->frame_num, + hw->put_num, + hw->run_count, + hw->not_run_ready, + hw->input_empty + ); + + for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) { + debug_print(DECODE_ID(hw), 0, + "index %d, used %d\n", i, hw->vfbuf_use[i]); + } + + if (vf_get_receiver(vdec->vf_provider_name)) { + enum receviver_start_e state = + vf_notify_receiver(vdec->vf_provider_name, + VFRAME_EVENT_PROVIDER_QUREY_STATE, + NULL); + debug_print(DECODE_ID(hw), 0, + "\nreceiver(%s) state %d\n", + vdec->vf_provider_name, + state); + } + debug_print(DECODE_ID(hw), 0, + "%s, newq(%d/%d), dispq(%d/%d) vf peek/get/put (%d/%d/%d),drop=%d, buffer_not_ready %d\n", + __func__, + kfifo_len(&hw->newframe_q), + VF_POOL_SIZE, + kfifo_len(&hw->display_q), + VF_POOL_SIZE, + hw->peek_num, + hw->get_num, + hw->put_num, + hw->drop_frame_count, + hw->buffer_not_ready + ); + debug_print(DECODE_ID(hw), 0, + "VIFF_BIT_CNT=0x%x\n", + READ_VREG(VIFF_BIT_CNT)); + debug_print(DECODE_ID(hw), 0, + "VLD_MEM_VIFIFO_LEVEL=0x%x\n", + READ_VREG(VLD_MEM_VIFIFO_LEVEL)); + debug_print(DECODE_ID(hw), 0, + "VLD_MEM_VIFIFO_WP=0x%x\n", + READ_VREG(VLD_MEM_VIFIFO_WP)); + debug_print(DECODE_ID(hw), 0, + "VLD_MEM_VIFIFO_RP=0x%x\n", + READ_VREG(VLD_MEM_VIFIFO_RP)); + debug_print(DECODE_ID(hw), 0, + "PARSER_VIDEO_RP=0x%x\n", + READ_PARSER_REG(PARSER_VIDEO_RP)); + debug_print(DECODE_ID(hw), 0, + "PARSER_VIDEO_WP=0x%x\n", + READ_PARSER_REG(PARSER_VIDEO_WP)); + if (input_frame_based(vdec) && + debug_enable & PRINT_FRAMEBASE_DATA + ) { + int jj; + if (hw->chunk && hw->chunk->block && + hw->chunk->size > 0) { + u8 *data = NULL; + + if (!hw->chunk->block->is_mapped) + data = codec_mm_vmap(hw->chunk->block->start + + hw->chunk->offset, hw->chunk->size); + else + data = ((u8 *)hw->chunk->block->start_virt) + + hw->chunk->offset; + + debug_print(DECODE_ID(hw), 0, + "frame data size 0x%x\n", + hw->chunk->size); + for (jj = 0; jj < hw->chunk->size; jj++) { + if ((jj & 0xf) == 0) + debug_print(DECODE_ID(hw), + PRINT_FRAMEBASE_DATA, + "%06x:", jj); + debug_print(DECODE_ID(hw), + PRINT_FRAMEBASE_DATA, + "%02x ", data[jj]); + if (((jj + 1) & 0xf) == 0) + debug_print(DECODE_ID(hw), + PRINT_FRAMEBASE_DATA, + "\n"); + } + + if (!hw->chunk->block->is_mapped) + codec_mm_unmap_phyaddr(data); + } + } +} + +static void reset_process_time(struct vdec_mpeg12_hw_s *hw) +{ + if (hw->start_process_time) { + unsigned process_time = + 1000 * (jiffies - hw->start_process_time) / HZ; + hw->start_process_time = 0; + if (process_time > max_process_time[DECODE_ID(hw)]) + max_process_time[DECODE_ID(hw)] = process_time; + } +} +static void start_process_time(struct vdec_mpeg12_hw_s *hw) +{ + hw->decode_timeout_count = 10; + hw->start_process_time = jiffies; +} +static void timeout_process(struct vdec_mpeg12_hw_s *hw) +{ + struct vdec_s *vdec = hw_to_vdec(hw); + + reset_process_time(hw); + amvdec_stop(); + debug_print(DECODE_ID(hw), PRINT_FLAG_ERROR, + "%s decoder timeout, status=%d, level=%d\n", + __func__, vdec->status, READ_VREG(VLD_MEM_VIFIFO_LEVEL)); + hw->dec_result = DEC_RESULT_DONE; + hw->first_i_frame_ready = 0; + vdec_schedule_work(&hw->work); +} + +static void check_timer_func(unsigned long arg) +{ + struct vdec_mpeg12_hw_s *hw = (struct vdec_mpeg12_hw_s *)arg; + struct vdec_s *vdec = hw_to_vdec(hw); + unsigned int timeout_val = decode_timeout_val; + + if (radr != 0) { + if (rval != 0) { + WRITE_VREG(radr, rval); + pr_info("WRITE_VREG(%x,%x)\n", radr, rval); + } else + pr_info("READ_VREG(%x)=%x\n", radr, READ_VREG(radr)); + rval = 0; + radr = 0; + } + + if (debug_enable == 0 && + (input_frame_based(vdec) || + (READ_VREG(VLD_MEM_VIFIFO_LEVEL) > 0x100)) && + (timeout_val > 0) && + (hw->start_process_time > 0) && + ((1000 * (jiffies - hw->start_process_time) / HZ) + > timeout_val)) { + if (hw->last_vld_level == READ_VREG(VLD_MEM_VIFIFO_LEVEL)) { + if (hw->decode_timeout_count > 0) + hw->decode_timeout_count--; + if (hw->decode_timeout_count == 0) + timeout_process(hw); + } + hw->last_vld_level = READ_VREG(VLD_MEM_VIFIFO_LEVEL); + } + + if (vdec->next_status == VDEC_STATUS_DISCONNECTED) { + hw->dec_result = DEC_RESULT_FORCE_EXIT; + vdec_schedule_work(&hw->work); + pr_info("vdec requested to be disconnected\n"); + return; + } + + mod_timer(&hw->check_timer, jiffies + CHECK_INTERVAL); +} + +static int vmpeg12_hw_ctx_restore(struct vdec_mpeg12_hw_s *hw) +{ + u32 index; + index = find_buffer(hw); + if (index >= DECODE_BUFFER_NUM_MAX) + return -1; + vmpeg12_canvas_init(hw); + + /* prepare REF0 & REF1 + points to the past two IP buffers + prepare REC_CANVAS_ADDR and ANC2_CANVAS_ADDR + points to the output buffer*/ + WRITE_VREG(MREG_REF0, + (hw->refs[1] == -1) ? 0xffffffff : hw->canvas_spec[hw->refs[0]]); + WRITE_VREG(MREG_REF1, + (hw->refs[0] == -1) ? 0xffffffff : hw->canvas_spec[hw->refs[1]]); + WRITE_VREG(REC_CANVAS_ADDR, hw->canvas_spec[index]); + WRITE_VREG(ANC2_CANVAS_ADDR, hw->canvas_spec[index]); + + debug_print(DECODE_ID(hw), PRINT_FLAG_RESTORE, + "%s,ref0=0x%x, ref1=0x%x,rec=0x%x, ctx_valid=%d,index=%d\n", + __func__, + READ_VREG(MREG_REF0), + READ_VREG(MREG_REF1), + READ_VREG(REC_CANVAS_ADDR), + hw->ctx_valid, index); + + /* set to mpeg1 default */ + WRITE_VREG(MPEG1_2_REG, + (hw->ctx_valid) ? hw->reg_mpeg1_2_reg : 0); + /* disable PSCALE for hardware sharing */ + WRITE_VREG(PSCALE_CTRL, 0); + /* for Mpeg1 default value */ + WRITE_VREG(PIC_HEAD_INFO, + (hw->ctx_valid) ? hw->reg_pic_head_info : 0x380); + /* disable mpeg4 */ + WRITE_VREG(M4_CONTROL_REG, 0); + /* clear mailbox interrupt */ + WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1); + /* clear buffer IN/OUT registers */ + WRITE_VREG(MREG_BUFFEROUT, 0); + /* set reference width and height */ + if ((hw->frame_width != 0) && (hw->frame_height != 0)) + WRITE_VREG(MREG_CMD, + (hw->frame_width << 16) | hw->frame_height); + else + WRITE_VREG(MREG_CMD, 0); + + + debug_print(DECODE_ID(hw), PRINT_FLAG_RESTORE, + "0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x\n", + hw->frame_width, hw->frame_height, hw->seqinfo, + hw->reg_f_code_reg, hw->reg_slice_ver_pos_pic_type, + hw->reg_mb_info); + + WRITE_VREG(MREG_PIC_WIDTH, hw->reg_pic_width); + WRITE_VREG(MREG_PIC_HEIGHT, hw->reg_pic_height); + WRITE_VREG(MREG_SEQ_INFO, hw->seqinfo); + WRITE_VREG(F_CODE_REG, hw->reg_f_code_reg); + WRITE_VREG(SLICE_VER_POS_PIC_TYPE, + hw->reg_slice_ver_pos_pic_type); + WRITE_VREG(MB_INFO, hw->reg_mb_info); + WRITE_VREG(VCOP_CTRL_REG, hw->reg_vcop_ctrl_reg); + WRITE_VREG(AV_SCRATCH_H, hw->reg_signal_type); + + /* clear error count */ + WRITE_VREG(MREG_ERROR_COUNT, 0); + WRITE_VREG(MREG_FATAL_ERROR, 0); + /* clear wait buffer status */ + WRITE_VREG(MREG_WAIT_BUFFER, 0); +#ifdef NV21 + SET_VREG_MASK(MDEC_PIC_DC_CTRL, 1<<17); +#endif + if (hw->chunk) { + /*frame based input*/ + WRITE_VREG(MREG_INPUT, + (hw->chunk->offset & 7) | (1<<7) | (hw->ctx_valid<<6)); + } else { + /*stream based input*/ + WRITE_VREG(MREG_INPUT, (hw->ctx_valid<<6)); + } + return 0; +} + +static void vmpeg12_local_init(struct vdec_mpeg12_hw_s *hw) +{ + int i; + INIT_KFIFO(hw->display_q); + INIT_KFIFO(hw->newframe_q); + + for (i = 0; i < VF_POOL_SIZE; i++) { + const struct vframe_s *vf; + vf = &hw->vfpool[i]; + hw->vfpool[i].index = DECODE_BUFFER_NUM_MAX; + kfifo_put(&hw->newframe_q, (const struct vframe_s *)vf); + } + + for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) + hw->vfbuf_use[i] = 0; + + + if (hw->mm_blk_handle) { + decoder_bmmu_box_free(hw->mm_blk_handle); + hw->mm_blk_handle = NULL; + } + + hw->mm_blk_handle = decoder_bmmu_box_alloc_box( + DRIVER_NAME, + 0, + MAX_BMMU_BUFFER_NUM, + 4 + PAGE_SHIFT, + CODEC_MM_FLAGS_CMA_CLEAR | + CODEC_MM_FLAGS_FOR_VDECODER); + hw->eos = 0; + hw->frame_width = hw->frame_height = 0; + hw->frame_dur = hw->frame_prog = 0; + hw->frame_force_skip_flag = 0; + hw->wait_buffer_counter = 0; + hw->first_i_frame_ready = 0; + hw->dec_control &= DEC_CONTROL_INTERNAL_MASK; + hw->refs[0] = -1; + hw->refs[1] = -1; + hw->frame_num = 0; + hw->put_num = 0; + hw->run_count = 0; + hw->not_run_ready = 0; + hw->input_empty = 0; + hw->peek_num = 0; + hw->get_num = 0; + hw->drop_frame_count = 0; + hw->buffer_not_ready = 0; + hw->start_process_time = 0; + hw->error_frame_skip_level = error_frame_skip_level; + if (dec_control) + hw->dec_control = dec_control; +} + +static s32 vmpeg12_init(struct vdec_mpeg12_hw_s *hw) +{ + int size; + u32 fw_size = 16*0x1000; + struct firmware_s *fw; + + vmpeg12_local_init(hw); + + fw = vmalloc(sizeof(struct firmware_s) + fw_size); + if (IS_ERR_OR_NULL(fw)) + return -ENOMEM; + + pr_debug("get firmware ...\n"); + size = get_firmware_data(VIDEO_DEC_MPEG12_MULTI, fw->data); + if (size < 0) { + pr_err("get firmware fail.\n"); + vfree(fw); + return -1; + } + + fw->len = size; + hw->fw = fw; + + INIT_WORK(&hw->userdata_push_work, userdata_push_do_work); + INIT_WORK(&hw->work, vmpeg12_work); + INIT_WORK(&hw->notify_work, vmpeg12_notify_work); + + if (NULL == hw->user_data_buffer) { + hw->user_data_buffer = kmalloc(USER_DATA_SIZE, + GFP_KERNEL); + if (!hw->user_data_buffer) { + pr_info("%s: Can not allocate user_data_buffer\n", + __func__); + return -1; + } + } + + vmmpeg2_crate_userdata_manager(hw, + hw->user_data_buffer, + USER_DATA_SIZE); + + amvdec_enable(); + init_timer(&hw->check_timer); + hw->check_timer.data = (unsigned long)hw; + hw->check_timer.function = check_timer_func; + hw->check_timer.expires = jiffies + CHECK_INTERVAL; + + hw->stat |= STAT_TIMER_ARM; + hw->stat |= STAT_ISR_REG; + + hw->buf_start = 0; + hw->init_flag = 0; + WRITE_VREG(DECODE_STOP_POS, udebug_flag); + + return 0; +} + +static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask) +{ + int index; + + struct vdec_mpeg12_hw_s *hw = + (struct vdec_mpeg12_hw_s *)vdec->private; + if (hw->eos) + return 0; + if (vdec_stream_based(vdec) && (hw->init_flag == 0) + && pre_decode_buf_level != 0) { + u32 rp, wp, level; + + rp = READ_PARSER_REG(PARSER_VIDEO_RP); + wp = READ_PARSER_REG(PARSER_VIDEO_WP); + if (wp < rp) + level = vdec->input.size + wp - rp; + else + level = wp - rp; + + if (level < pre_decode_buf_level) { + hw->not_run_ready++; + return 0; + } + } + +#ifdef AGAIN_HAS_THRESHOLD + if (hw->next_again_flag&& + (!vdec_frame_based(vdec))) { + u32 parser_wr_ptr = + READ_PARSER_REG(PARSER_VIDEO_WP); + if (parser_wr_ptr >= hw->pre_parser_wr_ptr && + (parser_wr_ptr - hw->pre_parser_wr_ptr) < + again_threshold) { + int r = vdec_sync_input(vdec); + debug_print(DECODE_ID(hw), PRINT_FLAG_RUN_FLOW, + "%s buf level%x\n", + __func__, r); + return 0; + } + } +#endif + + index = find_buffer(hw); + if (index >= DECODE_BUFFER_NUM_MAX) { + hw->buffer_not_ready++; + return 0; + } + hw->not_run_ready = 0; + hw->buffer_not_ready = 0; + if (vdec->parallel_dec == 1) + return (unsigned long)(CORE_MASK_VDEC_1); + else + return (unsigned long)(CORE_MASK_VDEC_1 | CORE_MASK_HEVC); +} + +static unsigned char get_data_check_sum + (struct vdec_mpeg12_hw_s *hw, int size) +{ + int jj; + int sum = 0; + u8 *data = NULL; + + if (!hw->chunk->block->is_mapped) + data = codec_mm_vmap(hw->chunk->block->start + + hw->chunk->offset, size); + else + data = ((u8 *)hw->chunk->block->start_virt) + + hw->chunk->offset; + + for (jj = 0; jj < size; jj++) + sum += data[jj]; + + if (!hw->chunk->block->is_mapped) + codec_mm_unmap_phyaddr(data); + return sum; +} + +static void run(struct vdec_s *vdec, unsigned long mask, +void (*callback)(struct vdec_s *, void *), + void *arg) +{ + struct vdec_mpeg12_hw_s *hw = + (struct vdec_mpeg12_hw_s *)vdec->private; + int save_reg = READ_VREG(POWER_CTL_VLD); + int size, ret; + /* reset everything except DOS_TOP[1] and APB_CBUS[0]*/ + WRITE_VREG(DOS_SW_RESET0, 0xfffffff0); + WRITE_VREG(DOS_SW_RESET0, 0); + WRITE_VREG(POWER_CTL_VLD, save_reg); + hw->run_count++; + vdec_reset_core(vdec); + hw->vdec_cb_arg = arg; + hw->vdec_cb = callback; + +#ifdef AGAIN_HAS_THRESHOLD + hw->pre_parser_wr_ptr = + READ_PARSER_REG(PARSER_VIDEO_WP); + hw->next_again_flag = 0; +#endif + + size = vdec_prepare_input(vdec, &hw->chunk); + if (size < 0) { + hw->input_empty++; + hw->dec_result = DEC_RESULT_AGAIN; + vdec_schedule_work(&hw->work); + return; + } + if (input_frame_based(vdec)) { + u8 *data = NULL; + + if (!hw->chunk->block->is_mapped) + data = codec_mm_vmap(hw->chunk->block->start + + hw->chunk->offset, size); + else + data = ((u8 *)hw->chunk->block->start_virt) + + hw->chunk->offset; + + if (debug_enable & PRINT_FLAG_VDEC_STATUS + ) { + debug_print(DECODE_ID(hw), 0, + "%s: size 0x%x sum 0x%x %02x %02x %02x %02x %02x %02x .. %02x %02x %02x %02x\n", + __func__, size, get_data_check_sum(hw, size), + data[0], data[1], data[2], data[3], + data[4], data[5], data[size - 4], + data[size - 3], data[size - 2], + data[size - 1]); + } + if (debug_enable & PRINT_FRAMEBASE_DATA + ) { + int jj; + + for (jj = 0; jj < size; jj++) { + if ((jj & 0xf) == 0) + debug_print(DECODE_ID(hw), + PRINT_FRAMEBASE_DATA, + "%06x:", jj); + debug_print(DECODE_ID(hw), + PRINT_FRAMEBASE_DATA, + "%02x ", data[jj]); + if (((jj + 1) & 0xf) == 0) + debug_print(DECODE_ID(hw), + PRINT_FRAMEBASE_DATA, + "\n"); + } + } + + if (!hw->chunk->block->is_mapped) + codec_mm_unmap_phyaddr(data); + } else + debug_print(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS, + "%s: %x %x %x %x %x size 0x%x\n", + __func__, + READ_VREG(VLD_MEM_VIFIFO_LEVEL), + READ_VREG(VLD_MEM_VIFIFO_WP), + READ_VREG(VLD_MEM_VIFIFO_RP), + READ_PARSER_REG(PARSER_VIDEO_RP), + READ_PARSER_REG(PARSER_VIDEO_WP), + size); + + + hw->input_empty = 0; + debug_print(DECODE_ID(hw), PRINT_FLAG_RUN_FLOW, + "%s,%d, size=%d\n", __func__, __LINE__, size); + vdec_enable_input(vdec); + hw->init_flag = 1; + + if (hw->chunk) + debug_print(DECODE_ID(hw), PRINT_FLAG_RUN_FLOW, + "input chunk offset %d, size %d\n", + hw->chunk->offset, hw->chunk->size); + + hw->dec_result = DEC_RESULT_NONE; + if (vdec->mc_loaded) { + /*firmware have load before, + and not changes to another. + ignore reload. + */ + } else { + ret = amvdec_vdec_loadmc_buf_ex(VFORMAT_MPEG12, "mmpeg12", vdec, + hw->fw->data, hw->fw->len); + if (ret < 0) { + pr_err("[%d] %s: the %s fw loading failed, err: %x\n", vdec->id, + hw->fw->name, tee_enabled() ? "TEE" : "local", ret); + hw->dec_result = DEC_RESULT_FORCE_EXIT; + vdec_schedule_work(&hw->work); + return; + } + vdec->mc_loaded = 1; + vdec->mc_type = VFORMAT_MPEG12; + } + if (vmpeg12_hw_ctx_restore(hw) < 0) { + hw->dec_result = DEC_RESULT_ERROR; + debug_print(DECODE_ID(hw), PRINT_FLAG_ERROR, + "ammvdec_mpeg12: error HW context restore\n"); + vdec_schedule_work(&hw->work); + return; + } + /*wmb();*/ + hw->stat |= STAT_MC_LOAD; + hw->last_vld_level = 0; + start_process_time(hw); + amvdec_start(); + hw->stat |= STAT_VDEC_RUN; + mod_timer(&hw->check_timer, jiffies + CHECK_INTERVAL); +} + +static void reset(struct vdec_s *vdec) +{ + pr_info("ammvdec_mpeg12: reset.\n"); +} + +static int ammvdec_mpeg12_probe(struct platform_device *pdev) +{ + struct vdec_s *pdata = *(struct vdec_s **)pdev->dev.platform_data; + struct vdec_mpeg12_hw_s *hw = NULL; + + pr_info("ammvdec_mpeg12 probe start.\n"); + + if (pdata == NULL) { + pr_info("ammvdec_mpeg12 platform data undefined.\n"); + return -EFAULT; + } + + hw = vzalloc(sizeof(struct vdec_mpeg12_hw_s)); + if (hw == NULL) { + pr_info("\nammvdec_mpeg12 decoder driver alloc failed\n"); + return -ENOMEM; + } + + pdata->private = hw; + pdata->dec_status = vmmpeg12_dec_status; + pdata->run_ready = run_ready; + pdata->run = run; + pdata->reset = reset; + pdata->irq_handler = vmpeg12_isr; + pdata->threaded_irq_handler = vmpeg12_isr_thread_fn; + pdata->dump_state = vmpeg2_dump_state; + + pdata->user_data_read = vmmpeg2_user_data_read; + pdata->reset_userdata_fifo = vmmpeg2_reset_userdata_fifo; + pdata->wakeup_userdata_poll = vmmpeg2_wakeup_userdata_poll; + + if (pdata->use_vfm_path) { + snprintf(pdata->vf_provider_name, VDEC_PROVIDER_NAME_SIZE, + VFM_DEC_PROVIDER_NAME); + hw->frameinfo_enable = 1; + } + else + snprintf(pdata->vf_provider_name, VDEC_PROVIDER_NAME_SIZE, + PROVIDER_NAME ".%02x", pdev->id & 0xff); + if (pdata->parallel_dec == 1) { + int i; + for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) + hw->canvas_spec[i] = 0xffffff; + } + vf_provider_init(&pdata->vframe_provider, pdata->vf_provider_name, + &vf_provider_ops, pdata); + + platform_set_drvdata(pdev, pdata); + hw->canvas_mode = pdata->canvas_mode; + hw->platform_dev = pdev; + + if (pdata->sys_info) + hw->vmpeg12_amstream_dec_info = *pdata->sys_info; + + if (vmpeg12_init(hw) < 0) { + pr_info("ammvdec_mpeg12 init failed.\n"); + if (hw) { + vfree(hw); + hw = NULL; + } + pdata->dec_status = NULL; + return -ENODEV; + } + if (pdata->parallel_dec == 1) + vdec_core_request(pdata, CORE_MASK_VDEC_1); + else { + vdec_core_request(pdata, CORE_MASK_VDEC_1 | CORE_MASK_HEVC + | CORE_MASK_COMBINE); + } +#ifdef DUMP_USER_DATA + amvdec_mmpeg12_init_userdata_dump(hw); + reset_user_data_buf(hw); +#endif + + /*INIT_WORK(&userdata_push_work, userdata_push_do_work);*/ + return 0; +} + +static int ammvdec_mpeg12_remove(struct platform_device *pdev) + +{ + struct vdec_mpeg12_hw_s *hw = + (struct vdec_mpeg12_hw_s *) + (((struct vdec_s *)(platform_get_drvdata(pdev)))->private); + struct vdec_s *vdec = hw_to_vdec(hw); + int i; + + if (hw->stat & STAT_VDEC_RUN) { + amvdec_stop(); + hw->stat &= ~STAT_VDEC_RUN; + } + + if (hw->stat & STAT_ISR_REG) { + vdec_free_irq(VDEC_IRQ_1, (void *)hw); + hw->stat &= ~STAT_ISR_REG; + } + + if (hw->stat & STAT_TIMER_ARM) { + del_timer_sync(&hw->check_timer); + hw->stat &= ~STAT_TIMER_ARM; + } + cancel_work_sync(&hw->userdata_push_work); + cancel_work_sync(&hw->work); + cancel_work_sync(&hw->notify_work); + + if (hw->mm_blk_handle) { + decoder_bmmu_box_free(hw->mm_blk_handle); + hw->mm_blk_handle = NULL; + } + if (vdec->parallel_dec == 1) + vdec_core_release(hw_to_vdec(hw), CORE_MASK_VDEC_1); + else + vdec_core_release(hw_to_vdec(hw), CORE_MASK_VDEC_1 | CORE_MASK_HEVC); + vdec_set_status(hw_to_vdec(hw), VDEC_STATUS_DISCONNECTED); + + if (vdec->parallel_dec == 1) { + for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) { + vdec->free_canvas_ex(canvas_y(hw->canvas_spec[i]), vdec->id); + vdec->free_canvas_ex(canvas_u(hw->canvas_spec[i]), vdec->id); + } + } + + if (hw->ccbuf_phyAddress_is_remaped_nocache) + codec_mm_unmap_phyaddr(hw->ccbuf_phyAddress_virt); + hw->ccbuf_phyAddress_virt = NULL; + hw->ccbuf_phyAddress = 0; + hw->ccbuf_phyAddress_is_remaped_nocache = 0; + + if (hw->user_data_buffer != NULL) { + kfree(hw->user_data_buffer); + hw->user_data_buffer = NULL; + } + vmmpeg2_destroy_userdata_manager(hw); + +#ifdef DUMP_USER_DATA + amvdec_mmpeg12_uninit_userdata_dump(hw); +#endif + + if (hw->fw) { + vfree(hw->fw); + hw->fw = NULL; + } + if (hw) { + vfree(hw); + hw = NULL; + } + pr_info("ammvdec_mpeg12 removed.\n"); + memset(&gvs, 0x0, sizeof(gvs)); + + return 0; +} + +/****************************************/ + +static struct platform_driver ammvdec_mpeg12_driver = { + .probe = ammvdec_mpeg12_probe, + .remove = ammvdec_mpeg12_remove, +#ifdef CONFIG_PM + .suspend = amvdec_suspend, + .resume = amvdec_resume, +#endif + .driver = { + .name = DRIVER_NAME, + } +}; + +static struct codec_profile_t ammvdec_mpeg12_profile = { + .name = "mmpeg12", + .profile = "" +}; + +static struct mconfig mmpeg12_configs[] = { + MC_PU32("stat", &stat), + MC_PU32("radr", &radr), + MC_PU32("rval", &rval), + MC_PU32("dec_control", &dec_control), + MC_PU32("error_frame_skip_level", &error_frame_skip_level), + MC_PU32("decode_timeout_val", &decode_timeout_val), +}; +static struct mconfig_node mmpeg12_node; + +static int __init ammvdec_mpeg12_driver_init_module(void) +{ + pr_info("ammvdec_mpeg12 module init\n"); + + if (platform_driver_register(&ammvdec_mpeg12_driver)) { + pr_info("failed to register ammvdec_mpeg12 driver\n"); + return -ENODEV; + } + vcodec_profile_register(&ammvdec_mpeg12_profile); + INIT_REG_NODE_CONFIGS("media.decoder", &mmpeg12_node, + "mmpeg12", mmpeg12_configs, CONFIG_FOR_RW); + return 0; +} + +static void __exit ammvdec_mpeg12_driver_remove_module(void) +{ + pr_info("ammvdec_mpeg12 module exit.\n"); + platform_driver_unregister(&ammvdec_mpeg12_driver); +} + +/****************************************/ +module_param(dec_control, uint, 0664); +MODULE_PARM_DESC(dec_control, "\n ammvdec_mpeg12 decoder control\n"); +module_param(error_frame_skip_level, uint, 0664); +MODULE_PARM_DESC(error_frame_skip_level, + "\n ammvdec_mpeg12 error_frame_skip_level\n"); + +module_param(radr, uint, 0664); +MODULE_PARM_DESC(radr, "\nradr\n"); + +module_param(rval, uint, 0664); +MODULE_PARM_DESC(rval, "\nrval\n"); + +module_param(debug_enable, uint, 0664); +MODULE_PARM_DESC(debug_enable, + "\n ammvdec_mpeg12 debug enable\n"); +module_param(pre_decode_buf_level, int, 0664); +MODULE_PARM_DESC(pre_decode_buf_level, + "\n ammvdec_mpeg12 pre_decode_buf_level\n"); +module_param(decode_timeout_val, uint, 0664); +MODULE_PARM_DESC(decode_timeout_val, "\n ammvdec_mpeg12 decode_timeout_val\n"); + +module_param_array(max_process_time, uint, &max_decode_instance_num, 0664); + +module_param(udebug_flag, uint, 0664); +MODULE_PARM_DESC(udebug_flag, "\n ammvdec_mpeg12 udebug_flag\n"); + +#ifdef AGAIN_HAS_THRESHOLD +module_param(again_threshold, uint, 0664); +MODULE_PARM_DESC(again_threshold, "\n again_threshold\n"); +#endif + +module_init(ammvdec_mpeg12_driver_init_module); +module_exit(ammvdec_mpeg12_driver_remove_module); + +MODULE_DESCRIPTION("AMLOGIC MULTI MPEG1/2 Video Decoder Driver"); +MODULE_LICENSE("GPL"); + + diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/mpeg4/vmpeg4.c b/drivers/amlogic/media_modules/frame_provider/decoder/mpeg4/vmpeg4.c index f6a5910316b4..53ff674b8793 100644 --- a/drivers/amlogic/media_modules/frame_provider/decoder/mpeg4/vmpeg4.c +++ b/drivers/amlogic/media_modules/frame_provider/decoder/mpeg4/vmpeg4.c @@ -40,6 +40,10 @@ #include "../utils/decoder_bmmu_box.h" #include #include +#include + +#include + /* #define CONFIG_AM_VDEC_MPEG4_LOG */ #ifdef CONFIG_AM_VDEC_MPEG4_LOG @@ -116,6 +120,8 @@ MODULE_AMLOG(LOG_LEVEL_ERROR, 0, LOG_LEVEL_DESC, LOG_DEFAULT_MASK_DESC); #define DUR2PTS(x) ((x) - ((x) >> 4)) +#define MAX_MPEG4_SUPPORT_SIZE (1920*1088) + static struct vframe_s *vmpeg_vf_peek(void *); static struct vframe_s *vmpeg_vf_get(void *); static void vmpeg_vf_put(struct vframe_s *, void *); @@ -159,6 +165,7 @@ static u64 vmpeg4_ratio64; static u32 rate_detect; static u32 vmpeg4_rotation; static u32 fr_hint_status; +static u32 keyframe_pts_only; static u32 total_frame; static u32 last_vop_time_inc, last_duration; @@ -287,6 +294,7 @@ static irqreturn_t vmpeg4_isr(int irq, void *dev_id) u32 pts, pts_valid = 0, offset = 0; u64 pts_us64 = 0; u32 rate, vop_time_inc, repeat_cnt, duration = 3200; + u32 frame_size; reg = READ_VREG(MREG_BUFFEROUT); @@ -371,7 +379,7 @@ static irqreturn_t vmpeg4_isr(int irq, void *dev_id) } if ((picture_type == I_PICTURE) || - (picture_type == P_PICTURE)) { + ((P_PICTURE == picture_type) && (keyframe_pts_only == 0))) { offset = READ_VREG(MP4_OFFSET_REG); /*2500-->3000,because some mpeg4 *video may checkout failed; @@ -379,7 +387,8 @@ static irqreturn_t vmpeg4_isr(int irq, void *dev_id) *263 may need small? */ if (pts_lookup_offset_us64 - (PTS_TYPE_VIDEO, offset, &pts, 3000, + (PTS_TYPE_VIDEO, offset, &pts, + &frame_size, 3000, &pts_us64) == 0) { pts_valid = 1; last_anch_pts = pts; @@ -489,6 +498,7 @@ static irqreturn_t vmpeg4_isr(int irq, void *dev_id) buffer_index); kfifo_put(&display_q, (const struct vframe_s *)vf); + ATRACE_COUNTER(MODULE_NAME, vf->pts); vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_VFRAME_READY, @@ -535,6 +545,7 @@ static irqreturn_t vmpeg4_isr(int irq, void *dev_id) vmpeg4_amstream_dec_info.rate, picture_type); kfifo_put(&display_q, (const struct vframe_s *)vf); + ATRACE_COUNTER(MODULE_NAME, vf->pts); vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_VFRAME_READY, @@ -582,6 +593,7 @@ static irqreturn_t vmpeg4_isr(int irq, void *dev_id) buffer_index); kfifo_put(&display_q, (const struct vframe_s *)vf); + ATRACE_COUNTER(MODULE_NAME, vf->pts); vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_VFRAME_READY, @@ -697,14 +709,11 @@ static void reset_do_work(struct work_struct *work) static void vmpeg4_set_clk(struct work_struct *work) { - if (frame_dur > 0 && saved_resolution != - frame_width * frame_height * (96000 / frame_dur)) { int fps = 96000 / frame_dur; saved_resolution = frame_width * frame_height * fps; vdec_source_changed(VFORMAT_MPEG4, frame_width, frame_height, fps); - } } static void vmpeg_put_timer_func(unsigned long arg) @@ -715,8 +724,7 @@ static void vmpeg_put_timer_func(unsigned long arg) struct vframe_s *vf; if (kfifo_get(&recycle_q, &vf)) { - if ((vf->index >= 0) - && (vf->index < DECODE_BUFFER_NUM_MAX) + if ((vf->index < DECODE_BUFFER_NUM_MAX) && (--vfbuf_use[vf->index] == 0)) { WRITE_VREG(MREG_BUFFERIN, ~(1 << vf->index)); vf->index = DECODE_BUFFER_NUM_MAX; @@ -725,7 +733,9 @@ static void vmpeg_put_timer_func(unsigned long arg) } } - schedule_work(&set_clk_work); + if (frame_dur > 0 && saved_resolution != + frame_width * frame_height * (96000 / frame_dur)) + schedule_work(&set_clk_work); if (READ_VREG(AV_SCRATCH_L)) { pr_info("mpeg4 fatal error happened,need reset !!\n"); @@ -740,6 +750,9 @@ static void vmpeg_put_timer_func(unsigned long arg) int vmpeg4_dec_status(struct vdec_s *vdec, struct vdec_info *vstatus) { + if (!(stat & STAT_VDEC_RUN)) + return -1; + vstatus->frame_width = vmpeg4_amstream_dec_info.width; vstatus->frame_height = vmpeg4_amstream_dec_info.height; if (0 != vmpeg4_amstream_dec_info.rate) @@ -963,6 +976,8 @@ static void vmpeg4_local_init(void) (((unsigned long) vmpeg4_amstream_dec_info.param) >> 16) & 0xffff; + keyframe_pts_only = ((u32)vmpeg4_amstream_dec_info.param) & 0x100; + frame_width = frame_height = frame_dur = frame_prog = 0; total_frame = 0; @@ -1010,45 +1025,29 @@ static void vmpeg4_local_init(void) static s32 vmpeg4_init(void) { - int r; int trickmode_fffb = 0; - int size = -1; + int size = -1, ret = -1; + char fw_name[32] = {0}; char *buf = vmalloc(0x1000 * 16); if (IS_ERR_OR_NULL(buf)) return -ENOMEM; - - query_video_status(0, &trickmode_fffb); - amlog_level(LOG_LEVEL_INFO, "vmpeg4_init\n"); - init_timer(&recycle_timer); - stat |= STAT_TIMER_INIT; - - amvdec_enable(); - - vmpeg4_local_init(); - - if (vmpeg4_amstream_dec_info.format == VIDEO_DEC_FORMAT_MPEG4_3) { - size = get_firmware_data(VIDEO_DEC_MPEG4_3, buf); - - amlog_level(LOG_LEVEL_INFO, "load VIDEO_DEC_FORMAT_MPEG4_3\n"); - } else if (vmpeg4_amstream_dec_info.format == - VIDEO_DEC_FORMAT_MPEG4_4) { - size = get_firmware_data(VIDEO_DEC_MPEG4_4, buf); - - amlog_level(LOG_LEVEL_INFO, "load VIDEO_DEC_FORMAT_MPEG4_4\n"); - } else if (vmpeg4_amstream_dec_info.format == + if (vmpeg4_amstream_dec_info.format == VIDEO_DEC_FORMAT_MPEG4_5) { size = get_firmware_data(VIDEO_DEC_MPEG4_5, buf); + strncpy(fw_name, "vmpeg4_mc_5", sizeof(fw_name)); amlog_level(LOG_LEVEL_INFO, "load VIDEO_DEC_FORMAT_MPEG4_5\n"); } else if (vmpeg4_amstream_dec_info.format == VIDEO_DEC_FORMAT_H263) { size = get_firmware_data(VIDEO_DEC_H263, buf); + strncpy(fw_name, "h263_mc", sizeof(fw_name)); - amlog_level(LOG_LEVEL_INFO, "load VIDEO_DEC_FORMAT_H263\n"); + pr_info("load VIDEO_DEC_FORMAT_H263\n"); } else - amlog_level(LOG_LEVEL_ERROR, "not supported MPEG4 format\n"); + pr_err("unsupport mpeg4 sub format %d\n", + vmpeg4_amstream_dec_info.format); if (size < 0) { pr_err("get firmware fail."); @@ -1056,32 +1055,39 @@ static s32 vmpeg4_init(void) return -1; } - if (size == 1) - pr_info ("tee load ok"); - else if (amvdec_loadmc_ex(VFORMAT_MPEG4, NULL, buf) < 0) { + ret = amvdec_loadmc_ex(VFORMAT_MPEG4, fw_name, buf); + if (ret < 0) { amvdec_disable(); vfree(buf); + pr_err("%s: the %s fw loading failed, err: %x\n", + fw_name, tee_enabled() ? "TEE" : "local", ret); return -EBUSY; } vfree(buf); - stat |= STAT_MC_LOAD; + query_video_status(0, &trickmode_fffb); - /* enable AMRISC side protocol */ - r = vmpeg4_prot_init(); - if (r < 0) - return r; + init_timer(&recycle_timer); + stat |= STAT_TIMER_INIT; if (vdec_request_irq(VDEC_IRQ_1, vmpeg4_isr, "vmpeg4-irq", (void *)vmpeg4_dec_id)) { - amvdec_disable(); - amlog_level(LOG_LEVEL_ERROR, "vmpeg4 irq register error.\n"); return -ENOENT; } - stat |= STAT_ISR_REG; + vmpeg4_local_init(); + /* enable AMRISC side protocol */ + ret = vmpeg4_prot_init(); + if (ret < 0) { + if (mm_blk_handle) { + decoder_bmmu_box_free(mm_blk_handle); + mm_blk_handle = NULL; + } + return ret; + } + amvdec_enable(); fr_hint_status = VDEC_NO_NEED_HINT; #ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER vf_provider_init(&vmpeg_vf_prov, PROVIDER_NAME, &vmpeg_vf_provider, @@ -1094,13 +1100,14 @@ static s32 vmpeg4_init(void) vf_reg_provider(&vmpeg_vf_prov); #endif if (vmpeg4_amstream_dec_info.rate != 0) { - if (!is_reset) + if (!is_reset) { vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_FR_HINT, (void *) ((unsigned long) vmpeg4_amstream_dec_info.rate)); - fr_hint_status = VDEC_HINTED; + fr_hint_status = VDEC_HINTED; + } } else fr_hint_status = VDEC_NEED_HINT; @@ -1131,9 +1138,17 @@ static int amvdec_mpeg4_probe(struct platform_device *pdev) return -EFAULT; } - if (pdata->sys_info) + if (pdata->sys_info) { vmpeg4_amstream_dec_info = *pdata->sys_info; - + if ((vmpeg4_amstream_dec_info.height != 0) && + (vmpeg4_amstream_dec_info.width > + (MAX_MPEG4_SUPPORT_SIZE/vmpeg4_amstream_dec_info.height))) { + pr_info("amvdec_mpeg4: oversize, unsupport: %d*%d\n", + vmpeg4_amstream_dec_info.width, + vmpeg4_amstream_dec_info.height); + return -EFAULT; + } + } pdata->dec_status = vmpeg4_dec_status; pdata->set_isreset = vmpeg4_set_isreset; is_reset = 0; @@ -1148,6 +1163,7 @@ static int amvdec_mpeg4_probe(struct platform_device *pdev) amlog_level(LOG_LEVEL_ERROR, "amvdec_mpeg4 init failed.\n"); kfree(gvs); gvs = NULL; + pdata->dec_status = NULL; return -ENODEV; } @@ -1172,7 +1188,7 @@ static int amvdec_mpeg4_remove(struct platform_device *pdev) } if (stat & STAT_VF_HOOK) { - if (fr_hint_status == VDEC_HINTED && !is_reset) + if (fr_hint_status == VDEC_HINTED) vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_FR_END_HINT, NULL); fr_hint_status = VDEC_NO_NEED_HINT; diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/mpeg4/vmpeg4_multi.c b/drivers/amlogic/media_modules/frame_provider/decoder/mpeg4/vmpeg4_multi.c index f21d830360b9..84a8d38d23be 100644 --- a/drivers/amlogic/media_modules/frame_provider/decoder/mpeg4/vmpeg4_multi.c +++ b/drivers/amlogic/media_modules/frame_provider/decoder/mpeg4/vmpeg4_multi.c @@ -32,9 +32,8 @@ #include #include #include - +#include #include -#include "vmpeg4.h" #include #include "../../../stream_input/amports/amports_priv.h" @@ -42,11 +41,18 @@ #include "../utils/vdec_input.h" #include "../utils/vdec.h" #include "../utils/firmware.h" +#include "../utils/decoder_mmu_box.h" +#include "../utils/decoder_bmmu_box.h" +#include +#include "../utils/firmware.h" + +#include + #define DRIVER_NAME "ammvdec_mpeg4" #define MODULE_NAME "ammvdec_mpeg4" -#define MEM_NAME "codec_mpeg4" +#define MEM_NAME "codec_mmpeg4" #define DEBUG_PTS @@ -89,6 +95,9 @@ #define VF_POOL_SIZE 16 #define DECODE_BUFFER_NUM_MAX 4 #define PUT_INTERVAL (HZ/100) +#define MAX_BMMU_BUFFER_NUM (DECODE_BUFFER_NUM_MAX + 1) +#define WORKSPACE_SIZE (12*SZ_64K) +static u32 buf_size = 32 * 1024 * 1024; #define CTX_LMEM_SWAP_OFFSET 0 #define CTX_QUANT_MATRIX_OFFSET 0x800 @@ -99,24 +108,79 @@ #define RATE_DETECT_COUNT 5 #define DURATION_UNIT 96000 #define PTS_UNIT 90000 +#define CHECK_INTERVAL (HZ/100) #define DUR2PTS(x) ((x) - ((x) >> 4)) +#define MAX_MPEG4_SUPPORT_SIZE (1920*1088) + #define DEC_RESULT_NONE 0 #define DEC_RESULT_DONE 1 #define DEC_RESULT_AGAIN 2 #define DEC_RESULT_ERROR 3 +#define DEC_RESULT_FORCE_EXIT 4 +#define DEC_RESULT_EOS 5 +#define DEC_DECODE_TIMEOUT 0x21 +#define DECODE_ID(hw) (hw_to_vdec(hw)->id) +#define DECODE_STOP_POS AV_SCRATCH_K +static u32 udebug_flag; static struct vframe_s *vmpeg_vf_peek(void *); static struct vframe_s *vmpeg_vf_get(void *); static void vmpeg_vf_put(struct vframe_s *, void *); static int vmpeg_vf_states(struct vframe_states *states, void *); static int vmpeg_event_cb(int type, void *data, void *private_data); +static int pre_decode_buf_level = 0x800; +static int debug_enable; +static unsigned int radr; +static unsigned int rval; + +#define VMPEG4_DEV_NUM 9 +static unsigned int max_decode_instance_num = VMPEG4_DEV_NUM; +static unsigned int max_process_time[VMPEG4_DEV_NUM]; +static unsigned int decode_timeout_val = 100; + + +#undef pr_info +#define pr_info printk +unsigned int mpeg4_debug_mask = 0xff; + +#define PRINT_FLAG_ERROR 0x0 +#define PRINT_FLAG_RUN_FLOW 0X0001 +#define PRINT_FLAG_TIMEINFO 0x0002 +#define PRINT_FLAG_UCODE_DETAIL 0x0004 +#define PRINT_FLAG_VLD_DETAIL 0x0008 +#define PRINT_FLAG_DEC_DETAIL 0x0010 +#define PRINT_FLAG_BUFFER_DETAIL 0x0020 +#define PRINT_FLAG_RESTORE 0x0040 +#define PRINT_FRAME_NUM 0x0080 +#define PRINT_FLAG_FORCE_DONE 0x0100 +#define PRINT_FLAG_COUNTER 0X0200 +#define PRINT_FRAMEBASE_DATA 0x0400 +#define PRINT_FLAG_VDEC_STATUS 0x0800 +#define PRINT_FLAG_TIMEOUT_STATUS 0x1000 + +int mmpeg4_debug_print(int index, int debug_flag, const char *fmt, ...) +{ + if (((debug_enable & debug_flag) && + ((1 << index) & mpeg4_debug_mask)) + || (debug_flag == PRINT_FLAG_ERROR)) { + unsigned char buf[512]; + int len = 0; + va_list args; + va_start(args, fmt); + len = sprintf(buf, "%d: ", index); + vsnprintf(buf + len, 512-len, fmt, args); + pr_info("%s", buf); + va_end(args); + } + return 0; +} struct vdec_mpeg4_hw_s { spinlock_t lock; struct platform_device *platform_dev; - struct device *cma_dev; + /* struct device *cma_dev; */ DECLARE_KFIFO(newframe_q, struct vframe_s *, VF_POOL_SIZE); DECLARE_KFIFO(display_q, struct vframe_s *, VF_POOL_SIZE); @@ -140,13 +204,22 @@ struct vdec_mpeg4_hw_s { u32 reg_iqidct_control; u32 reg_resync_marker_length; u32 reg_rv_ai_mb_count; + struct timer_list check_timer; + u32 decode_timeout_count; + u32 start_process_time; + u32 last_vld_level; + u8 init_flag; + u32 eos; + void *mm_blk_handle; struct vframe_chunk_s *chunk; u32 stat; - u32 buf_start; + unsigned long buf_start; u32 buf_size; + /* unsigned long cma_alloc_addr; int cma_alloc_count; + */ u32 vmpeg4_ratio; u64 vmpeg4_ratio64; u32 rate_detect; @@ -163,7 +236,7 @@ struct vdec_mpeg4_hw_s { u32 pts_missed; u32 pts_i_hit; u32 pts_i_missed; - + u32 decoded_type[DECODE_BUFFER_NUM_MAX]; u32 buffer_info[DECODE_BUFFER_NUM_MAX]; u32 pts[DECODE_BUFFER_NUM_MAX]; u64 pts64[DECODE_BUFFER_NUM_MAX]; @@ -182,6 +255,19 @@ struct vdec_mpeg4_hw_s { void (*vdec_cb)(struct vdec_s *, void *); void *vdec_cb_arg; + u32 frame_num; + u32 put_num; + u32 sys_mp4_rate; + u32 run_count; + u32 not_run_ready; + u32 buffer_not_ready; + u32 input_empty; + u32 peek_num; + u32 get_num; + u32 first_i_frame_ready; + u32 drop_frame_count; + u32 timeout_flag; + struct firmware_s *fw; }; static void vmpeg4_local_init(struct vdec_mpeg4_hw_s *hw); @@ -212,6 +298,7 @@ static unsigned char aspect_ratio_table[16] = { PARC_RESERVED, PARC_EXTENDED }; +static void reset_process_time(struct vdec_mpeg4_hw_s *hw); static int find_buffer(struct vdec_mpeg4_hw_s *hw) { int i; @@ -221,7 +308,7 @@ static int find_buffer(struct vdec_mpeg4_hw_s *hw) return i; } - return -1; + return DECODE_BUFFER_NUM_MAX; } static int spec_to_index(struct vdec_mpeg4_hw_s *hw, u32 spec) @@ -342,7 +429,7 @@ static inline void vmpeg4_save_hw_context(struct vdec_mpeg4_hw_s *hw) hw->reg_rv_ai_mb_count = READ_VREG(RV_AI_MB_COUNT); } -static irqreturn_t vmpeg4_isr(struct vdec_s *vdec, int irq) +static irqreturn_t vmpeg4_isr_thread_fn(struct vdec_s *vdec, int irq) { u32 reg; struct vframe_s *vf = NULL; @@ -351,26 +438,46 @@ static irqreturn_t vmpeg4_isr(struct vdec_s *vdec, int irq) u32 pts, offset = 0; bool pts_valid = false; u64 pts_us64 = 0; + u32 frame_size; u32 time_increment_resolution, fixed_vop_rate, vop_time_inc; u32 repeat_cnt, duration = 3200; struct vdec_mpeg4_hw_s *hw = (struct vdec_mpeg4_hw_s *)(vdec->private); + if (hw->eos) + return IRQ_HANDLED; WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1); - + if (READ_VREG(AV_SCRATCH_M) != 0 && + (debug_enable & PRINT_FLAG_UCODE_DETAIL)) { + mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_UCODE_DETAIL, + "dbg %x: %x, level %x, wp %x, rp %x, cnt %x\n", + READ_VREG(AV_SCRATCH_M), READ_VREG(AV_SCRATCH_N), + READ_VREG(VLD_MEM_VIFIFO_LEVEL), + READ_VREG(VLD_MEM_VIFIFO_WP), + READ_VREG(VLD_MEM_VIFIFO_RP), + READ_VREG(VIFF_BIT_CNT)); + WRITE_VREG(AV_SCRATCH_M, 0); + return IRQ_HANDLED; + } reg = READ_VREG(MREG_BUFFEROUT); time_increment_resolution = READ_VREG(MP4_RATE); fixed_vop_rate = time_increment_resolution >> 16; time_increment_resolution &= 0xffff; - + if (time_increment_resolution > 0 && fixed_vop_rate == 0) + hw->sys_mp4_rate = time_increment_resolution; if (hw->vmpeg4_amstream_dec_info.rate == 0) { if ((fixed_vop_rate != 0) && (time_increment_resolution != 0)) { /* fixed VOP rate */ hw->vmpeg4_amstream_dec_info.rate = fixed_vop_rate * - DURATION_UNIT / - time_increment_resolution; - } + DURATION_UNIT / time_increment_resolution; + } else if (time_increment_resolution == 0 + && hw->sys_mp4_rate > 0) + time_increment_resolution = hw->sys_mp4_rate; } + mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_DEC_DETAIL, + "resolution=%d,fvop=%d,rate=%d\n", + time_increment_resolution, fixed_vop_rate, + hw->vmpeg4_amstream_dec_info.rate); if (reg == 2) { /* timeout when decoding next frame */ @@ -379,15 +486,24 @@ static irqreturn_t vmpeg4_isr(struct vdec_s *vdec, int irq) * at the beginning when only VOL head is available save * HW context also, such as for the QTable from VCOP register */ - if (input_frame_based(vdec)) + mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_VLD_DETAIL, + "ammvdec_mpeg4: timeout\n"); + mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_VLD_DETAIL, + "level=%x, vtl=%x,bcnt=%d\n", + READ_VREG(VLD_MEM_VIFIFO_LEVEL), + READ_VREG(VLD_MEM_VIFIFO_CONTROL), + READ_VREG(VIFF_BIT_CNT)); + if (input_frame_based(vdec)) { vmpeg4_save_hw_context(hw); - + hw->timeout_flag++; + } else { hw->dec_result = DEC_RESULT_AGAIN; schedule_work(&hw->work); - + } return IRQ_HANDLED; } else { + reset_process_time(hw); picture_type = (reg >> 3) & 7; repeat_cnt = READ_VREG(MP4_NOT_CODED_CNT); vop_time_inc = READ_VREG(MP4_VOP_TIME_INC); @@ -395,42 +511,30 @@ static irqreturn_t vmpeg4_isr(struct vdec_s *vdec, int irq) index = spec_to_index(hw, READ_VREG(REC_CANVAS_ADDR)); if (index < 0) { - pr_err("invalid buffer index."); + mmpeg4_debug_print(DECODE_ID(hw), 0, + "invalid buffer index."); hw->dec_result = DEC_RESULT_ERROR; schedule_work(&hw->work); return IRQ_HANDLED; } + mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_BUFFER_DETAIL, + "index=%d, used=%d cnt=%d, vopinc=%d\n", + index, hw->vfbuf_use[index], repeat_cnt, vop_time_inc); hw->dec_result = DEC_RESULT_DONE; - pr_debug("amvdec_mpeg4: offset = 0x%x\n", - READ_VREG(MP4_OFFSET_REG)); - if (hw->vmpeg4_amstream_dec_info.width == 0) { hw->vmpeg4_amstream_dec_info.width = READ_VREG(MP4_PIC_WH) >> 16; } -#if 0 - else { - pr_info("info width = %d, ucode width = %d\n", - hw->vmpeg4_amstream_dec_info.width, - READ_VREG(MP4_PIC_WH) >> 16); - } -#endif if (hw->vmpeg4_amstream_dec_info.height == 0) { hw->vmpeg4_amstream_dec_info.height = READ_VREG(MP4_PIC_WH) & 0xffff; } -#if 0 - else { - pr_info("info height = %d, ucode height = %d\n", - hw->vmpeg4_amstream_dec_info.height, - READ_VREG(MP4_PIC_WH) & 0xffff); - } -#endif + if (hw->vmpeg4_amstream_dec_info.rate == 0) { if (vop_time_inc < hw->last_vop_time_inc) { duration = vop_time_inc + @@ -443,7 +547,8 @@ static irqreturn_t vmpeg4_isr(struct vdec_s *vdec, int irq) if (duration == hw->last_duration) { hw->rate_detect++; - if (hw->rate_detect >= RATE_DETECT_COUNT) { + if ((hw->rate_detect >= RATE_DETECT_COUNT) && + (time_increment_resolution != 0)) { hw->vmpeg4_amstream_dec_info.rate = duration * DURATION_UNIT / time_increment_resolution; @@ -463,8 +568,8 @@ static irqreturn_t vmpeg4_isr(struct vdec_s *vdec, int irq) #endif } - if ((picture_type == I_PICTURE) || - (picture_type == P_PICTURE)) { + if ((I_PICTURE == picture_type) || + (P_PICTURE == picture_type)) { offset = READ_VREG(MP4_OFFSET_REG); if (hw->chunk) { hw->pts_valid[index] = hw->chunk->pts_valid; @@ -472,7 +577,8 @@ static irqreturn_t vmpeg4_isr(struct vdec_s *vdec, int irq) hw->pts64[index] = hw->chunk->pts64; } else { if (pts_lookup_offset_us64 - (PTS_TYPE_VIDEO, offset, &pts, 3000, + (PTS_TYPE_VIDEO, offset, &pts, + &frame_size, 3000, &pts_us64) == 0) { hw->pts_valid[index] = true; hw->pts[index] = pts; @@ -483,9 +589,10 @@ static irqreturn_t vmpeg4_isr(struct vdec_s *vdec, int irq) hw->pts_missed++; } } - pr_debug("I/P offset 0x%x, pts_valid %d pts=0x%x\n", + mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_TIMEINFO, + "I/P offset 0x%x, pts_valid %d pts=0x%x,index=%d,used=%d\n", offset, hw->pts_valid[index], - hw->pts[index]); + hw->pts[index], index, hw->vfbuf_use[index]); } else { hw->pts_valid[index] = false; hw->pts[index] = 0; @@ -494,11 +601,13 @@ static irqreturn_t vmpeg4_isr(struct vdec_s *vdec, int irq) hw->buffer_info[index] = reg; hw->vfbuf_use[index] = 0; - - pr_debug("amvdec_mpeg4: decoded buffer %d, frame_type %s\n", + hw->decoded_type[index] = picture_type; + mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_RUN_FLOW, + "amvdec_mpeg4: decoded buffer %d, frame_type %s,pts=%x\n", index, (picture_type == I_PICTURE) ? "I" : - (picture_type == P_PICTURE) ? "P" : "B"); + (picture_type == P_PICTURE) ? "P" : "B", + hw->pts[index]); /* Buffer management * todo: add sequence-end flush @@ -541,15 +650,20 @@ static irqreturn_t vmpeg4_isr(struct vdec_s *vdec, int irq) pts = hw->pts[index]; pts_us64 = hw->pts64[index]; - pr_debug("queued buffer %d, pts = 0x%x, pts_valid=%d\n", - index, pts, pts_valid); + if ((hw->first_i_frame_ready == 0) && + (I_PICTURE == hw->decoded_type[index])) + hw->first_i_frame_ready = 1; + mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_TIMEINFO, + "queued %d, pts = 0x%x, pts_valid=%d,index=%d,used=%d,type=%d,decode_type=%d\n", + index, pts, pts_valid, index, hw->vfbuf_use[index], + picture_type, hw->decoded_type[index]); if (pts_valid) { hw->last_anch_pts = pts; hw->last_anch_pts_us64 = pts_us64; hw->frame_num_since_last_anch = 0; hw->vop_time_inc_since_last_anch = 0; - } else { + } else if (input_stream_based(vdec)) { pts = hw->last_anch_pts; pts_us64 = hw->last_anch_pts_us64; @@ -606,8 +720,8 @@ static irqreturn_t vmpeg4_isr(struct vdec_s *vdec, int irq) if (reg & INTERLACE_FLAG) { /* interlace */ if (kfifo_get(&hw->newframe_q, &vf) == 0) { - pr_err - ("fatal error, no available buffer slot."); + mmpeg4_debug_print(DECODE_ID(hw), 0, + "fatal error, no available buffer slot."); return IRQ_HANDLED; } @@ -630,15 +744,31 @@ static irqreturn_t vmpeg4_isr(struct vdec_s *vdec, int irq) set_frame_info(hw, vf, index); hw->vfbuf_use[index]++; + mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_TIMEINFO, + "pts0=%d,pts64=%lld,w%d,h%d,dur:%d\n", + vf->pts, vf->pts_us64, + vf->width, vf->height, + vf->duration); + if ((hw->first_i_frame_ready == 0) + && (picture_type != I_PICTURE)) { + hw->drop_frame_count++; + hw->vfbuf_use[index]--; - kfifo_put(&hw->display_q, (const struct vframe_s *)vf); - + kfifo_put(&hw->newframe_q, + (const struct vframe_s *)vf); + } else { + kfifo_put(&hw->display_q, + (const struct vframe_s *)vf); + ATRACE_COUNTER(MODULE_NAME, vf->pts); + hw->frame_num++; + vdec->vdec_fps_detec(vdec->id); vf_notify_receiver(vdec->vf_provider_name, VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); - + } if (kfifo_get(&hw->newframe_q, &vf) == 0) { - pr_err("fatal error, no available buffer slot."); + mmpeg4_debug_print(DECODE_ID(hw), 0, + "fatal error, no available buffer slot."); hw->dec_result = DEC_RESULT_ERROR; schedule_work(&hw->work); return IRQ_HANDLED; @@ -664,16 +794,32 @@ static irqreturn_t vmpeg4_isr(struct vdec_s *vdec, int irq) set_frame_info(hw, vf, index); hw->vfbuf_use[index]++; + mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_TIMEINFO, + "pts1=%d,pts64=%lld,w%d,h%d,dur:%d\n", + vf->pts, vf->pts_us64, + vf->width, vf->height, + vf->duration); + if ((hw->first_i_frame_ready == 0) + && (picture_type != I_PICTURE)) { + hw->drop_frame_count++; + hw->vfbuf_use[index]--; - kfifo_put(&hw->display_q, (const struct vframe_s *)vf); - + kfifo_put(&hw->newframe_q, + (const struct vframe_s *)vf); + } else { + kfifo_put(&hw->display_q, + (const struct vframe_s *)vf); + ATRACE_COUNTER(MODULE_NAME, vf->pts); + hw->frame_num++; + vdec->vdec_fps_detec(vdec->id); vf_notify_receiver(vdec->vf_provider_name, VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); - + } } else { /* progressive */ if (kfifo_get(&hw->newframe_q, &vf) == 0) { - pr_err("fatal error, no available buffer slot."); + mmpeg4_debug_print(DECODE_ID(hw), 0, + "fatal error, no available buffer slot."); return IRQ_HANDLED; } @@ -697,14 +843,35 @@ static irqreturn_t vmpeg4_isr(struct vdec_s *vdec, int irq) #endif set_frame_info(hw, vf, index); - hw->vfbuf_use[index]++; - - kfifo_put(&hw->display_q, (const struct vframe_s *)vf); - - vf_notify_receiver(vdec->vf_provider_name, - VFRAME_EVENT_PROVIDER_VFRAME_READY, - NULL); + mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_TIMEINFO, + "pts=%d,pts64=%lld,w%d,h%d,index=%d,used=%d,dur:%d, flag=%d, type=%d\n", + vf->pts, vf->pts_us64, + vf->width, vf->height, + index, hw->vfbuf_use[index], + vf->duration, + hw->timeout_flag, picture_type); + if ((hw->first_i_frame_ready == 0) + && (picture_type != I_PICTURE)) { + hw->drop_frame_count++; + hw->vfbuf_use[index]--; + hw->timeout_flag++; + kfifo_put(&hw->newframe_q, + (const struct vframe_s *)vf); + } else { + if (hw->timeout_flag > 2) + hw->timeout_flag = 2; + if (hw->timeout_flag && input_frame_based(vdec)) + vf->duration = duration * (hw->timeout_flag + 1); + kfifo_put(&hw->display_q, + (const struct vframe_s *)vf); + ATRACE_COUNTER(MODULE_NAME, vf->pts); + hw->frame_num++; + hw->timeout_flag = 0; + vdec->vdec_fps_detec(vdec->id); + vf_notify_receiver(vdec->vf_provider_name, + VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); + } } hw->total_frame += repeat_cnt + 1; @@ -712,19 +879,53 @@ static irqreturn_t vmpeg4_isr(struct vdec_s *vdec, int irq) schedule_work(&hw->work); } + mmpeg4_debug_print(DECODE_ID(hw), PRINT_FRAME_NUM, + "%s:frame num:%d\n", __func__, hw->frame_num); return IRQ_HANDLED; } +static irqreturn_t vmpeg4_isr(struct vdec_s *vdec, int irq) +{ + u32 time_increment_resolution, fixed_vop_rate; + struct vdec_mpeg4_hw_s *hw = (struct vdec_mpeg4_hw_s *)(vdec->private); + + if (hw->eos) + return IRQ_HANDLED; + WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1); + time_increment_resolution = READ_VREG(MP4_RATE); + fixed_vop_rate = time_increment_resolution >> 16; + time_increment_resolution &= 0xffff; + if (time_increment_resolution > 0 && fixed_vop_rate == 0) + hw->sys_mp4_rate = time_increment_resolution; + if (hw->vmpeg4_amstream_dec_info.rate == 0) { + if ((fixed_vop_rate != 0) && (time_increment_resolution != 0)) { + hw->vmpeg4_amstream_dec_info.rate = fixed_vop_rate * + DURATION_UNIT / + time_increment_resolution; + } else if (time_increment_resolution == 0 + && hw->sys_mp4_rate > 0) + time_increment_resolution = hw->sys_mp4_rate; + } + mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_DEC_DETAIL, + "resolution=%d,fvop=%d,rate=%d\n", + time_increment_resolution, fixed_vop_rate, + hw->vmpeg4_amstream_dec_info.rate); + return IRQ_WAKE_THREAD; +} static void vmpeg4_work(struct work_struct *work) { struct vdec_mpeg4_hw_s *hw = container_of(work, struct vdec_mpeg4_hw_s, work); + struct vdec_s *vdec = hw_to_vdec(hw); /* finished decoding one frame or error, * notify vdec core to switch context */ - amvdec_stop(); + if (hw->dec_result != DEC_RESULT_DONE) + mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_RUN_FLOW, + "mmpeg4: vmpeg_work,result=%d,status=%d\n", + hw->dec_result, hw_to_vdec(hw)->next_status); if ((hw->dec_result == DEC_RESULT_DONE) || ((hw->chunk) && @@ -733,10 +934,55 @@ static void vmpeg4_work(struct work_struct *work) hw->ctx_valid = 1; vdec_vframe_dirty(hw_to_vdec(hw), hw->chunk); + hw->chunk = NULL; + } else if (hw->dec_result == DEC_RESULT_AGAIN + && (hw_to_vdec(hw)->next_status != + VDEC_STATUS_DISCONNECTED)) { + /* + stream base: stream buf empty or timeout + frame base: vdec_prepare_input fail + */ + if (!vdec_has_more_input(hw_to_vdec(hw))) { + hw->dec_result = DEC_RESULT_EOS; + vdec_schedule_work(&hw->work); + /*pr_info("%s: return\n", + __func__);*/ + return; + } + } else if (hw->dec_result == DEC_RESULT_FORCE_EXIT) { + mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_ERROR, + "%s: force exit\n", __func__); + if (hw->stat & STAT_ISR_REG) { + amvdec_stop(); + /*disable mbox interrupt */ + WRITE_VREG(ASSIST_MBOX1_MASK, 0); + vdec_free_irq(VDEC_IRQ_1, (void *)hw); + hw->stat &= ~STAT_ISR_REG; + } + } else if (hw->dec_result == DEC_RESULT_EOS) { + /*pr_info("%s: end of stream\n", + __func__);*/ + hw->eos = 1; + if (hw->stat & STAT_VDEC_RUN) { + amvdec_stop(); + hw->stat &= ~STAT_VDEC_RUN; + } + vdec_vframe_dirty(hw_to_vdec(hw), hw->chunk); + hw->chunk = NULL; + vdec_clean_input(hw_to_vdec(hw)); } + if (hw->stat & STAT_VDEC_RUN) { + amvdec_stop(); + hw->stat &= ~STAT_VDEC_RUN; + } + del_timer_sync(&hw->check_timer); + hw->stat &= ~STAT_TIMER_ARM; /* mark itself has all HW resource released and input released */ - vdec_core_finish_run(hw_to_vdec(hw), CORE_MASK_VDEC_1 | CORE_MASK_HEVC); + if (vdec->parallel_dec == 1) + vdec_core_finish_run(hw_to_vdec(hw), CORE_MASK_VDEC_1); + else + vdec_core_finish_run(hw_to_vdec(hw), CORE_MASK_VDEC_1 | CORE_MASK_HEVC); if (hw->vdec_cb) hw->vdec_cb(hw_to_vdec(hw), hw->vdec_cb_arg); @@ -750,7 +996,7 @@ static struct vframe_s *vmpeg_vf_peek(void *op_arg) if (!hw) return NULL; - + hw->peek_num++; if (kfifo_peek(&hw->display_q, &vf)) return vf; @@ -762,7 +1008,7 @@ static struct vframe_s *vmpeg_vf_get(void *op_arg) struct vframe_s *vf; struct vdec_s *vdec = op_arg; struct vdec_mpeg4_hw_s *hw = (struct vdec_mpeg4_hw_s *)vdec->private; - + hw->get_num++; if (kfifo_get(&hw->display_q, &vf)) return vf; @@ -775,7 +1021,13 @@ static void vmpeg_vf_put(struct vframe_s *vf, void *op_arg) struct vdec_mpeg4_hw_s *hw = (struct vdec_mpeg4_hw_s *)vdec->private; hw->vfbuf_use[vf->index]--; - + hw->put_num++; + mmpeg4_debug_print(DECODE_ID(hw), PRINT_FRAME_NUM, + "%s:put num:%d\n", + __func__, hw->put_num); + mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_BUFFER_DETAIL, + "index=%d, used=%d\n", + vf->index, hw->vfbuf_use[vf->index]); kfifo_put(&hw->newframe_q, (const struct vframe_s *)vf); } @@ -807,6 +1059,9 @@ static int dec_status(struct vdec_s *vdec, struct vdec_info *vstatus) { struct vdec_mpeg4_hw_s *hw = (struct vdec_mpeg4_hw_s *)vdec->private; + if (!hw) + return -1; + vstatus->frame_width = hw->vmpeg4_amstream_dec_info.width; vstatus->frame_height = hw->vmpeg4_amstream_dec_info.height; if (0 != hw->vmpeg4_amstream_dec_info.rate) @@ -823,86 +1078,311 @@ static int dec_status(struct vdec_s *vdec, struct vdec_info *vstatus) /****************************************/ static int vmpeg4_canvas_init(struct vdec_mpeg4_hw_s *hw) { - int i; + int i, ret; + u32 canvas_width, canvas_height; u32 decbuf_size, decbuf_y_size; struct vdec_s *vdec = hw_to_vdec(hw); - u32 decbuf_start; + unsigned long decbuf_start; - int w = hw->vmpeg4_amstream_dec_info.width; - int h = hw->vmpeg4_amstream_dec_info.height; + if (buf_size <= 0x00400000) { + /* SD only */ + canvas_width = 768; + canvas_height = 576; + decbuf_y_size = 0x80000; + decbuf_size = 0x100000; + } else { + int w = hw->vmpeg4_amstream_dec_info.width; + int h = hw->vmpeg4_amstream_dec_info.height; + int align_w, align_h; + int max, min; + if (w == 0) + w = 1920; + if (h == 0) + h = 1088; + align_w = ALIGN(w, 64); + align_h = ALIGN(h, 64); + if (align_w > align_h) { + max = align_w; + min = align_h; + } else { + max = align_h; + min = align_w; + } + /* HD & SD */ + if ((max > 1920 || min > 1088) && + ALIGN(align_w * align_h * 3/2, SZ_64K) * 9 <= + buf_size) { + canvas_width = align_w; + canvas_height = align_h; + decbuf_y_size = + ALIGN(align_w * align_h, SZ_64K); + decbuf_size = + ALIGN(align_w * align_h * 3/2, SZ_64K); + } else { /*1080p*/ + if (h > w) { + canvas_width = 1088; + canvas_height = 1920; + } else { + canvas_width = 1920; + canvas_height = 1088; + } + decbuf_y_size = 0x200000; + decbuf_size = 0x300000; + } + } - if (w == 0) - w = 1920; - if (h == 0) - h = 1088; + for (i = 0; i < MAX_BMMU_BUFFER_NUM; i++) { - w = ALIGN(w, 64); - h = ALIGN(h, 64); - decbuf_y_size = ALIGN(w * h, SZ_64K); - decbuf_size = ALIGN(w * h * 3/2, SZ_64K); + unsigned canvas; + if (i == (MAX_BMMU_BUFFER_NUM - 1)) + decbuf_size = WORKSPACE_SIZE; + ret = decoder_bmmu_box_alloc_buf_phy(hw->mm_blk_handle, i, + decbuf_size, DRIVER_NAME, &decbuf_start); + if (ret < 0) { + pr_err("mmu alloc failed! size 0x%d idx %d\n", + decbuf_size, i); + return ret; + } - decbuf_start = hw->buf_start + CTX_DECBUF_OFFSET; + if (i == (MAX_BMMU_BUFFER_NUM - 1)) { + hw->buf_start = decbuf_start; + } else { + if (vdec->parallel_dec == 1) { + unsigned tmp; + if (canvas_u(hw->canvas_spec[i]) == 0xff) { + tmp = + vdec->get_canvas_ex(CORE_MASK_VDEC_1, vdec->id); + hw->canvas_spec[i] &= ~(0xffff << 8); + hw->canvas_spec[i] |= tmp << 8; + hw->canvas_spec[i] |= tmp << 16; + } + if (canvas_y(hw->canvas_spec[i]) == 0xff) { + tmp = + vdec->get_canvas_ex(CORE_MASK_VDEC_1, vdec->id); + hw->canvas_spec[i] &= ~0xff; + hw->canvas_spec[i] |= tmp; + } + canvas = hw->canvas_spec[i]; + } else { + canvas = vdec->get_canvas(i, 2); + hw->canvas_spec[i] = canvas; + } - for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) { -#ifdef NV21 - unsigned int canvas = vdec->get_canvas(i, 2); -#else - unsigned int canvas = vdec->get_canvas(i, 3); -#endif - - hw->canvas_spec[i] = canvas; - -#ifdef NV21 - hw->canvas_config[i][0].phy_addr = decbuf_start + - i * decbuf_size; - hw->canvas_config[i][0].width = w; - hw->canvas_config[i][0].height = h; - hw->canvas_config[i][0].block_mode = CANVAS_BLKMODE_32X32; + hw->canvas_config[i][0].phy_addr = + decbuf_start; + hw->canvas_config[i][0].width = + canvas_width; + hw->canvas_config[i][0].height = + canvas_height; + hw->canvas_config[i][0].block_mode = + CANVAS_BLKMODE_32X32; canvas_config_config(canvas_y(canvas), &hw->canvas_config[i][0]); - hw->canvas_config[i][1].phy_addr = decbuf_start + - i * decbuf_size + decbuf_y_size; - hw->canvas_config[i][1].width = w; - hw->canvas_config[i][1].height = h / 2; - hw->canvas_config[i][1].block_mode = CANVAS_BLKMODE_32X32; + hw->canvas_config[i][1].phy_addr = + decbuf_start + decbuf_y_size; + hw->canvas_config[i][1].width = + canvas_width; + hw->canvas_config[i][1].height = + canvas_height / 2; + hw->canvas_config[i][1].block_mode = + CANVAS_BLKMODE_32X32; canvas_config_config(canvas_u(canvas), &hw->canvas_config[i][1]); -#else - hw->canvas_config[i][0].phy_addr = decbuf_start + - i * decbuf_size; - hw->canvas_config[i][0].width = w; - hw->canvas_config[i][0].height = h; - hw->canvas_config[i][0].block_mode = CANVAS_BLKMODE_32X32; - - canvas_config_config(canvas_y(canvas), - &hw->canvas_config[i][0]); - - hw->canvas_config[i][1].phy_addr = decbuf_start + - i * decbuf_size + decbuf_y_size; - hw->canvas_config[i][1].width = w / 2; - hw->canvas_config[i][1].height = h / 2; - hw->canvas_config[i][1].block_mode = CANVAS_BLKMODE_32X32; - - canvas_config_config(canvas_u(canvas), - &hw->canvas_config[i][1]); - - hw->canvas_config[i][2].phy_addr = decbuf_start + - i * decbuf_size + decbuf_y_size + - decbuf_uv_size; - hw->canvas_config[i][2].width = w / 2; - hw->canvas_config[i][2].height = h / 2; - hw->canvas_config[i][2].block_mode = CANVAS_BLKMODE_32X32; - - canvas_config_config(canvas_v(canvas), - &hw->canvas_config[i][2]); -#endif + } } return 0; } +static void vmpeg4_dump_state(struct vdec_s *vdec) +{ + struct vdec_mpeg4_hw_s *hw = + (struct vdec_mpeg4_hw_s *)(vdec->private); + u32 i; + mmpeg4_debug_print(DECODE_ID(hw), 0, + "====== %s\n", __func__); + mmpeg4_debug_print(DECODE_ID(hw), 0, + "width/height (%d/%d), i_fram:%d, buffer_not_ready %d\n", + hw->vmpeg4_amstream_dec_info.width, + hw->vmpeg4_amstream_dec_info.height, + hw->first_i_frame_ready, + hw->buffer_not_ready + ); + for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) { + mmpeg4_debug_print(DECODE_ID(hw), 0, + "index %d, used %d\n", i, hw->vfbuf_use[i]); + } + + mmpeg4_debug_print(DECODE_ID(hw), 0, + "is_framebase(%d), eos %d, state 0x%x, dec_result 0x%x dec_frm %d\n", + input_frame_based(vdec), + hw->eos, + hw->stat, + hw->dec_result, + hw->frame_num + ); + mmpeg4_debug_print(DECODE_ID(hw), 0, + "is_framebase(%d), put_frm %d run %d not_run_ready %d input_empty %d,drop %d\n", + input_frame_based(vdec), + hw->put_num, + hw->run_count, + hw->not_run_ready, + hw->input_empty, + hw->drop_frame_count + ); + + if (vf_get_receiver(vdec->vf_provider_name)) { + enum receviver_start_e state = + vf_notify_receiver(vdec->vf_provider_name, + VFRAME_EVENT_PROVIDER_QUREY_STATE, + NULL); + mmpeg4_debug_print(DECODE_ID(hw), 0, + "\nreceiver(%s) state %d\n", + vdec->vf_provider_name, + state); + } + mmpeg4_debug_print(DECODE_ID(hw), 0, + "%s, newq(%d/%d), dispq(%d/%d) vf peek/get/put (%d/%d/%d)\n", + __func__, + kfifo_len(&hw->newframe_q), + VF_POOL_SIZE, + kfifo_len(&hw->display_q), + VF_POOL_SIZE, + hw->peek_num, + hw->get_num, + hw->put_num + ); + mmpeg4_debug_print(DECODE_ID(hw), 0, + "VIFF_BIT_CNT=0x%x\n", + READ_VREG(VIFF_BIT_CNT)); + mmpeg4_debug_print(DECODE_ID(hw), 0, + "VLD_MEM_VIFIFO_LEVEL=0x%x\n", + READ_VREG(VLD_MEM_VIFIFO_LEVEL)); + mmpeg4_debug_print(DECODE_ID(hw), 0, + "VLD_MEM_VIFIFO_WP=0x%x\n", + READ_VREG(VLD_MEM_VIFIFO_WP)); + mmpeg4_debug_print(DECODE_ID(hw), 0, + "VLD_MEM_VIFIFO_RP=0x%x\n", + READ_VREG(VLD_MEM_VIFIFO_RP)); + mmpeg4_debug_print(DECODE_ID(hw), 0, + "PARSER_VIDEO_RP=0x%x\n", + READ_PARSER_REG(PARSER_VIDEO_RP)); + mmpeg4_debug_print(DECODE_ID(hw), 0, + "PARSER_VIDEO_WP=0x%x\n", + READ_PARSER_REG(PARSER_VIDEO_WP)); + if (input_frame_based(vdec) && + debug_enable & PRINT_FRAMEBASE_DATA + ) { + int jj; + if (hw->chunk && hw->chunk->block && + hw->chunk->size > 0) { + u8 *data = NULL; + + if (!hw->chunk->block->is_mapped) + data = codec_mm_vmap(hw->chunk->block->start + + hw->chunk->offset, hw->chunk->size); + else + data = ((u8 *)hw->chunk->block->start_virt) + + hw->chunk->offset; + + mmpeg4_debug_print(DECODE_ID(hw), 0, + "frame data size 0x%x\n", + hw->chunk->size); + for (jj = 0; jj < hw->chunk->size; jj++) { + if ((jj & 0xf) == 0) + mmpeg4_debug_print(DECODE_ID(hw), + PRINT_FRAMEBASE_DATA, + "%06x:", jj); + mmpeg4_debug_print(DECODE_ID(hw), + PRINT_FRAMEBASE_DATA, + "%02x ", data[jj]); + if (((jj + 1) & 0xf) == 0) + mmpeg4_debug_print(DECODE_ID(hw), + PRINT_FRAMEBASE_DATA, + "\n"); + } + + if (!hw->chunk->block->is_mapped) + codec_mm_unmap_phyaddr(data); + } + } +} + +static void reset_process_time(struct vdec_mpeg4_hw_s *hw) +{ + if (hw->start_process_time) { + unsigned process_time = + 1000 * (jiffies - hw->start_process_time) / HZ; + hw->start_process_time = 0; + if (process_time > max_process_time[DECODE_ID(hw)]) + max_process_time[DECODE_ID(hw)] = process_time; + } +} +static void start_process_time(struct vdec_mpeg4_hw_s *hw) +{ + hw->decode_timeout_count = 2; + hw->start_process_time = jiffies; +} + +static void timeout_process(struct vdec_mpeg4_hw_s *hw) +{ + if (hw->stat & STAT_VDEC_RUN) { + amvdec_stop(); + hw->stat &= ~STAT_VDEC_RUN; + } + mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_TIMEOUT_STATUS, + "%s decoder timeout\n", __func__); + reset_process_time(hw); + hw->first_i_frame_ready = 0; + hw->dec_result = DEC_RESULT_DONE; + vdec_schedule_work(&hw->work); +} + + +static void check_timer_func(unsigned long arg) +{ + struct vdec_mpeg4_hw_s *hw = (struct vdec_mpeg4_hw_s *)arg; + struct vdec_s *vdec = hw_to_vdec(hw); + unsigned int timeout_val = decode_timeout_val; + + if (radr != 0) { + if (rval != 0) { + WRITE_VREG(radr, rval); + pr_info("WRITE_VREG(%x,%x)\n", radr, rval); + } else + pr_info("READ_VREG(%x)=%x\n", radr, READ_VREG(radr)); + rval = 0; + radr = 0; + } + + if (debug_enable == 0 && + (input_frame_based(vdec) || + (READ_VREG(VLD_MEM_VIFIFO_LEVEL) > 0x100)) && + (timeout_val > 0) && + (hw->start_process_time > 0) && + ((1000 * (jiffies - hw->start_process_time) / HZ) + > timeout_val)) { + if (hw->last_vld_level == READ_VREG(VLD_MEM_VIFIFO_LEVEL)) { + if (hw->decode_timeout_count > 0) + hw->decode_timeout_count--; + if (hw->decode_timeout_count == 0) + timeout_process(hw); + } + hw->last_vld_level = READ_VREG(VLD_MEM_VIFIFO_LEVEL); + } + + if (vdec->next_status == VDEC_STATUS_DISCONNECTED) { + mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_ERROR, + "vdec requested to be disconnected\n"); + hw->dec_result = DEC_RESULT_FORCE_EXIT; + vdec_schedule_work(&hw->work); + return; + } + + mod_timer(&hw->check_timer, jiffies + CHECK_INTERVAL); +} static int vmpeg4_hw_ctx_restore(struct vdec_mpeg4_hw_s *hw) { @@ -939,11 +1419,12 @@ static int vmpeg4_hw_ctx_restore(struct vdec_mpeg4_hw_s *hw) WRITE_VREG(REC_CANVAS_ADDR, hw->canvas_spec[index]); WRITE_VREG(ANC2_CANVAS_ADDR, hw->canvas_spec[index]); - pr_debug("vmpeg4_hw_ctx_restore ref0=0x%x, ref1=0x%x, rec=0x%x, ctx_valid=%d\n", + mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_RESTORE, + "restore ref0=0x%x, ref1=0x%x, rec=0x%x, ctx_valid=%d,index=%d\n", READ_VREG(MREG_REF0), READ_VREG(MREG_REF1), READ_VREG(REC_CANVAS_ADDR), - hw->ctx_valid); + hw->ctx_valid, index); /* notify ucode the buffer start address */ WRITE_VREG(MEM_OFFSET_REG, hw->buf_start); @@ -1011,7 +1492,7 @@ static void vmpeg4_local_init(struct vdec_mpeg4_hw_s *hw) hw->vmpeg4_rotation = (((unsigned long) hw->vmpeg4_amstream_dec_info.param) >> 16) & 0xffff; - + hw->sys_mp4_rate = hw->vmpeg4_amstream_dec_info.rate; hw->frame_width = hw->frame_height = hw->frame_dur = hw->frame_prog = 0; hw->total_frame = 0; @@ -1025,8 +1506,21 @@ static void vmpeg4_local_init(struct vdec_mpeg4_hw_s *hw) hw->vop_time_inc_since_last_anch = 0; hw->frame_num_since_last_anch = 0; + hw->frame_num = 0; + hw->put_num = 0; + hw->run_count = 0; + hw->not_run_ready = 0; + hw->input_empty = 0; + hw->peek_num = 0; + hw->get_num = 0; hw->pts_hit = hw->pts_missed = hw->pts_i_hit = hw->pts_i_missed = 0; + hw->refs[0] = -1; + hw->refs[1] = -1; + hw->first_i_frame_ready = 0; + hw->drop_frame_count = 0; + hw->buffer_not_ready = 0; + hw->timeout_flag = 0; for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) hw->vfbuf_use[i] = 0; @@ -1040,11 +1534,21 @@ static void vmpeg4_local_init(struct vdec_mpeg4_hw_s *hw) hw->vfpool[i].index = DECODE_BUFFER_NUM_MAX; kfifo_put(&hw->newframe_q, (const struct vframe_s *)vf); } - + if (hw->mm_blk_handle) { + decoder_bmmu_box_free(hw->mm_blk_handle); + hw->mm_blk_handle = NULL; + } + hw->mm_blk_handle = decoder_bmmu_box_alloc_box( + DRIVER_NAME, + 0, + MAX_BMMU_BUFFER_NUM, + 4 + PAGE_SHIFT, + CODEC_MM_FLAGS_CMA_CLEAR | + CODEC_MM_FLAGS_FOR_VDECODER); INIT_WORK(&hw->work, vmpeg4_work); } -static s32 vmpeg4_init(struct vdec_mpeg4_hw_s *hw) +static s32 vmmpeg4_init(struct vdec_mpeg4_hw_s *hw) { int trickmode_fffb = 0; int size = -1, fw_size = 0x1000 * 16; @@ -1055,29 +1559,19 @@ static s32 vmpeg4_init(struct vdec_mpeg4_hw_s *hw) return -ENOMEM; if (hw->vmpeg4_amstream_dec_info.format == - VIDEO_DEC_FORMAT_MPEG4_3) { - size = get_firmware_data(VIDEO_DEC_MPEG4_3, fw->data); - - pr_info("load VIDEO_DEC_FORMAT_MPEG4_3\n"); - } else if (hw->vmpeg4_amstream_dec_info.format == - VIDEO_DEC_FORMAT_MPEG4_4) { - size = get_firmware_data(VIDEO_DEC_MPEG4_4, fw->data); - - pr_info("load VIDEO_DEC_FORMAT_MPEG4_4\n"); - } else if (hw->vmpeg4_amstream_dec_info.format == VIDEO_DEC_FORMAT_MPEG4_5) { - size = get_firmware_data(VIDEO_DEC_MPEG4_5, fw->data); - - pr_info("load VIDEO_DEC_FORMAT_MPEG4_5\n"); + size = get_firmware_data(VIDEO_DEC_MPEG4_5_MULTI, fw->data); + strncpy(fw->name, "mmpeg4_mc_5", sizeof(fw->name)); } else if (hw->vmpeg4_amstream_dec_info.format == VIDEO_DEC_FORMAT_H263) { - size = get_firmware_data(VIDEO_DEC_H263, fw->data); - - pr_info("load VIDEO_DEC_FORMAT_H263\n"); - } - + size = get_firmware_data(VIDEO_DEC_H263_MULTI, fw->data); + strncpy(fw->name, "mh263_mc", sizeof(fw->name)); + } else + pr_err("unsupport mpeg4 sub format %d\n", + hw->vmpeg4_amstream_dec_info.format); + pr_info("mmpeg4 get fw %s, size %x\n", fw->name, size); if (size < 0) { - pr_err("get firmware fail."); + pr_err("get firmware failed."); vfree(fw); return -1; } @@ -1087,11 +1581,20 @@ static s32 vmpeg4_init(struct vdec_mpeg4_hw_s *hw) query_video_status(0, &trickmode_fffb); - pr_info("vmpeg4_init\n"); + pr_info("%s\n", __func__); amvdec_enable(); + init_timer(&hw->check_timer); + hw->check_timer.data = (unsigned long)hw; + hw->check_timer.function = check_timer_func; + hw->check_timer.expires = jiffies + CHECK_INTERVAL; + hw->stat |= STAT_TIMER_ARM; + hw->eos = 0; + WRITE_VREG(DECODE_STOP_POS, udebug_flag); + vmpeg4_local_init(hw); + wmb(); return 0; } @@ -1100,10 +1603,57 @@ static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask) { int index; struct vdec_mpeg4_hw_s *hw = (struct vdec_mpeg4_hw_s *)vdec->private; + if (hw->eos) + return 0; + if (vdec_stream_based(vdec) && (hw->init_flag == 0) + && pre_decode_buf_level != 0) { + u32 rp, wp, level; + + rp = READ_PARSER_REG(PARSER_VIDEO_RP); + wp = READ_PARSER_REG(PARSER_VIDEO_WP); + if (wp < rp) + level = vdec->input.size + wp - rp; + else + level = wp - rp; + if (level < pre_decode_buf_level) { + hw->not_run_ready++; + return 0; + } + } index = find_buffer(hw); + if (index >= DECODE_BUFFER_NUM_MAX) { + hw->buffer_not_ready++; + return 0; + } + hw->not_run_ready = 0; + hw->buffer_not_ready = 0; + if (vdec->parallel_dec == 1) + return (unsigned long)(CORE_MASK_VDEC_1); + else + return (unsigned long)(CORE_MASK_VDEC_1 | CORE_MASK_HEVC); +} - return (index >= 0) ? (CORE_MASK_VDEC_1 | CORE_MASK_HEVC) : 0; +static unsigned char get_data_check_sum + (struct vdec_mpeg4_hw_s *hw, int size) +{ + int jj; + int sum = 0; + u8 *data = NULL; + + if (!hw->chunk->block->is_mapped) + data = codec_mm_vmap(hw->chunk->block->start + + hw->chunk->offset, size); + else + data = ((u8 *)hw->chunk->block->start_virt) + + hw->chunk->offset; + + for (jj = 0; jj < size; jj++) + sum += data[jj]; + + if (!hw->chunk->block->is_mapped) + codec_mm_unmap_phyaddr(data); + return sum; } static void run(struct vdec_s *vdec, unsigned long mask, @@ -1111,8 +1661,9 @@ static void run(struct vdec_s *vdec, unsigned long mask, { struct vdec_mpeg4_hw_s *hw = (struct vdec_mpeg4_hw_s *)vdec->private; int save_reg = READ_VREG(POWER_CTL_VLD); - int ret = -1; + int size, ret = 0; + hw->run_count++; /* reset everything except DOS_TOP[1] and APB_CBUS[0] */ WRITE_VREG(DOS_SW_RESET0, 0xfffffff0); WRITE_VREG(DOS_SW_RESET0, 0); @@ -1120,72 +1671,163 @@ static void run(struct vdec_s *vdec, unsigned long mask, hw->vdec_cb_arg = arg; hw->vdec_cb = callback; - - ret = vdec_prepare_input(vdec, &hw->chunk); - if (ret < 0) { - pr_debug("amvdec_mpeg4: Input not ready\n"); + vdec_reset_core(vdec); + size = vdec_prepare_input(vdec, &hw->chunk); + if (size < 0) { + hw->input_empty++; hw->dec_result = DEC_RESULT_AGAIN; schedule_work(&hw->work); return; } - vdec_enable_input(vdec); + if (input_frame_based(vdec)) { + u8 *data = NULL; - if (hw->chunk) - pr_debug("input chunk offset %d, size %d\n", - hw->chunk->offset, hw->chunk->size); + if (!hw->chunk->block->is_mapped) + data = codec_mm_vmap(hw->chunk->block->start + + hw->chunk->offset, size); + else + data = ((u8 *)hw->chunk->block->start_virt) + + hw->chunk->offset; + + if (debug_enable & PRINT_FLAG_VDEC_STATUS + ) { + mmpeg4_debug_print(DECODE_ID(hw), 0, + "%s: size 0x%x sum 0x%x %02x %02x %02x %02x %02x %02x .. %02x %02x %02x %02x\n", + __func__, size, get_data_check_sum(hw, size), + data[0], data[1], data[2], data[3], + data[4], data[5], data[size - 4], + data[size - 3], data[size - 2], + data[size - 1]); + } + if (debug_enable & PRINT_FRAMEBASE_DATA + ) { + int jj; + + for (jj = 0; jj < size; jj++) { + if ((jj & 0xf) == 0) + mmpeg4_debug_print(DECODE_ID(hw), + PRINT_FRAMEBASE_DATA, + "%06x:", jj); + mmpeg4_debug_print(DECODE_ID(hw), + PRINT_FRAMEBASE_DATA, + "%02x ", data[jj]); + if (((jj + 1) & 0xf) == 0) + mmpeg4_debug_print(DECODE_ID(hw), + PRINT_FRAMEBASE_DATA, + "\n"); + } + } + + if (!hw->chunk->block->is_mapped) + codec_mm_unmap_phyaddr(data); + } else + mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS, + "%s: %x %x %x %x %x size 0x%x\n", + __func__, + READ_VREG(VLD_MEM_VIFIFO_LEVEL), + READ_VREG(VLD_MEM_VIFIFO_WP), + READ_VREG(VLD_MEM_VIFIFO_RP), + READ_PARSER_REG(PARSER_VIDEO_RP), + READ_PARSER_REG(PARSER_VIDEO_WP), + size); + + mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_RUN_FLOW, + "%s,%d, size=%d, %x %x %x %x %x\n", + __func__, __LINE__, size, + READ_VREG(VLD_MEM_VIFIFO_LEVEL), + READ_VREG(VLD_MEM_VIFIFO_WP), + READ_VREG(VLD_MEM_VIFIFO_RP), + READ_PARSER_REG(PARSER_VIDEO_RP), + READ_PARSER_REG(PARSER_VIDEO_WP)); hw->dec_result = DEC_RESULT_NONE; - - if (amvdec_vdec_loadmc_buf_ex(vdec, hw->fw->data, hw->fw->len) < 0) { - pr_err("VIDEO_DEC_FORMAT_MPEG4 ucode loading failed\n"); - hw->dec_result = DEC_RESULT_ERROR; - schedule_work(&hw->work); - return; + if (vdec->mc_loaded) { + /*firmware have load before, + and not changes to another. + ignore reload. + */ + } else { + ret = amvdec_vdec_loadmc_buf_ex(VFORMAT_MPEG4,hw->fw->name, vdec, + hw->fw->data, hw->fw->len); + if (ret < 0) { + pr_err("[%d] %s: the %s fw loading failed, err: %x\n", vdec->id, + hw->fw->name, tee_enabled() ? "TEE" : "local", ret); + hw->dec_result = DEC_RESULT_FORCE_EXIT; + schedule_work(&hw->work); + return; + } + vdec->mc_loaded = 1; + vdec->mc_type = VFORMAT_MPEG4; } - if (vmpeg4_hw_ctx_restore(hw) < 0) { hw->dec_result = DEC_RESULT_ERROR; - pr_err("amvdec_mpeg4: error HW context restore\n"); + mmpeg4_debug_print(DECODE_ID(hw), 0, + "amvdec_mpeg4: error HW context restore\n"); schedule_work(&hw->work); return; } - + hw->input_empty = 0; + hw->last_vld_level = 0; + start_process_time(hw); + vdec_enable_input(vdec); /* wmb before ISR is handled */ wmb(); amvdec_start(); + hw->stat |= STAT_VDEC_RUN; + mod_timer(&hw->check_timer, jiffies + CHECK_INTERVAL); } +static int vmpeg4_stop(struct vdec_mpeg4_hw_s *hw) +{ + cancel_work_sync(&hw->work); + + if (hw->mm_blk_handle) { + decoder_bmmu_box_free(hw->mm_blk_handle); + hw->mm_blk_handle = NULL; + } + + if (hw->stat & STAT_TIMER_ARM) { + del_timer_sync(&hw->check_timer); + hw->stat &= ~STAT_TIMER_ARM; + } + + if (hw->fw) { + vfree(hw->fw); + hw->fw = NULL; + } + return 0; +} static void reset(struct vdec_s *vdec) { struct vdec_mpeg4_hw_s *hw = (struct vdec_mpeg4_hw_s *)vdec->private; - pr_info("amvdec_mpeg4: reset.\n"); + pr_info("amvdec_mmpeg4: reset.\n"); vmpeg4_local_init(hw); hw->ctx_valid = false; } -static int amvdec_mpeg4_probe(struct platform_device *pdev) +static int ammvdec_mpeg4_probe(struct platform_device *pdev) { struct vdec_s *pdata = *(struct vdec_s **)pdev->dev.platform_data; struct vdec_mpeg4_hw_s *hw = NULL; - pr_info("amvdec_mpeg4[%d] probe start.\n", pdev->id); + pr_info("%s [%d] probe start.\n", __func__, pdev->id); if (pdata == NULL) { - pr_err("ammvdec_mpeg4 memory resource undefined.\n"); + pr_err("%s memory resource undefined.\n", __func__); return -EFAULT; } - hw = (struct vdec_mpeg4_hw_s *)devm_kzalloc(&pdev->dev, - sizeof(struct vdec_mpeg4_hw_s), GFP_KERNEL); + hw = vmalloc(sizeof(struct vdec_mpeg4_hw_s)); if (hw == NULL) { - pr_info("\namvdec_mpeg4 decoder driver alloc failed\n"); + pr_err("\namvdec_mpeg4 decoder driver alloc failed\n"); return -ENOMEM; } + memset(hw, 0, sizeof(struct vdec_mpeg4_hw_s)); pdata->private = hw; pdata->dec_status = dec_status; @@ -1194,7 +1836,8 @@ static int amvdec_mpeg4_probe(struct platform_device *pdev) pdata->run = run; pdata->reset = reset; pdata->irq_handler = vmpeg4_isr; - + pdata->threaded_irq_handler = vmpeg4_isr_thread_fn; + pdata->dump_state = vmpeg4_dump_state; if (pdata->use_vfm_path) snprintf(pdata->vf_provider_name, VDEC_PROVIDER_NAME_SIZE, @@ -1203,14 +1846,20 @@ static int amvdec_mpeg4_probe(struct platform_device *pdev) snprintf(pdata->vf_provider_name, VDEC_PROVIDER_NAME_SIZE, PROVIDER_NAME ".%02x", pdev->id & 0xff); - vf_provider_init(&pdata->vframe_provider, pdata->vf_provider_name, - &vf_provider_ops, pdata); + if (pdata->parallel_dec == 1) { + int i; + for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) + hw->canvas_spec[i] = 0xffffff; + } + + vf_provider_init(&pdata->vframe_provider, + pdata->vf_provider_name, &vf_provider_ops, pdata); platform_set_drvdata(pdev, pdata); - hw->platform_dev = pdev; - hw->cma_dev = pdata->cma_dev; +/* + hw->cma_dev = pdata->cma_dev; hw->cma_alloc_count = PAGE_ALIGN(DEFAULT_MEM_SIZE) / PAGE_SIZE; hw->cma_alloc_addr = codec_mm_alloc_for_dma(MEM_NAME, hw->cma_alloc_count, @@ -1220,59 +1869,106 @@ static int amvdec_mpeg4_probe(struct platform_device *pdev) pr_err("codec_mm alloc failed, request buf size 0x%lx\n", hw->cma_alloc_count * PAGE_SIZE); hw->cma_alloc_count = 0; + if (hw) { + vfree((void *)hw); + hw = NULL; + } return -ENOMEM; } hw->buf_start = hw->cma_alloc_addr; hw->buf_size = DEFAULT_MEM_SIZE; - - if (pdata->sys_info) +*/ + if (pdata->sys_info) { hw->vmpeg4_amstream_dec_info = *pdata->sys_info; + if ((hw->vmpeg4_amstream_dec_info.height != 0) && + (hw->vmpeg4_amstream_dec_info.width > + (MAX_MPEG4_SUPPORT_SIZE/hw->vmpeg4_amstream_dec_info.height))) { + pr_info("ammvdec_mpeg4: oversize, unsupport: %d*%d\n", + hw->vmpeg4_amstream_dec_info.width, + hw->vmpeg4_amstream_dec_info.height); + pdata->dec_status = NULL; + vfree((void *)hw); + hw = NULL; + return -EFAULT; + } + } + mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_ERROR, + "W:%d,H:%d,rate=%d\n", + hw->vmpeg4_amstream_dec_info.width, + hw->vmpeg4_amstream_dec_info.height, + hw->vmpeg4_amstream_dec_info.rate); + hw->vmpeg4_amstream_dec_info.height = 0; + hw->vmpeg4_amstream_dec_info.width = 0; - if (vmpeg4_init(hw) < 0) { - pr_err("amvdec_mpeg4 init failed.\n"); - + if (vmmpeg4_init(hw) < 0) { + pr_err("%s init failed.\n", __func__); +/* + if (hw->cma_alloc_addr) { + codec_mm_free_for_dma(MEM_NAME, hw->cma_alloc_addr); + hw->cma_alloc_count = 0; + } +*/ + if (hw) { + vfree((void *)hw); + hw = NULL; + } + pdata->dec_status = NULL; return -ENODEV; } - - vdec_core_request(pdata, CORE_MASK_VDEC_1 | CORE_MASK_HEVC + if (pdata->parallel_dec == 1) + vdec_core_request(pdata, CORE_MASK_VDEC_1); + else { + vdec_core_request(pdata, CORE_MASK_VDEC_1 | CORE_MASK_HEVC | CORE_MASK_COMBINE); + } return 0; } -static int amvdec_mpeg4_remove(struct platform_device *pdev) +static int ammvdec_mpeg4_remove(struct platform_device *pdev) { struct vdec_mpeg4_hw_s *hw = (struct vdec_mpeg4_hw_s *) (((struct vdec_s *)(platform_get_drvdata(pdev)))->private); + struct vdec_s *vdec = hw_to_vdec(hw); + int i; - - vdec_core_release(hw_to_vdec(hw), CORE_MASK_VDEC_1 | CORE_MASK_HEVC); - - amvdec_disable(); - + vmpeg4_stop(hw); + /* if (hw->cma_alloc_addr) { pr_info("codec_mm release buffer 0x%lx\n", hw->cma_alloc_addr); codec_mm_free_for_dma(MEM_NAME, hw->cma_alloc_addr); hw->cma_alloc_count = 0; } + */ + if (vdec->parallel_dec == 1) + vdec_core_release(hw_to_vdec(hw), CORE_MASK_VDEC_1); + else + vdec_core_release(hw_to_vdec(hw), CORE_MASK_VDEC_1 | CORE_MASK_HEVC); + vdec_set_status(hw_to_vdec(hw), VDEC_STATUS_DISCONNECTED); - vfree(hw->fw); - hw->fw = NULL; + if (vdec->parallel_dec == 1) { + for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) { + vdec->free_canvas_ex(canvas_y(hw->canvas_spec[i]), vdec->id); + vdec->free_canvas_ex(canvas_u(hw->canvas_spec[i]), vdec->id); + } + } pr_info("pts hit %d, pts missed %d, i hit %d, missed %d\n", hw->pts_hit, hw->pts_missed, hw->pts_i_hit, hw->pts_i_missed); pr_info("total frame %d, rate %d\n", hw->total_frame, hw->vmpeg4_amstream_dec_info.rate); + vfree((void *)hw); + hw = NULL; return 0; } /****************************************/ -static struct platform_driver amvdec_mpeg4_driver = { - .probe = amvdec_mpeg4_probe, - .remove = amvdec_mpeg4_remove, +static struct platform_driver ammvdec_mpeg4_driver = { + .probe = ammvdec_mpeg4_probe, + .remove = ammvdec_mpeg4_remove, #ifdef CONFIG_PM .suspend = amvdec_suspend, .resume = amvdec_resume, @@ -1287,29 +1983,49 @@ static struct codec_profile_t amvdec_mpeg4_profile = { .profile = "" }; -static int __init amvdec_mmpeg4_driver_init_module(void) +static int __init ammvdec_mpeg4_driver_init_module(void) { - pr_info("amvdec_mmpeg4 module init\n"); + pr_info("%s \n", __func__); - if (platform_driver_register(&amvdec_mpeg4_driver)) { - pr_err("failed to register amvdec_mpeg4 driver\n"); + if (platform_driver_register(&ammvdec_mpeg4_driver)) { + pr_err("failed to register ammvdec_mpeg4 driver\n"); return -ENODEV; } vcodec_profile_register(&amvdec_mpeg4_profile); return 0; } -static void __exit amvdec_mmpeg4_driver_remove_module(void) +static void __exit ammvdec_mpeg4_driver_remove_module(void) { - pr_info("amvdec_mmpeg4 module remove.\n"); + pr_info("ammvdec_mpeg4 module remove.\n"); - platform_driver_unregister(&amvdec_mpeg4_driver); + platform_driver_unregister(&ammvdec_mpeg4_driver); } /****************************************/ +module_param(debug_enable, uint, 0664); +MODULE_PARM_DESC(debug_enable, + "\n ammvdec_mpeg4 debug enable\n"); -module_init(amvdec_mmpeg4_driver_init_module); -module_exit(amvdec_mmpeg4_driver_remove_module); +module_param(radr, uint, 0664); +MODULE_PARM_DESC(radr, "\nradr\n"); + +module_param(rval, uint, 0664); +MODULE_PARM_DESC(rval, "\nrval\n"); + +module_param(decode_timeout_val, uint, 0664); +MODULE_PARM_DESC(decode_timeout_val, "\n ammvdec_mpeg4 decode_timeout_val\n"); + +module_param_array(max_process_time, uint, &max_decode_instance_num, 0664); + +module_param(pre_decode_buf_level, int, 0664); +MODULE_PARM_DESC(pre_decode_buf_level, + "\n ammvdec_ mpeg4 pre_decode_buf_level\n"); + +module_param(udebug_flag, uint, 0664); +MODULE_PARM_DESC(udebug_flag, "\n ammvdec_mpeg4 udebug_flag\n"); +module_init(ammvdec_mpeg4_driver_init_module); +module_exit(ammvdec_mpeg4_driver_remove_module); MODULE_DESCRIPTION("AMLOGIC MPEG4 Video Decoder Driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/real/vreal.c b/drivers/amlogic/media_modules/frame_provider/decoder/real/vreal.c index ef0f340d2b78..afce94eee6bf 100644 --- a/drivers/amlogic/media_modules/frame_provider/decoder/real/vreal.c +++ b/drivers/amlogic/media_modules/frame_provider/decoder/real/vreal.c @@ -52,6 +52,10 @@ #include #include #include "../utils/firmware.h" +#include + +#include + #define DRIVER_NAME "amvdec_real" #define MODULE_NAME "amvdec_real" @@ -354,6 +358,7 @@ static irqreturn_t vreal_isr(int irq, void *dev_id) buffer_index); kfifo_put(&display_q, (const struct vframe_s *)vf); + ATRACE_COUNTER(MODULE_NAME, vf->pts); frame_count++; vf_notify_receiver(PROVIDER_NAME, @@ -499,7 +504,7 @@ static void vreal_put_timer_func(unsigned long arg) struct vframe_s *vf; if (kfifo_get(&recycle_q, &vf)) { - if ((vf->index >= 0) && (vf->index < VF_BUF_NUM) + if ((vf->index < VF_BUF_NUM) && (--vfbuf_use[vf->index] == 0)) { WRITE_VREG(TO_AMRISC, ~(1 << vf->index)); vf->index = VF_BUF_NUM; @@ -518,6 +523,9 @@ static void vreal_put_timer_func(unsigned long arg) int vreal_dec_status(struct vdec_s *vdec, struct vdec_info *vstatus) { + if (!(stat & STAT_VDEC_RUN)) + return -1; + vstatus->frame_width = vreal_amstream_dec_info.width; vstatus->frame_height = vreal_amstream_dec_info.height; if (0 != vreal_amstream_dec_info.rate) @@ -793,6 +801,7 @@ static void load_block_data(void *dest, unsigned int count) s32 vreal_init(struct vdec_s *vdec) { int ret = -1, size = -1; + char fw_name[32] = {0}; char *buf = vmalloc(0x1000 * 16); if (IS_ERR_OR_NULL(buf)) @@ -832,10 +841,12 @@ s32 vreal_init(struct vdec_s *vdec) while (READ_VREG(LMEM_DMA_CTRL) & 0x8000) ; size = get_firmware_data(VIDEO_DEC_REAL_V8, buf); + strncpy(fw_name, "vreal_mc_8", sizeof(fw_name)); pr_info("load VIDEO_DEC_FORMAT_REAL_8\n"); } else if (vreal_amstream_dec_info.format == VIDEO_DEC_FORMAT_REAL_9) { size = get_firmware_data(VIDEO_DEC_REAL_V9, buf); + strncpy(fw_name, "vreal_mc_9", sizeof(fw_name)); pr_info("load VIDEO_DEC_FORMAT_REAL_9\n"); } else @@ -848,12 +859,14 @@ s32 vreal_init(struct vdec_s *vdec) vfree(buf); return -1; } - if (size == 1) - pr_info ("tee load ok"); - else if (amvdec_loadmc_ex(VFORMAT_REAL, NULL, buf) < 0) { + + ret = amvdec_loadmc_ex(VFORMAT_REAL, fw_name, buf); + if (ret < 0) { rmparser_release(); amvdec_disable(); vfree(buf); + pr_err("%s: the %s fw loading failed, err: %x\n", + fw_name, tee_enabled() ? "TEE" : "local", ret); return -EBUSY; } @@ -935,6 +948,7 @@ static int amvdec_real_probe(struct platform_device *pdev) if (vreal_init(pdata) < 0) { pr_info("amvdec_real init failed.\n"); + pdata->dec_status = NULL; return -ENODEV; } INIT_WORK(&set_clk_work, vreal_set_clk); diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/utils/Makefile b/drivers/amlogic/media_modules/frame_provider/decoder/utils/Makefile index 92eadc3e6ff2..ee7dbf425f11 100644 --- a/drivers/amlogic/media_modules/frame_provider/decoder/utils/Makefile +++ b/drivers/amlogic/media_modules/frame_provider/decoder/utils/Makefile @@ -2,3 +2,6 @@ obj-m += decoder_common.o decoder_common-objs += utils.o vdec.o vdec_input.o amvdec.o decoder_common-objs += decoder_mmu_box.o decoder_bmmu_box.o decoder_common-objs += config_parser.o secprot.o vdec_profile.o +decoder_common-objs += amstream_profile.o +decoder_common-objs += frame_check.o amlogic_fbc_hook.o + diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/utils/amlogic_fbc_hook.c b/drivers/amlogic/media_modules/frame_provider/decoder/utils/amlogic_fbc_hook.c new file mode 100644 index 000000000000..b6179fb9a629 --- /dev/null +++ b/drivers/amlogic/media_modules/frame_provider/decoder/utils/amlogic_fbc_hook.c @@ -0,0 +1,104 @@ +/* + * drivers/amlogic/media/frame_provider/decoder/utils/amlogic_fbc_hook.c + * + * Copyright (C) 2016 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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 +#include +#include + +#include "amlogic_fbc_hook.h" +static AMLOGIC_FBC_vframe_decoder_fun_t g_decoder_fun; +static AMLOGIC_FBC_vframe_encoder_fun_t g_encoder_fun; + + +int AMLOGIC_FBC_vframe_decoder( + void *dstyuv[4], + struct vframe_s *vf, + int out_format, + int flags) + +{ + if (g_decoder_fun) { + return g_decoder_fun(dstyuv, + vf, + out_format, + flags); + } + printk("no AMLOGIC_FBC_vframe_decoder ERRR!!\n"); + return -1; +} +EXPORT_SYMBOL(AMLOGIC_FBC_vframe_decoder); + +int AMLOGIC_FBC_vframe_encoder( + void *srcyuv[4], + void *dst_header, + void *dst_body, + int in_format, + int flags) + +{ + if (g_encoder_fun) { + return g_encoder_fun( + srcyuv, + dst_header, + dst_body, + in_format, + flags); + } + printk("no AMLOGIC_FBC_vframe_encoder ERRR!!\n"); + return -1; +} +EXPORT_SYMBOL(AMLOGIC_FBC_vframe_encoder); + +int register_amlogic_afbc_dec_fun(AMLOGIC_FBC_vframe_decoder_fun_t fn) +{ + if (g_decoder_fun) { + pr_err("error!!,AMLOGIC_FBC dec have register\n"); + return -1; + } + printk("register_amlogic_afbc_dec_fun\n"); + g_decoder_fun = fn; + return 0; +} +EXPORT_SYMBOL(register_amlogic_afbc_dec_fun); + +int register_amlogic_afbc_enc_fun(AMLOGIC_FBC_vframe_encoder_fun_t fn) +{ + if (g_encoder_fun) { + pr_err("error!!,AMLOGIC_FBC enc have register\n"); + return -1; + } + g_encoder_fun = fn; + return 0; +} +EXPORT_SYMBOL(register_amlogic_afbc_enc_fun); + +int unregister_amlogic_afbc_dec_fun(void) +{ + g_decoder_fun = NULL; + pr_err("unregister_amlogic_afbc_dec_fun\n"); + return 0; +} +EXPORT_SYMBOL(unregister_amlogic_afbc_dec_fun); + +int unregister_amlogic_afbc_enc_fun(void) +{ + g_encoder_fun = NULL; + pr_err("unregister_amlogic_afbc_dec_fun\n"); + return 0; +} +EXPORT_SYMBOL(unregister_amlogic_afbc_enc_fun); + + diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/utils/amlogic_fbc_hook.h b/drivers/amlogic/media_modules/frame_provider/decoder/utils/amlogic_fbc_hook.h new file mode 100644 index 000000000000..7eec4b719e9f --- /dev/null +++ b/drivers/amlogic/media_modules/frame_provider/decoder/utils/amlogic_fbc_hook.h @@ -0,0 +1,55 @@ +/* + * drivers/amlogic/media/frame_provider/decoder/utils/amlogic_fbc_hook.h + * + * Copyright (C) 2016 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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 AMLGIC_FBC_HEADER___ +#define AMLGIC_FBC_HEADER___ +#include +/* +unsigned short *planes[4], + unsigned char *buf, + unsigned *v2_head_buf // v2_head_buf_size=(((frame_info->mbw + 1)>>1)*2) * (((frame_info->mbh + 15)>>4)*16) +); +*/ + +int AMLOGIC_FBC_vframe_decoder( + void *dstyuv[4], + struct vframe_s *vf, + int out_format, + int flags); +int AMLOGIC_FBC_vframe_encoder( + void *srcyuv[4], + void *dst_header, + void *dst_body, + int in_format, + int flags); + +typedef int (*AMLOGIC_FBC_vframe_decoder_fun_t)( + void **, + struct vframe_s *, + int, + int); +typedef int (*AMLOGIC_FBC_vframe_encoder_fun_t)( + void **, + void *, + void *, + int, + int); +int register_amlogic_afbc_dec_fun(AMLOGIC_FBC_vframe_decoder_fun_t fn); +int register_amlogic_afbc_enc_fun(AMLOGIC_FBC_vframe_encoder_fun_t fn); +int unregister_amlogic_afbc_dec_fun(void); +int unregister_amlogic_afbc_enc_fun(void); +#endif \ No newline at end of file diff --git a/drivers/amlogic/media_modules/stream_input/amports/amstream_profile.c b/drivers/amlogic/media_modules/frame_provider/decoder/utils/amstream_profile.c similarity index 91% rename from drivers/amlogic/media_modules/stream_input/amports/amstream_profile.c rename to drivers/amlogic/media_modules/frame_provider/decoder/utils/amstream_profile.c index a2bc5564209f..93f50c793068 100644 --- a/drivers/amlogic/media_modules/stream_input/amports/amstream_profile.c +++ b/drivers/amlogic/media_modules/frame_provider/decoder/utils/amstream_profile.c @@ -20,7 +20,6 @@ #include #include #include -#include "amports_priv.h" static const struct codec_profile_t *vcodec_profile[SUPPORT_VDEC_NUM] = { 0 }; @@ -32,12 +31,13 @@ ssize_t vcodec_profile_read(char *buf) int i = 0; for (i = 0; i < vcodec_profile_idx; i++) { - pbuf += sprintf(pbuf, "%s:%s;\n", vcodec_profile[i]->name, + pbuf += snprintf(pbuf, PAGE_SIZE - (pbuf - buf), "%s:%s;\n", vcodec_profile[i]->name, vcodec_profile[i]->profile); } return pbuf - buf; } +EXPORT_SYMBOL(vcodec_profile_read); int vcodec_profile_register(const struct codec_profile_t *vdec_profile) { diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/utils/amvdec.c b/drivers/amlogic/media_modules/frame_provider/decoder/utils/amvdec.c index 7289fece7d21..1d4e6f5a49eb 100644 --- a/drivers/amlogic/media_modules/frame_provider/decoder/utils/amvdec.c +++ b/drivers/amlogic/media_modules/frame_provider/decoder/utils/amvdec.c @@ -14,7 +14,7 @@ * more details. * */ - +#define DEBUG #include #include #include @@ -44,6 +44,7 @@ #include #include "firmware.h" #include +#include "../../../common/chips/decoder_cpu_ver_info.h" #define MC_SIZE (4096 * 16) @@ -73,14 +74,14 @@ static void amvdec_pg_enable(bool enable) /* AMVDEC_CLK_GATE_ON(VLD_CLK); */ AMVDEC_CLK_GATE_ON(AMRISC); /* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6TVD */ - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M8) + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M8) WRITE_VREG(GCLK_EN, 0x3ff); /* #endif */ CLEAR_VREG_MASK(MDEC_PIC_DC_CTRL, 1 << 31); } else { AMVDEC_CLK_GATE_OFF(AMRISC); - timeout = jiffies + HZ / 10; + timeout = jiffies + HZ / 100; while (READ_VREG(MDEC_PIC_DC_STATUS) != 0) { if (time_after(jiffies, timeout)) { @@ -94,7 +95,7 @@ static void amvdec_pg_enable(bool enable) } AMVDEC_CLK_GATE_OFF(MDEC_CLK_PIC_DC); - timeout = jiffies + HZ / 10; + timeout = jiffies + HZ / 100; while (READ_VREG(DBLK_STATUS) & 1) { if (time_after(jiffies, timeout)) { @@ -107,7 +108,7 @@ static void amvdec_pg_enable(bool enable) } } AMVDEC_CLK_GATE_OFF(MDEC_CLK_DBLK); - timeout = jiffies + HZ / 10; + timeout = jiffies + HZ / 100; while (READ_VREG(MC_STATUS0) & 1) { if (time_after(jiffies, timeout)) { @@ -120,7 +121,7 @@ static void amvdec_pg_enable(bool enable) } } AMVDEC_CLK_GATE_OFF(MC_CLK); - timeout = jiffies + HZ / 10; + timeout = jiffies + HZ / 100; while (READ_VREG(DCAC_DMA_CTRL) & 0x8000) { if (time_after(jiffies, timeout)) break; @@ -266,7 +267,7 @@ static s32 am_vdec_loadmc_ex(struct vdec_s *vdec, pr_err("loading firmware %s to vdec ram failed!\n", name); return err; } - pr_debug("loading firmware %s to vdec ram ok!\n", name); + return err; } @@ -285,7 +286,7 @@ static s32 am_vdec_loadmc_buf_ex(struct vdec_s *vdec, pr_err("loading firmware to vdec ram failed!\n"); return err; } - pr_debug("loading firmware to vdec ram ok!\n"); + return err; } @@ -311,10 +312,11 @@ static s32 am_loadmc_ex(enum vformat_e type, err = (*load)((u32 *) pmc_addr); if (err < 0) { pr_err("loading firmware %s to vdec ram failed!\n", name); + vfree(mc_addr); return err; } vfree(mc_addr); - pr_debug("loading firmware %s to vdec ram ok!\n", name); + return err; } @@ -379,6 +381,7 @@ s32 optee_load_fw(enum vformat_e type, const char *fw_name) unsigned int format = FIRMWARE_MAX; unsigned int vdec = OPTEE_VDEC_LEGENCY; char *name = __getname(); + bool is_swap = false; sprintf(name, "%s", fw_name ? fw_name : "null"); @@ -395,11 +398,17 @@ s32 optee_load_fw(enum vformat_e type, const char *fw_name) break; case VFORMAT_MPEG12: - format = VIDEO_DEC_MPEG12; + if (!strcmp(name, "mpeg12")) + format = VIDEO_DEC_MPEG12; + else if (!strcmp(name, "mmpeg12")) + format = VIDEO_DEC_MPEG12_MULTI; break; case VFORMAT_MJPEG: - format = VIDEO_DEC_MJPEG; + if (!strcmp(name, "mmjpeg")) + format = VIDEO_DEC_MJPEG_MULTI; + else + format = VIDEO_DEC_MJPEG; break; case VFORMAT_VP9: @@ -415,10 +424,14 @@ s32 optee_load_fw(enum vformat_e type, const char *fw_name) break; case VFORMAT_HEVC: - if (!strcmp(name, "vh265_mc")) - format = VIDEO_DEC_HEVC; - else + if (!strcmp(name, "h265_mmu")) format = VIDEO_DEC_HEVC_MMU; + else if (!strcmp(name, "hevc_mmu_swap")) { + format = VIDEO_DEC_HEVC_MMU_SWAP; + vdec = OPTEE_VDEC_HEVC; + is_swap = true; + } else + format = VIDEO_DEC_HEVC; break; case VFORMAT_REAL: @@ -429,30 +442,53 @@ s32 optee_load_fw(enum vformat_e type, const char *fw_name) break; case VFORMAT_MPEG4: - if (!strcmp(name, "vmpeg4_mc_311")) - format = VIDEO_DEC_MPEG4_3; - else if (!strcmp(name, "vmpeg4_mc_4")) - format = VIDEO_DEC_MPEG4_4; + if (!strcmp(name, "mmpeg4_mc_5")) + format = VIDEO_DEC_MPEG4_5_MULTI; + else if ((!strcmp(name, "mh263_mc"))) + format = VIDEO_DEC_H263_MULTI; else if (!strcmp(name, "vmpeg4_mc_5")) format = VIDEO_DEC_MPEG4_5; else if (!strcmp(name, "h263_mc")) - format = VIDEO_DEC_FORMAT_H263; + format = VIDEO_DEC_H263; + /*not support now*/ + else if (!strcmp(name, "vmpeg4_mc_311")) + format = VIDEO_DEC_MPEG4_3; + else if (!strcmp(name, "vmpeg4_mc_4")) + format = VIDEO_DEC_MPEG4_4; + break; + + case VFORMAT_H264_4K2K: + if (!strcmp(name, "single_core")) + format = VIDEO_DEC_H264_4k2K_SINGLE; + else + format = VIDEO_DEC_H264_4k2K; + break; + + case VFORMAT_H264MVC: + format = VIDEO_DEC_H264_MVC; + break; + + case VFORMAT_H264: + if (!strcmp(name, "mh264")) + format = VIDEO_DEC_H264_MULTI; + else if (!strcmp(name, "mh264_mmu")) { + format = VIDEO_DEC_H264_MULTI_MMU; + vdec = OPTEE_VDEC_HEVC; + } else + format = VIDEO_DEC_H264; break; default: - if (!strcmp(name, "vh265_mc")) - format = VIDEO_DEC_HEVC; - else if (!strcmp(name, "vh265_mc_mmu")) - format = VIDEO_DEC_HEVC_MMU; - else if (!strcmp(name, "vmmjpeg_mc")) - format = VIDEO_DEC_MJPEG_MULTI; - else - pr_info("unknow dec format\n"); + pr_info("Unknow vdec format!\n"); break; } - if (format < FIRMWARE_MAX) - ret = tee_load_video_fw(format, vdec); + if (format < FIRMWARE_MAX) { + if (is_swap) + ret = tee_load_video_fw_swap(format, vdec, is_swap); + else + ret = tee_load_video_fw(format, vdec); + } __putname(name); @@ -469,18 +505,23 @@ s32 amvdec_loadmc_ex(enum vformat_e type, const char *name, char *def) } EXPORT_SYMBOL(amvdec_loadmc_ex); -s32 amvdec_vdec_loadmc_ex(struct vdec_s *vdec, const char *name, char *def) +s32 amvdec_vdec_loadmc_ex(enum vformat_e type, const char *name, + struct vdec_s *vdec, char *def) { if (tee_enabled()) - return optee_load_fw(FIRMWARE_MAX, name); + return optee_load_fw(type, name); else - return am_vdec_loadmc_ex(vdec, name, def, &amvdec_loadmc); + return am_vdec_loadmc_ex(vdec, name, def, &amvdec_loadmc); } EXPORT_SYMBOL(amvdec_vdec_loadmc_ex); -s32 amvdec_vdec_loadmc_buf_ex(struct vdec_s *vdec, char *buf, int size) +s32 amvdec_vdec_loadmc_buf_ex(enum vformat_e type, const char *name, + struct vdec_s *vdec, char *buf, int size) { - return am_vdec_loadmc_buf_ex(vdec, buf, size, &amvdec_loadmc); + if (tee_enabled()) + return optee_load_fw(type, name); + else + return am_vdec_loadmc_buf_ex(vdec, buf, size, &amvdec_loadmc); } EXPORT_SYMBOL(amvdec_vdec_loadmc_buf_ex); @@ -659,19 +700,20 @@ s32 amhevc_loadmc_ex(enum vformat_e type, const char *name, char *def) else return am_loadmc_ex(type, name, def, &amhevc_loadmc); else - return 0; + return -1; } EXPORT_SYMBOL(amhevc_loadmc_ex); -s32 amhevc_vdec_loadmc_ex(struct vdec_s *vdec, const char *name, char *def) +s32 amhevc_vdec_loadmc_ex(enum vformat_e type, struct vdec_s *vdec, + const char *name, char *def) { if (has_hevc_vdec()) if (tee_enabled()) - return optee_load_fw(FIRMWARE_MAX, name); + return optee_load_fw(type, name); else - return am_vdec_loadmc_ex(vdec, name, def, &amhevc_loadmc); + return am_vdec_loadmc_ex(vdec, name, def, &amhevc_loadmc); else - return 0; + return -1; } EXPORT_SYMBOL(amhevc_vdec_loadmc_ex); @@ -682,7 +724,7 @@ void amvdec_start(void) #endif /* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */ - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M6) { + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M6) { READ_VREG(DOS_SW_RESET0); READ_VREG(DOS_SW_RESET0); READ_VREG(DOS_SW_RESET0); @@ -768,7 +810,7 @@ EXPORT_SYMBOL(amhevc_start); void amvdec_stop(void) { - ulong timeout = jiffies + HZ; + ulong timeout = jiffies + HZ/10; WRITE_VREG(MPSR, 0); WRITE_VREG(CPSR, 0); @@ -778,8 +820,14 @@ void amvdec_stop(void) break; } + timeout = jiffies + HZ/10; + while (READ_VREG(LMEM_DMA_CTRL) & 0x8000) { + if (time_after(jiffies, timeout)) + break; + } + /* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */ - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M6) { + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M6) { READ_VREG(DOS_SW_RESET0); READ_VREG(DOS_SW_RESET0); READ_VREG(DOS_SW_RESET0); @@ -811,7 +859,7 @@ EXPORT_SYMBOL(amvdec_stop); void amvdec2_stop(void) { if (has_vdec2()) { - ulong timeout = jiffies + HZ; + ulong timeout = jiffies + HZ/10; WRITE_VREG(VDEC2_MPSR, 0); WRITE_VREG(VDEC2_CPSR, 0); @@ -841,7 +889,7 @@ EXPORT_SYMBOL(amhcodec_stop); void amhevc_stop(void) { if (has_hevc_vdec()) { - ulong timeout = jiffies + HZ; + ulong timeout = jiffies + HZ/10; WRITE_VREG(HEVC_MPSR, 0); WRITE_VREG(HEVC_CPSR, 0); @@ -851,6 +899,12 @@ void amhevc_stop(void) break; } + timeout = jiffies + HZ/10; + while (READ_VREG(HEVC_LMEM_DMA_CTRL) & 0x8000) { + if (time_after(jiffies, timeout)) + break; + } + READ_VREG(DOS_SW_RESET3); READ_VREG(DOS_SW_RESET3); READ_VREG(DOS_SW_RESET3); diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/utils/amvdec.h b/drivers/amlogic/media_modules/frame_provider/decoder/utils/amvdec.h index 8a269ad977ab..a3deecd916e7 100644 --- a/drivers/amlogic/media_modules/frame_provider/decoder/utils/amvdec.h +++ b/drivers/amlogic/media_modules/frame_provider/decoder/utils/amvdec.h @@ -38,7 +38,8 @@ extern void amvdec_stop(void); extern void amvdec_enable(void); extern void amvdec_disable(void); s32 amvdec_loadmc_ex(enum vformat_e type, const char *name, char *def); -s32 amvdec_vdec_loadmc_ex(struct vdec_s *vdec, const char *name, char *def); +s32 amvdec_vdec_loadmc_ex(enum vformat_e type, const char *name, + struct vdec_s *vdec, char *def); extern void amvdec2_start(void); extern void amvdec2_stop(void); @@ -51,8 +52,10 @@ extern void amhevc_stop(void); extern void amhevc_enable(void); extern void amhevc_disable(void); s32 amhevc_loadmc_ex(enum vformat_e type, const char *name, char *def); -s32 amhevc_vdec_loadmc_ex(struct vdec_s *vdec, const char *name, char *def); -s32 amvdec_vdec_loadmc_buf_ex(struct vdec_s *vdec, char *buf, int size); +s32 amhevc_vdec_loadmc_ex(enum vformat_e type, struct vdec_s *vdec, + const char *name, char *def); +s32 amvdec_vdec_loadmc_buf_ex(enum vformat_e type, const char *name, + struct vdec_s *vdec, char *buf, int size); extern void amhcodec_start(void); extern void amhcodec_stop(void); diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/utils/decoder_bmmu_box.c b/drivers/amlogic/media_modules/frame_provider/decoder/utils/decoder_bmmu_box.c index fe00832b061c..590b812d36dc 100644 --- a/drivers/amlogic/media_modules/frame_provider/decoder/utils/decoder_bmmu_box.c +++ b/drivers/amlogic/media_modules/frame_provider/decoder/utils/decoder_bmmu_box.c @@ -32,6 +32,7 @@ #include #include "decoder_bmmu_box.h" #include +#include struct decoder_bmmu_box { int max_mm_num; @@ -133,19 +134,28 @@ int decoder_bmmu_box_alloc_idx(void *handle, int idx, int size, int aligned_2n, mm = box->mm_list[idx]; if (mm) { int invalid = 0; + int keeped = 0; - if (mm->page_count * PAGE_SIZE < size) { - /*size is small. */ - invalid = 1; - } else if (box->change_size_on_need_smaller && - (mm->buffer_size > (size << 1))) { - /*size is too large. */ - invalid = 2; - } else if (mm->phy_addr & ((1 << align) - 1)) { - /*addr is not align */ - invalid = 4; - } - if (invalid) { + keeped = is_codec_mm_keeped(mm); + if (!keeped) { + if (mm->page_count * PAGE_SIZE < size) { + /*size is small. */ + invalid = 1; + } else if (box->change_size_on_need_smaller && + (mm->buffer_size > (size << 1))) { + /*size is too large. */ + invalid = 2; + } else if (mm->phy_addr & ((1 << align) - 1)) { + /*addr is not align */ + invalid = 4; + } + if (invalid) { + box->total_size -= mm->buffer_size; + codec_mm_release(mm, box->name); + box->mm_list[idx] = NULL; + mm = NULL; + } + } else { box->total_size -= mm->buffer_size; codec_mm_release(mm, box->name); box->mm_list[idx] = NULL; @@ -173,7 +183,7 @@ int decoder_bmmu_box_free_idx(void *handle, int idx) if (!box || idx < 0 || idx >= box->max_mm_num) { pr_err("can't free idx of box(%p),idx:%d in (%d-%d)\n", box, idx, 0, - box->max_mm_num - 1); + box ? (box->max_mm_num - 1) : 0); return -1; } mutex_lock(&box->mutex); @@ -289,15 +299,29 @@ int decoder_bmmu_box_alloc_idx_wait( { int have_space; int ret = -1; + int keeped = 0; - if (decoder_bmmu_box_get_mem_size(handle, idx) >= size) - return 0;/*have alloced memery before.*/ + if (decoder_bmmu_box_get_mem_size(handle, idx) >= size) { + struct decoder_bmmu_box *box = handle; + struct codec_mm_s *mm; + mutex_lock(&box->mutex); + mm = box->mm_list[idx]; + keeped = is_codec_mm_keeped(mm); + mutex_unlock(&box->mutex); + + if (!keeped) + return 0;/*have alloced memery before.*/ + } have_space = decoder_bmmu_box_check_and_wait_size( size, wait_flags); if (have_space) { ret = decoder_bmmu_box_alloc_idx(handle, idx, size, aligned_2n, mem_flags); + if (ret == -ENOMEM) { + pr_info("bmmu alloc idx fail, try free keep video.\n"); + try_free_keep_video(1); + } } else { try_free_keep_video(1); ret = -ENOMEM; @@ -335,7 +359,7 @@ int decoder_bmmu_box_alloc_buf_phy( * driver_name, idx, *buf_phy_addr, size); */ } else { - pr_info("%s malloc failed %d\n", driver_name, idx); + pr_info("%s malloc failed %d\n", driver_name, idx); return -ENOMEM; } @@ -353,7 +377,7 @@ static int decoder_bmmu_box_dump(struct decoder_bmmu_box *box, void *buf, int i; if (!buf) { pbuf = sbuf; - size = 100000; + size = 512; } #define BUFPRINT(args...) \ do {\ @@ -397,7 +421,7 @@ static int decoder_bmmu_box_dump_all(void *buf, int size) struct list_head *head, *list; if (!buf) { pbuf = sbuf; - size = 100000; + size = 512; } #define BUFPRINT(args...) \ do {\ diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/utils/decoder_mmu_box.c b/drivers/amlogic/media_modules/frame_provider/decoder/utils/decoder_mmu_box.c index 6135394b5735..cc9e7a906666 100644 --- a/drivers/amlogic/media_modules/frame_provider/decoder/utils/decoder_mmu_box.c +++ b/drivers/amlogic/media_modules/frame_provider/decoder/utils/decoder_mmu_box.c @@ -74,6 +74,16 @@ static int decoder_mmu_box_mgr_del_box(struct decoder_mmu_box *box) return 0; } +int decoder_mmu_box_sc_check(void *handle, int is_tvp) +{ + struct decoder_mmu_box *box = handle; + if (!box) { + pr_err("mmu box NULL !!!\n"); + return 0; + } + return codec_mm_scatter_size(is_tvp); +} +EXPORT_SYMBOL(decoder_mmu_box_sc_check); void *decoder_mmu_box_alloc_box(const char *name, @@ -152,7 +162,6 @@ int decoder_mmu_box_alloc_idx( for (i = 0; i < num_pages; i++) mmu_index_adr[i] = PAGE_INDEX(sc->pages_list[i]); - mmu_index_adr[num_pages] = 0; mutex_unlock(&box->mutex); @@ -170,7 +179,7 @@ int decoder_mmu_box_free_idx_tail( if (!box || idx < 0 || idx >= box->max_sc_num) { pr_err("can't free tail mmu box(%p),idx:%d in (%d-%d)\n", box, idx, 0, - box->max_sc_num - 1); + box ? (box->max_sc_num - 1) : 0); return -1; } mutex_lock(&box->mutex); @@ -191,7 +200,7 @@ int decoder_mmu_box_free_idx(void *handle, int idx) if (!box || idx < 0 || idx >= box->max_sc_num) { pr_err("can't free idx of box(%p),idx:%d in (%d-%d)\n", box, idx, 0, - box->max_sc_num - 1); + box ? (box->max_sc_num - 1) : 0); return -1; } mutex_lock(&box->mutex); @@ -251,7 +260,7 @@ static int decoder_mmu_box_dump(struct decoder_mmu_box *box, if (!buf) { pbuf = sbuf; - size = 100000; + size = 512; } #define BUFPRINT(args...) \ do {\ @@ -288,7 +297,7 @@ static int decoder_mmu_box_dump_all(void *buf, int size) if (!pbuf) { pbuf = sbuf; - size = 100000; + size = 512; } #define BUFPRINT(args...) \ diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/utils/decoder_mmu_box.h b/drivers/amlogic/media_modules/frame_provider/decoder/utils/decoder_mmu_box.h index 4aa9bf5ba781..9f4e0987567b 100644 --- a/drivers/amlogic/media_modules/frame_provider/decoder/utils/decoder_mmu_box.h +++ b/drivers/amlogic/media_modules/frame_provider/decoder/utils/decoder_mmu_box.h @@ -24,6 +24,8 @@ void *decoder_mmu_box_alloc_box(const char *name, int min_size_M, int mem_flags); +int decoder_mmu_box_sc_check(void *handle, int is_tvp); + int decoder_mmu_box_alloc_idx( void *handle, int idx, int num_pages, unsigned int *mmu_index_adr); diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/utils/firmware.h b/drivers/amlogic/media_modules/frame_provider/decoder/utils/firmware.h index 17f64e430b72..c799fd091a3a 100644 --- a/drivers/amlogic/media_modules/frame_provider/decoder/utils/firmware.h +++ b/drivers/amlogic/media_modules/frame_provider/decoder/utils/firmware.h @@ -1,3 +1,22 @@ +/* +* 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. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ #ifndef __VIDEO_FIRMWARE_HEADER_ #define __VIDEO_FIRMWARE_HEADER_ @@ -8,6 +27,7 @@ #define FW_LOAD_TRY (0X2) struct firmware_s { + char name[32]; unsigned int len; char data[0]; }; diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/utils/frame_check.c b/drivers/amlogic/media_modules/frame_provider/decoder/utils/frame_check.c new file mode 100644 index 000000000000..e783dbc41ae0 --- /dev/null +++ b/drivers/amlogic/media_modules/frame_provider/decoder/utils/frame_check.c @@ -0,0 +1,1161 @@ +/* + * drivers/amlogic/media/frame_provider/decoder/utils/frame_check.c + * + * Copyright (C) 2016 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "vdec.h" +#include "frame_check.h" +#include "amlogic_fbc_hook.h" +#include +#include +#include "../../../common/chips/decoder_cpu_ver_info.h" + + +#define FC_ERROR 0x0 + +#define FC_YUV_DEBUG 0x01 +#define FC_CRC_DEBUG 0x02 +#define FC_TST_DEBUG 0x80 +#define FC_ERR_CRC_BLOCK_MODE 0x10 +#define FC_CHECK_CRC_LOOP_MODE 0x20 + +#define YUV_MASK 0x01 +#define CRC_MASK 0x02 + +#define YUV_DEF_SIZE (1920*1088*3/2) +#define YUV_DEF_NUM 1 + +#define MAX_SIZE_AFBC_PLANES (4096 * 2048) + +#define VMAP_STRIDE_SIZE (1024*1024) + +static unsigned int fc_debug; +static unsigned int size_yuv_buf = (YUV_DEF_SIZE * YUV_DEF_NUM); + +#define dbg_print(mask, ...) do { \ + if ((fc_debug & mask) || \ + (mask == FC_ERROR)) \ + printk("[FRMAE_CHECK] "__VA_ARGS__);\ + } while(0) + + +#define CRC_PATH "/data/tmp/" +#define YUV_PATH "/data/tmp/" +static char comp_crc[128] = "name"; + +static struct vdec_s *single_mode_vdec = NULL; + +static unsigned int yuv_enable, check_enable; +static unsigned int yuv_start[MAX_INSTANCE_MUN]; +static unsigned int yuv_num[MAX_INSTANCE_MUN]; + + +static inline void set_enable(struct pic_check_mgr_t *p, int mask) +{ + p->enable |= mask; +} + +static inline void set_disable(struct pic_check_mgr_t *p, int mask) +{ + p->enable &= (~mask); +} + +static inline void check_schedule(struct pic_check_mgr_t *mgr) +{ + if (atomic_read(&mgr->work_inited)) + vdec_schedule_work(&mgr->frame_check_work); +} + +static int get_frame_size(struct pic_check_mgr_t *pic, + struct vframe_s *vf) +{ + if ((vf->width < 1) || (vf->height < 1)) + return -1; + pic->size_y = vf->width* vf->height; + pic->size_uv = pic->size_y >> 1; + pic->size_pic = pic->size_y + pic->size_uv; + + if (!(vf->type & VIDTYPE_VIU_NV21)) + return 0; + + if ((vf->canvas0Addr == vf->canvas1Addr) && + (vf->canvas0Addr != 0) && + (vf->canvas0Addr != -1)) { + pic->canvas_w = + canvas_get_width(canvasY(vf->canvas0Addr)); + pic->canvas_h = + canvas_get_height(canvasY(vf->canvas0Addr)); + } else { + pic->canvas_w = vf->canvas0_config[0].width; + pic->canvas_h = vf->canvas0_config[1].height; + } + + if ((pic->canvas_h < 1) || (pic->canvas_w < 1)) { + dbg_print(FC_ERROR, "(canvas,pic) w(%d,%d), h(%d,%d)\n", + pic->canvas_w, vf->width, pic->canvas_h, vf->height); + return -1; + } +/* + int blkmod; + blkmod = canvas_get_blkmode(canvasY(vf->canvas0Addr)); + if (blkmod != CANVAS_BLKMODE_LINEAR) { + dbg_print(0, "WARN: canvas blkmod %x\n", blkmod); + } +*/ + return 0; +} + +static int canvas_get_virt_addr(struct pic_check_mgr_t *pic, + struct vframe_s *vf) +{ + int phy_y_addr, phy_uv_addr; + void *vaddr_y, *vaddr_uv; + + if ((vf->canvas0Addr == vf->canvas1Addr) && + (vf->canvas0Addr != 0) && + (vf->canvas0Addr != -1)) { + phy_y_addr = canvas_get_addr(canvasY(vf->canvas0Addr)); + phy_uv_addr = canvas_get_addr(canvasUV(vf->canvas0Addr)); + } else { + phy_y_addr = vf->canvas0_config[0].phy_addr; + phy_uv_addr = vf->canvas0_config[1].phy_addr; + } + vaddr_y = codec_mm_phys_to_virt(phy_y_addr); + vaddr_uv = codec_mm_phys_to_virt(phy_uv_addr); + + if (((!vaddr_y) || (!vaddr_uv)) && ((!phy_y_addr) || (!phy_uv_addr))) { + dbg_print(FC_ERROR, "%s, y_addr %p(0x%x), uv_addr %p(0x%x)\n", + __func__, vaddr_y, phy_y_addr, vaddr_uv, phy_uv_addr); + return -1; + } + pic->y_vaddr = vaddr_y; + pic->uv_vaddr = vaddr_uv; + pic->y_phyaddr = phy_y_addr; + pic->uv_phyaddr = phy_uv_addr; + + return 0; +} + +static int str_strip(char *str) +{ + char *s = str; + int i = 0; + + while (s[i]) { + if (s[i] == '\n') + s[i] = 0; + else if (s[i] == ' ') + s[i] = '_'; + i++; + } + + return i; +} + +static char *fget_crc_str(char *buf, + unsigned int size, struct pic_check_t *fc) +{ + unsigned int c = 0, sz, ret, index, crc1, crc2; + mm_segment_t old_fs; + char *cs; + + if (!fc->compare_fp) + return NULL; + + old_fs = get_fs(); + set_fs(KERNEL_DS); + + do { + cs = buf; + sz = size; + while (--sz && (c = vfs_read(fc->compare_fp, + cs, 1, &fc->compare_pos) != 0)) { + if (*cs++ == '\n') + break; + } + *cs = '\0'; + if ((c == 0) && (cs == buf)) { + set_fs(old_fs); + return NULL; + } + ret = sscanf(buf, "%08u: %8x %8x", &index, &crc1, &crc2); + dbg_print(FC_CRC_DEBUG, "%s, index = %d, cmp = %d\n", + __func__, index, fc->cmp_crc_cnt); + }while(ret != 3 || index != fc->cmp_crc_cnt); + + set_fs(old_fs); + fc->cmp_crc_cnt++; + + return buf; +} + +static struct file* file_open(int mode, const char *str, ...) +{ + char file[256] = {0}; + struct file* fp = NULL; + va_list args; + + va_start(args, str); + vsnprintf(file, sizeof(file), str, args); + + fp = filp_open(file, mode, (mode&O_CREAT)?0666:0); + if (IS_ERR(fp)) { + fp = NULL; + dbg_print(FC_ERROR, "open %s failed\n", file); + return fp; + } + dbg_print(FC_ERROR, "open %s success\n", file); + va_end(args); + + return fp; +} + +static int write_yuv_work(struct pic_check_mgr_t *mgr) +{ + mm_segment_t old_fs; + unsigned int i, wr_size; + struct pic_dump_t *dump = &mgr->pic_dump; + + if (dump->dump_cnt > 0) { + if (!dump->yuv_fp) { + dump->yuv_fp = file_open(O_CREAT | O_WRONLY | O_TRUNC, + "%s%s-%d-%d.yuv", YUV_PATH, comp_crc, mgr->id, mgr->file_cnt); + dump->yuv_pos = 0; + } + + if ((mgr->enable & YUV_MASK) && + (dump->yuv_fp != NULL) && + (dump->dump_cnt >= dump->num)) { + + old_fs = get_fs(); + set_fs(KERNEL_DS); + + for (i = 0; dump->dump_cnt > 0; i++) { + wr_size = vfs_write(dump->yuv_fp, + (dump->buf_addr + i * mgr->size_pic), + mgr->size_pic, &dump->yuv_pos); + if (mgr->size_pic != wr_size) { + dbg_print(FC_ERROR, "buf failed to write yuv file\n"); + break; + } + dump->dump_cnt--; + } + set_fs(old_fs); + vfs_fsync(dump->yuv_fp, 0); + + filp_close(dump->yuv_fp, current->files); + dump->yuv_pos = 0; + dump->yuv_fp = NULL; + set_disable(mgr, YUV_MASK); + dbg_print(FC_YUV_DEBUG, + "closed yuv file, dump yuv exit\n"); + dump->num = 0; + dump->dump_cnt = 0; + if (dump->buf_addr != NULL) + vfree(dump->buf_addr); + dump->buf_addr = NULL; + dump->buf_size = 0; + } + } + + return 0; +} + +static int write_crc_work(struct pic_check_mgr_t *mgr) +{ + unsigned int wr_size; + char *crc_buf, crc_tmp[64*30]; + mm_segment_t old_fs; + struct pic_check_t *check = &mgr->pic_check; + + if (mgr->enable & CRC_MASK) { + wr_size = 0; + while (kfifo_get(&check->wr_chk_q, &crc_buf) != 0) { + wr_size += sprintf(&crc_tmp[wr_size], "%s", crc_buf); + if (check->compare_fp != NULL) { + if (!fget_crc_str(crc_buf, SIZE_CRC, check)) { + dbg_print(0, "%s, can't get more compare crc\n", __func__); + filp_close(check->compare_fp, current->files); + check->compare_fp = NULL; + } + } + kfifo_put(&check->new_chk_q, crc_buf); + } + if (check->check_fp && (wr_size != 0)) { + old_fs = get_fs(); + set_fs(KERNEL_DS); + if (wr_size != vfs_write(check->check_fp, + crc_tmp, wr_size, &check->check_pos)) { + dbg_print(FC_ERROR, "failed to check_dump_filp\n"); + } + set_fs(old_fs); + } + } + return 0; +} + +static void do_check_work(struct work_struct *work) +{ + struct pic_check_mgr_t *mgr = container_of(work, + struct pic_check_mgr_t, frame_check_work); + + write_yuv_work(mgr); + + write_crc_work(mgr); +} + +static int memcpy_phy_to_virt(char *to_virt, + ulong phy_from, unsigned int size) +{ + void *vaddr = NULL; + unsigned int tmp_size = 0; + + if (single_mode_vdec != NULL) { + unsigned int offset = phy_from & (~PAGE_MASK); + while (size > 0) { + if (offset + size >= PAGE_SIZE) { + vaddr = kmap_atomic(phys_to_page(phy_from)); + tmp_size = (PAGE_SIZE - offset); + phy_from += tmp_size; + size -= tmp_size; + vaddr += offset; + } else { + vaddr = kmap_atomic(phys_to_page(phy_from)); + vaddr += offset; + tmp_size = size; + size = 0; + } + if (vaddr == NULL) { + dbg_print(FC_CRC_DEBUG, "%s: kmap_atomic failed phy: 0x%x\n", + __func__, (unsigned int)phy_from); + return -1; + } + /* + codec_mm_dma_flush(vaddr, + tmp_size, DMA_FROM_DEVICE); + */ + memcpy(to_virt, vaddr, tmp_size); + + kunmap_atomic(vaddr - offset); + offset = 0; + } + } else { + while (size > 0) { + if (size >= VMAP_STRIDE_SIZE) { + vaddr = codec_mm_vmap(phy_from, VMAP_STRIDE_SIZE); + tmp_size = VMAP_STRIDE_SIZE; + phy_from += VMAP_STRIDE_SIZE; + size -= VMAP_STRIDE_SIZE; + } else { + vaddr = codec_mm_vmap(phy_from, size); + tmp_size = size; + size = 0; + } + if (vaddr == NULL) { + dbg_print(FC_YUV_DEBUG, "%s: codec_mm_vmap failed phy: 0x%x\n", + __func__, (unsigned int)phy_from); + return -1; + } + codec_mm_dma_flush(vaddr, + tmp_size, DMA_FROM_DEVICE); + memcpy(to_virt, vaddr, tmp_size); + to_virt += tmp_size; + + codec_mm_unmap_phyaddr(vaddr); + } + } + return 0; +} + +static int do_yuv_dump(struct pic_check_mgr_t *mgr, struct vframe_s *vf) +{ + int i, ret = 0; + void *tmp_addr, *tmp_yaddr, *tmp_uvaddr; + ulong y_phyaddr, uv_phyaddr; + struct pic_dump_t *dump = &mgr->pic_dump; + /* + if ((vf->type & VIDTYPE_VIU_NV21) == 0) + return 0; + */ + if (dump->start > 0) { + dump->start--; + return 0; + } + + if (dump->dump_cnt >= dump->num) + return 0; + + if (mgr->size_pic > + (dump->buf_size - dump->dump_cnt * mgr->size_pic)) { + if (dump->buf_size) { + dbg_print(FC_ERROR, + "not enough buf, force dump less\n"); + dump->num = dump->dump_cnt; + check_schedule(mgr); + } else + set_disable(mgr, YUV_MASK); + return -1; + } + + tmp_addr = dump->buf_addr + + mgr->size_pic * dump->dump_cnt; + if ((mgr->uv_vaddr == NULL) || (mgr->y_vaddr == NULL)) { + y_phyaddr = mgr->y_phyaddr; + uv_phyaddr = mgr->uv_phyaddr; + if (vf->width == mgr->canvas_w) { + ret |= memcpy_phy_to_virt(tmp_addr, y_phyaddr, mgr->size_y); + ret |= memcpy_phy_to_virt(tmp_addr + mgr->size_y, + uv_phyaddr, mgr->size_uv); + } else { + for (i = 0; i < vf->height; i++) { + ret |= memcpy_phy_to_virt(tmp_addr, y_phyaddr, vf->width); + y_phyaddr += mgr->canvas_w; + tmp_addr += vf->width; + } + for (i = 0; i < vf->height/2; i++) { + ret |= memcpy_phy_to_virt(tmp_addr, uv_phyaddr, vf->width); + uv_phyaddr += mgr->canvas_w; + tmp_addr += vf->width; + } + } + if (ret < 0) { + dbg_print(0, "dump yuv failed, may codec_mm_vmap failed\n"); + return ret; + } + } else { + if (vf->width == mgr->canvas_w) { + memcpy(tmp_addr, mgr->y_vaddr, mgr->size_y); + memcpy(tmp_addr + mgr->size_y, + mgr->uv_vaddr, mgr->size_uv); + } else { + tmp_yaddr = mgr->y_vaddr; + tmp_uvaddr = mgr->uv_vaddr; + for (i = 0; i < vf->height; i++) { + memcpy(tmp_addr, tmp_yaddr, vf->width); + tmp_yaddr += mgr->canvas_w; + tmp_addr += vf->width; + } + for (i = 0; i < vf->height/2; i++) { + memcpy(tmp_addr, tmp_uvaddr, vf->width); + tmp_uvaddr += mgr->canvas_w; + tmp_addr += vf->width; + } + } + } + dump->dump_cnt++; + dbg_print(0, "----->dump frame num: %d, dump %dst, size %x\n", + mgr->frame_cnt, dump->dump_cnt, mgr->size_pic); + + if (dump->dump_cnt >= dump->num) + check_schedule(mgr); + + return 0; +} + +static int crc_store(struct pic_check_mgr_t *mgr, struct vframe_s *vf, + int crc_y, int crc_uv) +{ + int ret = 0; + char *crc_addr = NULL; + int comp_frame = 0, comp_crc_y, comp_crc_uv; + struct pic_check_t *check = &mgr->pic_check; + + if (kfifo_get(&check->new_chk_q, &crc_addr) == 0) { + dbg_print(0, "%08d: %08x %08x\n", + mgr->frame_cnt, crc_y, crc_uv); + if (check->check_fp) { + dbg_print(0, "crc32 dropped\n"); + } else { + dbg_print(0, "no opened file to write crc32\n"); + } + return -1; + } + if (check->cmp_crc_cnt > mgr->frame_cnt) { + sscanf(crc_addr, "%08u: %8x %8x", + &comp_frame, &comp_crc_y, &comp_crc_uv); + + dbg_print(0, "%08d: %08x %08x <--> %08d: %08x %08x\n", + mgr->frame_cnt, crc_y, crc_uv, + comp_frame, comp_crc_y, comp_crc_uv); + + if (comp_frame == mgr->frame_cnt) { + if ((comp_crc_y != crc_y) || (crc_uv != comp_crc_uv)) { + mgr->pic_dump.start = 0; + mgr->pic_dump.num++; + dbg_print(0, "\n\nError: %08d: %08x %08x != %08x %08x\n\n", + mgr->frame_cnt, crc_y, crc_uv, comp_crc_y, comp_crc_uv); + do_yuv_dump(mgr, vf); + if (fc_debug & FC_ERR_CRC_BLOCK_MODE) + mgr->err_crc_block = 1; + } + } else { + dbg_print(0, "frame num error: frame_cnt(%d) frame_comp(%d)\n", + mgr->frame_cnt, comp_frame); + } + } else { + dbg_print(0, "%08d: %08x %08x\n", mgr->frame_cnt, crc_y, crc_uv); + } + + if ((check->check_fp) && (crc_addr != NULL)) { + ret = snprintf(crc_addr, SIZE_CRC, + "%08d: %08x %08x\n", mgr->frame_cnt, crc_y, crc_uv); + + kfifo_put(&check->wr_chk_q, crc_addr); + if ((mgr->frame_cnt & 0xf) == 0) + check_schedule(mgr); + } + return ret; +} + + +static int crc32_vmap_le(unsigned int *crc32, + ulong phyaddr, unsigned int size) +{ + void *vaddr = NULL; + unsigned int crc = 0; + unsigned int tmp_size = 0; + + /*single mode cannot use codec_mm_vmap*/ + if (single_mode_vdec != NULL) { + unsigned int offset = phyaddr & (~PAGE_MASK); + while (size > 0) { + if (offset + size >= PAGE_SIZE) { + vaddr = kmap_atomic(phys_to_page(phyaddr)); + tmp_size = (PAGE_SIZE - offset); + phyaddr += tmp_size; + size -= tmp_size; + vaddr += offset; + } else { + vaddr = kmap_atomic(phys_to_page(phyaddr)); + tmp_size = size; + vaddr += offset; + size = 0; + } + if (vaddr == NULL) { + dbg_print(FC_CRC_DEBUG, "%s: kmap_atomic failed phy: 0x%x\n", + __func__, (unsigned int)phyaddr); + return -1; + } + /* + codec_mm_dma_flush(vaddr, + tmp_size, DMA_FROM_DEVICE); + */ + crc = crc32_le(crc, vaddr, tmp_size); + + kunmap_atomic(vaddr - offset); + offset = 0; + } + } else { + while (size > 0) { + if (size >= VMAP_STRIDE_SIZE) { + vaddr = codec_mm_vmap(phyaddr, VMAP_STRIDE_SIZE); + tmp_size = VMAP_STRIDE_SIZE; + phyaddr += VMAP_STRIDE_SIZE; + size -= VMAP_STRIDE_SIZE; + } else { + vaddr = codec_mm_vmap(phyaddr, size); + tmp_size = size; + size = 0; + } + if (vaddr == NULL) { + dbg_print(FC_CRC_DEBUG, "%s: codec_mm_vmap failed phy: 0x%x\n", + __func__, (unsigned int)phyaddr); + return -1; + } + codec_mm_dma_flush(vaddr, + tmp_size, DMA_FROM_DEVICE); + + crc = crc32_le(crc, vaddr, tmp_size); + + codec_mm_unmap_phyaddr(vaddr); + } + } + *crc32 = crc; + + return 0; +} + +static int do_check_nv21(struct pic_check_mgr_t *mgr, struct vframe_s *vf) +{ + int i; + unsigned int crc_y = 0, crc_uv = 0; + void *p_yaddr, *p_uvaddr; + ulong y_phyaddr, uv_phyaddr; + int ret = 0; + + p_yaddr = mgr->y_vaddr; + p_uvaddr = mgr->uv_vaddr; + y_phyaddr = mgr->y_phyaddr; + uv_phyaddr = mgr->uv_phyaddr; + if ((p_yaddr == NULL) || (p_uvaddr == NULL)) + { + if (vf->width == mgr->canvas_w) { + ret = crc32_vmap_le(&crc_y, y_phyaddr, mgr->size_y); + ret |= crc32_vmap_le(&crc_uv, uv_phyaddr, mgr->size_uv); + } else { + for (i = 0; i < vf->height; i++) { + ret |= crc32_vmap_le(&crc_y, y_phyaddr, vf->width); + y_phyaddr += mgr->canvas_w; + } + for (i = 0; i < vf->height/2; i++) { + ret |= crc32_vmap_le(&crc_uv, uv_phyaddr, vf->width); + uv_phyaddr += mgr->canvas_w; + } + } + if (ret < 0) { + dbg_print(0, "calc crc failed, may codec_mm_vmap failed\n"); + return ret; + } + } else { + if (mgr->frame_cnt == 0) { + unsigned int *p = mgr->y_vaddr; + dbg_print(0, "YUV0000: %08x-%08x-%08x-%08x\n", + p[0], p[1], p[2], p[3]); + } + if (vf->width == mgr->canvas_w) { + crc_y = crc32_le(crc_y, p_yaddr, mgr->size_y); + crc_uv = crc32_le(crc_uv, p_uvaddr, mgr->size_uv); + } else { + for (i = 0; i < vf->height; i++) { + crc_y = crc32_le(crc_y, p_yaddr, vf->width); + p_yaddr += mgr->canvas_w; + } + for (i = 0; i < vf->height/2; i++) { + crc_uv = crc32_le(crc_uv, p_uvaddr, vf->width); + p_uvaddr += mgr->canvas_w; + } + } + } + + crc_store(mgr, vf, crc_y, crc_uv); + + return 0; +} + +static int do_check_yuv16(struct pic_check_mgr_t *mgr, + struct vframe_s *vf, char *ybuf, char *uvbuf, + char *ubuf, char *vbuf) +{ + unsigned int crc1, crc2, crc3, crc4; + int w, h; + + w = vf->width; + h = vf->height; + crc1 = 0; + crc2 = 0; + crc3 = 0; + crc4 = 0; + + crc1 = crc32_le(0, ybuf, w * h *2); + crc2 = crc32_le(0, ubuf, w * h/2); + crc3 = crc32_le(0, vbuf, w * h/2); + crc4 = crc32_le(0, uvbuf, w * h*2/2); + /* + printk("%08d: %08x %08x %08x %08x\n", + mgr->frame_cnt, crc1, crc4, crc2, crc3); + */ + mgr->size_y = w * h * 2; + mgr->size_uv = w * h; + mgr->size_pic = mgr->size_y + mgr->size_uv; + mgr->y_vaddr = ybuf; + mgr->uv_vaddr = uvbuf; + mgr->canvas_w = w; + mgr->canvas_h = h; + crc_store(mgr, vf, crc1, crc4); + + return 0; +} + +static int fbc_check_prepare(struct pic_check_t *check, + int resize, int y_size) +{ + int i = 0; + + if (y_size > MAX_SIZE_AFBC_PLANES) + return -1; + + if (((!check->fbc_planes[0]) || + (!check->fbc_planes[1]) || + (!check->fbc_planes[2]) || + (!check->fbc_planes[3])) && + (!resize)) + return -1; + + if (resize) { + dbg_print(0, "size changed to 0x%x(y_size)\n", y_size); + for (i = 0; i < ARRAY_SIZE(check->fbc_planes); i++) { + if (check->fbc_planes[i]) { + vfree(check->fbc_planes[i]); + check->fbc_planes[i] = NULL; + } + } + } + for (i = 0; i < ARRAY_SIZE(check->fbc_planes); i++) { + if (!check->fbc_planes[i]) + check->fbc_planes[i] = + vmalloc(y_size * sizeof(short)); + } + if ((!check->fbc_planes[0]) || + (!check->fbc_planes[1]) || + (!check->fbc_planes[2]) || + (!check->fbc_planes[3])) { + dbg_print(0, "vmalloc staicplanes failed %lx %lx %lx %lx\n", + (ulong)check->fbc_planes[0], + (ulong)check->fbc_planes[1], + (ulong)check->fbc_planes[2], + (ulong)check->fbc_planes[3]); + for (i = 0; i < ARRAY_SIZE(check->fbc_planes); i++) { + if (check->fbc_planes[i]) { + vfree(check->fbc_planes[i]); + check->fbc_planes[i] = NULL; + } + } + return -1; + } else + dbg_print(FC_CRC_DEBUG, "vmalloc staicplanes sucessed\n"); + + return 0; +} + + + +int decoder_do_frame_check(struct vdec_s *vdec, struct vframe_s *vf) +{ + int resize = 0; + void *planes[4]; + struct pic_check_t *check = NULL; + struct pic_check_mgr_t *mgr = NULL; + int ret = 0; + + if (vdec == NULL) { + if (single_mode_vdec == NULL) + return 0; + mgr = &single_mode_vdec->vfc; + } else { + mgr = &vdec->vfc; + single_mode_vdec = NULL; + } + + if ((mgr == NULL) || + (vf == NULL) || + (mgr->enable == 0)) + return 0; + + if (get_frame_size(mgr, vf) < 0) + return -1; + + if (mgr->last_size_pic != mgr->size_pic) { + resize = 1; + dbg_print(0, "size changed, %x-->%x\n", + mgr->last_size_pic, mgr->size_pic); + } else + resize = 0; + mgr->last_size_pic = mgr->size_pic; + + if (vf->type & VIDTYPE_VIU_NV21) { + if (canvas_get_virt_addr(mgr, vf) < 0) + return -2; + if ((mgr->y_vaddr) && (mgr->uv_vaddr)) { + codec_mm_dma_flush(mgr->y_vaddr, + mgr->size_y, DMA_FROM_DEVICE); + codec_mm_dma_flush(mgr->uv_vaddr, + mgr->size_uv, DMA_FROM_DEVICE); + } + if (mgr->enable & CRC_MASK) + ret = do_check_nv21(mgr, vf); + if (mgr->enable & YUV_MASK) + do_yuv_dump(mgr, vf); + + } else if (vf->type & VIDTYPE_SCATTER) { + check = &mgr->pic_check; + + if (mgr->pic_dump.buf_addr != NULL) { + dbg_print(0, "scatter free yuv buf\n"); + vfree(mgr->pic_dump.buf_addr); + mgr->pic_dump.buf_addr = NULL; + } + if (fbc_check_prepare(check, + resize, mgr->size_y) < 0) + return -3; + planes[0] = check->fbc_planes[0]; + planes[1] = check->fbc_planes[1]; + planes[2] = check->fbc_planes[2]; + planes[3] = check->fbc_planes[3]; + ret = AMLOGIC_FBC_vframe_decoder(planes, vf, 0, 0); + if (ret < 0) { + dbg_print(0, "amlogic_fbc_lib.ko error %d\n", ret); + } else { + do_check_yuv16(mgr, vf, + (void *)planes[0], (void *)planes[3],//uv + (void *)planes[1], (void *)planes[2]); + } + } + mgr->frame_cnt++; + + return ret; +} +EXPORT_SYMBOL(decoder_do_frame_check); + +static int dump_buf_alloc(struct pic_dump_t *dump) +{ + if ((dump->buf_addr != NULL) && + (dump->buf_size != 0)) + return 0; + + dump->buf_addr = + (char *)vmalloc(size_yuv_buf); + if (!dump->buf_addr) { + dump->buf_size = 0; + dbg_print(0, "vmalloc yuv buf failed\n"); + return -ENOMEM; + } + dump->buf_size = size_yuv_buf; + + dbg_print(0, "%s: buf for yuv is alloced\n", __func__); + + return 0; +} + +int dump_yuv_trig(struct pic_check_mgr_t *mgr, + int id, int start, int num) +{ + struct pic_dump_t *dump = &mgr->pic_dump; + + if (!dump->num) { + mgr->id = id; + dump->start = start; + dump->num = num; + dump->end = start + num; + dump->dump_cnt = 0; + dump->yuv_fp = NULL; + if (!atomic_read(&mgr->work_inited)) { + INIT_WORK(&mgr->frame_check_work, do_check_work); + atomic_set(&mgr->work_inited, 1); + } + dump_buf_alloc(dump); + str_strip(comp_crc); + set_enable(mgr, YUV_MASK); + } else { + dbg_print(FC_ERROR, "yuv dump now, trig later\n"); + return -EBUSY; + } + dbg_print(0, "dump yuv trigger, from %d to %d frame\n", + dump->start, dump->end); + return 0; +} + +int frame_check_init(struct pic_check_mgr_t *mgr, int id) +{ + int i; + struct pic_dump_t *dump = &mgr->pic_dump; + struct pic_check_t *check = &mgr->pic_check; + + mgr->frame_cnt = 0; + mgr->size_pic = 0; + mgr->last_size_pic = 0; + mgr->id = id; + + dump->num = 0; + dump->dump_cnt = 0; + dump->yuv_fp = NULL; + check->check_pos = 0; + check->compare_pos = 0; + + if (!atomic_read(&mgr->work_inited)) { + INIT_WORK(&mgr->frame_check_work, do_check_work); + atomic_set(&mgr->work_inited, 1); + } + /* for dump error yuv prepare. */ + dump_buf_alloc(dump); + + /* try to open compare crc32 file */ + str_strip(comp_crc); + check->compare_fp = file_open(O_RDONLY, + "%s%s", CRC_PATH, comp_crc); + + /* create crc32 log file */ + check->check_fp = file_open(O_CREAT| O_WRONLY | O_TRUNC, + "%s%s-%d-%d.crc", CRC_PATH, comp_crc, id, mgr->file_cnt); + + INIT_KFIFO(check->new_chk_q); + INIT_KFIFO(check->wr_chk_q); + check->check_addr = vmalloc(SIZE_CRC * SIZE_CHECK_Q); + if (check->check_addr == NULL) { + dbg_print(FC_ERROR, "vmalloc qbuf fail\n"); + } else { + void *qaddr = NULL, *rdret = NULL; + check->cmp_crc_cnt = 0; + for (i = 0; i < SIZE_CHECK_Q; i++) { + qaddr = check->check_addr + i * SIZE_CRC; + rdret = fget_crc_str(qaddr, + SIZE_CRC, check); + if (rdret == NULL) { + if (i < 3) + dbg_print(0, "can't get compare crc string\n"); + if (check->compare_fp) { + filp_close(check->compare_fp, current->files); + check->compare_fp = NULL; + } + } + + kfifo_put(&check->new_chk_q, qaddr); + } + } + set_enable(mgr, CRC_MASK); + dbg_print(0, "%s end\n", __func__); + + return 0; +} + +void frame_check_exit(struct pic_check_mgr_t *mgr) +{ + int i; + struct pic_dump_t *dump = &mgr->pic_dump; + struct pic_check_t *check = &mgr->pic_check; + + if (mgr->enable != 0) { + if (dump->dump_cnt != 0) { + dbg_print(0, "%s, cnt = %d, num = %d\n", + __func__, dump->dump_cnt, dump->num); + set_enable(mgr, YUV_MASK); + } + if (atomic_read(&mgr->work_inited)) { + cancel_work_sync(&mgr->frame_check_work); + atomic_set(&mgr->work_inited, 0); + } + write_yuv_work(mgr); + write_crc_work(mgr); + + for (i = 0; i < ARRAY_SIZE(check->fbc_planes); i++) { + if (check->fbc_planes[i]) { + vfree(check->fbc_planes[i]); + check->fbc_planes[i] = NULL; + } + } + if (check->check_addr) { + vfree(check->check_addr); + check->check_addr = NULL; + } + + if (check->check_fp) { + filp_close(check->check_fp, current->files); + check->check_fp = NULL; + } + if (check->compare_fp) { + filp_close(check->compare_fp, current->files); + check->compare_fp = NULL; + } + if (dump->yuv_fp) { + filp_close(dump->yuv_fp, current->files); + dump->yuv_fp = NULL; + } + if (dump->buf_addr) { + vfree(dump->buf_addr); + dump->buf_addr = NULL; + } + mgr->file_cnt++; + set_disable(mgr, YUV_MASK | CRC_MASK); + dbg_print(0, "%s end\n", __func__); + } +} + + +int vdec_frame_check_init(struct vdec_s *vdec) +{ + int ret = 0, id = 0; + + if (vdec == NULL) + return 0; + + if ((vdec->is_reset) && + (get_cpu_major_id() != AM_MESON_CPU_MAJOR_ID_GXL)) + return 0; + + vdec->vfc.err_crc_block = 0; + if (!check_enable && !yuv_enable) + return 0; + + if (vdec_single(vdec)) + single_mode_vdec = vdec; + + vdec->canvas_mode = CANVAS_BLKMODE_LINEAR; + id = vdec->id; + + if (check_enable & (0x01 << id)) { + frame_check_init(&vdec->vfc, id); + /*repeat check one video crc32, not clear enable*/ + if ((fc_debug & FC_CHECK_CRC_LOOP_MODE) == 0) + check_enable &= ~(0x01 << id); + } + + if (yuv_enable & (0x01 << id)) { + ret = dump_yuv_trig(&vdec->vfc, + id, yuv_start[id], yuv_num[id]); + if (ret < 0) + pr_info("dump yuv init failed\n"); + else { + pr_info("dump yuv init ok, total %d\n", + yuv_num[id]); + vdec->canvas_mode = CANVAS_BLKMODE_LINEAR; + } + yuv_num[id] = 0; + yuv_start[id] = 0; + yuv_enable &= ~(0x01 << id); + } + + return ret; +} + +void vdec_frame_check_exit(struct vdec_s *vdec) +{ + if (vdec == NULL) + return; + frame_check_exit(&vdec->vfc); + + single_mode_vdec = NULL; +} + +ssize_t dump_yuv_store(struct class *class, + struct class_attribute *attr, + const char *buf, size_t size) +{ + struct vdec_s *vdec = NULL; + unsigned int id = 0, num = 0, start = 0; + int ret = -1; + + ret = sscanf(buf, "%d %d %d", &id, &start, &num); + if (ret < 0) { + pr_info("%s, parse failed\n", buf); + return size; + } + if ((num == 0) || (num > YUV_MAX_DUMP_NUM)) { + pr_info("requred yuv num %d, max %d\n", + num, YUV_MAX_DUMP_NUM); + return size; + } + vdec = vdec_get_with_id(id); + if (vdec == NULL) { + yuv_start[id] = start; + yuv_num[id] = num; + yuv_enable |= (1 << id); + pr_info("no connected vdec.%d now, set dump ok\n", id); + return size; + } + + ret = dump_yuv_trig(&vdec->vfc, id, start, num); + if (ret < 0) + pr_info("trigger dump yuv failed\n"); + else + pr_info("trigger dump yuv init ok, total %d frames\n", num); + + return size; +} + +ssize_t dump_yuv_show(struct class *class, + struct class_attribute *attr, char *buf) +{ + int i; + char *pbuf = buf; + + for (i = 0; i < MAX_INSTANCE_MUN; i++) { + pbuf += pr_info("vdec.%d, start: %d, total: %d frames\n", + i, yuv_start[i], yuv_num[i]); + } + pbuf += sprintf(pbuf, + "\nUsage: echo [id] [start] [num] > dump_yuv\n\n"); + return pbuf - buf; +} + + +ssize_t frame_check_store(struct class *class, + struct class_attribute *attr, + const char *buf, size_t size) +{ + int ret = -1; + int on_off, id; + + ret = sscanf(buf, "%d %d", &id, &on_off); + if (ret < 0) { + pr_info("%s, parse failed\n", buf); + return size; + } + if (id >= MAX_INSTANCE_MUN) { + pr_info("%d out of max vdec id\n", id); + return size; + } + if (on_off) + check_enable |= (1 << id); + else + check_enable &= ~(1 << id); + + return size; +} + +ssize_t frame_check_show(struct class *class, + struct class_attribute *attr, char *buf) +{ + int i; + char *pbuf = buf; + + for (i = 0; i < MAX_INSTANCE_MUN; i++) { + pbuf += sprintf(pbuf, + "vdec.%d\tcrc: %s\n", i, + (check_enable & (0x01 << i))?"enabled":"--"); + } + pbuf += sprintf(pbuf, + "\nUsage:\techo [id] [1:on/0:off] > frame_check\n\n"); + + if (fc_debug & FC_ERR_CRC_BLOCK_MODE) { + /* cat frame_check to next frame when block */ + struct vdec_s *vdec = NULL; + vdec = vdec_get_with_id(__ffs(check_enable)); + if (vdec) + vdec->vfc.err_crc_block = 0; + } + + return pbuf - buf; +} + + +module_param_string(comp_crc, comp_crc, 128, 0664); +MODULE_PARM_DESC(comp_crc, "\n crc_filename\n"); + +module_param(fc_debug, uint, 0664); +MODULE_PARM_DESC(fc_debug, "\n frame check debug\n"); + +module_param(size_yuv_buf, uint, 0664); +MODULE_PARM_DESC(size_yuv_buf, "\n size_yuv_buf\n"); + diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/utils/frame_check.h b/drivers/amlogic/media_modules/frame_provider/decoder/utils/frame_check.h new file mode 100644 index 000000000000..f1ba6773fe43 --- /dev/null +++ b/drivers/amlogic/media_modules/frame_provider/decoder/utils/frame_check.h @@ -0,0 +1,111 @@ +/* + * drivers/amlogic/media/frame_provider/decoder/utils/frame_check.h + * + * Copyright (C) 2016 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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 __FRAME_CHECK_H__ +#define __FRAME_CHECK_H__ + + +#include +#include +#include +#include + +#define FRAME_CHECK + +#define YUV_MAX_DUMP_NUM 20 + +#define SIZE_CRC 64 +#define SIZE_CHECK_Q 128 + +struct pic_dump_t{ + struct file *yuv_fp; + loff_t yuv_pos; + unsigned int start; + unsigned int num; + unsigned int end; + unsigned int dump_cnt; + + unsigned int buf_size; + char *buf_addr; +}; + +struct pic_check_t{ + struct file *check_fp; + loff_t check_pos; + + struct file *compare_fp; + loff_t compare_pos; + unsigned int cmp_crc_cnt; + void *fbc_planes[4]; + void *check_addr; + DECLARE_KFIFO(new_chk_q, char *, SIZE_CHECK_Q); + DECLARE_KFIFO(wr_chk_q, char *, SIZE_CHECK_Q); +}; + +struct pic_check_mgr_t{ + int id; + int enable; + unsigned int frame_cnt; + /* pic info */ + unsigned int canvas_w; + unsigned int canvas_h; + unsigned int size_y; //real size + unsigned int size_uv; + unsigned int size_pic; + unsigned int last_size_pic; + void *y_vaddr; + void *uv_vaddr; + ulong y_phyaddr; + ulong uv_phyaddr; + int err_crc_block; + + int file_cnt; + atomic_t work_inited; + struct work_struct frame_check_work; + + struct pic_check_t pic_check; + struct pic_dump_t pic_dump; +}; + +int dump_yuv_trig(struct pic_check_mgr_t *mgr, + int id, int start, int num); + +int decoder_do_frame_check(struct vdec_s *vdec, struct vframe_s *vf); + +int frame_check_init(struct pic_check_mgr_t *mgr, int id); + +void frame_check_exit(struct pic_check_mgr_t *mgr); + +ssize_t frame_check_show(struct class *class, + struct class_attribute *attr, char *buf); + +ssize_t frame_check_store(struct class *class, + struct class_attribute *attr, + const char *buf, size_t size); + +ssize_t dump_yuv_show(struct class *class, + struct class_attribute *attr, char *buf); + +ssize_t dump_yuv_store(struct class *class, + struct class_attribute *attr, + const char *buf, size_t size); + +void vdec_frame_check_exit(struct vdec_s *vdec); +int vdec_frame_check_init(struct vdec_s *vdec); + +#endif /* __FRAME_CHECK_H__ */ + diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/utils/secprot.c b/drivers/amlogic/media_modules/frame_provider/decoder/utils/secprot.c index 1d14e2c39bef..a1e7fa79008f 100644 --- a/drivers/amlogic/media_modules/frame_provider/decoder/utils/secprot.c +++ b/drivers/amlogic/media_modules/frame_provider/decoder/utils/secprot.c @@ -15,7 +15,14 @@ * */ +#include +#include #include "secprot.h" +#ifndef CONFIG_ARM64 +#include +#endif + +#ifdef CONFIG_ARM64 int tee_config_device_secure(int dev_id, int secure) { @@ -40,4 +47,29 @@ int tee_config_device_secure(int dev_id, int secure) return ret; } +#else +int tee_config_device_secure(int dev_id, int secure) +{ + int ret = 0; + register unsigned int r0 asm("r0"); + register unsigned int r1 asm("r1"); + register unsigned int r2 asm("r2"); + + r0 = OPTEE_SMC_CONFIG_DEVICE_SECURE; + r1 = dev_id; + r2 = secure; + + asm volatile( + __asmeq("%0", "r0") + __asmeq("%1", "r0") + __asmeq("%2", "r1") + __asmeq("%3", "r2") + __SMC(0) + : "=r"(r0) + : "r"(r0), "r"(r1), "r"(r2)); + ret = r0; + + return ret; +} +#endif diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/utils/secprot.h b/drivers/amlogic/media_modules/frame_provider/decoder/utils/secprot.h index f8fc5da845e9..28ee47725dbc 100644 --- a/drivers/amlogic/media_modules/frame_provider/decoder/utils/secprot.h +++ b/drivers/amlogic/media_modules/frame_provider/decoder/utils/secprot.h @@ -31,7 +31,7 @@ #define OPTEE_SMC_CONFIG_DEVICE_SECURE 0xb200000e -#define __asmeq(x, y) ".ifnc " x "," y " ; .err ; .endif\n\t" +/*#define __asmeq(x, y) ".ifnc " x "," y " ; .err ; .endif\n\t"*/ extern int tee_config_device_secure(int dev_id, int secure); diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec.c b/drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec.c index e7fb7514ea55..a09c3eeb974d 100644 --- a/drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec.c +++ b/drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec.c @@ -67,6 +67,12 @@ #include #include #include "secprot.h" +#include "../../../common/chips/decoder_cpu_ver_info.h" +#include "frame_check.h" + +#ifdef CONFIG_AMLOGIC_POWER +#include +#endif static DEFINE_MUTEX(vdec_mutex); @@ -80,16 +86,42 @@ static int keep_vdec_mem; static unsigned int debug_trace_num = 16 * 20; static int step_mode; static unsigned int clk_config; +/* + &1: sched_priority to MAX_RT_PRIO -1. + &2: always reload firmware. + &4: vdec canvas debug enable + */ +static unsigned int debug; static int hevc_max_reset_count; -#define MAX_INSTANCE_MUN 9 static int no_powerdown; +static int parallel_decode = 1; +static int fps_detection; +static int fps_clear; + + +static int force_nosecure_even_drm; + static DEFINE_SPINLOCK(vdec_spin_lock); #define HEVC_TEST_LIMIT 100 #define GXBB_REV_A_MINOR 0xA +#define PRINT_FRAME_INFO 1 +#define DISABLE_FRAME_INFO 2 + +static int frameinfo_flag = 0; +//static int path_debug = 0; + +static struct vframe_qos_s *frame_info_buf_in = NULL; +static struct vframe_qos_s *frame_info_buf_out = NULL; +static int frame_qos_wr = 0; +static int frame_qos_rd = 0; +int decode_underflow = 0; + +#define CANVAS_MAX_SIZE (AMVDEC_CANVAS_MAX1 - AMVDEC_CANVAS_START_INDEX + 1 + AMVDEC_CANVAS_MAX2 + 1) + struct am_reg { char *name; int offset; @@ -104,13 +136,23 @@ struct vdec_isr_context_s { struct vdec_s *vdec; }; +struct decode_fps_s { + u32 frame_count; + u64 start_timestamp; + u64 last_timestamp; + u32 fps; +}; + struct vdec_core_s { struct list_head connected_vdec_list; spinlock_t lock; + spinlock_t canvas_lock; + spinlock_t fps_lock; struct ida ida; atomic_t vdec_nr; struct vdec_s *vfm_vdec; struct vdec_s *active_vdec; + struct vdec_s *active_hevc; struct vdec_s *hint_fr_vdec; struct platform_device *vdec_core_platform_device; struct device *cma_dev; @@ -121,8 +163,20 @@ struct vdec_core_s { unsigned long sched_mask; struct vdec_isr_context_s isr_context[VDEC_IRQ_MAX]; int power_ref_count[VDEC_MAX]; + struct vdec_s *last_vdec; + int parallel_dec; + unsigned long power_ref_mask; + int vdec_combine_flag; + struct decode_fps_s decode_fps[MAX_INSTANCE_MUN]; }; +struct canvas_status_s { + int type; + int canvas_used_flag; + int id; +}; + + static struct vdec_core_s *vdec_core; static const char * const vdec_status_string[] = { @@ -134,6 +188,9 @@ static const char * const vdec_status_string[] = { static int debugflags; +static struct canvas_status_s canvas_stat[AMVDEC_CANVAS_MAX1 - AMVDEC_CANVAS_START_INDEX + 1 + AMVDEC_CANVAS_MAX2 + 1]; + + int vdec_get_debug_flags(void) { return debugflags; @@ -168,6 +225,32 @@ static const int cores_int[VDEC_MAX] = { VDEC_IRQ_HEVC_BACK }; +unsigned long vdec_canvas_lock(struct vdec_core_s *core) +{ + unsigned long flags; + spin_lock_irqsave(&core->canvas_lock, flags); + + return flags; +} + +void vdec_canvas_unlock(struct vdec_core_s *core, unsigned long flags) +{ + spin_unlock_irqrestore(&core->canvas_lock, flags); +} + +unsigned long vdec_fps_lock(struct vdec_core_s *core) +{ + unsigned long flags; + spin_lock_irqsave(&core->fps_lock, flags); + + return flags; +} + +void vdec_fps_unlock(struct vdec_core_s *core, unsigned long flags) +{ + spin_unlock_irqrestore(&core->fps_lock, flags); +} + unsigned long vdec_core_lock(struct vdec_core_s *core) { unsigned long flags; @@ -182,10 +265,80 @@ void vdec_core_unlock(struct vdec_core_s *core, unsigned long flags) spin_unlock_irqrestore(&core->lock, flags); } +static u64 vdec_get_us_time_system(void) +{ + struct timeval tv; + + do_gettimeofday(&tv); + + return div64_u64(timeval_to_ns(&tv), 1000); +} + +static void vdec_fps_clear(int id) +{ + if (id >= MAX_INSTANCE_MUN) + return; + + vdec_core->decode_fps[id].frame_count = 0; + vdec_core->decode_fps[id].start_timestamp = 0; + vdec_core->decode_fps[id].last_timestamp = 0; + vdec_core->decode_fps[id].fps = 0; +} + +static void vdec_fps_clearall(void) +{ + int i; + + for (i = 0; i < MAX_INSTANCE_MUN; i++) { + vdec_core->decode_fps[i].frame_count = 0; + vdec_core->decode_fps[i].start_timestamp = 0; + vdec_core->decode_fps[i].last_timestamp = 0; + vdec_core->decode_fps[i].fps = 0; + } +} + +static void vdec_fps_detec(int id) +{ + unsigned long flags; + + if (fps_detection == 0) + return; + + if (id >= MAX_INSTANCE_MUN) + return; + + flags = vdec_fps_lock(vdec_core); + + if (fps_clear == 1) { + vdec_fps_clearall(); + fps_clear = 0; + } + + vdec_core->decode_fps[id].frame_count++; + if (vdec_core->decode_fps[id].frame_count == 1) { + vdec_core->decode_fps[id].start_timestamp = + vdec_get_us_time_system(); + vdec_core->decode_fps[id].last_timestamp = + vdec_core->decode_fps[id].start_timestamp; + } else { + vdec_core->decode_fps[id].last_timestamp = + vdec_get_us_time_system(); + vdec_core->decode_fps[id].fps = + (u32)div_u64(((u64)(vdec_core->decode_fps[id].frame_count) * + 10000000000), + (vdec_core->decode_fps[id].last_timestamp - + vdec_core->decode_fps[id].start_timestamp)); + } + vdec_fps_unlock(vdec_core, flags); +} + + + static int get_canvas(unsigned int index, unsigned int base) { int start; int canvas_index = index * base; + int ret; if ((base > 4) || (base == 0)) return -1; @@ -203,26 +356,173 @@ static int get_canvas(unsigned int index, unsigned int base) } if (base == 1) { - return start; + ret = start; } else if (base == 2) { - return ((start + 1) << 16) | ((start + 1) << 8) | start; + ret = ((start + 1) << 16) | ((start + 1) << 8) | start; } else if (base == 3) { - return ((start + 2) << 16) | ((start + 1) << 8) | start; + ret = ((start + 2) << 16) | ((start + 1) << 8) | start; } else if (base == 4) { - return (((start + 3) << 24) | (start + 2) << 16) | + ret = (((start + 3) << 24) | (start + 2) << 16) | ((start + 1) << 8) | start; } + return ret; +} + +static int get_canvas_ex(int type, int id) +{ + int i; + unsigned long flags; + + flags = vdec_canvas_lock(vdec_core); + + for (i = 0; i < CANVAS_MAX_SIZE; i++) { + /*0x10-0x15 has been used by rdma*/ + if ((i >= 0x10) && (i <= 0x15)) + continue; + if ((canvas_stat[i].type == type) && + (canvas_stat[i].id & (1 << id)) == 0) { + canvas_stat[i].canvas_used_flag++; + canvas_stat[i].id |= (1 << id); + if (debug & 4) + pr_debug("get used canvas %d\n", i); + vdec_canvas_unlock(vdec_core, flags); + if (i < AMVDEC_CANVAS_MAX2 + 1) + return i; + else + return (i + AMVDEC_CANVAS_START_INDEX - AMVDEC_CANVAS_MAX2 - 1); + } + } + + for (i = 0; i < CANVAS_MAX_SIZE; i++) { + /*0x10-0x15 has been used by rdma*/ + if ((i >= 0x10) && (i <= 0x15)) + continue; + if (canvas_stat[i].type == 0) { + canvas_stat[i].type = type; + canvas_stat[i].canvas_used_flag = 1; + canvas_stat[i].id = (1 << id); + if (debug & 4) { + pr_debug("get canvas %d\n", i); + pr_debug("canvas_used_flag %d\n", + canvas_stat[i].canvas_used_flag); + pr_debug("canvas_stat[i].id %d\n", + canvas_stat[i].id); + } + vdec_canvas_unlock(vdec_core, flags); + if (i < AMVDEC_CANVAS_MAX2 + 1) + return i; + else + return (i + AMVDEC_CANVAS_START_INDEX - AMVDEC_CANVAS_MAX2 - 1); + } + } + vdec_canvas_unlock(vdec_core, flags); + + pr_info("cannot get canvas\n"); + return -1; } +static void free_canvas_ex(int index, int id) +{ + unsigned long flags; + int offset; + + flags = vdec_canvas_lock(vdec_core); + if (index >= 0 && + index < AMVDEC_CANVAS_MAX2 + 1) + offset = index; + else if ((index >= AMVDEC_CANVAS_START_INDEX) && + (index <= AMVDEC_CANVAS_MAX1)) + offset = index + AMVDEC_CANVAS_MAX2 + 1 - AMVDEC_CANVAS_START_INDEX; + else { + vdec_canvas_unlock(vdec_core, flags); + return; + } + + if ((canvas_stat[offset].canvas_used_flag > 0) && + (canvas_stat[offset].id & (1 << id))) { + canvas_stat[offset].canvas_used_flag--; + canvas_stat[offset].id &= ~(1 << id); + if (canvas_stat[offset].canvas_used_flag == 0) { + canvas_stat[offset].type = 0; + canvas_stat[offset].id = 0; + } + if (debug & 4) { + pr_debug("free index %d used_flag %d, type = %d, id = %d\n", + offset, + canvas_stat[offset].canvas_used_flag, + canvas_stat[offset].type, + canvas_stat[offset].id); + } + } + vdec_canvas_unlock(vdec_core, flags); + + return; + +} + + + + +static int vdec_get_hw_type(int value) +{ + int type; + switch (value) { + case VFORMAT_HEVC: + case VFORMAT_VP9: + case VFORMAT_AVS2: + type = CORE_MASK_HEVC; + break; + + case VFORMAT_MPEG12: + case VFORMAT_MPEG4: + case VFORMAT_H264: + case VFORMAT_MJPEG: + case VFORMAT_REAL: + case VFORMAT_JPEG: + case VFORMAT_VC1: + case VFORMAT_AVS: + case VFORMAT_YUV: + case VFORMAT_H264MVC: + case VFORMAT_H264_4K2K: + case VFORMAT_H264_ENC: + case VFORMAT_JPEG_ENC: + type = CORE_MASK_VDEC_1; + break; + + default: + type = -1; + } + + return type; +} + + +static void vdec_save_active_hw(struct vdec_s *vdec) +{ + int type; + + type = vdec_get_hw_type(vdec->port->vformat); + + if (type == CORE_MASK_HEVC) { + vdec_core->active_hevc = vdec; + } else if (type == CORE_MASK_VDEC_1) { + vdec_core->active_vdec = vdec; + } else { + pr_info("save_active_fw wrong\n"); + } +} + int vdec_status(struct vdec_s *vdec, struct vdec_info *vstatus) { - if (vdec && vdec->dec_status) + if (vdec && vdec->dec_status && + ((vdec->status == VDEC_STATUS_CONNECTED || + vdec->status == VDEC_STATUS_ACTIVE))) return vdec->dec_status(vdec, vstatus); - return -1; + return 0; } EXPORT_SYMBOL(vdec_status); @@ -324,7 +624,7 @@ EXPORT_SYMBOL(update_vdec_clk_config_settings); static bool hevc_workaround_needed(void) { - return (get_cpu_type() == MESON_CPU_MAJOR_ID_GXBB) && + return (get_cpu_major_id() == AM_MESON_CPU_MAJOR_ID_GXBB) && (get_meson_cpu_version(MESON_CPU_VERSION_LVL_MINOR) == GXBB_REV_A_MINOR); } @@ -526,6 +826,13 @@ int vdec_set_pts(struct vdec_s *vdec, u32 pts) } EXPORT_SYMBOL(vdec_set_pts); +void vdec_set_timestamp(struct vdec_s *vdec, u64 timestamp) +{ + vdec->timestamp = timestamp; + vdec->timestamp_valid = true; +} +EXPORT_SYMBOL(vdec_set_timestamp); + int vdec_set_pts64(struct vdec_s *vdec, u64 pts64) { vdec->pts64 = pts64; @@ -537,6 +844,12 @@ int vdec_set_pts64(struct vdec_s *vdec, u64 pts64) } EXPORT_SYMBOL(vdec_set_pts64); +int vdec_get_status(struct vdec_s *vdec) +{ + return vdec->status; +} +EXPORT_SYMBOL(vdec_get_status); + void vdec_set_status(struct vdec_s *vdec, int status) { //trace_vdec_set_status(vdec, status);/*DEBUG_TMP*/ @@ -1198,7 +1511,7 @@ void vdec_clean_input(struct vdec_s *vdec) while (!list_empty(&input->vframe_chunk_list)) { struct vframe_chunk_s *chunk = vdec_input_next_chunk(input); - if (chunk->flag & VFRAME_CHUNK_FLAG_CONSUMED) + if (chunk && (chunk->flag & VFRAME_CHUNK_FLAG_CONSUMED)) vdec_input_release_chunk(input, chunk); else break; @@ -1207,12 +1520,74 @@ void vdec_clean_input(struct vdec_s *vdec) } EXPORT_SYMBOL(vdec_clean_input); + +static int vdec_input_read_restore(struct vdec_s *vdec) +{ + struct vdec_input_s *input = &vdec->input; + + if (!vdec_stream_based(vdec)) + return 0; + + if (!input->swap_valid) { + if (input->target == VDEC_INPUT_TARGET_VLD) { + WRITE_VREG(VLD_MEM_VIFIFO_START_PTR, + input->start); + WRITE_VREG(VLD_MEM_VIFIFO_END_PTR, + input->start + input->size - 8); + WRITE_VREG(VLD_MEM_VIFIFO_CURR_PTR, + input->start); + WRITE_VREG(VLD_MEM_VIFIFO_CONTROL, 1); + WRITE_VREG(VLD_MEM_VIFIFO_CONTROL, 0); + + /* set to manual mode */ + WRITE_VREG(VLD_MEM_VIFIFO_BUF_CNTL, 2); + WRITE_VREG(VLD_MEM_VIFIFO_RP, input->start); + } else if (input->target == VDEC_INPUT_TARGET_HEVC) { + WRITE_VREG(HEVC_STREAM_START_ADDR, + input->start); + WRITE_VREG(HEVC_STREAM_END_ADDR, + input->start + input->size); + WRITE_VREG(HEVC_STREAM_RD_PTR, + input->start); + } + return 0; + } + if (input->target == VDEC_INPUT_TARGET_VLD) { + /* restore read side */ + WRITE_VREG(VLD_MEM_SWAP_ADDR, + input->swap_page_phys); + + /*swap active*/ + WRITE_VREG(VLD_MEM_SWAP_CTL, 1); + + /*wait swap busy*/ + while (READ_VREG(VLD_MEM_SWAP_CTL) & (1<<7)) + ; + + WRITE_VREG(VLD_MEM_SWAP_CTL, 0); + } else if (input->target == VDEC_INPUT_TARGET_HEVC) { + /* restore read side */ + WRITE_VREG(HEVC_STREAM_SWAP_ADDR, + input->swap_page_phys); + WRITE_VREG(HEVC_STREAM_SWAP_CTRL, 1); + + while (READ_VREG(HEVC_STREAM_SWAP_CTRL) + & (1<<7)) + ; + WRITE_VREG(HEVC_STREAM_SWAP_CTRL, 0); + } + + return 0; +} + + int vdec_sync_input(struct vdec_s *vdec) { struct vdec_input_s *input = &vdec->input; u32 rp = 0, wp = 0, fifo_len = 0; int size; + vdec_input_read_restore(vdec); vdec_sync_input_read(vdec); vdec_sync_input_write(vdec); if (input->target == VDEC_INPUT_TARGET_VLD) { @@ -1343,7 +1718,7 @@ int vdec_disconnect(struct vdec_s *vdec) (vdec->status != VDEC_STATUS_ACTIVE)) { return 0; } - + mutex_lock(&vdec_mutex); /* *when a vdec is under the management of scheduler * the status change will only be from vdec_core_thread @@ -1354,16 +1729,26 @@ int vdec_disconnect(struct vdec_s *vdec) vdec_set_next_status(vdec->slave, VDEC_STATUS_DISCONNECTED); else if (vdec->master) vdec_set_next_status(vdec->master, VDEC_STATUS_DISCONNECTED); - + mutex_unlock(&vdec_mutex); up(&vdec_core->sem); - wait_for_completion(&vdec->inactive_done); + if(!wait_for_completion_timeout(&vdec->inactive_done, + msecs_to_jiffies(2000))) + goto discon_timeout; - if (vdec->slave) - wait_for_completion(&vdec->slave->inactive_done); - else if (vdec->master) - wait_for_completion(&vdec->master->inactive_done); + if (vdec->slave) { + if(!wait_for_completion_timeout(&vdec->slave->inactive_done, + msecs_to_jiffies(2000))) + goto discon_timeout; + } else if (vdec->master) { + if(!wait_for_completion_timeout(&vdec->master->inactive_done, + msecs_to_jiffies(2000))) + goto discon_timeout; + } + return 0; +discon_timeout: + pr_err("%s timeout!!! status: 0x%x\n", __func__, vdec->status); return 0; } EXPORT_SYMBOL(vdec_disconnect); @@ -1403,6 +1788,30 @@ static const char *get_dev_name(bool use_legacy_vdec, int format) #endif } +struct vdec_s *vdec_get_with_id(unsigned int id) +{ + struct vdec_s *vdec, *ret_vdec = NULL; + struct vdec_core_s *core = vdec_core; + unsigned long flags; + + if (id >= MAX_INSTANCE_MUN) + return NULL; + + flags = vdec_core_lock(vdec_core); + if (!list_empty(&core->connected_vdec_list)) { + list_for_each_entry(vdec, &core->connected_vdec_list, list) { + if (vdec->id == id) { + pr_info("searched avaliable vdec connected, id = %d\n", id); + ret_vdec = vdec; + break; + } + } + } + vdec_core_unlock(vdec_core, flags); + + return ret_vdec; +} + /* *register vdec_device * create output, vfm or create ionvideo output @@ -1449,6 +1858,9 @@ s32 vdec_init(struct vdec_s *vdec, int is_4k) p->cma_dev = vdec_core->cma_dev; p->get_canvas = get_canvas; + p->get_canvas_ex = get_canvas_ex; + p->free_canvas_ex = free_canvas_ex; + p->vdec_fps_detec = vdec_fps_detec; atomic_set(&p->inirq_flag, 0); atomic_set(&p->inirq_thread_flag, 0); /* todo */ @@ -1457,6 +1869,12 @@ s32 vdec_init(struct vdec_s *vdec, int is_4k) /* vdec_dev_reg.flag = 0; */ if (vdec->id >= 0) id = vdec->id; + p->parallel_dec = parallel_decode; + vdec_core->parallel_dec = parallel_decode; + vdec->canvas_mode = CANVAS_BLKMODE_32X32; +#ifdef FRAME_CHECK + vdec_frame_check_init(vdec); +#endif p->dev = platform_device_register_data( &vdec_core->vdec_core_platform_device->dev, dev_name, @@ -1510,31 +1928,33 @@ s32 vdec_init(struct vdec_s *vdec, int is_4k) goto error; } if (p->frame_base_video_path == FRAME_BASE_PATH_IONVIDEO) { +#ifdef CONFIG_AMLOGIC_IONVIDEO #if 1 r = ionvideo_assign_map(&vdec->vf_receiver_name, &vdec->vf_receiver_inst); #else - /* - * temporarily just use decoder instance ID as iondriver ID - * to solve OMX iondriver instance number check time sequence - * only the limitation is we can NOT mix different video - * decoders since same ID will be used for different decoder - * formats. - */ - vdec->vf_receiver_inst = p->dev->id; - r = ionvideo_assign_map(&vdec->vf_receiver_name, - &vdec->vf_receiver_inst); + /* + * temporarily just use decoder instance ID as iondriver ID + * to solve OMX iondriver instance number check time sequence + * only the limitation is we can NOT mix different video + * decoders since same ID will be used for different decoder + * formats. + */ + vdec->vf_receiver_inst = p->dev->id; + r = ionvideo_assign_map(&vdec->vf_receiver_name, + &vdec->vf_receiver_inst); #endif - if (r < 0) { - pr_err("IonVideo frame receiver allocation failed.\n"); + if (r < 0) { + pr_err("IonVideo frame receiver allocation failed.\n"); - mutex_lock(&vdec_mutex); - inited_vcodec_num--; - mutex_unlock(&vdec_mutex); + mutex_lock(&vdec_mutex); + inited_vcodec_num--; + mutex_unlock(&vdec_mutex); - goto error; - } + goto error; + } +#endif snprintf(vdec->vfm_map_chain, VDEC_MAP_NAME_SIZE, "%s %s", vdec->vf_provider_name, vdec->vf_receiver_name); @@ -1542,16 +1962,34 @@ s32 vdec_init(struct vdec_s *vdec, int is_4k) "vdec-map-%d", vdec->id); } else if (p->frame_base_video_path == FRAME_BASE_PATH_AMLVIDEO_AMVIDEO) { - snprintf(vdec->vfm_map_chain, VDEC_MAP_NAME_SIZE, - "%s %s", vdec->vf_provider_name, - "amlvideo deinterlace amvideo"); + if (vdec_secure(vdec)) { + snprintf(vdec->vfm_map_chain, VDEC_MAP_NAME_SIZE, + "%s %s", vdec->vf_provider_name, + "amlvideo amvideo"); + } else { + snprintf(vdec->vfm_map_chain, VDEC_MAP_NAME_SIZE, + "%s %s", vdec->vf_provider_name, + "amlvideo deinterlace amvideo"); + } snprintf(vdec->vfm_map_id, VDEC_MAP_NAME_SIZE, "vdec-map-%d", vdec->id); } else if (p->frame_base_video_path == FRAME_BASE_PATH_AMLVIDEO1_AMVIDEO2) { snprintf(vdec->vfm_map_chain, VDEC_MAP_NAME_SIZE, "%s %s", vdec->vf_provider_name, - "ppmgr amlvideo.1 amvide2"); + "aml_video.1 videosync.0 videopip"); + snprintf(vdec->vfm_map_id, VDEC_MAP_NAME_SIZE, + "vdec-map-%d", vdec->id); + } else if (p->frame_base_video_path == FRAME_BASE_PATH_V4L_VIDEO) { + snprintf(vdec->vfm_map_chain, VDEC_MAP_NAME_SIZE, + "%s %s", vdec->vf_provider_name, + vdec->vf_receiver_name); + snprintf(vdec->vfm_map_id, VDEC_MAP_NAME_SIZE, + "vdec-map-%d", vdec->id); + } else if (p->frame_base_video_path == FRAME_BASE_PATH_TUNNEL_MODE) { + snprintf(vdec->vfm_map_chain, VDEC_MAP_NAME_SIZE, + "%s %s", vdec->vf_provider_name, + "amvideo"); snprintf(vdec->vfm_map_id, VDEC_MAP_NAME_SIZE, "vdec-map-%d", vdec->id); } @@ -1601,13 +2039,14 @@ s32 vdec_init(struct vdec_s *vdec, int is_4k) if (vdec_core->hint_fr_vdec == vdec) { if (p->sys_info->rate != 0) { - if (!vdec->is_reset) + if (!vdec->is_reset) { vf_notify_receiver(p->vf_provider_name, VFRAME_EVENT_PROVIDER_FR_HINT, (void *) ((unsigned long) p->sys_info->rate)); - vdec->fr_hint_state = VDEC_HINTED; + vdec->fr_hint_state = VDEC_HINTED; + } } else { vdec->fr_hint_state = VDEC_NEED_HINT; } @@ -1622,7 +2061,25 @@ s32 vdec_init(struct vdec_s *vdec, int is_4k) vdec->sys_info->height); /* vdec is now ready to be active */ vdec_set_status(vdec, VDEC_STATUS_DISCONNECTED); + if (p->use_vfm_path) { + frame_info_buf_in = (struct vframe_qos_s *) + kmalloc(QOS_FRAME_NUM*sizeof(struct vframe_qos_s), GFP_KERNEL); + if (!frame_info_buf_in) + pr_err("kmalloc: frame_info_buf_in failed\n"); + else + memset(frame_info_buf_in, 0, + QOS_FRAME_NUM*sizeof(struct vframe_qos_s)); + frame_info_buf_out = (struct vframe_qos_s *) + kmalloc(QOS_FRAME_NUM*sizeof(struct vframe_qos_s), GFP_KERNEL); + if (!frame_info_buf_out) + pr_err("kmalloc: frame_info_buf_out failed\n"); + else + memset(frame_info_buf_out, 0, + QOS_FRAME_NUM*sizeof(struct vframe_qos_s)); + frame_qos_wr = 0; + frame_qos_rd = 0; + } return 0; error: @@ -1648,8 +2105,7 @@ void vdec_release(struct vdec_s *vdec) if (vdec->vframe_provider.name) { if (!vdec_single(vdec)) { if (vdec_core->hint_fr_vdec == vdec - && vdec->fr_hint_state == VDEC_HINTED - && !vdec->is_reset) + && vdec->fr_hint_state == VDEC_HINTED) vf_notify_receiver( vdec->vf_provider_name, VFRAME_EVENT_PROVIDER_FR_END_HINT, @@ -1676,15 +2132,28 @@ void vdec_release(struct vdec_s *vdec) || (atomic_read(&vdec->inirq_thread_flag) > 0)) schedule(); +#ifdef FRAME_CHECK + vdec_frame_check_exit(vdec); +#endif + vdec_fps_clear(vdec->id); + platform_device_unregister(vdec->dev); + pr_debug("vdec_release instance %p, total %d\n", vdec, + atomic_read(&vdec_core->vdec_nr)); + if (vdec->use_vfm_path) { + kfree(frame_info_buf_in); + frame_info_buf_in = NULL; + kfree(frame_info_buf_out); + frame_info_buf_out = NULL; + frame_qos_wr = 0; + frame_qos_rd = 0; + } vdec_destroy(vdec); mutex_lock(&vdec_mutex); inited_vcodec_num--; mutex_unlock(&vdec_mutex); - pr_debug("vdec_release instance %p, total %d\n", vdec, - atomic_read(&vdec_core->vdec_nr)); } EXPORT_SYMBOL(vdec_release); @@ -1707,9 +2176,14 @@ int vdec_reset(struct vdec_s *vdec) if (vdec->slave) vdec->slave->reset(vdec->slave); } - + vdec->mc_loaded = 0;/*clear for reload firmware*/ vdec_input_release(&vdec->input); + vdec_input_init(&vdec->input, vdec); + + vdec_input_prepare_bufs(&vdec->input, vdec->sys_info->width, + vdec->sys_info->height); + vf_reg_provider(&vdec->vframe_provider); vf_notify_receiver(vdec->vf_provider_name, VFRAME_EVENT_PROVIDER_START, vdec); @@ -1718,6 +2192,7 @@ int vdec_reset(struct vdec_s *vdec) vf_reg_provider(&vdec->slave->vframe_provider); vf_notify_receiver(vdec->slave->vf_provider_name, VFRAME_EVENT_PROVIDER_START, vdec->slave); + vdec->slave->mc_loaded = 0;/*clear for reload firmware*/ } vdec_connect(vdec); @@ -1730,21 +2205,24 @@ void vdec_free_cmabuf(void) { mutex_lock(&vdec_mutex); - if (inited_vcodec_num > 0) { + /*if (inited_vcodec_num > 0) { mutex_unlock(&vdec_mutex); return; - } + }*/ mutex_unlock(&vdec_mutex); } -int vdec_core_request(struct vdec_s *vdec, unsigned long mask) +void vdec_core_request(struct vdec_s *vdec, unsigned long mask) { vdec->core_mask |= mask; if (vdec->slave) vdec->slave->core_mask |= mask; + if (vdec_core->parallel_dec == 1) { + if (mask & CORE_MASK_COMBINE) + vdec_core->vdec_combine_flag++; + } - return 0; } EXPORT_SYMBOL(vdec_core_request); @@ -1754,12 +2232,15 @@ int vdec_core_release(struct vdec_s *vdec, unsigned long mask) if (vdec->slave) vdec->slave->core_mask &= ~mask; - + if (vdec_core->parallel_dec == 1) { + if (mask & CORE_MASK_COMBINE) + vdec_core->vdec_combine_flag--; + } return 0; } EXPORT_SYMBOL(vdec_core_release); -const bool vdec_core_with_input(unsigned long mask) +bool vdec_core_with_input(unsigned long mask) { enum vdec_type_e type; @@ -1775,7 +2256,7 @@ void vdec_core_finish_run(struct vdec_s *vdec, unsigned long mask) { unsigned long i; unsigned long t = mask; - + mutex_lock(&vdec_mutex); while (t) { i = __ffs(t); clear_bit(i, &vdec->active_mask); @@ -1784,6 +2265,8 @@ void vdec_core_finish_run(struct vdec_s *vdec, unsigned long mask) if (vdec->active_mask == 0) vdec_set_status(vdec, VDEC_STATUS_CONNECTED); + + mutex_unlock(&vdec_mutex); } EXPORT_SYMBOL(vdec_core_finish_run); /* @@ -1831,8 +2314,18 @@ static irqreturn_t vdec_isr(int irq, void *dev_id) { struct vdec_isr_context_s *c = (struct vdec_isr_context_s *)dev_id; - struct vdec_s *vdec = vdec_core->active_vdec; + struct vdec_s *vdec = vdec_core->last_vdec; irqreturn_t ret = IRQ_HANDLED; + + if (vdec_core->parallel_dec == 1) { + if (irq == vdec_core->isr_context[VDEC_IRQ_0].irq) + vdec = vdec_core->active_hevc; + else if (irq == vdec_core->isr_context[VDEC_IRQ_1].irq) + vdec = vdec_core->active_vdec; + else + vdec = NULL; + } + if (vdec) atomic_set(&vdec->inirq_flag, 1); if (c->dev_isr) { @@ -1875,8 +2368,18 @@ static irqreturn_t vdec_thread_isr(int irq, void *dev_id) { struct vdec_isr_context_s *c = (struct vdec_isr_context_s *)dev_id; - struct vdec_s *vdec = vdec_core->active_vdec; + struct vdec_s *vdec = vdec_core->last_vdec; irqreturn_t ret = IRQ_HANDLED; + + if (vdec_core->parallel_dec == 1) { + if (irq == vdec_core->isr_context[VDEC_IRQ_0].irq) + vdec = vdec_core->active_hevc; + else if (irq == vdec_core->isr_context[VDEC_IRQ_1].irq) + vdec = vdec_core->active_vdec; + else + vdec = NULL; + } + if (vdec) atomic_set(&vdec->inirq_thread_flag, 1); if (c->dev_threaded_isr) { @@ -1906,6 +2409,10 @@ unsigned long vdec_ready_to_run(struct vdec_s *vdec, unsigned long mask) if (!vdec->run_ready) return false; + /* when crc32 error, block at error frame */ + if (vdec->vfc.err_crc_block) + return false; + if ((vdec->slave || vdec->master) && (vdec->sched == 0)) return false; @@ -2014,6 +2521,15 @@ void vdec_prepare_run(struct vdec_s *vdec, unsigned long mask) if (!vdec_core_with_input(mask)) return; + if (secure && vdec_stream_based(vdec) && force_nosecure_even_drm) + { + /* Verimatrix ultra webclient (HLS) was played in drmmode and used hw demux. In drmmode VDEC only can access secure. + Now HW demux parsed es data to no-secure buffer. So the VDEC input was no-secure, VDEC playback failed. Forcing + use nosecure for verimatrix webclient HLS. If in the future HW demux can parse es data to secure buffer, make + VDEC r/w secure.*/ + secure = 0; + //pr_debug("allow VDEC can access nosecure even in drmmode\n"); + } if (input->target == VDEC_INPUT_TARGET_VLD) tee_config_device_secure(DMC_DEV_ID_VDEC, secure); else if (input->target == VDEC_INPUT_TARGET_HEVC) @@ -2039,8 +2555,9 @@ void vdec_prepare_run(struct vdec_s *vdec, unsigned long mask) static int vdec_core_thread(void *data) { struct vdec_core_s *core = (struct vdec_core_s *)data; - - struct sched_param param = {.sched_priority = MAX_RT_PRIO - 1}; + struct sched_param param = {.sched_priority = MAX_RT_PRIO/2}; + unsigned long flags; + int i; sched_setscheduler(current, SCHED_FIFO, ¶m); @@ -2053,7 +2570,16 @@ static int vdec_core_thread(void *data) if (kthread_should_stop()) break; + mutex_lock(&vdec_mutex); + if (core->parallel_dec == 1) { + for (i = VDEC_1; i < VDEC_MAX; i++) { + core->power_ref_mask = + core->power_ref_count[i] > 0 ? + (core->power_ref_mask | (1 << i)) : + (core->power_ref_mask & ~(1 << i)); + } + } /* clean up previous active vdec's input */ list_for_each_entry(vdec, &core->connected_vdec_list, list) { unsigned long mask = vdec->sched_mask & @@ -2075,8 +2601,8 @@ static int vdec_core_thread(void *data) &input->vframe_chunk_list)) { struct vframe_chunk_s *chunk = vdec_input_next_chunk(input); - if (chunk->flag & - VFRAME_CHUNK_FLAG_CONSUMED) + if (chunk && (chunk->flag & + VFRAME_CHUNK_FLAG_CONSUMED)) vdec_input_release_chunk(input, chunk); else @@ -2106,18 +2632,26 @@ static int vdec_core_thread(void *data) */ /* check disconnected decoders */ + flags = vdec_core_lock(vdec_core); list_for_each_entry_safe(vdec, tmp, &core->connected_vdec_list, list) { if ((vdec->status == VDEC_STATUS_CONNECTED) && (vdec->next_status == VDEC_STATUS_DISCONNECTED)) { - if (core->active_vdec == vdec) - core->active_vdec = NULL; + if (core->parallel_dec == 1) { + if (vdec_core->active_hevc == vdec) + vdec_core->active_hevc = NULL; + if (vdec_core->active_vdec == vdec) + vdec_core->active_vdec = NULL; + } + if (core->last_vdec == vdec) + core->last_vdec = NULL; list_move(&vdec->list, &disconnecting_list); } } - + vdec_core_unlock(vdec_core, flags); + mutex_unlock(&vdec_mutex); /* elect next vdec to be scheduled */ - vdec = core->active_vdec; + vdec = core->last_vdec; if (vdec) { vdec = list_entry(vdec->list.next, struct vdec_s, list); list_for_each_entry_from(vdec, @@ -2142,7 +2676,7 @@ static int vdec_core_thread(void *data) &core->connected_vdec_list, list) { sched_mask = vdec_schedule_mask(vdec, core->sched_mask); - if (vdec == core->active_vdec) { + if (vdec == core->last_vdec) { if (!sched_mask) { vdec = NULL; break; @@ -2188,11 +2722,19 @@ static int vdec_core_thread(void *data) /* vdec's sched_mask is only set from core thread */ vdec->sched_mask |= mask; - + if (core->last_vdec) { + if ((core->last_vdec != vdec) && + (core->last_vdec->mc_type != vdec->mc_type)) + vdec->mc_loaded = 0;/*clear for reload firmware*/ + } + core->last_vdec = vdec; + if (debug & 2) + vdec->mc_loaded = 0;/*alway reload firmware*/ vdec_set_status(vdec, VDEC_STATUS_ACTIVE); core->sched_mask |= mask; - core->active_vdec = vdec; + if (core->parallel_dec == 1) + vdec_save_active_hw(vdec); #ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC vdec_profile(vdec, VDEC_PROFILE_EVENT_RUN); #endif @@ -2207,20 +2749,39 @@ static int vdec_core_thread(void *data) /* we have some cores scheduled, keep working until * all vdecs are checked with no cores to schedule */ - up(&core->sem); + if (core->parallel_dec == 1) { + if (vdec_core->vdec_combine_flag == 0) + up(&core->sem); + } else + up(&core->sem); } /* remove disconnected decoder from active list */ list_for_each_entry_safe(vdec, tmp, &disconnecting_list, list) { list_del(&vdec->list); vdec_set_status(vdec, VDEC_STATUS_DISCONNECTED); + /*core->last_vdec = NULL;*/ complete(&vdec->inactive_done); } /* if there is no new work scheduled and nothing * is running, sleep 20ms */ - if ((!worker) && (!core->sched_mask)) { + if (core->parallel_dec == 1) { + if (vdec_core->vdec_combine_flag == 0) { + if ((!worker) && + ((core->sched_mask != core->power_ref_mask)) && + (atomic_read(&vdec_core->vdec_nr) > 0)) { + usleep_range(1000, 2000); + up(&core->sem); + } + } else { + if ((!worker) && (!core->sched_mask) && (atomic_read(&vdec_core->vdec_nr) > 0)) { + usleep_range(1000, 2000); + up(&core->sem); + } + } + } else if ((!worker) && (!core->sched_mask) && (atomic_read(&vdec_core->vdec_nr) > 0)) { usleep_range(1000, 2000); up(&core->sem); } @@ -2343,6 +2904,8 @@ void vdec_poweron(enum vdec_type_e core) dma_addr_t decomp_dma_addr; u32 decomp_addr_aligned = 0; int hevc_loop = 0; + int sleep_val, iso_val; + bool is_power_ctrl_ver2 = false; if (core >= VDEC_MAX) return; @@ -2360,6 +2923,10 @@ void vdec_poweron(enum vdec_type_e core) return; } + is_power_ctrl_ver2 = + ((get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) && + (get_cpu_major_id() != AM_MESON_CPU_MAJOR_ID_TL1)) ? true : false; + if (hevc_workaround_needed() && (core == VDEC_HEVC)) { decomp_addr = codec_mm_dma_alloc_coherent(MEM_NAME, @@ -2375,9 +2942,25 @@ void vdec_poweron(enum vdec_type_e core) } if (core == VDEC_1) { + sleep_val = is_power_ctrl_ver2 ? 0x2 : 0xc; + iso_val = is_power_ctrl_ver2 ? 0x2 : 0xc0; + /* vdec1 power on */ +#ifdef CONFIG_AMLOGIC_POWER + if (is_support_power_ctrl()) { + if (power_ctrl_sleep_mask(true, sleep_val, 0)) { + mutex_unlock(&vdec_mutex); + pr_err("vdec-1 power on ctrl sleep fail.\n"); + return; + } + } else { + WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0, + READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) & ~sleep_val); + } +#else WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0, - READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) & ~0xc); + READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) & ~sleep_val); +#endif /* wait 10uS */ udelay(10); /* vdec1 soft reset */ @@ -2389,16 +2972,31 @@ void vdec_poweron(enum vdec_type_e core) * m8baby and m8m2 can dynamic adjust vdec clock, * power on with default clock level */ + amports_switch_gate("clk_vdec_mux", 1); vdec_clock_hi_enable(); /* power up vdec memories */ WRITE_VREG(DOS_MEM_PD_VDEC, 0); + /* remove vdec1 isolation */ +#ifdef CONFIG_AMLOGIC_POWER + if (is_support_power_ctrl()) { + if (power_ctrl_iso_mask(true, iso_val, 0)) { + mutex_unlock(&vdec_mutex); + pr_err("vdec-1 power on ctrl iso fail.\n"); + return; + } + } else { + WRITE_AOREG(AO_RTI_GEN_PWR_ISO0, + READ_AOREG(AO_RTI_GEN_PWR_ISO0) & ~iso_val); + } +#else WRITE_AOREG(AO_RTI_GEN_PWR_ISO0, - READ_AOREG(AO_RTI_GEN_PWR_ISO0) & ~0xC0); + READ_AOREG(AO_RTI_GEN_PWR_ISO0) & ~iso_val); +#endif /* reset DOS top registers */ WRITE_VREG(DOS_VDEC_MCRCC_STALL_CTRL, 0); - if (get_cpu_type() >= - MESON_CPU_MAJOR_ID_GXBB) { + if (get_cpu_major_id() >= + AM_MESON_CPU_MAJOR_ID_GXBB) { /* *enable VDEC_1 DMC request */ @@ -2433,10 +3031,25 @@ void vdec_poweron(enum vdec_type_e core) } } else if (core == VDEC_HCODEC) { if (has_hdec()) { + sleep_val = is_power_ctrl_ver2 ? 0x1 : 0x3; + iso_val = is_power_ctrl_ver2 ? 0x1 : 0x30; + /* hcodec power on */ +#ifdef CONFIG_AMLOGIC_POWER + if (is_support_power_ctrl()) { + if (power_ctrl_sleep_mask(true, sleep_val, 0)) { + mutex_unlock(&vdec_mutex); + pr_err("hcodec power on ctrl sleep fail.\n"); + return; + } + } else { + WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0, + READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) & ~sleep_val); + } +#else WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0, - READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) & - ~0x3); + READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) & ~sleep_val); +#endif /* wait 10uS */ udelay(10); /* hcodec soft reset */ @@ -2447,34 +3060,75 @@ void vdec_poweron(enum vdec_type_e core) /* power up hcodec memories */ WRITE_VREG(DOS_MEM_PD_HCODEC, 0); /* remove hcodec isolation */ +#ifdef CONFIG_AMLOGIC_POWER + if (is_support_power_ctrl()) { + if (power_ctrl_iso_mask(true, iso_val, 0)) { + mutex_unlock(&vdec_mutex); + pr_err("hcodec power on ctrl iso fail.\n"); + return; + } + } else { + WRITE_AOREG(AO_RTI_GEN_PWR_ISO0, + READ_AOREG(AO_RTI_GEN_PWR_ISO0) & ~iso_val); + } +#else WRITE_AOREG(AO_RTI_GEN_PWR_ISO0, - READ_AOREG(AO_RTI_GEN_PWR_ISO0) & - ~0x30); + READ_AOREG(AO_RTI_GEN_PWR_ISO0) & ~iso_val); +#endif } } else if (core == VDEC_HEVC) { if (has_hevc_vdec()) { bool hevc_fixed = false; + sleep_val = is_power_ctrl_ver2 ? 0x4 : 0xc0; + iso_val = is_power_ctrl_ver2 ? 0x4 : 0xc00; + while (!hevc_fixed) { /* hevc power on */ +#ifdef CONFIG_AMLOGIC_POWER + if (is_support_power_ctrl()) { + if (power_ctrl_sleep_mask(true, sleep_val, 0)) { + mutex_unlock(&vdec_mutex); + pr_err("hevc power on ctrl sleep fail.\n"); + return; + } + } else { + WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0, + READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) & ~sleep_val); + } +#else WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0, - READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) & - ~0xc0); + READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) & ~sleep_val); +#endif /* wait 10uS */ udelay(10); /* hevc soft reset */ WRITE_VREG(DOS_SW_RESET3, 0xffffffff); WRITE_VREG(DOS_SW_RESET3, 0); /* enable hevc clock */ + amports_switch_gate("clk_hevc_mux", 1); + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A) + amports_switch_gate("clk_hevcb_mux", 1); hevc_clock_hi_enable(); hevc_back_clock_hi_enable(); /* power up hevc memories */ WRITE_VREG(DOS_MEM_PD_HEVC, 0); /* remove hevc isolation */ +#ifdef CONFIG_AMLOGIC_POWER + if (is_support_power_ctrl()) { + if (power_ctrl_iso_mask(true, iso_val, 0)) { + mutex_unlock(&vdec_mutex); + pr_err("hevc power on ctrl iso fail.\n"); + return; + } + } else { + WRITE_AOREG(AO_RTI_GEN_PWR_ISO0, + READ_AOREG(AO_RTI_GEN_PWR_ISO0) & ~iso_val); + } +#else WRITE_AOREG(AO_RTI_GEN_PWR_ISO0, - READ_AOREG(AO_RTI_GEN_PWR_ISO0) & - ~0xc00); - + READ_AOREG(AO_RTI_GEN_PWR_ISO0) & ~iso_val); +#endif if (!hevc_workaround_needed()) break; @@ -2526,6 +3180,9 @@ EXPORT_SYMBOL(vdec_poweron); void vdec_poweroff(enum vdec_type_e core) { + int sleep_val, iso_val; + bool is_power_ctrl_ver2 = false; + if (core >= VDEC_MAX) return; @@ -2537,9 +3194,16 @@ void vdec_poweroff(enum vdec_type_e core) return; } + is_power_ctrl_ver2 = + ((get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) && + (get_cpu_major_id() != AM_MESON_CPU_MAJOR_ID_TL1)) ? true : false; + if (core == VDEC_1) { - if (get_cpu_type() >= - MESON_CPU_MAJOR_ID_GXBB) { + sleep_val = is_power_ctrl_ver2 ? 0x2 : 0xc; + iso_val = is_power_ctrl_ver2 ? 0x2 : 0xc0; + + if (get_cpu_major_id() >= + AM_MESON_CPU_MAJOR_ID_GXBB) { /* disable VDEC_1 DMC REQ*/ unsigned long flags; @@ -2550,15 +3214,41 @@ void vdec_poweroff(enum vdec_type_e core) udelay(10); } /* enable vdec1 isolation */ +#ifdef CONFIG_AMLOGIC_POWER + if (is_support_power_ctrl()) { + if (power_ctrl_iso_mask(false, iso_val, 0)) { + mutex_unlock(&vdec_mutex); + pr_err("vdec-1 power off ctrl iso fail.\n"); + return; + } + } else { + WRITE_AOREG(AO_RTI_GEN_PWR_ISO0, + READ_AOREG(AO_RTI_GEN_PWR_ISO0) | iso_val); + } +#else WRITE_AOREG(AO_RTI_GEN_PWR_ISO0, - READ_AOREG(AO_RTI_GEN_PWR_ISO0) | 0xc0); + READ_AOREG(AO_RTI_GEN_PWR_ISO0) | iso_val); +#endif /* power off vdec1 memories */ WRITE_VREG(DOS_MEM_PD_VDEC, 0xffffffffUL); /* disable vdec1 clock */ vdec_clock_off(); /* vdec1 power off */ +#ifdef CONFIG_AMLOGIC_POWER + if (is_support_power_ctrl()) { + if (power_ctrl_sleep_mask(false, sleep_val, 0)) { + mutex_unlock(&vdec_mutex); + pr_err("vdec-1 power off ctrl sleep fail.\n"); + return; + } + } else { + WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0, + READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) | sleep_val); + } +#else WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0, - READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) | 0xc); + READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) | sleep_val); +#endif } else if (core == VDEC_2) { if (has_vdec2()) { /* enable vdec2 isolation */ @@ -2576,37 +3266,92 @@ void vdec_poweroff(enum vdec_type_e core) } } else if (core == VDEC_HCODEC) { if (has_hdec()) { + sleep_val = is_power_ctrl_ver2 ? 0x1 : 0x3; + iso_val = is_power_ctrl_ver2 ? 0x1 : 0x30; + /* enable hcodec isolation */ +#ifdef CONFIG_AMLOGIC_POWER + if (is_support_power_ctrl()) { + if (power_ctrl_iso_mask(false, iso_val, 0)) { + mutex_unlock(&vdec_mutex); + pr_err("hcodec power off ctrl iso fail.\n"); + return; + } + } else { + WRITE_AOREG(AO_RTI_GEN_PWR_ISO0, + READ_AOREG(AO_RTI_GEN_PWR_ISO0) | iso_val); + } +#else WRITE_AOREG(AO_RTI_GEN_PWR_ISO0, - READ_AOREG(AO_RTI_GEN_PWR_ISO0) | - 0x30); + READ_AOREG(AO_RTI_GEN_PWR_ISO0) | iso_val); +#endif /* power off hcodec memories */ WRITE_VREG(DOS_MEM_PD_HCODEC, 0xffffffffUL); /* disable hcodec clock */ hcodec_clock_off(); /* hcodec power off */ +#ifdef CONFIG_AMLOGIC_POWER + if (is_support_power_ctrl()) { + if (power_ctrl_sleep_mask(false, sleep_val, 0)) { + mutex_unlock(&vdec_mutex); + pr_err("hcodec power off ctrl sleep fail.\n"); + return; + } + } else { + WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0, + READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) | sleep_val); + } +#else WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0, - READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) | 3); + READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) | sleep_val); +#endif } } else if (core == VDEC_HEVC) { if (has_hevc_vdec()) { + sleep_val = is_power_ctrl_ver2 ? 0x4 : 0xc0; + iso_val = is_power_ctrl_ver2 ? 0x4 : 0xc00; + if (no_powerdown == 0) { /* enable hevc isolation */ +#ifdef CONFIG_AMLOGIC_POWER + if (is_support_power_ctrl()) { + if (power_ctrl_iso_mask(false, iso_val, 0)) { + mutex_unlock(&vdec_mutex); + pr_err("hevc power off ctrl iso fail.\n"); + return; + } + } else { + WRITE_AOREG(AO_RTI_GEN_PWR_ISO0, + READ_AOREG(AO_RTI_GEN_PWR_ISO0) | iso_val); + } +#else WRITE_AOREG(AO_RTI_GEN_PWR_ISO0, - READ_AOREG(AO_RTI_GEN_PWR_ISO0) | - 0xc00); - /* power off hevc memories */ - WRITE_VREG(DOS_MEM_PD_HEVC, 0xffffffffUL); + READ_AOREG(AO_RTI_GEN_PWR_ISO0) | iso_val); +#endif + /* power off hevc memories */ + WRITE_VREG(DOS_MEM_PD_HEVC, 0xffffffffUL); - /* disable hevc clock */ - hevc_clock_off(); - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) - hevc_back_clock_off(); + /* disable hevc clock */ + hevc_clock_off(); + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A) + hevc_back_clock_off(); - /* hevc power off */ - WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0, - READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) | - 0xc0); + /* hevc power off */ +#ifdef CONFIG_AMLOGIC_POWER + if (is_support_power_ctrl()) { + if (power_ctrl_sleep_mask(false, sleep_val, 0)) { + mutex_unlock(&vdec_mutex); + pr_err("hevc power off ctrl sleep fail.\n"); + return; + } + } else { + WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0, + READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) | sleep_val); + } +#else + WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0, + READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) | sleep_val); +#endif } else { pr_info("!!!!!!!!not power down\n"); hevc_reset_core(NULL); @@ -2623,7 +3368,10 @@ bool vdec_on(enum vdec_type_e core) bool ret = false; if (core == VDEC_1) { - if (((READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) & 0xc) == 0) && + if (((READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) & + (((get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) && + (get_cpu_major_id() != AM_MESON_CPU_MAJOR_ID_TL1)) + ? 0x2 : 0xc)) == 0) && (READ_HHI_REG(HHI_VDEC_CLK_CNTL) & 0x100)) ret = true; } else if (core == VDEC_2) { @@ -2634,13 +3382,19 @@ bool vdec_on(enum vdec_type_e core) } } else if (core == VDEC_HCODEC) { if (has_hdec()) { - if (((READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) & 0x3) == 0) && + if (((READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) & + (((get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) && + (get_cpu_major_id() != AM_MESON_CPU_MAJOR_ID_TL1)) + ? 0x1 : 0x3)) == 0) && (READ_HHI_REG(HHI_VDEC_CLK_CNTL) & 0x1000000)) ret = true; } } else if (core == VDEC_HEVC) { if (has_hevc_vdec()) { - if (((READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) & 0xc0) == 0) && + if (((READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) & + (((get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) && + (get_cpu_major_id() != AM_MESON_CPU_MAJOR_ID_TL1)) + ? 0x4 : 0xc0)) == 0) && (READ_HHI_REG(HHI_VDEC2_CLK_CNTL) & 0x1000000)) ret = true; } @@ -2746,6 +3500,82 @@ int vdec_source_changed(int format, int width, int height, int fps) } EXPORT_SYMBOL(vdec_source_changed); +void vdec_disable_DMC(struct vdec_s *vdec) +{ + /*close first,then wait pedding end,timing suggestion from vlsi*/ + unsigned long flags; + spin_lock_irqsave(&vdec_spin_lock, flags); + codec_dmcbus_write(DMC_REQ_CTRL, + codec_dmcbus_read(DMC_REQ_CTRL) & (~(1 << 13))); + spin_unlock_irqrestore(&vdec_spin_lock, flags); + + while (!(codec_dmcbus_read(DMC_CHAN_STS) + & (1 << 13))) + ; +} +EXPORT_SYMBOL(vdec_disable_DMC); + +void vdec_enable_DMC(struct vdec_s *vdec) +{ + unsigned long flags; + spin_lock_irqsave(&vdec_spin_lock, flags); + codec_dmcbus_write(DMC_REQ_CTRL, + codec_dmcbus_read(DMC_REQ_CTRL) | (1 << 13)); + spin_unlock_irqrestore(&vdec_spin_lock, flags); +} + +EXPORT_SYMBOL(vdec_enable_DMC); + +void vdec_reset_core(struct vdec_s *vdec) +{ + unsigned long flags; + spin_lock_irqsave(&vdec_spin_lock, flags); + codec_dmcbus_write(DMC_REQ_CTRL, + codec_dmcbus_read(DMC_REQ_CTRL) & (~(1 << 13))); + spin_unlock_irqrestore(&vdec_spin_lock, flags); + + while (!(codec_dmcbus_read(DMC_CHAN_STS) + & (1 << 13))) + ; + /* + * 2: assist + * 3: vld_reset + * 4: vld_part_reset + * 5: vfifo reset + * 6: iqidct + * 7: mc + * 8: dblk + * 9: pic_dc + * 10: psc + * 11: mcpu + * 12: ccpu + * 13: ddr + * 14: afifo + */ + + WRITE_VREG(DOS_SW_RESET0, + (1<<3)|(1<<4)|(1<<5)); + + WRITE_VREG(DOS_SW_RESET0, 0); + + spin_lock_irqsave(&vdec_spin_lock, flags); + codec_dmcbus_write(DMC_REQ_CTRL, + codec_dmcbus_read(DMC_REQ_CTRL) | (1 << 13)); + spin_unlock_irqrestore(&vdec_spin_lock, flags); +} +EXPORT_SYMBOL(vdec_reset_core); + +void hevc_enable_DMC(struct vdec_s *vdec) +{ + unsigned long flags; + spin_lock_irqsave(&vdec_spin_lock, flags); + codec_dmcbus_write(DMC_REQ_CTRL, + codec_dmcbus_read(DMC_REQ_CTRL) | (1 << 4)); + spin_unlock_irqrestore(&vdec_spin_lock, flags); +} + +EXPORT_SYMBOL(hevc_enable_DMC); + void hevc_reset_core(struct vdec_s *vdec) { unsigned long flags; @@ -2897,7 +3727,7 @@ static ssize_t amrisc_regs_show(struct class *class, unsigned int val; ssize_t ret; - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M8) { + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M8) { mutex_lock(&vdec_mutex); if (!vdec_on(VDEC_1)) { mutex_unlock(&vdec_mutex); @@ -2905,7 +3735,7 @@ static ssize_t amrisc_regs_show(struct class *class, ret = pbuf - buf; return ret; } - } else if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M6) { + } else if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M6) { /*TODO:M6 define */ /* * switch_mod_gate_by_type(MOD_VDEC, 1); @@ -2918,9 +3748,9 @@ static ssize_t amrisc_regs_show(struct class *class, pbuf += sprintf(pbuf, "%s(%#x)\t:%#x(%d)\n", regs[i].name, regs[i].offset, val, val); } - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M8) + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M8) mutex_unlock(&vdec_mutex); - else if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M6) { + else if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M6) { /*TODO:M6 define */ /* * switch_mod_gate_by_type(MOD_VDEC, 0); @@ -2944,7 +3774,7 @@ static ssize_t dump_trace_show(struct class *class, ret = pbuf - buf; return ret; } - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M8) { + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M8) { mutex_lock(&vdec_mutex); if (!vdec_on(VDEC_1)) { mutex_unlock(&vdec_mutex); @@ -2953,7 +3783,7 @@ static ssize_t dump_trace_show(struct class *class, ret = pbuf - buf; return ret; } - } else if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M6) { + } else if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M6) { /*TODO:M6 define */ /* * switch_mod_gate_by_type(MOD_VDEC, 1); @@ -2982,9 +3812,9 @@ static ssize_t dump_trace_show(struct class *class, i += 16; }; pr_info("dump trace steps:%d finished\n", debug_trace_num); - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M8) + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M8) mutex_unlock(&vdec_mutex); - else if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M6) { + else if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M6) { /*TODO:M6 define */ /* * switch_mod_gate_by_type(MOD_VDEC, 0); @@ -3141,6 +3971,7 @@ static ssize_t show_debug(struct class *class, struct vdec_s *vdec; struct vdec_core_s *core = vdec_core; unsigned long flags = vdec_core_lock(vdec_core); + u64 tmp; pbuf += sprintf(pbuf, "============== help:\n"); @@ -3180,11 +4011,12 @@ static ssize_t show_debug(struct class *class, vdec->input_underrun_count[type]); pbuf += sprintf(pbuf, "\t%d", vdec->not_run_ready_count[type]); + tmp = vdec->run_clk[type] * 100; + do_div(tmp, vdec->total_clk[type]); pbuf += sprintf(pbuf, "\t%d%%\n", vdec->total_clk[type] == 0 ? 0 : - (u32)((vdec->run_clk[type] * 100) - / vdec->total_clk[type])); + (u32)tmp); } } } @@ -3322,6 +4154,31 @@ struct vdec_s *vdec_get_default_vdec_for_userdata(void) } EXPORT_SYMBOL(vdec_get_default_vdec_for_userdata); +struct vdec_s *vdec_get_vdec_by_id(int vdec_id) +{ + struct vdec_s *vdec; + struct vdec_s *ret_vdec; + struct vdec_core_s *core = vdec_core; + unsigned long flags; + + flags = vdec_core_lock(vdec_core); + + ret_vdec = NULL; + if (!list_empty(&core->connected_vdec_list)) { + list_for_each_entry(vdec, &core->connected_vdec_list, list) { + if (vdec->id == vdec_id) { + ret_vdec = vdec; + break; + } + } + } + + vdec_core_unlock(vdec_core, flags); + + return ret_vdec; +} +EXPORT_SYMBOL(vdec_get_vdec_by_id); + int vdec_read_user_data(struct vdec_s *vdec, struct userdata_param_t *p_userdata_param) { @@ -3340,8 +4197,10 @@ EXPORT_SYMBOL(vdec_read_user_data); int vdec_wakeup_userdata_poll(struct vdec_s *vdec) { - /*if (vdec && vdec == vdec_get_default_vdec_for_userdata()) - amstream_wakeup_userdata_poll();*/ //DEBUG_TMP + if (vdec) { + if (vdec->wakeup_userdata_poll) + vdec->wakeup_userdata_poll(vdec); + } return 0; } @@ -3416,7 +4275,7 @@ static ssize_t dump_risc_mem_show(struct class *class, char *pbuf = buf; int ret; - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M8) { + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M8) { mutex_lock(&vdec_mutex); if (!vdec_on(VDEC_1)) { mutex_unlock(&vdec_mutex); @@ -3424,7 +4283,7 @@ static ssize_t dump_risc_mem_show(struct class *class, ret = pbuf - buf; return ret; } - } else if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M6) { + } else if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M6) { /*TODO:M6 define */ /* * switch_mod_gate_by_type(MOD_VDEC, 1); @@ -3444,9 +4303,9 @@ static ssize_t dump_risc_mem_show(struct class *class, } /*done*/ - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M8) + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M8) mutex_unlock(&vdec_mutex); - else if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M6) { + else if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M6) { /*TODO:M6 define */ /* * switch_mod_gate_by_type(MOD_VDEC, 0); @@ -3469,7 +4328,7 @@ static ssize_t core_show(struct class *class, struct class_attribute *attr, pbuf += sprintf(pbuf, " Core: last_sched %p, sched_mask %lx\n", - core->active_vdec, + core->last_vdec, core->sched_mask); list_for_each_entry(vdec, &core->connected_vdec_list, list) { @@ -3503,7 +4362,8 @@ static ssize_t vdec_status_show(struct class *class, } list_for_each_entry(vdec, &core->connected_vdec_list, list) { - if (VDEC_STATUS_CONNECTED == vdec->status) { + if ((vdec->status == VDEC_STATUS_CONNECTED + || vdec->status == VDEC_STATUS_ACTIVE)) { memset(&vs, 0, sizeof(vs)); if (vdec_status(vdec, &vs)) { pbuf += sprintf(pbuf, "err.\n"); @@ -3551,6 +4411,9 @@ static ssize_t vdec_status_show(struct class *class, pbuf += sprintf(pbuf, "%13s : %llu %s\n\n", "total data", vs.total_data / 1024, "KB"); + pbuf += sprintf(pbuf, + "%13s : %x\n", "ratio_control", + vs.ratio_control); vdec_num++; } @@ -3621,6 +4484,23 @@ static ssize_t dump_decoder_state_show(struct class *class, return pbuf - buf; } +static ssize_t dump_fps_show(struct class *class, + struct class_attribute *attr, char *buf) +{ + char *pbuf = buf; + struct vdec_core_s *core = vdec_core; + int i; + + unsigned long flags = vdec_fps_lock(vdec_core); + for (i = 0; i < MAX_INSTANCE_MUN; i++) + pbuf += sprintf(pbuf, "%d ", core->decode_fps[i].fps); + + pbuf += sprintf(pbuf, "\n"); + vdec_fps_unlock(vdec_core, flags); + + return pbuf - buf; +} + static struct class_attribute vdec_class_attrs[] = { @@ -3642,6 +4522,13 @@ static struct class_attribute vdec_class_attrs[] = { __ATTR(debug, S_IRUGO | S_IWUSR | S_IWGRP, show_debug, store_debug), #endif +#ifdef FRAME_CHECK + __ATTR(dump_yuv, S_IRUGO | S_IWUSR | S_IWGRP, + dump_yuv_show, dump_yuv_store), + __ATTR(frame_check, S_IRUGO | S_IWUSR | S_IWGRP, + frame_check_show, frame_check_store), +#endif + __ATTR_RO(dump_fps), __ATTR_NULL }; @@ -3699,7 +4586,7 @@ static int vdec_probe(struct platform_device *pdev) return r; } #if 0 - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) { + if (get_cpu_major_id() >= MESON_CPU_MAJOR_ID_G12A) { r = vdec_request_threaded_irq(VDEC_IRQ_HEVC_BACK, NULL, NULL, IRQF_ONESHOT, "vdec-hevc_back", NULL); if (r < 0) { @@ -3714,23 +4601,26 @@ static int vdec_probe(struct platform_device *pdev) vdec_core->cma_dev = &pdev->dev; - if (get_cpu_type() < MESON_CPU_MAJOR_ID_M8) { + if (get_cpu_major_id() < AM_MESON_CPU_MAJOR_ID_M8) { /* default to 250MHz */ vdec_clock_hi_enable(); } - if (get_cpu_type() == MESON_CPU_MAJOR_ID_GXBB) { + if (get_cpu_major_id() == AM_MESON_CPU_MAJOR_ID_GXBB) { /* set vdec dmc request to urgent */ WRITE_DMCREG(DMC_AM5_CHAN_CTRL, 0x3f203cf); } INIT_LIST_HEAD(&vdec_core->connected_vdec_list); spin_lock_init(&vdec_core->lock); + spin_lock_init(&vdec_core->canvas_lock); + spin_lock_init(&vdec_core->fps_lock); ida_init(&vdec_core->ida); vdec_core->thread = kthread_run(vdec_core_thread, vdec_core, "vdec-core"); - vdec_core->vdec_core_wq = create_singlethread_workqueue("threadvdec"); - + vdec_core->vdec_core_wq = alloc_ordered_workqueue("%s",__WQ_LEGACY | + WQ_MEM_RECLAIM |WQ_HIGHPRI/*high priority*/, "vdec-work"); + /*work queue priority lower than vdec-core.*/ return 0; } @@ -3782,6 +4672,11 @@ static struct platform_driver vdec_driver = { } }; +static struct codec_profile_t amvdec_input_profile = { + .name = "vdec_input", + .profile = "drm_framemode" +}; + int vdec_module_init(void) { if (platform_driver_register(&vdec_driver)) { @@ -3790,6 +4685,7 @@ int vdec_module_init(void) } INIT_REG_NODE_CONFIGS("media.decoder", &vdec_node, "vdec", vdec_configs, CONFIG_FOR_RW); + vcodec_profile_register(&amvdec_input_profile); return 0; } EXPORT_SYMBOL(vdec_module_init); @@ -3837,6 +4733,105 @@ static int __init vdec_mem_setup(struct reserved_mem *rmem) return 0; } +void vdec_fill_frame_info(struct vframe_qos_s *vframe_qos, int debug) +{ + if (frame_info_buf_in == NULL) { + pr_info("error,frame_info_buf_in is null\n"); + return; + } + if (frame_info_buf_out == NULL) { + pr_info("error,frame_info_buf_out is null\n"); + return; + } + if (frame_qos_wr >= QOS_FRAME_NUM) + frame_qos_wr = 0; + + if (frame_qos_wr >= QOS_FRAME_NUM || + frame_qos_wr < 0) { + pr_info("error,index :%d is error\n", frame_qos_wr); + return; + } + if (frameinfo_flag == DISABLE_FRAME_INFO) + return; + + if (frameinfo_flag == PRINT_FRAME_INFO) { + pr_info("num %d size %d pts %d\n", + vframe_qos->num, + vframe_qos->size, + vframe_qos->pts); + pr_info("mv min_mv %d avg_mv %d max_mv %d\n", + vframe_qos->min_mv, + vframe_qos->avg_mv, + vframe_qos->max_mv); + pr_info("qp min_qp %d avg_qp %d max_qp %d\n", + vframe_qos->min_qp, + vframe_qos->avg_qp, + vframe_qos->max_qp); + pr_info("skip min_skip %d avg_skip %d max_skip %d\n", + vframe_qos->min_skip, + vframe_qos->avg_skip, + vframe_qos->max_skip); + } + memcpy(&frame_info_buf_in[frame_qos_wr++], + vframe_qos, sizeof(struct vframe_qos_s)); + if (frame_qos_wr >= QOS_FRAME_NUM) + frame_qos_wr = 0; + + /*pr_info("frame_qos_wr:%d\n", frame_qos_wr);*/ + +} +EXPORT_SYMBOL(vdec_fill_frame_info); + +struct vframe_qos_s *vdec_get_qos_info(void) +{ + int write_count = 0; + int qos_wr = frame_qos_wr; + + if (frame_info_buf_in == NULL) { + pr_info("error,frame_info_buf_in is null\n"); + return NULL; + } + if (frame_info_buf_out == NULL) { + pr_info("error,frame_info_buf_out is null\n"); + return NULL; + } + + + memset(frame_info_buf_out, 0, + QOS_FRAME_NUM*sizeof(struct vframe_qos_s)); + if (frame_qos_rd > qos_wr) { + write_count = QOS_FRAME_NUM - frame_qos_rd; + if (write_count > 0 && write_count <= QOS_FRAME_NUM) { + memcpy(frame_info_buf_out, &frame_info_buf_in[0], + write_count*sizeof(struct vframe_qos_s)); + if ((write_count + qos_wr) <= QOS_FRAME_NUM) + memcpy(&frame_info_buf_out[write_count], frame_info_buf_in, + qos_wr*sizeof(struct vframe_qos_s)); + else + pr_info("get_qos_info:%d,out of range\n", __LINE__); + } else + pr_info("get_qos_info:%d,out of range\n", __LINE__); + } else if (frame_qos_rd < qos_wr) { + write_count = qos_wr - frame_qos_rd; + if (write_count > 0 && write_count < QOS_FRAME_NUM) + memcpy(frame_info_buf_out, &frame_info_buf_in[frame_qos_rd], + (write_count)*sizeof(struct vframe_qos_s)); + else + pr_info("get_qos_info:%d, out of range\n", __LINE__); + } + /* + pr_info("cnt:%d,size:%d,num:%d,rd:%d,wr:%d\n", + wirte_count, + frame_info_buf_out[0].size, + frame_info_buf_out[0].num, + frame_qos_rd,qos_wr); + */ + frame_qos_rd = qos_wr; + return frame_info_buf_out; +} +EXPORT_SYMBOL(vdec_get_qos_info); + + RESERVEDMEM_OF_DECLARE(vdec, "amlogic, vdec-memory", vdec_mem_setup); /* uint force_hevc_clock_cntl; @@ -3844,12 +4839,20 @@ EXPORT_SYMBOL(force_hevc_clock_cntl); module_param(force_hevc_clock_cntl, uint, 0664); */ +module_param(debug, uint, 0664); module_param(debug_trace_num, uint, 0664); module_param(hevc_max_reset_count, int, 0664); module_param(clk_config, uint, 0664); module_param(step_mode, int, 0664); module_param(debugflags, int, 0664); +module_param(parallel_decode, int, 0664); +module_param(fps_detection, int, 0664); +module_param(fps_clear, int, 0664); +module_param(force_nosecure_even_drm, int, 0664); +module_param(frameinfo_flag, int, 0664); +MODULE_PARM_DESC(frameinfo_flag, + "\n frameinfo_flag\n"); /* *module_init(vdec_module_init); *module_exit(vdec_module_exit); diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec.h b/drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec.h index 90158f300eae..b7287fb95238 100644 --- a/drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec.h +++ b/drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec.h @@ -32,6 +32,7 @@ /*#define CONFIG_AM_VDEC_DV*/ #include "vdec_input.h" +#include "frame_check.h" s32 vdec_dev_register(void); s32 vdec_dev_unregister(void); @@ -43,6 +44,8 @@ struct device *get_vdec_device(void); int vdec_module_init(void); void vdec_module_exit(void); +#define MAX_INSTANCE_MUN 9 + #define VDEC_DEBUG_SUPPORT #define DEC_FLAG_HEVC_WORKAROUND 0x01 @@ -117,6 +120,7 @@ extern void dma_contiguous_early_fixup(phys_addr_t base, unsigned long size); unsigned int get_vdec_clk_config_settings(void); void update_vdec_clk_config_settings(unsigned int config); //unsigned int get_mmu_mode(void);//DEBUG_TMP +extern void vdec_fill_frame_info(struct vframe_qos_s *vframe_qos, int debug); struct vdec_s; enum vformat_t; @@ -147,7 +151,7 @@ enum vformat_t; #define VDEC_PROVIDER_NAME_SIZE 16 #define VDEC_RECEIVER_NAME_SIZE 16 -#define VDEC_MAP_NAME_SIZE 45 +#define VDEC_MAP_NAME_SIZE 90 #define VDEC_FLAG_OTHER_INPUT_CONTEXT 0x0 #define VDEC_FLAG_SELF_INPUT_CONTEXT 0x01 @@ -175,9 +179,12 @@ struct vdec_s { u32 pts; u64 pts64; bool pts_valid; + u64 timestamp; + bool timestamp_valid; int flag; int sched; int need_more_data; + u32 canvas_mode; struct completion inactive_done; @@ -195,10 +202,13 @@ struct vdec_s { /* input */ struct vdec_input_s input; + /*frame check*/ + struct pic_check_mgr_t vfc; + /* mc cache */ u32 mc[4096 * 4]; bool mc_loaded; - + u32 mc_type; /* frame provider/receiver interface */ char vf_provider_name[VDEC_PROVIDER_NAME_SIZE]; struct vframe_provider_s vframe_provider; @@ -216,10 +226,13 @@ struct vdec_s { /* canvas */ int (*get_canvas)(unsigned int index, unsigned int base); + int (*get_canvas_ex)(int type, int id); + void (*free_canvas_ex)(int index, int id); int (*dec_status)(struct vdec_s *vdec, struct vdec_info *vstatus); int (*set_trickmode)(struct vdec_s *vdec, unsigned long trickmode); int (*set_isreset)(struct vdec_s *vdec, int isreset); + void (*vdec_fps_detec)(int id); unsigned long (*run_ready)(struct vdec_s *vdec, unsigned long mask); void (*run)(struct vdec_s *vdec, unsigned long mask, @@ -232,7 +245,7 @@ struct vdec_s { int (*user_data_read)(struct vdec_s *vdec, struct userdata_param_t *puserdata_para); void (*reset_userdata_fifo)(struct vdec_s *vdec, int bInit); - + void (*wakeup_userdata_poll)(struct vdec_s *vdec); /* private */ void *private; /* decoder per instance specific data */ #ifdef VDEC_DEBUG_SUPPORT @@ -247,6 +260,7 @@ struct vdec_s { #endif atomic_t inirq_thread_flag; atomic_t inirq_flag; + int parallel_dec; }; /* common decoder vframe provider name to use default vfm path */ @@ -383,6 +397,8 @@ extern void vdec_count_info(struct vdec_info *vs, unsigned int err, extern bool vdec_need_more_data(struct vdec_s *vdec); +extern void vdec_reset_core(struct vdec_s *vdec); + extern void hevc_reset_core(struct vdec_s *vdec); extern void vdec_set_suspend_clk(int mode, int hevc); @@ -391,11 +407,11 @@ extern unsigned long vdec_ready_to_run(struct vdec_s *vdec, unsigned long mask); extern void vdec_prepare_run(struct vdec_s *vdec, unsigned long mask); -extern int vdec_core_request(struct vdec_s *vdec, unsigned long mask); +extern void vdec_core_request(struct vdec_s *vdec, unsigned long mask); extern int vdec_core_release(struct vdec_s *vdec, unsigned long mask); -extern const bool vdec_core_with_input(unsigned long mask); +extern bool vdec_core_with_input(unsigned long mask); extern void vdec_core_finish_run(struct vdec_s *vdec, unsigned long mask); @@ -403,6 +419,10 @@ extern void vdec_core_finish_run(struct vdec_s *vdec, unsigned long mask); extern void vdec_set_step_mode(void); #endif +extern void vdec_disable_DMC(struct vdec_s *vdec); +extern void vdec_enable_DMC(struct vdec_s *vdec); +extern void hevc_enable_DMC(struct vdec_s *vdec); + int vdec_read_user_data(struct vdec_s *vdec, struct userdata_param_t *p_userdata_param); @@ -410,6 +430,8 @@ int vdec_wakeup_userdata_poll(struct vdec_s *vdec); void vdec_reset_userdata_fifo(struct vdec_s *vdec, int bInit); +struct vdec_s *vdec_get_vdec_by_id(int vdec_id); + #ifdef VDEC_DEBUG_SUPPORT extern void vdec_set_step_mode(void); #endif @@ -417,4 +439,11 @@ int vdec_get_debug_flags(void); unsigned char is_mult_inc(unsigned int); +int vdec_get_status(struct vdec_s *vdec); + +void vdec_set_timestamp(struct vdec_s *vdec, u64 timestamp); + +struct vdec_s *vdec_get_with_id(unsigned int id); + +extern struct vframe_qos_s *vdec_get_qos_info(void); #endif /* VDEC_H */ diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec_input.c b/drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec_input.c index 439e513677d3..f571bcf52592 100644 --- a/drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec_input.c +++ b/drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec_input.c @@ -25,6 +25,11 @@ #include "vdec.h" #include "vdec_input.h" +#include +#include + +#include + #define VFRAME_BLOCK_SIZE (512 * SZ_1K)/*512 for 1080p default init.*/ #define VFRAME_BLOCK_SIZE_4K (2 * SZ_1M) /*2M for 4K default.*/ #define VFRAME_BLOCK_SIZE_MAX (4 * SZ_1M) @@ -47,49 +52,96 @@ #define EXTRA_PADDING_SIZE (16 * SZ_1K) /*HEVC_PADDING_SIZE*/ #define MEM_NAME "VFRAME_INPUT" -static int vdec_input_get_duration_u64(struct vdec_input_s *input); + +//static int vdec_input_get_duration_u64(struct vdec_input_s *input); static struct vframe_block_list_s * - vdec_input_alloc_new_block(struct vdec_input_s *input); + vdec_input_alloc_new_block(struct vdec_input_s *input, + ulong phy_addr, + int size); + +static int copy_from_user_to_phyaddr(void *virts, const char __user *buf, + u32 size, ulong phys, u32 pading, bool is_mapped) +{ + u32 i, span = SZ_1M; + u32 count = size / PAGE_ALIGN(span); + u32 remain = size % PAGE_ALIGN(span); + ulong addr = phys; + u8 *p = virts; + + if (is_mapped) { + if (copy_from_user(p, buf, size)) + return -EFAULT; + + if (pading) + memset(p + size, 0, pading); + + codec_mm_dma_flush(p, size + pading, DMA_TO_DEVICE); + + return 0; + } + + for (i = 0; i < count; i++) { + addr = phys + i * span; + p = codec_mm_vmap(addr, span); + if (!p) + return -1; + + if (copy_from_user(p, buf + i * span, span)) { + codec_mm_unmap_phyaddr(p); + return -EFAULT; + } + + codec_mm_dma_flush(p, span, DMA_TO_DEVICE); + codec_mm_unmap_phyaddr(p); + } + + if (!remain) + return 0; + + span = size - remain; + addr = phys + span; + p = codec_mm_vmap(addr, remain + pading); + if (!p) + return -1; + + if (copy_from_user(p, buf + span, remain)) { + codec_mm_unmap_phyaddr(p); + return -EFAULT; + } + + if (pading) + memset(p + remain, 0, pading); + + codec_mm_dma_flush(p, remain + pading, DMA_TO_DEVICE); + codec_mm_unmap_phyaddr(p); + + return 0; +} static int vframe_chunk_fill(struct vdec_input_s *input, struct vframe_chunk_s *chunk, const char *buf, size_t count, struct vframe_block_list_s *block) { u8 *p = (u8 *)block->start_virt + block->wp; - int total_size = count + chunk->pading_size; if (block->type == VDEC_TYPE_FRAME_BLOCK) { - if (copy_from_user(p, buf, count)) - return -EFAULT; - - p += count; - - memset(p, 0, chunk->pading_size); - - dma_sync_single_for_device(get_vdec_device(), + copy_from_user_to_phyaddr(p, buf, count, block->start + block->wp, - total_size, DMA_TO_DEVICE); - + chunk->pading_size, + block->is_mapped); } else if (block->type == VDEC_TYPE_FRAME_CIRCULAR) { size_t len = min((size_t)(block->size - block->wp), count); u32 wp; - if (copy_from_user(p, buf, len)) - return -EFAULT; - - dma_sync_single_for_device(get_vdec_device(), - block->start + block->wp, - len, DMA_TO_DEVICE); - + copy_from_user_to_phyaddr(p, buf, len, + block->start + block->wp, 0, + block->is_mapped); p += len; if (count > len) { - p = (u8 *)block->start_virt; - if (copy_from_user(p, buf, count - len)) - return -EFAULT; - - dma_sync_single_for_device(get_vdec_device(), - block->start, - count-len, DMA_TO_DEVICE); + copy_from_user_to_phyaddr(p, buf + len, + count - len, + block->start, 0, + block->is_mapped); p += count - len; } @@ -100,20 +152,33 @@ static int vframe_chunk_fill(struct vdec_input_s *input, len = min(block->size - wp, chunk->pading_size); - memset(p, 0, len); - - dma_sync_single_for_device(get_vdec_device(), - block->start + wp, - len, DMA_TO_DEVICE); + if (!block->is_mapped) { + p = codec_mm_vmap(block->start + wp, len); + memset(p, 0, len); + codec_mm_dma_flush(p, len, DMA_TO_DEVICE); + codec_mm_unmap_phyaddr(p); + } else { + memset(p, 0, len); + codec_mm_dma_flush(p, len, DMA_TO_DEVICE); + } if (chunk->pading_size > len) { p = (u8 *)block->start_virt; - memset(p, 0, count - len); - - dma_sync_single_for_device(get_vdec_device(), - block->start, - chunk->pading_size - len, DMA_TO_DEVICE); + if (!block->is_mapped) { + p = codec_mm_vmap(block->start, + chunk->pading_size - len); + memset(p, 0, chunk->pading_size - len); + codec_mm_dma_flush(p, + chunk->pading_size - len, + DMA_TO_DEVICE); + codec_mm_unmap_phyaddr(p); + } else { + memset(p, 0, chunk->pading_size - len); + codec_mm_dma_flush(p, + chunk->pading_size - len, + DMA_TO_DEVICE); + } } } @@ -157,7 +222,9 @@ static void vframe_block_free_block(struct vframe_block_list_s *block) } static int vframe_block_init_alloc_storage(struct vdec_input_s *input, - struct vframe_block_list_s *block) + struct vframe_block_list_s *block, + ulong phy_addr, + int size) { int alloc_size = input->default_block_size; block->magic = 0x4b434c42; @@ -167,24 +234,34 @@ static int vframe_block_init_alloc_storage(struct vdec_input_s *input, /* * todo: for different type use different size */ - alloc_size = PAGE_ALIGN(alloc_size); - block->addr = codec_mm_alloc_for_dma_ex( - MEM_NAME, - alloc_size/PAGE_SIZE, - VFRAME_BLOCK_PAGEALIGN, - CODEC_MM_FLAGS_DMA_CPU | CODEC_MM_FLAGS_FOR_VDECODER, - input->id, - block->id); + if (phy_addr) { + block->is_out_buf = 1; + block->start_virt = NULL; + block->start = phy_addr; + block->size = size; + } else { + alloc_size = PAGE_ALIGN(alloc_size); + block->addr = codec_mm_alloc_for_dma_ex( + MEM_NAME, + alloc_size/PAGE_SIZE, + VFRAME_BLOCK_PAGEALIGN, + CODEC_MM_FLAGS_DMA_CPU | CODEC_MM_FLAGS_FOR_VDECODER, + input->id, + block->id); - if (!block->addr) { - pr_err("Input block allocation failed\n"); - return -ENOMEM; + if (!block->addr) { + pr_err("Input block allocation failed\n"); + return -ENOMEM; + } + + block->start_virt = (void *)codec_mm_phys_to_virt(block->addr); + if (block->start_virt) + block->is_mapped = true; + block->start = block->addr; + block->size = alloc_size; + block->is_out_buf = 0; } - block->start_virt = (void *)codec_mm_phys_to_virt(block->addr); - block->start = block->addr; - block->size = alloc_size; - return 0; } @@ -208,6 +285,8 @@ int vdec_input_prepare_bufs(struct vdec_input_s *input, int i; unsigned long flags; + if (vdec_secure(input->vdec)) + return 0; if (input->size > 0) return 0; if (frame_width * frame_height >= 1920 * 1088) { @@ -216,7 +295,7 @@ int vdec_input_prepare_bufs(struct vdec_input_s *input, } /*prepared 3 buffers for smooth start.*/ for (i = 0; i < 3; i++) { - block = vdec_input_alloc_new_block(input); + block = vdec_input_alloc_new_block(input, 0, 0); if (!block) break; flags = vdec_input_lock(input); @@ -505,7 +584,9 @@ int vdec_input_level(struct vdec_input_s *input) EXPORT_SYMBOL(vdec_input_level); static struct vframe_block_list_s * - vdec_input_alloc_new_block(struct vdec_input_s *input) + vdec_input_alloc_new_block(struct vdec_input_s *input, + ulong phy_addr, + int size) { struct vframe_block_list_s *block; block = kzalloc(sizeof(struct vframe_block_list_s), @@ -517,7 +598,7 @@ static struct vframe_block_list_s * } if (vframe_block_init_alloc_storage(input, - block) != 0) { + block, phy_addr, size) != 0) { kfree(block); pr_err("vframe_block storage allocation failed\n"); return NULL; @@ -551,7 +632,7 @@ static struct vframe_block_list_s * } return block; } -static int vdec_input_get_duration_u64(struct vdec_input_s *input) +int vdec_input_get_duration_u64(struct vdec_input_s *input) { int duration = (input->last_inpts_u64 - input->last_comsumed_pts_u64); if (input->last_in_nopts_cnt > 0 && @@ -571,6 +652,8 @@ static int vdec_input_get_duration_u64(struct vdec_input_s *input) duration = 0; return duration; } +EXPORT_SYMBOL(vdec_input_get_duration_u64); + /* ret >= 13: have enough buffer, blocked add more buffers */ @@ -646,7 +729,7 @@ static int vdec_input_get_free_block( /*128k aligned,same as codec_mm*/ input->default_block_size = def_size; } - block = vdec_input_alloc_new_block(input); + block = vdec_input_alloc_new_block(input, 0, 0); if (!block) { input->no_mem_err_cnt++; return -EAGAIN; @@ -656,94 +739,104 @@ static int vdec_input_get_free_block( return 0; } -int vdec_input_add_frame(struct vdec_input_s *input, const char *buf, - size_t count) +int vdec_input_add_chunk(struct vdec_input_s *input, const char *buf, + size_t count, u32 handle) { unsigned long flags; struct vframe_chunk_s *chunk; struct vdec_s *vdec = input->vdec; struct vframe_block_list_s *block; + int need_pading_size = MIN_FRAME_PADDING_SIZE; -#if 0 - if (add_count == 0) { - add_count++; - memcpy(sps, buf, 30); - return 30; - } else if (add_count == 1) { - add_count++; - memcpy(pps, buf, 8); - return 8; - } - add_count++; -#endif - -#if 0 - pr_info("vdec_input_add_frame add %p, count=%d\n", buf, (int)count); - - if (count >= 8) { - pr_info("%02x %02x %02x %02x %02x %02x %02x %02x\n", - buf[0], buf[1], buf[2], buf[3], - buf[4], buf[5], buf[6], buf[7]); - } - if (count >= 16) { - pr_info("%02x %02x %02x %02x %02x %02x %02x %02x\n", - buf[8], buf[9], buf[10], buf[11], - buf[12], buf[13], buf[14], buf[15]); - } - if (count >= 24) { - pr_info("%02x %02x %02x %02x %02x %02x %02x %02x\n", - buf[16], buf[17], buf[18], buf[19], - buf[20], buf[21], buf[22], buf[23]); - } - if (count >= 32) { - pr_info("%02x %02x %02x %02x %02x %02x %02x %02x\n", - buf[24], buf[25], buf[26], buf[27], - buf[28], buf[29], buf[30], buf[31]); - } -#endif - if (input_stream_based(input)) - return -EINVAL; - if (count < PAGE_SIZE) { - need_pading_size = PAGE_ALIGN(count + need_pading_size) - - count; + if (vdec_secure(vdec)) { + block = vdec_input_alloc_new_block(input, (ulong)buf, + PAGE_ALIGN(count + HEVC_PADDING_SIZE + 1)); /*Add padding large than HEVC_PADDING_SIZE */ + if (!block) + return -ENOMEM; + block->handle = handle; } else { - /*to 64 bytes aligned;*/ - if (count & 0x3f) - need_pading_size += 64 - (count & 0x3f); - } - block = input->wr_block; - if (block && - (vframe_block_space(block) > (count + need_pading_size))) { - /*this block have enough buffers. - do nothings. - */ - } else if (block && (block->type == VDEC_TYPE_FRAME_CIRCULAR)) { - /*in circular module. - only one block,.*/ - return -EAGAIN; - } else if (block != NULL) { - /*have block but not enough space. - recycle the no enough blocks.*/ - flags = vdec_input_lock(input); - if (input->wr_block == block && - block->chunk_count == 0) { - block->rp = 0; - block->wp = 0; - /*block no data move to freelist*/ - list_move_tail(&block->list, - &input->vframe_block_free_list); - input->wr_block = NULL; +#if 0 + if (add_count == 0) { + add_count++; + memcpy(sps, buf, 30); + return 30; + } else if (add_count == 1) { + add_count++; + memcpy(pps, buf, 8); + return 8; } - vdec_input_unlock(input, flags); - block = NULL; + add_count++; +#endif + +#if 0 + pr_info("vdec_input_add_frame add %p, count=%d\n", buf, (int)count); + + if (count >= 8) { + pr_info("%02x %02x %02x %02x %02x %02x %02x %02x\n", + buf[0], buf[1], buf[2], buf[3], + buf[4], buf[5], buf[6], buf[7]); + } + if (count >= 16) { + pr_info("%02x %02x %02x %02x %02x %02x %02x %02x\n", + buf[8], buf[9], buf[10], buf[11], + buf[12], buf[13], buf[14], buf[15]); + } + if (count >= 24) { + pr_info("%02x %02x %02x %02x %02x %02x %02x %02x\n", + buf[16], buf[17], buf[18], buf[19], + buf[20], buf[21], buf[22], buf[23]); + } + if (count >= 32) { + pr_info("%02x %02x %02x %02x %02x %02x %02x %02x\n", + buf[24], buf[25], buf[26], buf[27], + buf[28], buf[29], buf[30], buf[31]); } - if (!block) {/*try new block.*/ - int ret = vdec_input_get_free_block(input, - count + need_pading_size + EXTRA_PADDING_SIZE, - &block); - if (ret < 0)/*no enough block now.*/ - return ret; +#endif + if (input_stream_based(input)) + return -EINVAL; + + if (count < PAGE_SIZE) { + need_pading_size = PAGE_ALIGN(count + need_pading_size) - + count; + } else { + /*to 64 bytes aligned;*/ + if (count & 0x3f) + need_pading_size += 64 - (count & 0x3f); + } + block = input->wr_block; + if (block && + (vframe_block_space(block) > (count + need_pading_size))) { + /*this block have enough buffers. + do nothings. + */ + } else if (block && (block->type == VDEC_TYPE_FRAME_CIRCULAR)) { + /*in circular module. + only one block,.*/ + return -EAGAIN; + } else if (block != NULL) { + /*have block but not enough space. + recycle the no enough blocks.*/ + flags = vdec_input_lock(input); + if (input->wr_block == block && + block->chunk_count == 0) { + block->rp = 0; + block->wp = 0; + /*block no data move to freelist*/ + list_move_tail(&block->list, + &input->vframe_block_free_list); + input->wr_block = NULL; + } + vdec_input_unlock(input, flags); + block = NULL; + } + if (!block) {/*try new block.*/ + int ret = vdec_input_get_free_block(input, + count + need_pading_size + EXTRA_PADDING_SIZE, + &block); + if (ret < 0)/*no enough block now.*/ + return ret; + } } chunk = kzalloc(sizeof(struct vframe_chunk_s), GFP_KERNEL); @@ -758,6 +851,10 @@ int vdec_input_add_frame(struct vdec_input_s *input, const char *buf, chunk->pts = vdec->pts; chunk->pts64 = vdec->pts64; } + + if (vdec->timestamp_valid) + chunk->timestamp = vdec->timestamp; + if (vdec->pts_valid && input->last_inpts_u64 > 0 && input->last_in_nopts_cnt == 0) { @@ -771,17 +868,26 @@ int vdec_input_add_frame(struct vdec_input_s *input, const char *buf, } chunk->pts_valid = vdec->pts_valid; vdec->pts_valid = false; - chunk->offset = block->wp; - chunk->size = count; - chunk->pading_size = need_pading_size; INIT_LIST_HEAD(&chunk->list); - if (vframe_chunk_fill(input, chunk, buf, count, block)) { - pr_err("vframe_chunk_fill failed\n"); - kfree(chunk); - return -EFAULT; + if (vdec_secure(vdec)) { + chunk->offset = 0; + chunk->size = count; + chunk->pading_size = PAGE_ALIGN(chunk->size + need_pading_size) - + chunk->size; + } else { + chunk->offset = block->wp; + chunk->size = count; + chunk->pading_size = need_pading_size; + if (vframe_chunk_fill(input, chunk, buf, count, block)) { + pr_err("vframe_chunk_fill failed\n"); + kfree(chunk); + return -EFAULT; + } + } + flags = vdec_input_lock(input); vframe_block_add_chunk(block, chunk); @@ -789,6 +895,7 @@ int vdec_input_add_frame(struct vdec_input_s *input, const char *buf, list_add_tail(&chunk->list, &input->vframe_chunk_list); input->data_size += chunk->size; input->have_frame_num++; + ATRACE_COUNTER(MEM_NAME, input->have_frame_num); if (chunk->pts_valid) { input->last_inpts_u64 = chunk->pts64; input->last_in_nopts_cnt = 0; @@ -796,11 +903,10 @@ int vdec_input_add_frame(struct vdec_input_s *input, const char *buf, /*nopts*/ input->last_in_nopts_cnt++; } - vdec_input_unlock(input, flags); if (chunk->size > input->frame_max_size) input->frame_max_size = chunk->size; input->total_wr_count += count; - + vdec_input_unlock(input, flags); #if 0 if (add_count == 2) input->total_wr_count += 38; @@ -808,6 +914,39 @@ int vdec_input_add_frame(struct vdec_input_s *input, const char *buf, return count; } + +int vdec_input_add_frame(struct vdec_input_s *input, const char *buf, + size_t count) +{ + int ret = 0; + struct drm_info drm; + struct vdec_s *vdec = input->vdec; + unsigned long phy_buf; + + if (vdec_secure(vdec)) { + while (count > 0) { + if (count < sizeof(struct drm_info)) + return -EIO; + if (copy_from_user(&drm, buf + ret, sizeof(struct drm_info))) + return -EAGAIN; + if (!(drm.drm_flag & TYPE_DRMINFO_V2)) + return -EIO; /*must drm info v2 version*/ + phy_buf = (unsigned long) drm.drm_phy; + vdec_input_add_chunk(input, (char *)phy_buf, + (size_t)drm.drm_pktsize, drm.handle); + count -= sizeof(struct drm_info); + ret += sizeof(struct drm_info); + + /* the drm frame data might include head infos and raw */ + /* data thus the next drm unit still need a valid pts.*/ + if (count >= sizeof(struct drm_info)) + vdec->pts_valid = true; + } + } else { + ret = vdec_input_add_chunk(input, buf, count, 0); + } + return ret; +} EXPORT_SYMBOL(vdec_input_add_frame); struct vframe_chunk_s *vdec_input_next_chunk(struct vdec_input_s *input) @@ -855,6 +994,7 @@ void vdec_input_release_chunk(struct vdec_input_s *input, list_del(&chunk->list); input->have_frame_num--; + ATRACE_COUNTER(MEM_NAME, input->have_frame_num); if (chunk->pts_valid) { input->last_comsumed_no_pts_cnt = 0; input->last_comsumed_pts_u64 = chunk->pts64; @@ -867,8 +1007,11 @@ void vdec_input_release_chunk(struct vdec_input_s *input, block->chunk_count--; input->data_size -= chunk->size; input->total_rd_count += chunk->size; - if (block->chunk_count == 0 && - input->wr_block != block) {/*don't free used block*/ + if (block->is_out_buf) { + list_move_tail(&block->list, + &input->vframe_block_free_list); + } else if (block->chunk_count == 0 && + input->wr_block != block ) {/*don't free used block*/ if (block->size < input->default_block_size) { vdec_input_del_block_locked(input, block); tofreeblock = block; @@ -938,3 +1081,26 @@ void vdec_input_release(struct vdec_input_s *input) } EXPORT_SYMBOL(vdec_input_release); +u32 vdec_input_get_freed_handle(struct vdec_s *vdec) +{ + struct vframe_block_list_s *block; + struct vdec_input_s *input = &vdec->input; + unsigned long flags; + u32 handle = 0; + + if (!vdec_secure(vdec)) + return 0; + + flags = vdec_input_lock(input); + block = list_first_entry_or_null(&input->vframe_block_free_list, + struct vframe_block_list_s, list); + + if (block) { + handle = block->handle; + vdec_input_del_block_locked(input, block); + kfree(block); + } + vdec_input_unlock(input, flags); + return handle; +} +EXPORT_SYMBOL(vdec_input_get_freed_handle); diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec_input.h b/drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec_input.h index d95e13f97c42..d2304f6bcf4d 100644 --- a/drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec_input.h +++ b/drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec_input.h @@ -28,12 +28,15 @@ struct vframe_block_list_s { ulong start; void *start_virt; ulong addr; + bool is_mapped; int type; u32 size; u32 wp; u32 rp; int data_size; int chunk_count; + int is_out_buf; + u32 handle; struct vdec_input_s *input; }; @@ -49,12 +52,16 @@ struct vframe_chunk_s { u32 pading_size; u64 pts64; bool pts_valid; + u64 timestamp; + bool timestamp_valid; u64 sequence; struct vframe_block_list_s *block; }; #define VDEC_INPUT_TARGET_VLD 0 #define VDEC_INPUT_TARGET_HEVC 1 +#define VLD_PADDING_SIZE 1024 +#define HEVC_PADDING_SIZE (1024*16) struct vdec_input_s { struct list_head vframe_block_list; @@ -156,9 +163,13 @@ extern void vdec_input_unlock(struct vdec_input_s *input, unsigned long lock); /* release all resource for decoder's input */ extern void vdec_input_release(struct vdec_input_s *input); +/* return block handle and free block */ +extern u32 vdec_input_get_freed_handle(struct vdec_s *vdec); int vdec_input_dump_chunks(struct vdec_input_s *input, char *bufs, int size); int vdec_input_dump_blocks(struct vdec_input_s *input, char *bufs, int size); +int vdec_input_get_duration_u64(struct vdec_input_s *input); + #endif /* VDEC_INPUT_H */ diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec_profile.c b/drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec_profile.c index 77eb4e30f116..d03335a6297c 100644 --- a/drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec_profile.c +++ b/drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec_profile.c @@ -19,8 +19,11 @@ #include #include #include +#include + #include +#include #include "vdec_profile.h" #include "vdec.h" @@ -32,9 +35,40 @@ static DEFINE_MUTEX(vdec_profile_mutex); static int rec_wp; static bool rec_wrapped; +static uint dec_time_stat_flag; +static uint dec_time_stat_reset; + struct dentry *root, *event; +#define MAX_INSTANCE_MUN 9 + +struct vdec_profile_time_stat_s { + int time_6ms_less_cnt; + int time_6_9ms_cnt; + int time_9_12ms_cnt; + int time_12_15ms_cnt; + int time_15_18ms_cnt; + int time_18_21ms_cnt; + int time_21ms_up_cnt; + u64 time_max_us; + u64 time_total_us; +}; + +struct vdec_profile_statistics_s { + bool status; + u64 run_lasttimestamp; + int run_cnt; + u64 cb_lasttimestamp; + int cb_cnt; + u64 decode_first_us; + struct vdec_profile_time_stat_s run2cb_time_stat; + struct vdec_profile_time_stat_s decode_time_stat; +}; + +static struct vdec_profile_statistics_s statistics_s[MAX_INSTANCE_MUN]; + + struct vdec_profile_rec_s { struct vdec_s *vdec; u64 timestamp; @@ -62,7 +96,7 @@ static u64 get_us_time_hw(void) int offset = 0; /* txlx, g12a isa register base is 0x3c00 */ - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_TXLX) + if (get_cpu_major_id() >= MESON_CPU_MAJOR_ID_TXLX) offset = 0x1600; do { @@ -84,6 +118,90 @@ static u64 get_us_time_system(void) return div64_u64(timeval_to_ns(&tv), 1000); } +static void vdec_profile_update_alloc_time( + struct vdec_profile_time_stat_s *time_stat, u64 startus, u64 endus) +{ + u64 spend_time_us = endus - startus; + + if (spend_time_us > 0 && spend_time_us < 100000000) { + if (spend_time_us < 6000) + time_stat->time_6ms_less_cnt++; + else if (spend_time_us < 9000) + time_stat->time_6_9ms_cnt++; + else if (spend_time_us < 12000) + time_stat->time_9_12ms_cnt++; + else if (spend_time_us < 15000) + time_stat->time_12_15ms_cnt++; + else if (spend_time_us < 18000) + time_stat->time_15_18ms_cnt++; + else if (spend_time_us < 21000) + time_stat->time_18_21ms_cnt++; + else + time_stat->time_21ms_up_cnt++; + } + + if (spend_time_us > time_stat->time_max_us) + time_stat->time_max_us = spend_time_us; + + time_stat->time_total_us += spend_time_us; +} + + +static void vdec_profile_statistics(struct vdec_s *vdec, int event) +{ + struct vdec_profile_statistics_s *time_stat = NULL; + u64 timestamp; + int i; + + if (vdec->id >= MAX_INSTANCE_MUN) + return; + + if (event != VDEC_PROFILE_EVENT_RUN && + event != VDEC_PROFILE_EVENT_CB) + return; + + mutex_lock(&vdec_profile_mutex); + + if (dec_time_stat_reset == 1) { + if (event != VDEC_PROFILE_EVENT_RUN) { + mutex_unlock(&vdec_profile_mutex); + return; + } + for (i = 0; i < MAX_INSTANCE_MUN; i++) + memset(&statistics_s[i], 0, + sizeof(struct vdec_profile_statistics_s)); + dec_time_stat_reset = 0; + } + + time_stat = &statistics_s[vdec->id]; + timestamp = get_us_time_system(); + + if (time_stat->status == false) { + time_stat->decode_first_us = timestamp; + time_stat->status = true; + } + + if (event == VDEC_PROFILE_EVENT_RUN) { + time_stat->run_lasttimestamp = timestamp; + time_stat->run_cnt++; + } else if (event == VDEC_PROFILE_EVENT_CB) { + /*run2cb statistics*/ + vdec_profile_update_alloc_time(&time_stat->run2cb_time_stat, time_stat->run_lasttimestamp, timestamp); + + /*decode statistics*/ + if (time_stat->cb_cnt == 0) + vdec_profile_update_alloc_time(&time_stat->decode_time_stat, time_stat->decode_first_us, timestamp); + else + vdec_profile_update_alloc_time(&time_stat->decode_time_stat, time_stat->cb_lasttimestamp, timestamp); + + time_stat->cb_lasttimestamp = timestamp; + time_stat->cb_cnt++; + } + + mutex_unlock(&vdec_profile_mutex); +} + + void vdec_profile_more(struct vdec_s *vdec, int event, int para1, int para2) { mutex_lock(&vdec_profile_mutex); @@ -106,7 +224,10 @@ EXPORT_SYMBOL(vdec_profile_more); void vdec_profile(struct vdec_s *vdec, int event) { + ATRACE_COUNTER(vdec_device_name_str(vdec), event); vdec_profile_more(vdec, event, 0 , 0); + if (dec_time_stat_flag == 1) + vdec_profile_statistics(vdec, event); } EXPORT_SYMBOL(vdec_profile); @@ -114,6 +235,9 @@ void vdec_profile_flush(struct vdec_s *vdec) { int i; + if (vdec->id >= MAX_INSTANCE_MUN) + return; + mutex_lock(&vdec_profile_mutex); for (i = 0; i < PROFILE_REC_SIZE; i++) { @@ -121,6 +245,8 @@ void vdec_profile_flush(struct vdec_s *vdec) recs[i].vdec = NULL; } + memset(&statistics_s[vdec->id], 0, sizeof(struct vdec_profile_statistics_s)); + mutex_unlock(&vdec_profile_mutex); } @@ -183,11 +309,84 @@ static int vdec_profile_dbg_show(struct seq_file *m, void *v) return 0; } +static int time_stat_profile_dbg_show(struct seq_file *m, void *v) +{ + int i; + + mutex_lock(&vdec_profile_mutex); + + for (i = 0; i < MAX_INSTANCE_MUN; i++) + { + if (statistics_s[i].status == false) + continue; + + seq_printf(m, "[%d]run_cnt:%d, cb_cnt:%d\n\ + \t\t\ttime_total_us:%llu\n\ + \t\t\trun2cb time:\n\ + \t\t\ttime_max_us:%llu\n\ + \t\t\t[%d]run2cb ave_us:%llu\n\ + \t\t\ttime_6ms_less_cnt:%d\n\ + \t\t\ttime_6_9ms_cnt:%d\n\ + \t\t\ttime_9_12ms_cnt:%d\n\ + \t\t\ttime_12_15ms_cnt:%d\n\ + \t\t\ttime_15_18ms_cnt:%d\n\ + \t\t\ttime_18_21ms_cnt:%d\n\ + \t\t\ttime_21ms_up_cnt:%d\n\ + \t\t\tdecode time:\n\ + \t\t\ttime_total_us:%llu\n\ + \t\t\ttime_max_us:%llu\n\ + \t\t\t[%d]cb2cb ave_us:%llu\n\ + \t\t\ttime_6ms_less_cnt:%d\n\ + \t\t\ttime_6_9ms_cnt:%d\n\ + \t\t\ttime_9_12ms_cnt:%d\n\ + \t\t\ttime_12_15ms_cnt:%d\n\ + \t\t\ttime_15_18ms_cnt:%d\n\ + \t\t\ttime_18_21ms_cnt:%d\n\ + \t\t\ttime_21ms_up_cnt:%d\n", + i, + statistics_s[i].run_cnt, + statistics_s[i].cb_cnt, + statistics_s[i].run2cb_time_stat.time_total_us, + statistics_s[i].run2cb_time_stat.time_max_us, + i, + div_u64(statistics_s[i].run2cb_time_stat.time_total_us , statistics_s[i].cb_cnt), + statistics_s[i].run2cb_time_stat.time_6ms_less_cnt, + statistics_s[i].run2cb_time_stat.time_6_9ms_cnt, + statistics_s[i].run2cb_time_stat.time_9_12ms_cnt, + statistics_s[i].run2cb_time_stat.time_12_15ms_cnt, + statistics_s[i].run2cb_time_stat.time_15_18ms_cnt, + statistics_s[i].run2cb_time_stat.time_18_21ms_cnt, + statistics_s[i].run2cb_time_stat.time_21ms_up_cnt, + statistics_s[i].decode_time_stat.time_total_us, + statistics_s[i].decode_time_stat.time_max_us, + i, + div_u64(statistics_s[i].decode_time_stat.time_total_us , statistics_s[i].cb_cnt), + statistics_s[i].decode_time_stat.time_6ms_less_cnt, + statistics_s[i].decode_time_stat.time_6_9ms_cnt, + statistics_s[i].decode_time_stat.time_9_12ms_cnt, + statistics_s[i].decode_time_stat.time_12_15ms_cnt, + statistics_s[i].decode_time_stat.time_15_18ms_cnt, + statistics_s[i].decode_time_stat.time_18_21ms_cnt, + statistics_s[i].decode_time_stat.time_21ms_up_cnt); + } + + mutex_unlock(&vdec_profile_mutex); + + return 0; +} + + static int vdec_profile_dbg_open(struct inode *inode, struct file *file) { return single_open(file, vdec_profile_dbg_show, NULL); } +static int time_stat_profile_dbg_open(struct inode *inode, struct file *file) +{ + return single_open(file, time_stat_profile_dbg_show, NULL); +} + + static const struct file_operations event_dbg_fops = { .open = vdec_profile_dbg_open, .read = seq_read, @@ -195,6 +394,14 @@ static const struct file_operations event_dbg_fops = { .release = single_release, }; +static const struct file_operations time_stat_dbg_fops = { + .open = time_stat_profile_dbg_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + + #if 0 /*DEBUG_TMP*/ static int __init vdec_profile_init_debugfs(void) { @@ -224,7 +431,7 @@ err: int vdec_profile_init_debugfs(void) { - struct dentry *root, *event; + struct dentry *root, *event, *time_stat; root = debugfs_create_dir("vdec_profile", NULL); if (IS_ERR(root) || !root) @@ -235,10 +442,17 @@ int vdec_profile_init_debugfs(void) if (!event) goto err_1; + time_stat = debugfs_create_file("time_stat", 0400, root, NULL, + &time_stat_dbg_fops); + if (!time_stat) + goto err_2; + mutex_init(&vdec_profile_mutex); return 0; +err_2: + debugfs_remove(event); err_1: debugfs_remove(root); err: @@ -254,5 +468,10 @@ void vdec_profile_exit_debugfs(void) } EXPORT_SYMBOL(vdec_profile_exit_debugfs); +module_param(dec_time_stat_flag, uint, 0664); + +module_param(dec_time_stat_reset, uint, 0664); + + /*module_init(vdec_profile_init_debugfs);*/ diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/vc1/vvc1.c b/drivers/amlogic/media_modules/frame_provider/decoder/vc1/vvc1.c index 49517eebf562..0b338759e0fa 100644 --- a/drivers/amlogic/media_modules/frame_provider/decoder/vc1/vvc1.c +++ b/drivers/amlogic/media_modules/frame_provider/decoder/vc1/vvc1.c @@ -42,6 +42,9 @@ #include #include "../utils/firmware.h" #include +#include +#include + #define DRIVER_NAME "amvdec_vc1" #define MODULE_NAME "amvdec_vc1" @@ -51,6 +54,8 @@ #define NV21 #endif +#define VC1_MAX_SUPPORT_SIZE (1920*1088) + #define I_PICTURE 0 #define P_PICTURE 1 #define B_PICTURE 2 @@ -125,6 +130,7 @@ static u32 stat; static u32 buf_size = 32 * 1024 * 1024; static u32 buf_offset; static u32 avi_flag; +static u32 keyframe_pts_only; static u32 vvc1_ratio; static u32 vvc1_format; @@ -135,8 +141,11 @@ static u32 pts_by_offset = 1; static u32 total_frame; static u32 next_pts; static u64 next_pts_us64; +static u32 next_IP_pts; +static u64 next_IP_pts_us64; static bool is_reset; static struct work_struct set_clk_work; +static struct work_struct error_wd_work; #ifdef DEBUG_PTS static u32 pts_hit, pts_missed, pts_i_hit, pts_i_missed; @@ -161,6 +170,10 @@ enum { RATE_MEASURE_END_PTS, RATE_MEASURE_DONE }; + +struct VC1Decoder_s { + u32 ratio_control; +}; #define RATE_MEASURE_NUM 8 #define RATE_CORRECTION_THRESHOLD 5 #define RATE_24_FPS 3755 /* 23.97 */ @@ -273,9 +286,10 @@ static irqreturn_t vvc1_isr(int irq, void *dev_id) u32 repeat_count; u32 picture_type; u32 buffer_index; - unsigned int pts, pts_valid = 0, offset; - u32 v_width, v_height; + unsigned int pts, pts_valid = 0, offset = 0; + u32 v_width, v_height, dur; u64 pts_us64 = 0; + u32 frame_size; reg = READ_VREG(VC1_BUFFEROUT); @@ -297,13 +311,35 @@ static irqreturn_t vvc1_isr(int irq, void *dev_id) vvc1_amstream_dec_info.height = v_height; frame_height = v_height; } + repeat_count = READ_VREG(VC1_REPEAT_COUNT); + buffer_index = reg & 0x7; + picture_type = (reg >> 3) & 7; if (pts_by_offset) { offset = READ_VREG(VC1_OFFSET_REG); if (pts_lookup_offset_us64( PTS_TYPE_VIDEO, - offset, &pts, 0, &pts_us64) == 0) { + offset, &pts, &frame_size, + 0, &pts_us64) == 0) { pts_valid = 1; + if (keyframe_pts_only) { + //pr_info("PT:%d rpc:%d pts64:%lld\n", picture_type , repeat_count, pts_us64); + dur = DUR2PTS(vvc1_amstream_dec_info.rate); + if (picture_type == B_PICTURE) + { + next_IP_pts = pts; + next_IP_pts_us64 = pts_us64; + pts -= dur; + pts_us64 -= (dur * 100) / 9; + } + else if (next_IP_pts) + { + pts = next_IP_pts; + next_IP_pts = 0; + pts_us64 = next_IP_pts_us64; + next_IP_pts_us64 = 0; + } + } #ifdef DEBUG_PTS pts_hit++; #endif @@ -355,10 +391,10 @@ static irqreturn_t vvc1_isr(int irq, void *dev_id) frm.end_pts = pts; frm.rate = (frm.end_pts - frm.start_pts) / frm.num; - pr_info("frate before=%d,%d,num=%d\n", - frm.rate, - DUR2PTS(vvc1_amstream_dec_info.rate), - frm.num); + //pr_info("frate before=%d,%d,num=%d\n", + //frm.rate, + //DUR2PTS(vvc1_amstream_dec_info.rate), + //frm.num); /* check if measured rate is same as * settings from upper layer * and correct it if necessary @@ -379,10 +415,10 @@ static irqreturn_t vvc1_isr(int irq, void *dev_id) vvc1_amstream_dec_info.rate), RATE_30_FPS, RATE_CORRECTION_THRESHOLD))) { - pr_info( - "vvc1: frate from %d to %d\n", - vvc1_amstream_dec_info.rate, - PTS2DUR(frm.rate)); + //pr_info( + //"vvc1: frate from %d to %d\n", + //vvc1_amstream_dec_info.rate, + //PTS2DUR(frm.rate)); vvc1_amstream_dec_info.rate = PTS2DUR(frm.rate); @@ -490,6 +526,7 @@ static irqreturn_t vvc1_isr(int irq, void *dev_id) buffer_index); kfifo_put(&display_q, (const struct vframe_s *)vf); + ATRACE_COUNTER(MODULE_NAME, vf->pts); vf_notify_receiver( PROVIDER_NAME, @@ -549,6 +586,7 @@ static irqreturn_t vvc1_isr(int irq, void *dev_id) buffer_index); kfifo_put(&display_q, (const struct vframe_s *)vf); + ATRACE_COUNTER(MODULE_NAME, vf->pts); vf_notify_receiver( PROVIDER_NAME, @@ -633,6 +671,7 @@ static irqreturn_t vvc1_isr(int irq, void *dev_id) mm_blk_handle, buffer_index); kfifo_put(&display_q, (const struct vframe_s *)vf); + ATRACE_COUNTER(MODULE_NAME, vf->pts); vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_VFRAME_READY, @@ -721,6 +760,12 @@ static int vvc1_event_cb(int type, void *data, void *private_data) int vvc1_dec_status(struct vdec_s *vdec, struct vdec_info *vstatus) { + struct VC1Decoder_s *vc1 = + (struct VC1Decoder_s *)vdec->private; + + if (!(stat & STAT_VDEC_RUN)) + return -1; + vstatus->frame_width = vvc1_amstream_dec_info.width; vstatus->frame_height = vvc1_amstream_dec_info.height; if (vvc1_amstream_dec_info.rate != 0) @@ -742,6 +787,7 @@ int vvc1_dec_status(struct vdec_s *vdec, struct vdec_info *vstatus) snprintf(vstatus->vdec_name, sizeof(vstatus->vdec_name), "%s", DRIVER_NAME); + vstatus->ratio_control = vc1->ratio_control; return 0; } @@ -913,13 +959,16 @@ static void vvc1_local_init(void) /* vvc1_ratio = vvc1_amstream_dec_info.ratio; */ vvc1_ratio = 0x100; - avi_flag = (unsigned long) vvc1_amstream_dec_info.param; + avi_flag = (unsigned long) vvc1_amstream_dec_info.param & 0x1; + keyframe_pts_only = (unsigned long)vvc1_amstream_dec_info.param & 0x100; total_frame = 0; next_pts = 0; next_pts_us64 = 0; + next_IP_pts = 0; + next_IP_pts_us64 = 0; saved_resolution = 0; frame_width = frame_height = frame_dur = 0; #ifdef DEBUG_PTS @@ -978,23 +1027,18 @@ static void vvc1_ppmgr_reset(void) static void vvc1_set_clk(struct work_struct *work) { - if (frame_dur > 0 && saved_resolution != - frame_width * frame_height * (96000 / frame_dur)) { int fps = 96000 / frame_dur; saved_resolution = frame_width * frame_height * fps; vdec_source_changed(VFORMAT_VC1, frame_width, frame_height, fps); - } + } -static void vvc1_put_timer_func(unsigned long arg) +static void error_do_work(struct work_struct *work) { - struct timer_list *timer = (struct timer_list *)arg; - -#if 1 - if (READ_VREG(VC1_SOS_COUNT) > 10) { amvdec_stop(); + msleep(20); #ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER vvc1_ppmgr_reset(); #else @@ -1004,8 +1048,15 @@ static void vvc1_put_timer_func(unsigned long arg) #endif vvc1_prot_init(); amvdec_start(); - } -#endif +} + + +static void vvc1_put_timer_func(unsigned long arg) +{ + struct timer_list *timer = (struct timer_list *)arg; + + if (READ_VREG(VC1_SOS_COUNT) > 10) + schedule_work(&error_wd_work); while (!kfifo_is_empty(&recycle_q) && (READ_VREG(VC1_BUFFERIN) == 0)) { struct vframe_s *vf; @@ -1020,7 +1071,10 @@ static void vvc1_put_timer_func(unsigned long arg) kfifo_put(&newframe_q, (const struct vframe_s *)vf); } } - schedule_work(&set_clk_work); + + if (frame_dur > 0 && saved_resolution != + frame_width * frame_height * (96000 / frame_dur)) + schedule_work(&set_clk_work); timer->expires = jiffies + PUT_INTERVAL; add_timer(timer); @@ -1028,7 +1082,7 @@ static void vvc1_put_timer_func(unsigned long arg) static s32 vvc1_init(void) { - int ret = -1, size = -1; + int ret = -1; char *buf = vmalloc(0x1000 * 16); int fw_type = VIDEO_DEC_VC1; @@ -1056,19 +1110,19 @@ static s32 vvc1_init(void) } else pr_info("not supported VC1 format\n"); - size = get_firmware_data(fw_type, buf); - if (size < 0) { + if (get_firmware_data(fw_type, buf) < 0) { amvdec_disable(); pr_err("get firmware fail."); vfree(buf); return -1; } - if (size == 1) - pr_info("tee load ok\n"); - else if (amvdec_loadmc_ex(VFORMAT_VC1, NULL, buf) < 0) { + ret = amvdec_loadmc_ex(VFORMAT_VC1, NULL, buf); + if (ret < 0) { amvdec_disable(); vfree(buf); + pr_err("VC1: the %s fw loading failed, err: %x\n", + tee_enabled() ? "TEE" : "local", ret); return -EBUSY; } @@ -1128,34 +1182,54 @@ static s32 vvc1_init(void) static int amvdec_vc1_probe(struct platform_device *pdev) { struct vdec_s *pdata = *(struct vdec_s **)pdev->dev.platform_data; + struct VC1Decoder_s *pbi; if (pdata == NULL) { pr_info("amvdec_vc1 memory resource undefined.\n"); return -EFAULT; } - if (pdata->sys_info) + pbi = vmalloc(sizeof(struct VC1Decoder_s)); + if (pbi == NULL) { + pr_info("\namvdec_vc1 device data allocation failed\n"); + return -ENOMEM; + } + pdata->private = pbi; + + if (pdata->sys_info) { vvc1_amstream_dec_info = *pdata->sys_info; + if ((vvc1_amstream_dec_info.height != 0) && + (vvc1_amstream_dec_info.width > + (VC1_MAX_SUPPORT_SIZE/vvc1_amstream_dec_info.height))) { + pr_info("amvdec_vc1: over size, unsupport: %d * %d\n", + vvc1_amstream_dec_info.width, + vvc1_amstream_dec_info.height); + return -EFAULT; + } + } pdata->dec_status = vvc1_dec_status; pdata->set_isreset = vvc1_set_isreset; is_reset = 0; vvc1_vdec_info_init(); + INIT_WORK(&error_wd_work, error_do_work); + INIT_WORK(&set_clk_work, vvc1_set_clk); if (vvc1_init() < 0) { pr_info("amvdec_vc1 init failed.\n"); kfree(gvs); gvs = NULL; + pdata->dec_status = NULL; return -ENODEV; } - INIT_WORK(&set_clk_work, vvc1_set_clk); + return 0; } static int amvdec_vc1_remove(struct platform_device *pdev) { - cancel_work_sync(&set_clk_work); + cancel_work_sync(&error_wd_work); if (stat & STAT_VDEC_RUN) { amvdec_stop(); stat &= ~STAT_VDEC_RUN; @@ -1171,6 +1245,7 @@ static int amvdec_vc1_remove(struct platform_device *pdev) stat &= ~STAT_TIMER_ARM; } + cancel_work_sync(&set_clk_work); if (stat & STAT_VF_HOOK) { if (!is_reset) vf_notify_receiver(PROVIDER_NAME, diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/vp9/vvp9.c b/drivers/amlogic/media_modules/frame_provider/decoder/vp9/vvp9.c index df2880dffd39..cba58451788c 100644 --- a/drivers/amlogic/media_modules/frame_provider/decoder/vp9/vvp9.c +++ b/drivers/amlogic/media_modules/frame_provider/decoder/vp9/vvp9.c @@ -53,16 +53,19 @@ #include #include "../utils/config_parser.h" #include "../utils/firmware.h" +#include "../../../common/chips/decoder_cpu_ver_info.h" + +#include + #define MIX_STREAM_SUPPORT -#define SUPPORT_4K2K #include "vvp9.h" -#ifdef VP9_10B_MMU + /*#define SUPPORT_FB_DECODING*/ /*#define FB_DECODING_TEST_SCHEDULE*/ -#endif + #define HW_MASK_FRONT 0x1 #define HW_MASK_BACK 0x2 @@ -131,11 +134,6 @@ #define MULTI_INSTANCE_SUPPORT #define SUPPORT_10BIT /* #define ERROR_HANDLE_DEBUG */ -#if 0 /* MESON_CPU_TYPE == MESON_CPU_TYPE_MESON8B*/ -#undef SUPPORT_4K2K -#else -#define SUPPORT_4K2K -#endif #ifndef STAT_KTHREAD #define STAT_KTHREAD 0x40 @@ -156,11 +154,7 @@ static unsigned int not_run_ready[MAX_DECODE_INSTANCE_NUM]; static u32 decode_timeout_val = 200; static int start_decode_buf_level = 0x8000; -#ifdef VP9_10B_MMU -static u32 work_buf_size; /* = 24 * 1024 * 1024*/; -#else -static u32 work_buf_size = 32 * 1024 * 1024; -#endif +static u32 work_buf_size; static u32 mv_buf_margin; @@ -209,7 +203,6 @@ static void dump_data(struct VP9Decoder_s *pbi, int size); static unsigned char get_data_check_sum (struct VP9Decoder_s *pbi, int size); static void dump_pic_list(struct VP9Decoder_s *pbi); -#ifdef VP9_10B_MMU static int vp9_alloc_mmu( struct VP9Decoder_s *pbi, int cur_buf_idx, @@ -217,7 +210,7 @@ static int vp9_alloc_mmu( int pic_height, unsigned short bit_depth, unsigned int *mmu_index_adr); -#endif + static const char vvp9_dec_id[] = "vvp9-dev"; @@ -247,7 +240,7 @@ static u32 on_no_keyframe_skiped; #define COUNT_BUF_SIZE (0x300 * 4 * 4) /*compute_losless_comp_body_size(4096, 2304, 1) = 18874368(0x1200000)*/ #define MAX_FRAME_4K_NUM 0x1200 -#define FRAME_MMU_MAP_SIZE (MAX_FRAME_4K_NUM * 4) +#define MAX_FRAME_8K_NUM 0x4800 #define HEVC_ASSIST_MMU_MAP_ADDR 0x3009 @@ -269,8 +262,9 @@ static inline int div_r32(int64_t m, int n) *return (int)(m/n) */ #ifndef CONFIG_ARM64 - do_div(m, n); - return (int)m; + int64_t qu = 0; + qu = div_s64(m, n); + return (int)qu; #else return (int)(m/n); #endif @@ -298,7 +292,8 @@ struct MVBUF_s { /* #undef BUFMGR_ONLY to enable hardware configuration */ /*#define TEST_WR_PTR_INC*/ -#define WR_PTR_INC_NUM 128 +/*#define WR_PTR_INC_NUM 128*/ +#define WR_PTR_INC_NUM 1 #define SIMULATION #define DOS_PROJECT @@ -312,12 +307,6 @@ struct MVBUF_s { /*#define ENABLE_SWAP_TEST*/ #define MCRCC_ENABLE -#ifdef VP9_10B_NV21 -#define MEM_MAP_MODE 2 /* 0:linear 1:32x32 2:64x32*/ -#else -#define MEM_MAP_MODE 0 /* 0:linear 1:32x32 2:64x32*/ -#endif - #define VP9_LPF_LVL_UPDATE /*#define DBG_LF_PRINT*/ @@ -410,9 +399,12 @@ void WRITE_VREG_DBG2(unsigned int adr, unsigned int val) VP9 buffer management start ***************************************************/ -#ifdef VP9_10B_MMU + #define MMU_COMPRESS_HEADER_SIZE 0x48000 -#endif +#define MMU_COMPRESS_8K_HEADER_SIZE (0x48000*4) +#define MAX_SIZE_8K (8192 * 4608) +#define MAX_SIZE_4K (4096 * 2304) +#define IS_8K_SIZE(w, h) (((w) * (h)) > MAX_SIZE_4K) #define INVALID_IDX -1 /* Invalid buffer index.*/ @@ -512,12 +504,11 @@ struct PIC_BUFFER_CONFIG_s { /**/ int slice_idx; /*buffer*/ -#ifdef VP9_10B_MMU unsigned long header_adr; -#endif unsigned long mpred_mv_wr_start_addr; - unsigned long mc_y_adr; - unsigned long mc_u_v_adr; + /*unsigned long mc_y_adr; + *unsigned long mc_u_v_adr; + */ unsigned int dw_y_adr; unsigned int dw_u_v_adr; int mc_canvas_y; @@ -736,9 +727,7 @@ struct VP9_Common_s { int prev_fb_idx; int new_fb_idx; -#ifdef VP9_10B_MMU int cur_fb_idx_mmu; -#endif /*last frame's frame type for motion search*/ enum FRAME_TYPE last_frame_type; enum FRAME_TYPE frame_type; @@ -807,7 +796,7 @@ struct VP9_Common_s { int above_context_alloc_cols; -} VP9_COMMON; +}; static void set_canvas(struct VP9Decoder_s *pbi, struct PIC_BUFFER_CONFIG_s *pic_config); @@ -897,10 +886,8 @@ struct BuffInfo_s { struct buff_s dblk_para; struct buff_s dblk_data; struct buff_s seg_map; -#ifdef VP9_10B_MMU struct buff_s mmu_vbh; struct buff_s cm_header; -#endif struct buff_s mpred_above; #ifdef MV_USE_FIXED_BUF struct buff_s mpred_mv; @@ -983,12 +970,12 @@ struct VP9Decoder_s { unsigned last_lcu_idx; int decode_timeout_count; unsigned timeout_num; + int save_buffer_mode; int double_write_mode; #endif -#ifdef VP9_10B_MMU long used_4k_num; -#endif + unsigned char m_ins_flag; char *provider_name; union param_u param; @@ -1000,6 +987,7 @@ struct VP9Decoder_s { u32 frame_ar; int fatal_error; uint8_t init_flag; + uint8_t first_sc_checked; uint8_t process_busy; #define PROC_STATE_INIT 0 #define PROC_STATE_DECODESLICE 1 @@ -1008,9 +996,7 @@ struct VP9Decoder_s { u32 ucode_pause_pos; int show_frame_num; -#ifndef VP9_10B_MMU struct buff_s mc_buf_spec; -#endif struct dec_sysinfo vvp9_amstream_dec_info; void *rpm_addr; void *lmem_addr; @@ -1024,11 +1010,9 @@ struct VP9Decoder_s { dma_addr_t prob_buffer_phy_addr; dma_addr_t count_buffer_phy_addr; -#if 1 - /*VP9_10B_MMU*/ void *frame_mmu_map_addr; dma_addr_t frame_mmu_map_phy_addr; -#endif + unsigned int use_cma_flag; struct BUF_s m_BUF[MAX_BUF_NUM]; @@ -1078,10 +1062,11 @@ struct VP9Decoder_s { uint8_t hold_ref_buf; uint8_t ready_for_new_data; struct BufferPool_s vp9_buffer_pool; + struct BuffInfo_s *work_space_buf; -#ifndef VP9_10B_MMU + struct buff_s *mc_buf; -#endif + unsigned int frame_width; unsigned int frame_height; @@ -1121,10 +1106,12 @@ struct VP9Decoder_s { int new_frame_displayed; void *mmu_box; void *bmmu_box; + int mmu_enable; struct vframe_master_display_colour_s vf_dp; struct firmware_s *fw; int max_pic_w; int max_pic_h; + u32 ratio_control; #ifdef SUPPORT_FB_DECODING int dec_s1_result; int s1_test_cmd; @@ -1153,7 +1140,9 @@ struct VP9Decoder_s { union param_u s1_param; u8 back_not_run_ready; #endif -} ; + int need_cache_size; + u64 sc_start_time; +}; static void resize_context_buffers(struct VP9Decoder_s *pbi, struct VP9_Common_s *cm, int width, int height) @@ -1217,27 +1206,24 @@ static int setup_frame_size( (" * 16-bits h read : %d (height : %d)\n", width, height); WRITE_VREG(HEVC_PARSER_PICTURE_SIZE, (height << 16) | width); - -#ifdef VP9_10B_MMU - /* if(cm->prev_fb_idx >= 0) release_unused_4k(cm->prev_fb_idx);*/ - /* cm->prev_fb_idx = cm->new_fb_idx;*/ - /*pr_info - ("[DEBUG DEBUG]Before alloc_mmu, prev_fb_idx : %d, new_fb_idx : %d\r\n", - cm->prev_fb_idx, cm->new_fb_idx);*/ - ret = vp9_alloc_mmu(pbi, - cm->new_fb_idx, - params->p.width, - params->p.height, - params->p.bit_depth, - mmu_index_adr); - if (ret != 0) { - pr_err("can't alloc need mmu1,idx %d ret =%d\n", - cm->new_fb_idx, - ret); - return ret; - } - cm->cur_fb_idx_mmu = cm->new_fb_idx; +#ifdef VP9_10B_HED_FB + WRITE_VREG(HEVC_ASSIST_PIC_SIZE_FB_READ, (height << 16) | width); #endif + if (pbi->mmu_enable && ((pbi->double_write_mode & 0x10) == 0)) { + ret = vp9_alloc_mmu(pbi, + cm->new_fb_idx, + params->p.width, + params->p.height, + params->p.bit_depth, + mmu_index_adr); + if (ret != 0) { + pr_err("can't alloc need mmu1,idx %d ret =%d\n", + cm->new_fb_idx, + ret); + return ret; + } + cm->cur_fb_idx_mmu = cm->new_fb_idx; + } resize_context_buffers(pbi, cm, width, height); setup_display_size(cm, params, print_header_info); @@ -1340,22 +1326,25 @@ static int setup_frame_size_with_refs( params->p.height = height; WRITE_VREG(HEVC_PARSER_PICTURE_SIZE, (height << 16) | width); -#ifdef VP9_10B_MMU - /*if(cm->prev_fb_idx >= 0) release_unused_4k(cm->prev_fb_idx); - cm->prev_fb_idx = cm->new_fb_idx;*/ -/* pr_info - ("[DEBUG DEBUG]Before alloc_mmu, prev_fb_idx : %d, new_fb_idx : %d\r\n", - cm->prev_fb_idx, cm->new_fb_idx);*/ - ret = vp9_alloc_mmu(pbi, cm->new_fb_idx, - params->p.width, params->p.height, - params->p.bit_depth, mmu_index_adr); - if (ret != 0) { - pr_err("can't alloc need mmu,idx %d\r\n", - cm->new_fb_idx); - return ret; + if (pbi->mmu_enable && ((pbi->double_write_mode & 0x10) == 0)) { + /*if(cm->prev_fb_idx >= 0) release_unused_4k(cm->prev_fb_idx); + *cm->prev_fb_idx = cm->new_fb_idx; + */ + /* pr_info + * ("[DEBUG DEBUG]Before alloc_mmu, + * prev_fb_idx : %d, new_fb_idx : %d\r\n", + * cm->prev_fb_idx, cm->new_fb_idx); + */ + ret = vp9_alloc_mmu(pbi, cm->new_fb_idx, + params->p.width, params->p.height, + params->p.bit_depth, mmu_index_adr); + if (ret != 0) { + pr_err("can't alloc need mmu,idx %d\r\n", + cm->new_fb_idx); + return ret; + } + cm->cur_fb_idx_mmu = cm->new_fb_idx; } - cm->cur_fb_idx_mmu = cm->new_fb_idx; -#endif /*Check to make sure at least one of frames that this frame references *has valid dimensions. @@ -1513,8 +1502,7 @@ static void timeout_process(struct VP9Decoder_s *pbi) static u32 get_valid_double_write_mode(struct VP9Decoder_s *pbi) { - return (pbi->m_ins_flag && - ((double_write_mode & 0x80000000) == 0)) ? + return ((double_write_mode & 0x80000000) == 0) ? pbi->double_write_mode : (double_write_mode & 0x7fffffff); } @@ -1575,8 +1563,8 @@ static int get_double_write_ratio(struct VP9Decoder_s *pbi, return ratio; } -#define MAX_4K_NUM 0x1200 -#ifdef VP9_10B_MMU +//#define MAX_4K_NUM 0x1200 + int vp9_alloc_mmu( struct VP9Decoder_s *pbi, int cur_buf_idx, @@ -1587,11 +1575,13 @@ int vp9_alloc_mmu( { int bit_depth_10 = (bit_depth == VPX_BITS_10); int picture_size; - int cur_mmu_4k_number; + int cur_mmu_4k_number, max_frame_num; if (!pbi->mmu_box) { pr_err("error no mmu box!\n"); return -1; } + if (pbi->double_write_mode & 0x10) + return 0; if (bit_depth >= VPX_BITS_12) { pbi->fatal_error = DECODER_FATAL_ERROR_SIZE_OVERFLOW; pr_err("fatal_error, un support bit depth 12!\n\n"); @@ -1600,7 +1590,13 @@ int vp9_alloc_mmu( picture_size = compute_losless_comp_body_size(pic_width, pic_height, bit_depth_10); cur_mmu_4k_number = ((picture_size + (1 << 12) - 1) >> 12); - if (cur_mmu_4k_number > MAX_4K_NUM) { + + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) + max_frame_num = MAX_FRAME_8K_NUM; + else + max_frame_num = MAX_FRAME_4K_NUM; + + if (cur_mmu_4k_number > max_frame_num) { pr_err("over max !! cur_mmu_4k_number 0x%x width %d height %d\n", cur_mmu_4k_number, pic_width, pic_height); return -1; @@ -1611,7 +1607,7 @@ int vp9_alloc_mmu( cur_mmu_4k_number, mmu_index_adr); } -#endif + #ifndef MV_USE_FIXED_BUF static void dealloc_mv_bufs(struct VP9Decoder_s *pbi) @@ -2185,6 +2181,7 @@ static void refresh_ref_frames(struct VP9Decoder_s *pbi) unlock_buffer_pool(pool, flags); return; } + int vp9_bufmgr_process(struct VP9Decoder_s *pbi, union param_u *params) { struct VP9_Common_s *const cm = &pbi->common; @@ -2202,16 +2199,16 @@ int vp9_bufmgr_process(struct VP9Decoder_s *pbi, union param_u *params) } pbi->has_keyframe = 1; on_no_keyframe_skiped = 0; -/* -#ifdef VP9_10B_MMU - if (!pbi->m_ins_flag) - pbi->used_4k_num = (READ_VREG(HEVC_SAO_MMU_STATUS) >> 16); - if (cm->prev_fb_idx >= 0) { - decoder_mmu_box_free_idx_tail(pbi->mmu_box, - cm->prev_fb_idx, pbi->used_4k_num); +#if 0 + if (pbi->mmu_enable) { + if (!pbi->m_ins_flag) + pbi->used_4k_num = (READ_VREG(HEVC_SAO_MMU_STATUS) >> 16); + if (cm->prev_fb_idx >= 0) { + decoder_mmu_box_free_idx_tail(pbi->mmu_box, + cm->prev_fb_idx, pbi->used_4k_num); + } } #endif -*/ if (cm->new_fb_idx >= 0 && frame_bufs[cm->new_fb_idx].ref_count == 0){ vp9_release_frame_buffer @@ -2254,12 +2251,13 @@ int vp9_bufmgr_process(struct VP9Decoder_s *pbi, union param_u *params) cm->new_fb_idx);*/ pbi->cur_buf = &frame_bufs[cm->new_fb_idx]; -#ifdef VP9_10B_MMU - /* moved to after picture size ready - alloc_mmu(cm, params->p.width, params->p.height, - params->p.bit_depth, pbi->frame_mmu_map_addr);*/ - cm->prev_fb_idx = cm->new_fb_idx; -#endif + if (pbi->mmu_enable) { + /* moved to after picture size ready + *alloc_mmu(cm, params->p.width, params->p.height, + *params->p.bit_depth, pbi->frame_mmu_map_addr); + */ + cm->prev_fb_idx = cm->new_fb_idx; + } /*read_uncompressed_header()*/ cm->last_frame_type = cm->frame_type; cm->last_intra_only = cm->intra_only; @@ -2570,10 +2568,8 @@ int vp9_bufmgr_init(struct VP9Decoder_s *pbi, struct BuffInfo_s *buf_spec_i, spin_lock_init(&cm->buffer_pool->lock); cm->prev_fb_idx = INVALID_IDX; cm->new_fb_idx = INVALID_IDX; -#ifdef VP9_10B_MMU pbi->used_4k_num = -1; cm->cur_fb_idx_mmu = INVALID_IDX; -#endif pr_debug ("After vp9_bufmgr_init, prev_fb_idx : %d, new_fb_idx : %d\r\n", cm->prev_fb_idx, cm->new_fb_idx); @@ -2586,9 +2582,9 @@ int vp9_bufmgr_init(struct VP9Decoder_s *pbi, struct BuffInfo_s *buf_spec_i, /* private init */ pbi->work_space_buf = buf_spec_i; -#ifndef VP9_10B_MMU - pbi->mc_buf = mc_buf_i; -#endif + if (!pbi->mmu_enable) + pbi->mc_buf = mc_buf_i; + pbi->rpm_addr = NULL; pbi->lmem_addr = NULL; @@ -2673,8 +2669,11 @@ union param_u vp9_param; #define LOSLESS_COMPRESS_MODE /*#define DECOMP_HEADR_SURGENT*/ - +#ifdef VP9_10B_NV21 +static u32 mem_map_mode = 2 /* 0:linear 1:32x32 2:64x32*/ +#else static u32 mem_map_mode; /* 0:linear 1:32x32 2:64x32 ; m8baby test1902 */ +#endif static u32 enable_mem_saving = 1; static u32 force_w_h; @@ -2699,18 +2698,11 @@ static u32 decode_pic_begin; static uint slice_parse_begin; static u32 step; #ifdef MIX_STREAM_SUPPORT -#ifdef SUPPORT_4K2K static u32 buf_alloc_width = 4096; static u32 buf_alloc_height = 2304; static u32 vp9_max_pic_w = 4096; static u32 vp9_max_pic_h = 2304; -#else -static u32 buf_alloc_width = 1920; -static u32 buf_alloc_height = 1088; -static u32 vp9_max_pic_w = 1920; -static u32 vp9_max_pic_h = 1088; -#endif static u32 dynamic_buf_num_margin; #else static u32 buf_alloc_width; @@ -2771,11 +2763,14 @@ static u32 max_decoding_time; static u32 error_handle_policy; /*static u32 parser_sei_enable = 1;*/ - -static u32 max_buf_num = 10; +#define MAX_BUF_NUM_NORMAL 12 +#define MAX_BUF_NUM_LESS 10 +static u32 max_buf_num = MAX_BUF_NUM_NORMAL; +#define MAX_BUF_NUM_SAVE_BUF 8 static u32 run_ready_min_buf_num = 2; + static DEFINE_MUTEX(vvp9_mutex); #ifndef MULTI_INSTANCE_SUPPORT static struct device *cma_dev; @@ -2841,7 +2836,7 @@ static struct device *cma_dev; #endif #define LMEM_BUF_SIZE (0x400 * 2) -#define WORK_BUF_SPEC_NUM 2 +#define WORK_BUF_SPEC_NUM 3 static struct BuffInfo_s amvvp9_workbuff_spec[WORK_BUF_SPEC_NUM] = { { /* 8M bytes */ @@ -2918,7 +2913,6 @@ static struct BuffInfo_s amvvp9_workbuff_spec[WORK_BUF_SPEC_NUM] = { /*4096x2304/64/64 *24 = 0xd800 Bytes*/ .buf_size = 0xd800, }, -#ifdef VP9_10B_MMU .mmu_vbh = { .buf_size = 0x5000, /*2*16*(more than 2304)/4, 4K*/ }, @@ -2929,7 +2923,6 @@ static struct BuffInfo_s amvvp9_workbuff_spec[WORK_BUF_SPEC_NUM] = { (FRAME_BUFFERS + 1), /* 0x44000 = ((1088*2*1024*4)/32/4)*(32/8) */ }, -#endif #endif .mpred_above = { .buf_size = 0x10000, /* 2 * size of hevc*/ @@ -3020,7 +3013,6 @@ static struct BuffInfo_s amvvp9_workbuff_spec[WORK_BUF_SPEC_NUM] = { /*4096x2304/64/64 *24 = 0xd800 Bytes*/ .buf_size = 0xd800, }, -#ifdef VP9_10B_MMU .mmu_vbh = { .buf_size = 0x5000,/*2*16*(more than 2304)/4, 4K*/ }, @@ -3031,7 +3023,6 @@ static struct BuffInfo_s amvvp9_workbuff_spec[WORK_BUF_SPEC_NUM] = { (FRAME_BUFFERS + 1), /* 0x44000 = ((1088*2*1024*4)/32/4)*(32/8) */ }, -#endif #endif .mpred_above = { .buf_size = 0x10000, /* 2 * size of hevc*/ @@ -3044,6 +3035,83 @@ static struct BuffInfo_s amvvp9_workbuff_spec[WORK_BUF_SPEC_NUM] = { /* 4096x2304 , 0x120000 per buffer */ .buf_size = 0x120000 * FRAME_BUFFERS, }, +#endif + .rpm = { + .buf_size = RPM_BUF_SIZE, + }, + .lmem = { + .buf_size = 0x400 * 2, + } + }, + { + .max_width = 4096*2, + .max_height = 2304*2, + .ipp = { + // IPP work space calculation : 4096 * (Y+CbCr+Flags) = 12k, round to 16k + .buf_size = 0x4000*2, + }, + .sao_abv = { + .buf_size = 0x30000*2, + }, + .sao_vb = { + .buf_size = 0x30000*2, + }, + .short_term_rps = { + // SHORT_TERM_RPS - Max 64 set, 16 entry every set, total 64x16x2 = 2048 bytes (0x800) + .buf_size = 0x800, + }, + .vps = { + // VPS STORE AREA - Max 16 VPS, each has 0x80 bytes, total 0x0800 bytes + .buf_size = 0x800, + }, + .sps = { + // SPS STORE AREA - Max 16 SPS, each has 0x80 bytes, total 0x0800 bytes + .buf_size = 0x800, + }, + .pps = { + // PPS STORE AREA - Max 64 PPS, each has 0x80 bytes, total 0x2000 bytes + .buf_size = 0x2000, + }, + .sao_up = { + // SAO UP STORE AREA - Max 640(10240/16) LCU, each has 16 bytes total 0x2800 bytes + .buf_size = 0x2800*2, + }, + .swap_buf = { + // 256cyclex64bit = 2K bytes 0x800 (only 144 cycles valid) + .buf_size = 0x800, + }, + .swap_buf2 = { + .buf_size = 0x800, + }, + .scalelut = { + // support up to 32 SCALELUT 1024x32 = 32Kbytes (0x8000) + .buf_size = 0x8000*2, + }, + .dblk_para = { + // DBLK -> Max 256(4096/16) LCU, each para 1024bytes(total:0x40000), data 1024bytes(total:0x40000) + .buf_size = 0x80000*2, + }, + .dblk_data = { + .buf_size = 0x80000*2, + }, + .mmu_vbh = { + .buf_size = 0x5000*2, //2*16*(more than 2304)/4, 4K + }, +#if 0 + .cm_header = { + //.buf_size = MMU_COMPRESS_HEADER_SIZE*8, // 0x44000 = ((1088*2*1024*4)/32/4)*(32/8) + .buf_size = MMU_COMPRESS_HEADER_SIZE*16, // 0x44000 = ((1088*2*1024*4)/32/4)*(32/8) + }, +#endif + .mpred_above = { + .buf_size = 0x10000*2, /* 2 * size of hevc*/ + }, +#ifdef MV_USE_FIXED_BUF + .mpred_mv = { + //4k2k , 0x100000 per buffer */ + /* 4096x2304 , 0x120000 per buffer */ + .buf_size = 0x120000 * FRAME_BUFFERS * 4, + }, #endif .rpm = { .buf_size = RPM_BUF_SIZE, @@ -3067,11 +3135,7 @@ int compute_losless_comp_body_size(int width, int height, width_x64 >>= 6; height_x32 = height + 31; height_x32 >>= 5; -#ifdef VP9_10B_MMU - bsize = (is_bit_depth_10?4096:3200)*width_x64*height_x32; -#else - bsize = (is_bit_depth_10?4096:3072)*width_x64*height_x32; -#endif + bsize = (is_bit_depth_10?4096:3200)*width_x64*height_x32; if (debug & VP9_DEBUG_BUFMGR_MORE) pr_info("%s(%d,%d,%d)=>%d\n", __func__, width, height, @@ -3135,15 +3199,17 @@ static void init_buff_spec(struct VP9Decoder_s *pbi, buf_spec->dblk_para.buf_start + buf_spec->dblk_para.buf_size; buf_spec->seg_map.buf_start = buf_spec->dblk_data.buf_start + buf_spec->dblk_data.buf_size; -#ifdef VP9_10B_MMU - buf_spec->mmu_vbh.buf_start = + if (pbi == NULL || pbi->mmu_enable) { + buf_spec->mmu_vbh.buf_start = + buf_spec->seg_map.buf_start + + buf_spec->seg_map.buf_size; + buf_spec->mpred_above.buf_start = + buf_spec->mmu_vbh.buf_start + + buf_spec->mmu_vbh.buf_size; + } else { + buf_spec->mpred_above.buf_start = buf_spec->seg_map.buf_start + buf_spec->seg_map.buf_size; - buf_spec->mpred_above.buf_start = - buf_spec->mmu_vbh.buf_start + buf_spec->mmu_vbh.buf_size; -#else - buf_spec->mpred_above.buf_start = - buf_spec->seg_map.buf_start + buf_spec->seg_map.buf_size; -#endif + } #ifdef MV_USE_FIXED_BUF buf_spec->mpred_mv.buf_start = buf_spec->mpred_above.buf_start + @@ -3165,24 +3231,43 @@ static void init_buff_spec(struct VP9Decoder_s *pbi, buf_spec->lmem.buf_start + buf_spec->lmem.buf_size; - if (pbi) { + if (!pbi) + return; + + if (!vdec_secure(hw_to_vdec(pbi))) { mem_start_virt = codec_mm_phys_to_virt(buf_spec->dblk_para.buf_start); if (mem_start_virt) { - memset(mem_start_virt, 0, buf_spec->dblk_para.buf_size); + memset(mem_start_virt, 0, + buf_spec->dblk_para.buf_size); codec_mm_dma_flush(mem_start_virt, buf_spec->dblk_para.buf_size, DMA_TO_DEVICE); } else { - /*not virt for tvp playing, - may need clear on ucode.*/ - pr_err("mem_start_virt failed\n"); + mem_start_virt = codec_mm_vmap( + buf_spec->dblk_para.buf_start, + buf_spec->dblk_para.buf_size); + if (mem_start_virt) { + memset(mem_start_virt, 0, + buf_spec->dblk_para.buf_size); + codec_mm_dma_flush(mem_start_virt, + buf_spec->dblk_para.buf_size, + DMA_TO_DEVICE); + codec_mm_unmap_phyaddr(mem_start_virt); + } else { + /*not virt for tvp playing, + may need clear on ucode.*/ + pr_err("mem_start_virt failed\n"); + } } - if (debug) { - pr_info("%s workspace (%x %x) size = %x\n", __func__, - buf_spec->start_adr, buf_spec->end_adr, + } + + if (debug) { + pr_info("%s workspace (%x %x) size = %x\n", __func__, + buf_spec->start_adr, buf_spec->end_adr, buf_spec->end_adr - buf_spec->start_adr); } + if (debug) { pr_info("ipp.buf_start :%x\n", buf_spec->ipp.buf_start); @@ -3212,23 +3297,21 @@ static void init_buff_spec(struct VP9Decoder_s *pbi, buf_spec->dblk_data.buf_start); pr_info("seg_map.buf_start :%x\n", buf_spec->seg_map.buf_start); - #ifdef VP9_10B_MMU - pr_info("mmu_vbh.buf_start :%x\n", - buf_spec->mmu_vbh.buf_start); - #endif - pr_info("mpred_above.buf_start :%x\n", - buf_spec->mpred_above.buf_start); + if (pbi->mmu_enable) { + pr_info("mmu_vbh.buf_start :%x\n", + buf_spec->mmu_vbh.buf_start); + } + pr_info("mpred_above.buf_start :%x\n", + buf_spec->mpred_above.buf_start); #ifdef MV_USE_FIXED_BUF - pr_info("mpred_mv.buf_start :%x\n", - buf_spec->mpred_mv.buf_start); + pr_info("mpred_mv.buf_start :%x\n", + buf_spec->mpred_mv.buf_start); #endif - if ((debug & VP9_DEBUG_SEND_PARAM_WITH_REG) == 0) { - pr_info("rpm.buf_start :%x\n", - buf_spec->rpm.buf_start); - } + if ((debug & VP9_DEBUG_SEND_PARAM_WITH_REG) == 0) { + pr_info("rpm.buf_start :%x\n", + buf_spec->rpm.buf_start); } } - } /* cache_util.c */ @@ -4420,7 +4503,8 @@ static void uninit_mmu_buffers(struct VP9Decoder_s *pbi) #ifndef MV_USE_FIXED_BUF dealloc_mv_bufs(pbi); #endif - decoder_mmu_box_free(pbi->mmu_box); + if (pbi->mmu_box) + decoder_mmu_box_free(pbi->mmu_box); pbi->mmu_box = NULL; if (pbi->bmmu_box) @@ -4428,121 +4512,6 @@ static void uninit_mmu_buffers(struct VP9Decoder_s *pbi) pbi->bmmu_box = NULL; } -#ifndef VP9_10B_MMU -static void init_buf_list(struct VP9Decoder_s *pbi) -{ - int i; - int buf_size; -#ifndef VP9_10B_MMU - int mc_buffer_end = pbi->mc_buf->buf_start + pbi->mc_buf->buf_size; -#endif - pbi->used_buf_num = max_buf_num; - - if (pbi->used_buf_num > MAX_BUF_NUM) - pbi->used_buf_num = MAX_BUF_NUM; - if (buf_alloc_size > 0) { - buf_size = buf_alloc_size; - if (debug) - pr_info("[Buffer Management] init_buf_list:\n"); - } else { - int pic_width = pbi->init_pic_w; - int pic_height = pbi->init_pic_h; - - /*SUPPORT_10BIT*/ - int losless_comp_header_size = compute_losless_comp_header_size - (pic_width, pic_height); - int losless_comp_body_size = compute_losless_comp_body_size - (pic_width, pic_height, buf_alloc_depth == 10); - int mc_buffer_size = losless_comp_header_size - + losless_comp_body_size; - int mc_buffer_size_h = (mc_buffer_size + 0xffff)>>16; - - int dw_mode = get_double_write_mode_init(pbi); - - if (dw_mode) { - int pic_width_dw = pic_width / - get_double_write_ratio(pbi, dw_mode); - int pic_height_dw = pic_height / - get_double_write_ratio(pbi, dw_mode); - int lcu_size = 64; /*fixed 64*/ - int pic_width_64 = (pic_width_dw + 63) & (~0x3f); - int pic_height_32 = (pic_height_dw + 31) & (~0x1f); - int pic_width_lcu = - (pic_width_64 % lcu_size) ? pic_width_64 / lcu_size - + 1 : pic_width_64 / lcu_size; - int pic_height_lcu = - (pic_height_32 % lcu_size) ? pic_height_32 / lcu_size - + 1 : pic_height_32 / lcu_size; - int lcu_total = pic_width_lcu * pic_height_lcu; - int mc_buffer_size_u_v = lcu_total * lcu_size * lcu_size / 2; - int mc_buffer_size_u_v_h = (mc_buffer_size_u_v + 0xffff) >> 16; - /*64k alignment*/ - buf_size = ((mc_buffer_size_u_v_h << 16) * 3); - } else - buf_size = 0; - - if (mc_buffer_size & 0xffff) { /*64k alignment*/ - mc_buffer_size_h += 1; - } - if ((dw_mode & 0x10) == 0) - buf_size += (mc_buffer_size_h << 16); - if (debug) { - pr_info - ("init_buf_list num %d (width %d height %d):\n", - pbi->used_buf_num, pic_width, pic_height); - } - } - - for (i = 0; i < pbi->used_buf_num; i++) { - if (((i + 1) * buf_size) > pbi->mc_buf->buf_size) - pbi->use_cma_flag = 1; -#ifndef VP9_10B_MMU - pbi->m_BUF[i].alloc_flag = 0; - pbi->m_BUF[i].index = i; - - pbi->use_cma_flag = 1; - if (pbi->use_cma_flag) { - pbi->m_BUF[i].cma_page_count = - PAGE_ALIGN(buf_size) / PAGE_SIZE; - if (decoder_bmmu_box_alloc_buf_phy(pbi->bmmu_box, - VF_BUFFER_IDX(i), buf_size, DRIVER_NAME, - &pbi->m_BUF[i].alloc_addr) < 0) { - pbi->m_BUF[i].cma_page_count = 0; - if (i <= 5) { - pbi->fatal_error |= - DECODER_FATAL_ERROR_NO_MEM; - } - break; - } - pbi->m_BUF[i].start_adr = pbi->m_BUF[i].alloc_addr; - } else { - pbi->m_BUF[i].cma_page_count = 0; - pbi->m_BUF[i].alloc_addr = 0; - pbi->m_BUF[i].start_adr = - pbi->mc_buf->buf_start + i * buf_size; - } - pbi->m_BUF[i].size = buf_size; - pbi->m_BUF[i].free_start_adr = pbi->m_BUF[i].start_adr; - - if (((pbi->m_BUF[i].start_adr + buf_size) > mc_buffer_end) - && (pbi->m_BUF[i].alloc_addr == 0)) { - if (debug) { - pr_info - ("Max mc buffer or mpred_mv buffer is used\n"); - } - break; - } - - if (debug) { - pr_info("Buffer %d: start_adr %p size %x\n", i, - (void *)pbi->m_BUF[i].start_adr, - pbi->m_BUF[i].size); - } -#endif - } - pbi->buf_num = i; -} -#endif static int config_pic(struct VP9Decoder_s *pbi, struct PIC_BUFFER_CONFIG_s *pic_config) @@ -4605,20 +4574,19 @@ static int config_pic(struct VP9Decoder_s *pbi, if (mc_buffer_size & 0xffff) /*64k alignment*/ mc_buffer_size_h += 1; -#ifndef VP9_10B_MMU - if ((dw_mode & 0x10) == 0) + if ((!pbi->mmu_enable) && ((dw_mode & 0x10) == 0)) buf_size += (mc_buffer_size_h << 16); -#endif -#ifdef VP9_10B_MMU - pic_config->header_adr = decoder_bmmu_box_get_phy_addr( + + if (pbi->mmu_enable) { + pic_config->header_adr = decoder_bmmu_box_get_phy_addr( pbi->bmmu_box, HEADER_BUFFER_IDX(pic_config->index)); - if (debug & VP9_DEBUG_BUFMGR_MORE) { - pr_info("MMU header_adr %d: %ld\n", - pic_config->index, pic_config->header_adr); + if (debug & VP9_DEBUG_BUFMGR_MORE) { + pr_info("MMU header_adr %d: %ld\n", + pic_config->index, pic_config->header_adr); + } } -#endif i = pic_config->index; #ifdef MV_USE_FIXED_BUF @@ -4627,31 +4595,7 @@ static int config_pic(struct VP9Decoder_s *pbi, <= mpred_mv_end ) { #endif -#ifndef VP9_10B_MMU - if (debug) { - pr_err("start %x .size=%d\n", - pbi->mc_buf_spec.buf_start + i * buf_size, - buf_size); - } -#endif -#ifndef VP9_10B_MMU - for (i = 0; i < pbi->buf_num; i++) { - y_adr = ((pbi->m_BUF[i].free_start_adr - + 0xffff) >> 16) << 16; - /*64k alignment*/ - if ((y_adr+buf_size) <= (pbi->m_BUF[i].start_adr+ - pbi->m_BUF[i].size)) { - pbi->m_BUF[i].free_start_adr = - y_adr + buf_size; - break; - } - } - if (i < pbi->buf_num) -#else - /*if ((pbi->mc_buf->buf_start + (i + 1) * buf_size) < - pbi->mc_buf->buf_end) - y_adr = pbi->mc_buf->buf_start + i * buf_size; - else {*/ + if (buf_size > 0) { ret = decoder_bmmu_box_alloc_buf_phy(pbi->bmmu_box, VF_BUFFER_IDX(i), @@ -4677,7 +4621,6 @@ static int config_pic(struct VP9Decoder_s *pbi, return -1; } } -#endif { /*ensure get_pic_by_POC() not get the buffer not decoded*/ @@ -4686,37 +4629,22 @@ static int config_pic(struct VP9Decoder_s *pbi, pic_config->comp_body_size = losless_comp_body_size; pic_config->buf_size = buf_size; -#ifndef VP9_10B_MMU - pic_config->mc_y_adr = y_adr; -#endif + pic_config->mc_canvas_y = pic_config->index; pic_config->mc_canvas_u_v = pic_config->index; -#ifndef VP9_10B_MMU if (dw_mode & 0x10) { - pic_config->mc_u_v_adr = y_adr + - ((mc_buffer_size_u_v_h << 16) << 1); + pic_config->dw_y_adr = y_adr; + pic_config->dw_u_v_adr = y_adr + + ((mc_buffer_size_u_v_h << 16) << 1); pic_config->mc_canvas_y = (pic_config->index << 1); pic_config->mc_canvas_u_v = (pic_config->index << 1) + 1; - + } else if (dw_mode) { pic_config->dw_y_adr = y_adr; - pic_config->dw_u_v_adr = pic_config->mc_u_v_adr; - } else -#endif - if (dw_mode) { - pic_config->dw_y_adr = y_adr -#ifndef VP9_10B_MMU - + (mc_buffer_size_h << 16) -#endif - ; pic_config->dw_u_v_adr = pic_config->dw_y_adr + - ((mc_buffer_size_u_v_h << 16) << 1); -#ifdef VP9_10B_MMU - pic_config->mc_y_adr = pic_config->dw_y_adr; - pic_config->mc_u_v_adr = pic_config->dw_u_v_adr; -#endif + ((mc_buffer_size_u_v_h << 16) << 1); } #ifdef MV_USE_FIXED_BUF pic_config->mpred_mv_wr_start_addr = @@ -4726,10 +4654,9 @@ static int config_pic(struct VP9Decoder_s *pbi, #endif if (debug) { pr_info - ("%s index %d BUF_index %d mc_y_adr %lx ", + ("%s index %d BUF_index %d ", __func__, pic_config->index, - pic_config->BUF_index, - pic_config->mc_y_adr); + pic_config->BUF_index); pr_info ("comp_body_size %x comp_buf_size %x ", pic_config->comp_body_size, @@ -4749,32 +4676,73 @@ static int config_pic(struct VP9Decoder_s *pbi, return ret; } +static int is_oversize(int w, int h) +{ + int max = (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1)? + MAX_SIZE_8K : MAX_SIZE_4K; + + if (w < 0 || h < 0) + return true; + + if (h != 0 && (w > max / h)) + return true; + + return false; +} + +static int vvp9_mmu_compress_header_size(struct VP9Decoder_s *pbi) +{ + if ((get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) && + IS_8K_SIZE(pbi->max_pic_w, pbi->max_pic_h)) + return (MMU_COMPRESS_8K_HEADER_SIZE); + + return (MMU_COMPRESS_HEADER_SIZE); +} + +/*#define FRAME_MMU_MAP_SIZE (MAX_FRAME_4K_NUM * 4)*/ +static int vvp9_frame_mmu_map_size(struct VP9Decoder_s *pbi) +{ + if ((get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) && + IS_8K_SIZE(pbi->max_pic_w, pbi->max_pic_h)) + return (MAX_FRAME_8K_NUM * 4); + + return (MAX_FRAME_4K_NUM * 4); +} + + static void init_pic_list(struct VP9Decoder_s *pbi) { int i; struct VP9_Common_s *cm = &pbi->common; struct PIC_BUFFER_CONFIG_s *pic_config; -#ifdef VP9_10B_MMU - /*alloc VP9 compress header first*/ - for (i = 0; i < pbi->used_buf_num; i++) { - unsigned long buf_addr; - if (decoder_bmmu_box_alloc_buf_phy + u32 header_size; + struct vdec_s *vdec = hw_to_vdec(pbi); + if (pbi->mmu_enable && ((pbi->double_write_mode & 0x10) == 0)) { + header_size = vvp9_mmu_compress_header_size(pbi); + /*alloc VP9 compress header first*/ + for (i = 0; i < pbi->used_buf_num; i++) { + unsigned long buf_addr; + if (decoder_bmmu_box_alloc_buf_phy (pbi->bmmu_box, - HEADER_BUFFER_IDX(i), MMU_COMPRESS_HEADER_SIZE, + HEADER_BUFFER_IDX(i), header_size, DRIVER_HEADER_NAME, - &buf_addr) < 0){ - pr_info("%s malloc compress header failed %d\n", + &buf_addr) < 0) { + pr_info("%s malloc compress header failed %d\n", DRIVER_HEADER_NAME, i); - pbi->fatal_error |= DECODER_FATAL_ERROR_NO_MEM; - return; + pbi->fatal_error |= DECODER_FATAL_ERROR_NO_MEM; + return; + } } } -#endif for (i = 0; i < pbi->used_buf_num; i++) { pic_config = &cm->buffer_pool->frame_bufs[i].buf; pic_config->index = i; pic_config->BUF_index = -1; pic_config->mv_buf_index = -1; + if (vdec->parallel_dec == 1) { + pic_config->y_canvas_index = -1; + pic_config->uv_canvas_index = -1; + } if (config_pic(pbi, pic_config) < 0) { if (debug) pr_info("Config_pic %d fail\n", @@ -4784,20 +4752,26 @@ static void init_pic_list(struct VP9Decoder_s *pbi) } pic_config->y_crop_width = pbi->init_pic_w; pic_config->y_crop_height = pbi->init_pic_h; - /*set_canvas(pic_config);*/ + pic_config->double_write_mode = get_double_write_mode(pbi); + if (pic_config->double_write_mode) { + set_canvas(pbi, pic_config); + } } for (; i < pbi->used_buf_num; i++) { pic_config = &cm->buffer_pool->frame_bufs[i].buf; pic_config->index = -1; pic_config->BUF_index = -1; pic_config->mv_buf_index = -1; + if (vdec->parallel_dec == 1) { + pic_config->y_canvas_index = -1; + pic_config->uv_canvas_index = -1; + } } pr_info("%s ok, used_buf_num = %d\n", __func__, pbi->used_buf_num); } - static void init_pic_list_hw(struct VP9Decoder_s *pbi) { int i; @@ -4813,24 +4787,31 @@ static void init_pic_list_hw(struct VP9Decoder_s *pbi) if (pic_config->index < 0) break; -#ifdef VP9_10B_MMU - /*WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CMD_ADDR, - pic_config->header_adr - | (pic_config->mc_canvas_y << 8)|0x1);*/ - WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_DATA, pic_config->header_adr >> 5); -#else - /*WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CMD_ADDR, - pic_config->mc_y_adr - | (pic_config->mc_canvas_y << 8) | 0x1);*/ - WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_DATA, pic_config->mc_y_adr >> 5); -#endif -#ifndef LOSLESS_COMPRESS_MODE - /*WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CMD_ADDR, - pic_config->mc_u_v_adr - | (pic_config->mc_canvas_u_v << 8)| 0x1);*/ - WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_DATA, pic_config->mc_u_v_adr >> 5); -#endif + if (pbi->mmu_enable && ((pic_config->double_write_mode & 0x10) == 0)) { + WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_DATA, + pic_config->header_adr >> 5); + } else { + /*WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CMD_ADDR, + * pic_config->mc_y_adr + * | (pic_config->mc_canvas_y << 8) | 0x1); + */ + WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_DATA, + pic_config->dw_y_adr >> 5); + } +#ifndef LOSLESS_COMPRESS_MODE + /*WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CMD_ADDR, + * pic_config->mc_u_v_adr + * | (pic_config->mc_canvas_u_v << 8)| 0x1); + */ + WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_DATA, + pic_config->header_adr >> 5); +#else + if (pic_config->double_write_mode & 0x10) { + WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_DATA, + pic_config->dw_u_v_adr >> 5); + } +#endif } WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CONF_ADDR, 0x1); @@ -4900,21 +4881,24 @@ static int config_pic_size(struct VP9Decoder_s *pbi, unsigned short bit_depth) WRITE_VREG(HEVC_SAO_CTRL5, data32); -#ifdef VP9_10B_MMU - /*bit[4] : paged_mem_mode*/ - WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, (0x1 << 4)); -#else + if (pbi->mmu_enable) { + /*bit[4] : paged_mem_mode*/ + WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, (0x1 << 4)); + } else { /*bit[3] smem mdoe*/ - if (bit_depth == VPX_BITS_10) - WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, (0 << 3)); - else - WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, (1 << 3)); -#endif - WRITE_VREG(HEVCD_MPP_DECOMP_CTL2, (losless_comp_body_size >> 5)); + if (bit_depth == VPX_BITS_10) + WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, (0 << 3)); + else + WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, (1 << 3)); + } + if (get_cpu_major_id() < AM_MESON_CPU_MAJOR_ID_SM1) + WRITE_VREG(HEVCD_MPP_DECOMP_CTL2, (losless_comp_body_size >> 5)); /*WRITE_VREG(HEVCD_MPP_DECOMP_CTL3,(0xff<<20) | (0xff<<10) | 0xff);*/ WRITE_VREG(HEVC_CM_BODY_LENGTH, losless_comp_body_size); WRITE_VREG(HEVC_CM_HEADER_OFFSET, losless_comp_body_size); WRITE_VREG(HEVC_CM_HEADER_LENGTH, losless_comp_header_size); + if (get_double_write_mode(pbi) & 0x10) + WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, 0x1 << 31); #else WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, 0x1 << 31); #endif @@ -4982,11 +4966,10 @@ static int config_mc_buffer(struct VP9Decoder_s *pbi, unsigned short bit_depth) WRITE_VREG(VP9D_MPP_REFINFO_DATA, (pic_config->y_crop_height << 14) / cur_pic_config->y_crop_height); -#ifdef VP9_10B_MMU - WRITE_VREG(VP9D_MPP_REFINFO_DATA, 0); -#else - WRITE_VREG(VP9D_MPP_REFINFO_DATA, ref_pic_body_size >> 5); -#endif + if (pbi->mmu_enable) + WRITE_VREG(VP9D_MPP_REFINFO_DATA, 0); + else + WRITE_VREG(VP9D_MPP_REFINFO_DATA, ref_pic_body_size >> 5); } WRITE_VREG(VP9D_MPP_REF_SCALE_ENBL, scale_enable); return 0; @@ -5061,10 +5044,7 @@ static void config_sao_hw(struct VP9Decoder_s *pbi, union param_u *params) int mc_buffer_size_u_v_h = (mc_buffer_size_u_v + 0xffff) >> 16;/*64k alignment*/ -#ifndef VP9_10B_MMU - if ((get_double_write_mode(pbi) & 0x10) == 0) - WRITE_VREG(HEVC_CM_BODY_START_ADDR, pic_config->mc_y_adr); -#endif + if (get_double_write_mode(pbi)) { WRITE_VREG(HEVC_SAO_Y_START_ADDR, pic_config->dw_y_adr); WRITE_VREG(HEVC_SAO_C_START_ADDR, pic_config->dw_u_v_adr); @@ -5074,9 +5054,9 @@ static void config_sao_hw(struct VP9Decoder_s *pbi, union param_u *params) WRITE_VREG(HEVC_SAO_Y_START_ADDR, 0xffffffff); WRITE_VREG(HEVC_SAO_C_START_ADDR, 0xffffffff); } -#ifdef VP9_10B_MMU - WRITE_VREG(HEVC_CM_HEADER_START_ADDR, pic_config->header_adr); -#endif + if (pbi->mmu_enable) + WRITE_VREG(HEVC_CM_HEADER_START_ADDR, pic_config->header_adr); + data32 = (mc_buffer_size_u_v_h << 16) << 1; /*pr_info("data32=%x,mc_buffer_size_u_v_h=%x,lcu_total=%x\n", * data32, mc_buffer_size_u_v_h, pic_config->lcu_total); @@ -5091,7 +5071,7 @@ static void config_sao_hw(struct VP9Decoder_s *pbi, union param_u *params) data32 = READ_VREG(HEVC_SAO_CTRL1); data32 &= (~0x3000); /*[13:12] axi_aformat, 0-Linear, 1-32x32, 2-64x32*/ - data32 |= (MEM_MAP_MODE << 12); + data32 |= (mem_map_mode << 12); data32 &= (~0x3); data32 |= 0x1; /* [1]:dw_disable [0]:cm_disable*/ WRITE_VREG(HEVC_SAO_CTRL1, data32); @@ -5105,14 +5085,14 @@ static void config_sao_hw(struct VP9Decoder_s *pbi, union param_u *params) data32 = READ_VREG(HEVCD_IPP_AXIIF_CONFIG); data32 &= (~0x30); /*[5:4] address_format 00:linear 01:32x32 10:64x32*/ - data32 |= (MEM_MAP_MODE << 4); + data32 |= (mem_map_mode << 4); WRITE_VREG(HEVCD_IPP_AXIIF_CONFIG, data32); #else /*m8baby test1902*/ data32 = READ_VREG(HEVC_SAO_CTRL1); data32 &= (~0x3000); /*[13:12] axi_aformat, 0-Linear, 1-32x32, 2-64x32*/ - data32 |= (MEM_MAP_MODE << 12); + data32 |= (mem_map_mode << 12); data32 &= (~0xff0); /*data32 |= 0x670;*/ /*Big-Endian per 64-bit*/ data32 |= 0x880; /*.Big-Endian per 64-bit */ @@ -5130,7 +5110,7 @@ static void config_sao_hw(struct VP9Decoder_s *pbi, union param_u *params) data32 = READ_VREG(HEVCD_IPP_AXIIF_CONFIG); data32 &= (~0x30); /*[5:4] address_format 00:linear 01:32x32 10:64x32*/ - data32 |= (MEM_MAP_MODE << 4); + data32 |= (mem_map_mode << 4); data32 &= (~0xF); data32 |= 0x8; /*Big-Endian per 64-bit*/ WRITE_VREG(HEVCD_IPP_AXIIF_CONFIG, data32); @@ -5138,7 +5118,7 @@ static void config_sao_hw(struct VP9Decoder_s *pbi, union param_u *params) #else data32 = READ_VREG(HEVC_SAO_CTRL1); data32 &= (~0x3000); - data32 |= (MEM_MAP_MODE << + data32 |= (mem_map_mode << 12); /* [13:12] axi_aformat, 0-Linear, @@ -5147,22 +5127,19 @@ static void config_sao_hw(struct VP9Decoder_s *pbi, union param_u *params) data32 &= (~0xff0); /* data32 |= 0x670; // Big-Endian per 64-bit */ data32 |= endian; /* Big-Endian per 64-bit */ - if (get_cpu_type() < MESON_CPU_MAJOR_ID_G12A) { + if (get_cpu_major_id() < AM_MESON_CPU_MAJOR_ID_G12A) { data32 &= (~0x3); /*[1]:dw_disable [0]:cm_disable*/ if (get_double_write_mode(pbi) == 0) data32 |= 0x2; /*disable double write*/ -#ifndef VP9_10B_MMU - else - if (get_double_write_mode(pbi) & 0x10) + else if (get_double_write_mode(pbi) & 0x10) data32 |= 0x1; /*disable cm*/ -#endif } else { /* >= G12A dw write control */ unsigned int data; data = READ_VREG(HEVC_DBLK_CFGB); data &= (~0x300); /*[8]:first write enable (compress) [9]:double write enable (uncompress)*/ if (get_double_write_mode(pbi) == 0) data |= (0x1 << 8); /*enable first write*/ - else if (get_double_write_mode(pbi) == 0x10) + else if (get_double_write_mode(pbi) & 0x10) data |= (0x1 << 9); /*double write only*/ else data |= ((0x1 << 8) |(0x1 << 9)); @@ -5206,9 +5183,8 @@ static void config_sao_hw(struct VP9Decoder_s *pbi, union param_u *params) static void vp9_config_work_space_hw(struct VP9Decoder_s *pbi, u32 mask) { struct BuffInfo_s *buf_spec = pbi->work_space_buf; -#ifdef VP9_10B_MMU unsigned int data32; -#endif + if (debug && pbi->init_flag == 0) pr_info("%s %x %x %x %x %x %x %x %x %x %x %x %x\n", __func__, @@ -5255,24 +5231,33 @@ static void vp9_config_work_space_hw(struct VP9Decoder_s *pbi, u32 mask) buf_spec->ipp.buf_start); WRITE_VREG(HEVC_SAO_UP, buf_spec->sao_up.buf_start); WRITE_VREG(HEVC_SCALELUT, buf_spec->scalelut.buf_start); - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) { + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A) { /* cfg_addr_adp*/ WRITE_VREG(HEVC_DBLK_CFGE, buf_spec->dblk_para.buf_start); if (debug & VP9_DEBUG_BUFMGR_MORE) pr_info("Write HEVC_DBLK_CFGE\n"); - } else { - /* cfg_p_addr */ - WRITE_VREG(HEVC_DBLK_CFG4, buf_spec->dblk_para.buf_start); } + /* cfg_p_addr */ + WRITE_VREG(HEVC_DBLK_CFG4, buf_spec->dblk_para.buf_start); /* cfg_d_addr */ WRITE_VREG(HEVC_DBLK_CFG5, buf_spec->dblk_data.buf_start); + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) { + /* + * data32 = (READ_VREG(P_HEVC_DBLK_CFG3)>>8) & 0xff; // xio left offset, default is 0x40 + * data32 = data32 * 2; + * data32 = (READ_VREG(P_HEVC_DBLK_CFG3)>>16) & 0xff; // adp left offset, default is 0x040 + * data32 = data32 * 2; + */ + WRITE_VREG(HEVC_DBLK_CFG3, 0x808010); // make left storage 2 x 4k] + } #ifdef LOSLESS_COMPRESS_MODE -#ifdef VP9_10B_MMU + if (pbi->mmu_enable) { /*bit[4] : paged_mem_mode*/ WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, (0x1 << 4)); - WRITE_VREG(HEVCD_MPP_DECOMP_CTL2, 0); -#else + if (get_cpu_major_id() < AM_MESON_CPU_MAJOR_ID_SM1) + WRITE_VREG(HEVCD_MPP_DECOMP_CTL2, 0); + } else { /*if(cur_pic_config->bit_depth == VPX_BITS_10) * WRITE_VREG(P_HEVCD_MPP_DECOMP_CTL1, (0<<3)); */ @@ -5281,20 +5266,22 @@ static void vp9_config_work_space_hw(struct VP9Decoder_s *pbi, u32 mask) /*bit[3] smem mdoe*/ WRITE_VREG(HEVCD_MPP_DECOMP_CTL2, (losless_comp_body_size >> 5)); -#endif - /*WRITE_VREG(HEVCD_MPP_DECOMP_CTL2, - (losless_comp_body_size >> 5));*/ - /*WRITE_VREG(HEVCD_MPP_DECOMP_CTL3, - (0xff<<20) | (0xff<<10) | 0xff);*/ - /*8-bit mode */ - WRITE_VREG(HEVC_CM_BODY_LENGTH, losless_comp_body_size); - WRITE_VREG(HEVC_CM_HEADER_OFFSET, losless_comp_body_size); - WRITE_VREG(HEVC_CM_HEADER_LENGTH, losless_comp_header_size); + } + /*WRITE_VREG(HEVCD_MPP_DECOMP_CTL2, + (losless_comp_body_size >> 5));*/ + /*WRITE_VREG(HEVCD_MPP_DECOMP_CTL3, + (0xff<<20) | (0xff<<10) | 0xff);*/ + /*8-bit mode */ + WRITE_VREG(HEVC_CM_BODY_LENGTH, losless_comp_body_size); + WRITE_VREG(HEVC_CM_HEADER_OFFSET, losless_comp_body_size); + WRITE_VREG(HEVC_CM_HEADER_LENGTH, losless_comp_header_size); + if (get_double_write_mode(pbi) & 0x10) + WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, 0x1 << 31); #else WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, 0x1 << 31); #endif -#ifdef VP9_10B_MMU + if (pbi->mmu_enable) { WRITE_VREG(HEVC_SAO_MMU_VH0_ADDR, buf_spec->mmu_vbh.buf_start); WRITE_VREG(HEVC_SAO_MMU_VH1_ADDR, buf_spec->mmu_vbh.buf_start + buf_spec->mmu_vbh.buf_size/2); @@ -5306,20 +5293,21 @@ static void vp9_config_work_space_hw(struct VP9Decoder_s *pbi, u32 mask) data32 = READ_VREG(HEVC_SAO_CTRL5); data32 |= (1<<10); WRITE_VREG(HEVC_SAO_CTRL5, data32); -#endif + } + WRITE_VREG(VP9_SEG_MAP_BUFFER, buf_spec->seg_map.buf_start); + WRITE_VREG(LMEM_DUMP_ADR, (u32)pbi->lmem_phy_addr); /**/ WRITE_VREG(VP9_PROB_SWAP_BUFFER, pbi->prob_buffer_phy_addr); WRITE_VREG(VP9_COUNT_SWAP_BUFFER, pbi->count_buffer_phy_addr); -#ifdef VP9_10B_MMU - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) - WRITE_VREG(HEVC_ASSIST_MMU_MAP_ADDR, pbi->frame_mmu_map_phy_addr); - else - WRITE_VREG(VP9_MMU_MAP_BUFFER, pbi->frame_mmu_map_phy_addr); -#endif + if (pbi->mmu_enable) { + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A) + WRITE_VREG(HEVC_ASSIST_MMU_MAP_ADDR, pbi->frame_mmu_map_phy_addr); + else + WRITE_VREG(VP9_MMU_MAP_BUFFER, pbi->frame_mmu_map_phy_addr); + } } - } @@ -5453,6 +5441,7 @@ void vp9_loop_filter_init(struct VP9Decoder_s *pbi) struct loopfilter *lf = pbi->lf; struct segmentation *seg_4lf = pbi->seg_4lf; int i; + unsigned int data32; memset(lfi, 0, sizeof(struct loop_filter_info_n)); memset(lf, 0, sizeof(struct loopfilter)); @@ -5478,16 +5467,21 @@ void vp9_loop_filter_init(struct VP9Decoder_s *pbi) } /*video format is VP9*/ - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) { - unsigned int data32; + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) { + data32 = (0x3 << 14) | // (dw fifo thres r and b) + (0x3 << 12) | // (dw fifo thres r or b) + (0x3 << 10) | // (dw fifo thres not r/b) + (0x3 << 8) | // 1st/2nd write both enable + (0x1 << 0); // vp9 video format + } else if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A) { data32 = (0x57 << 8) | /*1st/2nd write both enable*/ - (0x1 << 0); /*vp9 video format*/ - WRITE_VREG(HEVC_DBLK_CFGB, data32); - - if (debug & VP9_DEBUG_BUFMGR_MORE) - pr_info("[DBLK DEBUG] CFGB : 0x%x\n", data32); + (0x1 << 0); /*vp9 video format*/ } else - WRITE_VREG(HEVC_DBLK_CFGB, 0x40400001); + data32 = 0x40400001; + + WRITE_VREG(HEVC_DBLK_CFGB, data32); + if (debug & VP9_DEBUG_BUFMGR_MORE) + pr_info("[DBLK DEBUG] CFGB : 0x%x\n", data32); } /* perform this function per frame*/ void vp9_loop_filter_frame_init(struct segmentation *seg, @@ -5613,7 +5607,7 @@ static void vp9_init_decoder_hw(struct VP9Decoder_s *pbi, u32 mask) 0x7C00 }; #if 0 - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) { + if (get_cpu_major_id() >= MESON_CPU_MAJOR_ID_G12A) { /* Set MCR fetch priorities*/ data32 = 0x1 | (0x1 << 2) | (0x1 <<3) | (24 << 4) | (32 << 11) | (24 << 18) | (32 << 25); @@ -5747,10 +5741,10 @@ static void vp9_init_decoder_hw(struct VP9Decoder_s *pbi, u32 mask) (1 << 1) | /*enable ipp*/ (0 << 0) /*software reset ipp and mpp*/ ); -#ifdef VP9_10B_NV21 + if (get_double_write_mode(pbi) & 0x10) { /*Enable NV21 reference read mode for MC*/ WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, 0x1 << 31); -#endif + } /*Initialize mcrcc and decomp perf counters*/ if (mcrcc_cache_alg_flag && @@ -5833,11 +5827,11 @@ static void config_mcrcc_axi_hw(struct VP9Decoder_s *pbi) return; } -#if 0 - mcrcc_get_hitrate(); - decomp_get_hitrate(); - decomp_get_comprate(); -#endif + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) { + mcrcc_get_hitrate(pbi->m_ins_flag); + decomp_get_hitrate(); + decomp_get_comprate(); + } WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR, (0 << 8) | (1 << 1) | 0); @@ -6082,15 +6076,17 @@ static void vp9_local_uninit(struct VP9Decoder_s *pbi) pbi->count_buffer_addr = NULL; } -#ifdef VP9_10B_MMU - if (pbi->frame_mmu_map_addr) { - if (pbi->frame_mmu_map_phy_addr) - dma_free_coherent(amports_get_dma_device(), - FRAME_MMU_MAP_SIZE, pbi->frame_mmu_map_addr, + if (pbi->mmu_enable) { + u32 mmu_map_size = vvp9_frame_mmu_map_size(pbi); + if (pbi->frame_mmu_map_addr) { + if (pbi->frame_mmu_map_phy_addr) + dma_free_coherent(amports_get_dma_device(), + mmu_map_size, + pbi->frame_mmu_map_addr, pbi->frame_mmu_map_phy_addr); - pbi->frame_mmu_map_addr = NULL; + pbi->frame_mmu_map_addr = NULL; + } } -#endif #ifdef SUPPORT_FB_DECODING if (pbi->stage_mmu_map_addr) { if (pbi->stage_mmu_map_phy_addr) @@ -6112,9 +6108,6 @@ static void vp9_local_uninit(struct VP9Decoder_s *pbi) pbi->gvs = NULL; } - - - static int vp9_local_init(struct VP9Decoder_s *pbi) { int ret = -1; @@ -6126,49 +6119,36 @@ static int vp9_local_init(struct VP9Decoder_s *pbi) memset(&pbi->common, 0, sizeof(struct VP9_Common_s)); #ifdef MULTI_INSTANCE_SUPPORT cur_buf_info = &pbi->work_space_buf_store; -#ifdef SUPPORT_4K2K - if (vdec_is_support_4k()) - memcpy(cur_buf_info, &amvvp9_workbuff_spec[1], /* 4k */ - sizeof(struct BuffInfo_s)); - else + + if (vdec_is_support_4k()) { + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) { + memcpy(cur_buf_info, &amvvp9_workbuff_spec[2], /* 8k */ + sizeof(struct BuffInfo_s)); + } else + memcpy(cur_buf_info, &amvvp9_workbuff_spec[1], /* 4k */ + sizeof(struct BuffInfo_s)); + } else memcpy(cur_buf_info, &amvvp9_workbuff_spec[0],/* 1080p */ sizeof(struct BuffInfo_s)); -#else - memcpy(cur_buf_info, &amvvp9_workbuff_spec[0], /* 1080p work space */ - sizeof(struct BuffInfo_s)); -#endif + cur_buf_info->start_adr = pbi->buf_start; -#ifndef VP9_10B_MMU - pbi->mc_buf_spec.buf_end = pbi->buf_start + pbi->buf_size; -#endif + if (!pbi->mmu_enable) + pbi->mc_buf_spec.buf_end = pbi->buf_start + pbi->buf_size; + #else /*! MULTI_INSTANCE_SUPPORT*/ -#ifdef SUPPORT_4K2K - if (vdec_is_support_4k()) - cur_buf_info = &amvvp9_workbuff_spec[1];/* 4k2k work space */ - else + if (vdec_is_support_4k()) { + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) + cur_buf_info = &amvvp9_workbuff_spec[2];/* 8k work space */ + else + cur_buf_info = &amvvp9_workbuff_spec[1];/* 4k2k work space */ + } else cur_buf_info = &amvvp9_workbuff_spec[0];/* 1080p work space */ -#else - cur_buf_info = &amvvp9_workbuff_spec[0]; /* 1080p work space */ -#endif + #endif init_buff_spec(pbi, cur_buf_info); -#ifdef VP9_10B_MMU vp9_bufmgr_init(pbi, cur_buf_info, NULL); -#else - pbi->mc_buf_spec.buf_start = (cur_buf_info->end_adr + 0xffff) - & (~0xffff); - pbi->mc_buf_spec.buf_size = (pbi->mc_buf_spec.buf_end - - pbi->mc_buf_spec.buf_start); - if (debug) { - pr_err("pbi->mc_buf_spec.buf_start %x-%x\n", - pbi->mc_buf_spec.buf_start, - pbi->mc_buf_spec.buf_start + - pbi->mc_buf_spec.buf_size); - } - vp9_bufmgr_init(pbi, cur_buf_info, &pbi->mc_buf_spec); -#endif if (!vdec_is_support_4k() && (buf_alloc_width > 1920 && buf_alloc_height > 1088)) { @@ -6178,6 +6158,9 @@ static int vp9_local_init(struct VP9Decoder_s *pbi) pbi->max_pic_w = 1920; pbi->max_pic_h = 1088; } + } else if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) { + buf_alloc_width = 8192; + buf_alloc_height = 4608; } pbi->init_pic_w = pbi->max_pic_w ? pbi->max_pic_w : (buf_alloc_width ? buf_alloc_width : @@ -6189,6 +6172,13 @@ static int vp9_local_init(struct VP9Decoder_s *pbi) (pbi->vvp9_amstream_dec_info.height ? pbi->vvp9_amstream_dec_info.height : pbi->work_space_buf->max_height)); + + if ((get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) && + (pbi->double_write_mode != 0) && + (((pbi->max_pic_w % 64) != 0) || + (pbi->vvp9_amstream_dec_info.width % 64) != 0)) + mem_map_mode = 2; + #ifndef MV_USE_FIXED_BUF if (init_mv_buf_list(pbi) < 0) { pr_err("%s: init_mv_buf_list fail\n", __func__); @@ -6196,15 +6186,16 @@ static int vp9_local_init(struct VP9Decoder_s *pbi) } #endif -#ifndef VP9_10B_MMU - init_buf_list(pbi); -#else - pbi->used_buf_num = max_buf_num; + if (pbi->save_buffer_mode) + pbi->used_buf_num = MAX_BUF_NUM_SAVE_BUF; + else + pbi->used_buf_num = max_buf_num; + if (pbi->used_buf_num > MAX_BUF_NUM) pbi->used_buf_num = MAX_BUF_NUM; if (pbi->used_buf_num > FRAME_BUFFERS) pbi->used_buf_num = FRAME_BUFFERS; -#endif + init_pic_list(pbi); pbi->pts_unstable = ((unsigned long)(pbi->vvp9_amstream_dec_info.param) @@ -6286,26 +6277,27 @@ static int vp9_local_init(struct VP9Decoder_s *pbi) return -1; } */ -#ifdef VP9_10B_MMU - pbi->frame_mmu_map_addr = dma_alloc_coherent(amports_get_dma_device(), - FRAME_MMU_MAP_SIZE, + if (pbi->mmu_enable) { + u32 mmu_map_size = vvp9_frame_mmu_map_size(pbi); + pbi->frame_mmu_map_addr = + dma_alloc_coherent(amports_get_dma_device(), + mmu_map_size, &pbi->frame_mmu_map_phy_addr, GFP_KERNEL); - if (pbi->frame_mmu_map_addr == NULL) { - pr_err("%s: failed to alloc count_buffer\n", __func__); - return -1; + if (pbi->frame_mmu_map_addr == NULL) { + pr_err("%s: failed to alloc count_buffer\n", __func__); + return -1; + } + memset(pbi->frame_mmu_map_addr, 0, COUNT_BUF_SIZE); + /* pbi->frame_mmu_map_phy_addr = dma_map_single(amports_get_dma_device(), + pbi->frame_mmu_map_addr, mmu_map_size, DMA_BIDIRECTIONAL); + if (dma_mapping_error(amports_get_dma_device(), + pbi->frame_mmu_map_phy_addr)) { + pr_err("%s: failed to map count_buffer\n", __func__); + kfree(pbi->frame_mmu_map_addr); + pbi->frame_mmu_map_addr = NULL; + return -1; + }*/ } - memset(pbi->frame_mmu_map_addr, 0, FRAME_MMU_MAP_SIZE); -/* pbi->frame_mmu_map_phy_addr = dma_map_single(amports_get_dma_device(), - pbi->frame_mmu_map_addr, FRAME_MMU_MAP_SIZE, DMA_BIDIRECTIONAL); - if (dma_mapping_error(amports_get_dma_device(), - pbi->frame_mmu_map_phy_addr)) { - pr_err("%s: failed to map count_buffer\n", __func__); - kfree(pbi->frame_mmu_map_addr); - pbi->frame_mmu_map_addr = NULL; - return -1; - }*/ -#endif - #ifdef SUPPORT_FB_DECODING if (pbi->m_ins_flag && stage_buf_num > 0) { pbi->stage_mmu_map_addr = @@ -6351,6 +6343,7 @@ static int vp9_local_init(struct VP9Decoder_s *pbi) static void set_canvas(struct VP9Decoder_s *pbi, struct PIC_BUFFER_CONFIG_s *pic_config) { + struct vdec_s *vdec = hw_to_vdec(pbi); int canvas_w = ALIGN(pic_config->y_crop_width, 64)/4; int canvas_h = ALIGN(pic_config->y_crop_height, 32)/4; int blkmode = mem_map_mode; @@ -6369,8 +6362,17 @@ static void set_canvas(struct VP9Decoder_s *pbi, canvas_w = ALIGN(canvas_w, 64); canvas_h = ALIGN(canvas_h, 32); - pic_config->y_canvas_index = 128 + pic_config->index * 2; - pic_config->uv_canvas_index = 128 + pic_config->index * 2 + 1; + if (vdec->parallel_dec == 1) { + if (pic_config->y_canvas_index == -1) + pic_config->y_canvas_index = + vdec->get_canvas_ex(CORE_MASK_HEVC, vdec->id); + if (pic_config->uv_canvas_index == -1) + pic_config->uv_canvas_index = + vdec->get_canvas_ex(CORE_MASK_HEVC, vdec->id); + } else { + pic_config->y_canvas_index = 128 + pic_config->index * 2; + pic_config->uv_canvas_index = 128 + pic_config->index * 2 + 1; + } canvas_config_ex(pic_config->y_canvas_index, pic_config->dw_y_adr, canvas_w, canvas_h, @@ -6378,6 +6380,7 @@ static void set_canvas(struct VP9Decoder_s *pbi, canvas_config_ex(pic_config->uv_canvas_index, pic_config->dw_u_v_adr, canvas_w, canvas_h, CANVAS_ADDR_NOWRAP, blkmode, 0x7); + #ifdef MULTI_INSTANCE_SUPPORT pic_config->canvas_config[0].phy_addr = pic_config->dw_y_adr; @@ -6399,18 +6402,6 @@ static void set_canvas(struct VP9Decoder_s *pbi, blkmode; pic_config->canvas_config[1].endian = 7; #endif - } else { - #ifndef VP9_10B_MMU - pic_config->y_canvas_index = 128 + pic_config->index; - pic_config->uv_canvas_index = 128 + pic_config->index; - - canvas_config_ex(pic_config->y_canvas_index, - pic_config->mc_y_adr, canvas_w, canvas_h, - CANVAS_ADDR_NOWRAP, blkmode, 0x7); - canvas_config_ex(pic_config->uv_canvas_index, - pic_config->mc_u_v_adr, canvas_w, canvas_h, - CANVAS_ADDR_NOWRAP, blkmode, 0x7); - #endif } } @@ -6427,6 +6418,7 @@ static void set_frame_info(struct VP9Decoder_s *pbi, struct vframe_s *vf) ar = min_t(u32, pbi->frame_ar, DISP_RATIO_ASPECT_RATIO_MAX); vf->ratio_control = (ar << DISP_RATIO_ASPECT_RATIO_BIT); + pbi->ratio_control = vf->ratio_control; } @@ -6476,7 +6468,7 @@ static struct vframe_s *vvp9_vf_get(void *op_arg) if (kfifo_get(&pbi->display_q, &vf)) { struct vframe_s *next_vf; uint8_t index = vf->index & 0xff; - if (index >= 0 && index < pbi->used_buf_num) { + if (index < pbi->used_buf_num) { pbi->vf_get_count++; if (debug & VP9_DEBUG_BUFMGR) pr_info("%s type 0x%x w/h %d/%d, pts %d, %lld\n", @@ -6504,8 +6496,7 @@ static void vvp9_vf_put(struct vframe_s *vf, void *op_arg) kfifo_put(&pbi->newframe_q, (const struct vframe_s *)vf); pbi->vf_put_count++; - if (index >= 0 - && index < pbi->used_buf_num) { + if (index < pbi->used_buf_num) { struct VP9_Common_s *cm = &pbi->common; struct BufferPool_s *pool = cm->buffer_pool; unsigned long flags; @@ -6630,7 +6621,31 @@ static int frame_duration_adapt(struct VP9Decoder_s *pbi, struct vframe_s *vf, u return true; } - +static void update_vf_memhandle(struct VP9Decoder_s *pbi, + struct vframe_s *vf, struct PIC_BUFFER_CONFIG_s *pic) +{ + if (pic->index < 0) { + vf->mem_handle = NULL; + vf->mem_head_handle = NULL; + } else if (vf->type & VIDTYPE_SCATTER) { + vf->mem_handle = + decoder_mmu_box_get_mem_handle( + pbi->mmu_box, pic->index); + vf->mem_head_handle = + decoder_bmmu_box_get_mem_handle( + pbi->bmmu_box, + HEADER_BUFFER_IDX(pic->BUF_index)); + } else { + vf->mem_handle = + decoder_bmmu_box_get_mem_handle( + pbi->bmmu_box, VF_BUFFER_IDX(pic->BUF_index)); + vf->mem_head_handle = NULL; + /*vf->mem_head_handle = + *decoder_bmmu_box_get_mem_handle( + *hevc->bmmu_box, VF_BUFFER_IDX(BUF_index)); + */ + } +} static int prepare_display_buf(struct VP9Decoder_s *pbi, struct PIC_BUFFER_CONFIG_s *pic_config) { @@ -6640,6 +6655,7 @@ static int prepare_display_buf(struct VP9Decoder_s *pbi, u32 pts_valid = 0, pts_us64_valid = 0; u32 pts_save; u64 pts_us64_save; + u32 frame_size; if (debug & VP9_DEBUG_BUFMGR) pr_info("%s index = %d\r\n", __func__, pic_config->index); @@ -6670,8 +6686,9 @@ static int prepare_display_buf(struct VP9Decoder_s *pbi, * stream_offset, &vf->pts, 0) != 0) { */ if (pts_lookup_offset_us64 - (PTS_TYPE_VIDEO, stream_offset, &vf->pts, 0, - &vf->pts_us64) != 0) { + (PTS_TYPE_VIDEO, stream_offset, &vf->pts, + &frame_size, 0, + &vf->pts_us64) != 0) { #ifdef DEBUG_PTS pbi->pts_missed++; #endif @@ -6768,25 +6785,27 @@ static int prepare_display_buf(struct VP9Decoder_s *pbi, vf->compBodyAddr = 0; vf->compHeadAddr = 0; } else { -#ifdef VP9_10B_MMU - vf->compBodyAddr = 0; - vf->compHeadAddr = pic_config->header_adr; -#else - vf->compBodyAddr = pic_config->mc_y_adr; /*body adr*/ - vf->compHeadAddr = pic_config->mc_y_adr + - pic_config->comp_body_size; - /*head adr*/ -#endif + if (pbi->mmu_enable) { + vf->compBodyAddr = 0; + vf->compHeadAddr = pic_config->header_adr; + } else { + /*vf->compBodyAddr = pic_config->mc_y_adr; + *vf->compHeadAddr = pic_config->mc_y_adr + + *pic_config->comp_body_size; */ + /*head adr*/ + } + vf->canvas0Addr = vf->canvas1Addr = 0; } if (pic_config->double_write_mode) { vf->type = VIDTYPE_PROGRESSIVE | VIDTYPE_VIU_FIELD; vf->type |= VIDTYPE_VIU_NV21; - if (pic_config->double_write_mode == 3) { + if ((pic_config->double_write_mode == 3) && + (!IS_8K_SIZE(pic_config->y_crop_width, + pic_config->y_crop_height))) { vf->type |= VIDTYPE_COMPRESS; -#ifdef VP9_10B_MMU - vf->type |= VIDTYPE_SCATTER; -#endif + if (pbi->mmu_enable) + vf->type |= VIDTYPE_SCATTER; } #ifdef MULTI_INSTANCE_SUPPORT if (pbi->m_ins_flag) { @@ -6808,9 +6827,8 @@ static int prepare_display_buf(struct VP9Decoder_s *pbi, } else { vf->canvas0Addr = vf->canvas1Addr = 0; vf->type = VIDTYPE_COMPRESS | VIDTYPE_VIU_FIELD; -#ifdef VP9_10B_MMU - vf->type |= VIDTYPE_SCATTER; -#endif + if (pbi->mmu_enable) + vf->type |= VIDTYPE_SCATTER; } switch (pic_config->bit_depth) { @@ -6861,39 +6879,22 @@ static int prepare_display_buf(struct VP9Decoder_s *pbi, else vf->duration = 0; } -#ifdef VP9_10B_MMU - if (vf->type & VIDTYPE_SCATTER) { - vf->mem_handle = decoder_mmu_box_get_mem_handle( - pbi->mmu_box, - pic_config->index); - vf->mem_head_handle = decoder_bmmu_box_get_mem_handle( - pbi->bmmu_box, - HEADER_BUFFER_IDX(pic_config->index)); - } else { - vf->mem_handle = decoder_bmmu_box_get_mem_handle( - pbi->bmmu_box, - VF_BUFFER_IDX(pic_config->index)); - vf->mem_head_handle = decoder_bmmu_box_get_mem_handle( - pbi->bmmu_box, - HEADER_BUFFER_IDX(pic_config->index)); - } -#else - vf->mem_handle = decoder_bmmu_box_get_mem_handle( - pbi->bmmu_box, - VF_BUFFER_IDX(pic_config->index)); -#endif + update_vf_memhandle(pbi, vf, pic_config); if (!(pic_config->y_crop_width == 196 && pic_config->y_crop_height == 196 && (debug & VP9_DEBUG_NO_TRIGGER_FRAME) == 0 )) { inc_vf_ref(pbi, pic_config->index); + decoder_do_frame_check(hw_to_vdec(pbi), vf); kfifo_put(&pbi->display_q, (const struct vframe_s *)vf); + ATRACE_COUNTER(MODULE_NAME, vf->pts); pbi->vf_pre_count++; #ifndef CONFIG_AMLOGIC_MEDIA_MULTI_DEC /*count info*/ gvs->frame_dur = pbi->frame_dur; vdec_count_info(gvs, 0, stream_offset); #endif + hw_to_vdec(pbi)->vdec_fps_detec(hw_to_vdec(pbi)->id); vf_notify_receiver(pbi->provider_name, VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); } else { @@ -6998,10 +6999,12 @@ static void debug_buffer_mgr_more(struct VP9Decoder_s *pbi) } -#ifdef VP9_10B_MMU + static void vp9_recycle_mmu_buf_tail(struct VP9Decoder_s *pbi) { struct VP9_Common_s *const cm = &pbi->common; + if (pbi->double_write_mode & 0x10) + return; if (cm->cur_fb_idx_mmu != INVALID_IDX) { if (pbi->used_4k_num == -1) pbi->used_4k_num = @@ -7018,6 +7021,8 @@ static void vp9_recycle_mmu_buf_tail(struct VP9Decoder_s *pbi) static void vp9_recycle_mmu_buf(struct VP9Decoder_s *pbi) { struct VP9_Common_s *const cm = &pbi->common; + if (pbi->double_write_mode & 0x10) + return; if (cm->cur_fb_idx_mmu != INVALID_IDX) { decoder_mmu_box_free_idx(pbi->mmu_box, cm->cur_fb_idx_mmu); @@ -7027,7 +7032,7 @@ static void vp9_recycle_mmu_buf(struct VP9Decoder_s *pbi) } } #endif -#endif + static void dec_again_process(struct VP9Decoder_s *pbi) { @@ -7037,6 +7042,8 @@ static void dec_again_process(struct VP9Decoder_s *pbi) PROC_STATE_DECODESLICE) { pbi->process_state = PROC_STATE_SENDAGAIN; + if (pbi->mmu_enable) + vp9_recycle_mmu_buf(pbi); } reset_process_time(pbi); vdec_schedule_work(&pbi->work); @@ -7058,22 +7065,22 @@ int continue_decoding(struct VP9Decoder_s *pbi) pbi->slice_idx++; } else { union param_u *params = &vp9_param; -#ifdef VP9_10B_MMU - ret = vp9_alloc_mmu(pbi, - cm->new_fb_idx, - params->p.width, - params->p.height, - params->p.bit_depth, - pbi->frame_mmu_map_addr); - if (ret >= 0) - cm->cur_fb_idx_mmu = cm->new_fb_idx; - else - pr_err("can't alloc need mmu1,idx %d ret =%d\n", + if (pbi->mmu_enable && ((pbi->double_write_mode & 0x10) == 0)) { + ret = vp9_alloc_mmu(pbi, cm->new_fb_idx, - ret); -#else - ret = 0; -#endif + params->p.width, + params->p.height, + params->p.bit_depth, + pbi->frame_mmu_map_addr); + if (ret >= 0) + cm->cur_fb_idx_mmu = cm->new_fb_idx; + else + pr_err("can't alloc need mmu1,idx %d ret =%d\n", + cm->new_fb_idx, + ret); + } else { + ret = 0; + } WRITE_VREG(HEVC_PARSER_PICTURE_SIZE, (params->p.height << 16) | params->p.width); } @@ -7082,9 +7089,8 @@ int continue_decoding(struct VP9Decoder_s *pbi) ret); WRITE_VREG(HEVC_DEC_STATUS_REG, VP9_10B_DISCARD_NAL); cm->show_frame = 0; -#ifdef VP9_10B_MMU - vp9_recycle_mmu_buf(pbi); -#endif + if (pbi->mmu_enable) + vp9_recycle_mmu_buf(pbi); #ifdef MULTI_INSTANCE_SUPPORT if (pbi->m_ins_flag) { pbi->dec_result = DEC_RESULT_DONE; @@ -7139,46 +7145,46 @@ int continue_decoding(struct VP9Decoder_s *pbi) config_sao_hw(pbi, &vp9_param); #ifdef VP9_LPF_LVL_UPDATE - /* - * Get loop filter related picture level parameters from Parser - */ - pbi->lf->mode_ref_delta_enabled = vp9_param.p.mode_ref_delta_enabled; - pbi->lf->sharpness_level = vp9_param.p.sharpness_level; - for (i = 0; i < 4; i++) - pbi->lf->ref_deltas[i] = vp9_param.p.ref_deltas[i]; - for (i = 0; i < 2; i++) - pbi->lf->mode_deltas[i] = vp9_param.p.mode_deltas[i]; - pbi->default_filt_lvl = vp9_param.p.filter_level; - pbi->seg_4lf->enabled = vp9_param.p.seg_enabled; - pbi->seg_4lf->abs_delta = vp9_param.p.seg_abs_delta; - for (i = 0; i < MAX_SEGMENTS; i++) - pbi->seg_4lf->feature_mask[i] = (vp9_param.p.seg_lf_info[i] & - 0x8000) ? (1 << SEG_LVL_ALT_LF) : 0; - for (i = 0; i < MAX_SEGMENTS; i++) - pbi->seg_4lf->feature_data[i][SEG_LVL_ALT_LF] - = (vp9_param.p.seg_lf_info[i] - & 0x100) ? -(vp9_param.p.seg_lf_info[i] - & 0x3f) : (vp9_param.p.seg_lf_info[i] & 0x3f); - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) { - /*Set pipeline mode*/ - uint32_t lpf_data32 = READ_VREG(HEVC_DBLK_CFGB); - /*dblk pipeline mode=1 for performance*/ - if (vp9_param.p.width >= 1280) - lpf_data32 |= (0x1 << 4); - else - lpf_data32 &= ~(0x3 << 4); - WRITE_VREG(HEVC_DBLK_CFGB, lpf_data32); - } - /* - * Update loop filter Thr/Lvl table for every frame - */ - /*pr_info - ("vp9_loop_filter (run before every frame decoding start)\n");*/ - vp9_loop_filter_frame_init(pbi->seg_4lf, - pbi->lfi, pbi->lf, pbi->default_filt_lvl); + /* + * Get loop filter related picture level parameters from Parser + */ + pbi->lf->mode_ref_delta_enabled = vp9_param.p.mode_ref_delta_enabled; + pbi->lf->sharpness_level = vp9_param.p.sharpness_level; + for (i = 0; i < 4; i++) + pbi->lf->ref_deltas[i] = vp9_param.p.ref_deltas[i]; + for (i = 0; i < 2; i++) + pbi->lf->mode_deltas[i] = vp9_param.p.mode_deltas[i]; + pbi->default_filt_lvl = vp9_param.p.filter_level; + pbi->seg_4lf->enabled = vp9_param.p.seg_enabled; + pbi->seg_4lf->abs_delta = vp9_param.p.seg_abs_delta; + for (i = 0; i < MAX_SEGMENTS; i++) + pbi->seg_4lf->feature_mask[i] = (vp9_param.p.seg_lf_info[i] & + 0x8000) ? (1 << SEG_LVL_ALT_LF) : 0; + for (i = 0; i < MAX_SEGMENTS; i++) + pbi->seg_4lf->feature_data[i][SEG_LVL_ALT_LF] + = (vp9_param.p.seg_lf_info[i] + & 0x100) ? -(vp9_param.p.seg_lf_info[i] + & 0x3f) : (vp9_param.p.seg_lf_info[i] & 0x3f); + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A) { + /*Set pipeline mode*/ + uint32_t lpf_data32 = READ_VREG(HEVC_DBLK_CFGB); + /*dblk pipeline mode=1 for performance*/ + if (vp9_param.p.width >= 1280) + lpf_data32 |= (0x1 << 4); + else + lpf_data32 &= ~(0x3 << 4); + WRITE_VREG(HEVC_DBLK_CFGB, lpf_data32); + } + /* + * Update loop filter Thr/Lvl table for every frame + */ + /*pr_info + ("vp9_loop_filter (run before every frame decoding start)\n");*/ + vp9_loop_filter_frame_init(pbi->seg_4lf, + pbi->lfi, pbi->lf, pbi->default_filt_lvl); #endif - /*pr_info("HEVC_DEC_STATUS_REG <= VP9_10B_DECODE_SLICE\n");*/ - WRITE_VREG(HEVC_DEC_STATUS_REG, VP9_10B_DECODE_SLICE); + /*pr_info("HEVC_DEC_STATUS_REG <= VP9_10B_DECODE_SLICE\n");*/ + WRITE_VREG(HEVC_DEC_STATUS_REG, VP9_10B_DECODE_SLICE); } else { pr_info("Skip search next start code\n"); cm->prev_fb_idx = INVALID_IDX; @@ -7186,19 +7192,20 @@ int continue_decoding(struct VP9Decoder_s *pbi) WRITE_VREG(HEVC_DEC_STATUS_REG, VP9_10B_DECODE_SLICE); } pbi->process_state = PROC_STATE_DECODESLICE; -#ifdef VP9_10B_MMU - if (pbi->last_put_idx >= 0 && pbi->last_put_idx < pbi->used_buf_num) { - struct RefCntBuffer_s *frame_bufs = cm->buffer_pool->frame_bufs; - int i = pbi->last_put_idx; - /*free not used buffers.*/ - if ((frame_bufs[i].ref_count == 0) && - (frame_bufs[i].buf.vf_ref == 0) && - (frame_bufs[i].buf.index != -1)) { - decoder_mmu_box_free_idx(pbi->mmu_box, i); + if (pbi->mmu_enable && ((pbi->double_write_mode & 0x10) == 0)) { + if (pbi->last_put_idx < pbi->used_buf_num) { + struct RefCntBuffer_s *frame_bufs = + cm->buffer_pool->frame_bufs; + int i = pbi->last_put_idx; + /*free not used buffers.*/ + if ((frame_bufs[i].ref_count == 0) && + (frame_bufs[i].buf.vf_ref == 0) && + (frame_bufs[i].buf.index != -1)) { + decoder_mmu_box_free_idx(pbi->mmu_box, i); + } + pbi->last_put_idx = -1; } - pbi->last_put_idx = -1; } -#endif return ret; } @@ -7270,6 +7277,9 @@ static irqreturn_t vvp9_isr_thread_fn(int irq, void *data) #endif { reset_process_time(pbi); + if (pbi->vf_pre_count == 0) + vp9_bufmgr_postproc(pbi); + pbi->dec_result = DEC_RESULT_DONE; amhevc_stop(); if (mcrcc_cache_alg_flag) @@ -7330,9 +7340,9 @@ static irqreturn_t vvp9_isr_thread_fn(int irq, void *data) && pbi->used_stage_buf_num == 0 #endif ) { -#ifdef VP9_10B_MMU - vp9_recycle_mmu_buf_tail(pbi); -#endif + if (pbi->mmu_enable) + vp9_recycle_mmu_buf_tail(pbi); + if (pbi->frame_count > 0) vp9_bufmgr_postproc(pbi); @@ -7395,11 +7405,13 @@ static irqreturn_t vvp9_isr_thread_fn(int irq, void *data) return IRQ_HANDLED; } else #endif - for (i = 0; i < (RPM_END - RPM_BEGIN); i += 4) { - int ii; - for (ii = 0; ii < 4; ii++) - vp9_param.l.data[i + ii] = - pbi->rpm_ptr[i + 3 - ii]; + { + for (i = 0; i < (RPM_END - RPM_BEGIN); i += 4) { + int ii; + for (ii = 0; ii < 4; ii++) + vp9_param.l.data[i + ii] = + pbi->rpm_ptr[i + 3 - ii]; + } } } @@ -7564,17 +7576,12 @@ static void vp9_set_clk(struct work_struct *work) struct VP9Decoder_s *pbi = container_of(work, struct VP9Decoder_s, work); - if (pbi->get_frame_dur && pbi->show_frame_num > 60 && - pbi->frame_dur > 0 && pbi->saved_resolution != - frame_width * frame_height * - (96000 / pbi->frame_dur)) { int fps = 96000 / pbi->frame_dur; if (hevc_source_changed(VFORMAT_VP9, frame_width, frame_height, fps) > 0) pbi->saved_resolution = frame_width * frame_height * fps; - } } static void vvp9_put_timer_func(unsigned long arg) @@ -7698,6 +7705,8 @@ static void vvp9_put_timer_func(unsigned long arg) pbi->dec_result = DEC_RESULT_AGAIN; if (pbi->process_state == PROC_STATE_DECODESLICE) { + if (pbi->mmu_enable) + vp9_recycle_mmu_buf(pbi); pbi->process_state = PROC_STATE_SENDAGAIN; } @@ -7762,7 +7771,7 @@ static void vvp9_put_timer_func(unsigned long arg) if (dbg_cmd == 1) { u32 disp_laddr; - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXBB && + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXBB && get_double_write_mode(pbi) == 0) { disp_laddr = READ_VCBUS_REG(AFBC_BODY_BADDR) << 4; @@ -7779,7 +7788,11 @@ static void vvp9_put_timer_func(unsigned long arg) dbg_cmd = 0; } /*don't changed at start.*/ - schedule_work(&pbi->set_clk_work); + if (pbi->get_frame_dur && pbi->show_frame_num > 60 && + pbi->frame_dur > 0 && pbi->saved_resolution != + frame_width * frame_height * + (96000 / pbi->frame_dur)) + schedule_work(&pbi->set_clk_work); timer->expires = jiffies + PUT_INTERVAL; add_timer(timer); @@ -7790,6 +7803,10 @@ int vvp9_dec_status(struct vdec_s *vdec, struct vdec_info *vstatus) { struct VP9Decoder_s *vp9 = (struct VP9Decoder_s *)vdec->private; + + if (!vp9) + return -1; + vstatus->frame_width = frame_width; vstatus->frame_height = frame_height; if (vp9->frame_dur != 0) @@ -7812,6 +7829,7 @@ int vvp9_dec_status(struct vdec_s *vdec, struct vdec_info *vstatus) snprintf(vstatus->vdec_name, sizeof(vstatus->vdec_name), "%s", DRIVER_NAME); #endif + vstatus->ratio_control = vp9->ratio_control; return 0; } @@ -7868,7 +7886,7 @@ static void vvp9_prot_init(struct VP9Decoder_s *pbi, u32 mask) ; WRITE_VREG(HEVC_STREAM_CONTROL, data32); - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) { + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A) { if (debug & VP9_DEBUG_BUFMGR) pr_info("[test.c] Config STREAM_FIFO_CTL\n"); data32 = READ_VREG(HEVC_STREAM_FIFO_CTL); @@ -8039,34 +8057,20 @@ static s32 vvp9_init(struct vdec_s *vdec) static s32 vvp9_init(struct VP9Decoder_s *pbi) { #endif - int ret, size = -1; + int ret; int fw_size = 0x1000 * 16; struct firmware_s *fw = NULL; - INIT_WORK(&pbi->set_clk_work, vp9_set_clk); - - init_timer(&pbi->timer); - pbi->stat |= STAT_TIMER_INIT; + if (vvp9_local_init(pbi) < 0) return -EBUSY; fw = vmalloc(sizeof(struct firmware_s) + fw_size); if (IS_ERR_OR_NULL(fw)) return -ENOMEM; -#ifdef MULTI_INSTANCE_SUPPORT - if (tee_enabled()) { - size = 1; - pr_debug ("laod\n"); - } else -#endif - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) - size = get_firmware_data(VIDEO_DEC_VP9, fw->data); - else - size = get_firmware_data(VIDEO_DEC_VP9_MMU, fw->data); - - if (size < 0) { + if (get_firmware_data(VIDEO_DEC_VP9_MMU, fw->data) < 0) { pr_err("get firmware fail.\n"); vfree(fw); return -1; @@ -8074,6 +8078,9 @@ static s32 vvp9_init(struct VP9Decoder_s *pbi) fw->len = fw_size; + INIT_WORK(&pbi->set_clk_work, vp9_set_clk); + init_timer(&pbi->timer); + #ifdef MULTI_INSTANCE_SUPPORT if (pbi->m_ins_flag) { pbi->timer.data = (ulong) pbi; @@ -8095,21 +8102,15 @@ static s32 vvp9_init(struct VP9Decoder_s *pbi) return 0; } #endif - + hevc_enable_DMC(hw_to_vdec(pbi)); amhevc_enable(); - if (size == 1) { - pr_info ("tee load ok\n"); - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) - ret = tee_load_video_fw((u32)VIDEO_DEC_VP9, 0); - else - ret = tee_load_video_fw((u32)VIDEO_DEC_VP9_MMU, 0); - } else - ret = amhevc_loadmc_ex(VFORMAT_VP9, NULL, fw->data); - + ret = amhevc_loadmc_ex(VFORMAT_VP9, NULL, fw->data); if (ret < 0) { amhevc_disable(); vfree(fw); + pr_err("VP9: the %s fw loading failed, err: %x\n", + tee_enabled() ? "TEE" : "local", ret); return -EBUSY; } @@ -8160,17 +8161,14 @@ static s32 vvp9_init(struct VP9Decoder_s *pbi) pbi->timer.function = vvp9_put_timer_func; pbi->timer.expires = jiffies + PUT_INTERVAL; + pbi->stat |= STAT_VDEC_RUN; add_timer(&pbi->timer); pbi->stat |= STAT_TIMER_ARM; - /* pbi->stat |= STAT_KTHREAD; */ - amhevc_start(); - pbi->stat |= STAT_VDEC_RUN; - pbi->init_flag = 1; pbi->process_busy = 0; pr_info("%d, vvp9_init, RP=0x%x\n", @@ -8223,7 +8221,7 @@ static int vvp9_stop(struct VP9Decoder_s *pbi) { pbi->init_flag = 0; - + pbi->first_sc_checked = 0; if (pbi->stat & STAT_VDEC_RUN) { amhevc_stop(); pbi->stat &= ~STAT_VDEC_RUN; @@ -8273,14 +8271,12 @@ static int vvp9_stop(struct VP9Decoder_s *pbi) pbi->fw = NULL; return 0; } - static int amvdec_vp9_mmu_init(struct VP9Decoder_s *pbi) { int tvp_flag = vdec_secure(hw_to_vdec(pbi)) ? CODEC_MM_FLAGS_TVP : 0; - -#ifdef VP9_10B_MMU int buf_size = 48; + if ((pbi->max_pic_w * pbi->max_pic_h > 1280*736) && (pbi->max_pic_w * pbi->max_pic_h <= 1920*1088)) { buf_size = 12; @@ -8288,16 +8284,19 @@ static int amvdec_vp9_mmu_init(struct VP9Decoder_s *pbi) (pbi->max_pic_w * pbi->max_pic_h <= 1280*736)) { buf_size = 4; } - pbi->mmu_box = decoder_mmu_box_alloc_box(DRIVER_NAME, - pbi->index, FRAME_BUFFERS + STAGE_MAX_BUFFERS, - buf_size * SZ_1M, - tvp_flag - ); - if (!pbi->mmu_box) { - pr_err("vp9 alloc mmu box failed!!\n"); - return -1; + pbi->need_cache_size = buf_size * SZ_1M; + pbi->sc_start_time = get_jiffies_64(); + if (pbi->mmu_enable && ((pbi->double_write_mode & 0x10) == 0)) { + pbi->mmu_box = decoder_mmu_box_alloc_box(DRIVER_NAME, + pbi->index, FRAME_BUFFERS, + pbi->need_cache_size, + tvp_flag + ); + if (!pbi->mmu_box) { + pr_err("vp9 alloc mmu box failed!!\n"); + return -1; + } } -#endif pbi->bmmu_box = decoder_bmmu_box_alloc_box( DRIVER_NAME, pbi->index, @@ -8340,6 +8339,11 @@ static int amvdec_vp9_probe(struct platform_device *pdev) memcpy(&pbi->m_BUF[0], &BUF[0], sizeof(struct BUF_s) * MAX_BUF_NUM); pbi->init_flag = 0; + pbi->first_sc_checked= 0; + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) { + vp9_max_pic_w = 8192; + vp9_max_pic_h = 4608; + } pbi->max_pic_w = vp9_max_pic_w; pbi->max_pic_h = vp9_max_pic_h; @@ -8361,6 +8365,8 @@ static int amvdec_vp9_probe(struct platform_device *pdev) pbi->platform_dev = pdev; platform_set_drvdata(pdev, pdata); #endif + pbi->double_write_mode = double_write_mode; + pbi->mmu_enable = 1; if (amvdec_vp9_mmu_init(pbi) < 0) { vfree(pbi); mutex_unlock(&vvp9_mutex); @@ -8381,9 +8387,9 @@ static int amvdec_vp9_probe(struct platform_device *pdev) #ifdef MULTI_INSTANCE_SUPPORT pbi->buf_start = pdata->mem_start; #else -#ifndef VP9_10B_MMU - pbi->mc_buf_spec.buf_end = pdata->mem_start + pbi->buf_size; -#endif + if (!pbi->mmu_enable) + pbi->mc_buf_spec.buf_end = pdata->mem_start + pbi->buf_size; + for (i = 0; i < WORK_BUF_SPEC_NUM; i++) amvvp9_workbuff_spec[i].start_adr = pdata->mem_start; #endif @@ -8420,6 +8426,7 @@ static int amvdec_vp9_probe(struct platform_device *pdev) vp9_local_uninit(pbi); uninit_mmu_buffers(pbi); vfree(pbi); + pdata->dec_status = NULL; mutex_unlock(&vvp9_mutex); return -ENODEV; } @@ -8480,20 +8487,37 @@ static unsigned char get_data_check_sum { int jj; int sum = 0; - u8 *data = ((u8 *)pbi->chunk->block->start_virt) + - pbi->chunk->offset; + u8 *data = NULL; + + if (!pbi->chunk->block->is_mapped) + data = codec_mm_vmap(pbi->chunk->block->start + + pbi->chunk->offset, size); + else + data = ((u8 *)pbi->chunk->block->start_virt) + + pbi->chunk->offset; + for (jj = 0; jj < size; jj++) sum += data[jj]; + + if (!pbi->chunk->block->is_mapped) + codec_mm_unmap_phyaddr(data); return sum; } static void dump_data(struct VP9Decoder_s *pbi, int size) { int jj; - u8 *data = ((u8 *)pbi->chunk->block->start_virt) + - pbi->chunk->offset; + u8 *data = NULL; int padding_size = pbi->chunk->offset & (VDEC_FIFO_ALIGN - 1); + + if (!pbi->chunk->block->is_mapped) + data = codec_mm_vmap(pbi->chunk->block->start + + pbi->chunk->offset, size); + else + data = ((u8 *)pbi->chunk->block->start_virt) + + pbi->chunk->offset; + vp9_print(pbi, 0, "padding: "); for (jj = padding_size; jj > 0; jj--) vp9_print_cont(pbi, @@ -8518,6 +8542,9 @@ static void dump_data(struct VP9Decoder_s *pbi, int size) vp9_print(pbi, 0, "\n"); + + if (!pbi->chunk->block->is_mapped) + codec_mm_unmap_phyaddr(data); } static void vp9_work(struct work_struct *work) @@ -8626,10 +8653,9 @@ static void vp9_work(struct work_struct *work) pbi->process_state = PROC_STATE_INIT; decode_frame_count[pbi->index] = pbi->frame_count; -#ifdef VP9_10B_MMU - pbi->used_4k_num = - (READ_VREG(HEVC_SAO_MMU_STATUS) >> 16); -#endif + if (pbi->mmu_enable) + pbi->used_4k_num = + (READ_VREG(HEVC_SAO_MMU_STATUS) >> 16); vp9_print(pbi, PRINT_FLAG_VDEC_STATUS, "%s (===> %d) dec_result %d %x %x %x shiftbytes 0x%x decbytes 0x%x\n", __func__, @@ -8648,10 +8674,6 @@ static void vp9_work(struct work_struct *work) stream base: stream buf empty or timeout frame base: vdec_prepare_input fail */ -#ifdef VP9_10B_MMU - if (pbi->process_state == PROC_STATE_SENDAGAIN) - vp9_recycle_mmu_buf(pbi); -#endif if (!vdec_has_more_input(vdec)) { pbi->dec_result = DEC_RESULT_EOS; vdec_schedule_work(&pbi->work); @@ -8702,8 +8724,11 @@ static void vp9_work(struct work_struct *work) | CORE_MASK_HEVC_BACK ); #else - vdec_core_finish_run(hw_to_vdec(pbi), CORE_MASK_VDEC_1 - | CORE_MASK_HEVC); + if (vdec->parallel_dec == 1) + vdec_core_finish_run(vdec, CORE_MASK_HEVC); + else + vdec_core_finish_run(hw_to_vdec(pbi), CORE_MASK_VDEC_1 + | CORE_MASK_HEVC); #endif trigger_schedule(pbi); } @@ -8723,15 +8748,23 @@ static int vp9_hw_ctx_restore(struct VP9Decoder_s *pbi) #endif return 0; } - static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask) { struct VP9Decoder_s *pbi = (struct VP9Decoder_s *)vdec->private; + int tvp = vdec_secure(hw_to_vdec(pbi)) ? + CODEC_MM_FLAGS_TVP : 0; unsigned long ret = 0; if (pbi->eos) return ret; + if (!pbi->first_sc_checked && pbi->mmu_enable) { + int size = decoder_mmu_box_sc_check(pbi->mmu_box, tvp); + pbi->first_sc_checked = 1; + vp9_print(pbi, 0, "vp9 cached=%d need_size=%d speed= %d ms\n", + size, (pbi->need_cache_size >> PAGE_SHIFT), + (int)(get_jiffies_64() - pbi->sc_start_time) * 1000/HZ); + } #ifdef SUPPORT_FB_DECODING if (pbi->used_stage_buf_num > 0) { if (mask & CORE_MASK_HEVC_FRONT) { @@ -8782,8 +8815,12 @@ static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask) #else if (get_free_buf_count(pbi) >= - run_ready_min_buf_num) - ret = CORE_MASK_VDEC_1 | CORE_MASK_HEVC; + run_ready_min_buf_num) { + if (vdec->parallel_dec == 1) + ret = CORE_MASK_HEVC; + else + ret = CORE_MASK_VDEC_1 | CORE_MASK_HEVC; + } if (ret) not_run_ready[pbi->index] = 0; else @@ -8839,37 +8876,54 @@ static void run_front(struct vdec_s *vdec) pbi->frame_count, size, pbi->chunk ? pbi->chunk->size : 0, pbi->chunk ? pbi->chunk->offset : 0, - (vdec_frame_based(vdec) && + pbi->chunk ? ((vdec_frame_based(vdec) && (debug & PRINT_FLAG_VDEC_STATUS)) ? - get_data_check_sum(pbi, size) : 0, + get_data_check_sum(pbi, size) : 0) : 0, READ_VREG(HEVC_STREAM_START_ADDR), READ_VREG(HEVC_STREAM_END_ADDR), READ_VREG(HEVC_STREAM_LEVEL), READ_VREG(HEVC_STREAM_WR_PTR), READ_VREG(HEVC_STREAM_RD_PTR), pbi->start_shift_bytes); - if (vdec_frame_based(vdec)) { - u8 *data = ((u8 *)pbi->chunk->block->start_virt) + - pbi->chunk->offset; + if (vdec_frame_based(vdec) && pbi->chunk) { + u8 *data = NULL; + + if (!pbi->chunk->block->is_mapped) + data = codec_mm_vmap(pbi->chunk->block->start + + pbi->chunk->offset, 8); + else + data = ((u8 *)pbi->chunk->block->start_virt) + + pbi->chunk->offset; + vp9_print_cont(pbi, 0, "data adr %p:", data); for (ii = 0; ii < 8; ii++) vp9_print_cont(pbi, 0, "%02x ", data[ii]); + + if (!pbi->chunk->block->is_mapped) + codec_mm_unmap_phyaddr(data); } vp9_print_cont(pbi, 0, "\r\n"); } - - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) - ret = amhevc_loadmc_ex(VFORMAT_VP9, "vp9_mc", pbi->fw->data); - else - ret = amhevc_loadmc_ex(VFORMAT_VP9, NULL, pbi->fw->data); - - if (ret < 0) { - amhevc_disable(); - vp9_print(pbi, 0, - "%s: Error amvdec_loadmc fail\n", __func__); - return; + if (vdec->mc_loaded) { + /*firmware have load before, + and not changes to another. + ignore reload. + */ + } else { + ret = amhevc_loadmc_ex(VFORMAT_VP9, NULL, pbi->fw->data); + if (ret < 0) { + amhevc_disable(); + vp9_print(pbi, PRINT_FLAG_ERROR, + "VP9: the %s fw loading failed, err: %x\n", + tee_enabled() ? "TEE" : "local", ret); + pbi->dec_result = DEC_RESULT_FORCE_EXIT; + vdec_schedule_work(&pbi->work); + return; + } + vdec->mc_loaded = 1; + vdec->mc_type = VFORMAT_VP9; } if (vp9_hw_ctx_restore(pbi) < 0) { @@ -9206,9 +9260,16 @@ static void vp9_dump_state(struct vdec_s *vdec) int jj; if (pbi->chunk && pbi->chunk->block && pbi->chunk->size > 0) { - u8 *data = - ((u8 *)pbi->chunk->block->start_virt) + - pbi->chunk->offset; + u8 *data = NULL; + + if (!pbi->chunk->block->is_mapped) + data = codec_mm_vmap( + pbi->chunk->block->start + + pbi->chunk->offset, + pbi->chunk->size); + else + data = ((u8 *)pbi->chunk->block->start_virt) + + pbi->chunk->offset; vp9_print(pbi, 0, "frame data size 0x%x\n", pbi->chunk->size); @@ -9222,6 +9283,9 @@ static void vp9_dump_state(struct vdec_s *vdec) vp9_print_cont(pbi, 0, "\n"); } + + if (!pbi->chunk->block->is_mapped) + codec_mm_unmap_phyaddr(data); } } @@ -9283,11 +9347,17 @@ static int ammvdec_vp9_probe(struct platform_device *pdev) pbi->platform_dev = pdev; pbi->video_signal_type = 0; - if (get_cpu_type() < MESON_CPU_MAJOR_ID_TXLX) + pbi->m_ins_flag = 1; + if (get_cpu_major_id() < AM_MESON_CPU_MAJOR_ID_TXLX) pbi->stat |= VP9_TRIGGER_FRAME_ENABLE; + + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) { + pbi->max_pic_w = 8192; + pbi->max_pic_h = 4608; + } #if 1 if ((debug & IGNORE_PARAM_FROM_CONFIG) == 0 && - pdata->config && pdata->config_len) { + pdata->config_len) { #ifdef MULTI_INSTANCE_SUPPORT /*use ptr config for doubel_write_mode, etc*/ vp9_print(pbi, 0, "pdata->config=%s\n", pdata->config); @@ -9297,6 +9367,12 @@ static int ammvdec_vp9_probe(struct platform_device *pdev) else pbi->double_write_mode = double_write_mode; + if (get_config_int(pdata->config, "save_buffer_mode", + &config_val) == 0) + pbi->save_buffer_mode = config_val; + else + pbi->save_buffer_mode = 0; + /*use ptr config for max_pic_w, etc*/ if (get_config_int(pdata->config, "vp9_max_pic_w", &config_val) == 0) { @@ -9353,6 +9429,12 @@ static int ammvdec_vp9_probe(struct platform_device *pdev) pbi->vvp9_amstream_dec_info.rate = 30;*/ pbi->double_write_mode = double_write_mode; } + if (is_oversize(pbi->max_pic_w, pbi->max_pic_h)) { + pr_err("over size: %dx%d, probe failed\n", + pbi->max_pic_w, pbi->max_pic_h); + return -1; + } + pbi->mmu_enable = 1; video_signal_type = pbi->video_signal_type; #if 0 pbi->buf_start = pdata->mem_start; @@ -9362,6 +9444,7 @@ static int ammvdec_vp9_probe(struct platform_device *pdev) pr_err("vp9 alloc bmmu box failed!!\n"); /* devm_kfree(&pdev->dev, (void *)pbi); */ vfree((void *)pbi); + pdata->dec_status = NULL; return -1; } @@ -9373,23 +9456,17 @@ static int ammvdec_vp9_probe(struct platform_device *pdev) uninit_mmu_buffers(pbi); /* devm_kfree(&pdev->dev, (void *)pbi); */ vfree((void *)pbi); + pdata->dec_status = NULL; return ret; } pbi->buf_start = pbi->cma_alloc_addr; pbi->buf_size = work_buf_size; #endif - pbi->m_ins_flag = 1; pbi->init_flag = 0; + pbi->first_sc_checked = 0; pbi->fatal_error = 0; pbi->show_frame_num = 0; - if (pdata == NULL) { - pr_info("\namvdec_vp9 memory resource undefined.\n"); - uninit_mmu_buffers(pbi); - /* devm_kfree(&pdev->dev, (void *)pbi); */ - vfree((void *)pbi); - return -EFAULT; - } if (debug) { pr_info("===VP9 decoder mem resource 0x%lx size 0x%x\n", @@ -9412,6 +9489,7 @@ static int ammvdec_vp9_probe(struct platform_device *pdev) uninit_mmu_buffers(pbi); /* devm_kfree(&pdev->dev, (void *)pbi); */ vfree((void *)pbi); + pdata->dec_status = NULL; return -ENODEV; } vdec_set_prepare_level(pdata, start_decode_buf_level); @@ -9426,6 +9504,9 @@ static int ammvdec_vp9_probe(struct platform_device *pdev) | CORE_MASK_HEVC_FRONT | CORE_MASK_HEVC_BACK | CORE_MASK_COMBINE); #else + if (pdata->parallel_dec == 1) + vdec_core_request(pdata, CORE_MASK_HEVC); + else vdec_core_request(pdata, CORE_MASK_VDEC_1 | CORE_MASK_HEVC | CORE_MASK_COMBINE); #endif @@ -9436,6 +9517,8 @@ static int ammvdec_vp9_remove(struct platform_device *pdev) { struct VP9Decoder_s *pbi = (struct VP9Decoder_s *) (((struct vdec_s *)(platform_get_drvdata(pdev)))->private); + struct vdec_s *vdec = hw_to_vdec(pbi); + int i; if (debug) pr_info("amvdec_vp9_remove\n"); @@ -9446,10 +9529,24 @@ static int ammvdec_vp9_remove(struct platform_device *pdev) | CORE_MASK_HEVC_FRONT | CORE_MASK_HEVC_BACK ); #else - vdec_core_release(hw_to_vdec(pbi), CORE_MASK_VDEC_1 | CORE_MASK_HEVC); + if (vdec->parallel_dec == 1) + vdec_core_release(hw_to_vdec(pbi), CORE_MASK_HEVC); + else + vdec_core_release(hw_to_vdec(pbi), CORE_MASK_VDEC_1 | CORE_MASK_HEVC); #endif vdec_set_status(hw_to_vdec(pbi), VDEC_STATUS_DISCONNECTED); + if (vdec->parallel_dec == 1) { + for (i = 0; i < FRAME_BUFFERS; i++) { + vdec->free_canvas_ex + (pbi->common.buffer_pool->frame_bufs[i].buf.y_canvas_index, + vdec->id); + vdec->free_canvas_ex + (pbi->common.buffer_pool->frame_bufs[i].buf.uv_canvas_index, + vdec->id); + } + } + #ifdef DEBUG_PTS pr_info("pts missed %ld, pts hit %ld, duration %d\n", @@ -9515,24 +9612,23 @@ static struct mconfig_node vp9_node; static int __init amvdec_vp9_driver_init_module(void) { -#ifdef VP9_10B_MMU - struct BuffInfo_s *p_buf_info; -#ifdef SUPPORT_4K2K - if (vdec_is_support_4k()) - p_buf_info = &amvvp9_workbuff_spec[1]; - else + + if (vdec_is_support_4k()) { + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) + p_buf_info = &amvvp9_workbuff_spec[2]; + else + p_buf_info = &amvvp9_workbuff_spec[1]; + } else p_buf_info = &amvvp9_workbuff_spec[0]; -#else - p_buf_info = &amvvp9_workbuff_spec[0]; -#endif + init_buff_spec(NULL, p_buf_info); work_buf_size = (p_buf_info->end_adr - p_buf_info->start_adr + 0xffff) & (~0xffff); -#endif pr_debug("amvdec_vp9 module init\n"); + error_handle_policy = 0; #ifdef ERROR_HANDLE_DEBUG @@ -9554,8 +9650,12 @@ static int __init amvdec_vp9_driver_init_module(void) return -ENODEV; } - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXL - /*&& get_cpu_type() != MESON_CPU_MAJOR_ID_GXLX*/) { + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) { + amvdec_vp9_profile.profile = + "8k, 10bit, dwrite, compressed"; + } else if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXL + /*&& get_cpu_major_id() != MESON_CPU_MAJOR_ID_GXLX*/ + && get_cpu_major_id() != AM_MESON_CPU_MAJOR_ID_TXL) { if (vdec_is_support_4k()) amvdec_vp9_profile.profile = "4k, 10bit, dwrite, compressed"; @@ -9566,6 +9666,9 @@ static int __init amvdec_vp9_driver_init_module(void) amvdec_vp9_profile.name = "vp9_unsupport"; } + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A) + max_buf_num = MAX_BUF_NUM_LESS; + vcodec_profile_register(&amvdec_vp9_profile); INIT_REG_NODE_CONFIGS("media.decoder", &vp9_node, "vp9", vp9_configs, CONFIG_FOR_RW); diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/vp9/vvp9.h b/drivers/amlogic/media_modules/frame_provider/decoder/vp9/vvp9.h index 3f4959ccccc2..1db9d0998ff2 100644 --- a/drivers/amlogic/media_modules/frame_provider/decoder/vp9/vvp9.h +++ b/drivers/amlogic/media_modules/frame_provider/decoder/vp9/vvp9.h @@ -17,7 +17,7 @@ #ifndef VVP9_H #define VVP9_H -#define VP9_10B_MMU + void adapt_coef_probs(int pic_count, int prev_kf, int cur_kf, int pre_fc, unsigned int *prev_prob, unsigned int *cur_prob, unsigned int *count); #endif diff --git a/drivers/amlogic/media_modules/frame_sink/encoder/h264/encoder.c b/drivers/amlogic/media_modules/frame_sink/encoder/h264/encoder.c index 48e701a56ee5..fadff431d0b5 100644 --- a/drivers/amlogic/media_modules/frame_sink/encoder/h264/encoder.c +++ b/drivers/amlogic/media_modules/frame_sink/encoder/h264/encoder.c @@ -762,6 +762,9 @@ static void avc_buffspec_init(struct encode_wq_s *wq) wq->mem.buf_start + wq->mem.bufspec.cbr_info.buf_start; wq->mem.cbr_info_ddr_size = wq->mem.bufspec.cbr_info.buf_size; + wq->mem.cbr_info_ddr_virt_addr = + codec_mm_vmap(wq->mem.cbr_info_ddr_start_addr, + wq->mem.bufspec.cbr_info.buf_size); wq->mem.dblk_buf_canvas = ((ENC_CANVAS_OFFSET + 2) << 16) | @@ -1059,6 +1062,9 @@ static int scale_frame(struct encode_wq_s *wq, || (request->fmt == FMT_NV12)) { src_canvas = src_addr & 0xffff; input_format = GE2D_FORMAT_M24_NV21; + } else if (request->fmt == FMT_BGR888) { + src_canvas = src_addr & 0xffffff; + input_format = GE2D_FORMAT_S24_RGB; //Opposite color after ge2d } else { src_canvas = src_addr & 0xffffff; input_format = GE2D_FORMAT_M24_YUV420; @@ -1082,6 +1088,16 @@ static int scale_frame(struct encode_wq_s *wq, ((ENC_CANVAS_OFFSET + 10) << 8) | (ENC_CANVAS_OFFSET + 9); input_format = GE2D_FORMAT_M24_NV21; + } else if (request->fmt == FMT_BGR888) { + src_canvas_w = + ((request->src_w + 31) >> 5) << 5; + canvas_config(ENC_CANVAS_OFFSET + 9, + src_addr, + src_canvas_w * 3, src_h, + CANVAS_ADDR_NOWRAP, + CANVAS_BLKMODE_LINEAR); + src_canvas = ENC_CANVAS_OFFSET + 9; + input_format = GE2D_FORMAT_S24_RGB; //Opposite color after ge2d } else { src_canvas_w = ((request->src_w + 63) >> 6) << 6; @@ -1169,6 +1185,7 @@ static int scale_frame(struct encode_wq_s *wq, ge2d_config->dst_para.height = dst_h; ge2d_config->dst_para.x_rev = 0; ge2d_config->dst_para.y_rev = 0; + if (ge2d_context_config_ex(context, ge2d_config) < 0) { pr_err("++ge2d configing error.\n"); return -1; @@ -2401,7 +2418,11 @@ static s32 avc_poweron(u32 clock) /* Powerup HCODEC */ /* [1:0] HCODEC */ WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0, - (READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) & (~0x3))); + READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) & + ((get_cpu_type() == MESON_CPU_MAJOR_ID_SM1 || + get_cpu_type() >= MESON_CPU_MAJOR_ID_TM2) + ? ~0x1 : ~0x3)); + udelay(10); WRITE_VREG(DOS_SW_RESET1, 0xffffffff); @@ -2415,7 +2436,11 @@ static s32 avc_poweron(u32 clock) /* Remove HCODEC ISO */ WRITE_AOREG(AO_RTI_GEN_PWR_ISO0, - (READ_AOREG(AO_RTI_GEN_PWR_ISO0) & (~0x30))); + READ_AOREG(AO_RTI_GEN_PWR_ISO0) & + ((get_cpu_type() == MESON_CPU_MAJOR_ID_SM1 || + get_cpu_type() >= MESON_CPU_MAJOR_ID_TM2) + ? ~0x1 : ~0x30)); + udelay(10); /* Disable auto-clock gate */ WRITE_VREG(DOS_GEN_CTRL0, @@ -2437,7 +2462,11 @@ static s32 avc_poweroff(void) /* enable HCODEC isolation */ WRITE_AOREG(AO_RTI_GEN_PWR_ISO0, - READ_AOREG(AO_RTI_GEN_PWR_ISO0) | 0x30); + READ_AOREG(AO_RTI_GEN_PWR_ISO0) | + ((get_cpu_type() == MESON_CPU_MAJOR_ID_SM1 || + get_cpu_type() >= MESON_CPU_MAJOR_ID_TM2) + ? 0x1 : 0x30)); + /* power off HCODEC memories */ WRITE_VREG(DOS_MEM_PD_HCODEC, 0xffffffffUL); @@ -2446,7 +2475,10 @@ static s32 avc_poweroff(void) /* HCODEC power off */ WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0, - READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) | 0x3); + READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) | + ((get_cpu_type() == MESON_CPU_MAJOR_ID_SM1 || + get_cpu_type() >= MESON_CPU_MAJOR_ID_TM2) + ? 0x1 : 0x3)); spin_unlock_irqrestore(&lock, flags); @@ -3236,11 +3268,10 @@ static s32 encode_process_request(struct encode_manager_s *manager, if (request->cmd == ENCODER_IDR || request->cmd == ENCODER_NON_IDR) { if (request->flush_flag & AMVENC_FLUSH_FLAG_CBR && get_cpu_type() >= MESON_CPU_MAJOR_ID_GXTVBB) { - void *vaddr = - phys_to_virt(wq->mem.cbr_info_ddr_start_addr); + void *vaddr = wq->mem.cbr_info_ddr_virt_addr; ConvertTable2Risc(vaddr, 0xa00); buf_start = getbuffer(wq, ENCODER_BUFFER_CBR); - dma_flush(buf_start, wq->mem.cbr_info_ddr_size); + codec_mm_dma_flush(vaddr, wq->mem.cbr_info_ddr_size, DMA_TO_DEVICE); } } #endif @@ -3526,6 +3557,10 @@ s32 destroy_encode_work_queue(struct encode_wq_s *encode_work_queue) spin_unlock(&encode_manager.event.sem_lock); #ifdef CONFIG_CMA if (encode_work_queue->mem.buf_start) { + if (wq->mem.cbr_info_ddr_virt_addr != NULL) { + codec_mm_unmap_phyaddr(wq->mem.cbr_info_ddr_virt_addr); + wq->mem.cbr_info_ddr_virt_addr = NULL; + } codec_mm_free_for_dma( ENCODE_NAME, encode_work_queue->mem.buf_start); diff --git a/drivers/amlogic/media_modules/frame_sink/encoder/h264/encoder.h b/drivers/amlogic/media_modules/frame_sink/encoder/h264/encoder.h index 1c3ade4427d7..a5e0ceee1c12 100644 --- a/drivers/amlogic/media_modules/frame_sink/encoder/h264/encoder.h +++ b/drivers/amlogic/media_modules/frame_sink/encoder/h264/encoder.h @@ -149,6 +149,7 @@ enum amvenc_frame_fmt_e { FMT_YUV422_12BIT, FMT_YUV444_10BIT, FMT_YUV422_10BIT, + FMT_BGR888, MAX_FRAME_FMT }; @@ -259,6 +260,8 @@ struct encode_meminfo_s { u32 cbr_info_ddr_start_addr; u32 cbr_info_ddr_size; + u8 * cbr_info_ddr_virt_addr; + s32 dblk_buf_canvas; s32 ref_buf_canvas; struct BuffInfo_s bufspec; diff --git a/drivers/amlogic/media_modules/frame_sink/encoder/h265/vmm.h b/drivers/amlogic/media_modules/frame_sink/encoder/h265/vmm.h index 3c9c6d8734f8..a32dd06eb7ab 100644 --- a/drivers/amlogic/media_modules/frame_sink/encoder/h265/vmm.h +++ b/drivers/amlogic/media_modules/frame_sink/encoder/h265/vmm.h @@ -476,7 +476,7 @@ s32 vmem_init(struct video_mm_t *mm, ulong addr, ulong size) (struct page_t *)VMEM_P_ALLOC( mm->num_pages * sizeof(struct page_t)); if (mm->page_list == NULL) { - pr_err("%s:%d failed to kmalloc(%ld)\n", + pr_err("%s:%d failed to kmalloc(%zu)\n", __func__, __LINE__, mm->num_pages * sizeof(struct page_t)); return -1; diff --git a/drivers/amlogic/media_modules/frame_sink/encoder/h265/vpu.c b/drivers/amlogic/media_modules/frame_sink/encoder/h265/vpu.c index 3345b0a23e07..3180b4968a9e 100644 --- a/drivers/amlogic/media_modules/frame_sink/encoder/h265/vpu.c +++ b/drivers/amlogic/media_modules/frame_sink/encoder/h265/vpu.c @@ -154,8 +154,7 @@ static s32 vpu_alloc_dma_buffer(struct vpudrv_buffer_t *vb) return -1; } - vb->base = (ulong)(s_video_memory.base + - (vb->phys_addr - s_video_memory.phys_addr)); + enc_pr(LOG_INFO, "vpu_alloc_dma_buffer: vb->phys_addr 0x%lx \n",vb->phys_addr); return 0; } @@ -163,8 +162,9 @@ static void vpu_free_dma_buffer(struct vpudrv_buffer_t *vb) { if (!vb) return; + enc_pr(LOG_INFO, "vpu_free_dma_buffer 0x%lx\n",vb->phys_addr); - if (vb->base) + if (vb->phys_addr) vmem_free(&s_vmem, vb->phys_addr, 0); } @@ -211,7 +211,7 @@ static s32 vpu_free_buffers(struct file *filp) list_for_each_entry_safe(pool, n, &s_vbp_head, list) { if (pool->filp == filp) { vb = pool->vb; - if (vb.base) { + if (vb.phys_addr) { vpu_free_dma_buffer(&vb); list_del(&pool->list); kfree(pool); @@ -323,14 +323,8 @@ static s32 vpu_open(struct inode *inode, struct file *filp) s_video_memory.size = VPU_INIT_VIDEO_MEMORY_SIZE_IN_BYTE; s_video_memory.phys_addr = (ulong)codec_mm_alloc_for_dma(VPU_DEV_NAME, - VPU_INIT_VIDEO_MEMORY_SIZE_IN_BYTE >> PAGE_SHIFT, 0, - CODEC_MM_FLAGS_CPU); - if (s_video_memory.phys_addr) - s_video_memory.base = - (ulong)phys_to_virt(s_video_memory.phys_addr); - else - s_video_memory.base = 0; - if (s_video_memory.base) { + VPU_INIT_VIDEO_MEMORY_SIZE_IN_BYTE >> PAGE_SHIFT, 0, 0); + if (s_video_memory.phys_addr) { enc_pr(LOG_DEBUG, "allocating phys 0x%lx, virt addr 0x%lx, size %dk\n", s_video_memory.phys_addr, @@ -366,7 +360,7 @@ static s32 vpu_open(struct inode *inode, struct file *filp) "No CMA and reserved memory for HevcEnc!!!\n"); r = -ENOMEM; #endif - } else if (!s_video_memory.base) { + } else if (!s_video_memory.phys_addr) { enc_pr(LOG_ERROR, "HevcEnc memory is not malloced!!!\n"); r = -ENOMEM; @@ -383,6 +377,7 @@ static s32 vpu_open(struct inode *inode, struct file *filp) if (err) { enc_pr(LOG_ERROR, "fail to register interrupt handler\n"); + s_vpu_drv_context.open_count--; return -EFAULT; } s_vpu_irq_requested = true; @@ -390,7 +385,9 @@ static s32 vpu_open(struct inode *inode, struct file *filp) amports_switch_gate("vdec", 1); spin_lock_irqsave(&s_vpu_lock, flags); WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0, - READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) & ~(0x3<<24)); + READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) & + (get_cpu_type() == MESON_CPU_MAJOR_ID_SM1 + ? ~0x8 : ~(0x3<<24))); udelay(10); if (get_cpu_type() <= MESON_CPU_MAJOR_ID_TXLX) { @@ -423,12 +420,16 @@ static s32 vpu_open(struct inode *inode, struct file *filp) WRITE_VREG(DOS_MEM_PD_WAVE420L, 0x0); WRITE_AOREG(AO_RTI_GEN_PWR_ISO0, - READ_AOREG(AO_RTI_GEN_PWR_ISO0) & ~(0x3<<12)); + READ_AOREG(AO_RTI_GEN_PWR_ISO0) & + (get_cpu_type() == MESON_CPU_MAJOR_ID_SM1 + ? ~0x8 : ~(0x3<<12))); udelay(10); spin_unlock_irqrestore(&s_vpu_lock, flags); } Err: + if (r != 0) + s_vpu_drv_context.open_count--; enc_pr(LOG_DEBUG, "[-] %s, ret: %d\n", __func__, r); return r; } @@ -491,6 +492,7 @@ static long vpu_ioctl(struct file *filp, u32 cmd, ulong arg) "[-]VDI_IOCTL_ALLOCATE_PHYSICAL_MEMORY\n"); } break; +#ifdef CONFIG_COMPAT case VDI_IOCTL_ALLOCATE_PHYSICAL_MEMORY32: { struct vpudrv_buffer_pool_t *vbp; @@ -519,8 +521,6 @@ static long vpu_ioctl(struct file *filp, u32 cmd, ulong arg) vbp->vb.cached = buf32.cached; vbp->vb.phys_addr = (ulong)buf32.phys_addr; - vbp->vb.base = - (ulong)buf32.base; vbp->vb.virt_addr = (ulong)buf32.virt_addr; ret = vpu_alloc_dma_buffer(&(vbp->vb)); @@ -534,8 +534,6 @@ static long vpu_ioctl(struct file *filp, u32 cmd, ulong arg) buf32.size = vbp->vb.size; buf32.phys_addr = (compat_ulong_t)vbp->vb.phys_addr; - buf32.base = - (compat_ulong_t)vbp->vb.base; buf32.virt_addr = (compat_ulong_t)vbp->vb.virt_addr; @@ -560,6 +558,7 @@ static long vpu_ioctl(struct file *filp, u32 cmd, ulong arg) "[-]VDI_IOCTL_ALLOCATE_PHYSICAL_MEMORY32\n"); } break; +#endif case VDI_IOCTL_FREE_PHYSICALMEMORY: { struct vpudrv_buffer_pool_t *vbp, *n; @@ -577,25 +576,27 @@ static long vpu_ioctl(struct file *filp, u32 cmd, ulong arg) return -EACCES; } - if (vb.base) + if (vb.phys_addr) vpu_free_dma_buffer(&vb); spin_lock(&s_vpu_lock); list_for_each_entry_safe(vbp, n, &s_vbp_head, list) { - if (vbp->vb.base == vb.base) { + if (vbp->vb.phys_addr == vb.phys_addr) { list_del(&vbp->list); kfree(vbp); break; } } spin_unlock(&s_vpu_lock); + up(&s_vpu_sem); } enc_pr(LOG_ALL, "[-]VDI_IOCTL_FREE_PHYSICALMEMORY\n"); } break; +#ifdef CONFIG_COMPAT case VDI_IOCTL_FREE_PHYSICALMEMORY32: { struct vpudrv_buffer_pool_t *vbp, *n; @@ -617,12 +618,10 @@ static long vpu_ioctl(struct file *filp, u32 cmd, ulong arg) vb.size = buf32.size; vb.phys_addr = (ulong)buf32.phys_addr; - vb.base = - (ulong)buf32.base; vb.virt_addr = (ulong)buf32.virt_addr; - if (vb.base) + if (vb.phys_addr) vpu_free_dma_buffer(&vb); spin_lock(&s_vpu_lock); @@ -642,11 +641,12 @@ static long vpu_ioctl(struct file *filp, u32 cmd, ulong arg) "[-]VDI_IOCTL_FREE_PHYSICALMEMORY32\n"); } break; +#endif case VDI_IOCTL_GET_RESERVED_VIDEO_MEMORY_INFO: { enc_pr(LOG_ALL, "[+]VDI_IOCTL_GET_RESERVED_VIDEO_MEMORY_INFO\n"); - if (s_video_memory.base != 0) { + if (s_video_memory.phys_addr != 0) { ret = copy_to_user((void __user *)arg, &s_video_memory, sizeof(struct vpudrv_buffer_t)); @@ -659,6 +659,7 @@ static long vpu_ioctl(struct file *filp, u32 cmd, ulong arg) "[-]VDI_IOCTL_GET_RESERVED_VIDEO_MEMORY_INFO\n"); } break; +#ifdef CONFIG_COMPAT case VDI_IOCTL_GET_RESERVED_VIDEO_MEMORY_INFO32: { struct compat_vpudrv_buffer_t buf32; @@ -669,11 +670,9 @@ static long vpu_ioctl(struct file *filp, u32 cmd, ulong arg) buf32.size = s_video_memory.size; buf32.phys_addr = (compat_ulong_t)s_video_memory.phys_addr; - buf32.base = - (compat_ulong_t)s_video_memory.base; buf32.virt_addr = (compat_ulong_t)s_video_memory.virt_addr; - if (s_video_memory.base != 0) { + if (s_video_memory.phys_addr != 0) { ret = copy_to_user((void __user *)arg, &buf32, sizeof(struct compat_vpudrv_buffer_t)); @@ -686,6 +685,7 @@ static long vpu_ioctl(struct file *filp, u32 cmd, ulong arg) "[-]VDI_IOCTL_GET_RESERVED_VIDEO_MEMORY_INFO32\n"); } break; +#endif case VDI_IOCTL_WAIT_INTERRUPT: { struct vpudrv_intr_info_t info; @@ -706,6 +706,9 @@ static long vpu_ioctl(struct file *filp, u32 cmd, ulong arg) ret = -ETIME; break; } + enc_pr(LOG_INFO, + "s_interrupt_flag(%d), reason(0x%08lx)\n", + s_interrupt_flag, dev->interrupt_reason); if (dev->interrupt_reason & (1 << W4_INT_ENC_PIC)) { u32 start, end, size, core = 0; @@ -804,6 +807,7 @@ static long vpu_ioctl(struct file *filp, u32 cmd, ulong arg) "[-]VDI_IOCTL_GET_INSTANCE_POOL\n"); } break; +#ifdef CONFIG_COMPAT case VDI_IOCTL_GET_INSTANCE_POOL32: { struct compat_vpudrv_buffer_t buf32; @@ -818,9 +822,6 @@ static long vpu_ioctl(struct file *filp, u32 cmd, ulong arg) buf32.phys_addr = (compat_ulong_t) s_instance_pool.phys_addr; - buf32.base = - (compat_ulong_t) - s_instance_pool.base; buf32.virt_addr = (compat_ulong_t) s_instance_pool.virt_addr; @@ -875,11 +876,12 @@ static long vpu_ioctl(struct file *filp, u32 cmd, ulong arg) "[-]VDI_IOCTL_GET_INSTANCE_POOL32\n"); } break; +#endif case VDI_IOCTL_GET_COMMON_MEMORY: { enc_pr(LOG_ALL, "[+]VDI_IOCTL_GET_COMMON_MEMORY\n"); - if (s_common_memory.base != 0) { + if (s_common_memory.phys_addr != 0) { ret = copy_to_user((void __user *)arg, &s_common_memory, sizeof(struct vpudrv_buffer_t)); @@ -907,6 +909,7 @@ static long vpu_ioctl(struct file *filp, u32 cmd, ulong arg) "[-]VDI_IOCTL_GET_COMMON_MEMORY\n"); } break; +#ifdef CONFIG_COMPAT case VDI_IOCTL_GET_COMMON_MEMORY32: { struct compat_vpudrv_buffer_t buf32; @@ -918,13 +921,10 @@ static long vpu_ioctl(struct file *filp, u32 cmd, ulong arg) buf32.phys_addr = (compat_ulong_t) s_common_memory.phys_addr; - buf32.base = - (compat_ulong_t) - s_common_memory.base; buf32.virt_addr = (compat_ulong_t) s_common_memory.virt_addr; - if (s_common_memory.base != 0) { + if (s_common_memory.phys_addr != 0) { ret = copy_to_user((void __user *)arg, &buf32, sizeof(struct compat_vpudrv_buffer_t)); @@ -946,9 +946,6 @@ static long vpu_ioctl(struct file *filp, u32 cmd, ulong arg) buf32.phys_addr = (compat_ulong_t) s_common_memory.phys_addr; - buf32.base = - (compat_ulong_t) - s_common_memory.base; buf32.virt_addr = (compat_ulong_t) s_common_memory.virt_addr; @@ -965,6 +962,7 @@ static long vpu_ioctl(struct file *filp, u32 cmd, ulong arg) "[-]VDI_IOCTL_GET_COMMON_MEMORY32\n"); } break; +#endif case VDI_IOCTL_OPEN_INSTANCE: { struct vpudrv_inst_info_t inst_info; @@ -1133,6 +1131,7 @@ static long vpu_ioctl(struct file *filp, u32 cmd, ulong arg) s_vpu_register.size); } break; +#ifdef CONFIG_COMPAT case VDI_IOCTL_GET_REGISTER_INFO32: { struct compat_vpudrv_buffer_t buf32; @@ -1144,9 +1143,6 @@ static long vpu_ioctl(struct file *filp, u32 cmd, ulong arg) buf32.phys_addr = (compat_ulong_t) s_vpu_register.phys_addr; - buf32.base = - (compat_ulong_t) - s_vpu_register.base; buf32.virt_addr = (compat_ulong_t) s_vpu_register.virt_addr; @@ -1207,6 +1203,7 @@ static long vpu_ioctl(struct file *filp, u32 cmd, ulong arg) "[-]VDI_IOCTL_FLUSH_BUFFER32\n"); } break; +#endif case VDI_IOCTL_FLUSH_BUFFER: { struct vpudrv_buffer_pool_t *pool, *n; @@ -1248,6 +1245,7 @@ static long vpu_ioctl(struct file *filp, u32 cmd, ulong arg) { enc_pr(LOG_ERROR, "No such IOCTL, cmd is %d\n", cmd); + ret = -EFAULT; } break; } @@ -1341,18 +1339,24 @@ static s32 vpu_release(struct inode *inode, struct file *filp) vpu_free_instances(filp); s_vpu_drv_context.open_count--; if (s_vpu_drv_context.open_count == 0) { + enc_pr(LOG_INFO, + "vpu_release: s_interrupt_flag(%d), reason(0x%08lx)\n", + s_interrupt_flag, s_vpu_drv_context.interrupt_reason); + s_vpu_drv_context.interrupt_reason = 0; + s_interrupt_flag = 0; if (s_instance_pool.base) { enc_pr(LOG_DEBUG, "free instance pool\n"); vfree((const void *)s_instance_pool.base); s_instance_pool.base = 0; } - if (s_common_memory.base) { - enc_pr(LOG_DEBUG, "free common memory\n"); + if (s_common_memory.phys_addr) { + enc_pr(LOG_INFO, "vpu_release, s_common_memory 0x%lx\n",s_common_memory.phys_addr); vpu_free_dma_buffer(&s_common_memory); - s_common_memory.base = 0; + s_common_memory.phys_addr = 0; } - if (s_video_memory.base && !use_reserve) { + if (s_video_memory.phys_addr && !use_reserve) { + enc_pr(LOG_DEBUG, "vpu_release, s_video_memory 0x%lx\n",s_video_memory.phys_addr); codec_mm_free_for_dma( VPU_DEV_NAME, (u32)s_video_memory.phys_addr); @@ -1368,7 +1372,9 @@ static s32 vpu_release(struct inode *inode, struct file *filp) } spin_lock_irqsave(&s_vpu_lock, flags); WRITE_AOREG(AO_RTI_GEN_PWR_ISO0, - READ_AOREG(AO_RTI_GEN_PWR_ISO0) | (0x3<<12)); + READ_AOREG(AO_RTI_GEN_PWR_ISO0) | + (get_cpu_type() == MESON_CPU_MAJOR_ID_SM1 + ? 0x8 : (0x3<<12))); udelay(10); WRITE_VREG(DOS_MEM_PD_WAVE420L, 0xffffffff); @@ -1376,7 +1382,9 @@ static s32 vpu_release(struct inode *inode, struct file *filp) vpu_clk_config(0); #endif WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0, - READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) | (0x3<<24)); + READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) | + (get_cpu_type() == MESON_CPU_MAJOR_ID_SM1 + ? 0x8 : (0x3<<24))); udelay(10); spin_unlock_irqrestore(&s_vpu_lock, flags); amports_switch_gate("vdec", 0); @@ -1563,18 +1571,8 @@ static s32 hevc_mem_device_init( r = 0; s_video_memory.size = rmem->size; s_video_memory.phys_addr = (ulong)rmem->base; - s_video_memory.base = - (ulong)phys_to_virt(s_video_memory.phys_addr); - if (!s_video_memory.base) { - enc_pr(LOG_ERROR, "fail to remap video memory "); - enc_pr(LOG_ERROR, - "physical phys_addr=0x%lx, base=0x%lx, size=0x%x\n", - (ulong)s_video_memory.phys_addr, - (ulong)s_video_memory.base, - (u32)s_video_memory.size); - s_video_memory.phys_addr = 0; - r = -EFAULT; - } + enc_pr(LOG_DEBUG, "hevc_mem_device_init %d, 0x%lx\n ",s_video_memory.size,s_video_memory.phys_addr); + return r; } @@ -1741,7 +1739,7 @@ ERROR_PROVE_DEVICE: memset(&s_vpu_register, 0, sizeof(struct vpudrv_buffer_t)); } - if (s_video_memory.base) { + if (s_video_memory.phys_addr) { vmem_exit(&s_vmem); memset(&s_video_memory, 0, sizeof(struct vpudrv_buffer_t)); memset(&s_vmem, 0, sizeof(struct video_mm_t)); @@ -1769,16 +1767,17 @@ static s32 vpu_remove(struct platform_device *pdev) s_instance_pool.base = 0; } - if (s_common_memory.base) { + if (s_common_memory.phys_addr) { vpu_free_dma_buffer(&s_common_memory); - s_common_memory.base = 0; + s_common_memory.phys_addr = 0; } - if (s_video_memory.base) { - if (!use_reserve) + if (s_video_memory.phys_addr) { + if (!use_reserve) { codec_mm_free_for_dma( VPU_DEV_NAME, (u32)s_video_memory.phys_addr); + } vmem_exit(&s_vmem); memset(&s_video_memory, 0, sizeof(struct vpudrv_buffer_t)); @@ -1880,72 +1879,73 @@ static s32 vpu_resume(struct platform_device *pdev) enc_pr(LOG_DEBUG, "vpu_resume\n"); vpu_clk_config(1); - - for (core = 0; core < MAX_NUM_VPU_CORE; core++) { - if (s_bit_firmware_info[core].size == 0) - continue; - code_base = s_common_memory.phys_addr; - /* ALIGN TO 4KB */ - code_size = (s_common_memory.size & ~0xfff); - if (code_size < s_bit_firmware_info[core].size * 2) - goto DONE_WAKEUP; - - /*---- LOAD BOOT CODE */ - for (i = 0; i < 512; i += 2) { - val = s_bit_firmware_info[core].bit_code[i]; - val |= (s_bit_firmware_info[core].bit_code[i+1] << 16); - WriteVpu(code_base+(i*2), val); - } - - regVal = 0; - WriteVpuRegister(W4_PO_CONF, regVal); - - /* Reset All blocks */ - regVal = 0x7ffffff; - WriteVpuRegister(W4_VPU_RESET_REQ, regVal); - - /* Waiting reset done */ - while (ReadVpuRegister(W4_VPU_RESET_STATUS)) { - if (time_after(jiffies, timeout)) + if (s_vpu_open_ref_count > 0) { + for (core = 0; core < MAX_NUM_VPU_CORE; core++) { + if (s_bit_firmware_info[core].size == 0) + continue; + code_base = s_common_memory.phys_addr; + /* ALIGN TO 4KB */ + code_size = (s_common_memory.size & ~0xfff); + if (code_size < s_bit_firmware_info[core].size * 2) goto DONE_WAKEUP; - } - WriteVpuRegister(W4_VPU_RESET_REQ, 0); + /*---- LOAD BOOT CODE */ + for (i = 0; i < 512; i += 2) { + val = s_bit_firmware_info[core].bit_code[i]; + val |= (s_bit_firmware_info[core].bit_code[i+1] << 16); + WriteVpu(code_base+(i*2), val); + } - /* remap page size */ - remap_size = (code_size >> 12) & 0x1ff; - regVal = 0x80000000 | (W4_REMAP_CODE_INDEX<<12) - | (0 << 16) | (1<<11) | remap_size; - WriteVpuRegister(W4_VPU_REMAP_CTRL, regVal); - /* DO NOT CHANGE! */ - WriteVpuRegister(W4_VPU_REMAP_VADDR, 0x00000000); - WriteVpuRegister(W4_VPU_REMAP_PADDR, code_base); - WriteVpuRegister(W4_ADDR_CODE_BASE, code_base); - WriteVpuRegister(W4_CODE_SIZE, code_size); - WriteVpuRegister(W4_CODE_PARAM, 0); - WriteVpuRegister(W4_INIT_VPU_TIME_OUT_CNT, timeout); - WriteVpuRegister(W4_HW_OPTION, hwOption); + regVal = 0; + WriteVpuRegister(W4_PO_CONF, regVal); - /* Interrupt */ - regVal = (1 << W4_INT_DEC_PIC_HDR); - regVal |= (1 << W4_INT_DEC_PIC); - regVal |= (1 << W4_INT_QUERY_DEC); - regVal |= (1 << W4_INT_SLEEP_VPU); - regVal |= (1 << W4_INT_BSBUF_EMPTY); - regVal = 0xfffffefe; - WriteVpuRegister(W4_VPU_VINT_ENABLE, regVal); - Wave4BitIssueCommand(core, W4_CMD_INIT_VPU); - WriteVpuRegister(W4_VPU_REMAP_CORE_START, 1); - while (ReadVpuRegister(W4_VPU_BUSY_STATUS)) { - if (time_after(jiffies, timeout)) + /* Reset All blocks */ + regVal = 0x7ffffff; + WriteVpuRegister(W4_VPU_RESET_REQ, regVal); + + /* Waiting reset done */ + while (ReadVpuRegister(W4_VPU_RESET_STATUS)) { + if (time_after(jiffies, timeout)) + goto DONE_WAKEUP; + } + + WriteVpuRegister(W4_VPU_RESET_REQ, 0); + + /* remap page size */ + remap_size = (code_size >> 12) & 0x1ff; + regVal = 0x80000000 | (W4_REMAP_CODE_INDEX<<12) + | (0 << 16) | (1<<11) | remap_size; + WriteVpuRegister(W4_VPU_REMAP_CTRL, regVal); + /* DO NOT CHANGE! */ + WriteVpuRegister(W4_VPU_REMAP_VADDR, 0x00000000); + WriteVpuRegister(W4_VPU_REMAP_PADDR, code_base); + WriteVpuRegister(W4_ADDR_CODE_BASE, code_base); + WriteVpuRegister(W4_CODE_SIZE, code_size); + WriteVpuRegister(W4_CODE_PARAM, 0); + WriteVpuRegister(W4_INIT_VPU_TIME_OUT_CNT, timeout); + WriteVpuRegister(W4_HW_OPTION, hwOption); + + /* Interrupt */ + regVal = (1 << W4_INT_DEC_PIC_HDR); + regVal |= (1 << W4_INT_DEC_PIC); + regVal |= (1 << W4_INT_QUERY_DEC); + regVal |= (1 << W4_INT_SLEEP_VPU); + regVal |= (1 << W4_INT_BSBUF_EMPTY); + regVal = 0xfffffefe; + WriteVpuRegister(W4_VPU_VINT_ENABLE, regVal); + Wave4BitIssueCommand(core, W4_CMD_INIT_VPU); + WriteVpuRegister(W4_VPU_REMAP_CORE_START, 1); + while (ReadVpuRegister(W4_VPU_BUSY_STATUS)) { + if (time_after(jiffies, timeout)) + goto DONE_WAKEUP; + } + + if (ReadVpuRegister(W4_RET_SUCCESS) == 0) { + enc_pr(LOG_ERROR, + "WAKEUP_VPU failed [0x%x]", + ReadVpuRegister(W4_RET_FAIL_REASON)); goto DONE_WAKEUP; - } - - if (ReadVpuRegister(W4_RET_SUCCESS) == 0) { - enc_pr(LOG_ERROR, - "WAKEUP_VPU failed [0x%x]", - ReadVpuRegister(W4_RET_FAIL_REASON)); - goto DONE_WAKEUP; + } } } @@ -1988,7 +1988,8 @@ static s32 __init vpu_init(void) if ((get_cpu_type() != MESON_CPU_MAJOR_ID_GXM) && (get_cpu_type() != MESON_CPU_MAJOR_ID_G12A) && (get_cpu_type() != MESON_CPU_MAJOR_ID_GXLX) - && (get_cpu_type() != MESON_CPU_MAJOR_ID_G12B)) { + && (get_cpu_type() != MESON_CPU_MAJOR_ID_G12B) + && (get_cpu_type() != MESON_CPU_MAJOR_ID_SM1)) { enc_pr(LOG_DEBUG, "The chip is not support hevc encoder\n"); return -1; @@ -2010,8 +2011,16 @@ static s32 __init vpu_init(void) static void __exit vpu_exit(void) { enc_pr(LOG_DEBUG, "vpu_exit\n"); - if (get_cpu_type() == MESON_CPU_MAJOR_ID_GXM) - platform_driver_unregister(&vpu_driver); + if ((get_cpu_type() != MESON_CPU_MAJOR_ID_GXM) && + (get_cpu_type() != MESON_CPU_MAJOR_ID_G12A) && + (get_cpu_type() != MESON_CPU_MAJOR_ID_GXLX) && + (get_cpu_type() != MESON_CPU_MAJOR_ID_G12B) && + (get_cpu_type() != MESON_CPU_MAJOR_ID_SM1)) { + enc_pr(LOG_INFO, + "The chip is not support hevc encoder\n"); + return; + } + platform_driver_unregister(&vpu_driver); } static const struct reserved_mem_ops rmem_hevc_ops = { diff --git a/drivers/amlogic/media_modules/frame_sink/encoder/h265/vpu.h b/drivers/amlogic/media_modules/frame_sink/encoder/h265/vpu.h index 9c29a430f4e0..eaf764c1c4b3 100644 --- a/drivers/amlogic/media_modules/frame_sink/encoder/h265/vpu.h +++ b/drivers/amlogic/media_modules/frame_sink/encoder/h265/vpu.h @@ -101,6 +101,7 @@ READ_HHI_REG(HHI_WAVE420L_CLK_CNTL2) \ & (~(1 << 8))) +#ifdef CONFIG_COMPAT struct compat_vpudrv_buffer_t { u32 size; u32 cached; @@ -108,6 +109,7 @@ struct compat_vpudrv_buffer_t { compat_ulong_t base; /* kernel logical address in use kernel */ compat_ulong_t virt_addr; /* virtual user space address */ }; +#endif struct vpudrv_buffer_t { u32 size; @@ -204,6 +206,7 @@ struct vpudrv_instance_pool_t { #define VDI_IOCTL_FLUSH_BUFFER \ _IOW(VDI_MAGIC, 13, VPUDRV_BUF_LEN) +#ifdef CONFIG_COMPAT #define VDI_IOCTL_ALLOCATE_PHYSICAL_MEMORY32 \ _IOW(VDI_MAGIC, 0, VPUDRV_BUF_LEN32) @@ -224,6 +227,7 @@ struct vpudrv_instance_pool_t { #define VDI_IOCTL_FLUSH_BUFFER32 \ _IOW(VDI_MAGIC, 13, VPUDRV_BUF_LEN32) +#endif enum { W4_INT_INIT_VPU = 0, diff --git a/drivers/amlogic/media_modules/stream_input/Makefile b/drivers/amlogic/media_modules/stream_input/Makefile index fdc41621e46f..73dfd13058ab 100644 --- a/drivers/amlogic/media_modules/stream_input/Makefile +++ b/drivers/amlogic/media_modules/stream_input/Makefile @@ -1,7 +1,6 @@ obj-m += stream_input.o stream_input-objs += amports/amstream.o -stream_input-objs += amports/amstream_profile.o stream_input-objs += amports/adec.o stream_input-objs += parser/thread_rw.o stream_input-objs += parser/streambuf.o @@ -9,9 +8,10 @@ stream_input-objs += parser/esparser.o stream_input-objs += parser/tsdemux.o stream_input-objs += parser/psparser.o stream_input-objs += parser/rmparser.o +stream_input-objs += subtitle/subtitle.o -obj-y += parser/hw_demux/ -obj-y += tv_frontend/ +obj-$(CONFIG_AMLOGIC_DVB) += parser/hw_demux/ +#obj-y += tv_frontend/ # obj-y += box-frontend/avl6211/ # obj-y += box-frontend/atbm8881/ -# obj-y += box-frontend/avl68xx/ \ No newline at end of file +# obj-y += box-frontend/avl68xx/ diff --git a/drivers/amlogic/media_modules/stream_input/amports/Makefile b/drivers/amlogic/media_modules/stream_input/amports/Makefile index 55fbdce8aa7a..82f5934b5f9b 100644 --- a/drivers/amlogic/media_modules/stream_input/amports/Makefile +++ b/drivers/amlogic/media_modules/stream_input/amports/Makefile @@ -1,2 +1,2 @@ obj-y += amports.o -amports-objs += amstream.o amstream_profile.o adec.o +amports-objs += amstream.o adec.o diff --git a/drivers/amlogic/media_modules/stream_input/amports/adec.c b/drivers/amlogic/media_modules/stream_input/amports/adec.c index b1bd0726fad8..5bca205c4262 100644 --- a/drivers/amlogic/media_modules/stream_input/amports/adec.c +++ b/drivers/amlogic/media_modules/stream_input/amports/adec.c @@ -29,7 +29,7 @@ #include #include #include "amports_priv.h" - +#include "../../common/chips/decoder_cpu_ver_info.h" #define INFO_VALID ((astream_dev) && (astream_dev->format)) struct astream_device_s { @@ -121,13 +121,14 @@ static ssize_t datawidth_show(struct class *class, static ssize_t pts_show(struct class *class, struct class_attribute *attr, char *buf) { - u32 pts; + u32 pts, frame_size; u32 pts_margin = 0; if (astream_dev->samplerate <= 12000) pts_margin = 512; - if (INFO_VALID && (pts_lookup(PTS_TYPE_AUDIO, &pts, pts_margin) >= 0)) + if (INFO_VALID && (pts_lookup(PTS_TYPE_AUDIO, &pts, + &frame_size, pts_margin) >= 0)) return sprintf(buf, "0x%x\n", pts); else return sprintf(buf, "%s\n", na_string); @@ -155,9 +156,13 @@ static struct class astream_class = { }; #if 1 -#define IO_CBUS_PHY_BASE 0xc1100000 +#define IO_CBUS_PHY_BASE 0xc1100000ULL +#define IO_AOBUS_PHY_BASE 0xc8100000ULL #define CBUS_REG_OFFSET(reg) ((reg) << 2) -#define IO_SECBUS_PHY_BASE 0xda000000 +#define IO_SECBUS_PHY_BASE 0xda000000ULL + + +#define IO_AOBUS_PHY_BASE_AFTER_G12A 0xff800000ULL static struct uio_info astream_uio_info = { .name = "astream_uio", @@ -179,13 +184,15 @@ static struct uio_info astream_uio_info = { (IO_CBUS_PHY_BASE + CBUS_REG_OFFSET(VCOP_CTRL_REG)), .size = PAGE_SIZE, }, +/* [2] = { .name = "SECBUS", .memtype = UIO_MEM_PHYS, .addr = (IO_SECBUS_PHY_BASE), .size = PAGE_SIZE, }, - [3] = { +*/ + [2] = { .name = "CBUS", .memtype = UIO_MEM_PHYS, .addr = @@ -193,11 +200,17 @@ static struct uio_info astream_uio_info = { &(PAGE_MASK), .size = PAGE_SIZE, }, - [4] = { + [3] = { .name = "CBUS-START", .memtype = UIO_MEM_PHYS, .addr = (IO_CBUS_PHY_BASE + CBUS_REG_OFFSET(0x1000)), - .size = PAGE_SIZE * 4, + .size = PAGE_SIZE, + }, + [4] = { + .name = "AOBUS-START", + .memtype = UIO_MEM_PHYS, + .addr = (IO_AOBUS_PHY_BASE), + .size = PAGE_SIZE, }, }, }; @@ -224,12 +237,13 @@ s32 adec_init(struct stream_port_s *port) astream_dev->datawidth = port->adatawidth; /*wmb();don't need it...*/ - if (af <= ARRAY_SIZE(astream_format)) + if (af < ARRAY_SIZE(astream_format)) astream_dev->format = astream_format[af]; else astream_dev->format = NULL; return 0; } +EXPORT_SYMBOL(adec_init); s32 adec_release(enum aformat_e vf) { @@ -242,13 +256,14 @@ s32 adec_release(enum aformat_e vf) return 0; } +EXPORT_SYMBOL(adec_release); int amstream_adec_show_fun(const char *trigger, int id, char *sbuf, int size) { int ret = -1; void *buf, *getbuf = NULL; if (size < PAGE_SIZE) { - void *getbuf = (void *)__get_free_page(GFP_KERNEL); + getbuf = (void *)__get_free_page(GFP_KERNEL); if (!getbuf) return -ENOMEM; buf = getbuf; @@ -275,7 +290,7 @@ int amstream_adec_show_fun(const char *trigger, int id, char *sbuf, int size) ret = -1; } if (ret > 0 && getbuf != NULL) { - int ret = min_t(int, ret, size); + ret = min_t(int, ret, size); strncpy(sbuf, buf, ret); } if (getbuf != NULL) @@ -326,14 +341,18 @@ s32 astream_dev_register(void) goto err_2; } - if (MESON_CPU_MAJOR_ID_TXL < get_cpu_type()) { + if (AM_MESON_CPU_MAJOR_ID_TXL < get_cpu_major_id()) { node = of_find_node_by_path("/codec_io/io_cbus_base"); if (!node) { pr_info("No io_cbus_base node found."); goto err_1; } +#ifdef CONFIG_ARM64_A32 + r = of_property_read_u32_index(node, "reg", 0, &cbus_base); +#else r = of_property_read_u32_index(node, "reg", 1, &cbus_base); +#endif if (r) { pr_info("No find node.\n"); goto err_1; @@ -343,9 +362,11 @@ s32 astream_dev_register(void) astream_dev->offset = -0x100; /*need to offset -0x180 in g12a.*/ - if (MESON_CPU_MAJOR_ID_G12A <= get_cpu_type()) + if (AM_MESON_CPU_MAJOR_ID_G12A <= get_cpu_major_id()) { astream_dev->offset = -0x180; - + /* after G12A chip, the aobus base addr changed */ + astream_uio_info.mem[4].addr = IO_AOBUS_PHY_BASE_AFTER_G12A; + } astream_uio_info.mem[0].addr = (cbus_base + CBUS_REG_OFFSET(AIU_AIFIFO_CTRL + astream_dev->offset)) & (PAGE_MASK); diff --git a/drivers/amlogic/media_modules/stream_input/amports/amports_priv.h b/drivers/amlogic/media_modules/stream_input/amports/amports_priv.h index 53669a5951a9..b09118d19057 100644 --- a/drivers/amlogic/media_modules/stream_input/amports/amports_priv.h +++ b/drivers/amlogic/media_modules/stream_input/amports/amports_priv.h @@ -26,6 +26,7 @@ struct port_priv_s { struct vdec_s *vdec; struct stream_port_s *port; + struct mutex mutex; }; struct stream_buf_s *get_buf_by_type(u32 type); @@ -44,6 +45,7 @@ int amstream_request_firmware_from_sys(const char *file_name, void set_vsync_pts_inc_mode(int inc); void set_real_audio_info(void *arg); +void amstream_wakeup_userdata_poll(struct vdec_s *vdec); #define dbg() pr_info("on %s,line %d\n", __func__, __LINE__); struct device *amports_get_dma_device(void); diff --git a/drivers/amlogic/media_modules/stream_input/amports/amstream.c b/drivers/amlogic/media_modules/stream_input/amports/amstream.c index 6546633df359..32bc739289a7 100644 --- a/drivers/amlogic/media_modules/stream_input/amports/amstream.c +++ b/drivers/amlogic/media_modules/stream_input/amports/amstream.c @@ -79,6 +79,8 @@ #include #include "../../frame_provider/decoder/utils/firmware.h" #include "../../common/chips/chips.h" +#include "../../common/chips/decoder_cpu_ver_info.h" +#include "../subtitle/subtitle.h" //#define G12A_BRINGUP_DEBUG @@ -103,8 +105,8 @@ u32 amstream_audio_reset = 0; #endif #define NO_VDEC2_INIT 1 -#define DEFAULT_VIDEO_BUFFER_SIZE (1024 * 1024 * 3) -#define DEFAULT_VIDEO_BUFFER_SIZE_4K (1024 * 1024 * 6) +#define DEFAULT_VIDEO_BUFFER_SIZE (1024 * 1024 * 10) +#define DEFAULT_VIDEO_BUFFER_SIZE_4K (1024 * 1024 * 15) #define DEFAULT_VIDEO_BUFFER_SIZE_TVP (1024 * 1024 * 10) #define DEFAULT_VIDEO_BUFFER_SIZE_4K_TVP (1024 * 1024 * 15) @@ -321,6 +323,8 @@ static wait_queue_head_t amstream_userdata_wait; static struct userdata_poc_info_t userdata_poc_info[USERDATA_FIFO_NUM]; static int userdata_poc_ri, userdata_poc_wi; static int last_read_wi; +static u32 ud_ready_vdec_flag; + static DEFINE_MUTEX(userdata_mutex); @@ -520,6 +524,7 @@ static void amstream_change_vbufsize(struct port_priv_s *priv, pvbuf->buf_size = pvbuf->buf_size >> 1; } } else if (pvbuf->buf_size > def_vstreambuf_sizeM * SZ_1M) { + pvbuf->buf_size = def_vstreambuf_sizeM * SZ_1M; if (priv->vdec->port_flag & PORT_FLAG_DRM) pvbuf->buf_size = DEFAULT_VIDEO_BUFFER_SIZE_TVP; } else { @@ -600,17 +605,16 @@ static int video_port_init(struct port_priv_s *priv, pr_err("vformat not set\n"); return -EPERM; } - + if (vdec_dual(vdec) && vdec_secure(vdec)) { + /*copy drm flags for slave dec.*/ + vdec->slave->port_flag |= PORT_FLAG_DRM; + } if (port->vformat == VFORMAT_H264_4K2K || (priv->vdec->sys_info->height * priv->vdec->sys_info->width) > 1920*1088) { pbuf->for_4k = 1; - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_TXLX + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_TXLX && port->vformat == VFORMAT_H264) { - amports_switch_gate("clk_hevc_mux", 1); - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) - amports_switch_gate("clk_hevcb_mux", 1); - vdec_poweron(VDEC_HEVC); } } else { @@ -682,8 +686,6 @@ static int video_port_init(struct port_priv_s *priv, pbuf->flag |= BUF_FLAG_IN_USE; - vdec_connect(priv->vdec); - return 0; } @@ -875,7 +877,7 @@ static int amstream_port_init(struct port_priv_s *priv) mutex_lock(&amstream_mutex); - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) { + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A) { r = check_efuse_chip(port->vformat); if (r) { pr_info("No support video format %d.\n", port->vformat); @@ -916,11 +918,14 @@ static int amstream_port_init(struct port_priv_s *priv) port->vformat == VFORMAT_VP9) pvbuf = &bufs[BUF_TYPE_HEVC]; } + mutex_lock(&priv->mutex); r = video_port_init(priv, pvbuf); if (r < 0) { + mutex_unlock(&priv->mutex); pr_err("video_port_init failed\n"); goto error2; } + mutex_unlock(&priv->mutex); } if ((port->type & PORT_TYPE_SUB) && (port->flag & PORT_FLAG_SID)) { @@ -1025,6 +1030,7 @@ static int amstream_port_release(struct port_priv_s *priv) } if (port->type & PORT_TYPE_MPTS) { + vdec_disconnect(priv->vdec); tsync_pcr_stop(); tsdemux_release(); } @@ -1264,8 +1270,7 @@ static ssize_t amstream_sub_read(struct file *file, char __user *buf, res = copy_to_user((void *)buf, (void *)(codec_mm_phys_to_virt(sub_rp)), data_size); - if (res >= 0) - stbuf_sub_rp_set(sub_rp + data_size - res); + stbuf_sub_rp_set(sub_rp + data_size - res); return data_size - res; } else { @@ -1273,10 +1278,8 @@ static ssize_t amstream_sub_read(struct file *file, char __user *buf, res = copy_to_user((void *)buf, (void *)(codec_mm_phys_to_virt(sub_rp)), first_num); - if (res >= 0) { - stbuf_sub_rp_set(sub_rp + first_num - - res); - } + stbuf_sub_rp_set(sub_rp + first_num - + res); return first_num - res; } @@ -1285,10 +1288,8 @@ static ssize_t amstream_sub_read(struct file *file, char __user *buf, (void *)(codec_mm_phys_to_virt(sub_start)), data_size - first_num); - if (res >= 0) { - stbuf_sub_rp_set(sub_start + data_size - - first_num - res); - } + stbuf_sub_rp_set(sub_start + data_size - + first_num - res); return data_size - first_num - res; } @@ -1298,8 +1299,7 @@ static ssize_t amstream_sub_read(struct file *file, char __user *buf, (void *)(codec_mm_phys_to_virt(sub_rp)), data_size); - if (res >= 0) - stbuf_sub_rp_set(sub_rp + data_size - res); + stbuf_sub_rp_set(sub_rp + data_size - res); return data_size - res; } @@ -1414,6 +1414,28 @@ int wakeup_userdata_poll(struct userdata_poc_info_t poc, } EXPORT_SYMBOL(wakeup_userdata_poll); + +void amstream_wakeup_userdata_poll(struct vdec_s *vdec) +{ + int vdec_id; + + vdec_id = vdec->id; + if (vdec_id > 31) { + pr_info("Error, not support so many instances(%d) user data push\n", + vdec_id); + return; + } + + mutex_lock(&userdata_mutex); + ud_ready_vdec_flag |= (1<mutex); + priv->port = port; - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M6) { + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M6) { /* TODO: mod gate */ /* switch_mod_gate_by_name("demux", 1); */ amports_switch_gate("demux", 1); - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M8) { + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M8) { /* TODO: clc gate */ /* CLK_GATE_ON(HIU_PARSER_TOP); */ amports_switch_gate("parser_top", 1); @@ -1615,22 +1639,14 @@ static int amstream_open(struct inode *inode, struct file *file) if (has_hevc_vdec()) { if (port->type & - (PORT_TYPE_MPTS | PORT_TYPE_HEVC)) { - amports_switch_gate("clk_hevc_mux", 1); - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) - amports_switch_gate("clk_hevcb_mux", 1); + (PORT_TYPE_MPTS | PORT_TYPE_HEVC)) vdec_poweron(VDEC_HEVC); - } - if ((port->type & PORT_TYPE_HEVC) == 0) { - amports_switch_gate("clk_vdec_mux", 1); + if ((port->type & PORT_TYPE_HEVC) == 0) vdec_poweron(VDEC_1); - } } else { - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M8) { - amports_switch_gate("clk_vdec_mux", 1); + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M8) vdec_poweron(VDEC_1); - } } } @@ -1738,16 +1754,16 @@ static int amstream_release(struct inode *inode, struct file *file) debug_file_pos = 0; } #endif - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M6) { + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M6) { if (port->type & PORT_TYPE_VIDEO) { - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M8) { + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M8) { #ifndef CONFIG_AMLOGIC_MEDIA_MULTI_DEC if (has_hevc_vdec()) vdec_poweroff(VDEC_HEVC); vdec_poweroff(VDEC_1); #else - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_TXLX + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_TXLX && port->vformat == VFORMAT_H264 && bufs[BUF_TYPE_VIDEO].for_4k) vdec_poweroff(VDEC_HEVC); @@ -1772,7 +1788,7 @@ static int amstream_release(struct inode *inode, struct file *file) /* amports_switch_gate("audio", 0); */ } - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M8) { + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M8) { /* TODO: clc gate */ /* CLK_GATE_OFF(HIU_PARSER_TOP); */ amports_switch_gate("parser_top", 0); @@ -1782,6 +1798,8 @@ static int amstream_release(struct inode *inode, struct file *file) amports_switch_gate("demux", 0); } + mutex_destroy(&priv->mutex); + kfree(priv); mutex_unlock(&amstream_mutex); @@ -1839,10 +1857,11 @@ static long amstream_ioctl_get(struct port_priv_s *priv, ulong arg) break; case AMSTREAM_GET_APTS_LOOKUP: if (this->type & PORT_TYPE_AUDIO) { - u32 pts = 0, offset; + u32 pts = 0, frame_size, offset; offset = parm.data_32; - pts_lookup_offset(PTS_TYPE_AUDIO, offset, &pts, 300); + pts_lookup_offset(PTS_TYPE_AUDIO, offset, &pts, + &frame_size, 300); parm.data_32 = pts; } break; @@ -1935,6 +1954,9 @@ static long amstream_ioctl_get(struct port_priv_s *priv, ulong arg) case AMSTREAM_GET_NEED_MORE_DATA: parm.data_32 = vdec_need_more_data(priv->vdec); break; + case AMSTREAM_GET_FREED_HANDLE: + parm.data_32 = vdec_input_get_freed_handle(priv->vdec); + break; default: r = -ENOIOCTLCMD; break; @@ -1979,7 +2001,7 @@ static long amstream_ioctl_set(struct port_priv_s *priv, ulong arg) parm.data_32, false); } - r = stbuf_change_size( + r += stbuf_change_size( &bufs[BUF_TYPE_VIDEO], parm.data_32, false); @@ -2169,10 +2191,7 @@ static long amstream_ioctl_set(struct port_priv_s *priv, ulong arg) tsync_set_dec_reset(); break; case AMSTREAM_SET_TS_SKIPBYTE: - if (parm.data_32 >= 0) - tsdemux_set_skipbyte(parm.data_32); - else - r = -EINVAL; + tsdemux_set_skipbyte(parm.data_32); break; case AMSTREAM_SET_SUB_TYPE: sub_type = parm.data_32; @@ -2251,6 +2270,34 @@ static long amstream_ioctl_set(struct port_priv_s *priv, ulong arg) } return r; } + +static enum E_ASPECT_RATIO get_normalized_aspect_ratio(u32 ratio_control) +{ + enum E_ASPECT_RATIO euAspectRatio; + + ratio_control = ratio_control >> DISP_RATIO_ASPECT_RATIO_BIT; + + switch (ratio_control) { + case 0x8c: + case 0x90: + euAspectRatio = ASPECT_RATIO_16_9; + /*pr_info("ASPECT_RATIO_16_9\n");*/ + break; + case 0xbb: + case 0xc0: + euAspectRatio = ASPECT_RATIO_4_3; + /*pr_info("ASPECT_RATIO_4_3\n");*/ + break; + default: + euAspectRatio = ASPECT_UNDEFINED; + /*pr_info("ASPECT_UNDEFINED and ratio_control = 0x%x\n", + ratio_control);*/ + break; + } + + return euAspectRatio; +} + static long amstream_ioctl_get_ex(struct port_priv_s *priv, ulong arg) { struct stream_port_s *this = priv->port; @@ -2274,11 +2321,6 @@ static long amstream_ioctl_get_ex(struct port_priv_s *priv, ulong arg) &bufs[BUF_TYPE_HEVC] : &bufs[BUF_TYPE_VIDEO]; - if (p == NULL) { - r = -EINVAL; - break; - } - if (this->type & PORT_TYPE_FRAME) { struct vdec_input_status_s status; @@ -2315,8 +2357,6 @@ static long amstream_ioctl_get_ex(struct port_priv_s *priv, ulong arg) struct am_ioctl_parm_ex *p = &parm; struct stream_buf_s *buf = &bufs[BUF_TYPE_AUDIO]; - if (p == NULL) - r = -EINVAL; p->status.size = stbuf_canusesize(buf); p->status.data_len = stbuf_level(buf); @@ -2334,15 +2374,24 @@ static long amstream_ioctl_get_ex(struct port_priv_s *priv, ulong arg) struct vdec_info vstatus; struct am_ioctl_parm_ex *p = &parm; - if (p == NULL) - return -EINVAL; - if (vdec_status(priv->vdec, &vstatus) == -1) + memset(&vstatus, 0, sizeof(vstatus)); + + mutex_lock(&priv->mutex); + if (vdec_status(priv->vdec, &vstatus) == -1) { + mutex_unlock(&priv->mutex); return -ENODEV; + } + mutex_unlock(&priv->mutex); + p->vstatus.width = vstatus.frame_width; p->vstatus.height = vstatus.frame_height; p->vstatus.fps = vstatus.frame_rate; p->vstatus.error_count = vstatus.error_count; p->vstatus.status = vstatus.status; + p->vstatus.euAspectRatio = + get_normalized_aspect_ratio( + vstatus.ratio_control); + } break; case AMSTREAM_GET_EX_ADECSTAT: @@ -2360,8 +2409,6 @@ static long amstream_ioctl_get_ex(struct port_priv_s *priv, ulong arg) struct adec_status astatus; struct am_ioctl_parm_ex *p = &parm; - if (p == NULL) - return -EINVAL; amstream_adec_status(&astatus); p->astatus.channels = astatus.channels; p->astatus.sample_rate = astatus.sample_rate; @@ -2411,7 +2458,7 @@ static long amstream_ioctl_get_ptr(struct port_priv_s *priv, ulong arg) if (copy_from_user ((void *)&parm, (void *)arg, sizeof(parm))) - r = -EFAULT; + return -EFAULT; switch (parm.cmd) { case AMSTREAM_GET_PTR_SUB_INFO: @@ -2461,10 +2508,14 @@ static long amstream_ioctl_set_ptr(struct port_priv_s *priv, ulong arg) case AMSTREAM_SET_PTR_AUDIO_INFO: if ((this->type & PORT_TYPE_VIDEO) || (this->type & PORT_TYPE_AUDIO)) { - if (parm.pdata_audio_info != NULL) - memcpy((void *)&audio_dec_info, - (void *)parm.pdata_audio_info, - sizeof(audio_dec_info)); + if (parm.pdata_audio_info != NULL) { + if (copy_from_user + ((void *)&audio_dec_info, (void *)parm.pdata_audio_info, + sizeof(audio_dec_info))) { + pr_err("[%s]%d, arg err\n", __func__, __LINE__); + r = -EFAULT; + } + } } else r = -EINVAL; break; @@ -2525,6 +2576,20 @@ static long amstream_do_ioctl_new(struct port_priv_s *priv, else r = -EINVAL; break; + case AMSTREAM_IOC_GET_QOSINFO: + { + struct av_param_qosinfo_t __user *uarg = (void *)arg; + struct vframe_qos_s *qos_info = vdec_get_qos_info(); + if (this->type & PORT_TYPE_VIDEO) { + if (qos_info != NULL && copy_to_user((void *)uarg->vframe_qos, + qos_info, + QOS_FRAME_NUM*sizeof(struct vframe_qos_s))) { + r = -EFAULT; + break; + } + } + } + break; default: r = -ENOIOCTLCMD; break; @@ -2560,7 +2625,7 @@ static long amstream_do_ioctl_old(struct port_priv_s *priv, &bufs[BUF_TYPE_HEVC], arg, false); } - r = stbuf_change_size( + r += stbuf_change_size( &bufs[BUF_TYPE_VIDEO], arg, false); } @@ -2660,11 +2725,6 @@ static long amstream_do_ioctl_old(struct port_priv_s *priv, &bufs[BUF_TYPE_HEVC] : &bufs[BUF_TYPE_VIDEO]; - if (p == NULL) { - r = -EINVAL; - break; - } - if (this->type & PORT_TYPE_FRAME) { struct vdec_input_status_s status; @@ -2709,9 +2769,6 @@ static long amstream_do_ioctl_old(struct port_priv_s *priv, struct am_io_param *p = ¶ struct stream_buf_s *buf = &bufs[BUF_TYPE_AUDIO]; - if (p == NULL) - r = -EINVAL; - p->status.size = stbuf_canusesize(buf); p->status.data_len = stbuf_level(buf); p->status.free_len = stbuf_space(buf); @@ -2815,15 +2872,24 @@ static long amstream_do_ioctl_old(struct port_priv_s *priv, struct am_io_param para; struct am_io_param *p = ¶ - if (p == NULL) - return -EINVAL; - if (vdec_status(priv->vdec, &vstatus) == -1) + memset(&vstatus, 0, sizeof(vstatus)); + + mutex_lock(&priv->mutex); + if (vdec_status(priv->vdec, &vstatus) == -1) { + mutex_unlock(&priv->mutex); return -ENODEV; + } + mutex_unlock(&priv->mutex); + p->vstatus.width = vstatus.frame_width; p->vstatus.height = vstatus.frame_height; p->vstatus.fps = vstatus.frame_rate; p->vstatus.error_count = vstatus.error_count; p->vstatus.status = vstatus.status; + p->vstatus.euAspectRatio = + get_normalized_aspect_ratio( + vstatus.ratio_control); + if (copy_to_user((void *)arg, p, sizeof(para))) r = -EFAULT; return r; @@ -2836,8 +2902,15 @@ static long amstream_do_ioctl_old(struct port_priv_s *priv, struct vdec_info vinfo; struct am_io_info para; - if (vdec_status(priv->vdec, &vinfo) == -1) + memset(¶, 0x0, sizeof(struct am_io_info)); + + mutex_lock(&priv->mutex); + if (vdec_status(priv->vdec, &vinfo) == -1) { + mutex_unlock(&priv->mutex); return -ENODEV; + } + mutex_unlock(&priv->mutex); + memcpy(¶.vinfo, &vinfo, sizeof(struct vdec_info)); if (copy_to_user((void *)arg, ¶, sizeof(para))) r = -EFAULT; @@ -2854,8 +2927,6 @@ static long amstream_do_ioctl_old(struct port_priv_s *priv, struct am_io_param para; struct am_io_param *p = ¶ - if (p == NULL) - return -EINVAL; amstream_adec_status(&astatus); p->astatus.channels = astatus.channels; p->astatus.sample_rate = astatus.sample_rate; @@ -2993,10 +3064,72 @@ static long amstream_do_ioctl_old(struct port_priv_s *priv, } break; + case AMSTREAM_IOC_UD_BUF_READ: + { + if (this->type & PORT_TYPE_USERDATA) { + struct userdata_param_t param; + struct userdata_param_t *p_userdata_param; + struct vdec_s *vdec; + + p_userdata_param = ¶m; + + if (copy_from_user(p_userdata_param, + (void __user *)arg, + sizeof(struct userdata_param_t))) { + r = -EFAULT; + break; + } + + vdec = vdec_get_vdec_by_id(p_userdata_param->instance_id); + if (vdec) { + if (vdec_read_user_data(vdec, + p_userdata_param) == 0) { + r = -EFAULT; + break; + } + + if (copy_to_user((void *)arg, + p_userdata_param, + sizeof(struct userdata_param_t))) + r = -EFAULT; + } else + r = -EINVAL; + } + } + break; + + case AMSTREAM_IOC_UD_AVAILABLE_VDEC: + { + unsigned int ready_vdec; + + mutex_lock(&userdata_mutex); + ready_vdec = ud_ready_vdec_flag; + ud_ready_vdec_flag = 0; + mutex_unlock(&userdata_mutex); + + put_user(ready_vdec, (uint32_t __user *)arg); + } + break; + + case AMSTREAM_IOC_GET_VDEC_ID: + if (this->type & PORT_TYPE_VIDEO && priv->vdec) { + put_user(priv->vdec->id, (int32_t __user *)arg); + } else + r = -EINVAL; + break; + + case AMSTREAM_IOC_UD_FLUSH_USERDATA: if (this->type & PORT_TYPE_USERDATA) { - reset_userdata_fifo(0); - pr_info("reset_userdata_fifo\n"); + struct vdec_s *vdec; + int vdec_id; + + get_user(vdec_id, (int __user *)arg); + vdec = vdec_get_vdec_by_id(vdec_id); + if (vdec) { + vdec_reset_userdata_fifo(vdec, 0); + pr_info("reset_userdata_fifo for vdec: %d\n", vdec_id); + } } else r = -EINVAL; break; @@ -3018,10 +3151,11 @@ static long amstream_do_ioctl_old(struct port_priv_s *priv, case AMSTREAM_IOC_APTS_LOOKUP: if (this->type & PORT_TYPE_AUDIO) { - u32 pts = 0, offset; + u32 pts = 0, frame_size, offset; get_user(offset, (unsigned long __user *)arg); - pts_lookup_offset(PTS_TYPE_AUDIO, offset, &pts, 300); + pts_lookup_offset(PTS_TYPE_AUDIO, offset, &pts, + &frame_size, 300); put_user(pts, (int __user *)arg); } return 0; @@ -3193,6 +3327,7 @@ static long amstream_do_ioctl(struct port_priv_s *priv, case AMSTREAM_IOC_GET_PTR: case AMSTREAM_IOC_SET_PTR: case AMSTREAM_IOC_SYSINFO: + case AMSTREAM_IOC_GET_QOSINFO: r = amstream_do_ioctl_new(priv, cmd, arg); break; default: @@ -3252,19 +3387,23 @@ static long amstream_ioc_setget_ptr(struct port_priv_s *priv, unsigned int cmd, struct am_ioctl_parm_ptr32 __user *arg) { struct am_ioctl_parm_ptr __user *data; - struct am_ioctl_parm_ptr32 __user *data32 = arg; + struct am_ioctl_parm_ptr32 param; int ret; + if (copy_from_user(¶m, + (void __user *)arg, + sizeof(struct am_ioctl_parm_ptr32))) + return -EFAULT; + data = compat_alloc_user_space(sizeof(*data)); if (!access_ok(VERIFY_WRITE, data, sizeof(*data))) return -EFAULT; - if (put_user(data32->cmd, &data->cmd) || - put_user(compat_ptr(data32->pointer), &data->pointer) || - put_user(data32->len, &data->len)) + if (put_user(param.cmd, &data->cmd) || + put_user(compat_ptr(param.pointer), &data->pointer) || + put_user(param.len, &data->len)) return -EFAULT; - ret = amstream_do_ioctl(priv, cmd, (unsigned long)data); if (ret < 0) return ret; @@ -3278,13 +3417,19 @@ static long amstream_set_sysinfo(struct port_priv_s *priv, struct dec_sysinfo __user *data; struct dec_sysinfo32 __user *data32 = arg; int ret; + struct dec_sysinfo32 param; + + if (copy_from_user(¶m, + (void __user *)arg, + sizeof(struct dec_sysinfo32))) + return -EFAULT; data = compat_alloc_user_space(sizeof(*data)); if (!access_ok(VERIFY_WRITE, data, sizeof(*data))) return -EFAULT; if (copy_in_user(data, data32, 7 * sizeof(u32))) return -EFAULT; - if (put_user(compat_ptr(data32->param), &data->param)) + if (put_user(compat_ptr(param.param), &data->param)) return -EFAULT; if (copy_in_user(&data->ratio64, &data32->ratio64, sizeof(data->ratio64))) @@ -3302,6 +3447,60 @@ static long amstream_set_sysinfo(struct port_priv_s *priv, return 0; } + + +struct userdata_param32_t { + uint32_t version; + uint32_t instance_id; /*input, 0~9*/ + uint32_t buf_len; /*input*/ + uint32_t data_size; /*output*/ + compat_uptr_t pbuf_addr; /*input*/ + struct userdata_meta_info_t meta_info; /*output*/ +}; + + +static long amstream_ioc_get_userdata(struct port_priv_s *priv, + struct userdata_param32_t __user *arg) +{ + struct userdata_param_t __user *data; + struct userdata_param32_t __user *data32 = arg; + int ret; + struct userdata_param32_t param; + + + if (copy_from_user(¶m, + (void __user *)arg, + sizeof(struct userdata_param32_t))) + return -EFAULT; + + data = compat_alloc_user_space(sizeof(*data)); + if (!access_ok(VERIFY_WRITE, data, sizeof(*data))) + return -EFAULT; + + if (copy_in_user(data, data32, 4 * sizeof(u32))) + return -EFAULT; + + if (copy_in_user(&data->meta_info, &data32->meta_info, + sizeof(data->meta_info))) + return -EFAULT; + + if (put_user(compat_ptr(param.pbuf_addr), &data->pbuf_addr)) + return -EFAULT; + + ret = amstream_do_ioctl(priv, AMSTREAM_IOC_UD_BUF_READ, + (unsigned long)data); + if (ret < 0) + return ret; + + if (copy_in_user(&data32->version, &data->version, 4 * sizeof(u32)) || + copy_in_user(&data32->meta_info, &data->meta_info, + sizeof(data32->meta_info))) + return -EFAULT; + + return 0; +} + + static long amstream_compat_ioctl(struct file *file, unsigned int cmd, ulong arg) { @@ -3320,6 +3519,8 @@ static long amstream_compat_ioctl(struct file *file, return amstream_ioc_setget_ptr(priv, cmd, compat_ptr(arg)); case AMSTREAM_IOC_SYSINFO: return amstream_set_sysinfo(priv, compat_ptr(arg)); + case AMSTREAM_IOC_UD_BUF_READ: + return amstream_ioc_get_userdata(priv, compat_ptr(arg)); default: return amstream_do_ioctl(priv, cmd, (ulong)compat_ptr(arg)); } @@ -3438,7 +3639,7 @@ static ssize_t bufs_show(struct class *class, struct class_attribute *attr, "\tbuf regbase:%#lx\n", p->reg_base); if (p->reg_base && p->flag & BUF_FLAG_IN_USE) { - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M6) { + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M6) { /* TODO: mod gate */ /* switch_mod_gate_by_name("vdec", 1);*/ amports_switch_gate("vdec", 1); @@ -3450,7 +3651,7 @@ static ssize_t bufs_show(struct class *class, struct class_attribute *attr, pbuf += sprintf(pbuf, "\tbuf read pointer:%#x\n", stbuf_rp(p)); - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M6) { + if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M6) { /* TODO: mod gate */ /* switch_mod_gate_by_name("vdec", 0);*/ amports_switch_gate("vdec", 0); @@ -3797,7 +3998,7 @@ static int amstream_probe(struct platform_device *pdev) REG_PATH_CONFIGS("media.amports", amports_configs); /* poweroff the decode core because dos can not be reset when reboot */ - if (get_cpu_type() == MESON_CPU_MAJOR_ID_G12A) + if (get_cpu_major_id() == AM_MESON_CPU_MAJOR_ID_G12A) vdec_power_reset(); return 0; @@ -3899,12 +4100,19 @@ static int __init amstream_module_init(void) pr_err("failed to register amstream module\n"); return -ENODEV; } + + if (subtitle_init()) { + pr_err("failed to init subtitle\n"); + return -ENODEV; + } + return 0; } static void __exit amstream_module_exit(void) { platform_driver_unregister(&amstream_driver); + subtitle_exit(); } module_init(amstream_module_init); diff --git a/drivers/amlogic/media_modules/stream_input/parser/esparser.c b/drivers/amlogic/media_modules/stream_input/parser/esparser.c index f04b9decb969..38d36216627d 100644 --- a/drivers/amlogic/media_modules/stream_input/parser/esparser.c +++ b/drivers/amlogic/media_modules/stream_input/parser/esparser.c @@ -61,6 +61,9 @@ #define PARSER_DISCARD (ES_DISCARD | ES_PARSER_START) #define PARSER_BUSY (ES_PARSER_BUSY) +#define MAX_DRM_PACKAGE_SIZE 0x500000 + + static unsigned char *search_pattern; static dma_addr_t search_pattern_map; static u32 audio_real_wp; @@ -151,7 +154,7 @@ static inline u32 buf_wp(u32 type) } static ssize_t _esparser_write(const char __user *buf, - size_t count, u32 type, int isphybuf) + size_t count, struct stream_buf_s *stbuf, int isphybuf) { size_t r = count; const char __user *p = buf; @@ -161,6 +164,7 @@ static ssize_t _esparser_write(const char __user *buf, int ret; u32 wp; dma_addr_t dma_addr = 0; + u32 type = stbuf->type; if (type == BUF_TYPE_HEVC) parser_type = PARSER_VIDEO; @@ -245,11 +249,12 @@ static ssize_t _esparser_write(const char __user *buf, else if (type == BUF_TYPE_AUDIO) audio_data_parsed += len; + threadrw_update_buffer_level(stbuf, len); return len; } static ssize_t _esparser_write_s(const char __user *buf, - size_t count, u32 type) + size_t count, struct stream_buf_s *stbuf) { size_t r = count; const char __user *p = buf; @@ -257,6 +262,7 @@ static ssize_t _esparser_write_s(const char __user *buf, int ret; u32 wp, buf_start, buf_end; dma_addr_t buf_wp_map; + u32 type = stbuf->type; if (type != BUF_TYPE_AUDIO) BUG(); @@ -310,7 +316,10 @@ static ssize_t _esparser_write_s(const char __user *buf, end_write: if (type == BUF_TYPE_AUDIO) + { audio_data_parsed += len; + threadrw_update_buffer_level(stbuf, len); + } return len; } @@ -347,7 +356,11 @@ s32 es_vpts_checkin(struct stream_buf_s *buf, u32 pts) return 0; } #endif - u32 passed = video_data_parsed + threadrw_buffer_level(buf); + u32 passed = 0; + + mutex_lock(&esparser_mutex); + passed = video_data_parsed + threadrw_buffer_level(buf); + mutex_unlock(&esparser_mutex); return pts_checkin_offset(PTS_TYPE_VIDEO, passed, pts); @@ -363,7 +376,10 @@ s32 es_apts_checkin(struct stream_buf_s *buf, u32 pts) return 0; } #endif - u32 passed = audio_data_parsed + threadrw_buffer_level(buf); + u32 passed = 0; + mutex_lock(&esparser_mutex); + passed = audio_data_parsed + threadrw_buffer_level(buf); + mutex_unlock(&esparser_mutex); return pts_checkin_offset(PTS_TYPE_AUDIO, passed, pts); } @@ -434,7 +450,7 @@ s32 esparser_init(struct stream_buf_s *buf, struct vdec_s *vdec) /* TS data path */ #ifndef CONFIG_AM_DVB - WRITE_DEMUX_REG(FEC_INPUT_CONTROL, 0); +// WRITE_DEMUX_REG(FEC_INPUT_CONTROL, 0); #else tsdemux_set_reset_flag(); #endif @@ -609,6 +625,7 @@ Err_1: mutex_unlock(&esparser_mutex); return r; } +EXPORT_SYMBOL(esparser_init); void esparser_audio_reset_s(struct stream_buf_s *buf) { @@ -714,6 +731,7 @@ void esparser_release(struct stream_buf_s *buf) buf->flag &= ~BUF_FLAG_PARSER; pts_stop(pts_type); } +EXPORT_SYMBOL(esparser_release); ssize_t drm_write(struct file *file, struct stream_buf_s *stbuf, const char __user *buf, size_t count) @@ -745,6 +763,10 @@ ssize_t drm_write(struct file *file, struct stream_buf_s *stbuf, } if ((drm->drm_flag & TYPE_DRMINFO) && (drm->drm_hasesdata == 0)) { + if (drm->drm_pktsize > MAX_DRM_PACKAGE_SIZE) { + pr_err("drm package size is error, size is %u\n", drm->drm_pktsize); + return -EINVAL; + } /* buf only has drminfo not have esdata; */ realbuf = drm->drm_phy; realcount = drm->drm_pktsize; @@ -755,6 +777,10 @@ ssize_t drm_write(struct file *file, struct stream_buf_s *stbuf, *drm->drm_hasesdata,stbuf->type,buf); */ } else if (drm->drm_hasesdata == 1) { /* buf is drminfo+es; */ + if (drm->drm_pktsize > MAX_DRM_PACKAGE_SIZE) { + pr_err("drm package size is error, size is %u\n", drm->drm_pktsize); + return -EINVAL; + } realcount = drm->drm_pktsize; realbuf = (unsigned long)buf + sizeof(struct drm_info); isphybuf = 0; @@ -781,7 +807,9 @@ ssize_t drm_write(struct file *file, struct stream_buf_s *stbuf, if (stbuf->type != BUF_TYPE_SUBTITLE && stbuf_space(stbuf) < count) { /*should not write partial data in drm mode*/ - stbuf_wait_space(stbuf, count); + r = stbuf_wait_space(stbuf, count); + if (r < 0) + return r; if (stbuf_space(stbuf) < count) return -EAGAIN; } @@ -791,12 +819,13 @@ ssize_t drm_write(struct file *file, struct stream_buf_s *stbuf, if (stbuf->type != BUF_TYPE_AUDIO) r = _esparser_write((const char __user *)realbuf, len, - stbuf->type, isphybuf); + stbuf, isphybuf); else r = _esparser_write_s((const char __user *)realbuf, len, - stbuf->type); + stbuf); if (r < 0) { pr_info("drm_write _esparser_write failed [%d]\n", r); + mutex_unlock(&esparser_mutex); return r; } havewritebytes += r; @@ -821,6 +850,8 @@ ssize_t drm_write(struct file *file, struct stream_buf_s *stbuf, return re_count; } +EXPORT_SYMBOL(drm_write); + /* *flags: *1:phy @@ -864,9 +895,9 @@ ssize_t esparser_write_ex(struct file *file, mutex_lock(&esparser_mutex); if (stbuf->type == BUF_TYPE_AUDIO) - r = _esparser_write_s(buf, len, stbuf->type); + r = _esparser_write_s(buf, len, stbuf); else - r = _esparser_write(buf, len, stbuf->type, flags & 1); + r = _esparser_write(buf, len, stbuf, flags & 1); mutex_unlock(&esparser_mutex); @@ -914,7 +945,7 @@ ssize_t esparser_write(struct file *file, } return esparser_write_ex(file, stbuf, buf, count, 0); } - +EXPORT_SYMBOL(esparser_write); void esparser_sub_reset(void) { diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/Makefile b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/Makefile index e0315940b63a..594f78f42e12 100644 --- a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/Makefile +++ b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/Makefile @@ -5,4 +5,4 @@ ccflags-y += -I$(srctree)/drivers/media/dvb-core -I$(srctree)/drivers/gpio -I$(s aml_hardware_dmx-objs += aml_dvb.o aml_hardware_dmx-objs += aml_dmx.o -#obj-y += dvb_ci/ +obj-y += dvb_ci/ diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/aml_demod_gt.h b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/aml_demod_gt.h index b923798f02ed..3a5b3b0d7496 100644 --- a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/aml_demod_gt.h +++ b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/aml_demod_gt.h @@ -1,3 +1,22 @@ +/* +* 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. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ #ifndef __AML_DEMOD_GT_H__ #define __AML_DEMOD_GT_H__ @@ -18,22 +37,41 @@ struct amlfe_demod_config { int reset_value; }; +/* For configure different tuners */ +/* It can add fields as extensions */ +struct tuner_config { + u8 id; + u8 i2c_addr; + u8 xtal; /* 0: 16MHz, 1: 24MHz, 3: 27MHz */ + u8 xtal_cap; + u8 xtal_mode; +}; + static inline struct dvb_frontend* aml_dtvdm_attach (const struct amlfe_exp_config *config) { return NULL; } -static inline struct dvb_frontend* si2151_attach (struct dvb_frontend *fe,struct i2c_adapter *i2c,u8 i2c_addr/*, - struct si2151_config *cfg*/) +static inline struct dvb_frontend* si2151_attach (struct dvb_frontend *fe,struct i2c_adapter *i2c, struct tuner_config *cfg) { return NULL; } -static inline struct dvb_frontend* mxl661_attach (struct dvb_frontend *fe,struct i2c_adapter *i2c,u8 i2c_addr/*, - struct mxl661_config *cfg*/) + +static inline struct dvb_frontend* mxl661_attach (struct dvb_frontend *fe,struct i2c_adapter *i2c, struct tuner_config *cfg) { return NULL; } -static inline struct dvb_frontend* si2159_attach (struct dvb_frontend *fe,struct i2c_adapter *i2c,u8 i2c_addr/*, - struct si2159_config *cfg*/) + +static inline struct dvb_frontend* si2159_attach (struct dvb_frontend *fe,struct i2c_adapter *i2c, struct tuner_config *cfg) +{ + return NULL; +} + +static inline struct dvb_frontend* r842_attach (struct dvb_frontend *fe, struct i2c_adapter *i2c, struct tuner_config *cfg) +{ + return NULL; +} + +static inline struct dvb_frontend* r840_attach (struct dvb_frontend *fe, struct i2c_adapter *i2c, struct tuner_config *cfg) { return NULL; } @@ -43,4 +81,9 @@ static inline struct dvb_frontend* atbm8881_attach (const struct amlfe_demod_con return NULL; } +static inline struct dvb_frontend* si2168_attach (const struct amlfe_demod_config *config) +{ + return NULL; +} + #endif /*__AML_DEMOD_GT_H__*/ diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/aml_dmx.c b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/aml_dmx.c index e5226ccde533..3b2b9a7106f3 100644 --- a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/aml_dmx.c +++ b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/aml_dmx.c @@ -1,3 +1,22 @@ +/* +* 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. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ /* * AMLOGIC demux driver. */ @@ -24,7 +43,7 @@ #include #include #include - +#include #include "../streambuf.h" #include "c_stb_define.h" #include "c_stb_regs_define.h" @@ -207,7 +226,6 @@ dmx_write_reg(int r, u32 v) return; } } - WRITE_MPEG_REG(r, v); } @@ -234,14 +252,17 @@ dmx_write_reg(int r, u32 v) #define WRITE_PERI_REG WRITE_CBUS_REG #define READ_ASYNC_FIFO_REG(i, r)\ - ((i) ? READ_PERI_REG(ASYNC_FIFO2_##r) : READ_PERI_REG(ASYNC_FIFO_##r)) + ((i) ? ((i-1)?READ_PERI_REG(ASYNC_FIFO1_##r):\ + READ_PERI_REG(ASYNC_FIFO2_##r)) : READ_PERI_REG(ASYNC_FIFO_##r)) #define WRITE_ASYNC_FIFO_REG(i, r, d)\ do {\ - if (i == 1) {\ - WRITE_PERI_REG(ASYNC_FIFO2_##r, d);\ - } else {\ + if (i == 2) {\ + WRITE_PERI_REG(ASYNC_FIFO1_##r, d);\ + } else if (i == 0) {\ WRITE_PERI_REG(ASYNC_FIFO_##r, d);\ + } else {\ + WRITE_PERI_REG(ASYNC_FIFO2_##r, d);\ } \ } while (0) @@ -287,13 +308,10 @@ static inline int _set(int v, int b) { return b; } static int dsc_set_csa_key(struct aml_dsc_channel *ch, int flags, enum ca_cw_type type, u8 *key); -static int dsc_set_aes_key(struct aml_dsc_channel *ch, int flags, +static int dsc_set_aes_des_sm4_key(struct aml_dsc_channel *ch, int flags, enum ca_cw_type type, u8 *key); - -static void aml_ci_plus_disable_output(void); static void aml_ci_plus_disable(void); static void am_ci_plus_set_output(struct aml_dsc_channel *ch); -static void aml_ci_plus_enable(void); static void dmxn_op_chan(int dmx, int ch, int(*op)(int, int), int ch_op) { @@ -417,10 +435,13 @@ static int dmx_timeout_set(struct aml_dmxtimeout *dto, int enable, /*Audio & Video PTS value*/ static u32 video_pts; static u32 audio_pts; +static u32 video_pts_bit32; +static u32 audio_pts_bit32; static u32 first_video_pts; static u32 first_audio_pts; static int demux_skipbyte; static int tsfile_clkdiv = 4; +static int asyncfifo_buf_len = ASYNCFIFO_BUFFER_SIZE_DEFAULT; #define SF_DMX_ID 2 #define SF_AFIFO_ID 1 @@ -1109,10 +1130,14 @@ static void process_sub(struct aml_dmx *dmx) pr_dbg("sub no data\n"); } - if (buffer1) - buffer1_virt = phys_to_virt(buffer1); - if (buffer2) - buffer2_virt = phys_to_virt(buffer2); + if (buffer1 && len1) + buffer1_virt = codec_mm_phys_to_virt(buffer1); + + if (buffer2 && len2) + buffer2_virt = codec_mm_phys_to_virt(buffer2); + +// printk("rd_ptr %p buffer1 %p len1 %d buffer2 %p len2 %d buffer1_virt %p buffer2_virt %p\n", +// (void*)rd_ptr, (void*)buffer1, len1, (void*)buffer2, len2, buffer1_virt, buffer2_virt); if (len1) dma_sync_single_for_cpu(dmx_get_dev(dmx), @@ -1124,7 +1149,9 @@ static void process_sub(struct aml_dmx *dmx) DMA_FROM_DEVICE); if (dmx->channel[2].used) { - if (dmx->channel[2].feed && dmx->channel[2].feed->cb.ts) { + if (dmx->channel[2].feed && dmx->channel[2].feed->cb.ts && + ((buffer1_virt != NULL && len1 !=0 ) | (buffer2_virt != NULL && len2 != 0))) + { dmx->channel[2].feed->cb.ts(buffer1_virt, len1, buffer2_virt, len2, &dmx->channel[2].feed->feed.ts); @@ -1282,6 +1309,8 @@ static irqreturn_t dmx_irq_handler(int irq_number, void *para) if (pdts_status & (1 << VIDEO_PTS_READY)) { video_pts = DMX_READ_REG(dmx->id, VIDEO_PTS_DEMUX); + video_pts_bit32 = + (status & (1 << VIDEO_PTS_BIT32)) ? 1 : 0; if (!first_video_pts || 0 > (int)(video_pts - first_video_pts)) first_video_pts = video_pts; @@ -1289,6 +1318,8 @@ static irqreturn_t dmx_irq_handler(int irq_number, void *para) if (pdts_status & (1 << AUDIO_PTS_READY)) { audio_pts = DMX_READ_REG(dmx->id, AUDIO_PTS_DEMUX); + audio_pts_bit32 = + (status & (1 << AUDIO_PTS_BIT32)) ? 1 : 0; if (!first_audio_pts || 0 > (int)(audio_pts - first_audio_pts)) first_audio_pts = audio_pts; @@ -1358,9 +1389,11 @@ static void dvr_process_channel(struct aml_asyncfifo *afifo, { int cnt; int ret = 0; + struct aml_dvr_block blk; if (afifo->buf_read > afifo->buf_toggle) { cnt = total - afifo->buf_read; + if (!afifo->secure_enable) { dma_sync_single_for_cpu(asyncfifo_get_dev(afifo), afifo->pages_map+afifo->buf_read*size, cnt*size, @@ -1374,11 +1407,27 @@ static void dvr_process_channel(struct aml_asyncfifo *afifo, (u8 *)afifo->pages+afifo->buf_read*size, cnt*size, NULL, 0, &channel->dvr_feed->feed.ts); + } else { + blk.addr = afifo->blk.addr+afifo->buf_read*size; + blk.len = cnt*size; + if (sf) + ret = _rbuf_write(&sf->rbuf, + (u8 *)afifo->pages+afifo->buf_read*size, + cnt*size); + else { + channel->dvr_feed->cb.ts( + (u8 *)&blk, + sizeof(struct aml_dvr_block), + NULL, 0, + &channel->dvr_feed->feed.ts); + } + } afifo->buf_read = 0; } if (afifo->buf_toggle > afifo->buf_read) { cnt = afifo->buf_toggle - afifo->buf_read; + if (!afifo->secure_enable) { dma_sync_single_for_cpu(asyncfifo_get_dev(afifo), afifo->pages_map+afifo->buf_read*size, cnt*size, @@ -1388,11 +1437,27 @@ static void dvr_process_channel(struct aml_asyncfifo *afifo, ret = _rbuf_write(&sf->rbuf, (u8 *)afifo->pages+afifo->buf_read*size, cnt*size); - } else + } else { channel->dvr_feed->cb.ts( (u8 *)afifo->pages+afifo->buf_read*size, cnt*size, NULL, 0, + &channel->dvr_feed->feed.ts); + } + } else { + blk.addr = afifo->blk.addr+afifo->buf_read*size; + blk.len = cnt*size; + if (sf) + ret = _rbuf_write(&sf->rbuf, + (u8 *)afifo->pages+afifo->buf_read*size, + cnt*size); + else { + channel->dvr_feed->cb.ts( + (u8 *)&blk, + sizeof(struct aml_dvr_block), + NULL, 0, &channel->dvr_feed->feed.ts); + } + } afifo->buf_read = afifo->buf_toggle; } @@ -1421,6 +1486,7 @@ static void dvr_irq_bh_handler(unsigned long arg) if (dvb && afifo->source >= AM_DMX_0 && afifo->source < AM_DMX_MAX) { dmx = &dvb->dmx[afifo->source]; + // pr_inf("async fifo %d irq, source:%d\n", afifo->id,afifo->source); if (dmx->init && dmx->record) { struct aml_swfilter *sf = &dvb->swfilter; int issf = 0; @@ -1465,8 +1531,8 @@ static void stb_enable(struct aml_dvb *dvb) { int out_src, des_in, en_des, fec_clk, hiu, dec_clk_en; int src, tso_src, i; - u32 fec_s0, fec_s1; - u32 invert0, invert1; + u32 fec_s0, fec_s1,fec_s2; + u32 invert0, invert1, invert2; u32 data; switch (dvb->stb_source) { @@ -1497,6 +1563,10 @@ static void stb_enable(struct aml_dvb *dvb) fec_clk = tsfile_clkdiv; hiu = 0; break; + case AM_TS_SRC_TS3: + fec_clk = tsfile_clkdiv; + hiu = 0; + break; case AM_TS_SRC_S_TS0: fec_clk = tsfile_clkdiv; hiu = 0; @@ -1513,6 +1583,10 @@ static void stb_enable(struct aml_dvb *dvb) fec_clk = tsfile_clkdiv; hiu = 1; break; + case AM_TS_SRC_HIU1: + fec_clk = tsfile_clkdiv; + hiu = 1; + break; default: fec_clk = 0; hiu = 0; @@ -1567,11 +1641,18 @@ static void stb_enable(struct aml_dvb *dvb) case AM_TS_SRC_TS2: out_src = 2; break; + case AM_TS_SRC_TS3: + out_src = 3; + break; case AM_TS_SRC_S_TS0: - case AM_TS_SRC_S_TS1: - case AM_TS_SRC_S_TS2: out_src = 6; break; + case AM_TS_SRC_S_TS1: + out_src = 5; + break; + case AM_TS_SRC_S_TS2: + out_src = 4; + break; case AM_TS_SRC_HIU: out_src = 7; break; @@ -1584,14 +1665,18 @@ static void stb_enable(struct aml_dvb *dvb) fec_s0 = 0; fec_s1 = 0; + fec_s2 = 0; invert0 = 0; invert1 = 0; + invert2 = 0; - for (i = 0; i < TS_IN_COUNT; i++) { + for (i = 0; i < dvb->ts_in_total_count; i++) { if (dvb->ts[i].s2p_id == 0) fec_s0 = i; else if (dvb->ts[i].s2p_id == 1) fec_s1 = i; + else if (dvb->ts[i].s2p_id == 2) + fec_s2 = i; } invert0 = dvb->s2p[0].invert; @@ -1607,6 +1692,15 @@ static void stb_enable(struct aml_dvb *dvb) (invert0 << INVERT_S2P0_FEC_CLK) | (fec_s0 << S2P0_FEC_SERIAL_SEL)); + + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_TL1) { + invert2 = dvb->s2p[2].invert; + + WRITE_MPEG_REG(STB_S2P2_CONFIG, + (invert2 << INVERT_S2P2_FEC_CLK) | + (fec_s2 << S2P2_FEC_SERIAL_SEL)); + } + if (dvb->reset_flag) hiu = 0; /* invert ts out clk,add ci model need add this*/ @@ -1616,13 +1710,23 @@ static void stb_enable(struct aml_dvb *dvb) data |= 1 << TS_OUT_CLK_INVERT; WRITE_MPEG_REG(TS_TOP_CONFIG, data); } - /* invert ts out clk end */ - WRITE_MPEG_REG(TS_FILE_CONFIG, - (demux_skipbyte << 16) | - (6 << DES_OUT_DLY) | - (3 << TRANSPORT_SCRAMBLING_CONTROL_ODD) | - (3 << TRANSPORT_SCRAMBLING_CONTROL_ODD_2) | - (hiu << TS_HIU_ENABLE) | (fec_clk << FEC_FILE_CLK_DIV)); + + if (src == AM_TS_SRC_HIU1) { + WRITE_MPEG_REG(TS_HIU1_CONFIG, + (demux_skipbyte << FILE_M2TS_SKIP_BYTES_HIU1) | + (hiu << TS_HIU_ENABLE_HIU1) | + (fec_clk << FEC_CLK_DIV_HIU1) | + (0xBB << TS_PACKAGE_LENGTH_SUB_1_HIU1) | + (0x47 << FEC_SYNC_BYTE_HIU1)); + } else { + /* invert ts out clk end */ + WRITE_MPEG_REG(TS_FILE_CONFIG, + (demux_skipbyte << 16) | + (6 << DES_OUT_DLY) | + (3 << TRANSPORT_SCRAMBLING_CONTROL_ODD) | + (3 << TRANSPORT_SCRAMBLING_CONTROL_ODD_2) | + (hiu << TS_HIU_ENABLE) | (fec_clk << FEC_FILE_CLK_DIV)); + } } int dsc_set_pid(struct aml_dsc_channel *ch, int pid) @@ -1663,43 +1767,105 @@ int dsc_set_key(struct aml_dsc_channel *ch, int flags, enum ca_cw_type type, /*struct aml_dsc *dsc = ch->dsc;*/ int ret = -1; - if (type == CA_CW_DVB_CSA_EVEN || type == CA_CW_DVB_CSA_ODD) { + switch (type) { + case CA_CW_DVB_CSA_EVEN: + case CA_CW_DVB_CSA_ODD: + aml_ci_plus_disable(); ret = dsc_set_csa_key(ch, flags, type, key); if (ret != 0) goto END; /* Different with old mode, do change */ if (ch->work_mode == CIPLUS_MODE || ch->work_mode == -1) { if (ch->work_mode == -1) - pr_error("Dsc set output and enable\n"); + pr_inf("dsc[%d:%d] enable\n", + ch->dsc->id, ch->id); else - pr_error("Dsc set output change from ciplus\n"); - aml_ci_plus_disable_output(); - ch->aes_mode = AES_ECB_MODE; - /*aml_ci_plus_disable();*/ + pr_inf("dsc[%d:%d] enable (from ciplus)\n", + ch->dsc->id, ch->id); + ch->mode = ECB_MODE; ch->work_mode = DVBCSA_MODE; } - } else if (type == CA_CW_AES_EVEN || - type == CA_CW_AES_ODD || - type == CA_CW_AES_EVEN_IV || - type == CA_CW_AES_ODD_IV) { - ret = dsc_set_aes_key(ch, flags, type, key); + break; + case CA_CW_AES_EVEN: + case CA_CW_AES_ODD: + case CA_CW_AES_EVEN_IV: + case CA_CW_AES_ODD_IV: + case CA_CW_DES_EVEN: + case CA_CW_DES_ODD: + case CA_CW_SM4_EVEN: + case CA_CW_SM4_ODD: + case CA_CW_SM4_EVEN_IV: + case CA_CW_SM4_ODD_IV: + am_ci_plus_set_output(ch); + ret = dsc_set_aes_des_sm4_key(ch, flags, type, key); if (ret != 0) goto END; /* Different with old mode, do change */ if (ch->work_mode == DVBCSA_MODE || ch->work_mode == -1) { if (ch->work_mode == -1) - pr_error("Ciplus set output and enable\n"); + pr_inf("dsc[%d:%d] ciplus enable\n", + ch->dsc->id, ch->id); else - pr_error("Ciplus set output change from dsc\n"); - am_ci_plus_set_output(ch); - aml_ci_plus_enable(); + pr_inf("dsc[%d:%d] ciplus enable (from dsc)\n", + ch->dsc->id, ch->id); ch->work_mode = CIPLUS_MODE; } + break; + default: + break; } END: return ret; } +int dsc_set_keys(struct aml_dsc_channel *ch) +{ + int types = ch->set & 0xFFFFFF; + int flag = (ch->set >> 24) & 0xFF; + int i; + u8 *k; + int ret = 0; + + for (i = 0; i < CA_CW_TYPE_MAX; i++) { + if (types & (1 << i)) { + k = NULL; + switch (i) { + case CA_CW_DVB_CSA_EVEN: + case CA_CW_AES_EVEN: + case CA_CW_DES_EVEN: + case CA_CW_SM4_EVEN: + k = ch->even; + break; + case CA_CW_DVB_CSA_ODD: + case CA_CW_AES_ODD: + case CA_CW_DES_ODD: + case CA_CW_SM4_ODD: + k = ch->odd; + break; + case CA_CW_AES_EVEN_IV: + case CA_CW_SM4_EVEN_IV: + k = ch->even_iv; + break; + case CA_CW_AES_ODD_IV: + case CA_CW_SM4_ODD_IV: + k = ch->odd_iv; + break; + default: + break; + } + /* + if (k) + pr_inf("dsc ch:%d flag:%d type:%d\n", ch->id, flag, i); + */ + if (k) + ret = dsc_set_key(ch, flag, + i, + k); + } + } + return 0; +} + static int dsc_set_csa_key(struct aml_dsc_channel *ch, int flags, enum ca_cw_type type, u8 *key) { @@ -1707,18 +1873,10 @@ static int dsc_set_csa_key(struct aml_dsc_channel *ch, int flags, int is_dsc2 = (dsc->id == 1) ? 1 : 0; u16 k0, k1, k2, k3; u32 key0, key1; - int reg; /*not sure if reg readable*/ -/* u32 data; - * u32 pid = 0x1fff; - */ - int from_kl = flags & CA_CW_FROM_KL; -/* int pid = ch->pid; */ + int reg; - if (from_kl) { + if (flags & DSC_FROM_KL) { k0 = k1 = k2 = k3 = 0; -/* ch->used = 1; - * dsc_set_pid(ch, pid); - */ /*dummy write to check if kl not working*/ key0 = key1 = 0; WRITE_MPEG_REG(COMM_DESC_KEY0, key0); @@ -1732,7 +1890,9 @@ static int dsc_set_csa_key(struct aml_dsc_channel *ch, int flags, ((ch->id + type * DSC_COUNT)+ (is_dsc2 ? 16 : 0))); } - if (get_cpu_type() == MESON_CPU_MAJOR_ID_GXL) { + if (get_cpu_type() == MESON_CPU_MAJOR_ID_GXL || + get_cpu_type() == MESON_CPU_MAJOR_ID_GXM) { + pr_info("do kl..\n"); WRITE_MPEG_REG(COMM_DESC_KEY_RW, (type ? (1 << 6) : (1 << 5)) | (1<<7) | ((ch->id + type * DSC_COUNT)+ @@ -1751,9 +1911,9 @@ static int dsc_set_csa_key(struct aml_dsc_channel *ch, int flags, key1 = (k2 << 16) | k3; WRITE_MPEG_REG(COMM_DESC_KEY0, key0); WRITE_MPEG_REG(COMM_DESC_KEY1, key1); - WRITE_MPEG_REG(COMM_DESC_KEY_RW, - (ch->id + type * DSC_COUNT)+(is_dsc2 ? 16 : 0)); + reg = (ch->id + type * DSC_COUNT)+(is_dsc2 ? 16 : 0); + WRITE_MPEG_REG(COMM_DESC_KEY_RW, reg); } return 0; @@ -1778,7 +1938,11 @@ static int dsc_set_csa_key(struct aml_dsc_channel *ch, int flags, #define KEY_WR_AES_IV_A 4 #define KEY_WR_AES_B 3 #define KEY_WR_AES_A 2 +#define KEY_WR_DES_B 1 +#define KEY_WR_DES_A 0 +#define IDSA_MODE_BIT 31 +#define SM4_MODE 30 #define CNTL_ENABLE 3 #define AES_CBC_DISABLE 2 #define AES_EN 1 @@ -1787,7 +1951,13 @@ static int dsc_set_csa_key(struct aml_dsc_channel *ch, int flags, #define AES_MSG_OUT_ENDIAN 24 #define AES_MSG_IN_ENDIAN 20 #define AES_KEY_ENDIAN 16 +#define DES_MSG_OUT_ENDIAN 8 +#define DES_MSG_IN_ENDIAN 4 +#define DES_KEY_ENDIAN 0 +#define ALGO_AES 0 +#define ALGO_SM4 1 +#define ALGO_DES 2 #if 0 static void aml_ci_plus_set_stb(void) @@ -1834,14 +2004,16 @@ void aml_ci_plus_set_iv(struct aml_dsc_channel *ch, enum ca_cw_type type, k1 = (key[8] << 24) | (key[9] << 16) | (key[10] << 8) | key[11]; k0 = (key[12] << 24) | (key[13] << 16) | (key[14] << 8) | key[15]; - if (type == CA_CW_AES_EVEN_IV) { + if (type == CA_CW_AES_EVEN_IV || + type == CA_CW_SM4_EVEN_IV) { WRITE_MPEG_REG(CIPLUS_KEY0, k0); WRITE_MPEG_REG(CIPLUS_KEY1, k1); WRITE_MPEG_REG(CIPLUS_KEY2, k2); WRITE_MPEG_REG(CIPLUS_KEY3, k3); WRITE_MPEG_REG(CIPLUS_KEY_WR, (ch->id << 9) | (1<dsc; u32 data; + u32 in = 0, out = 0; + int set = 0; if (dsc->id != 0) { pr_error("Ciplus set output can only work at dsc0 device\n"); return; } + switch (dsc->source) { + case AM_TS_SRC_DMX0: + in = 0; + break; + case AM_TS_SRC_DMX1: + in = 1; + break; + case AM_TS_SRC_DMX2: + in = 2; + break; + default: + break; + } + if (ciplus_out_auto_mode == 1) { - data = READ_MPEG_REG(STB_TOP_CONFIG); - switch (dsc->source) { + switch (dsc->dst) { case AM_TS_SRC_DMX0: - data |= 1 << CIPLUS_OUT_SEL; - ciplus_out_sel = 1; - break; + out = 1; + break; case AM_TS_SRC_DMX1: - data |= 2 << CIPLUS_OUT_SEL; - ciplus_out_sel = 2; - break; + out = 2; + break; case AM_TS_SRC_DMX2: - data |= 4 << CIPLUS_OUT_SEL; - ciplus_out_sel = 4; - break; + out = 4; + break; default: - pr_error("ciplus auto set source failed\n"); - return; + break; } - WRITE_MPEG_REG(STB_TOP_CONFIG, data); + set = 1; + ciplus_out_sel = out; } else if (ciplus_out_sel >= 0 && ciplus_out_sel <= 7) { - pr_error("Set output selection %d\n", ciplus_out_sel); + set = 1; + out = ciplus_out_sel; + } else { + pr_error("dsc ciplus out config is invalid\n"); + } + + if (set) { + /* Set ciplus input source , + * output set 0 means no output. ---> need confirm. + * if output set 0 still affects dsc output, we need to disable + * ciplus module. + */ data = READ_MPEG_REG(STB_TOP_CONFIG); + data &= ~(3<aes_mode == -1) - ch->aes_mode = AES_ECB_MODE; - } else if (type == CA_CW_AES_ODD) { - aes_a = 1; - aes_b = 0; - if (ch->aes_mode == -1) - ch->aes_mode = AES_ECB_MODE; - } else if ((type == CA_CW_AES_EVEN_IV) - || (type == CA_CW_AES_ODD_IV)) { - aml_ci_plus_set_iv(ch, type, key); - ch->aes_mode = AES_CBC_MODE; - return 0; + if (!from_kl) { + if (get_cpu_type() < MESON_CPU_MAJOR_ID_SM1) { + k3 = (key[0] << 24) | (key[1] << 16) | (key[2] << 8) | key[3]; + k2 = (key[4] << 24) | (key[5] << 16) | (key[6] << 8) | key[7]; + k1 = (key[8] << 24) | (key[9] << 16) | (key[10] << 8) | key[11]; + k0 = (key[12] << 24) | (key[13] << 16) + | (key[14] << 8) | key[15]; + } else { + k0 = (key[0]) | (key[1] << 8) | (key[2] << 16) | (key[3] << 24); + k1 = (key[4]) | (key[5] << 8) | (key[6] << 16) | (key[7] << 24); + k2 = (key[8]) | (key[9] << 8) | (key[10] << 16)| (key[11] << 24); + k3 = (key[12])| (key[13] << 8)| (key[14] << 16)| (key[15] << 24); + } + } else + k0 = k1 = k2 = k3 = 0; + + switch (type) { + case CA_CW_AES_EVEN: + case CA_CW_SM4_EVEN: + ab_aes = (from_kl) ? 0x2 : 0x1; + if (ch->mode == -1) + ch->mode = ECB_MODE; + aes = 1; + if (type == CA_CW_AES_EVEN) + algo = ALGO_AES; + else + algo = ALGO_SM4; + break; + case CA_CW_AES_ODD: + case CA_CW_SM4_ODD: + ab_aes = (from_kl) ? 0x1 : 0x2; + if (ch->mode == -1) + ch->mode = ECB_MODE; + aes = 1; + if (type == CA_CW_AES_ODD) + algo = ALGO_AES; + else + algo = ALGO_SM4; + break; + case CA_CW_AES_EVEN_IV: + case CA_CW_SM4_EVEN_IV: + ab_iv = 0x1; + if (ch->mode == -1) + ch->mode = CBC_MODE; + iv = 1; + if (type == CA_CW_AES_EVEN_IV) + algo = ALGO_AES; + else + algo = ALGO_SM4; + break; + case CA_CW_AES_ODD_IV: + case CA_CW_SM4_ODD_IV: + ab_iv = 0x2; + if (ch->mode == -1) + ch->mode = CBC_MODE; + iv = 1; + if (type == CA_CW_AES_ODD_IV) + algo = ALGO_AES; + else + algo = ALGO_SM4; + break; + case CA_CW_DES_EVEN: + ab_des = 0x1; + ch->mode = ECB_MODE; + des = 1; + algo = ALGO_DES; + break; + case CA_CW_DES_ODD: + ab_des = 0x2; + ch->mode = ECB_MODE; + algo = ALGO_DES; + des = 1; + break; + default: + break; } /* Set endian and cbc/ecb mode */ if (from_kl) - aml_ci_plus_config(7, ch->aes_mode); + aml_ci_plus_config(7, ch->mode, algo); else - aml_ci_plus_config(0, ch->aes_mode); + aml_ci_plus_config(0, ch->mode, algo); /* Write keys to work */ - if (from_kl) { - k0 = k1 = k2 = k3 = 0; - -/* dummy write to - * check if kl not working - */ + if (iv || aes) { WRITE_MPEG_REG(CIPLUS_KEY0, k0); WRITE_MPEG_REG(CIPLUS_KEY1, k1); WRITE_MPEG_REG(CIPLUS_KEY2, k2); WRITE_MPEG_REG(CIPLUS_KEY3, k3); - WRITE_MPEG_REG(CIPLUS_KEY_WR, - (ch->id << 9) | - -/* bit[11:9] the key of index, - * need match PID index - */ - (0 << 8) | /* bit[8] des key use cw[127:64]*/ - (0 << 7) | /* bit[7] aes iv use cw*/ - (1 << 6) | /* bit[6] aes/des key use cw*/ - (0 << 5) | /* bit[5] write AES IV B value*/ - (0 << 4) | /* bit[4] write AES IV A value*/ - (aes_b << 3) | /* bit[3] write AES B key*/ - (aes_a << 2) | /* bit[2] write AES A key*/ - (0 << 1) | /* bit[1] write DES B key*/ - (0)); /* bit[0] write DES A key*/ - } else { - - k3 = (key[0] << 24) | (key[1] << 16) | (key[2] << 8) | key[3]; - k2 = (key[4] << 24) | (key[5] << 16) | (key[6] << 8) | key[7]; - k1 = (key[8] << 24) | (key[9] << 16) | - (key[10] << 8) | key[11]; - k0 = (key[12] << 24) | (key[13] << 16) | - (key[14] << 8) | key[15]; - - WRITE_MPEG_REG(CIPLUS_KEY0, k0); - WRITE_MPEG_REG(CIPLUS_KEY1, k1); - WRITE_MPEG_REG(CIPLUS_KEY2, k2); - WRITE_MPEG_REG(CIPLUS_KEY3, k3); - index_flag = (ch->id << 9); - if (type == 2) { /* even */ - WRITE_MPEG_REG(CIPLUS_KEY_WR, - index_flag | (1<id << 9) | + /* bit[11:9] the key of index, + need match PID index*/ + ((from_kl && des) ? (1 << 8) : 0) | + /* bit[8] des key use cw[127:64]*/ + (0 << 7) | /* bit[7] aes iv use cw*/ + ((from_kl && (aes || des)) ? (1 << 6) : 0) | + /* bit[6] aes/des key use cw*/ + /* bit[5] write AES IV B value*/ + (ab_iv << 4) | /* bit[4] write AES IV A value*/ + /* bit[3] write AES B key*/ + (ab_aes << 2) | /* bit[2] write AES A key*/ + /* bit[1] write DES B key*/ + (ab_des)); /* bit[0] write DES A key*/ + + /* + pr_inf("k:%08x:%08x:%08x:%08x kl:%d aes:%d des:%d ab_iv:%d ab_aes:%d ab_des:%d id:%d mod:%d\n", + k0, k1, k2, k3, + from_kl, aes, des, ab_iv, ab_aes, ab_des, ch->id, ch->aes_mode); + */ return 0; } - void dsc_release(void) { aml_ci_plus_disable(); @@ -2054,7 +2342,7 @@ int dsc_enable(struct aml_dsc *dsc, int enable) (1 << ENABLE_DES_PL)| (1 << ENABLE_DES_PL_CLK))); } else if (dsc->id == 1) { - WRITE_MPEG_REG(COMM_DESC_2_CTL, 0); + WRITE_MPEG_REG(COMM_DESC_2_CTL, 0); } return 0; } @@ -2196,7 +2484,7 @@ static int asyncfifo_set_buffer(struct aml_asyncfifo *afifo, afifo->buf_toggle = 0; afifo->buf_read = 0; afifo->buf_len = len; - pr_error("async fifo %d buf size %d, flush size %d\n", + pr_error("++++async fifo %d buf size %d, flush size %d\n", afifo->id, afifo->buf_len, afifo->flush_size); if ((afifo->flush_size <= 0) @@ -2275,11 +2563,16 @@ int async_fifo_init(struct aml_asyncfifo *afifo, int initirq, int async_fifo_deinit(struct aml_asyncfifo *afifo, int freeirq) { + struct aml_dvb *dvb = afifo->dvb; + unsigned long flags; + if (!afifo->init) return 0; + spin_lock_irqsave(&dvb->slock, flags); CLEAR_ASYNC_FIFO_REG_MASK(afifo->id, REG1, 1 << ASYNC_FIFO_FLUSH_EN); CLEAR_ASYNC_FIFO_REG_MASK(afifo->id, REG2, 1 << ASYNC_FIFO_FILL_EN); + spin_unlock_irqrestore(&dvb->slock, flags); asyncfifo_put_buffer(afifo); @@ -2447,12 +2740,22 @@ static int dmx_init(struct aml_dmx *dmx) { struct aml_dvb *dvb = (struct aml_dvb *)dmx->demux.priv; int irq; + int ret = 0; + char buf[32]; + u32 value = 0; if (dmx->init) return 0; pr_inf("demux init\n"); + memset(buf, 0, 32); + snprintf(buf, sizeof(buf), "asyncfifo_buf_len"); + ret = of_property_read_u32(dvb->pdev->dev.of_node, buf, &value); + if (!ret) { + pr_inf("%s: 0x%x\n", buf, value); + asyncfifo_buf_len = value; + } /*Register irq handlers */ if (dmx->dmx_irq != -1) { pr_dbg("request irq\n"); @@ -2556,7 +2859,7 @@ static int dmx_get_record_flag(struct aml_dmx *dmx) struct aml_dvb *dvb = (struct aml_dvb *)dmx->demux.priv; /*Check whether a async fifo connected to this dmx */ - for (i = 0; i < ASYNCFIFO_COUNT; i++) { + for (i = 0; i < dvb->async_fifo_total_count; i++) { if (!dvb->asyncfifo[i].init) continue; if ((dvb->asyncfifo[i].source == dmx->id) @@ -2601,6 +2904,29 @@ find_done: return record_flag; } +static void dmx_cascade_set(int cur_dmx, int source) { + int fec_sel_demux = 0; + int data; + + switch (source) { + case AM_TS_SRC_DMX0: + case AM_TS_SRC_DMX1: + case AM_TS_SRC_DMX2: + fec_sel_demux = source -AM_TS_SRC_DMX0; + break; + default: + fec_sel_demux = cur_dmx; + break; + } + + data = READ_MPEG_REG(TS_TOP_CONFIG1); + data &= ~(0x3 << (cur_dmx*2)); + data |= (fec_sel_demux << (cur_dmx*2)); + WRITE_MPEG_REG(TS_TOP_CONFIG1,data); + + pr_dbg("%s id:%d, source:%d data:0x%0x\n",__FUNCTION__,cur_dmx,fec_sel_demux,data); +} + /*Enable the demux device*/ static int dmx_enable(struct aml_dmx *dmx) { @@ -2609,7 +2935,7 @@ static int dmx_enable(struct aml_dmx *dmx) int fec_core_sel = 0; int set_stb = 0, fec_s = 0; int s2p_id; - u32 invert0 = 0, invert1 = 0, fec_s0 = 0, fec_s1 = 0; + u32 invert0 = 0, invert1 = 0, invert2 = 0, fec_s0 = 0, fec_s1 = 0, fec_s2 = 0; u32 use_sop = 0; record = dmx_get_record_flag(dmx); @@ -2648,7 +2974,8 @@ static int dmx_enable(struct aml_dmx *dmx) s2p_id = dvb->ts[2].s2p_id; fec_ctrl = dvb->ts[2].control; } - fec_sel = (s2p_id == 1) ? 5 : 6; + //fec_sel = (s2p_id == 1) ? 5 : 6; + fec_sel = 6 - s2p_id; record = record ? 1 : 0; set_stb = 1; fec_s = dmx->source - AM_TS_SRC_S_TS0; @@ -2656,7 +2983,25 @@ static int dmx_enable(struct aml_dmx *dmx) case AM_TS_SRC_HIU: fec_sel = 7; fec_ctrl = 0; + /* + support record in HIU mode record = 0; + */ + break; + case AM_TS_SRC_HIU1: + fec_sel = 8; + fec_ctrl = 0; + /* + support record in HIU mode + record = 0; + */ + break; + case AM_TS_SRC_DMX0: + case AM_TS_SRC_DMX1: + case AM_TS_SRC_DMX2: + fec_sel = -1; + fec_ctrl = 0; + record = record ? 1 : 0; break; default: fec_sel = 0; @@ -2665,11 +3010,14 @@ static int dmx_enable(struct aml_dmx *dmx) break; } - if (dmx->channel[0].used || dmx->channel[1].used) + if (dmx->channel[0].used || dmx->channel[1].used) { hi_bsf = 1; - else + if (fec_sel == 8) { + hi_bsf = 2; /*hi_bsf select hiu1*/ + } + }else { hi_bsf = 0; - + } if ((dvb->dsc[0].dst != -1) && ((dvb->dsc[0].dst - AM_TS_SRC_DMX0) == dmx->id)) fec_core_sel = 1; @@ -2734,11 +3082,13 @@ static int dmx_enable(struct aml_dmx *dmx) u32 v = READ_MPEG_REG(STB_TOP_CONFIG); int i; - for (i = 0; i < TS_IN_COUNT; i++) { + for (i = 0; i < dvb->ts_in_total_count; i++) { if (dvb->ts[i].s2p_id == 0) fec_s0 = i; else if (dvb->ts[i].s2p_id == 1) fec_s1 = i; + else if (dvb->ts[i].s2p_id == 2) + fec_s2 = i; } invert0 = dvb->s2p[0].invert; @@ -2754,6 +3104,18 @@ static int dmx_enable(struct aml_dmx *dmx) (fec_s1 << S2P1_FEC_SERIAL_SEL) | (invert1 << INVERT_S2P1_FEC_CLK); WRITE_MPEG_REG(STB_TOP_CONFIG, v); + + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_TL1) { + invert2 = dvb->s2p[2].invert; + + //add s2p2 config + v = READ_MPEG_REG(STB_S2P2_CONFIG); + v &= ~((0x3 << S2P2_FEC_SERIAL_SEL) | + (0x1f << INVERT_S2P2_FEC_CLK)); + v |= (fec_s2 << S2P2_FEC_SERIAL_SEL) | + (invert2 << INVERT_S2P2_FEC_CLK); + WRITE_MPEG_REG(STB_S2P2_CONFIG, v); + } } /*Initialize the registers */ @@ -2780,13 +3142,33 @@ static int dmx_enable(struct aml_dmx *dmx) (7<id, TS_HIU_CTL, - (0 << LAST_BURST_THRESHOLD) | - (hi_bsf << USE_HI_BSF_INTERFACE)); + if (fec_sel != 8) { + DMX_WRITE_REG(dmx->id, TS_HIU_CTL, +// (0 << LAST_BURST_THRESHOLD) | + (hi_bsf << USE_HI_BSF_INTERFACE)); + } else { + DMX_WRITE_REG(dmx->id, TS_HIU_CTL, + (1 << PDTS_WR_SEL) | + (hi_bsf << USE_HI_BSF_INTERFACE)); + } - DMX_WRITE_REG(dmx->id, FEC_INPUT_CONTROL, + if (fec_sel == -1) { + dmx_cascade_set(dmx->id,dmx->source); + DMX_WRITE_REG(dmx->id, FEC_INPUT_CONTROL, (fec_core_sel << FEC_CORE_SEL) | - (fec_sel << FEC_SEL) | (fec_ctrl << 0)); + (0 << FEC_SEL) | (fec_ctrl << 0)); + } else { + dmx_cascade_set(dmx->id,dmx->source); + if (fec_sel != 8) { + DMX_WRITE_REG(dmx->id, FEC_INPUT_CONTROL, + (fec_core_sel << FEC_CORE_SEL) | + (fec_sel << FEC_SEL) | (fec_ctrl << 0)); + } else { + DMX_WRITE_REG(dmx->id, FEC_INPUT_CONTROL, + (fec_core_sel << FEC_CORE_SEL) | + (1 << FEC_SEL_3BIT) | (fec_ctrl << 0)); + } + } DMX_WRITE_REG(dmx->id, STB_OM_CTL, (0x40 << MAX_OM_DMA_COUNT) | (0x7f << LAST_OM_ADDR)); @@ -2808,8 +3190,13 @@ static int dmx_enable(struct aml_dmx *dmx) DMX_WRITE_REG(dmx->id, STB_INT_MASK, 0); DMX_WRITE_REG(dmx->id, FEC_INPUT_CONTROL, 0); DMX_WRITE_REG(dmx->id, DEMUX_CONTROL, 0); + //dmx not used, but it can cascade for other dmx + if ((dmx->source == AM_TS_SRC_DMX0 || + dmx->source == AM_TS_SRC_DMX1 || + dmx->source == AM_TS_SRC_DMX2 ) && + (dmx->id != dmx->source-AM_TS_SRC_DMX0)) + dmx_cascade_set(dmx->id,dmx->source); } - return 0; } @@ -3138,12 +3525,13 @@ static void dmx_clear_filter_buffer(struct aml_dmx *dmx, int fid) static void async_fifo_set_regs(struct aml_asyncfifo *afifo, int source_val) { - u32 start_addr = virt_to_phys((void *)afifo->pages); + u32 start_addr = afifo->secure_enable ? afifo->blk.addr : + virt_to_phys((void *)afifo->pages); u32 size = afifo->buf_len; u32 flush_size = afifo->flush_size; int factor = dmx_get_order(size / flush_size); - - pr_dbg("ASYNC FIFO id=%d, link to DMX%d, start_addr %x, buf_size %d,source value 0x%x, factor %d\n", + pr_error("ASYNC FIFO id=%d, link to DMX%d, start_addr %x, buf_size %d," + "source value 0x%x, factor %d\n", afifo->id, afifo->source, start_addr, size, source_val, factor); /* Destination address */ WRITE_ASYNC_FIFO_REG(afifo->id, REG0, start_addr); @@ -3208,11 +3596,12 @@ static void reset_async_fifos(struct aml_dvb *dvb) { struct aml_asyncfifo *low_dmx_fifo = NULL; struct aml_asyncfifo *high_dmx_fifo = NULL; + struct aml_asyncfifo *highest_dmx_fifo = NULL; int i, j; int record_enable; pr_dbg("reset ASYNC FIFOs\n"); - for (i = 0; i < ASYNCFIFO_COUNT; i++) { + for (i = 0; i < dvb->async_fifo_total_count; i++) { if (!dvb->asyncfifo[i].init) continue; pr_dbg("Disable ASYNC FIFO id=%d\n", dvb->asyncfifo[i].id); @@ -3235,7 +3624,7 @@ static void reset_async_fifos(struct aml_dvb *dvb) if (!dvb->dmx[j].init) continue; record_enable = 0; - for (i = 0; i < ASYNCFIFO_COUNT; i++) { + for (i = 0; i < dvb->async_fifo_total_count; i++) { if (!dvb->asyncfifo[i].init) continue; @@ -3249,11 +3638,25 @@ static void reset_async_fifos(struct aml_dvb *dvb) low_dmx_fifo = &dvb->asyncfifo[i]; } else if (low_dmx_fifo->source > dvb->asyncfifo[i].source) { - high_dmx_fifo = low_dmx_fifo; + if (!high_dmx_fifo) + high_dmx_fifo = low_dmx_fifo; + else { + highest_dmx_fifo = high_dmx_fifo; + high_dmx_fifo = low_dmx_fifo; + } low_dmx_fifo = &dvb->asyncfifo[i]; } else if (low_dmx_fifo->source < dvb->asyncfifo[i].source) { - high_dmx_fifo = &dvb->asyncfifo[i]; + if (!high_dmx_fifo) + high_dmx_fifo = &dvb->asyncfifo[i]; + else { + if (high_dmx_fifo->source > dvb->asyncfifo[i].source) { + highest_dmx_fifo = high_dmx_fifo; + high_dmx_fifo = &dvb->asyncfifo[i]; + } else { + highest_dmx_fifo = &dvb->asyncfifo[i]; + } + } } break; @@ -3282,8 +3685,12 @@ static void reset_async_fifos(struct aml_dvb *dvb) if (low_dmx_fifo) { async_fifo_set_regs(low_dmx_fifo, 0x3); - if (high_dmx_fifo) + if (high_dmx_fifo) { async_fifo_set_regs(high_dmx_fifo, 0x2); + + if (highest_dmx_fifo) + async_fifo_set_regs(highest_dmx_fifo, 0x0); + } } } @@ -3326,6 +3733,7 @@ void dmx_reset_hw_ex(struct aml_dvb *dvb, int reset_irq) } WRITE_MPEG_REG(STB_TOP_CONFIG, 0); + WRITE_MPEG_REG(STB_S2P2_CONFIG, 0); for (id = 0; id < DMX_DEV_COUNT; id++) { u32 version, data; @@ -3450,28 +3858,9 @@ void dmx_reset_hw_ex(struct aml_dvb *dvb, int reset_irq) /*if(ch->used) */ { ch->id = n; + ch->work_mode = -1; dsc_set_pid(ch, ch->pid); - - if (ch->flags & DSC_SET_EVEN) { - dsc_set_key(ch, 0, - CA_CW_DVB_CSA_EVEN, - ch->even); - } - if (ch->flags & DSC_SET_ODD) { - dsc_set_key(ch, 0, - CA_CW_DVB_CSA_ODD, - ch->odd); - } - if (ch->flags & DSC_SET_AES_EVEN) { - dsc_set_key(ch, 0, - CA_CW_AES_EVEN, - ch->aes_even); - } - if (ch->flags & DSC_SET_AES_ODD) { - dsc_set_key(ch, 0, - CA_CW_AES_ODD, - ch->aes_odd); - } + dsc_set_keys(ch); } } } @@ -3653,28 +4042,9 @@ void dmx_reset_dmx_hw_ex_unlock(struct aml_dvb *dvb, struct aml_dmx *dmx, for (n = 0; n < DSC_COUNT; n++) { struct aml_dsc_channel *ch = &dsc->channel[n]; /*if(ch->used) */ + ch->work_mode = -1; dsc_set_pid(ch, ch->pid); - - if (ch->flags & DSC_SET_EVEN) { - dsc_set_key(ch, 0, - CA_CW_DVB_CSA_EVEN, - ch->even); - } - if (ch->flags & DSC_SET_ODD) { - dsc_set_key(ch, 0, - CA_CW_DVB_CSA_ODD, - ch->odd); - } - if (ch->flags & DSC_SET_AES_EVEN) { - dsc_set_key(ch, 0, - CA_CW_AES_EVEN, - ch->aes_even); - } - if (ch->flags & DSC_SET_AES_ODD) { - dsc_set_key(ch, 0, - CA_CW_AES_ODD, - ch->aes_odd); - } + dsc_set_keys(ch); } } } @@ -3718,6 +4088,7 @@ void dmx_reset_dmx_hw(struct aml_dvb *dvb, int id) } /*Allocate subtitle pes buffer*/ +#if 0 static int alloc_subtitle_pes_buffer(struct aml_dmx *dmx) { int start_ptr = 0; @@ -3747,6 +4118,7 @@ static int alloc_subtitle_pes_buffer(struct aml_dmx *dmx) exit: return 0; } +#endif /*Allocate a new channel*/ int dmx_alloc_chan(struct aml_dmx *dmx, int type, int pes_type, int pid) @@ -3768,7 +4140,7 @@ int dmx_alloc_chan(struct aml_dmx *dmx, int type, int pes_type, int pid) case DMX_PES_TELETEXT: if (!dmx->channel[2].used) id = 2; - alloc_subtitle_pes_buffer(dmx); + //alloc_subtitle_pes_buffer(dmx); break; case DMX_PES_PCR: if (!dmx->channel[3].used) @@ -4351,7 +4723,7 @@ int aml_asyncfifo_hw_init(struct aml_asyncfifo *afifo) */ int ret; - int len = ASYNCFIFO_BUFFER_SIZE_DEFAULT; + int len = asyncfifo_buf_len; unsigned long buf = asyncfifo_alloc_buffer(len); if (!buf) @@ -4401,17 +4773,18 @@ int aml_asyncfifo_hw_reset(struct aml_asyncfifo *afifo) unsigned long flags; int ret, src = -1; - int len = ASYNCFIFO_BUFFER_SIZE_DEFAULT; - unsigned long buf = asyncfifo_alloc_buffer(len); - + unsigned long buf = 0; + int len = asyncfifo_buf_len; + buf = asyncfifo_alloc_buffer(len); if (!buf) return -1; - spin_lock_irqsave(&dvb->slock, flags); if (afifo->init) { src = afifo->source; async_fifo_deinit(afifo, 0); } + + spin_lock_irqsave(&dvb->slock, flags); ret = async_fifo_init(afifo, 0, len, buf); /* restore the source */ if (src != -1) @@ -4494,21 +4867,38 @@ int aml_dmx_hw_set_source(struct dmx_demux *demux, dmx_source_t src) case DMX_SOURCE_FRONT0: hw_src = (dvb->ts[0].mode == - AM_TS_SERIAL) ? AM_TS_SRC_S_TS0 : AM_TS_SRC_TS0; + AM_TS_SERIAL) ? (dvb->ts[0].s2p_id + AM_TS_SRC_S_TS0) : AM_TS_SRC_TS0; break; case DMX_SOURCE_FRONT1: hw_src = (dvb->ts[1].mode == - AM_TS_SERIAL) ? AM_TS_SRC_S_TS1 : AM_TS_SRC_TS1; + AM_TS_SERIAL) ? (dvb->ts[1].s2p_id + AM_TS_SRC_S_TS0) : AM_TS_SRC_TS1; break; case DMX_SOURCE_FRONT2: hw_src = (dvb->ts[2].mode == - AM_TS_SERIAL) ? AM_TS_SRC_S_TS2 : AM_TS_SRC_TS2; + AM_TS_SERIAL) ? (dvb->ts[2].s2p_id + AM_TS_SRC_S_TS0) : AM_TS_SRC_TS2; + break; + case DMX_SOURCE_FRONT3: + hw_src = + (dvb->ts[3].mode == + AM_TS_SERIAL) ? (dvb->ts[3].s2p_id + AM_TS_SRC_S_TS0) : AM_TS_SRC_TS2; break; case DMX_SOURCE_DVR0: hw_src = AM_TS_SRC_HIU; break; + case DMX_SOURCE_DVR1: + hw_src = AM_TS_SRC_HIU1; + break; + case DMX_SOURCE_FRONT0_OFFSET: + hw_src = AM_TS_SRC_DMX0; + break; + case DMX_SOURCE_FRONT1_OFFSET: + hw_src = AM_TS_SRC_DMX1; + break; + case DMX_SOURCE_FRONT2_OFFSET: + hw_src = AM_TS_SRC_DMX2; + break; default: pr_error("illegal demux source %d\n", src); ret = -EINVAL; @@ -4543,21 +4933,29 @@ int aml_stb_hw_set_source(struct aml_dvb *dvb, dmx_source_t src) case DMX_SOURCE_FRONT0: hw_src = (dvb->ts[0].mode == - AM_TS_SERIAL) ? AM_TS_SRC_S_TS0 : AM_TS_SRC_TS0; + AM_TS_SERIAL) ? (dvb->ts[0].s2p_id + AM_TS_SRC_S_TS0) : AM_TS_SRC_TS0; break; case DMX_SOURCE_FRONT1: hw_src = (dvb->ts[1].mode == - AM_TS_SERIAL) ? AM_TS_SRC_S_TS1 : AM_TS_SRC_TS1; + AM_TS_SERIAL) ? (dvb->ts[1].s2p_id + AM_TS_SRC_S_TS0) : AM_TS_SRC_TS1; break; case DMX_SOURCE_FRONT2: hw_src = (dvb->ts[2].mode == - AM_TS_SERIAL) ? AM_TS_SRC_S_TS2 : AM_TS_SRC_TS2; + AM_TS_SERIAL) ? (dvb->ts[2].s2p_id + AM_TS_SRC_S_TS0) : AM_TS_SRC_TS2; + break; + case DMX_SOURCE_FRONT3: + hw_src = + (dvb->ts[3].mode == + AM_TS_SERIAL) ? (dvb->ts[3].s2p_id + AM_TS_SRC_S_TS0) : AM_TS_SRC_TS3; break; case DMX_SOURCE_DVR0: hw_src = AM_TS_SRC_HIU; break; + case DMX_SOURCE_DVR1: + hw_src = AM_TS_SRC_HIU1; + break; case DMX_SOURCE_FRONT0_OFFSET: hw_src = AM_TS_SRC_DMX0; break; @@ -4664,34 +5062,34 @@ int aml_dsc_hw_set_source(struct aml_dsc *dsc, } if (src_reset) { - pr_dbg("dsc%d source changed: %d -> %d\n", + pr_inf("dsc%d source changed: %d -> %d\n", dsc->id, org_src, hw_src); if (org_src != -1) { - pr_dbg("reset dmx%d\n", (org_src - AM_TS_SRC_DMX0)); + pr_inf("reset dmx%d\n", (org_src - AM_TS_SRC_DMX0)); dmx_reset_dmx_id_hw_ex_unlock(dvb, (org_src - AM_TS_SRC_DMX0), 0); } if (hw_src != -1) { - pr_dbg("reset dmx%d\n", (hw_src - AM_TS_SRC_DMX0)); + pr_inf("reset dmx%d\n", (hw_src - AM_TS_SRC_DMX0)); dmx_reset_dmx_id_hw_ex_unlock(dvb, (hw_src - AM_TS_SRC_DMX0), 0); } else dsc_enable(dsc, 0); } if (dst_reset) { - pr_dbg("dsc%d dest changed: %d -> %d\n", + pr_inf("dsc%d dest changed: %d -> %d\n", dsc->id, org_dst, hw_dst); if (((!src_reset) && (org_dst != -1)) || (src_reset && (org_dst != -1) && (org_dst != org_src) && (org_dst != hw_src))) { - pr_dbg("reset dmx%d\n", (org_dst - AM_TS_SRC_DMX0)); + pr_inf("reset dmx%d\n", (org_dst - AM_TS_SRC_DMX0)); dmx_reset_dmx_id_hw_ex_unlock(dvb, (org_dst - AM_TS_SRC_DMX0), 0); } if (((!src_reset) && (hw_dst != -1)) || (src_reset && (hw_dst != -1) && (hw_dst != org_src) && (hw_dst != hw_src))) { - pr_dbg("reset dmx%d\n", (hw_dst - AM_TS_SRC_DMX0)); + pr_inf("reset dmx%d\n", (hw_dst - AM_TS_SRC_DMX0)); dmx_reset_dmx_id_hw_ex_unlock(dvb, (hw_dst - AM_TS_SRC_DMX0), 0); } @@ -4704,47 +5102,6 @@ int aml_dsc_hw_set_source(struct aml_dsc *dsc, return ret; } -int aml_ciplus_hw_set_source(int src) -{ - int hw_src = 0; - int hw_dst = 0; - u32 data; - - switch (src) { - case DMX_SOURCE_FRONT0_OFFSET: - hw_src = 0; - hw_dst = 1; - break; - case DMX_SOURCE_FRONT1_OFFSET: - hw_src = 1; - hw_dst = 2; - break; - case DMX_SOURCE_FRONT2_OFFSET: - hw_src = 2; - hw_dst = 4; - break; - default: - return -1; - } - - data = READ_MPEG_REG(STB_TOP_CONFIG); - - /* Set ciplus input source , - * output set 0 means no output. ---> need confirm. - * if output set 0 still affects dsc output, we need to disable - * ciplus module. - */ - data &= ~(3<ts[0].mode == AM_TS_SERIAL) - ? AM_TS_SRC_S_TS0 : AM_TS_SRC_TS0; + ? (dvb->ts[0].s2p_id + AM_TS_SRC_S_TS0) : AM_TS_SRC_TS0; break; case DMX_SOURCE_FRONT1: hw_src = (dvb->ts[1].mode == AM_TS_SERIAL) - ? AM_TS_SRC_S_TS1 : AM_TS_SRC_TS1; + ? (dvb->ts[1].s2p_id + AM_TS_SRC_S_TS0) : AM_TS_SRC_TS1; break; case DMX_SOURCE_FRONT2: hw_src = (dvb->ts[2].mode == AM_TS_SERIAL) - ? AM_TS_SRC_S_TS2 : AM_TS_SRC_TS2; + ? (dvb->ts[2].s2p_id + AM_TS_SRC_S_TS0) : AM_TS_SRC_TS2; + break; + case DMX_SOURCE_FRONT3: + hw_src = (dvb->ts[3].mode == AM_TS_SERIAL) + ? (dvb->ts[3].s2p_id + AM_TS_SRC_S_TS0) : AM_TS_SRC_TS3; break; case DMX_SOURCE_DVR0: hw_src = AM_TS_SRC_HIU; @@ -4877,6 +5238,29 @@ u32 aml_dmx_get_audio_pts(struct aml_dvb *dvb) return pts; } +u32 aml_dmx_get_video_pts_bit32(struct aml_dvb *dvb) +{ + unsigned long flags; + u32 bit32; + + spin_lock_irqsave(&dvb->slock, flags); + bit32 = video_pts_bit32; + spin_unlock_irqrestore(&dvb->slock, flags); + + return bit32; +} + +u32 aml_dmx_get_audio_pts_bit32(struct aml_dvb *dvb) +{ + unsigned long flags; + u32 bit32; + + spin_lock_irqsave(&dvb->slock, flags); + bit32 = audio_pts_bit32; + spin_unlock_irqrestore(&dvb->slock, flags); + + return bit32; +} u32 aml_dmx_get_first_video_pts(struct aml_dvb *dvb) { unsigned long flags; @@ -5048,22 +5432,29 @@ static ssize_t ciplus_output_ctrl_show(struct class *class, char *buf) { int ret; + char *out = "none"; - pr_error("output demux use 3 bit to indicate. "); - pr_error("1bit:demux0 2bit:demux1 3bit:demux2\n"); - if (ciplus_out_auto_mode == 1) - ret = sprintf(buf, "Using auto mode, value: %x\n", - ciplus_out_sel); - else - ret = sprintf(buf, "%d\n", ciplus_out_sel); - pr_error("ciplus output path:\n"); - if (ciplus_out_sel&1) - pr_error("demux0 "); - if (ciplus_out_sel&1<<1) - pr_error("demux1 "); - if (ciplus_out_sel&1<<2) - pr_error("demux2 "); - pr_error("\n"); + pr_inf("output demux use 3 bit to indicate.\n"); + pr_inf("1bit:demux0 2bit:demux1 3bit:demux2\n"); + + switch (ciplus_out_sel) { + case 1: + out = "dmx0"; + break; + case 2: + out = "dmx1"; + break; + case 4: + out = "dmx2"; + break; + default: + break; + } + + ret = sprintf(buf, "%s 0x%x %s\n", + out, + ciplus_out_sel, + (ciplus_out_auto_mode) ? "" : "(force)"); return ret; } @@ -5073,9 +5464,6 @@ static ssize_t ciplus_output_ctrl_store(struct class *class, { int i, tmp; - pr_error("output demux use 3 bit to indicate. "); - pr_error("1bit:demux0 2bit:demux1 3bit:demux2, 8 for auto\n"); - /*i = sscanf(buf, "%d", &tmp); */ i = kstrtoint(buf, -1, &tmp); if (tmp > 8 || tmp < 0) pr_error("Invalid output set\n"); diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/aml_dvb.c b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/aml_dvb.c index 1c882ff1e6cc..b3ffbb7cefa6 100644 --- a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/aml_dvb.c +++ b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/aml_dvb.c @@ -1,3 +1,22 @@ +/* +* 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. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ /* * AMLOGIC DVB driver. */ @@ -44,6 +63,7 @@ typedef enum __demod_type DEMOD_INVALID, DEMOD_INTERNAL, DEMOD_ATBM8881, + DEMOD_SI2168, DEMOD_MAX_NUM }demod_type; @@ -53,6 +73,8 @@ typedef enum __tuner_type TUNER_SI2151, TUNER_MXL661, TUNER_SI2159, + TUNER_R842, + TUNER_R840, TUNER_MAX_NUM }tuner_type; @@ -120,6 +142,65 @@ static struct tsdemux_ops aml_tsdemux_ops = { .set_demux = aml_tsdemux_set_demux }; +static int dvb_attach_tuner(struct dvb_frontend *fe, struct aml_tuner *tuner, tuner_type *type) +{ + struct tuner_config *cfg = &tuner->cfg; + struct i2c_adapter *i2c_adap = tuner->i2c_adp; + + switch (cfg->id) { + case AM_TUNER_R840: + if (!dvb_attach(r840_attach, fe, i2c_adap, cfg)) { + pr_error("dvb attach r840_attach tuner error\n"); + return -1; + } else { + pr_inf("r840_attach attach sucess\n"); + *type = TUNER_R840; + } + break; + case AM_TUNER_R842: + if (!dvb_attach(r842_attach, fe, i2c_adap, cfg)) { + pr_error("dvb attach r842_attach tuner error\n"); + return -1; + } else { + pr_inf("r842_attach attach sucess\n"); + *type = TUNER_R842; + } + break; + case AM_TUNER_SI2151: + if (!dvb_attach(si2151_attach, fe, i2c_adap, cfg)) { + pr_error("dvb attach tuner error\n"); + return -1; + } else { + pr_inf("si2151 attach sucess\n"); + *type = TUNER_SI2151; + } + break; + case AM_TUNER_SI2159: + if (!dvb_attach(si2159_attach, fe, i2c_adap, cfg)) { + pr_error("dvb attach si2159_attach tuner error\n"); + return -1; + } else { + pr_inf("si2159_attach attach sucess\n"); + *type = TUNER_SI2159; + } + break; + case AM_TUNER_MXL661: + if (!dvb_attach(mxl661_attach, fe, i2c_adap, cfg)) { + pr_error("dvb attach mxl661_attach tuner error\n"); + return -1; + } else { + pr_inf("mxl661_attach attach sucess\n"); + *type = TUNER_MXL661; + } + break; + default: + pr_error("can't support tuner type: %d\n", cfg->id); + break; + } + + return 0; +} + long aml_stb_get_base(int id) { int newbase = 0; @@ -135,6 +216,8 @@ long aml_stb_get_base(int id) return (newbase) ? 0x9400 : 0x2110; case ID_ASYNC_FIFO_REG_BASE: return (newbase) ? 0x2800 : 0x2310; + case ID_ASYNC_FIFO1_REG_BASE: + return 0x9800; case ID_ASYNC_FIFO2_REG_BASE: return (newbase) ? 0x2400 : 0x2314; case ID_RESET_BASE: @@ -317,9 +400,9 @@ static void dsc_channel_alloc(struct aml_dsc *dsc, int id, unsigned int pid) ch->work_mode = -1; ch->id = id; ch->pid = pid; - ch->flags = 0; + ch->set = 0; ch->dsc = dsc; - ch->aes_mode = -1; + ch->mode = -1; dsc_set_pid(ch, ch->pid); } @@ -334,9 +417,9 @@ static void dsc_channel_free(struct aml_dsc_channel *ch) dsc_release(); ch->pid = 0x1fff; - ch->flags = 0; + ch->set = 0; ch->work_mode = -1; - ch->aes_mode = -1; + ch->mode = -1; } static void dsc_reset(struct aml_dsc *dsc) @@ -349,15 +432,26 @@ static void dsc_reset(struct aml_dsc *dsc) static int get_dsc_key_work_mode(enum ca_cw_type cw_type) { - int work_mode = 0; + int work_mode = DVBCSA_MODE; - if (cw_type == CA_CW_DVB_CSA_EVEN || cw_type == CA_CW_DVB_CSA_ODD) + switch (cw_type) { + case CA_CW_DVB_CSA_EVEN: + case CA_CW_DVB_CSA_ODD: work_mode = DVBCSA_MODE; - else if (cw_type == CA_CW_AES_EVEN || - cw_type == CA_CW_AES_ODD || - cw_type == CA_CW_AES_EVEN_IV || - cw_type == CA_CW_AES_ODD_IV) { + break; + case CA_CW_AES_EVEN: + case CA_CW_AES_ODD: + case CA_CW_AES_ODD_IV: + case CA_CW_AES_EVEN_IV: + case CA_CW_DES_EVEN: + case CA_CW_DES_ODD: + case CA_CW_SM4_EVEN: + case CA_CW_SM4_ODD: + case CA_CW_SM4_ODD_IV: + case CA_CW_SM4_EVEN_IV: work_mode = CIPLUS_MODE; + default: + break; } return work_mode; } @@ -385,6 +479,8 @@ static void dsc_ciplus_switch_check(struct aml_dsc_channel *ch, pr_error("Dsc work mode changed,"); pr_error("but there are still some channels"); pr_error("run in different mode\n"); + pr_error("mod_pre[%d] -> mod[%d] ch[%d]\n", + pch->work_mode, work_mode, i); } } } @@ -400,32 +496,36 @@ static int dsc_set_cw(struct aml_dsc *dsc, struct ca_descr_ex *d) switch (d->type) { case CA_CW_DVB_CSA_EVEN: - memcpy(ch->even, d->cw, 8); - ch->flags &= ~(DSC_SET_AES_EVEN|DSC_SET_AES_ODD); - ch->flags |= DSC_SET_EVEN; + case CA_CW_AES_EVEN: + case CA_CW_DES_EVEN: + case CA_CW_SM4_EVEN: + memcpy(ch->even, d->cw, DSC_KEY_SIZE_MAX); break; case CA_CW_DVB_CSA_ODD: - memcpy(ch->odd, d->cw, 8); - ch->flags &= ~(DSC_SET_AES_EVEN|DSC_SET_AES_ODD); - ch->flags |= DSC_SET_ODD; - break; - case CA_CW_AES_EVEN: - memcpy(ch->aes_even, d->cw, 16); - ch->flags &= ~(DSC_SET_EVEN|DSC_SET_ODD); - ch->flags |= DSC_SET_AES_EVEN; - break; case CA_CW_AES_ODD: - memcpy(ch->aes_odd, d->cw, 16); - ch->flags &= ~(DSC_SET_EVEN|DSC_SET_ODD); - ch->flags |= DSC_SET_AES_ODD; + case CA_CW_DES_ODD: + case CA_CW_SM4_ODD: + memcpy(ch->odd, d->cw, DSC_KEY_SIZE_MAX); + break; + case CA_CW_AES_EVEN_IV: + case CA_CW_SM4_EVEN_IV: + memcpy(ch->even_iv, d->cw, DSC_KEY_SIZE_MAX); + break; + case CA_CW_AES_ODD_IV: + case CA_CW_SM4_ODD_IV: + memcpy(ch->odd_iv, d->cw, DSC_KEY_SIZE_MAX); break; default: break; } - if (d->flags & CA_CW_FROM_KL) - ch->flags = DSC_FROM_KL; + ch->set |= (1 << d->type) | (d->flags << 24); + if (d->mode == CA_DSC_IDSA) { + ch->mode = IDSA_MODE; + } + + /*do key set*/ dsc_set_key(ch, d->flags, d->type, d->cw); dsc_ciplus_switch_check(ch, d->type); @@ -478,6 +578,7 @@ static int dvb_dsc_do_ioctl(struct file *file, unsigned int cmd, dex.index = d->index; dex.type = d->parity ? CA_CW_DVB_CSA_ODD : CA_CW_DVB_CSA_EVEN; + dex.mode = -1; dex.flags = 0; memcpy(dex.cw, d->cw, sizeof(d->cw)); @@ -656,6 +757,8 @@ static int aml_dvb_asyncfifo_init(struct aml_dvb *advb, if (id == 0) asyncfifo->asyncfifo_irq = INT_ASYNC_FIFO_FLUSH; + else if(id == 2) + asyncfifo->asyncfifo_irq = INT_ASYNC_FIFO3_FLUSH; else asyncfifo->asyncfifo_irq = INT_ASYNC_FIFO2_FLUSH; @@ -668,6 +771,9 @@ static int aml_dvb_asyncfifo_init(struct aml_dvb *advb, asyncfifo->id = id; asyncfifo->init = 0; asyncfifo->flush_size = 256 * 1024; + asyncfifo->secure_enable = 0; + asyncfifo->blk.addr = 0; + asyncfifo->blk.len = 0; return aml_asyncfifo_hw_init(asyncfifo); } @@ -685,7 +791,7 @@ static int aml_dvb_dsc_init(struct aml_dvb *advb, for (i = 0; i < DSC_COUNT; i++) { dsc->channel[i].id = i; dsc->channel[i].used = 0; - dsc->channel[i].flags = 0; + dsc->channel[i].set = 0; dsc->channel[i].pid = 0x1fff; dsc->channel[i].dsc = dsc; } @@ -728,9 +834,15 @@ static ssize_t stb_show_source(struct class *class, case AM_TS_SRC_S_TS2: src = "ts2"; break; + case AM_TS_SRC_TS3: + src = "ts3"; + break; case AM_TS_SRC_HIU: src = "hiu"; break; + case AM_TS_SRC_HIU1: + src = "hiu1"; + break; case AM_TS_SRC_DMX0: src = "dmx0"; break; @@ -749,6 +861,20 @@ static ssize_t stb_show_source(struct class *class, return ret; } +static ssize_t stb_clear_av(struct class *class, + struct class_attribute *attr, const char *buf, + size_t size) +{ + if (!strncmp("1", buf, 1)) { + aml_tsdemux_set_vid(0x1fff); + aml_tsdemux_set_aid(0x1fff); + aml_tsdemux_set_sid(0x1fff); + aml_tsdemux_set_pcrid(0x1fff); + } + + return size; +} + /*Set the STB input source*/ static ssize_t stb_store_source(struct class *class, struct class_attribute *attr, const char *buf, @@ -762,6 +888,10 @@ static ssize_t stb_store_source(struct class *class, src = DMX_SOURCE_FRONT1; else if (!strncmp("ts2", buf, 3)) src = DMX_SOURCE_FRONT2; + else if (!strncmp("ts3", buf, 3)) + src = DMX_SOURCE_FRONT3; + else if (!strncmp("hiu1", buf, 4)) + src = DMX_SOURCE_DVR1; else if (!strncmp("hiu", buf, 3)) src = DMX_SOURCE_DVR0; else if (!strncmp("dmx0", buf, 4)) @@ -842,8 +972,6 @@ static ssize_t dsc##i##_store_source(struct class *class, \ else \ dst = src; \ aml_dsc_hw_set_source(&aml_dvb_device.dsc[i], src, dst);\ - if (i == 0) \ - aml_ciplus_hw_set_source(src); \ return size;\ } @@ -899,6 +1027,9 @@ static ssize_t tso_show_source(struct class *class, case AM_TS_SRC_S_TS2: src = "ts2"; break; + case AM_TS_SRC_TS3: + src = "ts3"; + break; case AM_TS_SRC_HIU: src = "hiu"; break; @@ -933,6 +1064,8 @@ static ssize_t tso_store_source(struct class *class, src = DMX_SOURCE_FRONT1; else if (!strncmp("ts2", buf, 3)) src = DMX_SOURCE_FRONT2; + else if (!strncmp("ts3", buf, 3)) + src = DMX_SOURCE_FRONT3; else if (!strncmp("hiu", buf, 3)) src = DMX_SOURCE_DVR0; else if (!strncmp("dmx0", buf, 4)) @@ -984,9 +1117,21 @@ static ssize_t demux##i##_show_source(struct class *class, \ CASE_PREFIX case AM_TS_SRC_S_TS2:\ src = "ts2";\ break;\ + CASE_PREFIX case AM_TS_SRC_DMX0:\ + src = "dmx0";\ + break;\ + CASE_PREFIX case AM_TS_SRC_DMX1:\ + src = "dmx1";\ + break;\ + CASE_PREFIX case AM_TS_SRC_DMX2:\ + src = "dmx2";\ + break;\ CASE_PREFIX case AM_TS_SRC_HIU:\ src = "hiu";\ break;\ + CASE_PREFIX case AM_TS_SRC_HIU1:\ + src = "hiu1";\ + break;\ CASE_PREFIX default :\ src = "";\ break;\ @@ -1005,8 +1150,16 @@ static ssize_t demux##i##_store_source(struct class *class, \ src = DMX_SOURCE_FRONT1;\ } else if (!strncmp("ts2", buf, 3)) {\ src = DMX_SOURCE_FRONT2;\ + } else if (!strncmp("hiu1", buf, 4)) {\ + src = DMX_SOURCE_DVR1;\ } else if (!strncmp("hiu", buf, 3)) {\ src = DMX_SOURCE_DVR0;\ + } else if (!strncmp("dmx0", buf, 4)) {\ + src = DMX_SOURCE_FRONT0_OFFSET;\ + } else if (!strncmp("dmx1", buf, 4)) {\ + src = DMX_SOURCE_FRONT1_OFFSET;\ + } else if (!strncmp("dmx2", buf, 4)) {\ + src = DMX_SOURCE_FRONT2_OFFSET;\ } \ if (src != -1) {\ aml_dmx_hw_set_source(aml_dvb_device.dmx[i].dmxdev.demux, src);\ @@ -1201,6 +1354,8 @@ static ssize_t asyncfifo##i##_show_source(struct class *class, \ struct aml_asyncfifo *afifo = &dvb->asyncfifo[i];\ ssize_t ret = 0;\ char *src;\ + if (dvb->async_fifo_total_count <= i)\ + return ret;\ switch (afifo->source) {\ CASE_PREFIX case AM_DMX_0:\ src = "dmx0";\ @@ -1223,6 +1378,8 @@ static ssize_t asyncfifo##i##_store_source(struct class *class, \ {\ enum aml_dmx_id_t src = -1;\ \ + if (aml_dvb_device.async_fifo_total_count <= i)\ + return 0;\ if (!strncmp("dmx0", buf, 4)) {\ src = AM_DMX_0;\ } else if (!strncmp("dmx1", buf, 4)) {\ @@ -1242,6 +1399,11 @@ ASYNCFIFO_SOURCE_FUNC_DECL(0) #if ASYNCFIFO_COUNT > 1 ASYNCFIFO_SOURCE_FUNC_DECL(1) #endif + +#if ASYNCFIFO_COUNT > 2 + ASYNCFIFO_SOURCE_FUNC_DECL(2) +#endif + /*Show the async fifo flush size*/ #define ASYNCFIFO_FLUSHSIZE_FUNC_DECL(i) \ static ssize_t asyncfifo##i##_show_flush_size(struct class *class, \ @@ -1250,6 +1412,8 @@ static ssize_t asyncfifo##i##_show_flush_size(struct class *class, \ struct aml_dvb *dvb = &aml_dvb_device;\ struct aml_asyncfifo *afifo = &dvb->asyncfifo[i];\ ssize_t ret = 0;\ + if (dvb->async_fifo_total_count <= i)\ + return ret;\ ret = sprintf(buf, "%d\n", afifo->flush_size);\ return ret;\ } \ @@ -1262,7 +1426,10 @@ static ssize_t asyncfifo##i##_store_flush_size(struct class *class, \ /*int fsize = simple_strtol(buf, NULL, 10);*/\ int fsize = 0;\ long value;\ - int ret = kstrtol(buf, 0, &value);\ + int ret =0;\ + if (dvb->async_fifo_total_count <= i)\ + return (size_t)0;\ + ret = kstrtol(buf, 0, &value);\ if (ret == 0)\ fsize = value;\ if (fsize != afifo->flush_size) {\ @@ -1279,6 +1446,101 @@ ASYNCFIFO_FLUSHSIZE_FUNC_DECL(0) #if ASYNCFIFO_COUNT > 1 ASYNCFIFO_FLUSHSIZE_FUNC_DECL(1) #endif + +#if ASYNCFIFO_COUNT > 2 + ASYNCFIFO_FLUSHSIZE_FUNC_DECL(2) +#endif + +/*Show the async fifo secure buffer addr*/ +#define ASYNCFIFO_SECUREADDR_FUNC_DECL(i) \ +static ssize_t asyncfifo##i##_show_secure_addr(struct class *class, \ + struct class_attribute *attr, char *buf)\ +{\ + struct aml_dvb *dvb = &aml_dvb_device;\ + struct aml_asyncfifo *afifo = &dvb->asyncfifo[i];\ + ssize_t ret = 0;\ + if (dvb->async_fifo_total_count <= i)\ + return ret;\ + ret = sprintf(buf, "0x%x\n", afifo->blk.addr);\ + return ret;\ +} \ +static ssize_t asyncfifo##i##_store_secure_addr(struct class *class, \ + struct class_attribute *attr, \ +const char *buf, size_t size)\ +{\ + struct aml_dvb *dvb = &aml_dvb_device;\ + struct aml_asyncfifo *afifo = &dvb->asyncfifo[i];\ + unsigned long value;\ + int ret=0;\ + if (dvb->async_fifo_total_count <= i)\ + return (size_t)0;\ + ret = kstrtol(buf, 0, &value);\ + if (ret == 0 && value != afifo->blk.addr) {\ + afifo->blk.addr = value;\ + aml_asyncfifo_hw_reset(&aml_dvb_device.asyncfifo[i]);\ + } \ + return size;\ +} + +#if ASYNCFIFO_COUNT > 0 + ASYNCFIFO_SECUREADDR_FUNC_DECL(0) +#endif + +#if ASYNCFIFO_COUNT > 1 + ASYNCFIFO_SECUREADDR_FUNC_DECL(1) +#endif + +#if ASYNCFIFO_COUNT > 2 + ASYNCFIFO_SECUREADDR_FUNC_DECL(2) +#endif + + +/*Show the async fifo secure enable*/ +#define ASYNCFIFO_SECURENABLE_FUNC_DECL(i) \ +static ssize_t asyncfifo##i##_show_secure_enable(struct class *class, \ + struct class_attribute *attr, char *buf)\ +{\ + struct aml_dvb *dvb = &aml_dvb_device;\ + struct aml_asyncfifo *afifo = &dvb->asyncfifo[i];\ + ssize_t ret = 0;\ + if (dvb->async_fifo_total_count <= i)\ + return ret;\ + ret = sprintf(buf, "%d\n", afifo->secure_enable);\ + return ret;\ +} \ +static ssize_t asyncfifo##i##_store_secure_enable(struct class *class, \ + struct class_attribute *attr, \ + const char *buf, size_t size)\ +{\ + struct aml_dvb *dvb = &aml_dvb_device;\ + struct aml_asyncfifo *afifo = &dvb->asyncfifo[i];\ + int enable = 0;\ + long value;\ + int ret=0;\ + if (dvb->async_fifo_total_count <= i)\ + return (size_t)0;\ + ret = kstrtol(buf, 0, &value);\ + if (ret == 0)\ + enable = value;\ + if (enable != afifo->secure_enable) {\ + afifo->secure_enable = enable;\ + aml_asyncfifo_hw_reset(&aml_dvb_device.asyncfifo[i]);\ + } \ + return size;\ +} + +#if ASYNCFIFO_COUNT > 0 +ASYNCFIFO_SECURENABLE_FUNC_DECL(0) +#endif + +#if ASYNCFIFO_COUNT > 1 + ASYNCFIFO_SECURENABLE_FUNC_DECL(1) +#endif + +#if ASYNCFIFO_COUNT > 2 + ASYNCFIFO_SECURENABLE_FUNC_DECL(2) +#endif + /*Reset the Demux*/ static ssize_t demux_do_reset(struct class *class, struct class_attribute *attr, @@ -1321,6 +1583,31 @@ static ssize_t demux_show_audio_pts(struct class *class, return ret; } +/*Show the Video PTS bit32 value*/ +static ssize_t demux_show_video_pts_bit32(struct class *class, + struct class_attribute *attr, char *buf) +{ + struct aml_dvb *dvb = &aml_dvb_device; + ssize_t ret = 0; + + ret = sprintf(buf, "%u\n", aml_dmx_get_video_pts_bit32(dvb)); + + return ret; +} + +/*Show the Audio PTS bit32 value*/ +static ssize_t demux_show_audio_pts_bit32(struct class *class, + struct class_attribute *attr, char *buf) +{ + struct aml_dvb *dvb = &aml_dvb_device; + ssize_t ret = 0; + + ret = sprintf(buf, "%u\n", aml_dmx_get_audio_pts_bit32(dvb)); + + return ret; +} + + /*Show the First Video PTS value*/ static ssize_t demux_show_first_video_pts(struct class *class, struct class_attribute *attr, @@ -1355,7 +1642,7 @@ static ssize_t stb_show_hw_setting(struct class *class, struct aml_dvb *dvb = &aml_dvb_device; int invert, ctrl; - for (i = 0; i < TS_IN_COUNT; i++) { + for (i = 0; i < dvb->ts_in_total_count; i++) { struct aml_ts_input *ts = &dvb->ts[i]; if (ts->s2p_id != -1) @@ -1391,7 +1678,7 @@ static ssize_t stb_store_hw_setting(struct class *class, if (r != 4) return -EINVAL; - if (id < 0 || id >= TS_IN_COUNT) + if (id < 0 || id >= dvb->ts_in_total_count) return -EINVAL; if ((mname[0] == 's') || (mname[0] == 'S')) { @@ -1411,12 +1698,12 @@ static ssize_t stb_store_hw_setting(struct class *class, int i; int scnt = 0; - for (i = 0; i < TS_IN_COUNT; i++) { + for (i = 0; i < dvb->ts_in_total_count; i++) { if (dvb->ts[i].s2p_id != -1) scnt++; } - if (scnt >= S2P_COUNT) + if (scnt >= dvb->s2p_total_count) pr_error("no free s2p\n"); else ts->s2p_id = scnt; @@ -1445,6 +1732,82 @@ static ssize_t stb_store_hw_setting(struct class *class, return count; } +static ssize_t stb_show_tuner_setting(struct class *class, + struct class_attribute *attr, char *buf) +{ + struct aml_dvb *dvb = &aml_dvb_device; + + if (dvb->tuner_cur >= 0) + pr_inf("dvb current attatch tuner %d, id: %d\n", + dvb->tuner_cur, dvb->tuners[dvb->tuner_cur].cfg.id); + else + pr_inf("dvb has no attatch tuner.\n"); + + return 0; +} + +static ssize_t stb_store_tuner_setting(struct class *class, + struct class_attribute *attr, + const char *buf, size_t count) +{ + int n = 0, i = 0, val = 0; + unsigned long tmp = 0; + char *buf_orig = NULL, *ps = NULL, *token = NULL; + char *parm[4] = { NULL }; + struct aml_dvb *dvb = &aml_dvb_device; + int tuner_id = 0; + struct aml_tuner *tuner = NULL; + + buf_orig = kstrdup(buf, GFP_KERNEL); + ps = buf_orig; + + while (1) { + token = strsep(&ps, "\n "); + if (token == NULL) + break; + if (*token == '\0') + continue; + parm[n++] = token; + } + + if (parm[0] && kstrtoul(parm[0], 10, &tmp) == 0) { + val = tmp; + + for (i = 0; i < dvb->tuner_num; ++i) { + if (dvb->tuners[i].cfg.id == val) { + tuner_id = dvb->tuners[i].cfg.id; + break; + } + } + + if (tuner_id == 0 || dvb->tuner_cur == i) { + pr_error("%s: set nonsupport or the same tuner %d.\n", + __func__, val); + goto EXIT; + } + + dvb->tuner_cur = i; + + for (i = 0; i < FE_DEV_COUNT; i++) { + tuner = &dvb->tuners[dvb->tuner_cur]; + + if (frontend[i] == NULL) + continue; + + if (dvb_attach_tuner(frontend[i], tuner, &s_tuner_type[i]) < 0) { + pr_error("attach tuner %d failed\n", dvb->tuner_cur); + goto EXIT; + } + } + + pr_error("%s: attach tuner %d done.\n", __func__, dvb->tuners[dvb->tuner_cur].cfg.id); + } + +EXIT: + + return count; +} + static struct class_attribute aml_stb_class_attrs[] = { __ATTR(hw_setting, 0664, stb_show_hw_setting, stb_store_hw_setting), @@ -1514,13 +1877,33 @@ static struct class_attribute aml_stb_class_attrs[] = { __ATTR(asyncfifo##i##_flush_size, 0664,\ asyncfifo##i##_show_flush_size, \ asyncfifo##i##_store_flush_size) +#define ASYNCFIFO_SECUREADDR_ATTR_DECL(i)\ + __ATTR(asyncfifo##i##_secure_addr, S_IRUGO | S_IWUSR | S_IWGRP,\ + asyncfifo##i##_show_secure_addr, \ + asyncfifo##i##_store_secure_addr) +#define ASYNCFIFO_SECURENABLE_ATTR_DECL(i)\ + __ATTR(asyncfifo##i##_secure_enable, S_IRUGO | S_IWUSR | S_IWGRP,\ + asyncfifo##i##_show_secure_enable, \ + asyncfifo##i##_store_secure_enable) + #if ASYNCFIFO_COUNT > 0 ASYNCFIFO_SOURCE_ATTR_DECL(0), ASYNCFIFO_FLUSHSIZE_ATTR_DECL(0), + ASYNCFIFO_SECUREADDR_ATTR_DECL(0), + ASYNCFIFO_SECURENABLE_ATTR_DECL(0), #endif #if ASYNCFIFO_COUNT > 1 ASYNCFIFO_SOURCE_ATTR_DECL(1), ASYNCFIFO_FLUSHSIZE_ATTR_DECL(1), + ASYNCFIFO_SECUREADDR_ATTR_DECL(1), + ASYNCFIFO_SECURENABLE_ATTR_DECL(1), +#endif + +#if ASYNCFIFO_COUNT > 2 + ASYNCFIFO_SOURCE_ATTR_DECL(2), + ASYNCFIFO_FLUSHSIZE_ATTR_DECL(2), + ASYNCFIFO_SECUREADDR_ATTR_DECL(2), + ASYNCFIFO_SECURENABLE_ATTR_DECL(2), #endif __ATTR(demux_reset, 0644, NULL, demux_do_reset), @@ -1528,10 +1911,13 @@ static struct class_attribute aml_stb_class_attrs[] = { NULL), __ATTR(audio_pts, 0664, demux_show_audio_pts, NULL), + __ATTR(video_pts_bit32, 0644, demux_show_video_pts_bit32, NULL), + __ATTR(audio_pts_bit32, 0644, demux_show_audio_pts_bit32, NULL), __ATTR(first_video_pts, 0644, demux_show_first_video_pts, NULL), __ATTR(first_audio_pts, 0644, demux_show_first_audio_pts, NULL), + __ATTR(clear_av, 0644, NULL, stb_clear_av), #define DSC_SOURCE_ATTR_DECL(i)\ __ATTR(dsc##i##_source, 0664,\ @@ -1549,6 +1935,8 @@ static struct class_attribute aml_stb_class_attrs[] = { DSC_FREE_ATTR_DECL(1), #endif + __ATTR(tuner_setting, 0664, stb_show_tuner_setting, stb_store_tuner_setting), + __ATTR_NULL }; @@ -1577,7 +1965,7 @@ static int aml_dvb_probe(struct platform_device *pdev) int i, ret = 0; struct devio_aml_platform_data *pd_dvb; - pr_inf("probe amlogic dvb driver\n"); + pr_dbg("probe amlogic dvb driver\n"); /*switch_mod_gate_by_name("demux", 1); */ #if 0 @@ -1642,6 +2030,16 @@ static int aml_dvb_probe(struct platform_device *pdev) amports_switch_gate("demux", 1); amports_switch_gate("ahbarb0", 1); amports_switch_gate("parser_top", 1); + if (get_cpu_type() == MESON_CPU_MAJOR_ID_TL1) + { + aml_dvb_afifo_clk = + devm_clk_get(&pdev->dev, "asyncfifo"); + if (IS_ERR_OR_NULL(aml_dvb_afifo_clk)) { + dev_err(&pdev->dev, "get asyncfifo clk fail\n"); + return -1; + } + clk_prepare_enable(aml_dvb_afifo_clk); + } } #endif advb = &aml_dvb_device; @@ -1654,6 +2052,16 @@ static int aml_dvb_probe(struct platform_device *pdev) advb->stb_source = -1; advb->tso_source = -1; + if (get_cpu_type() < MESON_CPU_MAJOR_ID_TL1) { + advb->ts_in_total_count = 3; + advb->s2p_total_count = 2; + advb->async_fifo_total_count = 2; + } else { + advb->ts_in_total_count = 4; + advb->s2p_total_count = 3; + advb->async_fifo_total_count = 3; + } + for (i = 0; i < DMX_DEV_COUNT; i++) { advb->dmx[i].dmx_irq = -1; advb->dmx[i].dvr_irq = -1; @@ -1666,7 +2074,7 @@ static int aml_dvb_probe(struct platform_device *pdev) const char *str; u32 value; - for (i = 0; i < TS_IN_COUNT; i++) { + for (i = 0; i < advb->ts_in_total_count; i++) { advb->ts[i].mode = AM_TS_DISABLE; advb->ts[i].s2p_id = -1; @@ -1680,7 +2088,7 @@ static int aml_dvb_probe(struct platform_device *pdev) if (!strcmp(str, "serial")) { pr_inf("%s: serial\n", buf); - if (s2p_id >= S2P_COUNT) + if (s2p_id >= advb->s2p_total_count) pr_error("no free s2p\n"); else { snprintf(buf, sizeof(buf), @@ -1760,10 +2168,9 @@ static int aml_dvb_probe(struct platform_device *pdev) for (i = 0; idsc[i].id = -1; - if (get_cpu_type() < MESON_CPU_MAJOR_ID_G12A) { - for (i = 0; i < ASYNCFIFO_COUNT; i++) - advb->asyncfifo[i].id = -1; - } + for (i = 0; i < advb->async_fifo_total_count; i++) + advb->asyncfifo[i].id = -1; + advb->dvb_adapter.priv = advb; dev_set_drvdata(advb->dev, advb); @@ -1778,15 +2185,14 @@ static int aml_dvb_probe(struct platform_device *pdev) if (ret < 0) goto error; } - if (get_cpu_type() < MESON_CPU_MAJOR_ID_G12A) - { - /*Init the async fifos */ - for (i = 0; i < ASYNCFIFO_COUNT; i++) { - ret = aml_dvb_asyncfifo_init(advb, &advb->asyncfifo[i], i); - if (ret < 0) - goto error; - } + + /*Init the async fifos */ + for (i = 0; i < advb->async_fifo_total_count; i++) { + ret = aml_dvb_asyncfifo_init(advb, &advb->asyncfifo[i], i); + if (ret < 0) + goto error; } + aml_regist_dmx_class(); if (class_register(&aml_stb_class) < 0) { @@ -1803,11 +2209,13 @@ static int aml_dvb_probe(struct platform_device *pdev) //pengcc add for dvb using linux TV frontend api init { struct amlfe_exp_config config; - struct i2c_adapter *i2c_adapter = NULL; char buf[32]; const char *str = NULL; + struct device_node *node_tuner = NULL; struct device_node *node_i2c = NULL; u32 i2c_addr = 0xFFFFFFFF; + u32 value = 0; + int j = 0; for (i=0; idev.of_node, buf, &str); - if (ret) { - // pr_error("tuner%d type error\n",i); - ret = 0; - continue; - } - memset(buf, 0, 32); - snprintf(buf, sizeof(buf), "fe%d_i2c_adap_id",i); - node_i2c = of_parse_phandle(pdev->dev.of_node,buf,0); - if (!node_i2c) { - pr_error("tuner_i2c_adap_id error\n"); - } else { - i2c_adapter = of_find_i2c_adapter_by_node(node_i2c); - of_node_put(node_i2c); - if (i2c_adapter == NULL) { - pr_error("i2c_get_adapter error\n"); - goto error_fe; - } + node_tuner = of_parse_phandle(pdev->dev.of_node, buf, 0); + if (!node_tuner) { + pr_err("can't find tuner.\n"); + goto error_fe; } - memset(buf, 0, 32); - snprintf(buf, sizeof(buf), "fe%d_tuner_i2c_addr",i); - ret = of_property_read_u32(pdev->dev.of_node, buf,&i2c_addr); + ret = of_property_read_u32(node_tuner, "tuner_num", &value); if (ret) { - pr_error("i2c_addr error\n"); + pr_err("can't find tuner_num.\n"); + goto error_fe; + } else + advb->tuner_num = value; + + advb->tuners = kzalloc(sizeof(struct aml_tuner) * advb->tuner_num, GFP_KERNEL); + if (!advb->tuners) { + pr_err("can't kzalloc for tuners.\n"); + goto error_fe; } + + ret = of_property_read_u32(node_tuner, "tuner_cur", &value); + if (ret) { + pr_err("can't find tuner_cur, use default 0.\n"); + advb->tuner_cur = -1; + } else + advb->tuner_cur = value; + + for (j = 0; j < advb->tuner_num; ++j) { + snprintf(buf, sizeof(buf), "tuner_name_%d", j); + ret = of_property_read_string(node_tuner, buf, &str); + if (ret) { + //pr_error("tuner%d type error\n",i); + ret = 0; + continue; + } else { + if (!strncmp(str, "mxl661_tuner", 12)) + advb->tuners[j].cfg.id = AM_TUNER_MXL661; + else if (!strncmp(str, "si2151_tuner", 12)) + advb->tuners[j].cfg.id = AM_TUNER_SI2151; + else if (!strncmp(str, "si2159_tuner", 12)) + advb->tuners[j].cfg.id = AM_TUNER_SI2159; + else if (!strncmp(str, "r840_tuner", 10)) + advb->tuners[j].cfg.id = AM_TUNER_R840; + else if (!strncmp(str, "r842_tuner", 10)) + advb->tuners[j].cfg.id = AM_TUNER_R842; + else { + pr_err("nonsupport tuner: %s.\n", str); + advb->tuners[j].cfg.id = AM_TUNER_NONE; + } + } + + snprintf(buf, sizeof(buf), "tuner_i2c_adap_%d", j); + node_i2c = of_parse_phandle(node_tuner, buf, 0); + if (!node_i2c) { + pr_error("tuner_i2c_adap_id error\n"); + } else { + advb->tuners[j].i2c_adp = of_find_i2c_adapter_by_node(node_i2c); + of_node_put(node_i2c); + if (advb->tuners[j].i2c_adp == NULL) { + pr_error("i2c_get_adapter error\n"); + of_node_put(node_tuner); + goto error_fe; + } + } + + snprintf(buf, sizeof(buf), "tuner_i2c_addr_%d", j); + ret = of_property_read_u32(node_tuner, buf, &i2c_addr); + if (ret) { + pr_error("i2c_addr error\n"); + } + else + advb->tuners[j].cfg.i2c_addr = i2c_addr; + + snprintf(buf, sizeof(buf), "tuner_xtal_%d", j); + ret = of_property_read_u32(node_tuner, buf, &value); + if (ret) + pr_err("tuner_xtal error.\n"); + else + advb->tuners[j].cfg.xtal = value; + + snprintf(buf, sizeof(buf), "tuner_xtal_mode_%d", j); + ret = of_property_read_u32(node_tuner, buf, &value); + if (ret) + pr_err("tuner_xtal_mode error.\n"); + else + advb->tuners[j].cfg.xtal_mode = value; + + snprintf(buf, sizeof(buf), "tuner_xtal_cap_%d", j); + ret = of_property_read_u32(node_tuner, buf, &value); + if (ret) + pr_err("tuner_xtal_cap error.\n"); + else + advb->tuners[j].cfg.xtal_cap = value; + } + + of_node_put(node_tuner); + /* define general-purpose callback pointer */ frontend[i]->callback = NULL; - if (!strcmp(str,"si2151_tuner")) { - if (!dvb_attach(si2151_attach, frontend[i],i2c_adapter,i2c_addr)) { - pr_error("dvb attach tuner error\n"); + if (advb->tuner_cur >= 0) { + if (dvb_attach_tuner(frontend[i], &advb->tuners[advb->tuner_cur], &s_tuner_type[i]) < 0) { + pr_error("attach tuner failed\n"); goto error_fe; - } else { - pr_inf("si2151 attach sucess\n"); - s_tuner_type[i] = TUNER_SI2151; } - }else if(!strcmp(str,"mxl661_tuner")) { - if (!dvb_attach(mxl661_attach, frontend[i],i2c_adapter,i2c_addr)) { - pr_error("dvb attach mxl661_attach tuner error\n"); - goto error_fe; - } else { - pr_inf("mxl661_attach attach sucess\n"); - s_tuner_type[i] = TUNER_MXL661; - } - }else if(!strcmp(str,"si2159_tuner")) { - if (!dvb_attach(si2159_attach, frontend[i],i2c_adapter,i2c_addr)) { - pr_error("dvb attach si2159_attach tuner error\n"); - goto error_fe; - } else { - pr_inf("si2159_attach attach sucess\n"); - s_tuner_type[i] = TUNER_SI2159; - } - }else { - pr_error("can't support tuner type: %s\n",str); } + ret = dvb_register_frontend(&advb->dvb_adapter, frontend[i]); if (ret) { pr_error("register dvb frontend failed\n"); @@ -1966,6 +2424,16 @@ static int aml_dvb_probe(struct platform_device *pdev) s_demod_type[i] = DEMOD_ATBM8881; } } + if (!strcmp(name,"Si2168")) { + frontend[i] = dvb_attach(si2168_attach,&config); + if (frontend[i] == NULL) { + pr_error("dvb attach demod error\n"); + goto error_fe; + } else { + pr_inf("dtvdemod attatch sucess\n"); + s_demod_type[i] = DEMOD_SI2168; + } + } if (frontend[i]) { ret = dvb_register_frontend(&advb->dvb_adapter, frontend[i]); if (ret) { @@ -1986,6 +2454,10 @@ error_fe: dvb_detach(atbm8881_attach); frontend[i] = NULL; s_demod_type[i] = DEMOD_INVALID; + }else if (s_demod_type[i] == DEMOD_SI2168) { + dvb_detach(si2168_attach); + frontend[i] = NULL; + s_demod_type[i] = DEMOD_INVALID; } if (s_tuner_type[i] == TUNER_SI2151) { dvb_detach(si2151_attach); @@ -1996,19 +2468,27 @@ error_fe: }else if (s_tuner_type[i] == TUNER_SI2159) { dvb_detach(si2159_attach); s_tuner_type[i] = TUNER_INVALID; + }else if (s_tuner_type[i] == TUNER_R842) { + dvb_detach(r842_attach); + s_tuner_type[i] = TUNER_INVALID; + }else if (s_tuner_type[i] == TUNER_R840) { + dvb_detach(r840_attach); + s_tuner_type[i] = TUNER_INVALID; } } return 0; } + + if (advb->tuners) + kfree(advb->tuners); + return 0; error: - if (get_cpu_type() < MESON_CPU_MAJOR_ID_G12A) - { - for (i = 0; i < ASYNCFIFO_COUNT; i++) { - if (advb->asyncfifo[i].id != -1) - aml_dvb_asyncfifo_release(advb, &advb->asyncfifo[i]); - } + for (i = 0; i < advb->async_fifo_total_count; i++) { + if (advb->asyncfifo[i].id != -1) + aml_dvb_asyncfifo_release(advb, &advb->asyncfifo[i]); } + for (i = 0; i < DMX_DEV_COUNT; i++) { if (advb->dmx[i].id != -1) aml_dvb_dmx_release(advb, &advb->dmx[i]); @@ -2033,6 +2513,8 @@ static int aml_dvb_remove(struct platform_device *pdev) dvb_detach(aml_dtvdm_attach); }else if (s_demod_type[i] == DEMOD_ATBM8881) { dvb_detach(atbm8881_attach); + }else if (s_demod_type[i] == DEMOD_SI2168) { + dvb_detach(si2168_attach); } if (s_tuner_type[i] == TUNER_SI2151) { dvb_detach(si2151_attach); @@ -2040,10 +2522,14 @@ static int aml_dvb_remove(struct platform_device *pdev) dvb_detach(mxl661_attach); }else if (s_tuner_type[i] == TUNER_SI2159) { dvb_detach(si2159_attach); + }else if (s_tuner_type[i] == TUNER_R842) { + dvb_detach(r842_attach); + }else if (s_tuner_type[i] == TUNER_R840) { + dvb_detach(r840_attach); } if (frontend[i] && \ - ( (s_tuner_type[i] == TUNER_SI2151) || (s_tuner_type[i] == TUNER_MXL661) || (s_tuner_type[i] == TUNER_SI2159) ) \ + ( (s_tuner_type[i] == TUNER_SI2151) || (s_tuner_type[i] == TUNER_MXL661) || (s_tuner_type[i] == TUNER_SI2159) || (s_tuner_type[i] == TUNER_R842) || (s_tuner_type[i] == TUNER_R840)) \ ) { dvb_unregister_frontend(frontend[i]); @@ -2058,12 +2544,10 @@ static int aml_dvb_remove(struct platform_device *pdev) aml_unregist_dmx_class(); class_unregister(&aml_stb_class); - if (get_cpu_type() < MESON_CPU_MAJOR_ID_G12A) - { - for (i = 0; i < ASYNCFIFO_COUNT; i++) { - if (advb->asyncfifo[i].id != -1) - aml_dvb_asyncfifo_release(advb, &advb->asyncfifo[i]); - } + + for (i = 0; i < advb->async_fifo_total_count; i++) { + if (advb->asyncfifo[i].id != -1) + aml_dvb_asyncfifo_release(advb, &advb->asyncfifo[i]); } for (i = 0; i < DMX_DEV_COUNT; i++) { @@ -2078,7 +2562,7 @@ static int aml_dvb_remove(struct platform_device *pdev) } dvb_unregister_adapter(&advb->dvb_adapter); - for (i = 0; i < TS_IN_COUNT; i++) { + for (i = 0; i < advb->ts_in_total_count; i++) { if (advb->ts[i].pinctrl && !IS_ERR_VALUE(advb->ts[i].pinctrl)) devm_pinctrl_put(advb->ts[i].pinctrl); } @@ -2103,9 +2587,17 @@ static int aml_dvb_remove(struct platform_device *pdev) amports_switch_gate("demux", 0); amports_switch_gate("ahbarb0", 0); amports_switch_gate("parser_top", 0); + + if (get_cpu_type() == MESON_CPU_MAJOR_ID_TL1) { + clk_disable_unprepare(aml_dvb_afifo_clk); + } } #endif #endif + + if (advb->tuners) + kfree(advb->tuners); + return 0; } diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/aml_dvb.h b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/aml_dvb.h index f04c5c915a47..50ad86215f46 100644 --- a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/aml_dvb.h +++ b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/aml_dvb.h @@ -1,3 +1,22 @@ +/* +* 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. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ #ifndef _AML_DVB_H_ #define _AML_DVB_H_ @@ -35,8 +54,16 @@ #include #include +#include "aml_demod_gt.h" + +#define TS_IN_COUNT 4 +#define S2P_COUNT 3 +#define ASYNCFIFO_COUNT 3 +#if 0 #define TS_IN_COUNT 3 #define S2P_COUNT 2 +#define ASYNCFIFO_COUNT 2 +#endif #define DMX_DEV_COUNT 3 #define FE_DEV_COUNT 2 @@ -48,7 +75,6 @@ #define SEC_BUF_GRP_COUNT 4 #define SEC_BUF_BUSY_SIZE 4 #define SEC_BUF_COUNT (SEC_BUF_GRP_COUNT*8) -#define ASYNCFIFO_COUNT 2 enum aml_dmx_id_t { AM_DMX_0 = 0, @@ -61,10 +87,14 @@ enum aml_ts_source_t { AM_TS_SRC_TS0, AM_TS_SRC_TS1, AM_TS_SRC_TS2, + AM_TS_SRC_TS3, + AM_TS_SRC_S_TS0, AM_TS_SRC_S_TS1, AM_TS_SRC_S_TS2, + AM_TS_SRC_HIU, + AM_TS_SRC_HIU1, AM_TS_SRC_DMX0, AM_TS_SRC_DMX1, AM_TS_SRC_DMX2 @@ -97,27 +127,32 @@ struct aml_filter { #define DVBCSA_MODE 0 #define CIPLUS_MODE 1 -#define AES_CBC_MODE 0 -#define AES_ECB_MODE 1 +#define CBC_MODE 0 +#define ECB_MODE 1 +#define IDSA_MODE 2 #define DSC_SET_EVEN 1 #define DSC_SET_ODD 2 #define DSC_SET_AES_EVEN 4 #define DSC_SET_AES_ODD 8 #define DSC_FROM_KL 16 +#define DSC_SET_SM4_EVEN 32 +#define DSC_SET_SM4_ODD 64 + +#define DSC_KEY_SIZE_MAX 16 struct aml_dsc_channel { int pid; - u8 even[8]; - u8 odd[8]; - u8 aes_even[16]; - u8 aes_odd[16]; + u8 even[DSC_KEY_SIZE_MAX]; + u8 odd[DSC_KEY_SIZE_MAX]; + u8 even_iv[DSC_KEY_SIZE_MAX]; + u8 odd_iv[DSC_KEY_SIZE_MAX]; int used; - int flags; + int set; int id; struct aml_dsc *dsc; int work_mode; - int aes_mode; + int mode; }; struct aml_dsc { @@ -214,6 +249,11 @@ struct aml_dmx { u32 crc_check_time; }; +struct aml_dvr_block { + u32 addr; + u32 len; +}; + struct aml_asyncfifo { int id; int init; @@ -225,8 +265,10 @@ struct aml_asyncfifo { int buf_toggle; int buf_read; int flush_size; + int secure_enable; struct tasklet_struct asyncfifo_tasklet; struct aml_dvb *dvb; + struct aml_dvr_block blk; }; enum{ @@ -258,13 +300,21 @@ struct aml_swfilter { int track_dmx; }; +struct aml_tuner { + struct tuner_config cfg; + unsigned int i2c_adapter_id; + struct i2c_adapter *i2c_adp; +}; + struct aml_dvb { struct dvb_device dvb_dev; - + int ts_in_total_count; struct aml_ts_input ts[TS_IN_COUNT]; + int s2p_total_count; struct aml_s2p s2p[S2P_COUNT]; struct aml_dmx dmx[DMX_DEV_COUNT]; struct aml_dsc dsc[DSC_DEV_COUNT]; + int async_fifo_total_count; struct aml_asyncfifo asyncfifo[ASYNCFIFO_COUNT]; struct dvb_adapter dvb_adapter; struct device *dev; @@ -278,6 +328,11 @@ struct aml_dvb { int dmx_watchdog_disable[DMX_DEV_COUNT]; struct aml_swfilter swfilter; int ts_out_invert; + + unsigned int tuner_num; + unsigned int tuner_cur; + struct aml_tuner *tuners; + bool tuner_attached; }; @@ -320,6 +375,8 @@ extern int aml_asyncfifo_hw_reset(struct aml_asyncfifo *afifo); /*Get the Audio & Video PTS*/ extern u32 aml_dmx_get_video_pts(struct aml_dvb *dvb); extern u32 aml_dmx_get_audio_pts(struct aml_dvb *dvb); +extern u32 aml_dmx_get_video_pts_bit32(struct aml_dvb *dvb); +extern u32 aml_dmx_get_audio_pts_bit32(struct aml_dvb *dvb); extern u32 aml_dmx_get_first_video_pts(struct aml_dvb *dvb); extern u32 aml_dmx_get_first_audio_pts(struct aml_dvb *dvb); diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/aml_dvb_reg.h b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/aml_dvb_reg.h index 180b3d897e96..dbfa6ba43a6d 100644 --- a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/aml_dvb_reg.h +++ b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/aml_dvb_reg.h @@ -25,9 +25,10 @@ #define ID_STB_CBUS_BASE 0 #define ID_SMARTCARD_REG_BASE 1 #define ID_ASYNC_FIFO_REG_BASE 2 -#define ID_ASYNC_FIFO2_REG_BASE 3 -#define ID_RESET_BASE 4 -#define ID_PARSER_SUB_START_PTR_BASE 5 +#define ID_ASYNC_FIFO1_REG_BASE 3 +#define ID_ASYNC_FIFO2_REG_BASE 4 +#define ID_RESET_BASE 5 +#define ID_PARSER_SUB_START_PTR_BASE 6 long aml_stb_get_base(int id); #include "c_stb_define.h" @@ -52,5 +53,6 @@ long aml_stb_get_base(int id); #define INT_ASYNC_FIFO2_FILL AM_IRQ(24) #define INT_ASYNC_FIFO2_FLUSH AM_IRQ(25) +#define INT_ASYNC_FIFO3_FLUSH AM_IRQ(17) #endif diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/c_stb_define.h b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/c_stb_define.h index a5309d52753c..6b815b67bbd7 100644 --- a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/c_stb_define.h +++ b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/c_stb_define.h @@ -1,3 +1,22 @@ +/* +* 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. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ /* ----------------------------------------------------------------------*/ /* This file is automatically generated from the script:*/ /**/ @@ -43,11 +62,12 @@ /* bit 19 -- invert fec_valid for S2P1*/ /* bit 18 -- invert fec_clk for S2P1*/ /* bit 17:16 -- fec_s_sel for S2P1 - * 00 - select TS0, 01 -- select TS1, 10 -- select TS2, 11 - reserved*/ + * 00 - select TS0, 01 -- select TS1, 10 -- select TS2, 11 - TS3*/ /* Bit 15 -- enable_des_pl_clk*/ -/* Bit 14:13 -- reserved*/ +/* Bit 14 -- reserved*/ +/* Bit 13 -- use FAIL for TS3*/ /* Bit 12:10 -- ts_out_select, - * 0-TS0, 1-TS1, 2-TS2, 3,4-Reserved, 5-S2P1, 6-S2P0, 7-File*/ + * 0-TS0, 1-TS1, 2-TS2, 3-TS3,4-S2P2, 5-S2P1, 6-S2P0, 7-File*/ /* bit 9:8 -- des_i_sel 00 -- select demux0 as des input, * 01 -- select_demux1, 10 -- select_demux2, 11 - reserved*/ /* bit 7 -- enable_des_pl*/ @@ -67,6 +87,7 @@ #define INVERT_S2P1_FEC_CLK 18 #define S2P1_FEC_SERIAL_SEL 16 #define ENABLE_DES_PL_CLK 15 +#define FAIL_TS3 13 #define TS_OUTPUT_SOURCE 10 #define DES_INPUT_SEL 8 #define ENABLE_DES_PL 7 @@ -77,6 +98,37 @@ #define INVERT_S2P0_FEC_CLK 2 #define S2P0_FEC_SERIAL_SEL 0 +//define STB_S2P2_CONFIG +#define S2P2_DISABLE 11 +#define S2P2_CLK_DIV 7 +#define INVERT_S2P2_FEC_ERROR 6 +#define INVERT_S2P2_FEC_DATA 5 +#define INVERT_S2P2_FEC_SYNC 4 +#define INVERT_S2P2_FEC_VALID 3 +#define INVERT_S2P2_FEC_CLK 2 +#define S2P2_FEC_SERIAL_SEL 0 + + +/* 31:24 -- file_m2ts_skip_bytes_hiu1*/ +/* 21 -- ts_hiu_enable_hiu1 */ +/*20:16 -- fec_clk_div_hiu1*/ +/*15:8 -- TS_package_length_sub_1_hiu1 */ +/*7:0 -- fec_sync_byte_hiu1*/ +/*#define TS_HIU1_CONFIG (STB_CBUS_BASE + 0x4e)*/ +#define FILE_M2TS_SKIP_BYTES_HIU1 24 +#define TS_HIU_ENABLE_HIU1 21 +#define FEC_CLK_DIV_HIU1 16 +#define TS_PACKAGE_LENGTH_SUB_1_HIU1 8 +#define FEC_SYNC_BYTE_HIU1 0 + +/*5:4 -- fec_sel_demux_2, default:2*/ +/*3:2 -- fec_sel_demux_1, default:1*/ +/*1:0 -- fec_sel_demux_0, default:0*/ +/*#define TS_TOP_CONFIG1 (STB_CBUS_BASE + 0x4f)*/ +#define FEC_SEL_DEMUX_2 4 +#define FEC_SEL_DEMUX_1 2 +#define FEC_SEL_DEMUX_0 0 + /* 31:28 - s2p1_clk_div*/ /* 27:24 - s2p0_clk_div*/ /* 23 - s2p1_disable*/ @@ -183,6 +235,7 @@ /*#define FEC_INPUT_CONTROL_3 * (STB_CBUS_BASE + DEMUX_3_OFFSET + 0x02) // 0x16a2*/ /*----------- bit define -----------*/ +#define FEC_SEL_3BIT 16 #define FEC_CORE_SEL 15 #define FEC_SEL 12 #define FEC_INPUT_FEC_CLK 11 @@ -705,8 +758,8 @@ #define BYPASS_ENDIAN 3 #define SECTION_ENDIAN 0 -/* Bit 15:8 -- last_burst_threshold*/ -/* Bit 7 -- use hi_bsf interface*/ +/* Bit 10:9 -- PDTS_wr_sel: 0 select video_PDTS_wr_ptr; 1 select video_PDTS_wr_ptr_parser_B; */ +/* Bit 7:8 -- use hi_bsf interface*/ /* Bit 6:2 - fec_clk_div*/ /* Bit 1 ts_source_sel */ /* Bit 0 - Hiu TS generate enable */ @@ -717,7 +770,8 @@ /*#define TS_HIU_CTL_3 * (STB_CBUS_BASE + DEMUX_3_OFFSET + 0x25) // 0x16c5*/ /*----------- bit define -----------*/ -#define LAST_BURST_THRESHOLD 8 +//#define LAST_BURST_THRESHOLD 8 +#define PDTS_WR_SEL 9 #define USE_HI_BSF_INTERFACE 7 /* bit 15:0 -- base address for section buffer start diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/c_stb_regs_define.h b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/c_stb_regs_define.h index 5651ba7f5aa8..b12db6898f7d 100644 --- a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/c_stb_regs_define.h +++ b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/c_stb_regs_define.h @@ -1,3 +1,22 @@ +/* +* 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. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ /* * This file is automaticly generated by genregs.awk. Please do not edit it * Base files are .. @@ -15,6 +34,7 @@ #define STB_CBUS_BASE aml_stb_get_base(ID_STB_CBUS_BASE) #define SMARTCARD_REG_BASE aml_stb_get_base(ID_SMARTCARD_REG_BASE) #define ASYNC_FIFO_REG_BASE aml_stb_get_base(ID_ASYNC_FIFO_REG_BASE) +#define ASYNC_FIFO1_REG_BASE aml_stb_get_base(ID_ASYNC_FIFO1_REG_BASE) #define ASYNC_FIFO2_REG_BASE aml_stb_get_base(ID_ASYNC_FIFO2_REG_BASE) #define RESET_BASE aml_stb_get_base(ID_RESET_BASE) #define PARSER_SUB_START_PTR_BASE \ @@ -27,6 +47,18 @@ #define DEMUX_3_OFFSET 0xa0 +#define TS_HIU1_CONFIG (STB_CBUS_BASE + 0x4e) +#define P_TS_HIU1_CONFIG CBUS_REG_ADDR(TS_HIU1_CONFIG) + +#define TS_TOP_CONFIG1 (STB_CBUS_BASE + 0x4f) +#define P_TS_TOP_CONFIG1 CBUS_REG_ADDR(TS_TOP_CONFIG1) + +#define STB_S2P2_CONFIG (STB_CBUS_BASE + 0xef) +#define P_STB_S2P2_CONFIG CBUS_REG_ADDR(STB_S2P2_CONFIG) + +#define STB_RECORDER2_CNTL (STB_CBUS_BASE + 0xee) +#define P_STB_RECORDER2_CNTL CBUS_REG_ADDR(STB_RECORDER2_CNTL) + #define STB_TOP_CONFIG (STB_CBUS_BASE + 0xf0) #define P_STB_TOP_CONFIG CBUS_REG_ADDR(STB_TOP_CONFIG) #define TS_TOP_CONFIG (STB_CBUS_BASE + 0xf1) @@ -90,6 +122,19 @@ #define ASYNC_FIFO_REG5 (ASYNC_FIFO_REG_BASE + 0x5) #define P_ASYNC_FIFO_REG5 CBUS_REG_ADDR(ASYNC_FIFO_REG5) +#define ASYNC_FIFO1_REG0 (ASYNC_FIFO1_REG_BASE + 0x0) +#define P_ASYNC_FIFO1_REG0 CBUS_REG_ADDR(ASYNC_FIFO1_REG0) +#define ASYNC_FIFO1_REG1 (ASYNC_FIFO1_REG_BASE + 0x1) +#define P_ASYNC_FIFO1_REG1 CBUS_REG_ADDR(ASYNC_FIFO1_REG1) +#define ASYNC_FIFO1_REG2 (ASYNC_FIFO1_REG_BASE + 0x2) +#define P_ASYNC_FIFO1_REG2 CBUS_REG_ADDR(ASYNC_FIFO1_REG2) +#define ASYNC_FIFO1_REG3 (ASYNC_FIFO1_REG_BASE + 0x3) +#define P_ASYNC_FIFO1_REG3 CBUS_REG_ADDR(ASYNC_FIFO1_REG3) +#define ASYNC_FIFO1_REG4 (ASYNC_FIFO1_REG_BASE + 0x4) +#define P_ASYNC_FIFO1_REG4 CBUS_REG_ADDR(ASYNC_FIFO1_REG4) +#define ASYNC_FIFO1_REG5 (ASYNC_FIFO1_REG_BASE + 0x5) +#define P_ASYNC_FIFO1_REG5 CBUS_REG_ADDR(ASYNC_FIFO1_REG5) + #define ASYNC_FIFO2_REG0 (ASYNC_FIFO2_REG_BASE + 0x0) #define P_ASYNC_FIFO2_REG0 CBUS_REG_ADDR(ASYNC_FIFO2_REG0) diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/Makefile b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/Makefile index e258f64ad7dd..bbfbdd48e16a 100644 --- a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/Makefile +++ b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/Makefile @@ -1,9 +1,15 @@ -obj-m += aml_hardware_spi.o aml_hardware_pcmcia.o aml_hardware_ci.o +obj-m += ci.o cimax-usb.o -ccflags-y += -I$(srctree)/drivers/media/dvb-core -I$(srctree)/drivers/gpio -I$(srctree)/include +ci-objs = $(amlci-objs) $(cimax-objs) -aml_hardware_spi-objs += aml_spi.o +amlci-objs = aml_pcmcia.o aml_ci.o +cimax-objs = cimax/dvb_ca_en50221_cimax.o cimax/aml_cimax.o cimax/dvb_ringbuffer.o +cimax-usb-objs += cimax/usb/SRC/cimax+usb-driver.o cimax/usb/SRC/cimax+usb_fw.o +cimax-usb-objs += cimax/usb/SRC/cimax+usb_config.o +cimax-objs += cimax/aml_cimax_usb.o -aml_hardware_pcmcia-objs += aml_pcmcia.o +ccflags-y += -I$(srctree)/ +ccflags-y += -I$(srctree)/include +ccflags-y += -I$(srctree)/drivers/gpio +ccflags-y += -I$(srctree)/drivers/media/dvb-core -aml_hardware_ci-objs += aml_ci.o diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/aml_ci.c b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/aml_ci.c index bf72b4ec5a5b..c28d2fc3cf83 100644 --- a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/aml_ci.c +++ b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/aml_ci.c @@ -1,36 +1,37 @@ +/* +* 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. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ + #include #include #include #include -#include -#include -#include -#include -#include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include #include -#include #include "aml_ci.h" #include "aml_spi.h" +#include "cimax/aml_cimax.h" MODULE_PARM_DESC(aml_ci_debug, "\n\t\t dvb ci debug"); static int aml_ci_debug = 1; -module_param(aml_ci_debug, int, 0444); +module_param(aml_ci_debug, int, S_IRUGO); #define pr_dbg(args...)\ do {\ @@ -71,7 +72,7 @@ static int aml_ci_mem_read(struct dvb_ca_en50221 *en50221, int slot, int addr) * - -EINVAL : error */ static int aml_ci_mem_write(struct dvb_ca_en50221 *en50221, - int slot, int addr, u8 data) + int slot, int addr, u8 data) { struct aml_ci *ci = en50221->data; @@ -118,8 +119,8 @@ static int aml_ci_io_read(struct dvb_ca_en50221 *en50221, int slot, u8 addr) * - 0:ok * - -EINVAL : error */ -static int aml_ci_io_write( - struct dvb_ca_en50221 *en50221, int slot, u8 addr, u8 data) +static int aml_ci_io_write(struct dvb_ca_en50221 *en50221, + int slot, u8 addr, u8 data) { struct aml_ci *ci = en50221->data; @@ -144,7 +145,6 @@ static int aml_ci_io_write( static int aml_ci_slot_reset(struct dvb_ca_en50221 *en50221, int slot) { struct aml_ci *ci = en50221->data; - pr_dbg("Slot(%d): Slot RESET\n", slot); if (ci->ci_slot_reset != NULL) { ci->ci_slot_reset(ci, slot); @@ -164,7 +164,6 @@ static int aml_ci_slot_reset(struct dvb_ca_en50221 *en50221, int slot) static int aml_ci_slot_shutdown(struct dvb_ca_en50221 *en50221, int slot) { struct aml_ci *ci = en50221->data; - pr_dbg("Slot(%d): Slot shutdown\n", slot); if (ci->ci_slot_shutdown != NULL) { ci->ci_slot_shutdown(ci, slot); @@ -185,7 +184,6 @@ static int aml_ci_ts_control(struct dvb_ca_en50221 *en50221, int slot) { struct aml_ci *ci = en50221->data; - pr_dbg("Slot(%d): TS control\n", slot); if (ci->ci_slot_ts_enable != NULL) { ci->ci_slot_ts_enable(ci, slot); @@ -203,18 +201,282 @@ static int aml_ci_ts_control(struct dvb_ca_en50221 *en50221, int slot) * - cam status * - -EINVAL : error */ -static int aml_ci_slot_status( - struct dvb_ca_en50221 *en50221, int slot, int open) +static int aml_ci_slot_status(struct dvb_ca_en50221 *en50221, + int slot, int open) { struct aml_ci *ci = en50221->data; pr_dbg("Slot(%d): Poll Slot status\n", slot); - if (ci->ci_poll_slot_status != NULL) + if (ci->ci_poll_slot_status != NULL) { return ci->ci_poll_slot_status(ci, slot, open); - pr_error("ci_poll_slot_status is null %s\r\n", __func__); + } else { + pr_error("ci_poll_slot_status is null %s\r\n", __func__); + return -EINVAL; + } + return -EINVAL; } +static int aml_ci_cimax_slot_reset(struct dvb_ca_en50221_cimax *en50221, + int slot) +{ + struct aml_ci *ci = en50221->data; + pr_dbg("Slot(%d): Slot RESET\n", slot); + if (ci->ci_slot_reset != NULL) { + ci->ci_slot_reset(ci, slot); + } else { + pr_error("ci_slot_reset is null %s\r\n", __func__); + return -EINVAL; + } + return 0; +} +/**\brief aml_ci_slot_shutdown:show slot + * \param en50221: en50221 obj,used this data to get dvb_ci obj + * \param slot: slot index + * \return + * - 0:ok + * - -EINVAL : error + */ +static int aml_ci_cimax_slot_shutdown(struct dvb_ca_en50221_cimax *en50221, + int slot) +{ + struct aml_ci *ci = en50221->data; + pr_dbg("Slot(%d): Slot shutdown\n", slot); + if (ci->ci_slot_shutdown != NULL) { + ci->ci_slot_shutdown(ci, slot); + } else { + pr_error("aml_ci_slot_shutdown is null %s\r\n", __func__); + return -EINVAL; + } + return 0; +} +/**\brief aml_ci_ts_control:control slot ts + * \param en50221: en50221 obj,used this data to get dvb_ci obj + * \param slot: slot index + * \return + * - 0:ok + * - -EINVAL : error + */ +static int aml_ci_cimax_ts_control(struct dvb_ca_en50221_cimax *en50221, + int slot) +{ + + struct aml_ci *ci = en50221->data; + pr_dbg("Slot(%d): TS control\n", slot); + if (ci->ci_slot_ts_enable != NULL) { + ci->ci_slot_ts_enable(ci, slot); + } else { + pr_error("aml_ci_ts_control is null %s\r\n", __func__); + return -EINVAL; + } + return 0; +} +/**\brief aml_ci_slot_status:get slot status + * \param en50221: en50221 obj,used this data to get dvb_ci obj + * \param slot: slot index + * \param open: no used + * \return + * - cam status + * - -EINVAL : error + */ +static int aml_ci_cimax_slot_status( + struct dvb_ca_en50221_cimax *en50221, int slot, int open) +{ + struct aml_ci *ci = en50221->data; + + /*pr_dbg("Slot(%d): Poll Slot status\n", slot);*/ + + if (ci->ci_poll_slot_status != NULL) { + return ci->ci_poll_slot_status(ci, slot, open); + } else { + pr_error("ci_poll_slot_status is null %s\r\n", __func__); + return -EINVAL; + } + + return -EINVAL; +} + +/**\brief aml_ci_read_cis: read cis + * \param en50221_max: en50221 obj,used this data to get dvb_ci obj + * \param slot: slot index + * \param buf: buf for cis data + * \param size: buf size + * \return + * --EINVAL : error + * - : actual size read + */ +static int aml_ci_read_cis(struct dvb_ca_en50221_cimax *en50221, + int slot, u8 *buf, int size) +{ + struct aml_ci *ci = en50221->data; + + if (slot != 0) { + pr_error("slot !=0 %s :%d\r\n", __func__, slot); + return -EINVAL; + } + + if (ci->ci_read_cis != NULL) + return ci->ci_read_cis(ci, slot, buf, size); + + pr_error("ci_read_cis is null %s\r\n", __func__); + return -EINVAL; +} +/**\brief aml_ci_write_cor: write cor + * \param en50221_max: en50221 obj,used this data to get dvb_ci obj + * \param slot: slot index + * \param addr: + * \param buf: + * \return + * --EINVAL : error + * -0 : ok + */ +static int aml_ci_write_cor(struct dvb_ca_en50221_cimax *en50221, + int slot, int address, u8 *buf) +{ + struct aml_ci *ci = en50221->data; + + if (slot != 0) { + pr_error("slot !=0 %s :%d\r\n", __func__, slot); + return -EINVAL; + } + + if (ci->ci_write_cor != NULL) + return ci->ci_write_cor(ci, slot, address, buf); + + pr_error("ci_write_cor is null %s\r\n", __func__); + return -EINVAL; +} +/**\brief aml_ci_negociate: negotiate + * \param en50221_max: en50221 obj,used this data to get dvb_ci obj + * \param slot: slot index + * \param size: suggested size + * \return + * --EINVAL : error + * - : size negotiated + */ +static int aml_ci_negotiate(struct dvb_ca_en50221_cimax *en50221, + int slot, int size) +{ + struct aml_ci *ci = en50221->data; + + if (slot != 0) { + pr_error("slot !=0 %s :%d\r\n", __func__, slot); + return -EINVAL; + } + + if (ci->ci_negotiate != NULL) + return ci->ci_negotiate(ci, slot, size); + + pr_error("ci_negotiate is null %s\r\n", __func__); + return -EINVAL; +} +/**\brief aml_ci_read_lpdu: read lpdu + * \param en50221_max: en50221 obj,used this data to get dvb_ci obj + * \param slot: slot index + * \param buf: buf + * \param size: buf size + * \return + * --EINVAL : error + * - : size read + */ +static int aml_ci_read_lpdu(struct dvb_ca_en50221_cimax *en50221, + int slot, u8 *buf, int size) +{ + struct aml_ci *ci = en50221->data; + + if (slot != 0) { + pr_error("slot !=0 %s :%d\r\n", __func__, slot); + return -EINVAL; + } + + if (ci->ci_read_lpdu != NULL) + return ci->ci_read_lpdu(ci, slot, buf, size); + + pr_error("ci_read_lpdu is null %s\r\n", __func__); + return -EINVAL; +} + +/**\brief aml_ci_write_lpdu: write lpdu + * \param en50221_max: en50221 obj,used this data to get dvb_ci obj + * \param slot: slot index + * \param buf: buf + * \param size: write size + * \return + * --EINVAL : error + * - : size written + */ +static int aml_ci_write_lpdu(struct dvb_ca_en50221_cimax *en50221, + int slot, u8 *buf, int size) +{ + struct aml_ci *ci = en50221->data; + + if (slot != 0) { + pr_error("slot !=0 %s :%d\r\n", __func__, slot); + return -EINVAL; + } + + if (ci->ci_write_lpdu != NULL) + return ci->ci_write_lpdu(ci, slot, buf, size); + + pr_error("ci_write_lpdu is null %s\r\n", __func__); + return -EINVAL; +} + +static int aml_ci_read_cam_status(struct dvb_ca_en50221_cimax *en50221, + int slot) +{ + struct aml_ci *ci = en50221->data; + + if (slot != 0) { + pr_error("slot !=0 %s :%d\r\n", __func__, slot); + return -EINVAL; + } + + if (ci->ci_read_cam_status != NULL) + return ci->ci_read_cam_status(ci, slot); + + pr_error("ci_read_cam_status is null %s\r\n", __func__); + return -EINVAL; +} + +static int aml_ci_cam_reset(struct dvb_ca_en50221_cimax *en50221, int slot) +{ + struct aml_ci *ci = en50221->data; + + if (slot != 0) { + pr_error("slot !=0 %s :%d\r\n", __func__, slot); + return -EINVAL; + } + + if (ci->ci_cam_reset != NULL) + return ci->ci_cam_reset(ci, slot); + + pr_error("ci_cam_reset is null %s\r\n", __func__); + return -EINVAL; +} + +/**\brief aml_ci_get_capbility + * \param en50221_max: en50221 obj,used this data to get dvb_ci obj + * \param slot: slot index + * \return + * - : capbilities + */ +static int aml_ci_get_capbility(struct dvb_ca_en50221_cimax *en50221, int slot) +{ + struct aml_ci *ci = en50221->data; + + if (slot != 0) { + pr_error("slot !=0 %s :%d\r\n", __func__, slot); + return -EINVAL; + } + + if (ci->ci_get_capbility != NULL) + return ci->ci_get_capbility(ci, slot); + + pr_error("ci_get_capbility is null %s\r\n", __func__); + return -EINVAL; +} + /**\brief get ci config from dts * \param np: device node @@ -222,8 +484,8 @@ static int aml_ci_slot_status( * - 0 成功 * - 其他值 : */ -static int aml_ci_get_config_from_dts( - struct platform_device *pdev, struct aml_ci *ci) +static int aml_ci_get_config_from_dts(struct platform_device *pdev, + struct aml_ci *ci) { char buf[32]; int ret = 0; @@ -263,67 +525,106 @@ int aml_ci_init(struct platform_device *pdev, aml_ci_get_config_from_dts(pdev, ci); ci->priv = dvb; - ca_flags = DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE; /* register CA interface */ - ci->en50221.owner = THIS_MODULE; - ci->en50221.read_attribute_mem = aml_ci_mem_read; - ci->en50221.write_attribute_mem = aml_ci_mem_write; - ci->en50221.read_cam_control = aml_ci_io_read; - ci->en50221.write_cam_control = aml_ci_io_write; - ci->en50221.slot_reset = aml_ci_slot_reset; - ci->en50221.slot_shutdown = aml_ci_slot_shutdown; - ci->en50221.slot_ts_enable = aml_ci_ts_control; - ci->en50221.poll_slot_status = aml_ci_slot_status; - ci->en50221.data = ci; + if (ci->io_type == AML_DVB_IO_TYPE_CIMAX) { + ci->en50221_cimax.owner = THIS_MODULE; + ci->en50221_cimax.read_cis = aml_ci_read_cis; + ci->en50221_cimax.write_cor = aml_ci_write_cor; + ci->en50221_cimax.negotiate = aml_ci_negotiate; + ci->en50221_cimax.read_lpdu = aml_ci_read_lpdu; + ci->en50221_cimax.write_lpdu = aml_ci_write_lpdu; + ci->en50221_cimax.read_cam_status = aml_ci_read_cam_status; + ci->en50221_cimax.cam_reset = aml_ci_cam_reset; + ci->en50221_cimax.get_capbility = aml_ci_get_capbility; + ci->en50221_cimax.slot_reset = aml_ci_cimax_slot_reset; + ci->en50221_cimax.slot_shutdown = aml_ci_cimax_slot_shutdown; + ci->en50221_cimax.slot_ts_enable = aml_ci_cimax_ts_control; + ci->en50221_cimax.poll_slot_status = aml_ci_cimax_slot_status; + ci->en50221_cimax.data = ci; + + pr_dbg("Registering EN50221 CIMAX device\n"); + result = dvb_ca_en50221_cimax_init(dvb_adapter, + &ci->en50221_cimax, ca_flags, 1); + if (result != 0) { + pr_error("EN50221 CIMAX: Initialization failed <%d>\n", + result); + goto err; + } + } else { + ca_flags = DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE; + ci->en50221.read_attribute_mem = aml_ci_mem_read; + ci->en50221.write_attribute_mem = aml_ci_mem_write; + ci->en50221.read_cam_control = aml_ci_io_read; + ci->en50221.write_cam_control = aml_ci_io_write; + ci->en50221.slot_reset = aml_ci_slot_reset; + ci->en50221.slot_shutdown = aml_ci_slot_shutdown; + ci->en50221.slot_ts_enable = aml_ci_ts_control; + ci->en50221.poll_slot_status = aml_ci_slot_status; + ci->en50221.data = ci; - pr_dbg("Registering EN50221 device\n"); - result = dvb_ca_en50221_init(dvb_adapter, &ci->en50221, ca_flags, 1); - if (result != 0) { - pr_error("EN50221: Initialization failed <%d>\n", result); - goto err; + pr_dbg("Registering EN50221 device\n"); + result = dvb_ca_en50221_init(dvb_adapter, + &ci->en50221, ca_flags, 1); + if (result != 0) { + pr_error("EN50221: Initialization failed <%d>\n", + result); + goto err; + } } *cip = ci; pr_dbg("Registered EN50221 device\n"); + if (ci->io_type == AML_DVB_IO_TYPE_SPI) { /* spi init */ - aml_spi_init(pdev, ci); + //ci->ci_init = aml_spi_init; + //ci->ci_exit = aml_spi_exit; + } else if (ci->io_type == AML_DVB_IO_TYPE_CIMAX) { + ci->ci_init = aml_cimax_init; + ci->ci_exit = aml_cimax_exit; } else { /* no io dev init,is error */ - pr_dbg("io dev no init,we do not known use spi or iobus or other,please check io_type in dts file\r\n"); + pr_dbg("unknown io type, please check io_type in dts file\r\n"); } - return 0; + + if (ci->ci_init) + result = ci->ci_init(pdev, ci); + + if (result) + dvb_ca_en50221_cimax_release(&ci->en50221_cimax); + + return result; err: - /* for init spi */ - aml_spi_exit(); kfree(ci); return result; } -EXPORT_SYMBOL_GPL(aml_ci_init); void aml_ci_exit(struct aml_ci *ci) { pr_dbg("Unregistering EN50221 device\n"); if (ci) { - dvb_ca_en50221_release(&ci->en50221); + if (ci->io_type == AML_DVB_IO_TYPE_CIMAX) + dvb_ca_en50221_cimax_release(&ci->en50221_cimax); + else + dvb_ca_en50221_release(&ci->en50221); + if (ci->ci_exit) + ci->ci_exit(ci); kfree(ci); } } -EXPORT_SYMBOL_GPL(aml_ci_exit); static struct aml_ci *ci_dev; static ssize_t aml_ci_ts_show(struct class *class, -struct class_attribute *attr, char *buf) + struct class_attribute *attr, char *buf) { int ret; - ret = sprintf(buf, "ts%d\n", 1); return ret; } static struct class_attribute amlci_class_attrs[] = { - __ATTR(ts, 0644, aml_ci_ts_show, NULL), + __ATTR(ts, S_IRUGO | S_IWUSR, aml_ci_ts_show, NULL), __ATTR_NULL }; @@ -361,7 +662,6 @@ static int aml_ci_probe(struct platform_device *pdev) { struct aml_dvb *dvb = aml_get_dvb_device(); int err = 0; - pr_dbg("---Amlogic CI Init---\n"); err = aml_ci_init(pdev, dvb, &ci_dev); if (err < 0) @@ -375,10 +675,13 @@ static int aml_ci_remove(struct platform_device *pdev) { aml_ci_unregister_class(ci_dev); platform_set_drvdata(pdev, NULL); - if (ci_dev->io_type == AML_DVB_IO_TYPE_SPI) - aml_spi_exit(); + if (ci_dev->io_type == AML_DVB_IO_TYPE_SPI) { + //aml_spi_exit(ci_dev); + } + else if (ci_dev->io_type == AML_DVB_IO_TYPE_CIMAX) + aml_cimax_exit(ci_dev); else - pr_dbg("---Amlogic CI remove unknown io type---\n"); + pr_dbg("---Amlogic CI remove unkown io type---\n"); aml_ci_exit(ci_dev); return 0; @@ -387,10 +690,13 @@ static int aml_ci_remove(struct platform_device *pdev) static int aml_ci_suspend(struct platform_device *pdev, pm_message_t state) { pr_dbg("Amlogic CI Suspend!\n"); - if (ci_dev->io_type == AML_DVB_IO_TYPE_SPI) - aml_spi_exit(); + if (ci_dev->io_type == AML_DVB_IO_TYPE_SPI) { + //aml_spi_exit(ci_dev); + } + else if (ci_dev->io_type == AML_DVB_IO_TYPE_CIMAX) + aml_cimax_exit(ci_dev); else - pr_dbg("---Amlogic CI remove unknown io type---\n"); + pr_dbg("---Amlogic CI remove unkown io type---\n"); return 0; } @@ -398,12 +704,14 @@ static int aml_ci_suspend(struct platform_device *pdev, pm_message_t state) static int aml_ci_resume(struct platform_device *pdev) { int err = 0; - pr_dbg("Amlogic CI Resume!\n"); - if (ci_dev->io_type == AML_DVB_IO_TYPE_SPI) - aml_spi_init(pdev, ci_dev); + if (ci_dev->io_type == AML_DVB_IO_TYPE_SPI) { + //aml_spi_init(pdev, ci_dev); + } + else if (ci_dev->io_type == AML_DVB_IO_TYPE_CIMAX) + aml_cimax_init(pdev, ci_dev); else - pr_dbg("---Amlogic CI remove unknown io type---\n"); + pr_dbg("---Amlogic CI remove unkown io type---\n"); return err; } @@ -428,13 +736,13 @@ static struct platform_driver aml_ci_driver = { } }; -static int __init aml_ci_mod_init(void) +static int aml_ci_mod_init(void) { pr_dbg("Amlogic CI mode init\n"); return platform_driver_register(&aml_ci_driver); } -static void __exit aml_ci_mod_exit(void) +static void aml_ci_mod_exit(void) { pr_dbg("Amlogic CI mode Exit\n"); platform_driver_unregister(&aml_ci_driver); @@ -442,7 +750,5 @@ static void __exit aml_ci_mod_exit(void) module_init(aml_ci_mod_init); module_exit(aml_ci_mod_exit); - MODULE_LICENSE("GPL"); - diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/aml_ci.h b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/aml_ci.h index 03f5e5e2c141..3e34417e0c39 100644 --- a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/aml_ci.h +++ b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/aml_ci.h @@ -1,22 +1,47 @@ +/* +* 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. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ + #ifndef __AML_CI_H_ #define __AML_CI_H_ -#include +#include "drivers/media/dvb-core/dvb_ca_en50221.h" +#include "cimax/dvb_ca_en50221_cimax.h" #include "../aml_dvb.h" enum aml_dvb_io_type_e { AML_DVB_IO_TYPE_IOBUS = 0, AML_DVB_IO_TYPE_SPI, + AML_DVB_IO_TYPE_CIMAX, AML_DVB_IO_TYPE_MAX, }; struct aml_ci { - struct dvb_ca_en50221 en50221; - struct mutex ci_lock; - int io_type; - void *priv; - int id; - struct class class; + struct dvb_ca_en50221 en50221; + struct mutex ci_lock; + int io_type; + void *priv; + int id; + struct class class; + + int (*ci_init)(struct platform_device *pdev, struct aml_ci *ci); + int (*ci_exit)(struct aml_ci *ci); /* NOTE: the read_*, write_* and poll_slot_status functions will be * called for different slots concurrently and need to use locks where @@ -37,11 +62,28 @@ struct aml_ci { int (*ci_slot_ts_enable)(struct aml_ci *ca, int slot); /* - * Poll slot status. - * Only necessary if DVB_CA_FLAG_EN50221_IRQ_CAMCHANGE is not set - */ + * Poll slot status. + * Only necessary if DVB_CA_FLAG_EN50221_IRQ_CAMCHANGE is not set + */ int (*ci_poll_slot_status)(struct aml_ci *ca, int slot, int open); + + struct dvb_ca_en50221_cimax en50221_cimax; + + int (*ci_read_cis)(struct aml_ci *ca, int slot, u8 *buf, int size); + int (*ci_write_cor)(struct aml_ci *ca, int slot, int address, u8 *buf); + /*return the final size or -1 for error*/ + int (*ci_negotiate)(struct aml_ci *ca, int slot, int size); + + /* functions for accessing the control interface on the CAM */ + int (*ci_read_lpdu)(struct aml_ci *ca, int slot, u8 *buf, int size); + int (*ci_write_lpdu)(struct aml_ci *ca, int slot, u8 *buf, int size); + + int (*ci_get_capbility)(struct aml_ci *ca, int slot); + + int (*ci_cam_reset)(struct aml_ci *ca, int slot); + int (*ci_read_cam_status)(struct aml_ci *ca, int slot); + /* private data, used by caller */ void *data; }; @@ -52,8 +94,8 @@ struct ci_dev_config_s { int cs_hold_delay; int cs_clk_delay; }; -extern int aml_ci_init(struct platform_device - *pdev, struct aml_dvb *dvb, struct aml_ci **cip); +extern int aml_ci_init(struct platform_device *pdev, + struct aml_dvb *dvb, struct aml_ci **cip); extern void aml_ci_exit(struct aml_ci *ci); #endif /* __AML_CI_H_ */ diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/aml_pcmcia.c b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/aml_pcmcia.c index b840db43918d..ac8c87d71128 100644 --- a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/aml_pcmcia.c +++ b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/aml_pcmcia.c @@ -61,7 +61,6 @@ static int pcmcia_unplug(struct aml_pcmcia *pc) static irqreturn_t pcmcia_irq_handler(int irq, void *dev_id) { struct aml_pcmcia *pc = (struct aml_pcmcia *)dev_id; - pr_dbg("pcmcia_irq_handler--into--\r\n"); disable_irq_nosync(pc->irq); schedule_work(&pc->pcmcia_work); @@ -96,7 +95,6 @@ static struct aml_pcmcia *pc_cur; int aml_pcmcia_init(struct aml_pcmcia *pc) { int err = 0; - pr_dbg("aml_pcmcia_init start pc->irq=%d\r\n", pc->irq); pc->rst(pc, AML_L); /*power on*/ @@ -144,7 +142,7 @@ int aml_pcmcia_reset(struct aml_pcmcia *pc) EXPORT_SYMBOL(aml_pcmcia_reset); - +#if 0 static ssize_t aml_pcmcia_test_cmd(struct class *class, struct class_attribute *attr, const char *buf, size_t size) { @@ -167,7 +165,7 @@ struct class_attribute *attr, const char *buf, size_t size) } static struct class_attribute aml_pcmcia_class_attrs[] = { - __ATTR(cmd, 0644, NULL, aml_pcmcia_test_cmd), + __ATTR(cmd, S_IRUGO | S_IWUSR, NULL, aml_pcmcia_test_cmd), __ATTR_NULL }; @@ -198,3 +196,4 @@ module_init(aml_pcmcia_mod_init); module_exit(aml_pcmcia_mod_exit); MODULE_LICENSE("GPL"); +#endif diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/aml_pcmcia.h b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/aml_pcmcia.h index 2d8a3ad4b9fc..612d5776e081 100644 --- a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/aml_pcmcia.h +++ b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/aml_pcmcia.h @@ -1,3 +1,22 @@ +/* +* 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. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ #ifndef _AML_PCMCIA_ #define _AML_PCMCIA_ diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/aml_spi.c b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/aml_spi.c index bbfe295b6977..62f4f5315dc6 100644 --- a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/aml_spi.c +++ b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/aml_spi.c @@ -1,3 +1,23 @@ +/* +* 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. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ + #include #include @@ -14,7 +34,6 @@ #include #include #include -#include #include "aml_spi.h" #include "aml_ci.h" @@ -59,25 +78,25 @@ struct spi_board_info aml_ci_spi_bdinfo = { #define PULLHIGH 0 /* - *sendbuf data struct - *---------------------------------------------------- - *|start flag| cmd | data | addr |end flag | - *---------------------------------------------------- - *| 2 byte | 1byte | 1byte | 2 byte| 2 byte | - *---------------------------------------------------- - */ +sendbuf data struct +---------------------------------------------------- +|start flag| cmd | data | addr |end flag | +---------------------------------------------------- +| 2 byte | 1byte | 1byte | 2 byte| 2 byte | +---------------------------------------------------- +*/ #define SENDBUFLEN 8 static u8 sendbuf[SENDBUFLEN];/* send data */ static u8 rbuf[SENDBUFLEN];/*save get data */ /**\brief aml_init_send_buf:init spi send buf - * \param cmd: ci cmd - * \param data: write value - * \param addr: read or write addr - * \return - * - read value:ok - * - -EINVAL : error - */ +* \param cmd: ci cmd +* \param data: write value +* \param addr: read or write addr +* \return +* - read value:ok +* - -EINVAL : error +*/ static int aml_init_send_buf(u8 cmd, u8 data, u16 addr) { /* start flag */ @@ -96,20 +115,20 @@ static int aml_init_send_buf(u8 cmd, u8 data, u16 addr) return 0; } /**\brief aml_ci_spi_reciver - * \param[out] None - * \param[in] value,get from spi - * \return - * - 0:reciver end,-1:reciver - * - - */ +* \param[out] None +* \param[in] value,get from spi +* \return +* - 0:reciver end,-1:reciver +* - +*/ /* - *data strouct - *---------------------------------------------------- - *|start flag| cmd | data | addr |end flag | - *---------------------------------------------------- - *| 2 byte | 1byte | 1byte | 2 byte| 2 byte | - *---------------------------------------------------- - */ +data strouct +---------------------------------------------------- +|start flag| cmd | data | addr |end flag | +---------------------------------------------------- +| 2 byte | 1byte | 1byte | 2 byte| 2 byte | +---------------------------------------------------- +*/ int aml_ci_spi_paser_bit(uint8_t value) { /* read spi data from slave */ @@ -161,21 +180,20 @@ int aml_ci_spi_paser_bit(uint8_t value) } /**\brief aml_spi_io_api:spi read or write api with mcu - * \param spi_dev: aml_spi obj,used this data to get spi obj - * \param val: write value - * \param len: write value len - * \param mode: read or write - * \return - * - read value:ok - * - -EINVAL : error - */ +* \param spi_dev: aml_spi obj,used this data to get spi obj +* \param val: write value +* \param len: write value len +* \param mode: read or write +* \return +* - read value:ok +* - -EINVAL : error +*/ static int aml_spi_io_api(struct aml_spi *spi_dev, u8 *val, int len, int mode) { u8 rb[32] = {0}; int ret = 0; int i = 0; u8 rd = 0; - if (spi_dev->spi == NULL) { pr_error("%s spi is null\r\n", __func__); return -EINVAL; @@ -226,16 +244,15 @@ static int aml_spi_io_api(struct aml_spi *spi_dev, u8 *val, int len, int mode) /********************************************************/ /********************************************************/ /**\brief aml_set_gpio_out:set gio out and set val value - * \param gpio: gpio_desc obj, - * \param val: set val - * \return - * - 0:ok - * - -EINVAL : error - */ +* \param gpio: gpio_desc obj, +* \param val: set val +* \return +* - 0:ok +* - -EINVAL : error +*/ static int aml_set_gpio_out(struct gpio_desc *gpio, int val) { int ret = 0; - if (val < 0) { pr_dbg("gpio out val = -1.\n"); return -1; @@ -246,51 +263,53 @@ static int aml_set_gpio_out(struct gpio_desc *gpio, int val) pr_dbg("dvb ci gpio out ret %d set val:%d\n", ret, val); return ret; } +#if 0 /**\brief aml_set_gpio_in:set gio in - * \param gpio: gpio_desc obj, - * \return - * - 0:ok - * - -EINVAL : error - */ -static inline int aml_set_gpio_in(struct gpio_desc *gpio) +* \param gpio: gpio_desc obj, +* \return +* - 0:ok +* - -EINVAL : error +*/ +static int aml_set_gpio_in(struct gpio_desc *gpio) { gpiod_direction_input(gpio); return 0; } +#endif + /**\brief aml_get_gpio_value:get gio value - * \param gpio: gpio_desc obj, - * \return - * - gpio value:ok - * - -EINVAL : error - */ -static inline int aml_get_gpio_value(struct gpio_desc *gpio) +* \param gpio: gpio_desc obj, +* \return +* - gpio value:ok +* - -EINVAL : error +*/ +static int aml_get_gpio_value(struct gpio_desc *gpio) { int ret = 0; - ret = gpiod_get_value(gpio); return ret; } /**\brief aml_gpio_free:free gio - * \param gpio: gpio_desc obj, - * \return - * - 0:ok - * - -EINVAL : error - */ +* \param gpio: gpio_desc obj, +* \return +* - 0:ok +* - -EINVAL : error +*/ static int aml_gpio_free(struct gpio_desc *gpio) { gpiod_put(gpio); return 0; } /**\brief spi_get_gpio_by_name:get gpio desc from dts file - * \param spi_dev: aml_spi obj - * \param gpiod: gpio_desc * obj - * \param str: gpio name at dts file - * \param input_output: gpio input or output type - * \param output_value: gpio out put value - * \return - * - 0:ok - * - -EINVAL : error - */ +* \param spi_dev: aml_spi obj +* \param gpiod: gpio_desc * obj +* \param str: gpio name at dts file +* \param input_output: gpio input or output type +* \param output_value: gpio out put value +* \return +* - 0:ok +* - -EINVAL : error +*/ static int spi_get_gpio_by_name(struct aml_spi *spi_dev, struct gpio_desc **gpiod, int *pin_value, char *str, int input_output, int output_level) @@ -332,120 +351,117 @@ char *str, int input_output, int output_level) /******* gpio api end *************/ /********************************************************/ /********************************************************/ +#if 0 /**\brief aml_ci_cis_test_by_spi:test cis - * \param ci_dev: aml_ci obj,used this data to get spi_dev obj - * \param slot: slot index - * \param addr: read addr - * \return - * - test :ok - * - -EINVAL : error - */ +* \param ci_dev: aml_ci obj,used this data to get spi_dev obj +* \param slot: slot index +* \param addr: read addr +* \return +* - test :ok +* - -EINVAL : error +*/ /**\brief aml_ci_full_test_by_spi:ci full test - * \param ci_dev: aml_ci obj,used this data to get spi_dev obj - * \param slot: slot index - * \param addr: read addr - * \return - * - read value:ok - * - -EINVAL : error - */ +* \param ci_dev: aml_ci obj,used this data to get spi_dev obj +* \param slot: slot index +* \param addr: read addr +* \return +* - read value:ok +* - -EINVAL : error +*/ static int aml_ci_full_test_by_spi( struct aml_ci *ci_dev, int slot, int addr) { u8 data = 0; - u16 address = addr; + u16 addres = addr; int value = 0; struct aml_spi *spi_dev = ci_dev->data; - - aml_init_send_buf(AM_CI_CMD_FULLTEST, data, address); + aml_init_send_buf(AM_CI_CMD_FULLTEST, data, addres); value = aml_spi_io_api(spi_dev, sendbuf, SENDBUFLEN, AM_CI_CMD_FULLTEST); pr_dbg("FULL : TEST END \r\n"); return value; } - +#endif /**\brief aml_ci_mem_read_by_spi:io read from cam - * \param ci_dev: aml_ci obj,used this data to get spi_dev obj - * \param slot: slot index - * \param addr: read addr - * \return - * - read value:ok - * - -EINVAL : error - */ +* \param ci_dev: aml_ci obj,used this data to get spi_dev obj +* \param slot: slot index +* \param addr: read addr +* \return +* - read value:ok +* - -EINVAL : error +*/ static int aml_ci_mem_read_by_spi( struct aml_ci *ci_dev, int slot, int addr) { u8 data = 0; - u16 address = addr; + u16 addres = addr; int value = 0; struct aml_spi *spi_dev = ci_dev->data; - - aml_init_send_buf(AM_CI_CMD_MEMR, data, address); + aml_init_send_buf(AM_CI_CMD_MEMR, data, addres); value = aml_spi_io_api(spi_dev, sendbuf, SENDBUFLEN, AM_CI_CMD_MEMR); /*pr_dbg("Read : mem[%d] = 0x%x\n", addr, value);*/ return value; } /**\brief aml_ci_mem_write_by_spi:io write to cam by spi api - * \param ci_dev: aml_ci obj,used this data to get spi_dev obj - * \param slot: slot index - * \param addr: write addr - * \param addr: write value - * \return - * - 0:ok - * - -EINVAL : error - */ +* \param ci_dev: aml_ci obj,used this data to get spi_dev obj +* \param slot: slot index +* \param addr: write addr +* \param addr: write value +* \return +* - 0:ok +* - -EINVAL : error +*/ static int aml_ci_mem_write_by_spi( struct aml_ci *ci_dev, int slot, int addr, u8 val) { u8 data = val; - u16 address = addr; + u16 addres = addr; int value = 0; struct aml_spi *spi_dev = ci_dev->data; - - aml_init_send_buf(AM_CI_CMD_MEMW, data, address); + aml_init_send_buf(AM_CI_CMD_MEMW, data, addres); value = aml_spi_io_api(spi_dev, sendbuf, SENDBUFLEN, AM_CI_CMD_MEMW); /*pr_dbg("write : mem[%d] = 0x%x\n", addr, data);*/ - return value; +return value; } /**\brief aml_ci_io_read_by_spi:io read from cam by spi api - * \param ci_dev: aml_ci obj,used this data to get spi_dev obj - * \param slot: slot index - * \param addr: read addr - * \return - * - read value:ok - * - -EINVAL : error - */ +* \param ci_dev: aml_ci obj,used this data to get spi_dev obj +* \param slot: slot index +* \param addr: read addr +* \return +* - read value:ok +* - -EINVAL : error +*/ static int aml_ci_io_read_by_spi( struct aml_ci *ci_dev, int slot, int addr) { u8 data = 0; - u16 address = addr; + u16 addres = addr; int value = 0; struct aml_spi *spi_dev = ci_dev->data; - - aml_init_send_buf(AM_CI_CMD_IOR, data, address); + aml_init_send_buf(AM_CI_CMD_IOR, data, addres); value = aml_spi_io_api(spi_dev, sendbuf, SENDBUFLEN, AM_CI_CMD_IOR); /*pr_dbg("read : io[%d] = 0x%x\n", addr, value);*/ return value; } /**\brief aml_ci_io_write_by_spi:io write to cam - * \param ci_dev: aml_ci obj,used this data to get spi_dev obj - * \param slot: slot index - * \param addr: write addr - * \param addr: write value - * \return - * - 0:ok - * - -EINVAL : error - */ +* \param ci_dev: aml_ci obj,used this data to get spi_dev obj +* \param slot: slot index +* \param addr: write addr +* \param addr: write value +* \return +* - 0:ok +* - -EINVAL : error +*/ static int aml_ci_io_write_by_spi( struct aml_ci *ci_dev, int slot, int addr, u8 val) { u8 data = val; - u16 address = addr; + u16 addres = addr; int value = 0; struct aml_spi *spi_dev = ci_dev->data; /*add by chl,need add time delay*/ mdelay(10); - aml_init_send_buf(AM_CI_CMD_IOW, data, address); + aml_init_send_buf(AM_CI_CMD_IOW, data, addres); value = aml_spi_io_api(spi_dev, sendbuf, SENDBUFLEN, AM_CI_CMD_IOW); /*pr_dbg("write : ATTR[%d] = 0x%x\n", addr, data);*/ return value; @@ -453,55 +469,54 @@ static int aml_ci_io_write_by_spi( /**\brief aml_ci_slot_reset:reset slot - * \param ci_dev: aml_ci obj,used this data to get spi_dev obj - * \param slot: slot index - * \return - * - 0:ok - * - -EINVAL : error - */ +* \param ci_dev: aml_ci obj,used this data to get spi_dev obj +* \param slot: slot index +* \return +* - 0:ok +* - -EINVAL : error +*/ static int aml_ci_slot_reset(struct aml_ci *ci_dev, int slot) { struct aml_spi *spi_dev = ci_dev->data; - pr_dbg("Slot(%d): Slot RESET\n", slot); aml_pcmcia_reset(&spi_dev->pc); dvb_ca_en50221_camready_irq(&ci_dev->en50221, 0); return 0; } /**\brief aml_ci_slot_shutdown:show slot - * \param ci_dev: aml_ci obj,used this data to get spi_dev obj - * \param slot: slot index - * \return - * - 0:ok - * - -EINVAL : error - * readme:no use this api - */ +* \param ci_dev: aml_ci obj,used this data to get spi_dev obj +* \param slot: slot index +* \return +* - 0:ok +* - -EINVAL : error +* readme:no use this api +*/ static int aml_ci_slot_shutdown(struct aml_ci *ci_dev, int slot) { pr_dbg("Slot(%d): Slot shutdown\n", slot); return 0; } /**\brief aml_ci_ts_control:control slot ts - * \param ci_dev: aml_ci obj,used this data to get spi_dev obj - * \param slot: slot index - * \return - * - 0:ok - * - -EINVAL : error - * readme:no use this api - */ +* \param ci_dev: aml_ci obj,used this data to get spi_dev obj +* \param slot: slot index +* \return +* - 0:ok +* - -EINVAL : error +* readme:no use this api +*/ static int aml_ci_ts_control(struct aml_ci *ci_dev, int slot) { pr_dbg("Slot(%d): TS control\n", slot); return 0; } /**\brief aml_ci_slot_status:get slot status - * \param ci_dev: aml_ci obj,used this data to get spi_dev obj - * \param slot: slot index - * \param open: no used - * \return - * - cam status - * - -EINVAL : error - */ +* \param ci_dev: aml_ci obj,used this data to get spi_dev obj +* \param slot: slot index +* \param open: no used +* \return +* - cam status +* - -EINVAL : error +*/ static int aml_ci_slot_status(struct aml_ci *ci_dev, int slot, int open) { struct aml_spi *spi_dev = ci_dev->data; @@ -517,36 +532,36 @@ static int aml_ci_slot_status(struct aml_ci *ci_dev, int slot, int open) } return -EINVAL; } - +#if 0 /**\brief aml_ci_gio_get_irq:get gpio cam irq pin value - * \return - * - irq pin value - * - -EINVAL : error - */ +* \return +* - irq pin value +* - -EINVAL : error +*/ static int aml_ci_gio_get_irq(void) { int ret = 0; - ret = aml_get_gpio_value(g_spi_dev->irq_cam_pin); return ret; } +#endif + /********************************************************/ /********************************************************/ /******* for pcmcid api *************/ /********************************************************/ /********************************************************/ /**\brief aml_gio_power:set power gpio hi or low - * \param pc: aml_pcmcia obj,used this priv to get spi_dev obj - * \param enable: power pin hi or low - * \return - * - 0 - * - -EINVAL : error - */ +* \param pc: aml_pcmcia obj,used this priv to get spi_dev obj +* \param enable: power pin hi or low +* \return +* - 0 +* - -EINVAL : error +*/ static int aml_gio_power(struct aml_pcmcia *pc, int enable) { int ret = 0; struct aml_spi *spi_dev = pc->priv; - if (spi_dev == NULL) { pr_dbg("spi dev is null %s : %d\r\n", __func__, enable); return -1; @@ -562,18 +577,17 @@ static int aml_gio_power(struct aml_pcmcia *pc, int enable) return ret; } /**\brief aml_gio_reset:set reset gpio hi or low - * \param pc: aml_pcmcia obj,used this priv to get spi_dev obj - * \param enable: reset pin hi or low - * \return - * - 0 - * - -EINVAL : error - */ +* \param pc: aml_pcmcia obj,used this priv to get spi_dev obj +* \param enable: reset pin hi or low +* \return +* - 0 +* - -EINVAL : error +*/ static int aml_gio_reset(struct aml_pcmcia *pc, int enable) { /*need set hi and sleep set low*/ int ret = 0; struct aml_spi *spi_dev = pc->priv; - pr_dbg("%s : %d\r\n", __func__, enable); if (enable == AML_L) ret = aml_set_gpio_out(spi_dev->reset_pin, AML_GPIO_LOW); @@ -583,80 +597,79 @@ static int aml_gio_reset(struct aml_pcmcia *pc, int enable) } /**\brief aml_gio_init_irq:set gpio irq - * \param pc: aml_pcmcia obj,used this priv to get spi_dev obj - * \param flag: rising or falling or hi or low - * \return - * - 0 - * - -EINVAL : error - */ +* \param pc: aml_pcmcia obj,used this priv to get spi_dev obj +* \param flag: rising or falling or hi or low +* \return +* - 0 +* - -EINVAL : error +*/ /*need change*/ static int aml_gio_init_irq(struct aml_pcmcia *pc, int flag) -{ - struct aml_spi *spi_dev = (struct aml_spi *)pc->priv; - + { + struct aml_spi *spi_dev = (struct aml_spi *)pc->priv; + #if 0 - int cd1_pin = desc_to_gpio(spi_dev->cd_pin1); - - int irq = pc->irq-AML_CI_GPIO_IRQ_BASE; - - printk("----cd1_pin=%d irq=%d\r\n", cd1_pin, irq); - aml_set_gpio_in(spi_dev->cd_pin1); - - if (flag == IRQF_TRIGGER_RISING) - gpio_for_irq(cd1_pin, - AML_GPIO_IRQ(irq, FILTER_NUM7, GPIO_IRQ_RISING)); - else if (flag == IRQF_TRIGGER_FALLING) - gpio_for_irq(cd1_pin, - AML_GPIO_IRQ(irq, FILTER_NUM7, GPIO_IRQ_FALLING)); - else if (flag == IRQF_TRIGGER_HIGH) - gpio_for_irq(cd1_pin, - AML_GPIO_IRQ(irq, FILTER_NUM7, GPIO_IRQ_HIGH)); - else if (flag == IRQF_TRIGGER_LOW) - gpio_for_irq(cd1_pin, - AML_GPIO_IRQ(irq, FILTER_NUM7, GPIO_IRQ_LOW)); - else - return -1; + int cd1_pin = desc_to_gpio(spi_dev->cd_pin1); + + int irq = pc->irq-AML_CI_GPIO_IRQ_BASE; + + printk("----cd1_pin=%d irq=%d\r\n", cd1_pin, irq); + aml_set_gpio_in(spi_dev->cd_pin1); + + if (flag == IRQF_TRIGGER_RISING) + gpio_for_irq(cd1_pin, + AML_GPIO_IRQ(irq, FILTER_NUM7, GPIO_IRQ_RISING)); + else if (flag == IRQF_TRIGGER_FALLING) + gpio_for_irq(cd1_pin, + AML_GPIO_IRQ(irq, FILTER_NUM7, GPIO_IRQ_FALLING)); + else if (flag == IRQF_TRIGGER_HIGH) + gpio_for_irq(cd1_pin, + AML_GPIO_IRQ(irq, FILTER_NUM7, GPIO_IRQ_HIGH)); + else if (flag == IRQF_TRIGGER_LOW) + gpio_for_irq(cd1_pin, + AML_GPIO_IRQ(irq, FILTER_NUM7, GPIO_IRQ_LOW)); + else + return -1; #endif - gpiod_to_irq(spi_dev->cd_pin1); + gpiod_to_irq(spi_dev->cd_pin1); + + return 0; + } - return 0; -} /**\brief aml_gio_get_cd1:get gpio cd1 pin value - * \param pc: aml_pcmcia obj,used this priv to get spi_dev obj - * \return - * - cd1 pin value - * - -EINVAL : error - */ +* \param pc: aml_pcmcia obj,used this priv to get spi_dev obj +* \return +* - cd1 pin value +* - -EINVAL : error +*/ static int aml_gio_get_cd1(struct aml_pcmcia *pc) { int ret = 0; struct aml_spi *spi_dev = pc->priv; - ret = aml_get_gpio_value(spi_dev->cd_pin1); return ret; } /**\brief aml_gio_get_cd2:get gpio cd2 pin value - * \param pc: aml_pcmcia obj,used this priv to get spi_dev obj - * \return - * - cd2 pin value - * - -EINVAL : error - */ +* \param pc: aml_pcmcia obj,used this priv to get spi_dev obj +* \return +* - cd2 pin value +* - -EINVAL : error +*/ static int aml_gio_get_cd2(struct aml_pcmcia *pc) { int ret = 0; struct aml_spi *spi_dev = pc->priv; - ret = aml_get_gpio_value(spi_dev->cd_pin2); pr_dbg("%s : %d\r\n", __func__, ret); return ret; } /**\brief aml_cam_plugin:notify en50221 cam card in or out - * \param pc: aml_pcmcia obj,used this priv to get spi_dev obj - * \plugin: 0:remove;1:in - * \return - * - 0 - * - -EINVAL : error - */ +* \param pc: aml_pcmcia obj,used this priv to get spi_dev obj +* \plugin: 0:remove;1:in +* \return +* - 0 +* - -EINVAL : error +*/ static int aml_cam_plugin(struct aml_pcmcia *pc, int plugin) { struct aml_ci *ci = (struct aml_ci *) @@ -672,12 +685,12 @@ static int aml_cam_plugin(struct aml_pcmcia *pc, int plugin) return 0; } /**\brief aml_pcmcia_alloc:alloc nad init pcmcia obj - * \param spi_dev: aml_spi obj, - * \param pcmcia: aml_pcmcia * obj, - * \return - * - 0 - * - -EINVAL : error - */ +* \param spi_dev: aml_spi obj, +* \param pcmcia: aml_pcmcia * obj, +* \return +* - 0 +* - -EINVAL : error +*/ static void aml_pcmcia_alloc(struct aml_spi *spi_dev, struct aml_pcmcia **pcmcia) { @@ -696,11 +709,11 @@ static void aml_pcmcia_alloc(struct aml_spi *spi_dev, } /**\brief aml_spi_get_config_from_dts:get spi config and gpio config from dts - * \param spi_dev: aml_spi obj, - * \return - * - 0 - * - -EINVAL : error - */ +* \param spi_dev: aml_spi obj, +* \return +* - 0 +* - -EINVAL : error +*/ static int aml_spi_get_config_from_dts(struct aml_spi *spi_dev) { struct device_node *child = NULL; @@ -708,7 +721,6 @@ static int aml_spi_get_config_from_dts(struct aml_spi *spi_dev) struct device_node *np = pdev->dev.of_node; unsigned int temp[5], val; int ret = 0; - pr_dbg("into get spi dts \r\n"); /*get spi and gpio config from dts*/ @@ -770,11 +782,10 @@ static int aml_spi_get_config_from_dts(struct aml_spi *spi_dev) spi_dev->irq = 5; } else { /*set irq value need add - *AML_CI_GPIO_IRQ_BASE,but - *we need minus - *AML_CI_GPIO_IRQ_BASE - *when gpio request irq - */ + AML_CI_GPIO_IRQ_BASE,but + we need minus + AML_CI_GPIO_IRQ_BASE + when gpio request irq */ spi_dev->irq = val+AML_CI_GPIO_IRQ_BASE; } @@ -803,11 +814,8 @@ static int aml_spi_get_config_from_dts(struct aml_spi *spi_dev) } spi_dev->cd_pin2 = spi_dev->cd_pin1; spi_dev->cd_pin2_value = spi_dev->cd_pin1_value; - /*set irq*/ - spi_dev->irq = gpiod_to_irq(spi_dev->cd_pin1); spi_dev->pwr_pin = NULL; - pr_dbg("spi_dev->cd_pin1_value==%d irq=%d\r\n", - spi_dev->cd_pin1_value, spi_dev->irq); + pr_dbg("spi_dev->cd_pin1_value==%d\r\n", spi_dev->cd_pin1_value); ret = spi_get_gpio_by_name(spi_dev, &spi_dev->pwr_pin, &spi_dev->pwr_pin_value, "pwr_pin", OUTPUT, OUTLEVEL_HIGH); @@ -827,11 +835,11 @@ static int aml_spi_get_config_from_dts(struct aml_spi *spi_dev) return 0; } /**\brief aml_ci_free_gpio:free ci gpio - * \param spi_dev: aml_spi obj, - * \return - * - 0 - * - -EINVAL : error - */ +* \param spi_dev: aml_spi obj, +* \return +* - 0 +* - -EINVAL : error +*/ static void aml_ci_free_gpio(struct aml_spi *spi_dev) { if (spi_dev == NULL) { @@ -856,23 +864,23 @@ static void aml_ci_free_gpio(struct aml_spi *spi_dev) aml_gpio_free(spi_dev->irq_cam_pin); spi_dev->irq_cam_pin = NULL; } + return; } /**\brief ci_spi_dev_remove:spi probe api - * \param spi: spi obj, - * \return - * - 0 - * - -EINVAL : error - */ +* \param spi: spi obj, +* \return +* - 0 +* - -EINVAL : error +*/ static int ci_spi_dev_probe(struct spi_device *spi) { int ret; - pr_dbg("spi Dev probe--\n"); if (g_spi_dev) g_spi_dev->spi = spi; - else + else pr_dbg("spi Dev probe-error-\n"); spi->bits_per_word = 8; ret = spi_setup(spi); @@ -881,11 +889,11 @@ static int ci_spi_dev_probe(struct spi_device *spi) return ret; } /**\brief ci_spi_dev_remove:spi remove api - * \param spi: spi obj, - * \return - * - 0 - * - -EINVAL : error - */ +* \param spi: spi obj, +* \return +* - 0 +* - -EINVAL : error +*/ static int ci_spi_dev_remove(struct spi_device *spi) { pr_dbg("spi Dev remove--\n"); @@ -904,12 +912,12 @@ static struct spi_driver ci_spi_dev_driver = { }, }; /**\brief aml_spi_init:spi_dev init - * \param ci_dev: aml_ci obj, - * \param pdev: platform_device obj,used to get dts info - * \return - * - 0 - * - -EINVAL : error - */ +* \param ci_dev: aml_ci obj, +* \param pdev: platform_device obj,used to get dts info +* \return +* - 0 +* - -EINVAL : error +*/ int aml_spi_init(struct platform_device *pdev, struct aml_ci *ci_dev) { struct aml_spi *spi_dev = NULL; @@ -936,8 +944,10 @@ int aml_spi_init(struct platform_device *pdev, struct aml_ci *ci_dev) } aml_pcmcia_alloc(spi_dev, &pc); result = aml_pcmcia_init(pc); - if (result < 0) + if (result < 0) { pr_error("aml_pcmcia_init failed\n"); + goto fail2; + } /*init ci_dev used api.*/ ci_dev->ci_mem_read = aml_ci_mem_read_by_spi; @@ -952,20 +962,21 @@ int aml_spi_init(struct platform_device *pdev, struct aml_ci *ci_dev) /*init spi_lock*/ spin_lock_init(&(spi_dev->spi_lock)); return 0; +fail2: spi_unregister_driver(&ci_spi_dev_driver); fail1: - kfree(spi_dev); - spi_dev = NULL; + kfree(spi_dev); + spi_dev = NULL; err: return -1; } EXPORT_SYMBOL(aml_spi_init); /**\brief aml_spi_exit:spi exit - * \return - * - 0 - * - -EINVAL : error - */ -int aml_spi_exit(void) +* \return +* - 0 +* - -EINVAL : error +*/ +int aml_spi_exit(struct aml_ci *ci) { /*exit pc card*/ aml_pcmcia_exit(&g_spi_dev->pc); @@ -981,6 +992,8 @@ int aml_spi_exit(void) } EXPORT_SYMBOL(aml_spi_exit); + +#if 0 /********************************************************/ /********************************************************/ /******* for spi test api *************/ @@ -1011,7 +1024,6 @@ static void aml_spi_ca_full_test(struct aml_ci *ci_dev) int cnt = 0; unsigned char buf[10]; int count = 1000; - mdelay(1000); pr_dbg("READ CIS START\r\n"); for (i = 0; i < 267; i++) { @@ -1040,18 +1052,17 @@ static void aml_spi_ca_full_test(struct aml_ci *ci_dev) unsigned char reg; unsigned char reg1; int count1 = 4000; - while (1) { mdelay(20); count1--; reg1 = aml_ci_io_read_by_spi( ci_dev, 0, COM_STA_REG); if (FR != (FR & reg1)) { - continue; - } else { - pr_dbg("CAM Reset Ok\r\n"); - break; - } + continue; + } else { + pr_dbg("CAM Reset Ok\r\n"); + break; + } } reg = aml_ci_io_read_by_spi(ci_dev, 0, COM_STA_REG); pr_dbg("STA_REG = 0x%2.2x\r\n", reg); @@ -1076,11 +1087,9 @@ end: if ((reg & DA) == DA) { pr_dbg("Buffer negotiate size date avalible.\r\n"); break; - } - { + } else { /*pr_dbg("Buffer negotiate - *size date NOT avalible\r\n"); - */ + size date NOT avalible\r\n");*/ continue; } mdelay(100); @@ -1196,8 +1205,7 @@ end: if (WE == (WE & reg)) { pr_dbg("Write CAM ERR!\r\n"); return; - } - { + } else { aml_ci_io_write_by_spi(ci_dev, 0, COM_STA_REG, SW); mdelay(100); aml_ci_io_write_by_spi(ci_dev, 0, COM_STA_REG, 0); @@ -1208,17 +1216,17 @@ end: } /** - * Read a tuple from attribute memory. - * - * @param ca CA instance. - * @param slot Slot id. - * @param address Address to read from. Updated. - * @param tupleType Tuple id byte. Updated. - * @param tupleLength Tuple length. Updated. - * @param tuple Dest buffer for tuple (must be 256 bytes). Updated. - * - * @return 0 on success, nonzero on error. - */ +* Read a tuple from attribute memory. +* +* @param ca CA instance. +* @param slot Slot id. +* @param address Address to read from. Updated. +* @param tupleType Tuple id byte. Updated. +* @param tupleLength Tuple length. Updated. +* @param tuple Dest buffer for tuple (must be 256 bytes). Updated. +* +* @return 0 on success, nonzero on error. +*/ static int dvb_ca_en50221_read_tuple( int *address, int *tupleType, int *tupleLength, u8 *tuple) { @@ -1279,15 +1287,14 @@ static char *findstr(char *haystack, int hlen, char *needle, int nlen) } /** - * Parse attribute memory of a CAM module, - * extracting Config register, and checking - * it is a DVB CAM module. - * - * @param ca CA instance. - * @param slot Slot id. - * - * @return 0 on success, <0 on failure. - */ +* Parse attribute memory of a CAM module, extracting Config register, and checking +* it is a DVB CAM module. +* +* @param ca CA instance. +* @param slot Slot id. +* +* @return 0 on success, <0 on failure. +*/ static int dvb_ca_en50221_parse_attributes(void) { int address = 0; @@ -1413,13 +1420,13 @@ static int dvb_ca_en50221_parse_attributes(void) } /* process the CFTABLE_ENTRY tuples, and any after those */ - while ((!end_chain) && (address < 0x1000)) { +while ((!end_chain) && (address < 0x1000)) { status = dvb_ca_en50221_read_tuple(&address, &tupleType, - &tupleLength, tuple); - if (status < 0) { - pr_error("process the CFTABLE_ENTRY tuples error\r\n"); - return status; - } + &tupleLength, tuple); + if (status < 0) { + pr_error("process the CFTABLE_ENTRY tuples error\r\n"); + return status; + } switch (tupleType) { case 0x1B: /* CISTPL_CFTABLE_ENTRY */ @@ -1453,9 +1460,9 @@ static int dvb_ca_en50221_parse_attributes(void) default: /* Unknown tuple type - just skip - *this tuple and move to the next one - */ - pr_error("Skipping unknown tupletype:0x%x L:0x%x\n", + *this tuple and move to the next one + */ +pr_error("Skipping unknown tupletype:0x%x L:0x%x\n", tupleType, tupleLength); break; } @@ -1474,7 +1481,6 @@ static ssize_t aml_spi_ci_reset_help(struct class *class, struct class_attribute *attr, char *buf) { int ret; - ret = sprintf(buf, "echo 1 > %s\n\t", attr->attr.name); return ret; } @@ -1484,7 +1490,6 @@ struct class_attribute *attr, const char *buf, size_t size) { int ret; struct aml_ci *ci = (struct aml_ci *)g_spi_dev->priv; - ret = aml_ci_slot_reset(ci, 0); return size; } @@ -1493,7 +1498,6 @@ static ssize_t aml_spi_ci_pwr_help(struct class *class, struct class_attribute *attr, char *buf) { int ret; - ret = sprintf(buf, "echo 1|0> %s\n\t", attr->attr.name); return ret; } @@ -1504,7 +1508,6 @@ struct class_attribute *attr, const char *buf, size_t size) int ret = 0; int enable = 0; long value; - if (kstrtol(buf, 0, &value) == 0) enable = (int)value; ret = aml_gio_power(&g_spi_dev->pc, enable); @@ -1515,7 +1518,6 @@ struct class_attribute *attr, char *buf) { int ret; struct aml_ci *ci = (struct aml_ci *)g_spi_dev->priv; - ret = aml_ci_slot_status(ci, 0, 0); ret = sprintf(buf, "%s: %d;\n\t", attr->attr.name, ret); return ret; @@ -1525,7 +1527,6 @@ static ssize_t aml_spi_ci_irq_show(struct class *class, struct class_attribute *attr, char *buf) { int ret; - ret = aml_ci_gio_get_irq(); ret = sprintf(buf, "%s irq: %d\n\t", attr->attr.name, ret); return ret; @@ -1535,7 +1536,6 @@ static ssize_t aml_spi_io_test_help(struct class *class, struct class_attribute *attr, char *buf) { int ret; - ret = sprintf(buf, "echo (r|w|f|c)(i|a) addr data > %s\n", attr->attr.name); return ret; @@ -1550,7 +1550,6 @@ struct class_attribute *attr, const char *buf, size_t size) unsigned int addr = 0, val = 0, retval = 0; long value = 0; struct aml_ci *ci = (struct aml_ci *)g_spi_dev->priv; - buf_orig = kstrdup(buf, GFP_KERNEL); ps = buf_orig; while (1) { @@ -1563,7 +1562,7 @@ struct class_attribute *attr, const char *buf, size_t size) parm[n++] = token; } - if ((n > 0) && (strlen(parm[0]) != 2)) { + if (!n || ((n > 0) && (strlen(parm[0]) != 2))) { pr_err("invalid command\n"); kfree(buf_orig); return size; @@ -1579,16 +1578,15 @@ struct class_attribute *attr, const char *buf, size_t size) addr = (int)value; pr_err("%s 0x%x\n", parm[0], addr); /* switch ((char)parm[0][1]) { - * case 'i': - * retval = aml_ci_io_read_by_spi(ci, 0, addr); - * break; - * case 'a': - * retval = aml_ci_mem_read_by_spi(ci, 0, addr); - * break; - * default: - * break; - * } - */ + case 'i': + retval = aml_ci_io_read_by_spi(ci, 0, addr); + break; + case 'a': + retval = aml_ci_mem_read_by_spi(ci, 0, addr); + break; + default: + break; + }*/ pr_dbg("%s: 0x%x --> 0x%x\n", parm[0], addr, retval); } else if ((parm[0][0] == 'w')) { if (n != 3) { @@ -1597,22 +1595,21 @@ struct class_attribute *attr, const char *buf, size_t size) return size; } if (kstrtol(parm[1], 0, &value) == 0) - addr = (int)value; + addr = (int)value; if (kstrtol(parm[2], 0, &value) == 0) - val = (int)value; + val = (int)value; pr_err("%s 0x%x 0x%x", parm[0], addr, val); /*switch ((char)parm[0][1]) { - * case 'i': + case 'i': retval = aml_ci_io_write_by_spi(ci, 0, addr, val); - * break; - * case 'a': + break; + case 'a': retval = aml_ci_mem_write_by_spi(ci, 0, addr, val); - * break; - * default: - * break; - *} - */ + break; + default: + break; + }*/ pr_dbg("%s: 0x%x <-- 0x%x\n", parm[0], addr, retval); } else if ((parm[0][0] == 'f')) { pr_dbg("full test----\r\n"); @@ -1630,15 +1627,15 @@ retval = aml_ci_mem_write_by_spi(ci, 0, addr, val); } static struct class_attribute aml_spi_class_attrs[] = { - __ATTR(reset, 0644, + __ATTR(reset, S_IRUGO | S_IWUSR, aml_spi_ci_reset_help, aml_spi_ci_reset), - __ATTR(pwr, 0644, + __ATTR(pwr, S_IRUGO | S_IWUSR, aml_spi_ci_pwr_help, aml_spi_ci_pwr), - __ATTR(irq, 0644, + __ATTR(irq, S_IRUGO | S_IWUSR, aml_spi_ci_irq_show, NULL), - __ATTR(status, 0644, + __ATTR(status, S_IRUGO | S_IWUSR, aml_spi_ci_state_show, NULL), - __ATTR(iotest, 0644, + __ATTR(iotest, S_IRUGO | S_IWUSR, aml_spi_io_test_help, aml_spi_io_test), __ATTR_NULL }; @@ -1648,14 +1645,15 @@ static struct class aml_spi_class = { .class_attrs = aml_spi_class_attrs, }; -static int __init aml_spi_mod_init(void) +static int aml_spi_mod_init(void) { + int ret; pr_dbg("Amlogic DVB SPI Init\n"); - class_register(&aml_spi_class); -return 0; + ret = class_register(&aml_spi_class); + return 0; } -static void __exit aml_spi_mod_exit(void) +static void aml_spi_mod_exit(void) { pr_dbg("Amlogic DVB SPI Exit\n"); class_unregister(&aml_spi_class); @@ -1665,3 +1663,4 @@ module_init(aml_spi_mod_init); module_exit(aml_spi_mod_exit); MODULE_LICENSE("GPL"); +#endif diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/aml_spi.h b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/aml_spi.h index 2795dc9dae5d..43d0d162e32e 100644 --- a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/aml_spi.h +++ b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/aml_spi.h @@ -3,13 +3,13 @@ #include #include -#include #include "aml_pcmcia.h" #include "aml_ci.h" +#include "drivers/media/dvb-core/dvb_ca_en50221.h" /* - *aml spi dev - */ +aml spi dev +*/ struct aml_spi { spinlock_t spi_lock; @@ -76,6 +76,6 @@ extern void dirspi_start(struct spi_device *spi); extern void dirspi_stop(struct spi_device *spi); extern void dvb_ca_en50221_camready_irq(struct dvb_ca_en50221 *pubca, int slot); extern int aml_spi_init(struct platform_device *pdev, struct aml_ci *ci_dev); -extern int aml_spi_exit(void); +extern int aml_spi_exit(struct aml_ci *ci_dev); #endif /* __AML_SPI_H_ */ diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/aml_cimax.c b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/aml_cimax.c new file mode 100644 index 000000000000..9346b8dd46c5 --- /dev/null +++ b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/aml_cimax.c @@ -0,0 +1,279 @@ + +/*************************************************************************** + * Copyright (c) 2014 Amlogic, Inc. All rights reserved. + * + * This source code is subject to the terms and conditions defined in the + * file 'LICENSE' which is part of this source code package. + * + * Description: + * +***************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +//#include +#include "../aml_ci.h" +#include "aml_cimax.h" +#include "aml_cimax_spi.h" +#include "aml_cimax_usb.h" + +#define MODUDLE_NAME "aml_cimax" + +MODULE_PARM_DESC(cimax_debug, "enable verbose debug messages"); +static int aml_cimax_debug = 1; +module_param_named(cimax_debug, aml_cimax_debug, int, 0644); + +//static struct switch_dev slot_state = { +// .name = "ci_slot", +//}; + +#define pr_dbg(fmt...)\ + do {\ + if (aml_cimax_debug)\ + pr_info("AML_CIMAX: " fmt);\ + } while (0) +#define pr_error(fmt...) pr_err("AML_CIMAX: " fmt) + +static int aml_cimax_slot_reset(struct aml_ci *ci, int slot) +{ + int ret = 0; + struct aml_cimax *cimax = ci->data; + pr_dbg("cimax: slot(%d) reset\n", slot); + if (cimax->ops.slot_reset) + ret = cimax->ops.slot_reset(cimax, slot); + return ret; +} + +static int aml_cimax_slot_shutdown(struct aml_ci *ci, int slot) +{ + pr_dbg("slot(%d) shutdown\n", slot); + return 0; +} + +static int aml_cimax_slot_ts_enable(struct aml_ci *ci, int slot) +{ + pr_dbg("slot(%d) ts control\n", slot); + return 0; +} + +static int aml_cimax_slot_status(struct aml_ci *ci, int slot, int open) +{ + int ret = 0; + struct aml_cimax *cimax = ci->data; + + /*pr_dbg("cimax: slot(%d) poll\n", slot);*/ + if (cimax->ops.slot_status) + ret = cimax->ops.slot_status(cimax, slot); + return ret; +} + +#define DEF_FUNC_WRAPPER3(_pre, _fn, _S, _P1, _P2, _P3) \ +static int _pre##_fn(_S s, _P1 p1, _P2 p2, _P3 p3)\ +{\ + struct aml_cimax *cimax = s->data;\ + /*pr_dbg("%s\n", #_fn);*/\ + if (cimax->ops._fn)\ + return cimax->ops._fn(cimax, p1, p2, p3);\ + return 0;\ +} + +/*DEF_FUNC_WRAPPER3(aml_cimax_, read_reg, struct aml_ci*, int, u8*, int)*/ +/*DEF_FUNC_WRAPPER3(aml_cimax_, write_reg, struct aml_ci*, int, u8*, int)*/ +DEF_FUNC_WRAPPER3(aml_cimax_, read_cis, struct aml_ci*, int, u8*, int) +DEF_FUNC_WRAPPER3(aml_cimax_, read_lpdu, struct aml_ci*, int, u8*, int) +DEF_FUNC_WRAPPER3(aml_cimax_, write_lpdu, struct aml_ci*, int, u8*, int) + +static int aml_cimax_write_cor(struct aml_ci *ci, int slot, int addr, u8 *buf) +{ + struct aml_cimax *cimax = ci->data; + pr_dbg("write_cor\n"); + if (cimax->ops.write_cor) + return cimax->ops.write_cor(cimax, slot, addr, buf); + return 0; +} + +static int aml_cimax_negotiate(struct aml_ci *ci, int slot, int size) +{ + struct aml_cimax *cimax = ci->data; + pr_dbg("negotiate\n"); + if (cimax->ops.negotiate) + return cimax->ops.negotiate(cimax, slot, size); + return 0; +} + +static int aml_cimax_read_cam_status(struct aml_ci *ci, int slot) +{ + struct aml_cimax *cimax = ci->data; + if (cimax->ops.read_cam_status) + return cimax->ops.read_cam_status(cimax, slot); + return 0; +} + +static int aml_cimax_cam_reset(struct aml_ci *ci, int slot) +{ + struct aml_cimax *cimax = ci->data; + if (cimax->ops.cam_reset) + return cimax->ops.cam_reset(cimax, slot); + return 0; +} + +static int aml_cimax_get_capbility(struct aml_ci *ci, int slot) +{ + return 0; +} + +int aml_cimax_camchanged(struct aml_cimax *cimax, int slot, int plugin) +{ + struct aml_ci *ci = cimax->ci; + if (plugin) { + dvb_ca_en50221_cimax_camchange_irq(&ci->en50221_cimax, + slot, DVB_CA_EN50221_CAMCHANGE_INSERTED); + } else { + dvb_ca_en50221_cimax_camchange_irq(&ci->en50221_cimax, + slot, DVB_CA_EN50221_CAMCHANGE_REMOVED); + } + return 0; +} + +static int aml_cimax_start(struct aml_cimax *cimax) +{ + int ret = 0; + if (cimax->ops.start) + ret = cimax->ops.start(cimax); + return ret; +} + +static int aml_cimax_stop(struct aml_cimax *cimax) +{ + int ret = 0; + if (cimax->ops.stop) + ret = cimax->ops.stop(cimax); + return ret; +} + +static int aml_cimax_get_config_from_dts(struct aml_cimax *cimax) +{ + struct device_node *child = NULL; + struct platform_device *pdev = cimax->pdev; + struct device_node *np = pdev->dev.of_node; + unsigned int val; + int ret = 0; + pr_dbg("get cimax dts\n"); + + child = of_get_child_by_name(np, "cimax"); + if (child == NULL) { + pr_error("failed to get cimax\n"); + return -1; + } + ret = of_property_read_u32(child, "io_type", &val); + if (ret) + cimax->io_type = IO_TYPE_SPI; + else + cimax->io_type = val; + + return 0; +} + +int aml_cimax_init(struct platform_device *pdev, struct aml_ci *ci) +{ + struct aml_cimax *cimax = NULL; + int ret = 0; + + cimax = kzalloc(sizeof(struct aml_cimax), GFP_KERNEL); + if (!cimax) { + pr_error("Out of memory!, exiting ..\n"); + return -ENOMEM; + } + cimax->pdev = pdev; + cimax->ci = ci; + + aml_cimax_get_config_from_dts(cimax); + + if (cimax->io_type == IO_TYPE_SPI) { + //ret = aml_cimax_spi_init(pdev, cimax); + } + else { + ret = aml_cimax_usb_init(pdev, cimax); + } + + if (ret != 0) { + kfree(cimax); + cimax = NULL; + return -EIO; + } + + ret = aml_cimax_start(cimax); + if (ret != 0) + return ret; + + ci->ci_read_cis = aml_cimax_read_cis; + ci->ci_write_cor = aml_cimax_write_cor; + ci->ci_negotiate = aml_cimax_negotiate; + ci->ci_read_lpdu = aml_cimax_read_lpdu; + ci->ci_write_lpdu = aml_cimax_write_lpdu; + ci->ci_read_cam_status = aml_cimax_read_cam_status; + ci->ci_cam_reset = aml_cimax_cam_reset; + ci->ci_get_capbility = aml_cimax_get_capbility; + ci->ci_slot_reset = aml_cimax_slot_reset; + ci->ci_slot_shutdown = aml_cimax_slot_shutdown; + ci->ci_slot_ts_enable = aml_cimax_slot_ts_enable; + ci->ci_poll_slot_status = aml_cimax_slot_status; + + ci->data = cimax; + return 0; +} +EXPORT_SYMBOL(aml_cimax_init); + +int aml_cimax_exit(struct aml_ci *ci) +{ + struct aml_cimax *cimax = ci->data; + + aml_cimax_stop(cimax); + + if (cimax->io_type == IO_TYPE_SPI) { + //aml_cimax_spi_exit(cimax); + } + else { + aml_cimax_usb_exit(cimax); + } + kfree(cimax); + ci->data = NULL; + + return 0; +} +EXPORT_SYMBOL(aml_cimax_exit); + +int aml_cimax_slot_state_changed(struct aml_cimax *cimax, int slot, int state) +{ + //if (slot == 0) + // switch_set_state(&slot_state, state); + return 0; +} +EXPORT_SYMBOL(aml_cimax_slot_state_changed); +#if 0 +static int __init aml_cimax_mod_init(void) +{ + pr_dbg("Amlogic DVB CIMAX Init\n"); + //switch_dev_register(&slot_state); + //switch_set_state(&slot_state, 0); + return 0; +} + +static void __exit aml_cimax_mod_exit(void) +{ + pr_dbg("Amlogic DVB CIMAX Exit\n"); + //switch_dev_unregister(&slot_state); +} + +module_init(aml_cimax_mod_init); +module_exit(aml_cimax_mod_exit); + +MODULE_LICENSE("GPL"); +#endif + diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/aml_cimax.h b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/aml_cimax.h new file mode 100644 index 000000000000..17c62fad7625 --- /dev/null +++ b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/aml_cimax.h @@ -0,0 +1,61 @@ +/*************************************************************************** + * Copyright (c) 2014 Amlogic, Inc. All rights reserved. + * + * This source code is subject to the terms and conditions defined in the + * file 'LICENSE' which is part of this source code package. + * + * Description: + * +***************************************************************************/ + +#ifndef __AML_CIMAX_H_ +#define __AML_CIMAX_H_ + +#include "../aml_ci.h" +#include "dvb_ca_en50221_cimax.h" + +struct aml_cimax; + +struct aml_cimax_ops { + int (*read_cis)(struct aml_cimax *cimax, int slot, u8 *buf, int size); + int (*write_cor)(struct aml_cimax *cimax, + int slot, int address, u8 *buf); + int (*negotiate)(struct aml_cimax *cimax, int slot, int size); + int (*read_lpdu)(struct aml_cimax *cimax, int slot, u8 *buf, int size); + int (*write_lpdu)(struct aml_cimax *cimax, int slot, u8 *buf, int size); + int (*read_cam_status)(struct aml_cimax *cimax, int slot); + int (*cam_reset)(struct aml_cimax *cimax, int slot); + int (*get_capblility)(struct aml_cimax *cimax, int slot); + + int (*slot_reset)(struct aml_cimax *cimax, int slot); + int (*slot_shutdown)(struct aml_cimax *cimax, int slot); + int (*slot_ts_enable)(struct aml_cimax *cimax, int slot); + int (*slot_status)(struct aml_cimax *cimax, int slot); + + /*load fw etc.*/ + int (*start)(struct aml_cimax *cimax); + int (*stop)(struct aml_cimax *cimax); + + /*cimax reg*/ + int (*read_reg)(struct aml_cimax *cimax, int addr, u8 *buf, int size); + int (*write_reg)(struct aml_cimax *cimax, int addr, u8 *buf, int size); +}; + +struct aml_cimax { + struct platform_device *pdev; + struct device *dev; + struct aml_ci *ci; + + int io_type; +#define IO_TYPE_SPI 0 +#define IO_TYPE_USB 1 + struct aml_cimax_ops ops; + void *priv; +}; + +int aml_cimax_init(struct platform_device *pdev, struct aml_ci *ci_dev); +int aml_cimax_exit(struct aml_ci *ci_dev); + +int aml_cimax_camchanged(struct aml_cimax *cimax, int slot, int plugin); +int aml_cimax_slot_state_changed(struct aml_cimax *cimax, int slot, int state); +#endif diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/aml_cimax_spi.c b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/aml_cimax_spi.c new file mode 100644 index 000000000000..a4aaddae0260 --- /dev/null +++ b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/aml_cimax_spi.c @@ -0,0 +1,2139 @@ +/*************************************************************************** + * Copyright (c) 2014 Amlogic, Inc. All rights reserved. + * + * This source code is subject to the terms and conditions defined in the + * file 'LICENSE' which is part of this source code package. + * + * Description: + * +***************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "aml_cimax.h" + +#define MOD_NAME "aml_cimax_spi" + +#define pr_dbg(fmt...)\ + do {\ + if (cimax_spi_debug)\ + pr_info("cimax_spi: "fmt);\ + } while (0) +#define pr_error(fmt...) pr_err("AML_CIMAX_SPI: " fmt) + +#define BUFFIN_CFG 0x0000 +#define BUFFIN_ADDR_LSB 0x0001 +#define BUFFIN_ADDR_MSB 0x0002 +#define BUFFIN_DATA 0x0003 +#define BUFFOUT_CFG 0x0004 +#define BUFFOUT_ADDR_LSB 0x0005 +#define BUFFOUT_ADDR_MSB 0x0006 +#define BUFFOUT_DATA 0x0007 +#define BOOT_Key 0x0008 +#define BOOT_Status 0x0009 +#define BOOT_Test 0x000A +#define usb2_0_irq_mask 0x0010 +#define usb2_0_status 0x0011 +#define usb2_0_rx 0x0012 +#define usb2_0_tx 0x0013 +#define SPI_Slave_Ctrl 0x0018 +#define SPI_Slave_Status 0x0019 +#define SPI_Slave_Rx 0x001A +#define SPI_Slave_Tx 0x001B +#define SPI_Slave_Mask 0x001C +#define UCSG_Ctrl 0x0020 +#define UCSG_Status 0x0021 +#define UCSG_RxData 0x0022 +#define UCSG_TxData 0x0023 +#define PCtrl_Ctrl 0x0028 +#define PCtrl_Status 0x0029 +#define PCtrl_NbByte_LSB 0x002A +#define PCtrl_NbByte_MSB 0x002B +#define SPI_Master_Ctl 0x0030 +#define SPI_Master_NCS 0x0031 +#define SPI_Master_Status 0x0032 +#define SPI_Master_TxBuf 0x0033 +#define SPI_Master_RxBuf 0x0034 +#define BISTRAM_Ctl 0x0038 +#define BISTRAM_Bank 0x0039 +#define BISTRAM_Pat 0x003A +#define BISTRAM_SM 0x003B +#define BISTRAM_AddrLSB 0x003C +#define BISTROM_Config 0x0040 +#define BISTROM_SignatureLSB 0x0041 +#define BISTROM_SignatureMSB 0x0042 +#define BISTROM_StartAddrLSB 0x0043 +#define BISTROM_StartAddrMSB 0x0043 +#define BISTROM_StopAddrLSB 0x0043 +#define BISTROM_StopAddrMSB 0x0043 +#define CkMan_Config 0x0048 +#define CkMan_Select 0x0049 +#define CkMan_Test 0x004A +#define Revision_Number 0x004B +#define ResMan_Config 0x0050 +#define ResMan_Status 0x0051 +#define ResMan_WD 0x0052 +#define ResMan_WD_MSB 0x0053 +#define CPU_Test 0x0060 +#define IrqMan_Config0 0x0068 +#define IrqMan_Config1 0x0069 +#define IrqMan_Irq0 0x006A +#define IrqMan_NMI 0x006B +#define IrqMan_SleepKey 0x006C +#define Tim_Config 0x0070 +#define Tim_Value_LSB 0x0071 +#define Tim_Value_MSB 0x0072 +#define Tim_Comp_LSB 0x0073 +#define Tim_Comp_MSB 0x0074 +#define TI_Config 0x0076 +#define TI_Data 0x0077 +#define TI_Reg0 0x0078 +#define TI_Reg1 0x0079 +#define TI_Reg2 0x007A +#define TI_Reg3 0x007B +#define TI_Reg4 0x007C +#define TI_ROM1 0x007D +#define TI_ROM2 0x007E +#define TI_ROM3 0x007F +#define DVBCI_START_ADDR 0x0100 +#define DVBCI_END_ADDR 0x017F +#define DATA 0x0180 +/*#define CTRL 0x0181*/ +#define QB_HOST 0x0182 +#define LEN_HOST_LSB 0x0183 +#define LEN_HOST_MSB 0x0184 +#define FIFO_TX_TH_LSB 0x0185 +#define FIFO_TX_TH_MSB 0x0186 +#define FIFO_TX_D_NB_LSB 0x0187 +#define FIFO_TX_D_NB_MSB 0x0188 +#define QB_MOD_CURR 0x0189 +#define LEN_MOD_CURR_LSB 0x018A +#define LEN_MOD_CURR_MSB 0x018B +#define QB_MOD 0x018C +#define LEN_MOD_LSB 0x018D +#define LEN_MOD_MSB 0x018E +#define FIFO_RX_TH_LSB 0x018F +#define FIFO_RX_TH_MSB 0x0190 +#define FIFO_RX_D_NB_LSB 0x0191 +#define FIFO_RX_D_NB_MSB 0x0192 +#define IT_STATUS_0 0x0193 +#define IT_STATUS_1 0x0194 +#define IT_MASK_0 0x0195 +#define IT_MASK_1 0x0196 +#define IT_HOST_PIN_CFG 0x0200 +#define CFG_0 0x0201 +#define CFG_1 0x0202 +#define CFG_2 0x0203 +#define IT_HOST 0x0204 +#define MOD_IT_STATUS 0x0205 +#define MOD_IT_MASK 0x0206 +#define MOD_CTRL_A 0x0207 +#define MOD_CTRL_B 0x0208 +#define DEST_SEL 0x0209 +#define CAM_MSB_ADD 0x020A +#define GPIO0_DIR 0x020B +#define GPIO0_DATA_IN 0x020C +#define GPIO0_DATA_OUT 0x020D +#define GPIO0_STATUS 0x020E +#define GPIO0_IT_MASK 0x020F +#define GPIO0_DFT 0x0210 +#define GPIO0_MASK_DATA 0x0211 +#define GPIO1_DIR 0x0212 +#define GPIO1_DATA_IN 0x0213 +#define GPIO1_DATA_OUT 0x0214 +#define GPIO1_STATUS 0x0215 +#define GPIO1_IT_MASK 0x0216 +#define MEM_ACC_TIME_A 0x0217 +#define MEM_ACC_TIME_B 0x0218 +#define IO_ACC_TIME_A 0x0219 +#define IO_ACC_TIME_B 0x021A +#define EXT_CH_ACC_TIME_A 0x021B +#define EXT_CH_ACC_TIME_B 0x021C +#define PAR_IF_0 0x021D +#define PAR_IF_1 0x021E +#define PAR_IF_CTRL 0x021F +#define PCK_LENGTH 0x0220 +#define USB2TS_CTRL 0x0221 +#define USB2TS0_RDL 0x0222 +#define USB2TS1_RDL 0x0223 +#define TS2USB_CTRL 0x0224 +#define TSOUT_PAR_CTRL 0x0225 +#define TSOUT_PAR_CLK_SEL 0x0226 +#define S2P_CH0_CTRL 0x0227 +#define S2P_CH1_CTRL 0x0228 +#define P2S_CH0_CTRL 0x0229 +#define P2S_CH1_CTRL 0x022A +#define TS_IT_STATUS 0x022B +#define TS_IT_MASK 0x022C +#define IN_SEL 0x022D +#define OUT_SEL 0x022E +#define ROUTER_CAM_CH 0x022F +#define ROUTER_CAM_MOD 0x0230 +#define FIFO_CTRL 0x0231 +#define FIFO1_2_STATUS 0x0232 +#define FIFO3_4_STATUS 0x0233 +#define GAP_REMOVER_CH0_CTRL 0x0234 +#define GAP_REMOVER_CH1_CTRL 0x0235 +#define SYNC_RTV_CTRL 0x0236 +#define SYNC_RTV_CH0_SYNC_NB 0x0237 +#define SYNC_RTV_CH0_PATTERN 0x0238 +#define SYNC_RTV_CH1_SYNC_NB 0x0239 +#define SYNC_RTV_CH1_PATTERN 0x023A +#define SYNC_RTV_OFFSET_PATT 0x023B +#define CTRL_FILTER 0x023D +#define PID_EN_FILTER_CH0 0x023E +#define PID_EN_FILTER_CH1 0x023F +#define PID_LSB_FILTER_CH0_0 0x0240 +#define PID_MSB_FILTER_CH0_0 0x0241 +#define PID_LSB_FILTER_CH0_1 0x0242 +#define PID_MSB_FILTER_CH0_1 0x0243 +#define PID_LSB_FILTER_CH0_2 0x0244 +#define PID_MSB_FILTER_CH0_2 0x0245 +#define PID_LSB_FILTER_CH0_3 0x0246 +#define PID_MSB_FILTER_CH0_3 0x0247 +#define PID_LSB_FILTER_CH0_4 0x0248 +#define PID_MSB_FILTER_CH0_4 0x0249 +#define PID_LSB_FILTER_CH0_5 0x024A +#define PID_MSB_FILTER_CH0_5 0x024B +#define PID_LSB_FILTER_CH0_6 0x024C +#define PID_MSB_FILTER_CH0_6 0x024D +#define PID_LSB_FILTER_CH0_7 0x024E +#define PID_MSB_FILTER_CH0_7 0x024F +#define PID_LSB_FILTER_CH1_0 0x0260 +#define PID_MSB_FILTER_CH1_0 0x0261 +#define PID_LSB_FILTER_CH1_1 0x0262 +#define PID_MSB_FILTER_CH1_1 0x0263 +#define PID_LSB_FILTER_CH1_2 0x0264 +#define PID_MSB_FILTER_CH1_2 0x0265 +#define PID_LSB_FILTER_CH1_3 0x0266 +#define PID_MSB_FILTER_CH1_3 0x0267 +#define PID_LSB_FILTER_CH1_4 0x0268 +#define PID_MSB_FILTER_CH1_4 0x0269 +#define PID_LSB_FILTER_CH1_5 0x026A +#define PID_MSB_FILTER_CH1_5 0x026B +#define PID_LSB_FILTER_CH1_6 0x026C +#define PID_MSB_FILTER_CH1_6 0x026D +#define PID_LSB_FILTER_CH1_7 0x026E +#define PID_MSB_FILTER_CH1_7 0x026F +#define PID_OLD_LSB_REMAPPER_0 0x0280 +#define PID_OLD_MSB_REMAPPER_0 0x0281 +#define PID_OLD_LSB_REMAPPER_1 0x0282 +#define PID_OLD_MSB_REMAPPER_1 0x0283 +#define PID_OLD_LSB_REMAPPER_2 0x0284 +#define PID_OLD_MSB_REMAPPER_2 0x0285 +#define PID_OLD_LSB_REMAPPER_3 0x0286 +#define PID_OLD_MSB_REMAPPER_3 0x0287 +#define PID_OLD_LSB_REMAPPER_4 0x0288 +#define PID_OLD_MSB_REMAPPER_4 0x0289 +#define PID_OLD_LSB_REMAPPER_5 0x028A +#define PID_OLD_MSB_REMAPPER_5 0x028B +#define PID_OLD_LSB_REMAPPER_6 0x028C +#define PID_OLD_MSB_REMAPPER_6 0x028D +#define PID_OLD_LSB_REMAPPER_7 0x028E +#define PID_OLD_MSB_REMAPPER_7 0x028F +#define PID_NEW_LSB_REMAPPER_0 0x02A0 +#define PID_NEW_MSB_REMAPPER_0 0x02A1 +#define PID_NEW_LSB_REMAPPER_1 0x02A2 +#define PID_NEW_MSB_REMAPPER_1 0x02A3 +#define PID_NEW_LSB_REMAPPER_2 0x02A4 +#define PID_NEW_MSB_REMAPPER_2 0x02A5 +#define PID_NEW_LSB_REMAPPER_3 0x02A6 +#define PID_NEW_MSB_REMAPPER_3 0x02A7 +#define PID_NEW_LSB_REMAPPER_4 0x02A8 +#define PID_NEW_MSB_REMAPPER_4 0x02A9 +#define PID_NEW_LSB_REMAPPER_5 0x02AA +#define PID_NEW_MSB_REMAPPER_5 0x02AB +#define PID_NEW_LSB_REMAPPER_6 0x02AC +#define PID_NEW_MSB_REMAPPER_6 0x02AD +#define PID_NEW_LSB_REMAPPER_7 0x02AE +#define PID_NEW_MSB_REMAPPER_7 0x02AF +#define MERGER_DIV_MICLK 0x02C0 +#define PID_AND_SYNC_REMAPPER_CTRL 0x02C1 +#define PID_EN_REMAPPER 0x02C2 +#define SYNC_SYMBOL 0x02C3 +#define PID_AND_SYNC_REMAPPER_INV_CTRL 0x02C4 +#define BITRATE_CH0_LSB 0x02C5 +#define BITRATE_CH0_MSB 0x02C6 +#define BITRATE_CH1_LSB 0x02C7 +#define BITRATE_CH1_MSB 0x02C8 +#define STATUS_CLK_SWITCH_0 0x02C9 +#define STATUS_CLK_SWITCH_1 0x02CA +#define RESET_CLK_SWITCH_0 0x02CB +#define RESET_CLK_SWITCH_1 0x02CC +#define PAD_DRVSTR_CTRL 0x02CD +#define PAD_PUPD_CTRL 0x02CE +#define PRE_HEADER_ADDER_CH0_0 0x02D0 +#define PRE_HEADER_ADDER_CH0_1 0x02D1 +#define PRE_HEADER_ADDER_CH0_2 0x02D2 +#define PRE_HEADER_ADDER_CH0_3 0x02D3 +#define PRE_HEADER_ADDER_CH0_4 0x02D4 +#define PRE_HEADER_ADDER_CH0_5 0x02D5 +#define PRE_HEADER_ADDER_CH0_6 0x02D6 +#define PRE_HEADER_ADDER_CH0_7 0x02D7 +#define PRE_HEADER_ADDER_CH0_8 0x02D8 +#define PRE_HEADER_ADDER_CH0_9 0x02D9 +#define PRE_HEADER_ADDER_CH0_10 0x02DA +#define PRE_HEADER_ADDER_CH0_11 0x02DB +#define PRE_HEADER_ADDER_CH1_0 0x02E0 +#define PRE_HEADER_ADDER_CH1_1 0x02E1 +#define PRE_HEADER_ADDER_CH1_2 0x02E2 +#define PRE_HEADER_ADDER_CH1_3 0x02E3 +#define PRE_HEADER_ADDER_CH1_4 0x02E4 +#define PRE_HEADER_ADDER_CH1_5 0x02E5 +#define PRE_HEADER_ADDER_CH1_6 0x02E6 +#define PRE_HEADER_ADDER_CH1_7 0x02E7 +#define PRE_HEADER_ADDER_CH1_8 0x02E8 +#define PRE_HEADER_ADDER_CH1_9 0x02E9 +#define PRE_HEADER_ADDER_CH1_10 0x02EA +#define PRE_HEADER_ADDER_CH1_11 0x02EB +#define PRE_HEADER_ADDER_CTRL 0x02EC +#define PRE_HEADER_ADDER_LEN 0x02ED +#define PRE_HEADER_REMOVER_CTRL 0x02EE +#define FSM_DVB 0x02F0 +#define TS2USB_FSM_DEBUG 0x02F2 +#define TSOUT_PAR_FSM_DEBUG 0x02F3 +#define GAP_REMOVER_FSM_DEBUG 0x02F4 +#define PID_AND_SYNC_REMAPPER_FSM_DEBUG 0x02F5 +#define PRE_HEADER_ADDER_FSM_DEBUG 0x02F6 +#define SYNC_RTV_FSM_DEBUG 0x02F7 +#define CHECK_PHY_CLK 0x0E00 +#define USB_CTRL1 0x0E01 +#define USB_ISO2_out 0x0800 +#define USB_ISO1_out 0x1000 +#define USB_Interrupt_out 0x1E00 +#define USB_Bulk_in 0x1F00 +#define CC2_Buffer_out 0x2000 +#define USB_EP0 0x30C0 +#define CC2_Buffer_in 0x4000 +#define USB_ISO2_in 0x5800 +#define USB_ISO1_in 0x6000 +#define nmb_vector_address_lsb 0xFFFA +#define nmb_vector_address_msb 0xFFFB +#define reset_vector_address_lsb 0xFFFC +#define reset_vector_address_msb 0xFFFD +#define irb_vector_address_lsb 0xFFFE +#define irb_vector_address_msb 0xFFFF + + +#define CIMAX_REG_HDR_SIZE 4 +#define CIMAX_REG_PLD_SIZE 255 +#define CIMAX_CAM_HDR_SIZE 4 +#define CIMAX_CAM_PLD_SIZE 65535 + +#define DEF_LOCK(_l_) struct mutex _l_ + +struct cimax_spi { + struct platform_device *pdev; + struct spi_device *dev; + + struct aml_cimax *cimax; + + u8 buf[CIMAX_REG_HDR_SIZE + CIMAX_CAM_HDR_SIZE + CIMAX_CAM_PLD_SIZE]; + + int cam_inserted[2]; + int cam_data_ready[2]; + + int poll_mode; +#define STOP_MODE 0 +#define POLL_MODE 1 +#define INT_MODE 2 + + int irq; + int irq_io; + int rst_io; + + struct workqueue_struct *workq; + struct delayed_work work; + int work_cnt; + + DEF_LOCK(lock); +#define lock_init(_spi) mutex_init(&(_spi)->lock) +#define lock_lock(_spi) do {\ + int err = mutex_lock_interruptible(&(_spi)->lock);\ + if (err)\ + return err;\ +} while (0) +#define lock_unlock(_spi) mutex_unlock(&(_spi)->lock) + + u8 *cis; +#define CIS_MAX 512 +}; + +static struct cimax_spi *g_spi; + +MODULE_PARM_DESC(debug, "enable verbose debug messages"); +static int cimax_spi_debug = 1; +module_param_named(debug, cimax_spi_debug, int, 0644); + +MODULE_PARM_DESC(poll_interval, "interval for spi poll"); +static int spi_poll_interval = 100; +module_param_named(poll_interval, spi_poll_interval, int, 0644); + +MODULE_PARM_DESC(poll_mode, "set cimax poll mode, need reset"); +static int cimax_poll_mode = 1; +module_param_named(poll_mode, cimax_poll_mode, int, 0644); + +MODULE_PARM_DESC(cam_irq_mode, "set cam irq mode, need reset"); +static int cam_irq_mode; +module_param_named(cam_irq_mode, cam_irq_mode, int, 0644); + +#define CIMAX_REG_READ 0xff +#define CIMAX_REG_READ_OK 0x4c +#define CIMAX_REG_WRITE 0x7f +#define CIMAX_REG_WRITE_OK 0x4d +#define CIMAX_REG_INIT 0x00 +#define CIMAX_REG_INIT_OK 0x4b +#define CIMAX_REG_CMD_ERROR 0x51 + +#define CIMAX_CAM_RESET 0x01 +#define CIMAX_CAM_RESET_OK 0x40 +#define CIMAX_CAM_CIS 0x02 +#define CIMAX_CAM_CIS_OK 0x41 +#define CIMAX_CAM_COR 0x03 +#define CIMAX_CAM_COR_OK 0x42 +#define CIMAX_CAM_NEG 0x04 +#define CIMAX_CAM_NEG_OK 0x43 +#define CIMAX_CAM_WLPDU 0x05 +#define CIMAX_CAM_WLPDU_OK 0x44 +#define CIMAX_CAM_RLPDU 0x06 +#define CIMAX_CAM_RLPDU_OK 0x46 +#define CIMAX_CAM_EVT 0x0d +#define CIMAX_CAM_DET_OK 0x45 +#define CIMAX_CAM_NOCAM 0x49 +#define CIMAX_CAM_ERROR 0x4a +#define CIMAX_CAM_NOEVT 0x55 +#define CIMAX_CAM_DATA_READY 0x4e +#define CIMAX_CAM_WBUSY 0x54 +#define CIMAX_CAM_PENDING 0x56 +#define CIMAX_CAM_REGSTAT 0x0e +#define CIMAX_CAM_REGSTAT_OK 0x57 + + +#define CIMAX_CAM_PKT_CNT_VAL 1 + +#define CIMAX_SLOT_A 0 +#define CIMAX_SLOT_B 1 + +#define CIMAX_CMD_RESP_MASK 0x7f + +#define cimax_to_spi(_c) ((struct cimax_spi *)((_c)->priv)) +#define dev_to_spi(_d) ((struct cimax_spi *)spi_get_drvdata(_d)) + +#define byte_to_u16(_b1, _b2) (((_b1)<<8) | (_b2)) + +#define hdr_cmd_resp(_s) ((_s)->buf[0] & CIMAX_CMD_RESP_MASK) + +#define reg_hdr(_s) ((_s)->buf) +#define reg_addr(_s) byte_to_u16((_s)->buf[1], (_s)->buf[2]) +#define reg_hdr_dat_size(_s) ((_s)->buf[3]) +#define reg_dat(_s) (&((_s)->buf[CIMAX_REG_HDR_SIZE])) + +#define cam_hdr(_s) ((_s)->buf) +#define cam_hdr_slot(_s) (((_s)->buf[0] & 0x80) ? 1 : 0) +#define cam_hdr_pkt_cnt(_s) ((_s)->buf[1]) +#define cam_hdr_dat_size(_s) byte_to_u16((_s)->buf[2], (_s)->buf[3]) +#define cam_dat(_s) (&((_s)->buf[CIMAX_CAM_HDR_SIZE])) + +#define REG_TIMEOUT 500 +#define CAM_TIMEOUT 5000 + +#define USE_INT_PIO + +static int aml_cimax_spi_mod_init(void); +static void aml_cimax_spi_mod_exit(void); + +static void dump(char *title, u8 *buf, int size) +{ + int i; + pr_info("%s\n", title); + for (i = 0; i < size; i++) { + if (!(i & 0xf)) + pr_info("\n\t"); + pr_info("%02x ", *(buf+i)); + } + pr_info("\n"); +} + +static void perr(char *err, struct cimax_spi *spi) +{ + pr_error("error: %s\n", err); + dump("dump:", spi->buf, 16); +} + +static inline unsigned long get_jiffies(void) +{ + return (unsigned long)(sched_clock()/10000000); +} + +static inline void set_spi_cam_ready(struct cimax_spi *spi, int slot) +{ + if (spi->cam_inserted[slot] == 1) { + spi->cam_inserted[slot] = 2; + aml_cimax_slot_state_changed(spi->cimax, + slot, spi->cam_inserted[slot]); + } +} + + +static int cimax_spi_get_resp(struct cimax_spi *spi, int timeout) +{ + struct spi_device *dev = spi->dev; + int ret = 0; + unsigned long start = get_jiffies(); +#ifndef USE_INT_PIO + u8 t = 0; + + while (!t && jiffies_to_msecs(get_jiffies() - start) < timeout) { + ret = spi_read(dev, &t, 1); + if (ret) + return ret; + usleep_range(1000, 2000); + } + if (!t) { + pr_error("resp timeout: %dms\n", timeout); + return -EIO; + } + cam_hdr(spi)[0] = t; + ret = spi_read(dev, cam_hdr(spi)+1, CIMAX_CAM_HDR_SIZE-1); + if (ret) + return ret; +#else + do { + if (jiffies_to_msecs(get_jiffies() - start) >= timeout) { + pr_error("resp timeout: %dms\n", timeout); + return -EIO; + } + usleep_range(1000, 2000); + } while (gpio_get_value(spi->irq_io)); + + ret = spi_read(dev, cam_hdr(spi), CIMAX_CAM_HDR_SIZE); + if (ret) + return ret; +#endif + /*pr_dbg("rp: %02x:%02x:%02x:%02x\n", + cam_hdr(spi)[0], cam_hdr(spi)[1], + cam_hdr(spi)[2], cam_hdr(spi)[3]);*/ + switch (hdr_cmd_resp(spi)) { + case CIMAX_REG_READ_OK: + case CIMAX_REG_WRITE_OK: + case CIMAX_REG_INIT_OK: + case CIMAX_REG_CMD_ERROR: { + int len = reg_hdr_dat_size(spi); + if (len) { + ret = spi_read(dev, reg_dat(spi), len); + if (ret != 0) + return ret; + } + } break; + case CIMAX_CAM_RESET_OK: + case CIMAX_CAM_CIS_OK: + case CIMAX_CAM_COR_OK: + case CIMAX_CAM_NEG_OK: + case CIMAX_CAM_WLPDU_OK: + case CIMAX_CAM_RLPDU_OK: + case CIMAX_CAM_NOCAM: + case CIMAX_CAM_ERROR: + case CIMAX_CAM_WBUSY: + case CIMAX_CAM_DET_OK: + case CIMAX_CAM_DATA_READY: + case CIMAX_CAM_PENDING: + case CIMAX_CAM_REGSTAT_OK: + case CIMAX_CAM_NOEVT: { + int len = cam_hdr_dat_size(spi); + if (len) { + ret = spi_read(dev, cam_dat(spi), len); + if (ret != 0) + return ret; + /*if (len) + dump("dat:", cam_dat(spi), len);*/ + } + } + break; + default: + pr_error("unknown resp:0x%02x\n", hdr_cmd_resp(spi)); + return -EINVAL; + } + return 0; +} + +static int init_reg_hdr(u8 *hdr, u8 tag, int addr, int size) +{ + hdr[0] = tag; + hdr[1] = (addr>>8) & 0xff; + hdr[2] = addr & 0xff; + hdr[3] = size; + return 0; +} + +static int check_reg_hdr(u8 *hdr, u8 tag, int addr, int size) +{ + return hdr[0] != tag + || hdr[1] != ((addr>>8) & 0xff) + || hdr[2] != (addr & 0xff) + || hdr[3] != size; +} + +static int aml_cimax_spi_read_reg(struct aml_cimax *cimax, int addr, + u8 *buf, int size) +{ + struct cimax_spi *spi = cimax_to_spi(cimax); + struct spi_device *dev = spi->dev; + int err = 0; + + init_reg_hdr(spi->buf, CIMAX_REG_READ, addr, size); + + lock_lock(spi); + + pr_dbg("rd %02x:%02x:%02x:%02x\n", + reg_hdr(spi)[0], reg_hdr(spi)[1], + reg_hdr(spi)[2], reg_hdr(spi)[3]); + err = spi_write(dev, spi->buf, CIMAX_REG_HDR_SIZE); + if (err) + goto end; + err = cimax_spi_get_resp(spi, REG_TIMEOUT); + if (err) + goto end; + if (check_reg_hdr(reg_hdr(spi), CIMAX_REG_READ_OK, addr, size) != 0) { + perr("read reg fail.", spi); + err = -EINVAL; + goto end; + } + memcpy(buf, reg_dat(spi), size); +end: + lock_unlock(spi); + return err; +} + +static int aml_cimax_spi_write_reg(struct aml_cimax *cimax, int addr, + u8 *buf, int size) +{ + struct cimax_spi *spi = cimax_to_spi(cimax); + struct spi_device *dev = spi->dev; + int err = 0; + + init_reg_hdr(spi->buf, CIMAX_REG_WRITE, addr, size); + memcpy(&spi->buf[CIMAX_REG_HDR_SIZE], buf, size); + + lock_lock(spi); + + pr_dbg("wr %02x:%02x:%02x:%02x\n", + reg_hdr(spi)[0], reg_hdr(spi)[1], + reg_hdr(spi)[2], reg_hdr(spi)[3]); + err = spi_write(dev, spi->buf, CIMAX_REG_HDR_SIZE + size); + if (err) + goto end; + err = cimax_spi_get_resp(spi, REG_TIMEOUT); + if (err) + goto end; + if (check_reg_hdr(reg_hdr(spi), CIMAX_REG_WRITE_OK, addr, 0) != 0) { + perr("write reg fail.", spi); + err = -EINVAL; + goto end; + } +end: + lock_unlock(spi); + return err; +} + +static inline int init_cam_hdr(u8 *hdr, int cmd, int size) +{ + hdr[0] = cmd; + hdr[1] = CIMAX_CAM_PKT_CNT_VAL; + hdr[2] = (size>>8) & 0xff; + hdr[3] = size & 0xff; + return 0; +} + +static inline int cam_err(struct cimax_spi *spi) +{ + if (hdr_cmd_resp(spi) != CIMAX_CAM_ERROR + || cam_hdr_pkt_cnt(spi) != CIMAX_CAM_PKT_CNT_VAL + || cam_hdr_dat_size(spi) != 2) + return 0; + return byte_to_u16(cam_dat(spi)[0], cam_dat(spi)[1]); +} + +static inline char *cam_err_str(int err) +{ +#define CAMERROR_RESET 0x0101 +#define CAMERROR_CIS_BUF 0x0201 +#define CAMERROR_CIS_SIZE 0x0202 +#define CAMERROR_CAM_NOT_ACT 0x0203 +#define CAMERROR_COR_NOT_READY 0x0301 +#define CAMERROR_COR_VAL_CHK 0x0302 +#define CAMERROR_NEG_NO_RESP 0x0401 +#define CAMERROR_NEG_BAD_SIZE 0x0402 +#define CAMERROR_NEG_NOT_READY 0x0403 +#define CAMERROR_LPDU_NOT_AVAIL 0x0601 + struct { int err; char *str; } cam_err_strings[] = { + {CAMERROR_RESET, "reset error, not ready."}, + {CAMERROR_CIS_BUF, "cis error, buffer not allocated."}, + {CAMERROR_CIS_SIZE, "cis error, bad cis size."}, + {CAMERROR_CAM_NOT_ACT, "cam not activated."}, + {CAMERROR_COR_NOT_READY, "cam not ready during write COR."}, + {CAMERROR_COR_VAL_CHK, "COR value check failed."}, + {CAMERROR_NEG_NO_RESP, "cam not responding when negotiation."}, + {CAMERROR_NEG_BAD_SIZE, "cam buf size length != 2."}, + {CAMERROR_NEG_NOT_READY, "cam not ready during negotiation."}, + {CAMERROR_LPDU_NOT_AVAIL, "lpdu not available."} + }; + int i; + for (i = 0; + i < sizeof(cam_err_strings)/sizeof(cam_err_strings[0]); i++) { + if (cam_err_strings[i].err == err) + return cam_err_strings[i].str; + } + return "err unknown."; +} + +static int cimax_spi_access_cam(struct cimax_spi *spi, int slot, + int cmd, u8 *buf, int size) +{ + struct spi_device *dev = spi->dev; + int err = 0; + + cmd |= slot ? 0x80 : 0; + init_cam_hdr(cam_hdr(spi), cmd, size); + memcpy(cam_dat(spi), buf, size); + /*dump("access cam:", cam_hdr(spi), CIMAX_CAM_HDR_SIZE+size);*/ + err = spi_write(dev, cam_hdr(spi), CIMAX_CAM_HDR_SIZE + size); + if (err) + return err; + err = cimax_spi_get_resp(spi, CAM_TIMEOUT); + if (err) + return err; + if (cam_hdr_slot(spi) != slot) { + pr_error("expect slot(%d), but slot(%d)\n", + slot, cam_hdr_slot(spi)); + return -EINVAL; + } + switch (hdr_cmd_resp(spi)) { + case CIMAX_CAM_NOCAM: + pr_dbg("no cam\n"); + err = -ENODEV; + break; + case CIMAX_CAM_ERROR: + pr_error("cam error\n"); + pr_error("err code: 0x%04x(%s)\n", cam_err(spi), + cam_err_str(cam_err(spi))); + err = -ENODEV; + break; + case CIMAX_CAM_WBUSY: + pr_dbg("cam busy\n"); + err = -EBUSY; + break; + case CIMAX_CAM_PENDING: + pr_dbg("cam pending\n"); + err = -EAGAIN; + break; + } + return err; +} + +static int aml_cimax_spi_read_cis(struct aml_cimax *cimax, int slot, + u8 *buf, int size) +{ + struct cimax_spi *spi = cimax_to_spi(cimax); + int err = 0; + int len; + + lock_lock(spi); + + err = cimax_spi_access_cam(spi, slot, CIMAX_CAM_CIS, NULL, 0); + if (err) + goto end; + if (hdr_cmd_resp(spi) != CIMAX_CAM_CIS_OK + || cam_hdr_pkt_cnt(spi) != CIMAX_CAM_PKT_CNT_VAL) { + perr("read cis fail.", spi); + err = -EINVAL; + goto end; + } + len = cam_hdr_dat_size(spi); + if (size < len) { + pr_error("cis size too large, expect<%d, but:%d\n", size, len); + perr("cis fail.", spi); + err = -EINVAL; + goto end; + } + memcpy(buf, cam_dat(spi), len); + + if (!spi->cis) + spi->cis = kzalloc((len < 512) ? 512 : len, GFP_KERNEL); + if (spi->cis) + memcpy(spi->cis, cam_dat(spi), len); + +end: + lock_unlock(spi); + return err; +} +#define CIMAX_CAM_COR_PLD_SIZE 5 +static int aml_cimax_spi_write_cor(struct aml_cimax *cimax, int slot, + int addr, u8 *buf) +{ + struct cimax_spi *spi = cimax_to_spi(cimax); + int err = 0; + u8 out[CIMAX_CAM_COR_PLD_SIZE + 8]; + int sz = CIMAX_CAM_COR_PLD_SIZE; + + out[0] = addr>>8 & 0xff; + out[1] = addr & 0xff; + out[2] = buf[0]; + out[3] = 0; + out[4] = 0; + + if (!cam_irq_mode) { + out[5] = 0x40;/*cam poll mode*/ + sz++; + } + + lock_lock(spi); + + err = cimax_spi_access_cam(spi, slot, CIMAX_CAM_COR, out, sz); + if (err) + goto end; + if (hdr_cmd_resp(spi) != CIMAX_CAM_COR_OK + || cam_hdr_pkt_cnt(spi) != CIMAX_CAM_PKT_CNT_VAL + || cam_hdr_dat_size(spi) != 0) { + perr("write cor fail.", spi); + err = -EINVAL; + goto end; + } +end: + lock_unlock(spi); + return err; +} +#define CIMAX_CAM_NEG_PLD_SIZE 2 +static int aml_cimax_spi_negotiate(struct aml_cimax *cimax, int slot, int size) +{ + struct cimax_spi *spi = cimax_to_spi(cimax); + int ret = 0; + u8 out[CIMAX_CAM_NEG_PLD_SIZE]; + + out[0] = (size>>8) & 0xff; + out[1] = size & 0xff; + + lock_lock(spi); + + ret = cimax_spi_access_cam(spi, slot, CIMAX_CAM_NEG, + out, CIMAX_CAM_NEG_PLD_SIZE); + if (ret) + goto end; + if (hdr_cmd_resp(spi) != CIMAX_CAM_NEG_OK + || cam_hdr_pkt_cnt(spi) != CIMAX_CAM_PKT_CNT_VAL + || cam_hdr_dat_size(spi) != 2) { + perr("negotiate fail.", spi); + ret = -EINVAL; + goto end; + } + ret = byte_to_u16(cam_dat(spi)[0], cam_dat(spi)[1]); + + set_spi_cam_ready(spi, slot); +end: + lock_unlock(spi); + return ret; +} + +static int aml_cimax_spi_write_lpdu(struct aml_cimax *cimax, int slot, + u8 *buf, int size) +{ + struct cimax_spi *spi = cimax_to_spi(cimax); + int ret = 0; + + lock_lock(spi); + + /*dump("lpdu ->", buf, size);*/ + ret = cimax_spi_access_cam(spi, slot, CIMAX_CAM_WLPDU, buf, size); + if (ret) + goto end; + if (hdr_cmd_resp(spi) != CIMAX_CAM_WLPDU_OK + || cam_hdr_pkt_cnt(spi) != CIMAX_CAM_PKT_CNT_VAL + || cam_hdr_dat_size(spi) != 0) { + perr("write lpdu fail.", spi); + ret = -EINVAL; + goto end; + } + ret = size; +end: + lock_unlock(spi); + return ret; +} + +static int aml_cimax_spi_read_lpdu(struct aml_cimax *cimax, int slot, + u8 *buf, int size) +{ + struct cimax_spi *spi = cimax_to_spi(cimax); + int ret = 0; + + lock_lock(spi); + + ret = cimax_spi_access_cam(spi, slot, CIMAX_CAM_RLPDU, NULL, 0); + if (ret) + goto end; + if (hdr_cmd_resp(spi) != CIMAX_CAM_RLPDU_OK + || cam_hdr_pkt_cnt(spi) != CIMAX_CAM_PKT_CNT_VAL) { + perr("read lpdu fail.", spi); + ret = -EINVAL; + goto end; + } + ret = cam_hdr_dat_size(spi); + memcpy(buf, cam_dat(spi), ret); + + /*dump("lpdu <-", buf, ret);*/ + + spi->cam_data_ready[slot] = 0; +end: + lock_unlock(spi); + return ret; +} + +static int aml_cimax_spi_read_cam_status(struct aml_cimax *cimax, int slot) +{ + struct cimax_spi *spi = cimax_to_spi(cimax); + int ret = 0; + + if (cam_irq_mode && spi->cam_data_ready[slot]) + return 0x80; + + lock_lock(spi); + + ret = cimax_spi_access_cam(spi, slot, CIMAX_CAM_REGSTAT, NULL, 0); + if (ret) + goto end; + if (hdr_cmd_resp(spi) != CIMAX_CAM_REGSTAT_OK + || cam_hdr_pkt_cnt(spi) != CIMAX_CAM_PKT_CNT_VAL + || cam_hdr_dat_size(spi) != 1) { + perr("read cam status fail.", spi); + ret = -EINVAL; + goto end; + } + + ret = cam_dat(spi)[0]; +end: + lock_unlock(spi); + return ret; +} + +static int aml_cimax_spi_slot_reset(struct aml_cimax *cimax, int slot) +{ + struct cimax_spi *spi = cimax_to_spi(cimax); + int ret = 0; + + spi->cam_data_ready[slot] = 0; + + lock_lock(spi); + + ret = cimax_spi_access_cam(spi, slot, CIMAX_CAM_RESET, NULL, 0); + if (ret) + goto end; + if (hdr_cmd_resp(spi) != CIMAX_CAM_RESET_OK + || cam_hdr_pkt_cnt(spi) != CIMAX_CAM_PKT_CNT_VAL + || cam_hdr_dat_size(spi) != 0) { + perr("slot reset fail.", spi); + ret = -EINVAL; + goto end; + } +end: + lock_unlock(spi); + return ret; +} + +static int aml_cimax_spi_cam_reset(struct aml_cimax *cimax, int slot) +{ + pr_dbg("Slot(%d): camreset\n", slot); + return 0; +} + +static int aml_cimax_spi_slot_shutdown(struct aml_cimax *cimax, int slot) +{ + pr_dbg("Slot(%d): shutdown\n", slot); + return 0; +} +static int aml_cimax_spi_slot_ts_enable(struct aml_cimax *cimax, int slot) +{ + pr_dbg("Slot(%d): ts control\n", slot); + return 0; +} +static int aml_cimax_spi_slot_status(struct aml_cimax *cimax, int slot) +{ + struct cimax_spi *spi = cimax_to_spi(cimax); + if (spi->cam_inserted[slot]) { + /*pr_dbg("CA Module present and ready\n");*/ + return DVB_CA_EN50221_POLL_CAM_PRESENT | + DVB_CA_EN50221_POLL_CAM_READY; + } else { + /*pr_error("CA Module not present or not ready\n");*/ + } + return 0; +} + +static int cimax_spi_cam_plugin(struct cimax_spi *spi, int slot, int plugin) +{ + pr_dbg("cam plug: slot(%d) %s\n", + slot, plugin ? "plugged" : "unplugged"); + return aml_cimax_camchanged(spi->cimax, slot, plugin); +} + +static int cimax_spi_poll(struct cimax_spi *spi) +{ + struct spi_device *dev = spi->dev; + int err = 0; + + lock_lock(spi); + +#ifdef USE_INT_PIO + if (gpio_get_value(spi->irq_io)) + goto end; +#endif + + init_reg_hdr(spi->buf, CIMAX_CAM_EVT, 0x100, 0); + err = spi_write(dev, spi->buf, CIMAX_REG_HDR_SIZE); + if (err) + goto end; + err = cimax_spi_get_resp(spi, CAM_TIMEOUT); + if (err) + goto end; + switch (hdr_cmd_resp(spi)) { + case CIMAX_CAM_DET_OK: { + int slot = cam_hdr_slot(spi); + int insert = cam_dat(spi)[0]; + if (!!spi->cam_inserted[slot] != insert) { + spi->cam_inserted[slot] = insert; + cimax_spi_cam_plugin(spi, slot, insert); + aml_cimax_slot_state_changed(spi->cimax, slot, + spi->cam_inserted[slot]); + } + } break; + case CIMAX_CAM_DATA_READY: { + int slot = cam_hdr_slot(spi); + spi->cam_data_ready[slot] = 1; + } break; + case CIMAX_CAM_NOEVT: + break; + default: + pr_error("unknown resp:%02x\n", hdr_cmd_resp(spi)); + break; + } +end: + queue_delayed_work(spi->workq, &spi->work, spi_poll_interval); + lock_unlock(spi); + return 0; +} + +static void cimax_spi_poll_work(struct work_struct *work) +{ + struct cimax_spi *spi = + container_of(to_delayed_work(work), struct cimax_spi, work); + spi->work_cnt++; + cimax_spi_poll(spi); +} + +static irqreturn_t cimax_irq_handler(int irq, void *para) +{ + return IRQ_HANDLED; +} + +#define CTRL_DISABLE -1 +#define CTRL_STOP 0 +#define CTRL_START 1 + +static inline int cimax_spi_poll_ctrl(struct cimax_spi *spi, int ctrl) +{ + if (ctrl == CTRL_START) { + spi->workq = create_singlethread_workqueue("cimax_spi"); + INIT_DELAYED_WORK(&spi->work, &cimax_spi_poll_work); + queue_delayed_work(spi->workq, + &spi->work, spi_poll_interval); + pr_dbg("poll started\n"); + } else { + if (!spi->workq) + return 0; + cancel_delayed_work_sync(&spi->work); + destroy_workqueue(spi->workq); + spi->workq = NULL; + pr_dbg("poll stopped\n"); + } + return 0; +} + +static inline int cimax_spi_intr_ctrl(struct cimax_spi *spi, int ctrl) +{ + if (ctrl == CTRL_START) { + int ret; + if (spi->irq == -1) { + pr_error("incorrect irq"); + return -1; + } + ret = request_irq(spi->irq, cimax_irq_handler, + IRQF_SHARED|IRQF_TRIGGER_RISING, + "cimax irq", spi); + enable_irq(spi->irq); + } else { + if (spi->irq == -1) + return 0; + disable_irq(spi->irq); + free_irq(spi->irq, spi); + } + return 0; +} + +static int cimax_spi_setup_poll(struct cimax_spi *spi, int poll_mode) +{ + if (poll_mode == spi->poll_mode) + return 0; + switch (poll_mode) { + case POLL_MODE: + if (spi->poll_mode == INT_MODE) + cimax_spi_intr_ctrl(spi, CTRL_DISABLE); + cimax_spi_poll_ctrl(spi, CTRL_START); + spi->poll_mode = POLL_MODE; + break; + case INT_MODE: + if (spi->poll_mode == POLL_MODE) + cimax_spi_poll_ctrl(spi, CTRL_DISABLE); + cimax_spi_intr_ctrl(spi, CTRL_START); + spi->poll_mode = INT_MODE; + break; + case STOP_MODE: + if (spi->poll_mode == POLL_MODE) + cimax_spi_poll_ctrl(spi, CTRL_DISABLE); + else if (spi->poll_mode == INT_MODE) + cimax_spi_intr_ctrl(spi, CTRL_DISABLE); + spi->poll_mode = STOP_MODE; + break; + default: + break; + } + return 0; +} + +static int cimax_spi_hw_reset(struct cimax_spi *spi, int reset_val) +{ + /*trigger reset io*/ + if (spi->rst_io) { + gpio_direction_output(spi->rst_io, reset_val ? 1 : 0); + msleep(50); + gpio_direction_output(spi->rst_io, reset_val ? 0 : 1); + } + return 0; +} + + +enum regOperation_e { + /** Read register. */ + REG_OP_READ, + /** Write register. */ + REG_OP_WRITE, + /** Read register until some bits are set. */ + REG_OP_WAIT_TO_BE_SET, + /** Read register until some bits are cleared. */ + REG_OP_WAIT_TO_BE_CLEARED, + /** Read register until it's value is not equal to defined. */ + REG_OP_WAIT_EQUAL, + /** Perform logical AND over register. */ + REG_OP_LOGICAL_AND, + /** Perform logical OR over register. */ + REG_OP_LOGICAL_OR, + /** Wait timeout in miliseconds. */ + REG_OP_WAIT +}; + +struct regSettings_s { + /** CIMaX+ register address. */ + u16 reg; + /** CIMaX+ register value. */ + u16 val; + /** CIMaX+ register operation. */ + enum regOperation_e op; +}; + +static struct regSettings_s spiRegSettings[] = { + /** TS interface init. */ + {IN_SEL, 0x00, REG_OP_WRITE}, /** Close TS input. */ + {OUT_SEL, 0x00, REG_OP_WRITE}, /** Close TS output. */ + {FIFO_CTRL, 0x0f, REG_OP_WRITE}, /** Reset TS FIFO. */ + {SYNC_RTV_CTRL, 0x0f, REG_OP_WRITE}, + + /** CAM power. */ + {GPIO0_DATA_OUT, 0x00, REG_OP_WRITE}, + /** Unlock CFG. */ + {CFG_2, 0x00, REG_OP_WRITE}, + /** 1) DVB/CI/CI+/SCARD 2slot. */ + {CFG_1, 0x00, REG_OP_WRITE}, + /** 2) Set the Default "power off" state + such as VCC_MODA=VCC_MODB=VPPx_MODA=VPPx_MODB='Z'. */ + {GPIO0_DFT, 0x00, REG_OP_WRITE}, + /** 3) Set GPIO3 as external power switch driver. */ + {GPIO0_MASK_DATA, 0x07, REG_OP_WRITE}, + /** 4) Set "power on" state (VCC=VPP1=VPP2= 5V). */ + {GPIO0_DATA_OUT, 0x03, REG_OP_WRITE}, + /** 5) Lock config. */ + {CFG_2, 0x01, REG_OP_WRITE}, + /** 6) Write in the GPIO0_DIR_REG: defines the GPIOs, + which are used to drive the external power switch, in output mode. */ + {GPIO0_DIR, 0x07, REG_OP_WRITE}, + /** 7) Check VCCENable. */ + {CFG_1, 0x20, REG_OP_WAIT_TO_BE_SET}, + /** 8) Set & wait for PcmciaOutputEnable. */ + {CFG_1, 0x08, REG_OP_LOGICAL_OR}, + {CFG_1, 0x08, REG_OP_WAIT_TO_BE_SET}, + + /** Set router CAM. */ + /** CH0 & CH1 from CAM A & B, CAM A & B from CH0 & CH1. */ + {ROUTER_CAM_MOD, 0x21, REG_OP_WRITE}, + {ROUTER_CAM_CH, 0x00, REG_OP_WRITE}, + /** Wait 200 miliseconds. */ + {0x0000, 200, REG_OP_WAIT}, + + /** Set In/Out. */ + /** Route CAM Channel 0 to Channel 0, Channel 1 null. */ + {ROUTER_CAM_CH, 0x80, REG_OP_WRITE}, + +#ifdef PARALLEL_OUT +#else +#if 1 + /*72M internal clock source*/ + /*CLK Select SER0->72M*/ + {CkMan_Select, 0x20, REG_OP_WRITE}, + /*Enable SER0 clk source, Enable 72M clk source*/ + {CkMan_Config, 0x44, REG_OP_LOGICAL_OR}, +#else + /*108M internal clock source*/ + /*CLK Select SER0->108M*/ + {CkMan_Select, 0x30, REG_OP_WRITE}, + /*Enable SER0 clk source, Enable 108M clk source*/ + {CkMan_Config, 0x48, REG_OP_LOGICAL_OR}, +#endif + {P2S_CH0_CTRL, 0x19, REG_OP_WRITE}, /*Enable p2s*/ + {OUT_SEL, 0x02, REG_OP_WRITE}, /*Out1=p2s0*/ +#endif /*Parallel out*/ + + /** Input Ch0=Parallel, Ch1=null. */ + {IN_SEL, 0x01, REG_OP_WRITE}, +}; + +int downloadCfg(struct cimax_spi *spi) +{ + u32 cnt; + u8 buf[CIMAX_REG_PLD_SIZE]; + struct aml_cimax *cimax = spi->cimax; + + pr_info("Download CIMaX+ configuration(register settings):\n"); + + for (cnt = 0; cnt < sizeof(spiRegSettings)/sizeof(struct regSettings_s); + cnt++) { + pr_dbg("reg:%04x, val:%02x, op:%d\n", + spiRegSettings[cnt].reg, + spiRegSettings[cnt].val, + spiRegSettings[cnt].op); + switch (spiRegSettings[cnt].op) { + case REG_OP_READ: + /* Read register. */ + if (aml_cimax_spi_read_reg(cimax, + spiRegSettings[cnt].reg, buf, 1) < 0) { + /* CIMaX+ read error. */ + pr_error("FAILED at REG_OP_READ operation.\n"); + return -1; + } + break; + case REG_OP_WRITE: + /* Write register. */ + if (aml_cimax_spi_write_reg(cimax, + spiRegSettings[cnt].reg, + (u8 *)&spiRegSettings[cnt].val, + 1) < 0) { + /* CIMaX+ write error. */ + pr_error("FAILED at REG_OP_WRITE operation.\n"); + return -1; + } + break; + case REG_OP_WAIT_TO_BE_SET: + do { + if (aml_cimax_spi_read_reg(cimax, + spiRegSettings[cnt].reg, buf, 1) < 0) { + /* CIMaX+ read error. */ + pr_error("E REG_OP_WAIT_TO_BE_SET\n"); + return -1; + } + } while ((buf[0] & spiRegSettings[cnt].val) + != spiRegSettings[cnt].val); + break; + case REG_OP_WAIT_TO_BE_CLEARED: + do { + if (aml_cimax_spi_read_reg(cimax, + spiRegSettings[cnt].reg, buf, 1) < 0) { + /* CIMaX+ read error. */ + pr_error("REG_OP_WAIT_TO_BE_CLEARED\n"); + return -1; + } + } while ((buf[0] & spiRegSettings[cnt].val) != 0); + break; + case REG_OP_WAIT_EQUAL: + do { + if (aml_cimax_spi_read_reg(cimax, + spiRegSettings[cnt].reg, buf, 1) < 0) { + /* CIMaX+ read error. */ + pr_error("REG_OP_WAIT_EQUAL.\n"); + return -1; + } + } while (buf[0] != spiRegSettings[cnt].val); + break; + case REG_OP_LOGICAL_AND: + if (aml_cimax_spi_read_reg(cimax, + spiRegSettings[cnt].reg, buf, 1) < 0) { + /* CIMaX+ read error. */ + pr_error("FAILED at REG_OP_LOGICAL_AND(r).\n"); + return -1; + } + buf[0] &= spiRegSettings[cnt].val; + if (aml_cimax_spi_write_reg(cimax, + spiRegSettings[cnt].reg, buf, 1) < 0) { + /* CIMaX+ write error. */ + pr_error("FAILED at REG_OP_LOGICAL_AND(w).\n"); + return -1; + } + break; + case REG_OP_LOGICAL_OR: + if (aml_cimax_spi_read_reg(cimax, + spiRegSettings[cnt].reg, buf, 1) < 0) { + /* CIMaX+ read error. */ + pr_error("FAILED at REG_OP_LOGICAL_OR(r).\n"); + return -1; + } + buf[0] |= spiRegSettings[cnt].val; + if (aml_cimax_spi_write_reg(cimax, + spiRegSettings[cnt].reg, buf, 1) < 0) { + /* CIMaX+ write error. */ + pr_error("FAILED at REG_OP_LOGICAL_AND(w).\n"); + return -1; + } + break; + case REG_OP_WAIT: + msleep(spiRegSettings[cnt].val); + break; + default: + pr_error("\nInvalid operation 0x%02x!\n", + spiRegSettings[cnt].op); + } + } + pr_info("config OK.\n"); + return 0; +} + + +#define CIMAX_FW_PKT_SIZE 128 +#define CIMAX_FW_START_ADDR 0x8000 +#define CIMAX_FW_STOP_ADDR 0xcff9 +#define CIMAX_FW_VECT_ADDR 0xfffa +#define CIMAX_FW_VECT_SIZE 6 + +static u32 compute_bistrom(const u8 *ptr, int size, u32 sign) +{ + int k, i; + u16 s; + + for (k = 0; k < size; k++) { + s = ptr[k]&0x01; + for (i = 0; i < 16; i++) + if (0x88B7 & (1<>i) & 0x01; + s |= ((sign<<1) ^ (ptr[k])) & 0x00FE; + s |= (sign<<1) & 0x00FF00; + sign = s; + } + return sign; +} + +static int cimax_spi_upload_firmware(struct cimax_spi *spi, + const u8 *fw_data, u32 *sign) +{ + struct aml_cimax *cimax = spi->cimax; + int err = 0; + int addr; + const u8 *ptr; + int size; + int debug = cimax_spi_debug; + u8 *ptmp = kzalloc(CIMAX_FW_PKT_SIZE + CIMAX_REG_HDR_SIZE, GFP_KERNEL); + + if (!ptmp) + return -ENOMEM; + + cimax_spi_debug = 0; + + addr = CIMAX_FW_START_ADDR; + ptr = fw_data + addr; + while (addr < CIMAX_FW_STOP_ADDR) { + size = (addr <= (CIMAX_FW_STOP_ADDR+1-CIMAX_FW_PKT_SIZE)) ? + CIMAX_FW_PKT_SIZE : (CIMAX_FW_STOP_ADDR+1-addr); + + *sign = compute_bistrom(ptr, size, *sign); + + pr_dbg(">>%x@%x\n", size, addr); + + /*dump("w:", (u8*)ptr, size);*/ + err = aml_cimax_spi_write_reg(cimax, addr, (u8 *)ptr, size); + if (err) + break; + err = aml_cimax_spi_read_reg(cimax, addr, ptmp, size); + if (err) + break; + /*dump("r:", ptmp, size);*/ + if (memcmp(ptr, ptmp, size)) { + pr_error("fw write error.\n"); + err = -ENODEV; + break; + } + + addr += size; + ptr += size; + } + + if (!err) { + addr = CIMAX_FW_VECT_ADDR; + ptr = fw_data + addr; + size = CIMAX_FW_VECT_SIZE; + + *sign = compute_bistrom(ptr, size, *sign); + + err = aml_cimax_spi_write_reg(cimax, addr, (u8 *)ptr, size); + if (err) + goto end; + err = aml_cimax_spi_read_reg(cimax, addr, ptmp, size); + if (err) + goto end; + if (memcmp(ptr, ptmp, size)) { + pr_error("fw vect write error.\n"); + err = -ENODEV; + goto end; + } + } +end: + kfree(ptmp); + + cimax_spi_debug = debug; + return err; +} + +static int cimax_spi_check_bistrom(struct cimax_spi *spi, + int start, int end, u32 sign) +{ + struct aml_cimax *cimax = spi->cimax; + int err = 0; + u8 buf[2]; + + buf[0] = (0xd000-start) & 0xff; + buf[1] = (0xd000-start) >> 8; + err = aml_cimax_spi_write_reg(cimax, 0x8d, buf, 2); + if (err) + return err; + buf[0] = sign & 0xff; + buf[1] = sign >> 8; + err = aml_cimax_spi_write_reg(cimax, 0x80, buf, 2); + if (err) + return err; + buf[0] = 0xf; + err = aml_cimax_spi_write_reg(cimax, 0x82, buf, 1); + if (err) + return err; + err = aml_cimax_spi_read_reg(cimax, 0x41, buf, 2); + if (err) + return err; + pr_dbg("bist checked: 0x%04x\n", byte_to_u16(buf[0], buf[1])); + err = aml_cimax_spi_read_reg(cimax, 0x09, buf, 1); + if (err) + return err; + pr_dbg("rom status: 0x%02x\n", buf[0]); + return buf[0]; +} + +static int cimax_spi_init_firmware(struct cimax_spi *spi) +{ + struct spi_device *dev = spi->dev; + int err = 0; + + init_reg_hdr(spi->buf, CIMAX_REG_INIT, 0, 0); + err = spi_write(dev, spi->buf, CIMAX_REG_HDR_SIZE); + if (err) + return err; + err = cimax_spi_get_resp(spi, REG_TIMEOUT); + if (err) + return err; + if (check_reg_hdr(spi->buf, CIMAX_REG_INIT_OK, 0, 0)) { + perr("init fw fail.", spi); + return -EINVAL; + } + return err; +} + +static void request_fw_callback(const struct firmware *fw, void *context) +{ + u32 sign = 0; + int err = 0; + struct cimax_spi *spi = (struct cimax_spi *)context; + + if (!fw) + return; + + pr_dbg("got fw: %zd @ %p\n", fw->size, fw->data); + + /*cimax_spi_hw_reset(spi, 1);*/ + + err = cimax_spi_upload_firmware(spi, fw->data, &sign); + if (err) + goto end; + pr_dbg("upload fw done.\n"); + err = cimax_spi_check_bistrom(spi, + CIMAX_FW_START_ADDR, CIMAX_FW_STOP_ADDR, sign); + if (err != 0x2) + goto end; + pr_dbg("check bistrom done.\n"); + err = cimax_spi_init_firmware(spi); + if (err) + goto end; +end: + if (fw) + release_firmware(fw); + if (err) + return; + + if (downloadCfg(spi)) { + pr_error("download config fail.\n"); + return; + } + + cimax_spi_setup_poll(spi, cimax_poll_mode ? POLL_MODE : INT_MODE); + + return; +} + +static int cimax_spi_load_fw(struct cimax_spi *spi) +{ + char *name = "cimax_spidvb.bin"; + return request_firmware_nowait(THIS_MODULE, 1, name, + &spi->dev->dev, GFP_KERNEL, spi, request_fw_callback); +} + +static int cimax_spi_dev_probe(struct spi_device *spi) +{ + int ret; + struct cimax_spi *cimax_spi; + + pr_dbg("dev probe\n"); + /*setup again?*/ + spi->bits_per_word = 8; + ret = spi_setup(spi); + if (ret) + pr_dbg("spi setup failed\n"); + + cimax_spi = dev_get_platdata(&spi->dev); + cimax_spi->dev = spi; + + spi_set_drvdata(spi, cimax_spi); + + return cimax_spi_load_fw(cimax_spi); +} + +static int cimax_spi_dev_remove(struct spi_device *spi) +{ + struct cimax_spi *cimax_spi = dev_get_drvdata(&spi->dev); + + pr_dbg("dev remove\n"); + cimax_spi_setup_poll(cimax_spi, STOP_MODE); + return 0; +} + +static int cimax_spi_get_config_from_dts(struct cimax_spi *spi, + struct spi_board_info *bdinfo) +{ + struct device_node *child = NULL; + struct platform_device *pdev = spi->pdev; + struct device_node *np = pdev->dev.of_node; + unsigned int val; + int ret = 0; + pr_dbg("fetch cimax spi in dts\n"); + + child = of_get_child_by_name(np, "cimax"); + if (child == NULL) { + pr_error("cimax not found in dts\n"); + return -1; + } + child = of_get_child_by_name(child, "spi"); + if (!child) { + pr_error("spi not found in cimax"); + return -1; + } + + /* get spi config */ + ret = of_property_read_u32(child, "bus_num", &val); + if (ret) + pr_error("bus_num not found, use default.\n"); + else + bdinfo->bus_num = val; + pr_dbg("bus_num: %d\n", bdinfo->bus_num); + ret = of_property_read_u32(child, "chip_select", &val); + if (ret) + pr_error("chip_select not found, use default.\n"); + else + bdinfo->chip_select = val; + pr_dbg("chip_select: %d\n", bdinfo->chip_select); + ret = of_property_read_u32(child, "max_frequency", &val); + if (ret) + pr_error("max_frequency not found, use default.\n"); + else + bdinfo->max_speed_hz = val; + pr_dbg("max_speed_hz: %d\n", bdinfo->max_speed_hz); + ret = of_property_read_u32(child, "mode", &val); + if (ret) + pr_error("mode not found, use default.\n"); + else + bdinfo->mode = val; + pr_dbg("mode: %d\n", bdinfo->mode); +/* +dvbci { + compatible = "amlogic, dvbci"; + dev_name = "dvbci"; + io_type = <2>;//0:iobus,1:spi,2:cimax + cimax { + io_type = <0> //0:spi 1:usb + spi { + spi_bus_num = <0>; + spi_chip_select = <0>; + spi_max_frequency = <3000000>; + + rst_gpio = <&gpio_ao GPIOAO_2 GPIO_ACTIVE_HIGH>; + + irq_gpio = <&gpio_ao GPIOAO_2 GPIO_ACTIVE_HIGH>; + irq = <2>; + interrupts = ; + }; + }; + +}; +*/ +#ifdef USE_INT_PIO + { + int ret = 0; + int gpio = -1; + gpio = of_get_named_gpio_flags(child, "irq-gpios", 0, NULL); + ret = gpio_request(gpio, "cimax-irq"); + if (ret < 0) { + pr_error("irq-gpios request fail.\n"); + return ret; + } + + ret = gpio_direction_input(gpio); + + spi->irq_io = gpio; + pr_dbg("irq_io: %d\n", spi->irq_io); + } +#ifdef CIMAX_IRQ + { + int irq; + unsigned int irqflag; + ret = of_property_read_u32(child, "irq", &gpio_irq); + irq = irq_of_parse_and_map(child, 0); + + gpio_for_irq(gpio, + AML_GPIO_IRQ(gpio_irq, FILTER_NUM7, GPIO_IRQ_FALLING)); + spi->irq = irq; + pr_dbg("irq: %d\n", spi->irq); + } +#else + spi->irq = -1; +#endif +#endif/*USE_INT_PIO*/ + { + int ret = 0; + int gpio = -1; + gpio = of_get_named_gpio_flags(child, "rst-gpios", 0, NULL); + if (gpio != -1) { + ret = gpio_request(gpio, "cimax"); + if (ret < 0) { + pr_error("rst-gpios request fail.\n"); + return ret; + } + + cimax_spi_hw_reset(spi, 1); + + spi->rst_io = gpio; + pr_dbg("rst: %d\n", spi->rst_io); + } else { + pr_error("rst io got fail, %d\n", gpio); + } + } + return 0; +} + +static struct spi_board_info cimax_spi_bdinfo = { + .modalias = "cimax_spi", + .mode = SPI_MODE_3, + .max_speed_hz = 1000000, /* 1MHz */ + .bus_num = 0, /* SPI bus No. */ + .chip_select = 0, /* the device index on the spi bus */ + .controller_data = NULL, +}; + +static struct spi_driver cimax_spi_dev_driver = { + .probe = cimax_spi_dev_probe, + .remove = cimax_spi_dev_remove, + .driver = { + .name = "cimax_spi", + .owner = THIS_MODULE, + }, +}; + +int aml_cimax_spi_init(struct platform_device *pdev, struct aml_cimax *cimax) +{ + int ret; + struct cimax_spi *cimax_spi; + + cimax_spi = kzalloc(sizeof(struct cimax_spi), GFP_KERNEL); + if (!cimax_spi) + return -ENOMEM; + + cimax_spi->pdev = pdev; + cimax_spi->cimax = cimax; + cimax_spi_get_config_from_dts(cimax_spi, &cimax_spi_bdinfo); + + /*init spi_lock*/ + lock_init(cimax_spi); + + /*register device*/ + cimax_spi_bdinfo.platform_data = cimax_spi; + spi_register_board_info(&cimax_spi_bdinfo, 1); + + /*register driver*/ + ret = spi_register_driver(&cimax_spi_dev_driver); + if (ret) { + pr_error("register cimax spi driver failed\n"); + return ret; + } + + /*init cimax used api.*/ +#define WI(_f)\ + cimax->ops._f = aml_cimax_spi_##_f + WI(read_cis); + WI(write_cor); + WI(negotiate); + WI(read_lpdu); + WI(write_lpdu); + WI(read_cam_status); + WI(cam_reset); + WI(slot_reset); + WI(slot_shutdown); + WI(slot_ts_enable); + WI(slot_status); + /*WI(start);*/ + /*WI(stop);*/ + WI(read_reg); + WI(write_reg); + + cimax->priv = cimax_spi; + + g_spi = cimax_spi; + + aml_cimax_spi_mod_init(); + + return 0; +} +EXPORT_SYMBOL(aml_cimax_spi_init); + +int aml_cimax_spi_exit(struct aml_cimax *cimax) +{ + struct cimax_spi *spi = cimax_to_spi(cimax); + + if (!spi) + return -ENODEV; + + aml_cimax_spi_mod_exit(); + + /*unregister driver*/ + spi_unregister_driver(&cimax_spi_dev_driver); + /*unregister device*/ + spi_unregister_device(spi->dev); + + if (spi->irq_io) + gpio_free(spi->irq_io); + if (spi->rst_io) + gpio_free(spi->rst_io); + + kfree(spi->cis); + + kfree(spi); + cimax->priv = NULL; + + g_spi = NULL; + return 0; +} +EXPORT_SYMBOL(aml_cimax_spi_exit); + +static int cimax_spi_reset(struct cimax_spi *spi, int reset_val) +{ + pr_dbg("reset spi:%p, rst:%d\n", spi, spi ? spi->rst_io : -1); + if (!spi) + return -ENODEV; + + pr_dbg("cimax spi reset\n"); + + cimax_spi_setup_poll(spi, STOP_MODE); + + cimax_spi_hw_reset(spi, reset_val); + + /*notify unplugged*/ + aml_cimax_camchanged(spi->cimax, 0, 0); + aml_cimax_camchanged(spi->cimax, 1, 0); + + spi->cam_inserted[0] = spi->cam_inserted[1] = 0; + spi->cam_data_ready[0] = spi->cam_data_ready[1] = 0; + + /*async start fw*/ + cimax_spi_load_fw(spi); + + /*cimax_spi_setup_poll(spi, cimax_poll_mode? POLL_MODE : INT_MODE);*/ + return 0; +} + +static ssize_t reset_show(struct class *class, + struct class_attribute *attr, char *buf) +{ + int ret; + ret = sprintf(buf, "echo 1 > %s\n", attr->attr.name); + return ret; +} + +static ssize_t reset_store(struct class *class, + struct class_attribute *attr, const char *buf, size_t size) +{ + int ret; + int val = 0; + if (!g_spi) + return size; + ret = sscanf(buf, "%i", &val); + if (ret == 1) + ret = cimax_spi_reset(g_spi, val); + return size; +} + +static ssize_t debug_show(struct class *class, + struct class_attribute *attr, char *buf) +{ + int ret = 0; + if (!g_spi) + return ret; + + ret = sprintf(buf, "poll mode: %d\n", g_spi->poll_mode); + ret += sprintf(buf+ret, "status slot[0]=[%d] slot[1]=[%d]\n", + g_spi->cam_inserted[0], g_spi->cam_inserted[1]); + ret += sprintf(buf+ret, "data slot[0]=[%d] slot[1]=[%d]\n", + g_spi->cam_data_ready[0], g_spi->cam_data_ready[1]); + ret += sprintf(buf+ret, "work cnt:%d\n", g_spi->work_cnt); + return ret; +} + +static int reg_addr; +static ssize_t addr_show(struct class *class, + struct class_attribute *attr, char *buf) +{ + int ret = 0; + ret = sprintf(buf, "addr = 0x%04x\n", reg_addr); + return ret; +} + +static ssize_t addr_store(struct class *class, + struct class_attribute *attr, const char *buf, size_t size) +{ + if (!g_spi) + return size; + if (sscanf(buf, "%i", ®_addr) == 1) + return size; + return size; +} + +static ssize_t reg_show(struct class *class, + struct class_attribute *attr, char *buf) +{ + int ret = 0; + u8 reg_val = 0; + struct aml_cimax *cimax = NULL; + + if (!g_spi) + return ret; + + cimax = g_spi->cimax; + ret = aml_cimax_spi_read_reg(cimax, reg_addr, ®_val, 1); + if (ret) + ret = sprintf(buf, "read fail, err=%d\n", ret); + else + ret = sprintf(buf, "reg[0x%04x] = 0x%02x\n", reg_addr, reg_val); + return ret; +} + +static ssize_t reg_store(struct class *class, + struct class_attribute *attr, const char *buf, size_t size) +{ + int ret = 0; + struct aml_cimax *cimax = NULL; + int val = 0; + u8 reg_val = 0; + + if (!g_spi) + return size; + + if (sscanf(buf, "%i", &val) != 1) + return size; + reg_val = val; + cimax = g_spi->cimax; + ret = aml_cimax_spi_write_reg(cimax, reg_addr, ®_val, 1); + if (ret) + return ret; + return size; +} + +static int cis_mode; /*0:hex 1:binary*/ +static ssize_t cis_show(struct class *class, + struct class_attribute *attr, char *buf) +{ + int ret = 0; + + if (!g_spi || !g_spi->cis) + return ret; + + if (cis_mode == 0) { + int i; + for (i = 0; i < CIS_MAX; i++) { + if (i && !(i & 0xf)) + ret += sprintf(buf+ret, "\n"); + ret += sprintf(buf+ret, "%02X ", g_spi->cis[i]); + } + ret += sprintf(buf+ret, "\n"); + return ret; + } else { + memcpy(buf, g_spi->cis, CIS_MAX); + return CIS_MAX; + } + return ret; +} + +static ssize_t cis_store(struct class *class, + struct class_attribute *attr, const char *buf, size_t size) +{ + if (size >= 3 + && !memcmp(buf, "bin", 3)) + cis_mode = 1; + else + cis_mode = 0; + return size; +} + +static ssize_t ts_rate_show(struct class *class, + struct class_attribute *attr, char *buf) +{ + int ret = 0; + u8 lsb = 0, msb = 0, plen = 0; + struct aml_cimax *cimax = NULL; + int err = 0; + + if (!g_spi) + return ret; + + cimax = g_spi->cimax; + err = aml_cimax_spi_read_reg(cimax, PCK_LENGTH, &plen, 1); + err |= aml_cimax_spi_read_reg(cimax, BITRATE_CH0_LSB, &lsb, 1); + err |= aml_cimax_spi_read_reg(cimax, BITRATE_CH0_MSB, &msb, 1); + if (err || !byte_to_u16(msb, lsb)) + ret += sprintf(buf+ret, "read fail, err=%d\n", err); + else + ret += sprintf(buf+ret, "rate[0] = %d Kbps\n", + 540*plen*8/byte_to_u16(msb, lsb)); + if (err) + return ret; + + err = aml_cimax_spi_read_reg(cimax, BITRATE_CH1_LSB, &lsb, 1); + err |= aml_cimax_spi_read_reg(cimax, BITRATE_CH1_MSB, &msb, 1); + if (err || !byte_to_u16(msb, lsb)) + ret += sprintf(buf+ret, "read fail, err=%d\n", err); + else + ret += sprintf(buf+ret, "rate[1] = %d Kbps\n", + 540*plen*8/byte_to_u16(msb, lsb)); + return ret; +} + +static ssize_t loop_show(struct class *class, + struct class_attribute *attr, char *buf) +{ + int ret = 0; + u8 ch = 0, mod = 0; + struct aml_cimax *cimax = NULL; + int err = 0; + + if (!g_spi) + return ret; + + cimax = g_spi->cimax; + err = aml_cimax_spi_read_reg(cimax, ROUTER_CAM_CH, &ch, 1); + err |= aml_cimax_spi_read_reg(cimax, ROUTER_CAM_MOD, &mod, 1); + if (err) { + ret = sprintf(buf, "read fail, err=%d\n", err); + return ret; + } + ret += sprintf(buf + ret, "OUT-0 <= "); + switch (ch & 0x0f) { + case 0x0: + ret += sprintf(buf + ret, "CAM-A"); break; + case 0x1: + ret += sprintf(buf + ret, "CH0-IN"); break; + case 0x2: + ret += sprintf(buf + ret, "CH1-IN"); break; + case 0x3: + ret += sprintf(buf + ret, "REMAPPER"); break; + case 0x4: + ret += sprintf(buf + ret, "PREHEADER"); break; + case 0x5: + ret += sprintf(buf + ret, "CAM-B"); break; + case 0x6: + ret += sprintf(buf + ret, "GAPREMOVER-0"); break; + case 0x7: + ret += sprintf(buf + ret, "GAPREMOVER-1"); break; + case 0x8: + ret += sprintf(buf + ret, "NONE"); break; + default: + ret += sprintf(buf + ret, "UNKNOWN"); break; + } + ret += sprintf(buf + ret, "\nCAM-A <= "); + switch (mod & 0x07) { + case 0x1: + ret += sprintf(buf + ret, "CH0-IN"); break; + case 0x2: + ret += sprintf(buf + ret, "CH1-IN"); break; + case 0x3: + ret += sprintf(buf + ret, "REMAPPER"); break; + case 0x4: + ret += sprintf(buf + ret, "PREHEADER"); break; + case 0x5: + ret += sprintf(buf + ret, "CAM-B"); break; + case 0x6: + ret += sprintf(buf + ret, "GAPREMOVER-0"); break; + case 0x7: + ret += sprintf(buf + ret, "GAPREMOVER-1"); break; + default: + ret += sprintf(buf + ret, "NONE"); break; + } + ret += sprintf(buf + ret, "\n"); + + return ret; +} + + +static ssize_t loop_store(struct class *class, + struct class_attribute *attr, const char *buf, size_t size) +{ + int loop = 0; + int err = 0; + struct aml_cimax *cimax = NULL; + + if (!g_spi) + return size; + + if (sscanf(buf, "%i", &loop) == 1) { + int a = g_spi->cam_inserted[0]; + int b = g_spi->cam_inserted[1]; + u8 cm[2]; + cm[0] = loop ? (b ? 0x85 : 0x80) : 0x81;/*CH*/ + cm[1] = loop ? (a ? 0x51 : 0x11) : 0x00;/*MOD*/ + cimax = g_spi->cimax; + err = aml_cimax_spi_write_reg(cimax, ROUTER_CAM_CH, cm, 2); + } + return size; +} + +static ssize_t slot_reset_store(struct class *class, + struct class_attribute *attr, const char *buf, size_t size) +{ + int err = 0; + int slot = 0; + struct aml_cimax *cimax = NULL; + + if (!g_spi) + return size; + + if (sscanf(buf, "%i", &slot) == 1) { + if (slot == 0 || slot == 1) { + pr_dbg("reset slot %d\n", slot); + cimax = g_spi->cimax; + err = aml_cimax_spi_slot_reset(cimax, slot); + } + } + return size; +} + +static ssize_t detect_store(struct class *class, + struct class_attribute *attr, const char *buf, size_t size) +{ + int err = 0; + int slot = 0; + struct aml_cimax *cimax = NULL; + + if (!g_spi) + return size; + + if (sscanf(buf, "%i", &slot) == 1) { + if (slot == 0 || slot == 1) { + int addr = (!slot) ? MOD_CTRL_A : MOD_CTRL_B; + u8 reg = 0; + cimax = g_spi->cimax; + err = aml_cimax_spi_read_reg(cimax, addr, ®, 1); + g_spi->cam_inserted[slot] = reg & 1; + pr_dbg("detect slot(%d): %d\n", slot, reg & 1); + } + } + return size; +} + +static struct class_attribute cimax_spi_class_attrs[] = { + __ATTR_RW(reset), + __ATTR_RO(debug), + __ATTR_RW(addr), + __ATTR_RW(reg), + __ATTR_RW(cis), + __ATTR_RO(ts_rate), + __ATTR_RW(loop), + __ATTR_WO(slot_reset), + __ATTR_WO(detect), + __ATTR_NULL +}; + +static struct class cimax_spi_class = { + .name = "cimax_spi", + .class_attrs = cimax_spi_class_attrs, +}; + +static int aml_cimax_spi_mod_init(void) +{ + int ret; + pr_dbg("Amlogic CIMAX SPI Init\n"); + ret = class_register(&cimax_spi_class); + return 0; +} + +static void aml_cimax_spi_mod_exit(void) +{ + pr_dbg("Amlogic CIMAX SPI Exit\n"); + class_unregister(&cimax_spi_class); +} + diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/aml_cimax_spi.h b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/aml_cimax_spi.h new file mode 100644 index 000000000000..3548de0506dd --- /dev/null +++ b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/aml_cimax_spi.h @@ -0,0 +1,20 @@ +/*************************************************************************** + * Copyright (c) 2014 Amlogic, Inc. All rights reserved. + * + * This source code is subject to the terms and conditions defined in the + * file 'LICENSE' which is part of this source code package. + * + * Description: + * +***************************************************************************/ + +#ifndef _AML_CIMAX_SPI_H_ +#define _AML_CIMAX_SPI_H_ + +#include +#include "aml_cimax.h" + +int aml_cimax_spi_init(struct platform_device *pdev, struct aml_cimax *ci); +int aml_cimax_spi_exit(struct aml_cimax *ci); + +#endif diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/aml_cimax_usb.c b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/aml_cimax_usb.c new file mode 100644 index 000000000000..b74b34a63b51 --- /dev/null +++ b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/aml_cimax_usb.c @@ -0,0 +1,1714 @@ +/*************************************************************************** + * Copyright (c) 2014 Amlogic, Inc. All rights reserved. + * + * This source code is subject to the terms and conditions defined in the + * file 'LICENSE' which is part of this source code package. + * + * Description: + * +***************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//#include + +#include "aml_cimax.h" +#include "./usb/SRC/cimax+usb-driver.h" + +#define MOD_NAME "aml_cimax_usb" + +#define pr_dbg(fmt...)\ + do {\ + if (cimax_usb_debug)\ + pr_info("cimax_usb: "fmt);\ + } while (0) +#define pr_inf(fmt...) pr_info("cimax_usb: "fmt) +#define pr_error(fmt...) pr_err("AML_CIMAX_USB: " fmt) + +/* + Uncomment below and enable permanent power in cfg + to disable dynamic power control mechanism +*/ +/*#define DISABLE_POWER_PATCH*/ + +#define BUFFIN_CFG 0x0000 +#define BUFFIN_ADDR_LSB 0x0001 +#define BUFFIN_ADDR_MSB 0x0002 +#define BUFFIN_DATA 0x0003 +#define BUFFOUT_CFG 0x0004 +#define BUFFOUT_ADDR_LSB 0x0005 +#define BUFFOUT_ADDR_MSB 0x0006 +#define BUFFOUT_DATA 0x0007 +#define BOOT_Key 0x0008 +#define BOOT_Status 0x0009 +#define BOOT_Test 0x000A +#define usb2_0_irq_mask 0x0010 +#define usb2_0_status 0x0011 +#define usb2_0_rx 0x0012 +#define usb2_0_tx 0x0013 +#define SPI_Slave_Ctrl 0x0018 +#define SPI_Slave_Status 0x0019 +#define SPI_Slave_Rx 0x001A +#define SPI_Slave_Tx 0x001B +#define SPI_Slave_Mask 0x001C +#define UCSG_Ctrl 0x0020 +#define UCSG_Status 0x0021 +#define UCSG_RxData 0x0022 +#define UCSG_TxData 0x0023 +#define PCtrl_Ctrl 0x0028 +#define PCtrl_Status 0x0029 +#define PCtrl_NbByte_LSB 0x002A +#define PCtrl_NbByte_MSB 0x002B +#define SPI_Master_Ctl 0x0030 +#define SPI_Master_NCS 0x0031 +#define SPI_Master_Status 0x0032 +#define SPI_Master_TxBuf 0x0033 +#define SPI_Master_RxBuf 0x0034 +#define BISTRAM_Ctl 0x0038 +#define BISTRAM_Bank 0x0039 +#define BISTRAM_Pat 0x003A +#define BISTRAM_SM 0x003B +#define BISTRAM_AddrLSB 0x003C +#define BISTROM_Config 0x0040 +#define BISTROM_SignatureLSB 0x0041 +#define BISTROM_SignatureMSB 0x0042 +#define BISTROM_StartAddrLSB 0x0043 +#define BISTROM_StartAddrMSB 0x0043 +#define BISTROM_StopAddrLSB 0x0043 +#define BISTROM_StopAddrMSB 0x0043 +#define CkMan_Config 0x0048 +#define CkMan_Select 0x0049 +#define CkMan_Test 0x004A +#define Revision_Number 0x004B +#define ResMan_Config 0x0050 +#define ResMan_Status 0x0051 +#define ResMan_WD 0x0052 +#define ResMan_WD_MSB 0x0053 +#define CPU_Test 0x0060 +#define IrqMan_Config0 0x0068 +#define IrqMan_Config1 0x0069 +#define IrqMan_Irq0 0x006A +#define IrqMan_NMI 0x006B +#define IrqMan_SleepKey 0x006C +#define Tim_Config 0x0070 +#define Tim_Value_LSB 0x0071 +#define Tim_Value_MSB 0x0072 +#define Tim_Comp_LSB 0x0073 +#define Tim_Comp_MSB 0x0074 +#define TI_Config 0x0076 +#define TI_Data 0x0077 +#define TI_Reg0 0x0078 +#define TI_Reg1 0x0079 +#define TI_Reg2 0x007A +#define TI_Reg3 0x007B +#define TI_Reg4 0x007C +#define TI_ROM1 0x007D +#define TI_ROM2 0x007E +#define TI_ROM3 0x007F +#define DVBCI_START_ADDR 0x0100 +#define DVBCI_END_ADDR 0x017F +#define DATA 0x0180 +/*#define CTRL 0x0181*/ +#define QB_HOST 0x0182 +#define LEN_HOST_LSB 0x0183 +#define LEN_HOST_MSB 0x0184 +#define FIFO_TX_TH_LSB 0x0185 +#define FIFO_TX_TH_MSB 0x0186 +#define FIFO_TX_D_NB_LSB 0x0187 +#define FIFO_TX_D_NB_MSB 0x0188 +#define QB_MOD_CURR 0x0189 +#define LEN_MOD_CURR_LSB 0x018A +#define LEN_MOD_CURR_MSB 0x018B +#define QB_MOD 0x018C +#define LEN_MOD_LSB 0x018D +#define LEN_MOD_MSB 0x018E +#define FIFO_RX_TH_LSB 0x018F +#define FIFO_RX_TH_MSB 0x0190 +#define FIFO_RX_D_NB_LSB 0x0191 +#define FIFO_RX_D_NB_MSB 0x0192 +#define IT_STATUS_0 0x0193 +#define IT_STATUS_1 0x0194 +#define IT_MASK_0 0x0195 +#define IT_MASK_1 0x0196 +#define IT_HOST_PIN_CFG 0x0200 +#define CFG_0 0x0201 +#define CFG_1 0x0202 +#define CFG_2 0x0203 +#define IT_HOST 0x0204 +#define MOD_IT_STATUS 0x0205 +#define MOD_IT_MASK 0x0206 +#define MOD_CTRL_A 0x0207 +#define MOD_CTRL_B 0x0208 +#define DEST_SEL 0x0209 +#define CAM_MSB_ADD 0x020A +#define GPIO0_DIR 0x020B +#define GPIO0_DATA_IN 0x020C +#define GPIO0_DATA_OUT 0x020D +#define GPIO0_STATUS 0x020E +#define GPIO0_IT_MASK 0x020F +#define GPIO0_DFT 0x0210 +#define GPIO0_MASK_DATA 0x0211 +#define GPIO1_DIR 0x0212 +#define GPIO1_DATA_IN 0x0213 +#define GPIO1_DATA_OUT 0x0214 +#define GPIO1_STATUS 0x0215 +#define GPIO1_IT_MASK 0x0216 +#define MEM_ACC_TIME_A 0x0217 +#define MEM_ACC_TIME_B 0x0218 +#define IO_ACC_TIME_A 0x0219 +#define IO_ACC_TIME_B 0x021A +#define EXT_CH_ACC_TIME_A 0x021B +#define EXT_CH_ACC_TIME_B 0x021C +#define PAR_IF_0 0x021D +#define PAR_IF_1 0x021E +#define PAR_IF_CTRL 0x021F +#define PCK_LENGTH 0x0220 +#define USB2TS_CTRL 0x0221 +#define USB2TS0_RDL 0x0222 +#define USB2TS1_RDL 0x0223 +#define TS2USB_CTRL 0x0224 +#define TSOUT_PAR_CTRL 0x0225 +#define TSOUT_PAR_CLK_SEL 0x0226 +#define S2P_CH0_CTRL 0x0227 +#define S2P_CH1_CTRL 0x0228 +#define P2S_CH0_CTRL 0x0229 +#define P2S_CH1_CTRL 0x022A +#define TS_IT_STATUS 0x022B +#define TS_IT_MASK 0x022C +#define IN_SEL 0x022D +#define OUT_SEL 0x022E +#define ROUTER_CAM_CH 0x022F +#define ROUTER_CAM_MOD 0x0230 +#define FIFO_CTRL 0x0231 +#define FIFO1_2_STATUS 0x0232 +#define FIFO3_4_STATUS 0x0233 +#define GAP_REMOVER_CH0_CTRL 0x0234 +#define GAP_REMOVER_CH1_CTRL 0x0235 +#define SYNC_RTV_CTRL 0x0236 +#define SYNC_RTV_CH0_SYNC_NB 0x0237 +#define SYNC_RTV_CH0_PATTERN 0x0238 +#define SYNC_RTV_CH1_SYNC_NB 0x0239 +#define SYNC_RTV_CH1_PATTERN 0x023A +#define SYNC_RTV_OFFSET_PATT 0x023B +#define CTRL_FILTER 0x023D +#define PID_EN_FILTER_CH0 0x023E +#define PID_EN_FILTER_CH1 0x023F +#define PID_LSB_FILTER_CH0_0 0x0240 +#define PID_MSB_FILTER_CH0_0 0x0241 +#define PID_LSB_FILTER_CH0_1 0x0242 +#define PID_MSB_FILTER_CH0_1 0x0243 +#define PID_LSB_FILTER_CH0_2 0x0244 +#define PID_MSB_FILTER_CH0_2 0x0245 +#define PID_LSB_FILTER_CH0_3 0x0246 +#define PID_MSB_FILTER_CH0_3 0x0247 +#define PID_LSB_FILTER_CH0_4 0x0248 +#define PID_MSB_FILTER_CH0_4 0x0249 +#define PID_LSB_FILTER_CH0_5 0x024A +#define PID_MSB_FILTER_CH0_5 0x024B +#define PID_LSB_FILTER_CH0_6 0x024C +#define PID_MSB_FILTER_CH0_6 0x024D +#define PID_LSB_FILTER_CH0_7 0x024E +#define PID_MSB_FILTER_CH0_7 0x024F +#define PID_LSB_FILTER_CH1_0 0x0260 +#define PID_MSB_FILTER_CH1_0 0x0261 +#define PID_LSB_FILTER_CH1_1 0x0262 +#define PID_MSB_FILTER_CH1_1 0x0263 +#define PID_LSB_FILTER_CH1_2 0x0264 +#define PID_MSB_FILTER_CH1_2 0x0265 +#define PID_LSB_FILTER_CH1_3 0x0266 +#define PID_MSB_FILTER_CH1_3 0x0267 +#define PID_LSB_FILTER_CH1_4 0x0268 +#define PID_MSB_FILTER_CH1_4 0x0269 +#define PID_LSB_FILTER_CH1_5 0x026A +#define PID_MSB_FILTER_CH1_5 0x026B +#define PID_LSB_FILTER_CH1_6 0x026C +#define PID_MSB_FILTER_CH1_6 0x026D +#define PID_LSB_FILTER_CH1_7 0x026E +#define PID_MSB_FILTER_CH1_7 0x026F +#define PID_OLD_LSB_REMAPPER_0 0x0280 +#define PID_OLD_MSB_REMAPPER_0 0x0281 +#define PID_OLD_LSB_REMAPPER_1 0x0282 +#define PID_OLD_MSB_REMAPPER_1 0x0283 +#define PID_OLD_LSB_REMAPPER_2 0x0284 +#define PID_OLD_MSB_REMAPPER_2 0x0285 +#define PID_OLD_LSB_REMAPPER_3 0x0286 +#define PID_OLD_MSB_REMAPPER_3 0x0287 +#define PID_OLD_LSB_REMAPPER_4 0x0288 +#define PID_OLD_MSB_REMAPPER_4 0x0289 +#define PID_OLD_LSB_REMAPPER_5 0x028A +#define PID_OLD_MSB_REMAPPER_5 0x028B +#define PID_OLD_LSB_REMAPPER_6 0x028C +#define PID_OLD_MSB_REMAPPER_6 0x028D +#define PID_OLD_LSB_REMAPPER_7 0x028E +#define PID_OLD_MSB_REMAPPER_7 0x028F +#define PID_NEW_LSB_REMAPPER_0 0x02A0 +#define PID_NEW_MSB_REMAPPER_0 0x02A1 +#define PID_NEW_LSB_REMAPPER_1 0x02A2 +#define PID_NEW_MSB_REMAPPER_1 0x02A3 +#define PID_NEW_LSB_REMAPPER_2 0x02A4 +#define PID_NEW_MSB_REMAPPER_2 0x02A5 +#define PID_NEW_LSB_REMAPPER_3 0x02A6 +#define PID_NEW_MSB_REMAPPER_3 0x02A7 +#define PID_NEW_LSB_REMAPPER_4 0x02A8 +#define PID_NEW_MSB_REMAPPER_4 0x02A9 +#define PID_NEW_LSB_REMAPPER_5 0x02AA +#define PID_NEW_MSB_REMAPPER_5 0x02AB +#define PID_NEW_LSB_REMAPPER_6 0x02AC +#define PID_NEW_MSB_REMAPPER_6 0x02AD +#define PID_NEW_LSB_REMAPPER_7 0x02AE +#define PID_NEW_MSB_REMAPPER_7 0x02AF +#define MERGER_DIV_MICLK 0x02C0 +#define PID_AND_SYNC_REMAPPER_CTRL 0x02C1 +#define PID_EN_REMAPPER 0x02C2 +#define SYNC_SYMBOL 0x02C3 +#define PID_AND_SYNC_REMAPPER_INV_CTRL 0x02C4 +#define BITRATE_CH0_LSB 0x02C5 +#define BITRATE_CH0_MSB 0x02C6 +#define BITRATE_CH1_LSB 0x02C7 +#define BITRATE_CH1_MSB 0x02C8 +#define STATUS_CLK_SWITCH_0 0x02C9 +#define STATUS_CLK_SWITCH_1 0x02CA +#define RESET_CLK_SWITCH_0 0x02CB +#define RESET_CLK_SWITCH_1 0x02CC +#define PAD_DRVSTR_CTRL 0x02CD +#define PAD_PUPD_CTRL 0x02CE +#define PRE_HEADER_ADDER_CH0_0 0x02D0 +#define PRE_HEADER_ADDER_CH0_1 0x02D1 +#define PRE_HEADER_ADDER_CH0_2 0x02D2 +#define PRE_HEADER_ADDER_CH0_3 0x02D3 +#define PRE_HEADER_ADDER_CH0_4 0x02D4 +#define PRE_HEADER_ADDER_CH0_5 0x02D5 +#define PRE_HEADER_ADDER_CH0_6 0x02D6 +#define PRE_HEADER_ADDER_CH0_7 0x02D7 +#define PRE_HEADER_ADDER_CH0_8 0x02D8 +#define PRE_HEADER_ADDER_CH0_9 0x02D9 +#define PRE_HEADER_ADDER_CH0_10 0x02DA +#define PRE_HEADER_ADDER_CH0_11 0x02DB +#define PRE_HEADER_ADDER_CH1_0 0x02E0 +#define PRE_HEADER_ADDER_CH1_1 0x02E1 +#define PRE_HEADER_ADDER_CH1_2 0x02E2 +#define PRE_HEADER_ADDER_CH1_3 0x02E3 +#define PRE_HEADER_ADDER_CH1_4 0x02E4 +#define PRE_HEADER_ADDER_CH1_5 0x02E5 +#define PRE_HEADER_ADDER_CH1_6 0x02E6 +#define PRE_HEADER_ADDER_CH1_7 0x02E7 +#define PRE_HEADER_ADDER_CH1_8 0x02E8 +#define PRE_HEADER_ADDER_CH1_9 0x02E9 +#define PRE_HEADER_ADDER_CH1_10 0x02EA +#define PRE_HEADER_ADDER_CH1_11 0x02EB +#define PRE_HEADER_ADDER_CTRL 0x02EC +#define PRE_HEADER_ADDER_LEN 0x02ED +#define PRE_HEADER_REMOVER_CTRL 0x02EE +#define FSM_DVB 0x02F0 +#define TS2USB_FSM_DEBUG 0x02F2 +#define TSOUT_PAR_FSM_DEBUG 0x02F3 +#define GAP_REMOVER_FSM_DEBUG 0x02F4 +#define PID_AND_SYNC_REMAPPER_FSM_DEBUG 0x02F5 +#define PRE_HEADER_ADDER_FSM_DEBUG 0x02F6 +#define SYNC_RTV_FSM_DEBUG 0x02F7 +#define CHECK_PHY_CLK 0x0E00 +#define USB_CTRL1 0x0E01 +#define USB_ISO2_out 0x0800 +#define USB_ISO1_out 0x1000 +#define USB_Interrupt_out 0x1E00 +#define USB_Bulk_in 0x1F00 +#define CC2_Buffer_out 0x2000 +#define USB_EP0 0x30C0 +#define CC2_Buffer_in 0x4000 +#define USB_ISO2_in 0x5800 +#define USB_ISO1_in 0x6000 +#define nmb_vector_address_lsb 0xFFFA +#define nmb_vector_address_msb 0xFFFB +#define reset_vector_address_lsb 0xFFFC +#define reset_vector_address_msb 0xFFFD +#define irb_vector_address_lsb 0xFFFE +#define irb_vector_address_msb 0xFFFF + + +#define CIMAX_REG_HDR_SIZE 4 +#define CIMAX_REG_PLD_SIZE 255 +#define CIMAX_CAM_HDR_SIZE 4 +#define CIMAX_CAM_PLD_SIZE 65535 + +#define DEF_LOCK(_l_) struct mutex _l_ + +struct cimax_usb { + struct platform_device *pdev; + struct device_s *dev; + + struct aml_cimax *cimax; + + u8 buf[CIMAX_REG_HDR_SIZE + CIMAX_CAM_HDR_SIZE + CIMAX_CAM_PLD_SIZE]; + int buf_size; + + int cam_inserted[2]; +#define IN_INSERTED 0x01 +#define IN_POWERED 0x02 +#define IN_LINKED 0x04 + int cam_data_ready[2]; + + int poll_mode; +#define STOP_MODE 0 +#define POLL_MODE 1 +#define INT_MODE 2 + + int rst_io; + + struct workqueue_struct *workq; + struct delayed_work work; + int work_auto_restart; + int work_cnt; + + struct delayed_work power_work; + int power_work_cnt; + int cam_det; + + DEF_LOCK(lock); +#define lock_init(_usb) mutex_init(&(_usb)->lock) +#define lock_lock(_usb) do {\ + int err = mutex_lock_interruptible(&(_usb)->lock);\ + if (err)\ + return err;\ +} while (0) +#define lock_unlock(_usb) mutex_unlock(&(_usb)->lock) + + u8 *cis; +#define CIS_MAX 512 +}; + +static struct cimax_usb *g_usb; + +MODULE_PARM_DESC(usbdebug, "enable verbose debug messages"); +static int cimax_usb_debug = 1; +module_param_named(usbdebug, cimax_usb_debug, int, 0644); + +MODULE_PARM_DESC(usbpoll_interval, "interval for usb poll"); +static int usb_poll_interval = 100; +module_param_named(usbpoll_interval, usb_poll_interval, int, 0644); + +MODULE_PARM_DESC(usbpoll_mode, "set cimax poll mode, need reset"); +static int cimax_poll_mode = 1; +module_param_named(usbpoll_mode, cimax_poll_mode, int, 0644); + +MODULE_PARM_DESC(usbcam_irq_mode, "set cam irq mode, need reset"); +static int cam_irq_mode; +module_param_named(usbcam_irq_mode, cam_irq_mode, int, 0644); + + +#define CIMAX_REG_READ 0xff +#define CIMAX_REG_READ_OK 0x4c +#define CIMAX_REG_WRITE 0x7f +#define CIMAX_REG_WRITE_OK 0x4d +#define CIMAX_REG_INIT 0x00 +#define CIMAX_REG_INIT_OK 0x4b +#define CIMAX_REG_CMD_ERROR 0x51 + +#define CIMAX_CAM_RESET 0x01 +#define CIMAX_CAM_RESET_OK 0x40 +#define CIMAX_CAM_CIS 0x02 +#define CIMAX_CAM_CIS_OK 0x41 +#define CIMAX_CAM_COR 0x03 +#define CIMAX_CAM_COR_OK 0x42 +#define CIMAX_CAM_NEG 0x04 +#define CIMAX_CAM_NEG_OK 0x43 +#define CIMAX_CAM_WLPDU 0x05 +#define CIMAX_CAM_WLPDU_OK 0x44 +#define CIMAX_CAM_RLPDU 0x06 +#define CIMAX_CAM_RLPDU_OK 0x46 +#define CIMAX_CAM_EVT 0x0d +#define CIMAX_CAM_DET_OK 0x45 +#define CIMAX_CAM_NOCAM 0x49 +#define CIMAX_CAM_ERROR 0x4a +#define CIMAX_CAM_NOEVT 0x55 +#define CIMAX_CAM_DATA_READY 0x4e +#define CIMAX_CAM_WBUSY 0x54 +#define CIMAX_CAM_PENDING 0x56 +#define CIMAX_CAM_REGSTAT 0x0e +#define CIMAX_CAM_REGSTAT_OK 0x57 + + +#define CIMAX_CAM_PKT_CNT_VAL 1 + +#define CIMAX_SLOT_A 0 +#define CIMAX_SLOT_B 1 + +#define CIMAX_CMD_RESP_MASK 0x7f + +#define cimax_to_usb(_c) ((struct cimax_usb *)((_c)->priv)) +#define dev_to_usb(_d) ((struct cimax_usb *)usb_get_drvdata(_d)) + +#define byte_to_u16(_b1, _b2) (((_b1)<<8) | (_b2)) + +#define hdr_cmd_resp(_s) ((_s)->buf[0] & CIMAX_CMD_RESP_MASK) + +#define reg_hdr(_s) ((_s)->buf) +#define reg_addr(_s) byte_to_u16((_s)->buf[1], (_s)->buf[2]) +#define reg_hdr_dat_size(_s) ((_s)->buf[3]) +#define reg_dat(_s) (&((_s)->buf[CIMAX_REG_HDR_SIZE])) + +#define cam_hdr(_s) ((_s)->buf) +#define cam_hdr_slot(_s) (((_s)->buf[0] & 0x80) ? 1 : 0) +#define cam_hdr_pkt_cnt(_s) ((_s)->buf[1]) +#define cam_hdr_dat_size(_s) byte_to_u16((_s)->buf[2], (_s)->buf[3]) +#define cam_dat(_s) (&((_s)->buf[CIMAX_CAM_HDR_SIZE])) + +#define REG_TIMEOUT 500 +#define CAM_TIMEOUT 5000 + +static int aml_cimax_usb_mod_init(void); +static void aml_cimax_usb_mod_exit(void); + +static int cimax_usb_set_loop(struct cimax_usb *usb, int loop); + +static void dump(char *title, u8 *buf, int size) +{ + int i; + pr_info("%s\n", title); + for (i = 0; i < size; i++) { + if (!(i & 0xf)) + pr_info("\n\t"); + pr_info("%02x ", *(buf+i)); + } + pr_info("\n"); +} + +static void perr(char *err, struct cimax_usb *usb) +{ + pr_error("error: %s\n", err); + dump("dump:", usb->buf, 16); +} + +static inline unsigned long get_jiffies(void) +{ + return (unsigned long)(sched_clock()/10000000); +} + +static int cam_usb_cam_detect(struct cimax_usb *usb, int slot, int flag) +{ + usb->cam_inserted[slot] = flag; + pr_inf("detect slot(%d): 0x%x(%s)\n", + slot, usb->cam_inserted[slot], + (!flag) ? "none" : + (flag & IN_LINKED) ? "linked" : + (flag & IN_POWERED) ? "powered" : + (flag & IN_INSERTED) ? "inserted" : + "unknown"); + aml_cimax_slot_state_changed(usb->cimax, slot, + usb->cam_inserted[slot]); + return 0; +} + +static inline void set_usb_cam_ready(struct cimax_usb *usb, int slot) +{ + if (usb->cam_inserted[slot] & IN_POWERED) { + cam_usb_cam_detect(usb, slot, + usb->cam_inserted[slot] | IN_LINKED); + cimax_usb_set_loop(usb, 1);/*set auto-loop*/ + } +} + +static int init_reg_hdr(u8 *hdr, u8 tag, int addr, int size) +{ + hdr[0] = tag; + hdr[1] = (addr>>8) & 0xff; + hdr[2] = addr & 0xff; + hdr[3] = size; + return 0; +} + +static int check_reg_hdr(u8 *hdr, u8 tag, int addr, int size) +{ + return hdr[0] != tag + || hdr[1] != ((addr>>8) & 0xff) + || hdr[2] != (addr & 0xff) + || hdr[3] != size; +} + +static int aml_cimax_usb_read_reg(struct aml_cimax *cimax, int addr, + u8 *buf, int size) +{ + struct cimax_usb *usb = cimax_to_usb(cimax); + struct device_s *dev = usb->dev; + u8 out[CIMAX_REG_HDR_SIZE]; + int err = 0; + + init_reg_hdr(out, CIMAX_REG_READ, addr, size); + + lock_lock(usb); + + /*pr_dbg("rd %02x:%02x:%02x:%02x\n", + out[0], out[1], + out[2], out[3]);*/ + err = cimax_usb_ci_write(dev, + out, CIMAX_REG_HDR_SIZE, usb->buf, sizeof(usb->buf)); + if (err) + goto end; + if (check_reg_hdr(reg_hdr(usb), CIMAX_REG_READ_OK, addr, size) != 0) { + pr_dbg("rd %02x:%02x:%02x:%02x\n", + out[0], out[1], + out[2], out[3]); + perr("read reg fail.", usb); + err = -EINVAL; + goto end; + } + memcpy(buf, reg_dat(usb), size); +end: + lock_unlock(usb); + return err; +} + +static int aml_cimax_usb_write_reg(struct aml_cimax *cimax, int addr, + u8 *buf, int size) +{ + struct cimax_usb *usb = cimax_to_usb(cimax); + struct device_s *dev = usb->dev; + u8 out[CIMAX_REG_HDR_SIZE + CIMAX_REG_PLD_SIZE]; + int err = 0; + + init_reg_hdr(out, CIMAX_REG_WRITE, addr, size); + memcpy(&out[CIMAX_REG_HDR_SIZE], buf, size); + + lock_lock(usb); + + pr_dbg("wr %02x:%02x:%02x:%02x\n", + out[0], out[1], + out[2], out[3]); + err = cimax_usb_ci_write(dev, + out, CIMAX_REG_HDR_SIZE + size, usb->buf, sizeof(usb->buf)); + if (err) + goto end; + if (check_reg_hdr(reg_hdr(usb), CIMAX_REG_WRITE_OK, addr, 0) != 0) { + perr("write reg fail.", usb); + err = -EINVAL; + goto end; + } +end: + lock_unlock(usb); + return err; +} + +static inline int init_cam_hdr(u8 *hdr, int cmd, int size) +{ + hdr[0] = cmd; + hdr[1] = CIMAX_CAM_PKT_CNT_VAL; + hdr[2] = (size>>8) & 0xff; + hdr[3] = size & 0xff; + return 0; +} + +static inline int cam_err(struct cimax_usb *usb) +{ + if (hdr_cmd_resp(usb) != CIMAX_CAM_ERROR + || cam_hdr_pkt_cnt(usb) != CIMAX_CAM_PKT_CNT_VAL + || cam_hdr_dat_size(usb) != 2) + return 0; + return byte_to_u16(cam_dat(usb)[0], cam_dat(usb)[1]); +} + +static inline char *cam_err_str(int err) +{ +#define CAMERROR_RESET 0x0101 +#define CAMERROR_CIS_BUF 0x0201 +#define CAMERROR_CIS_SIZE 0x0202 +#define CAMERROR_CAM_NOT_ACT 0x0203 +#define CAMERROR_COR_NOT_READY 0x0301 +#define CAMERROR_COR_VAL_CHK 0x0302 +#define CAMERROR_NEG_NO_RESP 0x0401 +#define CAMERROR_NEG_BAD_SIZE 0x0402 +#define CAMERROR_NEG_NOT_READY 0x0403 +#define CAMERROR_LPDU_NOT_AVAIL 0x0601 + struct { int err; char *str; } cam_err_strings[] = { + {CAMERROR_RESET, "reset error, not ready."}, + {CAMERROR_CIS_BUF, "cis error, buffer not allocated."}, + {CAMERROR_CIS_SIZE, "cis error, bad cis size."}, + {CAMERROR_CAM_NOT_ACT, "cam not activated."}, + {CAMERROR_COR_NOT_READY, "cam not ready during write COR."}, + {CAMERROR_COR_VAL_CHK, "COR value check failed."}, + {CAMERROR_NEG_NO_RESP, "cam not responding when negotiation."}, + {CAMERROR_NEG_BAD_SIZE, "cam buf size length != 2."}, + {CAMERROR_NEG_NOT_READY, "cam not ready during negotiation."}, + {CAMERROR_LPDU_NOT_AVAIL, "lpdu not available."} + }; + int i; + for (i = 0; + i < sizeof(cam_err_strings)/sizeof(cam_err_strings[0]); i++) { + if (cam_err_strings[i].err == err) + return cam_err_strings[i].str; + } + return "err unknown."; +} + +static int cimax_usb_access_cam(struct cimax_usb *usb, int slot, + int cmd, u8 *tx, int tx_size, u8 *rx, int rx_size) +{ + struct device_s *dev = usb->dev; + u8 *out = NULL; + int err = 0; + + out = kzalloc(CIMAX_CAM_HDR_SIZE + CIMAX_CAM_PLD_SIZE, GFP_KERNEL); + if (!out) { + pr_err("no mem for access cam.\n"); + return -ENOMEM; + } + + cmd |= slot ? 0x80 : 0; + init_cam_hdr(out, cmd, tx_size); + memcpy(&out[CIMAX_CAM_HDR_SIZE], tx, tx_size); + /*dump("access cam:", out, CIMAX_CAM_HDR_SIZE+size);*/ + + lock_lock(usb); + + err = cimax_usb_ci_write(dev, + out, CIMAX_CAM_HDR_SIZE + tx_size, rx, rx_size); + if (err) + goto end; + if (cam_hdr_slot(usb) != slot) { + pr_error("expect slot(%d), but slot(%d)\n", + slot, cam_hdr_slot(usb)); + err = -EINVAL; + goto end; + } + switch (hdr_cmd_resp(usb)) { + case CIMAX_CAM_NOCAM: + pr_dbg("no cam\n"); + err = -ENODEV; + break; + case CIMAX_CAM_ERROR: + pr_error("cam error\n"); + pr_error("err code: 0x%04x(%s)\n", cam_err(usb), + cam_err_str(cam_err(usb))); + err = -ENODEV; + break; + case CIMAX_CAM_WBUSY: + pr_dbg("cam busy\n"); + err = -EBUSY; + break; + case CIMAX_CAM_PENDING: + pr_dbg("cam pending\n"); + err = -EAGAIN; + break; + } +end: + kfree(out); + lock_unlock(usb); + return err; +} + +static int aml_cimax_usb_read_cis(struct aml_cimax *cimax, int slot, + u8 *buf, int size) +{ + struct cimax_usb *usb = cimax_to_usb(cimax); + int err = 0; + int len; + + err = cimax_usb_access_cam(usb, slot, CIMAX_CAM_CIS, + NULL, 0, usb->buf, sizeof(usb->buf)); + if (err) + goto end; + if (hdr_cmd_resp(usb) != CIMAX_CAM_CIS_OK + || cam_hdr_pkt_cnt(usb) != CIMAX_CAM_PKT_CNT_VAL) { + perr("read cis fail.", usb); + err = -EINVAL; + goto end; + } + len = cam_hdr_dat_size(usb); + if (size < len) { + pr_error("cis size too large, expect<%d, but:%d\n", size, len); + perr("cis fail.", usb); + err = -EINVAL; + goto end; + } + memcpy(buf, cam_dat(usb), len); + + if (!usb->cis) + usb->cis = kzalloc((len < 512) ? 512 : len, GFP_KERNEL); + if (usb->cis) + memcpy(usb->cis, cam_dat(usb), len); + +end: + return err; +} +#define CIMAX_CAM_COR_PLD_SIZE 5 +static int aml_cimax_usb_write_cor(struct aml_cimax *cimax, int slot, + int addr, u8 *buf) +{ + struct cimax_usb *usb = cimax_to_usb(cimax); + int err = 0; + u8 out[CIMAX_CAM_COR_PLD_SIZE + 8]; + int sz = CIMAX_CAM_COR_PLD_SIZE; + + out[0] = addr>>8 & 0xff; + out[1] = addr & 0xff; + out[2] = buf[0]; + out[3] = 0; + out[4] = 0; + + if (!cam_irq_mode) { + out[5] = 0x40;/*cam poll mode*/ + sz++; + } + + err = cimax_usb_access_cam(usb, slot, CIMAX_CAM_COR, + out, sz, usb->buf, sizeof(usb->buf)); + if (err) + goto end; + if (hdr_cmd_resp(usb) != CIMAX_CAM_COR_OK + || cam_hdr_pkt_cnt(usb) != CIMAX_CAM_PKT_CNT_VAL + || cam_hdr_dat_size(usb) != 0) { + perr("write cor fail.", usb); + err = -EINVAL; + goto end; + } +end: + return err; +} +#define CIMAX_CAM_NEG_PLD_SIZE 2 +static int aml_cimax_usb_negotiate(struct aml_cimax *cimax, int slot, int size) +{ + struct cimax_usb *usb = cimax_to_usb(cimax); + int ret = 0; + u8 out[CIMAX_CAM_NEG_PLD_SIZE]; + + out[0] = (size>>8) & 0xff; + out[1] = size & 0xff; + + ret = cimax_usb_access_cam(usb, slot, CIMAX_CAM_NEG, + out, CIMAX_CAM_NEG_PLD_SIZE, + usb->buf, sizeof(usb->buf)); + if (ret) + goto end; + if (hdr_cmd_resp(usb) != CIMAX_CAM_NEG_OK + || cam_hdr_pkt_cnt(usb) != CIMAX_CAM_PKT_CNT_VAL + || cam_hdr_dat_size(usb) != 2) { + perr("negotiate fail.", usb); + ret = -EINVAL; + goto end; + } + ret = byte_to_u16(cam_dat(usb)[0], cam_dat(usb)[1]); + + set_usb_cam_ready(usb, slot); +end: + return ret; +} + +static int aml_cimax_usb_write_lpdu(struct aml_cimax *cimax, int slot, + u8 *buf, int size) +{ + struct cimax_usb *usb = cimax_to_usb(cimax); + int ret = 0; + + /*dump("lpdu ->", buf, size);*/ + ret = cimax_usb_access_cam(usb, slot, CIMAX_CAM_WLPDU, + buf, size, usb->buf, sizeof(usb->buf)); + if (ret) + goto end; + if (hdr_cmd_resp(usb) != CIMAX_CAM_WLPDU_OK + || cam_hdr_pkt_cnt(usb) != CIMAX_CAM_PKT_CNT_VAL + || cam_hdr_dat_size(usb) != 0) { + perr("write lpdu fail.", usb); + ret = -EINVAL; + goto end; + } + ret = size; +end: + return ret; +} + +static int aml_cimax_usb_read_lpdu(struct aml_cimax *cimax, int slot, + u8 *buf, int size) +{ + struct cimax_usb *usb = cimax_to_usb(cimax); + int ret = 0; + + ret = cimax_usb_access_cam(usb, slot, CIMAX_CAM_RLPDU, + NULL, 0, usb->buf, sizeof(usb->buf)); + if (ret) + goto end; + if (hdr_cmd_resp(usb) != CIMAX_CAM_RLPDU_OK + || cam_hdr_pkt_cnt(usb) != CIMAX_CAM_PKT_CNT_VAL) { + perr("read lpdu fail.", usb); + ret = -EINVAL; + goto end; + } + ret = cam_hdr_dat_size(usb); + memcpy(buf, cam_dat(usb), ret); + + /*dump("lpdu <-", buf, ret);*/ + + usb->cam_data_ready[slot] = 0; +end: + return ret; +} + +static int aml_cimax_usb_read_cam_status(struct aml_cimax *cimax, int slot) +{ + struct cimax_usb *usb = cimax_to_usb(cimax); + int ret = 0; + + if (cam_irq_mode && usb->cam_data_ready[slot]) + return 0x80; + + ret = cimax_usb_access_cam(usb, slot, CIMAX_CAM_REGSTAT, + NULL, 0, usb->buf, sizeof(usb->buf)); + if (ret) + goto end; + if (hdr_cmd_resp(usb) != CIMAX_CAM_REGSTAT_OK + || cam_hdr_pkt_cnt(usb) != CIMAX_CAM_PKT_CNT_VAL + || cam_hdr_dat_size(usb) != 1) { + perr("read cam status fail.", usb); + ret = -EINVAL; + goto end; + } + + ret = cam_dat(usb)[0]; +end: + return ret; +} + +static int aml_cimax_usb_slot_reset(struct aml_cimax *cimax, int slot) +{ + struct cimax_usb *usb = cimax_to_usb(cimax); + int ret = 0; + + usb->cam_data_ready[slot] = 0; + + ret = cimax_usb_access_cam(usb, slot, CIMAX_CAM_RESET, + NULL, 0, usb->buf, sizeof(usb->buf)); + if (ret) + goto end; + if (hdr_cmd_resp(usb) != CIMAX_CAM_RESET_OK + || cam_hdr_pkt_cnt(usb) != CIMAX_CAM_PKT_CNT_VAL + || cam_hdr_dat_size(usb) != 0) { + perr("slot reset fail.", usb); + ret = -EINVAL; + goto end; + } +end: + return ret; +} + +static int aml_cimax_usb_cam_reset(struct aml_cimax *cimax, int slot) +{ + pr_dbg("Slot(%d): camreset\n", slot); + return 0; +} + +static int aml_cimax_usb_slot_shutdown(struct aml_cimax *cimax, int slot) +{ + pr_dbg("Slot(%d): shutdown\n", slot); + return 0; +} +static int aml_cimax_usb_slot_ts_enable(struct aml_cimax *cimax, int slot) +{ + pr_dbg("Slot(%d): ts control\n", slot); + return 0; +} +static int aml_cimax_usb_slot_status(struct aml_cimax *cimax, int slot) +{ + struct cimax_usb *usb = cimax_to_usb(cimax); + if (usb->cam_inserted[slot] & IN_POWERED) { + /*pr_dbg("CA Module present and ready\n");*/ + return DVB_CA_EN50221_POLL_CAM_PRESENT | + DVB_CA_EN50221_POLL_CAM_READY; + } else { + /*pr_error("CA Module not present or not ready\n");*/ + } + return 0; +} + +static int cimax_usb_cam_plugin(struct cimax_usb *usb, int slot, int plugin) +{ + pr_dbg("cam plug: slot(%d) %s\n", + slot, plugin ? "plugged" : "unplugged"); + return aml_cimax_camchanged(usb->cimax, slot, plugin); +} + +static int cimax_usb_set_power(struct cimax_usb *usb, int on) +{ + u8 reg = 0; + int err = 0; + if (!on) { + reg = 0; + err = aml_cimax_usb_read_reg(usb->cimax, MOD_IT_MASK, ®, 1); + if (err) + return err; + reg |= 0x03; + reg &= 0xf3; + + err = aml_cimax_usb_write_reg(usb->cimax, MOD_IT_MASK, ®, 1); + if (err) + return err; + } + reg = on ? 0x3 : 0x0; + return aml_cimax_usb_write_reg(usb->cimax, GPIO0_DATA_OUT, ®, 1); +} + +static int cimax_usb_check_poe(struct cimax_usb *usb, int *on) +{ + u8 reg = 0; + int err = 0; + + *on = 0; + + err = aml_cimax_usb_read_reg(usb->cimax, CFG_1, ®, 1); + if (err) + return err; + if (reg & 0x20) {/*if VCCEN*/ + reg |= 0x08;/*set POE*/ + err = aml_cimax_usb_write_reg(usb->cimax, CFG_1, ®, 1); + if (err) + return err; + err = aml_cimax_usb_read_reg(usb->cimax, CFG_1, ®, 1); + if (err) + return err; + if (reg & 0x08)/*if POE ok*/ + *on = 1; + } + return err; +} + +static void cimax_usb_power_work(struct work_struct *work) +{ + struct cimax_usb *usb = container_of(to_delayed_work(work), + struct cimax_usb, power_work); + int power = 0; + int err = 0; + + usb->power_work_cnt++; + err = cimax_usb_set_power(usb, 1); + if (err) + return; + + err = cimax_usb_check_poe(usb, &power); + if (err) + return; + + if (power) { + return; + } + + schedule_delayed_work(&usb->power_work, usb_poll_interval); +} + +static int cimax_usb_cam_powerctrl(struct cimax_usb *usb, + int slot, int power) +{ + if (slot != 0) + return 0; + +#ifdef DISABLE_POWER_PATCH + if (power) { + cam_usb_cam_detect(usb, slot, + usb->cam_inserted[slot] | IN_POWERED); + cimax_usb_cam_plugin(usb, slot, 1); + } + return 0; +#else + pr_inf("cancel power ctrl previous\n"); + cancel_delayed_work_sync(&usb->power_work); + + if (!power) { + int err = 0; + err = cimax_usb_set_power(usb, 0); + pr_inf("slot[%d] power off\n", slot); + return 0; + } + + INIT_DELAYED_WORK(&usb->power_work, &cimax_usb_power_work); + schedule_delayed_work(&usb->power_work, usb_poll_interval); + pr_inf("slot[%d] power ctrl started\n", slot); +#endif + return 0; +} + +static int cimax_usb_poll(struct cimax_usb *usb) +{ + struct device_s *dev = usb->dev; + int power = 0; + int err = 0; + int slot = 0; + + if (!usb->cam_det) { + for (slot = 0; slot < 2; slot++) { + int addr = (!slot) ? MOD_CTRL_A : MOD_CTRL_B; + u8 reg = 0; + err = aml_cimax_usb_read_reg(usb->cimax, + addr, ®, 1); + if (reg & 1) { + cam_usb_cam_detect(usb, slot, + (reg & 1) ? IN_INSERTED : 0); + msleep(200); + err = cimax_usb_set_power(usb, (reg & 1)); + err = cimax_usb_check_poe(usb, &power); + pr_inf("slot[%d] power on\n", slot); + msleep(200); + if (power) { + cam_usb_cam_detect(usb, slot, + usb->cam_inserted[slot] | IN_POWERED); + cimax_usb_cam_plugin(usb, slot, 1); + usb->cam_det = 1; + } + } + } + return 0; + } + err = cimax_usb_ci_read_evt(dev, CIMAX_SLOT_A, + usb->buf, sizeof(usb->buf)); + if (err) + goto end; + + switch (hdr_cmd_resp(usb)) { + case CIMAX_CAM_DET_OK: { + int slot = cam_hdr_slot(usb); + int insert = cam_dat(usb)[0]; + if ((!!usb->cam_inserted[slot]) != insert) { + cam_usb_cam_detect(usb, slot, + insert ? IN_INSERTED : 0); + cimax_usb_cam_powerctrl(usb, slot, insert); + } + if (!insert) + usb->cam_det = 0; + } break; + case CIMAX_CAM_DATA_READY: { + int slot = cam_hdr_slot(usb); + usb->cam_data_ready[slot] = 1; + } break; + case CIMAX_CAM_NOEVT: + break; + default: + pr_error("unknown resp:%02x\n", hdr_cmd_resp(usb)); + break; + } +end: + return 0; +} + +static void cimax_usb_poll_work(struct work_struct *work) +{ + struct cimax_usb *usb = + container_of(to_delayed_work(work), struct cimax_usb, work); + usb->work_cnt++; + cimax_usb_poll(usb); + if (usb->work_auto_restart) + queue_delayed_work(usb->workq, &usb->work, usb_poll_interval); +} + +#define CTRL_DISABLE -1 +#define CTRL_STOP 0 +#define CTRL_START 1 + +static inline int cimax_usb_poll_ctrl(struct cimax_usb *usb, int ctrl) +{ + if (ctrl == CTRL_START) { + if (usb->workq) + return 0; + usb->work_auto_restart = 1; + usb->workq = create_singlethread_workqueue("cimax_usb"); + INIT_DELAYED_WORK(&usb->work, &cimax_usb_poll_work); + queue_delayed_work(usb->workq, + &usb->work, usb_poll_interval); + pr_inf("poll started\n"); + } else { + if (!usb->workq) + return 0; + usb->work_auto_restart = 0; + cancel_delayed_work_sync(&usb->work); + destroy_workqueue(usb->workq); + usb->workq = NULL; + pr_inf("poll stopped\n"); + } + return 0; +} + +static int cimax_usb_setup_poll(struct cimax_usb *usb, int poll_mode) +{ + if (poll_mode == usb->poll_mode) + return 0; + switch (poll_mode) { + case POLL_MODE: + cimax_usb_poll_ctrl(usb, CTRL_START); + usb->poll_mode = POLL_MODE; + break; + case STOP_MODE: + if (usb->poll_mode == POLL_MODE) + cimax_usb_poll_ctrl(usb, CTRL_DISABLE); + usb->poll_mode = STOP_MODE; + break; + default: + break; + } + return 0; +} + +static int cimax_usb_hw_reset(struct cimax_usb *usb, int reset_val) +{ + /*trigger reset io*/ + if (usb->rst_io) { + gpio_direction_output(usb->rst_io, reset_val ? 1 : 0); + msleep(50); + gpio_direction_output(usb->rst_io, reset_val ? 0 : 1); + } + return 0; +} + +static int cimax_usb_set_loop(struct cimax_usb *usb, int loop) +{ + int a = usb->cam_inserted[0]; + int b = usb->cam_inserted[1]; + u8 cm[2]; + + pr_inf("set loop: %d\n", loop); + + cm[0] = loop ? (b ? 0x85 : 0x80) : 0x81;/*CH*/ + cm[1] = loop ? (a ? 0x51 : 0x11) : 0x00;/*MOD*/ + + return aml_cimax_usb_write_reg(usb->cimax, ROUTER_CAM_CH, cm, 2); +} + +int cimax_usb_dev_add(struct device_s *dev, int id) +{ + pr_inf("dev add\n"); + if (!g_usb) + return 0; + + id = id; + + cimax_usb_device_open(dev); + cimax_usb_select_interface(dev, 3); + + lock_lock(g_usb); + g_usb->dev = dev; + lock_unlock(g_usb); + + if (0) + { + /* + the cimax's fw do not report cam status + when board power on with cam plugged, + have to check manually here. + */ + int slot = 0; + int err = 0; + for (slot = 0; slot < 2; slot++) { + int addr = (!slot) ? MOD_CTRL_A : MOD_CTRL_B; + u8 reg = 0; + err = aml_cimax_usb_read_reg(g_usb->cimax, + addr, ®, 1); + cam_usb_cam_detect(g_usb, slot, + (reg & 1) ? IN_INSERTED : 0); + cimax_usb_cam_powerctrl(g_usb, slot, (reg & 1)); + } + } + cimax_usb_set_power(g_usb, 0); + cimax_usb_setup_poll(g_usb, cimax_poll_mode ? POLL_MODE : INT_MODE); + return 0; +} +EXPORT_SYMBOL(cimax_usb_dev_add); + +int cimax_usb_dev_remove(struct device_s *dev, int id) +{ + pr_dbg("dev remove\n"); + if (!g_usb) + return 0; + id = id; + pr_dbg("setup poll -> stop\n"); + cimax_usb_setup_poll(g_usb, STOP_MODE); + pr_dbg("setup poll end\n"); + lock_lock(g_usb); + g_usb->dev = NULL; + lock_unlock(g_usb); + return 0; +} +EXPORT_SYMBOL(cimax_usb_dev_remove); + +static int cimax_usb_get_config_from_dts(struct cimax_usb *usb) +{ + struct device_node *child = NULL; + struct platform_device *pdev = usb->pdev; + struct device_node *np = pdev->dev.of_node; + pr_dbg("fetch cimax usb in dts\n"); + + child = of_get_child_by_name(np, "cimax"); + if (child == NULL) { + pr_error("cimax not found in dts\n"); + return -1; + } + child = of_get_child_by_name(child, "usb"); + if (!child) { + pr_error("usb not found in cimax"); + return -1; + } +/* +dvbci { + compatible = "amlogic, dvbci"; + dev_name = "dvbci"; + io_type = <2>;//0:iobus,1:usb,2:cimax + cimax { + io_type = <1> //0:spi 1:usb + usb { + rst_gpio = <&gpio_ao GPIOAO_2 GPIO_ACTIVE_HIGH>; + }; + }; + +}; +*/ + { + int ret = 0; + int gpio = -1; + gpio = of_get_named_gpio_flags(child, "rst-gpios", 0, NULL); + if (gpio != -1) { + ret = gpio_request(gpio, "cimax"); + if (ret < 0) { + pr_error("rst-gpios request fail.\n"); + return ret; + } + usb->rst_io = gpio; + cimax_usb_hw_reset(usb, 1); + pr_dbg("rst: %d\n", usb->rst_io); + } else { + pr_error("rst io got fail, %d\n", gpio); + } + } + return 0; +} + +int aml_cimax_usb_init(struct platform_device *pdev, struct aml_cimax *cimax) +{ + struct cimax_usb *cimax_usb; + + cimax_usb = kzalloc(sizeof(struct cimax_usb), GFP_KERNEL); + if (!cimax_usb) + return -ENOMEM; + + cimax_usb->pdev = pdev; + cimax_usb->cimax = cimax; + cimax_usb_get_config_from_dts(cimax_usb); + + /*init usb_lock*/ + lock_init(cimax_usb); + + /*init cimax used api.*/ +#define WI(_f)\ + cimax->ops._f = aml_cimax_usb_##_f + WI(read_cis); + WI(write_cor); + WI(negotiate); + WI(read_lpdu); + WI(write_lpdu); + WI(read_cam_status); + WI(cam_reset); + WI(slot_reset); + WI(slot_shutdown); + WI(slot_ts_enable); + WI(slot_status); + WI(read_reg); + WI(write_reg); + + cimax->priv = cimax_usb; + + g_usb = cimax_usb; + + aml_cimax_usb_mod_init(); + + cimax_usb_set_cb(cimax_usb_dev_add, cimax_usb_dev_remove); + + return 0; +} +EXPORT_SYMBOL(aml_cimax_usb_init); + +int aml_cimax_usb_exit(struct aml_cimax *cimax) +{ + struct cimax_usb *usb = cimax_to_usb(cimax); + + if (!usb) + return -ENODEV; + + aml_cimax_usb_mod_exit(); + + cimax_usb_device_close(usb->dev); + cimax_usb_setup_poll(usb, STOP_MODE); + + if (usb->rst_io) + gpio_free(usb->rst_io); + + kfree(usb->cis); + + kfree(usb); + cimax->priv = NULL; + + g_usb = NULL; + return 0; +} +EXPORT_SYMBOL(aml_cimax_usb_exit); + +static int cimax_usb_reset(struct cimax_usb *usb, int reset_val) +{ + pr_dbg("reset usb:%p, rst:%d\n", usb, usb ? usb->rst_io : -1); + if (!usb) + return -ENODEV; + + pr_inf("cimax usb reset\n"); + + /*notify unplugged*/ + aml_cimax_camchanged(usb->cimax, 0, 0); + aml_cimax_camchanged(usb->cimax, 1, 0); + + if (usb->dev) + cimax_usb_device_close(usb->dev); + + cimax_usb_setup_poll(usb, STOP_MODE); + + usb->cam_inserted[0] = usb->cam_inserted[1] = 0; + usb->cam_data_ready[0] = usb->cam_data_ready[1] = 0; + + cimax_usb_hw_reset(usb, reset_val); + + pr_inf("cimax usb reset end\n"); + return 0; +} + +static ssize_t reset_show(struct class *class, + struct class_attribute *attr, char *buf) +{ + int ret; + ret = sprintf(buf, "echo 1 > %s\n", attr->attr.name); + return ret; +} + +static ssize_t reset_store(struct class *class, + struct class_attribute *attr, const char *buf, size_t size) +{ + int ret; + int val = 0; + if (!g_usb) + return size; + ret = sscanf(buf, "%i", &val); + if (ret == 1) + ret = cimax_usb_reset(g_usb, val); + return size; +} + +static ssize_t debug_show(struct class *class, + struct class_attribute *attr, char *buf) +{ + int ret = 0; + if (!g_usb) + return ret; + + ret = sprintf(buf, "poll mode: %d\n", g_usb->poll_mode); + ret += sprintf(buf+ret, "status slot[0]=[%d] slot[1]=[%d]\n", + g_usb->cam_inserted[0], g_usb->cam_inserted[1]); + { + int power = 0; + int err = cimax_usb_check_poe(g_usb, &power); + ret += sprintf(buf+ret, "power slot[0]=[%d] slot[1]=[%d]\n", + err ? -1 : power, 0); + } + ret += sprintf(buf+ret, "data slot[0]=[%d] slot[1]=[%d]\n", + g_usb->cam_data_ready[0], g_usb->cam_data_ready[1]); + ret += sprintf(buf+ret, "work cnt:%d\n", g_usb->work_cnt); + ret += sprintf(buf+ret, "pwr work cnt:%d\n", g_usb->power_work_cnt); + return ret; +} + +static int reg_addr; +static ssize_t addr_show(struct class *class, + struct class_attribute *attr, char *buf) +{ + int ret = 0; + ret = sprintf(buf, "addr = 0x%04x\n", reg_addr); + return ret; +} + +static ssize_t addr_store(struct class *class, + struct class_attribute *attr, const char *buf, size_t size) +{ + if (!g_usb) + return size; + if (sscanf(buf, "%i", ®_addr) != 1) + return size; + return size; +} + +static ssize_t reg_show(struct class *class, + struct class_attribute *attr, char *buf) +{ + int ret = 0; + u8 reg_val = 0; + struct aml_cimax *cimax = NULL; + + if (!g_usb) + return ret; + + cimax = g_usb->cimax; + ret = aml_cimax_usb_read_reg(cimax, reg_addr, ®_val, 1); + if (ret) + ret = sprintf(buf, "read fail, err=%d\n", ret); + else + ret = sprintf(buf, "reg[0x%04x] = 0x%02x\n", reg_addr, reg_val); + return ret; +} + +static ssize_t reg_store(struct class *class, + struct class_attribute *attr, const char *buf, size_t size) +{ + int ret = 0; + struct aml_cimax *cimax = NULL; + int val = 0; + u8 reg_val = 0; + + if (!g_usb) + return size; + + if (sscanf(buf, "%i", &val) != 1) + return size; + reg_val = val; + cimax = g_usb->cimax; + ret = aml_cimax_usb_write_reg(cimax, reg_addr, ®_val, 1); + if (ret) + return ret; + return size; +} + +static int cis_mode; /*0:hex 1:binary*/ +static ssize_t cis_show(struct class *class, + struct class_attribute *attr, char *buf) +{ + int ret = 0; + + if (!g_usb || !g_usb->cis) + return ret; + + if (cis_mode == 0) { + int i; + for (i = 0; i < CIS_MAX; i++) { + if (i && !(i & 0xf)) + ret += sprintf(buf+ret, "\n"); + ret += sprintf(buf+ret, "%02X ", g_usb->cis[i]); + } + ret += sprintf(buf+ret, "\n"); + return ret; + } else { + memcpy(buf, g_usb->cis, CIS_MAX); + return CIS_MAX; + } + return ret; +} + +static ssize_t cis_store(struct class *class, + struct class_attribute *attr, const char *buf, size_t size) +{ + if (size >= 3 + && !memcmp(buf, "bin", 3)) + cis_mode = 1; + else + cis_mode = 0; + return size; +} + +static ssize_t ts_rate_show(struct class *class, + struct class_attribute *attr, char *buf) +{ + int ret = 0; + u8 lsb = 0, msb = 0, plen = 0; + struct aml_cimax *cimax = NULL; + int err = 0; + + if (!g_usb) + return ret; + + cimax = g_usb->cimax; + err = aml_cimax_usb_read_reg(cimax, PCK_LENGTH, &plen, 1); + err |= aml_cimax_usb_read_reg(cimax, BITRATE_CH0_LSB, &lsb, 1); + err |= aml_cimax_usb_read_reg(cimax, BITRATE_CH0_MSB, &msb, 1); + if (err) + ret += sprintf(buf+ret, "read fail, err=%d\n", err); + else if (!byte_to_u16(msb, lsb)) + ret += sprintf(buf+ret, "rate[0] = 0 Kbps\n"); + else + ret += sprintf(buf+ret, "rate[0] = %d Kbps\n", + 540*plen*8/byte_to_u16(msb, lsb)); + if (err) + return ret; + + err = aml_cimax_usb_read_reg(cimax, BITRATE_CH1_LSB, &lsb, 1); + err |= aml_cimax_usb_read_reg(cimax, BITRATE_CH1_MSB, &msb, 1); + if (err) + ret += sprintf(buf+ret, "read fail, err=%d\n", err); + else if (!byte_to_u16(msb, lsb)) + ret += sprintf(buf+ret, "rate[1] = 0 Kbps\n"); + else + ret += sprintf(buf+ret, "rate[1] = %d Kbps\n", + 540*plen*8/byte_to_u16(msb, lsb)); + return ret; +} + +static ssize_t loop_show(struct class *class, + struct class_attribute *attr, char *buf) +{ + int ret = 0; + u8 ch = 0, mod = 0; + struct aml_cimax *cimax = NULL; + int err = 0; + + if (!g_usb) + return ret; + + cimax = g_usb->cimax; + err = aml_cimax_usb_read_reg(cimax, ROUTER_CAM_CH, &ch, 1); + err |= aml_cimax_usb_read_reg(cimax, ROUTER_CAM_MOD, &mod, 1); + if (err) { + ret = sprintf(buf, "read fail, err=%d\n", err); + return ret; + } + ret += sprintf(buf + ret, "OUT-0 <= "); + switch (ch & 0x0f) { + case 0x0: + ret += sprintf(buf + ret, "CAM-A"); break; + case 0x1: + ret += sprintf(buf + ret, "CH0-IN"); break; + case 0x2: + ret += sprintf(buf + ret, "CH1-IN"); break; + case 0x3: + ret += sprintf(buf + ret, "REMAPPER"); break; + case 0x4: + ret += sprintf(buf + ret, "PREHEADER"); break; + case 0x5: + ret += sprintf(buf + ret, "CAM-B"); break; + case 0x6: + ret += sprintf(buf + ret, "GAPREMOVER-0"); break; + case 0x7: + ret += sprintf(buf + ret, "GAPREMOVER-1"); break; + case 0x8: + ret += sprintf(buf + ret, "NONE"); break; + default: + ret += sprintf(buf + ret, "UNKNOWN"); break; + } + ret += sprintf(buf + ret, "\nCAM-A <= "); + switch (mod & 0x07) { + case 0x1: + ret += sprintf(buf + ret, "CH0-IN"); break; + case 0x2: + ret += sprintf(buf + ret, "CH1-IN"); break; + case 0x3: + ret += sprintf(buf + ret, "REMAPPER"); break; + case 0x4: + ret += sprintf(buf + ret, "PREHEADER"); break; + case 0x5: + ret += sprintf(buf + ret, "CAM-B"); break; + case 0x6: + ret += sprintf(buf + ret, "GAPREMOVER-0"); break; + case 0x7: + ret += sprintf(buf + ret, "GAPREMOVER-1"); break; + default: + ret += sprintf(buf + ret, "NONE"); break; + } + ret += sprintf(buf + ret, "\n"); + + return ret; +} + +static ssize_t loop_store(struct class *class, + struct class_attribute *attr, const char *buf, size_t size) +{ + int loop = 0; + + if (!g_usb) + return size; + + if (sscanf(buf, "%i", &loop) == 1) + cimax_usb_set_loop(g_usb, loop); + return size; +} + +static ssize_t slot_reset_store(struct class *class, + struct class_attribute *attr, const char *buf, size_t size) +{ + int err = 0; + int slot = 0; + struct aml_cimax *cimax = NULL; + + if (!g_usb) + return size; + + if (sscanf(buf, "%i", &slot) == 1) { + if (slot == 0 || slot == 1) { + pr_dbg("reset slot %d\n", slot); + cimax = g_usb->cimax; + err = aml_cimax_usb_slot_reset(cimax, slot); + } + } + return size; +} + +static ssize_t detect_store(struct class *class, + struct class_attribute *attr, const char *buf, size_t size) +{ + int err = 0; + int slot = 0; + struct aml_cimax *cimax = NULL; + + if (!g_usb) + return size; + + if (sscanf(buf, "%i", &slot) == 1) { + if (slot == 0 || slot == 1) { + int addr = (!slot) ? MOD_CTRL_A : MOD_CTRL_B; + u8 reg = 0; + cimax = g_usb->cimax; + err = aml_cimax_usb_read_reg(cimax, addr, ®, 1); + cam_usb_cam_detect(g_usb, slot, + (reg & 1) ? IN_INSERTED : 0); + cimax_usb_cam_powerctrl(g_usb, slot, (reg & 1)); + } + } + return size; +} + + +static struct class_attribute cimax_usb_class_attrs[] = { + __ATTR_RW(reset), + __ATTR_RO(debug), + __ATTR_RW(addr), + __ATTR_RW(reg), + __ATTR_RW(cis), + __ATTR_RO(ts_rate), + __ATTR_RW(loop), + __ATTR_WO(slot_reset), + __ATTR_WO(detect), + __ATTR_NULL +}; + +static struct class cimax_usb_class = { + .name = "cimax_usb", + .class_attrs = cimax_usb_class_attrs, +}; + +static int aml_cimax_usb_mod_init(void) +{ + int ret; + pr_dbg("Amlogic CIMAX USB Init\n"); + ret = class_register(&cimax_usb_class); + return 0; +} + +static void aml_cimax_usb_mod_exit(void) +{ + pr_dbg("Amlogic CIMAX USB Exit\n"); + class_unregister(&cimax_usb_class); +} + diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/aml_cimax_usb.h b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/aml_cimax_usb.h new file mode 100644 index 000000000000..471d2da5af56 --- /dev/null +++ b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/aml_cimax_usb.h @@ -0,0 +1,20 @@ +/*************************************************************************** + * Copyright (c) 2014 Amlogic, Inc. All rights reserved. + * + * This source code is subject to the terms and conditions defined in the + * file 'LICENSE' which is part of this source code package. + * + * Description: + * +***************************************************************************/ + +#ifndef _AML_CIMAX_USB_H_ +#define _AML_CIMAX_USB_H_ + +#include +#include "aml_cimax.h" + +int aml_cimax_usb_init(struct platform_device *pdev, struct aml_cimax *ci); +int aml_cimax_usb_exit(struct aml_cimax *ci); + +#endif diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/aml_cimax_usb_priv.h b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/aml_cimax_usb_priv.h new file mode 100644 index 000000000000..aec694c66a3c --- /dev/null +++ b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/aml_cimax_usb_priv.h @@ -0,0 +1,22 @@ +/*************************************************************************** + * Copyright (c) 2014 Amlogic, Inc. All rights reserved. + * + * This source code is subject to the terms and conditions defined in the + * file 'LICENSE' which is part of this source code package. + * + * Description: + * +***************************************************************************/ + +#ifndef _CIMAX_USB_DEV_H_ +#define _CIMAX_USB_DEV_H_ + +#if 0 +__attribute__ ((weak)) +int cimax_usb_dev_add(struct device_s *device, int id); +__attribute__ ((weak)) +int cimax_usb_dev_remove(struct device_s *device, int id); +#endif + +#endif + diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/dvb_ca_en50221_cimax.c b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/dvb_ca_en50221_cimax.c new file mode 100644 index 000000000000..e8fb0eec9064 --- /dev/null +++ b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/dvb_ca_en50221_cimax.c @@ -0,0 +1,1910 @@ +/* + * dvb_ca.c: generic DVB functions for EN50221 CAM CIMAX interfaces + * + * Parts of this file were based on sources as follows: + * + * based on code: + * + * Copyright (C) 1999-2002 Ralph Metzler + * & Marcus Metzler for convergence integrated media GmbH + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dvb_ca_en50221_cimax.h" +#include "dvb_ringbuffer.h" + +static int dvb_ca_en50221_debug = 1; + +module_param_named(cam_debug, dvb_ca_en50221_debug, int, 0644); +MODULE_PARM_DESC(cam_debug, "enable verbose debug messages"); + +#define HOST_LINK_BUF_SIZE 0x1000 + +static int dvb_ca_en50221_link_size = HOST_LINK_BUF_SIZE; +module_param_named(link_size, dvb_ca_en50221_link_size, int, 0644); +MODULE_PARM_DESC(link_size, "debug only, no more than 0x1000"); + + +#define dprintk(args...)\ + do {\ + if (dvb_ca_en50221_debug)\ + printk(args);\ + } while (0) +#define pr_error(fmt, args...) printk("CA EN50211: " fmt, ## args) + +#define INIT_TIMEOUT_SECS 40 + + +#define RX_BUFFER_SIZE 65535 + +#define MAX_RX_PACKETS_PER_ITERATION 10 + +#define CTRLIF_DATA 0 +#define CTRLIF_COMMAND 1 +#define CTRLIF_STATUS 1 +#define CTRLIF_SIZE_LOW 2 +#define CTRLIF_SIZE_HIGH 3 + +#define CMDREG_HC 1 /* Host control */ +#define CMDREG_SW 2 /* Size write */ +#define CMDREG_SR 4 /* Size read */ +#define CMDREG_RS 8 /* Reset interface */ +#define CMDREG_FRIE 0x40 /* Enable FR interrupt */ +#define CMDREG_DAIE 0x80 /* Enable DA interrupt */ +#define IRQEN (CMDREG_DAIE) + +#define STATUSREG_RE 1 /* read error */ +#define STATUSREG_WE 2 /* write error */ +#define STATUSREG_FR 0x40 /* module free */ +#define STATUSREG_DA 0x80 /* data available */ +#define STATUSREG_TXERR (STATUSREG_RE|STATUSREG_WE)/* general transfer error */ + + +#define DVB_CA_SLOTSTATE_NONE 0 +#define DVB_CA_SLOTSTATE_UNINITIALISED 1 +#define DVB_CA_SLOTSTATE_RUNNING 2 +#define DVB_CA_SLOTSTATE_INVALID 3 +#define DVB_CA_SLOTSTATE_WAITREADY 4 +#define DVB_CA_SLOTSTATE_VALIDATE 5 +#define DVB_CA_SLOTSTATE_WAITFR 6 +#define DVB_CA_SLOTSTATE_LINKINIT 7 +#define DVB_CA_SLOTSTATE_WAITLINKINIT 8 + +#define MAX_CIS_SIZE 512 + +/* Information on a CA slot */ +struct dvb_ca_slot { + + /* current state of the CAM */ + int slot_state; + + /* mutex used for serializing access to one CI slot */ + struct mutex slot_lock; + + /* Number of CAMCHANGES that have occurred since last processing */ + atomic_t camchange_count; + + /* Type of last CAMCHANGE */ + int camchange_type; + + /* base address of CAM config */ + u32 config_base; + + /* value to write into Config Control register */ + u8 config_option; + + /* if 1, the CAM supports DA IRQs */ + u8 da_irq_supported:1; + + /* size of the buffer to use when talking to the CAM */ + int link_buf_size; + + /* buffer for incoming packets */ + struct dvb_ringbuffer rx_buffer; + + /* timer used during various states of the slot */ + unsigned long timeout; +}; + +/* Private CA-interface information */ +struct dvb_ca_private { + + /* pointer back to the public data structure */ + struct dvb_ca_en50221_cimax *pub; + + /* the DVB device */ + struct dvb_device *dvbdev; + + /* Flags describing the interface (DVB_CA_FLAG_*) */ + u32 flags; + + /* number of slots supported by this CA interface */ + unsigned int slot_count; + + /* information on each slot */ + struct dvb_ca_slot *slot_info; + + /* wait queues for read() and write() operations */ + wait_queue_head_t wait_queue; + + /* PID of the monitoring thread */ + struct task_struct *thread; + + /* Flag indicating if the CA device is open */ + unsigned int open:1; + + /* Flag indicating the thread should wake up now */ + unsigned int wakeup:1; + + /* Delay the main thread should use */ + unsigned long delay; + + /* Slot to start looking for data + to read from in the next user-space read operation */ + int next_read_slot; + + /* mutex serializing ioctls */ + struct mutex ioctl_mutex; + + /*two bufs for read/write*/ + u8 *rbuf; + u8 *wbuf; +}; + +static void dvb_ca_en50221_thread_wakeup(struct dvb_ca_private *ca); +static int dvb_ca_en50221_read_data(struct dvb_ca_private *ca, + int slot, u8 *ebuf, int ecount); +static int dvb_ca_en50221_write_data(struct dvb_ca_private *ca, + int slot, u8 *ebuf, int ecount); + + +/** + * Safely find needle in haystack. + * + * @param haystack Buffer to look in. + * @param hlen Number of bytes in haystack. + * @param needle Buffer to find. + * @param nlen Number of bytes in needle. + * @return Pointer into haystack needle was found at, or NULL if not found. + */ +static char *findstr(char *haystack, int hlen, char *needle, int nlen) +{ + int i; + + if (hlen < nlen) + return NULL; + + for (i = 0; i <= hlen - nlen; i++) { + if (!strncmp(haystack + i, needle, nlen)) + return haystack + i; + } + + return NULL; +} + + + +/* ************************************************************************** */ +/* EN50221 physical interface functions */ + + +/** + * Check CAM status. + */ +static int dvb_ca_en50221_check_camstatus(struct dvb_ca_private *ca, int slot) +{ + int slot_status; + int cam_present; + int cam_changed; + + /* IRQ mode */ + if (ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE) + return atomic_read(&ca->slot_info[slot].camchange_count) != 0; + + /* poll mode */ + slot_status = ca->pub->poll_slot_status(ca->pub, slot, ca->open); + + cam_present = (slot_status & DVB_CA_EN50221_POLL_CAM_PRESENT) ? 1 : 0; + cam_changed = (slot_status & DVB_CA_EN50221_POLL_CAM_CHANGED) ? 1 : 0; + if (!cam_changed) { + int cam_present_old = + (ca->slot_info[slot].slot_state + != DVB_CA_SLOTSTATE_NONE); + cam_changed = (cam_present != cam_present_old); + } + + if (cam_changed) { + if (!cam_present) { + ca->slot_info[slot].camchange_type = + DVB_CA_EN50221_CAMCHANGE_REMOVED; + } else { + ca->slot_info[slot].camchange_type = + DVB_CA_EN50221_CAMCHANGE_INSERTED; + } + atomic_set(&ca->slot_info[slot].camchange_count, 1); + } else { + if ((ca->slot_info[slot].slot_state + == DVB_CA_SLOTSTATE_WAITREADY) && + (slot_status & DVB_CA_EN50221_POLL_CAM_READY)) { + /* move to validate state if reset is completed */ + ca->slot_info[slot].slot_state = + DVB_CA_SLOTSTATE_VALIDATE; + } + } + return cam_changed; +} + + +/** + * Initialise the link layer connection to a CAM. + * + * @param ca CA instance. + * @param slot Slot id. + * + * @return 0 on success, nonzero on failure. + */ +static int dvb_ca_en50221_link_init(struct dvb_ca_private *ca, int slot) +{ + int ret; + dprintk("%s\n", __func__); + + /* we'll be determining these during this function */ + ca->slot_info[slot].da_irq_supported = 0; + + /* set the host link buffer size temporarily. + it will be overwritten with the real negotiated size later. */ + ca->slot_info[slot].link_buf_size = dvb_ca_en50221_link_size; + dprintk("negotiate: host(%i)\n", ca->slot_info[slot].link_buf_size); + + ret = ca->pub->negotiate(ca->pub, + slot, ca->slot_info[slot].link_buf_size); + if (ret <= 0) + return ret; + + ca->slot_info[slot].link_buf_size = ret; + dprintk("Chosen link buffer size of %i\n", ret); + + /* success */ + return 0; +} + +/** + * Read a tuple from attribute memory. + * + * @param ca CA instance. + * @param slot Slot id. + * @param cis CIS data + * @param address Address to read from. Updated. + * @param tupleType Tuple id byte. Updated. + * @param tupleLength Tuple length. Updated. + * @param tuple Dest buffer for tuple (must be 256 bytes). Updated. + * + * @return 0 on success, nonzero on error. + */ +static int dvb_ca_en50221_read_tuple(struct dvb_ca_private *ca, + int slot, u8 *cis, + int *address, int *tupleType, int *tupleLength, u8 *tuple) +{ + int i; + int _tupleType; + int _tupleLength; + int _address = *address; + + /* grab the next tuple length and type */ + _tupleType = cis[_address]; + if (_tupleType < 0) + return _tupleType; + if (_tupleType == 0xff) { + dprintk("END OF CHAIN TUPLE type:0x%x\n", _tupleType); + *address += 1; + *tupleType = _tupleType; + *tupleLength = 0; + return 0; + } + _tupleLength = cis[_address + 1]; + if (_tupleLength < 0) + return _tupleLength; + _address += 2; + + dprintk("TUPLE type:0x%x length:%i\n", _tupleType, _tupleLength); + + /* read in the whole tuple */ + for (i = 0; i < _tupleLength; i++) { + tuple[i] = cis[_address + (i)]; + dprintk(" 0x%02x: 0x%02x %c\n", + i, tuple[i] & 0xff, + ((tuple[i] > 31) && (tuple[i] < 127)) ? tuple[i] : '.'); + } + _address += (_tupleLength); + + /* success */ + *tupleType = _tupleType; + *tupleLength = _tupleLength; + *address = _address; + return 0; +} + + +/** + * Parse attribute memory of a CAM module, extracting Config register, + * and checking it is a DVB CAM module. + * + * @param ca CA instance. + * @param slot Slot id. + * + * @return 0 on success, <0 on failure. + */ +static int dvb_ca_en50221_parse_attributes(struct dvb_ca_private *ca, int slot) +{ + int address = 0; + int tupleLength; + int tupleType; + u8 tuple[257]; + char *dvb_str; + int rasz; + int status; + int got_cftableentry = 0; + int end_chain = 0; + int i; + u16 manfid = 0; + u16 devid = 0; + u8 cis[MAX_CIS_SIZE]; + + status = ca->pub->read_cis(ca->pub, slot, cis, MAX_CIS_SIZE); + if (status != 0) + return -EINVAL; + + /* CISTPL_DEVICE_0A */ + status = + dvb_ca_en50221_read_tuple(ca, slot, cis, &address, + &tupleType, &tupleLength, tuple); + if (status < 0) { + pr_error("read status error\r\n"); + return status; + } + if (tupleType != 0x1D) { + pr_error("read tupleType error [0x%x]\r\n", tupleType); + return -EINVAL; + } + + + + /* CISTPL_DEVICE_0C */ + status = dvb_ca_en50221_read_tuple(ca, slot, cis, &address, + &tupleType, &tupleLength, tuple); + + if (status < 0) { + pr_error("read read cis error\r\n"); + return -EINVAL; + } + if (tupleType != 0x1C) { + pr_error("read read cis type error\r\n"); + return -EINVAL; + } + + + + /* CISTPL_VERS_1 */ + status = + dvb_ca_en50221_read_tuple(ca, slot, cis, + &address, &tupleType, &tupleLength, tuple); + if (status < 0) { + pr_error("read read cis version error\r\n"); + return status; + } + if (tupleType != 0x15) { + pr_error("read read cis version type error\r\n"); + return -EINVAL; + } + + + + /* CISTPL_MANFID */ + status = dvb_ca_en50221_read_tuple(ca, slot, cis, &address, &tupleType, + &tupleLength, tuple); + if (status < 0) { + pr_error("read read cis manfid error\r\n"); + return status; + } + if (tupleType != 0x20) { + pr_error("read read cis manfid type error\r\n"); + return -EINVAL; + } + if (tupleLength != 4) { + pr_error("read read cis manfid len error\r\n"); + return -EINVAL; + } + manfid = (tuple[1] << 8) | tuple[0]; + devid = (tuple[3] << 8) | tuple[2]; + + + + /* CISTPL_CONFIG */ + status = dvb_ca_en50221_read_tuple(ca, slot, cis, &address, &tupleType, + &tupleLength, tuple); + if (status < 0) { + pr_error("read read cis config error\r\n"); + return status; + } + if (tupleType != 0x1A) { + pr_error("read read cis config type error\r\n"); + return -EINVAL; + } + if (tupleLength < 3) { + pr_error("read read cis config len error\r\n"); + return -EINVAL; + } + + /* extract the configbase */ + rasz = tuple[0] & 3; + if (tupleLength < (3 + rasz + 14)) { + pr_error("read extract the configbase error\r\n"); + return -EINVAL; + } + ca->slot_info[slot].config_base = 0; + for (i = 0; i < rasz + 1; i++) + ca->slot_info[slot].config_base |= (tuple[2 + i] << (8 * i)); + + /* check it contains the correct DVB string */ + dvb_str = findstr((char *)tuple, tupleLength, "DVB_CI_V", 8); + if (dvb_str == NULL) { + pr_error("find dvb str DVB_CI_V error\r\n"); + return -EINVAL; + } + if (tupleLength < ((dvb_str - (char *) tuple) + 12)) { + pr_error("find dvb str DVB_CI_V len error\r\n"); + return -EINVAL; + } + + /* is it a version we support? */ + if (strncmp(dvb_str + 8, "1.00", 4)) { + pr_info("dvb_ca adapter %d: ", ca->dvbdev->adapter->num); + pr_info("Unsupported DVB CAM module version %c%c%c%c\n", + dvb_str[8], dvb_str[9], dvb_str[10], dvb_str[11]); + return -EINVAL; + } + + /* process the CFTABLE_ENTRY tuples, and any after those */ + while ((!end_chain) && (address < 0x1000)) { + status = dvb_ca_en50221_read_tuple(ca, slot, cis, &address, + &tupleType, &tupleLength, tuple); + if (status < 0) { + pr_error("process tuples error\r\n"); + return status; + } + + switch (tupleType) { + case 0x1B: /* CISTPL_CFTABLE_ENTRY */ + if (tupleLength < (2 + 11 + 17)) + break; + + /* if we've already parsed one, just use it */ + if (got_cftableentry) + break; + + /* get the config option */ + ca->slot_info[slot].config_option = tuple[0] & 0x3f; + + /* OK, check it contains the correct strings */ + if ((findstr((char *)tuple, tupleLength, "DVB_HOST", 8) + == NULL) + || (findstr((char *)tuple, + tupleLength, "DVB_CI_MODULE", 13) + == NULL)) { + break; + } + got_cftableentry = 1; + break; + + case 0x14: /* CISTPL_NO_LINK */ + break; + + case 0xFF: /* CISTPL_END */ + end_chain = 1; + break; + + default: /* Unknown tuple type + -just skip this tuple and move to the next one */ + dprintk("dvb_ca: Skipping unknown tuple type:0x%x", + tupleType); + dprintk(" length:0x%x\n", tupleLength); + break; + } + } + + if ((address > 0x1000) || (!got_cftableentry)) { + pr_error("got_cftableentry :%d\r\n", got_cftableentry); + return -EINVAL; + } + + dprintk("Valid DVB CAM detected MANID:%x DEVID:%x", manfid, devid); + dprintk(" CONFIGBASE:0x%x CONFIGOPTION:0x%x\n", + ca->slot_info[slot].config_base, + ca->slot_info[slot].config_option); + + /* success! */ + return 0; +} + + +/** + * Set CAM's configoption correctly. + * + * @param ca CA instance. + * @param slot Slot containing the CAM. + */ +static int dvb_ca_en50221_set_configoption(struct dvb_ca_private *ca, int slot) +{ + int configoption; + + dprintk("%s\n", __func__); + + /* set the config option */ + ca->pub->write_cor(ca->pub, slot, + ca->slot_info[slot].config_base, + &ca->slot_info[slot].config_option); + + configoption = ca->slot_info[slot].config_option; + dprintk("Set configoption 0x%x, base 0x%x\n", + ca->slot_info[slot].config_option, + ca->slot_info[slot].config_base); + + /* fine! */ + return 0; + +} + + +/** + * This function talks to an EN50221 CAM control interface. It reads a buffer of + * data from the CAM. The data can either be stored in a supplied buffer, or + * automatically be added to the slot's rx_buffer. + * + * @param ca CA instance. + * @param slot Slot to read from. + * @param ebuf If non-NULL, the data will be written to this buffer. If NULL, + * the data will be added into the buffering system as a normal fragment. + * @param ecount Size of ebuf. Ignored if ebuf is NULL. + * + * @return Number of bytes read, or < 0 on error + */ +static int dvb_ca_en50221_read_data(struct dvb_ca_private *ca, + int slot, u8 *ebuf, int ecount) +{ + int bytes_read; + int status; + u8 *buf = ca->rbuf; + + /* dprintk("%s\n", __func__); */ + + /* check if we have space for a link buf in the rx_buffer */ + if (ebuf == NULL) { + int buf_free; + + if (ca->slot_info[slot].rx_buffer.data == NULL) { + status = -EIO; + goto exit; + } + buf_free = dvb_ringbuffer_free(&ca->slot_info[slot].rx_buffer); + + if (buf_free < (ca->slot_info[slot].link_buf_size + + DVB_RINGBUFFER_PKTHDRSIZE)) { + status = -EAGAIN; + goto exit; + } + } + + /* check if there is data available */ + status = ca->pub->read_cam_status(ca->pub, slot); + if (status < 0) + goto exit; + if (!(status & STATUSREG_DA)) { + /* no data */ + status = 0; + goto exit; + } + + /* read the amount of data */ + status = ca->pub->read_lpdu(ca->pub, + slot, buf, dvb_ca_en50221_link_size); + if (status < 0) { + ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_LINKINIT; + status = -EIO; + goto exit; + } + + bytes_read = status; + + /* check it will fit */ + if (ebuf == NULL) { + if (bytes_read > ca->slot_info[slot].link_buf_size) { + pr_error("dvb_ca adapter %d:", + ca->dvbdev->adapter->num); + pr_error(" CAM tried to send a buffer larger "); + pr_error("than the link buffer size(%i > %i)!\n", + bytes_read, ca->slot_info[slot].link_buf_size); + ca->slot_info[slot].slot_state = + DVB_CA_SLOTSTATE_LINKINIT; + status = -EIO; + goto exit; + } + if (bytes_read < 2) { + pr_error("dvb_ca adapter %d: ", + ca->dvbdev->adapter->num); + pr_error("CAM sent a buffer"); + pr_error("that was less than 2B!\n"); + ca->slot_info[slot].slot_state = + DVB_CA_SLOTSTATE_LINKINIT; + status = -EIO; + goto exit; + } + } else { + if (bytes_read > ecount) { + pr_error("dvb_ca adapter %d:", + ca->dvbdev->adapter->num); + pr_error(" CAM tried to send a buffer larger"); + pr_error(" than the ecount size!\n"); + status = -EIO; + goto exit; + } + } + + /* OK, add it to the receive buffer, + or copy into external buffer if supplied */ + if (ebuf == NULL) { + if (ca->slot_info[slot].rx_buffer.data == NULL) { + status = -EIO; + goto exit; + } + dvb_ringbuffer_pkt_write(&ca->slot_info[slot].rx_buffer, + buf, bytes_read); + } else { + memcpy(ebuf, buf, bytes_read); + } + + /* wake up readers when a last_fragment is received */ + if ((buf[1] & 0x80) == 0x00) + wake_up_interruptible(&ca->wait_queue); + status = bytes_read; + +exit: + return status; +} + + +/** + * This function talks to an EN50221 CAM control interface. + * It writes a buffer of data + * to a CAM. + * + * @param ca CA instance. + * @param slot Slot to write to. + * @param ebuf The data in this buffer + * is treated as a complete link-level packet to be written. + * @param count Size of ebuf. + * + * @return Number of bytes written, or < 0 on error. + */ +static int dvb_ca_en50221_write_data(struct dvb_ca_private *ca, + int slot, u8 *buf, int bytes_write) +{ + int status; + + /* dprintk("%s\n", __func__); */ + + /* sanity check */ + if (bytes_write > ca->slot_info[slot].link_buf_size) + return -EINVAL; + + /* it is possible we are dealing with a single buffer implementation, + thus if there is data available for read or if there is even a read + already in progress, we do nothing but awake the kernel thread to + process the data if necessary. */ + status = ca->pub->read_cam_status(ca->pub, slot); + if (status < 0) + return status; + if (status & (STATUSREG_DA | STATUSREG_RE)) { + if (status & STATUSREG_DA) + dvb_ca_en50221_thread_wakeup(ca); + status = -EAGAIN; + return status; + } + + if (!(status & STATUSREG_FR)) { + status = -EAGAIN; + return status; + } + + status = ca->pub->write_lpdu(ca->pub, slot, buf, bytes_write); + if (status < 0) { + if (status == -EBUSY) { + status = -EAGAIN; + return status; + } else { + ca->slot_info[slot].slot_state = + DVB_CA_SLOTSTATE_LINKINIT; + status = -EIO; + return status; + } + } + + status = bytes_write; + + return status; +} +EXPORT_SYMBOL(dvb_ca_en50221_cimax_camchange_irq); + + + +/* ************************************************************************** */ +/* EN50221 higher level functions */ + + +/** + * A CAM has been removed => shut it down. + * + * @param ca CA instance. + * @param slot Slot to shut down. + */ +static int dvb_ca_en50221_slot_shutdown(struct dvb_ca_private *ca, int slot) +{ + dprintk("%s\n", __func__); + + ca->pub->slot_shutdown(ca->pub, slot); + ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_NONE; + + /* need to wake up all processes to check if they're now + trying to write to a defunct CAM */ + wake_up_interruptible(&ca->wait_queue); + + dprintk("Slot %i shutdown\n", slot); + + /* success */ + return 0; +} +EXPORT_SYMBOL(dvb_ca_en50221_cimax_camready_irq); + + +/** + * A CAMCHANGE IRQ has occurred. + * + * @param ca CA instance. + * @param slot Slot concerned. + * @param change_type One of the DVB_CA_CAMCHANGE_* values. + */ +void dvb_ca_en50221_cimax_camchange_irq(struct dvb_ca_en50221_cimax *pubca, + int slot, int change_type) +{ + struct dvb_ca_private *ca = pubca->private; + + dprintk("CAMCHANGE IRQ slot:%i change_type:%i\n", slot, change_type); + + switch (change_type) { + case DVB_CA_EN50221_CAMCHANGE_REMOVED: + case DVB_CA_EN50221_CAMCHANGE_INSERTED: + break; + + default: + return; + } + + ca->slot_info[slot].camchange_type = change_type; + atomic_inc(&ca->slot_info[slot].camchange_count); + dvb_ca_en50221_thread_wakeup(ca); +} +EXPORT_SYMBOL(dvb_ca_en50221_cimax_frda_irq); + + +/** + * A CAMREADY IRQ has occurred. + * + * @param ca CA instance. + * @param slot Slot concerned. + */ +void dvb_ca_en50221_cimax_camready_irq(struct dvb_ca_en50221_cimax *pubca, + int slot) +{ + struct dvb_ca_private *ca = pubca->private; + + dprintk("CAMREADY IRQ slot:%i\n", slot); + + if (ca->slot_info[slot].slot_state == DVB_CA_SLOTSTATE_WAITREADY) { + ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_VALIDATE; + dvb_ca_en50221_thread_wakeup(ca); + } +} + + +/** + * An FR or DA IRQ has occurred. + * + * @param ca CA instance. + * @param slot Slot concerned. + */ +void dvb_ca_en50221_cimax_frda_irq(struct dvb_ca_en50221_cimax *pubca, + int slot) +{ + struct dvb_ca_private *ca = pubca->private; + int flags; + + dprintk("FR/DA IRQ slot:%i\n", slot); + + switch (ca->slot_info[slot].slot_state) { + case DVB_CA_SLOTSTATE_LINKINIT: + flags = ca->pub->get_capbility(pubca, slot); + if (flags & DVB_CA_EN50221_CAP_IRQ) { + dprintk("CAM supports DA IRQ\n"); + ca->slot_info[slot].da_irq_supported = 1; + } + break; + + case DVB_CA_SLOTSTATE_RUNNING: + if (ca->open) + dvb_ca_en50221_thread_wakeup(ca); + break; + } +} + + + +/* ************************************************************************** */ +/* EN50221 thread functions */ + +/** + * Wake up the DVB CA thread + * + * @param ca CA instance. + */ +static void dvb_ca_en50221_thread_wakeup(struct dvb_ca_private *ca) +{ + + dprintk("%s\n", __func__); + + ca->wakeup = 1; + mb(); /*original*/ + wake_up_process(ca->thread); +} + +/** + * Update the delay used by the thread. + * + * @param ca CA instance. + */ +static void dvb_ca_en50221_thread_update_delay(struct dvb_ca_private *ca) +{ + int delay; + int curdelay = 100000000; + int slot; + + /* Beware of too high polling frequency, because one polling + * call might take several hundred milliseconds until timeout! + */ + for (slot = 0; slot < ca->slot_count; slot++) { + switch (ca->slot_info[slot].slot_state) { + default: + case DVB_CA_SLOTSTATE_NONE: + delay = HZ * 60; /* 60s */ + if (!(ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE)) + delay = HZ * 5; /* 5s */ + break; + case DVB_CA_SLOTSTATE_INVALID: + delay = HZ * 60; /* 60s */ + if (!(ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE)) + delay = HZ / 10; /* 100ms */ + break; + + case DVB_CA_SLOTSTATE_UNINITIALISED: + case DVB_CA_SLOTSTATE_WAITREADY: + case DVB_CA_SLOTSTATE_VALIDATE: + case DVB_CA_SLOTSTATE_WAITFR: + case DVB_CA_SLOTSTATE_LINKINIT: + delay = HZ / 10; /* 100ms */ + break; + case DVB_CA_SLOTSTATE_WAITLINKINIT: + delay = HZ * 2; + break; + + case DVB_CA_SLOTSTATE_RUNNING: + delay = HZ * 60; /* 60s */ + if (!(ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE)) + delay = HZ / 10; /* 100ms */ + if (ca->open) { + if ((!ca->slot_info[slot].da_irq_supported) || + (!(ca->flags & DVB_CA_EN50221_FLAG_IRQ_DA))) + delay = HZ / 10; /* 100ms */ + } + break; + } + + if (delay < curdelay) + curdelay = delay; + } + + ca->delay = curdelay; +} + +static int dvb_ca_en50221_slot_process(struct dvb_ca_private *ca, int slot) +{ + int flags; + int status; + int pktcount; + void *rxbuf; + + mutex_lock(&ca->slot_info[slot].slot_lock); + + /*check the cam status + deal with CAMCHANGEs*/ + while (dvb_ca_en50221_check_camstatus(ca, slot)) { + /* clear down an old CI slot if necessary */ + if (ca->slot_info[slot].slot_state != DVB_CA_SLOTSTATE_NONE) + dvb_ca_en50221_slot_shutdown(ca, slot); + + /* if a CAM is NOW present, initialise it */ + if (ca->slot_info[slot].camchange_type + == DVB_CA_EN50221_CAMCHANGE_INSERTED) + ca->slot_info[slot].slot_state = + DVB_CA_SLOTSTATE_UNINITIALISED; + + /* we've handled one CAMCHANGE */ + dvb_ca_en50221_thread_update_delay(ca); + atomic_dec(&ca->slot_info[slot].camchange_count); + } + + /* CAM state machine */ + switch (ca->slot_info[slot].slot_state) { + case DVB_CA_SLOTSTATE_NONE: + case DVB_CA_SLOTSTATE_INVALID: + /* no action needed */ + break; + + case DVB_CA_SLOTSTATE_UNINITIALISED: + ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_WAITREADY; + ca->pub->slot_reset(ca->pub, slot); + ca->slot_info[slot].timeout = jiffies + + (INIT_TIMEOUT_SECS * HZ); + break; + + case DVB_CA_SLOTSTATE_WAITREADY: + if (time_after(jiffies, ca->slot_info[slot].timeout)) { + dprintk("%d: PC card did not respond\n", + ca->dvbdev->adapter->num); + ca->slot_info[slot].slot_state = + DVB_CA_SLOTSTATE_INVALID; + dvb_ca_en50221_thread_update_delay(ca); + break; + } + /* no other action needed; will automatically + * change state when ready + */ + break; + + case DVB_CA_SLOTSTATE_VALIDATE: + if (dvb_ca_en50221_parse_attributes(ca, slot) != 0) { + /* we need this extra check + for annoying interfaces like the budget-av */ + if ((!(ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE)) + && (ca->pub->poll_slot_status)) { + status = ca->pub->poll_slot_status(ca->pub, + slot, 0); + if (!(status + & DVB_CA_EN50221_POLL_CAM_PRESENT)) { + ca->slot_info[slot].slot_state = + DVB_CA_SLOTSTATE_NONE; + dvb_ca_en50221_thread_update_delay(ca); + break; + } + } + dprintk(" %d: Invalid PC card inserted :(\n", + ca->dvbdev->adapter->num); + ca->slot_info[slot].slot_state = + DVB_CA_SLOTSTATE_INVALID; + dvb_ca_en50221_thread_update_delay(ca); + break; + } + if (dvb_ca_en50221_set_configoption(ca, slot) != 0) { + dprintk("%d: Unable initialise CAM:(\n", + ca->dvbdev->adapter->num); + ca->slot_info[slot].slot_state = + DVB_CA_SLOTSTATE_INVALID; + dvb_ca_en50221_thread_update_delay(ca); + break; + } + + if (ca->pub->cam_reset(ca->pub, slot) != 0) { + dprintk("%d: Unable to reset CAM IF\n", + ca->dvbdev->adapter->num); + ca->slot_info[slot].slot_state = + DVB_CA_SLOTSTATE_INVALID; + dvb_ca_en50221_thread_update_delay(ca); + break; + } + + dprintk("DVB CAM validated successfully\n"); + + ca->slot_info[slot].timeout = + jiffies + (INIT_TIMEOUT_SECS * HZ); + ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_WAITFR; + ca->wakeup = 1; + break; + + case DVB_CA_SLOTSTATE_WAITFR: + if (time_after(jiffies, ca->slot_info[slot].timeout)) { + pr_error("dvb_ca adapter %d: ", + ca->dvbdev->adapter->num); + pr_error("DVB CAM did not respond :(\n"); + ca->slot_info[slot].slot_state = + DVB_CA_SLOTSTATE_INVALID; + dvb_ca_en50221_thread_update_delay(ca); + break; + } + + /*flags = ca->pub->read_cam_status(ca->pub, slot);*/ + flags = STATUSREG_FR; + if (flags & STATUSREG_FR) { + ca->slot_info[slot].slot_state = + DVB_CA_SLOTSTATE_LINKINIT; + ca->wakeup = 1; + } + break; + + case DVB_CA_SLOTSTATE_WAITLINKINIT: + if (time_after(jiffies, ca->slot_info[slot].timeout)) { + pr_error("dvb_ca adapter %d: ", + ca->dvbdev->adapter->num); + pr_error("DVB CAM link initialisation failed :(\n"); + ca->slot_info[slot].slot_state = + DVB_CA_SLOTSTATE_INVALID; + dvb_ca_en50221_thread_update_delay(ca); + break; + } + + case DVB_CA_SLOTSTATE_LINKINIT: + if (dvb_ca_en50221_link_init(ca, slot) != 0) { + /* we need this extra check for annoying interfaces + like the budget-av */ + if ((!(ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE)) + && (ca->pub->poll_slot_status)) { + status = ca->pub->poll_slot_status(ca->pub, + slot, 0); + if (!(status + & DVB_CA_EN50221_POLL_CAM_PRESENT)) { + ca->slot_info[slot].slot_state = + DVB_CA_SLOTSTATE_NONE; + dvb_ca_en50221_thread_update_delay(ca); + break; + } + } + + ca->slot_info[slot].timeout = + jiffies + (INIT_TIMEOUT_SECS * HZ); + ca->slot_info[slot].slot_state = + DVB_CA_SLOTSTATE_WAITLINKINIT; + ca->wakeup = 1; + break; + } + + if (ca->slot_info[slot].rx_buffer.data == NULL) { + rxbuf = vmalloc(RX_BUFFER_SIZE); + if (rxbuf == NULL) { + pr_error("dvb_ca adapter %d: ", + ca->dvbdev->adapter->num); + pr_error("Unable to allocate CAM rx buffer\n"); + ca->slot_info[slot].slot_state = + DVB_CA_SLOTSTATE_INVALID; + dvb_ca_en50221_thread_update_delay(ca); + break; + } + dvb_ringbuffer_init(&ca->slot_info[slot].rx_buffer, + rxbuf, RX_BUFFER_SIZE); + } + + ca->pub->slot_ts_enable(ca->pub, slot); + ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_RUNNING; + dvb_ca_en50221_thread_update_delay(ca); + dprintk("%d: DVB CAM Initialised successfully\n", + ca->dvbdev->adapter->num); + break; + + case DVB_CA_SLOTSTATE_RUNNING: + if (!ca->open) + break; + + pktcount = 0; + while ((status = dvb_ca_en50221_read_data(ca, slot, NULL, 0)) + > 0) { + if (!ca->open) + break; + + /* if a CAMCHANGE occurred at some point, + do not do any more processing of this slot */ + if (dvb_ca_en50221_check_camstatus(ca, slot)) { + /* we dont want to sleep on the next iteration + so we can handle the cam change*/ + ca->wakeup = 1; + break; + } + + /* check if we've hit our limit this time */ + if (++pktcount >= MAX_RX_PACKETS_PER_ITERATION) { + /*dont sleep; + there is likely to be more data to read*/ + ca->wakeup = 1; + break; + } + } + break; + } + + mutex_unlock(&ca->slot_info[slot].slot_lock); + return 0; +} + + +/** + * Kernel thread which monitors CA slots for CAM changes, + * and performs data transfers. + */ +static int dvb_ca_en50221_thread(void *data) +{ + struct dvb_ca_private *ca = data; + int slot; + + dprintk(" %s\n", __func__); + /* choose the correct initial delay */ + dvb_ca_en50221_thread_update_delay(ca); + + /* main loop */ + while (!kthread_should_stop()) { + /* sleep for a bit */ + if (!ca->wakeup) { + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(ca->delay); + if (kthread_should_stop()) + return 0; + } + ca->wakeup = 0; + + /* go through all the slots processing them */ + for (slot = 0; slot < ca->slot_count; slot++) + dvb_ca_en50221_slot_process(ca, slot); + } + + return 0; +} + + + +/* ************************************************************************** */ +/* EN50221 IO interface functions */ + +/** + * Real ioctl implementation. + * NOTE: CA_SEND_MSG/CA_GET_MSG ioctls have userspace buffers passed to them. + * + * @param inode Inode concerned. + * @param file File concerned. + * @param cmd IOCTL command. + * @param arg Associated argument. + * + * @return 0 on success, <0 on error. + */ +static int dvb_ca_en50221_io_do_ioctl(struct file *file, + unsigned int cmd, void *parg) +{ + struct dvb_device *dvbdev = file->private_data; + struct dvb_ca_private *ca = dvbdev->priv; + int err = 0; + int slot; + + if (mutex_lock_interruptible(&ca->ioctl_mutex)) { + pr_error("ci lock interrupt error\r\n"); + return -ERESTARTSYS; + } + + switch (cmd) { + case CA_RESET: + dprintk("ci reset---\r\n"); + for (slot = 0; slot < ca->slot_count; slot++) { + mutex_lock(&ca->slot_info[slot].slot_lock); + if (ca->slot_info[slot].slot_state + == DVB_CA_SLOTSTATE_NONE) + goto next; + dvb_ca_en50221_slot_shutdown(ca, slot); + if (ca->flags + & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE) + dvb_ca_en50221_cimax_camchange_irq( + ca->pub, + slot, + DVB_CA_EN50221_CAMCHANGE_INSERTED); +next: + mutex_unlock(&ca->slot_info[slot].slot_lock); + } + ca->next_read_slot = 0; + dvb_ca_en50221_thread_wakeup(ca); + break; + + case CA_GET_CAP: { + struct ca_caps *caps = parg; + + caps->slot_num = ca->slot_count; + caps->slot_type = CA_CI_LINK; + caps->descr_num = 0; + caps->descr_type = 0; + break; + } + + case CA_GET_SLOT_INFO: { + struct ca_slot_info *info = parg; + + if ((info->num > ca->slot_count) || (info->num < 0)) { + err = -EINVAL; + pr_error("info num error :%d\r\n", info->num); + goto out_unlock; + } + + info->type = CA_CI_LINK; + info->flags = 0; + if ((ca->slot_info[info->num].slot_state + != DVB_CA_SLOTSTATE_NONE) + && (ca->slot_info[info->num].slot_state + != DVB_CA_SLOTSTATE_INVALID)) { + info->flags = CA_CI_MODULE_PRESENT; + } + if (ca->slot_info[info->num].slot_state + == DVB_CA_SLOTSTATE_RUNNING) { + info->flags |= CA_CI_MODULE_READY; + } + break; + } + + default: + pr_error("Invalid cmd :%d\r\n", cmd); + err = -EINVAL; + break; + } + +out_unlock: + mutex_unlock(&ca->ioctl_mutex); + return err; +} + + +static int dvb_usercopy__(struct file *file, + unsigned int cmd, unsigned long arg, + int (*func)(struct file *file, + unsigned int cmd, void *arg)) +{ + char sbuf[128]; + void *mbuf = NULL; + void *parg = NULL; + int err = -EINVAL; + + /* Copy arguments into temp kernel buffer */ + switch (_IOC_DIR(cmd)) { + case _IOC_NONE: + /* + * For this command, the pointer is actually an integer + * argument. + */ + parg = (void *) arg; + break; + case _IOC_READ: /* some v4l ioctls are marked wrong ... */ + case _IOC_WRITE: + case (_IOC_WRITE | _IOC_READ): + if (_IOC_SIZE(cmd) <= sizeof(sbuf)) { + parg = sbuf; + } else { + /* too big to allocate from stack */ + mbuf = kmalloc(_IOC_SIZE(cmd), GFP_KERNEL); + if (NULL == mbuf) + return -ENOMEM; + parg = mbuf; + } + + err = -EFAULT; + if (copy_from_user(parg, (void __user *)arg, _IOC_SIZE(cmd))) + goto out; + break; + } + + /* call driver */ + if ((err = func(file, cmd, parg)) == -ENOIOCTLCMD) + err = -ENOTTY; + + if (err < 0) + goto out; + + /* Copy results into user buffer */ + switch (_IOC_DIR(cmd)) + { + case _IOC_READ: + case (_IOC_WRITE | _IOC_READ): + if (copy_to_user((void __user *)arg, parg, _IOC_SIZE(cmd))) + err = -EFAULT; + break; + } + +out: + kfree(mbuf); + return err; +} + + + +/** + * Wrapper for ioctl implementation. + * + * @param inode Inode concerned. + * @param file File concerned. + * @param cmd IOCTL command. + * @param arg Associated argument. + * + * @return 0 on success, <0 on error. + */ +static long dvb_ca_en50221_io_ioctl(struct file *file, + unsigned int cmd, unsigned long arg) +{ + return dvb_usercopy__(file, cmd, arg, dvb_ca_en50221_io_do_ioctl); +} + + +/** + * Implementation of write() syscall. + * + * @param file File structure. + * @param buf Source buffer. + * @param count Size of source buffer. + * @param ppos Position in file (ignored). + * + * @return Number of bytes read, or <0 on error. + */ +static ssize_t dvb_ca_en50221_io_write(struct file *file, + const char __user *buf, size_t count, loff_t *ppos) +{ + struct dvb_device *dvbdev = file->private_data; + struct dvb_ca_private *ca = dvbdev->priv; + u8 slot, connection_id; + int status; + u8 *fragbuf = ca->wbuf; + int fragpos = 0; + int fraglen; + unsigned long timeout; + int written; + + /* dprintk("%s\n", __func__); */ + + /* Incoming packet has a 2 byte header. + hdr[0] = slot_id, hdr[1] = connection_id */ + if (count < 2) + return -EINVAL; + + /* extract slot & connection id */ + if (copy_from_user(&slot, buf, 1)) + return -EFAULT; + if (copy_from_user(&connection_id, buf + 1, 1)) + return -EFAULT; + buf += 2; + count -= 2; + + if (slot >= ca->slot_count) + return -EFAULT; + /* check if the slot is actually running */ + if (ca->slot_info[slot].slot_state != DVB_CA_SLOTSTATE_RUNNING) + return -EINVAL; + + /* fragment the packets & store in the buffer */ + while (fragpos < count) { + fraglen = ca->slot_info[slot].link_buf_size - 2; + if (fraglen < 0) + break; + if (fraglen > dvb_ca_en50221_link_size - 2) + fraglen = dvb_ca_en50221_link_size - 2; + if ((count - fragpos) < fraglen) + fraglen = count - fragpos; + + fragbuf[0] = connection_id; + fragbuf[1] = ((fragpos + fraglen) < count) ? 0x80 : 0x00; + status = copy_from_user(fragbuf + 2, buf + fragpos, fraglen); + if (status) { + status = -EFAULT; + goto exit; + } + + timeout = jiffies + HZ / 2; + written = 0; + while (!time_after(jiffies, timeout)) { + /* check the CAM hasn't been removed/reset + in the meantime */ + if (ca->slot_info[slot].slot_state + != DVB_CA_SLOTSTATE_RUNNING) { + status = -EIO; + goto exit; + } + + mutex_lock(&ca->slot_info[slot].slot_lock); + status = dvb_ca_en50221_write_data(ca, + slot, fragbuf, fraglen + 2); + mutex_unlock(&ca->slot_info[slot].slot_lock); + if (status == (fraglen + 2)) { + written = 1; + break; + } + if (status != -EAGAIN) + goto exit; + + msleep(20); + } + if (!written) { + status = -EIO; + goto exit; + } + + fragpos += fraglen; + } + status = count + 2; + +exit: + return status; +} + + +/** + * Condition for waking up in dvb_ca_en50221_io_read_condition + */ +static int dvb_ca_en50221_io_read_condition(struct dvb_ca_private *ca, + int *result, int *_slot) +{ + int slot; + int slot_count = 0; + int idx; + size_t fraglen; + int connection_id = -1; + int found = 0; + u8 hdr[2]; + + slot = ca->next_read_slot; + while ((slot_count < ca->slot_count) && (!found)) { + if (ca->slot_info[slot].slot_state != DVB_CA_SLOTSTATE_RUNNING) + goto nextslot; + + if (ca->slot_info[slot].rx_buffer.data == NULL) + return 0; + + idx = dvb_ringbuffer_pkt_next(&ca->slot_info[slot].rx_buffer, + -1, &fraglen); + while (idx != -1) { + dvb_ringbuffer_pkt_read(&ca->slot_info[slot].rx_buffer, + idx, 0, hdr, 2); + if (connection_id == -1) + connection_id = hdr[0]; + if ((hdr[0] == connection_id) + && ((hdr[1] & 0x80) == 0)) { + *_slot = slot; + found = 1; + break; + } + + idx = dvb_ringbuffer_pkt_next( + &ca->slot_info[slot].rx_buffer, + idx, + &fraglen); + } + +nextslot: + slot = (slot + 1) % ca->slot_count; + slot_count++; + } + + ca->next_read_slot = slot; + return found; +} + + +/** + * Implementation of read() syscall. + * + * @param file File structure. + * @param buf Destination buffer. + * @param count Size of destination buffer. + * @param ppos Position in file (ignored). + * + * @return Number of bytes read, or <0 on error. + */ +static ssize_t dvb_ca_en50221_io_read(struct file *file, char __user *buf, + size_t count, loff_t *ppos) +{ + struct dvb_device *dvbdev = file->private_data; + struct dvb_ca_private *ca = dvbdev->priv; + int status; + int result = 0; + u8 hdr[2]; + int slot; + int connection_id = -1; + size_t idx, idx2; + int last_fragment = 0; + size_t fraglen; + int pktlen; + int dispose = 0; + + /* dprintk("%s\n", __func__); */ + + /* Outgoing packet has a 2 byte header. + hdr[0] = slot_id, hdr[1] = connection_id */ + if (count < 2) + return -EINVAL; + + /* wait for some data */ + status = dvb_ca_en50221_io_read_condition(ca, &result, &slot); + if (status == 0) { + /* if we're in nonblocking mode, exit immediately */ + if (file->f_flags & O_NONBLOCK) + return -EWOULDBLOCK; + + /* wait for some data */ + status = wait_event_interruptible(ca->wait_queue, + dvb_ca_en50221_io_read_condition + (ca, &result, &slot)); + } + if ((status < 0) || (result < 0)) { + if (result) + return result; + return status; + } + + idx = dvb_ringbuffer_pkt_next(&ca->slot_info[slot].rx_buffer, + -1, &fraglen); + pktlen = 2; + do { + if (idx == -1) { + pr_error("dvb_ca adapter %d: ", + ca->dvbdev->adapter->num); + pr_error("BUG: read packet ended"); + pr_error("before last_fragment encountered\n"); + status = -EIO; + goto exit; + } + + dvb_ringbuffer_pkt_read(&ca->slot_info[slot].rx_buffer, + idx, 0, hdr, 2); + if (connection_id == -1) + connection_id = hdr[0]; + if (hdr[0] == connection_id) { + if (pktlen < count) { + if ((pktlen + fraglen - 2) > count) + fraglen = count - pktlen; + else + fraglen -= 2; + + status = dvb_ringbuffer_pkt_read_user( + &ca->slot_info[slot].rx_buffer, + idx, + 2, + buf + pktlen, + fraglen); + if (status < 0) + goto exit; + pktlen += fraglen; + } + + if ((hdr[1] & 0x80) == 0) + last_fragment = 1; + dispose = 1; + } + + idx2 = dvb_ringbuffer_pkt_next(&ca->slot_info[slot].rx_buffer, + idx, &fraglen); + if (dispose) + dvb_ringbuffer_pkt_dispose( + &ca->slot_info[slot].rx_buffer, idx); + idx = idx2; + dispose = 0; + } while (!last_fragment); + + hdr[0] = slot; + hdr[1] = connection_id; + status = copy_to_user(buf, hdr, 2); + if (status) { + status = -EFAULT; + goto exit; + } + status = pktlen; + +exit: + return status; +} + + +/** + * Implementation of file open syscall. + * + * @param inode Inode concerned. + * @param file File concerned. + * + * @return 0 on success, <0 on failure. + */ +static int dvb_ca_en50221_io_open(struct inode *inode, struct file *file) +{ + struct dvb_device *dvbdev = file->private_data; + struct dvb_ca_private *ca = dvbdev->priv; + int err; + int i; + + dprintk("%s\n", __func__); + + if (!try_module_get(ca->pub->owner)) + return -EIO; + + err = dvb_generic_open(inode, file); + if (err < 0) { + module_put(ca->pub->owner); + return err; + } + + for (i = 0; i < ca->slot_count; i++) { + + if (ca->slot_info[i].slot_state == DVB_CA_SLOTSTATE_RUNNING) { + if (ca->slot_info[i].rx_buffer.data != NULL) { + /* it is safe to call this here without locks + because ca->open == 0. + Data is not read in this case */ + dvb_ringbuffer_flush( + &ca->slot_info[i].rx_buffer); + } + } + } + + ca->open = 1; + dvb_ca_en50221_thread_update_delay(ca); + dvb_ca_en50221_thread_wakeup(ca); + + return 0; +} + + +/** + * Implementation of file close syscall. + * + * @param inode Inode concerned. + * @param file File concerned. + * + * @return 0 on success, <0 on failure. + */ +static int dvb_ca_en50221_io_release(struct inode *inode, struct file *file) +{ + struct dvb_device *dvbdev = file->private_data; + struct dvb_ca_private *ca = dvbdev->priv; + int err; + + dprintk("%s\n", __func__); + + /* mark the CA device as closed */ + ca->open = 0; + dvb_ca_en50221_thread_update_delay(ca); + + err = dvb_generic_release(inode, file); + + module_put(ca->pub->owner); + + return err; +} + + +/** + * Implementation of poll() syscall. + * + * @param file File concerned. + * @param wait poll wait table. + * + * @return Standard poll mask. + */ +static unsigned int dvb_ca_en50221_io_poll(struct file *file, poll_table *wait) +{ + struct dvb_device *dvbdev = file->private_data; + struct dvb_ca_private *ca = dvbdev->priv; + unsigned int mask = 0; + int slot; + int result = 0; + + /* dprintk("%s\n", __func__); */ + + if (dvb_ca_en50221_io_read_condition(ca, &result, &slot) == 1) + mask |= POLLIN; + + /* if there is something, return now */ + if (mask) + return mask; + + /* wait for something to happen */ + poll_wait(file, &ca->wait_queue, wait); + + if (dvb_ca_en50221_io_read_condition(ca, &result, &slot) == 1) + mask |= POLLIN; + + return mask; +} +EXPORT_SYMBOL(dvb_ca_en50221_cimax_init); + +#ifdef CONFIG_COMPAT +static long dvb_ca_en50221_compat_ioctl(struct file *filp, + unsigned int cmd, unsigned long args) +{ + unsigned long ret; + + args = (unsigned long)compat_ptr(args); + ret = dvb_ca_en50221_io_ioctl(filp, cmd, args); + return ret; +} +#endif +static const struct file_operations dvb_ca_fops = { + .owner = THIS_MODULE, + .read = dvb_ca_en50221_io_read, + .write = dvb_ca_en50221_io_write, + .unlocked_ioctl = dvb_ca_en50221_io_ioctl, + .open = dvb_ca_en50221_io_open, + .release = dvb_ca_en50221_io_release, + .poll = dvb_ca_en50221_io_poll, + .llseek = noop_llseek, +#ifdef CONFIG_COMPAT + .compat_ioctl = dvb_ca_en50221_compat_ioctl, +#endif +}; + +static struct dvb_device dvbdev_ca = { + .priv = NULL, + .users = 1, + .readers = 1, + .writers = 1, + .fops = &dvb_ca_fops, +}; + + +/* ************************************************************************** */ +/* Initialisation/shutdown functions */ + + +/** + * Initialise a new DVB CA EN50221 CIMAX interface device. + * + * @param dvb_adapter DVB adapter to attach the new CA device to. + * @param ca The dvb_ca instance. + * @param flags Flags describing the CA device (DVB_CA_FLAG_*). + * @param slot_count Number of slots supported. + * + * @return 0 on success, nonzero on failure + */ +int dvb_ca_en50221_cimax_init(struct dvb_adapter *dvb_adapter, + struct dvb_ca_en50221_cimax *pubca, + int flags, int slot_count) +{ + int ret; + struct dvb_ca_private *ca = NULL; + int i; + + dprintk("%s\n", __func__); + + if (slot_count < 1) + return -EINVAL; + + /* initialise the system data */ + ca = kzalloc(sizeof(struct dvb_ca_private), GFP_KERNEL); + if (ca == NULL) { + ret = -ENOMEM; + goto error; + } + ca->pub = pubca; + ca->flags = flags; + ca->slot_count = slot_count; + ca->slot_info = + kcalloc(slot_count, sizeof(struct dvb_ca_slot), GFP_KERNEL); + if (ca->slot_info == NULL) { + ret = -ENOMEM; + goto error; + } + init_waitqueue_head(&ca->wait_queue); + ca->open = 0; + ca->wakeup = 0; + ca->next_read_slot = 0; + ca->rbuf = kcalloc(HOST_LINK_BUF_SIZE, 1, GFP_KERNEL); + ca->wbuf = kcalloc(HOST_LINK_BUF_SIZE, 1, GFP_KERNEL); + if (ca->rbuf == NULL || ca->wbuf == NULL) { + ret = -ENOMEM; + goto error; + } + pubca->private = ca; + + /* register the DVB device */ + ret = dvb_register_device(dvb_adapter, + &ca->dvbdev, &dvbdev_ca, ca, DVB_DEVICE_CA, 0); + if (ret) + goto error; + + /* now initialise each slot */ + for (i = 0; i < slot_count; i++) { + memset(&ca->slot_info[i], 0, sizeof(struct dvb_ca_slot)); + ca->slot_info[i].slot_state = DVB_CA_SLOTSTATE_NONE; + atomic_set(&ca->slot_info[i].camchange_count, 0); + ca->slot_info[i].camchange_type = + DVB_CA_EN50221_CAMCHANGE_REMOVED; + mutex_init(&ca->slot_info[i].slot_lock); + } + + mutex_init(&ca->ioctl_mutex); + + if (signal_pending(current)) { + ret = -EINTR; + goto error; + } + mb();/*original*/ + + /* create a kthread for monitoring this CA device */ + ca->thread = kthread_run(dvb_ca_en50221_thread, ca, "kdvb-ca-%i:%i", + ca->dvbdev->adapter->num, ca->dvbdev->id); + if (IS_ERR(ca->thread)) { + ret = PTR_ERR(ca->thread); + printk("dvb_ca_init: failed to start kernel_thread (%d)\n", + ret); + goto error; + } + return 0; + +error: + if (ca != NULL) { + if (ca->dvbdev != NULL) + dvb_unregister_device(ca->dvbdev); + kfree(ca->slot_info); + kfree(ca->rbuf); + kfree(ca->wbuf); + kfree(ca); + } + pubca->private = NULL; + return ret; +} +EXPORT_SYMBOL(dvb_ca_en50221_cimax_release); + + + +/** + * Release a DVB CA EN50221 CIMAX interface device. + * + * @param ca_dev The dvb_struct device_s instance for the CA device. + * @param ca The associated dvb_ca instance. + */ +void dvb_ca_en50221_cimax_release(struct dvb_ca_en50221_cimax *pubca) +{ + struct dvb_ca_private *ca = pubca->private; + int i; + + dprintk("%s\n", __func__); + + /* shutdown the thread if there was one */ + kthread_stop(ca->thread); + + for (i = 0; i < ca->slot_count; i++) { + dvb_ca_en50221_slot_shutdown(ca, i); + vfree(ca->slot_info[i].rx_buffer.data); + } + kfree(ca->slot_info); + kfree(ca->rbuf); + kfree(ca->wbuf); + dvb_unregister_device(ca->dvbdev); + kfree(ca); + pubca->private = NULL; +} diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/dvb_ca_en50221_cimax.h b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/dvb_ca_en50221_cimax.h new file mode 100644 index 000000000000..e2ebde6cbc62 --- /dev/null +++ b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/dvb_ca_en50221_cimax.h @@ -0,0 +1,144 @@ +/* + * dvb_ca_cimax.h: generic DVB functions for EN50221 CA CIMAX interfaces + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 + * 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 _DVB_CA_EN50221_CIMAX_H_ +#define _DVB_CA_EN50221_CIMAX_H_ + +#include +#include + +#include "dvbdev.h" + +#define DVB_CA_EN50221_POLL_CAM_PRESENT 1 +#define DVB_CA_EN50221_POLL_CAM_CHANGED 2 +#define DVB_CA_EN50221_POLL_CAM_READY 4 + +#define DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE 1 +#define DVB_CA_EN50221_FLAG_IRQ_FR 2 +#define DVB_CA_EN50221_FLAG_IRQ_DA 4 + +#define DVB_CA_EN50221_CAMCHANGE_REMOVED 0 +#define DVB_CA_EN50221_CAMCHANGE_INSERTED 1 + +#define DVB_CA_EN50221_CAP_IRQ 1 + +/* Structure describing a CA interface */ +struct dvb_ca_en50221_cimax { + + /* the module owning this structure */ + struct module *owner; + + /* NOTE: the read_*, write_* and poll_slot_status functions will be + * called for different slots concurrently and need to use locks where + * and if appropriate. There will be no concurrent access to one slot. + */ + + /* functions for accessing attribute memory on the CAM */ + int (*read_cis)(struct dvb_ca_en50221_cimax *ca, + int slot, u8 *buf, int size); + int (*write_cor)(struct dvb_ca_en50221_cimax *ca, + int slot, int address, u8 *buf); + /*return the final size or -1 for error*/ + int (*negotiate)(struct dvb_ca_en50221_cimax *ca, int slot, int size); + + /* functions for accessing the control interface on the CAM */ + int (*read_lpdu)(struct dvb_ca_en50221_cimax *ca, + int slot, u8 *buf, int size); + int (*write_lpdu)(struct dvb_ca_en50221_cimax *ca, + int slot, u8 *buf, int size); + + int (*cam_reset)(struct dvb_ca_en50221_cimax *ca, int slot); + int (*read_cam_status)(struct dvb_ca_en50221_cimax *ca, int slot); + int (*get_capbility)(struct dvb_ca_en50221_cimax *ca, int slot); + + /* Functions for controlling slots */ + int (*slot_reset)(struct dvb_ca_en50221_cimax *ca, int slot); + int (*slot_shutdown)(struct dvb_ca_en50221_cimax *ca, int slot); + int (*slot_ts_enable)(struct dvb_ca_en50221_cimax *ca, int slot); + + /* + * Poll slot status. + * Only necessary if DVB_CA_FLAG_EN50221_IRQ_CAMCHANGE is not set + */ + int (*poll_slot_status)(struct dvb_ca_en50221_cimax *ca, + int slot, int open); + + /* private data, used by caller */ + void *data; + + /* Opaque data used by the dvb_ca core. Do not modify! */ + void *private; +}; + + + + +/* ************************************************************************* */ +/* Functions for reporting IRQ events */ + +/** + * A CAMCHANGE IRQ has occurred. + * + * @param ca CA instance. + * @param slot Slot concerned. + * @param change_type One of the DVB_CA_CAMCHANGE_* values + */ +void dvb_ca_en50221_cimax_camchange_irq(struct dvb_ca_en50221_cimax *pubca, + int slot, int change_type); + +/** + * A CAMREADY IRQ has occurred. + * + * @param ca CA instance. + * @param slot Slot concerned. + */ +void dvb_ca_en50221_cimax_camready_irq(struct dvb_ca_en50221_cimax *pubca, + int slot); + +/** + * An FR or a DA IRQ has occurred. + * + * @param ca CA instance. + * @param slot Slot concerned. + */ +void dvb_ca_en50221_cimax_frda_irq(struct dvb_ca_en50221_cimax *ca, int slot); + + + +/* ************************************************************************** */ +/* Initialisation/shutdown functions */ + +/** + * Initialise a new DVB CA device. + * + * @param dvb_adapter DVB adapter to attach the new CA device to. + * @param ca The dvb_ca instance. + * @param flags Flags describing the CA device (DVB_CA_EN50221_FLAG_*). + * @param slot_count Number of slots supported. + * + * @return 0 on success, nonzero on failure + */ +extern int dvb_ca_en50221_cimax_init(struct dvb_adapter *dvb_adapter, + struct dvb_ca_en50221_cimax *ca, int flags, int slot_count); + +/** + * Release a DVB CA device. + * + * @param ca The associated dvb_ca instance. + */ +extern void dvb_ca_en50221_cimax_release(struct dvb_ca_en50221_cimax *ca); + + + +#endif diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/dvb_ringbuffer.c b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/dvb_ringbuffer.c new file mode 100644 index 000000000000..fa5c16335909 --- /dev/null +++ b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/dvb_ringbuffer.c @@ -0,0 +1,381 @@ +/* + * + * dvb_ringbuffer.c: ring buffer implementation for the dvb driver + * + * Copyright (C) 2003 Oliver Endriss + * Copyright (C) 2004 Andrew de Quincey + * + * based on code originally found in av7110.c & dvb_ci.c: + * Copyright (C) 1999-2003 Ralph Metzler + * & Marcus Metzler for convergence integrated media GmbH + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 + * 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + + + +#include +#include +#include +#include +#include +#include + +#include "dvb_ringbuffer.h" + +#define PKT_READY 0 +#define PKT_DISPOSED 1 + + +void dvb_ringbuffer_init(struct dvb_ringbuffer *rbuf, void *data, size_t len) +{ + rbuf->pread=rbuf->pwrite=0; + rbuf->data=data; + rbuf->size=len; + rbuf->error=0; + + init_waitqueue_head(&rbuf->queue); + + spin_lock_init(&(rbuf->lock)); +} + + + +int dvb_ringbuffer_empty(struct dvb_ringbuffer *rbuf) +{ + /* smp_load_acquire() to load write pointer on reader side + * this pairs with smp_store_release() in dvb_ringbuffer_write(), + * dvb_ringbuffer_write_user(), or dvb_ringbuffer_reset() + * + * for memory barriers also see Documentation/circular-buffers.txt + */ + return (rbuf->pread == smp_load_acquire(&rbuf->pwrite)); +} + + + +ssize_t dvb_ringbuffer_free(struct dvb_ringbuffer *rbuf) +{ + ssize_t free; + + /* ACCESS_ONCE() to load read pointer on writer side + * this pairs with smp_store_release() in dvb_ringbuffer_read(), + * dvb_ringbuffer_read_user(), dvb_ringbuffer_flush(), + * or dvb_ringbuffer_reset() + */ + free = ACCESS_ONCE(rbuf->pread) - rbuf->pwrite; + if (free <= 0) + free += rbuf->size; + return free-1; +} + + + +ssize_t dvb_ringbuffer_avail(struct dvb_ringbuffer *rbuf) +{ + ssize_t avail; + + /* smp_load_acquire() to load write pointer on reader side + * this pairs with smp_store_release() in dvb_ringbuffer_write(), + * dvb_ringbuffer_write_user(), or dvb_ringbuffer_reset() + */ + avail = smp_load_acquire(&rbuf->pwrite) - rbuf->pread; + if (avail < 0) + avail += rbuf->size; + return avail; +} + + + +void dvb_ringbuffer_flush(struct dvb_ringbuffer *rbuf) +{ + /* dvb_ringbuffer_flush() counts as read operation + * smp_load_acquire() to load write pointer + * smp_store_release() to update read pointer, this ensures that the + * correct pointer is visible for subsequent dvb_ringbuffer_free() + * calls on other cpu cores + */ + smp_store_release(&rbuf->pread, smp_load_acquire(&rbuf->pwrite)); + rbuf->error = 0; +} +//EXPORT_SYMBOL(dvb_ringbuffer_flush); + +void dvb_ringbuffer_reset(struct dvb_ringbuffer *rbuf) +{ + /* dvb_ringbuffer_reset() counts as read and write operation + * smp_store_release() to update read pointer + */ + smp_store_release(&rbuf->pread, 0); + /* smp_store_release() to update write pointer */ + smp_store_release(&rbuf->pwrite, 0); + rbuf->error = 0; +} + +void dvb_ringbuffer_flush_spinlock_wakeup(struct dvb_ringbuffer *rbuf) +{ + unsigned long flags; + + spin_lock_irqsave(&rbuf->lock, flags); + dvb_ringbuffer_flush(rbuf); + spin_unlock_irqrestore(&rbuf->lock, flags); + + wake_up(&rbuf->queue); +} + +ssize_t dvb_ringbuffer_read_user(struct dvb_ringbuffer *rbuf, u8 __user *buf, size_t len) +{ + size_t todo = len; + size_t split; + + split = (rbuf->pread + len > rbuf->size) ? rbuf->size - rbuf->pread : 0; + if (split > 0) { + if (copy_to_user(buf, rbuf->data+rbuf->pread, split)) + return -EFAULT; + buf += split; + todo -= split; + /* smp_store_release() for read pointer update to ensure + * that buf is not overwritten until read is complete, + * this pairs with ACCESS_ONCE() in dvb_ringbuffer_free() + */ + smp_store_release(&rbuf->pread, 0); + } + if (copy_to_user(buf, rbuf->data+rbuf->pread, todo)) + return -EFAULT; + + /* smp_store_release() to update read pointer, see above */ + smp_store_release(&rbuf->pread, (rbuf->pread + todo) % rbuf->size); + + return len; +} + +void dvb_ringbuffer_read(struct dvb_ringbuffer *rbuf, u8 *buf, size_t len) +{ + size_t todo = len; + size_t split; + + split = (rbuf->pread + len > rbuf->size) ? rbuf->size - rbuf->pread : 0; + if (split > 0) { + memcpy(buf, rbuf->data+rbuf->pread, split); + buf += split; + todo -= split; + /* smp_store_release() for read pointer update to ensure + * that buf is not overwritten until read is complete, + * this pairs with ACCESS_ONCE() in dvb_ringbuffer_free() + */ + smp_store_release(&rbuf->pread, 0); + } + memcpy(buf, rbuf->data+rbuf->pread, todo); + + /* smp_store_release() to update read pointer, see above */ + smp_store_release(&rbuf->pread, (rbuf->pread + todo) % rbuf->size); +} + + +ssize_t dvb_ringbuffer_write(struct dvb_ringbuffer *rbuf, const u8 *buf, size_t len) +{ + size_t todo = len; + size_t split; + + split = (rbuf->pwrite + len > rbuf->size) ? rbuf->size - rbuf->pwrite : 0; + + if (split > 0) { + memcpy(rbuf->data+rbuf->pwrite, buf, split); + buf += split; + todo -= split; + /* smp_store_release() for write pointer update to ensure that + * written data is visible on other cpu cores before the pointer + * update, this pairs with smp_load_acquire() in + * dvb_ringbuffer_empty() or dvb_ringbuffer_avail() + */ + smp_store_release(&rbuf->pwrite, 0); + } + memcpy(rbuf->data+rbuf->pwrite, buf, todo); + /* smp_store_release() for write pointer update, see above */ + smp_store_release(&rbuf->pwrite, (rbuf->pwrite + todo) % rbuf->size); + + return len; +} + +ssize_t dvb_ringbuffer_write_user(struct dvb_ringbuffer *rbuf, + const u8 __user *buf, size_t len) +{ + int status; + size_t todo = len; + size_t split; + + split = (rbuf->pwrite + len > rbuf->size) ? rbuf->size - rbuf->pwrite : 0; + + if (split > 0) { + status = copy_from_user(rbuf->data+rbuf->pwrite, buf, split); + if (status) + return len - todo; + buf += split; + todo -= split; + /* smp_store_release() for write pointer update to ensure that + * written data is visible on other cpu cores before the pointer + * update, this pairs with smp_load_acquire() in + * dvb_ringbuffer_empty() or dvb_ringbuffer_avail() + */ + smp_store_release(&rbuf->pwrite, 0); + } + status = copy_from_user(rbuf->data+rbuf->pwrite, buf, todo); + if (status) + return len - todo; + /* smp_store_release() for write pointer update, see above */ + smp_store_release(&rbuf->pwrite, (rbuf->pwrite + todo) % rbuf->size); + + return len; +} + +ssize_t dvb_ringbuffer_pkt_write(struct dvb_ringbuffer *rbuf, u8* buf, size_t len) +{ + int status; + ssize_t oldpwrite = rbuf->pwrite; + + DVB_RINGBUFFER_WRITE_BYTE(rbuf, len >> 8); + DVB_RINGBUFFER_WRITE_BYTE(rbuf, len & 0xff); + DVB_RINGBUFFER_WRITE_BYTE(rbuf, PKT_READY); + status = dvb_ringbuffer_write(rbuf, buf, len); + + if (status < 0) rbuf->pwrite = oldpwrite; + return status; +} + +ssize_t dvb_ringbuffer_pkt_read_user(struct dvb_ringbuffer *rbuf, size_t idx, + int offset, u8 __user *buf, size_t len) +{ + size_t todo; + size_t split; + size_t pktlen; + + pktlen = rbuf->data[idx] << 8; + pktlen |= rbuf->data[(idx + 1) % rbuf->size]; + if (offset > pktlen) return -EINVAL; + if ((offset + len) > pktlen) len = pktlen - offset; + + idx = (idx + DVB_RINGBUFFER_PKTHDRSIZE + offset) % rbuf->size; + todo = len; + split = ((idx + len) > rbuf->size) ? rbuf->size - idx : 0; + if (split > 0) { + if (copy_to_user(buf, rbuf->data+idx, split)) + return -EFAULT; + buf += split; + todo -= split; + idx = 0; + } + if (copy_to_user(buf, rbuf->data+idx, todo)) + return -EFAULT; + + return len; +} + +ssize_t dvb_ringbuffer_pkt_read(struct dvb_ringbuffer *rbuf, size_t idx, + int offset, u8* buf, size_t len) +{ + size_t todo; + size_t split; + size_t pktlen; + + pktlen = rbuf->data[idx] << 8; + pktlen |= rbuf->data[(idx + 1) % rbuf->size]; + if (offset > pktlen) return -EINVAL; + if ((offset + len) > pktlen) len = pktlen - offset; + + idx = (idx + DVB_RINGBUFFER_PKTHDRSIZE + offset) % rbuf->size; + todo = len; + split = ((idx + len) > rbuf->size) ? rbuf->size - idx : 0; + if (split > 0) { + memcpy(buf, rbuf->data+idx, split); + buf += split; + todo -= split; + idx = 0; + } + memcpy(buf, rbuf->data+idx, todo); + return len; +} + +void dvb_ringbuffer_pkt_dispose(struct dvb_ringbuffer *rbuf, size_t idx) +{ + size_t pktlen; + + rbuf->data[(idx + 2) % rbuf->size] = PKT_DISPOSED; + + // clean up disposed packets + while(dvb_ringbuffer_avail(rbuf) > DVB_RINGBUFFER_PKTHDRSIZE) { + if (DVB_RINGBUFFER_PEEK(rbuf, 2) == PKT_DISPOSED) { + pktlen = DVB_RINGBUFFER_PEEK(rbuf, 0) << 8; + pktlen |= DVB_RINGBUFFER_PEEK(rbuf, 1); + DVB_RINGBUFFER_SKIP(rbuf, pktlen + DVB_RINGBUFFER_PKTHDRSIZE); + } else { + // first packet is not disposed, so we stop cleaning now + break; + } + } +} + +ssize_t dvb_ringbuffer_pkt_next(struct dvb_ringbuffer *rbuf, size_t idx, size_t* pktlen) +{ + int consumed; + int curpktlen; + int curpktstatus; + + if (idx == -1) { + idx = rbuf->pread; + } else { + curpktlen = rbuf->data[idx] << 8; + curpktlen |= rbuf->data[(idx + 1) % rbuf->size]; + idx = (idx + curpktlen + DVB_RINGBUFFER_PKTHDRSIZE) % rbuf->size; + } + + consumed = (idx - rbuf->pread) % rbuf->size; + + while((dvb_ringbuffer_avail(rbuf) - consumed) > DVB_RINGBUFFER_PKTHDRSIZE) { + + curpktlen = rbuf->data[idx] << 8; + curpktlen |= rbuf->data[(idx + 1) % rbuf->size]; + curpktstatus = rbuf->data[(idx + 2) % rbuf->size]; + + if (curpktstatus == PKT_READY) { + *pktlen = curpktlen; + return idx; + } + + consumed += curpktlen + DVB_RINGBUFFER_PKTHDRSIZE; + idx = (idx + curpktlen + DVB_RINGBUFFER_PKTHDRSIZE) % rbuf->size; + } + + // no packets available + return -1; +} + + +#if 0 +EXPORT_SYMBOL(dvb_ringbuffer_init); +EXPORT_SYMBOL(dvb_ringbuffer_empty); +EXPORT_SYMBOL(dvb_ringbuffer_free); +EXPORT_SYMBOL(dvb_ringbuffer_avail); +EXPORT_SYMBOL(dvb_ringbuffer_flush_spinlock_wakeup); +EXPORT_SYMBOL(dvb_ringbuffer_read_user); +EXPORT_SYMBOL(dvb_ringbuffer_read); +EXPORT_SYMBOL(dvb_ringbuffer_write); +EXPORT_SYMBOL(dvb_ringbuffer_write_user); +#endif +EXPORT_SYMBOL(dvb_ringbuffer_pkt_read); +EXPORT_SYMBOL(dvb_ringbuffer_pkt_write); +EXPORT_SYMBOL(dvb_ringbuffer_pkt_next); +EXPORT_SYMBOL(dvb_ringbuffer_pkt_dispose); +EXPORT_SYMBOL(dvb_ringbuffer_pkt_read_user); + + diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/dvb_ringbuffer.h b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/dvb_ringbuffer.h new file mode 100644 index 000000000000..bbe94873d44d --- /dev/null +++ b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/dvb_ringbuffer.h @@ -0,0 +1,280 @@ +/* + * + * dvb_ringbuffer.h: ring buffer implementation for the dvb driver + * + * Copyright (C) 2003 Oliver Endriss + * Copyright (C) 2004 Andrew de Quincey + * + * based on code originally found in av7110.c & dvb_ci.c: + * Copyright (C) 1999-2003 Ralph Metzler & Marcus Metzler + * for convergence integrated media GmbH + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 + * 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 Lesser General Public License for more details. + */ + +#ifndef _DVB_RINGBUFFER_H_ +#define _DVB_RINGBUFFER_H_ + +#include +#include + +/** + * struct dvb_ringbuffer - Describes a ring buffer used at DVB framework + * + * @data: Area were the ringbuffer data is written + * @size: size of the ringbuffer + * @pread: next position to read + * @pwrite: next position to write + * @error: used by ringbuffer clients to indicate that an error happened. + * @queue: Wait queue used by ringbuffer clients to indicate when buffer + * was filled + * @lock: Spinlock used to protect the ringbuffer + */ +struct dvb_ringbuffer { + u8 *data; + ssize_t size; + ssize_t pread; + ssize_t pwrite; + int error; + + wait_queue_head_t queue; + spinlock_t lock; +}; + +#define DVB_RINGBUFFER_PKTHDRSIZE 3 + +/** + * dvb_ringbuffer_init - initialize ring buffer, lock and queue + * + * @rbuf: pointer to struct dvb_ringbuffer + * @data: pointer to the buffer where the data will be stored + * @len: bytes from ring buffer into @buf + */ +extern void dvb_ringbuffer_init(struct dvb_ringbuffer *rbuf, void *data, + size_t len); + +/** + * dvb_ringbuffer_empty - test whether buffer is empty + * + * @rbuf: pointer to struct dvb_ringbuffer + */ +extern int dvb_ringbuffer_empty(struct dvb_ringbuffer *rbuf); + +/** + * dvb_ringbuffer_free - returns the number of free bytes in the buffer + * + * @rbuf: pointer to struct dvb_ringbuffer + * + * Return: number of free bytes in the buffer + */ +extern ssize_t dvb_ringbuffer_free(struct dvb_ringbuffer *rbuf); + +/** + * dvb_ringbuffer_avail - returns the number of bytes waiting in the buffer + * + * @rbuf: pointer to struct dvb_ringbuffer + * + * Return: number of bytes waiting in the buffer + */ +extern ssize_t dvb_ringbuffer_avail(struct dvb_ringbuffer *rbuf); + +/** + * dvb_ringbuffer_reset - resets the ringbuffer to initial state + * + * @rbuf: pointer to struct dvb_ringbuffer + * + * Resets the read and write pointers to zero and flush the buffer. + * + * This counts as a read and write operation + */ +extern void dvb_ringbuffer_reset(struct dvb_ringbuffer *rbuf); + +/* + * read routines & macros + */ + +/** + * dvb_ringbuffer_flush - flush buffer + * + * @rbuf: pointer to struct dvb_ringbuffer + */ +extern void dvb_ringbuffer_flush(struct dvb_ringbuffer *rbuf); + +/** + * dvb_ringbuffer_flush_spinlock_wakeup- flush buffer protected by spinlock + * and wake-up waiting task(s) + * + * @rbuf: pointer to struct dvb_ringbuffer + */ +extern void dvb_ringbuffer_flush_spinlock_wakeup(struct dvb_ringbuffer *rbuf); + +/** + * DVB_RINGBUFFER_PEEK - peek at byte @offs in the buffer + * + * @rbuf: pointer to struct dvb_ringbuffer + * @offs: offset inside the ringbuffer + */ +#define DVB_RINGBUFFER_PEEK(rbuf, offs) \ + ((rbuf)->data[((rbuf)->pread + (offs)) % (rbuf)->size]) + +/** + * DVB_RINGBUFFER_SKIP - advance read ptr by @num bytes + * + * @rbuf: pointer to struct dvb_ringbuffer + * @num: number of bytes to advance + */ +#define DVB_RINGBUFFER_SKIP(rbuf, num) {\ + (rbuf)->pread = ((rbuf)->pread + (num)) % (rbuf)->size;\ +} + +/** + * dvb_ringbuffer_read_user - Reads a buffer into an user pointer + * + * @rbuf: pointer to struct dvb_ringbuffer + * @buf: pointer to the buffer where the data will be stored + * @len: bytes from ring buffer into @buf + * + * This variant assumes that the buffer is a memory at the userspace. So, + * it will internally call copy_to_user(). + * + * Return: number of bytes transferred or -EFAULT + */ +extern ssize_t dvb_ringbuffer_read_user(struct dvb_ringbuffer *rbuf, + u8 __user *buf, size_t len); + +/** + * dvb_ringbuffer_read - Reads a buffer into a pointer + * + * @rbuf: pointer to struct dvb_ringbuffer + * @buf: pointer to the buffer where the data will be stored + * @len: bytes from ring buffer into @buf + * + * This variant assumes that the buffer is a memory at the Kernel space + * + * Return: number of bytes transferred or -EFAULT + */ +extern void dvb_ringbuffer_read(struct dvb_ringbuffer *rbuf, + u8 *buf, size_t len); + +/* + * write routines & macros + */ + +/** + * DVB_RINGBUFFER_WRITE_BYTE - write single byte to ring buffer + * + * @rbuf: pointer to struct dvb_ringbuffer + * @byte: byte to write + */ +#define DVB_RINGBUFFER_WRITE_BYTE(rbuf, byte) \ + { (rbuf)->data[(rbuf)->pwrite] = (byte); \ + (rbuf)->pwrite = ((rbuf)->pwrite + 1) % (rbuf)->size; } + +/** + * dvb_ringbuffer_write - Writes a buffer into the ringbuffer + * + * @rbuf: pointer to struct dvb_ringbuffer + * @buf: pointer to the buffer where the data will be read + * @len: bytes from ring buffer into @buf + * + * This variant assumes that the buffer is a memory at the Kernel space + * + * return: number of bytes transferred or -EFAULT + */ +extern ssize_t dvb_ringbuffer_write(struct dvb_ringbuffer *rbuf, const u8 *buf, + size_t len); + +/** + * dvb_ringbuffer_write_user - Writes a buffer received via an user pointer + * + * @rbuf: pointer to struct dvb_ringbuffer + * @buf: pointer to the buffer where the data will be read + * @len: bytes from ring buffer into @buf + * + * This variant assumes that the buffer is a memory at the userspace. So, + * it will internally call copy_from_user(). + * + * Return: number of bytes transferred or -EFAULT + */ +extern ssize_t dvb_ringbuffer_write_user(struct dvb_ringbuffer *rbuf, + const u8 __user *buf, size_t len); + +/** + * dvb_ringbuffer_pkt_write - Write a packet into the ringbuffer. + * + * @rbuf: Ringbuffer to write to. + * @buf: Buffer to write. + * @len: Length of buffer (currently limited to 65535 bytes max). + * + * Return: Number of bytes written, or -EFAULT, -ENOMEM, -EVINAL. + */ +extern ssize_t dvb_ringbuffer_pkt_write(struct dvb_ringbuffer *rbuf, u8 *buf, + size_t len); + +/** + * dvb_ringbuffer_pkt_read_user - Read from a packet in the ringbuffer. + * + * @rbuf: Ringbuffer concerned. + * @idx: Packet index as returned by dvb_ringbuffer_pkt_next(). + * @offset: Offset into packet to read from. + * @buf: Destination buffer for data. + * @len: Size of destination buffer. + * + * Return: Number of bytes read, or -EFAULT. + * + * .. note:: + * + * unlike dvb_ringbuffer_read(), this does **NOT** update the read pointer + * in the ringbuffer. You must use dvb_ringbuffer_pkt_dispose() to mark a + * packet as no longer required. + */ +extern ssize_t dvb_ringbuffer_pkt_read_user(struct dvb_ringbuffer *rbuf, + size_t idx, + int offset, u8 __user *buf, + size_t len); + +/** + * dvb_ringbuffer_pkt_read - Read from a packet in the ringbuffer. + * Note: unlike dvb_ringbuffer_read_user(), this DOES update the read pointer + * in the ringbuffer. + * + * @rbuf: Ringbuffer concerned. + * @idx: Packet index as returned by dvb_ringbuffer_pkt_next(). + * @offset: Offset into packet to read from. + * @buf: Destination buffer for data. + * @len: Size of destination buffer. + * + * Return: Number of bytes read, or -EFAULT. + */ +extern ssize_t dvb_ringbuffer_pkt_read(struct dvb_ringbuffer *rbuf, size_t idx, + int offset, u8 *buf, size_t len); + +/** + * dvb_ringbuffer_pkt_dispose - Dispose of a packet in the ring buffer. + * + * @rbuf: Ring buffer concerned. + * @idx: Packet index as returned by dvb_ringbuffer_pkt_next(). + */ +extern void dvb_ringbuffer_pkt_dispose(struct dvb_ringbuffer *rbuf, size_t idx); + +/** + * dvb_ringbuffer_pkt_next - Get the index of the next packet in a ringbuffer. + * + * @rbuf: Ringbuffer concerned. + * @idx: Previous packet index, or -1 to return the first packet index. + * @pktlen: On success, will be updated to contain the length of the packet + * in bytes. + * returns Packet index (if >=0), or -1 if no packets available. + */ +extern ssize_t dvb_ringbuffer_pkt_next(struct dvb_ringbuffer *rbuf, + size_t idx, size_t *pktlen); + +#endif /* _DVB_RINGBUFFER_H_ */ diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/dvbdev.c b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/dvbdev.c new file mode 100644 index 000000000000..0e9599bcb1b5 --- /dev/null +++ b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/dvbdev.c @@ -0,0 +1,968 @@ +/* + * dvbdev.c + * + * Copyright (C) 2000 Ralph Metzler + * & Marcus Metzler + * for convergence integrated media GmbH + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "dvbdev.h" + +/* Due to enum tuner_pad_index */ +#include + +static DEFINE_MUTEX(dvbdev_mutex); +static int dvbdev_debug; + +module_param(dvbdev_debug, int, 0644); +MODULE_PARM_DESC(dvbdev_debug, "Turn on/off device debugging (default:off)."); + +#define dprintk if (dvbdev_debug) printk + +static LIST_HEAD(dvb_adapter_list); +static DEFINE_MUTEX(dvbdev_register_lock); + +static const char * const dnames[] = { + "video", "audio", "sec", "frontend", "demux", "dvr", "ca", + "net", "osd" +}; + +#ifdef CONFIG_DVB_DYNAMIC_MINORS +#define MAX_DVB_MINORS 256 +#define DVB_MAX_IDS MAX_DVB_MINORS +#else +#define DVB_MAX_IDS 4 +#define nums2minor(num, type, id) ((num << 6) | (id << 4) | type) +#define MAX_DVB_MINORS (DVB_MAX_ADAPTERS*64) +#endif + +static struct class *dvb_class; + +static struct dvb_device *dvb_minors[MAX_DVB_MINORS]; +static DECLARE_RWSEM(minor_rwsem); + +static int dvb_device_open(struct inode *inode, struct file *file) +{ + struct dvb_device *dvbdev; + + mutex_lock(&dvbdev_mutex); + down_read(&minor_rwsem); + dvbdev = dvb_minors[iminor(inode)]; + + if (dvbdev && dvbdev->fops) { + int err = 0; + const struct file_operations *new_fops; + + new_fops = fops_get(dvbdev->fops); + if (!new_fops) + goto fail; + file->private_data = dvbdev; + replace_fops(file, new_fops); + if (file->f_op->open) + err = file->f_op->open(inode, file); + up_read(&minor_rwsem); + mutex_unlock(&dvbdev_mutex); + return err; + } +fail: + up_read(&minor_rwsem); + mutex_unlock(&dvbdev_mutex); + return -ENODEV; +} + + +static const struct file_operations dvb_device_fops = +{ + .owner = THIS_MODULE, + .open = dvb_device_open, + .llseek = noop_llseek, +}; + +static struct cdev dvb_device_cdev; + +int dvb_generic_open(struct inode *inode, struct file *file) +{ + struct dvb_device *dvbdev = file->private_data; + + if (!dvbdev) + return -ENODEV; + + if (!dvbdev->users) + return -EBUSY; + + if ((file->f_flags & O_ACCMODE) == O_RDONLY) { + if (!dvbdev->readers) + return -EBUSY; + dvbdev->readers--; + } else { + if (!dvbdev->writers) + return -EBUSY; + dvbdev->writers--; + } + + dvbdev->users--; + return 0; +} +EXPORT_SYMBOL(dvb_generic_open); + + +int dvb_generic_release(struct inode *inode, struct file *file) +{ + struct dvb_device *dvbdev = file->private_data; + + if (!dvbdev) + return -ENODEV; + + if ((file->f_flags & O_ACCMODE) == O_RDONLY) { + dvbdev->readers++; + } else { + dvbdev->writers++; + } + + dvbdev->users++; + return 0; +} +EXPORT_SYMBOL(dvb_generic_release); + + +long dvb_generic_ioctl(struct file *file, + unsigned int cmd, unsigned long arg) +{ + struct dvb_device *dvbdev = file->private_data; + + if (!dvbdev) + return -ENODEV; + + if (!dvbdev->kernel_ioctl) + return -EINVAL; + + return dvb_usercopy(file, cmd, arg, dvbdev->kernel_ioctl); +} +EXPORT_SYMBOL(dvb_generic_ioctl); + + +static int dvbdev_get_free_id (struct dvb_adapter *adap, int type) +{ + u32 id = 0; + + while (id < DVB_MAX_IDS) { + struct dvb_device *dev; + list_for_each_entry(dev, &adap->device_list, list_head) + if (dev->type == type && dev->id == id) + goto skip; + return id; +skip: + id++; + } + return -ENFILE; +} + +static void dvb_media_device_free(struct dvb_device *dvbdev) +{ +#if defined(CONFIG_MEDIA_CONTROLLER_DVB) + if (dvbdev->entity) { + media_device_unregister_entity(dvbdev->entity); + kfree(dvbdev->entity); + kfree(dvbdev->pads); + dvbdev->entity = NULL; + dvbdev->pads = NULL; + } + + if (dvbdev->tsout_entity) { + int i; + + for (i = 0; i < dvbdev->tsout_num_entities; i++) { + media_device_unregister_entity(&dvbdev->tsout_entity[i]); + kfree(dvbdev->tsout_entity[i].name); + } + kfree(dvbdev->tsout_entity); + kfree(dvbdev->tsout_pads); + dvbdev->tsout_entity = NULL; + dvbdev->tsout_pads = NULL; + + dvbdev->tsout_num_entities = 0; + } + + if (dvbdev->intf_devnode) { + media_devnode_remove(dvbdev->intf_devnode); + dvbdev->intf_devnode = NULL; + } + + if (dvbdev->adapter->conn) { + media_device_unregister_entity(dvbdev->adapter->conn); + dvbdev->adapter->conn = NULL; + kfree(dvbdev->adapter->conn_pads); + dvbdev->adapter->conn_pads = NULL; + } +#endif +} + +#if defined(CONFIG_MEDIA_CONTROLLER_DVB) +static int dvb_create_tsout_entity(struct dvb_device *dvbdev, + const char *name, int npads) +{ + int i, ret = 0; + + dvbdev->tsout_pads = kcalloc(npads, sizeof(*dvbdev->tsout_pads), + GFP_KERNEL); + if (!dvbdev->tsout_pads) + return -ENOMEM; + + dvbdev->tsout_entity = kcalloc(npads, sizeof(*dvbdev->tsout_entity), + GFP_KERNEL); + if (!dvbdev->tsout_entity) + return -ENOMEM; + + dvbdev->tsout_num_entities = npads; + + for (i = 0; i < npads; i++) { + struct media_pad *pads = &dvbdev->tsout_pads[i]; + struct media_entity *entity = &dvbdev->tsout_entity[i]; + + entity->name = kasprintf(GFP_KERNEL, "%s #%d", name, i); + if (!entity->name) + return -ENOMEM; + + entity->function = MEDIA_ENT_F_IO_DTV; + pads->flags = MEDIA_PAD_FL_SINK; + + ret = media_entity_pads_init(entity, 1, pads); + if (ret < 0) + return ret; + + ret = media_device_register_entity(dvbdev->adapter->mdev, + entity); + if (ret < 0) + return ret; + } + return 0; +} + +#define DEMUX_TSOUT "demux-tsout" +#define DVR_TSOUT "dvr-tsout" + +static int dvb_create_media_entity(struct dvb_device *dvbdev, + int type, int demux_sink_pads) +{ + int i, ret, npads; + + switch (type) { + case DVB_DEVICE_FRONTEND: + npads = 2; + break; + case DVB_DEVICE_DVR: + ret = dvb_create_tsout_entity(dvbdev, DVR_TSOUT, + demux_sink_pads); + return ret; + case DVB_DEVICE_DEMUX: + npads = 1 + demux_sink_pads; + ret = dvb_create_tsout_entity(dvbdev, DEMUX_TSOUT, + demux_sink_pads); + if (ret < 0) + return ret; + break; + case DVB_DEVICE_CA: + npads = 2; + break; + case DVB_DEVICE_NET: + /* + * We should be creating entities for the MPE/ULE + * decapsulation hardware (or software implementation). + * + * However, the number of for the MPE/ULE decaps may not be + * fixed. As we don't have yet dynamic support for PADs at + * the Media Controller, let's not create the decap + * entities yet. + */ + return 0; + default: + return 0; + } + + dvbdev->entity = kzalloc(sizeof(*dvbdev->entity), GFP_KERNEL); + if (!dvbdev->entity) + return -ENOMEM; + + dvbdev->entity->name = dvbdev->name; + + if (npads) { + dvbdev->pads = kcalloc(npads, sizeof(*dvbdev->pads), + GFP_KERNEL); + if (!dvbdev->pads) + return -ENOMEM; + } + + switch (type) { + case DVB_DEVICE_FRONTEND: + dvbdev->entity->function = MEDIA_ENT_F_DTV_DEMOD; + dvbdev->pads[0].flags = MEDIA_PAD_FL_SINK; + dvbdev->pads[1].flags = MEDIA_PAD_FL_SOURCE; + break; + case DVB_DEVICE_DEMUX: + dvbdev->entity->function = MEDIA_ENT_F_TS_DEMUX; + dvbdev->pads[0].flags = MEDIA_PAD_FL_SINK; + for (i = 1; i < npads; i++) + dvbdev->pads[i].flags = MEDIA_PAD_FL_SOURCE; + break; + case DVB_DEVICE_CA: + dvbdev->entity->function = MEDIA_ENT_F_DTV_CA; + dvbdev->pads[0].flags = MEDIA_PAD_FL_SINK; + dvbdev->pads[1].flags = MEDIA_PAD_FL_SOURCE; + break; + default: + /* Should never happen, as the first switch prevents it */ + kfree(dvbdev->entity); + kfree(dvbdev->pads); + dvbdev->entity = NULL; + dvbdev->pads = NULL; + return 0; + } + + if (npads) { + ret = media_entity_pads_init(dvbdev->entity, npads, dvbdev->pads); + if (ret) + return ret; + } + ret = media_device_register_entity(dvbdev->adapter->mdev, + dvbdev->entity); + if (ret) + return ret; + + printk(KERN_DEBUG "%s: media entity '%s' registered.\n", + __func__, dvbdev->entity->name); + + return 0; +} +#endif + +static int dvb_register_media_device(struct dvb_device *dvbdev, + int type, int minor, + unsigned demux_sink_pads) +{ +#if defined(CONFIG_MEDIA_CONTROLLER_DVB) + struct media_link *link; + u32 intf_type; + int ret; + + if (!dvbdev->adapter->mdev) + return 0; + + ret = dvb_create_media_entity(dvbdev, type, demux_sink_pads); + if (ret) + return ret; + + switch (type) { + case DVB_DEVICE_FRONTEND: + intf_type = MEDIA_INTF_T_DVB_FE; + break; + case DVB_DEVICE_DEMUX: + intf_type = MEDIA_INTF_T_DVB_DEMUX; + break; + case DVB_DEVICE_DVR: + intf_type = MEDIA_INTF_T_DVB_DVR; + break; + case DVB_DEVICE_CA: + intf_type = MEDIA_INTF_T_DVB_CA; + break; + case DVB_DEVICE_NET: + intf_type = MEDIA_INTF_T_DVB_NET; + break; + default: + return 0; + } + + dvbdev->intf_devnode = media_devnode_create(dvbdev->adapter->mdev, + intf_type, 0, + DVB_MAJOR, minor); + + if (!dvbdev->intf_devnode) + return -ENOMEM; + + /* + * Create the "obvious" link, e. g. the ones that represent + * a direct association between an interface and an entity. + * Other links should be created elsewhere, like: + * DVB FE intf -> tuner + * DVB demux intf -> dvr + */ + + if (!dvbdev->entity) + return 0; + + link = media_create_intf_link(dvbdev->entity, &dvbdev->intf_devnode->intf, + MEDIA_LNK_FL_ENABLED); + if (!link) + return -ENOMEM; +#endif + return 0; +} + +int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev, + const struct dvb_device *template, void *priv, int type, + int demux_sink_pads) +{ + struct dvb_device *dvbdev; + struct file_operations *dvbdevfops; + struct device *clsdev; + int minor; + int id, ret; + + mutex_lock(&dvbdev_register_lock); + + if ((id = dvbdev_get_free_id (adap, type)) < 0){ + mutex_unlock(&dvbdev_register_lock); + *pdvbdev = NULL; + printk(KERN_ERR "%s: couldn't find free device id\n", __func__); + return -ENFILE; + } + + *pdvbdev = dvbdev = kzalloc(sizeof(*dvbdev), GFP_KERNEL); + + if (!dvbdev){ + mutex_unlock(&dvbdev_register_lock); + return -ENOMEM; + } + + dvbdevfops = kzalloc(sizeof(struct file_operations), GFP_KERNEL); + + if (!dvbdevfops){ + kfree (dvbdev); + mutex_unlock(&dvbdev_register_lock); + return -ENOMEM; + } + + memcpy(dvbdev, template, sizeof(struct dvb_device)); + dvbdev->type = type; + dvbdev->id = id; + dvbdev->adapter = adap; + dvbdev->priv = priv; + dvbdev->fops = dvbdevfops; + init_waitqueue_head (&dvbdev->wait_queue); + + memcpy(dvbdevfops, template->fops, sizeof(struct file_operations)); + dvbdevfops->owner = adap->module; + + list_add_tail (&dvbdev->list_head, &adap->device_list); + + down_write(&minor_rwsem); +#ifdef CONFIG_DVB_DYNAMIC_MINORS + for (minor = 0; minor < MAX_DVB_MINORS; minor++) + if (dvb_minors[minor] == NULL) + break; + + if (minor == MAX_DVB_MINORS) { + kfree(dvbdevfops); + kfree(dvbdev); + up_write(&minor_rwsem); + mutex_unlock(&dvbdev_register_lock); + return -EINVAL; + } +#else + minor = nums2minor(adap->num, type, id); +#endif + + dvbdev->minor = minor; + dvb_minors[minor] = dvbdev; + up_write(&minor_rwsem); + + ret = dvb_register_media_device(dvbdev, type, minor, demux_sink_pads); + if (ret) { + printk(KERN_ERR + "%s: dvb_register_media_device failed to create the mediagraph\n", + __func__); + + dvb_media_device_free(dvbdev); + kfree(dvbdevfops); + kfree(dvbdev); + up_write(&minor_rwsem); + mutex_unlock(&dvbdev_register_lock); + return ret; + } + + mutex_unlock(&dvbdev_register_lock); + + clsdev = device_create(dvb_class, adap->device, + MKDEV(DVB_MAJOR, minor), + dvbdev, "dvb%d.%s%d", adap->num, dnames[type], id); + if (IS_ERR(clsdev)) { + printk(KERN_ERR "%s: failed to create device dvb%d.%s%d (%ld)\n", + __func__, adap->num, dnames[type], id, PTR_ERR(clsdev)); + return PTR_ERR(clsdev); + } + dprintk(KERN_DEBUG "DVB: register adapter%d/%s%d @ minor: %i (0x%02x)\n", + adap->num, dnames[type], id, minor, minor); + + return 0; +} +EXPORT_SYMBOL(dvb_register_device); + + +void dvb_unregister_device(struct dvb_device *dvbdev) +{ + if (!dvbdev) + return; + + down_write(&minor_rwsem); + dvb_minors[dvbdev->minor] = NULL; + up_write(&minor_rwsem); + + dvb_media_device_free(dvbdev); + + device_destroy(dvb_class, MKDEV(DVB_MAJOR, dvbdev->minor)); + + list_del (&dvbdev->list_head); + kfree (dvbdev->fops); + kfree (dvbdev); +} +EXPORT_SYMBOL(dvb_unregister_device); + + +#ifdef CONFIG_MEDIA_CONTROLLER_DVB + +static int dvb_create_io_intf_links(struct dvb_adapter *adap, + struct media_interface *intf, + char *name) +{ + struct media_device *mdev = adap->mdev; + struct media_entity *entity; + struct media_link *link; + + media_device_for_each_entity(entity, mdev) { + if (entity->function == MEDIA_ENT_F_IO_DTV) { + if (strncmp(entity->name, name, strlen(name))) + continue; + link = media_create_intf_link(entity, intf, + MEDIA_LNK_FL_ENABLED); + if (!link) + return -ENOMEM; + } + } + return 0; +} + +int dvb_create_media_graph(struct dvb_adapter *adap, + bool create_rf_connector) +{ + struct media_device *mdev = adap->mdev; + struct media_entity *entity, *tuner = NULL, *demod = NULL, *conn; + struct media_entity *demux = NULL, *ca = NULL; + struct media_link *link; + struct media_interface *intf; + unsigned demux_pad = 0; + unsigned dvr_pad = 0; + unsigned ntuner = 0, ndemod = 0; + int ret; + static const char *connector_name = "Television"; + + if (!mdev) + return 0; + + media_device_for_each_entity(entity, mdev) { + switch (entity->function) { + case MEDIA_ENT_F_TUNER: + tuner = entity; + ntuner++; + break; + case MEDIA_ENT_F_DTV_DEMOD: + demod = entity; + ndemod++; + break; + case MEDIA_ENT_F_TS_DEMUX: + demux = entity; + break; + case MEDIA_ENT_F_DTV_CA: + ca = entity; + break; + } + } + + /* + * Prepare to signalize to media_create_pad_links() that multiple + * entities of the same type exists and a 1:n or n:1 links need to be + * created. + * NOTE: if both tuner and demod have multiple instances, it is up + * to the caller driver to create such links. + */ + if (ntuner > 1) + tuner = NULL; + if (ndemod > 1) + demod = NULL; + + if (create_rf_connector) { + conn = kzalloc(sizeof(*conn), GFP_KERNEL); + if (!conn) + return -ENOMEM; + adap->conn = conn; + + adap->conn_pads = kzalloc(sizeof(*adap->conn_pads), GFP_KERNEL); + if (!adap->conn_pads) + return -ENOMEM; + + conn->flags = MEDIA_ENT_FL_CONNECTOR; + conn->function = MEDIA_ENT_F_CONN_RF; + conn->name = connector_name; + adap->conn_pads->flags = MEDIA_PAD_FL_SOURCE; + + ret = media_entity_pads_init(conn, 1, adap->conn_pads); + if (ret) + return ret; + + ret = media_device_register_entity(mdev, conn); + if (ret) + return ret; + + if (!ntuner) + ret = media_create_pad_links(mdev, + MEDIA_ENT_F_CONN_RF, + conn, 0, + MEDIA_ENT_F_DTV_DEMOD, + demod, 0, + MEDIA_LNK_FL_ENABLED, + false); + else + ret = media_create_pad_links(mdev, + MEDIA_ENT_F_CONN_RF, + conn, 0, + MEDIA_ENT_F_TUNER, + tuner, TUNER_PAD_RF_INPUT, + MEDIA_LNK_FL_ENABLED, + false); + if (ret) + return ret; + } + + if (ntuner && ndemod) { + ret = media_create_pad_links(mdev, + MEDIA_ENT_F_TUNER, + tuner, TUNER_PAD_OUTPUT, + MEDIA_ENT_F_DTV_DEMOD, + demod, 0, MEDIA_LNK_FL_ENABLED, + false); + if (ret) + return ret; + } + + if (ndemod && demux) { + ret = media_create_pad_links(mdev, + MEDIA_ENT_F_DTV_DEMOD, + demod, 1, + MEDIA_ENT_F_TS_DEMUX, + demux, 0, MEDIA_LNK_FL_ENABLED, + false); + if (ret) + return ret; + } + if (demux && ca) { + ret = media_create_pad_link(demux, 1, ca, + 0, MEDIA_LNK_FL_ENABLED); + if (ret) + return ret; + } + + /* Create demux links for each ringbuffer/pad */ + if (demux) { + media_device_for_each_entity(entity, mdev) { + if (entity->function == MEDIA_ENT_F_IO_DTV) { + if (!strncmp(entity->name, DVR_TSOUT, + strlen(DVR_TSOUT))) { + ret = media_create_pad_link(demux, + ++dvr_pad, + entity, 0, 0); + if (ret) + return ret; + } + if (!strncmp(entity->name, DEMUX_TSOUT, + strlen(DEMUX_TSOUT))) { + ret = media_create_pad_link(demux, + ++demux_pad, + entity, 0, 0); + if (ret) + return ret; + } + } + } + } + + /* Create interface links for FE->tuner, DVR->demux and CA->ca */ + media_device_for_each_intf(intf, mdev) { + if (intf->type == MEDIA_INTF_T_DVB_CA && ca) { + link = media_create_intf_link(ca, intf, + MEDIA_LNK_FL_ENABLED); + if (!link) + return -ENOMEM; + } + + if (intf->type == MEDIA_INTF_T_DVB_FE && tuner) { + link = media_create_intf_link(tuner, intf, + MEDIA_LNK_FL_ENABLED); + if (!link) + return -ENOMEM; + } +#if 0 + /* + * Indirect link - let's not create yet, as we don't know how + * to handle indirect links, nor if this will + * actually be needed. + */ + if (intf->type == MEDIA_INTF_T_DVB_DVR && demux) { + link = media_create_intf_link(demux, intf, + MEDIA_LNK_FL_ENABLED); + if (!link) + return -ENOMEM; + } +#endif + if (intf->type == MEDIA_INTF_T_DVB_DVR) { + ret = dvb_create_io_intf_links(adap, intf, DVR_TSOUT); + if (ret) + return ret; + } + if (intf->type == MEDIA_INTF_T_DVB_DEMUX) { + ret = dvb_create_io_intf_links(adap, intf, DEMUX_TSOUT); + if (ret) + return ret; + } + } + return 0; +} +EXPORT_SYMBOL_GPL(dvb_create_media_graph); +#endif + +static int dvbdev_check_free_adapter_num(int num) +{ + struct list_head *entry; + list_for_each(entry, &dvb_adapter_list) { + struct dvb_adapter *adap; + adap = list_entry(entry, struct dvb_adapter, list_head); + if (adap->num == num) + return 0; + } + return 1; +} + +static int dvbdev_get_free_adapter_num (void) +{ + int num = 0; + + while (num < DVB_MAX_ADAPTERS) { + if (dvbdev_check_free_adapter_num(num)) + return num; + num++; + } + + return -ENFILE; +} + + +int dvb_register_adapter(struct dvb_adapter *adap, const char *name, + struct module *module, struct device *device, + short *adapter_nums) +{ + int i, num; + + mutex_lock(&dvbdev_register_lock); + + for (i = 0; i < DVB_MAX_ADAPTERS; ++i) { + num = adapter_nums[i]; + if (num >= 0 && num < DVB_MAX_ADAPTERS) { + /* use the one the driver asked for */ + if (dvbdev_check_free_adapter_num(num)) + break; + } else { + num = dvbdev_get_free_adapter_num(); + break; + } + num = -1; + } + + if (num < 0) { + mutex_unlock(&dvbdev_register_lock); + return -ENFILE; + } + + memset (adap, 0, sizeof(struct dvb_adapter)); + INIT_LIST_HEAD (&adap->device_list); + + printk(KERN_INFO "DVB: registering new adapter (%s)\n", name); + + adap->num = num; + adap->name = name; + adap->module = module; + adap->device = device; + adap->mfe_shared = 0; + adap->mfe_dvbdev = NULL; + mutex_init (&adap->mfe_lock); + + list_add_tail (&adap->list_head, &dvb_adapter_list); + + mutex_unlock(&dvbdev_register_lock); + + return num; +} +EXPORT_SYMBOL(dvb_register_adapter); + + +int dvb_unregister_adapter(struct dvb_adapter *adap) +{ + mutex_lock(&dvbdev_register_lock); + list_del (&adap->list_head); + mutex_unlock(&dvbdev_register_lock); + return 0; +} +EXPORT_SYMBOL(dvb_unregister_adapter); + +/* if the miracle happens and "generic_usercopy()" is included into + the kernel, then this can vanish. please don't make the mistake and + define this as video_usercopy(). this will introduce a dependecy + to the v4l "videodev.o" module, which is unnecessary for some + cards (ie. the budget dvb-cards don't need the v4l module...) */ +int dvb_usercopy(struct file *file, + unsigned int cmd, unsigned long arg, + int (*func)(struct file *file, + unsigned int cmd, void *arg)) +{ + char sbuf[128]; + void *mbuf = NULL; + void *parg = NULL; + int err = -EINVAL; + + /* Copy arguments into temp kernel buffer */ + switch (_IOC_DIR(cmd)) { + case _IOC_NONE: + /* + * For this command, the pointer is actually an integer + * argument. + */ + parg = (void *) arg; + break; + case _IOC_READ: /* some v4l ioctls are marked wrong ... */ + case _IOC_WRITE: + case (_IOC_WRITE | _IOC_READ): + if (_IOC_SIZE(cmd) <= sizeof(sbuf)) { + parg = sbuf; + } else { + /* too big to allocate from stack */ + mbuf = kmalloc(_IOC_SIZE(cmd), GFP_KERNEL); + if (NULL == mbuf) + return -ENOMEM; + parg = mbuf; + } + + err = -EFAULT; + if (copy_from_user(parg, (void __user *)arg, _IOC_SIZE(cmd))) + goto out; + break; + } + + /* call driver */ + if ((err = func(file, cmd, parg)) == -ENOIOCTLCMD) + err = -ENOTTY; + + if (err < 0) + goto out; + + /* Copy results into user buffer */ + switch (_IOC_DIR(cmd)) + { + case _IOC_READ: + case (_IOC_WRITE | _IOC_READ): + if (copy_to_user((void __user *)arg, parg, _IOC_SIZE(cmd))) + err = -EFAULT; + break; + } + +out: + kfree(mbuf); + return err; +} +EXPORT_SYMBOL(dvb_usercopy); +static int dvb_uevent(struct device *dev, struct kobj_uevent_env *env) +{ + struct dvb_device *dvbdev = dev_get_drvdata(dev); + + add_uevent_var(env, "DVB_ADAPTER_NUM=%d", dvbdev->adapter->num); + add_uevent_var(env, "DVB_DEVICE_TYPE=%s", dnames[dvbdev->type]); + add_uevent_var(env, "DVB_DEVICE_NUM=%d", dvbdev->id); + return 0; +} + +static char *dvb_devnode(struct device *dev, umode_t *mode) +{ + struct dvb_device *dvbdev = dev_get_drvdata(dev); + + return kasprintf(GFP_KERNEL, "dvb/adapter%d/%s%d", + dvbdev->adapter->num, dnames[dvbdev->type], dvbdev->id); +} + + +static int __init init_dvbdev(void) +{ + int retval; + dev_t dev = MKDEV(DVB_MAJOR, 0); + + if ((retval = register_chrdev_region(dev, MAX_DVB_MINORS, "DVB")) != 0) { + printk(KERN_ERR "dvb-core: unable to get major %d\n", DVB_MAJOR); + return retval; + } + + cdev_init(&dvb_device_cdev, &dvb_device_fops); + if ((retval = cdev_add(&dvb_device_cdev, dev, MAX_DVB_MINORS)) != 0) { + printk(KERN_ERR "dvb-core: unable register character device\n"); + goto error; + } + + dvb_class = class_create(THIS_MODULE, "dvb"); + if (IS_ERR(dvb_class)) { + retval = PTR_ERR(dvb_class); + goto error; + } + dvb_class->dev_uevent = dvb_uevent; + dvb_class->devnode = dvb_devnode; + return 0; + +error: + cdev_del(&dvb_device_cdev); + unregister_chrdev_region(dev, MAX_DVB_MINORS); + return retval; +} + + +static void __exit exit_dvbdev(void) +{ + class_destroy(dvb_class); + cdev_del(&dvb_device_cdev); + unregister_chrdev_region(MKDEV(DVB_MAJOR, 0), MAX_DVB_MINORS); +} +#if 0 +subsys_initcall(init_dvbdev); +module_exit(exit_dvbdev); + +MODULE_DESCRIPTION("DVB Core Driver"); +MODULE_AUTHOR("Marcus Metzler, Ralph Metzler, Holger Waechtler"); +MODULE_LICENSE("GPL"); +#endif diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/dvbdev.h b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/dvbdev.h new file mode 100644 index 000000000000..4aff7bd3dea8 --- /dev/null +++ b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/dvbdev.h @@ -0,0 +1,299 @@ +/* + * dvbdev.h + * + * Copyright (C) 2000 Ralph Metzler & Marcus Metzler + * for convergence integrated media GmbH + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Lesser Public License + * as published by the Free Software Foundation; either version 2.1 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#ifndef _DVBDEV_H_ +#define _DVBDEV_H_ + +#include +#include +#include +#include +#include + +#define DVB_MAJOR 212 + +#if defined(CONFIG_DVB_MAX_ADAPTERS) && CONFIG_DVB_MAX_ADAPTERS > 0 + #define DVB_MAX_ADAPTERS CONFIG_DVB_MAX_ADAPTERS +#else + #define DVB_MAX_ADAPTERS 8 +#endif + +#define DVB_UNSET (-1) + +#define DVB_DEVICE_VIDEO 0 +#define DVB_DEVICE_AUDIO 1 +#define DVB_DEVICE_SEC 2 +#define DVB_DEVICE_FRONTEND 3 +#define DVB_DEVICE_DEMUX 4 +#define DVB_DEVICE_DVR 5 +#define DVB_DEVICE_CA 6 +#define DVB_DEVICE_NET 7 +#define DVB_DEVICE_OSD 8 + +#define DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr) \ + static short adapter_nr[] = \ + {[0 ... (DVB_MAX_ADAPTERS - 1)] = DVB_UNSET }; \ + module_param_array(adapter_nr, short, NULL, 0444); \ + MODULE_PARM_DESC(adapter_nr, "DVB adapter numbers") + +struct dvb_frontend; + +/** + * struct dvb_adapter - represents a Digital TV adapter using Linux DVB API + * + * @num: Number of the adapter + * @list_head: List with the DVB adapters + * @device_list: List with the DVB devices + * @name: Name of the adapter + * @proposed_mac: proposed MAC address for the adapter + * @priv: private data + * @device: pointer to struct device + * @module: pointer to struct module + * @mfe_shared: mfe shared: indicates mutually exclusive frontends + * Thie usage of this flag is currently deprecated + * @mfe_dvbdev: Frontend device in use, in the case of MFE + * @mfe_lock: Lock to prevent using the other frontends when MFE is + * used. + * @mdev: pointer to struct media_device, used when the media + * controller is used. + * @conn: RF connector. Used only if the device has no separate + * tuner. + * @conn_pads: pointer to struct media_pad associated with @conn; + */ +struct dvb_adapter { + int num; + struct list_head list_head; + struct list_head device_list; + const char *name; + u8 proposed_mac [6]; + void* priv; + + struct device *device; + + struct module *module; + + int mfe_shared; /* indicates mutually exclusive frontends */ + struct dvb_device *mfe_dvbdev; /* frontend device in use */ + struct mutex mfe_lock; /* access lock for thread creation */ + +#if defined(CONFIG_MEDIA_CONTROLLER_DVB) + struct media_device *mdev; + struct media_entity *conn; + struct media_pad *conn_pads; +#endif +}; + +/** + * struct dvb_device - represents a DVB device node + * + * @list_head: List head with all DVB devices + * @fops: pointer to struct file_operations + * @adapter: pointer to the adapter that holds this device node + * @type: type of the device: DVB_DEVICE_SEC, DVB_DEVICE_FRONTEND, + * DVB_DEVICE_DEMUX, DVB_DEVICE_DVR, DVB_DEVICE_CA, DVB_DEVICE_NET + * @minor: devnode minor number. Major number is always DVB_MAJOR. + * @id: device ID number, inside the adapter + * @readers: Initialized by the caller. Each call to open() in Read Only mode + * decreases this counter by one. + * @writers: Initialized by the caller. Each call to open() in Read/Write + * mode decreases this counter by one. + * @users: Initialized by the caller. Each call to open() in any mode + * decreases this counter by one. + * @wait_queue: wait queue, used to wait for certain events inside one of + * the DVB API callers + * @kernel_ioctl: callback function used to handle ioctl calls from userspace. + * @name: Name to be used for the device at the Media Controller + * @entity: pointer to struct media_entity associated with the device node + * @pads: pointer to struct media_pad associated with @entity; + * @priv: private data + * @intf_devnode: Pointer to media_intf_devnode. Used by the dvbdev core to + * store the MC device node interface + * @tsout_num_entities: Number of Transport Stream output entities + * @tsout_entity: array with MC entities associated to each TS output node + * @tsout_pads: array with the source pads for each @tsout_entity + * + * This structure is used by the DVB core (frontend, CA, net, demux) in + * order to create the device nodes. Usually, driver should not initialize + * this struct diretly. + */ +struct dvb_device { + struct list_head list_head; + const struct file_operations *fops; + struct dvb_adapter *adapter; + int type; + int minor; + u32 id; + + /* in theory, 'users' can vanish now, + but I don't want to change too much now... */ + int readers; + int writers; + int users; + + wait_queue_head_t wait_queue; + /* don't really need those !? -- FIXME: use video_usercopy */ + int (*kernel_ioctl)(struct file *file, unsigned int cmd, void *arg); + + /* Needed for media controller register/unregister */ +#if defined(CONFIG_MEDIA_CONTROLLER_DVB) + const char *name; + + /* Allocated and filled inside dvbdev.c */ + struct media_intf_devnode *intf_devnode; + + unsigned tsout_num_entities; + struct media_entity *entity, *tsout_entity; + struct media_pad *pads, *tsout_pads; +#endif + + void *priv; +}; + +/** + * dvb_register_adapter - Registers a new DVB adapter + * + * @adap: pointer to struct dvb_adapter + * @name: Adapter's name + * @module: initialized with THIS_MODULE at the caller + * @device: pointer to struct device that corresponds to the device driver + * @adapter_nums: Array with a list of the numbers for @dvb_register_adapter; + * to select among them. Typically, initialized with: + * DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nums) + */ +int dvb_register_adapter(struct dvb_adapter *adap, const char *name, + struct module *module, struct device *device, + short *adapter_nums); + +/** + * dvb_unregister_adapter - Unregisters a DVB adapter + * + * @adap: pointer to struct dvb_adapter + */ +int dvb_unregister_adapter(struct dvb_adapter *adap); + +/** + * dvb_register_device - Registers a new DVB device + * + * @adap: pointer to struct dvb_adapter + * @pdvbdev: pointer to the place where the new struct dvb_device will be + * stored + * @template: Template used to create &pdvbdev; + * @priv: private data + * @type: type of the device: %DVB_DEVICE_SEC, %DVB_DEVICE_FRONTEND, + * %DVB_DEVICE_DEMUX, %DVB_DEVICE_DVR, %DVB_DEVICE_CA, + * %DVB_DEVICE_NET + * @demux_sink_pads: Number of demux outputs, to be used to create the TS + * outputs via the Media Controller. + */ +int dvb_register_device(struct dvb_adapter *adap, + struct dvb_device **pdvbdev, + const struct dvb_device *template, + void *priv, + int type, + int demux_sink_pads); + +/** + * dvb_unregister_device - Unregisters a DVB device + * + * @dvbdev: pointer to struct dvb_device + */ +void dvb_unregister_device(struct dvb_device *dvbdev); + +#ifdef CONFIG_MEDIA_CONTROLLER_DVB +/** + * dvb_create_media_graph - Creates media graph for the Digital TV part of the + * device. + * + * @adap: pointer to struct dvb_adapter + * @create_rf_connector: if true, it creates the RF connector too + * + * This function checks all DVB-related functions at the media controller + * entities and creates the needed links for the media graph. It is + * capable of working with multiple tuners or multiple frontends, but it + * won't create links if the device has multiple tuners and multiple frontends + * or if the device has multiple muxes. In such case, the caller driver should + * manually create the remaining links. + */ +__must_check int dvb_create_media_graph(struct dvb_adapter *adap, + bool create_rf_connector); + +static inline void dvb_register_media_controller(struct dvb_adapter *adap, + struct media_device *mdev) +{ + adap->mdev = mdev; +} + +static inline struct media_device +*dvb_get_media_controller(struct dvb_adapter *adap) +{ + return adap->mdev; +} +#else +static inline +int dvb_create_media_graph(struct dvb_adapter *adap, + bool create_rf_connector) +{ + return 0; +}; +#define dvb_register_media_controller(a, b) {} +#define dvb_get_media_controller(a) NULL +#endif + +int dvb_generic_open (struct inode *inode, struct file *file); +int dvb_generic_release (struct inode *inode, struct file *file); +long dvb_generic_ioctl (struct file *file, + unsigned int cmd, unsigned long arg); + +/* we don't mess with video_usercopy() any more, +we simply define out own dvb_usercopy(), which will hopefully become +generic_usercopy() someday... */ + +int dvb_usercopy(struct file *file, unsigned int cmd, unsigned long arg, + int (*func)(struct file *file, unsigned int cmd, void *arg)); + +/** generic DVB attach function. */ +#ifdef CONFIG_MEDIA_ATTACH +#define dvb_attach(FUNCTION, ARGS...) ({ \ + void *__r = NULL; \ + typeof(&FUNCTION) __a = symbol_request(FUNCTION); \ + if (__a) { \ + __r = (void *) __a(ARGS); \ + if (__r == NULL) \ + symbol_put(FUNCTION); \ + } else { \ + printk(KERN_ERR "DVB: Unable to find symbol "#FUNCTION"()\n"); \ + } \ + __r; \ +}) + +#define dvb_detach(FUNC) symbol_put_addr(FUNC) + +#else +#define dvb_attach(FUNCTION, ARGS...) ({ \ + FUNCTION(ARGS); \ +}) + +#define dvb_detach(FUNC) {} + +#endif + +#endif /* #ifndef _DVBDEV_H_ */ diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/COPYING.LESSER b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/COPYING.LESSER new file mode 100644 index 000000000000..8f4a86041ed0 --- /dev/null +++ b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/COPYING.LESSER @@ -0,0 +1,499 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. +We sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/README.txt b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/README.txt new file mode 100644 index 000000000000..1d6a01c7dccd --- /dev/null +++ b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/README.txt @@ -0,0 +1,61 @@ +April 28, 2011 + +Linux CIMaX+ Kernel driver. +Release Code version: + +DISCLAIMER +---------- + +This is a Smardtv' Linux Kernel driver for use with +the CIMaX+ USB reference board hardware. + +IMPORTANT NOTE +-------------- + +This packages contains a Linux Kernel driver to be installed in the +/lib/modules target directory in order to be loaded automaticaly. + +1. High level driver: cimax+usb_driver.ko + This driver provide the high level interface to control the CIMaX+ USB interface. + +2. Firmware + To have a functional hardware, the firmware must be uploaded to the device. + + The firmwares is delivered in 2 files for dedicated usage and must be + installed in the Linux firmware directory on the target board: + + - /lib/firmware + + A) CIMaX+ firmware binary file + Copy the following firmware file to the /lib/firmware directory: + - firmware/cimax+_usbdvb.bin + + B) CIMaX+ configuration file + Copy the following firmware file to the /lib/firmware directory: + - firmware/cimax+usb.cfg + + +BUILD AND INSTALLATION INSTRUCTIONS +----------------------------------- + +2. Building LINUX USB DVB driver + On the target machine performs the following commands: + + 1. cd src + 2. make + 3. make install + +3. Installing firmware files + On the target machine performs the following command: + + 1. cp firmware/*.* /lib/firmware/ + +4. Installing rules file + 1. cp src/99-cimax+usb.rules /etc/udev/rules.d/ + 2. udevadm control --reload-rules + +5. Build modules dependencies + On the target machine performs the following command: + + 1. depmod -a + diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/99-cimax+usb.rules b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/99-cimax+usb.rules new file mode 100644 index 000000000000..82af37083592 --- /dev/null +++ b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/99-cimax+usb.rules @@ -0,0 +1,4 @@ +BUS=="usb", ACTION=="add", SYSFS{idProduct}=="2F00", SYSFS{idVendor}=="1B0D" +KERNEL=="cimaxusb[0-9]", GROUP="users" + + diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/HOWTO.txt b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/HOWTO.txt new file mode 100644 index 000000000000..23de038208c9 --- /dev/null +++ b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/HOWTO.txt @@ -0,0 +1,85 @@ +The following examples shows how to use the cimax+usb driver. +All structures and macro are defined in file cimax+usb-driver.h. + + +1.Open the device cimax+usb +=========================== +/* open device */ +dev = open("/dev/cimaxusb0", O_RDWR); +/* select USB alt_setting */ +ioctl(dev, DEVICE_IOC_SELECT_INTF, alt_setting); + + +2.Close the device cimax+usb +============================ +/* unlock read queue */ +ioctl(dev, DEVICE_IOC_UNLOCK_READ, 0); +/* close device */ +close(dev); + + +3.Send a CI message to a CAM through the device +=============================================== +/* Send CAM A Reset command */ +uint8 command[5] = {0x01, /* Command */ + 0x01, /* Counter */ + 0x00, /* MSB data size */ + 0x01, /* LSB data size */ + 0x00}; /* data */ +uint8 response[4100]; +struct ioctl_data_s stData; +stData.txData = command; +stData.txSize = 5; +stData.rxData = response; +stData.rxSize = 4100; +ioctl(dev, DEVICE_IOC_CI_WRITE, &stData); + +/* Send CAM B Get CIS command */ +uint8 command[5] = {0x82, /* Command */ + 0x01, /* Counter */ + 0x00, /* MSB data size */ + 0x00}; /* LSB data size */ +uint8 response[4100]; +struct ioctl_data_s stData; +stData.txData = command; +stData.txSize = 4; +stData.rxData = response; +stData.rxSize = 4100; +ioctl(dev, DEVICE_IOC_CI_WRITE, &stData); + + +4.Send a Transport Stream to a CAM through the device +===================================================== +/* Send to CAM A */ +struct rw_data_s rwData; +rwData.type = DEVICE_TYPE_TS_WRITE; +rwData.moduleId = 0; /* CAM A */ +rwData.data = stream; +rwData.size = size; +rwData.copiedSize = 0; +write(dev, &rwData, sizeof(struct rw_data_s)); + + +5.Read a Transport Stream from a CAM through the device +======================================================= +/* Read from CAM B */ +struct rw_data_s rwData; +rwData.type = DEVICE_TYPE_TS_READ; +rwData.moduleId = 1; /* CAM B */ +rwData.data = stream; +rwData.size = size; +rwData.copiedSize = 0; +read(dev, &rwData, sizeof(struct rw_data_s)); + + +6.Read a CI message from a CAM through the device +================================================= +/* Read from CAM A */ +uint8 response[4096]; +struct rw_data_s rwData; +rwData.type = DEVICE_TYPE_CI_READ; +rwData.moduleId = 0; /* CAM A */ +rwData.data = response; +rwData.size = 4096; +rwData.copiedSize = 0; +read(dev, &rwData, sizeof(struct rw_data_s)); diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/Makefile b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/Makefile new file mode 100644 index 000000000000..bc7994599d3f --- /dev/null +++ b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/Makefile @@ -0,0 +1,35 @@ +TARGET = cimax+usb_driver +OBJS = cimax+usb_driver.o +MDIR = drivers/misc + +ccflags-y = -DEXPORT_SYMTAB +#ccflags-y = -DEXPORT_SYMTAB -DDEBUG +CURRENT = $(shell uname -r) +KDIR = /lib/modules/$(CURRENT)/build +PWD = $(shell pwd) +DEST = /lib/modules/$(CURRENT)/kernel/$(MDIR) + +obj-m := $(TARGET).o +cimax+usb_driver-y := cimax+usb-driver.o cimax+usb_fw.o +cimax+usb_driver-y += cimax+usb_config.o +cimax+usb_driver-y += cimax+usb_time.o + +default: + make -C /usr/src/linux SUBDIRS=$(PWD) modules +# make -C /lib/modules/`uname -r`/build M=$(PWD) modules + +$(TARGET).o: $(OBJS) + $(LD) $(LD_RFLAG) -r -o $@ $(OBJS) + +ifneq (,$(findstring 2.4.,$(CURRENT))) +install: + su -c "cp -v $(TARGET).o $(DEST) && /sbin/depmod -a" +else +install: + su -c "cp -v $(TARGET).ko $(DEST) && /sbin/depmod -a" +endif + +clean: + -rm -f *.o *.ko .*.cmd .*.flags *.mod.c + +-include $(KDIR)/Rules.make diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/bodydef.h b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/bodydef.h new file mode 100644 index 000000000000..f93fef5d2274 --- /dev/null +++ b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/bodydef.h @@ -0,0 +1,424 @@ +/**************************************************************************//** + * @file bodydef.h + * + * @brief CIMaX+ USB Driver for linux based operating systems. + * + * Copyright (C) 2009-2011 Bruno Tonelli + * & Franck Descours + * for SmarDTV France, La Ciotat + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + ******************************************************************************/ + +#ifndef __BODYDEF_H +#define __BODYDEF_H + +struct reg_s { + __u8 RegisterName[50]; + __u16 RegAddr; +}; + +/*======================================================================= + Input/Output Ports and Data Direction Registers +=======================================================================*/ +struct reg_s cimax_reg_map[] = { + {"BUFFIN_CFG" , 0x0000}, + {"BUFFIN_ADDR_LSB" , 0x0001}, + {"BUFFIN_ADDR_MSB" , 0x0002}, + {"BUFFIN_DATA" , 0x0003}, + {"BUFFOUT_CFG" , 0x0004}, + {"BUFFOUT_ADDR_LSB" , 0x0005}, + {"BUFFOUT_ADDR_MSB" , 0x0006}, + {"BUFFOUT_DATA" , 0x0007}, + {"BOOT_Key" , 0x0008}, + {"BOOT_Status" , 0x0009}, + {"BOOT_Test " , 0x000A}, + {"RxDMA_Ctrl" , 0x0010}, + {"RxDMA_Status" , 0x0011}, + {"RxDMA_DbgL" , 0x0012}, + {"RxDMA_DbgH" , 0x0013}, + {"SPI_Slave_Ctrl" , 0x0018}, + {"SPI_Slave_Status" , 0x0019}, + {"SPI_Slave_Rx" , 0x001A}, + {"SPI_Slave_Tx" , 0x001B}, + {"SPI_Slave_Mask" , 0x001C}, + {"UCSG_Ctrl" , 0x0020}, + {"UCSG_Status" , 0x0021}, + {"UCSG_RxData" , 0x0022}, + {"UCSG_TxData" , 0x0023}, + {"PCtrl_Ctrl" , 0x0028}, + {"PCtrl_Status" , 0x0029}, + {"PCtrl_NbByte_LSB" , 0x002A}, + {"PCtrl_NbByte_MSB" , 0x002B}, + {"SPI_Master_Ctl" , 0x0030}, + {"SPI_Master_NCS" , 0x0031}, + {"SPI_Master_Status" , 0x0032}, + {"SPI_Master_TxBuf" , 0x0033}, + {"SPI_Master_RxBuf" , 0x0034}, + {"BISTRAM_Ctl" , 0x0038}, + {"BISTRAM_Bank" , 0x0039}, + {"BISTRAM_Pat" , 0x003A}, + {"BISTRAM_SM" , 0x003B}, + {"BISTRAM_AddrLSB" , 0x003C}, + {"BISTROM_Config" , 0x0040}, + {"BISTROM_SignatureLSB" , 0x0041}, + {"BISTROM_SignatureMSB" , 0x0042}, + {"BISTROM_StartAddrLSB" , 0x0043}, + {"BISTROM_StartAddrMSB" , 0x0044}, + {"BISTROM_StopAddrLSB" , 0x0045}, + {"BISTROM_StopAddrMSB" , 0x0046}, + {"CkMan_Config" , 0x0048}, + {"CkMan_Select" , 0x0049}, + {"CkMan_Test" , 0x004A}, + {"Revision_Number" , 0x004B}, + {"CkMan_PD_Key" , 0x004C}, + {"USB_Power_Mode" , 0x004D}, + {"ResMan_Config" , 0x0050}, + {"ResMan_Status" , 0x0051}, + {"ResMan_WD" , 0x0052}, + {"ResMan_WD_MSB" , 0x0053}, + {"TxDMA_Ctrl" , 0x0058}, + {"TxDMA_Status" , 0x0059}, + {"TxDMA_StartAddrL" , 0x005A}, + {"TxDMA_StartAddrH" , 0x005B}, + {"TxDMA_StopAddrL" , 0x005C}, + {"TxDMA_StopAddrH" , 0x005D}, + {"CPU_Test" , 0x0060}, + {"IrqMan_Config0" , 0x0068}, + {"IrqMan_Config1" , 0x0069}, + {"IrqMan_Irq0" , 0x006A}, + {"IrqMan_NMI" , 0x006B}, + {"IrqMan_SleepKey" , 0x006C}, + {"Tim_Config" , 0x0070}, + {"Tim_Value_LSB" , 0x0071}, + {"Tim_Value_MSB" , 0x0072}, + {"Tim_Comp_LSB" , 0x0073}, + {"Tim_Comp_MSB" , 0x0074}, + {"TI_Config" , 0x0076}, + {"TI_Data" , 0x0077}, + {"TI_Reg0" , 0x0078}, + {"TI_Reg1" , 0x0079}, + {"TI_Reg2" , 0x007A}, + {"TI_Reg3" , 0x007B}, + {"TI_Reg4" , 0x007C}, + {"TI_ROM1" , 0x007D}, + {"TI_ROM2" , 0x007E}, + {"TI_ROM3" , 0x007F}, + {"DVBCI_START_ADDR" , 0x0100}, + {"DVBCI_END_ADDR" , 0x017F}, + {"DATA" , 0x0180}, + {"CTRL" , 0x0181}, + {"QB_HOST" , 0x0182}, + {"LEN_HOST_LSB" , 0x0183}, + {"LEN_HOST_MSB" , 0x0184}, + {"FIFO_TX_TH_LSB" , 0x0185}, + {"FIFO_TX_TH_MSB" , 0x0186}, + {"FIFO_TX_D_NB_LSB" , 0x0187}, + {"FIFO_TX_D_NB_MSB" , 0x0188}, + {"QB_MOD_CURR" , 0x0189}, + {"LEN_MOD_CURR_LSB" , 0x018A}, + {"LEN_MOD_CURR_MSB" , 0x018B}, + {"QB_MOD" , 0x018C}, + {"LEN_MOD_LSB" , 0x018D}, + {"LEN_MOD_MSB" , 0x018E}, + {"FIFO_RX_TH_LSB" , 0x018F}, + {"FIFO_RX_TH_MSB" , 0x0190}, + {"FIFO_RX_D_NB_LSB" , 0x0191}, + {"FIFO_RX_D_NB_MSB" , 0x0192}, + {"IT_STATUS_0" , 0x0193}, + {"IT_STATUS_1" , 0x0194}, + {"IT_MASK_0" , 0x0195}, + {"IT_MASK_1" , 0x0196}, + {"IT_HOST_PIN_CFG" , 0x0200}, + {"CFG_0" , 0x0201}, + {"CFG_1" , 0x0202}, + {"CFG_2" , 0x0203}, + {"IT_HOST" , 0x0204}, + {"MOD_IT_STATUS" , 0x0205}, + {"MOD_IT_MASK" , 0x0206}, + {"MOD_CTRL_A" , 0x0207}, + {"MOD_CTRL_B" , 0x0208}, + {"DEST_SEL" , 0x0209}, + {"CAM_MSB_ADD" , 0x020A}, + {"GPIO0_DIR" , 0x020B}, + {"GPIO0_DATA_IN" , 0x020C}, + {"GPIO0_DATA_OUT" , 0x020D}, + {"GPIO0_STATUS" , 0x020E}, + {"GPIO0_IT_MASK" , 0x020F}, + {"GPIO0_DFT" , 0x0210}, + {"GPIO0_MASK_DATA" , 0x0211}, + {"GPIO1_DIR" , 0x0212}, + {"GPIO1_DATA_IN" , 0x0213}, + {"GPIO1_DATA_OUT" , 0x0214}, + {"GPIO1_STATUS" , 0x0215}, + {"GPIO1_IT_MASK" , 0x0216}, + {"MEM_ACC_TIME_A" , 0x0217}, + {"MEM_ACC_TIME_B" , 0x0218}, + {"IO_ACC_TIME_A" , 0x0219}, + {"IO_ACC_TIME_B" , 0x021A}, + {"EXT_CH_ACC_TIME_A" , 0x021B}, + {"EXT_CH_ACC_TIME_B" , 0x021C}, + {"PAR_IF_0" , 0x021D}, + {"PAR_IF_1" , 0x021E}, + {"PAR_IF_CTRL" , 0x021F}, + {"PCK_LENGTH" , 0x0220}, + {"USB2TS_CTRL" , 0x0221}, + {"USB2TS0_RDL" , 0x0222}, + {"USB2TS1_RDL" , 0x0223}, + {"TS2USB_CTRL" , 0x0224}, + {"TSOUT_PAR_CTRL" , 0x0225}, + {"TSOUT_PAR_CLK_SEL" , 0x0226}, + {"S2P_CH0_CTRL" , 0x0227}, + {"S2P_CH1_CTRL" , 0x0228}, + {"P2S_CH0_CTRL" , 0x0229}, + {"P2S_CH1_CTRL" , 0x022A}, + {"TS_IT_STATUS" , 0x022B}, + {"TS_IT_MASK" , 0x022C}, + {"IN_SEL" , 0x022D}, + {"OUT_SEL" , 0x022E}, + {"ROUTER_CAM_CH" , 0x022F}, + {"ROUTER_CAM_MOD" , 0x0230}, + {"FIFO_CTRL" , 0x0231}, + {"FIFO1_2_STATUS" , 0x0232}, + {"FIFO3_4_STATUS" , 0x0233}, + {"GAP_REMOVER_CH0_CTRL" , 0x0234}, + {"GAP_REMOVER_CH1_CTRL" , 0x0235}, + {"SYNC_RTV_CTRL" , 0x0236}, + {"SYNC_RTV_CH0_SYNC_NB" , 0x0237}, + {"SYNC_RTV_CH0_PATTERN" , 0x0238}, + {"SYNC_RTV_CH1_SYNC_NB" , 0x0239}, + {"SYNC_RTV_CH1_PATTERN" , 0x023A}, + {"SYNC_RTV_OFFSET_PATT" , 0x023B}, + {"CTRL_FILTER" , 0x023D}, + {"PID_EN_FILTER_CH0" , 0x023E}, + {"PID_EN_FILTER_CH1" , 0x023F}, + {"PID_LSB_FILTER_CH0_0" , 0x0240}, + {"PID_MSB_FILTER_CH0_0" , 0x0241}, + {"PID_LSB_FILTER_CH0_1" , 0x0242}, + {"PID_MSB_FILTER_CH0_1" , 0x0243}, + {"PID_LSB_FILTER_CH0_2" , 0x0244}, + {"PID_MSB_FILTER_CH0_2" , 0x0245}, + {"PID_LSB_FILTER_CH0_3" , 0x0246}, + {"PID_MSB_FILTER_CH0_3" , 0x0247}, + {"PID_LSB_FILTER_CH0_4" , 0x0248}, + {"PID_MSB_FILTER_CH0_4" , 0x0249}, + {"PID_LSB_FILTER_CH0_5" , 0x024A}, + {"PID_MSB_FILTER_CH0_5" , 0x024B}, + {"PID_LSB_FILTER_CH0_6" , 0x024C}, + {"PID_MSB_FILTER_CH0_6" , 0x024D}, + {"PID_LSB_FILTER_CH0_7" , 0x024E}, + {"PID_MSB_FILTER_CH0_7" , 0x024F}, + {"PID_LSB_FILTER_CH1_0" , 0x0260}, + {"PID_MSB_FILTER_CH1_0" , 0x0261}, + {"PID_LSB_FILTER_CH1_1" , 0x0262}, + {"PID_MSB_FILTER_CH1_1" , 0x0263}, + {"PID_LSB_FILTER_CH1_2" , 0x0264}, + {"PID_MSB_FILTER_CH1_2" , 0x0265}, + {"PID_LSB_FILTER_CH1_3" , 0x0266}, + {"PID_MSB_FILTER_CH1_3" , 0x0267}, + {"PID_LSB_FILTER_CH1_4" , 0x0268}, + {"PID_MSB_FILTER_CH1_4" , 0x0269}, + {"PID_LSB_FILTER_CH1_5" , 0x026A}, + {"PID_MSB_FILTER_CH1_5" , 0x026B}, + {"PID_LSB_FILTER_CH1_6" , 0x026C}, + {"PID_MSB_FILTER_CH1_6" , 0x026D}, + {"PID_LSB_FILTER_CH1_7" , 0x026E}, + {"PID_MSB_FILTER_CH1_7" , 0x026F}, + {"PID_OLD_LSB_REMAPPER_0" , 0x0280}, + {"PID_OLD_MSB_REMAPPER_0" , 0x0281}, + {"PID_OLD_LSB_REMAPPER_1" , 0x0282}, + {"PID_OLD_MSB_REMAPPER_1" , 0x0283}, + {"PID_OLD_LSB_REMAPPER_2" , 0x0284}, + {"PID_OLD_MSB_REMAPPER_2" , 0x0285}, + {"PID_OLD_LSB_REMAPPER_3" , 0x0286}, + {"PID_OLD_MSB_REMAPPER_3" , 0x0287}, + {"PID_OLD_LSB_REMAPPER_4" , 0x0288}, + {"PID_OLD_MSB_REMAPPER_4" , 0x0289}, + {"PID_OLD_LSB_REMAPPER_5" , 0x028A}, + {"PID_OLD_MSB_REMAPPER_5" , 0x028B}, + {"PID_OLD_LSB_REMAPPER_6" , 0x028C}, + {"PID_OLD_MSB_REMAPPER_6" , 0x028D}, + {"PID_OLD_LSB_REMAPPER_7" , 0x028E}, + {"PID_OLD_MSB_REMAPPER_7" , 0x028F}, + {"PID_NEW_LSB_REMAPPER_0" , 0x02A0}, + {"PID_NEW_MSB_REMAPPER_0" , 0x02A1}, + {"PID_NEW_LSB_REMAPPER_1" , 0x02A2}, + {"PID_NEW_MSB_REMAPPER_1" , 0x02A3}, + {"PID_NEW_LSB_REMAPPER_2" , 0x02A4}, + {"PID_NEW_MSB_REMAPPER_2" , 0x02A5}, + {"PID_NEW_LSB_REMAPPER_3" , 0x02A6}, + {"PID_NEW_MSB_REMAPPER_3" , 0x02A7}, + {"PID_NEW_LSB_REMAPPER_4" , 0x02A8}, + {"PID_NEW_MSB_REMAPPER_4" , 0x02A9}, + {"PID_NEW_LSB_REMAPPER_5" , 0x02AA}, + {"PID_NEW_MSB_REMAPPER_5" , 0x02AB}, + {"PID_NEW_LSB_REMAPPER_6" , 0x02AC}, + {"PID_NEW_MSB_REMAPPER_6" , 0x02AD}, + {"PID_NEW_LSB_REMAPPER_7" , 0x02AE}, + {"PID_NEW_MSB_REMAPPER_7" , 0x02AF}, + {"MERGER_DIV_MICLK" , 0x02C0}, + {"PID_AND_SYNC_REMAPPER_CTRL" , 0x02C1}, + {"PID_EN_REMAPPER" , 0x02C2}, + {"SYNC_SYMBOL" , 0x02C3}, + {"PID_AND_SYNC_REMAPPER_INV_CTRL" , 0x02C4}, + {"BITRATE_CH0_LSB" , 0x02C5}, + {"BITRATE_CH0_MSB" , 0x02C6}, + {"BITRATE_CH1_LSB" , 0x02C7}, + {"BITRATE_CH1_MSB" , 0x02C8}, + {"STATUS_CLK_SWITCH_0" , 0x02C9}, + {"STATUS_CLK_SWITCH_1" , 0x02CA}, + {"RESET_CLK_SWITCH_0" , 0x02CB}, + {"RESET_CLK_SWITCH_1" , 0x02CC}, + {"PAD_DRVSTR_CTRL" , 0x02CD}, + {"PAD_PUPD_CTRL" , 0x02CE}, + {"PRE_HEADER_ADDER_CH0_0" , 0x02D0}, + {"PRE_HEADER_ADDER_CH0_1" , 0x02D1}, + {"PRE_HEADER_ADDER_CH0_2" , 0x02D2}, + {"PRE_HEADER_ADDER_CH0_3" , 0x02D3}, + {"PRE_HEADER_ADDER_CH0_4" , 0x02D4}, + {"PRE_HEADER_ADDER_CH0_5" , 0x02D5}, + {"PRE_HEADER_ADDER_CH0_6" , 0x02D6}, + {"PRE_HEADER_ADDER_CH0_7" , 0x02D7}, + {"PRE_HEADER_ADDER_CH0_8" , 0x02D8}, + {"PRE_HEADER_ADDER_CH0_9" , 0x02D9}, + {"PRE_HEADER_ADDER_CH0_10" , 0x02DA}, + {"PRE_HEADER_ADDER_CH0_11" , 0x02DB}, + {"PRE_HEADER_ADDER_CH1_0" , 0x02E0}, + {"PRE_HEADER_ADDER_CH1_1" , 0x02E1}, + {"PRE_HEADER_ADDER_CH1_2" , 0x02E2}, + {"PRE_HEADER_ADDER_CH1_3" , 0x02E3}, + {"PRE_HEADER_ADDER_CH1_4" , 0x02E4}, + {"PRE_HEADER_ADDER_CH1_5" , 0x02E5}, + {"PRE_HEADER_ADDER_CH1_6" , 0x02E6}, + {"PRE_HEADER_ADDER_CH1_7" , 0x02E7}, + {"PRE_HEADER_ADDER_CH1_8" , 0x02E8}, + {"PRE_HEADER_ADDER_CH1_9" , 0x02E9}, + {"PRE_HEADER_ADDER_CH1_10" , 0x02EA}, + {"PRE_HEADER_ADDER_CH1_11" , 0x02EB}, + {"PRE_HEADER_ADDER_CTRL" , 0x02EC}, + {"PRE_HEADER_ADDER_LEN" , 0x02ED}, + {"PRE_HEADER_REMOVER_CTRL" , 0x02EE}, + {"FSM_DVB" , 0x02F0}, + {"TS2USB_FSM_DEBUG" , 0x02F2}, + {"TSOUT_PAR_FSM_DEBUG" , 0x02F3}, + {"GAP_REMOVER_FSM_DEBUG" , 0x02F4}, + {"PID_AND_SYNC_REMAPPER_FSM_DEBUG" , 0x02F5}, + {"PRE_HEADER_ADDER_FSM_DEBUG" , 0x02F6}, + {"SYNC_RTV_FSM_DEBUG" , 0x02F7}, + {"CHECK_PHY_CLK" , 0x0E00}, + {"CONTROL1" , 0x0E01}, + {"WAKE_UP" , 0x0E02}, + {"CONTROL2" , 0x0E03}, + {"PHY_RELATED" , 0x0E04}, + {"EP_CFG" , 0x0E05}, + {"MAX_PKT_EP1L" , 0x0E06}, + {"MAX_PKT_EP1H" , 0x0E07}, + {"MAX_PKT_EP2L" , 0x0E08}, + {"MAX_PKT_EP2H" , 0x0E09}, + {"MAX_PKT_EP3L" , 0x0E0A}, + {"MAX_PKT_EP3H" , 0x0E0B}, + {"MAX_PKT_EP4L" , 0x0E0C}, + {"MAX_PKT_EP4H" , 0x0E0D}, + {"EPS_STALL_SET" , 0x0E10}, + {"EPS_STALL_CLR" , 0x0E11}, + {"EPS_ENABLE" , 0x0E12}, + {"DMA_ACC_EPS" , 0x0E13}, + {"CPU_ACC_EPS_EN" , 0x0E14}, + {"SETUP_BYTE0" , 0x0E15}, + {"SETUP_BYTE1" , 0x0E16}, + {"SETUP_BYTE2" , 0x0E17}, + {"SETUP_BYTE3" , 0x0E18}, + {"SETUP_BYTE4" , 0x0E19}, + {"SETUP_BYTE5" , 0x0E1A}, + {"SETUP_BYTE6" , 0x0E1B}, + {"SETUP_BYTE7" , 0x0E1C}, + {"SETUP_DT_VLD" , 0x0E1D}, + {"CLR_EPS_TOG" , 0x0E1E}, + {"EP0_CTRL" , 0x0E20}, + {"EP0_DATA_CNT" , 0x0E21}, + {"EP0_DATA" , 0x0E22}, + {"EP1_CTRL" , 0x0E30}, + {"EP1_DATA_CNTL" , 0x0E31}, + {"EP1_DATA_CNTH" , 0x0E32}, + {"EP1_DATA" , 0x0E33}, + {"EP1_HEADER" , 0x0E34}, + {"EP2_CTRL" , 0x0E40}, + {"EP2_DATA_CNTL" , 0x0E41}, + {"EP2_DATA_CNTH" , 0x0E42}, + {"EP2_DATA" , 0x0E43}, + {"EP2_HEADER" , 0x0E44}, + {"EP3_DATA_CNTL" , 0x0E50}, + {"EP3_DATA_CNTH" , 0x0E51}, + {"EP3_DATA" , 0x0E52}, + {"EP3_HEADER" , 0x0E53}, + {"EP3_HEADER_CNT" , 0x0E54}, + {"EP3_HEADER_DATA" , 0x0E55}, + {"EP4_DATA_CNTL" , 0x0E60}, + {"EP4_DATA_CNTH" , 0x0E61}, + {"EP4_DATA" , 0x0E62}, + {"EP4_HEADER" , 0x0E63}, + {"EP4_HEADER_CNT" , 0x0E64}, + {"EP4_HEADER_DATA" , 0x0E65}, + {"EP5_CTRL" , 0x0E70}, + {"EP5_DATA_CNTL" , 0x0E71}, + {"EP5_DATA_CNTH" , 0x0E72}, + {"EP5_DATA" , 0x0E73}, + {"MAX_PKT_EP5L" , 0x0E74}, + {"MAX_PKT_EP5H" , 0x0E75}, + {"EP6_DATA_CNTL" , 0x0E80}, + {"EP6_DATA_CNTH" , 0x0E81}, + {"EP6_DATA" , 0x0E82}, + {"MAX_PKT_EP6L" , 0x0E83}, + {"MAX_PKT_EP6H" , 0x0E84}, + {"FRAME_NUML" , 0x0E90}, + {"FRAME_NUMH" , 0x0E91}, + {"FRAME_TIMEL" , 0x0E92}, + {"FRAME_TIMEH" , 0x0E93}, + {"STC_DIVL" , 0x0E94}, + {"STC_DIVM" , 0x0E95}, + {"STC_DIVH" , 0x0E96}, + {"USB_STATUS" , 0x0E97}, + {"DEV_STATE1" , 0x0E98}, + {"DEV_STATE2" , 0x0E99}, + {"DEV_STATE3" , 0x0E9A}, + {"DEV_STATE4" , 0x0E9B}, + {"INTR_EN1" , 0x0EA0}, + {"INTR_EN2" , 0x0EA1}, + {"INTR_EN3" , 0x0EA2}, + {"INTR_EN4" , 0x0EA3}, + {"INTR_SRC1" , 0x0EB0}, + {"INTR_SRC2" , 0x0EB1}, + {"INTR_SRC3" , 0x0EB2}, + {"INTR_SRC4" , 0x0EB3}, + {"INTR_FLAG1" , 0x0EC0}, + {"INTR_FLAG2" , 0x0EC1}, + {"INTR_FLAG3" , 0x0EC2}, + {"INTR_FLAG4" , 0x0EC3}, + {"EP0_INAK_CNT" , 0x0ED0}, + {"EP0_ONAK_CNT" , 0x0ED1}, + {"EP1_NAK_CNT" , 0x0ED2}, + {"EP2_NAK_CNT" , 0x0ED3}, + {"EP3_NAK_CNT" , 0x0ED4}, + {"EP4_NAK_CNT" , 0x0ED5}, + {"EP5_NAK_CNT" , 0x0ED6}, + {"EP6_NAK_CNT" , 0x0ED7}, + {"NAK_CNT_LEVEL" , 0x0ED8}, + {"CC2_Buffer_out" , 0x2000}, + {"CC2_Buffer_in" , 0x4000}, + {"nmb_vector_address_lsb" , 0xFFFA}, + {"nmb_vector_address_msb" , 0xFFFB}, + {"reset_vector_address_lsb" , 0xFFFC}, + {"reset_vector_address_msb" , 0xFFFD}, + {"irb_vector_address_lsb" , 0xFFFE}, + {"irb_vector_address_msb" , 0xFFFF} +}; +#endif diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/cimax+usb-driver.c b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/cimax+usb-driver.c new file mode 100644 index 000000000000..43cdcde5b8eb --- /dev/null +++ b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/cimax+usb-driver.c @@ -0,0 +1,2535 @@ +/**************************************************************************//** + * @file cimax+usb-driver.c + * + * @brief CIMaX+ USB Driver for linux based operating systems. + * + * Copyright (C) 2009-2011 Bruno Tonelli + * & Franck Descours + * for SmarDTV France, La Ciotat + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + ******************************************************************************/ + +#define FRBIT +/*#define DEBUG*/ +/*#define DEBUG_BITRATE*/ +/*#define DEBUG_ISOC_IN*/ +/*#define DEBUG_ISOC_OUT*/ +/*#define DEBUG_CONTINUITY*/ + +/****************************************************************************** + * Include + ******************************************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "cimax+usb-driver.h" +#include "cimax+usb_fw.h" +#include "cimax+usb_config.h" +#ifdef TIMESTAMP +#include "cimax+usb_time.h" +#endif +#include "../../aml_cimax_usb_priv.h" + +/****************************************************************************** + * Defines + *****************************************************************************/ +#define DRIVER_VERSION "v1.1.2" +#define DRIVER_AUTHOR "Bruno Tonelli, tonelli@smardtv.com" +#define DRIVER_DESC "CIMaX+ USB Driver for Linux (c)2009-2011" + +#define DRIVER_MAX_NUMBER 1 + +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_LICENSE("GPL"); + +/****************************************************************************** + * Structures + ******************************************************************************/ +/****************************************************************************** + * Globals + ******************************************************************************/ +#ifdef FRBIT +int CimaxCfg = 1; +module_param_named(CimaxCfg, CimaxCfg, int, 0644); +MODULE_PARM_DESC(CimaxCfg, "Turn on/off configuration of CIMaX+ (default: on)"); +int CimaxDwnl = 1; +module_param_named(CimaxDwnl, CimaxDwnl, int, 0644); +MODULE_PARM_DESC(CimaxDwnl, "Enable upload of FW in CIMaX+ chip (default: on)"); +#endif + +static struct device_s *gdevice; +static unsigned int gdeviceNumber; + +static struct usb_driver device_driver; +static struct timespec gStart; + +static __u8 nullHeader[] = { + 0x47, 0x1F, 0xFF, 0x1F, 0xFA, 0xDE, 0xBA, 0xBE +}; + +static struct bulk_timer_s gbulk_timer[DEVICE_NUM_CAM]; +int (*cimax_usb_dev_add)(struct device_s *device, int id); +int (*cimax_usb_dev_remove)(struct device_s *device, int id); + +#ifdef TIMESTAMP +static int bSetTimestamps; +#endif + +/****************************************************************************** + * Functions + ******************************************************************************/ +#ifdef DEBUG_CONTINUITY +#define TS_MAXPIDS 8192 /* max value of a PID */ +unsigned char tab_cc[TS_MAXPIDS]; + +__u16 get_ts_pid(unsigned char *pid) +{ + __u16 pp = 0; + + pp = (pid[0] & 0X1f)<<8; + pp |= pid[1]; + + return pp; +} + +static void init_tab_cc(void) +{ + memset(tab_cc, 0xff, TS_MAXPIDS); +} + +static int dbg_cc(unsigned char *buf) +{ + int pid; + unsigned char cc; + + if (buf[0] != DEVICE_MPEG2_SYNC_BYTE) { + err("Out Of Sync: "); + return -1; + } + + pid = get_ts_pid(buf + 1); + + if (!(buf[3] & 0x10)) /* no payload?*/ + return 0; + + if (buf[1] & 0x80) + err("Error in TS for PID: %d\n", pid); + + /* Check continuity count*/ + cc = tab_cc[pid]; + if (cc == 255) + cc = (buf[3] & 15); + else { + cc = ((cc) + 1) & 15; + if (cc != (buf[3] & 15)) { + /* Otherwise, this is a real corruption */ + err("pid %d cc %d expected cc %d actual\n", + pid, cc, buf[3] & 15); + cc = (buf[3] & 15); + } + } + return 0; +} +#endif + +/*-------------------------------------------------------------------*/ +#ifdef DEBUG +static void dbg_dump(char *hdr, unsigned char *data, int size) +{ + int i; + char line[40]; + char str[9]; + line[0] = 0; + for (i = 0; i < size; i++) { + sprintf(line, "%s%.2x ", line, data[i]); + if ((data[i] >= 32) && (data[i] <= 126)) + str[i%8] = data[i]; + else + str[i%8] = '.'; + if (!((i+1)%8)) { + str[i%8 + 1] = 0; + dbg_s("%s %s %s", hdr, line, str); + line[0] = 0; + } /* if */ + } /* for */ + if (i%8) { + int j; + str[i%8 + 1] = 0; + for (j = (i%8); j < 8; j++) + sprintf(line, "%s ", line); + dbg_s("%s %s %s", hdr, line, str); + line[0] = 0; + } /* if */ +} /* dbg_dump */ +#else +#define dbg_dump(format, arg...) do {} while (0) +#endif /* DEBUG */ + +static unsigned long copyDataFrom(int us, + void *to, const void *from, unsigned long n) +{ + if (us) + return copy_from_user(to, from, n); + memcpy(to, from, n); + return 0; +} + +static unsigned long copyDataTo(int us, + void *to, const void *from, unsigned long n) +{ + if (us) + return copy_to_user(to, from, n); + memcpy(to, from, n); + return 0; +} + +static void vb_init(struct video_buf_s *buf) +{ + buf->readOffset = 0; + buf->writeOffset = 0; + buf->isEmpty = 1; +} /* vb_init */ + +static int vb_get_write_size(struct video_buf_s *buf) +{ + int writeSize = 0; + + if (buf->writeOffset == buf->readOffset) { + if (buf->isEmpty) + writeSize = DEVICE_VB_LENGTH; + } else if (buf->writeOffset > buf->readOffset) + writeSize = + DEVICE_VB_LENGTH - (buf->writeOffset - buf->readOffset); + else + writeSize = buf->readOffset - buf->writeOffset; + return writeSize; +} /* vb_get_write_size */ + +static int vb_write(struct video_buf_s *buf, __u8 *data, int size) +{ + int writeSize = vb_get_write_size(buf); + int firstPart = DEVICE_VB_LENGTH - buf->writeOffset; + if (size > writeSize) + size = writeSize; + + if (size < firstPart) { + memcpy(&buf->data[buf->writeOffset], data, size); + buf->writeOffset += size; + } /* if */ else { + memcpy(&buf->data[buf->writeOffset], data, firstPart); + memcpy(buf->data, &data[firstPart], size - firstPart); + buf->writeOffset = size - firstPart; + } /* else */ + + if (size > 0) + buf->isEmpty = 0; + return size; +} /* vb_write */ + +static int vb_read_next(struct video_buf_s *buf, __u8 *data) +{ + int readSize; + int firstPart; + int nextOffset; + int isStuffing; + int ret; + + readSize = DEVICE_VB_LENGTH - vb_get_write_size(buf); + nextOffset = buf->readOffset + DEVICE_MPEG2_PACKET_SIZE; + if (nextOffset >= DEVICE_VB_LENGTH) + nextOffset -= DEVICE_VB_LENGTH; + while (readSize > DEVICE_MPEG2_PACKET_SIZE) { + if ((buf->data[buf->readOffset] == DEVICE_MPEG2_SYNC_BYTE) && + (buf->data[nextOffset] == DEVICE_MPEG2_SYNC_BYTE)) { + /* packet in sync */ + break; + } /* if */ + buf->readOffset++; + if (buf->readOffset == DEVICE_VB_LENGTH) + buf->readOffset = 0; + nextOffset++; + if (nextOffset == DEVICE_VB_LENGTH) + nextOffset = 0; + readSize--; + } /* while */ + if (readSize <= DEVICE_MPEG2_PACKET_SIZE) { + buf->isEmpty = 1; + return 0; + } /* if */ + + /* packet is in sync, check if it is a stuffing packet */ + isStuffing = 0; + firstPart = DEVICE_VB_LENGTH - buf->readOffset; + if (firstPart < DEVICE_NULL_HEADER_SIZE) { + if ((memcmp(nullHeader, &buf->data[buf->readOffset], firstPart) + == 0) && + (memcmp(&nullHeader[firstPart], buf->data, + DEVICE_NULL_HEADER_SIZE - firstPart) + == 0)) { + isStuffing = 1; + } /* if */ + } /* if */ + else { + if (memcmp(nullHeader, &buf->data[buf->readOffset], + DEVICE_NULL_HEADER_SIZE) == 0) { + isStuffing = 1; + } /* if */ + } /* else */ + readSize -= DEVICE_MPEG2_PACKET_SIZE; + if (readSize <= DEVICE_MPEG2_PACKET_SIZE) + buf->isEmpty = 1; + + /* skip stuffing packet */ + if (isStuffing) { + buf->readOffset = nextOffset; + return 0; + } /* if */ + + /* copy packet to user space */ + if (firstPart >= DEVICE_MPEG2_PACKET_SIZE) { + ret = copy_to_user(data, + &buf->data[buf->readOffset], DEVICE_MPEG2_PACKET_SIZE); + } /* if */ else { + ret = copy_to_user(data, + &buf->data[buf->readOffset], firstPart); + ret = copy_to_user(&data[firstPart], + buf->data, DEVICE_MPEG2_PACKET_SIZE - firstPart); + } /* else */ + buf->readOffset = nextOffset; + return DEVICE_MPEG2_PACKET_SIZE; +} /* vb_read_next */ + +/*-------------------------------------------------------------------*/ +#ifdef DEBUG_BITRATE +static void print_bitrate(struct ts_channel_s *channel, __u8 channel_number) +{ + int readSize; + ktime_t currentTime; + int diffTime_us; + int bitrate; + + currentTime = ktime_get_real(); + if (!(channel->bitrateTime.tv64)) { + channel->bitrateTime = currentTime; + } else { + readSize = DEVICE_VB_LENGTH - vb_get_write_size(&channel->inVb); + dbg("%d bytes received\n", readSize); + diffTime_us = (int)(ktime_us_delta(currentTime, + channel->bitrateTime)); + if (diffTime_us) { + bitrate = (int)((readSize * 8 * USEC_PER_SEC) + / diffTime_us); + } + channel->bitrateTime = currentTime; + dbg("received bitrate for channel[%d] = %dbps\n", + channel_number, bitrate); + } +} +#endif /* DEBUG_BITRATE */ +/*-------------------------------------------------------------------*/ + +static void device_cibulk_complete(struct urb *urb) +{ + dbg("start"); + kfree(urb->transfer_buffer); + usb_free_urb(urb); + dbg("end"); +} /* device_cibulk_complete */ + +static int device_cibulk_send(struct device_s *device, + struct ioctl_data_s *data, + int user_space) +{ + int res; + struct urb *urb; + int size; + int index = -1; + __u8 *ptr; + __u32 todo = data->txSize; + __u8 *userData = data->txData; + + dbg("start"); + + do { + /* get a free bulk message */ + urb = usb_alloc_urb(0, GFP_KERNEL); + if (!urb) { + err("alloc urb"); + return -ENOMEM; + } /* if */ + urb->dev = device->usbdev; + + /* allocate bulk data */ + size = device->ciBulk.outMaxPacketSize; + if (todo < size) + size = todo; + urb->transfer_buffer = kmalloc(size, GFP_KERNEL); + if (!urb->transfer_buffer) { + err("alloc transfer buffer"); + usb_free_urb(urb); + return -ENOMEM; + } /* if */ + + /* copy data */ + ptr = urb->transfer_buffer; + res = copyDataFrom(user_space, ptr, userData, size); + +#ifdef TIMESTAMP + if (bSetTimestamps) { + if (index == -1) { + SetTimestamp("urb %x, toSend %d, send %d", + urb, todo, size); + SetTimestamp("cmd 0x%02x", ptr[0]); + } else { + SetTimestamp("urb %x, toSend %d, send %d", + urb, todo, size); + } + } +#endif + + /* first packet, get index */ + if (index == -1) { + if ((ptr[DEVICE_COMMAND_OFFSET] == DEVICE_CMD_INIT) || + (ptr[DEVICE_COMMAND_OFFSET] + == DEVICE_CMD_WRITE_REG) || + (ptr[DEVICE_COMMAND_OFFSET] + == DEVICE_CMD_READ_REG)) { + index = 0; /* register command, no module */ + } else if (ptr[DEVICE_COMMAND_OFFSET] + & DEVICE_SEL_MASK) { + index = 1; /* module B */ + } else { + index = 0; /* module A */ + } /* else */ + device->ciBulk.ciData[index].syncDataSize = 0; + device->ciBulk.ciData[index].syncSignal = 0; + } /* if */ + + /* submit bulk */ + urb->pipe = usb_sndbulkpipe(device->usbdev, + DEVICE_BULK_OUT_PIPE); + urb->transfer_buffer_length = size; + urb->complete = device_cibulk_complete; + urb->context = NULL; + dbg_dump("txBuf", urb->transfer_buffer, + urb->transfer_buffer_length); + res = usb_submit_urb(urb, GFP_KERNEL); + if (res < 0) { + err("submit urb res = %d", res); + kfree(urb->transfer_buffer); + usb_free_urb(urb); + return -ENOMEM; + } /* if */ + todo -= size; + userData += size; + } while (todo); + + device->ciBulk.ciData[index].bPendingSend = 1; + dbg("end"); + return index; +} /* device_cibulk_send */ + +static void device_int_complete(struct urb *urb) +{ + unsigned long flags; + struct device_s *device = urb->context; + __u8 *dataToCopy; + int sizeToCopy, SizeReceived; + __u8 isFirstPacket = 0; + __u8 isLastPacket = 0; + __u8 index, i; + __u8 status; + struct message_node_s *message; + + dbg("start"); + + if (urb->status) { + dbg("urb status %d, not submitted again", urb->status); + kfree(urb->transfer_buffer); + usb_free_urb(urb); + for (i = 0; i < DEVICE_NUM_INT_IN_URBS; i++) { + if (device->ciBulk.intUrb[i] == urb) + device->ciBulk.intUrb[i] = NULL; + } + return; + } /* if */ + + spin_lock_irqsave(&device->ciBulk.intUrbLock, flags); + dbg("urb status %d, transfer_buffer_length %d actual_length %d", + urb->status, + urb->transfer_buffer_length, + urb->actual_length); + dataToCopy = urb->transfer_buffer; + SizeReceived = urb->actual_length; + dbg_dump("total rxBuf", dataToCopy, SizeReceived); + + + do { + if (device->ciBulk.intSizeToReceive == 0) { + if (!dataToCopy[DEVICE_STATUS_OFFSET] && + !dataToCopy[DEVICE_LENGTH_MSB_OFFSET] && + !dataToCopy[DEVICE_LENGTH_LSB_OFFSET] && + !dataToCopy[DEVICE_COUNTER_OFFSET]){ + dbg("no data receive"); + memset(urb->transfer_buffer, + 0, urb->transfer_buffer_length); + usb_submit_urb(urb, GFP_ATOMIC); + return; + } + /* first packet, read header */ + isFirstPacket = 1; + device->ciBulk.intCurrStatus = + dataToCopy[DEVICE_STATUS_OFFSET] & + DEVICE_CMD_MASK; + if (dataToCopy[DEVICE_STATUS_OFFSET] + & DEVICE_SEL_MASK) { + device->ciBulk.intCurrIndex = 1; /* module B */ + } else { + device->ciBulk.intCurrIndex = 0; /* module A */ + } + if ((device->ciBulk.intCurrStatus == DEVICE_READ_REGOK) + || (device->ciBulk.intCurrStatus + == DEVICE_WRITE_REGOK)) { + device->ciBulk.intSizeToReceive = + dataToCopy[DEVICE_LENGTH_LSB_OFFSET] + + DEVICE_DATA_OFFSET; + } else { + device->ciBulk.intSizeToReceive = + dataToCopy[DEVICE_LENGTH_MSB_OFFSET] * 256 + + dataToCopy[DEVICE_LENGTH_LSB_OFFSET] + + DEVICE_DATA_OFFSET; + } + } /* if */ + + /* get last packet state */ + status = device->ciBulk.intCurrStatus; + index = device->ciBulk.intCurrIndex; + sizeToCopy = device->ciBulk.intSizeToReceive; + if (sizeToCopy > urb->actual_length) { + /* limit size to received buffer size */ + sizeToCopy = urb->actual_length; + } /* if */ else + isLastPacket = 1; + dbg_dump("rxBuf", dataToCopy, sizeToCopy); + +#ifndef FRBIT + if (status == DEVICE_DATAREADY) { + if (device->ciBulk.ciData[index].bPendingSend) + status = DEVICE_DATAREADY_SYNC; + } +#endif + +#ifdef TIMESTAMP + if (device->ciBulk.intSizeToReceive > 2000) + bSetTimestamps = 1; + if (bSetTimestamps) { + SetTimestamp("urb %x,toReceive %d,received %d,toCopy%d", + urb, + device->ciBulk.intSizeToReceive, + SizeReceived, + sizeToCopy); + SetTimestamp("status 0x%02x, camIndex %d, isLast %d", + status, index, isLastPacket); + } +#endif + + switch (status) { + case DEVICE_INITOK: + case DEVICE_READ_REGOK: + case DEVICE_WRITE_REGOK: + index = 0; + case DEVICE_CAMRESETOK: + /*only for debug*/ + if (!dataToCopy[DEVICE_STATUS_OFFSET] && + !dataToCopy[DEVICE_LENGTH_MSB_OFFSET] && + !dataToCopy[DEVICE_LENGTH_LSB_OFFSET] && + !dataToCopy[DEVICE_COUNTER_OFFSET]){ + break; + } + case DEVICE_CISOK: + case DEVICE_WRITECOROK: + case DEVICE_NEGOTIATEOK: + case DEVICE_WRITELPDUOK: + case DEVICE_WRITELPDUBUSY: + case DEVICE_READLPDUOK: + case DEVICE_WRITEEXTOK: + case DEVICE_READEXTOK: + case DEVICE_NO_CAM: + case DEVICE_NOK: + case DEVICE_MCARD_WRITEOK: + case DEVICE_CAMPARSE_ERROR: + case DEVICE_CMDPENDING: + case DEVICE_REGSTATUSOK: + case DEVICE_DATAREADY_SYNC: + /* copy partial message */ + spin_lock_irqsave(&device->ciBulk.intLock, + flags); + memcpy(&device->ciBulk.ciData[index]. + syncData[device->ciBulk.ciData[index]. + syncDataSize], + dataToCopy, sizeToCopy); + device->ciBulk.intSizeToReceive -= sizeToCopy; + device->ciBulk.ciData[index].syncDataSize += + sizeToCopy; + spin_unlock_irqrestore(&device->ciBulk.intLock, + flags); + dbg("copied %d bytes at offset %d", sizeToCopy, + device->ciBulk.ciData[index]. + syncDataSize - sizeToCopy); + + if (isLastPacket) { + /* last packet received, sync message */ + device->ciBulk.ciData[index].syncSignal = 1; + wake_up_interruptible(&device->ciBulk. + ciData[index].syncWait); + device->ciBulk.ciData[index].bPendingSend = 0; + dbg("sync signal return %d %d ", + device->ciBulk.ciData[index]. + syncDataSize, index); + } /* if */ + break; + case DEVICE_CAMDET: + case DEVICE_DATAREADY: + case DEVICE_MCARD_READ: + case DEVICE_FRBit: + if (isFirstPacket) { + /* create new async message */ + message = kmalloc(sizeof(struct message_node_s), + GFP_ATOMIC); + if (!message) { + err("cannot allocate async message"); + break; + } + memset(message, + 0, sizeof(struct message_node_s)); + list_add_tail(&message->node, + &device->ciBulk.ciData[index]. + asyncDataList); + } /* if */ + else { + /* get tail message */ + message = list_entry((device->ciBulk. + ciData[index].asyncDataList.prev), + struct message_node_s, node); + } /* else */ + + /* copy partial message */ + spin_lock_irqsave(&device->ciBulk.intLock, flags); + memcpy(&message->data[message->size], + dataToCopy, sizeToCopy); + device->ciBulk.intSizeToReceive -= sizeToCopy; + message->size += sizeToCopy; + spin_unlock_irqrestore(&device->ciBulk.intLock, flags); + dbg("async copied %d bytes at offset %d", sizeToCopy, + message->size - sizeToCopy); + + if (isLastPacket) { + /* last packet received, signal async message */ + wake_up_interruptible(&device->ciBulk. + ciData[index].asyncWait); + dbg("async signal %d", index); + } /* if */ + break; + case DEVICE_GPIOCHANGE: + info("GPIO change %x %x %x", + status, dataToCopy[4], dataToCopy[5]); + device->ciBulk.intSizeToReceive -= sizeToCopy; + break; + default: + err("unknown status 0x%2x", status); + break; + } /* switch */ + dataToCopy += sizeToCopy; + SizeReceived -= sizeToCopy; + + } while (SizeReceived > 0); + + memset(urb->transfer_buffer, 0, urb->transfer_buffer_length); + usb_submit_urb(urb, GFP_ATOMIC); + +#ifdef TIMESTAMP + /*if (bSetTimestamps) { + SetTimestamp("urb %x submitted", urb); + }*/ +#endif + + spin_unlock_irqrestore(&device->ciBulk.intUrbLock, flags); + + dbg("end"); +} /* device_int_complete */ + +static int device_wait_sync_data(struct device_s *device, + __u8 index, + struct ioctl_data_s *data, + int user_space) +{ + unsigned long flags; + int ret; + + dbg("start %d", index); + + spin_lock_irqsave(&device->ciBulk.intLock, flags); + while (device->ciBulk.ciData[index].syncSignal == 0) { + /* nothing to copy */ + spin_unlock_irqrestore(&device->ciBulk.intLock, flags); + if (wait_event_interruptible(device->ciBulk. + ciData[index].syncWait, + device->ciBulk.ciData[index].syncSignal)) { + device->ciBulk.ciData[index].bPendingSend = 0; + err("interrupt"); + return -ERESTARTSYS; + /* signal: tell the fs layer to handle it */ + } /* if */ + /* otherwise loop, but first reacquire the lock */ + spin_lock_irqsave(&device->ciBulk.intLock, flags); + } /* while */ + + /* copy packet to user space buffer */ + if (device->ciBulk.ciData[index].syncDataSize < data->rxSize) + /* truncate returned message against user buffer size */ + data->rxSize = device->ciBulk.ciData[index].syncDataSize; + spin_unlock_irqrestore(&device->ciBulk.intLock, flags); + /* release the lock */ + ret = copyDataTo(user_space, + data->rxData, + device->ciBulk.ciData[index].syncData, data->rxSize); + dbg_dump("userMsg", + device->ciBulk.ciData[index].syncData, data->rxSize); + dbg("userRet %d", data->rxSize); + device->ciBulk.ciData[index].syncDataSize = 0; + device->ciBulk.ciData[index].syncSignal = 0; + + dbg("end"); + return 0; +} /* device_wait_sync_data */ + +static int device_wait_async_data(struct device_s *device, + __u8 index, + struct rw_data_s *data, + int user_space) +{ + struct list_head *item; + struct message_node_s *message; + unsigned long flags; + int ret; + + dbg("start %d", index); + + if ((device->askToRelease) || (device->askToSuspend)) { + err("ask to release or ask to suspend"); + return -EINTR; /* device close interrupt */ + } /* if */ + + if (index >= DEVICE_NUM_CAM) { + err("bad index(%d)", index); + return -EINVAL; + } + + spin_lock_irqsave(&device->ciBulk.intLock, flags); + while (list_empty(&device->ciBulk.ciData[index].asyncDataList)) { + /* nothing to copy */ + spin_unlock_irqrestore(&device->ciBulk.intLock, flags); + /* release the lock */ + if (wait_event_interruptible(device->ciBulk. + ciData[index].asyncWait, + device->askToRelease || + device->askToSuspend || + (!list_empty(&device->ciBulk. + ciData[index].asyncDataList)))) { + err("interrupt"); + return -ERESTARTSYS; + /* signal: tell the fs layer to handle it */ + } /* if */ + if ((device->askToRelease) || (device->askToSuspend)) { + err("ask to release or ask to suspend"); + return -EINTR; /* device close interrupt */ + } /* if */ + /* otherwise loop, but first reacquire the lock */ + spin_lock_irqsave(&device->ciBulk.intLock, flags); + } /* while */ + + /* ok, data is there, return first item */ + item = device->ciBulk.ciData[index].asyncDataList.next; + message = list_entry(item, struct message_node_s, node); + if (message->size < data->size) { + /* truncate returned message against user buffer size */ + data->size = message->size; + } /* if */ + spin_unlock_irqrestore(&device->ciBulk.intLock, flags); + /* release the lock */ + ret = copyDataTo(user_space, data->data, message->data, data->size); + dbg_dump("userMsg", message->data, data->size); + dbg("userRet %d", data->size); + list_del(item); + kfree(message); + + dbg("end"); + return 0; +} /* device_wait_async_data */ + +static int device_start_intr(struct device_s *device) +{ + __u8 i, j; + struct urb *urb; + + dbg("start"); + + for (i = 0; i < DEVICE_NUM_INT_IN_URBS; i++) { + urb = usb_alloc_urb(0, GFP_KERNEL); + if (!urb) { + err("alloc urb"); + return -ENOMEM; + } /* if */ + urb->transfer_buffer = + kmalloc(device->ciBulk.inMaxPacketSize, GFP_KERNEL); + if (!urb->transfer_buffer) { + err("alloc transfer buffer"); + usb_free_urb(urb); + urb = NULL; + return -ENOMEM; + } /* if */ + + urb->dev = device->usbdev; + urb->pipe = usb_rcvintpipe(device->usbdev, DEVICE_INT_IN_PIPE); + urb->transfer_buffer_length = device->ciBulk.inMaxPacketSize; + urb->complete = device_int_complete; + urb->context = device; + urb->interval = 1; + device->ciBulk.intUrb[i] = urb; + for (j = 0; j < DEVICE_NUM_CAM; j++) { + init_waitqueue_head(&device->ciBulk.ciData[j].syncWait); + init_waitqueue_head(&device->ciBulk. + ciData[j].asyncWait); + } /* for */ + usb_submit_urb(device->ciBulk.intUrb[i], GFP_KERNEL); + } + + dbg("end"); + return 0; +} /* device_start_intr */ + +static void device_stop_intr(struct device_s *device) +{ + struct list_head *item; + struct list_head *tmp; + struct message_node_s *message; + int i, j; + + dbg("start"); + + for (i = 0; i < DEVICE_NUM_INT_IN_URBS; i++) { + if (!device->ciBulk.intUrb[i]) + break; + usb_unlink_urb(device->ciBulk.intUrb[i]); + device->ciBulk.intUrb[i] = NULL; + for (j = 0; j < DEVICE_NUM_CAM; j++) { + for (item = device->ciBulk.ciData[j].asyncDataList.next; + item != &device->ciBulk.ciData[j].asyncDataList; + ) { + message = list_entry(item, + struct message_node_s, node); + tmp = item->next; + list_del(item); + kfree(item); + item = tmp; + } /* for */ + } /* for */ + dbg("unlink urb"); + } + + dbg("end"); +} /* device_stop_intr */ + +static void device_iso_in_complete(struct urb *urb) +{ + unsigned long flags; + struct ts_channel_s *channel = urb->context; + __u8 i; + __u8 *data; + + /*dbg("start");*/ + + if (urb->status) { + dbg("urb status %d, not submitted again", urb->status); + kfree(urb->transfer_buffer); + usb_free_urb(urb); + return; + } /* if */ + + spin_lock_irqsave(&channel->inLock, flags); + for (i = 0; i < urb->number_of_packets; i++) { + data = urb->transfer_buffer + urb->iso_frame_desc[i].offset; + if (!urb->iso_frame_desc[i].status && + (urb->iso_frame_desc[i].actual_length > 0)) { + if (vb_get_write_size(&channel->inVb) + >= urb->iso_frame_desc[i].actual_length) { + vb_write(&channel->inVb, data, + urb->iso_frame_desc[i].actual_length); + } /* if */ + else { + err("video buffer is full, packet loss %d", + urb->iso_frame_desc[i].actual_length); + } /* else */ + } /* if */ + else { + err("frame rejected, status %x, actual_length %d bytes", + urb->iso_frame_desc[i].status, + urb->iso_frame_desc[i].actual_length); + } + } /* for */ + spin_unlock_irqrestore(&channel->inLock, flags); + + if (!channel->inVb.isEmpty) + wake_up_interruptible(&channel->inWait); + + memset(urb->transfer_buffer, + 0, DEVICE_ISOC_LENGTH(channel->maxPacketSize)); + urb->transfer_buffer_length = + DEVICE_ISOC_LENGTH(channel->maxPacketSize); + urb->number_of_packets = DEVICE_NUM_FRAMES_PER_URB; + urb->complete = device_iso_in_complete; + urb->context = channel; + urb->transfer_flags = URB_ISO_ASAP; + urb->interval = 1; + for (i = 0; i < DEVICE_NUM_FRAMES_PER_URB; i++) { + urb->iso_frame_desc[i].offset = i * channel->maxPacketSize; + urb->iso_frame_desc[i].length = channel->maxPacketSize; + } /* for */ + usb_submit_urb(urb, GFP_ATOMIC); + + /*dbg("end");*/ +} /* device_iso_in_complete */ + +static void device_tsbulk_in_complete(struct urb *urb) +{ + unsigned long flags; + struct ts_channel_s *channel = urb->context; + __u8 *data; +#ifdef DEBUG_CONTINUITY + unsigned int i; +#endif + + /*dbg("start");*/ + + if (urb->status) { + err("urb status %d(%x), not submitted again", + urb->status, urb->status); + kfree(urb->transfer_buffer); + usb_free_urb(urb); + return; + } /* if */ + + spin_lock_irqsave(&channel->inLock, flags); + data = urb->transfer_buffer; + +#ifdef DEBUG_CONTINUITY + i = 0; + /* check synchro byte*/ + while (i < urb->actual_length) { + if (!((data[i] == DEVICE_MPEG2_SYNC_BYTE) && + (data[i+DEVICE_MPEG2_PACKET_SIZE] + == DEVICE_MPEG2_SYNC_BYTE))) { + i++; + } else { + /* Synchro find*/ + break; + } + } + + /* Synchro Ok, check discontinuity*/ + while (i < urb->actual_length) { + if (dbg_cc(&data[i]) < 0) { + dbg("(actual_length= %d i=%d pkt=%d)", + urb->actual_length, + i, + i/DEVICE_MPEG2_PACKET_SIZE); + dbg("%02x %02x %02x %02x %02x %02x %02x %02x\n", + data[i-4], data[i-3], data[i-2], data[i-1], + data[i], data[i+1], data[i+2], data[i+3]); + } + i += DEVICE_MPEG2_PACKET_SIZE; + } +#endif + + if (urb->actual_length) { + channel->nbByteRead += urb->actual_length; + if (vb_get_write_size(&channel->inVb) >= urb->actual_length) + vb_write(&channel->inVb, data, urb->actual_length); + else + err("video buffer is full, packet loss %d", + urb->actual_length); + } else { + /*warn("receive size of 0\n");*/ + } + + spin_unlock_irqrestore(&channel->inLock, flags); + /* dbg("urb->actual_length=%d",urb->actual_length);*/ + /* info("urb->actual_length=%d\n",urb->actual_length);*/ + + if (!channel->inVb.isEmpty) + wake_up_interruptible(&channel->inWait); + kfree(urb->transfer_buffer); + usb_free_urb(urb); + /*dbg("end");*/ +} /* device_tsbulk_in_complete */ + +static int device_fill_ts(struct device_s *device, + __u8 index, + struct rw_data_s *data) +{ + unsigned long flags; + __u32 copiedSize; + struct ts_channel_s *channel = &device->channel[index]; + + /*dbg("start");*/ + + spin_lock_irqsave(&channel->inLock, flags); + do { + while (channel->inVb.isEmpty) { + /* nothing to copy */ + spin_unlock_irqrestore(&channel->inLock, flags); + /* release the lock */ + if (wait_event_interruptible(channel->inWait, + device->askToRelease || + device->askToSuspend || + (!channel->inVb.isEmpty))) { + err("interrupt"); + return -ERESTARTSYS; + /* signal: tell the fs layer to handle it */ + } /* if */ + if ((device->askToRelease) || (device->askToSuspend)) { + err("ask to release or ask to suspend"); + return -EINTR; /* device close interrupt */ + } /* if */ + /* otherwise loop, but first reacquire the lock */ + spin_lock_irqsave(&channel->inLock, flags); + } /* while */ + + spin_unlock_irqrestore(&channel->inLock, flags); + + copiedSize = vb_read_next(&channel->inVb, + &data->data[data->copiedSize]); + if (copiedSize) { + /*dbg("copied %d bytes in buffer 0x%p, offset %d", + copiedSize, data->data, data->copiedSize);*/ + data->copiedSize += copiedSize; + } /* if */ + spin_lock_irqsave(&channel->inLock, flags); + } while ((data->copiedSize+DEVICE_MPEG2_PACKET_SIZE) <= data->size); + /* buffer not full */ + + spin_unlock_irqrestore(&channel->inLock, flags); + +#ifdef DEBUG_BITRATE + print_bitrate(channel, index); +#endif + + /*dbg("end, buffer 0x%p", data->data);*/ + return 0; +} /* device_fill_ts */ + +static int device_start_iso_in(struct device_s *device, __u8 index) +{ + int i, j; + int ret = 0; + struct urb *urb; + + /*dbg("start");*/ + +#ifdef DEBUG_BITRATE + device->channel[index].bitrateTime = ktime_set(0, 0); +#endif + for (i = 0; i < DEVICE_NUM_ISOC_IN_URBS; i++) { + urb = usb_alloc_urb(DEVICE_NUM_FRAMES_PER_URB, GFP_KERNEL); + device->channel[index].isocInUrb[i] = urb; + if (urb) { + /*urb->transfer_buffer = + kmalloc(DEVICE_ISOC_LENGTH, GFP_KERNEL);*/ + urb->transfer_buffer = + kmalloc(DEVICE_ISOC_LENGTH( + device->channel[index].maxPacketSize), + GFP_KERNEL); + if (!urb->transfer_buffer) { + ret = -ENOMEM; + err("transfer_buffer allocation failed %d", i); + break; + } /* if */ + } /* if */ else { + ret = -ENOMEM; + err("usb_alloc_urb failed %d", i); + break; + } /* if */ + } /* for */ + + if (ret) { + /* Allocation error, must free already allocated data */ + for (i = 0; i < DEVICE_NUM_ISOC_IN_URBS; i++) { + urb = device->channel[index].isocInUrb[i]; + if (urb) { + kfree(urb->transfer_buffer); + if (urb->transfer_buffer) + urb->transfer_buffer = NULL; + usb_free_urb(urb); + device->channel[index].isocInUrb[i] = NULL; + } /* if */ + } /* for */ + return ret; + } /* if */ + + for (i = 0; i < DEVICE_NUM_ISOC_IN_URBS; i++) { + urb = device->channel[index].isocInUrb[i]; + memset(urb->transfer_buffer, + 0, + DEVICE_ISOC_LENGTH( + device->channel[index].maxPacketSize)); + urb->transfer_buffer_length = + DEVICE_ISOC_LENGTH( + device->channel[index].maxPacketSize); + urb->number_of_packets = DEVICE_NUM_FRAMES_PER_URB; + urb->complete = device_iso_in_complete; + urb->context = &device->channel[index]; + urb->dev = device->usbdev; + urb->pipe = usb_rcvisocpipe( + device->usbdev, DEVICE_TS_IN_PIPE + index); + urb->transfer_flags = URB_ISO_ASAP; + urb->interval = 1; + for (j = 0; j < DEVICE_NUM_FRAMES_PER_URB; j++) { + urb->iso_frame_desc[j].offset = + j * device->channel[index].maxPacketSize; + urb->iso_frame_desc[j].length = + device->channel[index].maxPacketSize; + } /* for */ + } /* for */ + for (i = 0; i < DEVICE_NUM_ISOC_IN_URBS; i++) + usb_submit_urb(device->channel[index].isocInUrb[i], GFP_KERNEL); + + /*dbg("end");*/ + return 0; +} /* device_start_iso_in */ + +static void device_stop_iso_in(struct device_s *device, __u8 index) +{ + int i; + + /*dbg("start");*/ + + for (i = 0; i < DEVICE_NUM_ISOC_IN_URBS; i++) { + if (device->channel[index].isocInUrb[i]) { + usb_unlink_urb(device->channel[index].isocInUrb[i]); + device->channel[index].isocInUrb[i] = NULL; + dbg("unlink urb %i", i); + } /* if */ + } /* for */ + + /*dbg("end");*/ +} /* device_stop_iso_in */ + +static int device_start_tsbulk_in(struct device_s *device, __u8 index) +{ + struct urb *urb; + + dbg("start"); + + urb = usb_alloc_urb(0, GFP_KERNEL); + if (urb) { + urb->transfer_buffer = kmalloc(3072, GFP_KERNEL); + if (!urb->transfer_buffer) { + err("transfer_buffer allocation failed"); + usb_free_urb(urb); + return -ENOMEM; + } /* if */ + } /* if */ else { + err("usb_alloc_urb failed"); + return -ENOMEM; + } /* if */ + device->channel[index].bulkInUrb = urb; + memset(urb->transfer_buffer, 0, 3072); + urb->transfer_buffer_length = 3072; + + urb->complete = device_tsbulk_in_complete; + urb->context = &device->channel[index]; + urb->dev = device->usbdev; + urb->pipe = usb_rcvbulkpipe(device->usbdev, DEVICE_TS_IN_PIPE + index); + usb_submit_urb(device->channel[index].bulkInUrb, GFP_KERNEL); + + dbg("end"); + return 0; +} /* device_start_tsbulk_in */ + +static void device_stop_tsbulk_in(struct device_s *device, __u8 index) +{ + dbg("start"); + + if (device->channel[index].bulkInUrb) { + usb_unlink_urb(device->channel[index].bulkInUrb); + device->channel[index].bulkInUrb = NULL; + dbg("unlink urb"); + } /* if */ + + dbg("end"); +} /* device_stop_tsbulk_in */ + +static void device_iso_out_complete(struct urb *urb) +{ + struct ts_channel_s *channel = urb->context; + struct urb *tmpUrb; + int i; + int ret = 0; + + /*dbg("start");*/ + +/*dbg_dump("txBuf", urb->transfer_buffer, urb->transfer_buffer_length);*/ + + if (urb->status || channel->outStop) { + /* error, free all coming urbs */ + err("free urb"); + channel->outStop = 1; + atomic_dec(&channel->numOutUrbs); + kfree(urb->transfer_buffer); + usb_free_urb(urb); + return; + } /* if */ + + for (i = 0; i < DEVICE_NUM_ISOC_OUT_URBS; i++) { + if (urb == channel->isocOutUrb[i]) + break; + } /* for */ + if (i == DEVICE_NUM_ISOC_OUT_URBS) { + /* urb must be deleted */ + kfree(urb->transfer_buffer); + usb_free_urb(urb); + } /* if */ + + if (atomic_dec_and_test(&channel->numOutUrbs)) { + /* get next free urb */ + tmpUrb = channel->isocOutUrb[channel->nextFreeOutUrbIndex++]; + if (channel->nextFreeOutUrbIndex == DEVICE_NUM_ISOC_OUT_URBS) + channel->nextFreeOutUrbIndex = 0; + + /* reinitialize urb with null packets */ + memset(tmpUrb->transfer_buffer, + 0xCD, DEVICE_ISOC_LENGTH(channel->maxPacketSize)); + for (i = 0; + i < DEVICE_ISOC_LENGTH(channel->maxPacketSize); + i += DEVICE_MPEG2_PACKET_SIZE) { + memcpy(tmpUrb->transfer_buffer+i, + nullHeader, sizeof(nullHeader)); + } /* for */ + tmpUrb->transfer_buffer_length = + DEVICE_ISOC_LENGTH(channel->maxPacketSize); + tmpUrb->number_of_packets = DEVICE_NUM_FRAMES_PER_URB; + tmpUrb->complete = device_iso_out_complete; + tmpUrb->context = channel; + tmpUrb->transfer_flags = URB_ISO_ASAP; + tmpUrb->interval = 1; + for (i = 0; i < DEVICE_NUM_FRAMES_PER_URB; i++) { + tmpUrb->iso_frame_desc[i].offset = + i * channel->maxPacketSize; + tmpUrb->iso_frame_desc[i].length = + channel->maxPacketSize; + } /* for */ + + /* submit urb */ + ret = usb_submit_urb(tmpUrb, GFP_ATOMIC); + if (ret) + err("usb_submit_urb failed %d", ret); + + atomic_inc(&channel->numOutUrbs); + } /* if */ + + /*dbg("end");*/ +} /* device_iso_out_complete */ + +static int device_tsiso_send(struct device_s *device, + __u8 index, __u8 *data, int size) +{ + int i, j; + struct urb **urb; + __u32 numUrbs; + int ret = 0; + + /* dbg("start");*/ + + numUrbs = + size / DEVICE_ISOC_LENGTH(device->channel[index].maxPacketSize); + urb = kmalloc(numUrbs * sizeof(struct urb *), GFP_KERNEL); + if (!urb) { + err("urb array allocation failed %d", numUrbs); + return -ENOMEM; + + } /* if */ + memset(urb, 0, numUrbs * sizeof(struct urb *)); + + for (i = 0; i < numUrbs; i++) { + urb[i] = usb_alloc_urb(DEVICE_NUM_FRAMES_PER_URB, GFP_KERNEL); + if (urb[i]) { + urb[i]->transfer_buffer = + kmalloc(DEVICE_ISOC_LENGTH( + device->channel[index].maxPacketSize), + GFP_KERNEL); + if (!urb[i]->transfer_buffer) { + ret = -ENOMEM; + err("transfer_buffer allocation failed %d", i); + break; + } /* if */ + } /* if */ + else { + ret = -ENOMEM; + err("usb_alloc_urb failed %d", i); + break; + } /* if */ + } /* for */ + if (ret) { + /* Allocation error, must free already allocated data */ + for (i = 0; i < numUrbs; i++) { + if (urb[i]) { + kfree(urb[i]->transfer_buffer); + urb[i]->transfer_buffer = NULL; + usb_free_urb(urb[i]); + urb[i] = NULL; + } /* if */ + } /* for */ + kfree(urb); + return ret; + } /* if */ + + for (i = 0; i < numUrbs; i++) { + ret = copy_from_user(urb[i]->transfer_buffer, + &data[i*DEVICE_ISOC_LENGTH( + device->channel[index].maxPacketSize)], + DEVICE_ISOC_LENGTH( + device->channel[index].maxPacketSize)); + urb[i]->transfer_buffer_length = DEVICE_ISOC_LENGTH( + device->channel[index].maxPacketSize); + urb[i]->number_of_packets = DEVICE_NUM_FRAMES_PER_URB; + urb[i]->complete = device_iso_out_complete; + urb[i]->context = &device->channel[index]; + urb[i]->dev = device->usbdev; + urb[i]->pipe = usb_sndisocpipe(device->usbdev, + DEVICE_TS_OUT_PIPE + index); + urb[i]->transfer_flags = URB_ISO_ASAP; + urb[i]->interval = 1; + for (j = 0; j < DEVICE_NUM_FRAMES_PER_URB; j++) { + urb[i]->iso_frame_desc[j].offset = + j * device->channel[index].maxPacketSize; + urb[i]->iso_frame_desc[j].length = + device->channel[index].maxPacketSize; + } /* for */ + } /* for */ + + atomic_add(numUrbs, &device->channel[index].numOutUrbs); + for (i = 0; i < numUrbs; i++) { + ret = usb_submit_urb(urb[i], GFP_ATOMIC); + if (ret) + err("usb_submit_urb failed %d", ret); + } /* for */ + + kfree(urb); + + /* dbg("end");*/ + return size; +} /* device_tsiso_send */ + +static int device_start_iso_out(struct device_s *device, __u8 index) +{ + int i, j; + int ret = 0; + struct urb *urb; + + /*dbg("start");*/ + + device->channel[index].outStop = 0; + for (i = 0; i < DEVICE_NUM_ISOC_OUT_URBS; i++) { + urb = usb_alloc_urb(DEVICE_NUM_FRAMES_PER_URB, GFP_KERNEL); + device->channel[index].isocOutUrb[i] = urb; + if (urb) { + urb->transfer_buffer = kmalloc(DEVICE_ISOC_LENGTH( + device->channel[index].maxPacketSize), + GFP_KERNEL); + if (!urb->transfer_buffer) { + ret = -ENOMEM; + err("transfer_buffer allocation failed %d", i); + break; + } /* if */ + } /* if */ else { + ret = -ENOMEM; + err("usb_alloc_urb failed %d", i); + break; + } /* if */ + } /* for */ + + if (ret) { + /* Allocation error, must free already allocated data */ + for (i = 0; i < DEVICE_NUM_ISOC_OUT_URBS; i++) { + urb = device->channel[index].isocOutUrb[i]; + if (urb) { + kfree(urb->transfer_buffer); + urb->transfer_buffer = NULL; + usb_free_urb(urb); + device->channel[index].isocOutUrb[i] = NULL; + } /* if */ + } /* for */ + return ret; + } /* if */ + + for (i = 0; i < DEVICE_NUM_ISOC_OUT_URBS; i++) { + urb = device->channel[index].isocOutUrb[i]; + memset(urb->transfer_buffer, 0, DEVICE_ISOC_LENGTH( + device->channel[index].maxPacketSize)); + for (j = 0; + j < DEVICE_ISOC_LENGTH( + device->channel[index].maxPacketSize); + j += DEVICE_MPEG2_PACKET_SIZE) { + memcpy(urb->transfer_buffer+j, + nullHeader, sizeof(nullHeader)); + } /* for */ + urb->transfer_buffer_length = DEVICE_ISOC_LENGTH( + device->channel[index].maxPacketSize); + urb->number_of_packets = DEVICE_NUM_FRAMES_PER_URB; + urb->complete = device_iso_out_complete; + urb->context = &device->channel[index]; + urb->dev = device->usbdev; + urb->pipe = usb_sndisocpipe(device->usbdev, + DEVICE_TS_OUT_PIPE + index); + urb->transfer_flags = URB_ISO_ASAP; + urb->interval = 1; + for (j = 0; j < DEVICE_NUM_FRAMES_PER_URB; j++) { + urb->iso_frame_desc[j].offset = + j * device->channel[index].maxPacketSize; + urb->iso_frame_desc[j].length = + device->channel[index].maxPacketSize; + } /* for */ + } /* for */ + device->channel[index].nextFreeOutUrbIndex = DEVICE_NUM_ISOC_OUT_URBS-1; + atomic_set(&device->channel[index].numOutUrbs, 1); + for (i = 0; i < DEVICE_NUM_ISOC_OUT_URBS-1; i++) { + ret = usb_submit_urb( + device->channel[index].isocOutUrb[i], GFP_KERNEL); + if (ret) + err("usb_submit_urb failed %d", ret); + } /* for */ + + /*dbg("end");*/ + return 0; +} /* device_start_iso_out */ + +static void device_stop_iso_out(struct device_s *device, __u8 index) +{ + dbg("start"); + + device->channel[index].outStop = 1; + + dbg("end"); +} /* device_stop_iso_out */ + +static void device_tsbulk_complete(struct urb *urb) +{ + struct device_s *device = urb->context; + __u8 index = 0; + + /*dbg("start");*/ + if (!urb->status) { + if (usb_endpoint_num(&(urb->ep->desc)) != DEVICE_TS_OUT_PIPE) + index = 1; + device->channel[index].nbByteSend += urb->actual_length; + } + kfree(urb->transfer_buffer); + usb_free_urb(urb); + /*dbg("end");*/ +} /* device_tsbulk_complete */ + +static int device_tsbulk_send(struct device_s *device, + __u8 index, __u8 *data, int size) +{ + struct urb *urb; + /* int todo = size;*/ + int ret = 0; + + dbg("start"); + + /* get a free bulk message */ + urb = usb_alloc_urb(0, GFP_KERNEL); + if (!urb) { + err("alloc urb"); + return -ENOMEM; + } /* if */ + urb->dev = device->usbdev; + + /* allocate bulk data */ + urb->transfer_buffer = kmalloc(size, GFP_KERNEL); + if (!urb->transfer_buffer) { + err("alloc transfer buffer"); + usb_free_urb(urb); + return -ENOMEM; + } /* if */ + + /* copy data */ + ret = copy_from_user(urb->transfer_buffer, data, size); + + /* submit bulk */ + urb->pipe = usb_sndbulkpipe(device->usbdev, DEVICE_TS_OUT_PIPE + index); + urb->transfer_buffer_length = size; + urb->complete = device_tsbulk_complete; + urb->context = device; + /*dbg("Transmit %d bytes\n",urb->transfer_buffer_length);*/ + /*dbg_dump("txBuf", + urb->transfer_buffer, urb->transfer_buffer_length);*/ + mod_timer(&(device->channel[index].StartBulkReadTimer), + usecs_to_jiffies(50)); + + if (usb_submit_urb(urb, GFP_KERNEL) < 0) { + err("submit urb"); + kfree(urb->transfer_buffer); + usb_free_urb(urb); + return -ENOMEM; + } /* if */ + + dbg("end"); + return 0; +} /* device_tsbulk_send */ + +/* ---------------------------------------------------------- */ +static void StartBulkRead_func(unsigned long context) +{ + struct bulk_timer_s *bulk_time = (struct bulk_timer_s *) context; + + device_start_tsbulk_in(bulk_time->device, bulk_time->index); +} + +static int device_drv_open(struct device_s *device) +{ + int index; + mutex_lock(&device->lock); + + if (!device->usbdev) { + err("no dev, can not start dev"); + mutex_unlock(&device->lock); + return -ENODEV; + } + + if (device->opened) { + mutex_unlock(&device->lock); + device->opened++; + info("udev=%p opened=%d", (device->usbdev), device->opened); + return 0; + } /* while */ + + info("set interface 0"); + if (usb_set_interface(device->usbdev, 0, 0) < 0) { + mutex_unlock(&device->lock); + err("set_interface fail"); + return -EINVAL; + } /* if */ + + device->opened++; + device->askToRelease = 0; + mutex_unlock(&device->lock); + + for (index = 0; index < DEVICE_NUM_CAM; index++) { + device->channel[index].nbByteSend = -376; + device->channel[index].nbByteRead = 0; + device->channel[index].FirstTransfer = true; + gbulk_timer[index].device = device; + gbulk_timer[index].index = index; + setup_timer(&device->channel[index].StartBulkReadTimer, + StartBulkRead_func, + (unsigned long)&(gbulk_timer[index])); + } +#ifdef DEBUG_CONTINUITY + init_tab_cc(); +#endif + info("udev=%p opened=%d", (device->usbdev), device->opened); + return 0; +} + +static int device_ci_unlock_read(struct device_s *device) +{ + if (device->opened) { + /* release blocking functions */ + device->askToRelease = 1; + wake_up_interruptible(&device->ciBulk.ciData[0].asyncWait); + wake_up_interruptible(&device->ciBulk.ciData[1].asyncWait); + wake_up_interruptible(&device->channel[0].inWait); + wake_up_interruptible(&device->channel[1].inWait); + } + return 0; +} + +static int device_drv_close(struct device_s *device) +{ + int i; + mutex_lock(&device->lock); + if (device->opened && ((--device->opened) == 0)) { + device->askToRelease = 1; + device_stop_intr(device); + for (i = 0; i < DEVICE_NUM_CAM; i++) { + if (device->useIsoc) { + device_stop_iso_out(device, i); + device_stop_iso_in(device, i); + } else + device_stop_tsbulk_in(device, i); + } /* for */ + device->opened = 0; + } /* if */ + mutex_unlock(&device->lock); + return 0; +} + +static int device_open(struct inode *inode, struct file *file) +{ + int devnum = iminor(inode); +#ifdef DEBUG + int type = (MINOR(inode->i_rdev) >> 4); + int num = (MINOR(inode->i_rdev) & 0xf); +#endif + int ret = 0; + + struct device_s *device; + + dbg("start, devnum = %d type = %d num = %d", devnum, type, num); + + if (gdeviceNumber >= DRIVER_MAX_NUMBER) { + dbg("only support one device open"); + return -EINVAL; + } + device = &gdevice[gdeviceNumber]; + /*gdeviceNumber++;*/ + + ktime_get_ts(&gStart); + + ret = device_drv_open(device); + if (ret < 0) + return ret; + + file->f_pos = 0; + file->private_data = device; + + dbg("end"); + return nonseekable_open(inode, file); +} /* device_open */ + +static int device_release(struct inode *inode, struct file *file) +{ + struct device_s *device = (struct device_s *)file->private_data; + + dbg("start"); + device_drv_close(device); + dbg("end"); + return 0; +} /* device_release */ + +int cimax_usb_select_interface(struct device_s *device, unsigned long intf) +{ + int max = 0; + int mult = 0; + int ret = 0; + + info("set interface %ld", intf); + if (usb_set_interface(device->usbdev, 0, intf) < 0) { + err("set_interface failed interface 0, altSetting %ld", intf); + return -EINVAL; + } /* if */ + + /* check endpoints */ + /* CI bulk out */ + if (!usb_endpoint_is_bulk_out( + &device->usbdev->ep_out[DEVICE_BULK_OUT_PIPE]->desc)) { + err("unexpected endpoint %d", DEVICE_BULK_OUT_PIPE); + return -EINVAL; + } /* if */ + device->ciBulk.outMaxPacketSize = DEVICE_BULK_OUT_MAXPACKET; + dbg("CI bulk out (endpoint %d), packet size %d", DEVICE_BULK_OUT_PIPE, + device->ciBulk.outMaxPacketSize); + /* CI int in */ + if (!usb_endpoint_is_int_in( + &device->usbdev->ep_in[DEVICE_INT_IN_PIPE]->desc)) { + err("unexpected endpoint %d", DEVICE_INT_IN_PIPE); + return -EINVAL; + } /* if */ + device->ciBulk.inMaxPacketSize = + device->usbdev->ep_in[DEVICE_INT_IN_PIPE]->desc.wMaxPacketSize; + dbg("CI int in (endpoint %d), packet size %d", DEVICE_INT_IN_PIPE, + device->ciBulk.inMaxPacketSize); + /* TS out */ + if (device->usbdev->ep_out[DEVICE_TS_OUT_PIPE] == NULL) + dbg("no TS endpoint"); + else { + if (usb_endpoint_is_bulk_out( + &device->usbdev->ep_out[DEVICE_TS_OUT_PIPE]->desc)) { + device->useIsoc = 0; + dbg("TS is configured as bulk"); + } else if (usb_endpoint_is_isoc_out( + &device->usbdev->ep_out[DEVICE_TS_OUT_PIPE]->desc)) { + device->useIsoc = 1; + dbg("TS is configured as isochronous"); + } else { + err("unexpected endpoint %d", DEVICE_TS_OUT_PIPE); + return -EINVAL; + } /* if */ + max = device->usbdev-> + ep_out[DEVICE_TS_OUT_PIPE]->desc.wMaxPacketSize; + mult = 1 + ((max >> 11) & 0x03); + max &= 0x7ff; + device->channel[0].maxPacketSize = max * mult; + dbg("TS out (endpoint %d), packet size %d", DEVICE_TS_OUT_PIPE, + device->channel[0].maxPacketSize); + + max = device->usbdev-> + ep_out[DEVICE_TS_OUT_PIPE+1]->desc.wMaxPacketSize; + mult = 1 + ((max >> 11) & 0x03); + max &= 0x7ff; + device->channel[1].maxPacketSize = max * mult; + dbg("TS out (endpoint %d), packet size %d", + DEVICE_TS_OUT_PIPE + 1, + device->channel[1].maxPacketSize); + } + + /* start intr urb */ + if (device->ciBulk.intUrb[0] == NULL) { + ret = device_start_intr(device); + if (ret < 0) { + err("cannot start int urb"); + return ret; + } /* if */ + } /* if */ + + return ret; +} +EXPORT_SYMBOL(cimax_usb_select_interface); + +static int device_ci_write(struct device_s *device, + struct ioctl_data_s *data, int isIoctl) +{ + int ret = 0; + if (!device) + return -ENODEV; + ret = device_cibulk_send(device, data, isIoctl); + if (ret < 0) + return ret; + return device_wait_sync_data(device, ret, data, isIoctl); +} + +static int device_ci_write_ioctl(struct device_s *device, + struct ioctl_data_s *data) +{ + return device_ci_write(device, data, 1); +} + +int cimax_usb_ci_write(struct device_s *device, + u8 *txData, int txSize, u8 *rxData, int rxSize) +{ + struct ioctl_data_s data; + if (!device) + return -ENODEV; + memset(&data, 0, sizeof(data)); + data.txData = txData; + data.txSize = txSize; + data.rxData = rxData; + data.rxSize = rxSize; + return device_ci_write(device, &data, 0); +} +EXPORT_SYMBOL(cimax_usb_ci_write); + +int cimax_usb_ci_read_evt(struct device_s *device, + int moduleId, u8 *buf, int size) +{ + int ret = 0; + struct rw_data_s data; + if (!device || !device->opened) + return -ENODEV; + memset(&data, 0, sizeof(data)); + data.moduleId = moduleId; + data.data = buf; + data.size = size; + ret = device_wait_async_data(device, data.moduleId, &data, 0); + if (ret < 0) { + err("wait ci read failed"); + return ret; + } /* if */ + dbg("return CI, moduleId %d, data 0x%p, size %d", + data.moduleId, data.data, data.size); + return ret; +} +EXPORT_SYMBOL(cimax_usb_ci_read_evt); + +int cimax_usb_device_open(struct device_s *device) +{ + return device_drv_open(device); +} +EXPORT_SYMBOL(cimax_usb_device_open); + +int cimax_usb_device_unlock_read(struct device_s *device) +{ + int ret = 0; + if (!device) + return 0; + mutex_lock(&device->lock); + ret = device_ci_unlock_read(device); + mutex_unlock(&device->lock); + return ret; +} +EXPORT_SYMBOL(cimax_usb_device_unlock_read); + +int cimax_usb_device_close(struct device_s *device) +{ + if (!device) + return 0; + cimax_usb_device_unlock_read(device); + if (cimax_usb_dev_remove) + cimax_usb_dev_remove(device, gdeviceNumber); + return device_drv_close(device); +} +EXPORT_SYMBOL(cimax_usb_device_close); + +static long device_ioctl(struct file *file, + unsigned int cmd, unsigned long arg) +{ + struct device_s *device = (struct device_s *)file->private_data; + int err = 0; + int ret = 0; + struct ioctl_data_s data; + void *transfer_buffer = NULL; + + dbg("start"); + + /* Don't decode wrong cmds: return ENOTTY (inappropriate ioctl) */ + if (_IOC_TYPE(cmd) != DEVICE_IOC_MAGIC) + return -ENOTTY; + if (_IOC_NR(cmd) > DEVICE_IOC_MAXNR) + return -ENOTTY; + + /* Verify direction (read/write) */ + if (_IOC_DIR(cmd) & _IOC_READ) + err = !access_ok(VERIFY_WRITE, (void *)arg, _IOC_SIZE(cmd)); + else if (_IOC_DIR(cmd) & _IOC_WRITE) + err = !access_ok(VERIFY_READ, (void *)arg, _IOC_SIZE(cmd)); + if (err) + return -EFAULT; + + if (mutex_lock_interruptible(&device->lock)) + return -ERESTARTSYS; + + switch (cmd) { + case DEVICE_IOC_SELECT_INTF: + dbg("DEVICE_IOC_SELECT_INTF start"); + ret = cimax_usb_select_interface(device, arg); + dbg("DEVICE_IOC_SELECT_INTF end"); + break; + + case DEVICE_IOC_CI_WRITE: + dbg("DEVICE_IOC_CI_WRITE start"); + + /* send CI message */ + ret = copy_from_user(&data, + (void __user *)arg, sizeof(struct ioctl_data_s)); + dbg("inMsg, rx 0x%p, rxSize %d, tx 0x%p, txSize %d", + data.rxData, + data.rxSize, + data.txData, + data.txSize); + ret = device_ci_write_ioctl(device, &data); + if (ret < 0) + break; + ret = copy_to_user((void __user *)arg, + &data, sizeof(struct ioctl_data_s)); + + dbg("DEVICE_IOC_CI_WRITE end"); + break; + + case DEVICE_IOC_UNLOCK_READ: + dbg("DEVICE_IOC_UNLOCK_READ start"); + + ret = device_ci_unlock_read(device); + + dbg("DEVICE_IOC_UNLOCK_READ end"); + break; + + case DEVICE_IOC_SET_CONFIG: + dbg("DEVICE_IOC_SET_CONFIG start"); + + /* send CI message */ + ret = copy_from_user(&data, + (void __user *)arg, sizeof(struct ioctl_data_s)); + dbg("inMsg, rx 0x%p, rxSize %d, tx 0x%p, txSize %d", + data.rxData, data.rxSize, + data.txData, data.txSize); + transfer_buffer = kmalloc(data.txSize, GFP_KERNEL); + memcpy(transfer_buffer, data.txData, data.txSize); + dbg_dump("New config", transfer_buffer, data.txSize); + err = usb_control_msg(device->usbdev, + usb_sndctrlpipe(device->usbdev, 0), + USB_REQ_SET_DESCRIPTOR, + USB_TYPE_STANDARD, + (USB_DT_CONFIG << 8), + 0, + transfer_buffer, + data.txSize, + 5000); + if (err < 0) { + err("set_config failed %d", err); + ret = -EINVAL; + } + kfree(transfer_buffer); + dbg("DEVICE_IOC_SET_CONFIG end"); + break; + + default: + ret = -ENOIOCTLCMD; + break; + } /* switch */ + mutex_unlock(&device->lock); + + dbg("end, ret %d", ret); + return ret; +} /* device_ioctl */ + +static ssize_t device_write(struct file *file, const char __user *buf, + size_t count, loff_t *ppos) +{ + int ret; + struct rw_data_s data; + struct device_s *device = (struct device_s *)file->private_data; + + dbg("start"); + + /* get transmission buffer */ + ret = copy_from_user(&data, buf, sizeof(struct rw_data_s)); + dbg("txBuffer, moduleId %u, data 0x%p, size %d", + data.moduleId, data.data, data.size); + if (data.moduleId >= DEVICE_NUM_CAM) { + err("bad moduleId"); + return 0; + } + + if (device->useIsoc) { + if (!data.size || (data.size % DEVICE_ISOC_LENGTH( + device->channel[data.moduleId].maxPacketSize))) { + err("transmission buffer size must be a multiple of %d", + DEVICE_ISOC_LENGTH( + device->channel[data.moduleId].maxPacketSize)); + return -EINVAL; + } /* if */ + } + + if (device->useIsoc) { + if (device->channel[data.moduleId].isocInUrb[0] == NULL) { + ret = device_start_iso_in(device, data.moduleId); + if (ret < 0) + return ret; + } /* if */ + + if (device->channel[data.moduleId].isocOutUrb[0] == NULL) { + ret = device_start_iso_out(device, data.moduleId); + if (ret < 0) + return ret; + } /* if */ + + dbg("call device_tsiso_send moduleId %d, data 0x%p, size %d", + data.moduleId, data.data, data.size); + ret = device_tsiso_send(device, + data.moduleId, data.data, data.size); + } /* if */ + else { + ret = device_tsbulk_send(device, + data.moduleId, data.data, data.size); + } /* else */ + + dbg("end, moduleId %d return %d", data.moduleId, ret); + return ret; +} /* device_write */ + +static ssize_t device_read(struct file *file, char __user *buf, + size_t count, loff_t *ppos) +{ + int res; + struct rw_data_s data; + struct device_s *device = (struct device_s *)file->private_data; + + dbg("start"); + + if (count != sizeof(struct rw_data_s)) { + err("try to read uncorrect size %zd", count); + return -EFAULT; + } /* if */ + res = copy_from_user(&data, buf, sizeof(struct rw_data_s)); + data.copiedSize = 0; + if (data.type == DEVICE_TYPE_TS_READ) { + res = device_fill_ts(device, data.moduleId, &data); + if (res < 0) { + err("fill ts buffer failed"); + return res; + } /* if */ + dbg("return TS, moduleId %d, data 0x%p, size %d, copiedSize %d", + data.moduleId, data.data, data.size, data.copiedSize); + /*res = count;*/ + res = data.copiedSize; + } /* if */ + else if (data.type == DEVICE_TYPE_CI_READ) { + res = device_wait_async_data(device, data.moduleId, &data, 1); + if (res < 0) { + err("wait ci read failed"); + return res; + } /* if */ + dbg("return CI, moduleId %d, data 0x%p, size %d", + data.moduleId, data.data, data.size); + res = data.size; + } /* else if */ + else { + err("unknown data type %d", data.type); + res = -EFAULT; + } /* else */ + + dbg("end, return %d", res); + return res; +} /* device_read */ + +/****************************************************************************** + * @brief + * write data on Control endpoint. + * + + * @param dev + * Pointer to usb device. + * + * @param addr + + * register address to write. + * + * @param data + * data to write. + * + + * @param size + * size to write. + * + * @return + + * data writen or ENODEV error + ******************************************************************************/ +int write_ctrl_message(struct usb_device *dev, int addr, void *data, int size) +{ + int ret; + void *ptr = NULL; +#ifdef DEBUG + /* int i;*/ + /* unsigned char dump[500];*/ +#endif + + /* info("%s: . addr = %04x size=%d",DRIVER_NAME,addr,size);*/ + + if (size <= 0) + return 0; + + ptr = kmemdup(data, size, GFP_KERNEL); + if (!ptr) + return -ENOMEM; + + ret = usb_control_msg + (dev, usb_sndctrlpipe(dev, 0), 0xA0, 0x40, addr, 0x0001, + ptr, size, 300); + if (ret != size) { + err("Failed to write CIMaX+ register 0x%04x", addr); + ret = -ENODEV; + } + +#ifdef DEBUG + /* dump[0] =0; + for(i=0;i Init Status = %02X", *bootStatus); + if (bootStatus) + kfree(bootStatus); + return 0; + } + if (bootStatus) + kfree(bootStatus); + + return len; +} + +/****************************************************************************** + * @brief + * Start new Firmware. + * + * @param dev + * Pointer to usb device. + + * + * @return + * None. + ******************************************************************************/ +int write_ep6_message(struct usb_device *dev, void *data, int size) +{ + int ret; + void * ptr = NULL; + ptr = kmemdup(data, size, GFP_KERNEL); + if (!ptr) + return -ENOMEM; + + if (usb_bulk_msg(dev, usb_sndbulkpipe(dev, 6), + ptr, size, &ret, 200) < 0) { + err("Failed to write cmd 0x%02x", ((unsigned char *)data)[0]); + ret = -ENODEV; + } + kfree(ptr); + return ret; +} + +/****************************************************************************** + * @brief + * Start new Firmware. + * + * @param dev + * Pointer to usb device. + * + * @return + * None. + ******************************************************************************/ +int read_ep5_message(struct usb_device *dev, void *data, int size) +{ + int ret; + + if (usb_interrupt_msg(dev, usb_rcvintpipe(dev, 5), + data, size, &ret, 200) < 0) { + err("Failed read interrupt endpoint"); + ret = -ENODEV; + } + return ret; +} + +#ifdef CONFIG_COMPAT +static long device_compat_ioctl(struct file *filp, + unsigned int cmd, unsigned long args) +{ + unsigned long ret; + + args = (unsigned long)compat_ptr(args); + ret = device_ioctl(filp, cmd, args); + return ret; +} +#endif + +static const struct file_operations device_fops = { + .owner = THIS_MODULE, + .open = device_open, + .release = device_release, + .unlocked_ioctl = device_ioctl, + .write = device_write, + .read = device_read, + /* + .poll = device_poll, + */ +#ifdef CONFIG_COMPAT + .compat_ioctl = device_compat_ioctl, +#endif +}; + +struct cimaxusb_priv_ops_t cimaxusb_priv_ops = { + .write_ctrl_message = write_ctrl_message, + .read_ctrl_message = read_ctrl_message, + .init_fw = init_fw, + .write_ep6_message = write_ep6_message, + .read_ep5_message = read_ep5_message +}; + +static struct usb_class_driver device_class = { + .name = "cimaxusb%d", + .fops = &device_fops, + .minor_base = DEVICE_MINOR, +}; + +/* ---------------------------------------------------------- */ + + +void cimax_usb_set_cb(void *cb1, void *cb2) +{ + cimax_usb_dev_add = cb1; + cimax_usb_dev_remove = cb2; +} +EXPORT_SYMBOL(cimax_usb_set_cb); + +static int device_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + struct usb_device *usbdev = interface_to_usbdev(intf); + struct device_s *device; + char cmd[] = { 0x0C, 0x01, 0x00, 0x00 }; + char *rsp; + + dbg("start vendor id 0x%x, product id 0x%x, Device id 0x%x minor 0x%x", + le16_to_cpu(usbdev->descriptor.idVendor), + le16_to_cpu(usbdev->descriptor.idProduct), + le16_to_cpu(usbdev->descriptor.bcdDevice), + intf->minor); + + /* device = &gdevice[intf->minor];*/ + device = &gdevice[gdeviceNumber]; + + mutex_lock(&device->lock); + /* device->usbdev = usbdev;*/ + device->usbdev = usb_get_dev(usbdev); + dbg("device->usbdev 0x%p", (device->usbdev)); + + /* set private callback functions */ + device->ops = &cimaxusb_priv_ops; + + device->askToSuspend = 0; + + usb_set_intfdata(intf, device); + mutex_unlock(&device->lock); + + if (usb_register_dev(intf, &device_class)) { + err("usb_register_dev"); + usb_set_intfdata(intf, NULL); + return -ENOMEM; + } /* if */ + + /* test if firmware loafing is needed */ +#ifdef FRBIT + if ((le16_to_cpu(usbdev->descriptor.bcdDevice) != 0) && + (CimaxDwnl == 1)) { +#else + if (le16_to_cpu(usbdev->descriptor.bcdDevice) != 0) { +#endif + info("start firmware download"); + /* load firmware*/ + cimaxusb_fw_upload(device); + info("end firmware download"); + } else { + info("set alternate setting 1"); + if (usb_set_interface(device->usbdev, 0, 1) < 0) { + err("set_interface failed intf 0, alt 1"); + } else { + info("check FW version"); + /* Get BOOT version */ + if (write_ep6_message(device->usbdev, + cmd, sizeof(cmd)) == sizeof(cmd)) { + rsp = kcalloc(256, + sizeof(unsigned char), + GFP_KERNEL); + if (!rsp) { + err("out of memory"); + return -ENOMEM; + } + if (read_ep5_message(device->usbdev, + rsp, 256) >= 0) { + info("=> ---- F.W. Version -------"); + info("=>= %02X.%02X.%02X.%02X.%02X%c", + rsp[4], rsp[5], rsp[6], + rsp[7], rsp[8], rsp[9]); + info("=> Boot Version = %d.%d", + rsp[10], rsp[11]); + info("=> --------------------"); + } + kfree(rsp); + } + } + info("start cfg download"); + if (cimaxusb_configuration_setting(device) < 0) + err(" Error : set CIMaX+ configuration"); + info("end cfg download"); + + if (cimax_usb_dev_add) + cimax_usb_dev_add(device, gdeviceNumber); + } + + dbg("end"); + return 0; +} /* device_probe */ + +static void device_disconnect(struct usb_interface *intf) +{ + struct device_s *device = usb_get_intfdata(intf); + int i; + + dbg("start"); + + if (!device) + return; + + mutex_lock(&device->lock); + if (device->opened) { + /* release blocking functions */ + device->askToRelease = 1; + wake_up_interruptible(&device->ciBulk.ciData[0].asyncWait); + wake_up_interruptible(&device->ciBulk.ciData[1].asyncWait); + wake_up_interruptible(&device->channel[0].inWait); + wake_up_interruptible(&device->channel[1].inWait); + device_stop_intr(device); + for (i = 0; i < DEVICE_NUM_CAM; i++) { + if (device->useIsoc) { + device_stop_iso_out(device, i); + device_stop_iso_in(device, i); + } /* if */ + else + device_stop_tsbulk_in(device, i); + } /* for */ + device->opened = 0; + + if (cimax_usb_dev_remove) + cimax_usb_dev_remove(device, gdeviceNumber); + } /* if */ + mutex_unlock(&device->lock); + usb_set_intfdata(intf, NULL); + if (device) { + usb_deregister_dev(intf, &device_class); + device->usbdev = NULL; + } /* if */ + dbg("end"); +} /* device_disconnect */ + +static int cimaxusb_suspend(struct usb_interface *intf, pm_message_t message) +{ + struct device_s *device = usb_get_intfdata(intf); + int i; + + dbg("start"); + + if (!device) + return 0; + + mutex_lock(&device->lock); + if (device->opened) { + /* release blocking functions */ + device->askToSuspend = 1; + wake_up_interruptible(&device->ciBulk.ciData[0].asyncWait); + wake_up_interruptible(&device->ciBulk.ciData[1].asyncWait); + wake_up_interruptible(&device->channel[0].inWait); + wake_up_interruptible(&device->channel[1].inWait); + device_stop_intr(device); + for (i = 0; i < DEVICE_NUM_CAM; i++) { + if (device->useIsoc) { + device_stop_iso_out(device, i); + device_stop_iso_in(device, i); + } /* if */ + else + device_stop_tsbulk_in(device, i); + } /* for */ + device->opened = 0; + } /* if */ + mutex_unlock(&device->lock); + dbg("end"); + + return 0; +} + +static int cimaxusb_resume(struct usb_interface *intf) +{ + struct device_s *device = usb_get_intfdata(intf); + + dbg("start"); + + if (!device) + return 0; + + device->askToSuspend = 0; + dbg("end"); + return 0; +} + +static struct usb_device_id device_ids[] = { + { USB_DEVICE(0x1b0d, 0x2f00) }, + { USB_DEVICE(0x1b0d, 0x2f01) }, + { USB_DEVICE(0x1b0d, 0x2f02) }, + { USB_DEVICE(0x1b0d, 0x2f03) }, + { USB_DEVICE(0x1b0d, 0x2f04) }, + { } /* Terminating entry */ +}; + +MODULE_DEVICE_TABLE(usb, device_ids); + + +static struct usb_driver device_driver = { + .name = "cimaxusb", + .probe = device_probe, + .disconnect = device_disconnect, + .suspend = cimaxusb_suspend, + .resume = cimaxusb_resume, + .id_table = device_ids, +}; + +/* ---------------------------------------------------------- */ + +static int device_init_module(void) +{ + int ret = 0; + int i, j; + struct device_s *device; + + info("start"); + + if (!gdevice) + gdevice = kcalloc(DRIVER_MAX_NUMBER, + sizeof(struct device_s), GFP_KERNEL); + if (!gdevice) { + err("not enough memory"); + return -ENOMEM; + } + + for (i = 0; i < DRIVER_MAX_NUMBER; i++) { + device = &gdevice[i]; + /* initialize struct */ + memset(device, 0, sizeof(struct device_s)); + mutex_init(&device->lock); + + /* initialize ci bulk struct */ + device->ciBulk.counter = 1; + spin_lock_init(&device->ciBulk.intLock); + spin_lock_init(&device->ciBulk.intUrbLock); + for (j = 0; j < DEVICE_NUM_CAM; j++) { + init_waitqueue_head(&device->ciBulk.ciData[j].syncWait); + init_waitqueue_head( + &device->ciBulk.ciData[j].asyncWait); + INIT_LIST_HEAD(&device->ciBulk.ciData[j].asyncDataList); + } /* for */ + + /* initialize channels */ + for (j = 0; j < DEVICE_NUM_CAM; j++) { + spin_lock_init(&device->channel[j].inLock); + init_waitqueue_head(&device->channel[j].inWait); + vb_init(&device->channel[j].inVb); + device->channel[j].syncOffset = -1; + spin_lock_init(&device->channel[j].outLock); + } /* for */ + } /* for */ + + /* register misc device */ + ret = usb_register(&device_driver); + +#ifdef TIMESTAMP + InitTimestamp(); +#endif + + if (ret) + info("end driver register failed"); + else + info("end driver registered"); + + info(DRIVER_VERSION ":" DRIVER_DESC); + + return ret; +} /* device_init_module */ + +static void device_exit_module(void) +{ + int i; + struct device_s *device; + + info("start"); + +#ifdef TIMESTAMP + ShowTimestamp(); +#endif + + for (i = 0; i < DRIVER_MAX_NUMBER; i++) { + device = &gdevice[i]; + device->askToRelease = 1; + /* destroy struct */ + mutex_destroy(&device->lock); + } /* for */ + usb_deregister(&device_driver); + gdeviceNumber = 0; + + kfree(gdevice); + gdevice = NULL; + info("end"); +} /* device_exit_module */ + +module_init(device_init_module); +module_exit(device_exit_module); diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/cimax+usb-driver.h b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/cimax+usb-driver.h new file mode 100644 index 000000000000..e4656e0e54f8 --- /dev/null +++ b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/cimax+usb-driver.h @@ -0,0 +1,362 @@ +/**************************************************************************//** + * @file cimax+usb-driver.h + * + * @brief CIMaX+ USB Driver for linux based operating systems. + * + * Copyright (C) 2009-2011 Bruno Tonelli + * & Franck Descours + * for SmarDTV France, La Ciotat + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + ******************************************************************************/ + +#include + +#ifndef CIMAXPLUS_USB_DRIVER_H +#define CIMAXPLUS_USB_DRIVER_H + +/****************************************************************************** + * Includes + *****************************************************************************/ +/****************************************************************************** + * Defines + *****************************************************************************/ +/** + * @brief + * Driver Name + */ +#define DRIVER_NAME "cimax+usb" +/** + * @brief + * An unassigned USB minor. + */ +#define DEVICE_MINOR 240 + +/** + * @brief + * Driver version. + */ +#define DEVICE_VERSION 0x1000 + +/** + * @brief + * Number of CA module supported by the driver. + */ +#define DEVICE_NUM_CAM 2 + +/** + * @brief + * Buffer length. + */ +#define DEVICE_MESSAGE_LENGTH 4100 + +/* Offset */ +#define DEVICE_COMMAND_OFFSET 0 +#define DEVICE_STATUS_OFFSET 0 +#define DEVICE_COUNTER_OFFSET 1 +#define DEVICE_LENGTH_MSB_OFFSET 2 +#define DEVICE_LENGTH_LSB_OFFSET 3 +#define DEVICE_DATA_OFFSET 4 + +/* Mask */ +#define DEVICE_SEL_MASK 0x80 +#define DEVICE_TYP_MASK 0x40 +#define DEVICE_CMD_MASK 0x3F + +/* Command tag */ +#define DEVICE_CMD_INIT 0x00 +#define DEVICE_CMD_WRITE_REG 0x7F +#define DEVICE_CMD_READ_REG 0xFF +#define DEVICE_CMD_CAMRESET 0x01 +#define DEVICE_CMD_GETCIS 0x02 +#define DEVICE_CMD_WRITECOR 0x03 +#define DEVICE_CMD_NEGOTIATE 0x04 +#define DEVICE_CMD_WRITELPDU 0x05 +#define DEVICE_CMD_READLPDU 0x06 +#define DEVICE_CMD_WRITEEXT 0x07 +#define DEVICE_CMD_READEXT 0x08 +#define DEVICE_CMD_CC1RESET 0x09 +#define DEVICE_CMD_MCARD_WRITE 0x0a + +/* Status field */ +#define DEVICE_CAMRESETOK 0x00 +#define DEVICE_CISOK 0x01 +#define DEVICE_WRITECOROK 0x02 +#define DEVICE_NEGOTIATEOK 0x03 +#define DEVICE_WRITELPDUOK 0x04 +#define DEVICE_CAMDET 0x05 +#define DEVICE_READLPDUOK 0x06 +#define DEVICE_WRITEEXTOK 0x07 +#define DEVICE_READEXTOK 0x08 +#define DEVICE_NO_CAM 0x09 +#define DEVICE_NOK 0x0a +#define DEVICE_INITOK 0x0b +#define DEVICE_READ_REGOK 0x0c +#define DEVICE_WRITE_REGOK 0x0d +#define DEVICE_DATAREADY 0x0e +#define DEVICE_MCARD_WRITEOK 0x0f +#define DEVICE_MCARD_READ 0x10 +#define DEVICE_CAMPARSE_ERROR 0x11 +#define DEVICE_WRITELPDUBUSY 0x14 +#define DEVICE_CMDPENDING 0x16 +#define DEVICE_REGSTATUSOK 0x17 +#define DEVICE_GPIOCHANGE 0x18 +#define DEVICE_FRBit 0x1A + + +#define DEVICE_DATAREADY_SYNC 0x3e + +/** + * @brief + * MPEG2 transport size,.isochronous size and number of frames per URB. + */ +#define DEVICE_MPEG2_PACKET_SIZE 188 +#define DEVICE_MPEG2_SYNC_BYTE 0x47 +#define DEVICE_NULL_HEADER_SIZE 8 +#define DEVICE_NUM_FRAMES_PER_URB 8 +#define DEVICE_ISOC_LENGTH(x) (DEVICE_NUM_FRAMES_PER_URB*x) +#define DEVICE_VB_LENGTH 902400 + +/** + * @brief + * Endpoint address. + */ +#define DEVICE_TS_IN_PIPE 1 /* and 2 */ +#define DEVICE_TS_OUT_PIPE 3 /* and 4 */ +#define DEVICE_INT_IN_PIPE 5 +#define DEVICE_BULK_OUT_PIPE 6 +#define DEVICE_BULK_OUT_MAXPACKET 256 + +/** + * @brief + * Number of isochronous/int URBs in the driver. + */ +#define DEVICE_NUM_ISOC_OUT_URBS 3 +#define DEVICE_NUM_ISOC_IN_URBS 2 +#define DEVICE_NUM_INT_IN_URBS 2 + +/** + * @brief + * ioctl() calls definition. + */ +#define DEVICE_IOC_MAGIC 'a' +#define DEVICE_IOC_SELECT_INTF _IOWR(DEVICE_IOC_MAGIC, 0, signed long) +#define DEVICE_IOC_CI_WRITE _IOWR(DEVICE_IOC_MAGIC, 1, struct ioctl_data_s) +#define DEVICE_IOC_UNLOCK_READ _IOWR(DEVICE_IOC_MAGIC, 2, signed long) +#define DEVICE_IOC_SET_CONFIG _IOWR(DEVICE_IOC_MAGIC, 3, struct ioctl_data_s) +#define DEVICE_IOC_MAXNR 4 + +/****************************************************************************** + * Types + *****************************************************************************/ +#ifdef __KERNEL__ +#include +#include +#include + +#undef dbg +#undef dbg_isoc_in +#undef dbg_isoc_out + +#undef err +#undef info +#undef warn + +#define DEBUG + +#ifdef DEBUG +#define dbg(format, arg...) pr_debug("cimax+usb: %s> " format "\n" , \ + __func__, ## arg) +#define dbg_s(format, arg...)\ + pr_debug("cimax+usb: " format "\n" , ## arg) +#else +#define dbg(format, arg...) do {} while (0) +#define dbg_s(format, arg...) do {} while (0) +#endif + +#ifdef DEBUG_ISOC_IN +#define dbg_isoc_in(format, arg...)\ + pr_debug("cimax+usb: %s> " format "\n" , \ + __func__, ## arg) +#else +#define dbg_isoc_in(format, arg...) do {} while (0) +#endif + +#ifdef DEBUG_ISOC_OUT +#define dbg_isoc_out(format, arg...)\ + pr_debug("cimax+usb: %s> " format "\n" , \ + __func__, ## arg) +#else +#define dbg_isoc_out(format, arg...) do {} while (0) +#endif + +#define err(format, arg...)\ + pr_err("cimax+usb: %s> ERROR " format "\n" , \ + __func__, ## arg) +#define info(format, arg...)\ + pr_info("cimax+usb: %s> " format "\n" , \ + __func__, ## arg) +#define warn(format, arg...)\ + pr_warn("cimax+usb: %s> WARN" format "\n" , \ + __func__, ## arg) + +/** + * @brief + * Video buffer structure. + */ +struct video_buf_s { + __u8 data[DEVICE_VB_LENGTH]; + int readOffset; + int writeOffset; + int isEmpty; +}; +#endif + +/** + * @brief + * Io control data structure exchanged between user and kernel space. + */ +struct ioctl_data_s { + __u8 *txData; + __u32 txSize; + __u8 *rxData; + __u32 rxSize; +}; + +/** + * @brief + * Read/write type exchanged between user and kernel space. + */ +enum rw_type_e { + DEVICE_TYPE_CI_READ, + DEVICE_TYPE_TS_WRITE, + DEVICE_TYPE_TS_READ +}; + +/** + * @brief + * Read/write data structure exchanged between user and kernel space. + */ +struct rw_data_s { + enum rw_type_e type; + __u8 moduleId; + __u8 *data; + __u32 size; + __u32 copiedSize; +}; +#ifdef __KERNEL__ +/** + * @brief + * Message node structure. Can be inserted in a list. + */ +struct message_node_s { + __u8 data[DEVICE_MESSAGE_LENGTH]; + __u32 size; + struct list_head node; +}; + +/** + * @brief + * Received CI data. + */ +struct ci_rx_data_s { + wait_queue_head_t syncWait; + __u8 syncSignal; + __u8 syncData[DEVICE_MESSAGE_LENGTH]; + __u32 syncDataSize; + wait_queue_head_t asyncWait; + struct list_head asyncDataList; + __u8 bPendingSend; +}; + +/** + * @brief + * CI bulk channel. + */ +struct ci_bulk_s { + __u8 counter; + __u16 inMaxPacketSize; + __u16 outMaxPacketSize; + struct urb *intUrb[DEVICE_NUM_INT_IN_URBS]; + spinlock_t intLock; + spinlock_t intUrbLock; + __u8 intCurrStatus; + __u8 intCurrIndex; + __u16 intSizeToReceive; + struct ci_rx_data_s ciData[DEVICE_NUM_CAM]; +}; + +/** + * @brief + * TS channel (can use isoc or bulk interface). + */ +struct ts_channel_s { + spinlock_t inLock; + wait_queue_head_t inWait; + struct video_buf_s inVb; + int syncOffset; + int prevOffset; + __u8 lastPacket[DEVICE_MPEG2_PACKET_SIZE]; + __u8 lastPacketSize; + spinlock_t outLock; + __u8 nextFreeOutUrbIndex; + atomic_t numOutUrbs; + __u8 outStop; + __u16 maxPacketSize; + /* isochronous urbs */ + struct urb *isocInUrb[DEVICE_NUM_ISOC_IN_URBS]; + struct urb *isocOutUrb[DEVICE_NUM_ISOC_OUT_URBS]; + /* bulk urbs */ + struct urb *bulkInUrb; + int nbByteSend; + int nbByteRead; + __u8 FirstTransfer; + struct timer_list StartBulkReadTimer; + +#ifdef DEBUG_BITRATE + ktime_t bitrateTime +#endif +}; + +struct device_s { + struct mutex lock; + struct usb_device *usbdev; + __u8 opened; + __u8 askToRelease; + __u8 askToSuspend; + struct ci_bulk_s ciBulk; + __u8 useIsoc; + struct ts_channel_s channel[DEVICE_NUM_CAM]; + /* bus adapter private ops callback */ + struct cimaxusb_priv_ops_t *ops; + int ref; +}; + +struct bulk_timer_s { + struct device_s *device; + __u8 index; +}; + +int cimax_usb_select_interface(struct device_s *device, unsigned long intf); +int cimax_usb_ci_write(struct device_s *device, + u8 *txData, int txSize, u8 *rxData, int rxSize); +int cimax_usb_ci_read_evt(struct device_s *device, + int moduleId, u8 *buf, int size); + +int cimax_usb_device_unlock_read(struct device_s *device); +int cimax_usb_device_open(struct device_s *device); +int cimax_usb_device_close(struct device_s *device); +void cimax_usb_set_cb(void *cb1, void *cb2); + + +#endif +#endif diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/cimax+usb_config.c b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/cimax+usb_config.c new file mode 100644 index 000000000000..4469b872995b --- /dev/null +++ b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/cimax+usb_config.c @@ -0,0 +1,684 @@ +/**************************************************************************//** + * @file cimax+usb_config.c + * + * @brief CIMaX+ USB Driver for linux based operating systems. + * + * Copyright (C) 2009-2011 Bruno Tonelli + * & Franck Descours + * for SmarDTV France, La Ciotat + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + ******************************************************************************/ +/****************************************************************************** + * Include + ******************************************************************************/ + + +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include "cimax+usb-driver.h" +#include "cimax+usb_config.h" +#include "bodydef.h" + +#include + +#define DEBUG +#include + +/****************************************************************************** + * Structures + ******************************************************************************/ +/****************************************************************************** + * Globals + ******************************************************************************/ +char *cimax_config_file[4] = { + "cimax+usb.cfg", + "cimax+usb_vcc0.cfg", + "cimax+usb_vcc3.cfg", + "cimax+usb_vcc5.cfg" +}; + +/****************************************************************************** + * Functions + ******************************************************************************/ +/****************************************************************************** + * @brief + * set CIMaX+ register value. + * + * @param bus_adap + * Pointer to CIMaX+ usb adapter. + * + * @param addr + * Addr of CIMaX+ register. + * + * @param val + * CIMaX+ register value to set. + * + * @return + * 0 if OK otherwise -1. + ******************************************************************************/ +int usb_setbyte(struct device_s *bus_adap, unsigned int addr, unsigned char val) +{ + unsigned char cmd[5]; + unsigned char *buf; + int len; + struct usb_device *dev = bus_adap->usbdev; + + cmd[0] = 0x7F; + cmd[1] = (unsigned char)((addr>>8)&0xff); + cmd[2] = (unsigned char)(addr&0xff); + cmd[3] = 0x01; + cmd[4] = val; + if (bus_adap->ops->write_ep6_message(dev, cmd, sizeof(cmd)) + == sizeof(cmd)) { + /*pr_debug("%s-%s: cmd=0x%x\n", + DRIVER_NAME, __func__,cmd[0]);*/ + buf = kcalloc(256, sizeof(unsigned char), GFP_KERNEL); + if (!buf) { + pr_err("%s-%s: out of memory.\n", + DRIVER_NAME, __func__); + return -ENOMEM; + } + + while ((len = bus_adap->ops->read_ep5_message(dev, buf, 256)) + >= 0) { + if (len == 0) + continue; + if ((len == 5) && ((buf[0] & 0x7f) == 0x45)) + continue; + if (len < 4) { + pr_err("%s-%s: failed to read addr 0x%x\n", + DRIVER_NAME, __func__, addr); + kfree(buf); + return -1; + } else { + break; + } + } + } else { + pr_err("%s-%s: failed to write addr 0x%x\n", + DRIVER_NAME, __func__, addr); + return -1; + } + kfree(buf); + return 0; +} + +/****************************************************************************** + * @brief + * get CIMaX+ register value. + * + * @param bus_adap + * Pointer to CIMaX+ usb adapter. + * + * @param addr + * Addr of CIMaX+ register. + * + * @param val + * pointer to buffer to store CIMaX+ register value. + * + * @return + * 0 if OK otherwise -1. + ******************************************************************************/ +int usb_getbyte(struct device_s *bus_adap, + unsigned int addr, unsigned char *val) +{ + unsigned char cmd[4]; + unsigned char *buf; + int len; + struct usb_device *dev = bus_adap->usbdev; + + cmd[0] = 0xFF; + cmd[1] = (unsigned char)((addr>>8)&0xff); + cmd[2] = (unsigned char)(addr&0xff); + cmd[3] = 0x01; + if (bus_adap->ops->write_ep6_message(dev, cmd, sizeof(cmd)) + == sizeof(cmd)) { + /*pr_debug("%s-%s: cmd=0x%x\n", + DRIVER_NAME, __func__,cmd[0]);*/ + buf = kcalloc(256, sizeof(unsigned char), GFP_KERNEL); + if (!buf) { + pr_err("%s-%s: out of memory.\n", + DRIVER_NAME, __func__); + return -ENOMEM; + } + + while ((len = bus_adap->ops->read_ep5_message(dev, buf, 256)) + >= 0) { + if (len == 0) + continue; + /*pr_debug("%s-%s: 0x%x\n", + DRIVER_NAME, __func__,buf[0]);*/ + if ((len == 5) && ((buf[0] & 0x7f) == 0x45)) + continue; + if (len >= 5) { + *val = buf[4]; + break; + } else { + pr_err("%s-%s: failed to read addr 0x%x\n", + DRIVER_NAME, __func__, addr); + kfree(buf); + return -1; + } + } + } else { + pr_err("%s-%s: failed to read addr 0x%x\n", + DRIVER_NAME, __func__, addr); + return -1; + } + kfree(buf); + return 0; +} + +/****************************************************************************** + * @brief + * compute a logical Or between CIMaX+ register value and a param value. + * + * @param bus_adap + * Pointer to CIMaX+ usb adapter. + * + * @param addr + * Addr of CIMaX+ register. + * + * @param val + * value to compute. + * + * @param pval + * pointer to buffer to store CIMaX+ register value. + * + * @return + * 0 if OK otherwise -1. + ******************************************************************************/ +int setLogicalOr(struct device_s *bus_adap, + unsigned int addr, unsigned char val, unsigned char *pval) +{ + *pval |= val; + + if (usb_setbyte(bus_adap, addr, *pval) < 0) + return -1; + + if (usb_getbyte(bus_adap, addr, pval) < 0) + return -1; + + dbg("=> Logical OR [%02X] => %02X\n", val, *pval); + + return 0; +} + +/****************************************************************************** + * @brief + * compute a logical And between CIMaX+ register value and a param value. + * + * @param bus_adap + * Pointer to CIMaX+ usb adapter. + * + * @param addr + * Addr of CIMaX+ register. + * + * @param val + * value to compute. + * + * @param pval + * pointer to buffer to store CIMaX+ register value. + * + * @return + * 0 if OK otherwise -1. + ******************************************************************************/ +int setLogicalAnd(struct device_s *bus_adap, + unsigned int addr, unsigned char val, unsigned char *pval) +{ + *pval &= val; + + if (usb_setbyte(bus_adap, addr, *pval) < 0) + return -1; + + if (usb_getbyte(bus_adap, addr, pval) < 0) + return -1; + + dbg("=> Logical AND [%02X] => %02X\n", val, *pval); + + return 0; +} + +/****************************************************************************** + * @brief + * wait CIMaX+ register value match a param value. + * + * @param bus_adap + * Pointer to CIMaX+ usb adapter. + * + * @param addr + * Addr of CIMaX+ register. + * + * @param val + * value to match. + * + * @param pval + * pointer to buffer to store CIMaX+ register value. + * + * @return + * 0 if OK otherwise -1. + ******************************************************************************/ +int waitForValue(struct device_s *bus_adap, + unsigned int addr, unsigned char val, unsigned char *pval) +{ + dbg("=> Wait for Value [%02X]\n", val); + if (*pval == val) + return 0; + + while (1) { + if (usb_getbyte(bus_adap, addr, pval) < 0) + return -1; + + dbg("\r => %02X", *pval); + + if (*pval == val) + break; + } + + dbg("\n"); + + return 0; +} + +/****************************************************************************** + * @brief + * wait CIMaX+ register bits match a param value. + * + * @param bus_adap + * Pointer to CIMaX+ usb adapter. + * + * @param addr + * Addr of CIMaX+ register. + * + * @param val + * value to match. + * + * @param pval + * pointer to buffer to store CIMaX+ register value. + * + * @return + * 0 if OK otherwise -1. + ******************************************************************************/ +int waitForBitsSet(struct device_s *bus_adap, + unsigned int addr, unsigned char val, unsigned char *pval) +{ + dbg("=> Wait for Bits set [%02X]\n", val); + if ((*pval & val) == val) + return 0; + + while (1) { + if (usb_getbyte(bus_adap, addr, pval) < 0) + return -1; + + dbg("\r => %02X", *pval); + + if ((*pval & val) == val) + break; + } + + dbg("\n"); + + return 0; +} + +/****************************************************************************** + * @brief + * wait CIMaX+ register bits cleared. + * + * @param bus_adap + * Pointer to CIMaX+ usb adapter. + * + * @param addr + * Addr of CIMaX+ register. + * + * @param val + * bits to check. + * + * @param pval + * pointer to buffer to store CIMaX+ register value. + * + * @return + * 0 if OK otherwise -1. + ******************************************************************************/ +int waitForBitsCleared(struct device_s *bus_adap, + unsigned int addr, unsigned char val, unsigned char *pval) +{ + dbg("=> Wait for Bits cleared [%02X]\n", val); + if ((*pval & val) == 0x00) + return 0; + + while (1) { + if (usb_getbyte(bus_adap, addr, pval) < 0) + return -1; + + dbg("\r => %02X", *pval); + + if ((*pval & val) == 0x00) + break; + } + + dbg("\n"); + + return 0; +} + +/****************************************************************************** + * @brief + * retreive addr of CIMaX+ register. + * + * @param dev + * Pointer to CIMaX+ register Name. + * + * @return + * Address of CIMaX+ register. + *****************************************************************************/ +int cimaxusb_rtr_reg_addr(char *str_addr) +{ + int i32NbItem = sizeof(cimax_reg_map) / sizeof(struct reg_s); + int i32index; + int i32ValAddr = -1; + + for (i32index = 0; i32index < i32NbItem; i32index++) { + if (strcmp(str_addr, cimax_reg_map[i32index].RegisterName) + == 0) { + i32ValAddr = cimax_reg_map[i32index].RegAddr; + break; + } + } + return i32ValAddr; +} + +static int cimaxusb_parse_cfg_ops(struct device_s *bus_adap, + unsigned char **pptr, size_t *plen) +{ + unsigned char op; + int ret; + char param1[256], param2[256]; + char line[256], *ptr_line; + int val; + unsigned char val2; + unsigned int addr; + unsigned char *ptr = *pptr; + size_t len = *plen; + + ptr_line = line; + op = *ptr; + ret = sscanf(ptr, "%s %s", param1, param2); + ptr++; + len++; + if (sscanf(ptr, "%s %X", param1, &val) != 2) + return -EFAULT; + /*pr_debug("%s: param1=%s,param2=%s, val=%x\n", + DRIVER_NAME, param1, param2, val);*/ + strcpy(ptr_line, param1); + len += strlen(param1); + ptr += strlen(param1); + strncat(ptr_line, ptr, 1); + len++; + ptr++; + strcat(ptr_line, param2); + len += strlen(param2); + ptr += strlen(param2); + /*pr_debug("%s: len = %08d line: %s\n", + DRIVER_NAME, len, line);*/ + addr = cimaxusb_rtr_reg_addr(param1); + if (((signed)addr) < 0) { + pr_err("%s: unknown register name: %s\n", + DRIVER_NAME, param1); + return -ENODEV; + } + if (usb_getbyte(bus_adap, addr, &val2) < 0) { + pr_err("%s: CIMaX+ register reading problem: %s\n", + DRIVER_NAME, param1); + return -ENODEV; + } + + switch (op) { + case '=': + if (waitForValue(bus_adap, addr, val, &val2) == -1) { + pr_err("%s : waitForValue failed on : %s\n", + DRIVER_NAME, param1); + return -ENODEV; + } + pr_info("%s : wait for value ([%x] = %x = %x)\n", + line, addr, val, val2); + break; + case '?': + if (waitForBitsSet(bus_adap, addr, val, &val2) == -1) { + pr_err("%s : waitForBitsSet failed on : %s\n", + DRIVER_NAME, param1); + return -ENODEV; + } + pr_info("%s : wait for bitsset ([%x] = %x = %x)\n", + line, addr, val, val2); + break; + case '!': + if (waitForBitsCleared(bus_adap, addr, val, &val2) + == -1) { + pr_err("%s : waitForBitsCleared failed on : %s\n", + DRIVER_NAME, param1); + return -ENODEV; + } + pr_info("%s : wait for bits cleared ([%x] = %x = %x)\n", + line, addr, val, val2); + break; + case '|': + if (setLogicalOr(bus_adap, addr, val, &val2) == -1) { + pr_err("%s : setLogicalOr failed on : %s\n", + DRIVER_NAME, param1); + return -ENODEV; + } + pr_info("%s : setOr ([%x] = %x = %x)\n", + line, addr, val, val2); + break; + case '&': + if (setLogicalAnd(bus_adap, addr, val, &val2) == -1) { + pr_err("%s : setLogicalAnd failed on : %s\n", + DRIVER_NAME, param1); + return -ENODEV; + } + pr_info("%s : setAnd ([%x] = %x = %x)\n", + line, addr, val, val2); + break; + default: + pr_err("Error: Marker Unknown <%c> !!!\n", op); + return -ENODEV; + } + *pptr = ptr; + *plen = len; + return 0; +} + +static int cimaxusb_parse_cfg_default(struct device_s *bus_adap, + unsigned char **pptr, size_t *plen) +{ + unsigned char *ptr = *pptr; + size_t len = *plen; + int ret; + char param1[256], param2[256]; + char line[256], *ptr_line; + int val; + unsigned char val2; + unsigned int addr; + + ptr_line = line; + + ret = sscanf(ptr, "%s %s", param1, param2); + ret = sscanf(param2, "%X", &val); + /*pr_debug("%s: param1=%s,param2=%s,val=%x\n", + DRIVER_NAME,param1,param2,val);*/ + strcpy(ptr_line, param1); + len += strlen(param1); + ptr += strlen(param1); + strncat(ptr_line, ptr, 1); + len++; + ptr++; + strcat(ptr_line, param2); + len += strlen(param2); + ptr += strlen(param2); + /*pr_debug("%s: len = %08d line: %s\n", + DRIVER_NAME, len, line);*/ + addr = cimaxusb_rtr_reg_addr(param1); + if (((signed)addr) < 0) { + pr_err("%s: unknown register name: %s\n", + DRIVER_NAME, param1); + return -ENODEV; + } + if (usb_getbyte(bus_adap, addr, &val2) < 0) { + pr_err("%s: CIMaX+ register reading problem: %s\n", + DRIVER_NAME, param1); + return -ENODEV; + } + if (usb_setbyte(bus_adap, addr, val) < 0) { + pr_err("%s: CIMaX+ register writing problem: %s\n", + DRIVER_NAME, param1); + return -ENODEV; + } + if (usb_getbyte(bus_adap, addr, &val2) < 0) { + pr_err("%s: CIMaX+ register checking problem: %s\n", + DRIVER_NAME, param1); + return -ENODEV; + } + pr_info("set: %s(0x%04x) : 0x%02x\n", param1, addr, val); + + *pptr = ptr; + *plen = len; + return 0; +} + +/****************************************************************************** + * @brief + * parse CIMaX+ config file. + * + * @param dev + * Pointer to usb device. + * + * @param fw_data + * Pointer to buffer with firmware data. + * + * @return + * O if no error otherwise errno. + *****************************************************************************/ +int cimaxusb_parse_cfg(struct device_s *bus_adap, + const unsigned char *cfg_data, size_t size) +{ + char line[256], *ptr_line; + size_t len = 0; + unsigned char *ptr = (unsigned char *)cfg_data; + int ret = -EFAULT; + + dbg("%s: %s size = %zd\n", DRIVER_NAME, __func__, size); + do { + ptr_line = line; + switch (*ptr) { + case ';': + /* continue up to find \r character */ + while (*ptr != 0x0A) { + *ptr_line++ = *ptr; + ptr++; + len++; + } + *ptr_line = 0; + /*pr_debug("%s: len = %08d line: %s\n", + DRIVER_NAME, len, line);*/ + break; + case 0x0A: + case 0x0D: + ptr++; + len++; + break; + case '=': + case '?': + case '!': + case '|': + case '&': + ret = cimaxusb_parse_cfg_ops(bus_adap, &ptr, &len); + if (ret < 0) + return ret; + break; + default: + ret = cimaxusb_parse_cfg_default(bus_adap, &ptr, &len); + if (ret < 0) + return ret; + break; + } + } while (len < size); + + return (ret == -EFAULT) ? 0 : ret; +} + +/****************************************************************************** + * @brief + * read configuration file ( CIMAX_CONFIG_NAME) and set in CIMaX+ chip. + * + * @param bus_adap + * Pointer to usb device. + * + * @return + * None. + ******************************************************************************/ +/* +opt: 0: init, 1: off, 2: Vcc3.3 3: Vcc5 +*/ +int cimaxusb_configuration_setting_opt(struct device_s *bus_adap, int opt) +{ + int errno = -EFAULT; + const struct firmware *config; + char *cfg = cimax_config_file[opt]; + + struct usb_device *dev = bus_adap->usbdev; + + dbg("request configuration file"); + /* request kernel to locate firmware file */ + errno = request_firmware(&config, cfg, &dev->dev); + if (errno < 0) { + pr_err("%s: unable to locate configuration file: %s\n", + DRIVER_NAME, cfg); + goto error; + } + + dbg("parse configuration file"); + errno = cimaxusb_parse_cfg(bus_adap, config->data, config->size); + if (errno < 0) { + pr_err("%s: unable to parse config file: %s\n", + DRIVER_NAME, cfg); + goto error; + } + +error: + /* release firmware if needed */ + if (config != NULL) + release_firmware(config); + return errno; +} + +int cimaxusb_configuration_setting(struct device_s *bus_adap) +{ + return cimaxusb_configuration_setting_opt(bus_adap, 0); +} + +int cimaxusb_configuration_setting_vcc(struct device_s *bus_adap, int vcc) +{ + return cimaxusb_configuration_setting_opt(bus_adap, vcc); +} diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/cimax+usb_config.h b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/cimax+usb_config.h new file mode 100644 index 000000000000..5c55204c62cc --- /dev/null +++ b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/cimax+usb_config.h @@ -0,0 +1,58 @@ +/**************************************************************************//** + * @file cimax+usb_config.h + * + * @brief CIMaX+ USB Driver for linux based operating systems. + * + * Copyright (C) 2009-2011 Bruno Tonelli + * & Franck Descours + * for SmarDTV France, La Ciotat + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + ******************************************************************************/ + +#ifndef __CIMAXPLUS_USB_CFG_H +#define __CIMAXPLUS_USB_CFG_H + +/****************************************************************************** + * Include + ******************************************************************************/ +#include "cimax+usb_handle.h" + +/****************************************************************************** + * Defines + ******************************************************************************/ +#define CIMAX_CONFIG_NAME "cimax+usb.cfg" + +/****************************************************************************** + * Enums + ******************************************************************************/ +/****************************************************************************** + * Structures + ******************************************************************************/ + +/****************************************************************************** + * Functions + ******************************************************************************/ + +/****************************************************************************** + * @brief + * read configuration file ( CIMAX_CONFIG_NAME) and set in CIMaX+ chip. + * + * @param bus_adap + * Pointer to usb device. + * + * @return + * None. + ******************************************************************************/ +int cimaxusb_configuration_setting(struct device_s *bus_adap); + +#endif + diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/cimax+usb_fw.c b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/cimax+usb_fw.c new file mode 100644 index 000000000000..6bccf4b8e64b --- /dev/null +++ b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/cimax+usb_fw.c @@ -0,0 +1,325 @@ +/**************************************************************************//** + * @file cimax+usb_fw.c + * + * @brief CIMaX+ USB Driver for linux based operating systems. + * + * Copyright (C) 2009-2011 Bruno Tonelli + * & Franck Descours + * for SmarDTV France, La Ciotat + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + ******************************************************************************/ +/****************************************************************************** + * Include + ******************************************************************************/ +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include + +#include "cimax+usb-driver.h" +#include "cimax+usb_fw.h" + +/****************************************************************************** + * Structures + ******************************************************************************/ +/****************************************************************************** + * Globals + ******************************************************************************/ +char cimax_fw[] = CIMAX_FIRMWARE_NAME; + +/****************************************************************************** + * Functions + ******************************************************************************/ +/****************************************************************************** + * @brief + * Start & check Bistrom. + * + * @param dev + * Pointer to usb device. + * + * @param startAddr + * start address of firmware to compute + * + * @param endAddr + * stop address of firmware to compute + * + * @param FWSign + * Current signature to check + * + * + * @return + * None. + ******************************************************************************/ +int checkBistRom(struct device_s *bus_adap, + int startAddr, int endAddr, int signature) +{ + unsigned char *Val; + int rv; + + struct usb_device *dev = bus_adap->usbdev; + + Val = kcalloc(2, sizeof(unsigned char), GFP_KERNEL); + if (!Val) { + pr_err("%s-%s: out of memory.\n", DRIVER_NAME, __func__); + return -ENOMEM; + } + + /* Write "Flash" Size + (!) BistRom is computed since D000-flashSize to D0000-6 + */ + Val[0] = (0xD000-startAddr)&0x00ff; + Val[1] = (0xD000-startAddr)>>8; + if (bus_adap->ops->write_ctrl_message(dev, 0x008D, Val, 2) != 2) { + kfree(Val); + return -1; + } + + /* Write Signature*/ + Val[0] = signature&0x00ff; + Val[1] = signature>>8; + if (bus_adap->ops->write_ctrl_message(dev, 0x0080, Val, 2) != 2) { + kfree(Val); + return -1; + } + + /* Launch BistRom [(D000-flashSize)..CFF9]+[FFFA..FFFF] computation*/ + Val[0] = 0x0F; + if (bus_adap->ops->write_ctrl_message(dev, 0x0082, Val, 1) != 1) { + kfree(Val); + return -1; + } + + pr_info("\n>>Read Signature\n"); + + /* Read Signature*/ + if (bus_adap->ops->read_ctrl_message(dev, 0x0041, Val, 2) != 2) { + kfree(Val); + return -1; + } + + pr_info("\n>> Bistrom computed = %04X\n", Val[0]|Val[1]<<8); + + /* Read Boot status*/ + if (bus_adap->ops->read_ctrl_message(dev, 0x0009, Val, 1) != 1) { + kfree(Val); + return -1; + } + + pr_info("\n>> BootRom Status = %02X\n", Val[0]); + rv = Val[0]; + kfree(Val); + + return rv; +} + +/****************************************************************************** + * @brief + * Compute BistRom. + * + * @param ptr + * Pointer to buffer with register data + * + * @param size + * Number of register to process + * + * @param FWSign + * Current signature + * + * @return + * None. + ******************************************************************************/ +unsigned int MISR(const unsigned char *ptr, int size, unsigned int FWSign) +{ + int k, i; + + unsigned short mySign; + + for (k = 0; k < size; k++) { + mySign = ptr[k]&0x01; + + for (i = 0; i < 16; i++) { + if (0x88B7 & (1<>i) & 0x01; + } + + mySign |= ((FWSign<<1)^(ptr[k])) & 0x00FE; + mySign |= (FWSign<<1) & 0x00FF00; + + FWSign = mySign; + } + + return FWSign; +} + + +/****************************************************************************** + * @brief + * upload firmware in CIMaX+ chip. + * + * @param dev + * Pointer to usb device. + * + * @param fw_data + * Pointer to buffer with firmware data. + * + * @param FWSign + * Pointer to store computed signature. + * + * @return + * None. + ******************************************************************************/ +int cimaxusb_firmware_upload(struct device_s *bus_adap, + const unsigned char *fw_data, unsigned int *FWSign) +{ + int errno = -EFAULT; + const unsigned char *ptr; + int startAddr = START_FW_ADDR; + unsigned char *recv; + int size; + + struct usb_device *dev = bus_adap->usbdev; + + /* data firmware */ + ptr = fw_data; + ptr += START_FW_ADDR; + + recv = kcalloc(300, sizeof(unsigned char), GFP_KERNEL); + if (!recv) { + pr_err("%s-%s: out of memory.\n", DRIVER_NAME, __func__); + return -ENOMEM; + } + + do { + /* compute the size to send to CIMaX+ */ + size = (startAddr <= (STOP_FW_ADDR + 1 - MAX_FW_PKT_SIZE)) ? + (MAX_FW_PKT_SIZE) : (STOP_FW_ADDR + 1 - startAddr); + /* compute Signature */ + *FWSign = MISR(ptr, size, *FWSign); + + pr_info("%s: firmware start address %08x size %d\n", + DRIVER_NAME, startAddr, size); + + /* upload data firmware */ + if (bus_adap->ops->write_ctrl_message( + dev, startAddr, (void *)ptr, size) != size) { + pr_err("Failed to load CIMaX+ firmware\n"); + errno = -ENODEV; + break; + } + if (bus_adap->ops->read_ctrl_message( + dev, startAddr, (void *)recv, size) != size) { + pr_err("Failed to load CIMaX+ firmware\n"); + errno = -ENODEV; + break; + } + if (memcmp(ptr, recv, size)) { + pr_err("Failed compare at Address 0x%04x\n", + startAddr); + errno = -ENODEV; + break; + } + /* update size sent to CIMaX+ */ + startAddr += size; + ptr += size; + if (startAddr >= STOP_FW_ADDR) + break; + } while (1); + + kfree(recv); + + if (errno == -EFAULT) { + /* upload interrupt vector*/ + ptr = fw_data; + ptr += START_INTVECT_ADDR; + startAddr = START_INTVECT_ADDR; + + /* continue to compute Signature */ + *FWSign = MISR(ptr, 6, *FWSign); + + /* upload interrupt vector data*/ + if (bus_adap->ops->write_ctrl_message( + dev, startAddr, (void *)ptr, 6) != 6) { + pr_err("Failed to load CIMaX firmware(Int vector)\n"); + errno = -ENODEV; + } + } + return (errno == -EFAULT) ? 0 : errno; +} + +/****************************************************************************** + * @brief + * upload and start firmware in CIMaX+ chip. + * + * @param bus_adap + * Pointer to usb device. + * + * @return + * None. + ******************************************************************************/ +int cimaxusb_fw_upload(struct device_s *bus_adap) +{ + int errno = -EFAULT; + const struct firmware *firmware; + char *fw = cimax_fw; + unsigned int FWSign = 0; + int ret; + + struct usb_device *dev = bus_adap->usbdev; + + /* request kernel to locate firmware file */ + errno = request_firmware(&firmware, fw, &dev->dev); + if (errno < 0) { + pr_err("%s: unable to locate firmware file: %s\n", + DRIVER_NAME, fw); + goto error; + } + + errno = cimaxusb_firmware_upload(bus_adap, firmware->data, &FWSign); + if (errno < 0) { + pr_err("%s: unable to upload firmware file: %s\n", + DRIVER_NAME, fw); + goto error; + } + + pr_info("%s: firmware: %s loaded with success. Current Bistrom %04X\n", + DRIVER_NAME, fw, FWSign); + + ret = checkBistRom(bus_adap, START_FW_ADDR, STOP_FW_ADDR, FWSign); + if (ret != 0x02) { + pr_err("\nError: Fail on compare BistRom (%02X) !\n", ret); + errno = -ENODEV; + goto error; + } + + if (bus_adap->ops->init_fw(dev) != 0) { + pr_err("\nError: Fail on INIT command !\n"); + errno = -ENODEV; + goto error; + } + +error: + /* release firmware if needed */ + if (firmware != NULL) + release_firmware(firmware); + return errno; +} diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/cimax+usb_fw.h b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/cimax+usb_fw.h new file mode 100644 index 000000000000..bf3f64cab8e3 --- /dev/null +++ b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/cimax+usb_fw.h @@ -0,0 +1,61 @@ +/**************************************************************************//** + * @file cimax+usb_fw.h + * + * @brief CIMaX+ USB Driver for linux based operating systems. + * + * Copyright (C) 2009-2011 Bruno Tonelli + * & Franck Descours + * for SmarDTV France, La Ciotat + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + ******************************************************************************/ + +#ifndef __CIMAXPLUS_USB_FW_H +#define __CIMAXPLUS_USB_FW_H + +/****************************************************************************** + * Include + ******************************************************************************/ +#include "cimax+usb_handle.h" + +/****************************************************************************** + * Defines + ******************************************************************************/ +#define CIMAX_FIRMWARE_NAME "cimax+_usbdvb.bin" +#define START_FW_ADDR 0x8000 +#define STOP_FW_ADDR 0xCFF9 +#define START_INTVECT_ADDR 0xFFFA +#define MAX_FW_PKT_SIZE 256 + +/****************************************************************************** + * Enums + ******************************************************************************/ +/****************************************************************************** + * Structures + ******************************************************************************/ + +/****************************************************************************** + * Functions + ******************************************************************************/ +/****************************************************************************** + * @brief + * upload firmware in CIMaX+ chip. + * + * @param bus_adap + * Pointer to usb device. + * + * @return + * None. + ******************************************************************************/ +int cimaxusb_fw_upload(struct device_s *bus_adap); + +#endif diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/cimax+usb_handle.h b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/cimax+usb_handle.h new file mode 100644 index 000000000000..936b9cf56bad --- /dev/null +++ b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/cimax+usb_handle.h @@ -0,0 +1,46 @@ +/**************************************************************************//** + * @file cimax+usb_handle.h + * + * @brief CIMaX+ USB Driver for linux based operating systems. + * + * Copyright (C) 2009-2011 Bruno Tonelli + * & Franck Descours + * for SmarDTV France, La Ciotat + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + ******************************************************************************/ + +#ifndef __CIMAXPLUS_USB_HDLE_H +#define __CIMAXPLUS_USB_HDLE_H + +#ifdef __KERNEL__ + +struct cimaxusb_priv_ops_t { + int (*write_ctrl_message)( + struct usb_device *dev, int addr, void *data, int size); + + int (*read_ctrl_message)( + struct usb_device *dev, int addr, void *data, int size); + + int (*init_fw)( + struct usb_device *dev); + + int (*write_ep6_message)( + struct usb_device *dev, void *data, int size); + + int (*read_ep5_message)( + struct usb_device *dev, void *data, int size); +}; + +#endif + +#endif diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/cimax+usb_time.c b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/cimax+usb_time.c new file mode 100644 index 000000000000..ea80b5ef473f --- /dev/null +++ b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/cimax+usb_time.c @@ -0,0 +1,130 @@ +/**************************************************************************//** + * @file cimax+usb_fw.c + * + * @brief CIMaX+ USB Driver for linux based operating systems. + * + * Copyright (C) 2009-2011 Bruno Tonelli + * & Franck Descours + * for SmarDTV France, La Ciotat + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + ******************************************************************************/ + +/*#define TIMESTAMP*/ + +/****************************************************************************** + * Include + ******************************************************************************/ +#include + +#include "cimax+usb_time.h" + +/****************************************************************************** + * Structures + ******************************************************************************/ +#define err(format, arg...)\ + pr_err("cimax+usb_time: %s> ERROR " format "\n" , \ + __func__, ## arg) +#define info(format, arg...) pr_info("time> " format "\n", ## arg) +/****************************************************************************** + * Globals + ******************************************************************************/ +#ifdef TIMESTAMP +struct item_array_s gstArray; +#endif +/****************************************************************************** + * Functions + ******************************************************************************/ +/****************************************************************************** + * @brief + * Init timestamp. + * + * @param + * None + * + * @return + * None. + ******************************************************************************/ +void InitTimestamp(void) +{ +#ifdef TIMESTAMP + gstArray.count = 0; +#endif + return; +} + +/****************************************************************************** + * @brief + * Set timestamp. + * + * @param pcFormat + * Printf-like format + * + * @return + * None. + ******************************************************************************/ +void SetTimestamp(const char *pcFormat, ...) +{ +#ifdef TIMESTAMP + va_list stArgs; + + if (gstArray.count >= MAX_ITEMS) { + if (gstArray.count++ == MAX_ITEMS) + ShowTimestamp(); + return; + } + ktime_get_ts(&gstArray.stItem[gstArray.count].stTime); + va_start(stArgs, pcFormat); + vsprintf(gstArray.stItem[gstArray.count++].pcLine, pcFormat, stArgs); + va_end(stArgs); +#endif + return; +} + +/****************************************************************************** + * @brief + * Display all timestamps. + * + * @param + * None + * + * @return + * None. + ******************************************************************************/ +void ShowTimestamp(void) +{ +#ifdef TIMESTAMP + int i; + + if (gstArray.count == 0) { + err("No timestamps available"); + return; + } + + info("==============================================================="); + info(" TIMESTAMPS"); + info("==============================================================="); + + for (i = 0; i < gstArray.count; i++) { + info("[%04d] [%03d.%09d] %s", + i, + gstArray.stItem[i].stTime.tv_sec, + gstArray.stItem[i].stTime.tv_nsec, + gstArray.stItem[i].pcLine); + if ((i % 100) == 0) + msleep(20); + } + info("==============================================================="); + gstArray.count = 0; + +#endif + return; +} diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/cimax+usb_time.h b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/cimax+usb_time.h new file mode 100644 index 000000000000..0012c64dfba4 --- /dev/null +++ b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/SRC/cimax+usb_time.h @@ -0,0 +1,92 @@ +/**************************************************************************//** + * @file cimax+usb_time.h + * + * @brief CIMaX+ USB Driver for linux based operating systems. + * + * Copyright (C) 2009-2011 Bruno Tonelli + * & Franck Descours + * for SmarDTV France, La Ciotat + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + ******************************************************************************/ + +#ifndef __CIMAXPLUS_USB_TIME_H +#define __CIMAXPLUS_USB_TIME_H + +/****************************************************************************** + * Include + ******************************************************************************/ +#include + +/****************************************************************************** + * Defines + ******************************************************************************/ +#define MAX_ITEMS 100000 +#define MAX_LINE_SIZE 128 + +/****************************************************************************** + * Enums + ******************************************************************************/ +/****************************************************************************** + * Structures + ******************************************************************************/ +struct item_s { + struct timespec stTime; + char pcLine[MAX_LINE_SIZE]; +}; + +struct item_array_s { + int count; + item_s stItem[MAX_ITEMS]; +}; + +extern struct item_array_s gstArray; + +/****************************************************************************** + * Functions + ******************************************************************************/ +/****************************************************************************** + * @brief + * Init timestamp. + * + * @param + * None + * + * @return + * None. + ******************************************************************************/ +void InitTimestamp(void); + +/****************************************************************************** + * @brief + * Set timestamp. + * + * @param pcFormat + * Printf-like format + * + * @return + * None. + ******************************************************************************/ +void SetTimestamp(const char *pcFormat, ...); + +/****************************************************************************** + * @brief + * Display all timestamps. + * + * @param + * None + * + * @return + * None. + ******************************************************************************/ +void ShowTimestamp(void); + +#endif diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/firmware/cimax+_usbdvb.bin b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/firmware/cimax+_usbdvb.bin new file mode 100644 index 000000000000..315fe5e308a9 --- /dev/null +++ b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/firmware/cimax+_usbdvb.bin @@ -0,0 +1,81 @@ +@ / +@       "SDTV TBD "CIMAX TBD "SN000 TBD  + +آ ᆨ < Lކ +ii $y| +ㅑ7{ ͆ †ㅑ7{ ͆B +``Lކ`)8y|-y| %ʩ`HHH9{1O{)&r!qpD{9{O{)ߍL9{( || KA_CSD.EyF4GMHIJL܇MNPPQRSVSWXوî1Ōvιf6;0ʕuuLL9L9;0ʕuuL$L9ʕʕ8.ʭmmLL9ʕʕ8.ʭmmLL9;Kʕʕii uuLXL9ʭiiL9L9L9L9L9L9L9ʕʕ譪ʭii87ii LLL9ʕʕ譪ʭii87ii LLSL9ʕʕ譪ʭii87ii LJLL9L9L9L9L9L9L9L9L9;0ʕuuLL9ʕʕ8.ʭmmL6L9ʕʕ8.ʭmmLL9L9L9;0ʕuuLL9L9K>NQ Sː.ΰ*||ʕi||i}|Lʕʕ {i||i}|Lhhh`@@.Q  ÓL“F{b͐|ZSLE-=V|  @ ÓD{L“G{g͑|_ɁXQJ-B- V|  @ ÓD{L“ K 8l8 + 2&Ryj!, :L _L YL LJ{)J{H{~| LJ{)J{I{~| L~| L~| L~|ʕmLcʭʕii ΰV- ?-s|L8s|?-t|LX@ -w|LXɀLXLXL䐭 GL~|ʕmLfʭʕii ΰV- ?-u|L;u|?-v|L[@ -x|L[ɀL[L[L瑭 GL~| |L~| |L~| L~| LH{~| ĠH{LI{~| ĠI{L~| }ǍL~| }ǍL L /L + @ Ó`y|) -y|L$8{ [Z}|]||\ XX X8||}|   `):h h0)8y|0-y| l||)Ls|)L|||9{h)h|iX||-y|  )҄ts    ) |WP) + +|h)hLS)|h)hLS)|h)h| +|L|L.|| ) +||L畭|UD{P-y|CK{ L{|K{L{||E  @ Ó||=|8-y|0H{&H{N  Ó|L}|JD{E-y|8K{L{||E  @ Ó||LL|LL|| ) +||L|P-y|CM{ N{|M{N{||  @ Ó||=|8-y|0I{&I{  Ó|L|E-y|8M{N{||  @ Ó|7{-y| D{ 7{-y|EO{)&r!qp9{O{D{)ߍp)9{ +8{8{D{K<{={A:{X  Ó<{ <{h)h={ ={h)hLʩ`HHHHHHHxj)7{)||9{j)LB{q>{d>{gC{p@{|)@{@{ |)@{@{|)|L +||F{)B{C{q?{d?{gB{pA{|)A{A{ |)A{A{|)|L||G{)C{҄tsj)L|Ll)||#B{p>{p@{pLB{p>{|e>{p@{p))||#C{p?{pA{pLiC{p?{|e?{pA{p)L| +|L)Li)gB{)||p>{p@{pLp>{|e>{p@{)J{)J{p|o)gC{)||p?{pA{pLip?{|e?{pA{p)J{)J{) )L)Lk)Lk| ) ))ʕ-J{ J{||Lf|| L||) ʭo|ip|i-')| | |LX| |) Lk|)7|2)* ))ʕ-J{ J{|k) sk):YO{-O{- Xrqp)ߍ9{D{k))7{j)@ :{<{h @hj);{={h hjLrkLrXhhhhhhh@rʭqʕ  ʭ`||||p`ʩҕ o ΰ'8||||||pLp`p oʩ ΰL(pP  Ţc@-|| `c`}} }}}}`}} }}} }}}` +} }` Ϡ͒0LϞLϠ,} Ǟ)L`d ) ݝ LVp +`) +L +`d )L" ݝ ) Lp`)! }`" }`HHH }}}}}m}}m}8}}}}Lu8}}}}8V) L䠭 }@ L 񟭔 }}L}m}}}m}}hhh`HHHL硠!  L!)͓>"} }* }}}i}}i} }}LM@} }L) LL䡭 L硭} }Lܡ )Lhhh` d a )Ls)+)#   )Ls) Ls ݝ Lp` 6 ʭ})?})8}}}} `)Lڢ`)  D)}Hh r) L!L! L!3-} ! LX!  )Lo ! `)  )\)) +  L⣭) )L⣠   )   ۢ)-9{8{  8{- ) )@ @) ) a)  Ţa`HHH ͎L;ʕou{uŗl{mL;ʕpu{uʱʩ ]Hl{ʕhumLhhh` -}1|@Lm }   L$ +}} }  L LLʭ}} ,E}_)  L)J  L)JJ  L)JJJ  L)JJJJ  L) Hh r΍  L)@Hh r΍  L LL L `}LL-}L} KQ8j @ i)iL  i)iYL  i)iL  i)iL  i)iL  i)iL LL L `}L-}L} KC*u\  @ i)iL  i)iYL  i)iL  i)iL  i)iL  i)iL LL L `d ) ݝ   Lp +}L +}` }}}P{} Ǟ } }!}/"}#}$}}} `b }{} +}} `p)@p)@ s{s{-t{| @|Lp)@I-s{s{l }{}}} ` }{} }} `} }|}}}Lƪ;p) p +| Ǟ }|}"}}Lƪ;p) "p,| Ǟ* }|}"}}Lƪ;p) BpN| ǞL }|}"}}Lƪ Lƪ `  } K1.F LN TLN rLN LNLN ީ  LN LN  ~` }l }{} L ` +} L  `}  +}L᫭}  +}L᫠ ` +}} } n| L +  `HHH} I[Rdmv HL L L L תL bL L L 嫍L +}L} }L}n|n|LLu Ln|+   +  LUn| ʕpu{uʕqu{u1JJJi + + +ʕqu{u1 ʕwu{uʕxu{u1JJJi + + +ʕxu{u1  ʕ~u{u +ʕu{u1JJJi + + +ʕu{u1  ʕu{u ʕu{u1JJJi + + +ʕu{u1      tu  @ L LL Lhhh`E{ii&Ύ D{ՠE{`yΪ!ΨΩ뭪`HHHʕʩ + ε(|o|p|JIVL|q|r|ʌɌ֌ ʭii1LW + ii")L +HhL<)L,Hh L i/9{}} L09{}}} L0VF{L걠G{h<{h)h={h)h9{ L0hhh`K `HHHʕʕʕʩ ΐ/}}}L LQ;ʕuuH}hL}L h)hhhh`HHHʕʕLM h)hhhh`HHHhx|O |JI@h  |)ߍLI LLo|I |ʌɌh  |)ߍL L8LL:)L6Hh)L)LpHh)-L + Lm83|Lⵠ| L.}}} LP F{LaG{s| +t|w|Lu| +v|x|hhhh` Ϡhxh @hL`|||& |JIAL]|+}}}J L>I h<{h)h={h)hXLDL L |+|& |ʌɌL |+}}} L귩 h<{h)h={h)hXLD} L +iiiiʭʩ ε +ʭ))iiiiLfiiʭʩ ε +ʭ))iiiiLܸ8N}}}  +h<{h)h={h)hXLDiiʭʩ ε +ʭ))iiL-L׺iiʭVvHh r΍ʭVv詌} L L#}}}  +h<{h)h={h)hXLύHHHxF{ +G{hh @hLx}}o|p||L3|L3)L3 |JIBF{Vs|t| E}ʭʩ ε}ʭ))io|ip|o|p|LuI F{h<{h)h={h)hXLLL}}q|r||LF|LF)LF |ʌɌŒG{֌u|v| E}ʭʩ ε}ʭ))iq|ir|q|r|L G{h<{h)h={h)hXLLʕʕʭʩ ε +ʭ))ii)@w +  } +LD } + + ʭii ʭiiF{|LG{|Uʭii@1.9{}} XLL0@ (XLF{LBG{  +F{ G{h<{h)h={h)hXhhh`HHHh|=|8 |JIC} +o|p|LI LLwe|=|8 |ʌɌÌ} +q|r|Lw Lʭii (Lʭiiʭiiʕʕuu/}}} Lĭʕmʭiiʕʕuu8ʭL>ʭʭii@ (LĠ8 +ʭiiʭii@-L)é ʭiiLʭii@-/}}} Lʭiiʭii-Hh-Hhʭii ʭii)@"׍ Lĭ) 2--ۍ Lĩ-- +hhh`HHHxs|I|D |JIFw|} +o|p|L9ũI XLuLťLŭ|Lŭ|| |ʌɌƌx|} +q|r|) /}}  XLuLũ XLuʭii-Lʭiiʭii $ʭiiLʭiiJ{Lǭ}}}   Lǭ| +A | | Ltǥ | | Xhhh`HHHxʕʕuut|H|C |JIDTw|} +o|p|L9ȩI XLLȭq|H|C |ʌɌČԌx|} +q|r|Lȩ XLʭiiʭii詀1u8H{+H{|N L4ɠLlɭI{+I{| LlɠL1ʭiiʭii@-Lʭiiʭii8L ʭ$ʭiiLʭii L1˭$ʭiiLʭii" L1˩  +C | | L˭ | | Xhhh`HHHf|=|8 |JIW} +o|p|L ̩I LLx̭c|=|8 |ʌɌ׌} +q|r|Lx̩ Lʭii}}  +hhh`) ))|L̠|L ͭ )|L ͠|`HHH LέRББS L!Ω h)hhhh`}}Q h)h`VuLm`J``8`VvuuLε +6ڵ`8vv`Vv`II`hh 8ѕ 8 +e斠HhlL8ϕhhȱiLZȱHhlhhȱȱȱiLȱHhlhhHHHHlhhhh`@%] \ No newline at end of file diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/firmware/cimax+usb.cfg b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/firmware/cimax+usb.cfg new file mode 100644 index 000000000000..7e792d80285d --- /dev/null +++ b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/firmware/cimax+usb.cfg @@ -0,0 +1,97 @@ +; +; ************************ +; * INIT_TS.TXT SCRIPT * +; ************************ +; +; *** CLOSE INPUT *** +; +IN_SEL 0x00 +; +; *** CLOSE OUPUT *** +; +OUT_SEL 0x00 +; +; *** RESET FIFO *** +; +FIFO_CTRL 0x0f +SYNC_RTV_CTRL 0x0f +; +; +; ************************* +; * INIT_USB.TXT SCRIPT * +; ************************* +; +; *** Endpoint Config *** +; +DMA_ACC_EPS 0x3f +EPS_ENABLE 0x7f +; +; *** FIFO Control *** +; +USB2TS_CTRL 0x0f +TS2USB_CTRL 0x0f +; +; *** FREQ Control *** +; +USB2TS0_RDL 0x80 +USB2TS1_RDL 0x80 +; +;----------------------------------------------------------------------------- +; Set CAM power +;----------------------------------------------------------------------------- +; +GPIO0_DATA_OUT 0x00 +; +; unlock CFG +CFG_2 0x00 +; +; 1) DVB/CI/CI+/SCARD 2slot +CFG_1 0x00 +; +; 2) Set the Default "power off" state such as VCC_MODA=VCC_MODB=VPPx_MODA=VPPx_MODB='Z' +GPIO0_DFT 0x00 +; +; 3) Set GPIO3 as external power switch driver +GPIO0_MASK_DATA 0x07 +; +; 4) Set "power on" state (VCC=VPP1=VPP2= 5V) +GPIO0_DATA_OUT 0x01 +; +; 5) Lock config +CFG_2 0x01 +; +; 6) Write in the GPIO0_DIR_REG: defines the GPIOs, which +; are used to drive the external power switch, in output mode. +GPIO0_DIR 0x07 +; +; 7) Check VCCENable +?CFG_1 0x20 +; +; 8) Set & wait for PcmciaOutputEnable +|CFG_1 0x08 +?CFG_1 0x08 +; +;--------------------------------------- +; Set Router CAM +;--------------------------------------- +; +; +GAP_REMOVER_CH0_CTRL 0x0C +GAP_REMOVER_CH1_CTRL 0x0C + +; 9) CH0 & CH1 from CAM A & B, CAM A & B from CH0 & CH1 +; +ROUTER_CAM_MOD 0x21 +ROUTER_CAM_CH 0x00 +; +;_Wait 200 +;--------------------------------------- +; ROUTER CAM +;--------------------------------------- +OUT_SEL 0x03 +; +USB2TS0_RDL 0x80 +USB2TS1_RDL 0x80 +; +IN_SEL 0x22 + diff --git a/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/firmware/cimax+usb_ms.cfg b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/firmware/cimax+usb_ms.cfg new file mode 100644 index 000000000000..5c38429e78e5 --- /dev/null +++ b/drivers/amlogic/media_modules/stream_input/parser/hw_demux/dvb_ci/cimax/usb/firmware/cimax+usb_ms.cfg @@ -0,0 +1,136 @@ +; +; ************************ +; * INIT_TS.TXT SCRIPT * +; ************************ +; +; *** CLOSE INPUT *** +; +IN_SEL 0x00 +; +; *** CLOSE OUPUT *** +; +OUT_SEL 0x00 +; +; *** RESET FIFO *** +; +FIFO_CTRL 0x0f +SYNC_RTV_CTRL 0x0f +; +; +; ************************* +; * INIT_USB.TXT SCRIPT * +; ************************* +; +; *** Endpoint Config *** +; +DMA_ACC_EPS 0x3f +EPS_ENABLE 0x7f +; +; *** FIFO Control *** +; +USB2TS_CTRL 0x0f +TS2USB_CTRL 0x0f +; +; *** FREQ Control *** +; +USB2TS0_RDL 0x80 +USB2TS1_RDL 0x80 +; +;----------------------------------------------------------------------------- +; Set CAM power +;----------------------------------------------------------------------------- +; +GPIO0_DATA_OUT 0x00 +; +; unlock CFG +CFG_2 0x00 +; +; 1) DVB/CI/CI+/SCARD 2slot +CFG_1 0x00 +; +; 2) Set the Default "power off" state such as VCC_MODA=VCC_MODB=VPPx_MODA=VPPx_MODB='Z' +GPIO0_DFT 0x00 +; +; 3) Set GPIO3 as external power switch driver +GPIO0_MASK_DATA 0x07 +; +; 4) Set "power on" state (VCC=VPP1=VPP2= 5V) +GPIO0_DATA_OUT 0x01 +; +; 5) Lock config +CFG_2 0x01 +; +; 6) Write in the GPIO0_DIR_REG: defines the GPIOs, which +; are used to drive the external power switch, in output mode. +GPIO0_DIR 0x07 +; +; 7) Check VCCENable +?CFG_1 0x20 +; +; 8) Set & wait for PcmciaOutputEnable +|CFG_1 0x08 +?CFG_1 0x08 +; +;--------------------------------------- +; Set Router CAM +;--------------------------------------- +; +; +GAP_REMOVER_CH0_CTRL 0x0C +GAP_REMOVER_CH1_CTRL 0x0C + +; 9) CH0 & CH1 from CAM A & B, CAM A & B from CH0 & CH1 +; +ROUTER_CAM_MOD 0x21 +ROUTER_CAM_CH 0x00 +; +;_Wait 200 +;--------------------------------------- +; ROUTER CAM +;--------------------------------------- +OUT_SEL 0x03 +; +USB2TS0_RDL 0x80 +USB2TS1_RDL 0x80 +; +IN_SEL 0x22 + +; *************************** +; * MuliStream.TXT SCRIPT * +; *************************** +; +; *** CLOSE INPUT *** +; +IN_SEL 0x00 +; +; *** CLOSE OUPUT *** +; +OUT_SEL 0x00 +; +; *** RESET FIFO *** +; +FIFO_CTRL 0x0f +SYNC_RTV_CTRL 0x0f +; +; *** *** +; +CkMan_Config 0x1f +CkMan_Select 0x00 +MERGER_DIV_MICLK 0x02 +SYNC_SYMBOL 0x0d +PID_AND_SYNC_REMAPPER_INV_CTRL 0x01 + +FIFO_CTRL 0x0f +ROUTER_CAM_MOD 0x03 +ROUTER_CAM_CH 0x80 + +USB2TS_CTRL 0x0f +TS2USB_CTRL 0x0f +USB2TS0_RDL 0x20 +USB2TS1_RDL 0x20 + +OUT_SEL 0x03 +IN_SEL 0x22 +; +; ************************ +; diff --git a/drivers/amlogic/media_modules/stream_input/parser/psparser.c b/drivers/amlogic/media_modules/stream_input/parser/psparser.c index c3b63c181a98..3197976e437e 100644 --- a/drivers/amlogic/media_modules/stream_input/parser/psparser.c +++ b/drivers/amlogic/media_modules/stream_input/parser/psparser.c @@ -598,15 +598,6 @@ static u32 parser_process(s32 type, s32 packet_len) SET_DISCARD_SIZE(packet_len); return DISCARD_SEARCH; } - - if (!packet_len) - return SEARCH_START_CODE; - - else { - SET_BLOCK(packet_len); - audio_data_parsed += packet_len; - return SEND_AUDIO_SEARCH; - } } return SEARCH_START_CODE; @@ -1025,6 +1016,7 @@ void psparser_release(void) pr_info("psparser release subtitle info\n"); #endif } +EXPORT_SYMBOL(psparser_release); ssize_t psparser_write(struct file *file, struct stream_buf_s *vbuf, diff --git a/drivers/amlogic/media_modules/stream_input/parser/streambuf.c b/drivers/amlogic/media_modules/stream_input/parser/streambuf.c index 14991a940335..256afb99a80a 100644 --- a/drivers/amlogic/media_modules/stream_input/parser/streambuf.c +++ b/drivers/amlogic/media_modules/stream_input/parser/streambuf.c @@ -183,6 +183,7 @@ int stbuf_fetch_init(void) } return 0; } +EXPORT_SYMBOL(stbuf_fetch_init); void stbuf_fetch_release(void) { @@ -362,6 +363,7 @@ s32 stbuf_init(struct stream_buf_s *buf, struct vdec_s *vdec, bool is_multi) MEM_CTRL_EMPTY_EN); return 0; } +EXPORT_SYMBOL(stbuf_init); void stbuf_vdec2_init(struct stream_buf_s *buf) { @@ -425,6 +427,7 @@ void stbuf_release(struct stream_buf_s *buf, bool is_multi) } buf->flag &= ~BUF_FLAG_IN_USE; } +EXPORT_SYMBOL(stbuf_release); u32 stbuf_sub_rp_get(void) { diff --git a/drivers/amlogic/media_modules/stream_input/parser/streambuf.h b/drivers/amlogic/media_modules/stream_input/parser/streambuf.h index 6ea2c75c32c2..d73865e010f7 100644 --- a/drivers/amlogic/media_modules/stream_input/parser/streambuf.h +++ b/drivers/amlogic/media_modules/stream_input/parser/streambuf.h @@ -104,9 +104,11 @@ struct drm_info { u32 drm_vir; u32 drm_remap; u32 data_offset; - u32 extpad[8]; + u32 handle; + u32 extpad[7]; } /*drminfo_t */; +#define TYPE_DRMINFO_V2 0x100 #define TYPE_DRMINFO 0x80 #define TYPE_PATTERN 0x40 diff --git a/drivers/amlogic/media_modules/stream_input/parser/thread_rw.c b/drivers/amlogic/media_modules/stream_input/parser/thread_rw.c index 04e5a2c4613d..6fe6cd871dc0 100644 --- a/drivers/amlogic/media_modules/stream_input/parser/thread_rw.c +++ b/drivers/amlogic/media_modules/stream_input/parser/thread_rw.c @@ -254,7 +254,6 @@ static int do_write_work_in(struct threadrw_write_task *task) if (write_len > 0) { spin_lock_irqsave(&task->lock, flags); task->passed_data_len += write_len; - task->buffered_data_size -= write_len; spin_unlock_irqrestore(&task->lock, flags); } return need_re_write; @@ -445,6 +444,22 @@ err1: *fifo data size; */ +void threadrw_update_buffer_level(struct stream_buf_s *stbuf, + int parsed_size) +{ + struct threadrw_write_task *task = stbuf->write_thread; + unsigned long flags; + + if (task) + { + spin_lock_irqsave(&task->lock, flags); + task->buffered_data_size -= parsed_size; + spin_unlock_irqrestore(&task->lock, flags); + } + +} +EXPORT_SYMBOL(threadrw_update_buffer_level); + int threadrw_buffer_level(struct stream_buf_s *stbuf) { struct threadrw_write_task *task = stbuf->write_thread; diff --git a/drivers/amlogic/media_modules/stream_input/parser/thread_rw.h b/drivers/amlogic/media_modules/stream_input/parser/thread_rw.h index c6283f0963ab..a91b00498efc 100644 --- a/drivers/amlogic/media_modules/stream_input/parser/thread_rw.h +++ b/drivers/amlogic/media_modules/stream_input/parser/thread_rw.h @@ -48,5 +48,6 @@ int threadrw_alloc_more_buffer_size( struct stream_buf_s *stbuf, int size); int threadrw_support_more_buffers(struct stream_buf_s *stbuf); - +void threadrw_update_buffer_level(struct stream_buf_s *stbuf, + int parsed_size); #endif diff --git a/drivers/amlogic/media_modules/stream_input/parser/tsdemux.c b/drivers/amlogic/media_modules/stream_input/parser/tsdemux.c index a93396f350c0..ac34cf74c3d3 100644 --- a/drivers/amlogic/media_modules/stream_input/parser/tsdemux.c +++ b/drivers/amlogic/media_modules/stream_input/parser/tsdemux.c @@ -47,6 +47,8 @@ #include #include "../amports/amports_priv.h" +#define MAX_DRM_PACKAGE_SIZE 0x500000 + static const char tsdemux_fetch_id[] = "tsdemux-fetch-id"; static const char tsdemux_irq_id[] = "tsdemux-irq-id"; @@ -111,7 +113,7 @@ int tsdemux_set_reset_flag(void) static int tsdemux_reset(void) { unsigned long flags; - int r; + int r = 0; spin_lock_irqsave(&demux_ops_lock, flags); if (demux_ops && demux_ops->reset) { @@ -126,7 +128,7 @@ static int tsdemux_reset(void) static int tsdemux_request_irq(irq_handler_t handler, void *data) { unsigned long flags; - int r; + int r = 0; spin_lock_irqsave(&demux_ops_lock, flags); if (demux_ops && demux_ops->request_irq) @@ -139,7 +141,7 @@ static int tsdemux_request_irq(irq_handler_t handler, void *data) static int tsdemux_free_irq(void) { unsigned long flags; - int r; + int r = 0; spin_lock_irqsave(&demux_ops_lock, flags); if (demux_ops && demux_ops->free_irq) @@ -664,12 +666,13 @@ s32 tsdemux_init(u32 vid, u32 aid, u32 sid, u32 pcrid, bool is_hevc, } curr_pcr_id = pcrid; + pcrscr_valid = reset_pcr_regs(); + if ((pcrid < 0x1FFF) && (pcrid != vid) && (pcrid != aid) && (pcrid != sid)) tsdemux_set_pcrid(pcrid); } - pcrscr_valid = reset_pcr_regs(); first_pcr = 0; return 0; @@ -747,6 +750,7 @@ void tsdemux_release(void) amports_switch_gate("demux", 0); } +EXPORT_SYMBOL(tsdemux_release); static int limited_delay_check(struct file *file, struct stream_buf_s *vbuf, @@ -820,7 +824,12 @@ ssize_t drm_tswrite(struct file *file, if (drm->drm_flag == TYPE_DRMINFO && drm->drm_level == DRM_LEVEL1) { /* buf only has drminfo not have esdata; */ - realcount = drm->drm_pktsize; + if (drm->drm_pktsize <= MAX_DRM_PACKAGE_SIZE) + realcount = drm->drm_pktsize; + else { + pr_err("drm package size is error, size is %u\n", drm->drm_pktsize); + return -EINVAL; + } realbuf = drm->drm_phy; isphybuf = 1; } else @@ -1156,8 +1165,8 @@ u8 tsdemux_pcrvideo_valid(void) void tsdemux_pcr_set(unsigned int pcr) { if (pcr_init_flag == 0) { - timestamp_pcrscr_set(pcr); - timestamp_pcrscr_enable(1); + /*timestamp_pcrscr_set(pcr); + timestamp_pcrscr_enable(1);*/ pcr_init_flag = 1; } } diff --git a/drivers/amlogic/media_modules/stream_input/subtitle/subtitle.c b/drivers/amlogic/media_modules/stream_input/subtitle/subtitle.c new file mode 100644 index 000000000000..bfcf6122e7d8 --- /dev/null +++ b/drivers/amlogic/media_modules/stream_input/subtitle/subtitle.c @@ -0,0 +1,715 @@ +/* + * drivers/amlogic/media/subtitle/subtitle.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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//#include "amports_priv.h" + +//#include "amlog.h" +//MODULE_AMLOG(AMLOG_DEFAULT_LEVEL, 0, LOG_DEFAULT_LEVEL_DESC, + //LOG_DEFAULT_MASK_DESC); +#define DEVICE_NAME "amsubtitle" +/* Dev name as it appears in /proc/devices */ +#define DEVICE_CLASS_NAME "subtitle" + +static int subdevice_open; + +#define MAX_SUBTITLE_PACKET 10 +static DEFINE_MUTEX(amsubtitle_mutex); + +struct subtitle_data_s { + int subtitle_size; + int subtitle_pts; + char *data; +}; +static struct subtitle_data_s subtitle_data[MAX_SUBTITLE_PACKET]; +static int subtitle_enable = 1; +static int subtitle_total; +static int subtitle_width; +static int subtitle_height; +static int subtitle_type = -1; +static int subtitle_current; /* no subtitle */ +/* sub_index node will be modified by libplayer; amlogicplayer will use */ +/* it to detect wheather libplayer switch sub finished or not */ +static int subtitle_index; /* no subtitle */ +/* static int subtitle_size = 0; */ +/* static int subtitle_read_pos = 0; */ +static int subtitle_write_pos; +static int subtitle_start_pts; +static int subtitle_fps; +static int subtitle_subtype; +static int subtitle_reset; +/* static int *subltitle_address[MAX_SUBTITLE_PACKET]; */ + +enum subinfo_para_e { + SUB_NULL = -1, + SUB_ENABLE = 0, + SUB_TOTAL, + SUB_WIDTH, + SUB_HEIGHT, + SUB_TYPE, + SUB_CURRENT, + SUB_INDEX, + SUB_WRITE_POS, + SUB_START_PTS, + SUB_FPS, + SUB_SUBTYPE, + SUB_RESET, + SUB_DATA_T_SIZE, + SUB_DATA_T_DATA +}; + +struct subinfo_para_s { + enum subinfo_para_e subinfo_type; + int subtitle_info; + char *data; +}; + +/* total */ +/* curr */ +/* bimap */ +/* text */ +/* type */ +/* info */ +/* pts */ +/* duration */ +/* color pallete */ +/* width/height */ + +static ssize_t show_curr(struct class *class, struct class_attribute *attr, + char *buf) +{ + return sprintf(buf, "%d: current\n", subtitle_current); +} + +static ssize_t store_curr(struct class *class, struct class_attribute *attr, + const char *buf, size_t size) +{ + unsigned int curr; + ssize_t r; + + r = kstrtoint(buf, 0, &curr); + if (r < 0) + return -EINVAL; + + + subtitle_current = curr; + + return size; +} + +static ssize_t show_index(struct class *class, struct class_attribute *attr, + char *buf) +{ + return sprintf(buf, "%d: current\n", subtitle_index); +} + +static ssize_t store_index(struct class *class, struct class_attribute *attr, + const char *buf, size_t size) +{ + unsigned int curr; + ssize_t r; + + r = kstrtoint(buf, 0, &curr); + if (r < 0) + return -EINVAL; + + subtitle_index = curr; + + return size; +} + +static ssize_t show_reset(struct class *class, struct class_attribute *attr, + char *buf) +{ + return sprintf(buf, "%d: current\n", subtitle_reset); +} + +static ssize_t store_reset(struct class *class, struct class_attribute *attr, + const char *buf, size_t size) +{ + unsigned int reset; + ssize_t r; + + r = kstrtoint(buf, 0, &reset); + + pr_info("reset is %d\n", reset); + if (r < 0) + return -EINVAL; + + + subtitle_reset = reset; + + return size; +} + +static ssize_t show_type(struct class *class, struct class_attribute *attr, + char *buf) +{ + return sprintf(buf, "%d: type\n", subtitle_type); +} + +static ssize_t store_type(struct class *class, struct class_attribute *attr, + const char *buf, size_t size) +{ + unsigned int type; + ssize_t r; + + r = kstrtoint(buf, 0, &type); + if (r < 0) + return -EINVAL; + + subtitle_type = type; + + return size; +} + +static ssize_t show_width(struct class *class, struct class_attribute *attr, + char *buf) +{ + return sprintf(buf, "%d: width\n", subtitle_width); +} + +static ssize_t store_width(struct class *class, struct class_attribute *attr, + const char *buf, size_t size) +{ + unsigned int width; + ssize_t r; + + r = kstrtoint(buf, 0, &width); + if (r < 0) + return -EINVAL; + + subtitle_width = width; + + return size; +} + +static ssize_t show_height(struct class *class, struct class_attribute *attr, + char *buf) +{ + return sprintf(buf, "%d: height\n", subtitle_height); +} + +static ssize_t store_height(struct class *class, struct class_attribute *attr, + const char *buf, size_t size) +{ + unsigned int height; + ssize_t r; + + r = kstrtoint(buf, 0, &height); + if (r < 0) + return -EINVAL; + + subtitle_height = height; + + return size; +} + +static ssize_t show_total(struct class *class, struct class_attribute *attr, + char *buf) +{ + return sprintf(buf, "%d: num\n", subtitle_total); +} + +static ssize_t store_total(struct class *class, struct class_attribute *attr, + const char *buf, size_t size) +{ + unsigned int total; + ssize_t r; + + r = kstrtoint(buf, 0, &total); + if (r < 0) + return -EINVAL; + pr_info("subtitle num is %d\n", total); + subtitle_total = total; + + return size; +} + +static ssize_t show_enable(struct class *class, struct class_attribute *attr, + char *buf) +{ + if (subtitle_enable) + return sprintf(buf, "1: enabled\n"); + + return sprintf(buf, "0: disabled\n"); +} + +static ssize_t store_enable(struct class *class, struct class_attribute *attr, + const char *buf, size_t size) +{ + unsigned int mode; + ssize_t r; + + r = kstrtoint(buf, 0, &mode); + if (r < 0) + return -EINVAL; + pr_info("subtitle enable is %d\n", mode); + subtitle_enable = mode ? 1 : 0; + + return size; +} + +static ssize_t show_size(struct class *class, struct class_attribute *attr, + char *buf) +{ + if (subtitle_enable) + return sprintf(buf, "1: size\n"); + + return sprintf(buf, "0: size\n"); +} + +static ssize_t store_size(struct class *class, struct class_attribute *attr, + const char *buf, size_t size) +{ + unsigned int ssize; + ssize_t r; + + r = kstrtoint(buf, 0, &ssize); + if (r < 0) + return -EINVAL; + pr_info("subtitle size is %d\n", ssize); + subtitle_data[subtitle_write_pos].subtitle_size = ssize; + + return size; +} + +static ssize_t show_startpts(struct class *class, struct class_attribute *attr, + char *buf) +{ + return sprintf(buf, "%d: pts\n", subtitle_start_pts); +} + +static ssize_t store_startpts(struct class *class, struct class_attribute *attr, + const char *buf, size_t size) +{ + unsigned int spts; + ssize_t r; + + r = kstrtoint(buf, 0, &spts); + if (r < 0) + return -EINVAL; + pr_info("subtitle start pts is %x\n", spts); + subtitle_start_pts = spts; + + return size; +} + +static ssize_t show_data(struct class *class, struct class_attribute *attr, + char *buf) +{ +#if 0 + if (subtitle_data[subtitle_write_pos].data) + return sprintf(buf, "%lld\n", + (unsigned long)(subtitle_data[subtitle_write_pos].data)); +#endif + return sprintf(buf, "0: disabled\n"); +} + +static ssize_t store_data(struct class *class, struct class_attribute *attr, + const char *buf, size_t size) +{ + unsigned int address; + ssize_t r; + + r = kstrtoint(buf, 0, &address); + if ((r == 0)) + return -EINVAL; +#if 0 + if (subtitle_data[subtitle_write_pos].subtitle_size > 0) { + subtitle_data[subtitle_write_pos].data = vmalloc(( + subtitle_data[subtitle_write_pos].subtitle_size)); + if (subtitle_data[subtitle_write_pos].data) + memcpy(subtitle_data[subtitle_write_pos].data, + (unsigned long *)address, + subtitle_data[subtitle_write_pos].subtitle_size); + } + pr_info("subtitle data address is %x", + (unsigned int)(subtitle_data[subtitle_write_pos].data)); +#endif + subtitle_write_pos++; + if (subtitle_write_pos >= MAX_SUBTITLE_PACKET) + subtitle_write_pos = 0; + return 1; +} + +static ssize_t show_fps(struct class *class, struct class_attribute *attr, + char *buf) +{ + return sprintf(buf, "%d: fps\n", subtitle_fps); +} + +static ssize_t store_fps(struct class *class, struct class_attribute *attr, + const char *buf, size_t size) +{ + unsigned int ssize; + ssize_t r; + + r = kstrtoint(buf, 0, &ssize); + if (r < 0) + return -EINVAL; + pr_info("subtitle fps is %d\n", ssize); + subtitle_fps = ssize; + + return size; +} + +static ssize_t show_subtype(struct class *class, struct class_attribute *attr, + char *buf) +{ + return sprintf(buf, "%d: subtype\n", subtitle_subtype); +} + +static ssize_t store_subtype(struct class *class, struct class_attribute *attr, + const char *buf, size_t size) +{ + unsigned int ssize; + ssize_t r; + + r = kstrtoint(buf, 0, &ssize); + if (r < 0) + return -EINVAL; + pr_info("subtitle subtype is %d\n", ssize); + subtitle_subtype = ssize; + + return size; +} + +static struct class_attribute subtitle_class_attrs[] = { + __ATTR(enable, 0664, show_enable, store_enable), + __ATTR(total, 0664, show_total, store_total), + __ATTR(width, 0664, show_width, store_width), + __ATTR(height, 0664, show_height, store_height), + __ATTR(type, 0664, show_type, store_type), + __ATTR(curr, 0664, show_curr, store_curr), + __ATTR(index, 0664, show_index, store_index), + __ATTR(size, 0664, show_size, store_size), + __ATTR(data, 0664, show_data, store_data), + __ATTR(startpts, 0664, show_startpts, + store_startpts), + __ATTR(fps, 0664, show_fps, store_fps), + __ATTR(subtype, 0664, show_subtype, + store_subtype), + __ATTR(reset, 0644, show_reset, store_reset), + __ATTR_NULL +}; + + +/********************************************************* + * /dev/amvideo APIs + *********************************************************/ +static int amsubtitle_open(struct inode *inode, struct file *file) +{ + mutex_lock(&amsubtitle_mutex); + + if (subdevice_open) { + mutex_unlock(&amsubtitle_mutex); + return -EBUSY; + } + + subdevice_open = 1; + + try_module_get(THIS_MODULE); + + mutex_unlock(&amsubtitle_mutex); + + return 0; +} + +static int amsubtitle_release(struct inode *inode, struct file *file) +{ + mutex_lock(&amsubtitle_mutex); + + subdevice_open = 0; + + module_put(THIS_MODULE); + + mutex_unlock(&amsubtitle_mutex); + + return 0; +} + +static long amsubtitle_ioctl(struct file *file, unsigned int cmd, ulong arg) +{ + switch (cmd) { + case AMSTREAM_IOC_GET_SUBTITLE_INFO: { + struct subinfo_para_s Vstates; + struct subinfo_para_s *states = &Vstates; + + if (copy_from_user((void *)states, + (void *)arg, sizeof(Vstates))) + return -EFAULT; + switch (states->subinfo_type) { + case SUB_ENABLE: + states->subtitle_info = subtitle_enable; + break; + case SUB_TOTAL: + states->subtitle_info = subtitle_total; + break; + case SUB_WIDTH: + states->subtitle_info = subtitle_width; + break; + case SUB_HEIGHT: + states->subtitle_info = subtitle_height; + break; + case SUB_TYPE: + states->subtitle_info = subtitle_type; + break; + case SUB_CURRENT: + states->subtitle_info = subtitle_current; + break; + case SUB_INDEX: + states->subtitle_info = subtitle_index; + break; + case SUB_WRITE_POS: + states->subtitle_info = subtitle_write_pos; + break; + case SUB_START_PTS: + states->subtitle_info = subtitle_start_pts; + break; + case SUB_FPS: + states->subtitle_info = subtitle_fps; + break; + case SUB_SUBTYPE: + states->subtitle_info = subtitle_subtype; + break; + case SUB_RESET: + states->subtitle_info = subtitle_reset; + break; + case SUB_DATA_T_SIZE: + states->subtitle_info = + subtitle_data[subtitle_write_pos].subtitle_size; + break; + case SUB_DATA_T_DATA: { + if (states->subtitle_info > 0) + states->subtitle_info = + (long)subtitle_data[subtitle_write_pos].data; + } + break; + default: + break; + } + if (copy_to_user((void *)arg, (void *)states, sizeof(Vstates))) + return -EFAULT; + } + + break; + case AMSTREAM_IOC_SET_SUBTITLE_INFO: { + struct subinfo_para_s Vstates; + struct subinfo_para_s *states = &Vstates; + + if (copy_from_user((void *)states, + (void *)arg, sizeof(Vstates))) + return -EFAULT; + switch (states->subinfo_type) { + case SUB_ENABLE: + subtitle_enable = states->subtitle_info; + break; + case SUB_TOTAL: + subtitle_total = states->subtitle_info; + break; + case SUB_WIDTH: + subtitle_width = states->subtitle_info; + break; + case SUB_HEIGHT: + subtitle_height = states->subtitle_info; + break; + case SUB_TYPE: + subtitle_type = states->subtitle_info; + break; + case SUB_CURRENT: + subtitle_current = states->subtitle_info; + break; + case SUB_INDEX: + subtitle_index = states->subtitle_info; + break; + case SUB_WRITE_POS: + subtitle_write_pos = states->subtitle_info; + break; + case SUB_START_PTS: + subtitle_start_pts = states->subtitle_info; + break; + case SUB_FPS: + subtitle_fps = states->subtitle_info; + break; + case SUB_SUBTYPE: + subtitle_subtype = states->subtitle_info; + break; + case SUB_RESET: + subtitle_reset = states->subtitle_info; + break; + case SUB_DATA_T_SIZE: + subtitle_data[subtitle_write_pos].subtitle_size = + states->subtitle_info; + break; + case SUB_DATA_T_DATA: { + if (states->subtitle_info > 0) { + subtitle_data[subtitle_write_pos].data = + vmalloc((states->subtitle_info)); + if (subtitle_data[subtitle_write_pos].data) + memcpy( + subtitle_data[subtitle_write_pos].data, + (char *)states->data, + states->subtitle_info); + } + + subtitle_write_pos++; + if (subtitle_write_pos >= MAX_SUBTITLE_PACKET) + subtitle_write_pos = 0; + } + break; + default: + break; + } + + } + + break; + default: + break; + } + + return 0; +} + +#ifdef CONFIG_COMPAT +static long amsub_compat_ioctl(struct file *file, unsigned int cmd, ulong arg) +{ + long ret = 0; + + ret = amsubtitle_ioctl(file, cmd, (ulong)compat_ptr(arg)); + return ret; +} +#endif + +static const struct file_operations amsubtitle_fops = { + .owner = THIS_MODULE, + .open = amsubtitle_open, + .release = amsubtitle_release, + .unlocked_ioctl = amsubtitle_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = amsub_compat_ioctl, +#endif +}; + +static struct device *amsubtitle_dev; +static dev_t amsub_devno; +static struct class *amsub_clsp; +static struct cdev *amsub_cdevp; +#define AMSUBTITLE_DEVICE_COUNT 1 + +static void create_amsub_attrs(struct class *class) +{ + int i = 0; + + for (i = 0; subtitle_class_attrs[i].attr.name; i++) { + if (class_create_file(class, &subtitle_class_attrs[i]) < 0) + break; + } +} + +static void remove_amsub_attrs(struct class *class) +{ + int i = 0; + + for (i = 0; subtitle_class_attrs[i].attr.name; i++) + class_remove_file(class, &subtitle_class_attrs[i]); +} + +int subtitle_init(void) +{ + int ret = 0; + + ret = alloc_chrdev_region(&amsub_devno, 0, AMSUBTITLE_DEVICE_COUNT, + DEVICE_NAME); + if (ret < 0) { + pr_info("amsub: failed to alloc major number\n"); + ret = -ENODEV; + return ret; + } + + amsub_clsp = class_create(THIS_MODULE, DEVICE_CLASS_NAME); + if (IS_ERR(amsub_clsp)) { + ret = PTR_ERR(amsub_clsp); + goto err1; + } + + create_amsub_attrs(amsub_clsp); + + amsub_cdevp = kmalloc(sizeof(struct cdev), GFP_KERNEL); + if (!amsub_cdevp) { + /*pr_info("amsub: failed to allocate memory\n");*/ + ret = -ENOMEM; + goto err2; + } + + cdev_init(amsub_cdevp, &amsubtitle_fops); + amsub_cdevp->owner = THIS_MODULE; + /* connect the major/minor number to cdev */ + ret = cdev_add(amsub_cdevp, amsub_devno, AMSUBTITLE_DEVICE_COUNT); + if (ret) { + pr_info("amsub:failed to add cdev\n"); + goto err3; + } + + amsubtitle_dev = device_create(amsub_clsp, + NULL, MKDEV(MAJOR(amsub_devno), 0), + NULL, DEVICE_NAME); + + if (IS_ERR(amsubtitle_dev)) { + pr_err("## Can't create amsubtitle device\n"); + goto err4; + } + + return 0; + +err4: + cdev_del(amsub_cdevp); +err3: + kfree(amsub_cdevp); +err2: + remove_amsub_attrs(amsub_clsp); + class_destroy(amsub_clsp); +err1: + unregister_chrdev_region(amsub_devno, 1); + + return ret; +} +EXPORT_SYMBOL(subtitle_init); + +void subtitle_exit(void) +{ + unregister_chrdev_region(amsub_devno, 1); + device_destroy(amsub_clsp, MKDEV(MAJOR(amsub_devno), 0)); + cdev_del(amsub_cdevp); + kfree(amsub_cdevp); + remove_amsub_attrs(amsub_clsp); + class_destroy(amsub_clsp); +} +EXPORT_SYMBOL(subtitle_exit); + diff --git a/drivers/amlogic/media_modules/stream_input/subtitle/subtitle.h b/drivers/amlogic/media_modules/stream_input/subtitle/subtitle.h new file mode 100644 index 000000000000..375a31a06d25 --- /dev/null +++ b/drivers/amlogic/media_modules/stream_input/subtitle/subtitle.h @@ -0,0 +1,24 @@ +/* + * drivers/amlogic/media/stream_input/amports/amports_priv.h + * + * Copyright (C) 2016 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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 SUBTITLE_H +#define SUBTITLE_H + +int subtitle_init(void); +void subtitle_exit(void); + +#endif diff --git a/drivers/amlogic/media_modules/stream_input/tv_frontend/aml_fe.c b/drivers/amlogic/media_modules/stream_input/tv_frontend/aml_fe.c index f683f2ca5f34..6253def75c4f 100644 --- a/drivers/amlogic/media_modules/stream_input/tv_frontend/aml_fe.c +++ b/drivers/amlogic/media_modules/stream_input/tv_frontend/aml_fe.c @@ -1,3 +1,22 @@ +/* +* 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. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ /* * AMLOGIC DVB frontend driver. */ @@ -749,7 +768,7 @@ static int aml_fe_man_init(struct aml_fe_man *man, struct aml_fe *fe, int id) ret = fe_of_property_u32(fe, "tuner", &value); if (!ret) { - int id = value; + id = value; if ((id < 0) || (id >= FE_DEV_COUNT) || !fe_man.tuner[id].drv) { pr_error("invalid tuner device id %d\n", id); @@ -762,7 +781,7 @@ static int aml_fe_man_init(struct aml_fe_man *man, struct aml_fe *fe, int id) ret = fe_of_property_u32(fe, "atv_demod", &value); if (!ret) { - int id = value; + id = value; if ((id < 0) || (id >= FE_DEV_COUNT) || @@ -777,7 +796,7 @@ static int aml_fe_man_init(struct aml_fe_man *man, struct aml_fe *fe, int id) ret = fe_of_property_u32(fe, "dtv_demod", &value); if (!ret) { - int id = value; + id = value; if ((id < 0) || (id >= FE_DEV_COUNT) || @@ -813,7 +832,7 @@ static int aml_fe_man_init(struct aml_fe_man *man, struct aml_fe *fe, int id) ret = fe_of_property_u32(fe, "dev", &value); if (!ret) { - int id = value; + id = value; if ((id >= 0) && (id < FE_DEV_COUNT)) fe->dev_id = id; diff --git a/drivers/amlogic/media_modules/stream_input/tv_frontend/aml_fe.h b/drivers/amlogic/media_modules/stream_input/tv_frontend/aml_fe.h index c32c3801617f..c975b4ce8941 100644 --- a/drivers/amlogic/media_modules/stream_input/tv_frontend/aml_fe.h +++ b/drivers/amlogic/media_modules/stream_input/tv_frontend/aml_fe.h @@ -1,3 +1,22 @@ +/* +* 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. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ #ifndef _AML_FE_H_ #define _AML_FE_H_ @@ -42,6 +61,7 @@ #include "../parser/hw_demux/aml_dvb.h" enum aml_tuner_type_t { + AM_TUNER_NONE = 0, AM_TUNER_SI2176 = 1, AM_TUNER_SI2196 = 2, AM_TUNER_FQ1216 = 3, @@ -51,7 +71,10 @@ enum aml_tuner_type_t { AM_TUNER_R840 = 7, AM_TUNER_SI2157 = 8, AM_TUNER_SI2151 = 9, - AM_TUNER_MXL661 = 10 + AM_TUNER_MXL661 = 10, + AM_TUNER_MXL608 = 11, + AM_TUNER_SI2159 = 12, + AM_TUNER_R842 = 13, }; enum aml_atv_demod_type_t { diff --git a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/aml_demod.c b/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/aml_demod.c index 009f81e2f727..7ccdfae3e1a9 100644 --- a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/aml_demod.c +++ b/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/aml_demod.c @@ -1,3 +1,22 @@ +/* +* 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. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ #include #include #include diff --git a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/demod_func.c b/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/demod_func.c index 9609a93c6b00..a54d82cadddc 100644 --- a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/demod_func.c +++ b/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/demod_func.c @@ -1,3 +1,22 @@ +/* +* 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. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ /*#include "register.h"*/ /*#include "c_arc_pointer_reg.h"*/ /*#include "a9_func.h"*/ diff --git a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/dvbc_func.c b/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/dvbc_func.c index 8f10dccffd82..cf2ea8163947 100644 --- a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/dvbc_func.c +++ b/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/dvbc_func.c @@ -1,3 +1,22 @@ +/* +* 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. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ #include #include #include diff --git a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/dvbt_func.c b/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/dvbt_func.c index b8515d888eda..7654aaef1607 100644 --- a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/dvbt_func.c +++ b/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/dvbt_func.c @@ -1,3 +1,22 @@ +/* +* 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. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ #include #include #include diff --git a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/i2c_func.c b/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/i2c_func.c index 7edef46742ff..68b214efc470 100644 --- a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/i2c_func.c +++ b/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/i2c_func.c @@ -1,3 +1,22 @@ +/* +* 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. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ #include #include #include diff --git a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/acf_filter_coefficient.h b/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/acf_filter_coefficient.h index b1437a2cdab2..57448858678d 100644 --- a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/acf_filter_coefficient.h +++ b/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/acf_filter_coefficient.h @@ -1,3 +1,22 @@ +/* +* 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. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ void program_acf(int acf1[20], int acf2[33]) { int i; diff --git a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/addr_dtmb_che.h b/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/addr_dtmb_che.h index 01ff78361d2b..4b231320adbf 100644 --- a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/addr_dtmb_che.h +++ b/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/addr_dtmb_che.h @@ -1,3 +1,22 @@ +/* +* 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. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ #ifndef __ADDR_DTMB_CHE_H__ #define __ADDR_DTMB_CHE_H__ diff --git a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/addr_dtmb_che_bit.h b/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/addr_dtmb_che_bit.h index edb848c9e676..d81c47795d20 100644 --- a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/addr_dtmb_che_bit.h +++ b/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/addr_dtmb_che_bit.h @@ -1,3 +1,22 @@ +/* +* 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. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ #ifndef __ADDR_DTMB_CHE_BIT_H__ #define __ADDR_DTMB_CHE_BIT_H__ diff --git a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/addr_dtmb_front.h b/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/addr_dtmb_front.h index a120bc8dff82..bf2f524e1caf 100644 --- a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/addr_dtmb_front.h +++ b/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/addr_dtmb_front.h @@ -1,3 +1,22 @@ +/* +* 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. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ #ifndef __ADDR_DTMB_FRONT_H__ #define __ADDR_DTMB_FRONT_H__ diff --git a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/addr_dtmb_front_bit.h b/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/addr_dtmb_front_bit.h index b6df7f602041..ec74d2353f27 100644 --- a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/addr_dtmb_front_bit.h +++ b/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/addr_dtmb_front_bit.h @@ -1,3 +1,22 @@ +/* +* 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. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ #ifndef __ADDR_DTMB_FRONT_BIT_H__ #define __ADDR_DTMB_FRONT_BIT_H__ diff --git a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/addr_dtmb_sync.h b/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/addr_dtmb_sync.h index 0455a4e3e35f..0607b19b4e23 100644 --- a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/addr_dtmb_sync.h +++ b/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/addr_dtmb_sync.h @@ -1,3 +1,22 @@ +/* +* 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. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ #ifndef __ADDR_DTMB_SYNC_H__ #define __ADDR_DTMB_SYNC_H__ diff --git a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/addr_dtmb_sync_bit.h b/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/addr_dtmb_sync_bit.h index 51c2517d6eec..0aebdd101af2 100644 --- a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/addr_dtmb_sync_bit.h +++ b/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/addr_dtmb_sync_bit.h @@ -1,3 +1,22 @@ +/* +* 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. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ #ifndef __ADDR_DTMB_SYNC_BIT_H__ #define __ADDR_DTMB_SYNC_BIT_H__ diff --git a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/addr_dtmb_top.h b/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/addr_dtmb_top.h index 827c87a75260..c12d26f66c0f 100644 --- a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/addr_dtmb_top.h +++ b/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/addr_dtmb_top.h @@ -1,3 +1,22 @@ +/* +* 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. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ #ifndef __ADDR_DTMB_TOP_H__ #define __ADDR_DTMB_TOP_H__ diff --git a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/addr_dtmb_top_bit.h b/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/addr_dtmb_top_bit.h index 4a6df5d5e8b6..63233c4e49d9 100644 --- a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/addr_dtmb_top_bit.h +++ b/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/addr_dtmb_top_bit.h @@ -1,3 +1,22 @@ +/* +* 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. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ #ifndef __ADDR_DTMB_TOP_BIT_H__ #define __ADDR_DTMB_TOP_BIT_H__ diff --git a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/aml_dtv_demod_reg.h b/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/aml_dtv_demod_reg.h index 9c318b1524f3..4f49fa7c5261 100644 --- a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/aml_dtv_demod_reg.h +++ b/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/aml_dtv_demod_reg.h @@ -1,3 +1,22 @@ +/* +* 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. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ #ifndef _DTV_REG_H_ #define _DTV_REG_H_ diff --git a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/amlfrontend.h b/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/amlfrontend.h index 9867a24e4ee5..5df7b1c48995 100644 --- a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/amlfrontend.h +++ b/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/amlfrontend.h @@ -1,3 +1,23 @@ +/* +* 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. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ + /***************************************************************** ** ** Copyright (C) 2010 Amlogic,Inc. diff --git a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/demod_func.h b/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/demod_func.h index 37f0441c644c..4c9d28193b18 100644 --- a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/demod_func.h +++ b/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/include/demod_func.h @@ -1,3 +1,22 @@ +/* +* 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. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ #ifdef DEMOD_FUNC_H #else #define DEMOD_FUNC_H diff --git a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/tuner_func.c b/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/tuner_func.c index a6ab31882b64..f4c1a3808ba6 100644 --- a/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/tuner_func.c +++ b/drivers/amlogic/media_modules/stream_input/tv_frontend/dtv_demod/tuner_func.c @@ -1,3 +1,22 @@ +/* +* 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. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Description: +*/ #include #include #include diff --git a/drivers/amlogic/memory_ext/Kconfig b/drivers/amlogic/memory_ext/Kconfig index fc411738cb5a..f40e0e33025b 100644 --- a/drivers/amlogic/memory_ext/Kconfig +++ b/drivers/amlogic/memory_ext/Kconfig @@ -11,6 +11,7 @@ config AMLOGIC_PAGE_TRACE bool "Amlogic trace for page allocate" depends on AMLOGIC_MEMORY_EXTEND depends on KALLSYMS + depends on !NUMA_BALANCING default y help Amlogic page trace will record function address of caller for page @@ -39,11 +40,23 @@ config AMLOGIC_CMA Amlogic CMA optimization for cma alloc/free problems Including policy change of CMA usage +config AMLOGIC_KASAN32 + bool "Amlogic KASAN support for 32bit kernel" + depends on AMLOGIC_MEMORY_EXTEND + depends on KASAN + depends on !64BIT + default y + help + Amlogic implementation for KASAN on 32bit ARM kernel. + Which can help to debug memory of use-after-free, + out-of-bounds and other problems. This config will + change memory layout. + config AMLOGIC_VMAP bool "Amlogic kernel stack" depends on AMLOGIC_MEMORY_EXTEND depends on !KASAN - depends on 64BIT + depends on !AMLOGIC_KASAN32 default y help This config is used to enable amlogic kernel stack @@ -59,3 +72,13 @@ config AMLOGIC_SLUB_DEBUG help This option open trace debug for each slub objects. And will give slub objdect allocator information when detected bad objects + +config AMLOGIC_WATCHPOINT + tristate "Amlogic point driver" + depends on HAVE_HW_BREAKPOINT + depends on AMLOGIC_MEMORY_EXTEND + default y + help + This driver export a debug sysfs in order + to using watch point function on ARMv8. + say y to enable Amlogic watch point driver diff --git a/drivers/amlogic/memory_ext/Makefile b/drivers/amlogic/memory_ext/Makefile index 8d3c2666ac00..58406009fb2a 100644 --- a/drivers/amlogic/memory_ext/Makefile +++ b/drivers/amlogic/memory_ext/Makefile @@ -4,3 +4,4 @@ obj-$(CONFIG_AMLOGIC_CMA) += aml_cma.o obj-$(CONFIG_AMLOGIC_SLUB_DEBUG) += aml_slub_debug.o obj-$(CONFIG_AMLOGIC_RAMDUMP) += ram_dump.o obj-$(CONFIG_AMLOGIC_VMAP) += vmap_stack.o +obj-$(CONFIG_AMLOGIC_WATCHPOINT) += watch_point.o diff --git a/drivers/amlogic/memory_ext/aml_cma.c b/drivers/amlogic/memory_ext/aml_cma.c index 450af9a1439a..563cfb760c0f 100644 --- a/drivers/amlogic/memory_ext/aml_cma.c +++ b/drivers/amlogic/memory_ext/aml_cma.c @@ -30,11 +30,14 @@ #include #include #include +#include #include #ifdef CONFIG_AMLOGIC_PAGE_TRACE #include #endif /* CONFIG_AMLOGIC_PAGE_TRACE */ +#define MAX_DEBUG_LEVEL 5 + struct work_cma { struct list_head list; unsigned long pfn; @@ -52,6 +55,8 @@ struct cma_pcp { static bool can_boost; static DEFINE_PER_CPU(struct cma_pcp, cma_pcp_thread); +static struct proc_dir_entry *dentry; +int cma_debug_level; DEFINE_SPINLOCK(cma_iso_lock); static atomic_t cma_allocate; @@ -96,6 +101,7 @@ EXPORT_SYMBOL(cma_page_count_update); #define RESTRIC_ANON 0 #define ANON_RATIO 60 +bool cma_first_wm_low __read_mostly; bool can_use_cma(gfp_t gfp_flags) { @@ -103,6 +109,9 @@ bool can_use_cma(gfp_t gfp_flags) unsigned long anon_cma; #endif /* RESTRIC_ANON */ + if (unlikely(!cma_first_wm_low)) + return false; + if (cma_forbidden_mask(gfp_flags)) return false; @@ -261,6 +270,7 @@ static int aml_alloc_contig_migrate_range(struct compact_control *cc, pfn = isolate_migratepages_range(cc, pfn, end); if (!pfn) { ret = -EINTR; + cma_debug(1, NULL, " iso migrate page fail\n"); break; } tries = 0; @@ -336,7 +346,7 @@ static int cma_boost_work_func(void *cma_data) drain_local_pages(NULL); } if (ret) - pr_debug("%s, failed, ret:%d\n", __func__, ret); + cma_debug(1, NULL, "failed, ret:%d\n", ret); next: complete(&c_work->end); if (kthread_should_stop()) { @@ -441,34 +451,6 @@ int cma_alloc_contig_boost(unsigned long start_pfn, unsigned long count) return ret; } -/* - * Some of these functions are implemented from page_isolate.c - */ -static bool can_free_list_page(struct page *page, struct list_head *list) -{ -#if 0 - unsigned long flags; - bool ret = false; - - if (!spin_trylock_irqsave(&cma_iso_lock, flags)) - return ret; - - if (!(page->flags & PAGE_FLAGS_CHECK_AT_FREE) && - !PageSwapBacked(page) && - (page->lru.next != LIST_POISON1)) { - if (list_empty(&page->lru)) - list_add(&page->lru, list); - else - list_move(&page->lru, list); - ret = true; - } - spin_unlock_irqrestore(&cma_iso_lock, flags); - return ret; -#else - return false; -#endif -} - static int __aml_check_pageblock_isolate(unsigned long pfn, unsigned long end_pfn, bool skip_hwpoisoned_pages, @@ -496,13 +478,7 @@ static int __aml_check_pageblock_isolate(unsigned long pfn, */ pfn++; } else { - /* This page can be freed ? */ - if (!page_count(page)) { - if (can_free_list_page(page, list)) { - pfn++; - continue; - } - } + cma_debug(1, page, " isolate failed\n"); break; } } @@ -577,14 +553,18 @@ int aml_cma_alloc_range(unsigned long start, unsigned long end) .mode = MIGRATE_SYNC, .page_type = COMPACT_CMA, .ignore_skip_hint = true, + .contended = false, }; INIT_LIST_HEAD(&cc.migratepages); + cma_debug(0, NULL, " range [%lx-%lx]\n", start, end); ret = start_isolate_page_range(get_align_pfn_low(start), get_align_pfn_high(end), MIGRATE_CMA, false); - if (ret) + if (ret) { + cma_debug(1, NULL, "ret:%d\n", ret); return ret; + } try_again: /* @@ -599,8 +579,10 @@ try_again: } else ret = aml_alloc_contig_migrate_range(&cc, start, end, 0); - if (ret && ret != -EBUSY) + if (ret && ret != -EBUSY) { + cma_debug(1, NULL, "ret:%d\n", ret); goto done; + } ret = 0; if (!boost_ok) { @@ -611,11 +593,8 @@ try_again: outer_start = start; while (!PageBuddy(pfn_to_page(outer_start))) { if (++order >= MAX_ORDER) { - ret = -EBUSY; - try_times++; - if (try_times < 10) - goto try_again; - goto done; + outer_start = start; + break; } outer_start &= ~0UL << order; } @@ -635,8 +614,8 @@ try_again: /* Make sure the range is really isolated. */ if (aml_check_pages_isolated(outer_start, end, false)) { - pr_debug("%s check_pages_isolated(%lx, %lx) failed\n", - __func__, outer_start, end); + cma_debug(1, NULL, "check page isolate(%lx, %lx) failed\n", + outer_start, end); try_times++; if (try_times < 10) goto try_again; @@ -647,7 +626,13 @@ try_again: /* Grab isolated pages from freelists. */ outer_end = isolate_freepages_range(&cc, outer_start, end); if (!outer_end) { - ret = -EBUSY; + if (cc.contended) { + ret = -EINTR; + pr_info("cma_alloc [%lx-%lx] aborted\n", start, end); + } else + ret = -EBUSY; + cma_debug(1, NULL, "iso free range(%lx, %lx) failed\n", + outer_start, end); goto done; } @@ -731,11 +716,70 @@ void aml_cma_free(unsigned long pfn, unsigned int nr_pages) } EXPORT_SYMBOL(aml_cma_free); +void show_page(struct page *page) +{ + unsigned long trace = 0; + unsigned long map_flag = -1UL; + + if (!page) + return; +#ifdef CONFIG_AMLOGIC_PAGE_TRACE + trace = get_page_trace(page); +#endif + if (page->mapping && !((unsigned long)page->mapping & 0x3)) + map_flag = page->mapping->flags; + pr_info("page:%lx, map:%p, mf:%lx, pf:%lx, m:%d, c:%d, f:%pf\n", + page_to_pfn(page), page->mapping, map_flag, + page->flags & 0xffffffff, + page_mapcount(page), page_count(page), + (void *)trace); +} + +static int cma_debug_show(struct seq_file *m, void *arg) +{ + seq_printf(m, "level=%d\n", cma_debug_level); + return 0; +} + +static ssize_t cma_debug_write(struct file *file, const char __user *buffer, + size_t count, loff_t *ppos) +{ + int arg = 0; + + if (kstrtoint_from_user(buffer, count, 10, &arg)) + return -EINVAL; + + if (arg > MAX_DEBUG_LEVEL) + return -EINVAL; + + cma_debug_level = arg; + return count; +} + +static int cma_debug_open(struct inode *inode, struct file *file) +{ + return single_open(file, cma_debug_show, NULL); +} + +static const struct file_operations cma_dbg_file_ops = { + .open = cma_debug_open, + .read = seq_read, + .llseek = seq_lseek, + .write = cma_debug_write, + .release = single_release, +}; + static int __init aml_cma_init(void) { atomic_set(&cma_allocate, 0); atomic_long_set(&nr_cma_allocated, 0); + dentry = proc_create("cma_debug", 0644, NULL, &cma_dbg_file_ops); + if (IS_ERR_OR_NULL(dentry)) { + pr_err("%s, create sysfs failed\n", __func__); + return -1; + } + return 0; } arch_initcall(aml_cma_init); diff --git a/drivers/amlogic/memory_ext/page_trace.c b/drivers/amlogic/memory_ext/page_trace.c index 1c2f8ba34694..4350dbc09e0f 100644 --- a/drivers/amlogic/memory_ext/page_trace.c +++ b/drivers/amlogic/memory_ext/page_trace.c @@ -38,7 +38,11 @@ #define DEBUG_PAGE_TRACE 0 #endif +#ifdef CONFIG_NUMA +#define COMMON_CALLER_SIZE 64 /* more function names if NUMA */ +#else #define COMMON_CALLER_SIZE 32 +#endif /* * this is a driver which will hook during page alloc/free and @@ -95,6 +99,14 @@ static struct fun_symbol common_func[] __initdata = { {"vmalloc", 1}, {"__alloc_page_frag", 1}, {"kmalloc_order", 0}, +#ifdef CONFIG_NUMA + {"alloc_pages_current", 1}, + {"alloc_page_interleave", 1}, + {"kmalloc_large_node", 1}, + {"kmem_cache_alloc_node", 1}, + {"__kmalloc_node", 1}, + {"alloc_pages_vma", 1}, +#endif #ifdef CONFIG_SLUB /* for some static symbols not exported in headfile */ {"new_slab", 0}, {"slab_alloc", 0}, @@ -1065,8 +1077,9 @@ void __init page_trace_mem_init(void) * flags, you should disable AMLOGIC_PAGE_TRACE or reduce some page * flags. */ - BUILD_BUG_ON((__NR_PAGEFLAGS + ZONES_WIDTH) > 32); - BUILD_BUG_ON(NODES_WIDTH > 0); + BUILD_BUG_ON((__NR_PAGEFLAGS + ZONES_WIDTH + + NODES_WIDTH + SECTIONS_WIDTH + + LAST_CPUPID_SHIFT) > 32); #else if (page_trace_disable) return; diff --git a/drivers/amlogic/memory_ext/ram_dump.c b/drivers/amlogic/memory_ext/ram_dump.c index 3634ad4fb818..5290a82aaeb1 100644 --- a/drivers/amlogic/memory_ext/ram_dump.c +++ b/drivers/amlogic/memory_ext/ram_dump.c @@ -26,38 +26,39 @@ #include #include #include +#include #include #include #include #include #include +#include #include +#include +#include +#include +#include +#include #include static unsigned long ramdump_base __initdata; static unsigned long ramdump_size __initdata; static bool ramdump_disable __initdata; +#define WAIT_TIMEOUT (40ULL * 1000 * 1000 * 1000) + struct ramdump { unsigned long mem_base; unsigned long mem_size; - struct mutex lock; - struct kobject *kobj; - struct work_struct clear_work; + unsigned long long tick; + void *mnt_buf; + const char *storage_device; + struct delayed_work work; int disable; }; static struct ramdump *ram; -static void meson_set_reboot_reason(int reboot_reason) -{ - struct arm_smccc_res smccc; - - arm_smccc_smc(SET_REBOOT_REASON, - reboot_reason, 0, 0, 0, 0, 0, 0, &smccc); - return; -} - static int __init early_ramdump_para(char *buf) { int ret; @@ -84,94 +85,10 @@ static int __init early_ramdump_para(char *buf) ramdump_disable = 1; } } - if (ramdump_disable) - meson_set_reboot_reason(MESON_NORMAL_BOOT); - return 0; } early_param("ramdump", early_ramdump_para); -static ssize_t ramdump_bin_read(struct file *filp, struct kobject *kobj, - struct bin_attribute *attr, - char *buf, loff_t off, size_t count) -{ - void *p = NULL; -#ifndef CONFIG_64BIT - struct page *page, *pages[1]; -#endif - - if (!ram->mem_base || off >= ram->mem_size) - return 0; - -#ifndef CONFIG_64BIT - page = phys_to_page(ram->mem_base + off); - pages[0] = page; - p = vmap(pages, 1, VM_MAP, PAGE_KERNEL); - if (!p) { - pr_info("%s, map %lx, %d failed, page:%p, pfn:%lx\n", - __func__, (unsigned long)(ram->mem_base + off), - count, page, page_to_pfn(page)); - return -EINVAL; - } -#else - p = (void *)(ram->mem_base + off); -#endif - if (off + count > ram->mem_size) - count = ram->mem_size - off; - mutex_lock(&ram->lock); - memcpy(buf, p, count); - mutex_unlock(&ram->lock); - - /* debug when read end */ - if (off + count >= ram->mem_size) - pr_info("%s, p=%p %p, off:%lli, c:%zi\n", - __func__, buf, p, off, count); -#ifndef CONFIG_64BIT - vunmap(p); -#endif - return count; -} - -int ramdump_disabled(void) -{ - if (ram) - return ram->disable; - return 0; -} -EXPORT_SYMBOL(ramdump_disabled); - -static ssize_t ramdump_bin_write(struct file *filp, - struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buf, loff_t off, size_t count) -{ - if (!ram->mem_size) - return -EINVAL; - - if (ram->mem_base && !strncmp("reboot", buf, 6)) - kernel_restart("RAM-DUMP finished\n"); - - if (!strncmp("disable", buf, 7)) { - ram->disable = 1; - meson_set_reboot_reason(MESON_NORMAL_BOOT); - } - if (!strncmp("enable", buf, 6)) { - ram->disable = 0; - meson_set_reboot_reason(MESON_KERNEL_PANIC); - } - - return count; -} - -static struct bin_attribute ramdump_attr = { - .attr = { - .name = "compmsg", - .mode = S_IRUGO | S_IWUSR, - }, - .read = ramdump_bin_read, - .write = ramdump_bin_write, -}; - /* * clear memory to avoid large amount of memory not used. * for ramdom data, it's hard to compress @@ -279,9 +196,242 @@ void ramdump_sync_data(void) } #endif +#ifdef CONFIG_64BIT +static void free_reserved_highmem(unsigned long start, unsigned long end) +{ +} +#else +static void free_reserved_highmem(unsigned long start, unsigned long end) +{ + for (; start < end; ) { + free_highmem_page(phys_to_page(start)); + start += PAGE_SIZE; + } +} +#endif + +static void free_reserved_mem(unsigned long start, unsigned long size) +{ + unsigned long end = PAGE_ALIGN(start + size); + struct page *page, *epage; + + page = phys_to_page(start); + if (PageHighMem(page)) { + free_reserved_highmem(start, end); + } else { + epage = phys_to_page(end); + if (!PageHighMem(epage)) { + free_reserved_area(__va(start), + __va(end), 0, "ramdump"); + } else { + /* reserved area cross zone */ + struct zone *zone; + unsigned long bound; + + zone = page_zone(page); + bound = zone_end_pfn(zone); + free_reserved_area(__va(start), + __va(bound << PAGE_SHIFT), + 0, "ramdump"); + zone = page_zone(epage); + bound = zone->zone_start_pfn; + free_reserved_highmem(bound << PAGE_SHIFT, end); + } + } +} + +static int check_storage_mounted(char **root) +{ + int fd, cnt, ret = 0; + char mnt_dev[64] = {}, *mnt_ptr, *root_dir; + + fd = sys_open("/proc/mounts", O_RDONLY, 0); + if (!fd) { + pr_debug("%s, open mounts failed:%d\n", __func__, fd); + return -EINVAL; + } + cnt = sys_read(fd, ram->mnt_buf, PAGE_SIZE); + if (cnt < 0) { + pr_debug("%s, read mounts failed:%d\n", __func__, cnt); + ret = -ENODEV; + goto exit; + } + pr_debug("read:%d, %s\n", cnt, (char *)ram->mnt_buf); + sprintf(mnt_dev, "/dev/block/%s", ram->storage_device); + mnt_ptr = strstr((char *)ram->mnt_buf, mnt_dev); + if (mnt_ptr) { + pr_debug("%s, find %s in buffer, ptr:%p\n", + __func__, mnt_dev, mnt_ptr); + root_dir = strstr(mnt_ptr, " "); + root_dir++; + *root = root_dir; + pr_debug("mount:%s root:%s\n", mnt_ptr, root_dir); + } else + ret = -ENODEV; +exit: + sys_close(fd); + return ret; +} + +static size_t save_data(int fd) +{ + unsigned long saved = 0, off = 0, s = 0, e; + void *buffer; + int block = (1 << (PAGE_SHIFT + MAX_ORDER - 1)), wsize = 0, ret, i; + struct vm_struct *area; + struct page *page, **pages = NULL; + + area = get_vm_area(block, VM_ALLOC); + if (!area) { + pr_err("%s, get vma failed\n", __func__); + return -ENOMEM; + } + + pages = kzalloc(sizeof(unsigned long) * MAX_ORDER_NR_PAGES, GFP_KERNEL); + if (!pages) + goto out; + + buffer = area->addr; + while (saved < ram->mem_size) { + s = ram->mem_size - saved; + if (s >= block) + wsize = block; + else + wsize = s; + + s = ram->mem_base + off; + e = s + PAGE_ALIGN(wsize); + + page = phys_to_page(s); + for (i = 0; i < MAX_ORDER_NR_PAGES; i++) { + pages[i] = page; + page++; + } + ret = map_kernel_range_noflush((unsigned long)buffer, + PAGE_ALIGN(wsize), + PAGE_KERNEL, + pages); + if (!ret) { + pr_err("map page:%lx failed\n", page_to_pfn(page)); + goto out; + } + ret = sys_write(fd, buffer, wsize); + if (ret != wsize) { + unmap_kernel_range((unsigned long)buffer, + PAGE_ALIGN(wsize)); + pr_err("%s, write failed\n", __func__); + goto out; + } + unmap_kernel_range((unsigned long)buffer, PAGE_ALIGN(wsize)); + free_reserved_mem(s, PAGE_ALIGN(wsize)); + saved += wsize; + off += wsize; + pr_debug("%s, write %08lx, size:%08x, saved:%08lx, off:%lx\n", + __func__, s, wsize, saved, off); + } +out: + free_vm_area(area); + kfree(pages); + pr_info("%s, write %08lx, size:%08x, saved:%08lx, off:%lx\n", + __func__, s, wsize, saved, off); + return saved; +} + +#define OPEN_FLAGS (O_WRONLY | O_CREAT | O_DSYNC | O_TRUNC) + +static void wait_to_save(struct work_struct *work) +{ + char *root; + int fd, ret = 0; + int need_reboot = 0; + + if ((sched_clock() - ram->tick) >= WAIT_TIMEOUT) { + pr_err("can't find mounted device, free saved data\n"); + need_reboot = 3; + goto exit; + } + + if (!check_storage_mounted(&root)) { + char wname[64] = {}, *next_token; + + /* write compressed data to storage device */ + next_token = strstr(root, " "); + if (next_token) + *next_token = '\0'; + sprintf(wname, "%s/crashdump-1.bin", root); + fd = sys_open(wname, OPEN_FLAGS, 0644); + if (fd < 0) { + pr_info("open %s failed:%d\n", wname, fd); + need_reboot = 3; + goto exit; + } + ret = save_data(fd); + if (ret != ram->mem_size) { + pr_err("write size %d not match %ld\n", + ret, ram->mem_size); + } + sys_fsync(fd); + sys_close(fd); + sys_sync(); + need_reboot = 1; + } else + schedule_delayed_work(&ram->work, 500); + +exit: + /* Nomatter what happened, reboot must be done in this function */ + if (need_reboot) { + if (need_reboot & 0x1) + kfree(ram->mnt_buf); + if (need_reboot & 0x02) + free_reserved_mem(ram->mem_base, ram->mem_size); + kernel_restart("RAM-DUMP finished"); + } +} + static int __init ramdump_probe(struct platform_device *pdev) { void __iomem *p = NULL; + struct device_node *np; + unsigned long dts_memory[2] = {0}, total_mem; + struct resource *res; + unsigned int dump_set; + int ret; + void __iomem *base; + const char *dev_name = NULL; + + np = of_find_node_by_name(NULL, "memory"); + if (!np) + return -EINVAL; + +#ifdef CONFIG_64BIT + ret = of_property_read_u64_array(np, "linux,usable-memory", + (u64 *)&dts_memory, 2); + if (ret) + ret = of_property_read_u64_array(np, "reg", + (u64 *)&dts_memory, 2); +#else + ret = of_property_read_u32_array(np, "linux,usable-memory", + (u32 *)&dts_memory, 2); + if (ret) + ret = of_property_read_u32_array(np, "reg", + (u32 *)&dts_memory, 2); +#endif + if (ret) + pr_info("can't get dts memory\n"); + else + pr_info("MEMORY:[%lx+%lx]\n", dts_memory[0], dts_memory[1]); + of_node_put(np); + + /* + * memory in dts is [start_addr size] patten. For amlogic soc, + * ddr address range is started from 0x0, usually start_addr in + * dts should be started with 0x0, but some soc must reserve a + * small framgment of memory at 0x0 for start up code. So start_addr + * can be 0x100000/0x1000000. But we always using 0x0 to get real + * DDR size for ramdump. So we using following formula to get total + * DDR size. + */ + total_mem = dts_memory[0] + dts_memory[1]; ram = kzalloc(sizeof(struct ramdump), GFP_KERNEL); if (!ram) @@ -290,44 +440,52 @@ static int __init ramdump_probe(struct platform_device *pdev) if (ramdump_disable) ram->disable = 1; + np = pdev->dev.of_node; + ret = of_property_read_string(np, "store_device", &dev_name); + if (!ret) { + ram->storage_device = dev_name; + pr_info("%s, storage device:%s\n", __func__, dev_name); + } + if (!ramdump_base || !ramdump_size) { pr_info("NO valid ramdump args:%lx %lx\n", ramdump_base, ramdump_size); } else { - #ifdef CONFIG_64BIT - p = ioremap_cache(ramdump_base, ramdump_size); - ram->mem_base = (unsigned long)p; - ram->mem_size = ramdump_size; - #else ram->mem_base = ramdump_base; ram->mem_size = ramdump_size; - #endif pr_info("%s, mem_base:%p, %lx, size:%lx\n", __func__, p, ramdump_base, ramdump_size); } - ram->kobj = kobject_create_and_add("mdump", kernel_kobj); - if (!ram->kobj) { - pr_err("%s, create sysfs failed\n", __func__); - goto err; + + if (!ram->disable) { + if (!ram->mem_base) { /* No compressed data */ + INIT_DELAYED_WORK(&ram->work, lazy_clear_work); + } else { /* with compressed data */ + INIT_DELAYED_WORK(&ram->work, wait_to_save); + ram->tick = sched_clock(); + ram->mnt_buf = kmalloc(PAGE_SIZE, GFP_KERNEL); + WARN_ON(!ram->mnt_buf); + } + schedule_delayed_work(&ram->work, 1); } - ramdump_attr.size = ram->mem_size; - if (sysfs_create_bin_file(ram->kobj, &ramdump_attr)) { - pr_err("%s, create sysfs1 failed\n", __func__); - goto err1; - } - mutex_init(&ram->lock); - if (!ram->disable && !ram->mem_size) { - INIT_WORK(&ram->clear_work, lazy_clear_work); - schedule_work(&ram->clear_work); + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, + "PREG_STICKY_REG8"); + if (res) { + base = devm_ioremap(&pdev->dev, res->start, + res->end - res->start); + if (!base) { + pr_err("%s, map reg failed\n", __func__); + goto err; + } + dump_set = readl(base); + dump_set &= ~RAMDUMP_STICKY_DATA_MASK; + dump_set |= ((total_mem >> 20) | AMLOGIC_KERNEL_BOOTED); + writel(dump_set, base); + pr_info("%s, set sticky to %x\n", __func__, dump_set); } return 0; -err1: - kobject_put(ram->kobj); err: -#ifdef CONFIG_64BIT - iounmap((void *)ram->mem_base); -#endif kfree(ram); return -EINVAL; @@ -335,11 +493,6 @@ err: static int ramdump_remove(struct platform_device *pdev) { - sysfs_remove_bin_file(ram->kobj, &ramdump_attr); -#ifdef CONFIG_64BIT - iounmap((void *)ram->mem_base); -#endif - kobject_put(ram->kobj); kfree(ram); return 0; } diff --git a/drivers/amlogic/memory_ext/vmap_stack.c b/drivers/amlogic/memory_ext/vmap_stack.c index 511cfc73616a..d199f76548c9 100644 --- a/drivers/amlogic/memory_ext/vmap_stack.c +++ b/drivers/amlogic/memory_ext/vmap_stack.c @@ -50,8 +50,21 @@ static unsigned char vmap_shrink_enable; static atomic_t vmap_stack_size; static struct aml_vmap *avmap; +#ifdef CONFIG_ARM64 DEFINE_PER_CPU(unsigned long [THREAD_SIZE/sizeof(long)], vmap_stack) __aligned(16); +#else +static unsigned long irq_stack1[(THREAD_SIZE/sizeof(long))] + __aligned(THREAD_SIZE); +void *irq_stack[NR_CPUS] = { + irq_stack1, /* only assign 1st irq stack ,other need alloc */ +}; +static unsigned long vmap_stack1[(THREAD_SIZE/sizeof(long))] + __aligned(THREAD_SIZE); +static void *vmap_stack[NR_CPUS] = { + vmap_stack1, /* only assign 1st vmap stack ,other need alloc */ +}; +#endif void update_vmap_stack(int diff) { @@ -65,7 +78,153 @@ int get_vmap_stack_size(void) } EXPORT_SYMBOL(get_vmap_stack_size); -static int is_vmap_addr(unsigned long addr) +#ifdef CONFIG_ARM64 +bool on_vmap_stack(unsigned long sp, int cpu) +{ + /* variable names the same as kernel/stacktrace.c */ + unsigned long low = (unsigned long)per_cpu(vmap_stack, cpu); + unsigned long high = low + THREAD_START_SP; + + return (low <= sp && sp <= high); +} +#endif + +#ifdef CONFIG_ARM +void notrace __setup_vmap_stack(unsigned long cpu) +{ + void *stack; + +#ifdef CONFIG_THUMB2_KERNEL +#define TAG "r" +#else +#define TAG "I" +#endif + stack = vmap_stack[cpu]; + if (!stack) { + stack = kmalloc(THREAD_SIZE, GFP_ATOMIC | __GFP_ZERO); + WARN_ON(!stack); + vmap_stack[cpu] = stack; + irq_stack[cpu] = kmalloc(THREAD_SIZE, GFP_ATOMIC | __GFP_ZERO); + WARN_ON(!irq_stack[cpu]); + } + + pr_debug("cpu %ld, vmap stack:[%lx-%lx]\n", + cpu, (unsigned long)stack, + (unsigned long)stack + THREAD_START_SP); + pr_debug("cpu %ld, irq stack:[%lx-%lx]\n", + cpu, (unsigned long)irq_stack[cpu], + (unsigned long)irq_stack[cpu] + THREAD_START_SP); + stack += THREAD_SIZE; + stack -= sizeof(struct thread_info); + /* + * reserve 24 byte for r0, lr, spsr, sp_svc and 8 bytes gap + */ + stack -= (24); + asm volatile ( + "msr cpsr_c, %1 \n" + "mov sp, %0 \n" + "msr cpsr_c, %2 \n" + : + : "r" (stack), + TAG(PSR_F_BIT | PSR_I_BIT | ABT_MODE), + TAG(PSR_F_BIT | PSR_I_BIT | SVC_MODE) + : "memory", "cc" + ); +} + +int on_irq_stack(unsigned long sp, int cpu) +{ + unsigned long sp_irq; + + sp_irq = (unsigned long)irq_stack[cpu]; + if ((sp & ~(THREAD_SIZE - 1)) == (sp_irq & ~(THREAD_SIZE - 1))) + return 1; + return 0; +} + +unsigned long notrace irq_stack_entry(unsigned long sp) +{ + int cpu = raw_smp_processor_id(); + + if (!on_irq_stack(sp, cpu)) { + unsigned long sp_irq = (unsigned long)irq_stack[cpu]; + void *src, *dst; + + /* + * copy some data to irq stack + */ + src = current_thread_info(); + dst = (void *)(sp_irq + THREAD_INFO_OFFSET); + memcpy(dst, src, offsetof(struct thread_info, cpu_context)); + sp_irq = (unsigned long)dst - 8; + /* + * save start addr of the interrupted task's context + * minus an extra 12 to force base sp 16Bytes aligned + */ + sp_irq = sp_irq - sizeof(sp) - 12; + *((unsigned long *)sp_irq) = sp; + return sp_irq; + } + return sp; +} + +unsigned long notrace pmd_check(unsigned long addr, unsigned long far) +{ + unsigned int index; + pgd_t *pgd, *pgd_k; + pud_t *pud, *pud_k; + pmd_t *pmd, *pmd_k; + + if (addr < TASK_SIZE) + return addr; + + index = pgd_index(addr); + + pgd = cpu_get_pgd() + index; + pgd_k = init_mm.pgd + index; + + if (pgd_none(*pgd_k)) + goto bad_area; + if (!pgd_present(*pgd)) + set_pgd(pgd, *pgd_k); + + pud = pud_offset(pgd, addr); + pud_k = pud_offset(pgd_k, addr); + + if (pud_none(*pud_k)) + goto bad_area; + if (!pud_present(*pud)) + set_pud(pud, *pud_k); + + pmd = pmd_offset(pud, addr); + pmd_k = pmd_offset(pud_k, addr); + +#ifdef CONFIG_ARM_LPAE + /* + * Only one hardware entry per PMD with LPAE. + */ + index = 0; +#else + /* + * On ARM one Linux PGD entry contains two hardware entries (see page + * tables layout in pgtable.h). We normally guarantee that we always + * fill both L1 entries. But create_mapping() doesn't follow the rule. + * It can create inidividual L1 entries, so here we have to call + * pmd_none() check for the entry really corresponded to address, not + * for the first of pair. + */ + index = (addr >> SECTION_SHIFT) & 1; +#endif + if (pmd_none(pmd_k[index])) + goto bad_area; + + copy_pmd(pmd, pmd_k); +bad_area: + return addr; +} +#endif + +int is_vmap_addr(unsigned long addr) { unsigned long start, end; @@ -96,6 +255,50 @@ static struct page *get_vmap_cached_page(int *remain) return page; } +static struct page *check_pte_exist(unsigned long addr) +{ + struct mm_struct *mm; + pgd_t *pgd; + pud_t *pud; + pmd_t *pmd; + pte_t *pte; + + mm = &init_mm; + + pgd = pgd_offset(mm, addr); + + if (pgd_none(*pgd)) + return NULL; + + if (pgd_bad(*pgd)) + return NULL; + + pud = pud_offset(pgd, addr); + if (pud_none(*pud)) + return NULL; + + if (pud_bad(*pud)) + return NULL; + + pmd = pmd_offset(pud, addr); + if (pmd_none(*pmd)) + return NULL; + + if (pmd_bad(*pmd)) + return NULL; + + pte = pte_offset_kernel(pmd, addr); + if (pte_none(*pte)) + return NULL; +#ifdef CONFIG_ARM64 + return pte_page(*pte); +#elif defined(CONFIG_ARM) + return pte_page(pte_val(*pte)); +#else + return NULL; /* not supported */ +#endif +} + static int vmap_mmu_set(struct page *page, unsigned long addr, int set) { pgd_t *pgd = NULL; @@ -121,16 +324,22 @@ static int vmap_mmu_set(struct page *page, unsigned long addr, int set) goto nomem; } - pte = pte_offset_map(pmd, addr); + pte = pte_offset_kernel(pmd, addr); if (set) set_pte_at(&init_mm, addr, pte, mk_pte(page, PAGE_KERNEL)); else pte_clear(&init_mm, addr, pte); - pte_unmap(pte); flush_tlb_kernel_range(addr, addr + PAGE_SIZE); +#ifdef CONFIG_ARM64 D("add:%lx, pgd:%p %llx, pmd:%p %llx, pte:%p %llx\n", addr, pgd, pgd_val(*pgd), pmd, pmd_val(*pmd), pte, pte_val(*pte)); +#elif defined(CONFIG_ARM) + D("add:%lx, pgd:%p %x, pmd:%p %x, pte:%p %x\n", + addr, pgd, (unsigned int)pgd_val(*pgd), + pmd, (unsigned int)pmd_val(*pmd), + pte, pte_val(*pte)); +#endif return 0; nomem: E("allocation page talbe failed, G:%p, U:%p, M:%p, T:%p", @@ -140,10 +349,16 @@ nomem: static int stack_floor_page(unsigned long addr) { + unsigned long pos; + + pos = addr & (THREAD_SIZE - 1); /* * stack address must align to THREAD_SIZE */ - return ((addr & (THREAD_SIZE - 1)) < PAGE_SIZE); + if (THREAD_SIZE_ORDER > 1) + return pos < PAGE_SIZE; + else + return pos < (PAGE_SIZE / 4); } static int check_addr_up_flow(unsigned long addr) @@ -153,17 +368,17 @@ static int check_addr_up_flow(unsigned long addr) * rage(aligned to THREAD_SIZE) but next page of this * addr is not mapped */ - if (stack_floor_page(addr) && - !vmalloc_to_page((const void *)(addr + PAGE_SIZE))) + if (stack_floor_page(addr) && !check_pte_exist(addr + PAGE_SIZE)) return 1; return 0; } -#if DEBUG -static void dump_backtrace_entry(unsigned long ip, unsigned long fp) +static void dump_backtrace_entry(unsigned long ip, unsigned long fp, + unsigned long sp) { unsigned long fp_size = 0; +#ifdef CONFIG_ARM64 if (fp >= VMALLOC_START) { fp_size = *((unsigned long *)fp) - fp; /* fp cross IRQ or vmap stack */ @@ -172,29 +387,95 @@ static void dump_backtrace_entry(unsigned long ip, unsigned long fp) } pr_info("[%016lx+%4ld][<%p>] %pS\n", fp, fp_size, (void *) ip, (void *) ip); +#elif defined(CONFIG_ARM) + if (fp >= TASK_SIZE) { + fp_size = fp - sp + 4; + /* fp cross IRQ or vmap stack */ + if (fp_size >= THREAD_SIZE) + fp_size = 0; + } + pr_info("[%08lx+%4ld][<%p>] %pS\n", + fp, fp_size, (void *) ip, (void *) ip); +#endif } -static void show_fault_stack(unsigned long addr, struct pt_regs *regs) +static noinline void show_fault_stack(unsigned long addr, struct pt_regs *regs) { struct stackframe frame; +#ifdef CONFIG_ARM64 frame.fp = regs->regs[29]; frame.sp = addr; frame.pc = (unsigned long)regs->regs[30]; +#elif defined(CONFIG_ARM) + frame.fp = regs->ARM_fp; + frame.sp = regs->ARM_sp; + frame.lr = regs->ARM_lr; + frame.pc = (unsigned long)regs->uregs[15]; +#endif - pr_info("Call trace:\n"); + pr_info("Addr:%lx, Call trace:\n", addr); +#ifdef CONFIG_ARM64 pr_info("[%016lx+%4ld][<%p>] %pS\n", addr, frame.fp - addr, (void *)regs->pc, (void *) regs->pc); +#elif defined(CONFIG_ARM) + pr_info("[%08lx+%4ld][<%p>] %pS\n", + addr, frame.fp - addr, (void *)regs->uregs[15], + (void *) regs->uregs[15]); +#endif while (1) { int ret; - dump_backtrace_entry(frame.pc, frame.fp); + dump_backtrace_entry(frame.pc, frame.fp, frame.sp); + #ifdef CONFIG_ARM64 ret = unwind_frame(current, &frame); + #elif defined(CONFIG_ARM) + ret = unwind_frame(&frame); + #endif if (ret < 0) break; } } + +static void check_sp_fault_again(struct pt_regs *regs) +{ + unsigned long sp = 0, addr; + struct page *page; + int cache; + +#ifdef CONFIG_ARM + sp = regs->ARM_sp; +#elif defined(CONFIG_ARM64) + sp = regs->sp; #endif + addr = sp - sizeof(*regs); + + if (sp && ((addr & PAGE_MASK) != (sp & PAGE_MASK))) { + /* + * will fault when we copy back context, so handle + * it first + */ + E("fault again, sp:%lx, addr:%lx\n", sp, addr); + page = get_vmap_cached_page(&cache); + WARN_ON(!page); + vmap_mmu_set(page, addr, 1); + update_vmap_stack(1); + if ((THREAD_SIZE_ORDER > 1) && stack_floor_page(addr)) { + E("task:%d %s, stack near overflow, addr:%lx\n", + current->pid, current->comm, addr); + show_fault_stack(addr, regs); + } + + /* cache is not enough */ + if (cache <= (VMAP_CACHE_PAGE / 2)) + mod_delayed_work(system_highpri_wq, &avmap->mwork, 0); + + D("map page:%5lx for addr:%lx\n", page_to_pfn(page), addr); + #if DEBUG + show_fault_stack(addr, regs); + #endif + } +} /* * IRQ should *NEVER* been opened in this handler @@ -205,28 +486,54 @@ int handle_vmap_fault(unsigned long addr, unsigned int esr, struct page *page; int cache = 0; - if (!is_vmap_addr(addr)) + if (!is_vmap_addr(addr)) { + check_sp_fault_again(regs); return -EINVAL; + } D("addr:%lx, esr:%x, task:%5d %s\n", addr, esr, current->pid, current->comm); +#ifdef CONFIG_ARM64 D("pc:%pf, %llx, lr:%pf, %llx, sp:%llx, %lx\n", (void *)regs->pc, regs->pc, (void *)regs->regs[30], regs->regs[30], regs->sp, current_stack_pointer); +#elif defined(CONFIG_ARM) + D("pc:%pf, %lx, lr:%pf, %lx, sp:%lx, %lx\n", + (void *)regs->uregs[15], regs->uregs[15], + (void *)regs->uregs[14], regs->uregs[14], regs->uregs[13], + current_stack_pointer); +#endif if (check_addr_up_flow(addr)) { E("address %lx out of range\n", addr); + #ifdef CONFIG_ARM64 E("PC is:%llx, %pf, LR is:%llx %pf\n", regs->pc, (void *)regs->pc, regs->regs[30], (void *)regs->regs[30]); + #elif defined(CONFIG_ARM) + E("PC is:%lx, %pf, LR is:%lx %pf\n", + regs->uregs[15], (void *)regs->uregs[15], + regs->uregs[14], (void *)regs->uregs[14]); + #endif E("task:%d %s, stack:%p, %lx\n", current->pid, current->comm, current->stack, current_stack_pointer); - dump_stack(); + show_fault_stack(addr, regs); + check_sp_fault_again(regs); return -ERANGE; } +#ifdef CONFIG_ARM + page = check_pte_exist(addr); + if (page) { + D("task:%d %s, page:%lx mapped for addr:%lx\n", + current->pid, current->comm, page_to_pfn(page), addr); + check_sp_fault_again(regs); + return -EINVAL; + } +#endif + /* * allocate a new page for vmap */ @@ -234,10 +541,10 @@ int handle_vmap_fault(unsigned long addr, unsigned int esr, WARN_ON(!page); vmap_mmu_set(page, addr, 1); update_vmap_stack(1); - if ((THREAD_SIZE_ORDER > 1) && stack_floor_page(addr)) { + if ((THREAD_SIZE_ORDER > 1) && stack_floor_page(addr)) { E("task:%d %s, stack near overflow, addr:%lx\n", current->pid, current->comm, addr); - dump_stack(); + show_fault_stack(addr, regs); } /* cache is not enough */ @@ -248,7 +555,6 @@ int handle_vmap_fault(unsigned long addr, unsigned int esr, #if DEBUG show_fault_stack(addr, regs); #endif - return 0; } EXPORT_SYMBOL(handle_vmap_fault); @@ -344,6 +650,17 @@ void aml_account_task_stack(struct task_struct *tsk, int account) unsigned long stack = (unsigned long)task_stack_page(tsk); struct page *first_page; + if (unlikely(!is_vmap_addr(stack))) { + /* stack get from kmalloc */ + first_page = virt_to_page((void *)stack); + mod_zone_page_state(page_zone(first_page), NR_KERNEL_STACK_KB, + THREAD_SIZE / 1024 * account); + + memcg_kmem_update_page_stat(first_page, MEMCG_KERNEL_STACK_KB, + account * (THREAD_SIZE / 1024)); + update_vmap_stack(account * (THREAD_SIZE / PAGE_SIZE)); + return; + } stack += STACK_TOP_PAGE_OFF; first_page = vmalloc_to_page((void *)stack); mod_zone_page_state(page_zone(first_page), NR_KERNEL_STACK_KB, @@ -379,13 +696,18 @@ void *aml_stack_alloc(int node, struct task_struct *tsk) avmap->start_bit = bitmap_no + 1; /* next idle address space */ if (bitmap_no >= MAX_TASKS) { spin_unlock_irqrestore(&avmap->vmap_lock, flags); - E("BITMAP FULL!!!\n"); - return NULL; + /* + * if vmap address space is full, we still need to try + * to get stack from kmalloc + */ + addr = (unsigned long)kmalloc(THREAD_SIZE, GFP_KERNEL); + E("BITMAP FULL, kmalloc task stack:%lx\n", addr); + return (void *)addr; } bitmap_set(avmap->bitmap, bitmap_no, 1); spin_unlock_irqrestore(&avmap->vmap_lock, flags); - page = alloc_page(THREADINFO_GFP | __GFP_ZERO); + page = alloc_page(THREADINFO_GFP | __GFP_ZERO | __GFP_HIGHMEM); if (!page) { spin_lock_irqsave(&avmap->vmap_lock, flags); bitmap_clear(avmap->bitmap, bitmap_no, 1); @@ -400,6 +722,7 @@ void *aml_stack_alloc(int node, struct task_struct *tsk) map_addr = addr + STACK_TOP_PAGE_OFF; vmap_mmu_set(page, map_addr, 1); update_vmap_stack(1); + D("bit idx:%5ld, start:%5ld, addr:%lx, page:%lx\n", bitmap_no, raw_start, addr, page_to_pfn(page)); @@ -413,6 +736,12 @@ void aml_stack_free(struct task_struct *tsk) struct page *page; unsigned long flags; + if (unlikely(!is_vmap_addr(stack))) { + /* stack get from kmalloc */ + kfree((void *)stack); + return; + } + addr = stack + STACK_TOP_PAGE_OFF; for (; addr >= stack; addr -= PAGE_SIZE) { page = vmalloc_to_page((const void *)addr); @@ -458,7 +787,7 @@ static void page_cache_maintain_work(struct work_struct *work) INIT_LIST_HEAD(&head); for (i = 0; i < VMAP_CACHE_PAGE - cnt; i++) { - page = alloc_page(GFP_KERNEL | __GFP_HIGH); + page = alloc_page(GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO); if (!page) { E("get page failed, allocated:%d, cnt:%d\n", i, cnt); break; @@ -483,10 +812,9 @@ arch_initcall(start_thread_work); void __init thread_stack_cache_init(void) { int i; - unsigned long addr; struct page *page; - page = alloc_pages(GFP_KERNEL, VMAP_CACHE_PAGE_ORDER); + page = alloc_pages(GFP_KERNEL | __GFP_HIGHMEM, VMAP_CACHE_PAGE_ORDER); if (!page) return; @@ -505,8 +833,8 @@ void __init thread_stack_cache_init(void) pr_info("%s, vmap:%p, bitmap:%p, cache page:%lx\n", __func__, avmap, avmap->bitmap, page_to_pfn(page)); avmap->root_vm = __get_vm_area_node(VM_STACK_AREA_SIZE, - VM_STACK_AREA_SIZE, - 0, VMALLOC_START, VMALLOC_END, + VMAP_ALIGN, + 0, VMAP_ADDR_START, VMAP_ADDR_END, NUMA_NO_NODE, GFP_KERNEL, __builtin_return_address(0)); if (!avmap->root_vm) { @@ -530,7 +858,9 @@ void __init thread_stack_cache_init(void) avmap->cached_pages = VMAP_CACHE_PAGE; INIT_DELAYED_WORK(&avmap->mwork, page_cache_maintain_work); +#ifdef CONFIG_ARM64 for_each_possible_cpu(i) { + unsigned long addr; addr = (unsigned long)per_cpu_ptr(vmap_stack, i); pr_info("cpu %d, vmap_stack:[%lx-%lx]\n", i, addr, addr + THREAD_START_SP); @@ -538,5 +868,6 @@ void __init thread_stack_cache_init(void) pr_info("cpu %d, irq_stack: [%lx-%lx]\n", i, addr, addr + THREAD_START_SP); } +#endif register_shrinker(&vmap_shrinker); } diff --git a/drivers/amlogic/memory_ext/watch_point.c b/drivers/amlogic/memory_ext/watch_point.c new file mode 100644 index 000000000000..35b4a050b613 --- /dev/null +++ b/drivers/amlogic/memory_ext/watch_point.c @@ -0,0 +1,485 @@ +/* + * drivers/amlogic/memory_ext/watch_point.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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct aml_watch_points { + struct perf_event * __percpu *wp_event[MAX_WATCH_POINTS]; + perf_overflow_handler_t handler[MAX_WATCH_POINTS]; + int num_watch_points; + struct work_struct replace_work; + spinlock_t lock; +}; + +struct aml_watch_points *awp; + +static void get_cpu_wb_reg(void *info) +{ + unsigned long *p, r; + + p = (unsigned long *)info; + r = *p; + +#ifdef CONFIG_ARM64 + if (r < AARCH64_DBG_REG_WCR) + *p = read_wb_reg(AARCH64_DBG_REG_WVR, r - AARCH64_DBG_REG_WVR); + else + *p = read_wb_reg(AARCH64_DBG_REG_WCR, r - AARCH64_DBG_REG_WCR); +#else + *p = read_wb_reg(r); +#endif +} + +#ifdef CONFIG_ARM +static struct perf_event **wp_flag(struct perf_event **event, int set) +{ + unsigned long tmp; + + tmp = (unsigned long)event; + + if (set) + tmp |= 0x01; + else + tmp &= ~0x01; + return (struct perf_event **)tmp; +} + +static void wp_del(void *data) +{ + struct perf_event *bp; + + bp = (struct perf_event *)data; + bp->pmu->del(bp, PERF_EF_UPDATE); + pr_info("del for wp:%lx, wp:%p\n", + (unsigned long)bp->attr.bp_addr, bp); +} + +static void wp_add(void *data) +{ + struct perf_event *bp; + + bp = (struct perf_event *)data; + bp->pmu->add(bp, PERF_EF_START); + pr_info("add for wp:%lx, wp:%p\n", + (unsigned long)bp->attr.bp_addr, bp); +} +#endif + +static int dump_watch_point_reg(char *buf) +{ + int i, cpu = 0; + unsigned long addr, wvr, wcr; + int len, type, size = 0; + struct perf_event *bp; + + size += sprintf(buf + size, + "idx, addr, type, len, event, handler\n"); + for (i = 0; i < awp->num_watch_points; i++) { + if (awp->wp_event[i]) { + bp = get_cpu_var(*awp->wp_event[i]); + addr = bp->attr.bp_addr; + len = bp->attr.bp_len; + type = bp->attr.bp_type; + put_cpu_var(*awp->wp_event[i]); + } else { + addr = 0; + len = 0; + type = 0; + } + size += sprintf(buf + size, "%2d, %16lx, %x, %x, %p, %pf\n", + i, addr, type, len, awp->wp_event[i], + awp->handler[i]); + } + for_each_online_cpu(cpu) { + size += sprintf(buf + size, "CPU:%d\n", cpu); + for (i = 0; i < awp->num_watch_points; i++) { + #ifdef CONFIG_ARM64 + wvr = AARCH64_DBG_REG_WVR + i; + #else + wvr = ARM_BASE_WVR + i; + #endif + smp_call_function_single(cpu, get_cpu_wb_reg, &wvr, 1); + + #ifdef CONFIG_ARM64 + wcr = AARCH64_DBG_REG_WCR + i; + #else + wcr = ARM_BASE_WCR + i; + #endif + smp_call_function_single(cpu, get_cpu_wb_reg, &wcr, 1); + size += sprintf(buf + size, " WVR:%16lx WCR:%16lx\n", + wvr, wcr); + } + } + return size; +} + +static void wp_replace_back(struct work_struct *data) +{ + int i, cpu; + struct perf_event *bp; + + for (i = 0; i < awp->num_watch_points; i++) { + if (!awp->wp_event[i]) + continue; + #ifdef CONFIG_ARM64 + get_online_cpus(); + for_each_online_cpu(cpu) { + bp = per_cpu(*awp->wp_event[i], cpu); + if (is_default_overflow_handler(bp)) { + bp->overflow_handler = awp->handler[i]; + pr_info("replace handler for wp:%lx\n", + (unsigned long)bp->attr.bp_addr); + } + } + put_online_cpus(); + #else + if (!(((unsigned long)awp->wp_event[i]) & 0x01)) + continue; + + awp->wp_event[i] = wp_flag(awp->wp_event[i], 0); + get_online_cpus(); + for_each_online_cpu(cpu) { + bp = per_cpu(*awp->wp_event[i], cpu); + smp_call_function_single(cpu, wp_add, bp, 1); + } + put_online_cpus(); + #endif + } +} + +static void aml_default_hbp_handler(struct perf_event *bp, + struct perf_sample_data *data, + struct pt_regs *regs) +{ +#ifdef CONFIG_ARM64 + pr_info("watch addr %llx triggerd, pc:%pf, lr:%pf\n", + bp->attr.bp_addr, (void *)regs->pc, + (void *)regs->compat_lr_fiq); + bp->overflow_handler = perf_event_output_forward; + show_regs(regs); + dump_stack(); +#else + struct perf_event * __percpu *event = NULL; + int i, cpu; + + pr_info("watch addr %llx triggerd, pc:%pf, lr:%pf\n", + bp->attr.bp_addr, (void *)regs->ARM_pc, + (void *)regs->ARM_lr); + + for (i = 0; i < awp->num_watch_points; i++) { + if (!awp->wp_event[i]) + continue; + for_each_online_cpu(cpu) { + if (bp == per_cpu(*awp->wp_event[i], cpu)) { + event = awp->wp_event[i]; + break; + } + } + if (event) { + for_each_online_cpu(cpu) { + bp = per_cpu(*event, cpu); + smp_call_function_single(cpu, wp_del, bp, 1); + } + break; + } + } + if (event) + awp->wp_event[i] = wp_flag(awp->wp_event[i], 1); + show_regs(regs); +#endif + schedule_work_on(smp_processor_id(), &awp->replace_work); +} + +/* register a watch pointer */ +int aml_watch_point_register(unsigned long addr, + unsigned int len, + unsigned int type, + perf_overflow_handler_t handle) +{ + int i; + struct perf_event_attr attr; + struct perf_event * __percpu *event; + + if (!awp) + return -ENOMEM; + + /* parameter check */ + if ((len > HW_BREAKPOINT_LEN_8) || (len < HW_BREAKPOINT_LEN_1)) { + pr_err("bad input len:%d\n", len); + return -EINVAL; + } + if (type & ~(HW_BREAKPOINT_W | HW_BREAKPOINT_R)) { + pr_err("bad input type:%d\n", type); + return -EINVAL; + } + + /* check if all watch points are used */ + spin_lock(&awp->lock); + for (i = 0; i < awp->num_watch_points; i++) { + if (!awp->wp_event[i]) { + awp->wp_event[i]++; + break; + } + } + if (i == awp->num_watch_points) { + spin_unlock(&awp->lock); + pr_err("%s, watch point is all used\n", __func__); + return -ENODEV; + } + spin_unlock(&awp->lock); + + hw_breakpoint_init(&attr); + attr.bp_addr = addr; + attr.bp_len = len; + attr.bp_type = type; + if (!handle) + handle = aml_default_hbp_handler; + + event = register_wide_hw_breakpoint(&attr, handle, NULL); + spin_lock(&awp->lock); + if (IS_ERR_OR_NULL(event)) { + awp->wp_event[i] = NULL; + awp->handler[i] = NULL; + } else { + awp->wp_event[i] = event; + awp->handler[i] = handle; + } + spin_unlock(&awp->lock); + + pr_info("watch point[%d], addr:%lx, len:%d, type:%x, event:%p\n", + i, addr, len, type, awp->wp_event[i]); + return awp->wp_event[i] ? 0 : -EINVAL; +} +EXPORT_SYMBOL(aml_watch_point_register); + +/* remove watch point according given address */ +void aml_watch_point_remove(unsigned long addr) +{ + int i; + struct perf_event *bp; + struct perf_event * __percpu *event = NULL; + + if (!awp) + return; + + spin_lock(&awp->lock); + for (i = 0; i < awp->num_watch_points; i++) { + if (awp->wp_event[i]) { + bp = get_cpu_var(*awp->wp_event[i]); + if (bp->attr.bp_addr == addr) { + event = awp->wp_event[i]; + awp->wp_event[i] = NULL; + awp->handler[i] = NULL; + put_cpu_var(*awp->wp_event[i]); + break; + } + put_cpu_var(*awp->wp_event[i]); + } + } + spin_unlock(&awp->lock); + if (event) + unregister_wide_hw_breakpoint(event); +} +EXPORT_SYMBOL(aml_watch_point_remove); + +/* + * force clear a watch point + */ +static void aml_watch_point_clear(int idx) +{ + struct perf_event * __percpu *event = NULL; + + if (idx >= awp->num_watch_points) + return; + + spin_lock(&awp->lock); + if (awp->wp_event[idx]) { + event = awp->wp_event[idx]; + awp->wp_event[idx] = NULL; + awp->handler[idx] = NULL; + } + spin_unlock(&awp->lock); + if (event) + unregister_wide_hw_breakpoint(event); +} + +static ssize_t num_watch_points_show(struct class *cla, + struct class_attribute *attr, char *buf) +{ + return sprintf(buf, "%d\n", awp->num_watch_points); +} + +static ssize_t watch_addr_store(struct class *cla, + struct class_attribute *attr, const char *buf, size_t count) +{ + unsigned long addr; + u32 len = HW_BREAKPOINT_LEN_8; + u32 type = HW_BREAKPOINT_W; + int ret; + + ret = sscanf(buf, "%lx %x %x", &addr, &len, &type); + if (ret < 1) + return -EINVAL; + + ret = aml_watch_point_register(addr, len, type, NULL); + + return count; +} + +static ssize_t clear_store(struct class *cla, + struct class_attribute *attr, const char *buf, size_t count) +{ + int i; + int idx = -1; + + if (kstrtoint(buf, 10, &idx)) + return count; + + if (idx >= awp->num_watch_points) { + pr_err("input index %d out of range:[0 - %d]\n", + idx, awp->num_watch_points); + return -EINVAL; + } + + /* negative value means clear all watch point */ + if (idx < 0) { + for (i = 0; i < awp->num_watch_points; i++) + aml_watch_point_clear(i); + } else { + aml_watch_point_clear(idx); + } + + return count; +} + +static ssize_t dump_show(struct class *cla, + struct class_attribute *attr, char *buf) +{ + return dump_watch_point_reg(buf); +} + +static struct class_attribute watch_point_attr[] = { + __ATTR(watch_addr, 0664, dump_show, watch_addr_store), + __ATTR_RO(num_watch_points), + __ATTR_WO(clear), + __ATTR_NULL +}; + +static struct class watch_point_class = { + .name = "watch_point", + .class_attrs = watch_point_attr, +}; + +/* + * aml_watch_point_probe only executes before the init process starts + * to run, so add __ref to indicate it is okay to call __init function + * hook_debug_fault_code + */ +static int __init aml_watch_point_probe(struct platform_device *pdev) +{ + int r; + + r = hw_breakpoint_slots(TYPE_DATA); + pr_info("%s, in, wp:%d\n", __func__, r); + if (!r) + return -ENODEV; + + awp = devm_kzalloc(&pdev->dev, sizeof(*awp), GFP_KERNEL); + if (awp == NULL) + return -ENOMEM; + + awp->num_watch_points = r; + r = class_register(&watch_point_class); + if (r) { + pr_err("regist watch_point_class failed\n"); + return -EINVAL; + } + INIT_WORK(&awp->replace_work, wp_replace_back); + + return 0; +} + +static int aml_watch_point_drv_remove(struct platform_device *pdev) +{ + class_unregister(&watch_point_class); + return 0; +} + +static struct platform_driver aml_watch_point_driver = { + .driver = { + .name = "aml_watch_point", + .owner = THIS_MODULE, + }, + .probe = aml_watch_point_probe, + .remove = aml_watch_point_drv_remove, +}; + +static int __init aml_watch_pint_init(void) +{ + struct platform_device *pdev; + int ret; + + pdev = platform_device_alloc("aml_watch_point", 0); + if (!pdev) { + pr_err("alloc pdev aml_watch_point failed\n"); + return -EINVAL; + } + ret = platform_device_add(pdev); + if (ret) { + pr_err("regist pdev failed, ret:%d\n", ret); + platform_device_del(pdev); + return ret; + } + ret = platform_driver_probe(&aml_watch_point_driver, + aml_watch_point_probe); + if (ret) + platform_device_del(pdev); + return ret; +} + +static void __exit aml_watch_point_uninit(void) +{ + platform_driver_unregister(&aml_watch_point_driver); +} + +arch_initcall(aml_watch_pint_init); +module_exit(aml_watch_point_uninit); +MODULE_DESCRIPTION("amlogic watch point driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/amlogic/mmc/aml_sd_emmc.c b/drivers/amlogic/mmc/aml_sd_emmc.c index 71a5a47a80e1..17f86e8edef2 100644 --- a/drivers/amlogic/mmc/aml_sd_emmc.c +++ b/drivers/amlogic/mmc/aml_sd_emmc.c @@ -379,6 +379,8 @@ static int aml_cali_find(struct mmc_host *mmc, struct cali_data *c_data) if (host->data->chip_type == MMC_CHIP_GXBB) delay_step = 125; + else if (host->data->chip_type == MMC_CHIP_GXM) + delay_step = 250; else delay_step = 200; if (mmc->ios.bus_width == 0) @@ -1064,7 +1066,7 @@ static int aml_mmc_execute_tuning(struct mmc_host *mmc, u32 opcode) } -static void aml_mmc_clk_switch_off(struct amlsd_platform *pdata) +void aml_mmc_clk_switch_off(struct amlsd_platform *pdata) { u32 vcfg = 0; struct sd_emmc_config *conf = (struct sd_emmc_config *)&vcfg; @@ -1915,6 +1917,7 @@ static void aml_sd_emmc_enable_sdio_irq(struct mmc_host *mmc, int enable) } pdata->irq_sdio_sleep = 1; } + pdata->irq_sdio_sleep = 1; spin_unlock_irqrestore(&host->mrq_lock, flags); @@ -2616,7 +2619,7 @@ static irqreturn_t meson_mmc_irq(int irq, void *dev_id) mmc_hostname(host->mmc), vstat, virqc); host->status = HOST_RSP_CRC_ERR; - mrq->cmd->error = -EILSEQ; + mrq->cmd->error = -EBADMSG; } else if (ista->resp_timeout) { if (host->is_tunning == 0) pr_err("%s: resp_timeout,vstat:0x%x,virqc:%x\n", @@ -3325,6 +3328,16 @@ static int meson_mmc_probe(struct platform_device *pdev) #endif /* CONFIG_MESON_CPU_EMULATOR */ } pr_info("%s() : success!\n", __func__); + if (host->ctrl_ver >= 3) { + ret = device_create_file(&pdev->dev, &dev_attr_emmc_eyetest); + if (ret) + dev_warn(mmc_dev(host->mmc), + "Unable to creat sysfs attributes\n"); + ret = device_create_file(&pdev->dev, &dev_attr_emmc_clktest); + if (ret) + dev_warn(mmc_dev(host->mmc), + "Unable to creat sysfs attributes\n"); + } return 0; free_host: @@ -3403,6 +3416,12 @@ static void meson_mmc_shutdown(struct platform_device *pdev) } } } + +static int meson_mmc_suspend(struct platform_device *pdev, pm_message_t state) +{ + meson_mmc_shutdown(pdev); + return 0; +} #endif static struct meson_mmc_data mmc_data_gxbb = { @@ -3569,8 +3588,8 @@ static struct meson_mmc_data mmc_data_g12a = { .sdmmc.sdr104.tx_phase = 0, }; -static struct meson_mmc_data mmc_data_g12b = { - .chip_type = MMC_CHIP_G12B, +static struct meson_mmc_data mmc_data_g12b_a = { + .chip_type = MMC_CHIP_G12B_A, .port_a_base = 0xffe03000, .port_b_base = 0xffe05000, .port_c_base = 0xffe07000, @@ -3587,9 +3606,36 @@ static struct meson_mmc_data mmc_data_g12b = { .sdmmc.hs.core_phase = 1, .sdmmc.ddr.core_phase = 2, .sdmmc.ddr.tx_phase = 0, - .sdmmc.hs2.core_phase = 3, + .sdmmc.hs2.core_phase = 2, .sdmmc.hs2.tx_phase = 0, - .sdmmc.hs4.tx_delay = 0, + .sdmmc.sd_hs.core_phase = 2, + .sdmmc.sdr104.core_phase = 2, + .sdmmc.sdr104.tx_phase = 0, +}; + +static struct meson_mmc_data mmc_data_g12b = { + .chip_type = MMC_CHIP_G12B, + .port_a_base = 0xffe03000, + .port_b_base = 0xffe05000, + .port_c_base = 0xffe07000, + .pinmux_base = 0xff634400, + .clksrc_base = 0xff63c000, + .ds_pin_poll = 0x3a, + .ds_pin_poll_en = 0x48, + .ds_pin_poll_bit = 13, + .sdmmc.init.core_phase = 2, + .sdmmc.init.tx_phase = 0, + .sdmmc.init.rx_phase = 0, + .sdmmc.calc.core_phase = 0, + .sdmmc.calc.tx_phase = 2, + .sdmmc.hs.core_phase = 1, + .sdmmc.ddr.core_phase = 2, + .sdmmc.ddr.tx_phase = 0, + .sdmmc.hs2.core_phase = 2, + .sdmmc.hs2.tx_phase = 0, + .sdmmc.hs4.tx_phase = 0, + .sdmmc.hs4.core_phase = 0, + .sdmmc.hs4.tx_delay = 16, .sdmmc.sd_hs.core_phase = 2, .sdmmc.sdr104.core_phase = 2, .sdmmc.sdr104.tx_phase = 0, @@ -3608,10 +3654,59 @@ static struct meson_mmc_data mmc_data_tl1 = { .sdmmc.init.core_phase = 3, .sdmmc.init.tx_phase = 0, .sdmmc.init.rx_phase = 0, - .sdmmc.hs.core_phase = 1, + .sdmmc.hs.core_phase = 3, .sdmmc.ddr.core_phase = 2, - .sdmmc.hs2.core_phase = 3, + .sdmmc.hs2.core_phase = 2, + .sdmmc.hs4.core_phase = 0, + .sdmmc.hs4.tx_delay = 16, + .sdmmc.sd_hs.core_phase = 2, + .sdmmc.sdr104.core_phase = 2, +}; + +static struct meson_mmc_data mmc_data_sm1 = { + .chip_type = MMC_CHIP_SM1, + .port_a_base = 0xffe03000, + .port_b_base = 0xffe05000, + .port_c_base = 0xffe07000, + .pinmux_base = 0xff634400, + .clksrc_base = 0xff63c000, + .ds_pin_poll = 0x3a, + .ds_pin_poll_en = 0x48, + .ds_pin_poll_bit = 13, + .sdmmc.init.core_phase = 3, + .sdmmc.init.tx_phase = 0, + .sdmmc.init.rx_phase = 0, + .sdmmc.calc.core_phase = 0, + .sdmmc.calc.tx_phase = 2, + .sdmmc.hs.core_phase = 3, + .sdmmc.ddr.core_phase = 2, + .sdmmc.ddr.tx_phase = 0, + .sdmmc.hs2.core_phase = 2, + .sdmmc.hs2.tx_phase = 0, .sdmmc.hs4.tx_delay = 0, + .sdmmc.sd_hs.core_phase = 3, + .sdmmc.sdr104.core_phase = 2, + .sdmmc.sdr104.tx_phase = 0, +}; + +static struct meson_mmc_data mmc_data_tm2 = { + .chip_type = MMC_CHIP_TM2, + .port_a_base = 0xffe03000, + .port_b_base = 0xffe05000, + .port_c_base = 0xffe07000, + .pinmux_base = 0xff634400, + .clksrc_base = 0xff63c000, + .ds_pin_poll = 0x3a, + .ds_pin_poll_en = 0x48, + .ds_pin_poll_bit = 13, + .sdmmc.init.core_phase = 3, + .sdmmc.init.tx_phase = 0, + .sdmmc.init.rx_phase = 0, + .sdmmc.hs.core_phase = 3, + .sdmmc.ddr.core_phase = 2, + .sdmmc.hs2.core_phase = 2, + .sdmmc.hs4.core_phase = 0, + .sdmmc.hs4.tx_delay = 16, .sdmmc.sd_hs.core_phase = 2, .sdmmc.sdr104.core_phase = 2, }; @@ -3665,6 +3760,18 @@ static const struct of_device_id meson_mmc_of_match[] = { .compatible = "amlogic, meson-mmc-tl1", .data = &mmc_data_tl1, }, + { + .compatible = "amlogic, meson-mmc-g12b-a", + .data = &mmc_data_g12b_a, + }, + { + .compatible = "amlogic, meson-mmc-sm1", + .data = &mmc_data_sm1, + }, + { + .compatible = "amlogic, meson-mmc-tm2", + .data = &mmc_data_tm2, + }, {} }; @@ -3675,6 +3782,7 @@ static struct platform_driver meson_mmc_driver = { .remove = meson_mmc_remove, #if defined(CONFIG_ARCH_MESON64_ODROID_COMMON) .shutdown = meson_mmc_shutdown, + .suspend = meson_mmc_suspend, #endif .driver = { .name = "meson-aml-mmc", diff --git a/drivers/amlogic/mmc/aml_sd_emmc_v3.c b/drivers/amlogic/mmc/aml_sd_emmc_v3.c index a5e4b2a5dfee..f3e7e26c11b8 100644 --- a/drivers/amlogic/mmc/aml_sd_emmc_v3.c +++ b/drivers/amlogic/mmc/aml_sd_emmc_v3.c @@ -174,7 +174,7 @@ static int meson_mmc_clk_set_rate_v3(struct mmc_host *mmc, #ifdef SD_EMMC_CLK_CTRL if (clk_ios == 0) { - aml_mmc_clk_switch_off(host); + aml_mmc_clk_switch_off(pdata); return ret; } @@ -232,9 +232,33 @@ static int meson_mmc_clk_set_rate_v3(struct mmc_host *mmc, if (aml_card_type_mmc(pdata)) { if ((clk_ios >= 200000000) && conf->ddr) { src0_clk = devm_clk_get(host->dev, "clkin2"); + if (ret) + pr_warn("not get clkin2\n"); ret = clk_set_parent(host->mux_parent[0], src0_clk); if (ret) - pr_warn("set src0: div5 as comp0 parent error\n"); + pr_warn("set src0 as comp0 parent error\n"); + ret = clk_set_parent(host->mux_clk, + host->mux_parent[0]); + if (ret) + pr_warn("set comp0 as mux_clk parent error\n"); + } else if (((host->data->chip_type >= MMC_CHIP_TL1) + || (host->data->chip_type == MMC_CHIP_G12B)) + && (clk_ios >= 166000000)) { + src0_clk = devm_clk_get(host->dev, "clkin2"); + if (ret) + pr_warn("not get clkin2\n"); + if ((host->data->chip_type == MMC_CHIP_TL1) + && (clk_ios <= 198000000)) { + ret = clk_set_rate(src0_clk, 792000000); + if (ret) + pr_warn("not set tl1-gp0\n"); + } + pr_warn("set rate clkin2>>>>>>>>clk:%lu\n", + clk_get_rate(src0_clk)); + ret = clk_set_parent(host->mux_parent[0], + src0_clk); + if (ret) + pr_warn("set src0 as comp0 parent error\n"); ret = clk_set_parent(host->mux_clk, host->mux_parent[0]); if (ret) @@ -260,10 +284,12 @@ static int meson_mmc_clk_set_rate_v3(struct mmc_host *mmc, /* (re)start clock, if non-zero */ if (clk_ios) { + if (pdata->calc_f) { vclkc = readl(host->base + SD_EMMC_CLOCK_V3); pdata->clk_lay.source = clk_get_rate(host->cfg_div_clk) * clkc->div; pdata->clk_lay.core = clk_get_rate(host->cfg_div_clk); + } vcfg = readl(host->base + SD_EMMC_CFG); conf->stop_clk = 0; @@ -272,11 +298,11 @@ static int meson_mmc_clk_set_rate_v3(struct mmc_host *mmc, pdata->stop_clk = 0; } #endif - pr_debug("actual_clock :%u, HHI_nand: 0x%x\n", + pr_info("actual_clock :%u, HHI_nand: 0x%x\n", mmc->actual_clock, readl(host->clksrc_base + (HHI_NAND_CLK_CNTL << 2))); - pr_debug("[%s] after clock: 0x%x\n", + pr_info("[%s] after clock: 0x%x\n", __func__, readl(host->base + SD_EMMC_CLOCK_V3)); return ret; @@ -295,11 +321,21 @@ static void aml_sd_emmc_set_timing_v3(struct amlsd_platform *pdata, u8 clk_div = 0; struct para_e *para = &(host->data->sdmmc); unsigned int fixdiv = 0, ret = 0; + u32 irq_en = readl(host->base + SD_EMMC_IRQ_EN); vctrl = readl(host->base + SD_EMMC_CFG); if ((timing == MMC_TIMING_MMC_HS400) || (timing == MMC_TIMING_MMC_DDR52) || (timing == MMC_TIMING_UHS_DDR50)) { + + if (timing == MMC_TIMING_MMC_DDR52) { + if (aml_card_type_mmc(pdata)) { + clkc->core_phase = para->ddr.core_phase; + clkc->tx_phase = para->ddr.tx_phase; + } + pr_info("%s: try set sd/emmc to DDR mode\n", + mmc_hostname(host->mmc)); + } if (timing == MMC_TIMING_MMC_HS400) { /*ctrl->chk_ds = 1;*/ if (host->data->chip_type >= MMC_CHIP_TXLX) { @@ -313,6 +349,18 @@ static void aml_sd_emmc_set_timing_v3(struct amlsd_platform *pdata, */ if (pdata->tx_delay != 0) clkc->tx_delay = pdata->tx_delay; + + if (((host->data->chip_type == MMC_CHIP_TL1) + || (host->data->chip_type == MMC_CHIP_G12B)) + && aml_card_type_mmc(pdata)) { + clkc->core_phase = para->hs4.core_phase; + clkc->tx_phase = para->hs4.tx_phase; + + irq_en |= (1<<17); + writel(irq_en, + host->base + SD_EMMC_IRQ_EN); + /*improve CMD setup time by half SD_CLK cycle*/ + } } pr_info("%s: try set sd/emmc to HS400 mode\n", mmc_hostname(host->mmc)); @@ -322,12 +370,6 @@ static void aml_sd_emmc_set_timing_v3(struct amlsd_platform *pdata, if (clk_div & 0x01) clk_div++; clkc->div = clk_div / 2; - if (aml_card_type_mmc(pdata)) { - clkc->core_phase = para->ddr.core_phase; - clkc->tx_phase = para->ddr.tx_phase; - } - pr_info("%s: try set sd/emmc to DDR mode\n", - mmc_hostname(host->mmc)); } else if (timing == MMC_TIMING_MMC_HS) { clkc->core_phase = para->hs.core_phase; /* overide co-phase by dts */ @@ -341,7 +383,9 @@ static void aml_sd_emmc_set_timing_v3(struct amlsd_platform *pdata, clkc->core_phase = para->hs2.core_phase; clkc->tx_phase = para->hs2.tx_phase; } else if (timing == MMC_TIMING_SD_HS) { - if (aml_card_type_non_sdio(pdata)) + if (aml_card_type_non_sdio(pdata) + || (host->data->chip_type == MMC_CHIP_TXLX) + || (host->data->chip_type == MMC_CHIP_G12A)) clkc->core_phase = para->sd_hs.core_phase; if (pdata->calc_f) { clkc->core_phase = para->calc.core_phase; @@ -352,6 +396,11 @@ static void aml_sd_emmc_set_timing_v3(struct amlsd_platform *pdata, clkc->tx_phase = para->sdr104.tx_phase; } else { ctrl->ddr = 0; + clkc->tx_delay = 0; + clkc->core_phase = para->init.core_phase; + clkc->tx_phase = para->init.tx_phase; + irq_en &= ~(1<<17); + writel(irq_en, host->base + SD_EMMC_IRQ_EN); /* timing == MMC_TIMING_LEGACY */ if (pdata->calc_f) { clkc->core_phase = para->calc.core_phase; @@ -608,7 +657,7 @@ irqreturn_t meson_mmc_irq_thread_v3(int irq, void *dev_id) } static int aml_sd_emmc_cali_v3(struct mmc_host *mmc, - u8 opcode, u8 *blk_test, u32 blksz, u32 blocks) + u8 opcode, u8 *blk_test, u32 blksz, u32 blocks, u8 *pattern) { struct amlsd_platform *pdata = mmc_priv(mmc); struct amlsd_host *host = pdata->host; @@ -619,7 +668,14 @@ static int aml_sd_emmc_cali_v3(struct mmc_host *mmc, struct scatterlist sg; cmd.opcode = opcode; - cmd.arg = ((SZ_1M * (36 + 3)) / 512); + if (!strcmp(pattern, MMC_PATTERN_NAME)) + cmd.arg = MMC_PATTERN_OFFSET; + else if (!strcmp(pattern, MMC_MAGIC_NAME)) + cmd.arg = MMC_MAGIC_OFFSET; + else if (!strcmp(pattern, MMC_RANDOM_NAME)) + cmd.arg = MMC_RANDOM_OFFSET; + else if (!strcmp(pattern, MMC_DTB_NAME)) + cmd.arg = MMC_DTB_OFFSET; cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC; stop.opcode = MMC_STOP_TRANSMISSION; @@ -643,6 +699,28 @@ static int aml_sd_emmc_cali_v3(struct mmc_host *mmc, return data.error | cmd.error; } +static int emmc_test_bus(struct mmc_host *mmc) +{ + int err = 0; + u32 blksz = 512; + struct amlsd_platform *pdata = mmc_priv(mmc); + struct amlsd_host *host = pdata->host; + + err = aml_sd_emmc_cali_v3(mmc, MMC_READ_MULTIPLE_BLOCK, + host->blk_test, blksz, 40, MMC_PATTERN_NAME); + if (err) + return err; + err = aml_sd_emmc_cali_v3(mmc, MMC_READ_MULTIPLE_BLOCK, + host->blk_test, blksz, 80, MMC_RANDOM_NAME); + if (err) + return err; + err = aml_sd_emmc_cali_v3(mmc, MMC_READ_MULTIPLE_BLOCK, + host->blk_test, blksz, 40, MMC_MAGIC_NAME); + if (err) + return err; + return err; +} + static int emmc_send_cmd(struct mmc_host *mmc, u32 opcode, u32 arg, unsigned int flags) { @@ -655,7 +733,7 @@ static int emmc_send_cmd(struct mmc_host *mmc, u32 opcode, err = mmc_wait_for_cmd(mmc, &cmd, 3); if (err) { - pr_info("[%s][%d] cmd:0x%x send error\n", + pr_debug("[%s][%d] cmd:0x%x send error\n", __func__, __LINE__, cmd.opcode); return err; } @@ -717,7 +795,7 @@ RETRY: if (line_x < 9) aml_sd_emmc_cali_v3(mmc, MMC_READ_MULTIPLE_BLOCK, - host->blk_test, blksz, 40); + host->blk_test, blksz, 40, MMC_PATTERN_NAME); else aml_sd_emmc_cmd_v3(mmc); host->is_tunning = 0; @@ -725,7 +803,7 @@ RETRY: eyetest_log = readl(host->base + SD_EMMC_EYETEST_LOG); if (!(geyetest_log->eyetest_done & 0x1)) { - pr_debug("testing eyetest times:0x%x,out:0x%x,0x%x,line:%d\n", + pr_warn("testing eyetest times:0x%x,out:0x%x,0x%x,line:%d\n", readl(host->base + SD_EMMC_EYETEST_LOG), eyetest_out0, eyetest_out1, line_x); gintf3->eyetest_on = 0; @@ -743,6 +821,7 @@ RETRY: eyetest_out1 = readl(host->base + SD_EMMC_EYETEST_OUT1); gintf3->eyetest_on = 0; writel(intf3, host->base + SD_EMMC_INTF3); + writel(0, host->base + SD_EMMC_ADJUST_V3); pdata->intf3 = intf3; pdata->align[line_x] = ((tmp | eyetest_out1) << 32) | eyetest_out0; pr_debug("d1:0x%x,d2:0x%x,u64eyet:0x%016llx,l_x:%d\n", @@ -870,6 +949,25 @@ static void update_all_line_eyetest(struct mmc_host *mmc) } } +static unsigned int tl1_emmc_line_timing(struct mmc_host *mmc) +{ + struct amlsd_platform *pdata = mmc_priv(mmc); + struct amlsd_host *host = pdata->host; + u32 delay1 = 0, delay2 = 0, count = 12; + + delay1 = (count<<0)|(count<<6)|(count<<12) + |(count<<18)|(count<<24); + delay2 = (count<<0)|(count<<6)|(count<<12) + |(pdata->cmd_c<<24); + writel(delay1, host->base + SD_EMMC_DELAY1_V3); + writel(delay2, host->base + SD_EMMC_DELAY2_V3); + pr_info("[%s], delay1: 0x%x, delay2: 0x%x\n", + __func__, readl(host->base + SD_EMMC_DELAY1_V3), + readl(host->base + SD_EMMC_DELAY2_V3)); + return 0; + +} + static unsigned int get_emmc_cmd_win(struct mmc_host *mmc) { struct amlsd_platform *pdata = mmc_priv(mmc); @@ -987,36 +1085,25 @@ static int emmc_ds_manual_sht(struct mmc_host *mmc) struct amlsd_host *host = pdata->host; u32 intf3 = readl(host->base + SD_EMMC_INTF3); struct intf3 *gintf3 = (struct intf3 *)&(intf3); - u32 blksz = 512; int i, err = 0; - int match[32]; + int match[64]; int best_start = -1, best_size = -1; int cur_start = -1, cur_size = 0; - sd_emmc_debug = 0x2000; - update_all_line_eyetest(mmc); - emmc_ds_core_align(mmc); - update_all_line_eyetest(mmc); - emmc_all_data_line_alignment(mmc); - update_all_line_eyetest(mmc); - emmc_ds_data_alignment(mmc); - update_all_line_eyetest(mmc); host->is_tunning = 1; - for (i = 0; i < 32; i++) { - gintf3->ds_sht_m += 1; - writel(intf3, host->base + SD_EMMC_INTF3); - pdata->intf3 = intf3; - err = aml_sd_emmc_cali_v3(mmc, - MMC_READ_MULTIPLE_BLOCK, - host->blk_test, blksz, 20); + for (i = 0; i < 64; i++) { + err = emmc_test_bus(mmc); pr_debug("intf3: 0x%x, err[%d]: %d\n", readl(host->base + SD_EMMC_INTF3), i, err); if (!err) match[i] = 0; else match[i] = -1; + gintf3->ds_sht_m += 1; + writel(intf3, host->base + SD_EMMC_INTF3); + pdata->intf3 = intf3; } - for (i = 0; i < 32; i++) { + for (i = 0; i < 64; i++) { if (match[i] == 0) { if (cur_start < 0) cur_start = i; @@ -1052,16 +1139,129 @@ static int emmc_ds_manual_sht(struct mmc_host *mmc) gintf3->ds_sht_m = best_start + best_size / 2; writel(intf3, host->base + SD_EMMC_INTF3); pdata->intf3 = intf3; + pdata->win_start = best_start; pr_info("ds_sht:%u, window:%d, intf3:0x%x, clock:0x%x", gintf3->ds_sht_m, best_size, readl(host->base + SD_EMMC_INTF3), readl(host->base + SD_EMMC_CLOCK_V3)); + pr_info("adjust:0x%x\n", readl(host->base + SD_EMMC_ADJUST_V3)); host->is_tunning = 0; return 0; } #endif +static void aml_emmc_hs400_general(struct mmc_host *mmc) +{ + update_all_line_eyetest(mmc); + emmc_ds_core_align(mmc); + update_all_line_eyetest(mmc); + emmc_all_data_line_alignment(mmc); + update_all_line_eyetest(mmc); + emmc_ds_data_alignment(mmc); + update_all_line_eyetest(mmc); + emmc_ds_manual_sht(mmc); +} + +static void aml_emmc_hs400_tl1(struct mmc_host *mmc) +{ + + tl1_emmc_line_timing(mmc); + emmc_ds_manual_sht(mmc); +} + +static int emmc_data_alignment(struct mmc_host *mmc, int best_size) +{ + struct amlsd_platform *pdata = mmc_priv(mmc); + struct amlsd_host *host = pdata->host; + u32 delay1 = readl(host->base + SD_EMMC_DELAY1_V3); + u32 delay2 = readl(host->base + SD_EMMC_DELAY2_V3); + u32 intf3 = readl(host->base + SD_EMMC_INTF3); + struct intf3 *gintf3 = (struct intf3 *)&(intf3); + u32 delay1_bak = delay1; + u32 delay2_bak = delay2; + u32 intf3_bak = intf3; + int line_x, i, err = 0, win_new, blksz = 512; + u32 d[8]; + + host->is_tunning = 1; + gintf3->ds_sht_m = pdata->win_start + 4; + writel(intf3, host->base + SD_EMMC_INTF3); + for (line_x = 0; line_x < 8; line_x++) { + for (i = 0; i < 20; i++) { + if (line_x < 5) { + delay1 += (1 << 6*line_x); + writel(delay1, host->base + SD_EMMC_DELAY1_V3); + } else { + delay2 += (1 << 6*(line_x - 5)); + writel(delay2, host->base + SD_EMMC_DELAY2_V3); + } + err = aml_sd_emmc_cali_v3(mmc, MMC_READ_MULTIPLE_BLOCK, + host->blk_test, blksz, 40, MMC_RANDOM_NAME); + if (err) { + pr_info("[%s]adjust line_x[%d]:%d\n", + __func__, line_x, i); + d[line_x] = i; + delay1 = delay1_bak; + delay2 = delay2_bak; + writel(delay1_bak, + host->base + SD_EMMC_DELAY1_V3); + writel(delay2_bak, + host->base + SD_EMMC_DELAY2_V3); + break; + } + } + if (i == 20) { + pr_info("[%s][%d] return set default value", + __func__, __LINE__); + writel(delay1_bak, host->base + SD_EMMC_DELAY1_V3); + writel(delay2_bak, host->base + SD_EMMC_DELAY2_V3); + writel(intf3_bak, host->base + SD_EMMC_INTF3); + host->is_tunning = 0; + return -1; + } + } + delay1 += (d[0]<<0)|(d[1]<<6)|(d[2]<<12)|(d[3]<<18)|(d[4]<<24); + delay2 += (d[5]<<0)|(d[6]<<6)|(d[7]<<12); + writel(delay1, host->base + SD_EMMC_DELAY1_V3); + writel(delay2, host->base + SD_EMMC_DELAY2_V3); + pr_info("delay1:0x%x, delay2:0x%x\n", + readl(host->base + SD_EMMC_DELAY1_V3), + readl(host->base + SD_EMMC_DELAY2_V3)); + gintf3->ds_sht_m = 0; + writel(intf3, host->base + SD_EMMC_INTF3); + win_new = emmc_ds_manual_sht(mmc); + if (win_new < best_size) { + pr_info("[%s][%d] win_new:%d < win_old:%d,set default!", + __func__, __LINE__, win_new, best_size); + writel(delay1_bak, host->base + SD_EMMC_DELAY1_V3); + writel(delay2_bak, host->base + SD_EMMC_DELAY2_V3); + writel(intf3_bak, host->base + SD_EMMC_INTF3); + pr_info("intf3:0x%x, delay1:0x%x, delay2:0x%x\n", + readl(host->base + SD_EMMC_INTF3), + readl(host->base + SD_EMMC_DELAY1_V3), + readl(host->base + SD_EMMC_DELAY2_V3)); + } + host->is_tunning = 0; + return 0; +} + +static void aml_emmc_hs400_Revb(struct mmc_host *mmc) +{ + struct amlsd_platform *pdata = mmc_priv(mmc); + struct amlsd_host *host = pdata->host; + u32 delay2 = 0; + int win_size = 0; + + delay2 = readl(host->base + SD_EMMC_DELAY2_V3); + delay2 += (pdata->cmd_c<<24); + writel(delay2, host->base + SD_EMMC_DELAY2_V3); + pr_info("[%s], delay1: 0x%x, delay2: 0x%x\n", + __func__, readl(host->base + SD_EMMC_DELAY1_V3), + readl(host->base + SD_EMMC_DELAY2_V3)); + win_size = emmc_ds_manual_sht(mmc); + emmc_data_alignment(mmc, win_size); +} /* test clock, return delay cells for one cycle */ static unsigned int aml_sd_emmc_clktest(struct mmc_host *mmc) @@ -1149,6 +1349,7 @@ static int _aml_sd_emmc_execute_tuning(struct mmc_host *mmc, u32 opcode, int best_win_start, best_win_size; int curr_win_start, curr_win_size; u32 old_dly, d1_dly, dly; + struct para_e *para = &(host->data->sdmmc); if ((host->mem->start == host->data->port_b_base) && host->data->tdma_f) @@ -1177,6 +1378,28 @@ tunning: host->is_tunning = 1; pr_info("%s: clk %d tuning start\n", mmc_hostname(mmc), mmc->actual_clock); + + /*retry adj[clk_div-1] tuning result*/ + if ((clk_div == 5) && (aml_card_type_mmc(pdata))) { + gadjust->adj_delay = clk_div-1; + gadjust->adj_enable = 1; + gadjust->cali_enable = 0; + gadjust->cali_rise = 0; + writel(adjust, host->base + SD_EMMC_ADJUST_V3); + nmatch = aml_sd_emmc_tuning_transfer(mmc, opcode, + blk_pattern, host->blk_test, blksz); + if (nmatch != TUNING_NUM_PER_POINT) { + if (host->data->chip_type != MMC_CHIP_SM1) { + clkc->core_phase = para->hs2.tx_phase; + clkc->tx_phase = para->hs2.core_phase; + } + writel(vclk, host->base + SD_EMMC_CLOCK_V3); + pr_info("%s:try clock:0x%x>>>rx_tuning[%d] = %d\n", + mmc_hostname(host->mmc), + readl(host->base + SD_EMMC_CLOCK_V3), + gadjust->adj_delay, nmatch); + } + } for (adj_delay = 0; adj_delay < clk_div; adj_delay++) { gadjust->adj_delay = adj_delay; gadjust->adj_enable = 1; @@ -1356,7 +1579,51 @@ RETRY: return 0; } -int aml_emmc_hs200_timming(struct mmc_host *mmc) +int aml_emmc_hs200_tl1(struct mmc_host *mmc) +{ + struct amlsd_platform *pdata = mmc_priv(mmc); + struct amlsd_host *host = pdata->host; + u32 vclkc = readl(host->base + SD_EMMC_CLOCK_V3); + struct sd_emmc_clock_v3 *clkc = (struct sd_emmc_clock_v3 *)&vclkc; + struct para_e *para = &(host->data->sdmmc); + u32 clk_bak = 0; + u32 delay2 = 0, count = 0; + int i, err = 0; + + clk_bak = vclkc; + clkc->tx_phase = para->hs4.tx_phase; + clkc->core_phase = para->hs4.core_phase; + clkc->tx_delay = para->hs4.tx_delay; + if (pdata->tx_delay != 0) + clkc->tx_delay = pdata->tx_delay; + writel(vclkc, host->base + SD_EMMC_CLOCK_V3); + pr_info("[%s][%d] clk config:0x%x\n", + __func__, __LINE__, readl(host->base + SD_EMMC_CLOCK_V3)); + for (i = 0; i < 63; i++) { + delay2 += (1 << 24); + writel(delay2, host->base + SD_EMMC_DELAY2_V3); + err = emmc_eyetest_log(mmc, 9); + if (err) + continue; + count = fbinary(pdata->align[9]); + if (((count >= 10) && (count <= 22)) + || ((count >= 45) && (count <= 56))) + break; + } + if (i == 63) + pr_err("[%s]no find cmd timing\n", __func__); + pdata->cmd_c = (delay2 >> 24); + pr_info("cmd->u64eyet:0x%016llx\n", + pdata->align[9]); + writel(0, host->base + SD_EMMC_DELAY2_V3); + writel(clk_bak, host->base + SD_EMMC_CLOCK_V3); + pr_info("[%s][%d] clk config:0x%x\n", + __func__, __LINE__, readl(host->base + SD_EMMC_CLOCK_V3)); + return 0; + +} + +int __attribute__((unused)) aml_emmc_hs200_timming(struct mmc_host *mmc) { struct amlsd_platform *pdata = mmc_priv(mmc); struct amlsd_host *host = pdata->host; @@ -1598,23 +1865,27 @@ int aml_mmc_execute_tuning_v3(struct mmc_host *mmc, u32 opcode) pdata->intf3 = intf3; aml_sd_emmc_clktest(mmc); err = aml_sdio_timing(mmc, opcode, - &tuning_data, adj_win_start); + &tuning_data, adj_win_start); } } else if (!(pdata->caps2 & MMC_CAP2_HS400)) { - if (mmc->actual_clock >= 200000000) { - intf3 = readl(host->base + SD_EMMC_INTF3); - intf3 |= (1<<22); - writel(intf3, (host->base + SD_EMMC_INTF3)); - pdata->intf3 = intf3; - err = aml_emmc_hs200_timming(mmc); - } else - err = _aml_sd_emmc_execute_tuning(mmc, opcode, + /*if (mmc->actual_clock >= 200000000) { + * intf3 = readl(host->base + SD_EMMC_INTF3); + * intf3 |= (1<<22); + * writel(intf3, (host->base + SD_EMMC_INTF3)); + * pdata->intf3 = intf3; + * err = aml_emmc_hs200_timming(mmc); + *} else + */ + err = _aml_sd_emmc_execute_tuning(mmc, opcode, &tuning_data, adj_win_start); } else { intf3 = readl(host->base + SD_EMMC_INTF3); intf3 |= (1<<22); writel(intf3, (host->base + SD_EMMC_INTF3)); pdata->intf3 = intf3; + if ((host->data->chip_type == MMC_CHIP_TL1) + || (host->data->chip_type == MMC_CHIP_G12B)) + aml_emmc_hs200_tl1(mmc); err = 0; } @@ -1627,9 +1898,79 @@ int aml_mmc_execute_tuning_v3(struct mmc_host *mmc, u32 opcode) } int aml_post_hs400_timming(struct mmc_host *mmc) { - int ret = 0; + struct amlsd_platform *pdata = mmc_priv(mmc); + struct amlsd_host *host = pdata->host; aml_sd_emmc_clktest(mmc); - ret = emmc_ds_manual_sht(mmc); + if (host->data->chip_type == MMC_CHIP_TL1) + aml_emmc_hs400_tl1(mmc); + else if (host->data->chip_type == MMC_CHIP_G12B) + aml_emmc_hs400_Revb(mmc); + else + aml_emmc_hs400_general(mmc); return 0; } +ssize_t emmc_eyetest_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct amlsd_host *host = dev_get_drvdata(dev); + struct mmc_host *mmc = host->mmc; + + mmc_claim_host(mmc); + update_all_line_eyetest(mmc); + mmc_release_host(mmc); + return sprintf(buf, "%s\n", "Emmc all lines eyetest.\n"); +} + +ssize_t emmc_clktest_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct amlsd_host *host = dev_get_drvdata(dev); + struct mmc_host *mmc = host->mmc; + u32 intf3 = readl(host->base + SD_EMMC_INTF3); + struct intf3 *gintf3 = (struct intf3 *)&(intf3); + u32 clktest = 0, delay_cell = 0, clktest_log = 0, count = 0; + u32 vcfg = readl(host->base + SD_EMMC_CFG); + int i = 0; + unsigned int cycle = 0; + + writel(0, (host->base + SD_EMMC_ADJUST_V3)); + + /* one cycle = xxx(ps) */ + cycle = (1000000000 / mmc->actual_clock) * 1000; + vcfg &= ~(1 << 23); + writel(vcfg, host->base + SD_EMMC_CFG); + gintf3->clktest_exp = 8; + gintf3->clktest_on_m = 1; + writel(intf3, host->base + SD_EMMC_INTF3); + clktest_log = readl(host->base + SD_EMMC_CLKTEST_LOG); + clktest = readl(host->base + SD_EMMC_CLKTEST_OUT); + while (!(clktest_log & 0x80000000)) { + udelay(1); + i++; + clktest_log = readl(host->base + SD_EMMC_CLKTEST_LOG); + clktest = readl(host->base + SD_EMMC_CLKTEST_OUT); + if (i > 4000) { + pr_warn("[%s] [%d] emmc clktest error\n", + __func__, __LINE__); + break; + } + } + if (clktest_log & 0x80000000) { + clktest = readl(host->base + SD_EMMC_CLKTEST_OUT); + count = clktest / (1 << 8); + if (vcfg & 0x4) + delay_cell = ((cycle / 2) / count); + else + delay_cell = (cycle / count); + } + pr_info("%s [%d] clktest : %u, delay_cell: %d, count: %u\n", + __func__, __LINE__, clktest, delay_cell, count); + intf3 = readl(host->base + SD_EMMC_INTF3); + gintf3->clktest_on_m = 0; + writel(intf3, host->base + SD_EMMC_INTF3); + vcfg = readl(host->base + SD_EMMC_CFG); + vcfg |= (1 << 23); + writel(vcfg, host->base + SD_EMMC_CFG); + return count; +} diff --git a/drivers/amlogic/mmc/amlsd.c b/drivers/amlogic/mmc/amlsd.c index 5cb2648709f3..14b24fb62507 100644 --- a/drivers/amlogic/mmc/amlsd.c +++ b/drivers/amlogic/mmc/amlsd.c @@ -675,6 +675,9 @@ static int aml_is_sduart(struct amlsd_platform *pdata) struct amlsd_host *host = pdata->host; struct sd_emmc_status *ista = (struct sd_emmc_status *)&vstat; + if (pdata->no_sduart) + return 0; + mutex_lock(&host->pinmux_lock); pc = aml_devm_pinctrl_get_select(host, "sd_to_ao_uart_pins"); @@ -750,16 +753,22 @@ void jtag_set_state(unsigned int state, unsigned int select) void jtag_select_ao(void) { + struct cpumask org_cpumask; + + cpumask_copy(&org_cpumask, ¤t->cpus_allowed); set_cpus_allowed_ptr(current, cpumask_of(0)); jtag_set_state(AMLOGIC_JTAG_STATE_ON, AMLOGIC_JTAG_APAO); - set_cpus_allowed_ptr(current, cpu_all_mask); + set_cpus_allowed_ptr(current, &org_cpumask); } void jtag_select_sd(void) { + struct cpumask org_cpumask; + + cpumask_copy(&org_cpumask, ¤t->cpus_allowed); set_cpus_allowed_ptr(current, cpumask_of(0)); jtag_set_state(AMLOGIC_JTAG_STATE_ON, AMLOGIC_JTAG_APEE); - set_cpus_allowed_ptr(current, cpu_all_mask); + set_cpus_allowed_ptr(current, &org_cpumask); } #endif @@ -852,7 +861,8 @@ int aml_sd_uart_detect(struct amlsd_platform *pdata) return 1; pdata->is_in = true; pdata->gpio_cd_sta = true; - if (aml_is_sduart(pdata)) { + if ((host->data->chip_type < MMC_CHIP_TL1) + && aml_is_sduart(pdata)) { aml_uart_switch(pdata, 1); pr_info("Uart in\n"); mmc->caps &= ~MMC_CAP_4_BIT_DATA; @@ -867,8 +877,10 @@ int aml_sd_uart_detect(struct amlsd_platform *pdata) } } else { pr_info("normal card in\n"); - aml_uart_switch(pdata, 0); - aml_jtag_switch_ao(pdata); + if (host->data->chip_type < MMC_CHIP_TL1) { + aml_uart_switch(pdata, 0); + aml_jtag_switch_ao(pdata); + } if (host->data->chip_type == MMC_CHIP_G12A) host->is_sduart = 0; if (pdata->caps & MMC_CAP_4_BIT_DATA) @@ -890,8 +902,10 @@ int aml_sd_uart_detect(struct amlsd_platform *pdata) host->is_sduart = 0; if (mmc && mmc->card) mmc_card_set_removed(mmc->card); - aml_uart_switch(pdata, 0); - aml_jtag_switch_ao(pdata); + if (host->data->chip_type < MMC_CHIP_TL1) { + aml_uart_switch(pdata, 0); + aml_jtag_switch_ao(pdata); + } /* switch to 3.3V */ aml_sd_voltage_switch(mmc, MMC_SIGNAL_VOLTAGE_330); diff --git a/drivers/amlogic/mmc/emmc_partitions.c b/drivers/amlogic/mmc/emmc_partitions.c index 076f90aa1f39..12b11e52dedc 100644 --- a/drivers/amlogic/mmc/emmc_partitions.c +++ b/drivers/amlogic/mmc/emmc_partitions.c @@ -274,7 +274,7 @@ int amlmmc_dtb_read(struct mmc_card *card, memset(buf, 0x0, len); start_blk = MMC_DTB_PART_OFFSET; - buffer = kmalloc(CONFIG_DTB_SIZE, GFP_KERNEL); + buffer = kmalloc(CONFIG_DTB_SIZE, GFP_KERNEL|__GFP_RECLAIM); if (!buffer) return -ENOMEM; diff --git a/drivers/amlogic/mtd/aml_dtb.c b/drivers/amlogic/mtd/aml_dtb.c index e8711d886f88..4259e15a2352 100644 --- a/drivers/amlogic/mtd/aml_dtb.c +++ b/drivers/amlogic/mtd/aml_dtb.c @@ -129,10 +129,12 @@ ssize_t dtb_read(struct file *file, loff_t *ppos) { u8 *dtb_ptr = NULL; - /*struct nand_flash *flash = &aml_chip_dtb->flash;*/ + struct nand_chip *chip = &aml_chip_dtb->chip; struct mtd_info *mtd = aml_chip_dtb->mtd; ssize_t read_size = 0; int ret = 0; + loff_t addr; + int chipnr; if (*ppos == aml_chip_dtb->dtbsize) return 0; @@ -146,8 +148,10 @@ ssize_t dtb_read(struct file *file, if (dtb_ptr == NULL) return -ENOMEM; - /*not need nand_get_device here, mtd->_read_xx will done with it*/ - /*nand_get_device(mtd, FL_READING);*/ + addr = *ppos; + nand_get_device(mtd, FL_READING); + chipnr = (int)(addr >> chip->chip_shift); + chip->select_chip(mtd, chipnr); ret = amlnf_dtb_read((u8 *)dtb_ptr, aml_chip_dtb->dtbsize); if (ret) { pr_info("%s: read failed:%d\n", __func__, ret); @@ -163,8 +167,8 @@ ssize_t dtb_read(struct file *file, ret = copy_to_user(buf, (dtb_ptr + *ppos), read_size); *ppos += read_size; exit: - /*nand_release_device(mtd);*/ - /* kfree(dtb_ptr); */ + chip->select_chip(mtd, -1); + nand_release_device(mtd); vfree(dtb_ptr); return read_size; } @@ -175,9 +179,11 @@ ssize_t dtb_write(struct file *file, { u8 *dtb_ptr = NULL; ssize_t write_size = 0; - /*struct nand_flash *flash = &aml_chip_dtb->flash;*/ - struct mtd_info *mtd = aml_chip_dtb->mtd; int ret = 0; + struct nand_chip *chip = &aml_chip_dtb->chip; + struct mtd_info *mtd = aml_chip_dtb->mtd; + loff_t addr; + int chipnr; if (*ppos == aml_chip_dtb->dtbsize) return 0; @@ -191,8 +197,10 @@ ssize_t dtb_write(struct file *file, if (dtb_ptr == NULL) return -ENOMEM; - /*not need nand_get_device here, mtd->_read_xx will done with it*/ - /*nand_get_device(mtd, FL_WRITING);*/ + addr = *ppos; + nand_get_device(mtd, FL_WRITING); + chipnr = (int)(addr >> chip->chip_shift); + chip->select_chip(mtd, chipnr); ret = amlnf_dtb_read((u8 *)dtb_ptr, aml_chip_dtb->dtbsize); if (ret) { pr_info("%s: read failed\n", __func__); @@ -216,8 +224,8 @@ ssize_t dtb_write(struct file *file, *ppos += write_size; exit: - /*nand_release_device(mtd);*/ - /* kfree(dtb_ptr); */ + chip->select_chip(mtd, -1); + nand_release_device(mtd); vfree(dtb_ptr); return write_size; } diff --git a/drivers/amlogic/mtd/aml_env.c b/drivers/amlogic/mtd/aml_env.c index 0de2242ffca7..c56fb1147793 100644 --- a/drivers/amlogic/mtd/aml_env.c +++ b/drivers/amlogic/mtd/aml_env.c @@ -189,6 +189,10 @@ ssize_t uboot_env_read(struct file *file, u8 *env_ptr = NULL; ssize_t read_size = 0; int ret = 0; + struct nand_chip *chip = &aml_chip_env->chip; + struct mtd_info *mtd = aml_chip_env->mtd; + loff_t addr; + int chipnr; if (*ppos == CONFIG_ENV_SIZE) return 0; @@ -201,7 +205,11 @@ ssize_t uboot_env_read(struct file *file, env_ptr = vmalloc(CONFIG_ENV_SIZE + 2048); if (env_ptr == NULL) return -ENOMEM; - mutex_lock(&env_mutex); + + addr = *ppos; + nand_get_device(mtd, FL_READING); + chipnr = (int)(addr >> chip->chip_shift); + chip->select_chip(mtd, chipnr); /*amlnand_get_device(aml_chip_env, CHIP_READING);*/ ret = amlnf_env_read((u8 *)env_ptr, CONFIG_ENV_SIZE); @@ -220,7 +228,8 @@ ssize_t uboot_env_read(struct file *file, ret = copy_to_user(buf, (env_ptr + *ppos), read_size); *ppos += read_size; exit: - mutex_unlock(&env_mutex); + chip->select_chip(mtd, -1); + nand_release_device(mtd); /*amlnand_release_device(aml_chip_env);*/ vfree(env_ptr); return read_size; @@ -233,6 +242,10 @@ ssize_t uboot_env_write(struct file *file, u8 *env_ptr = NULL; ssize_t write_size = 0; int ret = 0; + struct nand_chip *chip = &aml_chip_env->chip; + struct mtd_info *mtd = aml_chip_env->mtd; + loff_t addr; + int chipnr; if (*ppos == CONFIG_ENV_SIZE) return 0; @@ -246,7 +259,10 @@ ssize_t uboot_env_write(struct file *file, if (env_ptr == NULL) return -ENOMEM; - mutex_lock(&env_mutex); + addr = *ppos; + nand_get_device(mtd, FL_WRITING); + chipnr = (int)(addr >> chip->chip_shift); + chip->select_chip(mtd, chipnr); if ((*ppos + count) > CONFIG_ENV_SIZE) write_size = CONFIG_ENV_SIZE - *ppos; @@ -264,7 +280,8 @@ ssize_t uboot_env_write(struct file *file, *ppos += write_size; exit: - mutex_unlock(&env_mutex); + chip->select_chip(mtd, -1); + nand_release_device(mtd); vfree(env_ptr); return write_size; } diff --git a/drivers/amlogic/mtd/aml_mtd.h b/drivers/amlogic/mtd/aml_mtd.h index a8d475e74630..3d4cadf84509 100644 --- a/drivers/amlogic/mtd/aml_mtd.h +++ b/drivers/amlogic/mtd/aml_mtd.h @@ -883,6 +883,9 @@ int boot_device_register(struct aml_nand_chip *aml_chip); int add_mtd_partitions(struct mtd_info *mtd, const struct mtd_partition *part, int num); +int nand_get_device(struct mtd_info *mtd, int new_state); +void nand_release_device(struct mtd_info *mtd); + #ifdef AML_NAND_UBOOT extern int get_partition_from_dts(unsigned char *buffer); #endif diff --git a/drivers/amlogic/mtd/aml_nand.c b/drivers/amlogic/mtd/aml_nand.c index 7251fffc0a12..e827a9a3e5c7 100644 --- a/drivers/amlogic/mtd/aml_nand.c +++ b/drivers/amlogic/mtd/aml_nand.c @@ -17,7 +17,6 @@ #include "aml_mtd.h" - uint8_t nand_boot_flag; /*#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 13)*/ @@ -1913,9 +1912,10 @@ int aml_nand_block_markbad(struct mtd_info *mtd, loff_t ofs) { struct nand_chip *chip = mtd->priv; struct aml_nand_chip *aml_chip = mtd_to_nand_chip(mtd); - struct mtd_oob_ops aml_oob_ops; int blk_addr, mtd_erase_shift; int8_t *buf = NULL; + int page, chipnr; + int ret = 0; if (!mtd->erasesize) return -EINVAL; @@ -1935,19 +1935,18 @@ int aml_nand_block_markbad(struct mtd_info *mtd, loff_t ofs) } mark_bad: /*no erase here, fixit*/ - aml_oob_ops.mode = MTD_OPS_AUTO_OOB; - aml_oob_ops.len = mtd->writesize; - aml_oob_ops.ooblen = mtd->oobavail; - /*aml_oob_ops.ooboffs = chip->ecc.layout->oobfree[0].offset;*/ - aml_oob_ops.ooboffs = 0; - aml_oob_ops.datbuf = chip->buffers->databuf; - aml_oob_ops.oobbuf = chip->oob_poi; chip->pagebuf = -1; - memset((unsigned char *)aml_oob_ops.datbuf, 0x0, mtd->writesize); - memset((unsigned char *)aml_oob_ops.oobbuf, 0x0, aml_oob_ops.ooblen); - - return mtd->_write_oob(mtd, ofs, &aml_oob_ops); + memset((unsigned char *)chip->buffers->databuf, 0x0, mtd->writesize); + memset((unsigned char *)chip->oob_poi, 0x0, mtd->oobavail); + chipnr = (int)(ofs >> chip->chip_shift); + page = (int)(ofs >> chip->page_shift); + chip->select_chip(mtd, chipnr); + ret = chip->write_page(mtd, chip, 0, mtd->writesize, + chip->buffers->databuf, + 1, page, 0, 0); + chip->select_chip(mtd, -1); + return ret; } static uint8_t aml_platform_read_byte(struct mtd_info *mtd) @@ -2195,3 +2194,4 @@ exit_error: aml_chip->block_status = NULL; return err; } + diff --git a/drivers/amlogic/mtd/nand_flash.c b/drivers/amlogic/mtd/nand_flash.c index 206e615aaaea..eaf9715bf610 100644 --- a/drivers/amlogic/mtd/nand_flash.c +++ b/drivers/amlogic/mtd/nand_flash.c @@ -288,6 +288,32 @@ struct aml_nand_flash_dev aml_nand_flash_ids[] = { 0, (NAND_TIMING_MODE5 | NAND_ECC_BCH8_MODE)}, + {"Zetta NAND ZDND2GXXXXX 2Gb", + {NAND_MFR_ZETTA, 0xda, 0x90, 0x95, 0x46}, + 2048, + 256, + 0x20000, + 64, + 1, + 20, + 15, + 0, + 0, + (NAND_TIMING_MODE5 | NAND_ECC_BCH8_MODE)}, + + {"Zetta NAND ZDND1G08U3D-xx 1Gb", + {NAND_MFR_ZETTA, 0xf1, 0x80, 0x95}, + 2048, + 128, + 0x20000, + 64, + 1, + 20, + 15, + 0, + 0, + (NAND_TIMING_MODE5 | NAND_ECC_BCH8_MODE)}, + {"A revision NAND 1GiB sF1G-A", {NAND_MFR_AMD, 0xf1, 0x80, 0x1d, 0x01, 0xf1}, 2048, diff --git a/drivers/amlogic/mtd/rsv_manage.c b/drivers/amlogic/mtd/rsv_manage.c index 79699363a573..cb0de55178bf 100644 --- a/drivers/amlogic/mtd/rsv_manage.c +++ b/drivers/amlogic/mtd/rsv_manage.c @@ -324,7 +324,8 @@ int aml_nand_scan_shipped_bbt(struct mtd_info *mtd) if (aml_chip->mfr_type == NAND_MFR_DOSILICON || aml_chip->mfr_type == NAND_MFR_ATO || - aml_chip->mfr_type == NAND_MFR_HYNIX) { + aml_chip->mfr_type == NAND_MFR_HYNIX || + aml_chip->mfr_type == NAND_MFR_ZETTA) { if (col0_oob != 0xFF) { pr_info("factory Bad blk:%llx blk=%d chip=%d\n", (uint64_t)addr, start_blk, i); @@ -417,9 +418,10 @@ int aml_nand_read_rsv_info(struct mtd_info *mtd, loff_t addr = 0; size_t amount_loaded = 0; size_t len; - struct mtd_oob_ops aml_oob_ops; unsigned char *data_buf; unsigned char oob_buf[sizeof(struct oobinfo_t)]; + int page, realpage, chipnr; + struct nand_chip *chip = mtd_to_nand(mtd); READ_RSV_AGAIN: addr = nandrsv_info->valid_node->phy_blk_addr; @@ -432,20 +434,19 @@ READ_RSV_AGAIN: oobinfo = (struct oobinfo_t *)oob_buf; while (amount_loaded < nandrsv_info->size) { - aml_oob_ops.mode = MTD_OPS_AUTO_OOB; - aml_oob_ops.len = mtd->writesize; - aml_oob_ops.ooblen = sizeof(struct oobinfo_t); - /*aml_oob_ops.ooboffs = mtd->ecclayout->oobfree[0].offset;*/ - aml_oob_ops.ooboffs = 0; - aml_oob_ops.datbuf = data_buf; - aml_oob_ops.oobbuf = oob_buf; - - memset((unsigned char *)aml_oob_ops.datbuf, + memset((unsigned char *)data_buf, 0x0, mtd->writesize); - memset((unsigned char *)aml_oob_ops.oobbuf, - 0x0, aml_oob_ops.ooblen); + memset((unsigned char *)oob_buf, + 0x0, sizeof(struct oobinfo_t)); + chipnr = (int)(addr >> chip->chip_shift); + chip->select_chip(mtd, chipnr); + realpage = (int)(addr >> chip->page_shift); + page = realpage & chip->pagemask; - error = mtd->_read_oob(mtd, addr, &aml_oob_ops); + chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page); + error = chip->ecc.read_page(mtd, chip, data_buf, + 1, page); + chip->select_chip(mtd, -1); if ((error != 0) && (error != -EUCLEAN)) { pr_info("blk good but read failed: %llx, %d\n", (uint64_t)addr, error); @@ -455,11 +456,12 @@ READ_RSV_AGAIN: goto READ_RSV_AGAIN; } + memcpy(oob_buf, chip->oob_poi, mtd->oobavail); if (memcmp(oobinfo->name, nandrsv_info->name, 4)) pr_info("invalid nand info %s magic: %llx\n", nandrsv_info->name, (uint64_t)addr); - addr += mtd->writesize; + page++; len = min_t(uint32_t, mtd->writesize, (nandrsv_info->size - amount_loaded)); memcpy(buf + amount_loaded, data_buf, len); @@ -486,8 +488,6 @@ READ_RSV_AGAIN: } } #endif - /* if(data_buf) */ - /* kfree(data_buf); */ return 0; } @@ -543,18 +543,17 @@ static int aml_nand_write_rsv(struct mtd_info *mtd, struct aml_nandrsv_info_t *nandrsv_info, loff_t offset, u_char *buf) { struct aml_nand_chip *aml_chip = mtd_to_nand_chip(mtd); + struct nand_chip *chip = mtd_to_nand(mtd); struct oobinfo_t *oobinfo; int error = 0; loff_t addr = 0; size_t amount_saved = 0; size_t len; - struct mtd_oob_ops aml_oob_ops; unsigned char *data_buf; unsigned char oob_buf[sizeof(struct oobinfo_t)]; + int page, chipnr; data_buf = aml_chip->rsv_data_buf; - /* if (data_buf == NULL) */ - /* return -ENOMEM; */ addr = offset; pr_info("%s:%d,write info to %llx\n", __func__, __LINE__, addr); @@ -583,21 +582,21 @@ static int aml_nand_write_rsv(struct mtd_info *mtd, } #endif while (amount_saved < nandrsv_info->size) { - aml_oob_ops.mode = MTD_OPS_AUTO_OOB; - aml_oob_ops.len = mtd->writesize; - aml_oob_ops.ooblen = sizeof(struct oobinfo_t); - aml_oob_ops.ooboffs = 0;/*mtd->ecclayout->oobfree[0].offset;*/ - aml_oob_ops.datbuf = data_buf; - aml_oob_ops.oobbuf = oob_buf; - - memset((unsigned char *)aml_oob_ops.datbuf, + memset((unsigned char *)data_buf, 0x0, mtd->writesize); len = min_t(uint32_t, mtd->writesize, nandrsv_info->size - amount_saved); - memcpy((unsigned char *)aml_oob_ops.datbuf, + memcpy((unsigned char *)data_buf, buf + amount_saved, len); - error = mtd->_write_oob(mtd, addr, &aml_oob_ops); + page = (int)(addr >> chip->page_shift); + chipnr = (int)(addr >> chip->chip_shift); + memset(chip->oob_poi, 0xff, mtd->oobsize); + memcpy(chip->oob_poi, oob_buf, mtd->oobsize); + chip->select_chip(mtd, chipnr); + error = chip->write_page(mtd, chip, 0, len, data_buf, + 1, page, 0, 0); + chip->select_chip(mtd, -1); if (error) { pr_info("blk check good but write failed: %llx, %d\n", (uint64_t)addr, error); @@ -608,17 +607,19 @@ static int aml_nand_write_rsv(struct mtd_info *mtd, } if (amount_saved < nandrsv_info->size) return 1; - /* kfree(data_buf); */ + return 0; } int aml_nand_save_rsv_info(struct mtd_info *mtd, struct aml_nandrsv_info_t *nandrsv_info, u_char *buf) { + struct nand_chip *chip = mtd_to_nand(mtd); struct free_node_t *free_node = NULL, *tmp_node = NULL; int error = 0, pages_per_blk, valid_page_addr, i = 1; loff_t addr = 0; - struct erase_info erase_info; + int chipnr = 0; + int page; pages_per_blk = mtd->erasesize / mtd->writesize; /*solve these abnormals caused by power off and ecc error*/ @@ -638,13 +639,12 @@ RE_SEARCH: if ((valid_page_addr - i) == pages_per_blk) { addr = nandrsv_info->valid_node->phy_blk_addr; addr *= mtd->erasesize; - memset(&erase_info, - 0, sizeof(struct erase_info)); - erase_info.mtd = mtd; - erase_info.addr = addr; - erase_info.len = mtd->erasesize; _aml_rsv_disprotect(); - error = mtd->_erase(mtd, &erase_info); + page = (int)(addr >> chip->page_shift); + chipnr = (int)(addr >> chip->chip_shift); + chip->select_chip(mtd, chipnr); + error = chip->erase(mtd, page & chip->pagemask); + chip->select_chip(mtd, -1); _aml_rsv_protect(); nandrsv_info->valid_node->ec++; pr_info("---erase bad env block:%llx\n", addr); @@ -690,7 +690,10 @@ RE_SEARCH: pr_info("%s:%d,save info to %llx\n", __func__, __LINE__, addr); if (nandrsv_info->valid_node->phy_page_addr == 0) { - error = mtd->_block_isbad(mtd, addr); + chipnr = (int)(addr >> chip->chip_shift); + chip->select_chip(mtd, chipnr); + error = chip->block_bad(mtd, addr); + chip->select_chip(mtd, -1); if (error != 0) { /* *bad block here, need fix it @@ -705,16 +708,18 @@ RE_SEARCH: goto RE_SEARCH; } - memset(&erase_info, 0, sizeof(struct erase_info)); - erase_info.mtd = mtd; - erase_info.addr = addr; - erase_info.len = mtd->erasesize; _aml_rsv_disprotect(); - error = mtd->_erase(mtd, &erase_info); + page = (int)(addr >> chip->page_shift); + //chipnr = (int)(addr >> chip->chip_shift); + chip->select_chip(mtd, chipnr); + error = chip->erase(mtd, page & chip->pagemask); + chip->select_chip(mtd, -1); _aml_rsv_protect(); if (error) { pr_info("env free blk erase failed %d\n", error); - mtd->_block_markbad(mtd, addr); + chip->select_chip(mtd, chipnr); + chip->block_markbad(mtd, addr); + chip->select_chip(mtd, -1); return error; } nandrsv_info->valid_node->ec++; @@ -940,20 +945,21 @@ int aml_nand_free_rsv_info(struct mtd_info *mtd, struct free_node_t *tmp_node, *next_node = NULL; int error = 0; loff_t addr = 0; - struct erase_info erase_info; + int page, chipnr; + struct nand_chip *chip = mtd_to_nand(mtd); pr_info("free %s:\n", nandrsv_info->name); if (nandrsv_info->valid) { addr = nandrsv_info->valid_node->phy_blk_addr; addr *= mtd->erasesize; - memset(&erase_info, - 0, sizeof(struct erase_info)); - erase_info.mtd = mtd; - erase_info.addr = addr; - erase_info.len = mtd->erasesize; + + page = (int)(addr >> chip->page_shift); + chipnr = (int)(addr >> chip->chip_shift); _aml_rsv_disprotect(); - error = mtd->_erase(mtd, &erase_info); + chip->select_chip(mtd, chipnr); + error = chip->erase(mtd, page & chip->pagemask); + chip->select_chip(mtd, -1); _aml_rsv_protect(); pr_info("erasing valid info block: %llx\n", addr); nandrsv_info->valid_node->phy_blk_addr = -1; @@ -979,7 +985,6 @@ int aml_nand_scan_rsv_info(struct mtd_info *mtd, { struct aml_nand_chip *aml_chip = mtd_to_nand_chip(mtd); struct nand_chip *chip = &aml_chip->chip; - struct mtd_oob_ops aml_oob_ops; struct oobinfo_t *oobinfo; struct free_node_t *free_node, *tmp_node = NULL; unsigned char oob_buf[sizeof(struct oobinfo_t)]; @@ -989,6 +994,7 @@ int aml_nand_scan_rsv_info(struct mtd_info *mtd, int phys_erase_shift, pages_per_blk, page_num; int error = 0, ret = 0; uint32_t remainder; + int page, realpage, chipnr; data_buf = aml_chip->rsv_data_buf; oobinfo = (struct oobinfo_t *)oob_buf; @@ -1006,19 +1012,20 @@ RE_RSV_INFO_EXT: offset *= start_blk; scan_status = 0; RE_RSV_INFO: - aml_oob_ops.mode = MTD_OPS_AUTO_OOB; - aml_oob_ops.len = mtd->writesize; - aml_oob_ops.ooblen = sizeof(struct oobinfo_t); - aml_oob_ops.ooboffs = 0;/*mtd->ecclayout->oobfree[0].offset;*/ - aml_oob_ops.datbuf = data_buf; - aml_oob_ops.oobbuf = oob_buf; - - memset((unsigned char *)aml_oob_ops.datbuf, + memset((unsigned char *)data_buf, 0x0, mtd->writesize); - memset((unsigned char *)aml_oob_ops.oobbuf, - 0x0, aml_oob_ops.ooblen); + memset((unsigned char *)oob_buf, + 0x0, sizeof(struct oobinfo_t)); - error = mtd->_read_oob(mtd, offset, &aml_oob_ops); + realpage = (int)(offset >> chip->page_shift); + page = realpage & chip->pagemask; + chipnr = (int)(offset >> chip->chip_shift); + + chip->select_chip(mtd, chipnr); + chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page); + error = chip->ecc.read_page(mtd, chip, data_buf, + 1, page); + chip->select_chip(mtd, -1); if ((error != 0) && (error != -EUCLEAN)) { pr_info("blk check good but read failed: %llx, %d\n", (uint64_t)offset, error); @@ -1032,6 +1039,7 @@ RE_RSV_INFO: goto RE_RSV_INFO; } + memcpy(oob_buf, chip->oob_poi, mtd->oobavail); nandrsv_info->init = 1; nandrsv_info->valid_node->status = 0; if (!memcmp(oobinfo->name, nandrsv_info->name, 4)) { @@ -1120,23 +1128,25 @@ RE_RSV_INFO: if (nandrsv_info->valid == 1) { pr_info("%s %d\n", __func__, __LINE__); - aml_oob_ops.mode = MTD_OPS_AUTO_OOB; - aml_oob_ops.len = mtd->writesize; - aml_oob_ops.ooblen = sizeof(struct oobinfo_t); - aml_oob_ops.ooboffs = 0;/*mtd->ecclayout->oobfree[0].offset;*/ - aml_oob_ops.datbuf = data_buf; - aml_oob_ops.oobbuf = oob_buf; for (i = 0; i < pages_per_blk; i++) { - memset((unsigned char *)aml_oob_ops.datbuf, + memset((unsigned char *)data_buf, 0x0, mtd->writesize); - memset((unsigned char *)aml_oob_ops.oobbuf, - 0x0, aml_oob_ops.ooblen); + memset((unsigned char *)oob_buf, + 0x0, sizeof(struct oobinfo_t)); offset = nandrsv_info->valid_node->phy_blk_addr; offset *= mtd->erasesize; offset += i * mtd->writesize; - error = mtd->_read_oob(mtd, offset, &aml_oob_ops); + + realpage = (int)(offset >> chip->page_shift); + page = realpage & chip->pagemask; + chipnr = (int)(offset >> chip->chip_shift); + chip->select_chip(mtd, chipnr); + chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page); + error = chip->ecc.read_page(mtd, chip, data_buf, + 1, page); + chip->select_chip(mtd, -1); if ((error != 0) && (error != -EUCLEAN)) { pr_info("blk good but read failed:%llx,%d\n", (uint64_t)offset, error); @@ -1145,6 +1155,7 @@ RE_RSV_INFO: continue; } + memcpy(oob_buf, chip->oob_poi, mtd->oobavail); if (!memcmp(oobinfo->name, nandrsv_info->name, 4)) { good_addr[i] = 1; nandrsv_info->valid_node->phy_page_addr = i; diff --git a/drivers/amlogic/pci/pcie-amlogic-v2.c b/drivers/amlogic/pci/pcie-amlogic-v2.c index 527ed2843b49..465f27bf529a 100644 --- a/drivers/amlogic/pci/pcie-amlogic-v2.c +++ b/drivers/amlogic/pci/pcie-amlogic-v2.c @@ -28,6 +28,7 @@ #include #include #include +#include #include "../drivers/pci/host/pcie-designware.h" #include "pcie-amlogic.h" @@ -51,11 +52,11 @@ struct amlogic_pcie { u32 pm_enable; u32 device_attch; u32 rst_mod; + u32 pwr_ctl; }; #define to_amlogic_pcie(x) container_of(x, struct amlogic_pcie, pp) struct pcie_phy_aml_regs pcie_aml_regs_v2; -struct pcie_phy *g_pcie_phy_v2; static void amlogic_elb_writel(struct amlogic_pcie *amlogic_pcie, u32 val, u32 reg) @@ -220,12 +221,20 @@ static ssize_t store_pcie_cr_read(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { + struct platform_device *pdev = to_platform_device(dev); + struct amlogic_pcie *amlogic_pcie = platform_get_drvdata(pdev); u32 reg; u32 val; + int j; if (kstrtouint(buf, 0, ®) != 0) return -EINVAL; + for (j = 0; j < 7; j++) + pcie_aml_regs_v2.pcie_phy_r[j] = (void __iomem *) + ((unsigned long)amlogic_pcie->phy->phy_base + + 4*j); + val = amlogic_phy_cr_readl(reg); dev_info(dev, "reg 0x%x value is 0x%x\n", reg, val); @@ -246,11 +255,14 @@ static ssize_t store_pcie_cr_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { + struct platform_device *pdev = to_platform_device(dev); + struct amlogic_pcie *amlogic_pcie = platform_get_drvdata(pdev); unsigned int reg, val; int ret = 0; char *pstr; char *pend; char *strbuf; + int j; if (count > 40) return -EINVAL; @@ -277,6 +289,12 @@ static ssize_t store_pcie_cr_write(struct device *dev, ret = -EINVAL; goto cr_end; } + + for (j = 0; j < 7; j++) + pcie_aml_regs_v2.pcie_phy_r[j] = (void __iomem *) + ((unsigned long)amlogic_pcie->phy->phy_base + + 4*j); + amlogic_phy_cr_writel(val, reg); ret = count; cr_end: @@ -639,6 +657,7 @@ static int __init amlogic_add_pcie_port(struct amlogic_pcie *amlogic_pcie, struct pcie_port *pp = &amlogic_pcie->pp; struct device *dev = pp->dev; int ret; + int j; if (IS_ENABLED(CONFIG_PCI_MSI)) { pp->msi_irq = platform_get_irq(pdev, 0); @@ -671,7 +690,12 @@ static int __init amlogic_add_pcie_port(struct amlogic_pcie *amlogic_pcie, dev_err(pp->dev, "link timeout, disable PCIE PLL\n"); clk_disable_unprepare(amlogic_pcie->bus_clk); clk_disable_unprepare(amlogic_pcie->clk); + clk_disable_unprepare(amlogic_pcie->phy_clk); dev_err(pp->dev, "power down pcie phy\n"); + for (j = 0; j < 7; j++) + pcie_aml_regs_v2.pcie_phy_r[j] = (void __iomem *) + ((unsigned long)amlogic_pcie->phy->phy_base + + 4*j); writel(0x1d, pcie_aml_regs_v2.pcie_phy_r[0]); amlogic_pcie->phy->power_state = 0; } @@ -679,6 +703,30 @@ static int __init amlogic_add_pcie_port(struct amlogic_pcie *amlogic_pcie, return 0; } +static void power_switch_to_pcie(struct pcie_phy *phy) +{ + u32 val; + + power_ctrl_sleep(1, phy->pcie_ctrl_sleep_shift); + + power_ctrl_mempd0(1, phy->pcie_hhi_mem_pd_mask, + phy->pcie_hhi_mem_pd_shift); + udelay(100); + + val = readl((void __iomem *)(unsigned long)phy->reset_base); + writel((val & (~(0x1<pcie_ctrl_a_rst_bit))), + (void __iomem *)(unsigned long)phy->reset_base); + udelay(100); + + power_ctrl_iso(1, phy->pcie_ctrl_iso_shift); + + val = readl((void __iomem *)(unsigned long)phy->reset_base); + writel((val | (0x1<pcie_ctrl_a_rst_bit)), + (void __iomem *)(unsigned long)phy->reset_base); + udelay(100); +} + + static int __init amlogic_pcie_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -703,6 +751,8 @@ static int __init amlogic_pcie_probe(struct platform_device *pdev) int pcie_apb_rst_bit = 0; int pcie_phy_rst_bit = 0; int pcie_ctrl_a_rst_bit = 0; + u32 pwr_ctl = 0; + const void *prop; dev_info(&pdev->dev, "amlogic_pcie_probe!\n"); @@ -716,16 +766,6 @@ static int __init amlogic_pcie_probe(struct platform_device *pdev) pp->dev = dev; port_num++; amlogic_pcie->port_num = port_num; - if (amlogic_pcie->port_num == 1) { - phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL); - if (!phy) { - port_num--; - return -ENOMEM; - } - g_pcie_phy_v2 = phy; - } - - amlogic_pcie->phy = g_pcie_phy_v2; ret = of_property_read_u32(np, "pcie-apb-rst-bit", &pcie_apb_rst_bit); if (ret) @@ -740,6 +780,15 @@ static int __init amlogic_pcie_probe(struct platform_device *pdev) if (ret) amlogic_pcie->rst_mod = 0; + phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL); + if (!phy) { + port_num--; + return -ENOMEM; + } + phy->pcie_ctrl_a_rst_bit = pcie_ctrl_a_rst_bit; + + amlogic_pcie->phy = phy; + ret = of_property_read_u32(np, "pcie-num", &pcie_num); if (ret) amlogic_pcie->pcie_num = 0; @@ -757,6 +806,60 @@ static int __init amlogic_pcie_probe(struct platform_device *pdev) pp->lanes = 0; pp->lanes = num_lanes; + ret = of_property_read_u32(np, "pwr-ctl", &pwr_ctl); + if (ret) + amlogic_pcie->pwr_ctl = 0; + else + amlogic_pcie->pwr_ctl = pwr_ctl; + + if (pwr_ctl) { + prop = of_get_property(dev->of_node, + "pcie-ctrl-sleep-shift", NULL); + if (prop) + amlogic_pcie->phy->pcie_ctrl_sleep_shift = + of_read_ulong(prop, 1); + else + pwr_ctl = 0; + + prop = of_get_property(dev->of_node, + "pcie-hhi-mem-pd-shift", NULL); + if (prop) + amlogic_pcie->phy->pcie_hhi_mem_pd_shift = + of_read_ulong(prop, 1); + else + pwr_ctl = 0; + + prop = of_get_property(dev->of_node, + "pcie-hhi-mem-pd-mask", NULL); + if (prop) + amlogic_pcie->phy->pcie_hhi_mem_pd_mask = + of_read_ulong(prop, 1); + else + pwr_ctl = 0; + + prop = of_get_property(dev->of_node, + "pcie-ctrl-iso-shift", NULL); + if (prop) + amlogic_pcie->phy->pcie_ctrl_iso_shift = + of_read_ulong(prop, 1); + else + pwr_ctl = 0; + } + + if (!amlogic_pcie->phy->reset_base) { + reset_base = platform_get_resource_byname( + pdev, IORESOURCE_MEM, "reset"); + amlogic_pcie->phy->reset_base = ioremap(reset_base->start, + resource_size(reset_base)); + if (IS_ERR(amlogic_pcie->phy->reset_base)) { + ret = PTR_ERR(amlogic_pcie->phy->reset_base); + return ret; + } + } + + if (pwr_ctl) + power_switch_to_pcie(amlogic_pcie->phy); + if (!amlogic_pcie->phy->phy_base) { phy_base = platform_get_resource_byname( pdev, IORESOURCE_MEM, "phy"); @@ -783,17 +886,6 @@ static int __init amlogic_pcie_probe(struct platform_device *pdev) amlogic_pcie->reset_gpio = of_get_named_gpio(np, "reset-gpio", 0); - if (!amlogic_pcie->phy->reset_base) { - reset_base = platform_get_resource_byname( - pdev, IORESOURCE_MEM, "reset"); - amlogic_pcie->phy->reset_base = devm_ioremap_resource( - dev, reset_base); - if (IS_ERR(amlogic_pcie->phy->reset_base)) { - ret = PTR_ERR(amlogic_pcie->phy->reset_base); - goto fail_pcie; - } - } - /* RESET0[1,2,6,7] = 0*/ if (!amlogic_pcie->phy->reset_state) { if (amlogic_pcie->rst_mod == 0) { @@ -830,10 +922,8 @@ static int __init amlogic_pcie_probe(struct platform_device *pdev) if (!amlogic_pcie->phy->reset_state) { rate = clk_get_rate(amlogic_pcie->bus_clk); - if (rate != PCIE_PLL_RATE) { - ret = -ENODEV; - goto fail_pcie; - } + if (rate != PCIE_PLL_RATE) + dev_info(dev, "pcie ref pll is 0x%lx\n", rate); } /*RESET0[6,7] = 1*/ @@ -1000,6 +1090,7 @@ static int amlogic_pcie_suspend_noirq(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); struct amlogic_pcie *amlogic_pcie = platform_get_drvdata(pdev); + int j; if (!amlogic_pcie->pm_enable) { dev_info(dev, "don't noirq suspend amlogic pcie\n"); @@ -1014,6 +1105,10 @@ static int amlogic_pcie_suspend_noirq(struct device *dev) if (amlogic_pcie->device_attch == 0) { dev_info(dev, "controller power off, no suspend noirq\n"); if (amlogic_pcie->pcie_num == 1) { + for (j = 0; j < 7; j++) + pcie_aml_regs_v2.pcie_phy_r[j] = (void __iomem *) + ((unsigned long)amlogic_pcie->phy->phy_base + + 4*j); writel(0x1d, pcie_aml_regs_v2.pcie_phy_r[0]); amlogic_pcie->phy->power_state = 0; } @@ -1040,6 +1135,7 @@ static int amlogic_pcie_resume_noirq(struct device *dev) struct platform_device *pdev = to_platform_device(dev); struct amlogic_pcie *amlogic_pcie = platform_get_drvdata(pdev); unsigned long rate = 100000000; + int j; if (!amlogic_pcie->pm_enable) { dev_info(dev, "don't noirq resume amlogic pcie\n"); @@ -1052,6 +1148,10 @@ static int amlogic_pcie_resume_noirq(struct device *dev) } if (amlogic_pcie->pcie_num == 1) { + for (j = 0; j < 7; j++) + pcie_aml_regs_v2.pcie_phy_r[j] = (void __iomem *) + ((unsigned long)amlogic_pcie->phy->phy_base + + 4*j); writel(0x1c, pcie_aml_regs_v2.pcie_phy_r[0]); amlogic_pcie->phy->power_state = 1; udelay(500); diff --git a/drivers/amlogic/pci/pcie-amlogic.h b/drivers/amlogic/pci/pcie-amlogic.h index d3fca8199e3a..38a7683988e2 100644 --- a/drivers/amlogic/pci/pcie-amlogic.h +++ b/drivers/amlogic/pci/pcie-amlogic.h @@ -162,6 +162,11 @@ struct pcie_phy { u32 reset_state; void __iomem *phy_base; /* DT 1st resource */ void __iomem *reset_base;/* DT 3nd resource */ + u32 pcie_ctrl_sleep_shift; + u32 pcie_hhi_mem_pd_mask; + u32 pcie_ctrl_iso_shift; + u32 pcie_hhi_mem_pd_shift; + u32 pcie_ctrl_a_rst_bit; }; diff --git a/drivers/amlogic/pinctrl/Kconfig b/drivers/amlogic/pinctrl/Kconfig index 6a8724b7f1ab..ebb2e64943ed 100644 --- a/drivers/amlogic/pinctrl/Kconfig +++ b/drivers/amlogic/pinctrl/Kconfig @@ -17,6 +17,12 @@ config AMLOGIC_PINCTRL_MESON8B select AMLOGIC_PINCTRL_MESON8_PMX default n +config AMLOGIC_PINCTRL_MESON_GXBB + bool "Meson gxbb SoC pinctrl driver" + depends on ARM64 || ARM64_A32 + select AMLOGIC_PINCTRL_MESON8_PMX + default n + config AMLOGIC_PINCTRL_MESON_GXL bool "Meson gxl SoC pinctrl driver" depends on ARM64 || ARM64_A32 diff --git a/drivers/amlogic/pinctrl/Makefile b/drivers/amlogic/pinctrl/Makefile index c3880f74c1b4..6e14eb1d2e2a 100644 --- a/drivers/amlogic/pinctrl/Makefile +++ b/drivers/amlogic/pinctrl/Makefile @@ -6,6 +6,7 @@ obj-$(CONFIG_AMLOGIC_PINCTRL_MESON8_PMX) += pinctrl-meson8-pmx.o obj-$(CONFIG_AMLOGIC_PINCONF_MESON_G12A) += pinconf-meson-g12a.o obj-$(CONFIG_AMLOGIC_PINCTRL_MESON_AXG_PMX) += pinctrl-meson-axg-pmx.o obj-$(CONFIG_AMLOGIC_PINCTRL_MESON8B) += pinctrl-meson8b.o +obj-$(CONFIG_AMLOGIC_PINCTRL_MESON_GXBB) += pinctrl-meson-gxbb.o obj-$(CONFIG_AMLOGIC_PINCTRL_MESON_GXL) += pinctrl-meson-gxl.o obj-$(CONFIG_AMLOGIC_PINCTRL_MESON_AXG) += pinctrl-meson-axg.o obj-$(CONFIG_AMLOGIC_PINCTRL_MESON_TXLX) += pinctrl-meson-txlx.o diff --git a/drivers/amlogic/pinctrl/pinctrl-meson-gxbb.c b/drivers/amlogic/pinctrl/pinctrl-meson-gxbb.c new file mode 100644 index 000000000000..a76ec79c7588 --- /dev/null +++ b/drivers/amlogic/pinctrl/pinctrl-meson-gxbb.c @@ -0,0 +1,913 @@ +/* + * Pin controller and GPIO driver for Amlogic Meson GXBB. + * + * Copyright (C) 2016 Endless Mobile, Inc. + * Author: Carlo Caione + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include "pinctrl-meson.h" +#include +#include +#include "pinctrl-meson8-pmx.h" + + +static const struct pinctrl_pin_desc meson_gxbb_periphs_pins[] = { + MESON_PIN(GPIOZ_0), + MESON_PIN(GPIOZ_1), + MESON_PIN(GPIOZ_2), + MESON_PIN(GPIOZ_3), + MESON_PIN(GPIOZ_4), + MESON_PIN(GPIOZ_5), + MESON_PIN(GPIOZ_6), + MESON_PIN(GPIOZ_7), + MESON_PIN(GPIOZ_8), + MESON_PIN(GPIOZ_9), + MESON_PIN(GPIOZ_10), + MESON_PIN(GPIOZ_11), + MESON_PIN(GPIOZ_12), + MESON_PIN(GPIOZ_13), + MESON_PIN(GPIOZ_14), + MESON_PIN(GPIOZ_15), + + MESON_PIN(GPIOH_0), + MESON_PIN(GPIOH_1), + MESON_PIN(GPIOH_2), + MESON_PIN(GPIOH_3), + + MESON_PIN(BOOT_0), + MESON_PIN(BOOT_1), + MESON_PIN(BOOT_2), + MESON_PIN(BOOT_3), + MESON_PIN(BOOT_4), + MESON_PIN(BOOT_5), + MESON_PIN(BOOT_6), + MESON_PIN(BOOT_7), + MESON_PIN(BOOT_8), + MESON_PIN(BOOT_9), + MESON_PIN(BOOT_10), + MESON_PIN(BOOT_11), + MESON_PIN(BOOT_12), + MESON_PIN(BOOT_13), + MESON_PIN(BOOT_14), + MESON_PIN(BOOT_15), + MESON_PIN(BOOT_16), + MESON_PIN(BOOT_17), + + MESON_PIN(CARD_0), + MESON_PIN(CARD_1), + MESON_PIN(CARD_2), + MESON_PIN(CARD_3), + MESON_PIN(CARD_4), + MESON_PIN(CARD_5), + MESON_PIN(CARD_6), + + MESON_PIN(GPIODV_0), + MESON_PIN(GPIODV_1), + MESON_PIN(GPIODV_2), + MESON_PIN(GPIODV_3), + MESON_PIN(GPIODV_4), + MESON_PIN(GPIODV_5), + MESON_PIN(GPIODV_6), + MESON_PIN(GPIODV_7), + MESON_PIN(GPIODV_8), + MESON_PIN(GPIODV_9), + MESON_PIN(GPIODV_10), + MESON_PIN(GPIODV_11), + MESON_PIN(GPIODV_12), + MESON_PIN(GPIODV_13), + MESON_PIN(GPIODV_14), + MESON_PIN(GPIODV_15), + MESON_PIN(GPIODV_16), + MESON_PIN(GPIODV_17), + MESON_PIN(GPIODV_18), + MESON_PIN(GPIODV_19), + MESON_PIN(GPIODV_20), + MESON_PIN(GPIODV_21), + MESON_PIN(GPIODV_22), + MESON_PIN(GPIODV_23), + MESON_PIN(GPIODV_24), + MESON_PIN(GPIODV_25), + MESON_PIN(GPIODV_26), + MESON_PIN(GPIODV_27), + MESON_PIN(GPIODV_28), + MESON_PIN(GPIODV_29), + + MESON_PIN(GPIOY_0), + MESON_PIN(GPIOY_1), + MESON_PIN(GPIOY_2), + MESON_PIN(GPIOY_3), + MESON_PIN(GPIOY_4), + MESON_PIN(GPIOY_5), + MESON_PIN(GPIOY_6), + MESON_PIN(GPIOY_7), + MESON_PIN(GPIOY_8), + MESON_PIN(GPIOY_9), + MESON_PIN(GPIOY_10), + MESON_PIN(GPIOY_11), + MESON_PIN(GPIOY_12), + MESON_PIN(GPIOY_13), + MESON_PIN(GPIOY_14), + MESON_PIN(GPIOY_15), + MESON_PIN(GPIOY_16), + + MESON_PIN(GPIOX_0), + MESON_PIN(GPIOX_1), + MESON_PIN(GPIOX_2), + MESON_PIN(GPIOX_3), + MESON_PIN(GPIOX_4), + MESON_PIN(GPIOX_5), + MESON_PIN(GPIOX_6), + MESON_PIN(GPIOX_7), + MESON_PIN(GPIOX_8), + MESON_PIN(GPIOX_9), + MESON_PIN(GPIOX_10), + MESON_PIN(GPIOX_11), + MESON_PIN(GPIOX_12), + MESON_PIN(GPIOX_13), + MESON_PIN(GPIOX_14), + MESON_PIN(GPIOX_15), + MESON_PIN(GPIOX_16), + MESON_PIN(GPIOX_17), + MESON_PIN(GPIOX_18), + MESON_PIN(GPIOX_19), + MESON_PIN(GPIOX_20), + MESON_PIN(GPIOX_21), + MESON_PIN(GPIOX_22), + + MESON_PIN(GPIOCLK_0), + MESON_PIN(GPIOCLK_1), + MESON_PIN(GPIOCLK_2), + MESON_PIN(GPIOCLK_3), +}; + +static const unsigned int emmc_nand_d07_pins[] = { + BOOT_0, BOOT_1, BOOT_2, BOOT_3, BOOT_4, BOOT_5, BOOT_6, BOOT_7, +}; +static const unsigned int emmc_clk_pins[] = { BOOT_8 }; +static const unsigned int emmc_cmd_pins[] = { BOOT_10 }; +static const unsigned int emmc_ds_pins[] = { BOOT_15 }; + +static const unsigned int nor_d_pins[] = { BOOT_11 }; +static const unsigned int nor_q_pins[] = { BOOT_12 }; +static const unsigned int nor_c_pins[] = { BOOT_13 }; +static const unsigned int nor_cs_pins[] = { BOOT_15 }; + +static const unsigned int spi_sclk_pins[] = { GPIOZ_6 }; +static const unsigned int spi_ss0_pins[] = { GPIOZ_7 }; +static const unsigned int spi_miso_pins[] = { GPIOZ_12 }; +static const unsigned int spi_mosi_pins[] = { GPIOZ_13 }; + +static const unsigned int sdcard_d0_pins[] = { CARD_1 }; +static const unsigned int sdcard_d1_pins[] = { CARD_0 }; +static const unsigned int sdcard_d2_pins[] = { CARD_5 }; +static const unsigned int sdcard_d3_pins[] = { CARD_4 }; +static const unsigned int sdcard_cmd_pins[] = { CARD_3 }; +static const unsigned int sdcard_clk_pins[] = { CARD_2 }; + +static const unsigned int sdio_d0_pins[] = { GPIOX_0 }; +static const unsigned int sdio_d1_pins[] = { GPIOX_1 }; +static const unsigned int sdio_d2_pins[] = { GPIOX_2 }; +static const unsigned int sdio_d3_pins[] = { GPIOX_3 }; +static const unsigned int sdio_cmd_pins[] = { GPIOX_4 }; +static const unsigned int sdio_clk_pins[] = { GPIOX_5 }; +static const unsigned int sdio_irq_pins[] = { GPIOX_7 }; + +static const unsigned int nand_ce0_pins[] = { BOOT_8 }; +static const unsigned int nand_ce1_pins[] = { BOOT_9 }; +static const unsigned int nand_rb0_pins[] = { BOOT_10 }; +static const unsigned int nand_ale_pins[] = { BOOT_11 }; +static const unsigned int nand_cle_pins[] = { BOOT_12 }; +static const unsigned int nand_wen_clk_pins[] = { BOOT_13 }; +static const unsigned int nand_ren_wr_pins[] = { BOOT_14 }; +static const unsigned int nand_dqs_pins[] = { BOOT_15 }; + +static const unsigned int uart_tx_a_pins[] = { GPIOX_12 }; +static const unsigned int uart_rx_a_pins[] = { GPIOX_13 }; +static const unsigned int uart_cts_a_pins[] = { GPIOX_14 }; +static const unsigned int uart_rts_a_pins[] = { GPIOX_15 }; + +static const unsigned int uart_tx_b_pins[] = { GPIODV_24 }; +static const unsigned int uart_rx_b_pins[] = { GPIODV_25 }; +static const unsigned int uart_cts_b_pins[] = { GPIODV_26 }; +static const unsigned int uart_rts_b_pins[] = { GPIODV_27 }; + +static const unsigned int uart_tx_c_pins[] = { GPIOY_13 }; +static const unsigned int uart_rx_c_pins[] = { GPIOY_14 }; +static const unsigned int uart_cts_c_pins[] = { GPIOX_11 }; +static const unsigned int uart_rts_c_pins[] = { GPIOX_12 }; + +static const unsigned int i2c_sck_a_pins[] = { GPIODV_25 }; +static const unsigned int i2c_sda_a_pins[] = { GPIODV_24 }; + +static const unsigned int i2c_sck_b_pins[] = { GPIODV_27 }; +static const unsigned int i2c_sda_b_pins[] = { GPIODV_26 }; + +static const unsigned int i2c_sck_c_pins[] = { GPIODV_29 }; +static const unsigned int i2c_sda_c_pins[] = { GPIODV_28 }; + +static const unsigned int eth_mdio_pins[] = { GPIOZ_0 }; +static const unsigned int eth_mdc_pins[] = { GPIOZ_1 }; +static const unsigned int eth_clk_rx_clk_pins[] = { GPIOZ_2 }; +static const unsigned int eth_rx_dv_pins[] = { GPIOZ_3 }; +static const unsigned int eth_rxd0_pins[] = { GPIOZ_4 }; +static const unsigned int eth_rxd1_pins[] = { GPIOZ_5 }; +static const unsigned int eth_rxd2_pins[] = { GPIOZ_6 }; +static const unsigned int eth_rxd3_pins[] = { GPIOZ_7 }; +static const unsigned int eth_rgmii_tx_clk_pins[] = { GPIOZ_8 }; +static const unsigned int eth_tx_en_pins[] = { GPIOZ_9 }; +static const unsigned int eth_txd0_pins[] = { GPIOZ_10 }; +static const unsigned int eth_txd1_pins[] = { GPIOZ_11 }; +static const unsigned int eth_txd2_pins[] = { GPIOZ_12 }; +static const unsigned int eth_txd3_pins[] = { GPIOZ_13 }; + +static const unsigned int pwm_a_x_pins[] = { GPIOX_6 }; +static const unsigned int pwm_a_y_pins[] = { GPIOY_16 }; +static const unsigned int pwm_b_pins[] = { GPIODV_29 }; +static const unsigned int pwm_d_pins[] = { GPIODV_28 }; +static const unsigned int pwm_e_pins[] = { GPIOX_19 }; +static const unsigned int pwm_f_x_pins[] = { GPIOX_7 }; +static const unsigned int pwm_f_y_pins[] = { GPIOY_15 }; + +static const unsigned int hdmi_hpd_pins[] = { GPIOH_0 }; +static const unsigned int hdmi_sda_pins[] = { GPIOH_1 }; +static const unsigned int hdmi_scl_pins[] = { GPIOH_2 }; + +static const unsigned int tsin_a_d_valid_pins[] = { GPIOY_0 }; +static const unsigned int tsin_a_sop_pins[] = { GPIOY_1 }; +static const unsigned int tsin_a_clk_pins[] = { GPIOY_2 }; +static const unsigned int tsin_a_d0_pins[] = { GPIOY_3 }; +static const unsigned int tsin_a_dp_pins[] = { GPIOY_4, GPIOY_5, GPIOY_6, GPIOY_7, GPIOY_8, GPIOY_9, GPIOY_10 }; +static const unsigned int i2s_out_ch23_y_pins[] = { GPIOY_8 }; +static const unsigned int i2s_out_ch45_y_pins[] = { GPIOY_9 }; +static const unsigned int i2s_out_ch67_y_pins[] = { GPIOY_10 }; + +static const unsigned int tsin_b_d_valid_pins[] = { GPIOX_6 }; +static const unsigned int tsin_b_sop_pins[] = { GPIOX_7 }; +static const unsigned int tsin_b_clk_pins[] = { GPIOX_8 }; +static const unsigned int tsin_b_d0_pins[] = { GPIOX_9 }; + +static const unsigned int spdif_out_y_pins[] = { GPIOY_12 }; + +static const unsigned int gen_clk_out_pins[] = { GPIOY_15 }; + +static const struct pinctrl_pin_desc meson_gxbb_aobus_pins[] = { + MESON_PIN(GPIOAO_0), + MESON_PIN(GPIOAO_1), + MESON_PIN(GPIOAO_2), + MESON_PIN(GPIOAO_3), + MESON_PIN(GPIOAO_4), + MESON_PIN(GPIOAO_5), + MESON_PIN(GPIOAO_6), + MESON_PIN(GPIOAO_7), + MESON_PIN(GPIOAO_8), + MESON_PIN(GPIOAO_9), + MESON_PIN(GPIOAO_10), + MESON_PIN(GPIOAO_11), + MESON_PIN(GPIOAO_12), + MESON_PIN(GPIOAO_13), + + MESON_PIN(GPIO_TEST_N), +}; + +static const unsigned int uart_tx_ao_a_pins[] = { GPIOAO_0 }; +static const unsigned int uart_rx_ao_a_pins[] = { GPIOAO_1 }; +static const unsigned int uart_cts_ao_a_pins[] = { GPIOAO_2 }; +static const unsigned int uart_rts_ao_a_pins[] = { GPIOAO_3 }; +static const unsigned int uart_tx_ao_b_pins[] = { GPIOAO_4 }; +static const unsigned int uart_rx_ao_b_pins[] = { GPIOAO_5 }; +static const unsigned int uart_cts_ao_b_pins[] = { GPIOAO_2 }; +static const unsigned int uart_rts_ao_b_pins[] = { GPIOAO_3 }; + +static const unsigned int i2c_sck_ao_pins[] = { GPIOAO_4 }; +static const unsigned int i2c_sda_ao_pins[] = { GPIOAO_5 }; +static const unsigned int i2c_slave_sck_ao_pins[] = {GPIOAO_4 }; +static const unsigned int i2c_slave_sda_ao_pins[] = {GPIOAO_5 }; + +static const unsigned int remote_input_ao_pins[] = { GPIOAO_7 }; + +static const unsigned int pwm_ao_a_3_pins[] = { GPIOAO_3 }; +static const unsigned int pwm_ao_a_6_pins[] = { GPIOAO_6 }; +static const unsigned int pwm_ao_a_12_pins[] = { GPIOAO_12 }; +static const unsigned int pwm_ao_b_pins[] = { GPIOAO_13 }; + +static const unsigned int i2s_am_clk_pins[] = { GPIOAO_8 }; +static const unsigned int i2s_out_ao_clk_pins[] = { GPIOAO_9 }; +static const unsigned int i2s_out_lr_clk_pins[] = { GPIOAO_10 }; +static const unsigned int i2s_out_ch01_ao_pins[] = { GPIOAO_11 }; +static const unsigned int i2s_out_ch23_ao_pins[] = { GPIOAO_12 }; +static const unsigned int i2s_out_ch45_ao_pins[] = { GPIOAO_13 }; +static const unsigned int i2s_out_ch67_ao_pins[] = { GPIO_TEST_N }; + +static const unsigned int spdif_out_ao_6_pins[] = { GPIOAO_6 }; +static const unsigned int spdif_out_ao_13_pins[] = { GPIOAO_13 }; + +static const unsigned int ao_cec_pins[] = { GPIOAO_12 }; +static const unsigned int ee_cec_pins[] = { GPIOAO_12 }; + +static struct meson_pmx_group meson_gxbb_periphs_groups[] = { + GPIO_GROUP(GPIOZ_0), + GPIO_GROUP(GPIOZ_1), + GPIO_GROUP(GPIOZ_2), + GPIO_GROUP(GPIOZ_3), + GPIO_GROUP(GPIOZ_4), + GPIO_GROUP(GPIOZ_5), + GPIO_GROUP(GPIOZ_6), + GPIO_GROUP(GPIOZ_7), + GPIO_GROUP(GPIOZ_8), + GPIO_GROUP(GPIOZ_9), + GPIO_GROUP(GPIOZ_10), + GPIO_GROUP(GPIOZ_11), + GPIO_GROUP(GPIOZ_12), + GPIO_GROUP(GPIOZ_13), + GPIO_GROUP(GPIOZ_14), + GPIO_GROUP(GPIOZ_15), + + GPIO_GROUP(GPIOH_0), + GPIO_GROUP(GPIOH_1), + GPIO_GROUP(GPIOH_2), + GPIO_GROUP(GPIOH_3), + + GPIO_GROUP(BOOT_0), + GPIO_GROUP(BOOT_1), + GPIO_GROUP(BOOT_2), + GPIO_GROUP(BOOT_3), + GPIO_GROUP(BOOT_4), + GPIO_GROUP(BOOT_5), + GPIO_GROUP(BOOT_6), + GPIO_GROUP(BOOT_7), + GPIO_GROUP(BOOT_8), + GPIO_GROUP(BOOT_9), + GPIO_GROUP(BOOT_10), + GPIO_GROUP(BOOT_11), + GPIO_GROUP(BOOT_12), + GPIO_GROUP(BOOT_13), + GPIO_GROUP(BOOT_14), + GPIO_GROUP(BOOT_15), + GPIO_GROUP(BOOT_16), + GPIO_GROUP(BOOT_17), + + GPIO_GROUP(CARD_0), + GPIO_GROUP(CARD_1), + GPIO_GROUP(CARD_2), + GPIO_GROUP(CARD_3), + GPIO_GROUP(CARD_4), + GPIO_GROUP(CARD_5), + GPIO_GROUP(CARD_6), + + GPIO_GROUP(GPIODV_0), + GPIO_GROUP(GPIODV_1), + GPIO_GROUP(GPIODV_2), + GPIO_GROUP(GPIODV_3), + GPIO_GROUP(GPIODV_4), + GPIO_GROUP(GPIODV_5), + GPIO_GROUP(GPIODV_6), + GPIO_GROUP(GPIODV_7), + GPIO_GROUP(GPIODV_8), + GPIO_GROUP(GPIODV_9), + GPIO_GROUP(GPIODV_10), + GPIO_GROUP(GPIODV_11), + GPIO_GROUP(GPIODV_12), + GPIO_GROUP(GPIODV_13), + GPIO_GROUP(GPIODV_14), + GPIO_GROUP(GPIODV_15), + GPIO_GROUP(GPIODV_16), + GPIO_GROUP(GPIODV_17), + GPIO_GROUP(GPIODV_19), + GPIO_GROUP(GPIODV_20), + GPIO_GROUP(GPIODV_21), + GPIO_GROUP(GPIODV_22), + GPIO_GROUP(GPIODV_23), + GPIO_GROUP(GPIODV_24), + GPIO_GROUP(GPIODV_25), + GPIO_GROUP(GPIODV_26), + GPIO_GROUP(GPIODV_27), + GPIO_GROUP(GPIODV_28), + GPIO_GROUP(GPIODV_29), + + GPIO_GROUP(GPIOY_0), + GPIO_GROUP(GPIOY_1), + GPIO_GROUP(GPIOY_2), + GPIO_GROUP(GPIOY_3), + GPIO_GROUP(GPIOY_4), + GPIO_GROUP(GPIOY_5), + GPIO_GROUP(GPIOY_6), + GPIO_GROUP(GPIOY_7), + GPIO_GROUP(GPIOY_8), + GPIO_GROUP(GPIOY_9), + GPIO_GROUP(GPIOY_10), + GPIO_GROUP(GPIOY_11), + GPIO_GROUP(GPIOY_12), + GPIO_GROUP(GPIOY_13), + GPIO_GROUP(GPIOY_14), + GPIO_GROUP(GPIOY_15), + GPIO_GROUP(GPIOY_16), + + GPIO_GROUP(GPIOX_0), + GPIO_GROUP(GPIOX_1), + GPIO_GROUP(GPIOX_2), + GPIO_GROUP(GPIOX_3), + GPIO_GROUP(GPIOX_4), + GPIO_GROUP(GPIOX_5), + GPIO_GROUP(GPIOX_6), + GPIO_GROUP(GPIOX_7), + GPIO_GROUP(GPIOX_8), + GPIO_GROUP(GPIOX_9), + GPIO_GROUP(GPIOX_10), + GPIO_GROUP(GPIOX_11), + GPIO_GROUP(GPIOX_12), + GPIO_GROUP(GPIOX_13), + GPIO_GROUP(GPIOX_14), + GPIO_GROUP(GPIOX_15), + GPIO_GROUP(GPIOX_16), + GPIO_GROUP(GPIOX_17), + GPIO_GROUP(GPIOX_18), + GPIO_GROUP(GPIOX_19), + GPIO_GROUP(GPIOX_20), + GPIO_GROUP(GPIOX_21), + GPIO_GROUP(GPIOX_22), + + GPIO_GROUP(GPIOCLK_0), + GPIO_GROUP(GPIOCLK_1), + GPIO_GROUP(GPIOCLK_2), + GPIO_GROUP(GPIOCLK_3), + + GPIO_GROUP(GPIO_TEST_N), + + /* Bank X */ + GROUP(sdio_d0, 8, 5), + GROUP(sdio_d1, 8, 4), + GROUP(sdio_d2, 8, 3), + GROUP(sdio_d3, 8, 2), + GROUP(sdio_cmd, 8, 1), + GROUP(sdio_clk, 8, 0), + GROUP(sdio_irq, 8, 11), + GROUP(uart_tx_a, 4, 13), + GROUP(uart_rx_a, 4, 12), + GROUP(uart_cts_a, 4, 11), + GROUP(uart_rts_a, 4, 10), + GROUP(pwm_a_x, 3, 17), + GROUP(pwm_e, 2, 30), + GROUP(pwm_f_x, 3, 18), + GROUP(tsin_b_d_valid, 3, 9), + GROUP(tsin_b_sop, 3, 8), + GROUP(tsin_b_clk, 3, 10), + GROUP(tsin_b_d0, 3, 7), + + /* Bank Y */ + GROUP(tsin_a_d_valid, 3, 2), + GROUP(tsin_a_sop, 3, 1), + GROUP(tsin_a_clk, 3, 0), + GROUP(tsin_a_d0, 3, 4), + GROUP(tsin_a_dp, 3, 5), + GROUP(uart_cts_c, 1, 19), + GROUP(uart_rts_c, 1, 18), + GROUP(uart_tx_c, 1, 17), + GROUP(uart_rx_c, 1, 16), + GROUP(pwm_a_y, 1, 21), + GROUP(pwm_f_y, 1, 20), + GROUP(i2s_out_ch23_y, 1, 5), + GROUP(i2s_out_ch45_y, 1, 6), + GROUP(i2s_out_ch67_y, 1, 7), + GROUP(spdif_out_y, 1, 9), + GROUP(gen_clk_out, 6, 15), + + /* Bank Z */ + GROUP(eth_mdio, 6, 1), + GROUP(eth_mdc, 6, 0), + GROUP(eth_clk_rx_clk, 6, 13), + GROUP(eth_rx_dv, 6, 12), + GROUP(eth_rxd0, 6, 11), + GROUP(eth_rxd1, 6, 10), + GROUP(eth_rxd2, 6, 9), + GROUP(eth_rxd3, 6, 8), + GROUP(eth_rgmii_tx_clk, 6, 7), + GROUP(eth_tx_en, 6, 6), + GROUP(eth_txd0, 6, 5), + GROUP(eth_txd1, 6, 4), + GROUP(eth_txd2, 6, 3), + GROUP(eth_txd3, 6, 2), + GROUP(spi_ss0, 5, 26), + GROUP(spi_sclk, 5, 27), + GROUP(spi_miso, 5, 28), + GROUP(spi_mosi, 5, 29), + + /* Bank H */ + GROUP(hdmi_hpd, 1, 26), + GROUP(hdmi_sda, 1, 25), + GROUP(hdmi_scl, 1, 24), + + /* Bank DV */ + GROUP(uart_tx_b, 2, 29), + GROUP(uart_rx_b, 2, 28), + GROUP(uart_cts_b, 2, 27), + GROUP(uart_rts_b, 2, 26), + GROUP(pwm_b, 3, 21), + GROUP(pwm_d, 3, 20), + GROUP(i2c_sck_a, 7, 27), + GROUP(i2c_sda_a, 7, 26), + GROUP(i2c_sck_b, 7, 25), + GROUP(i2c_sda_b, 7, 24), + GROUP(i2c_sck_c, 7, 23), + GROUP(i2c_sda_c, 7, 22), + + /* Bank BOOT */ + GROUP(emmc_nand_d07, 4, 30), + GROUP(emmc_clk, 4, 18), + GROUP(emmc_cmd, 4, 19), + GROUP(emmc_ds, 4, 31), + GROUP(nor_d, 5, 1), + GROUP(nor_q, 5, 3), + GROUP(nor_c, 5, 2), + GROUP(nor_cs, 5, 0), + GROUP(nand_ce0, 4, 26), + GROUP(nand_ce1, 4, 27), + GROUP(nand_rb0, 4, 25), + GROUP(nand_ale, 4, 24), + GROUP(nand_cle, 4, 23), + GROUP(nand_wen_clk, 4, 22), + GROUP(nand_ren_wr, 4, 21), + GROUP(nand_dqs, 4, 20), + + /* Bank CARD */ + GROUP(sdcard_d1, 2, 14), + GROUP(sdcard_d0, 2, 15), + GROUP(sdcard_d3, 2, 12), + GROUP(sdcard_d2, 2, 13), + GROUP(sdcard_cmd, 2, 10), + GROUP(sdcard_clk, 2, 11), +}; + +static struct meson_pmx_group meson_gxbb_aobus_groups[] = { + GPIO_GROUP(GPIOAO_0), + GPIO_GROUP(GPIOAO_1), + GPIO_GROUP(GPIOAO_2), + GPIO_GROUP(GPIOAO_3), + GPIO_GROUP(GPIOAO_4), + GPIO_GROUP(GPIOAO_5), + GPIO_GROUP(GPIOAO_6), + GPIO_GROUP(GPIOAO_7), + GPIO_GROUP(GPIOAO_8), + GPIO_GROUP(GPIOAO_9), + GPIO_GROUP(GPIOAO_10), + GPIO_GROUP(GPIOAO_11), + GPIO_GROUP(GPIOAO_12), + GPIO_GROUP(GPIOAO_13), + + /* bank AO */ + GROUP(uart_tx_ao_b, 0, 24), + GROUP(uart_rx_ao_b, 0, 25), + GROUP(uart_tx_ao_a, 0, 12), + GROUP(uart_rx_ao_a, 0, 11), + GROUP(uart_cts_ao_a, 0, 10), + GROUP(uart_rts_ao_a, 0, 9), + GROUP(uart_cts_ao_b, 0, 8), + GROUP(uart_rts_ao_b, 0, 7), + GROUP(i2c_sck_ao, 0, 6), + GROUP(i2c_sda_ao, 0, 5), + GROUP(i2c_slave_sck_ao, 0, 2), + GROUP(i2c_slave_sda_ao, 0, 1), + GROUP(remote_input_ao, 0, 0), + GROUP(pwm_ao_a_3, 0, 22), + GROUP(pwm_ao_a_6, 0, 18), + GROUP(pwm_ao_a_12, 0, 17), + GROUP(pwm_ao_b, 0, 3), + GROUP(i2s_am_clk, 0, 30), + GROUP(i2s_out_ao_clk, 0, 29), + GROUP(i2s_out_lr_clk, 0, 28), + GROUP(i2s_out_ch01_ao, 0, 27), + GROUP(i2s_out_ch23_ao, 1, 0), + GROUP(i2s_out_ch45_ao, 1, 1), + GROUP(spdif_out_ao_6, 0, 16), + GROUP(spdif_out_ao_13, 0, 4), + GROUP(ao_cec, 0, 15), + GROUP(ee_cec, 0, 14), + + /* test n pin */ + GROUP(i2s_out_ch67_ao, 1, 2), +}; + +static const char * const gpio_periphs_groups[] = { + "GPIOZ_0", "GPIOZ_1", "GPIOZ_2", "GPIOZ_3", "GPIOZ_4", + "GPIOZ_5", "GPIOZ_6", "GPIOZ_7", "GPIOZ_8", "GPIOZ_9", + "GPIOZ_10", "GPIOZ_11", "GPIOZ_12", "GPIOZ_13", "GPIOZ_14", + "GPIOZ_15", + + "GPIOH_0", "GPIOH_1", "GPIOH_2", "GPIOH_3", + + "BOOT_0", "BOOT_1", "BOOT_2", "BOOT_3", "BOOT_4", + "BOOT_5", "BOOT_6", "BOOT_7", "BOOT_8", "BOOT_9", + "BOOT_10", "BOOT_11", "BOOT_12", "BOOT_13", "BOOT_14", + "BOOT_15", "BOOT_16", "BOOT_17", + + "CARD_0", "CARD_1", "CARD_2", "CARD_3", "CARD_4", + "CARD_5", "CARD_6", + + "GPIODV_0", "GPIODV_1", "GPIODV_2", "GPIODV_3", "GPIODV_4", + "GPIODV_5", "GPIODV_6", "GPIODV_7", "GPIODV_8", "GPIODV_9", + "GPIODV_10", "GPIODV_11", "GPIODV_12", "GPIODV_13", "GPIODV_14", + "GPIODV_15", "GPIODV_16", "GPIODV_17", "GPIODV_18", "GPIODV_19", + "GPIODV_20", "GPIODV_21", "GPIODV_22", "GPIODV_23", "GPIODV_24", + "GPIODV_25", "GPIODV_26", "GPIODV_27", "GPIODV_28", "GPIODV_29", + + "GPIOY_0", "GPIOY_1", "GPIOY_2", "GPIOY_3", "GPIOY_4", + "GPIOY_5", "GPIOY_6", "GPIOY_7", "GPIOY_8", "GPIOY_9", + "GPIOY_10", "GPIOY_11", "GPIOY_12", "GPIOY_13", "GPIOY_14", + "GPIOY_15", "GPIOY_16", + + "GPIOX_0", "GPIOX_1", "GPIOX_2", "GPIOX_3", "GPIOX_4", + "GPIOX_5", "GPIOX_6", "GPIOX_7", "GPIOX_8", "GPIOX_9", + "GPIOX_10", "GPIOX_11", "GPIOX_12", "GPIOX_13", "GPIOX_14", + "GPIOX_15", "GPIOX_16", "GPIOX_17", "GPIOX_18", "GPIOX_19", + "GPIOX_20", "GPIOX_21", "GPIOX_22", +}; + +static const char * const tsin_a_groups[] = { + "tsin_a_clk", "tsin_a_sop", "tsin_a_d_valid", "tsin_a_d0", + "tsin_a_dp", "tsin_a_fail", +}; +static const char * const tsin_b_groups[] = { + "tsin_b_clk", "tsin_b_sop", "tsin_b_d_valid", "tsin_b_d0", +}; + +static const char * const emmc_groups[] = { + "emmc_nand_d07", "emmc_clk", "emmc_cmd", "emmc_ds", +}; + +static const char * const nor_groups[] = { + "nor_d", "nor_q", "nor_c", "nor_cs", +}; + +static const char * const spi_groups[] = { + "spi_mosi", "spi_miso", "spi_ss0", "spi_sclk", +}; + +static const char * const sdcard_groups[] = { + "sdcard_d0", "sdcard_d1", "sdcard_d2", "sdcard_d3", + "sdcard_cmd", "sdcard_clk", +}; + +static const char * const sdio_groups[] = { + "sdio_d0", "sdio_d1", "sdio_d2", "sdio_d3", + "sdio_cmd", "sdio_clk", "sdio_irq", +}; + +static const char * const nand_groups[] = { + "emmc_nand_d07", "nand_ce0", "nand_ce1", "nand_rb0", "nand_ale", + "nand_cle", "nand_wen_clk", "nand_ren_wr", "nand_dqs", +}; + +static const char * const uart_a_groups[] = { + "uart_tx_a", "uart_rx_a", "uart_cts_a", "uart_rts_a", +}; + +static const char * const uart_b_groups[] = { + "uart_tx_b", "uart_rx_b", "uart_cts_b", "uart_rts_b", +}; + +static const char * const uart_c_groups[] = { + "uart_tx_c", "uart_rx_c", "uart_cts_c", "uart_rts_c", +}; + +static const char * const i2c_a_groups[] = { + "i2c_sck_a", "i2c_sda_a", +}; + +static const char * const i2c_b_groups[] = { + "i2c_sck_b", "i2c_sda_b", +}; + +static const char * const i2c_c_groups[] = { + "i2c_sck_c", "i2c_sda_c", +}; + +static const char * const eth_groups[] = { + "eth_mdio", "eth_mdc", "eth_clk_rx_clk", "eth_rx_dv", + "eth_rxd0", "eth_rxd1", "eth_rxd2", "eth_rxd3", + "eth_rgmii_tx_clk", "eth_tx_en", + "eth_txd0", "eth_txd1", "eth_txd2", "eth_txd3", +}; + +static const char * const pwm_a_x_groups[] = { + "pwm_a_x", +}; + +static const char * const pwm_a_y_groups[] = { + "pwm_a_y", +}; + +static const char * const pwm_b_groups[] = { + "pwm_b", +}; + +static const char * const pwm_d_groups[] = { + "pwm_d", +}; + +static const char * const pwm_e_groups[] = { + "pwm_e", +}; + +static const char * const pwm_f_x_groups[] = { + "pwm_f_x", +}; + +static const char * const pwm_f_y_groups[] = { + "pwm_f_y", +}; + +static const char * const hdmi_hpd_groups[] = { + "hdmi_hpd", +}; + +static const char * const hdmi_i2c_groups[] = { + "hdmi_sda", "hdmi_scl", +}; + +static const char * const i2s_out_groups[] = { + "i2s_out_ch23_y", "i2s_out_ch45_y", "i2s_out_ch67_y", +}; + +static const char * const spdif_out_groups[] = { + "spdif_out_y", +}; + +static const char * const gen_clk_out_groups[] = { + "gen_clk_out", +}; + +static const char * const gpio_aobus_groups[] = { + "GPIOAO_0", "GPIOAO_1", "GPIOAO_2", "GPIOAO_3", "GPIOAO_4", + "GPIOAO_5", "GPIOAO_6", "GPIOAO_7", "GPIOAO_8", "GPIOAO_9", + "GPIOAO_10", "GPIOAO_11", "GPIOAO_12", "GPIOAO_13", + + "GPIO_TEST_N", +}; + +static const char * const uart_ao_groups[] = { + "uart_tx_ao_a", "uart_rx_ao_a", "uart_cts_ao_a", "uart_rts_ao_a", +}; + +static const char * const uart_ao_b_groups[] = { + "uart_tx_ao_b", "uart_rx_ao_b", "uart_cts_ao_b", "uart_rts_ao_b", +}; + +static const char * const i2c_ao_groups[] = { + "i2c_sck_ao", "i2c_sda_ao", +}; + +static const char * const i2c_slave_ao_groups[] = { + "i2c_slave_sck_ao", "i2c_slave_sda_ao", +}; + +static const char * const remote_input_ao_groups[] = { + "remote_input_ao", +}; + +static const char * const pwm_ao_a_3_groups[] = { + "pwm_ao_a_3", +}; + +static const char * const pwm_ao_a_6_groups[] = { + "pwm_ao_a_6", +}; + +static const char * const pwm_ao_a_12_groups[] = { + "pwm_ao_a_12", +}; + +static const char * const pwm_ao_b_groups[] = { + "pwm_ao_b", +}; + +static const char * const i2s_out_ao_groups[] = { + "i2s_am_clk", "i2s_out_ao_clk", "i2s_out_lr_clk", + "i2s_out_ch01_ao", "i2s_out_ch23_ao", "i2s_out_ch45_ao", + "i2s_out_ch67_ao", +}; + +static const char * const spdif_out_ao_groups[] = { + "spdif_out_ao_6", "spdif_out_ao_13", +}; + +static const char * const cec_ao_groups[] = { + "ao_cec", "ee_cec", +}; + +static struct meson_pmx_func meson_gxbb_periphs_functions[] = { + FUNCTION(gpio_periphs), + FUNCTION(emmc), + FUNCTION(nor), + FUNCTION(spi), + FUNCTION(sdcard), + FUNCTION(sdio), + FUNCTION(nand), + FUNCTION(uart_a), + FUNCTION(uart_b), + FUNCTION(uart_c), + FUNCTION(i2c_a), + FUNCTION(i2c_b), + FUNCTION(i2c_c), + FUNCTION(eth), + FUNCTION(pwm_a_x), + FUNCTION(pwm_a_y), + FUNCTION(pwm_b), + FUNCTION(pwm_d), + FUNCTION(pwm_e), + FUNCTION(pwm_f_x), + FUNCTION(pwm_f_y), + FUNCTION(hdmi_hpd), + FUNCTION(hdmi_i2c), + FUNCTION(i2s_out), + FUNCTION(spdif_out), + FUNCTION(gen_clk_out), + FUNCTION(tsin_a), + FUNCTION(tsin_b), +}; + +static struct meson_pmx_func meson_gxbb_aobus_functions[] = { + FUNCTION(gpio_aobus), + FUNCTION(uart_ao), + FUNCTION(uart_ao_b), + FUNCTION(i2c_ao), + FUNCTION(i2c_slave_ao), + FUNCTION(remote_input_ao), + FUNCTION(pwm_ao_a_3), + FUNCTION(pwm_ao_a_6), + FUNCTION(pwm_ao_a_12), + FUNCTION(pwm_ao_b), + FUNCTION(i2s_out_ao), + FUNCTION(spdif_out_ao), + FUNCTION(cec_ao), +}; + +static struct meson_bank meson_gxbb_periphs_banks[] = { + /* name first last irq pullen pull dir out in */ + BANK("X", GPIOX_0, GPIOX_22, 106, 4, 0, 4, 0, 12, 0, 13, 0, 14, 0), + BANK("Y", GPIOY_0, GPIOY_16, 89, 1, 0, 1, 0, 3, 0, 4, 0, 5, 0), + BANK("DV", GPIODV_0, GPIODV_29, 59, 0, 0, 0, 0, 0, 0, 1, 0, 2, 0), + BANK("H", GPIOH_0, GPIOH_3, 30, 1, 20, 1, 20, 3, 20, 4, 20, 5, 20), + BANK("Z", GPIOZ_0, GPIOZ_15, 14, 3, 0, 3, 0, 9, 0, 10, 0, 11, 0), + BANK("CARD", CARD_0, CARD_6, 52, 2, 20, 2, 20, 6, 20, 7, 20, 8, 20), + BANK("BOOT", BOOT_0, BOOT_17, 34, 2, 0, 2, 0, 6, 0, 7, 0, 8, 0), + BANK("CLK", GPIOCLK_0, GPIOCLK_3, 129, 3, 28, 3, 28, 9, 28, 10, 28, 11, 28), +}; + +static struct meson_bank meson_gxbb_aobus_banks[] = { + /* name first last irq pullen pull dir out in */ + BANK("AO", GPIOAO_0, GPIOAO_13, 0, 0, 16, 0, 0, 0, 0, 0, 16, 1, 0), +}; + +static struct meson_pinctrl_data meson_gxbb_periphs_pinctrl_data = { + .name = "periphs-banks", + .pins = meson_gxbb_periphs_pins, + .groups = meson_gxbb_periphs_groups, + .funcs = meson_gxbb_periphs_functions, + .banks = meson_gxbb_periphs_banks, + .num_pins = ARRAY_SIZE(meson_gxbb_periphs_pins), + .num_groups = ARRAY_SIZE(meson_gxbb_periphs_groups), + .num_funcs = ARRAY_SIZE(meson_gxbb_periphs_functions), + .num_banks = ARRAY_SIZE(meson_gxbb_periphs_banks), + .pmx_ops = &meson8_pmx_ops, +}; + +static struct meson_pinctrl_data meson_gxbb_aobus_pinctrl_data = { + .name = "aobus-banks", + .pins = meson_gxbb_aobus_pins, + .groups = meson_gxbb_aobus_groups, + .funcs = meson_gxbb_aobus_functions, + .banks = meson_gxbb_aobus_banks, + .num_pins = ARRAY_SIZE(meson_gxbb_aobus_pins), + .num_groups = ARRAY_SIZE(meson_gxbb_aobus_groups), + .num_funcs = ARRAY_SIZE(meson_gxbb_aobus_functions), + .num_banks = ARRAY_SIZE(meson_gxbb_aobus_banks), + .pmx_ops = &meson8_pmx_ops, +}; + +static const struct of_device_id meson_gxbb_pinctrl_dt_match[] = { + { + .compatible = "amlogic,meson-gxbb-periphs-pinctrl", + .data = &meson_gxbb_periphs_pinctrl_data, + }, + { + .compatible = "amlogic,meson-gxbb-aobus-pinctrl", + .data = &meson_gxbb_aobus_pinctrl_data, + }, + { }, +}; + +static struct platform_driver meson_gxbb_pinctrl_driver = { + .probe = meson_pinctrl_probe, + .driver = { + .name = "meson-gxbb-pinctrl", + .of_match_table = meson_gxbb_pinctrl_dt_match, + }, +}; +builtin_platform_driver(meson_gxbb_pinctrl_driver); diff --git a/drivers/amlogic/pinctrl/pinctrl-meson-gxl.c b/drivers/amlogic/pinctrl/pinctrl-meson-gxl.c index a98e3e46c3c0..9366a7705d85 100644 --- a/drivers/amlogic/pinctrl/pinctrl-meson-gxl.c +++ b/drivers/amlogic/pinctrl/pinctrl-meson-gxl.c @@ -755,6 +755,7 @@ static const unsigned int ee_cec_pins[] = { GPIOAO_8 }; /*i2s_out_ao*/ static const unsigned int i2sout_ch23_ao8_pins[] = { GPIOAO_8 }; static const unsigned int i2sout_ch45_ao9_pins[] = { GPIOAO_9 }; +static const unsigned int i2sout_ch67_tn_pins[] = { GPIO_TEST_N }; /*spdif_out_ao*/ static const unsigned int spdid_out_ao9_pins[] = { GPIOAO_9 }; @@ -793,13 +794,14 @@ static struct meson_pmx_group meson_gxl_aobus_groups[] = { GROUP(ir_out_ao7, 0, 21), GROUP(ao_cec, 0, 15), GROUP(ee_cec, 0, 14), - GROUP(i2sout_ch23_ao8, 2, 0), + GROUP(i2sout_ch23_ao8, 1, 0), GROUP(pwm_ao_a_ao8, 0, 17), GROUP(ir_out_ao9, 0, 31), GROUP(spdid_out_ao6, 0, 16), GROUP(spdid_out_ao9, 0, 4), - GROUP(i2sout_ch45_ao9, 2, 1), + GROUP(i2sout_ch45_ao9, 1, 1), GROUP(pwm_ao_b_ao9, 0, 3), + GROUP(i2sout_ch67_tn, 1, 2), }; static const char * const gpio_periphs_groups[] = { @@ -1093,6 +1095,7 @@ static const char * const pwm_ao_b_groups[] = { static const char * const i2s_out_ao_groups[] = { "i2sout_ch23_ao8", "i2sout_ch45_ao9", + "i2sout_ch67_tn", }; static const char * const spdif_out_ao_groups[] = { diff --git a/drivers/amlogic/pinctrl/pinctrl-meson8b.c b/drivers/amlogic/pinctrl/pinctrl-meson8b.c index 96f1a2021cc4..b2fe9a009407 100644 --- a/drivers/amlogic/pinctrl/pinctrl-meson8b.c +++ b/drivers/amlogic/pinctrl/pinctrl-meson8b.c @@ -629,7 +629,7 @@ static struct meson_pmx_group meson8b_aobus_groups[] = { GROUP(i2s_lr_clk_in, 0, 14), }; -static const char * const gpio_groups[] = { +static const char * const gpio_periphs_groups[] = { "GPIOX_0", "GPIOX_1", "GPIOX_2", "GPIOX_3", "GPIOX_4", "GPIOX_5", "GPIOX_6", "GPIOX_7", "GPIOX_8", "GPIOX_9", "GPIOX_10", "GPIOX_11", "GPIOX_16", "GPIOX_17", "GPIOX_18", @@ -861,7 +861,7 @@ static const char * const tsin_b_groups[] = { }; static struct meson_pmx_func meson8b_cbus_functions[] = { - FUNCTION(gpio), + FUNCTION(gpio_periphs), FUNCTION(sd_a), FUNCTION(sdxc_a), FUNCTION(pcm_a), diff --git a/drivers/amlogic/pm/gx_pm.c b/drivers/amlogic/pm/gx_pm.c index 8228001d15b3..951a3dc4b7ed 100644 --- a/drivers/amlogic/pm/gx_pm.c +++ b/drivers/amlogic/pm/gx_pm.c @@ -218,8 +218,9 @@ static int __init meson_pm_probe(struct platform_device *pdev) { struct device_node *cpu_node; struct device_node *state_node; - int count = 0; + int count = 0, ret; u32 ver = psci_get_version(); + u32 paddr = 0; pr_info("enter meson_pm_probe!\n"); @@ -245,11 +246,26 @@ static int __init meson_pm_probe(struct platform_device *pdev) suspend_set_ops(&meson_gx_ops); } - debug_reg = of_iomap(pdev->dev.of_node, 0); - exit_reg = of_iomap(pdev->dev.of_node, 1); + ret = of_property_read_u32(pdev->dev.of_node, + "debug_reg", &paddr); + if (!ret) { + pr_debug("debug_reg: 0x%x\n", paddr); + debug_reg = ioremap(paddr, 0x4); + if (IS_ERR_OR_NULL(debug_reg)) + goto uniomap; + } + + ret = of_property_read_u32(pdev->dev.of_node, + "exit_reg", &paddr); + if (!ret) { + pr_debug("exit_reg: 0x%x\n", paddr); + exit_reg = ioremap(paddr, 0x4); + if (IS_ERR_OR_NULL(exit_reg)) + goto uniomap; + } + device_create_file(&pdev->dev, &dev_attr_suspend_reason); device_create_file(&pdev->dev, &dev_attr_time_out); - device_rename(&pdev->dev, "aml_pm"); #ifdef CONFIG_AMLOGIC_LEGACY_EARLY_SUSPEND if (lgcy_early_suspend_init()) return -1; @@ -258,9 +274,13 @@ static int __init meson_pm_probe(struct platform_device *pdev) pr_info("meson_pm_probe done\n"); return 0; +uniomap: + if (debug_reg) + iounmap(debug_reg); + return -ENXIO; } -static int __exit meson_pm_remove(struct platform_device *pdev) +static int meson_pm_remove(struct platform_device *pdev) { return 0; } @@ -277,12 +297,13 @@ static struct platform_driver meson_pm_driver = { .owner = THIS_MODULE, .of_match_table = amlogic_pm_dt_match, }, - .remove = __exit_p(meson_pm_remove), + .probe = meson_pm_probe, + .remove = meson_pm_remove, }; static int __init meson_pm_init(void) { - return platform_driver_probe(&meson_pm_driver, meson_pm_probe); + return platform_driver_register(&meson_pm_driver); } late_initcall(meson_pm_init); diff --git a/drivers/amlogic/power/Kconfig b/drivers/amlogic/power/Kconfig index 3c405e2f0ef3..53941f9e38ce 100644 --- a/drivers/amlogic/power/Kconfig +++ b/drivers/amlogic/power/Kconfig @@ -1,6 +1,5 @@ config AMLOGIC_POWER bool "Amloigc power related driver support" - depends on MACH_MESON8B default n help this config enables to use amlogic power management driver diff --git a/drivers/amlogic/power/Makefile b/drivers/amlogic/power/Makefile index 294b54188e4e..ea86bf8f9f8a 100644 --- a/drivers/amlogic/power/Makefile +++ b/drivers/amlogic/power/Makefile @@ -3,3 +3,4 @@ obj-$(CONFIG_AMLOGIC_PMU) += aml_pmu/ obj-$(CONFIG_AMLOGIC_PMU_OF) += aml_pmu_of_common.o obj-$(CONFIG_AMLOGIC_M8B_DVFS) += aml_dvfs/ +obj-$(CONFIG_AMLOGIC_POWER) += power_ctrl.o diff --git a/drivers/amlogic/power/power_ctrl.c b/drivers/amlogic/power/power_ctrl.c new file mode 100644 index 000000000000..d7f64d72aabe --- /dev/null +++ b/drivers/amlogic/power/power_ctrl.c @@ -0,0 +1,239 @@ +/* + * drivers/amlogic/power/power_ctrl.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 +#include +#include +#include +#include +#include +#include +#include + +struct power_ctrl { + void __iomem *sleep_addr; + void __iomem *iso_addr; + void __iomem *mempd0_addr; + void __iomem *reset_addr_base; + spinlock_t sleep_lock; + spinlock_t iso_lock; + spinlock_t mempd0_lock; +}; + +struct power_ctrl ctrl; +static bool probe_done; + +bool is_support_power_ctrl(void) +{ + return probe_done; +} +EXPORT_SYMBOL(is_support_power_ctrl); + +int power_ctrl_sleep(bool power_on, unsigned int shift) +{ + unsigned int val; + unsigned long flags; + + if (!probe_done) + return -ENXIO; + + if (power_on) { + spin_lock_irqsave(&ctrl.sleep_lock, flags); + val = readl(ctrl.sleep_addr); + val = val & (~(1 << shift)); + writel(val, ctrl.sleep_addr); + spin_unlock_irqrestore(&ctrl.sleep_lock, flags); + } else { + spin_lock_irqsave(&ctrl.sleep_lock, flags); + val = readl(ctrl.sleep_addr); + val = val | (1 << shift); + writel(val, ctrl.sleep_addr); + spin_unlock_irqrestore(&ctrl.sleep_lock, flags); + } + return 0; +} +EXPORT_SYMBOL(power_ctrl_sleep); + +int power_ctrl_sleep_mask(bool power_on, + unsigned int mask_val, unsigned int shift) +{ + unsigned int val; + unsigned long flags; + + if (!probe_done) + return -ENXIO; + + if (power_on) { + spin_lock_irqsave(&ctrl.sleep_lock, flags); + val = readl(ctrl.sleep_addr); + val = val & (~(mask_val << shift)); + writel(val, ctrl.sleep_addr); + spin_unlock_irqrestore(&ctrl.sleep_lock, flags); + } else { + spin_lock_irqsave(&ctrl.sleep_lock, flags); + val = readl(ctrl.sleep_addr); + val = val | (mask_val << shift); + writel(val, ctrl.sleep_addr); + spin_unlock_irqrestore(&ctrl.sleep_lock, flags); + } + return 0; +} +EXPORT_SYMBOL(power_ctrl_sleep_mask); + +int power_ctrl_iso(bool power_on, unsigned int shift) +{ + unsigned int val; + unsigned long flags; + + if (!probe_done) + return -ENXIO; + + if (power_on) { + spin_lock_irqsave(&(ctrl.iso_lock), flags); + val = readl(ctrl.iso_addr); + val = val & (~(1 << shift)); + writel(val, ctrl.iso_addr); + spin_unlock_irqrestore(&(ctrl.iso_lock), flags); + } else { + spin_lock_irqsave((&ctrl.iso_lock), flags); + val = readl(ctrl.iso_addr); + val = val | (1 << shift); + writel(val, ctrl.iso_addr); + spin_unlock_irqrestore(&(ctrl.iso_lock), flags); + } + return 0; +} +EXPORT_SYMBOL(power_ctrl_iso); + +int power_ctrl_iso_mask(bool power_on, + unsigned int mask_val, unsigned int shift) +{ + unsigned int val; + unsigned long flags; + + if (!probe_done) + return -ENXIO; + + if (power_on) { + spin_lock_irqsave(&(ctrl.iso_lock), flags); + val = readl(ctrl.iso_addr); + val = val & (~(mask_val << shift)); + writel(val, ctrl.iso_addr); + spin_unlock_irqrestore(&(ctrl.iso_lock), flags); + } else { + spin_lock_irqsave((&ctrl.iso_lock), flags); + val = readl(ctrl.iso_addr); + val = val | (mask_val << shift); + writel(val, ctrl.iso_addr); + spin_unlock_irqrestore(&(ctrl.iso_lock), flags); + } + return 0; +} +EXPORT_SYMBOL(power_ctrl_iso_mask); + +int power_ctrl_mempd0(bool power_on, unsigned int mask_val, unsigned int shift) +{ + unsigned int val; + unsigned long flags; + + if (!probe_done) + return -ENXIO; + + if (power_on) { + spin_lock_irqsave(&(ctrl.mempd0_lock), flags); + val = readl(ctrl.mempd0_addr); + val = val & (~(mask_val << shift)); + writel(val, ctrl.mempd0_addr); + spin_unlock_irqrestore(&(ctrl.mempd0_lock), flags); + } else { + spin_lock_irqsave((&ctrl.mempd0_lock), flags); + val = readl(ctrl.mempd0_addr); + val = val | (mask_val << shift); + writel(val, ctrl.mempd0_addr); + spin_unlock_irqrestore(&(ctrl.mempd0_lock), flags); + } + return 0; +} +EXPORT_SYMBOL(power_ctrl_mempd0); + +static int amlogic_powerctrl_probe(struct platform_device *pdev) +{ + struct resource *res; + struct device *dev = &pdev->dev; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(dev, "Fail to get power ctrl memory res0\n"); + return -ENXIO; + } + + ctrl.sleep_addr = devm_ioremap_resource(dev, res); + if (IS_ERR(ctrl.sleep_addr)) + return PTR_ERR(ctrl.sleep_addr); + + ctrl.iso_addr = ctrl.sleep_addr + 4; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 1); + if (!res) { + dev_err(dev, "Fail to get power ctrl memory res1\n"); + return -ENXIO; + } + ctrl.mempd0_addr = devm_ioremap_resource(dev, res); + if (IS_ERR(ctrl.mempd0_addr)) + return PTR_ERR(ctrl.mempd0_addr); + + spin_lock_init(&ctrl.sleep_lock); + spin_lock_init(&ctrl.iso_lock); + spin_lock_init(&ctrl.mempd0_lock); + + probe_done = 1; + return 0; +} + +static int amlogic_powerctrl_remove(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + + devm_iounmap(dev, ctrl.sleep_addr); + devm_iounmap(dev, ctrl.mempd0_addr); + devm_iounmap(dev, ctrl.reset_addr_base); + return 0; +} + +static const struct of_device_id amlogic_powerctrl_match[] = { + { .compatible = "amlogic, sm1-powerctrl", }, + {} +}; + +static struct platform_driver amlogic_powerctrl_driver = { + .driver = { + .name = "amlogic, sm1-powerctrl", + .of_match_table = amlogic_powerctrl_match, + }, + .probe = amlogic_powerctrl_probe, + .remove = amlogic_powerctrl_remove, +}; + +static int __init amlogic_powerctrl_init(void) +{ + return platform_driver_register(&amlogic_powerctrl_driver); +} +arch_initcall(amlogic_powerctrl_init); + +MODULE_AUTHOR("shunzhou jiang #include #include -#ifdef CONFIG_AMLOGIC_RAMDUMP -#include -#define RAMDUMP_REPLACE_MSG "ramdump disabled, replase panic to normal\n" -#endif /* CONFIG_AMLOGIC_RAMDUMP */ static u32 psci_function_id_restart; static u32 psci_function_id_poweroff; @@ -72,15 +68,7 @@ static u32 parse_reason(const char *cmd) } else { if (kernel_panic) { if (strcmp(kernel_panic, "kernel_panic") == 0) { - #ifdef CONFIG_AMLOGIC_RAMDUMP - if (ramdump_disabled()) { - reboot_reason = MESON_NORMAL_BOOT; - pr_info(RAMDUMP_REPLACE_MSG); - } else - reboot_reason = MESON_KERNEL_PANIC; - #else reboot_reason = MESON_KERNEL_PANIC; - #endif } } @@ -154,7 +142,21 @@ static int aml_restart_probe(struct platform_device *pdev) } ret = register_die_notifier(&panic_notifier); - return ret; + if (ret != 0) { + pr_err("%s,register die notifier failed,ret =%d!\n", + __func__, ret); + return ret; + } + + /* Register a call for panic conditions. */ + ret = atomic_notifier_chain_register(&panic_notifier_list, + &panic_notifier); + if (ret != 0) { + pr_err("%s,register panic notifier failed,ret =%d!\n", + __func__, ret); + return ret; + } + return 0; } static const struct of_device_id of_aml_restart_match[] = { diff --git a/drivers/amlogic/reg_access/reg_access.c b/drivers/amlogic/reg_access/reg_access.c index 3ae2bc1b1fa2..32418f3d0ad7 100644 --- a/drivers/amlogic/reg_access/reg_access.c +++ b/drivers/amlogic/reg_access/reg_access.c @@ -53,7 +53,25 @@ int aml_reg_access(struct aml_ddev *indio_dev, iounmap(vaddr); return 0; } +int aml_reg_access_16(struct aml_ddev *indio_dev, + unsigned int reg, unsigned int writeval, + unsigned int *readval) +{ + void __iomem *vaddr; + + reg = round_down(reg, 0x2); + + vaddr = ioremap(reg, 0x4); + + if (readval) + *readval = readw(vaddr); + else + writew(writeval, vaddr); + iounmap(vaddr); + return 0; +} static struct aml_ddev aml_dev; +static struct aml_ddev aml_dev_16; static ssize_t paddr_read_file(struct file *file, char __user *userbuf, size_t count, loff_t *ppos) { @@ -118,7 +136,6 @@ static const struct file_operations paddr_file_ops = { .write = paddr_write_file, }; - static ssize_t dump_write_file(struct file *file, const char __user *userbuf, size_t count, loff_t *ppos) { @@ -189,9 +206,12 @@ static int __init aml_debug_init(void) return -1; } aml_dev.debugfs_reg_access = aml_reg_access; + aml_dev_16.debugfs_reg_access = aml_reg_access_16; debugfs_create_file("paddr", S_IFREG | 0440, debugfs_root, &aml_dev, &paddr_file_ops); + debugfs_create_file("paddr16", S_IFREG | 0440, + debugfs_root, &aml_dev_16, &paddr_file_ops); debugfs_create_file("dump", S_IFREG | 0440, debugfs_root, &aml_dev, &dump_file_ops); return 0; diff --git a/drivers/amlogic/secure_monitor/flash_mutex.S b/drivers/amlogic/secure_monitor/flash_mutex.S index aa8989977374..164841ac2800 100644 --- a/drivers/amlogic/secure_monitor/flash_mutex.S +++ b/drivers/amlogic/secure_monitor/flash_mutex.S @@ -1,3 +1,20 @@ +/* + * drivers/amlogic/secure_monitor/flash_mutex.S + * + * 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. + * + */ + @ This file was created from a .asm file @ using the ads2gas.pl script. .equ DO1STROUNDING, 0 diff --git a/drivers/amlogic/tee/tee.c b/drivers/amlogic/tee/tee.c index 2d2e2245d112..b23213dbc1e6 100644 --- a/drivers/amlogic/tee/tee.c +++ b/drivers/amlogic/tee/tee.c @@ -21,8 +21,6 @@ #include #include -#include -#include #include #define DRIVER_NAME "tee_info" @@ -32,7 +30,7 @@ #define TEE_MSG_UID_1 0xe7f811e3 #define TEE_MSG_UID_2 0xaf630002 #define TEE_MSG_UID_3 0xa5d5c51b -static int disable_flag; +static int disable_flag = 1; #define TEE_SMC_FUNCID_CALLS_REVISION 0xFF03 #define TEE_SMC_CALLS_REVISION \ ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, ARM_SMCCC_SMC_32, \ @@ -73,25 +71,12 @@ static int tee_msg_os_revision(uint32_t *major, uint32_t *minor) struct arm_smccc_res smccc; struct tee_smc_calls_revision_result result; } res; - long cpu; - - if (get_meson_cpu_version(MESON_CPU_VERSION_LVL_MAJOR) - == MESON_CPU_MAJOR_ID_G12B) { - set_cpus_allowed_ptr(current, cpumask_of(0)); - cpu = read_cpuid_mpidr(); - cpu &= 0xfff; - if (cpu != 0x0) - usleep_range(10, 20); - } arm_smccc_smc(TEE_SMC_CALL_GET_OS_REVISION, 0, 0, 0, 0, 0, 0, 0, &res.smccc); *major = res.result.major; *minor = res.result.minor; - if (get_meson_cpu_version(MESON_CPU_VERSION_LVL_MAJOR) - == MESON_CPU_MAJOR_ID_G12B) - set_cpus_allowed_ptr(current, cpu_all_mask); return 0; } @@ -101,25 +86,12 @@ static int tee_msg_api_revision(uint32_t *major, uint32_t *minor) struct arm_smccc_res smccc; struct tee_smc_calls_revision_result result; } res; - long cpu; - - if (get_meson_cpu_version(MESON_CPU_VERSION_LVL_MAJOR) - == MESON_CPU_MAJOR_ID_G12B) { - set_cpus_allowed_ptr(current, cpumask_of(0)); - cpu = read_cpuid_mpidr(); - cpu &= 0xfff; - if (cpu != 0x0) - usleep_range(10, 20); - } arm_smccc_smc(TEE_SMC_CALLS_REVISION, 0, 0, 0, 0, 0, 0, 0, &res.smccc); *major = res.result.major; *minor = res.result.minor; - if (get_meson_cpu_version(MESON_CPU_VERSION_LVL_MAJOR) - == MESON_CPU_MAJOR_ID_G12B) - set_cpus_allowed_ptr(current, cpu_all_mask); return 0; } @@ -162,53 +134,37 @@ static CLASS_ATTR(api_version, 0644, tee_api_version_show, * index: firmware index * vdec: vdec type(0: compatible, 1: legency vdec, 2: HEVC vdec) */ -int tee_load_video_fw(uint32_t index, uint32_t vdec) +static int tee_load_firmware(uint32_t index, uint32_t vdec, bool is_swap) { struct arm_smccc_res res; - long cpu; - - if (get_meson_cpu_version(MESON_CPU_VERSION_LVL_MAJOR) - == MESON_CPU_MAJOR_ID_G12B) { - set_cpus_allowed_ptr(current, cpumask_of(0)); - cpu = read_cpuid_mpidr(); - cpu &= 0xfff; - if (cpu != 0x0) - usleep_range(10, 20); - } arm_smccc_smc(TEE_SMC_LOAD_VIDEO_FW, - index, vdec, 0, 0, 0, 0, 0, &res); + index, vdec, is_swap, 0, 0, 0, 0, &res); - if (get_meson_cpu_version(MESON_CPU_VERSION_LVL_MAJOR) - == MESON_CPU_MAJOR_ID_G12B) - set_cpus_allowed_ptr(current, cpu_all_mask); return res.a0; } + +int tee_load_video_fw(uint32_t index, uint32_t vdec) +{ + return tee_load_firmware(index, vdec, false); +} EXPORT_SYMBOL(tee_load_video_fw); +int tee_load_video_fw_swap(uint32_t index, uint32_t vdec, bool is_swap) +{ + return tee_load_firmware(index, vdec, is_swap); +} +EXPORT_SYMBOL(tee_load_video_fw_swap); + bool tee_enabled(void) { struct arm_smccc_res res; - long cpu; if (disable_flag == 1) return false; /*return false;*/ /*disable tee load temporary*/ - if (get_meson_cpu_version(MESON_CPU_VERSION_LVL_MAJOR) - == MESON_CPU_MAJOR_ID_G12B) { - set_cpus_allowed_ptr(current, cpumask_of(0)); - cpu = read_cpuid_mpidr(); - cpu &= 0xfff; - if (cpu != 0x0) - usleep_range(10, 20); - } - arm_smccc_smc(TEE_SMC_CALLS_UID, 0, 0, 0, 0, 0, 0, 0, &res); - if (get_meson_cpu_version(MESON_CPU_VERSION_LVL_MAJOR) - == MESON_CPU_MAJOR_ID_G12B) - set_cpus_allowed_ptr(current, cpu_all_mask); - if (res.a0 == TEE_MSG_UID_0 && res.a1 == TEE_MSG_UID_1 && res.a2 == TEE_MSG_UID_2 && res.a3 == TEE_MSG_UID_3) return true; diff --git a/drivers/amlogic/thermal/cpucore_cooling.c b/drivers/amlogic/thermal/cpucore_cooling.c index 0b0c7fc3c701..99502fda172b 100644 --- a/drivers/amlogic/thermal/cpucore_cooling.c +++ b/drivers/amlogic/thermal/cpucore_cooling.c @@ -140,7 +140,7 @@ static int cpucore_set_cur_state(struct thermal_cooling_device *cdev, unsigned long state) { struct cpucore_cooling_device *cpucore_device = cdev->devdata; - int set_max_num, id; + int set_max_num, id, i, core_num; mutex_lock(&cooling_cpucore_lock); if (cpucore_device->stop_flag) { @@ -156,8 +156,24 @@ static int cpucore_set_cur_state(struct thermal_cooling_device *cdev, cpucore_device->cpucore_state = state; set_max_num = cpucore_device->max_cpu_core_num - state; id = cpucore_device->cluster_id; - pr_debug("set max cpu num=%d,state=%ld\n", set_max_num, state); - cpufreq_set_max_cpu_num(set_max_num, id); + if (id != CLUSTER_FLAG) { + pr_debug("set max cpu num=%d,state=%ld\n", + set_max_num, state); + cpufreq_set_max_cpu_num(set_max_num, id); + } else { + for (i = 0; i < MAX_CLUSTER; i++) { + pr_debug("%s, set max num: %d, cluster: %d\n", + __func__, set_max_num, i); + core_num = cpucore_device->core_num[i]; + if (set_max_num < core_num) { + cpufreq_set_max_cpu_num(set_max_num, i); + set_max_num = 0; + } else { + set_max_num = set_max_num - core_num; + cpufreq_set_max_cpu_num(core_num, i); + } + } + } } return 0; @@ -256,7 +272,7 @@ cpucore_cooling_register(struct device_node *np, int cluster_id) struct thermal_cooling_device *cool_dev; struct cpucore_cooling_device *cpucore_dev = NULL; char dev_name[THERMAL_NAME_LENGTH]; - int ret = 0, cpu; + int ret = 0, cpu, i; int cores = 0; cpucore_dev = kzalloc(sizeof(struct cpucore_cooling_device), @@ -270,7 +286,8 @@ cpucore_cooling_register(struct device_node *np, int cluster_id) return ERR_PTR(-EINVAL); } - if (mc_capable()) { + if ((topology_physical_package_id(0) != -1) + && (cluster_id != CLUSTER_FLAG)) { for_each_possible_cpu(cpu) { if (topology_physical_package_id(cpu) == cluster_id) cores++; @@ -283,6 +300,17 @@ cpucore_cooling_register(struct device_node *np, int cluster_id) snprintf(dev_name, sizeof(dev_name), "thermal-cpucore-%d", cpucore_dev->id); + if (cluster_id == CLUSTER_FLAG) { + for (i = MAX_CLUSTER - 1; i >= 0; i--) { + cores = 0; + for_each_possible_cpu(cpu) { + if (topology_physical_package_id(cpu) == i) + cores++; + } + cpucore_dev->core_num[i] = cores; + pr_info("%s, clutser[%d] core num:%d\n", __func__, i, cores); + } + } cool_dev = thermal_of_cooling_device_register(np, dev_name, cpucore_dev, &cpucore_cooling_ops); if (!cool_dev) { diff --git a/drivers/amlogic/thermal/meson_cooldev.c b/drivers/amlogic/thermal/meson_cooldev.c index db2c9e474f2d..b12bdd9714d7 100644 --- a/drivers/amlogic/thermal/meson_cooldev.c +++ b/drivers/amlogic/thermal/meson_cooldev.c @@ -232,7 +232,7 @@ int meson_cooldev_min_update(struct platform_device *pdev, int index) case COOL_DEV_TYPE_CPU_FREQ: for_each_possible_cpu(cpu) { - if (mc_capable()) + if (topology_physical_package_id(0) != -1) c_id = topology_physical_package_id(cpu); else c_id = 0; /* force cluster 0 if no MC */ @@ -349,10 +349,12 @@ static int parse_cool_device(struct platform_device *pdev) else cool->gpupp = temp; - if (of_property_read_u32(child, "cluster_id", &temp)) - pr_err("thermal: read cluster_id failed\n"); - else + if (of_property_read_u32(child, "cluster_id", &temp)) { + pr_info("thermal: no cluster id, cpucore as one cooldev\n"); + cool->cluster_id = CLUSTER_FLAG; + } else { cool->cluster_id = temp; + } if (of_property_read_string(child, "device_type", &str)) pr_err("thermal: read device_type failed\n"); diff --git a/drivers/amlogic/uart/meson_uart.c b/drivers/amlogic/uart/meson_uart.c index 811e362b1920..3ce6eb15a523 100644 --- a/drivers/amlogic/uart/meson_uart.c +++ b/drivers/amlogic/uart/meson_uart.c @@ -15,6 +15,7 @@ * */ +#define SKIP_IO_TRACE #include #include #include @@ -640,7 +641,7 @@ static void meson_uart_set_termios(struct uart_port *port, writel(val, port->membase + AML_UART_CONTROL); spin_unlock_irqrestore(&port->lock, flags); - baud = uart_get_baud_rate(port, termios, old, 9600, 4000000); + baud = uart_get_baud_rate(port, termios, old, 2400, 4000000); meson_uart_change_speed(port, baud); port->read_status_mask = AML_UART_RX_FIFO_OVERFLOW; @@ -956,6 +957,7 @@ static int __init meson_early_console_setup(struct earlycon_device *device, return 0; } EARLYCON_DECLARE(aml_uart, meson_early_console_setup); +EARLYCON_DECLARE_COMP(aml-uart, meson_early_console_setup); static struct console meson_serial_console = { .name = AML_UART_DEV_NAME, diff --git a/drivers/amlogic/unifykey/unifykey.c b/drivers/amlogic/unifykey/unifykey.c index c1e35246b168..d2a9fadbcd60 100644 --- a/drivers/amlogic/unifykey/unifykey.c +++ b/drivers/amlogic/unifykey/unifykey.c @@ -1277,7 +1277,7 @@ static ssize_t name_store(struct class *cla, } key_cnt = unifykey_count_key(&(ukdev->uk_header)); - name = kzalloc(count, GFP_KERNEL); + name = kzalloc(count + 1, GFP_KERNEL); if (!name) { pr_err("can't kzalloc mem,%s:%d\n", __func__, diff --git a/drivers/amlogic/usb/dwc_otg/310/common_port/dwc_mem.c b/drivers/amlogic/usb/dwc_otg/310/common_port/dwc_mem.c index cf2c39940a02..5f882237daf9 100644 --- a/drivers/amlogic/usb/dwc_otg/310/common_port/dwc_mem.c +++ b/drivers/amlogic/usb/dwc_otg/310/common_port/dwc_mem.c @@ -1,4 +1,20 @@ -/* Memory Debugging */ +/* + * drivers/amlogic/usb/dwc_otg/310/common_port/dwc_mem.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + #ifdef DWC_DEBUG_MEMORY #include "dwc_os.h" diff --git a/drivers/amlogic/usb/dwc_otg/310/common_port/dwc_modpow.h b/drivers/amlogic/usb/dwc_otg/310/common_port/dwc_modpow.h index 64f00c276e71..54cbdd210e54 100644 --- a/drivers/amlogic/usb/dwc_otg/310/common_port/dwc_modpow.h +++ b/drivers/amlogic/usb/dwc_otg/310/common_port/dwc_modpow.h @@ -1,7 +1,20 @@ /* - * dwc_modpow.h - * See dwc_modpow.c for license and changes + * drivers/amlogic/usb/dwc_otg/310/common_port/dwc_modpow.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 _DWC_MODPOW_H #define _DWC_MODPOW_H diff --git a/drivers/amlogic/usb/dwc_otg/310/common_port/dwc_notifier.c b/drivers/amlogic/usb/dwc_otg/310/common_port/dwc_notifier.c index 8382ef230fe6..3b189ea965f1 100644 --- a/drivers/amlogic/usb/dwc_otg/310/common_port/dwc_notifier.c +++ b/drivers/amlogic/usb/dwc_otg/310/common_port/dwc_notifier.c @@ -1,3 +1,20 @@ +/* + * drivers/amlogic/usb/dwc_otg/310/common_port/dwc_notifier.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + #ifdef DWC_NOTIFYLIB #include "dwc_notifier.h" diff --git a/drivers/amlogic/usb/dwc_otg/310/common_port/dwc_notifier.h b/drivers/amlogic/usb/dwc_otg/310/common_port/dwc_notifier.h index 952f40ddc17a..0c182a5d91d1 100644 --- a/drivers/amlogic/usb/dwc_otg/310/common_port/dwc_notifier.h +++ b/drivers/amlogic/usb/dwc_otg/310/common_port/dwc_notifier.h @@ -1,3 +1,20 @@ +/* + * drivers/amlogic/usb/dwc_otg/310/common_port/dwc_notifier.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 __DWC_NOTIFIER_H__ #define __DWC_NOTIFIER_H__ diff --git a/drivers/amlogic/usb/dwc_otg/310/dwc_otg_cil.c b/drivers/amlogic/usb/dwc_otg/310/dwc_otg_cil.c index 4601a813ea4f..f0e4e5caa9d7 100644 --- a/drivers/amlogic/usb/dwc_otg/310/dwc_otg_cil.c +++ b/drivers/amlogic/usb/dwc_otg/310/dwc_otg_cil.c @@ -6249,8 +6249,11 @@ int dwc_otg_set_param_dev_perio_tx_fifo_size(dwc_otg_core_if_t *core_if, return -DWC_E_INVALID; } if (val > - (DWC_READ_REG32(&core_if->core_global_regs->dtxfsiz[fifo_num]) >> 16)) { - DWC_WARN("Value is larger then power-on FIFO size\n"); + (DWC_READ_REG32 + (&core_if->core_global_regs->dtxfsiz[fifo_num]) >> 16)) { + if (DWC_READ_REG32 + (&core_if->core_global_regs->dtxfsiz[fifo_num]) >> 16) + DWC_WARN("Value is larger then power-on FIFO size\n"); if (dwc_otg_param_initialized (core_if->core_params->dev_perio_tx_fifo_size[fifo_num])) DWC_ERROR @@ -6313,7 +6316,8 @@ int dwc_otg_set_param_dev_tx_fifo_size(dwc_otg_core_if_t *core_if, int32_t val, return -DWC_E_INVALID; } if (val > txfifosize.b.depth) { - DWC_WARN("Value is larger then power-on FIFO size\n"); + if (txfifosize.b.depth) + DWC_WARN("Value is larger then power-on FIFO size\n"); if (dwc_otg_param_initialized (core_if->core_params->dev_tx_fifo_size[fifo_num])) DWC_ERROR diff --git a/drivers/amlogic/usb/dwc_otg/310/dwc_otg_cil.h b/drivers/amlogic/usb/dwc_otg/310/dwc_otg_cil.h index a58ba8cb5d04..3c8ef428c127 100644 --- a/drivers/amlogic/usb/dwc_otg/310/dwc_otg_cil.h +++ b/drivers/amlogic/usb/dwc_otg/310/dwc_otg_cil.h @@ -1060,6 +1060,8 @@ struct dwc_otg_core_if { uint32_t phy_interface; + uint32_t phy_otg; + dwc_timer_t *device_connect_timer; uint64_t sof_counter; diff --git a/drivers/amlogic/usb/dwc_otg/310/dwc_otg_driver.c b/drivers/amlogic/usb/dwc_otg/310/dwc_otg_driver.c index d4ea8162d0ec..263ed2c1938f 100644 --- a/drivers/amlogic/usb/dwc_otg/310/dwc_otg_driver.c +++ b/drivers/amlogic/usb/dwc_otg/310/dwc_otg_driver.c @@ -71,6 +71,7 @@ #include #include #include +#include #ifdef CONFIG_AMLOGIC_LEGACY_EARLY_SUSPEND #include #endif @@ -957,6 +958,7 @@ static int dwc_otg_driver_probe(struct platform_device *pdev) unsigned int p_ctrl_reg_addr = 0; unsigned int phy_reg_addr_size = 0; unsigned int phy_interface = 1; + unsigned int phy_otg = 0; const char *s_clock_name = NULL; const char *cpu_type = NULL; const char *gpio_name = NULL; @@ -1058,6 +1060,15 @@ static int dwc_otg_driver_probe(struct platform_device *pdev) if (prop) phy_interface = of_read_ulong(prop, 1); + prop = of_get_property(of_node, "phy-otg", NULL); + if (prop) + phy_otg = of_read_ulong(prop, 1); + + if (is_meson_g12b_cpu()) { + if (!is_meson_rev_a()) + phy_interface = 2; + } + dwc_otg_module_params.host_rx_fifo_size = dwc_otg_module_params.data_fifo_size / 2; DWC_PRINTF("dwc_otg: %s: type: %d speed: %d, ", s_clock_name, port_type, port_speed); @@ -1156,6 +1167,7 @@ static int dwc_otg_driver_probe(struct platform_device *pdev) dwc_otg_device->core_if->usb_peri_reg = (usb_peri_reg_t *)phy_reg_addr; dwc_otg_device->core_if->controller_type = controller_type; dwc_otg_device->core_if->phy_interface = phy_interface; + dwc_otg_device->core_if->phy_otg = phy_otg; /* * Attempt to ensure this device is really a DWC_otg Controller. * Read and verify the SNPSID register contents. The value should be @@ -1401,10 +1413,14 @@ static int dwc_otg_driver_probe(struct platform_device *pdev) #ifdef CONFIG_AMLOGIC_USB3PHY if (dwc_otg_device->core_if->controller_type == USB_OTG) { - if (dwc_otg_device->core_if->phy_interface == 1) + if (dwc_otg_device->core_if->phy_interface == 1) { aml_new_usb_init(); - else - aml_new_usb_v2_init(); + } else { + if (dwc_otg_device->core_if->phy_otg) + aml_new_otg_init(); + else + aml_new_usb_v2_init(); + } } #endif diff --git a/drivers/amlogic/usb/dwc_otg/310/dwc_otg_driver.h b/drivers/amlogic/usb/dwc_otg/310/dwc_otg_driver.h index 897f51545164..69272923e5c7 100644 --- a/drivers/amlogic/usb/dwc_otg/310/dwc_otg_driver.h +++ b/drivers/amlogic/usb/dwc_otg/310/dwc_otg_driver.h @@ -47,6 +47,7 @@ #ifdef CONFIG_AMLOGIC_USB3PHY extern void aml_new_usb_init(void); extern void aml_new_usb_v2_init(void); +extern void aml_new_otg_init(void); #endif /* Type declarations */ diff --git a/drivers/amlogic/usb/dwc_otg/310/dwc_otg_os_dep.h b/drivers/amlogic/usb/dwc_otg/310/dwc_otg_os_dep.h index 37f5edff15f6..6518a03297e5 100644 --- a/drivers/amlogic/usb/dwc_otg/310/dwc_otg_os_dep.h +++ b/drivers/amlogic/usb/dwc_otg/310/dwc_otg_os_dep.h @@ -1,3 +1,20 @@ +/* + * drivers/amlogic/usb/dwc_otg/310/dwc_otg_os_dep.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 _DWC_OS_DEP_H_ #define _DWC_OS_DEP_H_ diff --git a/drivers/amlogic/usb/dwc_otg/310/dwc_otg_pcd.h b/drivers/amlogic/usb/dwc_otg/310/dwc_otg_pcd.h index ba54785315d1..8fbe4a4401c2 100644 --- a/drivers/amlogic/usb/dwc_otg/310/dwc_otg_pcd.h +++ b/drivers/amlogic/usb/dwc_otg/310/dwc_otg_pcd.h @@ -274,6 +274,8 @@ void dwc_otg_iso_buffer_done(dwc_otg_pcd_t *pcd, dwc_otg_pcd_ep_t *ep, void *req_handle); extern void do_test_mode(void *data); +extern int aml_new_usb_get_mode(void); +extern int aml_new_otg_get_mode(void); #ifdef CONFIG_AMLOGIC_USB3PHY extern void set_usb_phy_device_tuning(int port, int default_val); #endif diff --git a/drivers/amlogic/usb/dwc_otg/310/dwc_otg_pcd_intr.c b/drivers/amlogic/usb/dwc_otg/310/dwc_otg_pcd_intr.c index ecfc09be3ba1..cd503c67b9cb 100644 --- a/drivers/amlogic/usb/dwc_otg/310/dwc_otg_pcd_intr.c +++ b/drivers/amlogic/usb/dwc_otg/310/dwc_otg_pcd_intr.c @@ -1064,19 +1064,38 @@ int32_t dwc_otg_pcd_handle_enum_done_intr(dwc_otg_pcd_t *pcd) DWC_DEBUGPL(DBG_PCD, "SPEED ENUM\n"); #ifdef CONFIG_AMLOGIC_USB3PHY - if (GET_CORE_IF(pcd)->phy_interface == 0) { - speed = get_device_speed(GET_CORE_IF(pcd)); - if (speed != USB_SPEED_HIGH) { - gintsts.d32 = 0; - gintsts.b.enumdone = 1; - DWC_WRITE_REG32(&GET_CORE_IF(pcd)-> - core_global_regs->gintsts, gintsts.d32); - DWC_DEBUGPL(DBG_PCD, "false speed emun\n"); - return 1; + if (GET_CORE_IF(pcd)->phy_interface != 1) { + if (GET_CORE_IF(pcd)->controller_type == USB_OTG) { + speed = get_device_speed(GET_CORE_IF(pcd)); + if (GET_CORE_IF(pcd)->phy_otg == 1) { + if ((speed != USB_SPEED_HIGH) && + (aml_new_otg_get_mode() != 1)) { + gintsts.d32 = 0; + gintsts.b.enumdone = 1; + DWC_WRITE_REG32(&GET_CORE_IF(pcd)-> + core_global_regs->gintsts, + gintsts.d32); + DWC_DEBUGPL(DBG_PCD, + "false speed emun\n"); + return 1; + } + } else { + if ((speed != USB_SPEED_HIGH) && + (aml_new_usb_get_mode() != 1)) { + gintsts.d32 = 0; + gintsts.b.enumdone = 1; + DWC_WRITE_REG32(&GET_CORE_IF(pcd)-> + core_global_regs->gintsts, + gintsts.d32); + DWC_DEBUGPL(DBG_PCD, + "false speed emun\n"); + return 1; + } + } } set_usb_phy_device_tuning(1, 0); - } +} #endif if (GET_CORE_IF(pcd)->snpsid >= OTG_CORE_REV_2_60a) { @@ -1558,7 +1577,8 @@ static inline void do_get_status(dwc_otg_pcd_t *pcd) } break; } else { - *status = 0x1; /* Self powered */ + *status = 0x0; /* bus powered */ + //*status = 0x1; /* Self powered */ *status |= pcd->remote_wakeup_enable << 1; break; } diff --git a/drivers/amlogic/usb/dwc_otg/310/dwc_otg_pcd_linux.c b/drivers/amlogic/usb/dwc_otg/310/dwc_otg_pcd_linux.c index 72276e79bdc8..2ad6baf5ec30 100644 --- a/drivers/amlogic/usb/dwc_otg/310/dwc_otg_pcd_linux.c +++ b/drivers/amlogic/usb/dwc_otg/310/dwc_otg_pcd_linux.c @@ -1267,7 +1267,7 @@ int dwc_usb_change(struct notifier_block *nb, if (value) { DWC_DEBUGPL(DBG_PCDV, "start usb device\n"); dwc_otg_enable_global_interrupts(otg_dev->core_if); - if (otg_dev->core_if->phy_interface == 0) + if (otg_dev->core_if->phy_interface != 0) dwc_otg_enable_device_interrupts(otg_dev->core_if); otg_dev->pcd->core_if->pcd_cb->start(otg_dev->pcd); } else { @@ -1275,7 +1275,7 @@ int dwc_usb_change(struct notifier_block *nb, dwc_otg_disable_global_interrupts(otg_dev->core_if); /* Disable all interrupts. */ - if (otg_dev->core_if->phy_interface == 0) + if (otg_dev->core_if->phy_interface != 0) DWC_WRITE_REG32(&global_regs->gintmsk, 0); otg_dev->pcd->core_if->pcd_cb->stop(otg_dev->pcd); @@ -1304,10 +1304,14 @@ int pcd_init(struct platform_device *pdev) } #ifdef CONFIG_AMLOGIC_USB3PHY - if (otg_dev->core_if->phy_interface == 1) + if (otg_dev->core_if->phy_interface == 1) { aml_new_usb_register_notifier(&otg_dev->nb); - else - aml_new_usb_v2_register_notifier(&otg_dev->nb); + } else { + if (otg_dev->core_if->phy_otg == 1) + aml_new_otg_register_notifier(&otg_dev->nb); + else + aml_new_usb_v2_register_notifier(&otg_dev->nb); + } otg_dev->nb.notifier_call = dwc_usb_change; #endif @@ -1375,10 +1379,14 @@ void pcd_remove(struct platform_device *pdev) free_wrapper(gadget_wrapper); dwc_otg_pcd_remove(otg_dev->pcd); #ifdef CONFIG_AMLOGIC_USB3PHY - if (otg_dev->core_if->phy_interface == 1) + if (otg_dev->core_if->phy_interface == 1) { aml_new_usb_unregister_notifier(&otg_dev->nb); - else - aml_new_usb_v2_unregister_notifier(&otg_dev->nb); + } else { + if (otg_dev->core_if->phy_otg == 1) + aml_new_otg_unregister_notifier(&otg_dev->nb); + else + aml_new_usb_v2_unregister_notifier(&otg_dev->nb); + } #endif otg_dev->pcd = 0; } diff --git a/drivers/amlogic/usb/phy/Makefile b/drivers/amlogic/usb/phy/Makefile index 22433e19fc7b..47a6d6df259e 100644 --- a/drivers/amlogic/usb/phy/Makefile +++ b/drivers/amlogic/usb/phy/Makefile @@ -8,3 +8,5 @@ obj-$(CONFIG_AMLOGIC_USB3PHY) += phy-aml-new-usb3.o obj-$(CONFIG_AMLOGIC_USBPHY) += phy-aml-new-usb-v2.o obj-$(CONFIG_AMLOGIC_USB2PHY) += phy-aml-new-usb2-v2.o obj-$(CONFIG_AMLOGIC_USB3PHY) += phy-aml-new-usb3-v2.o +obj-$(CONFIG_AMLOGIC_USB3PHY) += phy-aml-new-usb3-v3.o +obj-$(CONFIG_AMLOGIC_USB3PHY) += phy-aml-new-otg.o diff --git a/drivers/amlogic/usb/phy/phy-aml-new-otg.c b/drivers/amlogic/usb/phy/phy-aml-new-otg.c new file mode 100644 index 000000000000..d4d4f1868998 --- /dev/null +++ b/drivers/amlogic/usb/phy/phy-aml-new-otg.c @@ -0,0 +1,388 @@ +/* + * drivers/amlogic/usb/phy/phy-aml-new-otg.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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "phy-aml-new-usb-v2.h" + +#define HOST_MODE 0 +#define DEVICE_MODE 1 + +struct usb_aml_regs_v2 usb_otg_aml_regs; +struct amlogic_otg *g_otg; + +struct amlogic_otg { + struct device *dev; + void __iomem *phy3_cfg; + void __iomem *phy3_cfg_r1; + void __iomem *phy3_cfg_r2; + void __iomem *phy3_cfg_r4; + void __iomem *phy3_cfg_r5; + void __iomem *usb2_phy_cfg; + /* Set VBus Power though GPIO */ + int vbus_power_pin; + int vbus_power_pin_work_mask; + struct delayed_work work; + struct gpio_desc *usb_gpio_desc; +}; + +static void set_mode(unsigned long reg_addr, int mode); +BLOCKING_NOTIFIER_HEAD(aml_new_otg_notifier_list); + +int aml_new_otg_register_notifier(struct notifier_block *nb) +{ + int ret; + + ret = blocking_notifier_chain_register + (&aml_new_otg_notifier_list, nb); + + return ret; +} +EXPORT_SYMBOL(aml_new_otg_register_notifier); + +int aml_new_otg_unregister_notifier(struct notifier_block *nb) +{ + int ret; + + ret = blocking_notifier_chain_unregister + (&aml_new_otg_notifier_list, nb); + + return ret; +} +EXPORT_SYMBOL(aml_new_otg_unregister_notifier); + +static void aml_new_usb_notifier_call(unsigned long is_device_on) +{ + blocking_notifier_call_chain + (&aml_new_otg_notifier_list, is_device_on, NULL); +} + +static void set_usb_vbus_power + (struct gpio_desc *usb_gd, int pin, char is_power_on) +{ + if (is_power_on) + /*set vbus on by gpio*/ + gpiod_direction_output(usb_gd, 1); + else + /*set vbus off by gpio first*/ + gpiod_direction_output(usb_gd, 0); +} + +static void amlogic_new_set_vbus_power + (struct amlogic_otg *phy, char is_power_on) +{ + if (phy->vbus_power_pin != -1) + set_usb_vbus_power(phy->usb_gpio_desc, + phy->vbus_power_pin, is_power_on); +} + + + +void aml_new_otg_init(void) +{ + union usb_r5_v2 r5 = {.d32 = 0}; + unsigned long reg_addr; + + if (!g_otg) + return; + + reg_addr = (unsigned long)g_otg->usb2_phy_cfg; + + r5.d32 = readl(usb_otg_aml_regs.usb_r_v2[5]); + if (r5.b.iddig_curr == 0) { + amlogic_new_set_vbus_power(g_otg, 1); + aml_new_usb_notifier_call(0); + set_mode(reg_addr, HOST_MODE); + } +} +EXPORT_SYMBOL(aml_new_otg_init); + +int aml_new_otg_get_mode(void) +{ + union usb_r5_v2 r5 = {.d32 = 0}; + + r5.d32 = readl(usb_otg_aml_regs.usb_r_v2[5]); + if (r5.b.iddig_curr == 0) + return 0; + else + return 1; +} +EXPORT_SYMBOL(aml_new_otg_get_mode); + + +static int amlogic_new_otg_init(struct amlogic_otg *phy) +{ + union usb_r1_v2 r1 = {.d32 = 0}; + union usb_r5_v2 r5 = {.d32 = 0}; + int i = 0; + + for (i = 0; i < 6; i++) { + usb_otg_aml_regs.usb_r_v2[i] = (void __iomem *) + ((unsigned long)phy->usb2_phy_cfg + 0x80 + 4*i); + } + + r1.d32 = readl(usb_otg_aml_regs.usb_r_v2[1]); + r1.b.u3h_fladj_30mhz_reg = 0x20; + writel(r1.d32, usb_otg_aml_regs.usb_r_v2[1]); + + r5.d32 = readl(usb_otg_aml_regs.usb_r_v2[5]); + r5.b.iddig_en0 = 1; + r5.b.iddig_en1 = 1; + r5.b.iddig_th = 255; + writel(r5.d32, usb_otg_aml_regs.usb_r_v2[5]); + + return 0; +} + +static void set_mode(unsigned long reg_addr, int mode) +{ + struct u2p_aml_regs_v2 u2p_aml_regs; + struct usb_aml_regs_v2 usb_gxl_aml_regs; + union u2p_r0_v2 reg0; + union usb_r0_v2 r0 = {.d32 = 0}; + union usb_r4_v2 r4 = {.d32 = 0}; + + u2p_aml_regs.u2p_r_v2[0] = (void __iomem *) + ((unsigned long)reg_addr + PHY_REGISTER_SIZE); + + usb_gxl_aml_regs.usb_r_v2[0] = (void __iomem *) + ((unsigned long)reg_addr + 4*PHY_REGISTER_SIZE + + 4*0); + usb_gxl_aml_regs.usb_r_v2[1] = (void __iomem *) + ((unsigned long)reg_addr + 4*PHY_REGISTER_SIZE + + 4*1); + usb_gxl_aml_regs.usb_r_v2[4] = (void __iomem *) + ((unsigned long)reg_addr + 4*PHY_REGISTER_SIZE + + 4*4); + + r0.d32 = readl(usb_gxl_aml_regs.usb_r_v2[0]); + if (mode == DEVICE_MODE) { + r0.b.u2d_act = 1; + r0.b.u2d_ss_scaledown_mode = 0; + } else + r0.b.u2d_act = 0; + writel(r0.d32, usb_gxl_aml_regs.usb_r_v2[0]); + + r4.d32 = readl(usb_gxl_aml_regs.usb_r_v2[4]); + if (mode == DEVICE_MODE) + r4.b.p21_SLEEPM0 = 0x1; + else + r4.b.p21_SLEEPM0 = 0x0; + writel(r4.d32, usb_gxl_aml_regs.usb_r_v2[4]); + + reg0.d32 = readl(u2p_aml_regs.u2p_r_v2[0]); + if (mode == DEVICE_MODE) { + reg0.b.host_device = 0; + reg0.b.POR = 0; + } else { + reg0.b.host_device = 1; + reg0.b.POR = 0; + } + writel(reg0.d32, u2p_aml_regs.u2p_r_v2[0]); + + udelay(500); +} + +static void amlogic_gxl_work(struct work_struct *work) +{ + struct amlogic_otg *phy = + container_of(work, struct amlogic_otg, work.work); + union usb_r5_v2 r5 = {.d32 = 0}; + unsigned long reg_addr = ((unsigned long)phy->usb2_phy_cfg); + + r5.d32 = readl(usb_otg_aml_regs.usb_r_v2[5]); + if (r5.b.iddig_curr == 0) { + amlogic_new_set_vbus_power(phy, 1); + aml_new_usb_notifier_call(0); + set_mode(reg_addr, HOST_MODE); + } else { + set_mode(reg_addr, DEVICE_MODE); + aml_new_usb_notifier_call(1); + amlogic_new_set_vbus_power(phy, 0); + } + r5.b.usb_iddig_irq = 0; + writel(r5.d32, usb_otg_aml_regs.usb_r_v2[5]); +} + +static irqreturn_t amlogic_botg_detect_irq(int irq, void *dev) +{ + struct amlogic_otg *phy = (struct amlogic_otg *)dev; + union usb_r5_v2 r5 = {.d32 = 0}; + + r5.d32 = readl(usb_otg_aml_regs.usb_r_v2[5]); + r5.b.usb_iddig_irq = 0; + writel(r5.d32, usb_otg_aml_regs.usb_r_v2[5]); + + schedule_delayed_work(&phy->work, msecs_to_jiffies(10)); + + return IRQ_HANDLED; +} + +static int amlogic_new_otg_probe(struct platform_device *pdev) +{ + struct amlogic_otg *phy; + struct device *dev = &pdev->dev; + void __iomem *usb2_phy_base; + unsigned int usb2_phy_mem; + unsigned int usb2_phy_mem_size = 0; + const char *gpio_name = NULL; + struct gpio_desc *usb_gd = NULL; + const void *prop; + int irq; + int retval; + int gpio_vbus_power_pin = -1; + int otg = 0; + + gpio_name = of_get_property(dev->of_node, "gpio-vbus-power", NULL); + if (gpio_name) { + gpio_vbus_power_pin = 1; + usb_gd = gpiod_get_index(&pdev->dev, + NULL, 0, GPIOD_OUT_LOW); + if (IS_ERR(usb_gd)) + return -1; + } + + prop = of_get_property(dev->of_node, "otg", NULL); + if (prop) + otg = of_read_ulong(prop, 1); + + retval = of_property_read_u32 + (dev->of_node, "usb2-phy-reg", &usb2_phy_mem); + if (retval < 0) + return -EINVAL; + + retval = of_property_read_u32 + (dev->of_node, "usb2-phy-reg-size", &usb2_phy_mem_size); + if (retval < 0) + return -EINVAL; + + usb2_phy_base = devm_ioremap_nocache + (&(pdev->dev), (resource_size_t)usb2_phy_mem, + (unsigned long)usb2_phy_mem_size); + if (!usb2_phy_base) + return -ENOMEM; + + phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL); + if (!phy) + return -ENOMEM; + + if (otg) { + irq = platform_get_irq(pdev, 0); + if (irq < 0) + return -ENODEV; + retval = request_irq(irq, amlogic_botg_detect_irq, + IRQF_SHARED | IRQ_LEVEL, + "amlogic_botg_detect", phy); + + if (retval) { + dev_err(&pdev->dev, "request of irq%d failed\n", irq); + retval = -EBUSY; + return retval; + } + } + + dev_info(&pdev->dev, "phy_mem:0x%lx, iomap phy_base:0x%lx\n", + (unsigned long)usb2_phy_mem, + (unsigned long)usb2_phy_base); + + phy->dev = dev; + phy->usb2_phy_cfg = usb2_phy_base; + phy->vbus_power_pin = gpio_vbus_power_pin; + phy->usb_gpio_desc = usb_gd; + + INIT_DELAYED_WORK(&phy->work, amlogic_gxl_work); + + platform_set_drvdata(pdev, phy); + + pm_runtime_enable(phy->dev); + g_otg = phy; + + amlogic_new_otg_init(phy); + + return 0; +} + +static int amlogic_new_otg_remove(struct platform_device *pdev) +{ + return 0; +} + +#ifdef CONFIG_PM_RUNTIME + +static int amlogic_new_otg_runtime_suspend(struct device *dev) +{ + return 0; +} + +static int amlogic_new_otg_runtime_resume(struct device *dev) +{ + u32 ret = 0; + + return ret; +} + +static const struct dev_pm_ops amlogic_new_otg_pm_ops = { + SET_RUNTIME_PM_OPS(amlogic_new_otg_runtime_suspend, + amlogic_new_otg_runtime_resume, + NULL) +}; + +#define DEV_PM_OPS (&amlogic_new_otg_pm_ops) +#else +#define DEV_PM_OPS NULL +#endif + +#ifdef CONFIG_OF +static const struct of_device_id amlogic_new_otg_id_table[] = { + { .compatible = "amlogic, amlogic-new-otg" }, + {} +}; +MODULE_DEVICE_TABLE(of, amlogic_new_otg_id_table); +#endif + +static struct platform_driver amlogic_new_otg_driver = { + .probe = amlogic_new_otg_probe, + .remove = amlogic_new_otg_remove, + .driver = { + .name = "amlogic-new-otg", + .owner = THIS_MODULE, + .pm = DEV_PM_OPS, + .of_match_table = of_match_ptr(amlogic_new_otg_id_table), + }, +}; + +module_platform_driver(amlogic_new_otg_driver); + +MODULE_ALIAS("platform: amlogic_usb3_v2"); +MODULE_AUTHOR("Amlogic Inc."); +MODULE_DESCRIPTION("amlogic USB3 v2 phy driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/amlogic/usb/phy/phy-aml-new-usb-v2.c b/drivers/amlogic/usb/phy/phy-aml-new-usb-v2.c index e862717202c3..0b4e372a0a89 100644 --- a/drivers/amlogic/usb/phy/phy-aml-new-usb-v2.c +++ b/drivers/amlogic/usb/phy/phy-aml-new-usb-v2.c @@ -30,7 +30,6 @@ int amlogic_new_usbphy_reset_v2(struct amlogic_usb_v2 *phy) { static int init_count; - int i = 0; if (!init_count) { init_count++; @@ -39,8 +38,6 @@ int amlogic_new_usbphy_reset_v2(struct amlogic_usb_v2 *phy) else writel((readl(phy->reset_regs) | (0x1 << 2)), phy->reset_regs); - for (i = 0; i < 1000; i++) - udelay(500); } return 0; diff --git a/drivers/amlogic/usb/phy/phy-aml-new-usb2-v2.c b/drivers/amlogic/usb/phy/phy-aml-new-usb2-v2.c index 46a42249dd14..6aaf4f997bd8 100644 --- a/drivers/amlogic/usb/phy/phy-aml-new-usb2-v2.c +++ b/drivers/amlogic/usb/phy/phy-aml-new-usb2-v2.c @@ -27,6 +27,8 @@ #include #include #include +#include +#include #include "phy-aml-new-usb-v2.h" struct amlogic_usb_v2 *g_phy2_v2; @@ -38,6 +40,10 @@ void set_usb_phy_host_tuning(int port, int default_val) if (!g_phy2_v2) return; + + if (g_phy2_v2->phy_version) + return; + if (port > g_phy2_v2->portnum) return; if (default_val == g_phy2_v2->phy_cfg_state[port]) @@ -63,6 +69,10 @@ void set_usb_phy_device_tuning(int port, int default_val) if (!g_phy2_v2) return; + + if (g_phy2_v2->phy_version) + return; + if (port > g_phy2_v2->portnum) return; if (default_val == g_phy2_v2->phy_cfg_state[port]) @@ -82,7 +92,6 @@ void set_usb_phy_device_tuning(int port, int default_val) g_phy2_v2->phy_cfg_state[port] = default_val; } - void set_usb_pll(struct amlogic_usb_v2 *phy, void __iomem *reg) { /* TO DO set usb PLL */ @@ -93,11 +102,24 @@ void set_usb_pll(struct amlogic_usb_v2 *phy, void __iomem *reg) writel((0x10000000 | (phy->pll_setting[0])), reg + 0x40); /* PHY Tune */ - writel(phy->pll_setting[3], reg + 0x50); - writel(phy->pll_setting[4], reg + 0x10); - /* Recovery analog status */ - writel(0, reg + 0x38); - writel(phy->pll_setting[5], reg + 0x34); + if (g_phy2_v2) { + if (g_phy2_v2->phy_version == 2) { + /**g12b revB don't need set 0x10 ,0x38 and 0x34**/ + writel(phy->pll_setting[3], reg + 0x50); + writel(0x2a, reg + 0x54); + writel(0x70000, reg + 0x34); + } else { + writel(phy->pll_setting[3], reg + 0x50); + writel(phy->pll_setting[4], reg + 0x10); + writel(0, reg + 0x38); + writel(phy->pll_setting[5], reg + 0x34); + } + } else { + writel(phy->pll_setting[3], reg + 0x50); + writel(phy->pll_setting[4], reg + 0x10); + writel(0, reg + 0x38); + writel(phy->pll_setting[5], reg + 0x34); + } writel(TUNING_DISCONNECT_THRESHOLD, reg + 0xC); } @@ -111,10 +133,15 @@ static int amlogic_new_usb2_init(struct usb_phy *x) union u2p_r0_v2 reg0; union u2p_r1_v2 reg1; u32 val; + u32 temp = 0; + u32 portnum = phy->portnum; + + while (portnum--) + temp = temp | (1 << (16 + portnum)); val = readl((void __iomem *) ((unsigned long)phy->reset_regs + (0x21 * 4 - 0x8))); - writel((val | (0x3 << 16)), (void __iomem *) + writel((val | temp), (void __iomem *) ((unsigned long)phy->reset_regs + (0x21 * 4 - 0x8))); amlogic_new_usbphy_reset_v2(phy); @@ -183,16 +210,39 @@ static void amlogic_new_usb2phy_shutdown(struct usb_phy *x) { struct amlogic_usb_v2 *phy = phy_to_amlusb(x); u32 val; + u32 temp = 0; + u32 cnt = phy->portnum; + + while (cnt--) + temp = temp | (1 << (16 + cnt)); /* set usb phy to low power mode */ val = readl((void __iomem *) ((unsigned long)phy->reset_regs + (0x21 * 4 - 0x8))); - writel((val & (~(0x3 << 16))), (void __iomem *) + writel((val & (~temp)), (void __iomem *) ((unsigned long)phy->reset_regs + (0x21 * 4 - 0x8))); phy->suspend_flag = 1; } +void power_switch_to_usb(struct amlogic_usb_v2 *phy) +{ + /* Powerup usb_comb */ + power_ctrl_sleep(1, phy->u2_ctrl_sleep_shift); + power_ctrl_mempd0(1, phy->u2_hhi_mem_pd_mask, phy->u2_hhi_mem_pd_shift); + udelay(100); + + writel((readl(phy->reset_regs + (0x21 * 4 - 0x8)) & ~(0x1 << 2)), + phy->reset_regs + (0x21 * 4 - 0x8)); + + udelay(100); + power_ctrl_iso(1, phy->u2_ctrl_iso_shift); + + writel((readl(phy->reset_regs + (0x21 * 4 - 0x8)) | (0x1 << 2)), + phy->reset_regs + (0x21 * 4 - 0x8)); + udelay(100); +} + static int amlogic_new_usb2_probe(struct platform_device *pdev) { struct amlogic_usb_v2 *phy; @@ -204,10 +254,16 @@ static int amlogic_new_usb2_probe(struct platform_device *pdev) void __iomem *reset_base = NULL; void __iomem *phy_cfg_base[4]; int portnum = 0; + int phy_version = 0; const void *prop; int i = 0; int retval; u32 pll_setting[8]; + u32 pwr_ctl = 0; + u32 u2_ctrl_sleep_shift = 0; + u32 u2_hhi_mem_pd_shift = 0; + u32 u2_hhi_mem_pd_mask = 0; + u32 u2_ctrl_iso_shift = 0; prop = of_get_property(dev->of_node, "portnum", NULL); if (prop) @@ -218,6 +274,17 @@ static int amlogic_new_usb2_probe(struct platform_device *pdev) return -ENOMEM; } + prop = of_get_property(dev->of_node, "version", NULL); + if (prop) + phy_version = of_read_ulong(prop, 1); + else + phy_version = 0; + + if (is_meson_g12b_cpu()) { + if (!is_meson_rev_a()) + phy_version = 2; + } + phy_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); phy_base = devm_ioremap_resource(dev, phy_mem); if (IS_ERR(phy_base)) @@ -242,6 +309,42 @@ static int amlogic_new_usb2_probe(struct platform_device *pdev) } } + prop = of_get_property(dev->of_node, "pwr-ctl", NULL); + if (prop) + pwr_ctl = of_read_ulong(prop, 1); + else + pwr_ctl = 0; + + if (pwr_ctl) { + prop = of_get_property(dev->of_node, + "u2-ctrl-sleep-shift", NULL); + if (prop) + u2_ctrl_sleep_shift = of_read_ulong(prop, 1); + else + pwr_ctl = 0; + + prop = of_get_property(dev->of_node, + "u2-hhi-mem-pd-shift", NULL); + if (prop) + u2_hhi_mem_pd_shift = of_read_ulong(prop, 1); + else + pwr_ctl = 0; + + prop = of_get_property(dev->of_node, + "u2-hhi-mem-pd-mask", NULL); + if (prop) + u2_hhi_mem_pd_mask = of_read_ulong(prop, 1); + else + pwr_ctl = 0; + + prop = of_get_property(dev->of_node, + "u2-ctrl-iso-shift", NULL); + if (prop) + u2_ctrl_iso_shift = of_read_ulong(prop, 1); + else + pwr_ctl = 0; + } + phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL); if (!phy) return -ENOMEM; @@ -308,12 +411,22 @@ static int amlogic_new_usb2_probe(struct platform_device *pdev) phy->pll_setting[6] = pll_setting[6]; phy->pll_setting[7] = pll_setting[7]; phy->suspend_flag = 0; + phy->phy_version = phy_version; + phy->pwr_ctl = pwr_ctl; for (i = 0; i < portnum; i++) { phy->phy_cfg[i] = phy_cfg_base[i]; /* set port default tuning state */ phy->phy_cfg_state[i] = 1; } + if (pwr_ctl) { + phy->u2_ctrl_sleep_shift = u2_ctrl_sleep_shift; + phy->u2_hhi_mem_pd_shift = u2_hhi_mem_pd_shift; + phy->u2_hhi_mem_pd_mask = u2_hhi_mem_pd_mask; + phy->u2_ctrl_iso_shift = u2_ctrl_iso_shift; + power_switch_to_usb(phy); + } + usb_add_phy_dev(&phy->phy); platform_set_drvdata(pdev, phy); diff --git a/drivers/amlogic/usb/phy/phy-aml-new-usb3-v2.c b/drivers/amlogic/usb/phy/phy-aml-new-usb3-v2.c index 3f360b589a79..ef22d475f7df 100644 --- a/drivers/amlogic/usb/phy/phy-aml-new-usb3-v2.c +++ b/drivers/amlogic/usb/phy/phy-aml-new-usb3-v2.c @@ -32,6 +32,7 @@ #include #include #include +#include #include "phy-aml-new-usb-v2.h" #define HOST_MODE 0 @@ -124,6 +125,19 @@ void aml_new_usb_v2_init(void) } EXPORT_SYMBOL(aml_new_usb_v2_init); +int aml_new_usb_get_mode(void) +{ + union usb_r5_v2 r5 = {.d32 = 0}; + + r5.d32 = readl(usb_new_aml_regs_v2.usb_r_v2[5]); + if (r5.b.iddig_curr == 0) + return 0; + else + return 1; +} +EXPORT_SYMBOL(aml_new_usb_get_mode); + + static void cr_bus_addr(unsigned int addr) { union phy3_r4 phy_r4 = {.d32 = 0}; @@ -469,13 +483,39 @@ static bool device_is_available(const struct device_node *device) return false; } +static void power_switch_to_pcie(struct amlogic_usb_v2 *phy) +{ + u32 val; + + power_ctrl_sleep(1, phy->u30_ctrl_sleep_shift); + power_ctrl_mempd0(1, phy->u30_hhi_mem_pd_mask, + phy->u30_hhi_mem_pd_shift); + udelay(100); + + val = readl((void __iomem *) + ((unsigned long)phy->reset_regs + (0x20 * 4 - 0x8))); + writel((val & (~(0x1<<12))), (void __iomem *) + ((unsigned long)phy->reset_regs + (0x20 * 4 - 0x8))); + udelay(100); + + power_ctrl_iso(1, phy->u30_ctrl_iso_shift); + + val = readl((void __iomem *) + ((unsigned long)phy->reset_regs + (0x20 * 4 - 0x8))); + writel((val | (0x1<<12)), (void __iomem *) + ((unsigned long)phy->reset_regs + (0x20 * 4 - 0x8))); + udelay(100); +} + static int amlogic_new_usb3_v2_probe(struct platform_device *pdev) { struct amlogic_usb_v2 *phy; struct device *dev = &pdev->dev; struct resource *phy_mem; - void __iomem *phy_base; + struct resource *reset_mem; + void __iomem *phy_base; void __iomem *phy3_base; + void __iomem *reset_base = NULL; unsigned int phy3_mem; unsigned int phy3_mem_size = 0; void __iomem *usb2_phy_base; @@ -491,6 +531,11 @@ static int amlogic_new_usb3_v2_probe(struct platform_device *pdev) int otg = 0; int ret; struct device_node *tsi_pci; + u32 pwr_ctl = 0; + u32 u3_ctrl_sleep_shift = 0; + u32 u3_hhi_mem_pd_shift = 0; + u32 u3_hhi_mem_pd_mask = 0; + u32 u3_ctrl_iso_shift = 0; gpio_name = of_get_property(dev->of_node, "gpio-vbus-power", NULL); if (gpio_name) { @@ -541,6 +586,50 @@ static int amlogic_new_usb3_v2_probe(struct platform_device *pdev) if (!phy3_base) return -ENOMEM; + prop = of_get_property(dev->of_node, "pwr-ctl", NULL); + if (prop) + pwr_ctl = of_read_ulong(prop, 1); + else + pwr_ctl = 0; + + if (pwr_ctl) { + reset_mem = platform_get_resource(pdev, IORESOURCE_MEM, 1); + if (reset_mem) { + reset_base = ioremap(reset_mem->start, + resource_size(reset_mem)); + if (IS_ERR(reset_base)) + return PTR_ERR(reset_base); + } + + prop = of_get_property(dev->of_node, + "u3-ctrl-sleep-shift", NULL); + if (prop) + u3_ctrl_sleep_shift = of_read_ulong(prop, 1); + else + pwr_ctl = 0; + + prop = of_get_property(dev->of_node, + "u3-hhi-mem-pd-shift", NULL); + if (prop) + u3_hhi_mem_pd_shift = of_read_ulong(prop, 1); + else + pwr_ctl = 0; + + prop = of_get_property(dev->of_node, + "u3-hhi-mem-pd-mask", NULL); + if (prop) + u3_hhi_mem_pd_mask = of_read_ulong(prop, 1); + else + pwr_ctl = 0; + + prop = of_get_property(dev->of_node, + "u3-ctrl-iso-shift", NULL); + if (prop) + u3_ctrl_iso_shift = of_read_ulong(prop, 1); + else + pwr_ctl = 0; + } + retval = of_property_read_u32 (dev->of_node, "usb2-phy-reg", &usb2_phy_mem); if (retval < 0) @@ -602,9 +691,18 @@ static int amlogic_new_usb3_v2_probe(struct platform_device *pdev) phy->phy.flags = AML_USB3_PHY_DISABLE; phy->vbus_power_pin = gpio_vbus_power_pin; phy->usb_gpio_desc = usb_gd; + phy->pwr_ctl = pwr_ctl; /* set the phy from pcie to usb3 */ if (phy->portnum > 0) { + if (phy->pwr_ctl) { + phy->u30_ctrl_sleep_shift = u3_ctrl_sleep_shift; + phy->u30_hhi_mem_pd_shift = u3_hhi_mem_pd_shift; + phy->u30_hhi_mem_pd_mask = u3_hhi_mem_pd_mask; + phy->u30_ctrl_iso_shift = u3_ctrl_iso_shift; + phy->reset_regs = reset_base; + power_switch_to_pcie(phy); + } writel((readl(phy->phy3_cfg) | (3<<5)), phy->phy3_cfg); udelay(100); diff --git a/drivers/amlogic/usb/phy/phy-aml-new-usb3-v3.c b/drivers/amlogic/usb/phy/phy-aml-new-usb3-v3.c new file mode 100644 index 000000000000..86b4c9fffea5 --- /dev/null +++ b/drivers/amlogic/usb/phy/phy-aml-new-usb3-v3.c @@ -0,0 +1,918 @@ +/* + * drivers/amlogic/usb/phy/phy-aml-new-usb3-v3.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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "phy-aml-new-usb-v2.h" + +#define HOST_MODE 0 +#define DEVICE_MODE 1 + +struct usb_aml_regs_v2 usb_new_aml_regs_v3; + +static int amlogic_new_usb3_suspend(struct usb_phy *x, int suspend) +{ + return 0; +} + +static void amlogic_new_usb3phy_shutdown(struct usb_phy *x) +{ + struct amlogic_usb_v2 *phy = phy_to_amlusb(x); + + if (phy->phy.flags == AML_USB3_PHY_ENABLE) { + clk_disable_unprepare(phy->clk); + clk_disable_unprepare(phy->gate1_clk); + clk_disable_unprepare(phy->gate0_clk); + } + + phy->suspend_flag = 1; +} + +static void cr_bus_addr(struct amlogic_usb_v2 *phy_v3, unsigned int addr) +{ + union phy3_r4 phy_r4 = {.d32 = 0}; + union phy3_r5 phy_r5 = {.d32 = 0}; + unsigned long timeout_jiffies; + + phy_r4.b.phy_cr_data_in = addr; + writel(phy_r4.d32, phy_v3->phy3_cfg_r4); + + phy_r4.b.phy_cr_cap_addr = 0; + writel(phy_r4.d32, phy_v3->phy3_cfg_r4); + phy_r4.b.phy_cr_cap_addr = 1; + writel(phy_r4.d32, phy_v3->phy3_cfg_r4); + timeout_jiffies = jiffies + + msecs_to_jiffies(1000); + do { + phy_r5.d32 = readl(phy_v3->phy3_cfg_r5); + } while (phy_r5.b.phy_cr_ack == 0 && + time_is_after_jiffies(timeout_jiffies)); + + phy_r4.b.phy_cr_cap_addr = 0; + writel(phy_r4.d32, phy_v3->phy3_cfg_r4); + timeout_jiffies = jiffies + + msecs_to_jiffies(1000); + do { + phy_r5.d32 = readl(phy_v3->phy3_cfg_r5); + } while (phy_r5.b.phy_cr_ack == 1 && + time_is_after_jiffies(timeout_jiffies)); +} + +static int cr_bus_read(struct amlogic_usb_v2 *phy_v3, unsigned int addr) +{ + int data; + union phy3_r4 phy_r4 = {.d32 = 0}; + union phy3_r5 phy_r5 = {.d32 = 0}; + unsigned long timeout_jiffies; + + cr_bus_addr(phy_v3, addr); + + phy_r4.b.phy_cr_read = 0; + writel(phy_r4.d32, phy_v3->phy3_cfg_r4); + phy_r4.b.phy_cr_read = 1; + writel(phy_r4.d32, phy_v3->phy3_cfg_r4); + + timeout_jiffies = jiffies + + msecs_to_jiffies(1000); + do { + phy_r5.d32 = readl(phy_v3->phy3_cfg_r5); + } while (phy_r5.b.phy_cr_ack == 0 && + time_is_after_jiffies(timeout_jiffies)); + + data = phy_r5.b.phy_cr_data_out; + + phy_r4.b.phy_cr_read = 0; + writel(phy_r4.d32, phy_v3->phy3_cfg_r4); + timeout_jiffies = jiffies + + msecs_to_jiffies(1000); + do { + phy_r5.d32 = readl(phy_v3->phy3_cfg_r5); + } while (phy_r5.b.phy_cr_ack == 1 && + time_is_after_jiffies(timeout_jiffies)); + + return data; +} + +static void cr_bus_write(struct amlogic_usb_v2 *phy_v3, + unsigned int addr, unsigned int data) +{ + union phy3_r4 phy_r4 = {.d32 = 0}; + union phy3_r5 phy_r5 = {.d32 = 0}; + unsigned long timeout_jiffies; + + cr_bus_addr(phy_v3, addr); + + phy_r4.b.phy_cr_data_in = data; + writel(phy_r4.d32, phy_v3->phy3_cfg_r4); + + phy_r4.b.phy_cr_cap_data = 0; + writel(phy_r4.d32, phy_v3->phy3_cfg_r4); + phy_r4.b.phy_cr_cap_data = 1; + writel(phy_r4.d32, phy_v3->phy3_cfg_r4); + timeout_jiffies = jiffies + + msecs_to_jiffies(1000); + do { + phy_r5.d32 = readl(phy_v3->phy3_cfg_r5); + } while (phy_r5.b.phy_cr_ack == 0 && + time_is_after_jiffies(timeout_jiffies)); + + phy_r4.b.phy_cr_cap_data = 0; + writel(phy_r4.d32, phy_v3->phy3_cfg_r4); + timeout_jiffies = jiffies + + msecs_to_jiffies(1000); + do { + phy_r5.d32 = readl(phy_v3->phy3_cfg_r5); + } while (phy_r5.b.phy_cr_ack == 1 && + time_is_after_jiffies(timeout_jiffies)); + + phy_r4.b.phy_cr_write = 0; + writel(phy_r4.d32, phy_v3->phy3_cfg_r4); + phy_r4.b.phy_cr_write = 1; + writel(phy_r4.d32, phy_v3->phy3_cfg_r4); + timeout_jiffies = jiffies + + msecs_to_jiffies(1000); + do { + phy_r5.d32 = readl(phy_v3->phy3_cfg_r5); + } while (phy_r5.b.phy_cr_ack == 0 && + time_is_after_jiffies(timeout_jiffies)); + + phy_r4.b.phy_cr_write = 0; + writel(phy_r4.d32, phy_v3->phy3_cfg_r4); + timeout_jiffies = jiffies + + msecs_to_jiffies(1000); + do { + phy_r5.d32 = readl(phy_v3->phy3_cfg_r5); + } while (phy_r5.b.phy_cr_ack == 1 && + time_is_after_jiffies(timeout_jiffies)); +} + +static void cr_bus_addr_31(struct amlogic_usb_v2 *phy_v3, unsigned int addr) +{ + union phy3_r4 phy_r4 = {.d32 = 0}; + union phy3_r5 phy_r5 = {.d32 = 0}; + unsigned long timeout_jiffies; + + phy_r4.b.phy_cr_data_in = addr; + writel(phy_r4.d32, phy_v3->phy31_cfg_r4); + + phy_r4.b.phy_cr_cap_addr = 0; + writel(phy_r4.d32, phy_v3->phy31_cfg_r4); + phy_r4.b.phy_cr_cap_addr = 1; + writel(phy_r4.d32, phy_v3->phy31_cfg_r4); + timeout_jiffies = jiffies + + msecs_to_jiffies(1000); + do { + phy_r5.d32 = readl(phy_v3->phy31_cfg_r5); + } while (phy_r5.b.phy_cr_ack == 0 && + time_is_after_jiffies(timeout_jiffies)); + + phy_r4.b.phy_cr_cap_addr = 0; + writel(phy_r4.d32, phy_v3->phy31_cfg_r4); + timeout_jiffies = jiffies + + msecs_to_jiffies(1000); + do { + phy_r5.d32 = readl(phy_v3->phy31_cfg_r5); + } while (phy_r5.b.phy_cr_ack == 1 && + time_is_after_jiffies(timeout_jiffies)); +} + +static int cr_bus_read_31(struct amlogic_usb_v2 *phy_v3, unsigned int addr) +{ + int data; + union phy3_r4 phy_r4 = {.d32 = 0}; + union phy3_r5 phy_r5 = {.d32 = 0}; + unsigned long timeout_jiffies; + + cr_bus_addr_31(phy_v3, addr); + + phy_r4.b.phy_cr_read = 0; + writel(phy_r4.d32, phy_v3->phy31_cfg_r4); + phy_r4.b.phy_cr_read = 1; + writel(phy_r4.d32, phy_v3->phy31_cfg_r4); + + timeout_jiffies = jiffies + + msecs_to_jiffies(1000); + do { + phy_r5.d32 = readl(phy_v3->phy31_cfg_r5); + } while (phy_r5.b.phy_cr_ack == 0 && + time_is_after_jiffies(timeout_jiffies)); + + data = phy_r5.b.phy_cr_data_out; + + phy_r4.b.phy_cr_read = 0; + writel(phy_r4.d32, phy_v3->phy31_cfg_r4); + timeout_jiffies = jiffies + + msecs_to_jiffies(1000); + do { + phy_r5.d32 = readl(phy_v3->phy31_cfg_r5); + } while (phy_r5.b.phy_cr_ack == 1 && + time_is_after_jiffies(timeout_jiffies)); + + return data; +} + +static void cr_bus_write_31(struct amlogic_usb_v2 *phy_v3, + unsigned int addr, unsigned int data) +{ + union phy3_r4 phy_r4 = {.d32 = 0}; + union phy3_r5 phy_r5 = {.d32 = 0}; + unsigned long timeout_jiffies; + + cr_bus_addr(phy_v3, addr); + + phy_r4.b.phy_cr_data_in = data; + writel(phy_r4.d32, phy_v3->phy31_cfg_r4); + + phy_r4.b.phy_cr_cap_data = 0; + writel(phy_r4.d32, phy_v3->phy31_cfg_r4); + phy_r4.b.phy_cr_cap_data = 1; + writel(phy_r4.d32, phy_v3->phy31_cfg_r4); + timeout_jiffies = jiffies + + msecs_to_jiffies(1000); + do { + phy_r5.d32 = readl(phy_v3->phy31_cfg_r5); + } while (phy_r5.b.phy_cr_ack == 0 && + time_is_after_jiffies(timeout_jiffies)); + + phy_r4.b.phy_cr_cap_data = 0; + writel(phy_r4.d32, phy_v3->phy31_cfg_r4); + timeout_jiffies = jiffies + + msecs_to_jiffies(1000); + do { + phy_r5.d32 = readl(phy_v3->phy31_cfg_r5); + } while (phy_r5.b.phy_cr_ack == 1 && + time_is_after_jiffies(timeout_jiffies)); + + phy_r4.b.phy_cr_write = 0; + writel(phy_r4.d32, phy_v3->phy31_cfg_r4); + phy_r4.b.phy_cr_write = 1; + writel(phy_r4.d32, phy_v3->phy31_cfg_r4); + timeout_jiffies = jiffies + + msecs_to_jiffies(1000); + do { + phy_r5.d32 = readl(phy_v3->phy31_cfg_r5); + } while (phy_r5.b.phy_cr_ack == 0 && + time_is_after_jiffies(timeout_jiffies)); + + phy_r4.b.phy_cr_write = 0; + writel(phy_r4.d32, phy_v3->phy31_cfg_r4); + timeout_jiffies = jiffies + + msecs_to_jiffies(1000); + do { + phy_r5.d32 = readl(phy_v3->phy31_cfg_r5); + } while (phy_r5.b.phy_cr_ack == 1 && + time_is_after_jiffies(timeout_jiffies)); +} + +static void usb3_phy_cr_config_30(struct amlogic_usb_v2 *phy) +{ + u32 data = 0; + + /* + * WORKAROUND: There is SSPHY suspend bug due to + * which USB enumerates + * in HS mode instead of SS mode. Workaround it by asserting + * LANE0.TX_ALT_BLOCK.EN_ALT_BUS to enable TX to use alt bus + * mode + */ + data = cr_bus_read(phy, 0x102d); + data |= (1 << 7); + cr_bus_write(phy, 0x102D, data); + + data = cr_bus_read(phy, 0x1010); + data &= ~0xff0; + data |= 0x20; + cr_bus_write(phy, 0x1010, data); + + /* + * Fix RX Equalization setting as follows + * LANE0.RX_OVRD_IN_HI. RX_EQ_EN set to 0 + * LANE0.RX_OVRD_IN_HI.RX_EQ_EN_OVRD set to 1 + * LANE0.RX_OVRD_IN_HI.RX_EQ set to 3 + * LANE0.RX_OVRD_IN_HI.RX_EQ_OVRD set to 1 + */ + data = cr_bus_read(phy, 0x1006); + data &= ~(1 << 6); + data |= (1 << 7); + data &= ~(0x7 << 8); + data |= (0x3 << 8); + data |= (0x1 << 11); + cr_bus_write(phy, 0x1006, data); + + /* + * S et EQ and TX launch amplitudes as follows + * LANE0.TX_OVRD_DRV_LO.PREEMPH set to 22 + * LANE0.TX_OVRD_DRV_LO.AMPLITUDE set to 127 + * LANE0.TX_OVRD_DRV_LO.EN set to 1. + */ + data = cr_bus_read(phy, 0x1002); + data &= ~0x3f80; + data |= (0x16 << 7); + data &= ~0x7f; + data |= (0x7f | (1 << 14)); + cr_bus_write(phy, 0x1002, data); + + /* + * MPLL_LOOP_CTL.PROP_CNTRL + */ + data = cr_bus_read(phy, 0x30); + data &= ~(0xf << 4); + data |= (0x8 << 4); + cr_bus_write(phy, 0x30, data); + udelay(2); +} + + +static void usb3_phy_cr_config_31(struct amlogic_usb_v2 *phy) +{ + u32 data = 0; + + /* + * WORKAROUND: There is SSPHY suspend bug due to + * which USB enumerates + * in HS mode instead of SS mode. Workaround it by asserting + * LANE0.TX_ALT_BLOCK.EN_ALT_BUS to enable TX to use alt bus + * mode + */ + data = cr_bus_read_31(phy, 0x102d); + data |= (1 << 7); + cr_bus_write_31(phy, 0x102D, data); + + data = cr_bus_read_31(phy, 0x1010); + data &= ~0xff0; + data |= 0x20; + cr_bus_write_31(phy, 0x1010, data); + + /* + * Fix RX Equalization setting as follows + * LANE0.RX_OVRD_IN_HI. RX_EQ_EN set to 0 + * LANE0.RX_OVRD_IN_HI.RX_EQ_EN_OVRD set to 1 + * LANE0.RX_OVRD_IN_HI.RX_EQ set to 3 + * LANE0.RX_OVRD_IN_HI.RX_EQ_OVRD set to 1 + */ + data = cr_bus_read_31(phy, 0x1006); + data &= ~(1 << 6); + data |= (1 << 7); + data &= ~(0x7 << 8); + data |= (0x3 << 8); + data |= (0x1 << 11); + cr_bus_write_31(phy, 0x1006, data); + + /* + * S et EQ and TX launch amplitudes as follows + * LANE0.TX_OVRD_DRV_LO.PREEMPH set to 22 + * LANE0.TX_OVRD_DRV_LO.AMPLITUDE set to 127 + * LANE0.TX_OVRD_DRV_LO.EN set to 1. + */ + data = cr_bus_read_31(phy, 0x1002); + data &= ~0x3f80; + data |= (0x16 << 7); + data &= ~0x7f; + data |= (0x7f | (1 << 14)); + cr_bus_write_31(phy, 0x1002, data); + + /* + * MPLL_LOOP_CTL.PROP_CNTRL + */ + data = cr_bus_read_31(phy, 0x30); + data &= ~(0xf << 4); + data |= (0x8 << 4); + cr_bus_write_31(phy, 0x30, data); + udelay(2); +} + + +static int amlogic_new_usb3_init_v3(struct usb_phy *x) +{ + struct amlogic_usb_v2 *phy = phy_to_amlusb(x); + union usb_r1_v2 r1 = {.d32 = 0}; + union usb_r2_v2 r2 = {.d32 = 0}; + union usb_r3_v2 r3 = {.d32 = 0}; + union usb_r7_v2 r7 = {.d32 = 0}; + union phy3_r2 p3_r2 = {.d32 = 0}; + union phy3_r1 p3_r1 = {.d32 = 0}; + int i = 0; + + if (phy->suspend_flag) { + if (phy->phy.flags == AML_USB3_PHY_ENABLE) { + clk_prepare_enable(phy->gate0_clk); + clk_prepare_enable(phy->gate1_clk); + clk_prepare_enable(phy->clk); + } + phy->suspend_flag = 0; + return 0; + } + + if (phy->phy.flags != AML_USB3_PHY_ENABLE) + return 0; + + for (i = 0; i < 8; i++) { + usb_new_aml_regs_v3.usb_r_v2[i] = (void __iomem *) + ((unsigned long)phy->regs + 4*i); + } + + /* config usb30 phy */ + r3.d32 = readl(usb_new_aml_regs_v3.usb_r_v2[3]); + r3.b.p30_ssc_en = 1; + r3.b.p30_ssc_range = 2; + r3.b.p30_ref_ssp_en = 1; + writel(r3.d32, usb_new_aml_regs_v3.usb_r_v2[3]); + udelay(2); + r2.d32 = readl(usb_new_aml_regs_v3.usb_r_v2[2]); + r2.b.p30_pcs_tx_deemph_3p5db = 0x15; + r2.b.p30_pcs_tx_deemph_6db = 0x20; + writel(r2.d32, usb_new_aml_regs_v3.usb_r_v2[2]); + udelay(2); + r1.d32 = readl(usb_new_aml_regs_v3.usb_r_v2[1]); + r1.b.u3h_host_port_power_control_present = 1; + r1.b.u3h_fladj_30mhz_reg = 0x20; + r1.b.p30_pcs_tx_swing_full = 127; + r1.b.u3h_host_u3_port_disable = 0; + writel(r1.d32, usb_new_aml_regs_v3.usb_r_v2[1]); + udelay(2); + p3_r2.d32 = readl(phy->phy3_cfg_r2); + p3_r2.b.phy_tx_vboost_lvl = 0x4; + writel(p3_r2.d32, phy->phy3_cfg_r2); + udelay(2); + + usb3_phy_cr_config_30(phy); + + /* + * LOS_BIAS to 0x5 + * LOS_LEVEL to 0x9 + */ + p3_r1.d32 = readl(phy->phy3_cfg_r1); + p3_r1.b.phy_los_bias = 0x4; + p3_r1.b.phy_los_level = 0x9; + writel(p3_r1.d32, phy->phy3_cfg_r1); + + /* config usb31 phy */ + r7.d32 = readl(usb_new_aml_regs_v3.usb_r_v2[7]); + r7.b.p31_ssc_en = 1; + r7.b.p31_ssc_range = 2; + r7.b.p31_ref_ssp_en = 1; + r7.b.p31_pcs_tx_deemph_6db = 0x20; + r7.b.p31_pcs_tx_swing_full = 127; + writel(r7.d32, usb_new_aml_regs_v3.usb_r_v2[7]); + + udelay(2); + p3_r2.d32 = readl(phy->phy31_cfg_r2); + p3_r2.b.phy_tx_vboost_lvl = 0x4; + writel(p3_r2.d32, phy->phy31_cfg_r2); + udelay(2); + + usb3_phy_cr_config_31(phy); + + /* + * LOS_BIAS to 0x5 + * LOS_LEVEL to 0x9 + */ + p3_r1.d32 = readl(phy->phy31_cfg_r1); + p3_r1.b.phy_los_bias = 0x4; + p3_r1.b.phy_los_level = 0x9; + writel(p3_r1.d32, phy->phy31_cfg_r1); + + return 0; +} + +static void power_switch_to_pcie(struct amlogic_usb_v2 *phy) +{ + u32 val; + + power_ctrl_sleep(1, phy->u30_ctrl_sleep_shift); + power_ctrl_mempd0(1, phy->u30_hhi_mem_pd_mask, + phy->u30_hhi_mem_pd_shift); + udelay(100); + + val = readl((void __iomem *) + ((unsigned long)phy->reset_regs + (0x20 * 4 - 0x8))); + writel((val & (~(0x1 << phy->usb30_ctrl_rst_bit))), (void __iomem *) + ((unsigned long)phy->reset_regs + (0x20 * 4 - 0x8))); + + udelay(100); + + power_ctrl_iso(1, phy->u30_ctrl_iso_shift); + + val = readl((void __iomem *) + ((unsigned long)phy->reset_regs + (0x20 * 4 - 0x8))); + + writel((val | (0x1 << phy->usb30_ctrl_rst_bit)), (void __iomem *) + ((unsigned long)phy->reset_regs + (0x20 * 4 - 0x8))); + + udelay(100); + + power_ctrl_sleep(1, phy->u31_ctrl_sleep_shift); + power_ctrl_mempd0(1, phy->u31_hhi_mem_pd_mask, + phy->u31_hhi_mem_pd_shift); + udelay(100); + + val = readl((void __iomem *) + ((unsigned long)phy->reset_regs + (0x20 * 4 - 0x8))); + writel((val & (~(0x1 << phy->usb31_ctrl_rst_bit))), (void __iomem *) + ((unsigned long)phy->reset_regs + (0x20 * 4 - 0x8))); + + udelay(100); + + power_ctrl_iso(1, phy->u31_ctrl_iso_shift); + + val = readl((void __iomem *) + ((unsigned long)phy->reset_regs + (0x20 * 4 - 0x8))); + + writel((val | (0x1 << phy->usb31_ctrl_rst_bit)), (void __iomem *) + ((unsigned long)phy->reset_regs + (0x20 * 4 - 0x8))); + + udelay(100); +} + +static int amlogic_new_usb3_v3_probe(struct platform_device *pdev) +{ + struct amlogic_usb_v2 *phy; + struct device *dev = &pdev->dev; + struct resource *phy_mem; + void __iomem *phy_base; + void __iomem *phy3_base; + void __iomem *phy31_base; + void __iomem *reset_base = NULL; + unsigned int phy3_mem; + unsigned int phy3_mem_size = 0; + unsigned int phy31_mem; + unsigned int phy31_mem_size = 0; + unsigned int reset_mem; + unsigned int reset_mem_size = 0; + + const void *prop; + int portnum = 0; + int retval; + int ret; + u32 pwr_ctl = 0; + u32 u30_ctrl_sleep_shift = 0; + u32 u30_hhi_mem_pd_shift = 0; + u32 u30_hhi_mem_pd_mask = 0; + u32 u30_ctrl_iso_shift = 0; + u32 usb30_ctrl_rst_bit = 0; + u32 u31_ctrl_sleep_shift = 0; + u32 u31_hhi_mem_pd_shift = 0; + u32 u31_hhi_mem_pd_mask = 0; + u32 u31_ctrl_iso_shift = 0; + u32 usb31_ctrl_rst_bit = 0; + u32 portconfig_30 = 0; + u32 portconfig_31 = 0; + unsigned long rate; +#define PCIE_PLL_RATE 100000000 + + prop = of_get_property(dev->of_node, "portnum", NULL); + if (prop) + portnum = of_read_ulong(prop, 1); + + if (!portnum) + dev_err(&pdev->dev, "This phy has no usb port\n"); + + phy_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + phy_base = devm_ioremap_resource(dev, phy_mem); + if (IS_ERR(phy_base)) + return PTR_ERR(phy_base); + + retval = of_property_read_u32(dev->of_node, "phy0-reg", &phy3_mem); + if (retval < 0) + return -EINVAL; + + retval = of_property_read_u32 + (dev->of_node, "phy0-reg-size", &phy3_mem_size); + if (retval < 0) + return -EINVAL; + + phy3_base = devm_ioremap_nocache + (&(pdev->dev), (resource_size_t)phy3_mem, + (unsigned long)phy3_mem_size); + if (!phy3_base) + return -ENOMEM; + + retval = of_property_read_u32(dev->of_node, "phy1-reg", &phy31_mem); + if (retval < 0) + return -EINVAL; + + retval = of_property_read_u32 + (dev->of_node, "phy1-reg-size", + &phy31_mem_size); + if (retval < 0) + return -EINVAL; + + phy31_base = devm_ioremap_nocache + (&(pdev->dev), (resource_size_t)phy31_mem, + (unsigned long)phy31_mem_size); + if (!phy31_base) + return -ENOMEM; + + prop = of_get_property(dev->of_node, "pwr-ctl", NULL); + if (prop) + pwr_ctl = of_read_ulong(prop, 1); + else + pwr_ctl = 0; + + if (pwr_ctl) { + retval = of_property_read_u32(dev->of_node, + "reset-reg", &reset_mem); + if (retval < 0) + return -EINVAL; + + retval = of_property_read_u32 + (dev->of_node, "reset-reg-size", + &reset_mem_size); + if (retval < 0) + return -EINVAL; + + reset_base = devm_ioremap_nocache + (&(pdev->dev), (resource_size_t)reset_mem, + (unsigned long)reset_mem_size); + if (!reset_base) + return -ENOMEM; + + prop = of_get_property(dev->of_node, + "u30-ctrl-sleep-shift", NULL); + if (prop) + u30_ctrl_sleep_shift = of_read_ulong(prop, 1); + else + pwr_ctl = 0; + + prop = of_get_property(dev->of_node, + "u30-hhi-mem-pd-shift", NULL); + if (prop) + u30_hhi_mem_pd_shift = of_read_ulong(prop, 1); + else + pwr_ctl = 0; + + prop = of_get_property(dev->of_node, + "u30-hhi-mem-pd-mask", NULL); + if (prop) + u30_hhi_mem_pd_mask = of_read_ulong(prop, 1); + else + pwr_ctl = 0; + + prop = of_get_property(dev->of_node, + "u30-ctrl-iso-shift", NULL); + if (prop) + u30_ctrl_iso_shift = of_read_ulong(prop, 1); + else + pwr_ctl = 0; + + prop = of_get_property(dev->of_node, + "usb30-ctrl-a-rst-bit", NULL); + if (prop) + usb30_ctrl_rst_bit = of_read_ulong(prop, 1); + else + pwr_ctl = 0; + + prop = of_get_property(dev->of_node, + "u31-ctrl-sleep-shift", NULL); + if (prop) + u31_ctrl_sleep_shift = of_read_ulong(prop, 1); + else + pwr_ctl = 0; + + prop = of_get_property(dev->of_node, + "u31-hhi-mem-pd-shift", NULL); + if (prop) + u31_hhi_mem_pd_shift = of_read_ulong(prop, 1); + else + pwr_ctl = 0; + + prop = of_get_property(dev->of_node, + "u31-hhi-mem-pd-mask", NULL); + if (prop) + u31_hhi_mem_pd_mask = of_read_ulong(prop, 1); + else + pwr_ctl = 0; + + prop = of_get_property(dev->of_node, + "u31-ctrl-iso-shift", NULL); + if (prop) + u31_ctrl_iso_shift = of_read_ulong(prop, 1); + else + pwr_ctl = 0; + + prop = of_get_property(dev->of_node, + "usb31-ctrl-a-rst-bit", NULL); + if (prop) + usb31_ctrl_rst_bit = of_read_ulong(prop, 1); + else + pwr_ctl = 0; + } + + prop = of_get_property(dev->of_node, + "portconfig-30", NULL); + if (prop) + portconfig_30 = of_read_ulong(prop, 1); + + prop = of_get_property(dev->of_node, + "portconfig-31", NULL); + if (prop) + portconfig_31 = of_read_ulong(prop, 1); + + phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL); + if (!phy) + return -ENOMEM; + + dev_info(&pdev->dev, "USB3 phy probe:phy_mem:0x%lx, iomap phy_base:0x%lx\n", + (unsigned long)phy_mem->start, (unsigned long)phy_base); + + phy->dev = dev; + phy->regs = phy_base; + phy->phy3_cfg = phy3_base; + phy->phy3_cfg_r1 = (void __iomem *) + ((unsigned long)phy->phy3_cfg + 4 * 1); + phy->phy3_cfg_r2 = (void __iomem *) + ((unsigned long)phy->phy3_cfg + 4 * 2); + phy->phy3_cfg_r4 = (void __iomem *) + ((unsigned long)phy->phy3_cfg + 4 * 4); + phy->phy3_cfg_r5 = (void __iomem *) + ((unsigned long)phy->phy3_cfg + 4 * 5); + phy->phy31_cfg = phy31_base; + phy->phy31_cfg_r1 = (void __iomem *) + ((unsigned long)phy->phy31_cfg + 4 * 1); + phy->phy31_cfg_r2 = (void __iomem *) + ((unsigned long)phy->phy31_cfg + 4 * 2); + phy->phy31_cfg_r4 = (void __iomem *) + ((unsigned long)phy->phy31_cfg + 4 * 4); + phy->phy31_cfg_r5 = (void __iomem *) + ((unsigned long)phy->phy31_cfg + 4 * 5); + phy->portnum = portnum; + phy->suspend_flag = 0; + phy->phy.dev = phy->dev; + phy->phy.label = "amlogic-usbphy3"; + phy->phy.init = amlogic_new_usb3_init_v3; + phy->phy.set_suspend = amlogic_new_usb3_suspend; + phy->phy.shutdown = amlogic_new_usb3phy_shutdown; + phy->phy.type = USB_PHY_TYPE_USB3; + phy->phy.flags = AML_USB3_PHY_DISABLE; + phy->pwr_ctl = pwr_ctl; + + /* set the phy from pcie to usb3 */ + if (phy->portnum > 0) { + if (phy->pwr_ctl) { + phy->u30_ctrl_sleep_shift = u30_ctrl_sleep_shift; + phy->u30_hhi_mem_pd_shift = u30_hhi_mem_pd_shift; + phy->u30_hhi_mem_pd_mask = u30_hhi_mem_pd_mask; + phy->u30_ctrl_iso_shift = u30_ctrl_iso_shift; + phy->reset_regs = reset_base; + phy->usb30_ctrl_rst_bit = usb30_ctrl_rst_bit; + phy->u31_ctrl_sleep_shift = u31_ctrl_sleep_shift; + phy->u31_hhi_mem_pd_shift = u31_hhi_mem_pd_shift; + phy->u31_hhi_mem_pd_mask = u31_hhi_mem_pd_mask; + phy->u31_ctrl_iso_shift = u31_ctrl_iso_shift; + phy->usb31_ctrl_rst_bit = usb31_ctrl_rst_bit; + power_switch_to_pcie(phy); + } + + if (portconfig_30) + writel((readl(phy->phy3_cfg) | (3<<5)), phy->phy3_cfg); + udelay(100); + + if (portconfig_31) + writel((readl(phy->phy31_cfg) | (3<<5)), + phy->phy31_cfg); + udelay(100); + + phy->gate0_clk = devm_clk_get(dev, "pcie0_gate"); + if (IS_ERR(phy->gate0_clk)) { + dev_err(dev, "Failed to get usb3 bus clock\n"); + ret = PTR_ERR(phy->gate0_clk); + return ret; + } + + ret = clk_prepare_enable(phy->gate0_clk); + if (ret) { + dev_err(dev, "Failed to enable usb3 bus clock\n"); + ret = PTR_ERR(phy->gate0_clk); + return ret; + } + + phy->gate1_clk = devm_clk_get(dev, "pcie1_gate"); + if (IS_ERR(phy->gate1_clk)) { + dev_err(dev, "Failed to get usb3 bus clock\n"); + ret = PTR_ERR(phy->gate1_clk); + return ret; + } + + ret = clk_prepare_enable(phy->gate1_clk); + if (ret) { + dev_err(dev, "Failed to enable usb3 bus clock\n"); + ret = PTR_ERR(phy->gate1_clk); + return ret; + } + + phy->clk = devm_clk_get(dev, "pcie_refpll"); + if (IS_ERR(phy->clk)) { + dev_err(dev, "Failed to get usb3 bus clock\n"); + ret = PTR_ERR(phy->clk); + return ret; + } + + ret = clk_prepare_enable(phy->clk); + if (ret) { + dev_err(dev, "Failed to enable usb3 bus clock\n"); + ret = PTR_ERR(phy->clk); + return ret; + } + + rate = clk_get_rate(phy->clk); + if (rate != PCIE_PLL_RATE) + dev_err(dev, "pcie_refpll is not 100M, it is %ld\n", + rate); + + phy->phy.flags = AML_USB3_PHY_ENABLE; + } + + usb_add_phy_dev(&phy->phy); + + platform_set_drvdata(pdev, phy); + + pm_runtime_enable(phy->dev); + + return 0; +} + +static int amlogic_new_usb3_v3_remove(struct platform_device *pdev) +{ + return 0; +} + +#ifdef CONFIG_PM_RUNTIME + +static int amlogic_new_usb3_v3_runtime_suspend(struct device *dev) +{ + return 0; +} + +static int amlogic_new_usb3_v3_runtime_resume(struct device *dev) +{ + u32 ret = 0; + + return ret; +} + +static const struct dev_pm_ops amlogic_new_usb3_pm_ops = { + SET_RUNTIME_PM_OPS(amlogic_new_usb3_v3_runtime_suspend, + amlogic_new_usb3_v3_runtime_resume, + NULL) +}; + +#define DEV_PM_OPS (&amlogic_new_usb3_pm_ops) +#else +#define DEV_PM_OPS NULL +#endif + +#ifdef CONFIG_OF +static const struct of_device_id amlogic_new_usb3_v3_id_table[] = { + { .compatible = "amlogic, amlogic-new-usb3-v3" }, + {} +}; +MODULE_DEVICE_TABLE(of, amlogic_new_usb3_v3_id_table); +#endif + +static struct platform_driver amlogic_new_usb3_v3_driver = { + .probe = amlogic_new_usb3_v3_probe, + .remove = amlogic_new_usb3_v3_remove, + .driver = { + .name = "amlogic-new-usb3-v3", + .owner = THIS_MODULE, + .pm = DEV_PM_OPS, + .of_match_table = of_match_ptr(amlogic_new_usb3_v3_id_table), + }, +}; + +module_platform_driver(amlogic_new_usb3_v3_driver); + +MODULE_ALIAS("platform: amlogic_usb3_v2"); +MODULE_AUTHOR("Amlogic Inc."); +MODULE_DESCRIPTION("amlogic USB3 v2 phy driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/amlogic/vrtc/aml_vrtc.c b/drivers/amlogic/vrtc/aml_vrtc.c index 1f102f36fbcd..2c79f35813e0 100644 --- a/drivers/amlogic/vrtc/aml_vrtc.c +++ b/drivers/amlogic/vrtc/aml_vrtc.c @@ -25,10 +25,55 @@ #include #include #include +#include +#include +#include static void __iomem *alarm_reg_vaddr; static void __iomem *timere_low_vaddr, *timere_high_vaddr; static unsigned int vrtc_init_date; +static int wakeup; +static int wakeup_time; +static struct input_dev *vinput_dev; + +static void send_power_btn_wakeup(void) +{ + if ((get_resume_method() == RTC_WAKEUP) || + (get_resume_method() == AUTO_WAKEUP)) { + input_event(vinput_dev, EV_KEY, KEY_POWER, 1); + input_sync(vinput_dev); + input_event(vinput_dev, EV_KEY, KEY_POWER, 0); + input_sync(vinput_dev); + } +} + +static int vinput_dev_init(struct platform_device *pdev) +{ + int r; + + vinput_dev = input_allocate_device(); + if (!vinput_dev) + return -ENOMEM; + + vinput_dev->name = "aml_vkeypad"; + vinput_dev->phys = "keypad/input0"; + vinput_dev->id.vendor = 0x0001; + vinput_dev->id.product = 0x0001; + vinput_dev->id.version = 0x0100; + set_bit(EV_KEY, vinput_dev->evbit); + set_bit(KEY_POWER, vinput_dev->keybit); + + vinput_dev->dev.parent = &pdev->dev; + device_init_wakeup(&vinput_dev->dev, 1); + + r = input_register_device(vinput_dev); + if (r) { + pr_err("failed to register power button: %d\n", r); + input_free_device(vinput_dev); + } + + return r; +} #define TIME_LEN 10 static int parse_init_date(const char *date) @@ -204,6 +249,11 @@ static int aml_vrtc_probe(struct platform_device *pdev) return -1; platform_set_drvdata(pdev, vrtc); + vinput_dev_init(pdev); + + debugfs_create_u32("wakeup", 0644, NULL, &wakeup); + debugfs_create_u32("wakeup_time", 0644, NULL, &wakeup_time); + return 0; } @@ -211,6 +261,8 @@ static int aml_vrtc_remove(struct platform_device *dev) { struct rtc_device *vrtc = platform_get_drvdata(dev); + input_unregister_device(vinput_dev); + rtc_device_unregister(vrtc); return 0; @@ -227,6 +279,11 @@ static int aml_vrtc_resume(struct platform_device *pdev) if (!scpi_get_vrtc(&vrtc_init_date)) pr_debug("get vrtc: %us\n", vrtc_init_date); + if (wakeup > 0) { + pr_info("aml_vrtc_suspend wakeup=%d\n", wakeup); + send_power_btn_wakeup(); + } + return 0; } @@ -234,6 +291,11 @@ static int aml_vrtc_suspend(struct platform_device *pdev, pm_message_t state) { u32 vrtc_val; + if (wakeup_time > 0) { + pr_info("aml_vrtc_suspend wakeup_time=%d\n", wakeup_time); + set_wakeup_time(wakeup_time); + } + vrtc_val = read_te(); if (scpi_set_vrtc(vrtc_val)) diff --git a/drivers/amlogic/watchdog/meson_wdt.c b/drivers/amlogic/watchdog/meson_wdt.c index 4da2517889a2..bb48362118d2 100644 --- a/drivers/amlogic/watchdog/meson_wdt.c +++ b/drivers/amlogic/watchdog/meson_wdt.c @@ -54,6 +54,7 @@ struct aml_wdt_dev { void __iomem *reg_base; struct notifier_block pm_notifier; struct notifier_block reboot_notifier; + bool is_running; /* 1:enable 0:disable */ }; static void aml_update_bits(void __iomem *reg, unsigned int mask, @@ -108,7 +109,9 @@ static int aml_wdt_start(struct watchdog_device *wdog) if (wdev->boot_queue) cancel_delayed_work(&wdev->boot_queue); #endif + wdev->is_running = true; dev_info(wdev->dev, "start watchdog\n"); + return 0; } @@ -119,6 +122,7 @@ static int aml_wdt_stop(struct watchdog_device *wdog) mutex_lock(&wdev->lock); disable_watchdog(wdev); mutex_unlock(&wdev->lock); + wdev->is_running = false; dev_info(wdev->dev, "stop watchdog\n"); return 0; @@ -153,12 +157,14 @@ static int aml_wdt_set_timeout(struct watchdog_device *wdog, unsigned int aml_wdt_get_timeleft(struct watchdog_device *wdog) { struct aml_wdt_dev *wdev = watchdog_get_drvdata(wdog); - unsigned int timeleft; + unsigned long timeleft, tick; mutex_lock(&wdev->lock); timeleft = read_watchdog_tcnt(wdev); + tick = readl(wdev->reg_base + TCNT) & 0xffff; mutex_unlock(&wdev->lock); - return timeleft/wdev->one_second; + + return (tick - timeleft)/wdev->one_second; } static void boot_moniter_work(struct work_struct *work) @@ -255,14 +261,18 @@ static int aml_wtd_pm_notify(struct notifier_block *nb, unsigned long event, wdev = container_of(nb, struct aml_wdt_dev, pm_notifier); if (event == PM_SUSPEND_PREPARE) { - disable_watchdog(wdev); - dev_info(wdev->dev, - "pm_notify: disable watchdog, event = %lu\n", event); + if (wdev->is_running) { + disable_watchdog(wdev); + dev_info(wdev->dev, + "pm_notify: disable watchdog, event = %lu\n", event); + } } if (event == PM_POST_SUSPEND) { - enable_watchdog(wdev); - dev_info(wdev->dev, - "pm_notify: enable watchdog, event = %lu\n", event); + if (wdev->is_running) { + enable_watchdog(wdev); + dev_info(wdev->dev, + "pm_notify: enable watchdog, event = %lu\n", event); + } } return NOTIFY_OK; } @@ -338,14 +348,13 @@ static int aml_wdt_probe(struct platform_device *pdev) watchdog_set_drvdata(aml_wdt, wdev); platform_set_drvdata(pdev, aml_wdt); + wdev->is_running = false; if (wdev->reset_watchdog_method == 1) { INIT_DELAYED_WORK(&wdev->boot_queue, boot_moniter_work); mod_delayed_work(system_freezable_wq, &wdev->boot_queue, round_jiffies(msecs_to_jiffies(wdev->reset_watchdog_time*1000))); - enable_watchdog(wdev); - set_watchdog_cnt(wdev, - wdev->default_timeout * wdev->one_second); + aml_wdt_start(aml_wdt); dev_info(wdev->dev, "creat work queue for watch dog\n"); } ret = watchdog_register_device(aml_wdt); diff --git a/drivers/amlogic/wifi/dhd_static_buf.c b/drivers/amlogic/wifi/dhd_static_buf.c index 27480d43f2d2..5ab937ee10cc 100644 --- a/drivers/amlogic/wifi/dhd_static_buf.c +++ b/drivers/amlogic/wifi/dhd_static_buf.c @@ -73,9 +73,9 @@ enum dhd_prealloc_index { #define DHD_PREALLOC_OSL_BUF_SIZE (STATIC_BUF_MAX_NUM * STATIC_BUF_SIZE) #define DHD_PREALLOC_WIPHY_ESCAN0_SIZE (64 * 1024) #define DHD_PREALLOC_DHD_INFO_SIZE (32 * 1024) -#define DHD_PREALLOC_MEMDUMP_RAM_SIZE (898 * 1024) +#define DHD_PREALLOC_MEMDUMP_RAM_SIZE (1280 * 1024) #define DHD_PREALLOC_DHD_WLFC_HANGER_SIZE (73 * 1024) -#define DHD_PREALLOC_WL_ESCAN_INFO_SIZE (66 * 1024) +#define DHD_PREALLOC_WL_ESCAN_INFO_SIZE (67 * 1024) #ifdef CONFIG_64BIT #define DHD_PREALLOC_IF_FLOW_LKUP_SIZE (20 * 1024 * 2) #else @@ -92,7 +92,7 @@ enum dhd_prealloc_index { #define WLAN_DHD_IF_FLOW_LKUP_SIZE (64 * 1024) #else #define WLAN_DHD_INFO_BUF_SIZE (16 * 1024) -#define WLAN_DHD_WLFC_BUF_SIZE (24 * 1024) +#define WLAN_DHD_WLFC_BUF_SIZE (29 * 1024) #define WLAN_DHD_IF_FLOW_LKUP_SIZE (20 * 1024) #endif /* CONFIG_64BIT */ #define WLAN_DHD_MEMDUMP_SIZE (800 * 1024) diff --git a/drivers/amlogic/wifi/wifi_dt.c b/drivers/amlogic/wifi/wifi_dt.c index 8a3219bb6e75..4601edb798a1 100644 --- a/drivers/amlogic/wifi/wifi_dt.c +++ b/drivers/amlogic/wifi/wifi_dt.c @@ -236,7 +236,7 @@ void set_usb_wifi_power(int is_power) { usb_power_control(is_power, WIFI_BIT); } - +EXPORT_SYMBOL(set_usb_wifi_power); static int wifi_power_open(struct inode *inode, struct file *file) { struct cdev *cdevp = inode->i_cdev; diff --git a/drivers/android/binder_alloc.c b/drivers/android/binder_alloc.c index bec6c0a90429..dfb9a24f030c 100644 --- a/drivers/android/binder_alloc.c +++ b/drivers/android/binder_alloc.c @@ -185,6 +185,152 @@ struct binder_buffer *binder_alloc_prepare_to_free(struct binder_alloc *alloc, return buffer; } +#ifdef CONFIG_AMLOGIC_BINDER_VMALLOC +static unsigned long check_range(struct binder_alloc *alloc, void *end) +{ + unsigned long size; + + size = (unsigned long)end - (unsigned long)alloc->buffer; + if (size > PAGE_SIZE && size > alloc->mapped_size) { + pr_debug("%s, %d, base:%p, end:%p, size:%ld, task:%d %s\n", + __func__, __LINE__, alloc->buffer, end, size, + current->pid, current->comm); + return size; + } + return 0; +} + +static int move_vma_mapping(void *old, void *new_addr, unsigned long size) +{ + struct page *page, *pages[2] = {}; + unsigned long addr, end, new, moved = 0; + int ret; + + addr = (unsigned long)old; + end = (unsigned long)old + size; + new = (unsigned long)new_addr; + for (; addr < end; addr += PAGE_SIZE) { + page = vmalloc_to_page((void *)addr); + if (!page) { + new += PAGE_SIZE; + continue; + } + /* Make sure cache same for other address */ + cpu_ca8_dcache_clean_area((void *)addr, PAGE_SIZE); + pages[0] = page; + ret = map_kernel_range_noflush(new, PAGE_SIZE, + PAGE_KERNEL, pages); + pr_debug("%s, addr:%lx->%lx, old:%p, new:%p, page:%lx %p %p\n", + __func__, addr, new, old, new_addr, + page_to_pfn(page), pages[0], pages[1]); + flush_cache_vmap(addr, addr + PAGE_SIZE); + new += PAGE_SIZE; + moved++; + if (ret < 0) + return ret; + } + return moved; +} + +static void free_back_buffer(struct binder_alloc *alloc) +{ + int i; + void *p; + + for (i = 0; i < MAX_BUFFER; i++) { + p = alloc->back_buffer[i]; + if (p && p != alloc->buffer) { + vfree(p); + pr_debug("free alloc %p, buffer:%p@%d\n", alloc, p, i); + } + } +} + +static unsigned long get_new_size(unsigned long curr_size, + unsigned long max_size, int next_step) +{ + int order, step; + long next_size; + + order = get_order(max_size); + step = (order + MAX_BUFFER / 2) / MAX_BUFFER; + next_step += 1; + next_size = (1 << (next_step * step + PAGE_SHIFT)); + if (next_size <= curr_size) + return curr_size + PAGE_SIZE * 4; + return next_size; +} + +static int try_to_replace_vmap(struct binder_alloc *alloc, + unsigned long new_sz, + void **start, void **endp) +{ + unsigned long max_size, diff, size; + unsigned long *old_buffer; + struct binder_buffer *buffer; + struct vm_struct *area; + int ret, i; + + for (i = 0; i < MAX_BUFFER; i++) { + if (!alloc->back_buffer[i]) + break; + } + + if (i == MAX_BUFFER) { + pr_info("max buffer:%d, new_sz:%lx, buffer:%p %p %p %p\n", + i, new_sz, alloc->back_buffer[0], + alloc->back_buffer[1], alloc->back_buffer[2], + alloc->back_buffer[3]); + dump_stack(); + return -ENOMEM; + } + + max_size = alloc->vma->vm_end - alloc->vma->vm_start; + size = get_new_size(new_sz, max_size, i); + if (size >= max_size) + size = max_size; + area = get_vm_area(size, VM_ALLOC | VM_NO_GUARD); + if (area == NULL) { + pr_err("%s, get vmalloc size:%lx failed\n", __func__, size); + return -ENOMEM; + } + + ret = move_vma_mapping(alloc->buffer, area->addr, alloc->mapped_size); + pr_debug("%s, move %p:%p, ret:%d, vm size:%x:%lx, want:%lx, alloc:%p\n", + __func__, alloc->buffer, area->addr, + ret, alloc->mapped_size, size, new_sz, alloc); + if (ret < 0) { + free_vm_area(area); + return -ENOMEM; + } + + old_buffer = alloc->buffer; + alloc->buffer = area->addr; + diff = (unsigned long)old_buffer - + (unsigned long)alloc->buffer; + pr_debug("old:%p, new:%p, size:%ld, mapped:%d, alloc:%p\n", + old_buffer, alloc->buffer, size, alloc->mapped_size, alloc); + alloc->user_buffer_offset = alloc->vma->vm_start - + (uintptr_t)alloc->buffer; + list_for_each_entry(buffer, &alloc->buffers, entry) { + void *tmp; + + tmp = buffer->data; + buffer->data = buffer->data - diff; + pr_debug("replace:%p, new:%p, diff:%lx\n", + tmp, buffer->data, diff); + } + *start = *start - diff; + *endp = *endp - diff; + alloc->mapped_size = size; + alloc->back_buffer[i] = area->addr; + pr_debug("replace %i, alloc:%p, size:%lx:%lx, start:%p, end:%p\n", + i, alloc, new_sz, size, *start, *endp); + + return 0; +} +#endif + static int binder_update_page_range(struct binder_alloc *alloc, int allocate, void *start, void *end) { @@ -194,6 +340,9 @@ static int binder_update_page_range(struct binder_alloc *alloc, int allocate, struct vm_area_struct *vma = NULL; struct mm_struct *mm = NULL; bool need_mm = false; +#ifdef CONFIG_AMLOGIC_BINDER_VMALLOC + unsigned long map_size; +#endif binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC, "%d: %s pages %pK-%pK\n", alloc->pid, @@ -229,6 +378,14 @@ static int binder_update_page_range(struct binder_alloc *alloc, int allocate, goto err_no_vma; } +#ifdef CONFIG_AMLOGIC_BINDER_VMALLOC + /* try to replace vmalloc */ + map_size = check_range(alloc, end); + if (map_size) { + if (try_to_replace_vmap(alloc, map_size, &start, &end)) + return -ENOMEM; + } +#endif for (page_addr = start; page_addr < end; page_addr += PAGE_SIZE) { int ret; bool on_lru; @@ -670,13 +827,20 @@ int binder_alloc_mmap_handler(struct binder_alloc *alloc, goto err_already_mapped; } +#ifdef CONFIG_AMLOGIC_BINDER_VMALLOC + area = get_vm_area(PAGE_SIZE, VM_ALLOC | VM_NO_GUARD); +#else area = get_vm_area(vma->vm_end - vma->vm_start, VM_ALLOC); +#endif if (area == NULL) { ret = -ENOMEM; failure_string = "get_vm_area"; goto err_get_vm_area_failed; } alloc->buffer = area->addr; +#ifdef CONFIG_AMLOGIC_BINDER_VMALLOC + alloc->first_addr = area->addr; +#endif alloc->user_buffer_offset = vma->vm_start - (uintptr_t)alloc->buffer; mutex_unlock(&binder_alloc_mmap_lock); @@ -701,6 +865,9 @@ int binder_alloc_mmap_handler(struct binder_alloc *alloc, goto err_alloc_pages_failed; } alloc->buffer_size = vma->vm_end - vma->vm_start; +#ifdef CONFIG_AMLOGIC_BINDER_VMALLOC + alloc->mapped_size = PAGE_SIZE; +#endif buffer = kzalloc(sizeof(*buffer), GFP_KERNEL); if (!buffer) { @@ -792,6 +959,11 @@ void binder_alloc_deferred_release(struct binder_alloc *alloc) } kfree(alloc->pages); vfree(alloc->buffer); + #ifdef CONFIG_AMLOGIC_BINDER_VMALLOC + free_back_buffer(alloc); + if (alloc->first_addr && alloc->first_addr != alloc->buffer) + vfree(alloc->first_addr); + #endif } mutex_unlock(&alloc->mutex); if (alloc->vma_vm_mm) diff --git a/drivers/android/binder_alloc.h b/drivers/android/binder_alloc.h index 9ef64e563856..2bda6b16584f 100644 --- a/drivers/android/binder_alloc.h +++ b/drivers/android/binder_alloc.h @@ -99,11 +99,22 @@ struct binder_lru_page { * calls. The address space is used for both user-visible buffers and for * struct binder_buffer objects used to track the user buffers */ +#if defined(CONFIG_AMLOGIC_MODIFY) && defined(CONFIG_ARM) +#define CONFIG_AMLOGIC_BINDER_VMALLOC +#define MAX_BUFFER 4 +extern void cpu_ca8_dcache_clean_area(void *addr, int size); +#endif + struct binder_alloc { struct mutex mutex; struct vm_area_struct *vma; struct mm_struct *vma_vm_mm; void *buffer; +#ifdef CONFIG_AMLOGIC_BINDER_VMALLOC + size_t mapped_size; + void *back_buffer[MAX_BUFFER]; + void *first_addr; +#endif /* CONFIG_AMLOGIC_BINDER_VMALLOC */ ptrdiff_t user_buffer_offset; struct list_head buffers; struct rb_root free_buffers; diff --git a/drivers/base/power/opp/of.c b/drivers/base/power/opp/of.c index 69379443e5eb..e13a3037effb 100644 --- a/drivers/base/power/opp/of.c +++ b/drivers/base/power/opp/of.c @@ -471,6 +471,59 @@ int dev_pm_opp_of_add_table(struct device *dev) } EXPORT_SYMBOL_GPL(dev_pm_opp_of_add_table); +#ifdef CONFIG_AMLOGIC_MODIFY +/** + * dev_pm_opp_of_add_table_indexed() - Initialize indexed opp + *table from device tree + * @dev: device pointer used to lookup OPP table. + * @index: Index number. + * + * Register the initial OPP table with the OPP library for given device only + * using the "operating-points-v2" property. + * + * Return: + * 0 On success OR + * Duplicate OPPs (both freq and volt are same) and opp->available + * -EEXIST Freq are same and volt are different OR + * Duplicate OPPs (both freq and volt are same) and !opp->available + * -ENOMEM Memory allocation failure + * -ENODEV when 'operating-points' property is not found or is invalid data + * in device node. + * -ENODATA when empty 'operating-points' property is found + * -EINVAL when invalid entries are found in opp-v2 table + */ +int dev_pm_opp_of_add_table_indexed(struct device *dev, int index) +{ + struct device_node *opp_np; + int ret, count; + +again: + opp_np = of_parse_phandle(dev->of_node, "operating-points-v2", index); + if (!opp_np) { + /* + * If only one phandle is present, then the same OPP table + * applies for all index requests. + */ + count = of_count_phandle_with_args(dev->of_node, + "operating-points-v2", NULL); + if (count <= index) { + pr_err("%s,count %d must smaller than index %d!\n", + __func__, count, index); + index = 0; + goto again; + } + + return -ENODEV; + } + + ret = _of_add_opp_table_v2(dev, opp_np); + of_node_put(opp_np); + + return ret; +} +EXPORT_SYMBOL_GPL(dev_pm_opp_of_add_table_indexed); +#endif + /* CPU device specific helpers */ /** @@ -534,6 +587,51 @@ int dev_pm_opp_of_cpumask_add_table(const struct cpumask *cpumask) } EXPORT_SYMBOL_GPL(dev_pm_opp_of_cpumask_add_table); +#ifdef CONFIG_AMLOGIC_MODIFY +/** + * dev_pm_opp_of_cpumask_add_table_index() - Adds OPP table for @cpumask + * @cpumask: cpumask for which OPP table needs to be added. + * + * This adds the OPP tables for CPUs present in the @cpumask. + * + * Locking: The internal opp_table and opp structures are RCU protected. + * Hence this function internally uses RCU updater strategy with mutex locks + * to keep the integrity of the internal data structures. Callers should ensure + * that this function is *NOT* called under RCU protection or in contexts where + * mutex cannot be locked. + */ +int dev_pm_opp_of_cpumask_add_table_indexed(const struct cpumask *cpumask, + int index) +{ + struct device *cpu_dev; + int cpu, ret = 0; + + WARN_ON(cpumask_empty(cpumask)); + + for_each_cpu(cpu, cpumask) { + cpu_dev = get_cpu_device(cpu); + if (!cpu_dev) { + pr_err("%s: failed to get cpu%d device\n", __func__, + cpu); + continue; + } + + ret = dev_pm_opp_of_add_table_indexed(cpu_dev, index); + if (ret) { + pr_err("%s: couldn't find opp table for cpu:%d, %d\n", + __func__, cpu, ret); + + /* Free all other OPPs */ + dev_pm_opp_of_cpumask_remove_table(cpumask); + break; + } + } + + return ret; +} +EXPORT_SYMBOL_GPL(dev_pm_opp_of_cpumask_add_table_indexed); +#endif + /* * Works only for OPP v2 bindings. * diff --git a/drivers/input/input-polldev.c b/drivers/input/input-polldev.c index 3664f81655ca..3dad3a24f115 100644 --- a/drivers/input/input-polldev.c +++ b/drivers/input/input-polldev.c @@ -30,7 +30,7 @@ static void input_polldev_queue_work(struct input_polled_dev *dev) if (delay >= HZ) delay = round_jiffies_relative(delay); - queue_delayed_work(system_freezable_wq, &dev->work, delay); + queue_delayed_work(system_wq, &dev->work, delay); } static void input_polled_device_work(struct work_struct *work) diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c index d6c404b3584d..43efc7ee675a 100644 --- a/drivers/irqchip/irq-gic.c +++ b/drivers/irqchip/irq-gic.c @@ -20,6 +20,7 @@ * As such, the enable set/clear, pending set/clear and active bit * registers are banked per-cpu for these sources. */ +#define SKIP_IO_TRACE #include #include #include diff --git a/drivers/media/dvb-core/dvb_frontend.c b/drivers/media/dvb-core/dvb_frontend.c index e42024d68152..9869e16c5d5a 100644 --- a/drivers/media/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb-core/dvb_frontend.c @@ -1554,7 +1554,8 @@ static bool is_dvbv3_delsys(u32 delsys) #ifdef CONFIG_AMLOGIC_MODIFY /* added by Amlogic 20180720 */ status = (delsys == SYS_DVBT) || (delsys == SYS_DVBC_ANNEX_A) || (delsys == SYS_DVBS) || (delsys == SYS_ATSC) || - (delsys == SYS_DTMB); + (delsys == SYS_DTMB) || (delsys == SYS_DVBS2) || + (delsys == SYS_DVBT2); #else status = (delsys == SYS_DVBT) || (delsys == SYS_DVBC_ANNEX_A) || (delsys == SYS_DVBS) || (delsys == SYS_ATSC); diff --git a/drivers/media/rc/Kconfig b/drivers/media/rc/Kconfig index 656fd3acf811..b7c9521ea632 100644 --- a/drivers/media/rc/Kconfig +++ b/drivers/media/rc/Kconfig @@ -12,6 +12,15 @@ menuconfig RC_DECODERS default y if RC_DECODERS +config IR_IRMP_DECODER + tristate "Enable IR raw decoder for IRMP" + depends on RC_CORE + default y + + ---help--- + Enable this option if to include the software + IR decoder IRMP. + config LIRC tristate "LIRC interface driver" depends on RC_CORE diff --git a/drivers/media/rc/Makefile b/drivers/media/rc/Makefile index a1400341093b..aba4d780e25c 100644 --- a/drivers/media/rc/Makefile +++ b/drivers/media/rc/Makefile @@ -3,6 +3,7 @@ rc-core-objs := rc-main.o rc-ir-raw.o obj-y += keymaps/ obj-$(CONFIG_RC_CORE) += rc-core.o +obj-$(CONFIG_IR_IRMP_DECODER) += ir-irmp-decoder.o obj-$(CONFIG_LIRC) += lirc_dev.o obj-$(CONFIG_IR_NEC_DECODER) += ir-nec-decoder.o obj-$(CONFIG_IR_RC5_DECODER) += ir-rc5-decoder.o diff --git a/drivers/media/rc/ir-irmp-decoder.c b/drivers/media/rc/ir-irmp-decoder.c new file mode 100644 index 000000000000..111d89ff843b --- /dev/null +++ b/drivers/media/rc/ir-irmp-decoder.c @@ -0,0 +1,147 @@ +/* ir-irmp-decoder.c - handle IR Pulse/Space by IRMP multiprotocol decoder + * + * Copyright (C) 2018 by Team CoreELEC + * + * 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 version 2 of the License. + * + * 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 +#include +#include "rc-core-priv.h" +#define IRMP_PULSE_IR_DECODER +#define U_BOOT_COMPATIBLE +#define IRMP_PROTOCOL_NAMES 1 +#ifdef unix +#undef unix +#endif +#include "irmp/irmp.h" +#include "irmp/irmp.c" + +/** + * ir_irmp_decode() - Decode one IRMP pulse or space + * @dev: the struct rc_dev descriptor of the device + * @duration: the struct ir_raw_event descriptor of the pulse/space + * + * This function returns -EINVAL if the pulse violates the state machine + */ +static int ir_irmp_decode(struct rc_dev *dev, struct ir_raw_event ev) +{ + u32 scancode; + IRMP_DATA irmp_data; + unsigned int pulse = TO_US(ev.duration); + u8 protocol = 0xFF; + + if (!is_timing_event(ev)) { + if (ev.reset) + pulse = 0; + } + + pulse = pulse > IRMP_TIMEOUT_TIME_MS ? 0 : pulse; + + IR_dprintk(2, "IRMP decode %uus (%uus): %s\n", + pulse, TO_US(ev.duration), TO_STR(ev.pulse)); + + // ready with decode + if (irmp_ISR(pulse ? ((pulse * 15) / 1000) : 0)) { + if (irmp_get_data(&irmp_data)) { + IR_dprintk(1, "IRMP decoded by protocol %s, command %04x, address %04x", + irmp_protocol_names[irmp_data.protocol], irmp_data.command, irmp_data.address); + + switch (irmp_data.protocol) { + case IRMP_NEC_PROTOCOL: + case IRMP_SAMSUNG_PROTOCOL: + case IRMP_SAMSUNG32_PROTOCOL: + protocol = 0x0; + break; + case IRMP_RC5_PROTOCOL: + protocol = 0x4; + break; + case IRMP_RC6_PROTOCOL: + protocol = 0xb; + break; + case IRMP_RC6A_PROTOCOL: + protocol = 0x5; + break; + } + // transfer decoded protocol + if (protocol != 0xFF) + scancode = 0xA0A0A000 | protocol; + else + scancode = 0xB0B0B000 | irmp_data.protocol; + + // transfer decoded ir protocol + rc_keydown(dev, RC_TYPE_IRMP, scancode, 0); + + switch (irmp_data.protocol) { + case IRMP_RC5_PROTOCOL: + scancode = 0x3000 | (((unsigned int)(irmp_data.address) & 0x7F) << 6) | (irmp_data.command & 0x3F); + break; + case IRMP_RC6_PROTOCOL: + scancode = (((unsigned int)(irmp_data.address) & 0x1FFF) << 8) | irmp_data.command; + break; + case IRMP_RC6A_PROTOCOL: + scancode = ((unsigned int)(irmp_data.address) << 16) | irmp_data.command; + break; + default: + scancode = ((unsigned int)(irmp_data.command) << 16) | irmp_data.address; + break; + } + + // transfer decoded command/address + rc_keydown(dev, RC_TYPE_IRMP, scancode, 0); + + switch (irmp_data.protocol) { + case IRMP_RC5_PROTOCOL: + scancode = 0x37FF; + break; + case IRMP_RC6_PROTOCOL: + scancode = 0x1EFFFF; + break; + case IRMP_RC6A_PROTOCOL: + scancode = 0xFFFF7FFF; + break; + default: + scancode = 0xFFFFFFFF; + break; + } + + // transfer decoding mask + rc_keydown(dev, RC_TYPE_IRMP, scancode, 0); + } + } + + return 0; +} + +static struct ir_raw_handler irmp_handler = { + .protocols = RC_BIT_IRMP, + .decode = ir_irmp_decode, +}; + +static int __init ir_irmp_decode_init(void) +{ + ir_raw_handler_register(&irmp_handler); + + printk(KERN_INFO "IR IRMP decoder handler initialized\n"); + return 0; +} + +static void __exit ir_irmp_decode_exit(void) +{ + ir_raw_handler_unregister(&irmp_handler); +} + +module_init(ir_irmp_decode_init); +module_exit(ir_irmp_decode_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Hugo Portisch"); +MODULE_AUTHOR("Team CoreELEC"); +MODULE_DESCRIPTION("IRMP IR protocol decoder"); diff --git a/drivers/media/rc/irmp/irmp.c b/drivers/media/rc/irmp/irmp.c new file mode 100644 index 000000000000..91ec7e6d89f9 --- /dev/null +++ b/drivers/media/rc/irmp/irmp.c @@ -0,0 +1,6087 @@ +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * irmp.c - infrared multi-protocol decoder, supports several remote control protocols + * + * Copyright (c) 2009-2018 Frank Meyer - frank(at)fli4l.de + * + * Supported AVR mikrocontrollers: + * + * ATtiny87, ATtiny167 + * ATtiny45, ATtiny85 + * ATtiny44, ATtiny84 + * ATmega8, ATmega16, ATmega32 + * ATmega162 + * ATmega164, ATmega324, ATmega644, ATmega644P, ATmega1284, ATmega1284P + * ATmega88, ATmega88P, ATmega168, ATmega168P, ATmega328P + * + * 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. + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ + +#include "irmp.h" + +#if IRMP_SUPPORT_GRUNDIG_PROTOCOL == 1 || IRMP_SUPPORT_NOKIA_PROTOCOL == 1 || IRMP_SUPPORT_IR60_PROTOCOL == 1 +# define IRMP_SUPPORT_GRUNDIG_NOKIA_IR60_PROTOCOL 1 +#else +# define IRMP_SUPPORT_GRUNDIG_NOKIA_IR60_PROTOCOL 0 +#endif + +#if IRMP_SUPPORT_SIEMENS_PROTOCOL == 1 || IRMP_SUPPORT_RUWIDO_PROTOCOL == 1 +# define IRMP_SUPPORT_SIEMENS_OR_RUWIDO_PROTOCOL 1 +#else +# define IRMP_SUPPORT_SIEMENS_OR_RUWIDO_PROTOCOL 0 +#endif + +#if IRMP_SUPPORT_RC5_PROTOCOL == 1 || \ + IRMP_SUPPORT_RCII_PROTOCOL == 1 || \ + IRMP_SUPPORT_S100_PROTOCOL == 1 || \ + IRMP_SUPPORT_RC6_PROTOCOL == 1 || \ + IRMP_SUPPORT_GRUNDIG_NOKIA_IR60_PROTOCOL == 1 || \ + IRMP_SUPPORT_SIEMENS_OR_RUWIDO_PROTOCOL == 1 || \ + IRMP_SUPPORT_IR60_PROTOCOL == 1 || \ + IRMP_SUPPORT_A1TVBOX_PROTOCOL == 1 || \ + IRMP_SUPPORT_MERLIN_PROTOCOL == 1 || \ + IRMP_SUPPORT_ORTEK_PROTOCOL == 1 +# define IRMP_SUPPORT_MANCHESTER 1 +#else +# define IRMP_SUPPORT_MANCHESTER 0 +#endif + +#if IRMP_SUPPORT_NETBOX_PROTOCOL == 1 +# define IRMP_SUPPORT_SERIAL 1 +#else +# define IRMP_SUPPORT_SERIAL 0 +#endif + +#define IRMP_KEY_REPETITION_LEN (uint_fast16_t)(F_INTERRUPTS * 150.0e-3 + 0.5) // autodetect key repetition within 150 msec + +#define MIN_TOLERANCE_00 1.0 // -0% +#define MAX_TOLERANCE_00 1.0 // +0% + +#define MIN_TOLERANCE_02 0.98 // -2% +#define MAX_TOLERANCE_02 1.02 // +2% + +#define MIN_TOLERANCE_03 0.97 // -3% +#define MAX_TOLERANCE_03 1.03 // +3% + +#define MIN_TOLERANCE_05 0.95 // -5% +#define MAX_TOLERANCE_05 1.05 // +5% + +#define MIN_TOLERANCE_10 0.9 // -10% +#define MAX_TOLERANCE_10 1.1 // +10% + +#define MIN_TOLERANCE_15 0.85 // -15% +#define MAX_TOLERANCE_15 1.15 // +15% + +#define MIN_TOLERANCE_20 0.8 // -20% +#define MAX_TOLERANCE_20 1.2 // +20% + +#define MIN_TOLERANCE_30 0.7 // -30% +#define MAX_TOLERANCE_30 1.3 // +30% + +#define MIN_TOLERANCE_40 0.6 // -40% +#define MAX_TOLERANCE_40 1.4 // +40% + +#define MIN_TOLERANCE_50 0.5 // -50% +#define MAX_TOLERANCE_50 1.5 // +50% + +#define MIN_TOLERANCE_60 0.4 // -60% +#define MAX_TOLERANCE_60 1.6 // +60% + +#define MIN_TOLERANCE_70 0.3 // -70% +#define MAX_TOLERANCE_70 1.7 // +70% + +#define SIRCS_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * SIRCS_START_BIT_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define SIRCS_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * SIRCS_START_BIT_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define SIRCS_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * SIRCS_START_BIT_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) +#if IRMP_SUPPORT_NETBOX_PROTOCOL // only 5% to avoid conflict with NETBOX: +# define SIRCS_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * SIRCS_START_BIT_PAUSE_TIME * MAX_TOLERANCE_05 + 0.5)) +#else // only 5% + 1 to avoid conflict with RC6: +# define SIRCS_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * SIRCS_START_BIT_PAUSE_TIME * MAX_TOLERANCE_05 + 0.5) + 1) +#endif +#define SIRCS_1_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * SIRCS_1_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define SIRCS_1_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * SIRCS_1_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define SIRCS_0_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * SIRCS_0_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define SIRCS_0_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * SIRCS_0_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define SIRCS_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * SIRCS_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define SIRCS_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * SIRCS_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) + +#define NEC_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * NEC_START_BIT_PULSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1) +#define NEC_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * NEC_START_BIT_PULSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1) +#define NEC_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * NEC_START_BIT_PAUSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1) +#define NEC_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * NEC_START_BIT_PAUSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1) +#define NEC_REPEAT_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * NEC_REPEAT_START_BIT_PAUSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1) +#define NEC_REPEAT_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * NEC_REPEAT_START_BIT_PAUSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1) +#define NEC_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * NEC_PULSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1) +#define NEC_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * NEC_PULSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1) +#define NEC_1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * NEC_1_PAUSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1) +#define NEC_1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * NEC_1_PAUSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1) +#define NEC_0_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * NEC_0_PAUSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1) +#define NEC_0_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * NEC_0_PAUSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1) +// autodetect nec repetition frame within 50 msec: +// NEC seems to send the first repetition frame after 40ms, further repetition frames after 100 ms +#if 0 +#define NEC_FRAME_REPEAT_PAUSE_LEN_MAX (uint_fast16_t)(F_INTERRUPTS * NEC_FRAME_REPEAT_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) +#else +#define NEC_FRAME_REPEAT_PAUSE_LEN_MAX (uint_fast16_t)(F_INTERRUPTS * 100.0e-3 * MAX_TOLERANCE_20 + 0.5) +#endif + +#define SAMSUNG_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * SAMSUNG_START_BIT_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define SAMSUNG_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * SAMSUNG_START_BIT_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define SAMSUNG_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * SAMSUNG_START_BIT_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define SAMSUNG_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * SAMSUNG_START_BIT_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define SAMSUNG_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * SAMSUNG_PULSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1) +#define SAMSUNG_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * SAMSUNG_PULSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1) +#define SAMSUNG_1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * SAMSUNG_1_PAUSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1) +#define SAMSUNG_1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * SAMSUNG_1_PAUSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1) +#define SAMSUNG_0_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * SAMSUNG_0_PAUSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1) +#define SAMSUNG_0_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * SAMSUNG_0_PAUSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1) + +#define SAMSUNGAH_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * SAMSUNGAH_START_BIT_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define SAMSUNGAH_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * SAMSUNGAH_START_BIT_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define SAMSUNGAH_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * SAMSUNGAH_START_BIT_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define SAMSUNGAH_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * SAMSUNGAH_START_BIT_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define SAMSUNGAH_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * SAMSUNGAH_PULSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1) +#define SAMSUNGAH_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * SAMSUNGAH_PULSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1) +#define SAMSUNGAH_1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * SAMSUNGAH_1_PAUSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1) +#define SAMSUNGAH_1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * SAMSUNGAH_1_PAUSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1) +#define SAMSUNGAH_0_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * SAMSUNGAH_0_PAUSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1) +#define SAMSUNGAH_0_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * SAMSUNGAH_0_PAUSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1) + +#define MATSUSHITA_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * MATSUSHITA_START_BIT_PULSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) +#define MATSUSHITA_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * MATSUSHITA_START_BIT_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) +#define MATSUSHITA_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * MATSUSHITA_START_BIT_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) +#define MATSUSHITA_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * MATSUSHITA_START_BIT_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) +#define MATSUSHITA_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * MATSUSHITA_PULSE_TIME * MIN_TOLERANCE_40 + 0.5) - 1) +#define MATSUSHITA_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * MATSUSHITA_PULSE_TIME * MAX_TOLERANCE_40 + 0.5) + 1) +#define MATSUSHITA_1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * MATSUSHITA_1_PAUSE_TIME * MIN_TOLERANCE_40 + 0.5) - 1) +#define MATSUSHITA_1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * MATSUSHITA_1_PAUSE_TIME * MAX_TOLERANCE_40 + 0.5) + 1) +#define MATSUSHITA_0_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * MATSUSHITA_0_PAUSE_TIME * MIN_TOLERANCE_40 + 0.5) - 1) +#define MATSUSHITA_0_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * MATSUSHITA_0_PAUSE_TIME * MAX_TOLERANCE_40 + 0.5) + 1) + +#define KASEIKYO_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * KASEIKYO_START_BIT_PULSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) +#define KASEIKYO_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * KASEIKYO_START_BIT_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) +#define KASEIKYO_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * KASEIKYO_START_BIT_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) +#define KASEIKYO_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * KASEIKYO_START_BIT_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) +#define KASEIKYO_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * KASEIKYO_PULSE_TIME * MIN_TOLERANCE_40 + 0.5) - 1) +#define KASEIKYO_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * KASEIKYO_PULSE_TIME * MAX_TOLERANCE_40 + 0.5) + 1) +#define KASEIKYO_1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * KASEIKYO_1_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) +#define KASEIKYO_1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * KASEIKYO_1_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) +#define KASEIKYO_0_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * KASEIKYO_0_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) +#define KASEIKYO_0_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * KASEIKYO_0_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) + +#define MITSU_HEAVY_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * MITSU_HEAVY_START_BIT_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define MITSU_HEAVY_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * MITSU_HEAVY_START_BIT_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define MITSU_HEAVY_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * MITSU_HEAVY_START_BIT_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define MITSU_HEAVY_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * MITSU_HEAVY_START_BIT_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define MITSU_HEAVY_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * MITSU_HEAVY_PULSE_TIME * MIN_TOLERANCE_40 + 0.5) - 1) +#define MITSU_HEAVY_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * MITSU_HEAVY_PULSE_TIME * MAX_TOLERANCE_40 + 0.5) + 1) +#define MITSU_HEAVY_1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * MITSU_HEAVY_1_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) +#define MITSU_HEAVY_1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * MITSU_HEAVY_1_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) +#define MITSU_HEAVY_0_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * MITSU_HEAVY_0_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) +#define MITSU_HEAVY_0_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * MITSU_HEAVY_0_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) + +#define VINCENT_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * VINCENT_START_BIT_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define VINCENT_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * VINCENT_START_BIT_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define VINCENT_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * VINCENT_START_BIT_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define VINCENT_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * VINCENT_START_BIT_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define VINCENT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * VINCENT_PULSE_TIME * MIN_TOLERANCE_40 + 0.5) - 1) +#define VINCENT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * VINCENT_PULSE_TIME * MAX_TOLERANCE_40 + 0.5) + 1) +#define VINCENT_1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * VINCENT_1_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) +#define VINCENT_1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * VINCENT_1_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) +#define VINCENT_0_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * VINCENT_0_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) +#define VINCENT_0_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * VINCENT_0_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) + +#define PANASONIC_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * PANASONIC_START_BIT_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define PANASONIC_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * PANASONIC_START_BIT_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define PANASONIC_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * PANASONIC_START_BIT_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define PANASONIC_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * PANASONIC_START_BIT_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define PANASONIC_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * PANASONIC_PULSE_TIME * MIN_TOLERANCE_40 + 0.5) - 1) +#define PANASONIC_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * PANASONIC_PULSE_TIME * MAX_TOLERANCE_40 + 0.5) + 1) +#define PANASONIC_1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * PANASONIC_1_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) +#define PANASONIC_1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * PANASONIC_1_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) +#define PANASONIC_0_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * PANASONIC_0_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) +#define PANASONIC_0_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * PANASONIC_0_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) + +#define RECS80_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RECS80_START_BIT_PULSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) +#define RECS80_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RECS80_START_BIT_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) +#define RECS80_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RECS80_START_BIT_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define RECS80_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RECS80_START_BIT_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define RECS80_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RECS80_PULSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) +#define RECS80_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RECS80_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) +#define RECS80_1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RECS80_1_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define RECS80_1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RECS80_1_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define RECS80_0_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RECS80_0_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define RECS80_0_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RECS80_0_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) + +#if IRMP_SUPPORT_BOSE_PROTOCOL == 1 // BOSE conflicts with RC5, so keep tolerance for RC5 minimal here: +#define RC5_START_BIT_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RC5_BIT_TIME * MIN_TOLERANCE_05 + 0.5) - 1) +#define RC5_START_BIT_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RC5_BIT_TIME * MAX_TOLERANCE_05 + 0.5) + 1) +#else +#define RC5_START_BIT_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RC5_BIT_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define RC5_START_BIT_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RC5_BIT_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#endif + +#define RC5_BIT_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RC5_BIT_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define RC5_BIT_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RC5_BIT_TIME * MAX_TOLERANCE_10 + 0.5) + 1) + +#define RCII_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RCII_START_BIT_PULSE_TIME * MIN_TOLERANCE_05 + 0.5) - 1) +#define RCII_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RCII_START_BIT_PULSE_TIME * MAX_TOLERANCE_05 + 0.5) + 1) +#define RCII_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RCII_START_BIT_PAUSE_TIME * MIN_TOLERANCE_05 + 0.5) - 1) +#define RCII_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RCII_START_BIT_PAUSE_TIME * MAX_TOLERANCE_05 + 0.5) + 1) +#define RCII_START_BIT2_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RCII_START_BIT2_PULSE_TIME * MIN_TOLERANCE_05 + 0.5) - 1) +#define RCII_START_BIT2_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RCII_START_BIT2_PULSE_TIME * MAX_TOLERANCE_05 + 0.5) + 1) + +#define RCII_BIT_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RCII_BIT_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define RCII_BIT_LEN ((uint_fast8_t)(F_INTERRUPTS * RCII_BIT_TIME)) +#define RCII_BIT_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RCII_BIT_TIME * MAX_TOLERANCE_10 + 0.5) + 1) + +#if IRMP_SUPPORT_BOSE_PROTOCOL == 1 // BOSE conflicts with S100, so keep tolerance for S100 minimal here: +#define S100_START_BIT_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * S100_BIT_TIME * MIN_TOLERANCE_05 + 0.5) - 1) +#define S100_START_BIT_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * S100_BIT_TIME * MAX_TOLERANCE_05 + 0.5) + 1) +#else +#define S100_START_BIT_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * S100_BIT_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define S100_START_BIT_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * S100_BIT_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#endif + +#define S100_BIT_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * S100_BIT_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define S100_BIT_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * S100_BIT_TIME * MAX_TOLERANCE_10 + 0.5) + 1) + +#define DENON_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * DENON_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define DENON_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * DENON_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) +#define DENON_1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * DENON_1_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define DENON_1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * DENON_1_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +// RUWIDO (see t-home-mediareceiver-15kHz.txt) conflicts here with DENON +#define DENON_0_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * DENON_0_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define DENON_0_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * DENON_0_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define DENON_AUTO_REPETITION_PAUSE_LEN ((uint_fast16_t)(F_INTERRUPTS * DENON_AUTO_REPETITION_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) + +#define THOMSON_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * THOMSON_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define THOMSON_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * THOMSON_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define THOMSON_1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * THOMSON_1_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define THOMSON_1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * THOMSON_1_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define THOMSON_0_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * THOMSON_0_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define THOMSON_0_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * THOMSON_0_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) + +#define RC6_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RC6_START_BIT_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define RC6_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RC6_START_BIT_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define RC6_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RC6_START_BIT_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define RC6_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RC6_START_BIT_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define RC6_TOGGLE_BIT_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RC6_TOGGLE_BIT_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define RC6_TOGGLE_BIT_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RC6_TOGGLE_BIT_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define RC6_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RC6_BIT_TIME * MIN_TOLERANCE_60 + 0.5) - 1) +#define RC6_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RC6_BIT_TIME * MAX_TOLERANCE_20 + 0.5) + 1) // pulses: 300 - 800 +#define RC6_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RC6_BIT_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define RC6_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RC6_BIT_TIME * MAX_TOLERANCE_20 + 0.5) + 1) // pauses: 300 - 600 + +#define RECS80EXT_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RECS80EXT_START_BIT_PULSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) +#define RECS80EXT_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RECS80EXT_START_BIT_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) +#define RECS80EXT_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RECS80EXT_START_BIT_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define RECS80EXT_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RECS80EXT_START_BIT_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define RECS80EXT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RECS80EXT_PULSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) +#define RECS80EXT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RECS80EXT_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) +#define RECS80EXT_1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RECS80EXT_1_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define RECS80EXT_1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RECS80EXT_1_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define RECS80EXT_0_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RECS80EXT_0_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define RECS80EXT_0_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RECS80EXT_0_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) + +#define NUBERT_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * NUBERT_START_BIT_PULSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) +#define NUBERT_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * NUBERT_START_BIT_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) +#define NUBERT_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * NUBERT_START_BIT_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) +#define NUBERT_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * NUBERT_START_BIT_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) +#define NUBERT_1_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * NUBERT_1_PULSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) +#define NUBERT_1_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * NUBERT_1_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) +#define NUBERT_1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * NUBERT_1_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) +#define NUBERT_1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * NUBERT_1_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) +#define NUBERT_0_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * NUBERT_0_PULSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) +#define NUBERT_0_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * NUBERT_0_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) +#define NUBERT_0_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * NUBERT_0_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) +#define NUBERT_0_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * NUBERT_0_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) + +#define FAN_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * FAN_START_BIT_PULSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) +#define FAN_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * FAN_START_BIT_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) +#define FAN_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * FAN_START_BIT_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) +#define FAN_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * FAN_START_BIT_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) +#define FAN_1_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * FAN_1_PULSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) +#define FAN_1_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * FAN_1_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) +#define FAN_1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * FAN_1_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) +#define FAN_1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * FAN_1_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) +#define FAN_0_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * FAN_0_PULSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) +#define FAN_0_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * FAN_0_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) +#define FAN_0_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * FAN_0_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) +#define FAN_0_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * FAN_0_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) + +#define SPEAKER_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * SPEAKER_START_BIT_PULSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) +#define SPEAKER_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * SPEAKER_START_BIT_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) +#define SPEAKER_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * SPEAKER_START_BIT_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) +#define SPEAKER_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * SPEAKER_START_BIT_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) +#define SPEAKER_1_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * SPEAKER_1_PULSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) +#define SPEAKER_1_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * SPEAKER_1_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) +#define SPEAKER_1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * SPEAKER_1_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) +#define SPEAKER_1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * SPEAKER_1_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) +#define SPEAKER_0_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * SPEAKER_0_PULSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) +#define SPEAKER_0_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * SPEAKER_0_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) +#define SPEAKER_0_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * SPEAKER_0_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) +#define SPEAKER_0_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * SPEAKER_0_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) + +#define BANG_OLUFSEN_START_BIT1_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT1_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define BANG_OLUFSEN_START_BIT1_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT1_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define BANG_OLUFSEN_START_BIT1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT1_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define BANG_OLUFSEN_START_BIT1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT1_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define BANG_OLUFSEN_START_BIT2_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT2_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define BANG_OLUFSEN_START_BIT2_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT2_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define BANG_OLUFSEN_START_BIT2_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT2_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define BANG_OLUFSEN_START_BIT2_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT2_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define BANG_OLUFSEN_START_BIT3_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT3_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define BANG_OLUFSEN_START_BIT3_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT3_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define BANG_OLUFSEN_START_BIT3_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT3_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define BANG_OLUFSEN_START_BIT3_PAUSE_LEN_MAX ((PAUSE_LEN)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT3_PAUSE_TIME * MAX_TOLERANCE_05 + 0.5) + 1) // value must be below IRMP_TIMEOUT +#define BANG_OLUFSEN_START_BIT4_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT4_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define BANG_OLUFSEN_START_BIT4_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT4_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define BANG_OLUFSEN_START_BIT4_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT4_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define BANG_OLUFSEN_START_BIT4_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT4_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define BANG_OLUFSEN_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * BANG_OLUFSEN_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define BANG_OLUFSEN_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * BANG_OLUFSEN_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define BANG_OLUFSEN_1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * BANG_OLUFSEN_1_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define BANG_OLUFSEN_1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * BANG_OLUFSEN_1_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define BANG_OLUFSEN_0_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * BANG_OLUFSEN_0_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define BANG_OLUFSEN_0_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * BANG_OLUFSEN_0_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define BANG_OLUFSEN_R_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * BANG_OLUFSEN_R_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define BANG_OLUFSEN_R_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * BANG_OLUFSEN_R_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define BANG_OLUFSEN_TRAILER_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * BANG_OLUFSEN_TRAILER_BIT_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define BANG_OLUFSEN_TRAILER_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * BANG_OLUFSEN_TRAILER_BIT_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) + +#define IR60_TIMEOUT_LEN ((uint_fast8_t)(F_INTERRUPTS * IR60_TIMEOUT_TIME * 0.5)) +#define GRUNDIG_NOKIA_IR60_START_BIT_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * GRUNDIG_NOKIA_IR60_BIT_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define GRUNDIG_NOKIA_IR60_START_BIT_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * GRUNDIG_NOKIA_IR60_BIT_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define GRUNDIG_NOKIA_IR60_BIT_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * GRUNDIG_NOKIA_IR60_BIT_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define GRUNDIG_NOKIA_IR60_BIT_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * GRUNDIG_NOKIA_IR60_BIT_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define GRUNDIG_NOKIA_IR60_PRE_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * GRUNDIG_NOKIA_IR60_PRE_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) + 1) +#define GRUNDIG_NOKIA_IR60_PRE_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * GRUNDIG_NOKIA_IR60_PRE_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) + +#define SIEMENS_OR_RUWIDO_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * SIEMENS_OR_RUWIDO_START_BIT_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define SIEMENS_OR_RUWIDO_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * SIEMENS_OR_RUWIDO_START_BIT_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define SIEMENS_OR_RUWIDO_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * SIEMENS_OR_RUWIDO_START_BIT_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define SIEMENS_OR_RUWIDO_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * SIEMENS_OR_RUWIDO_START_BIT_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define SIEMENS_OR_RUWIDO_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * SIEMENS_OR_RUWIDO_BIT_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define SIEMENS_OR_RUWIDO_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * SIEMENS_OR_RUWIDO_BIT_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define SIEMENS_OR_RUWIDO_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * SIEMENS_OR_RUWIDO_BIT_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define SIEMENS_OR_RUWIDO_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * SIEMENS_OR_RUWIDO_BIT_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) + +#define FDC_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * FDC_START_BIT_PULSE_TIME * MIN_TOLERANCE_05 + 0.5) - 1) // 5%: avoid conflict with NETBOX +#define FDC_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * FDC_START_BIT_PULSE_TIME * MAX_TOLERANCE_05 + 0.5)) +#define FDC_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * FDC_START_BIT_PAUSE_TIME * MIN_TOLERANCE_05 + 0.5) - 1) +#define FDC_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * FDC_START_BIT_PAUSE_TIME * MAX_TOLERANCE_05 + 0.5)) +#define FDC_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * FDC_PULSE_TIME * MIN_TOLERANCE_40 + 0.5) - 1) +#define FDC_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * FDC_PULSE_TIME * MAX_TOLERANCE_50 + 0.5) + 1) +#define FDC_1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * FDC_1_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) +#define FDC_1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * FDC_1_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) +#if 0 +#define FDC_0_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * FDC_0_PAUSE_TIME * MIN_TOLERANCE_40 + 0.5) - 1) // could be negative: 255 +#else +#define FDC_0_PAUSE_LEN_MIN (1) // simply use 1 +#endif +#define FDC_0_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * FDC_0_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) + +#define RCCAR_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RCCAR_START_BIT_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define RCCAR_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RCCAR_START_BIT_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define RCCAR_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RCCAR_START_BIT_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define RCCAR_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RCCAR_START_BIT_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define RCCAR_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RCCAR_PULSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) +#define RCCAR_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RCCAR_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) +#define RCCAR_1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RCCAR_1_PAUSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1) +#define RCCAR_1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RCCAR_1_PAUSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1) +#define RCCAR_0_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RCCAR_0_PAUSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1) +#define RCCAR_0_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RCCAR_0_PAUSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1) + +#define JVC_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * JVC_START_BIT_PULSE_TIME * MIN_TOLERANCE_40 + 0.5) - 1) +#define JVC_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * JVC_START_BIT_PULSE_TIME * MAX_TOLERANCE_40 + 0.5) + 1) +#define JVC_REPEAT_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * (JVC_FRAME_REPEAT_PAUSE_TIME - IRMP_TIMEOUT_TIME) * MIN_TOLERANCE_40 + 0.5) - 1) // HACK! +#define JVC_REPEAT_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * (JVC_FRAME_REPEAT_PAUSE_TIME - IRMP_TIMEOUT_TIME) * MAX_TOLERANCE_70 + 0.5) - 1) // HACK! +#define JVC_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * JVC_PULSE_TIME * MIN_TOLERANCE_40 + 0.5) - 1) +#define JVC_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * JVC_PULSE_TIME * MAX_TOLERANCE_40 + 0.5) + 1) +#define JVC_1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * JVC_1_PAUSE_TIME * MIN_TOLERANCE_40 + 0.5) - 1) +#define JVC_1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * JVC_1_PAUSE_TIME * MAX_TOLERANCE_40 + 0.5) + 1) +#define JVC_0_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * JVC_0_PAUSE_TIME * MIN_TOLERANCE_40 + 0.5) - 1) +#define JVC_0_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * JVC_0_PAUSE_TIME * MAX_TOLERANCE_40 + 0.5) + 1) +// autodetect JVC repetition frame within 50 msec: +#define JVC_FRAME_REPEAT_PAUSE_LEN_MAX (uint_fast16_t)(F_INTERRUPTS * JVC_FRAME_REPEAT_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + +#define NIKON_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * NIKON_START_BIT_PULSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) +#define NIKON_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * NIKON_START_BIT_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) +#define NIKON_START_BIT_PAUSE_LEN_MIN ((uint_fast16_t)(F_INTERRUPTS * NIKON_START_BIT_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) +#define NIKON_START_BIT_PAUSE_LEN_MAX ((uint_fast16_t)(F_INTERRUPTS * NIKON_START_BIT_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) +#define NIKON_REPEAT_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * NIKON_REPEAT_START_BIT_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) +#define NIKON_REPEAT_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * NIKON_REPEAT_START_BIT_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) +#define NIKON_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * NIKON_PULSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) +#define NIKON_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * NIKON_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) +#define NIKON_1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * NIKON_1_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) +#define NIKON_1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * NIKON_1_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) +#define NIKON_0_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * NIKON_0_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) +#define NIKON_0_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * NIKON_0_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) +#define NIKON_FRAME_REPEAT_PAUSE_LEN_MAX (uint_fast16_t)(F_INTERRUPTS * NIKON_FRAME_REPEAT_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + +#define KATHREIN_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * KATHREIN_START_BIT_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define KATHREIN_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * KATHREIN_START_BIT_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define KATHREIN_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * KATHREIN_START_BIT_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define KATHREIN_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * KATHREIN_START_BIT_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define KATHREIN_1_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * KATHREIN_1_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define KATHREIN_1_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * KATHREIN_1_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define KATHREIN_1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * KATHREIN_1_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define KATHREIN_1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * KATHREIN_1_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define KATHREIN_0_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * KATHREIN_0_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define KATHREIN_0_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * KATHREIN_0_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define KATHREIN_0_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * KATHREIN_0_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define KATHREIN_0_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * KATHREIN_0_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define KATHREIN_SYNC_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * KATHREIN_SYNC_BIT_PAUSE_LEN_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define KATHREIN_SYNC_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * KATHREIN_SYNC_BIT_PAUSE_LEN_TIME * MAX_TOLERANCE_10 + 0.5) + 1) + +#define NETBOX_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * NETBOX_START_BIT_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define NETBOX_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * NETBOX_START_BIT_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define NETBOX_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * NETBOX_START_BIT_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define NETBOX_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * NETBOX_START_BIT_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define NETBOX_PULSE_LEN ((uint_fast8_t)(F_INTERRUPTS * NETBOX_PULSE_TIME)) +#define NETBOX_PAUSE_LEN ((uint_fast8_t)(F_INTERRUPTS * NETBOX_PAUSE_TIME)) +#define NETBOX_PULSE_REST_LEN ((uint_fast8_t)(F_INTERRUPTS * NETBOX_PULSE_TIME / 4)) +#define NETBOX_PAUSE_REST_LEN ((uint_fast8_t)(F_INTERRUPTS * NETBOX_PAUSE_TIME / 4)) + +#define LEGO_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * LEGO_START_BIT_PULSE_TIME * MIN_TOLERANCE_40 + 0.5) - 1) +#define LEGO_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * LEGO_START_BIT_PULSE_TIME * MAX_TOLERANCE_40 + 0.5) + 1) +#define LEGO_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * LEGO_START_BIT_PAUSE_TIME * MIN_TOLERANCE_40 + 0.5) - 1) +#define LEGO_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * LEGO_START_BIT_PAUSE_TIME * MAX_TOLERANCE_40 + 0.5) + 1) +#define LEGO_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * LEGO_PULSE_TIME * MIN_TOLERANCE_40 + 0.5) - 1) +#define LEGO_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * LEGO_PULSE_TIME * MAX_TOLERANCE_40 + 0.5) + 1) +#define LEGO_1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * LEGO_1_PAUSE_TIME * MIN_TOLERANCE_40 + 0.5) - 1) +#define LEGO_1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * LEGO_1_PAUSE_TIME * MAX_TOLERANCE_40 + 0.5) + 1) +#define LEGO_0_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * LEGO_0_PAUSE_TIME * MIN_TOLERANCE_40 + 0.5) - 1) +#define LEGO_0_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * LEGO_0_PAUSE_TIME * MAX_TOLERANCE_40 + 0.5) + 1) + +#define IRMP16_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * IRMP16_START_BIT_PULSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) +#define IRMP16_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * IRMP16_START_BIT_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) +#define IRMP16_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * IRMP16_START_BIT_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) +#define IRMP16_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * IRMP16_START_BIT_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) +#define IRMP16_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * IRMP16_PULSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) +#define IRMP16_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * IRMP16_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) +#define IRMP16_1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * IRMP16_1_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) +#define IRMP16_1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * IRMP16_1_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) +#define IRMP16_0_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * IRMP16_0_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) +#define IRMP16_0_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * IRMP16_0_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) + +#define GREE_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * GREE_START_BIT_PULSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) +#define GREE_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * GREE_START_BIT_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) +#define GREE_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * GREE_START_BIT_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) +#define GREE_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * GREE_START_BIT_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) +#define GREE_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * GREE_PULSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) +#define GREE_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * GREE_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) +#define GREE_1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * GREE_1_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) +#define GREE_1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * GREE_1_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) +#define GREE_0_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * GREE_0_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) +#define GREE_0_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * GREE_0_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) + +#define BOSE_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * BOSE_START_BIT_PULSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1) +#define BOSE_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * BOSE_START_BIT_PULSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1) +#define BOSE_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * BOSE_START_BIT_PAUSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1) +#define BOSE_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * BOSE_START_BIT_PAUSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1) +#define BOSE_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * BOSE_PULSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1) +#define BOSE_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * BOSE_PULSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1) +#define BOSE_1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * BOSE_1_PAUSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1) +#define BOSE_1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * BOSE_1_PAUSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1) +#define BOSE_0_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * BOSE_0_PAUSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1) +#define BOSE_0_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * BOSE_0_PAUSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1) +#define BOSE_FRAME_REPEAT_PAUSE_LEN_MAX (uint_fast16_t)(F_INTERRUPTS * 100.0e-3 * MAX_TOLERANCE_20 + 0.5) + +#define A1TVBOX_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * A1TVBOX_START_BIT_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define A1TVBOX_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * A1TVBOX_START_BIT_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define A1TVBOX_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * A1TVBOX_START_BIT_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define A1TVBOX_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * A1TVBOX_START_BIT_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define A1TVBOX_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * A1TVBOX_BIT_PULSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1) +#define A1TVBOX_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * A1TVBOX_BIT_PULSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1) +#define A1TVBOX_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * A1TVBOX_BIT_PAUSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1) +#define A1TVBOX_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * A1TVBOX_BIT_PAUSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1) + +#define MERLIN_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * MERLIN_START_BIT_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define MERLIN_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * MERLIN_START_BIT_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define MERLIN_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * MERLIN_START_BIT_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define MERLIN_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * MERLIN_START_BIT_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define MERLIN_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * MERLIN_BIT_PULSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1) +#define MERLIN_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * MERLIN_BIT_PULSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1) +#define MERLIN_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * MERLIN_BIT_PAUSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1) +#define MERLIN_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * MERLIN_BIT_PAUSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1) + +#define ORTEK_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * ORTEK_START_BIT_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define ORTEK_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * ORTEK_START_BIT_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define ORTEK_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * ORTEK_START_BIT_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define ORTEK_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * ORTEK_START_BIT_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define ORTEK_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * ORTEK_BIT_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define ORTEK_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * ORTEK_BIT_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define ORTEK_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * ORTEK_BIT_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define ORTEK_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * ORTEK_BIT_TIME * MAX_TOLERANCE_10 + 0.5) + 1) + +#define TELEFUNKEN_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * TELEFUNKEN_START_BIT_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define TELEFUNKEN_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * TELEFUNKEN_START_BIT_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define TELEFUNKEN_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * (TELEFUNKEN_START_BIT_PAUSE_TIME) * MIN_TOLERANCE_10 + 0.5) - 1) +#define TELEFUNKEN_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * (TELEFUNKEN_START_BIT_PAUSE_TIME) * MAX_TOLERANCE_10 + 0.5) - 1) +#define TELEFUNKEN_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * TELEFUNKEN_PULSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1) +#define TELEFUNKEN_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * TELEFUNKEN_PULSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1) +#define TELEFUNKEN_1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * TELEFUNKEN_1_PAUSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1) +#define TELEFUNKEN_1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * TELEFUNKEN_1_PAUSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1) +#define TELEFUNKEN_0_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * TELEFUNKEN_0_PAUSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1) +#define TELEFUNKEN_0_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * TELEFUNKEN_0_PAUSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1) +// autodetect TELEFUNKEN repetition frame within 50 msec: +// #define TELEFUNKEN_FRAME_REPEAT_PAUSE_LEN_MAX (uint_fast16_t)(F_INTERRUPTS * TELEFUNKEN_FRAME_REPEAT_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + +#define ROOMBA_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * ROOMBA_START_BIT_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define ROOMBA_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * ROOMBA_START_BIT_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define ROOMBA_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * ROOMBA_START_BIT_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define ROOMBA_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * ROOMBA_START_BIT_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define ROOMBA_1_PAUSE_LEN_EXACT ((uint_fast8_t)(F_INTERRUPTS * ROOMBA_1_PAUSE_TIME + 0.5)) +#define ROOMBA_1_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * ROOMBA_1_PULSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) +#define ROOMBA_1_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * ROOMBA_1_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) +#define ROOMBA_1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * ROOMBA_1_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) +#define ROOMBA_1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * ROOMBA_1_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) +#define ROOMBA_0_PAUSE_LEN ((uint_fast8_t)(F_INTERRUPTS * ROOMBA_0_PAUSE_TIME)) +#define ROOMBA_0_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * ROOMBA_0_PULSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) +#define ROOMBA_0_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * ROOMBA_0_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) +#define ROOMBA_0_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * ROOMBA_0_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) +#define ROOMBA_0_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * ROOMBA_0_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) + +#define RCMM32_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RCMM32_START_BIT_PULSE_TIME * MIN_TOLERANCE_05 + 0.5) - 1) +#define RCMM32_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RCMM32_START_BIT_PULSE_TIME * MAX_TOLERANCE_05 + 0.5) + 1) +#define RCMM32_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RCMM32_START_BIT_PAUSE_TIME * MIN_TOLERANCE_05 + 0.5) - 1) +#define RCMM32_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RCMM32_START_BIT_PAUSE_TIME * MAX_TOLERANCE_05 + 0.5) + 1) +#define RCMM32_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RCMM32_PULSE_TIME * MIN_TOLERANCE_05 + 0.5) - 1) +#define RCMM32_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RCMM32_PULSE_TIME * MAX_TOLERANCE_05 + 0.5) + 1) +#define RCMM32_BIT_00_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RCMM32_00_PAUSE_TIME * MIN_TOLERANCE_05 + 0.5) - 1) +#define RCMM32_BIT_00_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RCMM32_00_PAUSE_TIME * MAX_TOLERANCE_05 + 0.5) + 1) +#define RCMM32_BIT_01_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RCMM32_01_PAUSE_TIME * MIN_TOLERANCE_05 + 0.5) - 1) +#define RCMM32_BIT_01_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RCMM32_01_PAUSE_TIME * MAX_TOLERANCE_05 + 0.5) + 1) +#define RCMM32_BIT_10_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RCMM32_10_PAUSE_TIME * MIN_TOLERANCE_05 + 0.5) - 1) +#define RCMM32_BIT_10_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RCMM32_10_PAUSE_TIME * MAX_TOLERANCE_05 + 0.5) + 1) +#define RCMM32_BIT_11_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RCMM32_11_PAUSE_TIME * MIN_TOLERANCE_05 + 0.5) - 1) +#define RCMM32_BIT_11_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RCMM32_11_PAUSE_TIME * MAX_TOLERANCE_05 + 0.5) + 1) + +#define PENTAX_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * PENTAX_START_BIT_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define PENTAX_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * PENTAX_START_BIT_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define PENTAX_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * PENTAX_START_BIT_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define PENTAX_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * PENTAX_START_BIT_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define PENTAX_1_PAUSE_LEN_EXACT ((uint_fast8_t)(F_INTERRUPTS * PENTAX_1_PAUSE_TIME + 0.5)) +#define PENTAX_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * PENTAX_PULSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) +#define PENTAX_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * PENTAX_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) +#define PENTAX_1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * PENTAX_1_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) +#define PENTAX_1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * PENTAX_1_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) +#define PENTAX_0_PAUSE_LEN ((uint_fast8_t)(F_INTERRUPTS * PENTAX_0_PAUSE_TIME)) +#define PENTAX_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * PENTAX_PULSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) +#define PENTAX_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * PENTAX_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) +#define PENTAX_0_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * PENTAX_0_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) +#define PENTAX_0_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * PENTAX_0_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) + +#define ACP24_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * ACP24_START_BIT_PULSE_TIME * MIN_TOLERANCE_15 + 0.5) - 1) +#define ACP24_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * ACP24_START_BIT_PULSE_TIME * MAX_TOLERANCE_15 + 0.5) + 1) +#define ACP24_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * ACP24_START_BIT_PAUSE_TIME * MIN_TOLERANCE_15 + 0.5) - 1) +#define ACP24_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * ACP24_START_BIT_PAUSE_TIME * MAX_TOLERANCE_15 + 0.5) + 1) +#define ACP24_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * ACP24_PULSE_TIME * MIN_TOLERANCE_15 + 0.5) - 1) +#define ACP24_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * ACP24_PULSE_TIME * MAX_TOLERANCE_15 + 0.5) + 1) +#define ACP24_1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * ACP24_1_PAUSE_TIME * MIN_TOLERANCE_15 + 0.5) - 1) +#define ACP24_1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * ACP24_1_PAUSE_TIME * MAX_TOLERANCE_15 + 0.5) + 1) +#define ACP24_0_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * ACP24_0_PAUSE_TIME * MIN_TOLERANCE_15 + 0.5) - 1) +#define ACP24_0_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * ACP24_0_PAUSE_TIME * MAX_TOLERANCE_15 + 0.5) + 1) + +#define RADIO1_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RADIO1_START_BIT_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define RADIO1_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RADIO1_START_BIT_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define RADIO1_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RADIO1_START_BIT_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) +#define RADIO1_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RADIO1_START_BIT_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) +#define RADIO1_1_PAUSE_LEN_EXACT ((uint_fast8_t)(F_INTERRUPTS * RADIO1_1_PAUSE_TIME + 0.5)) +#define RADIO1_1_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RADIO1_1_PULSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) +#define RADIO1_1_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RADIO1_1_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) +#define RADIO1_1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RADIO1_1_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) +#define RADIO1_1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RADIO1_1_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) +#define RADIO1_0_PAUSE_LEN ((uint_fast8_t)(F_INTERRUPTS * RADIO1_0_PAUSE_TIME)) +#define RADIO1_0_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RADIO1_0_PULSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) +#define RADIO1_0_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RADIO1_0_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) +#define RADIO1_0_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RADIO1_0_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) +#define RADIO1_0_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RADIO1_0_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) + +#define AUTO_FRAME_REPETITION_LEN (uint_fast16_t)(F_INTERRUPTS * AUTO_FRAME_REPETITION_TIME + 0.5) // use uint_fast16_t! + +#ifdef ANALYZE +# define ANALYZE_PUTCHAR(a) { if (! silent) { putchar (a); } } +# define ANALYZE_ONLY_NORMAL_PUTCHAR(a) { if (! silent && !verbose) { putchar (a); } } +# define ANALYZE_PRINTF(...) { if (verbose) { printf (__VA_ARGS__); } } +# define ANALYZE_ONLY_NORMAL_PRINTF(...) { if (! silent && !verbose) { printf (__VA_ARGS__); } } +# define ANALYZE_NEWLINE() { if (verbose) { putchar ('\n'); } } +static int silent; +static int time_counter; +static int verbose; + +/******************************* not every PIC compiler knows variadic macros :-( +#else +# define ANALYZE_PUTCHAR(a) +# define ANALYZE_ONLY_NORMAL_PUTCHAR(a) +# define ANALYZE_PRINTF(...) +# define ANALYZE_ONLY_NORMAL_PRINTF(...) +# endif +# define ANALYZE_NEWLINE() +*********************************/ +#endif + +#if IRMP_USE_CALLBACK == 1 +static void (*irmp_callback_ptr) (uint_fast8_t); +#endif // IRMP_USE_CALLBACK == 1 + +#define PARITY_CHECK_OK 1 +#define PARITY_CHECK_FAILED 0 + +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * Protocol names + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ +#if defined(UNIX_OR_WINDOWS) || IRMP_PROTOCOL_NAMES == 1 +static const char proto_unknown[] PROGMEM = "UNKNOWN"; +static const char proto_sircs[] PROGMEM = "SIRCS"; +static const char proto_nec[] PROGMEM = "NEC"; +static const char proto_samsung[] PROGMEM = "SAMSUNG"; +static const char proto_matsushita[] PROGMEM = "MATSUSH"; +static const char proto_kaseikyo[] PROGMEM = "KASEIKYO"; +static const char proto_recs80[] PROGMEM = "RECS80"; +static const char proto_rc5[] PROGMEM = "RC5"; +static const char proto_denon[] PROGMEM = "DENON"; +static const char proto_rc6[] PROGMEM = "RC6"; +static const char proto_samsung32[] PROGMEM = "SAMSG32"; +static const char proto_apple[] PROGMEM = "APPLE"; +static const char proto_recs80ext[] PROGMEM = "RECS80EX"; +static const char proto_nubert[] PROGMEM = "NUBERT"; +static const char proto_bang_olufsen[] PROGMEM = "BANG OLU"; +static const char proto_grundig[] PROGMEM = "GRUNDIG"; +static const char proto_nokia[] PROGMEM = "NOKIA"; +static const char proto_siemens[] PROGMEM = "SIEMENS"; +static const char proto_fdc[] PROGMEM = "FDC"; +static const char proto_rccar[] PROGMEM = "RCCAR"; +static const char proto_jvc[] PROGMEM = "JVC"; +static const char proto_rc6a[] PROGMEM = "RC6A"; +static const char proto_nikon[] PROGMEM = "NIKON"; +static const char proto_ruwido[] PROGMEM = "RUWIDO"; +static const char proto_ir60[] PROGMEM = "IR60"; +static const char proto_kathrein[] PROGMEM = "KATHREIN"; +static const char proto_netbox[] PROGMEM = "NETBOX"; +static const char proto_nec16[] PROGMEM = "NEC16"; +static const char proto_nec42[] PROGMEM = "NEC42"; +static const char proto_lego[] PROGMEM = "LEGO"; +static const char proto_thomson[] PROGMEM = "THOMSON"; +static const char proto_bose[] PROGMEM = "BOSE"; +static const char proto_a1tvbox[] PROGMEM = "A1TVBOX"; +static const char proto_ortek[] PROGMEM = "ORTEK"; +static const char proto_telefunken[] PROGMEM = "TELEFUNKEN"; +static const char proto_roomba[] PROGMEM = "ROOMBA"; +static const char proto_rcmm32[] PROGMEM = "RCMM32"; +static const char proto_rcmm24[] PROGMEM = "RCMM24"; +static const char proto_rcmm12[] PROGMEM = "RCMM12"; +static const char proto_speaker[] PROGMEM = "SPEAKER"; +static const char proto_lgair[] PROGMEM = "LGAIR"; +static const char proto_samsung48[] PROGMEM = "SAMSG48"; +static const char proto_merlin[] PROGMEM = "MERLIN"; +static const char proto_pentax[] PROGMEM = "PENTAX"; +static const char proto_fan[] PROGMEM = "FAN"; +static const char proto_s100[] PROGMEM = "S100"; +static const char proto_acp24[] PROGMEM = "ACP24"; +static const char proto_technics[] PROGMEM = "TECHNICS"; +static const char proto_panasonic[] PROGMEM = "PANASONIC"; +static const char proto_mitsu_heavy[] PROGMEM = "MITSU_HEAVY"; +static const char proto_vincent[] PROGMEM = "VINCENT"; +static const char proto_samsungah[] PROGMEM = "SAMSUNGAH"; +static const char proto_irmp16[] PROGMEM = "IRMP16"; +static const char proto_gree[] PROGMEM = "GREE"; +static const char proto_rcii[] PROGMEM = "RCII"; + +static const char proto_radio1[] PROGMEM = "RADIO1"; + +const char * const +irmp_protocol_names[IRMP_N_PROTOCOLS + 1] PROGMEM = +{ + proto_unknown, + proto_sircs, + proto_nec, + proto_samsung, + proto_matsushita, + proto_kaseikyo, + proto_recs80, + proto_rc5, + proto_denon, + proto_rc6, + proto_samsung32, + proto_apple, + proto_recs80ext, + proto_nubert, + proto_bang_olufsen, + proto_grundig, + proto_nokia, + proto_siemens, + proto_fdc, + proto_rccar, + proto_jvc, + proto_rc6a, + proto_nikon, + proto_ruwido, + proto_ir60, + proto_kathrein, + proto_netbox, + proto_nec16, + proto_nec42, + proto_lego, + proto_thomson, + proto_bose, + proto_a1tvbox, + proto_ortek, + proto_telefunken, + proto_roomba, + proto_rcmm32, + proto_rcmm24, + proto_rcmm12, + proto_speaker, + proto_lgair, + proto_samsung48, + proto_merlin, + proto_pentax, + proto_fan, + proto_s100, + proto_acp24, + proto_technics, + proto_panasonic, + proto_mitsu_heavy, + proto_vincent, + proto_samsungah, + proto_irmp16, + proto_gree, + proto_rcii, + proto_radio1 +}; + +#endif + +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * Logging + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ +#if IRMP_LOGGING == 1 // logging via UART + +#if defined(ARM_STM32F4XX) +# define STM32_GPIO_CLOCK RCC_AHB1Periph_GPIOA // UART2 on PA2 +# define STM32_UART_CLOCK RCC_APB1Periph_USART2 +# define STM32_GPIO_PORT GPIOA +# define STM32_GPIO_PIN GPIO_Pin_2 +# define STM32_GPIO_SOURCE GPIO_PinSource2 +# define STM32_UART_AF GPIO_AF_USART2 +# define STM32_UART_COM USART2 +# define STM32_UART_BAUD 115200 // 115200 Baud +# include "stm32f4xx_usart.h" +#elif defined(ARM_STM32F10X) +# define STM32_UART_COM USART3 // UART3 on PB10 +#elif defined(ARDUINO) // Arduino Serial implementation +# if defined(USB_SERIAL) +# include "usb_serial.h" +# else +# error USB_SERIAL not defined in ARDUINO Environment +# endif +#elif defined(_CHIBIOS_HAL_) // ChibiOS HAL +# if IRMP_EXT_LOGGING == 1 +# error IRMP_EXT_LOGGING not implemented for ChibiOS HAL, use regular logging instead +# endif +#else +# if IRMP_EXT_LOGGING == 1 // use external logging +# include "irmpextlog.h" +# else // normal UART log (IRMP_EXT_LOGGING == 0) +# define BAUD 9600L +# ifndef UNIX_OR_WINDOWS +# include +# endif + +#ifdef UBRR0H + +#define UART0_UBRRH UBRR0H +#define UART0_UBRRL UBRR0L +#define UART0_UCSRA UCSR0A +#define UART0_UCSRB UCSR0B +#define UART0_UCSRC UCSR0C +#define UART0_UDRE_BIT_VALUE (1< ENDBITS) // if high received then look at log-stop condition + { // if stop condition is true, output on uart + uint_fast8_t i8; + uint_fast16_t i; + uint_fast16_t j; + uint_fast8_t v = '1'; + uint_fast16_t d; + + for (i8 = 0; i8 < STARTCYCLES; i8++) + { + irmp_uart_putc ('0'); // the ignored starting zeros + } + + for (i = 0; i < buf_idx; i++) + { + d = buf[i]; + + if (d == 0xff) + { + i++; + d = buf[i]; + i++; + d |= ((uint_fast16_t) buf[i] << 8); + } + + for (j = 0; j < d; j++) + { + irmp_uart_putc (v); + } + + v = (v == '1') ? '0' : '1'; + } + + for (i8 = 0; i8 < 20; i8++) + { + irmp_uart_putc ('1'); + } + + irmp_uart_putc ('\n'); + buf_idx = 0; + last_val = 1; + cnt = 0; + } + } + else if (buf_idx < DATALEN - 3) + { + if (cnt >= 0xff) + { + buf[buf_idx++] = 0xff; + buf[buf_idx++] = (cnt & 0xff); + buf[buf_idx] = (cnt >> 8); + } + else + { + buf[buf_idx] = cnt; + } + + buf_idx++; + cnt = 1; + last_val = val; + } + } + } +} + +#else +#define irmp_log(val) +#endif //IRMP_LOGGING + +typedef struct +{ + uint_fast8_t protocol; // ir protocol + uint_fast8_t pulse_1_len_min; // minimum length of pulse with bit value 1 + uint_fast8_t pulse_1_len_max; // maximum length of pulse with bit value 1 + uint_fast8_t pause_1_len_min; // minimum length of pause with bit value 1 + uint_fast8_t pause_1_len_max; // maximum length of pause with bit value 1 + uint_fast8_t pulse_0_len_min; // minimum length of pulse with bit value 0 + uint_fast8_t pulse_0_len_max; // maximum length of pulse with bit value 0 + uint_fast8_t pause_0_len_min; // minimum length of pause with bit value 0 + uint_fast8_t pause_0_len_max; // maximum length of pause with bit value 0 + uint_fast8_t address_offset; // address offset + uint_fast8_t address_end; // end of address + uint_fast8_t command_offset; // command offset + uint_fast8_t command_end; // end of command + uint_fast8_t complete_len; // complete length of frame + uint_fast8_t stop_bit; // flag: frame has stop bit + uint_fast8_t lsb_first; // flag: LSB first + uint_fast8_t flags; // some flags +} IRMP_PARAMETER; + +#if IRMP_SUPPORT_SIRCS_PROTOCOL == 1 + +static const PROGMEM IRMP_PARAMETER sircs_param = +{ + IRMP_SIRCS_PROTOCOL, // protocol: ir protocol + SIRCS_1_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 + SIRCS_1_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 + SIRCS_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 + SIRCS_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 + SIRCS_0_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 + SIRCS_0_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 + SIRCS_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 + SIRCS_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 + SIRCS_ADDRESS_OFFSET, // address_offset: address offset + SIRCS_ADDRESS_OFFSET + SIRCS_ADDRESS_LEN, // address_end: end of address + SIRCS_COMMAND_OFFSET, // command_offset: command offset + SIRCS_COMMAND_OFFSET + SIRCS_COMMAND_LEN, // command_end: end of command + SIRCS_COMPLETE_DATA_LEN, // complete_len: complete length of frame + SIRCS_STOP_BIT, // stop_bit: flag: frame has stop bit + SIRCS_LSB, // lsb_first: flag: LSB first + SIRCS_FLAGS // flags: some flags +}; + +#endif + +#if IRMP_SUPPORT_NEC_PROTOCOL == 1 + +static const PROGMEM IRMP_PARAMETER nec_param = +{ + IRMP_NEC_PROTOCOL, // protocol: ir protocol + NEC_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 + NEC_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 + NEC_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 + NEC_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 + NEC_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 + NEC_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 + NEC_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 + NEC_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 + NEC_ADDRESS_OFFSET, // address_offset: address offset + NEC_ADDRESS_OFFSET + NEC_ADDRESS_LEN, // address_end: end of address + NEC_COMMAND_OFFSET, // command_offset: command offset + NEC_COMMAND_OFFSET + NEC_COMMAND_LEN, // command_end: end of command + NEC_COMPLETE_DATA_LEN, // complete_len: complete length of frame + NEC_STOP_BIT, // stop_bit: flag: frame has stop bit + NEC_LSB, // lsb_first: flag: LSB first + NEC_FLAGS // flags: some flags +}; + +static const PROGMEM IRMP_PARAMETER nec_rep_param = +{ + IRMP_NEC_PROTOCOL, // protocol: ir protocol + NEC_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 + NEC_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 + NEC_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 + NEC_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 + NEC_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 + NEC_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 + NEC_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 + NEC_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 + 0, // address_offset: address offset + 0, // address_end: end of address + 0, // command_offset: command offset + 0, // command_end: end of command + 0, // complete_len: complete length of frame + NEC_STOP_BIT, // stop_bit: flag: frame has stop bit + NEC_LSB, // lsb_first: flag: LSB first + NEC_FLAGS // flags: some flags +}; + +#endif + +#if IRMP_SUPPORT_NEC42_PROTOCOL == 1 + +static const PROGMEM IRMP_PARAMETER nec42_param = +{ + IRMP_NEC42_PROTOCOL, // protocol: ir protocol + NEC_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 + NEC_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 + NEC_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 + NEC_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 + NEC_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 + NEC_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 + NEC_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 + NEC_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 + NEC42_ADDRESS_OFFSET, // address_offset: address offset + NEC42_ADDRESS_OFFSET + NEC42_ADDRESS_LEN, // address_end: end of address + NEC42_COMMAND_OFFSET, // command_offset: command offset + NEC42_COMMAND_OFFSET + NEC42_COMMAND_LEN, // command_end: end of command + NEC42_COMPLETE_DATA_LEN, // complete_len: complete length of frame + NEC_STOP_BIT, // stop_bit: flag: frame has stop bit + NEC_LSB, // lsb_first: flag: LSB first + NEC_FLAGS // flags: some flags +}; + +#endif + +#if IRMP_SUPPORT_LGAIR_PROTOCOL == 1 + +static const PROGMEM IRMP_PARAMETER lgair_param = +{ + IRMP_LGAIR_PROTOCOL, // protocol: ir protocol + NEC_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 + NEC_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 + NEC_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 + NEC_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 + NEC_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 + NEC_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 + NEC_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 + NEC_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 + LGAIR_ADDRESS_OFFSET, // address_offset: address offset + LGAIR_ADDRESS_OFFSET + LGAIR_ADDRESS_LEN, // address_end: end of address + LGAIR_COMMAND_OFFSET, // command_offset: command offset + LGAIR_COMMAND_OFFSET + LGAIR_COMMAND_LEN, // command_end: end of command + LGAIR_COMPLETE_DATA_LEN, // complete_len: complete length of frame + NEC_STOP_BIT, // stop_bit: flag: frame has stop bit + NEC_LSB, // lsb_first: flag: LSB first + NEC_FLAGS // flags: some flags +}; + +#endif + +#if IRMP_SUPPORT_SAMSUNG_PROTOCOL == 1 + +static const PROGMEM IRMP_PARAMETER samsung_param = +{ + IRMP_SAMSUNG_PROTOCOL, // protocol: ir protocol + SAMSUNG_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 + SAMSUNG_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 + SAMSUNG_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 + SAMSUNG_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 + SAMSUNG_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 + SAMSUNG_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 + SAMSUNG_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 + SAMSUNG_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 + SAMSUNG_ADDRESS_OFFSET, // address_offset: address offset + SAMSUNG_ADDRESS_OFFSET + SAMSUNG_ADDRESS_LEN, // address_end: end of address + SAMSUNG_COMMAND_OFFSET, // command_offset: command offset + SAMSUNG_COMMAND_OFFSET + SAMSUNG_COMMAND_LEN, // command_end: end of command + SAMSUNG_COMPLETE_DATA_LEN, // complete_len: complete length of frame + SAMSUNG_STOP_BIT, // stop_bit: flag: frame has stop bit + SAMSUNG_LSB, // lsb_first: flag: LSB first + SAMSUNG_FLAGS // flags: some flags +}; + +#endif + +#if IRMP_SUPPORT_SAMSUNGAH_PROTOCOL == 1 + +static const PROGMEM IRMP_PARAMETER samsungah_param = +{ + IRMP_SAMSUNGAH_PROTOCOL, // protocol: ir protocol + SAMSUNGAH_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 + SAMSUNGAH_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 + SAMSUNGAH_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 + SAMSUNGAH_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 + SAMSUNGAH_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 + SAMSUNGAH_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 + SAMSUNGAH_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 + SAMSUNGAH_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 + SAMSUNGAH_ADDRESS_OFFSET, // address_offset: address offset + SAMSUNGAH_ADDRESS_OFFSET + SAMSUNGAH_ADDRESS_LEN, // address_end: end of address + SAMSUNGAH_COMMAND_OFFSET, // command_offset: command offset + SAMSUNGAH_COMMAND_OFFSET + SAMSUNGAH_COMMAND_LEN, // command_end: end of command + SAMSUNGAH_COMPLETE_DATA_LEN, // complete_len: complete length of frame + SAMSUNGAH_STOP_BIT, // stop_bit: flag: frame has stop bit + SAMSUNGAH_LSB, // lsb_first: flag: LSB first + SAMSUNGAH_FLAGS // flags: some flags +}; + +#endif + +#if IRMP_SUPPORT_TELEFUNKEN_PROTOCOL == 1 + +static const PROGMEM IRMP_PARAMETER telefunken_param = +{ + IRMP_TELEFUNKEN_PROTOCOL, // protocol: ir protocol + TELEFUNKEN_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 + TELEFUNKEN_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 + TELEFUNKEN_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 + TELEFUNKEN_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 + TELEFUNKEN_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 + TELEFUNKEN_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 + TELEFUNKEN_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 + TELEFUNKEN_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 + TELEFUNKEN_ADDRESS_OFFSET, // address_offset: address offset + TELEFUNKEN_ADDRESS_OFFSET + TELEFUNKEN_ADDRESS_LEN, // address_end: end of address + TELEFUNKEN_COMMAND_OFFSET, // command_offset: command offset + TELEFUNKEN_COMMAND_OFFSET + TELEFUNKEN_COMMAND_LEN, // command_end: end of command + TELEFUNKEN_COMPLETE_DATA_LEN, // complete_len: complete length of frame + TELEFUNKEN_STOP_BIT, // stop_bit: flag: frame has stop bit + TELEFUNKEN_LSB, // lsb_first: flag: LSB first + TELEFUNKEN_FLAGS // flags: some flags +}; + +#endif + +#if IRMP_SUPPORT_MATSUSHITA_PROTOCOL == 1 + +static const PROGMEM IRMP_PARAMETER matsushita_param = +{ + IRMP_MATSUSHITA_PROTOCOL, // protocol: ir protocol + MATSUSHITA_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 + MATSUSHITA_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 + MATSUSHITA_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 + MATSUSHITA_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 + MATSUSHITA_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 + MATSUSHITA_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 + MATSUSHITA_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 + MATSUSHITA_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 + MATSUSHITA_ADDRESS_OFFSET, // address_offset: address offset + MATSUSHITA_ADDRESS_OFFSET + MATSUSHITA_ADDRESS_LEN, // address_end: end of address + MATSUSHITA_COMMAND_OFFSET, // command_offset: command offset + MATSUSHITA_COMMAND_OFFSET + MATSUSHITA_COMMAND_LEN, // command_end: end of command + MATSUSHITA_COMPLETE_DATA_LEN, // complete_len: complete length of frame + MATSUSHITA_STOP_BIT, // stop_bit: flag: frame has stop bit + MATSUSHITA_LSB, // lsb_first: flag: LSB first + MATSUSHITA_FLAGS // flags: some flags +}; + +#endif + +#if IRMP_SUPPORT_KASEIKYO_PROTOCOL == 1 + +static const PROGMEM IRMP_PARAMETER kaseikyo_param = +{ + IRMP_KASEIKYO_PROTOCOL, // protocol: ir protocol + KASEIKYO_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 + KASEIKYO_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 + KASEIKYO_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 + KASEIKYO_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 + KASEIKYO_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 + KASEIKYO_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 + KASEIKYO_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 + KASEIKYO_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 + KASEIKYO_ADDRESS_OFFSET, // address_offset: address offset + KASEIKYO_ADDRESS_OFFSET + KASEIKYO_ADDRESS_LEN, // address_end: end of address + KASEIKYO_COMMAND_OFFSET, // command_offset: command offset + KASEIKYO_COMMAND_OFFSET + KASEIKYO_COMMAND_LEN, // command_end: end of command + KASEIKYO_COMPLETE_DATA_LEN, // complete_len: complete length of frame + KASEIKYO_STOP_BIT, // stop_bit: flag: frame has stop bit + KASEIKYO_LSB, // lsb_first: flag: LSB first + KASEIKYO_FLAGS // flags: some flags +}; + +#endif + +#if IRMP_SUPPORT_PANASONIC_PROTOCOL == 1 + +static const PROGMEM IRMP_PARAMETER panasonic_param = +{ + IRMP_PANASONIC_PROTOCOL, // protocol: ir protocol + PANASONIC_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 + PANASONIC_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 + PANASONIC_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 + PANASONIC_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 + PANASONIC_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 + PANASONIC_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 + PANASONIC_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 + PANASONIC_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 + PANASONIC_ADDRESS_OFFSET, // address_offset: address offset + PANASONIC_ADDRESS_OFFSET + PANASONIC_ADDRESS_LEN, // address_end: end of address + PANASONIC_COMMAND_OFFSET, // command_offset: command offset + PANASONIC_COMMAND_OFFSET + PANASONIC_COMMAND_LEN, // command_end: end of command + PANASONIC_COMPLETE_DATA_LEN, // complete_len: complete length of frame + PANASONIC_STOP_BIT, // stop_bit: flag: frame has stop bit + PANASONIC_LSB, // lsb_first: flag: LSB first + PANASONIC_FLAGS // flags: some flags +}; + +#endif + +#if IRMP_SUPPORT_MITSU_HEAVY_PROTOCOL == 1 + +static const PROGMEM IRMP_PARAMETER mitsu_heavy_param = +{ + IRMP_MITSU_HEAVY_PROTOCOL, // protocol: ir protocol + MITSU_HEAVY_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 + MITSU_HEAVY_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 + MITSU_HEAVY_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 + MITSU_HEAVY_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 + MITSU_HEAVY_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 + MITSU_HEAVY_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 + MITSU_HEAVY_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 + MITSU_HEAVY_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 + MITSU_HEAVY_ADDRESS_OFFSET, // address_offset: address offset + MITSU_HEAVY_ADDRESS_OFFSET + MITSU_HEAVY_ADDRESS_LEN, // address_end: end of address + MITSU_HEAVY_COMMAND_OFFSET, // command_offset: command offset + MITSU_HEAVY_COMMAND_OFFSET + MITSU_HEAVY_COMMAND_LEN, // command_end: end of command + MITSU_HEAVY_COMPLETE_DATA_LEN, // complete_len: complete length of frame + MITSU_HEAVY_STOP_BIT, // stop_bit: flag: frame has stop bit + MITSU_HEAVY_LSB, // lsb_first: flag: LSB first + MITSU_HEAVY_FLAGS // flags: some flags +}; + +#endif + +#if IRMP_SUPPORT_VINCENT_PROTOCOL == 1 + +static const PROGMEM IRMP_PARAMETER vincent_param = +{ + IRMP_VINCENT_PROTOCOL, // protocol: ir protocol + VINCENT_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 + VINCENT_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 + VINCENT_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 + VINCENT_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 + VINCENT_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 + VINCENT_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 + VINCENT_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 + VINCENT_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 + VINCENT_ADDRESS_OFFSET, // address_offset: address offset + VINCENT_ADDRESS_OFFSET + VINCENT_ADDRESS_LEN, // address_end: end of address + VINCENT_COMMAND_OFFSET, // command_offset: command offset + VINCENT_COMMAND_OFFSET + VINCENT_COMMAND_LEN, // command_end: end of command + VINCENT_COMPLETE_DATA_LEN, // complete_len: complete length of frame + VINCENT_STOP_BIT, // stop_bit: flag: frame has stop bit + VINCENT_LSB, // lsb_first: flag: LSB first + VINCENT_FLAGS // flags: some flags +}; + +#endif + +#if IRMP_SUPPORT_RECS80_PROTOCOL == 1 + +static const PROGMEM IRMP_PARAMETER recs80_param = +{ + IRMP_RECS80_PROTOCOL, // protocol: ir protocol + RECS80_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 + RECS80_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 + RECS80_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 + RECS80_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 + RECS80_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 + RECS80_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 + RECS80_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 + RECS80_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 + RECS80_ADDRESS_OFFSET, // address_offset: address offset + RECS80_ADDRESS_OFFSET + RECS80_ADDRESS_LEN, // address_end: end of address + RECS80_COMMAND_OFFSET, // command_offset: command offset + RECS80_COMMAND_OFFSET + RECS80_COMMAND_LEN, // command_end: end of command + RECS80_COMPLETE_DATA_LEN, // complete_len: complete length of frame + RECS80_STOP_BIT, // stop_bit: flag: frame has stop bit + RECS80_LSB, // lsb_first: flag: LSB first + RECS80_FLAGS // flags: some flags +}; + +#endif + +#if IRMP_SUPPORT_RC5_PROTOCOL == 1 + +static const PROGMEM IRMP_PARAMETER rc5_param = +{ + IRMP_RC5_PROTOCOL, // protocol: ir protocol + RC5_BIT_LEN_MIN, // pulse_1_len_min: here: minimum length of short pulse + RC5_BIT_LEN_MAX, // pulse_1_len_max: here: maximum length of short pulse + RC5_BIT_LEN_MIN, // pause_1_len_min: here: minimum length of short pause + RC5_BIT_LEN_MAX, // pause_1_len_max: here: maximum length of short pause + 0, // pulse_0_len_min: here: not used + 0, // pulse_0_len_max: here: not used + 0, // pause_0_len_min: here: not used + 0, // pause_0_len_max: here: not used + RC5_ADDRESS_OFFSET, // address_offset: address offset + RC5_ADDRESS_OFFSET + RC5_ADDRESS_LEN, // address_end: end of address + RC5_COMMAND_OFFSET, // command_offset: command offset + RC5_COMMAND_OFFSET + RC5_COMMAND_LEN, // command_end: end of command + RC5_COMPLETE_DATA_LEN, // complete_len: complete length of frame + RC5_STOP_BIT, // stop_bit: flag: frame has stop bit + RC5_LSB, // lsb_first: flag: LSB first + RC5_FLAGS // flags: some flags +}; + +#endif + +#if IRMP_SUPPORT_RCII_PROTOCOL == 1 + +static const PROGMEM IRMP_PARAMETER rcii_param = +{ + IRMP_RCII_PROTOCOL, // protocol: ir protocol + RCII_BIT_LEN_MIN, // pulse_1_len_min: here: minimum length of short pulse + RCII_BIT_LEN_MAX, // pulse_1_len_max: here: maximum length of short pulse + RCII_BIT_LEN_MIN, // pause_1_len_min: here: minimum length of short pause + RCII_BIT_LEN_MAX, // pause_1_len_max: here: maximum length of short pause + RCII_BIT_LEN_MIN, // pulse_0_len_min: here: not used + RCII_BIT_LEN_MAX, // pulse_0_len_max: here: not used + RCII_BIT_LEN_MIN, // pause_0_len_min: here: not used + RCII_BIT_LEN_MAX, // pause_0_len_max: here: not used + RCII_ADDRESS_OFFSET, // address_offset: address offset + RCII_ADDRESS_OFFSET + RCII_ADDRESS_LEN, // address_end: end of address + RCII_COMMAND_OFFSET, // command_offset: command offset + RCII_COMMAND_OFFSET + RCII_COMMAND_LEN, // command_end: end of command + RCII_COMPLETE_DATA_LEN, // complete_len: complete length of frame + RCII_STOP_BIT, // stop_bit: flag: frame has stop bit + RCII_LSB, // lsb_first: flag: LSB first + RCII_FLAGS // flags: some flags +}; + +#endif + +#if IRMP_SUPPORT_S100_PROTOCOL == 1 + +static const PROGMEM IRMP_PARAMETER s100_param = +{ + IRMP_S100_PROTOCOL, // protocol: ir protocol + S100_BIT_LEN_MIN, // pulse_1_len_min: here: minimum length of short pulse + S100_BIT_LEN_MAX, // pulse_1_len_max: here: maximum length of short pulse + S100_BIT_LEN_MIN, // pause_1_len_min: here: minimum length of short pause + S100_BIT_LEN_MAX, // pause_1_len_max: here: maximum length of short pause + 0, // pulse_0_len_min: here: not used + 0, // pulse_0_len_max: here: not used + 0, // pause_0_len_min: here: not used + 0, // pause_0_len_max: here: not used + S100_ADDRESS_OFFSET, // address_offset: address offset + S100_ADDRESS_OFFSET + S100_ADDRESS_LEN, // address_end: end of address + S100_COMMAND_OFFSET, // command_offset: command offset + S100_COMMAND_OFFSET + S100_COMMAND_LEN, // command_end: end of command + S100_COMPLETE_DATA_LEN, // complete_len: complete length of frame + S100_STOP_BIT, // stop_bit: flag: frame has stop bit + S100_LSB, // lsb_first: flag: LSB first + S100_FLAGS // flags: some flags +}; + +#endif + +#if IRMP_SUPPORT_DENON_PROTOCOL == 1 + +static const PROGMEM IRMP_PARAMETER denon_param = +{ + IRMP_DENON_PROTOCOL, // protocol: ir protocol + DENON_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 + DENON_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 + DENON_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 + DENON_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 + DENON_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 + DENON_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 + DENON_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 + DENON_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 + DENON_ADDRESS_OFFSET, // address_offset: address offset + DENON_ADDRESS_OFFSET + DENON_ADDRESS_LEN, // address_end: end of address + DENON_COMMAND_OFFSET, // command_offset: command offset + DENON_COMMAND_OFFSET + DENON_COMMAND_LEN, // command_end: end of command + DENON_COMPLETE_DATA_LEN, // complete_len: complete length of frame + DENON_STOP_BIT, // stop_bit: flag: frame has stop bit + DENON_LSB, // lsb_first: flag: LSB first + DENON_FLAGS // flags: some flags +}; + +#endif + +#if IRMP_SUPPORT_RC6_PROTOCOL == 1 + +static const PROGMEM IRMP_PARAMETER rc6_param = +{ + IRMP_RC6_PROTOCOL, // protocol: ir protocol + + RC6_BIT_PULSE_LEN_MIN, // pulse_1_len_min: here: minimum length of short pulse + RC6_BIT_PULSE_LEN_MAX, // pulse_1_len_max: here: maximum length of short pulse + RC6_BIT_PAUSE_LEN_MIN, // pause_1_len_min: here: minimum length of short pause + RC6_BIT_PAUSE_LEN_MAX, // pause_1_len_max: here: maximum length of short pause + 0, // pulse_0_len_min: here: not used + 0, // pulse_0_len_max: here: not used + 0, // pause_0_len_min: here: not used + 0, // pause_0_len_max: here: not used + RC6_ADDRESS_OFFSET, // address_offset: address offset + RC6_ADDRESS_OFFSET + RC6_ADDRESS_LEN, // address_end: end of address + RC6_COMMAND_OFFSET, // command_offset: command offset + RC6_COMMAND_OFFSET + RC6_COMMAND_LEN, // command_end: end of command + RC6_COMPLETE_DATA_LEN_SHORT, // complete_len: complete length of frame + RC6_STOP_BIT, // stop_bit: flag: frame has stop bit + RC6_LSB, // lsb_first: flag: LSB first + RC6_FLAGS // flags: some flags +}; + +#endif + +#if IRMP_SUPPORT_RECS80EXT_PROTOCOL == 1 + +static const PROGMEM IRMP_PARAMETER recs80ext_param = +{ + IRMP_RECS80EXT_PROTOCOL, // protocol: ir protocol + RECS80EXT_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 + RECS80EXT_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 + RECS80EXT_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 + RECS80EXT_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 + RECS80EXT_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 + RECS80EXT_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 + RECS80EXT_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 + RECS80EXT_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 + RECS80EXT_ADDRESS_OFFSET, // address_offset: address offset + RECS80EXT_ADDRESS_OFFSET + RECS80EXT_ADDRESS_LEN, // address_end: end of address + RECS80EXT_COMMAND_OFFSET, // command_offset: command offset + RECS80EXT_COMMAND_OFFSET + RECS80EXT_COMMAND_LEN, // command_end: end of command + RECS80EXT_COMPLETE_DATA_LEN, // complete_len: complete length of frame + RECS80EXT_STOP_BIT, // stop_bit: flag: frame has stop bit + RECS80EXT_LSB, // lsb_first: flag: LSB first + RECS80EXT_FLAGS // flags: some flags +}; + +#endif + +#if IRMP_SUPPORT_NUBERT_PROTOCOL == 1 + +static const PROGMEM IRMP_PARAMETER nubert_param = +{ + IRMP_NUBERT_PROTOCOL, // protocol: ir protocol + NUBERT_1_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 + NUBERT_1_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 + NUBERT_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 + NUBERT_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 + NUBERT_0_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 + NUBERT_0_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 + NUBERT_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 + NUBERT_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 + NUBERT_ADDRESS_OFFSET, // address_offset: address offset + NUBERT_ADDRESS_OFFSET + NUBERT_ADDRESS_LEN, // address_end: end of address + NUBERT_COMMAND_OFFSET, // command_offset: command offset + NUBERT_COMMAND_OFFSET + NUBERT_COMMAND_LEN, // command_end: end of command + NUBERT_COMPLETE_DATA_LEN, // complete_len: complete length of frame + NUBERT_STOP_BIT, // stop_bit: flag: frame has stop bit + NUBERT_LSB, // lsb_first: flag: LSB first + NUBERT_FLAGS // flags: some flags +}; + +#endif + +#if IRMP_SUPPORT_FAN_PROTOCOL == 1 + +static const PROGMEM IRMP_PARAMETER fan_param = +{ + IRMP_FAN_PROTOCOL, // protocol: ir protocol + FAN_1_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 + FAN_1_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 + FAN_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 + FAN_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 + FAN_0_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 + FAN_0_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 + FAN_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 + FAN_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 + FAN_ADDRESS_OFFSET, // address_offset: address offset + FAN_ADDRESS_OFFSET + FAN_ADDRESS_LEN, // address_end: end of address + FAN_COMMAND_OFFSET, // command_offset: command offset + FAN_COMMAND_OFFSET + FAN_COMMAND_LEN, // command_end: end of command + FAN_COMPLETE_DATA_LEN, // complete_len: complete length of frame + FAN_STOP_BIT, // stop_bit: flag: frame has NO stop bit + FAN_LSB, // lsb_first: flag: LSB first + FAN_FLAGS // flags: some flags +}; + +#endif + +#if IRMP_SUPPORT_SPEAKER_PROTOCOL == 1 + +static const PROGMEM IRMP_PARAMETER speaker_param = +{ + IRMP_SPEAKER_PROTOCOL, // protocol: ir protocol + SPEAKER_1_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 + SPEAKER_1_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 + SPEAKER_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 + SPEAKER_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 + SPEAKER_0_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 + SPEAKER_0_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 + SPEAKER_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 + SPEAKER_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 + SPEAKER_ADDRESS_OFFSET, // address_offset: address offset + SPEAKER_ADDRESS_OFFSET + SPEAKER_ADDRESS_LEN, // address_end: end of address + SPEAKER_COMMAND_OFFSET, // command_offset: command offset + SPEAKER_COMMAND_OFFSET + SPEAKER_COMMAND_LEN, // command_end: end of command + SPEAKER_COMPLETE_DATA_LEN, // complete_len: complete length of frame + SPEAKER_STOP_BIT, // stop_bit: flag: frame has stop bit + SPEAKER_LSB, // lsb_first: flag: LSB first + SPEAKER_FLAGS // flags: some flags +}; + +#endif + +#if IRMP_SUPPORT_BANG_OLUFSEN_PROTOCOL == 1 + +static const PROGMEM IRMP_PARAMETER bang_olufsen_param = +{ + IRMP_BANG_OLUFSEN_PROTOCOL, // protocol: ir protocol + BANG_OLUFSEN_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 + BANG_OLUFSEN_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 + BANG_OLUFSEN_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 + BANG_OLUFSEN_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 + BANG_OLUFSEN_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 + BANG_OLUFSEN_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 + BANG_OLUFSEN_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 + BANG_OLUFSEN_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 + BANG_OLUFSEN_ADDRESS_OFFSET, // address_offset: address offset + BANG_OLUFSEN_ADDRESS_OFFSET + BANG_OLUFSEN_ADDRESS_LEN, // address_end: end of address + BANG_OLUFSEN_COMMAND_OFFSET, // command_offset: command offset + BANG_OLUFSEN_COMMAND_OFFSET + BANG_OLUFSEN_COMMAND_LEN, // command_end: end of command + BANG_OLUFSEN_COMPLETE_DATA_LEN, // complete_len: complete length of frame + BANG_OLUFSEN_STOP_BIT, // stop_bit: flag: frame has stop bit + BANG_OLUFSEN_LSB, // lsb_first: flag: LSB first + BANG_OLUFSEN_FLAGS // flags: some flags +}; + +#endif + +#if IRMP_SUPPORT_GRUNDIG_NOKIA_IR60_PROTOCOL == 1 + +static uint_fast8_t first_bit; + +static const PROGMEM IRMP_PARAMETER grundig_param = +{ + IRMP_GRUNDIG_PROTOCOL, // protocol: ir protocol + + GRUNDIG_NOKIA_IR60_BIT_LEN_MIN, // pulse_1_len_min: here: minimum length of short pulse + GRUNDIG_NOKIA_IR60_BIT_LEN_MAX, // pulse_1_len_max: here: maximum length of short pulse + GRUNDIG_NOKIA_IR60_BIT_LEN_MIN, // pause_1_len_min: here: minimum length of short pause + GRUNDIG_NOKIA_IR60_BIT_LEN_MAX, // pause_1_len_max: here: maximum length of short pause + 0, // pulse_0_len_min: here: not used + 0, // pulse_0_len_max: here: not used + 0, // pause_0_len_min: here: not used + 0, // pause_0_len_max: here: not used + GRUNDIG_ADDRESS_OFFSET, // address_offset: address offset + GRUNDIG_ADDRESS_OFFSET + GRUNDIG_ADDRESS_LEN, // address_end: end of address + GRUNDIG_COMMAND_OFFSET, // command_offset: command offset + GRUNDIG_COMMAND_OFFSET + GRUNDIG_COMMAND_LEN + 1, // command_end: end of command (USE 1 bit MORE to STORE NOKIA DATA!) + NOKIA_COMPLETE_DATA_LEN, // complete_len: complete length of frame, here: NOKIA instead of GRUNDIG! + GRUNDIG_NOKIA_IR60_STOP_BIT, // stop_bit: flag: frame has stop bit + GRUNDIG_NOKIA_IR60_LSB, // lsb_first: flag: LSB first + GRUNDIG_NOKIA_IR60_FLAGS // flags: some flags +}; + +#endif + +#if IRMP_SUPPORT_SIEMENS_OR_RUWIDO_PROTOCOL == 1 + +static const PROGMEM IRMP_PARAMETER ruwido_param = +{ + IRMP_RUWIDO_PROTOCOL, // protocol: ir protocol + SIEMENS_OR_RUWIDO_BIT_PULSE_LEN_MIN, // pulse_1_len_min: here: minimum length of short pulse + SIEMENS_OR_RUWIDO_BIT_PULSE_LEN_MAX, // pulse_1_len_max: here: maximum length of short pulse + SIEMENS_OR_RUWIDO_BIT_PAUSE_LEN_MIN, // pause_1_len_min: here: minimum length of short pause + SIEMENS_OR_RUWIDO_BIT_PAUSE_LEN_MAX, // pause_1_len_max: here: maximum length of short pause + 0, // pulse_0_len_min: here: not used + 0, // pulse_0_len_max: here: not used + 0, // pause_0_len_min: here: not used + 0, // pause_0_len_max: here: not used + RUWIDO_ADDRESS_OFFSET, // address_offset: address offset + RUWIDO_ADDRESS_OFFSET + RUWIDO_ADDRESS_LEN, // address_end: end of address + RUWIDO_COMMAND_OFFSET, // command_offset: command offset + RUWIDO_COMMAND_OFFSET + RUWIDO_COMMAND_LEN, // command_end: end of command + SIEMENS_COMPLETE_DATA_LEN, // complete_len: complete length of frame, here: SIEMENS instead of RUWIDO! + SIEMENS_OR_RUWIDO_STOP_BIT, // stop_bit: flag: frame has stop bit + SIEMENS_OR_RUWIDO_LSB, // lsb_first: flag: LSB first + SIEMENS_OR_RUWIDO_FLAGS // flags: some flags +}; + +#endif + +#if IRMP_SUPPORT_FDC_PROTOCOL == 1 + +static const PROGMEM IRMP_PARAMETER fdc_param = +{ + IRMP_FDC_PROTOCOL, // protocol: ir protocol + FDC_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 + FDC_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 + FDC_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 + FDC_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 + FDC_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 + FDC_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 + FDC_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 + FDC_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 + FDC_ADDRESS_OFFSET, // address_offset: address offset + FDC_ADDRESS_OFFSET + FDC_ADDRESS_LEN, // address_end: end of address + FDC_COMMAND_OFFSET, // command_offset: command offset + FDC_COMMAND_OFFSET + FDC_COMMAND_LEN, // command_end: end of command + FDC_COMPLETE_DATA_LEN, // complete_len: complete length of frame + FDC_STOP_BIT, // stop_bit: flag: frame has stop bit + FDC_LSB, // lsb_first: flag: LSB first + FDC_FLAGS // flags: some flags +}; + +#endif + +#if IRMP_SUPPORT_RCCAR_PROTOCOL == 1 + +static const PROGMEM IRMP_PARAMETER rccar_param = +{ + IRMP_RCCAR_PROTOCOL, // protocol: ir protocol + RCCAR_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 + RCCAR_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 + RCCAR_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 + RCCAR_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 + RCCAR_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 + RCCAR_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 + RCCAR_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 + RCCAR_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 + RCCAR_ADDRESS_OFFSET, // address_offset: address offset + RCCAR_ADDRESS_OFFSET + RCCAR_ADDRESS_LEN, // address_end: end of address + RCCAR_COMMAND_OFFSET, // command_offset: command offset + RCCAR_COMMAND_OFFSET + RCCAR_COMMAND_LEN, // command_end: end of command + RCCAR_COMPLETE_DATA_LEN, // complete_len: complete length of frame + RCCAR_STOP_BIT, // stop_bit: flag: frame has stop bit + RCCAR_LSB, // lsb_first: flag: LSB first + RCCAR_FLAGS // flags: some flags +}; + +#endif + +#if IRMP_SUPPORT_NIKON_PROTOCOL == 1 + +static const PROGMEM IRMP_PARAMETER nikon_param = +{ + IRMP_NIKON_PROTOCOL, // protocol: ir protocol + NIKON_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 + NIKON_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 + NIKON_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 + NIKON_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 + NIKON_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 + NIKON_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 + NIKON_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 + NIKON_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 + NIKON_ADDRESS_OFFSET, // address_offset: address offset + NIKON_ADDRESS_OFFSET + NIKON_ADDRESS_LEN, // address_end: end of address + NIKON_COMMAND_OFFSET, // command_offset: command offset + NIKON_COMMAND_OFFSET + NIKON_COMMAND_LEN, // command_end: end of command + NIKON_COMPLETE_DATA_LEN, // complete_len: complete length of frame + NIKON_STOP_BIT, // stop_bit: flag: frame has stop bit + NIKON_LSB, // lsb_first: flag: LSB first + NIKON_FLAGS // flags: some flags +}; + +#endif + +#if IRMP_SUPPORT_KATHREIN_PROTOCOL == 1 + +static const PROGMEM IRMP_PARAMETER kathrein_param = +{ + IRMP_KATHREIN_PROTOCOL, // protocol: ir protocol + KATHREIN_1_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 + KATHREIN_1_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 + KATHREIN_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 + KATHREIN_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 + KATHREIN_0_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 + KATHREIN_0_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 + KATHREIN_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 + KATHREIN_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 + KATHREIN_ADDRESS_OFFSET, // address_offset: address offset + KATHREIN_ADDRESS_OFFSET + KATHREIN_ADDRESS_LEN, // address_end: end of address + KATHREIN_COMMAND_OFFSET, // command_offset: command offset + KATHREIN_COMMAND_OFFSET + KATHREIN_COMMAND_LEN, // command_end: end of command + KATHREIN_COMPLETE_DATA_LEN, // complete_len: complete length of frame + KATHREIN_STOP_BIT, // stop_bit: flag: frame has stop bit + KATHREIN_LSB, // lsb_first: flag: LSB first + KATHREIN_FLAGS // flags: some flags +}; + +#endif + +#if IRMP_SUPPORT_NETBOX_PROTOCOL == 1 + +static const PROGMEM IRMP_PARAMETER netbox_param = +{ + IRMP_NETBOX_PROTOCOL, // protocol: ir protocol + NETBOX_PULSE_LEN, // pulse_1_len_min: minimum length of pulse with bit value 1, here: exact value + NETBOX_PULSE_REST_LEN, // pulse_1_len_max: maximum length of pulse with bit value 1, here: rest value + NETBOX_PAUSE_LEN, // pause_1_len_min: minimum length of pause with bit value 1, here: exact value + NETBOX_PAUSE_REST_LEN, // pause_1_len_max: maximum length of pause with bit value 1, here: rest value + NETBOX_PULSE_LEN, // pulse_0_len_min: minimum length of pulse with bit value 0, here: exact value + NETBOX_PULSE_REST_LEN, // pulse_0_len_max: maximum length of pulse with bit value 0, here: rest value + NETBOX_PAUSE_LEN, // pause_0_len_min: minimum length of pause with bit value 0, here: exact value + NETBOX_PAUSE_REST_LEN, // pause_0_len_max: maximum length of pause with bit value 0, here: rest value + NETBOX_ADDRESS_OFFSET, // address_offset: address offset + NETBOX_ADDRESS_OFFSET + NETBOX_ADDRESS_LEN, // address_end: end of address + NETBOX_COMMAND_OFFSET, // command_offset: command offset + NETBOX_COMMAND_OFFSET + NETBOX_COMMAND_LEN, // command_end: end of command + NETBOX_COMPLETE_DATA_LEN, // complete_len: complete length of frame + NETBOX_STOP_BIT, // stop_bit: flag: frame has stop bit + NETBOX_LSB, // lsb_first: flag: LSB first + NETBOX_FLAGS // flags: some flags +}; + +#endif + +#if IRMP_SUPPORT_LEGO_PROTOCOL == 1 + +static const PROGMEM IRMP_PARAMETER lego_param = +{ + IRMP_LEGO_PROTOCOL, // protocol: ir protocol + LEGO_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 + LEGO_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 + LEGO_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 + LEGO_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 + LEGO_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 + LEGO_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 + LEGO_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 + LEGO_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 + LEGO_ADDRESS_OFFSET, // address_offset: address offset + LEGO_ADDRESS_OFFSET + LEGO_ADDRESS_LEN, // address_end: end of address + LEGO_COMMAND_OFFSET, // command_offset: command offset + LEGO_COMMAND_OFFSET + LEGO_COMMAND_LEN, // command_end: end of command + LEGO_COMPLETE_DATA_LEN, // complete_len: complete length of frame + LEGO_STOP_BIT, // stop_bit: flag: frame has stop bit + LEGO_LSB, // lsb_first: flag: LSB first + LEGO_FLAGS // flags: some flags +}; + +#endif + +#if IRMP_SUPPORT_IRMP16_PROTOCOL == 1 + +static const PROGMEM IRMP_PARAMETER irmp16_param = +{ + IRMP_IRMP16_PROTOCOL, // protocol: ir protocol + IRMP16_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 + IRMP16_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 + IRMP16_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 + IRMP16_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 + IRMP16_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 + IRMP16_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 + IRMP16_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 + IRMP16_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 + IRMP16_ADDRESS_OFFSET, // address_offset: address offset + IRMP16_ADDRESS_OFFSET + IRMP16_ADDRESS_LEN, // address_end: end of address + IRMP16_COMMAND_OFFSET, // command_offset: command offset + IRMP16_COMMAND_OFFSET + IRMP16_COMMAND_LEN, // command_end: end of command + IRMP16_COMPLETE_DATA_LEN, // complete_len: complete length of frame + IRMP16_STOP_BIT, // stop_bit: flag: frame has stop bit + IRMP16_LSB, // lsb_first: flag: LSB first + IRMP16_FLAGS // flags: some flags +}; + +#endif + +#if IRMP_SUPPORT_GREE_PROTOCOL == 1 + +static const PROGMEM IRMP_PARAMETER gree_param = +{ + IRMP_GREE_PROTOCOL, // protocol: ir protocol + GREE_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 + GREE_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 + GREE_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 + GREE_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 + GREE_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 + GREE_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 + GREE_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 + GREE_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 + GREE_ADDRESS_OFFSET, // address_offset: address offset + GREE_ADDRESS_OFFSET + GREE_ADDRESS_LEN, // address_end: end of address + GREE_COMMAND_OFFSET, // command_offset: command offset + GREE_COMMAND_OFFSET + GREE_COMMAND_LEN, // command_end: end of command + GREE_COMPLETE_DATA_LEN, // complete_len: complete length of frame + GREE_STOP_BIT, // stop_bit: flag: frame has stop bit + GREE_LSB, // lsb_first: flag: LSB first + GREE_FLAGS // flags: some flags +}; + +#endif + +#if IRMP_SUPPORT_THOMSON_PROTOCOL == 1 + +static const PROGMEM IRMP_PARAMETER thomson_param = +{ + IRMP_THOMSON_PROTOCOL, // protocol: ir protocol + THOMSON_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 + THOMSON_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 + THOMSON_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 + THOMSON_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 + THOMSON_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 + THOMSON_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 + THOMSON_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 + THOMSON_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 + THOMSON_ADDRESS_OFFSET, // address_offset: address offset + THOMSON_ADDRESS_OFFSET + THOMSON_ADDRESS_LEN, // address_end: end of address + THOMSON_COMMAND_OFFSET, // command_offset: command offset + THOMSON_COMMAND_OFFSET + THOMSON_COMMAND_LEN, // command_end: end of command + THOMSON_COMPLETE_DATA_LEN, // complete_len: complete length of frame + THOMSON_STOP_BIT, // stop_bit: flag: frame has stop bit + THOMSON_LSB, // lsb_first: flag: LSB first + THOMSON_FLAGS // flags: some flags +}; + +#endif + +#if IRMP_SUPPORT_BOSE_PROTOCOL == 1 + +static const PROGMEM IRMP_PARAMETER bose_param = +{ + IRMP_BOSE_PROTOCOL, // protocol: ir protocol + BOSE_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 + BOSE_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 + BOSE_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 + BOSE_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 + BOSE_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 + BOSE_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 + BOSE_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 + BOSE_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 + BOSE_ADDRESS_OFFSET, // address_offset: address offset + BOSE_ADDRESS_OFFSET + BOSE_ADDRESS_LEN, // address_end: end of address + BOSE_COMMAND_OFFSET, // command_offset: command offset + BOSE_COMMAND_OFFSET + BOSE_COMMAND_LEN, // command_end: end of command + BOSE_COMPLETE_DATA_LEN, // complete_len: complete length of frame + BOSE_STOP_BIT, // stop_bit: flag: frame has stop bit + BOSE_LSB, // lsb_first: flag: LSB first + BOSE_FLAGS // flags: some flags +}; + +#endif + +#if IRMP_SUPPORT_A1TVBOX_PROTOCOL == 1 + +static const PROGMEM IRMP_PARAMETER a1tvbox_param = +{ + IRMP_A1TVBOX_PROTOCOL, // protocol: ir protocol + + A1TVBOX_BIT_PULSE_LEN_MIN, // pulse_1_len_min: here: minimum length of short pulse + A1TVBOX_BIT_PULSE_LEN_MAX, // pulse_1_len_max: here: maximum length of short pulse + A1TVBOX_BIT_PAUSE_LEN_MIN, // pause_1_len_min: here: minimum length of short pause + A1TVBOX_BIT_PAUSE_LEN_MAX, // pause_1_len_max: here: maximum length of short pause + 0, // pulse_0_len_min: here: not used + 0, // pulse_0_len_max: here: not used + 0, // pause_0_len_min: here: not used + 0, // pause_0_len_max: here: not used + A1TVBOX_ADDRESS_OFFSET, // address_offset: address offset + A1TVBOX_ADDRESS_OFFSET + A1TVBOX_ADDRESS_LEN, // address_end: end of address + A1TVBOX_COMMAND_OFFSET, // command_offset: command offset + A1TVBOX_COMMAND_OFFSET + A1TVBOX_COMMAND_LEN, // command_end: end of command + A1TVBOX_COMPLETE_DATA_LEN, // complete_len: complete length of frame + A1TVBOX_STOP_BIT, // stop_bit: flag: frame has stop bit + A1TVBOX_LSB, // lsb_first: flag: LSB first + A1TVBOX_FLAGS // flags: some flags +}; + +#endif + +#if IRMP_SUPPORT_MERLIN_PROTOCOL == 1 + +static const PROGMEM IRMP_PARAMETER merlin_param = +{ + IRMP_MERLIN_PROTOCOL, // protocol: ir protocol + + MERLIN_BIT_PULSE_LEN_MIN, // pulse_1_len_min: here: minimum length of short pulse + MERLIN_BIT_PULSE_LEN_MAX, // pulse_1_len_max: here: maximum length of short pulse + MERLIN_BIT_PAUSE_LEN_MIN, // pause_1_len_min: here: minimum length of short pause + MERLIN_BIT_PAUSE_LEN_MAX, // pause_1_len_max: here: maximum length of short pause + 0, // pulse_0_len_min: here: not used + 0, // pulse_0_len_max: here: not used + 0, // pause_0_len_min: here: not used + 0, // pause_0_len_max: here: not used + MERLIN_ADDRESS_OFFSET, // address_offset: address offset + MERLIN_ADDRESS_OFFSET + MERLIN_ADDRESS_LEN, // address_end: end of address + MERLIN_COMMAND_OFFSET, // command_offset: command offset + MERLIN_COMMAND_OFFSET + MERLIN_COMMAND_LEN, // command_end: end of command + MERLIN_COMPLETE_DATA_LEN, // complete_len: complete length of frame + MERLIN_STOP_BIT, // stop_bit: flag: frame has stop bit + MERLIN_LSB, // lsb_first: flag: LSB first + MERLIN_FLAGS // flags: some flags +}; + +#endif + +#if IRMP_SUPPORT_ORTEK_PROTOCOL == 1 + +static const PROGMEM IRMP_PARAMETER ortek_param = +{ + IRMP_ORTEK_PROTOCOL, // protocol: ir protocol + + ORTEK_BIT_PULSE_LEN_MIN, // pulse_1_len_min: here: minimum length of short pulse + ORTEK_BIT_PULSE_LEN_MAX, // pulse_1_len_max: here: maximum length of short pulse + ORTEK_BIT_PAUSE_LEN_MIN, // pause_1_len_min: here: minimum length of short pause + ORTEK_BIT_PAUSE_LEN_MAX, // pause_1_len_max: here: maximum length of short pause + 0, // pulse_0_len_min: here: not used + 0, // pulse_0_len_max: here: not used + 0, // pause_0_len_min: here: not used + 0, // pause_0_len_max: here: not used + ORTEK_ADDRESS_OFFSET, // address_offset: address offset + ORTEK_ADDRESS_OFFSET + ORTEK_ADDRESS_LEN, // address_end: end of address + ORTEK_COMMAND_OFFSET, // command_offset: command offset + ORTEK_COMMAND_OFFSET + ORTEK_COMMAND_LEN, // command_end: end of command + ORTEK_COMPLETE_DATA_LEN, // complete_len: complete length of frame + ORTEK_STOP_BIT, // stop_bit: flag: frame has stop bit + ORTEK_LSB, // lsb_first: flag: LSB first + ORTEK_FLAGS // flags: some flags +}; + +#endif + +#if IRMP_SUPPORT_ROOMBA_PROTOCOL == 1 + +static const PROGMEM IRMP_PARAMETER roomba_param = +{ + IRMP_ROOMBA_PROTOCOL, // protocol: ir protocol + ROOMBA_1_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 + ROOMBA_1_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 + ROOMBA_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 + ROOMBA_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 + ROOMBA_0_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 + ROOMBA_0_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 + ROOMBA_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 + ROOMBA_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 + ROOMBA_ADDRESS_OFFSET, // address_offset: address offset + ROOMBA_ADDRESS_OFFSET + ROOMBA_ADDRESS_LEN, // address_end: end of address + ROOMBA_COMMAND_OFFSET, // command_offset: command offset + ROOMBA_COMMAND_OFFSET + ROOMBA_COMMAND_LEN, // command_end: end of command + ROOMBA_COMPLETE_DATA_LEN, // complete_len: complete length of frame + ROOMBA_STOP_BIT, // stop_bit: flag: frame has stop bit + ROOMBA_LSB, // lsb_first: flag: LSB first + ROOMBA_FLAGS // flags: some flags +}; + +#endif + +#if IRMP_SUPPORT_RCMM_PROTOCOL == 1 + +static const PROGMEM IRMP_PARAMETER rcmm_param = +{ + IRMP_RCMM32_PROTOCOL, // protocol: ir protocol + + RCMM32_BIT_PULSE_LEN_MIN, // pulse_1_len_min: here: minimum length of short pulse + RCMM32_BIT_PULSE_LEN_MAX, // pulse_1_len_max: here: maximum length of short pulse + 0, // pause_1_len_min: here: minimum length of short pause + 0, // pause_1_len_max: here: maximum length of short pause + RCMM32_BIT_PULSE_LEN_MIN, // pulse_0_len_min: here: not used + RCMM32_BIT_PULSE_LEN_MAX, // pulse_0_len_max: here: not used + 0, // pause_0_len_min: here: not used + 0, // pause_0_len_max: here: not used + RCMM32_ADDRESS_OFFSET, // address_offset: address offset + RCMM32_ADDRESS_OFFSET + RCMM32_ADDRESS_LEN, // address_end: end of address + RCMM32_COMMAND_OFFSET, // command_offset: command offset + RCMM32_COMMAND_OFFSET + RCMM32_COMMAND_LEN, // command_end: end of command + RCMM32_COMPLETE_DATA_LEN, // complete_len: complete length of frame + RCMM32_STOP_BIT, // stop_bit: flag: frame has stop bit + RCMM32_LSB, // lsb_first: flag: LSB first + RCMM32_FLAGS // flags: some flags +}; + +#endif + +#if IRMP_SUPPORT_PENTAX_PROTOCOL == 1 + +static const PROGMEM IRMP_PARAMETER pentax_param = +{ + IRMP_PENTAX_PROTOCOL, // protocol: ir protocol + PENTAX_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 + PENTAX_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 + PENTAX_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 + PENTAX_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 + PENTAX_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 + PENTAX_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 + PENTAX_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 + PENTAX_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 + PENTAX_ADDRESS_OFFSET, // address_offset: address offset + PENTAX_ADDRESS_OFFSET + PENTAX_ADDRESS_LEN, // address_end: end of address + PENTAX_COMMAND_OFFSET, // command_offset: command offset + PENTAX_COMMAND_OFFSET + PENTAX_COMMAND_LEN, // command_end: end of command + PENTAX_COMPLETE_DATA_LEN, // complete_len: complete length of frame + PENTAX_STOP_BIT, // stop_bit: flag: frame has stop bit + PENTAX_LSB, // lsb_first: flag: LSB first + PENTAX_FLAGS // flags: some flags +}; + +#endif + +#if IRMP_SUPPORT_ACP24_PROTOCOL == 1 + +static const PROGMEM IRMP_PARAMETER acp24_param = +{ + IRMP_ACP24_PROTOCOL, // protocol: ir protocol + ACP24_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 + ACP24_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 + ACP24_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 + ACP24_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 + ACP24_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 + ACP24_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 + ACP24_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 + ACP24_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 + ACP24_ADDRESS_OFFSET, // address_offset: address offset + ACP24_ADDRESS_OFFSET + ACP24_ADDRESS_LEN, // address_end: end of address + ACP24_COMMAND_OFFSET, // command_offset: command offset + ACP24_COMMAND_OFFSET + ACP24_COMMAND_LEN, // command_end: end of command + ACP24_COMPLETE_DATA_LEN, // complete_len: complete length of frame + ACP24_STOP_BIT, // stop_bit: flag: frame has stop bit + ACP24_LSB, // lsb_first: flag: LSB first + ACP24_FLAGS // flags: some flags +}; + +#endif + +#if IRMP_SUPPORT_RADIO1_PROTOCOL == 1 + +static const PROGMEM IRMP_PARAMETER radio1_param = +{ + IRMP_RADIO1_PROTOCOL, // protocol: ir protocol + + RADIO1_1_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 + RADIO1_1_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 + RADIO1_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 + RADIO1_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 + RADIO1_0_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 + RADIO1_0_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 + RADIO1_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 + RADIO1_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 + RADIO1_ADDRESS_OFFSET, // address_offset: address offset + RADIO1_ADDRESS_OFFSET + RADIO1_ADDRESS_LEN, // address_end: end of address + RADIO1_COMMAND_OFFSET, // command_offset: command offset + RADIO1_COMMAND_OFFSET + RADIO1_COMMAND_LEN, // command_end: end of command + RADIO1_COMPLETE_DATA_LEN, // complete_len: complete length of frame + RADIO1_STOP_BIT, // stop_bit: flag: frame has stop bit + RADIO1_LSB, // lsb_first: flag: LSB first + RADIO1_FLAGS // flags: some flags +}; + +#endif + +static uint_fast8_t irmp_bit; // current bit position +static IRMP_PARAMETER irmp_param; + +#if IRMP_SUPPORT_RC5_PROTOCOL == 1 && (IRMP_SUPPORT_FDC_PROTOCOL == 1 || IRMP_SUPPORT_RCCAR_PROTOCOL == 1) +static IRMP_PARAMETER irmp_param2; +#endif + +static volatile uint_fast8_t irmp_ir_detected = FALSE; +static volatile uint_fast8_t irmp_protocol; +static volatile uint_fast16_t irmp_address; +static volatile uint_fast16_t irmp_command; +static volatile uint_fast16_t irmp_id; // only used for SAMSUNG protocol +static volatile uint_fast8_t irmp_flags; +// static volatile uint_fast8_t irmp_busy_flag; + +#if defined(__MBED__) +// DigitalIn inputPin(IRMP_PIN, PullUp); // this requires mbed.h and source to be compiled as cpp +gpio_t gpioIRin; // use low level c function instead +#endif + + +#ifdef ANALYZE +#define input(x) (x) +static uint_fast8_t IRMP_PIN; +static uint_fast8_t radio; +#endif + +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * Initialize IRMP decoder + * @details Configures IRMP input pin + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ +#ifndef ANALYZE +void +irmp_init (void) +{ +#if defined(PIC_CCS) || defined(PIC_C18) // PIC: do nothing +#elif defined (ARM_STM32_HAL) // STM32 with Hal Library: do nothing +#elif defined (ARM_STM32) // STM32 + GPIO_InitTypeDef GPIO_InitStructure; + + /* GPIOx clock enable */ +# if defined (ARM_STM32L1XX) + RCC_AHBPeriphClockCmd(IRMP_PORT_RCC, ENABLE); +# elif defined (ARM_STM32F10X) + RCC_APB2PeriphClockCmd(IRMP_PORT_RCC, ENABLE); +# elif defined (ARM_STM32F4XX) + RCC_AHB1PeriphClockCmd(IRMP_PORT_RCC, ENABLE); +# endif + + /* GPIO Configuration */ + GPIO_InitStructure.GPIO_Pin = IRMP_BIT; +# if defined (ARM_STM32L1XX) || defined (ARM_STM32F4XX) + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; + GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; + GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; +# elif defined (ARM_STM32F10X) + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; +# endif + GPIO_Init(IRMP_PORT, &GPIO_InitStructure); + +#elif defined(STELLARIS_ARM_CORTEX_M4) + // Enable the GPIO port + ROM_SysCtlPeripheralEnable(IRMP_PORT_PERIPH); + + // Set as an input + ROM_GPIODirModeSet(IRMP_PORT_BASE, IRMP_PORT_PIN, GPIO_DIR_MODE_IN); + ROM_GPIOPadConfigSet(IRMP_PORT_BASE, IRMP_PORT_PIN, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD_WPU); + +#elif defined(__SDCC_stm8) // STM8 + IRMP_GPIO_STRUCT->DDR &= ~(1<CR1 |= (1<> 8) == (~irmp_command & 0x00FF)) + { + irmp_command &= 0xff; + irmp_command |= irmp_id << 8; + rtc = TRUE; + } + break; + +#if IRMP_SUPPORT_SAMSUNG48_PROTOCOL == 1 + case IRMP_SAMSUNG48_PROTOCOL: + irmp_command = (irmp_command & 0x00FF) | ((irmp_id & 0x00FF) << 8); + rtc = TRUE; + break; +#endif +#endif + +#if IRMP_SUPPORT_NEC_PROTOCOL == 1 + case IRMP_NEC_PROTOCOL: + if ((irmp_command >> 8) == (~irmp_command & 0x00FF)) + { +#if !defined(U_BOOT_COMPATIBLE) + irmp_command &= 0xff; +#endif + rtc = TRUE; + } + else if (irmp_address == 0x87EE) + { +#ifdef ANALYZE + ANALYZE_PRINTF ("Switching to APPLE protocol\n"); +#endif // ANALYZE + irmp_protocol = IRMP_APPLE_PROTOCOL; + irmp_address = (irmp_command & 0xFF00) >> 8; + irmp_command &= 0x00FF; + rtc = TRUE; + } + break; +#endif + + +#if IRMP_SUPPORT_NEC_PROTOCOL == 1 + case IRMP_VINCENT_PROTOCOL: + if ((irmp_command >> 8) == (irmp_command & 0x00FF)) + { + irmp_command &= 0xff; + rtc = TRUE; + } + break; +#endif + +#if IRMP_SUPPORT_BOSE_PROTOCOL == 1 + case IRMP_BOSE_PROTOCOL: + if ((irmp_command >> 8) == (~irmp_command & 0x00FF)) + { + irmp_command &= 0xff; + rtc = TRUE; + } + break; +#endif +#if IRMP_SUPPORT_SIEMENS_OR_RUWIDO_PROTOCOL == 1 + case IRMP_SIEMENS_PROTOCOL: + case IRMP_RUWIDO_PROTOCOL: + if (((irmp_command >> 1) & 0x0001) == (~irmp_command & 0x0001)) + { + irmp_command >>= 1; + rtc = TRUE; + } + break; +#endif +#if IRMP_SUPPORT_KATHREIN_PROTOCOL == 1 + case IRMP_KATHREIN_PROTOCOL: + if (irmp_command != 0x0000) + { + rtc = TRUE; + } + break; +#endif +#if IRMP_SUPPORT_RC5_PROTOCOL == 1 + case IRMP_RC5_PROTOCOL: +#if !defined(U_BOOT_COMPATIBLE) + irmp_address &= ~0x20; // clear toggle bit +#endif + rtc = TRUE; + break; +#endif +#if IRMP_SUPPORT_S100_PROTOCOL == 1 + case IRMP_S100_PROTOCOL: + irmp_address &= ~0x20; // clear toggle bit + rtc = TRUE; + break; +#endif +#if IRMP_SUPPORT_IR60_PROTOCOL == 1 + case IRMP_IR60_PROTOCOL: + if (irmp_command != 0x007d) // 0x007d (== 62<<1 + 1) is start instruction frame + { + rtc = TRUE; + } + else + { +#ifdef ANALYZE + ANALYZE_PRINTF("Info IR60: got start instruction frame\n"); +#endif // ANALYZE + } + break; +#endif +#if IRMP_SUPPORT_RCCAR_PROTOCOL == 1 + case IRMP_RCCAR_PROTOCOL: + // frame in irmp_data: + // Bit 12 11 10 9 8 7 6 5 4 3 2 1 0 + // V D7 D6 D5 D4 D3 D2 D1 D0 A1 A0 C1 C0 // 10 9 8 7 6 5 4 3 2 1 0 + irmp_address = (irmp_command & 0x000C) >> 2; // addr: 0 0 0 0 0 0 0 0 0 A1 A0 + irmp_command = ((irmp_command & 0x1000) >> 2) | // V-Bit: V 0 0 0 0 0 0 0 0 0 0 + ((irmp_command & 0x0003) << 8) | // C-Bits: 0 C1 C0 0 0 0 0 0 0 0 0 + ((irmp_command & 0x0FF0) >> 4); // D-Bits: D7 D6 D5 D4 D3 D2 D1 D0 + rtc = TRUE; // Summe: V C1 C0 D7 D6 D5 D4 D3 D2 D1 D0 + break; +#endif + +#if IRMP_SUPPORT_NETBOX_PROTOCOL == 1 // squeeze code to 8 bit, upper bit indicates release-key + case IRMP_NETBOX_PROTOCOL: + if (irmp_command & 0x1000) // last bit set? + { + if ((irmp_command & 0x1f) == 0x15) // key pressed: 101 01 (LSB) + { + irmp_command >>= 5; + irmp_command &= 0x7F; + rtc = TRUE; + } + else if ((irmp_command & 0x1f) == 0x10) // key released: 000 01 (LSB) + { + irmp_command >>= 5; + irmp_command |= 0x80; + rtc = TRUE; + } + else + { +#ifdef ANALYZE + ANALYZE_PRINTF("error NETBOX: bit6/7 must be 0/1\n"); +#endif // ANALYZE + } + } + else + { +#ifdef ANALYZE + ANALYZE_PRINTF("error NETBOX: last bit not set\n"); +#endif // ANALYZE + } + break; +#endif +#if IRMP_SUPPORT_LEGO_PROTOCOL == 1 + case IRMP_LEGO_PROTOCOL: + { + uint_fast8_t crc = 0x0F ^ ((irmp_command & 0xF000) >> 12) ^ ((irmp_command & 0x0F00) >> 8) ^ ((irmp_command & 0x00F0) >> 4); + + if ((irmp_command & 0x000F) == crc) + { + irmp_command >>= 4; + rtc = TRUE; + } + else + { +#ifdef ANALYZE + ANALYZE_PRINTF ("CRC error in LEGO protocol\n"); +#endif // ANALYZE + // rtc = TRUE; // don't accept codes with CRC errors + } + break; + } +#endif + + default: + { + rtc = TRUE; + break; + } + } + + if (rtc) + { + irmp_data_p->protocol = irmp_protocol; + irmp_data_p->address = irmp_address; + irmp_data_p->command = irmp_command; + irmp_data_p->flags = irmp_flags; + } + else + { + irmp_protocol = IRMP_UNKNOWN_PROTOCOL; + } + + irmp_command = 0; // don't reset irmp_protocol here, needed for detection of NEC & JVC repetition frames! + irmp_address = 0; + irmp_flags = 0; + + irmp_ir_detected = FALSE; + } + + return rtc; +} + +#if IRMP_USE_CALLBACK == 1 +void +irmp_set_callback_ptr (void (*cb)(uint_fast8_t)) +{ + irmp_callback_ptr = cb; +} +#endif // IRMP_USE_CALLBACK == 1 + +// these statics must not be volatile, because they are only used by irmp_store_bit(), which is called by irmp_ISR() +static uint_fast16_t irmp_tmp_address; // ir address +static uint_fast16_t irmp_tmp_command; // ir command + +#if (IRMP_SUPPORT_RC5_PROTOCOL == 1 && (IRMP_SUPPORT_FDC_PROTOCOL == 1 || IRMP_SUPPORT_RCCAR_PROTOCOL == 1)) || IRMP_SUPPORT_NEC42_PROTOCOL == 1 +static uint_fast16_t irmp_tmp_address2; // ir address +static uint_fast16_t irmp_tmp_command2; // ir command +#endif + +#if IRMP_SUPPORT_LGAIR_PROTOCOL == 1 +static uint_fast16_t irmp_lgair_address; // ir address +static uint_fast16_t irmp_lgair_command; // ir command +#endif + +#if IRMP_SUPPORT_SAMSUNG_PROTOCOL == 1 +static uint_fast16_t irmp_tmp_id; // ir id (only SAMSUNG) +#endif +#if IRMP_SUPPORT_KASEIKYO_PROTOCOL == 1 +static uint8_t xor_check[6]; // check kaseikyo "parity" bits +static uint_fast8_t genre2; // save genre2 bits here, later copied to MSB in flags +#endif + +#if IRMP_SUPPORT_ORTEK_PROTOCOL == 1 +static uint_fast8_t parity; // number of '1' of the first 14 bits, check if even. +#endif + +#if IRMP_SUPPORT_MITSU_HEAVY_PROTOCOL == 1 +static uint_fast8_t check; // number of '1' of the first 14 bits, check if even. +static uint_fast8_t mitsu_parity; // number of '1' of the first 14 bits, check if even. +#endif + +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * store bit + * @details store bit in temp address or temp command + * @param value to store: 0 or 1 + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ +// verhindert, dass irmp_store_bit() inline compiliert wird: +// static void irmp_store_bit (uint_fast8_t) __attribute__ ((noinline)); + +static void +irmp_store_bit (uint_fast8_t value) +{ +#if IRMP_SUPPORT_ACP24_PROTOCOL == 1 + if (irmp_param.protocol == IRMP_ACP24_PROTOCOL) // squeeze 64 bits into 16 bits: + { + if (value) + { + // ACP24-Frame: + // 1 2 3 4 5 6 + // 0123456789012345678901234567890123456789012345678901234567890123456789 + // N VVMMM ? ??? t vmA x y TTTT + // + // irmp_data_p->command: + // + // 5432109876543210 + // NAVVvMMMmtxyTTTT + + switch (irmp_bit) + { + case 0: irmp_tmp_command |= (1<<15); break; // N + case 2: irmp_tmp_command |= (1<<13); break; // V + case 3: irmp_tmp_command |= (1<<12); break; // V + case 4: irmp_tmp_command |= (1<<10); break; // M + case 5: irmp_tmp_command |= (1<< 9); break; // M + case 6: irmp_tmp_command |= (1<< 8); break; // M + case 20: irmp_tmp_command |= (1<< 6); break; // t + case 22: irmp_tmp_command |= (1<<11); break; // v + case 23: irmp_tmp_command |= (1<< 7); break; // m + case 24: irmp_tmp_command |= (1<<14); break; // A + case 26: irmp_tmp_command |= (1<< 5); break; // x + case 44: irmp_tmp_command |= (1<< 4); break; // y + case 66: irmp_tmp_command |= (1<< 3); break; // T + case 67: irmp_tmp_command |= (1<< 2); break; // T + case 68: irmp_tmp_command |= (1<< 1); break; // T + case 69: irmp_tmp_command |= (1<< 0); break; // T + } + } + } + else +#endif // IRMP_SUPPORT_ACP24_PROTOCOL + +#if IRMP_SUPPORT_ORTEK_PROTOCOL == 1 + if (irmp_param.protocol == IRMP_ORTEK_PROTOCOL) + { + if (irmp_bit < 14) + { + if (value) + { + parity++; + } + } + else if (irmp_bit == 14) + { + if (value) // value == 1: even parity + { + if (parity & 0x01) + { + parity = PARITY_CHECK_FAILED; + } + else + { + parity = PARITY_CHECK_OK; + } + } + else + { + if (parity & 0x01) // value == 0: odd parity + { + parity = PARITY_CHECK_OK; + } + else + { + parity = PARITY_CHECK_FAILED; + } + } + } + } + else +#endif + { + ; + } + +#if IRMP_SUPPORT_GRUNDIG_NOKIA_IR60_PROTOCOL == 1 + if (irmp_bit == 0 && irmp_param.protocol == IRMP_GRUNDIG_PROTOCOL) + { + first_bit = value; + } + else +#endif + + if (irmp_bit >= irmp_param.address_offset && irmp_bit < irmp_param.address_end) + { + if (irmp_param.lsb_first) + { + irmp_tmp_address |= (((uint_fast16_t) (value)) << (irmp_bit - irmp_param.address_offset)); // CV wants cast + } + else + { + irmp_tmp_address <<= 1; + irmp_tmp_address |= value; + } + } + else if (irmp_bit >= irmp_param.command_offset && irmp_bit < irmp_param.command_end) + { + if (irmp_param.lsb_first) + { +#if IRMP_SUPPORT_SAMSUNG48_PROTOCOL == 1 + if (irmp_param.protocol == IRMP_SAMSUNG48_PROTOCOL && irmp_bit >= 32) + { + irmp_tmp_id |= (((uint_fast16_t) (value)) << (irmp_bit - 32)); // CV wants cast + } + else +#endif + { + irmp_tmp_command |= (((uint_fast16_t) (value)) << (irmp_bit - irmp_param.command_offset)); // CV wants cast + } + } + else + { + irmp_tmp_command <<= 1; + irmp_tmp_command |= value; + } + } + +#if IRMP_SUPPORT_LGAIR_PROTOCOL == 1 + if (irmp_param.protocol == IRMP_NEC_PROTOCOL || irmp_param.protocol == IRMP_NEC42_PROTOCOL) + { + if (irmp_bit < 8) + { + irmp_lgair_address <<= 1; // LGAIR uses MSB + irmp_lgair_address |= value; + } + else if (irmp_bit < 24) + { + irmp_lgair_command <<= 1; // LGAIR uses MSB + irmp_lgair_command |= value; + } + } + // NO else! +#endif + +#if IRMP_SUPPORT_NEC42_PROTOCOL == 1 + if (irmp_param.protocol == IRMP_NEC42_PROTOCOL && irmp_bit >= 13 && irmp_bit < 26) + { + irmp_tmp_address2 |= (((uint_fast16_t) (value)) << (irmp_bit - 13)); // CV wants cast + } + else +#endif + +#if IRMP_SUPPORT_SAMSUNG_PROTOCOL == 1 + if (irmp_param.protocol == IRMP_SAMSUNG_PROTOCOL && irmp_bit >= SAMSUNG_ID_OFFSET && irmp_bit < SAMSUNG_ID_OFFSET + SAMSUNG_ID_LEN) + { + irmp_tmp_id |= (((uint_fast16_t) (value)) << (irmp_bit - SAMSUNG_ID_OFFSET)); // store with LSB first + } + else +#endif + +#if IRMP_SUPPORT_KASEIKYO_PROTOCOL == 1 + if (irmp_param.protocol == IRMP_KASEIKYO_PROTOCOL) + { + if (irmp_bit >= 20 && irmp_bit < 24) + { + irmp_tmp_command |= (((uint_fast16_t) (value)) << (irmp_bit - 8)); // store 4 system bits (genre 1) in upper nibble with LSB first + } + else if (irmp_bit >= 24 && irmp_bit < 28) + { + genre2 |= (((uint_fast8_t) (value)) << (irmp_bit - 20)); // store 4 system bits (genre 2) in upper nibble with LSB first + } + + if (irmp_bit < KASEIKYO_COMPLETE_DATA_LEN) + { + if (value) + { + xor_check[irmp_bit / 8] |= 1 << (irmp_bit % 8); + } + else + { + xor_check[irmp_bit / 8] &= ~(1 << (irmp_bit % 8)); + } + } + } + else +#endif + +#if IRMP_SUPPORT_MITSU_HEAVY_PROTOCOL == 1 + if (irmp_param.protocol == IRMP_MITSU_HEAVY_PROTOCOL) // squeeze 64 bits into 16 bits: + { + if (irmp_bit == 72 ) + { // irmp_tmp_address, irmp_tmp_command received: check parity & compress + mitsu_parity = PARITY_CHECK_OK; + + check = irmp_tmp_address >> 8; // inverted upper byte == lower byte? + check = ~ check; + + if (check == (irmp_tmp_address & 0xFF)) + { // ok: + irmp_tmp_address <<= 8; // throw away upper byte + } + else + { + mitsu_parity = PARITY_CHECK_FAILED; + } + + check = irmp_tmp_command >> 8; // inverted upper byte == lower byte? + check = ~ check; + if (check == (irmp_tmp_command & 0xFF)) + { // ok: pack together + irmp_tmp_address |= irmp_tmp_command & 0xFF; // byte 1, byte2 in irmp_tmp_address, irmp_tmp_command can be used for byte 3 + } + else + { + mitsu_parity = PARITY_CHECK_FAILED; + } + irmp_tmp_command = 0; + } + + if (irmp_bit >= 72 ) + { // receive 3. word in irmp_tmp_command + irmp_tmp_command <<= 1; + irmp_tmp_command |= value; + } + } + else +#endif // IRMP_SUPPORT_MITSU_HEAVY_PROTOCOL + { + ; + } + + irmp_bit++; +} + +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * store bit + * @details store bit in temp address or temp command + * @param value to store: 0 or 1 + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ +#if IRMP_SUPPORT_RC5_PROTOCOL == 1 && (IRMP_SUPPORT_FDC_PROTOCOL == 1 || IRMP_SUPPORT_RCCAR_PROTOCOL == 1) +static void +irmp_store_bit2 (uint_fast8_t value) +{ + uint_fast8_t irmp_bit2; + + if (irmp_param.protocol) + { + irmp_bit2 = irmp_bit - 2; + } + else + { + irmp_bit2 = irmp_bit - 1; + } + + if (irmp_bit2 >= irmp_param2.address_offset && irmp_bit2 < irmp_param2.address_end) + { + irmp_tmp_address2 |= (((uint_fast16_t) (value)) << (irmp_bit2 - irmp_param2.address_offset)); // CV wants cast + } + else if (irmp_bit2 >= irmp_param2.command_offset && irmp_bit2 < irmp_param2.command_end) + { + irmp_tmp_command2 |= (((uint_fast16_t) (value)) << (irmp_bit2 - irmp_param2.command_offset)); // CV wants cast + } +} +#endif // IRMP_SUPPORT_RC5_PROTOCOL == 1 && (IRMP_SUPPORT_FDC_PROTOCOL == 1 || IRMP_SUPPORT_RCCAR_PROTOCOL == 1) + +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * ISR routine + * @details ISR routine, called 10000 times per second + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ +#if !defined(IRMP_PULSE_IR_DECODER) +uint_fast8_t +irmp_ISR (void) +#else +uint_fast8_t +irmp_ISR (uint_fast16_t duration) +#endif +{ + static uint_fast8_t irmp_start_bit_detected; // flag: start bit detected + static uint_fast8_t wait_for_space; // flag: wait for data bit space + static uint_fast8_t wait_for_start_space; // flag: wait for start bit space +#if !defined(IRMP_PULSE_IR_DECODER) + static uint_fast8_t irmp_pulse_time; // count bit time for pulse +#else + static uint_fast16_t irmp_pulse_time; // count bit time for pulse +#endif + static PAUSE_LEN irmp_pause_time; // count bit time for pause + static uint_fast16_t last_irmp_address = 0xFFFF; // save last irmp address to recognize key repetition + static uint_fast16_t last_irmp_command = 0xFFFF; // save last irmp command to recognize key repetition + static uint_fast16_t key_repetition_len; // SIRCS repeats frame 2-5 times with 45 ms pause + static uint_fast8_t repetition_frame_number; +#if IRMP_SUPPORT_DENON_PROTOCOL == 1 + static uint_fast16_t last_irmp_denon_command; // save last irmp command to recognize DENON frame repetition + static uint_fast16_t denon_repetition_len = 0xFFFF; // denon repetition len of 2nd auto generated frame +#endif +#if IRMP_SUPPORT_RC5_PROTOCOL == 1 || IRMP_SUPPORT_S100_PROTOCOL == 1 + static uint_fast8_t rc5_cmd_bit6; // bit 6 of RC5 command is the inverted 2nd start bit +#endif +#if IRMP_SUPPORT_MANCHESTER == 1 + static PAUSE_LEN last_pause; // last pause value +#endif +#if IRMP_SUPPORT_MANCHESTER == 1 || IRMP_SUPPORT_BANG_OLUFSEN_PROTOCOL == 1 + static uint_fast8_t last_value; // last bit value +#endif +#if IRMP_SUPPORT_RCII_PROTOCOL == 1 + static uint_fast8_t waiting_for_2nd_pulse = 0; +#endif +#if !defined(IRMP_PULSE_IR_DECODER) + uint_fast8_t irmp_input; // input value +#else + if (!duration) // empty duration == timeout + duration = IRMP_TIMEOUT_LEN + 1; +#endif + +#ifdef ANALYZE + +#if 0 // only for test + static uint_fast8_t last_irmp_start_bit_detected = 0xFF; + static uint_fast8_t last_irmp_pulse_time = 0xFF; + + if (last_irmp_start_bit_detected != irmp_start_bit_detected || last_irmp_pulse_time != irmp_pulse_time) + { + last_irmp_start_bit_detected = irmp_start_bit_detected; + last_irmp_pulse_time = irmp_pulse_time; + + printf ("%d %d %d\n", time_counter, irmp_start_bit_detected, irmp_pulse_time); + } +#endif // 0 + + time_counter++; +#endif // ANALYZE + +#if !defined(IRMP_PULSE_IR_DECODER) +#if defined(__SDCC_stm8) + irmp_input = input(IRMP_GPIO_STRUCT->IDR) +#elif defined(__MBED__) + //irmp_input = inputPin; + irmp_input = gpio_read (&gpioIRin); +#else + irmp_input = input(IRMP_PIN); +#endif + +#if IRMP_USE_CALLBACK == 1 + if (irmp_callback_ptr) + { + static uint_fast8_t last_inverted_input; + + if (last_inverted_input != !irmp_input) + { + (*irmp_callback_ptr) (! irmp_input); + last_inverted_input = !irmp_input; + } + } +#endif // IRMP_USE_CALLBACK == 1 + + irmp_log(irmp_input); // log ir signal, if IRMP_LOGGING defined +#endif + + if (! irmp_ir_detected) // ir code already detected? + { // no... + if (! irmp_start_bit_detected) // start bit detected? + { // no... +#if !defined(IRMP_PULSE_IR_DECODER) + if (! irmp_input) // receiving burst? + { // yes... +// irmp_busy_flag = TRUE; +#ifdef ANALYZE + if (! irmp_pulse_time) + { + ANALYZE_PRINTF("%8.3fms [starting pulse]\n", (double) (time_counter * 1000) / F_INTERRUPTS); + } +#endif // ANALYZE + irmp_pulse_time++; // increment counter + } + else + { // no... + if (irmp_pulse_time) // it's dark.... +#else + irmp_pulse_time = duration; // increment counter + if (irmp_pulse_time && irmp_pulse_time < IRMP_TIMEOUT_LEN) // it's dark.... +#endif + { // set flags for counting the time of darkness... + irmp_start_bit_detected = 1; + wait_for_start_space = 1; + wait_for_space = 0; + irmp_tmp_command = 0; + irmp_tmp_address = 0; +#if IRMP_SUPPORT_KASEIKYO_PROTOCOL == 1 + genre2 = 0; +#endif +#if IRMP_SUPPORT_SAMSUNG_PROTOCOL == 1 + irmp_tmp_id = 0; +#endif + +#if IRMP_SUPPORT_RC5_PROTOCOL == 1 && (IRMP_SUPPORT_FDC_PROTOCOL == 1 || IRMP_SUPPORT_RCCAR_PROTOCOL == 1) || IRMP_SUPPORT_NEC42_PROTOCOL == 1 + irmp_tmp_command2 = 0; + irmp_tmp_address2 = 0; +#endif +#if IRMP_SUPPORT_LGAIR_PROTOCOL == 1 + irmp_lgair_command = 0; + irmp_lgair_address = 0; +#endif + irmp_bit = 0xff; + irmp_pause_time = 1; // 1st pause: set to 1, not to 0! +#if IRMP_SUPPORT_RC5_PROTOCOL == 1 || IRMP_SUPPORT_S100_PROTOCOL == 1 + rc5_cmd_bit6 = 0; // fm 2010-03-07: bugfix: reset it after incomplete RC5 frame! +#endif + } + else + { + if (key_repetition_len < 0xFFFF) // avoid overflow of counter + { +#if !defined(IRMP_PULSE_IR_DECODER) + key_repetition_len++; +#else + if ((uint32_t)(key_repetition_len) + duration >= 0xFFFF) + key_repetition_len = 0xFFFF; + else + key_repetition_len += duration; +#endif + + +#if IRMP_SUPPORT_DENON_PROTOCOL == 1 + if (denon_repetition_len < 0xFFFF) // avoid overflow of counter + { +#if !defined(IRMP_PULSE_IR_DECODER) + denon_repetition_len++; +#else + if ((uint32_t)(denon_repetition_len) + duration >= 0xFFFF) + denon_repetition_len = 0xFFFF; + else + denon_repetition_len += duration; +#endif + + + if (denon_repetition_len >= DENON_AUTO_REPETITION_PAUSE_LEN && last_irmp_denon_command != 0) + { +#ifdef ANALYZE + ANALYZE_PRINTF ("%8.3fms warning: did not receive inverted command repetition\n", + (double) (time_counter * 1000) / F_INTERRUPTS); +#endif // ANALYZE + last_irmp_denon_command = 0; + denon_repetition_len = 0xFFFF; + } + } +#endif // IRMP_SUPPORT_DENON_PROTOCOL == 1 + } + } +#if !defined(IRMP_PULSE_IR_DECODER) + } +#endif + } + else + { + if (wait_for_start_space) // we have received start bit... + { // ...and are counting the time of darkness +#if !defined(IRMP_PULSE_IR_DECODER) + if (irmp_input) // still dark? + { // yes + irmp_pause_time++; // increment counter +#else + irmp_pause_time = duration; // increment counter +#endif + +#if IRMP_SUPPORT_NIKON_PROTOCOL == 1 + if (((irmp_pulse_time < NIKON_START_BIT_PULSE_LEN_MIN || irmp_pulse_time > NIKON_START_BIT_PULSE_LEN_MAX) && irmp_pause_time > IRMP_TIMEOUT_LEN) || + irmp_pause_time > IRMP_TIMEOUT_NIKON_LEN) +#else + if (irmp_pause_time > IRMP_TIMEOUT_LEN) // timeout? +#endif + { // yes... +#if IRMP_SUPPORT_JVC_PROTOCOL == 1 + if (irmp_protocol == IRMP_JVC_PROTOCOL) // don't show eror if JVC protocol, irmp_pulse_time has been set below! + { + ; + } + else +#endif // IRMP_SUPPORT_JVC_PROTOCOL == 1 + { +#ifdef ANALYZE + ANALYZE_PRINTF ("%8.3fms error 1: pause after start bit pulse %d too long: %d\n", (double) (time_counter * 1000) / F_INTERRUPTS, irmp_pulse_time, irmp_pause_time); + ANALYZE_ONLY_NORMAL_PUTCHAR ('\n'); +#endif // ANALYZE + } + + irmp_start_bit_detected = 0; // reset flags, let's wait for another start bit + irmp_pulse_time = 0; + irmp_pause_time = 0; + } +#if !defined(IRMP_PULSE_IR_DECODER) + } + else +#endif + { // receiving first data pulse! + IRMP_PARAMETER * irmp_param_p; + irmp_param_p = (IRMP_PARAMETER *) 0; + +#if IRMP_SUPPORT_RC5_PROTOCOL == 1 && (IRMP_SUPPORT_FDC_PROTOCOL == 1 || IRMP_SUPPORT_RCCAR_PROTOCOL == 1) + irmp_param2.protocol = 0; +#endif + +#ifdef ANALYZE + ANALYZE_PRINTF ("%8.3fms [start-bit: pulse = %2d, pause = %2d]\n", (double) (time_counter * 1000) / F_INTERRUPTS, irmp_pulse_time, irmp_pause_time); +#endif // ANALYZE + +#if IRMP_SUPPORT_SIRCS_PROTOCOL == 1 + if (irmp_pulse_time >= SIRCS_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= SIRCS_START_BIT_PULSE_LEN_MAX && + irmp_pause_time >= SIRCS_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= SIRCS_START_BIT_PAUSE_LEN_MAX) + { // it's SIRCS +#ifdef ANALYZE + ANALYZE_PRINTF ("protocol = SIRCS, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", + SIRCS_START_BIT_PULSE_LEN_MIN, SIRCS_START_BIT_PULSE_LEN_MAX, + SIRCS_START_BIT_PAUSE_LEN_MIN, SIRCS_START_BIT_PAUSE_LEN_MAX); +#endif // ANALYZE + irmp_param_p = (IRMP_PARAMETER *) &sircs_param; + } + else +#endif // IRMP_SUPPORT_SIRCS_PROTOCOL == 1 + +#if IRMP_SUPPORT_JVC_PROTOCOL == 1 + if (irmp_protocol == IRMP_JVC_PROTOCOL && // last protocol was JVC, awaiting repeat frame + irmp_pulse_time >= JVC_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= JVC_START_BIT_PULSE_LEN_MAX && + irmp_pause_time >= JVC_REPEAT_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= JVC_REPEAT_START_BIT_PAUSE_LEN_MAX) + { +#ifdef ANALYZE + ANALYZE_PRINTF ("protocol = NEC or JVC (type 1) repeat frame, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", + JVC_START_BIT_PULSE_LEN_MIN, JVC_START_BIT_PULSE_LEN_MAX, + JVC_REPEAT_START_BIT_PAUSE_LEN_MIN, JVC_REPEAT_START_BIT_PAUSE_LEN_MAX); +#endif // ANALYZE + irmp_param_p = (IRMP_PARAMETER *) &nec_param; + } + else +#endif // IRMP_SUPPORT_JVC_PROTOCOL == 1 + +#if IRMP_SUPPORT_NEC_PROTOCOL == 1 + if (irmp_pulse_time >= NEC_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= NEC_START_BIT_PULSE_LEN_MAX && + irmp_pause_time >= NEC_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= NEC_START_BIT_PAUSE_LEN_MAX) + { +#if IRMP_SUPPORT_NEC42_PROTOCOL == 1 +#ifdef ANALYZE + ANALYZE_PRINTF ("protocol = NEC42, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", + NEC_START_BIT_PULSE_LEN_MIN, NEC_START_BIT_PULSE_LEN_MAX, + NEC_START_BIT_PAUSE_LEN_MIN, NEC_START_BIT_PAUSE_LEN_MAX); +#endif // ANALYZE + irmp_param_p = (IRMP_PARAMETER *) &nec42_param; +#else +#ifdef ANALYZE + ANALYZE_PRINTF ("protocol = NEC, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", + NEC_START_BIT_PULSE_LEN_MIN, NEC_START_BIT_PULSE_LEN_MAX, + NEC_START_BIT_PAUSE_LEN_MIN, NEC_START_BIT_PAUSE_LEN_MAX); +#endif // ANALYZE + irmp_param_p = (IRMP_PARAMETER *) &nec_param; +#endif + } + else if (irmp_pulse_time >= NEC_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= NEC_START_BIT_PULSE_LEN_MAX && + irmp_pause_time >= NEC_REPEAT_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= NEC_REPEAT_START_BIT_PAUSE_LEN_MAX) + { // it's NEC +#if IRMP_SUPPORT_JVC_PROTOCOL == 1 + if (irmp_protocol == IRMP_JVC_PROTOCOL) // last protocol was JVC, awaiting repeat frame + { // some jvc remote controls use nec repetition frame for jvc repetition frame +#ifdef ANALYZE + ANALYZE_PRINTF ("protocol = JVC repeat frame type 2, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", + NEC_START_BIT_PULSE_LEN_MIN, NEC_START_BIT_PULSE_LEN_MAX, + NEC_REPEAT_START_BIT_PAUSE_LEN_MIN, NEC_REPEAT_START_BIT_PAUSE_LEN_MAX); +#endif // ANALYZE + irmp_param_p = (IRMP_PARAMETER *) &nec_param; + } + else +#endif // IRMP_SUPPORT_JVC_PROTOCOL == 1 + { +#ifdef ANALYZE + ANALYZE_PRINTF ("protocol = NEC (repetition frame), start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", + NEC_START_BIT_PULSE_LEN_MIN, NEC_START_BIT_PULSE_LEN_MAX, + NEC_REPEAT_START_BIT_PAUSE_LEN_MIN, NEC_REPEAT_START_BIT_PAUSE_LEN_MAX); +#endif // ANALYZE + irmp_param_p = (IRMP_PARAMETER *) &nec_rep_param; + } + } + else + +#if IRMP_SUPPORT_JVC_PROTOCOL == 1 + if (irmp_protocol == IRMP_JVC_PROTOCOL && // last protocol was JVC, awaiting repeat frame + irmp_pulse_time >= NEC_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= NEC_START_BIT_PULSE_LEN_MAX && + irmp_pause_time >= NEC_0_PAUSE_LEN_MIN && irmp_pause_time <= NEC_0_PAUSE_LEN_MAX) + { // it's JVC repetition type 3 +#ifdef ANALYZE + ANALYZE_PRINTF ("protocol = JVC repeat frame type 3, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", + NEC_START_BIT_PULSE_LEN_MIN, NEC_START_BIT_PULSE_LEN_MAX, + NEC_0_PAUSE_LEN_MIN, NEC_0_PAUSE_LEN_MAX); +#endif // ANALYZE + irmp_param_p = (IRMP_PARAMETER *) &nec_param; + } + else +#endif // IRMP_SUPPORT_JVC_PROTOCOL == 1 + +#endif // IRMP_SUPPORT_NEC_PROTOCOL == 1 + +#if IRMP_SUPPORT_TELEFUNKEN_PROTOCOL == 1 + if (irmp_pulse_time >= TELEFUNKEN_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= TELEFUNKEN_START_BIT_PULSE_LEN_MAX && + irmp_pause_time >= TELEFUNKEN_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= TELEFUNKEN_START_BIT_PAUSE_LEN_MAX) + { +#ifdef ANALYZE + ANALYZE_PRINTF ("protocol = TELEFUNKEN, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", + TELEFUNKEN_START_BIT_PULSE_LEN_MIN, TELEFUNKEN_START_BIT_PULSE_LEN_MAX, + TELEFUNKEN_START_BIT_PAUSE_LEN_MIN, TELEFUNKEN_START_BIT_PAUSE_LEN_MAX); +#endif // ANALYZE + irmp_param_p = (IRMP_PARAMETER *) &telefunken_param; + } + else +#endif // IRMP_SUPPORT_TELEFUNKEN_PROTOCOL == 1 + +#if IRMP_SUPPORT_ROOMBA_PROTOCOL == 1 + if (irmp_pulse_time >= ROOMBA_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= ROOMBA_START_BIT_PULSE_LEN_MAX && + irmp_pause_time >= ROOMBA_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= ROOMBA_START_BIT_PAUSE_LEN_MAX) + { +#ifdef ANALYZE + ANALYZE_PRINTF ("protocol = ROOMBA, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", + ROOMBA_START_BIT_PULSE_LEN_MIN, ROOMBA_START_BIT_PULSE_LEN_MAX, + ROOMBA_START_BIT_PAUSE_LEN_MIN, ROOMBA_START_BIT_PAUSE_LEN_MAX); +#endif // ANALYZE + irmp_param_p = (IRMP_PARAMETER *) &roomba_param; + } + else +#endif // IRMP_SUPPORT_ROOMBA_PROTOCOL == 1 + +#if IRMP_SUPPORT_ACP24_PROTOCOL == 1 + if (irmp_pulse_time >= ACP24_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= ACP24_START_BIT_PULSE_LEN_MAX && + irmp_pause_time >= ACP24_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= ACP24_START_BIT_PAUSE_LEN_MAX) + { +#ifdef ANALYZE + ANALYZE_PRINTF ("protocol = ACP24, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", + ACP24_START_BIT_PULSE_LEN_MIN, ACP24_START_BIT_PULSE_LEN_MAX, + ACP24_START_BIT_PAUSE_LEN_MIN, ACP24_START_BIT_PAUSE_LEN_MAX); +#endif // ANALYZE + irmp_param_p = (IRMP_PARAMETER *) &acp24_param; + } + else +#endif // IRMP_SUPPORT_ROOMBA_PROTOCOL == 1 + +#if IRMP_SUPPORT_PENTAX_PROTOCOL == 1 + if (irmp_pulse_time >= PENTAX_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= PENTAX_START_BIT_PULSE_LEN_MAX && + irmp_pause_time >= PENTAX_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= PENTAX_START_BIT_PAUSE_LEN_MAX) + { +#ifdef ANALYZE + ANALYZE_PRINTF ("protocol = PENTAX, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", + PENTAX_START_BIT_PULSE_LEN_MIN, PENTAX_START_BIT_PULSE_LEN_MAX, + PENTAX_START_BIT_PAUSE_LEN_MIN, PENTAX_START_BIT_PAUSE_LEN_MAX); +#endif // ANALYZE + irmp_param_p = (IRMP_PARAMETER *) &pentax_param; + } + else +#endif // IRMP_SUPPORT_PENTAX_PROTOCOL == 1 + +#if IRMP_SUPPORT_NIKON_PROTOCOL == 1 + if (irmp_pulse_time >= NIKON_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= NIKON_START_BIT_PULSE_LEN_MAX && + irmp_pause_time >= NIKON_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= NIKON_START_BIT_PAUSE_LEN_MAX) + { +#ifdef ANALYZE + ANALYZE_PRINTF ("protocol = NIKON, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", + NIKON_START_BIT_PULSE_LEN_MIN, NIKON_START_BIT_PULSE_LEN_MAX, + NIKON_START_BIT_PAUSE_LEN_MIN, NIKON_START_BIT_PAUSE_LEN_MAX); +#endif // ANALYZE + irmp_param_p = (IRMP_PARAMETER *) &nikon_param; + } + else +#endif // IRMP_SUPPORT_NIKON_PROTOCOL == 1 + +#if IRMP_SUPPORT_SAMSUNG_PROTOCOL == 1 + if (irmp_pulse_time >= SAMSUNG_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= SAMSUNG_START_BIT_PULSE_LEN_MAX && + irmp_pause_time >= SAMSUNG_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= SAMSUNG_START_BIT_PAUSE_LEN_MAX) + { // it's SAMSUNG +#ifdef ANALYZE + ANALYZE_PRINTF ("protocol = SAMSUNG, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", + SAMSUNG_START_BIT_PULSE_LEN_MIN, SAMSUNG_START_BIT_PULSE_LEN_MAX, + SAMSUNG_START_BIT_PAUSE_LEN_MIN, SAMSUNG_START_BIT_PAUSE_LEN_MAX); +#endif // ANALYZE + irmp_param_p = (IRMP_PARAMETER *) &samsung_param; + } + else +#endif // IRMP_SUPPORT_SAMSUNG_PROTOCOL == 1 + +#if IRMP_SUPPORT_SAMSUNGAH_PROTOCOL == 1 + if (irmp_pulse_time >= SAMSUNGAH_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= SAMSUNGAH_START_BIT_PULSE_LEN_MAX && + irmp_pause_time >= SAMSUNGAH_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= SAMSUNGAH_START_BIT_PAUSE_LEN_MAX) + { // it's SAMSUNGAH +#ifdef ANALYZE + ANALYZE_PRINTF ("protocol = SAMSUNGAH, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", + SAMSUNGAH_START_BIT_PULSE_LEN_MIN, SAMSUNGAH_START_BIT_PULSE_LEN_MAX, + SAMSUNGAH_START_BIT_PAUSE_LEN_MIN, SAMSUNGAH_START_BIT_PAUSE_LEN_MAX); +#endif // ANALYZE + irmp_param_p = (IRMP_PARAMETER *) &samsungah_param; + } + else +#endif // IRMP_SUPPORT_SAMSUNGAH_PROTOCOL == 1 + +#if IRMP_SUPPORT_MATSUSHITA_PROTOCOL == 1 + if (irmp_pulse_time >= MATSUSHITA_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= MATSUSHITA_START_BIT_PULSE_LEN_MAX && + irmp_pause_time >= MATSUSHITA_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= MATSUSHITA_START_BIT_PAUSE_LEN_MAX) + { // it's MATSUSHITA +#ifdef ANALYZE + ANALYZE_PRINTF ("protocol = MATSUSHITA, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", + MATSUSHITA_START_BIT_PULSE_LEN_MIN, MATSUSHITA_START_BIT_PULSE_LEN_MAX, + MATSUSHITA_START_BIT_PAUSE_LEN_MIN, MATSUSHITA_START_BIT_PAUSE_LEN_MAX); +#endif // ANALYZE + irmp_param_p = (IRMP_PARAMETER *) &matsushita_param; + } + else +#endif // IRMP_SUPPORT_MATSUSHITA_PROTOCOL == 1 + +#if IRMP_SUPPORT_KASEIKYO_PROTOCOL == 1 + if (irmp_pulse_time >= KASEIKYO_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= KASEIKYO_START_BIT_PULSE_LEN_MAX && + irmp_pause_time >= KASEIKYO_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= KASEIKYO_START_BIT_PAUSE_LEN_MAX) + { // it's KASEIKYO +#ifdef ANALYZE + ANALYZE_PRINTF ("protocol = KASEIKYO, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", + KASEIKYO_START_BIT_PULSE_LEN_MIN, KASEIKYO_START_BIT_PULSE_LEN_MAX, + KASEIKYO_START_BIT_PAUSE_LEN_MIN, KASEIKYO_START_BIT_PAUSE_LEN_MAX); +#endif // ANALYZE + irmp_param_p = (IRMP_PARAMETER *) &kaseikyo_param; + } + else +#endif // IRMP_SUPPORT_KASEIKYO_PROTOCOL == 1 + +#if IRMP_SUPPORT_PANASONIC_PROTOCOL == 1 + if (irmp_pulse_time >= PANASONIC_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= PANASONIC_START_BIT_PULSE_LEN_MAX && + irmp_pause_time >= PANASONIC_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= PANASONIC_START_BIT_PAUSE_LEN_MAX) + { // it's PANASONIC +#ifdef ANALYZE + ANALYZE_PRINTF ("protocol = PANASONIC, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", + PANASONIC_START_BIT_PULSE_LEN_MIN, PANASONIC_START_BIT_PULSE_LEN_MAX, + PANASONIC_START_BIT_PAUSE_LEN_MIN, PANASONIC_START_BIT_PAUSE_LEN_MAX); +#endif // ANALYZE + irmp_param_p = (IRMP_PARAMETER *) &panasonic_param; + } + else +#endif // IRMP_SUPPORT_PANASONIC_PROTOCOL == 1 + +#if IRMP_SUPPORT_MITSU_HEAVY_PROTOCOL == 1 + if (irmp_pulse_time >= MITSU_HEAVY_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= MITSU_HEAVY_START_BIT_PULSE_LEN_MAX && + irmp_pause_time >= MITSU_HEAVY_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= MITSU_HEAVY_START_BIT_PAUSE_LEN_MAX) + { // it's MITSU_HEAVY +#ifdef ANALYZE + ANALYZE_PRINTF ("protocol = MITSU_HEAVY, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", + MITSU_HEAVY_START_BIT_PULSE_LEN_MIN, MITSU_HEAVY_START_BIT_PULSE_LEN_MAX, + MITSU_HEAVY_START_BIT_PAUSE_LEN_MIN, MITSU_HEAVY_START_BIT_PAUSE_LEN_MAX); +#endif // ANALYZE + irmp_param_p = (IRMP_PARAMETER *) &mitsu_heavy_param; + } + else +#endif // IRMP_SUPPORT_MITSU_HEAVY_PROTOCOL == 1 + +#if IRMP_SUPPORT_VINCENT_PROTOCOL == 1 + if (irmp_pulse_time >= VINCENT_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= VINCENT_START_BIT_PULSE_LEN_MAX && + irmp_pause_time >= VINCENT_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= VINCENT_START_BIT_PAUSE_LEN_MAX) + { // it's VINCENT +#ifdef ANALYZE + ANALYZE_PRINTF ("protocol = VINCENT, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", + VINCENT_START_BIT_PULSE_LEN_MIN, VINCENT_START_BIT_PULSE_LEN_MAX, + VINCENT_START_BIT_PAUSE_LEN_MIN, VINCENT_START_BIT_PAUSE_LEN_MAX); +#endif // ANALYZE + irmp_param_p = (IRMP_PARAMETER *) &vincent_param; + } + else +#endif // IRMP_SUPPORT_VINCENT_PROTOCOL == 1 + +#if IRMP_SUPPORT_RADIO1_PROTOCOL == 1 + if (irmp_pulse_time >= RADIO1_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= RADIO1_START_BIT_PULSE_LEN_MAX && + irmp_pause_time >= RADIO1_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= RADIO1_START_BIT_PAUSE_LEN_MAX) + { +#ifdef ANALYZE + ANALYZE_PRINTF ("protocol = RADIO1, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", + RADIO1_START_BIT_PULSE_LEN_MIN, RADIO1_START_BIT_PULSE_LEN_MAX, + RADIO1_START_BIT_PAUSE_LEN_MIN, RADIO1_START_BIT_PAUSE_LEN_MAX); +#endif // ANALYZE + irmp_param_p = (IRMP_PARAMETER *) &radio1_param; + } + else +#endif // IRMP_SUPPORT_RRADIO1_PROTOCOL == 1 + +#if IRMP_SUPPORT_RECS80_PROTOCOL == 1 + if (irmp_pulse_time >= RECS80_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= RECS80_START_BIT_PULSE_LEN_MAX && + irmp_pause_time >= RECS80_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= RECS80_START_BIT_PAUSE_LEN_MAX) + { // it's RECS80 +#ifdef ANALYZE + ANALYZE_PRINTF ("protocol = RECS80, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", + RECS80_START_BIT_PULSE_LEN_MIN, RECS80_START_BIT_PULSE_LEN_MAX, + RECS80_START_BIT_PAUSE_LEN_MIN, RECS80_START_BIT_PAUSE_LEN_MAX); +#endif // ANALYZE + irmp_param_p = (IRMP_PARAMETER *) &recs80_param; + } + else +#endif // IRMP_SUPPORT_RECS80_PROTOCOL == 1 + +#if IRMP_SUPPORT_S100_PROTOCOL == 1 + if (((irmp_pulse_time >= S100_START_BIT_LEN_MIN && irmp_pulse_time <= S100_START_BIT_LEN_MAX) || + (irmp_pulse_time >= 2 * S100_START_BIT_LEN_MIN && irmp_pulse_time <= 2 * S100_START_BIT_LEN_MAX)) && + ((irmp_pause_time >= S100_START_BIT_LEN_MIN && irmp_pause_time <= S100_START_BIT_LEN_MAX) || + (irmp_pause_time >= 2 * S100_START_BIT_LEN_MIN && irmp_pause_time <= 2 * S100_START_BIT_LEN_MAX))) + { // it's S100 +#ifdef ANALYZE + ANALYZE_PRINTF ("protocol = S100, start bit timings: pulse: %3d - %3d, pause: %3d - %3d or pulse: %3d - %3d, pause: %3d - %3d\n", + S100_START_BIT_LEN_MIN, S100_START_BIT_LEN_MAX, + 2 * S100_START_BIT_LEN_MIN, 2 * S100_START_BIT_LEN_MAX, + S100_START_BIT_LEN_MIN, S100_START_BIT_LEN_MAX, + 2 * S100_START_BIT_LEN_MIN, 2 * S100_START_BIT_LEN_MAX); +#endif // ANALYZE + + irmp_param_p = (IRMP_PARAMETER *) &s100_param; + last_pause = irmp_pause_time; + + if ((irmp_pulse_time > S100_START_BIT_LEN_MAX && irmp_pulse_time <= 2 * S100_START_BIT_LEN_MAX) || + (irmp_pause_time > S100_START_BIT_LEN_MAX && irmp_pause_time <= 2 * S100_START_BIT_LEN_MAX)) + { + last_value = 0; + rc5_cmd_bit6 = 1<<6; + } + else + { + last_value = 1; + } + } + else +#endif // IRMP_SUPPORT_S100_PROTOCOL == 1 + +#if IRMP_SUPPORT_RC5_PROTOCOL == 1 + if (((irmp_pulse_time >= RC5_START_BIT_LEN_MIN && irmp_pulse_time <= RC5_START_BIT_LEN_MAX) || + (irmp_pulse_time >= 2 * RC5_START_BIT_LEN_MIN && irmp_pulse_time <= 2 * RC5_START_BIT_LEN_MAX)) && + ((irmp_pause_time >= RC5_START_BIT_LEN_MIN && irmp_pause_time <= RC5_START_BIT_LEN_MAX) || + (irmp_pause_time >= 2 * RC5_START_BIT_LEN_MIN && irmp_pause_time <= 2 * RC5_START_BIT_LEN_MAX))) + { // it's RC5 +#if IRMP_SUPPORT_FDC_PROTOCOL == 1 + if (irmp_pulse_time >= FDC_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= FDC_START_BIT_PULSE_LEN_MAX && + irmp_pause_time >= FDC_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= FDC_START_BIT_PAUSE_LEN_MAX) + { +#ifdef ANALYZE + ANALYZE_PRINTF ("protocol = RC5 or FDC\n"); + ANALYZE_PRINTF ("FDC start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", + FDC_START_BIT_PULSE_LEN_MIN, FDC_START_BIT_PULSE_LEN_MAX, + FDC_START_BIT_PAUSE_LEN_MIN, FDC_START_BIT_PAUSE_LEN_MAX); + ANALYZE_PRINTF ("RC5 start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", + RC5_START_BIT_LEN_MIN, RC5_START_BIT_LEN_MAX, + RC5_START_BIT_LEN_MIN, RC5_START_BIT_LEN_MAX); +#endif // ANALYZE + memcpy_P (&irmp_param2, &fdc_param, sizeof (IRMP_PARAMETER)); + } + else +#endif // IRMP_SUPPORT_FDC_PROTOCOL == 1 + +#if IRMP_SUPPORT_RCCAR_PROTOCOL == 1 + if (irmp_pulse_time >= RCCAR_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= RCCAR_START_BIT_PULSE_LEN_MAX && + irmp_pause_time >= RCCAR_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= RCCAR_START_BIT_PAUSE_LEN_MAX) + { +#ifdef ANALYZE + ANALYZE_PRINTF ("protocol = RC5 or RCCAR\n"); + ANALYZE_PRINTF ("RCCAR start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", + RCCAR_START_BIT_PULSE_LEN_MIN, RCCAR_START_BIT_PULSE_LEN_MAX, + RCCAR_START_BIT_PAUSE_LEN_MIN, RCCAR_START_BIT_PAUSE_LEN_MAX); + ANALYZE_PRINTF ("RC5 start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", + RC5_START_BIT_LEN_MIN, RC5_START_BIT_LEN_MAX, + RC5_START_BIT_LEN_MIN, RC5_START_BIT_LEN_MAX); +#endif // ANALYZE + memcpy_P (&irmp_param2, &rccar_param, sizeof (IRMP_PARAMETER)); + } + else +#endif // IRMP_SUPPORT_RCCAR_PROTOCOL == 1 + { +#ifdef ANALYZE + ANALYZE_PRINTF ("protocol = RC5, start bit timings: pulse: %3d - %3d, pause: %3d - %3d or pulse: %3d - %3d, pause: %3d - %3d\n", + RC5_START_BIT_LEN_MIN, RC5_START_BIT_LEN_MAX, + 2 * RC5_START_BIT_LEN_MIN, 2 * RC5_START_BIT_LEN_MAX, + RC5_START_BIT_LEN_MIN, RC5_START_BIT_LEN_MAX, + 2 * RC5_START_BIT_LEN_MIN, 2 * RC5_START_BIT_LEN_MAX); +#endif // ANALYZE + } + + irmp_param_p = (IRMP_PARAMETER *) &rc5_param; + last_pause = irmp_pause_time; + + if ((irmp_pulse_time > RC5_START_BIT_LEN_MAX && irmp_pulse_time <= 2 * RC5_START_BIT_LEN_MAX) || + (irmp_pause_time > RC5_START_BIT_LEN_MAX && irmp_pause_time <= 2 * RC5_START_BIT_LEN_MAX)) + { + last_value = 0; + rc5_cmd_bit6 = 1<<6; + } + else + { + last_value = 1; + } + } + else +#endif // IRMP_SUPPORT_RC5_PROTOCOL == 1 + +#if IRMP_SUPPORT_RCII_PROTOCOL == 1 + if ((irmp_pulse_time >= RCII_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= RCII_START_BIT_PULSE_LEN_MAX) && + (irmp_pause_time >= RCII_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= RCII_START_BIT_PAUSE_LEN_MAX)) + { // it's RCII +#ifdef ANALYZE + ANALYZE_PRINTF ("protocol = RCII, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", + RCII_START_BIT_PULSE_LEN_MIN, RCII_START_BIT_PULSE_LEN_MAX, + RCII_START_BIT_PAUSE_LEN_MIN, RCII_START_BIT_PAUSE_LEN_MAX) +#endif // ANALYZE + irmp_param_p = (IRMP_PARAMETER *) &rcii_param; + last_pause = irmp_pause_time; + waiting_for_2nd_pulse = 1; + last_value = 1; + } + else +#endif // IRMP_SUPPORT_RCII_PROTOCOL == 1 + +#if IRMP_SUPPORT_DENON_PROTOCOL == 1 + if ( (irmp_pulse_time >= DENON_PULSE_LEN_MIN && irmp_pulse_time <= DENON_PULSE_LEN_MAX) && + ((irmp_pause_time >= DENON_1_PAUSE_LEN_MIN && irmp_pause_time <= DENON_1_PAUSE_LEN_MAX) || + (irmp_pause_time >= DENON_0_PAUSE_LEN_MIN && irmp_pause_time <= DENON_0_PAUSE_LEN_MAX))) + { // it's DENON +#ifdef ANALYZE + ANALYZE_PRINTF ("protocol = DENON, start bit timings: pulse: %3d - %3d, pause: %3d - %3d or %3d - %3d\n", + DENON_PULSE_LEN_MIN, DENON_PULSE_LEN_MAX, + DENON_1_PAUSE_LEN_MIN, DENON_1_PAUSE_LEN_MAX, + DENON_0_PAUSE_LEN_MIN, DENON_0_PAUSE_LEN_MAX); +#endif // ANALYZE + irmp_param_p = (IRMP_PARAMETER *) &denon_param; + } + else +#endif // IRMP_SUPPORT_DENON_PROTOCOL == 1 + +#if IRMP_SUPPORT_THOMSON_PROTOCOL == 1 + if ( (irmp_pulse_time >= THOMSON_PULSE_LEN_MIN && irmp_pulse_time <= THOMSON_PULSE_LEN_MAX) && + ((irmp_pause_time >= THOMSON_1_PAUSE_LEN_MIN && irmp_pause_time <= THOMSON_1_PAUSE_LEN_MAX) || + (irmp_pause_time >= THOMSON_0_PAUSE_LEN_MIN && irmp_pause_time <= THOMSON_0_PAUSE_LEN_MAX))) + { // it's THOMSON +#ifdef ANALYZE + ANALYZE_PRINTF ("protocol = THOMSON, start bit timings: pulse: %3d - %3d, pause: %3d - %3d or %3d - %3d\n", + THOMSON_PULSE_LEN_MIN, THOMSON_PULSE_LEN_MAX, + THOMSON_1_PAUSE_LEN_MIN, THOMSON_1_PAUSE_LEN_MAX, + THOMSON_0_PAUSE_LEN_MIN, THOMSON_0_PAUSE_LEN_MAX); +#endif // ANALYZE + irmp_param_p = (IRMP_PARAMETER *) &thomson_param; + } + else +#endif // IRMP_SUPPORT_THOMSON_PROTOCOL == 1 + +#if IRMP_SUPPORT_BOSE_PROTOCOL == 1 + if (irmp_pulse_time >= BOSE_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= BOSE_START_BIT_PULSE_LEN_MAX && + irmp_pause_time >= BOSE_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= BOSE_START_BIT_PAUSE_LEN_MAX) + { +#ifdef ANALYZE + ANALYZE_PRINTF ("protocol = BOSE, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", + BOSE_START_BIT_PULSE_LEN_MIN, BOSE_START_BIT_PULSE_LEN_MAX, + BOSE_START_BIT_PAUSE_LEN_MIN, BOSE_START_BIT_PAUSE_LEN_MAX); +#endif // ANALYZE + irmp_param_p = (IRMP_PARAMETER *) &bose_param; + } + else +#endif // IRMP_SUPPORT_BOSE_PROTOCOL == 1 + +#if IRMP_SUPPORT_RC6_PROTOCOL == 1 + if (irmp_pulse_time >= RC6_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= RC6_START_BIT_PULSE_LEN_MAX && + irmp_pause_time >= RC6_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= RC6_START_BIT_PAUSE_LEN_MAX) + { // it's RC6 +#ifdef ANALYZE + ANALYZE_PRINTF ("protocol = RC6, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", + RC6_START_BIT_PULSE_LEN_MIN, RC6_START_BIT_PULSE_LEN_MAX, + RC6_START_BIT_PAUSE_LEN_MIN, RC6_START_BIT_PAUSE_LEN_MAX); +#endif // ANALYZE + irmp_param_p = (IRMP_PARAMETER *) &rc6_param; + last_pause = 0; + last_value = 1; + } + else +#endif // IRMP_SUPPORT_RC6_PROTOCOL == 1 + +#if IRMP_SUPPORT_RECS80EXT_PROTOCOL == 1 + if (irmp_pulse_time >= RECS80EXT_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= RECS80EXT_START_BIT_PULSE_LEN_MAX && + irmp_pause_time >= RECS80EXT_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= RECS80EXT_START_BIT_PAUSE_LEN_MAX) + { // it's RECS80EXT +#ifdef ANALYZE + ANALYZE_PRINTF ("protocol = RECS80EXT, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", + RECS80EXT_START_BIT_PULSE_LEN_MIN, RECS80EXT_START_BIT_PULSE_LEN_MAX, + RECS80EXT_START_BIT_PAUSE_LEN_MIN, RECS80EXT_START_BIT_PAUSE_LEN_MAX); +#endif // ANALYZE + irmp_param_p = (IRMP_PARAMETER *) &recs80ext_param; + } + else +#endif // IRMP_SUPPORT_RECS80EXT_PROTOCOL == 1 + +#if IRMP_SUPPORT_NUBERT_PROTOCOL == 1 + if (irmp_pulse_time >= NUBERT_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= NUBERT_START_BIT_PULSE_LEN_MAX && + irmp_pause_time >= NUBERT_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= NUBERT_START_BIT_PAUSE_LEN_MAX) + { // it's NUBERT +#ifdef ANALYZE + ANALYZE_PRINTF ("protocol = NUBERT, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", + NUBERT_START_BIT_PULSE_LEN_MIN, NUBERT_START_BIT_PULSE_LEN_MAX, + NUBERT_START_BIT_PAUSE_LEN_MIN, NUBERT_START_BIT_PAUSE_LEN_MAX); +#endif // ANALYZE + irmp_param_p = (IRMP_PARAMETER *) &nubert_param; + } + else +#endif // IRMP_SUPPORT_NUBERT_PROTOCOL == 1 + +#if IRMP_SUPPORT_FAN_PROTOCOL == 1 + if (irmp_pulse_time >= FAN_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= FAN_START_BIT_PULSE_LEN_MAX && + irmp_pause_time >= FAN_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= FAN_START_BIT_PAUSE_LEN_MAX) + { // it's FAN +#ifdef ANALYZE + ANALYZE_PRINTF ("protocol = FAN, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", + FAN_START_BIT_PULSE_LEN_MIN, FAN_START_BIT_PULSE_LEN_MAX, + FAN_START_BIT_PAUSE_LEN_MIN, FAN_START_BIT_PAUSE_LEN_MAX); +#endif // ANALYZE + irmp_param_p = (IRMP_PARAMETER *) &fan_param; + } + else +#endif // IRMP_SUPPORT_FAN_PROTOCOL == 1 + +#if IRMP_SUPPORT_SPEAKER_PROTOCOL == 1 + if (irmp_pulse_time >= SPEAKER_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= SPEAKER_START_BIT_PULSE_LEN_MAX && + irmp_pause_time >= SPEAKER_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= SPEAKER_START_BIT_PAUSE_LEN_MAX) + { // it's SPEAKER +#ifdef ANALYZE + ANALYZE_PRINTF ("protocol = SPEAKER, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", + SPEAKER_START_BIT_PULSE_LEN_MIN, SPEAKER_START_BIT_PULSE_LEN_MAX, + SPEAKER_START_BIT_PAUSE_LEN_MIN, SPEAKER_START_BIT_PAUSE_LEN_MAX); +#endif // ANALYZE + irmp_param_p = (IRMP_PARAMETER *) &speaker_param; + } + else +#endif // IRMP_SUPPORT_SPEAKER_PROTOCOL == 1 + +#if IRMP_SUPPORT_BANG_OLUFSEN_PROTOCOL == 1 + if (irmp_pulse_time >= BANG_OLUFSEN_START_BIT1_PULSE_LEN_MIN && irmp_pulse_time <= BANG_OLUFSEN_START_BIT1_PULSE_LEN_MAX && + irmp_pause_time >= BANG_OLUFSEN_START_BIT1_PAUSE_LEN_MIN && irmp_pause_time <= BANG_OLUFSEN_START_BIT1_PAUSE_LEN_MAX) + { // it's BANG_OLUFSEN +#ifdef ANALYZE + ANALYZE_PRINTF ("protocol = BANG_OLUFSEN\n"); + ANALYZE_PRINTF ("start bit 1 timings: pulse: %3d - %3d, pause: %3d - %3d\n", + BANG_OLUFSEN_START_BIT1_PULSE_LEN_MIN, BANG_OLUFSEN_START_BIT1_PULSE_LEN_MAX, + BANG_OLUFSEN_START_BIT1_PAUSE_LEN_MIN, BANG_OLUFSEN_START_BIT1_PAUSE_LEN_MAX); + ANALYZE_PRINTF ("start bit 2 timings: pulse: %3d - %3d, pause: %3d - %3d\n", + BANG_OLUFSEN_START_BIT2_PULSE_LEN_MIN, BANG_OLUFSEN_START_BIT2_PULSE_LEN_MAX, + BANG_OLUFSEN_START_BIT2_PAUSE_LEN_MIN, BANG_OLUFSEN_START_BIT2_PAUSE_LEN_MAX); + ANALYZE_PRINTF ("start bit 3 timings: pulse: %3d - %3d, pause: %3d - %3d\n", + BANG_OLUFSEN_START_BIT3_PULSE_LEN_MIN, BANG_OLUFSEN_START_BIT3_PULSE_LEN_MAX, + BANG_OLUFSEN_START_BIT3_PAUSE_LEN_MIN, BANG_OLUFSEN_START_BIT3_PAUSE_LEN_MAX); + ANALYZE_PRINTF ("start bit 4 timings: pulse: %3d - %3d, pause: %3d - %3d\n", + BANG_OLUFSEN_START_BIT4_PULSE_LEN_MIN, BANG_OLUFSEN_START_BIT4_PULSE_LEN_MAX, + BANG_OLUFSEN_START_BIT4_PAUSE_LEN_MIN, BANG_OLUFSEN_START_BIT4_PAUSE_LEN_MAX); +#endif // ANALYZE + irmp_param_p = (IRMP_PARAMETER *) &bang_olufsen_param; + last_value = 0; + } + else +#endif // IRMP_SUPPORT_BANG_OLUFSEN_PROTOCOL == 1 + +#if IRMP_SUPPORT_GRUNDIG_NOKIA_IR60_PROTOCOL == 1 + if (irmp_pulse_time >= GRUNDIG_NOKIA_IR60_START_BIT_LEN_MIN && irmp_pulse_time <= GRUNDIG_NOKIA_IR60_START_BIT_LEN_MAX && + irmp_pause_time >= GRUNDIG_NOKIA_IR60_PRE_PAUSE_LEN_MIN && irmp_pause_time <= GRUNDIG_NOKIA_IR60_PRE_PAUSE_LEN_MAX) + { // it's GRUNDIG +#ifdef ANALYZE + ANALYZE_PRINTF ("protocol = GRUNDIG, pre bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", + GRUNDIG_NOKIA_IR60_START_BIT_LEN_MIN, GRUNDIG_NOKIA_IR60_START_BIT_LEN_MAX, + GRUNDIG_NOKIA_IR60_PRE_PAUSE_LEN_MIN, GRUNDIG_NOKIA_IR60_PRE_PAUSE_LEN_MAX); +#endif // ANALYZE + irmp_param_p = (IRMP_PARAMETER *) &grundig_param; + last_pause = irmp_pause_time; + last_value = 1; + } + else +#endif // IRMP_SUPPORT_GRUNDIG_NOKIA_IR60_PROTOCOL == 1 + +#if IRMP_SUPPORT_MERLIN_PROTOCOL == 1 // check MERLIN before RUWIDO! + if (irmp_pulse_time >= MERLIN_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= MERLIN_START_BIT_PULSE_LEN_MAX && + irmp_pause_time >= MERLIN_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= MERLIN_START_BIT_PAUSE_LEN_MAX) + { // it's MERLIN +#ifdef ANALYZE + ANALYZE_PRINTF ("protocol = MERLIN, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", + MERLIN_START_BIT_PULSE_LEN_MIN, MERLIN_START_BIT_PULSE_LEN_MAX, + MERLIN_START_BIT_PAUSE_LEN_MIN, MERLIN_START_BIT_PAUSE_LEN_MAX); +#endif // ANALYZE + irmp_param_p = (IRMP_PARAMETER *) &merlin_param; + last_pause = 0; + last_value = 1; + } + else +#endif // IRMP_SUPPORT_MERLIN_PROTOCOL == 1 + +#if IRMP_SUPPORT_SIEMENS_OR_RUWIDO_PROTOCOL == 1 + if (((irmp_pulse_time >= SIEMENS_OR_RUWIDO_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= SIEMENS_OR_RUWIDO_START_BIT_PULSE_LEN_MAX) || + (irmp_pulse_time >= 2 * SIEMENS_OR_RUWIDO_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= 2 * SIEMENS_OR_RUWIDO_START_BIT_PULSE_LEN_MAX)) && + ((irmp_pause_time >= SIEMENS_OR_RUWIDO_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= SIEMENS_OR_RUWIDO_START_BIT_PAUSE_LEN_MAX) || + (irmp_pause_time >= 2 * SIEMENS_OR_RUWIDO_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= 2 * SIEMENS_OR_RUWIDO_START_BIT_PAUSE_LEN_MAX))) + { // it's RUWIDO or SIEMENS +#ifdef ANALYZE + ANALYZE_PRINTF ("protocol = RUWIDO, start bit timings: pulse: %3d - %3d or %3d - %3d, pause: %3d - %3d or %3d - %3d\n", + SIEMENS_OR_RUWIDO_START_BIT_PULSE_LEN_MIN, SIEMENS_OR_RUWIDO_START_BIT_PULSE_LEN_MAX, + 2 * SIEMENS_OR_RUWIDO_START_BIT_PULSE_LEN_MIN, 2 * SIEMENS_OR_RUWIDO_START_BIT_PULSE_LEN_MAX, + SIEMENS_OR_RUWIDO_START_BIT_PAUSE_LEN_MIN, SIEMENS_OR_RUWIDO_START_BIT_PAUSE_LEN_MAX, + 2 * SIEMENS_OR_RUWIDO_START_BIT_PAUSE_LEN_MIN, 2 * SIEMENS_OR_RUWIDO_START_BIT_PAUSE_LEN_MAX); +#endif // ANALYZE + irmp_param_p = (IRMP_PARAMETER *) &ruwido_param; + last_pause = irmp_pause_time; + last_value = 1; + } + else +#endif // IRMP_SUPPORT_SIEMENS_OR_RUWIDO_PROTOCOL == 1 + +#if IRMP_SUPPORT_FDC_PROTOCOL == 1 + if (irmp_pulse_time >= FDC_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= FDC_START_BIT_PULSE_LEN_MAX && + irmp_pause_time >= FDC_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= FDC_START_BIT_PAUSE_LEN_MAX) + { +#ifdef ANALYZE + ANALYZE_PRINTF ("protocol = FDC, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", + FDC_START_BIT_PULSE_LEN_MIN, FDC_START_BIT_PULSE_LEN_MAX, + FDC_START_BIT_PAUSE_LEN_MIN, FDC_START_BIT_PAUSE_LEN_MAX); +#endif // ANALYZE + irmp_param_p = (IRMP_PARAMETER *) &fdc_param; + } + else +#endif // IRMP_SUPPORT_FDC_PROTOCOL == 1 + +#if IRMP_SUPPORT_RCCAR_PROTOCOL == 1 + if (irmp_pulse_time >= RCCAR_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= RCCAR_START_BIT_PULSE_LEN_MAX && + irmp_pause_time >= RCCAR_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= RCCAR_START_BIT_PAUSE_LEN_MAX) + { +#ifdef ANALYZE + ANALYZE_PRINTF ("protocol = RCCAR, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", + RCCAR_START_BIT_PULSE_LEN_MIN, RCCAR_START_BIT_PULSE_LEN_MAX, + RCCAR_START_BIT_PAUSE_LEN_MIN, RCCAR_START_BIT_PAUSE_LEN_MAX); +#endif // ANALYZE + irmp_param_p = (IRMP_PARAMETER *) &rccar_param; + } + else +#endif // IRMP_SUPPORT_RCCAR_PROTOCOL == 1 + +#if IRMP_SUPPORT_KATHREIN_PROTOCOL == 1 + if (irmp_pulse_time >= KATHREIN_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= KATHREIN_START_BIT_PULSE_LEN_MAX && + irmp_pause_time >= KATHREIN_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= KATHREIN_START_BIT_PAUSE_LEN_MAX) + { // it's KATHREIN +#ifdef ANALYZE + ANALYZE_PRINTF ("protocol = KATHREIN, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", + KATHREIN_START_BIT_PULSE_LEN_MIN, KATHREIN_START_BIT_PULSE_LEN_MAX, + KATHREIN_START_BIT_PAUSE_LEN_MIN, KATHREIN_START_BIT_PAUSE_LEN_MAX); +#endif // ANALYZE + irmp_param_p = (IRMP_PARAMETER *) &kathrein_param; + } + else +#endif // IRMP_SUPPORT_KATHREIN_PROTOCOL == 1 + +#if IRMP_SUPPORT_NETBOX_PROTOCOL == 1 + if (irmp_pulse_time >= NETBOX_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= NETBOX_START_BIT_PULSE_LEN_MAX && + irmp_pause_time >= NETBOX_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= NETBOX_START_BIT_PAUSE_LEN_MAX) + { // it's NETBOX +#ifdef ANALYZE + ANALYZE_PRINTF ("protocol = NETBOX, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", + NETBOX_START_BIT_PULSE_LEN_MIN, NETBOX_START_BIT_PULSE_LEN_MAX, + NETBOX_START_BIT_PAUSE_LEN_MIN, NETBOX_START_BIT_PAUSE_LEN_MAX); +#endif // ANALYZE + irmp_param_p = (IRMP_PARAMETER *) &netbox_param; + } + else +#endif // IRMP_SUPPORT_NETBOX_PROTOCOL == 1 + +#if IRMP_SUPPORT_LEGO_PROTOCOL == 1 + if (irmp_pulse_time >= LEGO_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= LEGO_START_BIT_PULSE_LEN_MAX && + irmp_pause_time >= LEGO_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= LEGO_START_BIT_PAUSE_LEN_MAX) + { +#ifdef ANALYZE + ANALYZE_PRINTF ("protocol = LEGO, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", + LEGO_START_BIT_PULSE_LEN_MIN, LEGO_START_BIT_PULSE_LEN_MAX, + LEGO_START_BIT_PAUSE_LEN_MIN, LEGO_START_BIT_PAUSE_LEN_MAX); +#endif // ANALYZE + irmp_param_p = (IRMP_PARAMETER *) &lego_param; + } + else +#endif // IRMP_SUPPORT_LEGO_PROTOCOL == 1 + +#if IRMP_SUPPORT_IRMP16_PROTOCOL == 1 + if (irmp_pulse_time >= IRMP16_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= IRMP16_START_BIT_PULSE_LEN_MAX && + irmp_pause_time >= IRMP16_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= IRMP16_START_BIT_PAUSE_LEN_MAX) + { +#ifdef ANALYZE + ANALYZE_PRINTF ("protocol = IRMP16, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", + IRMP16_START_BIT_PULSE_LEN_MIN, IRMP16_START_BIT_PULSE_LEN_MAX, + IRMP16_START_BIT_PAUSE_LEN_MIN, IRMP16_START_BIT_PAUSE_LEN_MAX); +#endif // ANALYZE + irmp_param_p = (IRMP_PARAMETER *) &irmp16_param; + } + else +#endif // IRMP_SUPPORT_IRMP16_PROTOCOL == 1 + +#if IRMP_SUPPORT_GREE_PROTOCOL == 1 + if (irmp_pulse_time >= GREE_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= GREE_START_BIT_PULSE_LEN_MAX && + irmp_pause_time >= GREE_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= GREE_START_BIT_PAUSE_LEN_MAX) + { +#ifdef ANALYZE + ANALYZE_PRINTF ("protocol = GREE, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", + GREE_START_BIT_PULSE_LEN_MIN, GREE_START_BIT_PULSE_LEN_MAX, + GREE_START_BIT_PAUSE_LEN_MIN, GREE_START_BIT_PAUSE_LEN_MAX); +#endif // ANALYZE + irmp_param_p = (IRMP_PARAMETER *) &gree_param; + } + else +#endif // IRMP_SUPPORT_GREE_PROTOCOL == 1 + +#if IRMP_SUPPORT_A1TVBOX_PROTOCOL == 1 + if (irmp_pulse_time >= A1TVBOX_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= A1TVBOX_START_BIT_PULSE_LEN_MAX && + irmp_pause_time >= A1TVBOX_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= A1TVBOX_START_BIT_PAUSE_LEN_MAX) + { // it's A1TVBOX +#ifdef ANALYZE + ANALYZE_PRINTF ("protocol = A1TVBOX, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", + A1TVBOX_START_BIT_PULSE_LEN_MIN, A1TVBOX_START_BIT_PULSE_LEN_MAX, + A1TVBOX_START_BIT_PAUSE_LEN_MIN, A1TVBOX_START_BIT_PAUSE_LEN_MAX); +#endif // ANALYZE + irmp_param_p = (IRMP_PARAMETER *) &a1tvbox_param; + last_pause = 0; + last_value = 1; + } + else +#endif // IRMP_SUPPORT_A1TVBOX_PROTOCOL == 1 + +#if IRMP_SUPPORT_ORTEK_PROTOCOL == 1 + if (irmp_pulse_time >= ORTEK_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= ORTEK_START_BIT_PULSE_LEN_MAX && + irmp_pause_time >= ORTEK_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= ORTEK_START_BIT_PAUSE_LEN_MAX) + { // it's ORTEK (Hama) +#ifdef ANALYZE + ANALYZE_PRINTF ("protocol = ORTEK, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", + ORTEK_START_BIT_PULSE_LEN_MIN, ORTEK_START_BIT_PULSE_LEN_MAX, + ORTEK_START_BIT_PAUSE_LEN_MIN, ORTEK_START_BIT_PAUSE_LEN_MAX); +#endif // ANALYZE + irmp_param_p = (IRMP_PARAMETER *) &ortek_param; + last_pause = 0; + last_value = 1; + parity = 0; + } + else +#endif // IRMP_SUPPORT_ORTEK_PROTOCOL == 1 + +#if IRMP_SUPPORT_RCMM_PROTOCOL == 1 + if (irmp_pulse_time >= RCMM32_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= RCMM32_START_BIT_PULSE_LEN_MAX && + irmp_pause_time >= RCMM32_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= RCMM32_START_BIT_PAUSE_LEN_MAX) + { // it's RCMM +#ifdef ANALYZE + ANALYZE_PRINTF ("protocol = RCMM, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", + RCMM32_START_BIT_PULSE_LEN_MIN, RCMM32_START_BIT_PULSE_LEN_MAX, + RCMM32_START_BIT_PAUSE_LEN_MIN, RCMM32_START_BIT_PAUSE_LEN_MAX); +#endif // ANALYZE + irmp_param_p = (IRMP_PARAMETER *) &rcmm_param; + } + else +#endif // IRMP_SUPPORT_RCMM_PROTOCOL == 1 + { +#ifdef ANALYZE + ANALYZE_PRINTF ("protocol = UNKNOWN\n"); +#endif // ANALYZE + irmp_start_bit_detected = 0; // wait for another start bit... + } + + if (irmp_start_bit_detected) + { + memcpy_P (&irmp_param, irmp_param_p, sizeof (IRMP_PARAMETER)); + + if (! (irmp_param.flags & IRMP_PARAM_FLAG_IS_MANCHESTER)) + { +#ifdef ANALYZE + ANALYZE_PRINTF ("pulse_1: %3d - %3d\n", irmp_param.pulse_1_len_min, irmp_param.pulse_1_len_max); + ANALYZE_PRINTF ("pause_1: %3d - %3d\n", irmp_param.pause_1_len_min, irmp_param.pause_1_len_max); +#endif // ANALYZE + } + else + { +#ifdef ANALYZE + ANALYZE_PRINTF ("pulse: %3d - %3d or %3d - %3d\n", irmp_param.pulse_1_len_min, irmp_param.pulse_1_len_max, + 2 * irmp_param.pulse_1_len_min, 2 * irmp_param.pulse_1_len_max); + ANALYZE_PRINTF ("pause: %3d - %3d or %3d - %3d\n", irmp_param.pause_1_len_min, irmp_param.pause_1_len_max, + 2 * irmp_param.pause_1_len_min, 2 * irmp_param.pause_1_len_max); +#endif // ANALYZE + } + +#if IRMP_SUPPORT_RC5_PROTOCOL == 1 && (IRMP_SUPPORT_FDC_PROTOCOL == 1 || IRMP_SUPPORT_RCCAR_PROTOCOL == 1) + if (irmp_param2.protocol) + { +#ifdef ANALYZE + ANALYZE_PRINTF ("pulse_0: %3d - %3d\n", irmp_param2.pulse_0_len_min, irmp_param2.pulse_0_len_max); + ANALYZE_PRINTF ("pause_0: %3d - %3d\n", irmp_param2.pause_0_len_min, irmp_param2.pause_0_len_max); + ANALYZE_PRINTF ("pulse_1: %3d - %3d\n", irmp_param2.pulse_1_len_min, irmp_param2.pulse_1_len_max); + ANALYZE_PRINTF ("pause_1: %3d - %3d\n", irmp_param2.pause_1_len_min, irmp_param2.pause_1_len_max); +#endif // ANALYZE + } +#endif + + +#if IRMP_SUPPORT_RC6_PROTOCOL == 1 + if (irmp_param.protocol == IRMP_RC6_PROTOCOL) + { +#ifdef ANALYZE + ANALYZE_PRINTF ("pulse_toggle: %3d - %3d\n", RC6_TOGGLE_BIT_LEN_MIN, RC6_TOGGLE_BIT_LEN_MAX); +#endif // ANALYZE + } +#endif + + if (! (irmp_param.flags & IRMP_PARAM_FLAG_IS_MANCHESTER)) + { +#ifdef ANALYZE + ANALYZE_PRINTF ("pulse_0: %3d - %3d\n", irmp_param.pulse_0_len_min, irmp_param.pulse_0_len_max); + ANALYZE_PRINTF ("pause_0: %3d - %3d\n", irmp_param.pause_0_len_min, irmp_param.pause_0_len_max); +#endif // ANALYZE + } + else + { +#ifdef ANALYZE + ANALYZE_PRINTF ("pulse: %3d - %3d or %3d - %3d\n", irmp_param.pulse_0_len_min, irmp_param.pulse_0_len_max, + 2 * irmp_param.pulse_0_len_min, 2 * irmp_param.pulse_0_len_max); + ANALYZE_PRINTF ("pause: %3d - %3d or %3d - %3d\n", irmp_param.pause_0_len_min, irmp_param.pause_0_len_max, + 2 * irmp_param.pause_0_len_min, 2 * irmp_param.pause_0_len_max); +#endif // ANALYZE + } + +#ifdef ANALYZE +#if IRMP_SUPPORT_BANG_OLUFSEN_PROTOCOL == 1 + if (irmp_param.protocol == IRMP_BANG_OLUFSEN_PROTOCOL) + { + ANALYZE_PRINTF ("pulse_r: %3d - %3d\n", irmp_param.pulse_0_len_min, irmp_param.pulse_0_len_max); + ANALYZE_PRINTF ("pause_r: %3d - %3d\n", BANG_OLUFSEN_R_PAUSE_LEN_MIN, BANG_OLUFSEN_R_PAUSE_LEN_MAX); + } +#endif + + ANALYZE_PRINTF ("command_offset: %2d\n", irmp_param.command_offset); + ANALYZE_PRINTF ("command_len: %3d\n", irmp_param.command_end - irmp_param.command_offset); + ANALYZE_PRINTF ("complete_len: %3d\n", irmp_param.complete_len); + ANALYZE_PRINTF ("stop_bit: %3d\n", irmp_param.stop_bit); +#endif // ANALYZE + } + + irmp_bit = 0; + +#if IRMP_SUPPORT_MANCHESTER == 1 + if ((irmp_param.flags & IRMP_PARAM_FLAG_IS_MANCHESTER) && + irmp_param.protocol != IRMP_RUWIDO_PROTOCOL && // Manchester, but not RUWIDO + irmp_param.protocol != IRMP_RC6_PROTOCOL /*** && // Manchester, but not RC6 + irmp_param.protocol != IRMP_RCII_PROTOCOL ****/) // Manchester, but not RCII + { + if (irmp_pause_time > irmp_param.pulse_1_len_max && irmp_pause_time <= 2 * irmp_param.pulse_1_len_max) + { +#ifdef ANALYZE + ANALYZE_PRINTF ("%8.3fms [bit %2d: pulse = %3d, pause = %3d] ", (double) (time_counter * 1000) / F_INTERRUPTS, irmp_bit, irmp_pulse_time, irmp_pause_time); + ANALYZE_PUTCHAR ((irmp_param.flags & IRMP_PARAM_FLAG_1ST_PULSE_IS_1) ? '0' : '1'); + ANALYZE_NEWLINE (); +#endif // ANALYZE + irmp_store_bit ((irmp_param.flags & IRMP_PARAM_FLAG_1ST_PULSE_IS_1) ? 0 : 1); + } + else if (! last_value) // && irmp_pause_time >= irmp_param.pause_1_len_min && irmp_pause_time <= irmp_param.pause_1_len_max) + { +#ifdef ANALYZE + ANALYZE_PRINTF ("%8.3fms [bit %2d: pulse = %3d, pause = %3d] ", (double) (time_counter * 1000) / F_INTERRUPTS, irmp_bit, irmp_pulse_time, irmp_pause_time); + ANALYZE_PUTCHAR ((irmp_param.flags & IRMP_PARAM_FLAG_1ST_PULSE_IS_1) ? '1' : '0'); + ANALYZE_NEWLINE (); +#endif // ANALYZE + irmp_store_bit ((irmp_param.flags & IRMP_PARAM_FLAG_1ST_PULSE_IS_1) ? 1 : 0); + } + } + else +#endif // IRMP_SUPPORT_MANCHESTER == 1 + +#if IRMP_SUPPORT_SERIAL == 1 + if (irmp_param.flags & IRMP_PARAM_FLAG_IS_SERIAL) + { + ; // do nothing + } + else +#endif // IRMP_SUPPORT_SERIAL == 1 + + +#if IRMP_SUPPORT_DENON_PROTOCOL == 1 + if (irmp_param.protocol == IRMP_DENON_PROTOCOL) + { +#ifdef ANALYZE + ANALYZE_PRINTF ("%8.3fms [bit %2d: pulse = %3d, pause = %3d] ", (double) (time_counter * 1000) / F_INTERRUPTS, irmp_bit, irmp_pulse_time, irmp_pause_time); +#endif // ANALYZE + + if (irmp_pause_time >= DENON_1_PAUSE_LEN_MIN && irmp_pause_time <= DENON_1_PAUSE_LEN_MAX) + { // pause timings correct for "1"? +#ifdef ANALYZE + ANALYZE_PUTCHAR ('1'); // yes, store 1 + ANALYZE_NEWLINE (); +#endif // ANALYZE + irmp_store_bit (1); + } + else // if (irmp_pause_time >= DENON_0_PAUSE_LEN_MIN && irmp_pause_time <= DENON_0_PAUSE_LEN_MAX) + { // pause timings correct for "0"? +#ifdef ANALYZE + ANALYZE_PUTCHAR ('0'); // yes, store 0 + ANALYZE_NEWLINE (); +#endif // ANALYZE + irmp_store_bit (0); + } + } + else +#endif // IRMP_SUPPORT_DENON_PROTOCOL == 1 +#if IRMP_SUPPORT_THOMSON_PROTOCOL == 1 + if (irmp_param.protocol == IRMP_THOMSON_PROTOCOL) + { +#ifdef ANALYZE + ANALYZE_PRINTF ("%8.3fms [bit %2d: pulse = %3d, pause = %3d] ", (double) (time_counter * 1000) / F_INTERRUPTS, irmp_bit, irmp_pulse_time, irmp_pause_time); +#endif // ANALYZE + + if (irmp_pause_time >= THOMSON_1_PAUSE_LEN_MIN && irmp_pause_time <= THOMSON_1_PAUSE_LEN_MAX) + { // pause timings correct for "1"? +#ifdef ANALYZE + ANALYZE_PUTCHAR ('1'); // yes, store 1 + ANALYZE_NEWLINE (); +#endif // ANALYZE + irmp_store_bit (1); + } + else // if (irmp_pause_time >= THOMSON_0_PAUSE_LEN_MIN && irmp_pause_time <= THOMSON_0_PAUSE_LEN_MAX) + { // pause timings correct for "0"? +#ifdef ANALYZE + ANALYZE_PUTCHAR ('0'); // yes, store 0 + ANALYZE_NEWLINE (); +#endif // ANALYZE + irmp_store_bit (0); + } + } + else +#endif // IRMP_SUPPORT_THOMSON_PROTOCOL == 1 + { + ; // else do nothing + } + + irmp_pulse_time = 1; // set counter to 1, not 0 + irmp_pause_time = 0; + wait_for_start_space = 0; + } + } + else if (wait_for_space) // the data section.... + { // counting the time of darkness.... +#if !defined(IRMP_PULSE_IR_DECODER) + uint_fast8_t got_light = FALSE; + + if (irmp_input) // still dark? +#else + uint_fast8_t got_light = duration > IRMP_TIMEOUT_LEN ? FALSE : TRUE; + irmp_pause_time = duration; // increment counter + + if (duration > IRMP_TIMEOUT_LEN) +#endif + { // yes... + if (irmp_bit == irmp_param.complete_len && irmp_param.stop_bit == 1) + { + if ( +#if IRMP_SUPPORT_MANCHESTER == 1 + (irmp_param.flags & IRMP_PARAM_FLAG_IS_MANCHESTER) || +#endif +#if IRMP_SUPPORT_SERIAL == 1 + (irmp_param.flags & IRMP_PARAM_FLAG_IS_SERIAL) || +#endif + (irmp_pulse_time >= irmp_param.pulse_0_len_min && irmp_pulse_time <= irmp_param.pulse_0_len_max)) + { +#ifdef ANALYZE + if (! (irmp_param.flags & IRMP_PARAM_FLAG_IS_MANCHESTER)) + { + ANALYZE_PRINTF ("stop bit detected\n"); + } +#endif // ANALYZE + irmp_param.stop_bit = 0; + } + else + { +#ifdef ANALYZE + ANALYZE_PRINTF ("error: stop bit timing wrong, irmp_bit = %d, irmp_pulse_time = %d, pulse_0_len_min = %d, pulse_0_len_max = %d\n", + irmp_bit, irmp_pulse_time, irmp_param.pulse_0_len_min, irmp_param.pulse_0_len_max); +#endif // ANALYZE + irmp_start_bit_detected = 0; // wait for another start bit... + irmp_pulse_time = 0; + irmp_pause_time = 0; + } + } + else + { +#if !defined(IRMP_PULSE_IR_DECODER) + irmp_pause_time++; // increment counter + +#else + irmp_pause_time = duration; // increment counter +#endif + +#if IRMP_SUPPORT_SIRCS_PROTOCOL == 1 + if (irmp_param.protocol == IRMP_SIRCS_PROTOCOL && // Sony has a variable number of bits: + irmp_pause_time > SIRCS_PAUSE_LEN_MAX && // minimum is 12 + irmp_bit >= 12 - 1) // pause too long? + { // yes, break and close this frame + irmp_param.complete_len = irmp_bit + 1; // set new complete length + got_light = TRUE; // this is a lie, but helps (generates stop bit) + irmp_tmp_address |= (irmp_bit - SIRCS_MINIMUM_DATA_LEN + 1) << 8; // new: store number of additional bits in upper byte of address! + irmp_param.command_end = irmp_param.command_offset + irmp_bit + 1; // correct command length + irmp_pause_time = SIRCS_PAUSE_LEN_MAX - 1; // correct pause length + } + else +#endif +#if IRMP_SUPPORT_FAN_PROTOCOL == 1 + if (irmp_param.protocol == IRMP_FAN_PROTOCOL && // FAN has no stop bit. + irmp_bit >= FAN_COMPLETE_DATA_LEN - 1) // last bit in frame + { // yes, break and close this frame + if (irmp_pulse_time <= FAN_0_PULSE_LEN_MAX && irmp_pause_time >= FAN_0_PAUSE_LEN_MIN) + { +#ifdef ANALYZE + ANALYZE_PRINTF ("Generating virtual stop bit\n"); +#endif // ANALYZE + got_light = TRUE; // this is a lie, but helps (generates stop bit) + } + else if (irmp_pulse_time >= FAN_1_PULSE_LEN_MIN && irmp_pause_time >= FAN_1_PAUSE_LEN_MIN) + { +#ifdef ANALYZE + ANALYZE_PRINTF ("Generating virtual stop bit\n"); +#endif // ANALYZE + got_light = TRUE; // this is a lie, but helps (generates stop bit) + } + } + else +#endif +#if IRMP_SUPPORT_SERIAL == 1 + // NETBOX generates no stop bit, here is the timeout condition: + if ((irmp_param.flags & IRMP_PARAM_FLAG_IS_SERIAL) && irmp_param.protocol == IRMP_NETBOX_PROTOCOL && + irmp_pause_time >= NETBOX_PULSE_LEN * (NETBOX_COMPLETE_DATA_LEN - irmp_bit)) + { + got_light = TRUE; // this is a lie, but helps (generates stop bit) + } + else +#endif +#if IRMP_SUPPORT_GRUNDIG_NOKIA_IR60_PROTOCOL == 1 + if (irmp_param.protocol == IRMP_GRUNDIG_PROTOCOL && !irmp_param.stop_bit) + { + if (irmp_pause_time > IR60_TIMEOUT_LEN && (irmp_bit == 5 || irmp_bit == 6)) + { +#ifdef ANALYZE + ANALYZE_PRINTF ("Switching to IR60 protocol\n"); +#endif // ANALYZE + got_light = TRUE; // this is a lie, but generates a stop bit ;-) + irmp_param.stop_bit = TRUE; // set flag + + irmp_param.protocol = IRMP_IR60_PROTOCOL; // change protocol + irmp_param.complete_len = IR60_COMPLETE_DATA_LEN; // correct complete len + irmp_param.address_offset = IR60_ADDRESS_OFFSET; + irmp_param.address_end = IR60_ADDRESS_OFFSET + IR60_ADDRESS_LEN; + irmp_param.command_offset = IR60_COMMAND_OFFSET; + irmp_param.command_end = IR60_COMMAND_OFFSET + IR60_COMMAND_LEN; + + irmp_tmp_command <<= 1; + irmp_tmp_command |= first_bit; + } + else if (irmp_pause_time >= 2 * irmp_param.pause_1_len_max && irmp_bit >= GRUNDIG_COMPLETE_DATA_LEN - 2) + { // special manchester decoder + irmp_param.complete_len = GRUNDIG_COMPLETE_DATA_LEN; // correct complete len + got_light = TRUE; // this is a lie, but generates a stop bit ;-) + irmp_param.stop_bit = TRUE; // set flag + } + else if (irmp_bit >= GRUNDIG_COMPLETE_DATA_LEN) + { +#ifdef ANALYZE + ANALYZE_PRINTF ("Switching to NOKIA protocol, irmp_bit = %d\n", irmp_bit); +#endif // ANALYZE + irmp_param.protocol = IRMP_NOKIA_PROTOCOL; // change protocol + irmp_param.address_offset = NOKIA_ADDRESS_OFFSET; + irmp_param.address_end = NOKIA_ADDRESS_OFFSET + NOKIA_ADDRESS_LEN; + irmp_param.command_offset = NOKIA_COMMAND_OFFSET; + irmp_param.command_end = NOKIA_COMMAND_OFFSET + NOKIA_COMMAND_LEN; + + if (irmp_tmp_command & 0x300) + { + irmp_tmp_address = (irmp_tmp_command >> 8); + irmp_tmp_command &= 0xFF; + } + } + } + else +#endif +#if IRMP_SUPPORT_SIEMENS_OR_RUWIDO_PROTOCOL == 1 + if (irmp_param.protocol == IRMP_RUWIDO_PROTOCOL && !irmp_param.stop_bit) + { + if (irmp_pause_time >= 2 * irmp_param.pause_1_len_max && irmp_bit >= RUWIDO_COMPLETE_DATA_LEN - 2) + { // special manchester decoder + irmp_param.complete_len = RUWIDO_COMPLETE_DATA_LEN; // correct complete len + got_light = TRUE; // this is a lie, but generates a stop bit ;-) + irmp_param.stop_bit = TRUE; // set flag + } + else if (irmp_bit >= RUWIDO_COMPLETE_DATA_LEN) + { +#ifdef ANALYZE + ANALYZE_PRINTF ("Switching to SIEMENS protocol\n"); +#endif // ANALYZE + irmp_param.protocol = IRMP_SIEMENS_PROTOCOL; // change protocol + irmp_param.address_offset = SIEMENS_ADDRESS_OFFSET; + irmp_param.address_end = SIEMENS_ADDRESS_OFFSET + SIEMENS_ADDRESS_LEN; + irmp_param.command_offset = SIEMENS_COMMAND_OFFSET; + irmp_param.command_end = SIEMENS_COMMAND_OFFSET + SIEMENS_COMMAND_LEN; + + // 76543210 + // RUWIDO: AAAAAAAAACCCCCCCp + // SIEMENS: AAAAAAAAAAACCCCCCCCCCp + irmp_tmp_address <<= 2; + irmp_tmp_address |= (irmp_tmp_command >> 6); + irmp_tmp_command &= 0x003F; +// irmp_tmp_command <<= 4; + irmp_tmp_command |= last_value; + } + } + else +#endif +#if IRMP_SUPPORT_ROOMBA_PROTOCOL == 1 + if (irmp_param.protocol == IRMP_ROOMBA_PROTOCOL && // Roomba has no stop bit + irmp_bit >= ROOMBA_COMPLETE_DATA_LEN - 1) // it's the last data bit... + { // break and close this frame + if (irmp_pulse_time >= ROOMBA_1_PULSE_LEN_MIN && irmp_pulse_time <= ROOMBA_1_PULSE_LEN_MAX) + { + irmp_pause_time = ROOMBA_1_PAUSE_LEN_EXACT; + } + else if (irmp_pulse_time >= ROOMBA_0_PULSE_LEN_MIN && irmp_pulse_time <= ROOMBA_0_PULSE_LEN_MAX) + { + irmp_pause_time = ROOMBA_0_PAUSE_LEN; + } + + got_light = TRUE; // this is a lie, but helps (generates stop bit) + } + else +#endif +#if IRMP_SUPPORT_MANCHESTER == 1 + if ((irmp_param.flags & IRMP_PARAM_FLAG_IS_MANCHESTER) && + irmp_pause_time >= 2 * irmp_param.pause_1_len_max && irmp_bit >= irmp_param.complete_len - 2 && !irmp_param.stop_bit) + { // special manchester decoder + got_light = TRUE; // this is a lie, but generates a stop bit ;-) + irmp_param.stop_bit = TRUE; // set flag + } + else +#endif // IRMP_SUPPORT_MANCHESTER == 1 + if (irmp_pause_time > IRMP_TIMEOUT_LEN) // timeout? + { // yes... + if (irmp_bit == irmp_param.complete_len - 1 && irmp_param.stop_bit == 0) + { + irmp_bit++; + } +#if IRMP_SUPPORT_NEC_PROTOCOL == 1 + else if ((irmp_param.protocol == IRMP_NEC_PROTOCOL || irmp_param.protocol == IRMP_NEC42_PROTOCOL) && irmp_bit == 0) + { // it was a non-standard repetition frame +#ifdef ANALYZE // with 4500s pause instead of 2250s + ANALYZE_PRINTF ("Detected non-standard repetition frame, switching to NEC repetition\n"); +#endif // ANALYZE + if (key_repetition_len < NEC_FRAME_REPEAT_PAUSE_LEN_MAX) + { + irmp_param.stop_bit = TRUE; // set flag + irmp_param.protocol = IRMP_NEC_PROTOCOL; // switch protocol + irmp_param.complete_len = irmp_bit; // patch length: 16 or 17 + irmp_tmp_address = last_irmp_address; // address is last address + irmp_tmp_command = last_irmp_command; // command is last command + irmp_flags |= IRMP_FLAG_REPETITION; + key_repetition_len = 0; + } + else + { +#ifdef ANALYZE + ANALYZE_PRINTF ("ignoring NEC repetition frame: timeout occured, key_repetition_len = %d > %d\n", + key_repetition_len, NEC_FRAME_REPEAT_PAUSE_LEN_MAX); +#endif // ANALYZE + irmp_ir_detected = FALSE; + } + } +#endif // IRMP_SUPPORT_NEC_PROTOCOL == 1 +#if IRMP_SUPPORT_JVC_PROTOCOL == 1 + else if (irmp_param.protocol == IRMP_NEC_PROTOCOL && (irmp_bit == 16 || irmp_bit == 17)) // it was a JVC stop bit + { +#ifdef ANALYZE + ANALYZE_PRINTF ("Switching to JVC protocol, irmp_bit = %d\n", irmp_bit); +#endif // ANALYZE + irmp_param.stop_bit = TRUE; // set flag + irmp_param.protocol = IRMP_JVC_PROTOCOL; // switch protocol + irmp_param.complete_len = irmp_bit; // patch length: 16 or 17 + irmp_tmp_command = (irmp_tmp_address >> 4); // set command: upper 12 bits are command bits + irmp_tmp_address = irmp_tmp_address & 0x000F; // lower 4 bits are address bits + irmp_start_bit_detected = 1; // tricky: don't wait for another start bit... + } +#endif // IRMP_SUPPORT_JVC_PROTOCOL == 1 +#if IRMP_SUPPORT_LGAIR_PROTOCOL == 1 + else if (irmp_param.protocol == IRMP_NEC_PROTOCOL && (irmp_bit == 28 || irmp_bit == 29)) // it was a LGAIR stop bit + { +#ifdef ANALYZE + ANALYZE_PRINTF ("Switching to LGAIR protocol, irmp_bit = %d\n", irmp_bit); +#endif // ANALYZE + irmp_param.stop_bit = TRUE; // set flag + irmp_param.protocol = IRMP_LGAIR_PROTOCOL; // switch protocol + irmp_param.complete_len = irmp_bit; // patch length: 16 or 17 + irmp_tmp_command = irmp_lgair_command; // set command: upper 8 bits are command bits + irmp_tmp_address = irmp_lgair_address; // lower 4 bits are address bits + irmp_start_bit_detected = 1; // tricky: don't wait for another start bit... + } +#endif // IRMP_SUPPORT_LGAIR_PROTOCOL == 1 + +#if IRMP_SUPPORT_NEC42_PROTOCOL == 1 +#if IRMP_SUPPORT_NEC_PROTOCOL == 1 + else if (irmp_param.protocol == IRMP_NEC42_PROTOCOL && irmp_bit == 32) // it was a NEC stop bit + { +#ifdef ANALYZE + ANALYZE_PRINTF ("Switching to NEC protocol\n"); +#endif // ANALYZE + irmp_param.stop_bit = TRUE; // set flag + irmp_param.protocol = IRMP_NEC_PROTOCOL; // switch protocol + irmp_param.complete_len = irmp_bit; // patch length: 16 or 17 + + // 0123456789ABC0123456789ABC0123456701234567 + // NEC42: AAAAAAAAAAAAAaaaaaaaaaaaaaCCCCCCCCcccccccc + // NEC: AAAAAAAAaaaaaaaaCCCCCCCCcccccccc + irmp_tmp_address |= (irmp_tmp_address2 & 0x0007) << 13; // fm 2012-02-13: 12 -> 13 + irmp_tmp_command = (irmp_tmp_address2 >> 3) | (irmp_tmp_command << 10); + } +#endif // IRMP_SUPPORT_NEC_PROTOCOL == 1 +#if IRMP_SUPPORT_LGAIR_PROTOCOL == 1 + else if (irmp_param.protocol == IRMP_NEC42_PROTOCOL && irmp_bit == 28) // it was a NEC stop bit + { +#ifdef ANALYZE + ANALYZE_PRINTF ("Switching to LGAIR protocol\n"); +#endif // ANALYZE + irmp_param.stop_bit = TRUE; // set flag + irmp_param.protocol = IRMP_LGAIR_PROTOCOL; // switch protocol + irmp_param.complete_len = irmp_bit; // patch length: 16 or 17 + irmp_tmp_address = irmp_lgair_address; + irmp_tmp_command = irmp_lgair_command; + } +#endif // IRMP_SUPPORT_LGAIR_PROTOCOL == 1 +#if IRMP_SUPPORT_JVC_PROTOCOL == 1 + else if (irmp_param.protocol == IRMP_NEC42_PROTOCOL && (irmp_bit == 16 || irmp_bit == 17)) // it was a JVC stop bit + { +#ifdef ANALYZE + ANALYZE_PRINTF ("Switching to JVC protocol, irmp_bit = %d\n", irmp_bit); +#endif // ANALYZE + irmp_param.stop_bit = TRUE; // set flag + irmp_param.protocol = IRMP_JVC_PROTOCOL; // switch protocol + irmp_param.complete_len = irmp_bit; // patch length: 16 or 17 + + // 0123456789ABC0123456789ABC0123456701234567 + // NEC42: AAAAAAAAAAAAAaaaaaaaaaaaaaCCCCCCCCcccccccc + // JVC: AAAACCCCCCCCCCCC + irmp_tmp_command = (irmp_tmp_address >> 4) | (irmp_tmp_address2 << 9); // set command: upper 12 bits are command bits + irmp_tmp_address = irmp_tmp_address & 0x000F; // lower 4 bits are address bits + } +#endif // IRMP_SUPPORT_JVC_PROTOCOL == 1 +#endif // IRMP_SUPPORT_NEC42_PROTOCOL == 1 + +#if IRMP_SUPPORT_SAMSUNG48_PROTOCOL == 1 + else if (irmp_param.protocol == IRMP_SAMSUNG48_PROTOCOL && irmp_bit == 32) // it was a SAMSUNG32 stop bit + { +#ifdef ANALYZE + ANALYZE_PRINTF ("Switching to SAMSUNG32 protocol\n"); +#endif // ANALYZE + irmp_param.protocol = IRMP_SAMSUNG32_PROTOCOL; + irmp_param.command_offset = SAMSUNG32_COMMAND_OFFSET; + irmp_param.command_end = SAMSUNG32_COMMAND_OFFSET + SAMSUNG32_COMMAND_LEN; + irmp_param.complete_len = SAMSUNG32_COMPLETE_DATA_LEN; + } +#endif // IRMP_SUPPORT_SAMSUNG_PROTOCOL == 1 + +#if IRMP_SUPPORT_RCMM_PROTOCOL == 1 + else if (irmp_param.protocol == IRMP_RCMM32_PROTOCOL && (irmp_bit == 12 || irmp_bit == 24)) // it was a RCMM stop bit + { + if (irmp_bit == 12) + { + irmp_tmp_command = (irmp_tmp_address & 0xFF); // set command: lower 8 bits are command bits + irmp_tmp_address >>= 8; // upper 4 bits are address bits + +#ifdef ANALYZE + ANALYZE_PRINTF ("Switching to RCMM12 protocol, irmp_bit = %d\n", irmp_bit); +#endif // ANALYZE + irmp_param.protocol = IRMP_RCMM12_PROTOCOL; // switch protocol + } + else // if ((irmp_bit == 24) + { +#ifdef ANALYZE + ANALYZE_PRINTF ("Switching to RCMM24 protocol, irmp_bit = %d\n", irmp_bit); +#endif // ANALYZE + irmp_param.protocol = IRMP_RCMM24_PROTOCOL; // switch protocol + } + irmp_param.stop_bit = TRUE; // set flag + irmp_param.complete_len = irmp_bit; // patch length + } +#endif // IRMP_SUPPORT_RCMM_PROTOCOL == 1 + +#if IRMP_SUPPORT_TECHNICS_PROTOCOL == 1 + else if (irmp_param.protocol == IRMP_MATSUSHITA_PROTOCOL && irmp_bit == 22) // it was a TECHNICS stop bit + { +#ifdef ANALYZE + ANALYZE_PRINTF ("Switching to TECHNICS protocol, irmp_bit = %d\n", irmp_bit); +#endif // ANALYZE + // Situation: + // The first 12 bits have been stored in irmp_tmp_command (LSB first) + // The following 10 bits have been stored in irmp_tmp_address (LSB first) + // The code of TECHNICS is: + // cccccccccccCCCCCCCCCCC (11 times c and 11 times C) + // ccccccccccccaaaaaaaaaa + // where C is inverted value of c + + irmp_tmp_address <<= 1; + if (irmp_tmp_command & (1<<11)) + { + irmp_tmp_address |= 1; + irmp_tmp_command &= ~(1<<11); + } + + if (irmp_tmp_command == ((~irmp_tmp_address) & 0x07FF)) + { + irmp_tmp_address = 0; + + irmp_param.protocol = IRMP_TECHNICS_PROTOCOL; // switch protocol + irmp_param.complete_len = irmp_bit; // patch length + } + else + { +#ifdef ANALYZE + ANALYZE_PRINTF ("error 8: TECHNICS frame error\n"); + ANALYZE_ONLY_NORMAL_PUTCHAR ('\n'); +#endif // ANALYZE + irmp_start_bit_detected = 0; // wait for another start bit... + irmp_pulse_time = 0; + irmp_pause_time = 0; + } + } +#endif // IRMP_SUPPORT_TECHNICS_PROTOCOL == 1 + else + { +#ifdef ANALYZE + ANALYZE_PRINTF ("error 2: pause %d after data bit %d too long\n", irmp_pause_time, irmp_bit); + ANALYZE_ONLY_NORMAL_PUTCHAR ('\n'); +#endif // ANALYZE + irmp_start_bit_detected = 0; // wait for another start bit... + irmp_pulse_time = 0; + irmp_pause_time = 0; + } + } + } + } + else + { // got light now! + got_light = TRUE; + } + + if (got_light) + { +#ifdef ANALYZE + ANALYZE_PRINTF ("%8.3fms [bit %2d: pulse = %3d, pause = %3d] ", (double) (time_counter * 1000) / F_INTERRUPTS, irmp_bit, irmp_pulse_time, irmp_pause_time); +#endif // ANALYZE + +#if IRMP_SUPPORT_MANCHESTER == 1 + if ((irmp_param.flags & IRMP_PARAM_FLAG_IS_MANCHESTER)) // Manchester + { +#if 1 + if (irmp_pulse_time > irmp_param.pulse_1_len_max /* && irmp_pulse_time <= 2 * irmp_param.pulse_1_len_max */) +#else // better, but some IR-RCs use asymmetric timings :-/ + if (irmp_pulse_time > irmp_param.pulse_1_len_max && irmp_pulse_time <= 2 * irmp_param.pulse_1_len_max && + irmp_pause_time <= 2 * irmp_param.pause_1_len_max) +#endif + { +#if IRMP_SUPPORT_RC6_PROTOCOL == 1 + if (irmp_param.protocol == IRMP_RC6_PROTOCOL && irmp_bit == 4 && irmp_pulse_time > RC6_TOGGLE_BIT_LEN_MIN) // RC6 toggle bit + { +#ifdef ANALYZE + ANALYZE_PUTCHAR ('T'); +#endif // ANALYZE + if (irmp_param.complete_len == RC6_COMPLETE_DATA_LEN_LONG) // RC6 mode 6A + { + irmp_store_bit (1); + last_value = 1; + } + else // RC6 mode 0 + { + irmp_store_bit (0); + last_value = 0; + } +#ifdef ANALYZE + ANALYZE_NEWLINE (); +#endif // ANALYZE + } + else +#endif // IRMP_SUPPORT_RC6_PROTOCOL == 1 + { +#ifdef ANALYZE + ANALYZE_PUTCHAR ((irmp_param.flags & IRMP_PARAM_FLAG_1ST_PULSE_IS_1) ? '0' : '1'); +#endif // ANALYZE + irmp_store_bit ((irmp_param.flags & IRMP_PARAM_FLAG_1ST_PULSE_IS_1) ? 0 : 1 ); + +#if IRMP_SUPPORT_RC6_PROTOCOL == 1 + if (irmp_param.protocol == IRMP_RC6_PROTOCOL && irmp_bit == 4 && irmp_pulse_time > RC6_TOGGLE_BIT_LEN_MIN) // RC6 toggle bit + { +#ifdef ANALYZE + ANALYZE_PUTCHAR ('T'); +#endif // ANALYZE + irmp_store_bit (1); + + if (irmp_pause_time > 2 * irmp_param.pause_1_len_max) + { + last_value = 0; + } + else + { + last_value = 1; + } +#ifdef ANALYZE + ANALYZE_NEWLINE (); +#endif // ANALYZE + } + else +#endif // IRMP_SUPPORT_RC6_PROTOCOL == 1 + { +#ifdef ANALYZE + ANALYZE_PUTCHAR ((irmp_param.flags & IRMP_PARAM_FLAG_1ST_PULSE_IS_1) ? '1' : '0'); +#endif // ANALYZE + irmp_store_bit ((irmp_param.flags & IRMP_PARAM_FLAG_1ST_PULSE_IS_1) ? 1 : 0 ); + +#if IRMP_SUPPORT_RC5_PROTOCOL == 1 && IRMP_SUPPORT_RCII_PROTOCOL == 1 && (IRMP_SUPPORT_FDC_PROTOCOL == 1 || IRMP_SUPPORT_RCCAR_PROTOCOL == 1) + if (! irmp_param2.protocol) +#endif + { +#ifdef ANALYZE + ANALYZE_NEWLINE (); +#endif // ANALYZE + } + last_value = (irmp_param.flags & IRMP_PARAM_FLAG_1ST_PULSE_IS_1) ? 1 : 0; + } + } + } + else if (irmp_pulse_time >= irmp_param.pulse_1_len_min && irmp_pulse_time <= irmp_param.pulse_1_len_max + /* && irmp_pause_time <= 2 * irmp_param.pause_1_len_max */) + { + uint_fast8_t manchester_value; + + if (last_pause > irmp_param.pause_1_len_max && last_pause <= 2 * irmp_param.pause_1_len_max) + { + manchester_value = last_value ? 0 : 1; + last_value = manchester_value; + } + else + { + manchester_value = last_value; + } + +#ifdef ANALYZE + ANALYZE_PUTCHAR (manchester_value + '0'); +#endif // ANALYZE + +#if IRMP_SUPPORT_RC5_PROTOCOL == 1 && (IRMP_SUPPORT_FDC_PROTOCOL == 1 || IRMP_SUPPORT_RCCAR_PROTOCOL == 1) + if (! irmp_param2.protocol) +#endif + { +#ifdef ANALYZE + ANALYZE_NEWLINE (); +#endif // ANALYZE + } + +#if IRMP_SUPPORT_RC6_PROTOCOL == 1 + if (irmp_param.protocol == IRMP_RC6_PROTOCOL && irmp_bit == 1 && manchester_value == 1) // RC6 mode != 0 ??? + { +#ifdef ANALYZE + ANALYZE_PRINTF ("Switching to RC6A protocol\n"); +#endif // ANALYZE + irmp_param.complete_len = RC6_COMPLETE_DATA_LEN_LONG; +#if !defined(U_BOOT_COMPATIBLE) + irmp_param.address_offset = 5; + irmp_param.address_end = irmp_param.address_offset + 15; + irmp_param.command_offset = irmp_param.address_end + 1; // skip 1 system bit, changes like a toggle bit + irmp_param.command_end = irmp_param.command_offset + 16 - 1; +#else + irmp_param.address_offset = 4; + irmp_param.address_end = irmp_param.address_offset + 16; + irmp_param.command_offset = irmp_param.address_end + 1; + irmp_param.command_end = irmp_param.command_offset + 16 - 1; +#endif + irmp_tmp_address = 0; + } +#endif // IRMP_SUPPORT_RC6_PROTOCOL == 1 + + irmp_store_bit (manchester_value); + +#if defined(IRMP_PULSE_IR_DECODER) + if (irmp_bit == irmp_param.complete_len && irmp_param.stop_bit == 1) + { + if ( +#if IRMP_SUPPORT_MANCHESTER == 1 + (irmp_param.flags & IRMP_PARAM_FLAG_IS_MANCHESTER) || +#endif +#if IRMP_SUPPORT_SERIAL == 1 + (irmp_param.flags & IRMP_PARAM_FLAG_IS_SERIAL) || +#endif + (irmp_pulse_time >= irmp_param.pulse_0_len_min && irmp_pulse_time <= irmp_param.pulse_0_len_max)) + { +#ifdef ANALYZE + if (!(irmp_param.flags & IRMP_PARAM_FLAG_IS_MANCHESTER)) + { + ANALYZE_PRINTF("stop bit detected\n"); + } +#endif // ANALYZE + irmp_param.stop_bit = 0; + } + else + { +#ifdef ANALYZE + ANALYZE_PRINTF("error: stop bit timing wrong, irmp_bit = %d, irmp_pulse_time = %d, pulse_0_len_min = %d, pulse_0_len_max = %d\n", + irmp_bit, irmp_pulse_time, irmp_param.pulse_0_len_min, irmp_param.pulse_0_len_max); +#endif // ANALYZE + irmp_start_bit_detected = 0; // wait for another start bit... + irmp_pulse_time = 0; + irmp_pause_time = 0; + } + } +#endif + } + else + { +#if IRMP_SUPPORT_RC5_PROTOCOL == 1 && IRMP_SUPPORT_FDC_PROTOCOL == 1 + if (irmp_param2.protocol == IRMP_FDC_PROTOCOL && + irmp_pulse_time >= FDC_PULSE_LEN_MIN && irmp_pulse_time <= FDC_PULSE_LEN_MAX && + ((irmp_pause_time >= FDC_1_PAUSE_LEN_MIN && irmp_pause_time <= FDC_1_PAUSE_LEN_MAX) || + (irmp_pause_time >= FDC_0_PAUSE_LEN_MIN && irmp_pause_time <= FDC_0_PAUSE_LEN_MAX))) + { +#ifdef ANALYZE + ANALYZE_PUTCHAR ('?'); +#endif // ANALYZE + irmp_param.protocol = 0; // switch to FDC, see below + } + else +#endif // IRMP_SUPPORT_FDC_PROTOCOL == 1 +#if IRMP_SUPPORT_RC5_PROTOCOL == 1 && IRMP_SUPPORT_RCCAR_PROTOCOL == 1 + if (irmp_param2.protocol == IRMP_RCCAR_PROTOCOL && + irmp_pulse_time >= RCCAR_PULSE_LEN_MIN && irmp_pulse_time <= RCCAR_PULSE_LEN_MAX && + ((irmp_pause_time >= RCCAR_1_PAUSE_LEN_MIN && irmp_pause_time <= RCCAR_1_PAUSE_LEN_MAX) || + (irmp_pause_time >= RCCAR_0_PAUSE_LEN_MIN && irmp_pause_time <= RCCAR_0_PAUSE_LEN_MAX))) + { +#ifdef ANALYZE + ANALYZE_PUTCHAR ('?'); +#endif // ANALYZE + irmp_param.protocol = 0; // switch to RCCAR, see below + } + else +#endif // IRMP_SUPPORT_RCCAR_PROTOCOL == 1 + { +#ifdef ANALYZE + ANALYZE_PUTCHAR ('?'); + ANALYZE_NEWLINE (); + ANALYZE_PRINTF ("error 3 manchester: timing not correct: data bit %d, pulse: %d, pause: %d\n", irmp_bit, irmp_pulse_time, irmp_pause_time); + ANALYZE_ONLY_NORMAL_PUTCHAR ('\n'); +#endif // ANALYZE + irmp_start_bit_detected = 0; // reset flags and wait for next start bit + irmp_pause_time = 0; + } + } + +#if IRMP_SUPPORT_RC5_PROTOCOL == 1 && IRMP_SUPPORT_FDC_PROTOCOL == 1 + if (irmp_param2.protocol == IRMP_FDC_PROTOCOL && irmp_pulse_time >= FDC_PULSE_LEN_MIN && irmp_pulse_time <= FDC_PULSE_LEN_MAX) + { + if (irmp_pause_time >= FDC_1_PAUSE_LEN_MIN && irmp_pause_time <= FDC_1_PAUSE_LEN_MAX) + { +#ifdef ANALYZE + ANALYZE_PRINTF (" 1 (FDC)\n"); +#endif // ANALYZE + irmp_store_bit2 (1); + } + else if (irmp_pause_time >= FDC_0_PAUSE_LEN_MIN && irmp_pause_time <= FDC_0_PAUSE_LEN_MAX) + { +#ifdef ANALYZE + ANALYZE_PRINTF (" 0 (FDC)\n"); +#endif // ANALYZE + irmp_store_bit2 (0); + } + + if (! irmp_param.protocol) + { +#ifdef ANALYZE + ANALYZE_PRINTF ("Switching to FDC protocol\n"); +#endif // ANALYZE + memcpy (&irmp_param, &irmp_param2, sizeof (IRMP_PARAMETER)); + irmp_param2.protocol = 0; + irmp_tmp_address = irmp_tmp_address2; + irmp_tmp_command = irmp_tmp_command2; + } + } +#endif // IRMP_SUPPORT_FDC_PROTOCOL == 1 +#if IRMP_SUPPORT_RC5_PROTOCOL == 1 && IRMP_SUPPORT_RCCAR_PROTOCOL == 1 + if (irmp_param2.protocol == IRMP_RCCAR_PROTOCOL && irmp_pulse_time >= RCCAR_PULSE_LEN_MIN && irmp_pulse_time <= RCCAR_PULSE_LEN_MAX) + { + if (irmp_pause_time >= RCCAR_1_PAUSE_LEN_MIN && irmp_pause_time <= RCCAR_1_PAUSE_LEN_MAX) + { +#ifdef ANALYZE + ANALYZE_PRINTF (" 1 (RCCAR)\n"); +#endif // ANALYZE + irmp_store_bit2 (1); + } + else if (irmp_pause_time >= RCCAR_0_PAUSE_LEN_MIN && irmp_pause_time <= RCCAR_0_PAUSE_LEN_MAX) + { +#ifdef ANALYZE + ANALYZE_PRINTF (" 0 (RCCAR)\n"); +#endif // ANALYZE + irmp_store_bit2 (0); + } + + if (! irmp_param.protocol) + { +#ifdef ANALYZE + ANALYZE_PRINTF ("Switching to RCCAR protocol\n"); +#endif // ANALYZE + memcpy (&irmp_param, &irmp_param2, sizeof (IRMP_PARAMETER)); + irmp_param2.protocol = 0; + irmp_tmp_address = irmp_tmp_address2; + irmp_tmp_command = irmp_tmp_command2; + } + } +#endif // IRMP_SUPPORT_RCCAR_PROTOCOL == 1 + + last_pause = irmp_pause_time; + wait_for_space = 0; + } + else +#endif // IRMP_SUPPORT_MANCHESTER == 1 + +#if IRMP_SUPPORT_SERIAL == 1 + if (irmp_param.flags & IRMP_PARAM_FLAG_IS_SERIAL) + { + while (irmp_bit < irmp_param.complete_len && irmp_pulse_time > irmp_param.pulse_1_len_max) + { +#ifdef ANALYZE + ANALYZE_PUTCHAR ('1'); +#endif // ANALYZE + irmp_store_bit (1); + + if (irmp_pulse_time >= irmp_param.pulse_1_len_min) + { + irmp_pulse_time -= irmp_param.pulse_1_len_min; + } + else + { + irmp_pulse_time = 0; + } + } + + while (irmp_bit < irmp_param.complete_len && irmp_pause_time > irmp_param.pause_1_len_max) + { +#ifdef ANALYZE + ANALYZE_PUTCHAR ('0'); +#endif // ANALYZE + irmp_store_bit (0); + + if (irmp_pause_time >= irmp_param.pause_1_len_min) + { + irmp_pause_time -= irmp_param.pause_1_len_min; + } + else + { + irmp_pause_time = 0; + } + } +#ifdef ANALYZE + ANALYZE_NEWLINE (); +#endif // ANALYZE + wait_for_space = 0; + } + else +#endif // IRMP_SUPPORT_SERIAL == 1 + +#if IRMP_SUPPORT_SAMSUNG_PROTOCOL == 1 + if (irmp_param.protocol == IRMP_SAMSUNG_PROTOCOL && irmp_bit == 16) // Samsung: 16th bit + { + if (irmp_pulse_time >= SAMSUNG_PULSE_LEN_MIN && irmp_pulse_time <= SAMSUNG_PULSE_LEN_MAX && + irmp_pause_time >= SAMSUNG_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= SAMSUNG_START_BIT_PAUSE_LEN_MAX) + { +#ifdef ANALYZE + ANALYZE_PRINTF ("SYNC\n"); +#endif // ANALYZE + wait_for_space = 0; + irmp_bit++; + } + else if (irmp_pulse_time >= SAMSUNG_PULSE_LEN_MIN && irmp_pulse_time <= SAMSUNG_PULSE_LEN_MAX) + { +#if IRMP_SUPPORT_SAMSUNG48_PROTOCOL == 1 +#ifdef ANALYZE + ANALYZE_PRINTF ("Switching to SAMSUNG48 protocol "); +#endif // ANALYZE + irmp_param.protocol = IRMP_SAMSUNG48_PROTOCOL; + irmp_param.command_offset = SAMSUNG48_COMMAND_OFFSET; + irmp_param.command_end = SAMSUNG48_COMMAND_OFFSET + SAMSUNG48_COMMAND_LEN; + irmp_param.complete_len = SAMSUNG48_COMPLETE_DATA_LEN; +#else +#ifdef ANALYZE + ANALYZE_PRINTF ("Switching to SAMSUNG32 protocol "); +#endif // ANALYZE + irmp_param.protocol = IRMP_SAMSUNG32_PROTOCOL; + irmp_param.command_offset = SAMSUNG32_COMMAND_OFFSET; + irmp_param.command_end = SAMSUNG32_COMMAND_OFFSET + SAMSUNG32_COMMAND_LEN; + irmp_param.complete_len = SAMSUNG32_COMPLETE_DATA_LEN; +#endif + if (irmp_pause_time >= SAMSUNG_1_PAUSE_LEN_MIN && irmp_pause_time <= SAMSUNG_1_PAUSE_LEN_MAX) + { +#ifdef ANALYZE + ANALYZE_PUTCHAR ('1'); + ANALYZE_NEWLINE (); +#endif // ANALYZE + irmp_store_bit (1); + wait_for_space = 0; + } + else + { +#ifdef ANALYZE + ANALYZE_PUTCHAR ('0'); + ANALYZE_NEWLINE (); +#endif // ANALYZE + irmp_store_bit (0); + wait_for_space = 0; + } + } + else + { // timing incorrect! +#ifdef ANALYZE + ANALYZE_PRINTF ("error 3 Samsung: timing not correct: data bit %d, pulse: %d, pause: %d\n", irmp_bit, irmp_pulse_time, irmp_pause_time); + ANALYZE_ONLY_NORMAL_PUTCHAR ('\n'); +#endif // ANALYZE + irmp_start_bit_detected = 0; // reset flags and wait for next start bit + irmp_pause_time = 0; + } + } + else +#endif // IRMP_SUPPORT_SAMSUNG_PROTOCOL + +#if IRMP_SUPPORT_NEC16_PROTOCOL +#if IRMP_SUPPORT_NEC42_PROTOCOL == 1 + if (irmp_param.protocol == IRMP_NEC42_PROTOCOL && +#else // IRMP_SUPPORT_NEC_PROTOCOL instead + if (irmp_param.protocol == IRMP_NEC_PROTOCOL && +#endif // IRMP_SUPPORT_NEC42_PROTOCOL == 1 + irmp_bit == 8 && irmp_pause_time >= NEC_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= NEC_START_BIT_PAUSE_LEN_MAX) + { +#ifdef ANALYZE + ANALYZE_PRINTF ("Switching to NEC16 protocol\n"); +#endif // ANALYZE + irmp_param.protocol = IRMP_NEC16_PROTOCOL; + irmp_param.address_offset = NEC16_ADDRESS_OFFSET; + irmp_param.address_end = NEC16_ADDRESS_OFFSET + NEC16_ADDRESS_LEN; + irmp_param.command_offset = NEC16_COMMAND_OFFSET; + irmp_param.command_end = NEC16_COMMAND_OFFSET + NEC16_COMMAND_LEN; + irmp_param.complete_len = NEC16_COMPLETE_DATA_LEN; + wait_for_space = 0; + } + else +#endif // IRMP_SUPPORT_NEC16_PROTOCOL + +#if IRMP_SUPPORT_BANG_OLUFSEN_PROTOCOL == 1 + if (irmp_param.protocol == IRMP_BANG_OLUFSEN_PROTOCOL) + { + if (irmp_pulse_time >= BANG_OLUFSEN_PULSE_LEN_MIN && irmp_pulse_time <= BANG_OLUFSEN_PULSE_LEN_MAX) + { + if (irmp_bit == 1) // Bang & Olufsen: 3rd bit + { + if (irmp_pause_time >= BANG_OLUFSEN_START_BIT3_PAUSE_LEN_MIN && irmp_pause_time <= BANG_OLUFSEN_START_BIT3_PAUSE_LEN_MAX) + { +#ifdef ANALYZE + ANALYZE_PRINTF ("3rd start bit\n"); +#endif // ANALYZE + wait_for_space = 0; + irmp_bit++; + } + else + { // timing incorrect! +#ifdef ANALYZE + ANALYZE_PRINTF ("error 3a B&O: timing not correct: data bit %d, pulse: %d, pause: %d\n", irmp_bit, irmp_pulse_time, irmp_pause_time); + ANALYZE_ONLY_NORMAL_PUTCHAR ('\n'); +#endif // ANALYZE + irmp_start_bit_detected = 0; // reset flags and wait for next start bit + irmp_pause_time = 0; + } + } + else if (irmp_bit == 19) // Bang & Olufsen: trailer bit + { + if (irmp_pause_time >= BANG_OLUFSEN_TRAILER_BIT_PAUSE_LEN_MIN && irmp_pause_time <= BANG_OLUFSEN_TRAILER_BIT_PAUSE_LEN_MAX) + { +#ifdef ANALYZE + ANALYZE_PRINTF ("trailer bit\n"); +#endif // ANALYZE + wait_for_space = 0; + irmp_bit++; + } + else + { // timing incorrect! +#ifdef ANALYZE + ANALYZE_PRINTF ("error 3b B&O: timing not correct: data bit %d, pulse: %d, pause: %d\n", irmp_bit, irmp_pulse_time, irmp_pause_time); + ANALYZE_ONLY_NORMAL_PUTCHAR ('\n'); +#endif // ANALYZE + irmp_start_bit_detected = 0; // reset flags and wait for next start bit + irmp_pause_time = 0; + } + } + else + { + if (irmp_pause_time >= BANG_OLUFSEN_1_PAUSE_LEN_MIN && irmp_pause_time <= BANG_OLUFSEN_1_PAUSE_LEN_MAX) + { // pulse & pause timings correct for "1"? +#ifdef ANALYZE + ANALYZE_PUTCHAR ('1'); + ANALYZE_NEWLINE (); +#endif // ANALYZE + irmp_store_bit (1); + last_value = 1; + wait_for_space = 0; + } + else if (irmp_pause_time >= BANG_OLUFSEN_0_PAUSE_LEN_MIN && irmp_pause_time <= BANG_OLUFSEN_0_PAUSE_LEN_MAX) + { // pulse & pause timings correct for "0"? +#ifdef ANALYZE + ANALYZE_PUTCHAR ('0'); + ANALYZE_NEWLINE (); +#endif // ANALYZE + irmp_store_bit (0); + last_value = 0; + wait_for_space = 0; + } + else if (irmp_pause_time >= BANG_OLUFSEN_R_PAUSE_LEN_MIN && irmp_pause_time <= BANG_OLUFSEN_R_PAUSE_LEN_MAX) + { +#ifdef ANALYZE + ANALYZE_PUTCHAR (last_value + '0'); + ANALYZE_NEWLINE (); +#endif // ANALYZE + irmp_store_bit (last_value); + wait_for_space = 0; + } + else + { // timing incorrect! +#ifdef ANALYZE + ANALYZE_PRINTF ("error 3c B&O: timing not correct: data bit %d, pulse: %d, pause: %d\n", irmp_bit, irmp_pulse_time, irmp_pause_time); + ANALYZE_ONLY_NORMAL_PUTCHAR ('\n'); +#endif // ANALYZE + irmp_start_bit_detected = 0; // reset flags and wait for next start bit + irmp_pause_time = 0; + } + } + } + else + { // timing incorrect! +#ifdef ANALYZE + ANALYZE_PRINTF ("error 3d B&O: timing not correct: data bit %d, pulse: %d, pause: %d\n", irmp_bit, irmp_pulse_time, irmp_pause_time); + ANALYZE_ONLY_NORMAL_PUTCHAR ('\n'); +#endif // ANALYZE + irmp_start_bit_detected = 0; // reset flags and wait for next start bit + irmp_pause_time = 0; + } + } + else +#endif // IRMP_SUPPORT_BANG_OLUFSEN_PROTOCOL + +#if IRMP_SUPPORT_RCMM_PROTOCOL == 1 + if (irmp_param.protocol == IRMP_RCMM32_PROTOCOL) + { + if (irmp_pause_time >= RCMM32_BIT_00_PAUSE_LEN_MIN && irmp_pause_time <= RCMM32_BIT_00_PAUSE_LEN_MAX) + { +#ifdef ANALYZE + ANALYZE_PUTCHAR ('0'); + ANALYZE_PUTCHAR ('0'); +#endif // ANALYZE + irmp_store_bit (0); + irmp_store_bit (0); + } + else if (irmp_pause_time >= RCMM32_BIT_01_PAUSE_LEN_MIN && irmp_pause_time <= RCMM32_BIT_01_PAUSE_LEN_MAX) + { +#ifdef ANALYZE + ANALYZE_PUTCHAR ('0'); + ANALYZE_PUTCHAR ('1'); +#endif // ANALYZE + irmp_store_bit (0); + irmp_store_bit (1); + } + else if (irmp_pause_time >= RCMM32_BIT_10_PAUSE_LEN_MIN && irmp_pause_time <= RCMM32_BIT_10_PAUSE_LEN_MAX) + { +#ifdef ANALYZE + ANALYZE_PUTCHAR ('1'); + ANALYZE_PUTCHAR ('0'); +#endif // ANALYZE + irmp_store_bit (1); + irmp_store_bit (0); + } + else if (irmp_pause_time >= RCMM32_BIT_11_PAUSE_LEN_MIN && irmp_pause_time <= RCMM32_BIT_11_PAUSE_LEN_MAX) + { +#ifdef ANALYZE + ANALYZE_PUTCHAR ('1'); + ANALYZE_PUTCHAR ('1'); +#endif // ANALYZE + irmp_store_bit (1); + irmp_store_bit (1); + } +#ifdef ANALYZE + ANALYZE_PRINTF ("\n"); +#endif // ANALYZE + wait_for_space = 0; + } + else +#endif + + if (irmp_pulse_time >= irmp_param.pulse_1_len_min && irmp_pulse_time <= irmp_param.pulse_1_len_max && + irmp_pause_time >= irmp_param.pause_1_len_min && irmp_pause_time <= irmp_param.pause_1_len_max) + { // pulse & pause timings correct for "1"? +#ifdef ANALYZE + ANALYZE_PUTCHAR ('1'); + ANALYZE_NEWLINE (); +#endif // ANALYZE + irmp_store_bit (1); + wait_for_space = 0; + } + else if (irmp_pulse_time >= irmp_param.pulse_0_len_min && irmp_pulse_time <= irmp_param.pulse_0_len_max && + irmp_pause_time >= irmp_param.pause_0_len_min && irmp_pause_time <= irmp_param.pause_0_len_max) + { // pulse & pause timings correct for "0"? +#ifdef ANALYZE + ANALYZE_PUTCHAR ('0'); + ANALYZE_NEWLINE (); +#endif // ANALYZE + irmp_store_bit (0); + wait_for_space = 0; + } + else +#if IRMP_SUPPORT_KATHREIN_PROTOCOL + + if (irmp_param.protocol == IRMP_KATHREIN_PROTOCOL && + irmp_pulse_time >= KATHREIN_1_PULSE_LEN_MIN && irmp_pulse_time <= KATHREIN_1_PULSE_LEN_MAX && + (((irmp_bit == 8 || irmp_bit == 6) && + irmp_pause_time >= KATHREIN_SYNC_BIT_PAUSE_LEN_MIN && irmp_pause_time <= KATHREIN_SYNC_BIT_PAUSE_LEN_MAX) || + (irmp_bit == 12 && + irmp_pause_time >= KATHREIN_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= KATHREIN_START_BIT_PAUSE_LEN_MAX))) + + { + if (irmp_bit == 8) + { + irmp_bit++; +#ifdef ANALYZE + ANALYZE_PUTCHAR ('S'); + ANALYZE_NEWLINE (); +#endif // ANALYZE + irmp_tmp_command <<= 1; + } + else + { +#ifdef ANALYZE + ANALYZE_PUTCHAR ('S'); + ANALYZE_NEWLINE (); +#endif // ANALYZE + irmp_store_bit (1); + } + wait_for_space = 0; + } + else +#endif // IRMP_SUPPORT_KATHREIN_PROTOCOL + { // timing incorrect! +#ifdef ANALYZE + ANALYZE_PRINTF ("error 3: timing not correct: data bit %d, pulse: %d, pause: %d\n", irmp_bit, irmp_pulse_time, irmp_pause_time); + ANALYZE_ONLY_NORMAL_PUTCHAR ('\n'); +#endif // ANALYZE + irmp_start_bit_detected = 0; // reset flags and wait for next start bit + irmp_pause_time = 0; + } + + irmp_pulse_time = 1; // set counter to 1, not 0 + } + } + else + { // counting the pulse length ... +#if !defined(IRMP_PULSE_IR_DECODER) + if (! irmp_input) // still light? + { // yes... + irmp_pulse_time++; // increment counter + } + else + { // now it's dark! +#else + irmp_pulse_time = duration; // increment counter +#endif + wait_for_space = 1; // let's count the time (see above) + irmp_pause_time = 1; // set pause counter to 1, not 0 + +#if IRMP_SUPPORT_RCII_PROTOCOL == 1 + if (irmp_param.protocol == IRMP_RCII_PROTOCOL && waiting_for_2nd_pulse) + { + if (irmp_pulse_time >= RCII_BIT_LEN) + { + irmp_pulse_time -= RCII_BIT_LEN; + last_value = 0; + } + else + { + last_value = 1; + } +#ifdef ANALYZE + ANALYZE_PRINTF ("RCII: got 2nd pulse, irmp_pulse_time = %d\n", irmp_pulse_time); +#endif + waiting_for_2nd_pulse = 0; + } +#endif +#if !defined(IRMP_PULSE_IR_DECODER) + } +#endif + } + + if (irmp_start_bit_detected && irmp_bit == irmp_param.complete_len && irmp_param.stop_bit == 0) // enough bits received? + { + if (last_irmp_command == irmp_tmp_command && key_repetition_len < AUTO_FRAME_REPETITION_LEN) + { + repetition_frame_number++; + } + else + { + repetition_frame_number = 0; + } + +#if IRMP_SUPPORT_SIRCS_PROTOCOL == 1 + // if SIRCS protocol and the code will be repeated within 50 ms, we will ignore 2nd and 3rd repetition frame + if (irmp_param.protocol == IRMP_SIRCS_PROTOCOL && (repetition_frame_number == 1 || repetition_frame_number == 2)) + { +#ifdef ANALYZE + ANALYZE_PRINTF ("code skipped: SIRCS auto repetition frame #%d, counter = %d, auto repetition len = %d\n", + repetition_frame_number + 1, key_repetition_len, AUTO_FRAME_REPETITION_LEN); +#endif // ANALYZE + key_repetition_len = 0; + } + else +#endif + +#if IRMP_SUPPORT_ORTEK_PROTOCOL == 1 + // if ORTEK protocol and the code will be repeated within 50 ms, we will ignore 2nd repetition frame + if (irmp_param.protocol == IRMP_ORTEK_PROTOCOL && repetition_frame_number == 1) + { +#ifdef ANALYZE + ANALYZE_PRINTF ("code skipped: ORTEK auto repetition frame #%d, counter = %d, auto repetition len = %d\n", + repetition_frame_number + 1, key_repetition_len, AUTO_FRAME_REPETITION_LEN); +#endif // ANALYZE + key_repetition_len = 0; + } + else +#endif + +#if 0 && IRMP_SUPPORT_KASEIKYO_PROTOCOL == 1 // fm 2015-12-02: don't ignore every 2nd frame + // if KASEIKYO protocol and the code will be repeated within 50 ms, we will ignore 2nd repetition frame + if (irmp_param.protocol == IRMP_KASEIKYO_PROTOCOL && repetition_frame_number == 1) + { +#ifdef ANALYZE + ANALYZE_PRINTF ("code skipped: KASEIKYO auto repetition frame #%d, counter = %d, auto repetition len = %d\n", + repetition_frame_number + 1, key_repetition_len, AUTO_FRAME_REPETITION_LEN); +#endif // ANALYZE + key_repetition_len = 0; + } + else +#endif + +#if 0 && IRMP_SUPPORT_SAMSUNG_PROTOCOL == 1 // fm 2015-12-02: don't ignore every 2nd frame + // if SAMSUNG32 or SAMSUNG48 protocol and the code will be repeated within 50 ms, we will ignore every 2nd frame + if ((irmp_param.protocol == IRMP_SAMSUNG32_PROTOCOL || irmp_param.protocol == IRMP_SAMSUNG48_PROTOCOL) && (repetition_frame_number & 0x01)) + { +#ifdef ANALYZE + ANALYZE_PRINTF ("code skipped: SAMSUNG32/SAMSUNG48 auto repetition frame #%d, counter = %d, auto repetition len = %d\n", + repetition_frame_number + 1, key_repetition_len, AUTO_FRAME_REPETITION_LEN); +#endif // ANALYZE + key_repetition_len = 0; + } + else +#endif + +#if IRMP_SUPPORT_NUBERT_PROTOCOL == 1 + // if NUBERT protocol and the code will be repeated within 50 ms, we will ignore every 2nd frame + if (irmp_param.protocol == IRMP_NUBERT_PROTOCOL && (repetition_frame_number & 0x01)) + { +#ifdef ANALYZE + ANALYZE_PRINTF ("code skipped: NUBERT auto repetition frame #%d, counter = %d, auto repetition len = %d\n", + repetition_frame_number + 1, key_repetition_len, AUTO_FRAME_REPETITION_LEN); +#endif // ANALYZE + key_repetition_len = 0; + } + else +#endif + +#if IRMP_SUPPORT_SPEAKER_PROTOCOL == 1 + // if SPEAKER protocol and the code will be repeated within 50 ms, we will ignore every 2nd frame + if (irmp_param.protocol == IRMP_SPEAKER_PROTOCOL && (repetition_frame_number & 0x01)) + { +#ifdef ANALYZE + ANALYZE_PRINTF ("code skipped: SPEAKER auto repetition frame #%d, counter = %d, auto repetition len = %d\n", + repetition_frame_number + 1, key_repetition_len, AUTO_FRAME_REPETITION_LEN); +#endif // ANALYZE + key_repetition_len = 0; + } + else +#endif + + { +#ifdef ANALYZE + ANALYZE_PRINTF ("%8.3fms code detected, length = %d\n", (double) (time_counter * 1000) / F_INTERRUPTS, irmp_bit); +#endif // ANALYZE + irmp_ir_detected = TRUE; + +#if IRMP_SUPPORT_DENON_PROTOCOL == 1 + if (irmp_param.protocol == IRMP_DENON_PROTOCOL) + { // check for repetition frame + if ((~irmp_tmp_command & 0x3FF) == last_irmp_denon_command) // command bits must be inverted + { + irmp_tmp_command = last_irmp_denon_command; // use command received before! + last_irmp_denon_command = 0; + + irmp_protocol = irmp_param.protocol; // store protocol + irmp_address = irmp_tmp_address; // store address + irmp_command = irmp_tmp_command; // store command + } + else + { + if ((irmp_tmp_command & 0x01) == 0x00) + { +#ifdef ANALYZE + ANALYZE_PRINTF ("%8.3fms info Denon: waiting for inverted command repetition\n", (double) (time_counter * 1000) / F_INTERRUPTS); +#endif // ANALYZE + last_irmp_denon_command = irmp_tmp_command; + denon_repetition_len = 0; + irmp_ir_detected = FALSE; + } + else + { +#ifdef ANALYZE + ANALYZE_PRINTF ("%8.3fms warning Denon: got unexpected inverted command, ignoring it\n", (double) (time_counter * 1000) / F_INTERRUPTS); +#endif // ANALYZE + last_irmp_denon_command = 0; + irmp_ir_detected = FALSE; + } + } + } + else +#endif // IRMP_SUPPORT_DENON_PROTOCOL + +#if IRMP_SUPPORT_GRUNDIG_PROTOCOL == 1 + if (irmp_param.protocol == IRMP_GRUNDIG_PROTOCOL && irmp_tmp_command == 0x01ff) + { // Grundig start frame? +#ifdef ANALYZE + ANALYZE_PRINTF ("Detected GRUNDIG start frame, ignoring it\n"); +#endif // ANALYZE + irmp_ir_detected = FALSE; + } + else +#endif // IRMP_SUPPORT_GRUNDIG_PROTOCOL + +#if IRMP_SUPPORT_NOKIA_PROTOCOL == 1 + if (irmp_param.protocol == IRMP_NOKIA_PROTOCOL && irmp_tmp_address == 0x00ff && irmp_tmp_command == 0x00fe) + { // Nokia start frame? +#ifdef ANALYZE + ANALYZE_PRINTF ("Detected NOKIA start frame, ignoring it\n"); +#endif // ANALYZE + irmp_ir_detected = FALSE; + } + else +#endif // IRMP_SUPPORT_NOKIA_PROTOCOL + { +#if IRMP_SUPPORT_NEC_PROTOCOL == 1 + if (irmp_param.protocol == IRMP_NEC_PROTOCOL && irmp_bit == 0) // repetition frame + { + if (key_repetition_len < NEC_FRAME_REPEAT_PAUSE_LEN_MAX) + { +#ifdef ANALYZE + ANALYZE_PRINTF ("Detected NEC repetition frame, key_repetition_len = %d\n", key_repetition_len); + ANALYZE_ONLY_NORMAL_PRINTF("REPETETION FRAME "); +#endif // ANALYZE + irmp_tmp_address = last_irmp_address; // address is last address + irmp_tmp_command = last_irmp_command; // command is last command + irmp_flags |= IRMP_FLAG_REPETITION; + key_repetition_len = 0; + } + else + { +#ifdef ANALYZE + ANALYZE_PRINTF ("Detected NEC repetition frame, ignoring it: timeout occured, key_repetition_len = %d > %d\n", + key_repetition_len, NEC_FRAME_REPEAT_PAUSE_LEN_MAX); +#endif // ANALYZE + irmp_ir_detected = FALSE; + } + } +#endif // IRMP_SUPPORT_NEC_PROTOCOL + +#if IRMP_SUPPORT_KASEIKYO_PROTOCOL == 1 + if (irmp_param.protocol == IRMP_KASEIKYO_PROTOCOL) + { + uint_fast8_t xor_value; + + xor_value = (xor_check[0] & 0x0F) ^ ((xor_check[0] & 0xF0) >> 4) ^ (xor_check[1] & 0x0F) ^ ((xor_check[1] & 0xF0) >> 4); + + if (xor_value != (xor_check[2] & 0x0F)) + { +#ifdef ANALYZE + ANALYZE_PRINTF ("error 4: wrong XOR check for customer id: 0x%1x 0x%1x\n", xor_value, xor_check[2] & 0x0F); +#endif // ANALYZE + irmp_ir_detected = FALSE; + } + + xor_value = xor_check[2] ^ xor_check[3] ^ xor_check[4]; + + if (xor_value != xor_check[5]) + { +#ifdef ANALYZE + ANALYZE_PRINTF ("error 5: wrong XOR check for data bits: 0x%02x 0x%02x\n", xor_value, xor_check[5]); +#endif // ANALYZE + irmp_ir_detected = FALSE; + } + + irmp_flags |= genre2; // write the genre2 bits into MSB of the flag byte + } +#endif // IRMP_SUPPORT_KASEIKYO_PROTOCOL == 1 + +#if IRMP_SUPPORT_ORTEK_PROTOCOL == 1 + if (irmp_param.protocol == IRMP_ORTEK_PROTOCOL) + { + if (parity == PARITY_CHECK_FAILED) + { +#ifdef ANALYZE + ANALYZE_PRINTF ("error 6: parity check failed\n"); +#endif // ANALYZE + irmp_ir_detected = FALSE; + } + + if ((irmp_tmp_address & 0x03) == 0x02) + { +#ifdef ANALYZE + ANALYZE_PRINTF ("code skipped: ORTEK end of transmission frame (key release)\n"); +#endif // ANALYZE + irmp_ir_detected = FALSE; + } + irmp_tmp_address >>= 2; + } +#endif // IRMP_SUPPORT_ORTEK_PROTOCOL == 1 + +#if IRMP_SUPPORT_MITSU_HEAVY_PROTOCOL == 1 + if (irmp_param.protocol == IRMP_MITSU_HEAVY_PROTOCOL) + { + check = irmp_tmp_command >> 8; // inverted upper byte == lower byte? + check = ~ check; + if (check == (irmp_tmp_command & 0xFF)) { //ok: + irmp_tmp_command &= 0xFF; + } + else mitsu_parity = PARITY_CHECK_FAILED; + if (mitsu_parity == PARITY_CHECK_FAILED) + { +#ifdef ANALYZE + ANALYZE_PRINTF ("error 7: parity check failed\n"); +#endif // ANALYZE + irmp_ir_detected = FALSE; + } + } +#endif // IRMP_SUPPORT_MITSU_HEAVY_PROTOCOL + +#if IRMP_SUPPORT_RC6_PROTOCOL == 1 + if (irmp_param.protocol == IRMP_RC6_PROTOCOL && irmp_param.complete_len == RC6_COMPLETE_DATA_LEN_LONG) // RC6 mode = 6? + { + irmp_protocol = IRMP_RC6A_PROTOCOL; + } + else +#endif // IRMP_SUPPORT_RC6_PROTOCOL == 1 + { + irmp_protocol = irmp_param.protocol; + } + +#if IRMP_SUPPORT_FDC_PROTOCOL == 1 + if (irmp_param.protocol == IRMP_FDC_PROTOCOL) + { + if (irmp_tmp_command & 0x000F) // released key? + { + irmp_tmp_command = (irmp_tmp_command >> 4) | 0x80; // yes, set bit 7 + } + else + { + irmp_tmp_command >>= 4; // no, it's a pressed key + } + irmp_tmp_command |= (irmp_tmp_address << 2) & 0x0F00; // 000000CCCCAAAAAA -> 0000CCCC00000000 + irmp_tmp_address &= 0x003F; + } +#endif + + irmp_address = irmp_tmp_address; // store address +#if IRMP_SUPPORT_NEC_PROTOCOL == 1 + if (irmp_param.protocol == IRMP_NEC_PROTOCOL) + { + last_irmp_address = irmp_tmp_address; // store as last address, too + } +#endif + +#if IRMP_SUPPORT_RC5_PROTOCOL == 1 + if (irmp_param.protocol == IRMP_RC5_PROTOCOL) + { + irmp_tmp_command |= rc5_cmd_bit6; // store bit 6 + } +#endif +#if IRMP_SUPPORT_S100_PROTOCOL == 1 + if (irmp_param.protocol == IRMP_S100_PROTOCOL) + { + irmp_tmp_command |= rc5_cmd_bit6; // store bit 6 + } +#endif + irmp_command = irmp_tmp_command; // store command + +#if IRMP_SUPPORT_SAMSUNG_PROTOCOL == 1 + irmp_id = irmp_tmp_id; +#endif + } + } + + if (irmp_ir_detected) + { + if (last_irmp_command == irmp_tmp_command && + last_irmp_address == irmp_tmp_address && + key_repetition_len < IRMP_KEY_REPETITION_LEN) + { + irmp_flags |= IRMP_FLAG_REPETITION; + } + + last_irmp_address = irmp_tmp_address; // store as last address, too + last_irmp_command = irmp_tmp_command; // store as last command, too + + key_repetition_len = 0; + } + else + { +#ifdef ANALYZE + ANALYZE_ONLY_NORMAL_PUTCHAR ('\n'); +#endif // ANALYZE + } + + irmp_start_bit_detected = 0; // and wait for next start bit + irmp_tmp_command = 0; + irmp_pulse_time = 0; + irmp_pause_time = 0; + +#if IRMP_SUPPORT_JVC_PROTOCOL == 1 + if (irmp_protocol == IRMP_JVC_PROTOCOL) // the stop bit of JVC frame is also start bit of next frame + { // set pulse time here! + irmp_pulse_time = ((uint_fast8_t)(F_INTERRUPTS * JVC_START_BIT_PULSE_TIME)); + } +#endif // IRMP_SUPPORT_JVC_PROTOCOL == 1 + } + } + } + +#if defined(STELLARIS_ARM_CORTEX_M4) + // Clear the timer interrupt + TimerIntClear(TIMER1_BASE, TIMER_TIMA_TIMEOUT); +#endif + +#if (defined(_CHIBIOS_RT_) || defined(_CHIBIOS_NIL_)) && IRMP_USE_EVENT == 1 + if (IRMP_EVENT_THREAD_PTR != NULL && irmp_ir_detected) + chEvtSignalI(IRMP_EVENT_THREAD_PTR,IRMP_EVENT_BIT); +#endif + +#if IRMP_USE_IDLE_CALL == 1 + // check if there is no ongoing transmission or repetition + if (!irmp_start_bit_detected && !irmp_pulse_time + && key_repetition_len > IRMP_KEY_REPETITION_LEN) + { + // no ongoing transmission + // enough time passed since last decoded signal that a repetition won't affect our output + + irmp_idle(); + } +#endif // IRMP_USE_IDLE_CALL + + return (irmp_ir_detected); +} + +#ifdef ANALYZE + +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * main functions - for Unix/Linux + Windows only! + * + * AVR: see main.c! + * + * Compile it under linux with: + * cc irmp.c -o irmp + * + * usage: ./irmp [-v|-s|-a|-l] < file + * + * options: + * -v verbose + * -s silent + * -a analyze + * -l list pulse/pauses + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ + +void +print_spectrum (char * text, int * buf, int is_pulse) +{ + int i; + int j; + int min; + int max; + int max_value = 0; + int value; + int sum = 0; + int counter = 0; + double average = 0; + double tolerance; + + puts ("-----------------------------------------------------------------------------"); + printf ("%s:\n", text); + + for (i = 0; i < 256; i++) + { + if (buf[i] > max_value) + { + max_value = buf[i]; + } + } + + for (i = 1; i < 200; i++) + { + if (buf[i] > 0) + { + printf ("%3d ", i); + value = (buf[i] * 60) / max_value; + + for (j = 0; j < value; j++) + { + putchar ('o'); + } + printf (" %d\n", buf[i]); + + sum += i * buf[i]; + counter += buf[i]; + } + else + { + max = i - 1; + + if (counter > 0) + { + average = (float) sum / (float) counter; + + if (is_pulse) + { + printf ("pulse "); + } + else + { + printf ("pause "); + } + + printf ("avg: %4.1f=%6.1f us, ", average, (1000000. * average) / (float) F_INTERRUPTS); + printf ("min: %2d=%6.1f us, ", min, (1000000. * min) / (float) F_INTERRUPTS); + printf ("max: %2d=%6.1f us, ", max, (1000000. * max) / (float) F_INTERRUPTS); + + tolerance = (max - average); + + if (average - min > tolerance) + { + tolerance = average - min; + } + + tolerance = tolerance * 100 / average; + printf ("tol: %4.1f%%\n", tolerance); + } + + counter = 0; + sum = 0; + min = i + 1; + } + } +} + +#define STATE_LEFT_SHIFT 0x01 +#define STATE_RIGHT_SHIFT 0x02 +#define STATE_LEFT_CTRL 0x04 +#define STATE_LEFT_ALT 0x08 +#define STATE_RIGHT_ALT 0x10 + +#define KEY_ESCAPE 0x1B // keycode = 0x006e +#define KEY_MENUE 0x80 // keycode = 0x0070 +#define KEY_BACK 0x81 // keycode = 0x0071 +#define KEY_FORWARD 0x82 // keycode = 0x0072 +#define KEY_ADDRESS 0x83 // keycode = 0x0073 +#define KEY_WINDOW 0x84 // keycode = 0x0074 +#define KEY_1ST_PAGE 0x85 // keycode = 0x0075 +#define KEY_STOP 0x86 // keycode = 0x0076 +#define KEY_MAIL 0x87 // keycode = 0x0077 +#define KEY_FAVORITES 0x88 // keycode = 0x0078 +#define KEY_NEW_PAGE 0x89 // keycode = 0x0079 +#define KEY_SETUP 0x8A // keycode = 0x007a +#define KEY_FONT 0x8B // keycode = 0x007b +#define KEY_PRINT 0x8C // keycode = 0x007c +#define KEY_ON_OFF 0x8E // keycode = 0x007c + +#define KEY_INSERT 0x90 // keycode = 0x004b +#define KEY_DELETE 0x91 // keycode = 0x004c +#define KEY_LEFT 0x92 // keycode = 0x004f +#define KEY_HOME 0x93 // keycode = 0x0050 +#define KEY_END 0x94 // keycode = 0x0051 +#define KEY_UP 0x95 // keycode = 0x0053 +#define KEY_DOWN 0x96 // keycode = 0x0054 +#define KEY_PAGE_UP 0x97 // keycode = 0x0055 +#define KEY_PAGE_DOWN 0x98 // keycode = 0x0056 +#define KEY_RIGHT 0x99 // keycode = 0x0059 +#define KEY_MOUSE_1 0x9E // keycode = 0x0400 +#define KEY_MOUSE_2 0x9F // keycode = 0x0800 + +static uint_fast8_t +get_fdc_key (uint_fast16_t cmd) +{ + static uint8_t key_table[128] = + { + // 0 1 2 3 4 5 6 7 8 9 A B C D E F + 0, '^', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', 0xDF, '', 0, '\b', + '\t', 'q', 'w', 'e', 'r', 't', 'z', 'u', 'i', 'o', 'p', 0xFC, '+', 0, 0, 'a', + 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 0xF6, 0xE4, '#', '\r', 0, '<', 'y', 'x', + 'c', 'v', 'b', 'n', 'm', ',', '.', '-', 0, 0, 0, 0, 0, ' ', 0, 0, + + 0, '', '!', '"', '', '$', '%', '&', '/', '(', ')', '=', '?', '`', 0, '\b', + '\t', 'Q', 'W', 'E', 'R', 'T', 'Z', 'U', 'I', 'O', 'P', 0xDC, '*', 0, 0, 'A', + 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', 0xD6, 0xC4, '\'', '\r', 0, '>', 'Y', 'X', + 'C', 'V', 'B', 'N', 'M', ';', ':', '_', 0, 0, 0, 0, 0, ' ', 0, 0 + }; + static uint_fast8_t state; + + uint_fast8_t key = 0; + + switch (cmd) + { + case 0x002C: state |= STATE_LEFT_SHIFT; break; // pressed left shift + case 0x00AC: state &= ~STATE_LEFT_SHIFT; break; // released left shift + case 0x0039: state |= STATE_RIGHT_SHIFT; break; // pressed right shift + case 0x00B9: state &= ~STATE_RIGHT_SHIFT; break; // released right shift + case 0x003A: state |= STATE_LEFT_CTRL; break; // pressed left ctrl + case 0x00BA: state &= ~STATE_LEFT_CTRL; break; // released left ctrl + case 0x003C: state |= STATE_LEFT_ALT; break; // pressed left alt + case 0x00BC: state &= ~STATE_LEFT_ALT; break; // released left alt + case 0x003E: state |= STATE_RIGHT_ALT; break; // pressed left alt + case 0x00BE: state &= ~STATE_RIGHT_ALT; break; // released left alt + + case 0x006e: key = KEY_ESCAPE; break; + case 0x004b: key = KEY_INSERT; break; + case 0x004c: key = KEY_DELETE; break; + case 0x004f: key = KEY_LEFT; break; + case 0x0050: key = KEY_HOME; break; + case 0x0051: key = KEY_END; break; + case 0x0053: key = KEY_UP; break; + case 0x0054: key = KEY_DOWN; break; + case 0x0055: key = KEY_PAGE_UP; break; + case 0x0056: key = KEY_PAGE_DOWN; break; + case 0x0059: key = KEY_RIGHT; break; + case 0x0400: key = KEY_MOUSE_1; break; + case 0x0800: key = KEY_MOUSE_2; break; + + default: + { + if (!(cmd & 0x80)) // pressed key + { + if (cmd >= 0x70 && cmd <= 0x7F) // function keys + { + key = cmd + 0x10; // 7x -> 8x + } + else if (cmd < 64) // key listed in key_table + { + if (state & (STATE_LEFT_ALT | STATE_RIGHT_ALT)) + { + switch (cmd) + { + case 0x0003: key = 0xB2; break; // upper 2 + case 0x0008: key = '{'; break; + case 0x0009: key = '['; break; + case 0x000A: key = ']'; break; + case 0x000B: key = '}'; break; + case 0x000C: key = '\\'; break; + case 0x001C: key = '~'; break; + case 0x002D: key = '|'; break; + case 0x0034: key = 0xB5; break; // Mu + } + } + else if (state & (STATE_LEFT_CTRL)) + { + if (key_table[cmd] >= 'a' && key_table[cmd] <= 'z') + { + key = key_table[cmd] - 'a' + 1; + } + else + { + key = key_table[cmd]; + } + } + else + { + int idx = cmd + ((state & (STATE_LEFT_SHIFT | STATE_RIGHT_SHIFT)) ? 64 : 0); + + if (key_table[idx]) + { + key = key_table[idx]; + } + } + } + } + break; + } + } + + return (key); +} + +static int analyze = FALSE; +static int list = FALSE; +static IRMP_DATA irmp_data; +static int expected_protocol; +static int expected_address; +static int expected_command; +static int do_check_expected_values; + +static void +next_tick (void) +{ + if (! analyze && ! list) + { + (void) irmp_ISR (); + + if (irmp_get_data (&irmp_data)) + { + uint_fast8_t key; + + ANALYZE_ONLY_NORMAL_PUTCHAR (' '); + + if (verbose) + { + printf ("%8.3fms ", (double) (time_counter * 1000) / F_INTERRUPTS); + } + + if (irmp_data.protocol == IRMP_ACP24_PROTOCOL) + { + uint16_t temp = (irmp_data.command & 0x000F) + 15; + + printf ("p=%2d (%s), a=0x%04x, c=0x%04x, f=0x%02x, temp=%d", + irmp_data.protocol, irmp_protocol_names[irmp_data.protocol], irmp_data.address, irmp_data.command, irmp_data.flags, temp); + } + else if (irmp_data.protocol == IRMP_FDC_PROTOCOL && (key = get_fdc_key (irmp_data.command)) != 0) + { + if ((key >= 0x20 && key < 0x7F) || key >= 0xA0) + { + printf ("p=%2d (%s), a=0x%04x, c=0x%04x, f=0x%02x, asc=0x%02x, key='%c'", + irmp_data.protocol, irmp_protocol_names[irmp_data.protocol], irmp_data.address, irmp_data.command, irmp_data.flags, key, key); + } + else if (key == '\r' || key == '\t' || key == KEY_ESCAPE || (key >= 0x80 && key <= 0x9F)) // function keys + { + char * p = (char *) NULL; + + switch (key) + { + case '\t' : p = "TAB"; break; + case '\r' : p = "CR"; break; + case KEY_ESCAPE : p = "ESCAPE"; break; + case KEY_MENUE : p = "MENUE"; break; + case KEY_BACK : p = "BACK"; break; + case KEY_FORWARD : p = "FORWARD"; break; + case KEY_ADDRESS : p = "ADDRESS"; break; + case KEY_WINDOW : p = "WINDOW"; break; + case KEY_1ST_PAGE : p = "1ST_PAGE"; break; + case KEY_STOP : p = "STOP"; break; + case KEY_MAIL : p = "MAIL"; break; + case KEY_FAVORITES : p = "FAVORITES"; break; + case KEY_NEW_PAGE : p = "NEW_PAGE"; break; + case KEY_SETUP : p = "SETUP"; break; + case KEY_FONT : p = "FONT"; break; + case KEY_PRINT : p = "PRINT"; break; + case KEY_ON_OFF : p = "ON_OFF"; break; + + case KEY_INSERT : p = "INSERT"; break; + case KEY_DELETE : p = "DELETE"; break; + case KEY_LEFT : p = "LEFT"; break; + case KEY_HOME : p = "HOME"; break; + case KEY_END : p = "END"; break; + case KEY_UP : p = "UP"; break; + case KEY_DOWN : p = "DOWN"; break; + case KEY_PAGE_UP : p = "PAGE_UP"; break; + case KEY_PAGE_DOWN : p = "PAGE_DOWN"; break; + case KEY_RIGHT : p = "RIGHT"; break; + case KEY_MOUSE_1 : p = "KEY_MOUSE_1"; break; + case KEY_MOUSE_2 : p = "KEY_MOUSE_2"; break; + default : p = ""; break; + } + + printf ("p=%2d (%s), a=0x%04x, c=0x%04x, f=0x%02x, asc=0x%02x, key=%s", + irmp_data.protocol, irmp_protocol_names[irmp_data.protocol], irmp_data.address, irmp_data.command, irmp_data.flags, key, p); + } + else + { + printf ("p=%2d (%s), a=0x%04x, c=0x%04x, f=0x%02x, asc=0x%02x", + irmp_data.protocol, irmp_protocol_names[irmp_data.protocol], irmp_data.address, irmp_data.command, irmp_data.flags, key); + } + } + else + { + printf ("p=%2d (%s), a=0x%04x, c=0x%04x, f=0x%02x", + irmp_data.protocol, irmp_protocol_names[irmp_data.protocol], irmp_data.address, irmp_data.command, irmp_data.flags); + } + + if (do_check_expected_values) + { + if (irmp_data.protocol != expected_protocol || + irmp_data.address != expected_address || + irmp_data.command != expected_command) + { + printf ("\nerror 7: expected values differ: p=%2d (%s), a=0x%04x, c=0x%04x\n", + expected_protocol, irmp_protocol_names[expected_protocol], expected_address, expected_command); + } + else + { + printf (" checked!\n"); + } + do_check_expected_values = FALSE; // only check 1st frame in a line! + } + else + { + putchar ('\n'); + } + } + } +} + +int +main (int argc, char ** argv) +{ + int i; + int ch; + int last_ch = 0; + int pulse = 0; + int pause = 0; + + int start_pulses[256]; + int start_pauses[256]; + int pulses[256]; + int pauses[256]; + + int first_pulse = TRUE; + int first_pause = TRUE; + + if (argc == 2) + { + if (! strcmp (argv[1], "-v")) + { + verbose = TRUE; + } + else if (! strcmp (argv[1], "-l")) + { + list = TRUE; + } + else if (! strcmp (argv[1], "-a")) + { + analyze = TRUE; + } + else if (! strcmp (argv[1], "-s")) + { + silent = TRUE; + } + else if (! strcmp (argv[1], "-r")) + { + radio = TRUE; + } + } + + for (i = 0; i < 256; i++) + { + start_pulses[i] = 0; + start_pauses[i] = 0; + pulses[i] = 0; + pauses[i] = 0; + } + + IRMP_PIN = 0xFF; + + while ((ch = getchar ()) != EOF) + { + if (ch == '_' || ch == '0') + { + if (last_ch != ch) + { + if (pause > 0) + { + if (list) + { + printf ("pause: %d\n", pause); + } + + if (analyze) + { + if (first_pause) + { + if (pause < 256) + { + start_pauses[pause]++; + } + first_pause = FALSE; + } + else + { + if (pause < 256) + { + pauses[pause]++; + } + } + } + } + pause = 0; + } + pulse++; + IRMP_PIN = 0x00; + } + else if (ch == 0xaf || ch == '-' || ch == '1') + { + if (last_ch != ch) + { + if (list) + { + printf ("pulse: %d ", pulse); + } + + if (analyze) + { + if (first_pulse) + { + if (pulse < 256) + { + start_pulses[pulse]++; + } + first_pulse = FALSE; + } + else + { + if (pulse < 256) + { + pulses[pulse]++; + } + } + } + pulse = 0; + } + + pause++; + IRMP_PIN = 0xff; + } + else if (ch == '\n') + { + IRMP_PIN = 0xff; + time_counter = 0; + + if (list && pause > 0) + { + printf ("pause: %d\n", pause); + } + pause = 0; + + if (! analyze) + { + for (i = 0; i < (int) ((10000.0 * F_INTERRUPTS) / 10000); i++) // newline: long pause of 10000 msec + { + next_tick (); + } + } + first_pulse = TRUE; + first_pause = TRUE; + } + else if (ch == '#') + { + time_counter = 0; + + if (analyze) + { + while ((ch = getchar()) != '\n' && ch != EOF) + { + ; + } + } + else + { + char buf[1024]; + char * p; + int idx = -1; + + puts ("----------------------------------------------------------------------"); + putchar (ch); + + + while ((ch = getchar()) != '\n' && ch != EOF) + { + if (ch != '\r') // ignore CR in DOS/Windows files + { + if (ch == '[' && idx == -1) + { + idx = 0; + } + else if (idx >= 0) + { + if (ch == ']') + { + do_check_expected_values = FALSE; + buf[idx] = '\0'; + idx = -1; + + expected_protocol = atoi (buf); + + if (expected_protocol > 0) + { + p = buf; + while (*p) + { + if (*p == 'x') + { + p++; + + if (sscanf (p, "%x", &expected_address) == 1) + { + do_check_expected_values = TRUE; + } + break; + } + p++; + } + + if (do_check_expected_values) + { + do_check_expected_values = FALSE; + + while (*p) + { + if (*p == 'x') + { + p++; + + if (sscanf (p, "%x", &expected_command) == 1) + { + do_check_expected_values = TRUE; + } + break; + } + p++; + } + + if (do_check_expected_values) + { + // printf ("!%2d %04x %04x!\n", expected_protocol, expected_address, expected_command); + } + } + } + } + else if (idx < 1024 - 2) + { + buf[idx++] = ch; + } + } + putchar (ch); + } + } + putchar ('\n'); + } + + } + + last_ch = ch; + + next_tick (); + } + + if (analyze) + { + print_spectrum ("START PULSES", start_pulses, TRUE); + print_spectrum ("START PAUSES", start_pauses, FALSE); + print_spectrum ("PULSES", pulses, TRUE); + print_spectrum ("PAUSES", pauses, FALSE); + puts ("-----------------------------------------------------------------------------"); + } + return 0; +} + +#endif // ANALYZE diff --git a/drivers/media/rc/irmp/irmp.h b/drivers/media/rc/irmp/irmp.h new file mode 100644 index 000000000000..bdc88badb723 --- /dev/null +++ b/drivers/media/rc/irmp/irmp.h @@ -0,0 +1,290 @@ +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * irmp.h + * + * Copyright (c) 2009-2018 Frank Meyer - frank(at)fli4l.de + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ + +#ifndef _IRMP_H_ +#define _IRMP_H_ + +#include "irmpsystem.h" + +#ifndef IRMP_USE_AS_LIB +# include "irmpconfig.h" +#endif + +#if defined (__AVR_XMEGA__) +# define _CONCAT(a,b) a##b +# define CONCAT(a,b) _CONCAT(a,b) +# define IRMP_PORT_PRE CONCAT(PORT, IRMP_PORT_LETTER) +# define IRMP_DDR_PRE CONCAT(PORT, IRMP_PORT_LETTER) +# define IRMP_PIN_PRE CONCAT(PORT, IRMP_PORT_LETTER) +# define IRMP_PORT IRMP_PORT_PRE.OUT +# define IRMP_DDR IRMP_DDR_PRE.DIR +# define IRMP_PIN IRMP_PIN_PRE.IN +# define IRMP_BIT IRMP_BIT_NUMBER +# define input(x) ((x) & (1 << IRMP_BIT)) + +#elif defined (ATMEL_AVR) +# define _CONCAT(a,b) a##b +# define CONCAT(a,b) _CONCAT(a,b) +# define IRMP_PORT CONCAT(PORT, IRMP_PORT_LETTER) +# define IRMP_DDR CONCAT(DDR, IRMP_PORT_LETTER) +# define IRMP_PIN CONCAT(PIN, IRMP_PORT_LETTER) +# define IRMP_BIT IRMP_BIT_NUMBER +# define input(x) ((x) & (1 << IRMP_BIT)) + +#elif defined (PIC_C18) || defined (PIC_CCS) +# define input(x) (x) + +#elif defined (ARM_STM32) +# define _CONCAT(a,b) a##b +# define CONCAT(a,b) _CONCAT(a,b) +# define IRMP_PORT CONCAT(GPIO, IRMP_PORT_LETTER) +# if defined (ARM_STM32L1XX) +# define IRMP_PORT_RCC CONCAT(RCC_AHBPeriph_GPIO, IRMP_PORT_LETTER) +# elif defined (ARM_STM32F10X) +# define IRMP_PORT_RCC CONCAT(RCC_APB2Periph_GPIO, IRMP_PORT_LETTER) +# elif defined (ARM_STM32F4XX) +# define IRMP_PORT_RCC CONCAT(RCC_AHB1Periph_GPIO, IRMP_PORT_LETTER) +# endif +# define IRMP_BIT CONCAT(GPIO_Pin_, IRMP_BIT_NUMBER) +# define IRMP_PIN IRMP_PORT // for use with input(x) below +# define input(x) (GPIO_ReadInputDataBit(x, IRMP_BIT)) +# ifndef USE_STDPERIPH_DRIVER +# warning The STM32 port of IRMP uses the ST standard peripheral drivers which are not enabled in your build configuration. +# endif + +#elif defined (ARM_STM32_HAL) +# define IRMP_BIT IRMP_BIT_NUMBER +# define IRMP_PIN IRMP_BIT_NUMBER // for use with input(x) below +# define input(x) HAL_GPIO_ReadPin(IRMP_PORT_LETTER, x) + +#elif defined (STELLARIS_ARM_CORTEX_M4) +# define _CONCAT(a,b) a##b +# define CONCAT(a,b) _CONCAT(a,b) +# define IRMP_PORT_PERIPH CONCAT(SYSCTL_PERIPH_GPIO, IRMP_PORT_LETTER) +# define IRMP_PORT_BASE CONCAT(GPIO_PORT, CONCAT(IRMP_PORT_LETTER, _BASE)) +# define IRMP_PORT_PIN CONCAT(GPIO_PIN_, IRMP_BIT_NUMBER) +# define IRMP_PIN IRMP_PORT_PIN +# define input(x) ((uint8_t)(ROM_GPIOPinRead(IRMP_PORT_BASE, IRMP_PORT_PIN))) +# define sei() IntMasterEnable() + +#elif defined(__SDCC_stm8) +# define _CONCAT(a,b) a##b +# define CONCAT(a,b) _CONCAT(a,b) +# define IRMP_GPIO_STRUCT CONCAT(GPIO, IRMP_PORT_LETTER) +# define IRMP_BIT IRMP_BIT_NUMBER +# define input(x) ((x) & (1 << IRMP_BIT)) + +#elif defined (TEENSY_ARM_CORTEX_M4) +# define input(x) ((uint8_t)(digitalReadFast(x))) + +#elif defined(__xtensa__) +# define IRMP_BIT IRMP_BIT_NUMBER +# define input(x) GPIO_INPUT_GET(IRMP_BIT_NUMBER) + +#elif defined(_CHIBIOS_HAL_) +# define input(x) palReadLine(x) + +#endif + +#if IRMP_USE_IDLE_CALL == 1 +void irmp_idle(void); // the user has to provide an implementation of the irmp_idle() function and link it +#endif + +#if IRMP_SUPPORT_TECHNICS_PROTOCOL == 1 +# undef IRMP_SUPPORT_MATSUSHITA_PROTOCOL +# define IRMP_SUPPORT_MATSUSHITA_PROTOCOL 1 +#endif + +#if IRMP_SUPPORT_DENON_PROTOCOL == 1 && IRMP_SUPPORT_RUWIDO_PROTOCOL == 1 +# warning DENON protocol conflicts wih RUWIDO, please enable only one of both protocols +# warning RUWIDO protocol disabled +# undef IRMP_SUPPORT_RUWIDO_PROTOCOL +# define IRMP_SUPPORT_RUWIDO_PROTOCOL 0 +#endif + +#if IRMP_SUPPORT_KASEIKYO_PROTOCOL == 1 && IRMP_SUPPORT_PANASONIC_PROTOCOL == 1 +# warning KASEIKYO protocol conflicts wih PANASONIC, please enable only one of both protocols +# warning PANASONIC protocol disabled +# undef IRMP_SUPPORT_PANASONIC_PROTOCOL +# define IRMP_SUPPORT_PANASONIC_PROTOCOL 0 +#endif + +#if IRMP_SUPPORT_DENON_PROTOCOL == 1 && IRMP_SUPPORT_ACP24_PROTOCOL == 1 +# warning DENON protocol conflicts wih ACP24, please enable only one of both protocols +# warning ACP24 protocol disabled +# undef IRMP_SUPPORT_ACP24_PROTOCOL +# define IRMP_SUPPORT_ACP24_PROTOCOL 0 +#endif + +#if IRMP_SUPPORT_RC6_PROTOCOL == 1 && IRMP_SUPPORT_ROOMBA_PROTOCOL == 1 +# warning RC6 protocol conflicts wih ROOMBA, please enable only one of both protocols +# warning ROOMBA protocol disabled +# undef IRMP_SUPPORT_ROOMBA_PROTOCOL +# define IRMP_SUPPORT_ROOMBA_PROTOCOL 0 +#endif + +#if IRMP_SUPPORT_PANASONIC_PROTOCOL == 1 && IRMP_SUPPORT_MITSU_HEAVY_PROTOCOL == 1 +# warning PANASONIC protocol conflicts wih MITSU_HEAVY, please enable only one of both protocols +# warning MITSU_HEAVY protocol disabled +# undef IRMP_SUPPORT_MITSU_HEAVY_PROTOCOL +# define IRMP_SUPPORT_MITSU_HEAVY_PROTOCOL 0 +#endif + +#if IRMP_SUPPORT_RC5_PROTOCOL == 1 && IRMP_SUPPORT_ORTEK_PROTOCOL == 1 +# warning RC5 protocol conflicts wih ORTEK, please enable only one of both protocols +# warning ORTEK protocol disabled +# undef IRMP_SUPPORT_ORTEK_PROTOCOL +# define IRMP_SUPPORT_ORTEK_PROTOCOL 0 +#endif + +#if IRMP_SUPPORT_RC5_PROTOCOL == 1 && IRMP_SUPPORT_S100_PROTOCOL == 1 +# warning RC5 protocol conflicts wih S100, please enable only one of both protocols +# warning S100 protocol disabled +# undef IRMP_SUPPORT_S100_PROTOCOL +# define IRMP_SUPPORT_S100_PROTOCOL 0 +#endif + +#if IRMP_SUPPORT_NUBERT_PROTOCOL == 1 && IRMP_SUPPORT_FAN_PROTOCOL == 1 +# warning NUBERT protocol conflicts wih FAN, please enable only one of both protocols +# warning FAN protocol disabled +# undef IRMP_SUPPORT_FAN_PROTOCOL +# define IRMP_SUPPORT_FAN_PROTOCOL 0 +#endif + +#if IRMP_SUPPORT_FDC_PROTOCOL == 1 && IRMP_SUPPORT_ORTEK_PROTOCOL == 1 +# warning FDC protocol conflicts wih ORTEK, please enable only one of both protocols +# warning ORTEK protocol disabled +# undef IRMP_SUPPORT_ORTEK_PROTOCOL +# define IRMP_SUPPORT_ORTEK_PROTOCOL 0 +#endif + +#if IRMP_SUPPORT_ORTEK_PROTOCOL == 1 && IRMP_SUPPORT_NETBOX_PROTOCOL == 1 +# warning ORTEK protocol conflicts wih NETBOX, please enable only one of both protocols +# warning NETBOX protocol disabled +# undef IRMP_SUPPORT_NETBOX_PROTOCOL +# define IRMP_SUPPORT_NETBOX_PROTOCOL 0 +#endif + +#if IRMP_SUPPORT_GRUNDIG_PROTOCOL == 1 && IRMP_SUPPORT_RCII_PROTOCOL == 1 +# warning GRUNDIG protocol conflicts wih RCII, please enable only one of both protocols +# warning RCII protocol disabled +# undef IRMP_SUPPORT_RCII_PROTOCOL +# define IRMP_SUPPORT_RCII_PROTOCOL 0 +#endif + +#if IRMP_SUPPORT_NOKIA_PROTOCOL == 1 && IRMP_SUPPORT_RCII_PROTOCOL == 1 +# warning NOKIA protocol conflicts wih RCII, please enable only one of both protocols +# warning RCII protocol disabled +# undef IRMP_SUPPORT_RCII_PROTOCOL +# define IRMP_SUPPORT_RCII_PROTOCOL 0 +#endif + +#if IRMP_SUPPORT_SIEMENS_PROTOCOL == 1 && F_INTERRUPTS < 15000 +# warning F_INTERRUPTS too low, SIEMENS protocol disabled (should be at least 15000) +# undef IRMP_SUPPORT_SIEMENS_PROTOCOL +# define IRMP_SUPPORT_SIEMENS_PROTOCOL 0 +#endif + +#if IRMP_SUPPORT_RUWIDO_PROTOCOL == 1 && F_INTERRUPTS < 15000 +# warning F_INTERRUPTS too low, RUWIDO protocol disabled (should be at least 15000) +# undef IRMP_SUPPORT_RUWIDO_PROTOCOL +# define IRMP_SUPPORT_RUWIDO_PROTOCOL 0 +#endif + +#if IRMP_SUPPORT_RECS80_PROTOCOL == 1 && F_INTERRUPTS < 15000 +# warning F_INTERRUPTS too low, RECS80 protocol disabled (should be at least 15000) +# undef IRMP_SUPPORT_RECS80_PROTOCOL +# define IRMP_SUPPORT_RECS80_PROTOCOL 0 +#endif + +#if IRMP_SUPPORT_RECS80EXT_PROTOCOL == 1 && F_INTERRUPTS < 15000 +# warning F_INTERRUPTS too low, RECS80EXT protocol disabled (should be at least 15000) +# undef IRMP_SUPPORT_RECS80EXT_PROTOCOL +# define IRMP_SUPPORT_RECS80EXT_PROTOCOL 0 +#endif + +#if IRMP_SUPPORT_LEGO_PROTOCOL == 1 && F_INTERRUPTS < 20000 +# warning F_INTERRUPTS too low, LEGO protocol disabled (should be at least 20000) +# undef IRMP_SUPPORT_LEGO_PROTOCOL +# define IRMP_SUPPORT_LEGO_PROTOCOL 0 +#endif + +#if IRMP_SUPPORT_SAMSUNG48_PROTOCOL == 1 && IRMP_SUPPORT_SAMSUNG_PROTOCOL == 0 +# warning SAMSUNG48 protocol needs also SAMSUNG protocol, SAMSUNG protocol enabled +# undef IRMP_SUPPORT_SAMSUNG_PROTOCOL +# define IRMP_SUPPORT_SAMSUNG_PROTOCOL 1 +#endif + +#if IRMP_SUPPORT_JVC_PROTOCOL == 1 && IRMP_SUPPORT_NEC_PROTOCOL == 0 +# warning JVC protocol needs also NEC protocol, NEC protocol enabled +# undef IRMP_SUPPORT_NEC_PROTOCOL +# define IRMP_SUPPORT_NEC_PROTOCOL 1 +#endif + +#if IRMP_SUPPORT_NEC16_PROTOCOL == 1 && IRMP_SUPPORT_NEC_PROTOCOL == 0 +# warning NEC16 protocol needs also NEC protocol, NEC protocol enabled +# undef IRMP_SUPPORT_NEC_PROTOCOL +# define IRMP_SUPPORT_NEC_PROTOCOL 1 +#endif + +#if IRMP_SUPPORT_NEC42_PROTOCOL == 1 && IRMP_SUPPORT_NEC_PROTOCOL == 0 +# warning NEC42 protocol needs also NEC protocol, NEC protocol enabled +# undef IRMP_SUPPORT_NEC_PROTOCOL +# define IRMP_SUPPORT_NEC_PROTOCOL 1 +#endif + +#if IRMP_SUPPORT_LGAIR_PROTOCOL == 1 && IRMP_SUPPORT_NEC_PROTOCOL == 0 +# warning LGAIR protocol needs also NEC protocol, NEC protocol enabled +# undef IRMP_SUPPORT_NEC_PROTOCOL +# define IRMP_SUPPORT_NEC_PROTOCOL 1 +#endif + +#if IRMP_SUPPORT_RCMM_PROTOCOL == 1 && F_INTERRUPTS < 20000 +# warning F_INTERRUPTS too low, RCMM protocol disabled (should be at least 20000) +# undef IRMP_SUPPORT_RCMM_PROTOCOL +# define IRMP_SUPPORT_RCMM_PROTOCOL 0 +#endif + +#if F_INTERRUPTS > 20000 +#error F_INTERRUPTS too high (should be not greater than 20000) +#endif + +#include "irmpprotocols.h" + +#define IRMP_FLAG_REPETITION 0x01 + +#ifdef __cplusplus +extern "C" +{ +#endif + +extern void irmp_init (void); +extern uint_fast8_t irmp_get_data (IRMP_DATA *); +#if !defined(IRMP_PULSE_IR_DECODER) +extern uint_fast8_t irmp_ISR (void); +#else +extern uint_fast8_t irmp_ISR (uint_fast16_t duration); +#endif + +#if IRMP_PROTOCOL_NAMES == 1 +extern const char * const irmp_protocol_names[IRMP_N_PROTOCOLS + 1] PROGMEM; +#endif + +#if IRMP_USE_CALLBACK == 1 +extern void irmp_set_callback_ptr (void (*cb)(uint_fast8_t)); +#endif // IRMP_USE_CALLBACK == 1 + +#ifdef __cplusplus +} +#endif + +#endif /* _IRMP_H_ */ diff --git a/drivers/media/rc/irmp/irmpconfig.h b/drivers/media/rc/irmp/irmpconfig.h new file mode 100644 index 000000000000..5fb0fc5543e8 --- /dev/null +++ b/drivers/media/rc/irmp/irmpconfig.h @@ -0,0 +1,273 @@ +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * irmpconfig.h + * + * DO NOT INCLUDE THIS FILE, WILL BE INCLUDED BY IRMP.H! + * + * Copyright (c) 2009-2018 Frank Meyer - frank(at)fli4l.de + * Extensions for PIC 12F1820 W.Strobl 2014-07-20 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ + +#ifndef _IRMPCONFIG_H_ +#define _IRMPCONFIG_H_ + +#ifndef _IRMP_H_ +# error please include only irmp.h, not irmpconfig.h +#endif + +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * Change F_INTERRUPTS if you change the number of interrupts per second, + * Normally, F_INTERRUPTS should be in the range from 10000 to 15000, typical is 15000 + * A value above 15000 costs additional program space, absolute maximum value is 20000. + * On PIC with XC8/C18 Compiler, use 15151 as the correct value. + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ +#ifndef F_INTERRUPTS +# define F_INTERRUPTS 15000 // interrupts per second, min: 10000, max: 20000, typ: 15000 +#endif + +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * Change settings from 1 to 0 if you want to disable one or more decoders. + * This saves program space. + * + * 1 enable decoder + * 0 disable decoder + * + * The standard decoders are enabled per default. + * Less common protocols are disabled here, you need to enable them manually. + * + * If you want to use FDC or RCCAR simultaneous with RC5 protocol, additional program space is required. + * If you don't need RC5 when using FDC/RCCAR, you should disable RC5. + * You cannot enable both DENON and RUWIDO, only enable one of them. + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ + +// typical protocols, disable here! Enable Remarks F_INTERRUPTS Program Space +#define IRMP_SUPPORT_SIRCS_PROTOCOL 1 // Sony SIRCS >= 10000 ~150 bytes +#define IRMP_SUPPORT_NEC_PROTOCOL 1 // NEC + APPLE >= 10000 ~300 bytes +#define IRMP_SUPPORT_SAMSUNG_PROTOCOL 1 // Samsung + Samsg32 >= 10000 ~300 bytes +#define IRMP_SUPPORT_KASEIKYO_PROTOCOL 0 // Kaseikyo >= 10000 ~250 bytes + +// more protocols, enable here! Enable Remarks F_INTERRUPTS Program Space +#define IRMP_SUPPORT_JVC_PROTOCOL 1 // JVC >= 10000 ~150 bytes +#define IRMP_SUPPORT_NEC16_PROTOCOL 1 // NEC16 >= 10000 ~100 bytes +#define IRMP_SUPPORT_NEC42_PROTOCOL 0 // NEC42 >= 10000 ~300 bytes +#define IRMP_SUPPORT_MATSUSHITA_PROTOCOL 0 // Matsushita >= 10000 ~50 bytes +#define IRMP_SUPPORT_DENON_PROTOCOL 0 // DENON, Sharp >= 10000 ~250 bytes +#define IRMP_SUPPORT_RC5_PROTOCOL 1 // RC5 >= 10000 ~250 bytes +#define IRMP_SUPPORT_RC6_PROTOCOL 1 // RC6 & RC6A >= 10000 ~250 bytes +#define IRMP_SUPPORT_IR60_PROTOCOL 0 // IR60 (SDA2008) >= 10000 ~300 bytes +#define IRMP_SUPPORT_GRUNDIG_PROTOCOL 0 // Grundig >= 10000 ~300 bytes +#define IRMP_SUPPORT_SIEMENS_PROTOCOL 0 // Siemens Gigaset >= 15000 ~550 bytes +#define IRMP_SUPPORT_NOKIA_PROTOCOL 0 // Nokia >= 10000 ~300 bytes + +// exotic protocols, enable here! Enable Remarks F_INTERRUPTS Program Space +#define IRMP_SUPPORT_BOSE_PROTOCOL 0 // BOSE >= 10000 ~150 bytes +#define IRMP_SUPPORT_KATHREIN_PROTOCOL 0 // Kathrein >= 10000 ~200 bytes +#define IRMP_SUPPORT_NUBERT_PROTOCOL 0 // NUBERT >= 10000 ~50 bytes +#define IRMP_SUPPORT_FAN_PROTOCOL 0 // FAN (ventilator) >= 10000 ~50 bytes +#define IRMP_SUPPORT_SPEAKER_PROTOCOL 0 // SPEAKER (~NUBERT) >= 10000 ~50 bytes +#define IRMP_SUPPORT_BANG_OLUFSEN_PROTOCOL 0 // Bang & Olufsen >= 10000 ~200 bytes +#define IRMP_SUPPORT_RECS80_PROTOCOL 0 // RECS80 (SAA3004) >= 15000 ~50 bytes +#define IRMP_SUPPORT_RECS80EXT_PROTOCOL 0 // RECS80EXT (SAA3008) >= 15000 ~50 bytes +#define IRMP_SUPPORT_THOMSON_PROTOCOL 0 // Thomson >= 10000 ~250 bytes +#define IRMP_SUPPORT_NIKON_PROTOCOL 0 // NIKON camera >= 10000 ~250 bytes +#define IRMP_SUPPORT_NETBOX_PROTOCOL 0 // Netbox keyboard >= 10000 ~400 bytes (PROTOTYPE!) +#define IRMP_SUPPORT_ORTEK_PROTOCOL 0 // ORTEK (Hama) >= 10000 ~150 bytes +#define IRMP_SUPPORT_TELEFUNKEN_PROTOCOL 0 // Telefunken 1560 >= 10000 ~150 bytes +#define IRMP_SUPPORT_FDC_PROTOCOL 0 // FDC3402 keyboard >= 10000 (better 15000) ~150 bytes (~400 in combination with RC5) +#define IRMP_SUPPORT_RCCAR_PROTOCOL 0 // RC Car >= 10000 (better 15000) ~150 bytes (~500 in combination with RC5) +#define IRMP_SUPPORT_ROOMBA_PROTOCOL 0 // iRobot Roomba >= 10000 ~150 bytes +#define IRMP_SUPPORT_RUWIDO_PROTOCOL 0 // RUWIDO, T-Home >= 15000 ~550 bytes +#define IRMP_SUPPORT_A1TVBOX_PROTOCOL 0 // A1 TV BOX >= 15000 (better 20000) ~300 bytes +#define IRMP_SUPPORT_LEGO_PROTOCOL 0 // LEGO Power RC >= 20000 ~150 bytes +#define IRMP_SUPPORT_RCMM_PROTOCOL 0 // RCMM 12,24, or 32 >= 20000 ~150 bytes +#define IRMP_SUPPORT_LGAIR_PROTOCOL 0 // LG Air Condition >= 10000 ~300 bytes +#define IRMP_SUPPORT_SAMSUNG48_PROTOCOL 1 // Samsung48 >= 10000 ~100 bytes (SAMSUNG must be enabled!) +#define IRMP_SUPPORT_MERLIN_PROTOCOL 0 // Merlin >= 15000 (better 20000) ~300 bytes +#define IRMP_SUPPORT_PENTAX_PROTOCOL 0 // Pentax >= 10000 ~150 bytes +#define IRMP_SUPPORT_S100_PROTOCOL 0 // S100 >= 10000 ~250 bytes +#define IRMP_SUPPORT_ACP24_PROTOCOL 0 // ACP24 >= 10000 ~250 bytes +#define IRMP_SUPPORT_TECHNICS_PROTOCOL 0 // TECHNICS >= 10000 ~250 bytes +#define IRMP_SUPPORT_PANASONIC_PROTOCOL 0 // PANASONIC Beamer >= 10000 ~250 bytes +#define IRMP_SUPPORT_MITSU_HEAVY_PROTOCOL 0 // Mitsubishi Aircond >= 10000 ~250 bytes +#define IRMP_SUPPORT_VINCENT_PROTOCOL 0 // VINCENT >= 10000 ~250 bytes +#define IRMP_SUPPORT_SAMSUNGAH_PROTOCOL 0 // SAMSUNG AH >= 10000 ~250 bytes +#define IRMP_SUPPORT_IRMP16_PROTOCOL 0 // IRMP specific >= 15000 ~250 bytes +#define IRMP_SUPPORT_GREE_PROTOCOL 0 // GREE CLIMATE >= 10000 ~250 bytes +#define IRMP_SUPPORT_RCII_PROTOCOL 0 // RCII T+A >= 15000 ~250 bytes + +#define IRMP_SUPPORT_RADIO1_PROTOCOL 0 // RADIO, e.g. TEVION >= 10000 ~250 bytes (experimental) + +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * Change hardware pin here for ATMEL ATMega/ATTiny/XMega + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ +#if defined (ATMEL_AVR) || defined (__AVR_XMEGA__) // use PB6 as IR input on AVR +# define IRMP_PORT_LETTER B +# define IRMP_BIT_NUMBER 6 + +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * Change hardware pin here for PIC C18 or XC8 compiler + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ +#elif defined (PIC_C18) // use RB4 as IR input on PIC (C18 or XC8 compiler) +# if defined(__12F1840) +# define IRMP_PIN RA5 // on 12F1840 with XC8 compiler +# else +# define IRMP_PIN PORTBbits.RB4 // PIC C18 +# endif + +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * Change hardware pin here for PIC CCS compiler + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ +#elif defined (PIC_CCS) +# define IRMP_PIN PIN_B4 // use PB4 as IR input on PIC (CCS compiler) + +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * Change hardware pin here for ARM STM32 + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ +#elif defined (ARM_STM32) // use C13 as IR input on STM32 +# define IRMP_PORT_LETTER C +# define IRMP_BIT_NUMBER 13 + +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * Hardware pin for ARM STM32 (HAL) - don't change here, define IRMP_RECEIVE_GPIO_Port & IRMP_RECEIVE_PIN in STM32Cube (Main.h) + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ +#elif defined (ARM_STM32_HAL) // STM32: IRMP_RECEIVE_GPIO_Port & IRMP_RECEIVE_PIN must be defined in STM32Cube +# define IRMP_PORT_LETTER IRMP_Receive_GPIO_Port +# define IRMP_BIT_NUMBER IRMP_Receive_Pin + +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * Change hardware pin here for Stellaris ARM Cortex M4 + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ +#elif defined (STELLARIS_ARM_CORTEX_M4) // use B4 as IR input on Stellaris LM4F +# define IRMP_PORT_LETTER B +# define IRMP_BIT_NUMBER 4 + +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * Change hardware pin here for STM8 + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ +#elif defined (SDCC_STM8) // use PA1 as IR input on STM8 +# define IRMP_PORT_LETTER A +# define IRMP_BIT_NUMBER 1 + +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * Change hardware pin here for ESP8266 + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ +#elif defined (__xtensa__) +# define IRMP_BIT_NUMBER 12 // use GPIO12 (Pin 7 UEXT) on ESP8266-EVB evaluation board + +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * Change hardware pin here for Teensy 3.x with teensyduino gcc compiler + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ +#elif defined (TEENSY_ARM_CORTEX_M4) +# define IRMP_PIN 1 // use Digital pin 1 as IR input on Teensy + +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * Change hardware pin here for MBED + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ +#elif defined(__MBED__) +# define IRMP_PIN P0_22 // use P1_27 on LPC1347 +# define IRMP_PINMODE PullUp // hardware dependent + +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * Change hardware pin here for ChibiOS HAL + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ +#elif defined(_CHIBIOS_HAL_) +# define IRMP_PIN LINE_IR_IN // use pin names as defined in the board config file, prefixed with "LINE_" +# define IRMP_LOGGING_SD SD1 // the ChibiOS HAL Serial Driver instance to log to + // (when IRMP_LOGGING is enabled below). + // Make sure SERIAL_BUFFERS_SIZE is large enough when enabling logging + +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * Nothing to do with measured pulses + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ +#elif defined(IRMP_PULSE_IR_DECODER) + +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * Handling of unknown target system: DON'T CHANGE + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ +#elif !defined (UNIX_OR_WINDOWS) +# error target system not defined. +#endif + +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * Set IRMP_LOGGING to 1 if want to log data to UART with 9600Bd + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ +#ifndef IRMP_LOGGING +# define IRMP_LOGGING 0 // 1: log IR signal (scan), 0: do not. default is 0 +#endif + +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * Use external logging routines + * If you enable external logging, you have also to enable IRMP_LOGGING above + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ +#ifndef IRMP_EXT_LOGGING +# define IRMP_EXT_LOGGING 0 // 1: use external logging, 0: do not. default is 0 +#endif + +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * Set IRMP_PROTOCOL_NAMES to 1 if want to access protocol names (for logging etc), costs ~300 bytes RAM! + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ +#ifndef IRMP_PROTOCOL_NAMES +# define IRMP_PROTOCOL_NAMES 0 // 1: access protocol names, 0: do not. default is 0 +#endif + +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * Use Callbacks to indicate input signal + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ +#ifndef IRMP_USE_CALLBACK +# define IRMP_USE_CALLBACK 0 // 1: use callbacks. 0: do not. default is 0 +#endif + +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * Call the user-provided irmp_idle() function when IRMP is idle. + * Can be used to disable the timer irq and enter a sleep mode to save power + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ +#ifndef IRMP_USE_IDLE_CALL +# define IRMP_USE_IDLE_CALL 0 // 1: use idle calls. 0: do not. default is 0 +#endif + +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * Use ChibiOS Events to signal that valid IR data was received + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ +#if defined(_CHIBIOS_RT_) || defined(_CHIBIOS_NIL_) + +# ifndef IRMP_USE_EVENT +# define IRMP_USE_EVENT 0 // 1: use event. 0: do not. default is 0 +# endif + +# if IRMP_USE_EVENT == 1 && !defined(IRMP_EVENT_BIT) +# define IRMP_EVENT_BIT 1 // event flag or bit to send +# endif +# if IRMP_USE_EVENT == 1 && !defined(IRMP_EVENT_THREAD_PTR) +# define IRMP_EVENT_THREAD_PTR ir_receive_thread_p // pointer to the thread to send the event to +extern thread_t *IRMP_EVENT_THREAD_PTR; // the pointer must be defined and initialized elsewhere +# endif + +#endif // _CHIBIOS_RT_ || _CHIBIOS_NIL_ + +#endif // _IRMPCONFIG_H_ diff --git a/drivers/media/rc/irmp/irmpprotocols.h b/drivers/media/rc/irmp/irmpprotocols.h new file mode 100644 index 000000000000..616451a363db --- /dev/null +++ b/drivers/media/rc/irmp/irmpprotocols.h @@ -0,0 +1,1066 @@ +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * irmpprotocols.h - irmp protocols + * + * DO NOT INCLUDE THIS FILE, WILL BE INCLUDED BY IRMP.H or IRSND.H! + * + * Copyright (c) 2013-2018 Frank Meyer - frank(at)fli4l.de + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ + +#ifndef _IRMP_PROTOCOLS_H_ +#define _IRMP_PROTOCOLS_H_ + +#if !defined(_IRMP_H_) && !defined(_IRSND_H_) +# error please include only irmp.h or irsnd.h, not irmpprotocols.h +#endif + +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * IR protocols: + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ +#define IRMP_UNKNOWN_PROTOCOL 0 // uknown protocol +#define IRMP_SIRCS_PROTOCOL 1 // Sony +#define IRMP_NEC_PROTOCOL 2 // NEC, Pioneer, JVC, Toshiba, NoName etc. +#define IRMP_SAMSUNG_PROTOCOL 3 // Samsung +#define IRMP_MATSUSHITA_PROTOCOL 4 // Matsushita +#define IRMP_KASEIKYO_PROTOCOL 5 // Kaseikyo (Panasonic etc) +#define IRMP_RECS80_PROTOCOL 6 // Philips, Thomson, Nordmende, Telefunken, Saba +#define IRMP_RC5_PROTOCOL 7 // Philips etc +#define IRMP_DENON_PROTOCOL 8 // Denon, Sharp +#define IRMP_RC6_PROTOCOL 9 // Philips etc +#define IRMP_SAMSUNG32_PROTOCOL 10 // Samsung32: no sync pulse at bit 16, length 32 instead of 37 +#define IRMP_APPLE_PROTOCOL 11 // Apple, very similar to NEC +#define IRMP_RECS80EXT_PROTOCOL 12 // Philips, Technisat, Thomson, Nordmende, Telefunken, Saba +#define IRMP_NUBERT_PROTOCOL 13 // Nubert +#define IRMP_BANG_OLUFSEN_PROTOCOL 14 // Bang & Olufsen +#define IRMP_GRUNDIG_PROTOCOL 15 // Grundig +#define IRMP_NOKIA_PROTOCOL 16 // Nokia +#define IRMP_SIEMENS_PROTOCOL 17 // Siemens, e.g. Gigaset +#define IRMP_FDC_PROTOCOL 18 // FDC keyboard +#define IRMP_RCCAR_PROTOCOL 19 // RC Car +#define IRMP_JVC_PROTOCOL 20 // JVC (NEC with 16 bits) +#define IRMP_RC6A_PROTOCOL 21 // RC6A, e.g. Kathrein, XBOX +#define IRMP_NIKON_PROTOCOL 22 // Nikon +#define IRMP_RUWIDO_PROTOCOL 23 // Ruwido, e.g. T-Home Mediareceiver +#define IRMP_IR60_PROTOCOL 24 // IR60 (SDA2008) +#define IRMP_KATHREIN_PROTOCOL 25 // Kathrein +#define IRMP_NETBOX_PROTOCOL 26 // Netbox keyboard (bitserial) +#define IRMP_NEC16_PROTOCOL 27 // NEC with 16 bits (incl. sync) +#define IRMP_NEC42_PROTOCOL 28 // NEC with 42 bits +#define IRMP_LEGO_PROTOCOL 29 // LEGO Power Functions RC +#define IRMP_THOMSON_PROTOCOL 30 // Thomson +#define IRMP_BOSE_PROTOCOL 31 // BOSE +#define IRMP_A1TVBOX_PROTOCOL 32 // A1 TV Box +#define IRMP_ORTEK_PROTOCOL 33 // ORTEK - Hama +#define IRMP_TELEFUNKEN_PROTOCOL 34 // Telefunken (1560) +#define IRMP_ROOMBA_PROTOCOL 35 // iRobot Roomba vacuum cleaner +#define IRMP_RCMM32_PROTOCOL 36 // Fujitsu-Siemens (Activy remote control) +#define IRMP_RCMM24_PROTOCOL 37 // Fujitsu-Siemens (Activy keyboard) +#define IRMP_RCMM12_PROTOCOL 38 // Fujitsu-Siemens (Activy keyboard) +#define IRMP_SPEAKER_PROTOCOL 39 // Another loudspeaker protocol, similar to Nubert +#define IRMP_LGAIR_PROTOCOL 40 // LG air conditioner +#define IRMP_SAMSUNG48_PROTOCOL 41 // air conditioner with SAMSUNG protocol (48 bits) +#define IRMP_MERLIN_PROTOCOL 42 // Merlin (Pollin 620 185) +#define IRMP_PENTAX_PROTOCOL 43 // Pentax camera +#define IRMP_FAN_PROTOCOL 44 // FAN (ventilator), very similar to NUBERT, but last bit is data bit instead of stop bit +#define IRMP_S100_PROTOCOL 45 // very similar to RC5, but 14 instead of 13 data bits +#define IRMP_ACP24_PROTOCOL 46 // Stiebel Eltron ACP24 air conditioner +#define IRMP_TECHNICS_PROTOCOL 47 // Technics, similar to Matsushita, but 22 instead of 24 bits +#define IRMP_PANASONIC_PROTOCOL 48 // Panasonic (Beamer), start bits similar to KASEIKYO +#define IRMP_MITSU_HEAVY_PROTOCOL 49 // Mitsubishi-Heavy Aircondition, similar timing as Panasonic beamer +#define IRMP_VINCENT_PROTOCOL 50 // Vincent +#define IRMP_SAMSUNGAH_PROTOCOL 51 // SAMSUNG AH +#define IRMP_IRMP16_PROTOCOL 52 // IRMP specific protocol for data transfer, e.g. between two microcontrollers via IR +#define IRMP_GREE_PROTOCOL 53 // Gree climate +#define IRMP_RCII_PROTOCOL 54 // RC II Infra Red Remote Control Protocol for FM8 + +#define IRMP_RADIO1_PROTOCOL 55 // Radio protocol (experimental status), do not use it yet! + +#define IRMP_N_PROTOCOLS 55 // number of supported protocols + +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * timing constants: + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ +// fm 22.09.2011: may not be more than 16000L, otherwise some JVC codes will not be accepted +#define IRMP_TIMEOUT_TIME 15500.0e-6 // timeout after 15.5 ms darkness +#define IRMP_TIMEOUT_TIME_MS 15500L // timeout after 15.5 ms darkness + +#if IRMP_SUPPORT_NIKON_PROTOCOL == 1 +# define IRMP_TIMEOUT_NIKON_TIME 29500.0e-6 // 2nd timeout after 29.5 ms darkness (only for NIKON!) +# define IRMP_TIMEOUT_NIKON_TIME_MS 29500L // 2nd timeout after 29.5 ms darkness +typedef uint16_t PAUSE_LEN; +# define IRMP_TIMEOUT_NIKON_LEN (PAUSE_LEN)(F_INTERRUPTS * IRMP_TIMEOUT_NIKON_TIME + 0.5) +#else +# if (F_INTERRUPTS * IRMP_TIMEOUT_TIME_MS) / 1000000 >= 254 +typedef uint16_t PAUSE_LEN; +# else +#if !defined(IRMP_PULSE_IR_DECODER) +typedef uint8_t PAUSE_LEN; +#else +typedef uint16_t PAUSE_LEN; +#endif +# endif +#endif + +#define IRMP_TIMEOUT_LEN (PAUSE_LEN)(F_INTERRUPTS * IRMP_TIMEOUT_TIME + 0.5) + +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * flags of struct IRMP_PARAMETER: + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ +#define IRMP_PARAM_FLAG_IS_MANCHESTER 0x01 +#define IRMP_PARAM_FLAG_1ST_PULSE_IS_1 0x02 +#define IRMP_PARAM_FLAG_IS_SERIAL 0x04 + +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * SIRCS: + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ +#define SIRCS_START_BIT_PULSE_TIME 2400.0e-6 // 2400 usec pulse +#define SIRCS_START_BIT_PAUSE_TIME 600.0e-6 // 600 usec pause +#define SIRCS_1_PULSE_TIME 1200.0e-6 // 1200 usec pulse +#define SIRCS_0_PULSE_TIME 600.0e-6 // 600 usec pulse +#define SIRCS_PAUSE_TIME 600.0e-6 // 600 usec pause +#define SIRCS_FRAMES 3 // SIRCS sends each frame 3 times +#define SIRCS_AUTO_REPETITION_PAUSE_TIME 25.0e-3 // auto repetition after 25ms +#define SIRCS_FRAME_REPEAT_PAUSE_TIME 25.0e-3 // frame repeat after 25ms +#define SIRCS_ADDRESS_OFFSET 15 // skip 15 bits +#define SIRCS_ADDRESS_LEN 5 // read up to 5 address bits +#define SIRCS_COMMAND_OFFSET 0 // skip 0 bits +#define SIRCS_COMMAND_LEN 15 // read 12-15 command bits +#define SIRCS_MINIMUM_DATA_LEN 12 // minimum data length +#define SIRCS_COMPLETE_DATA_LEN 20 // complete length - may be up to 20 +#define SIRCS_STOP_BIT 0 // has no stop bit +#define SIRCS_LSB 1 // LSB...MSB +#define SIRCS_FLAGS 0 // flags + +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * NEC & NEC42 & NEC16 & LGAIR: + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ +#define NEC_START_BIT_PULSE_TIME 9000.0e-6 // 9000 usec pulse +#define NEC_START_BIT_PAUSE_TIME 4500.0e-6 // 4500 usec pause +#define NEC_REPEAT_START_BIT_PAUSE_TIME 2250.0e-6 // 2250 usec pause +#define NEC_PULSE_TIME 560.0e-6 // 560 usec pulse +#define NEC_1_PAUSE_TIME 1690.0e-6 // 1690 usec pause +#define NEC_0_PAUSE_TIME 560.0e-6 // 560 usec pause +#define NEC_FRAME_REPEAT_PAUSE_TIME 40.0e-3 // frame repeat after 40ms +#define NEC_ADDRESS_OFFSET 0 // skip 0 bits +#define NEC_ADDRESS_LEN 16 // read 16 address bits +#define NEC_COMMAND_OFFSET 16 // skip 16 bits (8 address + 8 /address) +#define NEC_COMMAND_LEN 16 // read 16 bits (8 command + 8 /command) +#define NEC_COMPLETE_DATA_LEN 32 // complete length +#define NEC_STOP_BIT 1 // has stop bit +#define NEC_LSB 1 // LSB...MSB +#define NEC_FLAGS 0 // flags + +#define NEC42_ADDRESS_OFFSET 0 // skip 0 bits +#define NEC42_ADDRESS_LEN 13 // read 13 address bits +#define NEC42_COMMAND_OFFSET 26 // skip 26 bits (2 x 13 address bits) +#define NEC42_COMMAND_LEN 8 // read 8 command bits +#define NEC42_COMPLETE_DATA_LEN 42 // complete length (2 x 13 + 2 x 8) + +#define LGAIR_ADDRESS_OFFSET 0 // skip 0 bits +#define LGAIR_ADDRESS_LEN 8 // read 8 address bits +#define LGAIR_COMMAND_OFFSET 8 // skip 8 bits (8 address) +#define LGAIR_COMMAND_LEN 16 // read 16 bits (16 command) +#define LGAIR_COMPLETE_DATA_LEN 28 // complete length (8 address + 16 command + 4 checksum) + +#define NEC16_ADDRESS_OFFSET 0 // skip 0 bits +#define NEC16_ADDRESS_LEN 8 // read 8 address bits +#define NEC16_COMMAND_OFFSET 8 // skip 8 bits (8 address) +#define NEC16_COMMAND_LEN 8 // read 8 bits (8 command) +#define NEC16_COMPLETE_DATA_LEN 16 // complete length + +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * SAMSUNG & SAMSUNG32 & SAMSUNG48: + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ +#define SAMSUNG_START_BIT_PULSE_TIME 4500.0e-6 // 4500 usec pulse +#define SAMSUNG_START_BIT_PAUSE_TIME 4500.0e-6 // 4500 usec pause +#define SAMSUNG_PULSE_TIME 550.0e-6 // 550 usec pulse +#define SAMSUNG_1_PAUSE_TIME 1500.0e-6 // 1550 usec pause +#define SAMSUNG_0_PAUSE_TIME 500.0e-6 // 500 usec pause + +#define SAMSUNG_FRAME_REPEAT_PAUSE_TIME 25.0e-3 // frame repeat after 25ms +#define SAMSUNG_ADDRESS_OFFSET 0 // skip 0 bits +#define SAMSUNG_ADDRESS_LEN 16 // read 16 address bits +#define SAMSUNG_ID_OFFSET 17 // skip 16 + 1 sync bit +#define SAMSUNG_ID_LEN 4 // read 4 id bits +#define SAMSUNG_COMMAND_OFFSET 21 // skip 16 + 1 sync + 4 data bits +#define SAMSUNG_COMMAND_LEN 16 // read 16 command bits +#define SAMSUNG_COMPLETE_DATA_LEN 37 // complete length +#define SAMSUNG_STOP_BIT 1 // has stop bit +#define SAMSUNG_LSB 1 // LSB...MSB? +#define SAMSUNG_FLAGS 0 // flags + +#define SAMSUNG32_COMMAND_OFFSET 16 // skip 16 bits +#define SAMSUNG32_COMMAND_LEN 16 // read 16 command bits +#define SAMSUNG32_COMPLETE_DATA_LEN 32 // complete length +#define SAMSUNG32_FRAMES 1 // SAMSUNG32 sends one frame +#define SAMSUNG32_AUTO_REPETITION_PAUSE_TIME 47.0e-3 // repetition after 47 ms +#define SAMSUNG32_FRAME_REPEAT_PAUSE_TIME 47.0e-3 // frame repeat after 47ms + +#define SAMSUNG48_COMMAND_OFFSET 16 // skip 16 bits +#define SAMSUNG48_COMMAND_LEN 32 // read 32 command bits +#define SAMSUNG48_COMPLETE_DATA_LEN 48 // complete length +#define SAMSUNG48_FRAMES 2 // SAMSUNG48 sends each frame 2 times +#define SAMSUNG48_AUTO_REPETITION_PAUSE_TIME 5.0e-3 // repetition after 5 ms +#define SAMSUNG48_FRAME_REPEAT_PAUSE_TIME 47.0e-3 // frame repeat after 47ms + +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * SAMSUNGAH: + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ +#define SAMSUNGAH_START_BIT_PULSE_TIME 2500.0e-6 // 2500 usec pulse +#define SAMSUNGAH_START_BIT_PAUSE_TIME 1900.0e-6 // 1900 usec pause +#define SAMSUNGAH_PULSE_TIME 450.0e-6 // 450 usec pulse +#define SAMSUNGAH_1_PAUSE_TIME 1100.0e-6 // 1100 usec pause +#define SAMSUNGAH_0_PAUSE_TIME 450.0e-6 // 450 usec pause +#define SAMSUNGAH_FRAME_REPEAT_PAUSE_TIME 40.0e-3 // frame repeat after 40ms +#define SAMSUNGAH_ADDRESS_OFFSET 0 // skip 0 bits +#define SAMSUNGAH_ADDRESS_LEN 16 // read 16 address bits, ignore 17..31 +#define SAMSUNGAH_COMMAND_OFFSET 32 // skip 32 bits +#define SAMSUNGAH_COMMAND_LEN 16 // read 32 bits +#define SAMSUNGAH_COMPLETE_DATA_LEN 48 // complete length +#define SAMSUNGAH_STOP_BIT 1 // has stop bit +#define SAMSUNGAH_LSB 1 // LSB...MSB? +#define SAMSUNGAH_FLAGS 0 // flags + +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * MATSUSHITA: + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ +#define MATSUSHITA_START_BIT_PULSE_TIME 3488.0e-6 // 3488 usec pulse +#define MATSUSHITA_START_BIT_PAUSE_TIME 3488.0e-6 // 3488 usec pause +#define MATSUSHITA_PULSE_TIME 872.0e-6 // 872 usec pulse +#define MATSUSHITA_1_PAUSE_TIME 2616.0e-6 // 2616 usec pause +#define MATSUSHITA_0_PAUSE_TIME 872.0e-6 // 872 usec pause +#define MATSUSHITA_FRAME_REPEAT_PAUSE_TIME 40.0e-3 // frame repeat after 40ms +#define MATSUSHITA_ADDRESS_OFFSET 12 // skip 12 bits +#define MATSUSHITA_ADDRESS_LEN 12 // read 12 address bits +#define MATSUSHITA_COMMAND_OFFSET 0 // skip 0 bits +#define MATSUSHITA_COMMAND_LEN 12 // read 12 bits (6 custom + 6 command) +#define MATSUSHITA_COMPLETE_DATA_LEN 24 // complete length +#define MATSUSHITA_STOP_BIT 1 // has stop bit +#define MATSUSHITA_LSB 1 // LSB...MSB? +#define MATSUSHITA_FLAGS 0 // flags + +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * TECHNICS: same timings as MATSUSHITA + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ +#define TECHNICS_ADDRESS_LEN 0 // read 0 address bits +#define TECHNICS_COMMAND_LEN 11 // read 11 bits +#define TECHNICS_COMPLETE_DATA_LEN 22 // complete length + +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * KASEIKYO: + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ +#define KASEIKYO_START_BIT_PULSE_TIME 3380.0e-6 // 3380 usec pulse +#define KASEIKYO_START_BIT_PAUSE_TIME 1690.0e-6 // 1690 usec pause +#define KASEIKYO_PULSE_TIME 423.0e-6 // 525 usec pulse +#define KASEIKYO_1_PAUSE_TIME 1269.0e-6 // 525 usec pause +#define KASEIKYO_0_PAUSE_TIME 423.0e-6 // 1690 usec pause +#define KASEIKYO_AUTO_REPETITION_PAUSE_TIME 74.0e-3 // repetition after 74 ms +#define KASEIKYO_FRAME_REPEAT_PAUSE_TIME 74.0e-3 // frame repeat after 74 ms +#define KASEIKYO_ADDRESS_OFFSET 0 // skip 0 bits +#define KASEIKYO_ADDRESS_LEN 16 // read 16 address bits +#define KASEIKYO_COMMAND_OFFSET 28 // skip 28 bits (16 manufacturer & 4 parity & 8 genre) +#define KASEIKYO_COMMAND_LEN 12 // read 12 command bits (10 real command & 2 id) +#define KASEIKYO_COMPLETE_DATA_LEN 48 // complete length +#define KASEIKYO_STOP_BIT 1 // has stop bit +#define KASEIKYO_LSB 1 // LSB...MSB? +#define KASEIKYO_FRAMES 1 // KASEIKYO sends 1 frame +#define KASEIKYO_FLAGS 0 // flags + +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * PANASONIC (Beamer), start bit timings similar to KASEIKYO + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ +#define PANASONIC_START_BIT_PULSE_TIME 3600.0e-6 // 3600 usec pulse +#define PANASONIC_START_BIT_PAUSE_TIME 1600.0e-6 // 1690 usec pause +#define PANASONIC_PULSE_TIME 565.0e-6 // 565 usec pulse +#define PANASONIC_1_PAUSE_TIME 1140.0e-6 // 1140 usec pause +#define PANASONIC_0_PAUSE_TIME 316.0e-6 // 316 usec pause +#define PANASONIC_AUTO_REPETITION_PAUSE_TIME 40.0e-3 // repetition after 40 ms? +#define PANASONIC_FRAME_REPEAT_PAUSE_TIME 40.0e-3 // frame repeat after 40 ms +#define PANASONIC_ADDRESS_OFFSET 24 // skip 24 bits: 010000000000010000000001 +#define PANASONIC_ADDRESS_LEN 16 // read 16 address bits +#define PANASONIC_COMMAND_OFFSET 40 // skip 40 bits +#define PANASONIC_COMMAND_LEN 16 // read 16 command bits +#define PANASONIC_COMPLETE_DATA_LEN 56 // complete length +#define PANASONIC_STOP_BIT 1 // has stop bit +#define PANASONIC_LSB 1 // LSB...MSB? +#define PANASONIC_FRAMES 1 // PANASONIC sends 1 frame +#define PANASONIC_FLAGS 0 // flags + +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * MITSUBISHI-Heavy Aircondition, timings similar to PANASONIC beamer + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ +#define MITSU_HEAVY_START_BIT_PULSE_TIME 3200.0e-6 // 3600 usec pulse +#define MITSU_HEAVY_START_BIT_PAUSE_TIME 1560.0e-6 // 1690 usec pause +#define MITSU_HEAVY_PULSE_TIME 400.0e-6 // 565 usec pulse +#define MITSU_HEAVY_1_PAUSE_TIME 1200.0e-6 // 1140 usec pause +#define MITSU_HEAVY_0_PAUSE_TIME 430.0e-6 // 316 usec pause +#define MITSU_HEAVY_FRAME_REPEAT_PAUSE_TIME 40.0e-3 // frame repeat after 40 ms +#define MITSU_HEAVY_ADDRESS_OFFSET 40 // skip 24 bits: 010000000000010000000001 +#define MITSU_HEAVY_ADDRESS_LEN 16 // read 16 address bits +#define MITSU_HEAVY_COMMAND_OFFSET 56 // skip 40 bits +#define MITSU_HEAVY_COMMAND_LEN 16 // read 16 command bits +#define MITSU_HEAVY_COMPLETE_DATA_LEN 88 // complete length +#define MITSU_HEAVY_STOP_BIT 1 // has stop bit +#define MITSU_HEAVY_LSB 0 // LSB...MSB? +#define MITSU_HEAVY_FRAMES 1 // PANASONIC sends 1 frame +#define MITSU_HEAVY_FLAGS 0 // flags + +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * VINCENT + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ +#define VINCENT_START_BIT_PULSE_TIME 2500.0e-6 // 2500 usec pulse +#define VINCENT_START_BIT_PAUSE_TIME 4600.0e-6 // 4600 usec pause +#define VINCENT_PULSE_TIME 550.0e-6 // 550 usec pulse +#define VINCENT_1_PAUSE_TIME 1540.0e-6 // 1540 usec pause +#define VINCENT_0_PAUSE_TIME 550.0e-6 // 550 usec pause +#define VINCENT_FRAME_REPEAT_PAUSE_TIME 40.0e-3 // frame repeat after 40 ms ? +#define VINCENT_ADDRESS_OFFSET 0 // skip 0 bits +#define VINCENT_ADDRESS_LEN 16 // read 16 address bits +#define VINCENT_COMMAND_OFFSET 16 // skip 16 bits +#define VINCENT_COMMAND_LEN 16 // read 16 command bits +#define VINCENT_COMPLETE_DATA_LEN 32 // complete length +#define VINCENT_STOP_BIT 1 // has stop bit +#define VINCENT_LSB 0 // LSB...MSB? +#define VINCENT_FRAMES 1 // VINCENT sends 1 frame +#define VINCENT_FLAGS 0 // flags + +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * RECS80: + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ +#define RECS80_START_BIT_PULSE_TIME 158.0e-6 // 158 usec pulse +#define RECS80_START_BIT_PAUSE_TIME 7432.0e-6 // 7432 usec pause +#define RECS80_PULSE_TIME 158.0e-6 // 158 usec pulse +#define RECS80_1_PAUSE_TIME 7432.0e-6 // 7432 usec pause +#define RECS80_0_PAUSE_TIME 4902.0e-6 // 4902 usec pause +#define RECS80_FRAME_REPEAT_PAUSE_TIME 45.0e-3 // frame repeat after 45ms +#define RECS80_ADDRESS_OFFSET 1 // skip 1 bit (toggle bit) +#define RECS80_ADDRESS_LEN 3 // read 3 address bits +#define RECS80_COMMAND_OFFSET 4 // skip 4 bits (1 toggle + 3 address) +#define RECS80_COMMAND_LEN 6 // read 6 command bits +#define RECS80_COMPLETE_DATA_LEN 10 // complete length +#define RECS80_STOP_BIT 1 // has stop bit +#define RECS80_LSB 0 // MSB...LSB +#define RECS80_FLAGS 0 // flags + +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * RC5: + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ +#define RC5_BIT_TIME 889.0e-6 // 889 usec pulse/pause +#define RC5_FRAME_REPEAT_PAUSE_TIME 88.9e-3 // frame repeat after 88.9ms + +#if !defined(U_BOOT_COMPATIBLE) +#define RC5_ADDRESS_OFFSET 1 // skip 1 bit (2nd start) +#define RC5_ADDRESS_LEN 6 // read 1 toggle bit (for key repetition detection) + 5 address bits +#define RC5_COMMAND_OFFSET 7 // skip 5 bits (2nd start + 1 toggle + 5 address) +#else +#define RC5_ADDRESS_OFFSET 0 // skip 0 bit +#define RC5_ADDRESS_LEN 7 // read 2nd start, 1 toggle bit (for key repetition detection) + 5 address bits +#define RC5_COMMAND_OFFSET 7 // skip 8 bits (2nd start + 1 toggle + 5 address) +#endif +#define RC5_COMMAND_LEN 6 // read 6 command bits +#define RC5_COMPLETE_DATA_LEN 13 // complete length +#define RC5_STOP_BIT 0 // has no stop bit +#define RC5_LSB 0 // MSB...LSB +#define RC5_FLAGS IRMP_PARAM_FLAG_IS_MANCHESTER // flags + +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * RCII: + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ +#define RCII_START_BIT_PULSE_TIME 512.0e-6 // 512 usec pulse +#define RCII_START_BIT_PAUSE_TIME 2560.0e-6 // 2560 usec pause +#define RCII_START_BIT2_PULSE_TIME 1024.0e-6 // 1024 usec pulse + +#define RCII_BIT_TIME 512.0e-6 // 512 usec pulse/pause +#define RCII_FRAME_REPEAT_PAUSE_TIME 117.76e-3 // frame repeat after 117.76ms + +#define RCII_ADDRESS_OFFSET 0 // skip 1 bit (2nd start) +#define RCII_ADDRESS_LEN 0 // no address +#define RCII_COMMAND_OFFSET 0 // command offset is 0 +#define RCII_COMMAND_LEN 10 // read 1 + 9 command bits +#define RCII_COMPLETE_DATA_LEN 10 // complete length +#define RCII_STOP_BIT 0 // has no stop bit +#define RCII_LSB 0 // MSB...LSB +#define RCII_FLAGS (IRMP_PARAM_FLAG_IS_MANCHESTER | IRMP_PARAM_FLAG_1ST_PULSE_IS_1) // flags + +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * S100: very similar to RC5, but 14 insted of 13 bits + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ +#define S100_BIT_TIME 889.0e-6 // 889 usec pulse/pause +#define S100_FRAME_REPEAT_PAUSE_TIME 88.9e-3 // frame repeat after 88.9ms + +#define S100_ADDRESS_OFFSET 1 // skip 1 bit (2nd start) +#define S100_ADDRESS_LEN 6 // read 1 toggle bit (for key repetition detection) + 5 address bits +#define S100_COMMAND_OFFSET 7 // skip 5 bits (2nd start + 1 toggle + 5 address) +#define S100_COMMAND_LEN 7 // read 7 command bits +#define S100_COMPLETE_DATA_LEN 14 // complete length +#define S100_STOP_BIT 0 // has no stop bit +#define S100_LSB 0 // MSB...LSB +#define S100_FLAGS IRMP_PARAM_FLAG_IS_MANCHESTER // flags + +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * DENON: + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ +#define DENON_PULSE_TIME 310.0e-6 // 310 usec pulse in practice, 275 in theory +#define DENON_1_PAUSE_TIME 1780.0e-6 // 1780 usec pause in practice, 1900 in theory +#define DENON_0_PAUSE_TIME 745.0e-6 // 745 usec pause in practice, 775 in theory +#define DENON_FRAMES 2 // DENON sends each frame 2 times +#define DENON_AUTO_REPETITION_PAUSE_TIME 45.0e-3 // inverted repetition after 45ms +#define DENON_FRAME_REPEAT_PAUSE_TIME 45.0e-3 // frame repeat after 45ms +#define DENON_ADDRESS_OFFSET 0 // skip 0 bits +#define DENON_ADDRESS_LEN 5 // read 5 address bits +#define DENON_COMMAND_OFFSET 5 // skip 5 +#define DENON_COMMAND_LEN 10 // read 10 command bits +#define DENON_COMPLETE_DATA_LEN 15 // complete length +#define DENON_STOP_BIT 1 // has stop bit +#define DENON_LSB 0 // MSB...LSB +#define DENON_FLAGS 0 // flags + +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * RC6: + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ +#define RC6_START_BIT_PULSE_TIME 2666.0e-6 // 2.666 msec pulse +#define RC6_START_BIT_PAUSE_TIME 889.0e-6 // 889 usec pause +#define RC6_TOGGLE_BIT_TIME 889.0e-6 // 889 msec pulse/pause +#define RC6_BIT_TIME 444.0e-6 // 444 usec pulse/pause +#define RC6_BIT_2_TIME 889.0e-6 // 889 usec pulse/pause +#define RC6_BIT_3_TIME 1333.0e-6 // 1333 usec pulse/pause +#define RC6_FRAME_REPEAT_PAUSE_TIME 45.0e-3 // frame repeat after 45ms +#if !defined(U_BOOT_COMPATIBLE) +#define RC6_ADDRESS_OFFSET 5 // skip "1" + 3 mode bits + 1 toggle bit +#define RC6_ADDRESS_LEN 8 // read 8 address bits +#else +#define RC6_ADDRESS_OFFSET 0 // skip 0 bit +#define RC6_ADDRESS_LEN 13 // read "1" + 3 mode bits + 1 toggle bit + 8 address bits +#endif +#define RC6_COMMAND_OFFSET 13 // skip 12 bits ("1" + 3 mode + 1 toggle + 8 address) +#define RC6_COMMAND_LEN 8 // read 8 command bits +#define RC6_COMPLETE_DATA_LEN_SHORT 21 // complete length +#define RC6_COMPLETE_DATA_LEN_LONG 36 // complete length +#define RC6_STOP_BIT 0 // has no stop bit +#define RC6_LSB 0 // MSB...LSB +#define RC6_FLAGS (IRMP_PARAM_FLAG_IS_MANCHESTER | IRMP_PARAM_FLAG_1ST_PULSE_IS_1) // flags + +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * RECS80EXT: + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ +#define RECS80EXT_START_BIT_PULSE_TIME 158.0e-6 // 158 usec pulse +#define RECS80EXT_START_BIT_PAUSE_TIME 3637.0e-6 // 3637 usec pause +#define RECS80EXT_PULSE_TIME 158.0e-6 // 158 usec pulse +#define RECS80EXT_1_PAUSE_TIME 7432.0e-6 // 7432 usec pause +#define RECS80EXT_0_PAUSE_TIME 4902.0e-6 // 4902 usec pause +#define RECS80EXT_FRAME_REPEAT_PAUSE_TIME 45.0e-3 // frame repeat after 45ms +#define RECS80EXT_ADDRESS_OFFSET 2 // skip 2 bits (2nd start + 1 toggle) +#define RECS80EXT_ADDRESS_LEN 4 // read 4 address bits +#define RECS80EXT_COMMAND_OFFSET 6 // skip 6 bits (2nd start + 1 toggle + 4 address) +#define RECS80EXT_COMMAND_LEN 6 // read 6 command bits +#define RECS80EXT_COMPLETE_DATA_LEN 12 // complete length +#define RECS80EXT_STOP_BIT 1 // has stop bit +#define RECS80EXT_LSB 0 // MSB...LSB +#define RECS80EXT_FLAGS 0 // flags + +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * NUBERT: + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ +#define NUBERT_START_BIT_PULSE_TIME 1340.0e-6 // 1340 usec pulse +#define NUBERT_START_BIT_PAUSE_TIME 340.0e-6 // 340 usec pause +#define NUBERT_1_PULSE_TIME 1340.0e-6 // 1340 usec pulse +#define NUBERT_1_PAUSE_TIME 340.0e-6 // 340 usec pause +#define NUBERT_0_PULSE_TIME 500.0e-6 // 500 usec pulse +#define NUBERT_0_PAUSE_TIME 1300.0e-6 // 1300 usec pause +#define NUBERT_FRAMES 2 // Nubert sends 2 frames +#define NUBERT_AUTO_REPETITION_PAUSE_TIME 35.0e-3 // auto repetition after 35ms +#define NUBERT_FRAME_REPEAT_PAUSE_TIME 35.0e-3 // frame repeat after 45ms +#define NUBERT_ADDRESS_OFFSET 0 // skip 0 bits +#define NUBERT_ADDRESS_LEN 0 // read 0 address bits +#define NUBERT_COMMAND_OFFSET 0 // skip 0 bits +#define NUBERT_COMMAND_LEN 10 // read 10 bits +#define NUBERT_COMPLETE_DATA_LEN 10 // complete length +#define NUBERT_STOP_BIT 1 // has stop bit +#define NUBERT_LSB 0 // MSB? +#define NUBERT_FLAGS 0 // flags + +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * FAN: (ventilator) + * + * Similar to NUBERT, but + * - has data bit instead of stop bit + * - has NO frame repetition + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ +#define FAN_START_BIT_PULSE_TIME 1280.0e-6 // 1280 usec pulse +#define FAN_START_BIT_PAUSE_TIME 380.0e-6 // 380 usec pause +#define FAN_1_PULSE_TIME 1280.0e-6 // 1280 usec pulse +#define FAN_1_PAUSE_TIME 380.0e-6 // 380 usec pause +#define FAN_0_PULSE_TIME 380.0e-6 // 380 usec pulse +#define FAN_0_PAUSE_TIME 1280.0e-6 // 1280 usec pause +#define FAN_FRAMES 1 // FAN sends only 1 frame (NUBERT sends 2) +#define FAN_AUTO_REPETITION_PAUSE_TIME 6.6e-3 // auto repetition after 6.6ms +#define FAN_FRAME_REPEAT_PAUSE_TIME 6.6e-3 // frame repeat after 6.6ms +#define FAN_ADDRESS_OFFSET 0 // skip 0 bits +#define FAN_ADDRESS_LEN 0 // read 0 address bits +#define FAN_COMMAND_OFFSET 0 // skip 0 bits +#define FAN_COMMAND_LEN 11 // read 10 bits +#define FAN_COMPLETE_DATA_LEN 11 // complete length +#define FAN_STOP_BIT 0 // has NO stop bit (fm: this seems to be wrong) +#define FAN_LSB 0 // MSB +#define FAN_FLAGS 0 // flags + +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * SPEAKER: + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ +#define SPEAKER_START_BIT_PULSE_TIME 440.0e-6 // 440 usec pulse +#define SPEAKER_START_BIT_PAUSE_TIME 1250.0e-6 // 1250 usec pause +#define SPEAKER_1_PULSE_TIME 1250.0e-6 // 1250 usec pulse +#define SPEAKER_1_PAUSE_TIME 440.0e-6 // 440 usec pause +#define SPEAKER_0_PULSE_TIME 440.0e-6 // 440 usec pulse +#define SPEAKER_0_PAUSE_TIME 1250.0e-6 // 1250 usec pause +#define SPEAKER_FRAMES 2 // SPEAKER sends 2 frames +#define SPEAKER_AUTO_REPETITION_PAUSE_TIME 35.0e-3 // auto repetition after 35ms +#define SPEAKER_FRAME_REPEAT_PAUSE_TIME 35.0e-3 // frame repeat after 45ms +#define SPEAKER_ADDRESS_OFFSET 0 // skip 0 bits +#define SPEAKER_ADDRESS_LEN 0 // read 0 address bits +#define SPEAKER_COMMAND_OFFSET 0 // skip 0 bits +#define SPEAKER_COMMAND_LEN 10 // read 10 bits +#define SPEAKER_COMPLETE_DATA_LEN 10 // complete length +#define SPEAKER_STOP_BIT 1 // has stop bit +#define SPEAKER_LSB 0 // MSB? +#define SPEAKER_FLAGS 0 // flags + +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * BANG_OLUFSEN: + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ +#define BANG_OLUFSEN_START_BIT1_PULSE_TIME 200.0e-6 // 200 usec pulse +#define BANG_OLUFSEN_START_BIT1_PAUSE_TIME 3125.0e-6 // 3125 usec pause +#define BANG_OLUFSEN_START_BIT2_PULSE_TIME 200.0e-6 // 200 usec pulse +#define BANG_OLUFSEN_START_BIT2_PAUSE_TIME 3125.0e-6 // 3125 usec pause +#define BANG_OLUFSEN_START_BIT3_PULSE_TIME 200.0e-6 // 200 usec pulse +#define BANG_OLUFSEN_START_BIT3_PAUSE_TIME 15625.0e-6 // 15625 usec pause +#define BANG_OLUFSEN_START_BIT4_PULSE_TIME 200.0e-6 // 200 usec pulse +#define BANG_OLUFSEN_START_BIT4_PAUSE_TIME 3125.0e-6 // 3125 usec pause +#define BANG_OLUFSEN_PULSE_TIME 200.0e-6 // 200 usec pulse +#define BANG_OLUFSEN_1_PAUSE_TIME 9375.0e-6 // 9375 usec pause +#define BANG_OLUFSEN_0_PAUSE_TIME 3125.0e-6 // 3125 usec pause +#define BANG_OLUFSEN_R_PAUSE_TIME 6250.0e-6 // 6250 usec pause (repeat last bit) +#define BANG_OLUFSEN_TRAILER_BIT_PAUSE_TIME 12500.0e-6 // 12500 usec pause (trailer bit) +#define BANG_OLUFSEN_FRAME_REPEAT_PAUSE_TIME 45.0e-3 // frame repeat after 45ms +#define BANG_OLUFSEN_ADDRESS_OFFSET 0 // no address bits +#define BANG_OLUFSEN_ADDRESS_LEN 0 // no address bits +#define BANG_OLUFSEN_COMMAND_OFFSET 3 // skip startbits 2, 3, 4 +#define BANG_OLUFSEN_COMMAND_LEN 16 // read 16 command bits +#define BANG_OLUFSEN_COMPLETE_DATA_LEN 20 // complete length: startbits 2, 3, 4 + 16 data bits + trailer bit +#define BANG_OLUFSEN_STOP_BIT 1 // has stop bit +#define BANG_OLUFSEN_LSB 0 // MSB...LSB +#define BANG_OLUFSEN_FLAGS 0 // flags + +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * GRUNDIG & NOKIA + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ +#define GRUNDIG_NOKIA_IR60_BIT_TIME 528.0e-6 // 528 usec pulse/pause +#define GRUNDIG_NOKIA_IR60_PRE_PAUSE_TIME 2639.0e-6 // 2639 usec pause after pre bit +#define GRUNDIG_NOKIA_IR60_FRAME_REPEAT_PAUSE_TIME 117.76e-3 // info frame repeat after 117.76 ms +#define GRUNDIG_NOKIA_IR60_STOP_BIT 0 // has no stop bit +#define GRUNDIG_NOKIA_IR60_LSB 1 // MSB...LSB +#define GRUNDIG_NOKIA_IR60_FLAGS (IRMP_PARAM_FLAG_IS_MANCHESTER | IRMP_PARAM_FLAG_1ST_PULSE_IS_1) // flags + +#define GRUNDIG_FRAMES 2 // GRUNDIG sends each frame 1+1 times +#define GRUNDIG_AUTO_REPETITION_PAUSE_TIME 20.0e-3 // repetition after 20ms +#define GRUNDIG_ADDRESS_OFFSET 0 // no address +#define GRUNDIG_ADDRESS_LEN 0 // no address +#define GRUNDIG_COMMAND_OFFSET 1 // skip 1 start bit +#define GRUNDIG_COMMAND_LEN 9 // read 9 command bits +#define GRUNDIG_COMPLETE_DATA_LEN 10 // complete length: 1 start bit + 9 data bits + +#define NOKIA_FRAMES 3 // NOKIA sends each frame 1 + 1 + 1 times +#define NOKIA_AUTO_REPETITION_PAUSE_TIME 20.0e-3 // repetition after 20ms +#define NOKIA_ADDRESS_OFFSET 9 // skip 9 bits (1 start bit + 8 data bits) +#define NOKIA_ADDRESS_LEN 8 // 7 address bits +#define NOKIA_COMMAND_OFFSET 1 // skip 1 bit (1 start bit) +#define NOKIA_COMMAND_LEN 8 // read 8 command bits +#define NOKIA_COMPLETE_DATA_LEN 17 // complete length: 1 start bit + 8 address bits + 8 command bits + +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * IR60: + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ +#define IR60_FRAMES 2 // IR60 sends each frame 1+1 times +#define IR60_AUTO_REPETITION_PAUSE_TIME 22.2e-3 // repetition after 22.2ms +#define IR60_TIMEOUT_TIME 5000.0e-6 // timeout grundig frame, switch to IR60 +#define IR60_ADDRESS_OFFSET 0 // skip 1 bits +#define IR60_ADDRESS_LEN 0 // read 0 address bits +#define IR60_COMMAND_OFFSET 0 // skip 1 bit (start bit after pre bit, always 1) +#define IR60_COMMAND_LEN 7 // read 6 command bits +#define IR60_COMPLETE_DATA_LEN 7 // complete length + +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * SIEMENS & RUWIDO: + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ + +#if 0 +#define SIEMENS_OR_RUWIDO_START_BIT_PULSE_TIME 275.0e-6 // 275 usec pulse +#define SIEMENS_OR_RUWIDO_START_BIT_PAUSE_TIME 550.0e-6 // 550 usec pause +#define SIEMENS_OR_RUWIDO_BIT_PULSE_TIME 275.0e-6 // 275 usec short pulse +#define SIEMENS_OR_RUWIDO_BIT_PULSE_TIME_2 550.0e-6 // 550 usec long pulse +#define SIEMENS_OR_RUWIDO_BIT_PAUSE_TIME 275.0e-6 // 275 usec short pause +#define SIEMENS_OR_RUWIDO_BIT_PAUSE_TIME_2 550.0e-6 // 550 usec long pause +#else +#define SIEMENS_OR_RUWIDO_START_BIT_PULSE_TIME 370.0e-6 // 370 usec pulse +#define SIEMENS_OR_RUWIDO_START_BIT_PAUSE_TIME 550.0e-6 // 550 usec pause +#define SIEMENS_OR_RUWIDO_BIT_PULSE_TIME 370.0e-6 // 370 usec short pulse +#define SIEMENS_OR_RUWIDO_BIT_PULSE_TIME_2 680.0e-6 // 680 usec long pulse +#define SIEMENS_OR_RUWIDO_BIT_PAUSE_TIME 275.0e-6 // 275 usec short pause +#define SIEMENS_OR_RUWIDO_BIT_PAUSE_TIME_2 550.0e-6 // 550 usec long pause +#endif + +#define SIEMENS_OR_RUWIDO_FRAME_REPEAT_PAUSE_TIME 45.0e-3 // frame repeat after 45ms +#define SIEMENS_OR_RUWIDO_STOP_BIT 0 // has no stop bit +#define SIEMENS_OR_RUWIDO_LSB 0 // MSB...LSB +#define SIEMENS_OR_RUWIDO_FLAGS (IRMP_PARAM_FLAG_IS_MANCHESTER | IRMP_PARAM_FLAG_1ST_PULSE_IS_1) // flags + +#define RUWIDO_ADDRESS_OFFSET 0 // skip 0 bits +#define RUWIDO_ADDRESS_LEN 9 // read 9 address bits +#define RUWIDO_COMMAND_OFFSET 9 // skip 9 bits +#define RUWIDO_COMMAND_LEN 8 // read 7 + 1 command bits, last bit is only check bit +#define RUWIDO_COMPLETE_DATA_LEN 17 // complete length + +#define SIEMENS_ADDRESS_OFFSET 0 // skip 0 bits +#define SIEMENS_ADDRESS_LEN 11 // read 11 bits +#define SIEMENS_COMMAND_OFFSET 11 // skip 11 bits +#define SIEMENS_COMMAND_LEN 11 // read 10 + 1 command bits, last bit is only check bit +#define SIEMENS_COMPLETE_DATA_LEN 22 // complete length + +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * FDC: + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ +#define FDC_START_BIT_PULSE_TIME 2085.0e-6 // 2085 usec pulse +#define FDC_START_BIT_PAUSE_TIME 966.0e-6 // 966 usec pause +#define FDC_PULSE_TIME 300.0e-6 // 300 usec pulse +#define FDC_1_PAUSE_TIME 715.0e-6 // 715 usec pause +#define FDC_0_PAUSE_TIME 220.0e-6 // 220 usec pause +#define FDC_FRAME_REPEAT_PAUSE_TIME 60.0e-3 // frame repeat after 60ms +#define FDC_ADDRESS_OFFSET 0 // skip 0 bits +#define FDC_ADDRESS_LEN 14 // read 14 address bits, but use only 6, shift 8 into command +#define FDC_COMMAND_OFFSET 20 // skip 20 bits +#define FDC_COMMAND_LEN 12 // read 12 bits +#define FDC_COMPLETE_DATA_LEN 40 // complete length +#define FDC_STOP_BIT 1 // has stop bit +#define FDC_LSB 1 // LSB...MSB +#define FDC_FLAGS 0 // flags + +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * RCCAR: + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ +#define RCCAR_START_BIT_PULSE_TIME 2000.0e-6 // 2000 usec pulse +#define RCCAR_START_BIT_PAUSE_TIME 2000.0e-6 // 2000 usec pause +#define RCCAR_PULSE_TIME 600.0e-6 // 360 usec pulse +#define RCCAR_1_PAUSE_TIME 450.0e-6 // 650 usec pause +#define RCCAR_0_PAUSE_TIME 900.0e-6 // 180 usec pause +#define RCCAR_FRAME_REPEAT_PAUSE_TIME 40.0e-3 // frame repeat after 40ms +#define RCCAR_ADDRESS_OFFSET 0 // skip 0 bits +#define RCCAR_ADDRESS_LEN 0 // read 0 address bits +#define RCCAR_COMMAND_OFFSET 0 // skip 0 bits +#define RCCAR_COMMAND_LEN 13 // read 13 bits +#define RCCAR_COMPLETE_DATA_LEN 13 // complete length +#define RCCAR_STOP_BIT 1 // has stop bit +#define RCCAR_LSB 1 // LSB...MSB +#define RCCAR_FLAGS 0 // flags + +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * JVC: + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ +#define JVC_START_BIT_PULSE_TIME 9000.0e-6 // 9000 usec pulse +#define JVC_START_BIT_PAUSE_TIME 4500.0e-6 // 4500 usec pause +#define JVC_PULSE_TIME 560.0e-6 // 560 usec pulse +#define JVC_1_PAUSE_TIME 1690.0e-6 // 1690 usec pause +#define JVC_0_PAUSE_TIME 560.0e-6 // 560 usec pause +#define JVC_FRAME_REPEAT_PAUSE_TIME 22.0e-3 // frame repeat after 22ms +#define JVC_ADDRESS_OFFSET 0 // skip 0 bits +#define JVC_ADDRESS_LEN 4 // read 4 address bits +#define JVC_COMMAND_OFFSET 4 // skip 4 bits +#define JVC_COMMAND_LEN 12 // read 12 bits +#define JVC_COMPLETE_DATA_LEN 16 // complete length +#define JVC_STOP_BIT 1 // has stop bit +#define JVC_LSB 1 // LSB...MSB +#define JVC_FLAGS 0 // flags + +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * NIKON: + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ +#define NIKON_START_BIT_PULSE_TIME 2200.0e-6 // 2200 usec pulse +#define NIKON_START_BIT_PAUSE_TIME 27100.0e-6 // 27100 usec pause +#define NIKON_PULSE_TIME 500.0e-6 // 500 usec pulse +#define NIKON_1_PAUSE_TIME 3500.0e-6 // 3500 usec pause +#define NIKON_0_PAUSE_TIME 1500.0e-6 // 1500 usec pause +#define NIKON_FRAME_REPEAT_PAUSE_TIME 60.0e-3 // frame repeat after 60ms +#define NIKON_ADDRESS_OFFSET 0 // skip 0 bits +#define NIKON_ADDRESS_LEN 0 // read 0 address bits +#define NIKON_COMMAND_OFFSET 0 // skip 0 bits +#define NIKON_COMMAND_LEN 2 // read 2 bits +#define NIKON_COMPLETE_DATA_LEN 2 // complete length +#define NIKON_STOP_BIT 1 // has stop bit +#define NIKON_LSB 0 // LSB...MSB +#define NIKON_FLAGS 0 // flags + +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * KATHREIN: + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ +#define KATHREIN_START_BIT_PULSE_TIME 210.0e-6 // 1340 usec pulse +#define KATHREIN_START_BIT_PAUSE_TIME 6218.0e-6 // 340 usec pause +#define KATHREIN_1_PULSE_TIME 210.0e-6 // 1340 usec pulse +#define KATHREIN_1_PAUSE_TIME 3000.0e-6 // 340 usec pause +#define KATHREIN_0_PULSE_TIME 210.0e-6 // 500 usec pulse +#define KATHREIN_0_PAUSE_TIME 1400.0e-6 // 1300 usec pause +#define KATHREIN_SYNC_BIT_PAUSE_LEN_TIME 4600.0e-6 // 4600 usec sync (on 6th and/or 8th bit) +#define KATHREIN_FRAMES 1 // Kathrein sends 1 frame +#define KATHREIN_AUTO_REPETITION_PAUSE_TIME 35.0e-3 // auto repetition after 35ms +#define KATHREIN_FRAME_REPEAT_PAUSE_TIME 35.0e-3 // frame repeat after 35ms +#define KATHREIN_ADDRESS_OFFSET 1 // skip 1 bits +#define KATHREIN_ADDRESS_LEN 4 // read 4 address bits +#define KATHREIN_COMMAND_OFFSET 5 // skip 5 bits +#define KATHREIN_COMMAND_LEN 7 // read 7 bits +#define KATHREIN_COMPLETE_DATA_LEN 13 // complete length +#define KATHREIN_STOP_BIT 1 // has stop bit +#define KATHREIN_LSB 0 // MSB +#define KATHREIN_FLAGS 0 // flags + +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * NETBOX: + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ +#define NETBOX_START_BIT_PULSE_TIME 2400.0e-6 // 2400 usec pulse +#define NETBOX_START_BIT_PAUSE_TIME 800.0e-6 // 800 usec pause +#define NETBOX_PULSE_TIME 800.0e-6 // 800 usec pulse +#define NETBOX_PAUSE_TIME 800.0e-6 // 800 usec pause +#define NETBOX_FRAMES 1 // Netbox sends 1 frame +#define NETBOX_AUTO_REPETITION_PAUSE_TIME 35.0e-3 // auto repetition after 35ms +#define NETBOX_FRAME_REPEAT_PAUSE_TIME 35.0e-3 // frame repeat after 35ms +#define NETBOX_ADDRESS_OFFSET 0 // skip 0 bits +#define NETBOX_ADDRESS_LEN 3 // read 3 address bits +#define NETBOX_COMMAND_OFFSET 3 // skip 3 bits +#define NETBOX_COMMAND_LEN 13 // read 13 bits +#define NETBOX_COMPLETE_DATA_LEN 16 // complete length +#define NETBOX_STOP_BIT 0 // has no stop bit +#define NETBOX_LSB 1 // LSB +#define NETBOX_FLAGS IRMP_PARAM_FLAG_IS_SERIAL // flags + +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * LEGO: + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ +#define LEGO_START_BIT_PULSE_TIME 158.0e-6 // 158 usec pulse ( 6 x 1/38kHz) +#define LEGO_START_BIT_PAUSE_TIME 1026.0e-6 // 1026 usec pause (39 x 1/38kHz) +#define LEGO_PULSE_TIME 158.0e-6 // 158 usec pulse ( 6 x 1/38kHz) +#define LEGO_1_PAUSE_TIME 553.0e-6 // 553 usec pause (21 x 1/38kHz) +#define LEGO_0_PAUSE_TIME 263.0e-6 // 263 usec pause (10 x 1/38kHz) +#define LEGO_FRAME_REPEAT_PAUSE_TIME 40.0e-3 // frame repeat after 40ms +#define LEGO_ADDRESS_OFFSET 0 // skip 0 bits +#define LEGO_ADDRESS_LEN 0 // read 0 address bits +#define LEGO_COMMAND_OFFSET 0 // skip 0 bits +#define LEGO_COMMAND_LEN 16 // read 16 bits (12 command + 4 CRC) +#define LEGO_COMPLETE_DATA_LEN 16 // complete length +#define LEGO_STOP_BIT 1 // has stop bit +#define LEGO_LSB 0 // MSB...LSB +#define LEGO_FLAGS 0 // flags + +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * THOMSON: + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ +#define THOMSON_PULSE_TIME 550.0e-6 // 550 usec pulse +#define THOMSON_1_PAUSE_TIME 4500.0e-6 // 4500 usec pause +#define THOMSON_0_PAUSE_TIME 2000.0e-6 // 2000 usec pause +#define THOMSON_FRAMES 1 // THOMSON sends 1 frame +#define THOMSON_AUTO_REPETITION_PAUSE_TIME 35.0e-3 // repetition after 35ms +#define THOMSON_FRAME_REPEAT_PAUSE_TIME 35.0e-3 // frame repeat after 35ms +#define THOMSON_ADDRESS_OFFSET 0 // skip 0 bits +#define THOMSON_ADDRESS_LEN 4 // read 4 address bits +#define THOMSON_COMMAND_OFFSET 5 // skip 4 address bits + 1 toggle bit +#define THOMSON_COMMAND_LEN 7 // read 7 command bits +#define THOMSON_COMPLETE_DATA_LEN 12 // complete length +#define THOMSON_STOP_BIT 1 // has stop bit +#define THOMSON_LSB 0 // MSB...LSB +#define THOMSON_FLAGS 0 // flags + +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * BOSE: + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ +#define BOSE_START_BIT_PULSE_TIME 1060.0e-6 // 1060 usec pulse +#define BOSE_START_BIT_PAUSE_TIME 1425.0e-6 // 1425 usec pause +#define BOSE_PULSE_TIME 550.0e-6 // 550 usec pulse +#define BOSE_1_PAUSE_TIME 1425.0e-6 // 1425 usec pause +#define BOSE_0_PAUSE_TIME 437.0e-6 // 437 usec pause +#define BOSE_FRAMES 1 +#define BOSE_AUTO_REPETITION_PAUSE_TIME 40.0e-3 // repetition after 40ms? +#define BOSE_FRAME_REPEAT_PAUSE_TIME 40.0e-3 // frame repeat after 40ms? +#define BOSE_ADDRESS_OFFSET 0 // skip 0 bits +#define BOSE_ADDRESS_LEN 0 // read 16 address bits +#define BOSE_COMMAND_OFFSET 0 // skip 16 bits (8 address + 8 /address) +#define BOSE_COMMAND_LEN 16 // read 16 bits (8 command + 8 /command) +#define BOSE_COMPLETE_DATA_LEN 16 // complete length +#define BOSE_STOP_BIT 1 // has stop bit +#define BOSE_LSB 1 // LSB...MSB +#define BOSE_FLAGS 0 // flags + +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * A1TVBOX: + * In reality A1 TV Box has no start bit with 300/340 usec. There are 2 start bits "10" with 250us pulse + 150us pause + 150us pause + 250us pulse + * This is not very easy to detect, because 1st and 2nd pause of both start bits are closely spaced. + * So IRMP looks for pseudo start bit with 300/340 usec and ignores the second half of the 2nd bit (250us pulse) + * This method only works because the first data bit (which is the 3rd bit) following is always "1": + * IRMP treats the first "long" pulse (250us of 2nd start bit + 250us of 1st data bit) of this "1" as a first _short_ pulse. + * This is a bug in IRMP's manchester decoder, but a good feature here ;-) + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ +#define A1TVBOX_START_BIT_PULSE_TIME 300.0e-6 // 300 usec pulse +#define A1TVBOX_START_BIT_PAUSE_TIME 340.0e-6 // 340 usec pause +#define A1TVBOX_BIT_PULSE_TIME 250.0e-6 // 250 usec pulse +#define A1TVBOX_BIT_PAUSE_TIME 150.0e-6 // 150 usec pulse +#define A1TVBOX_STOP_BIT 0 // has no stop bit +#define A1TVBOX_LSB 0 // MSB...LSB +#define A1TVBOX_FLAGS (IRMP_PARAM_FLAG_IS_MANCHESTER | IRMP_PARAM_FLAG_1ST_PULSE_IS_1 ) // flags +#define A1TVBOX_FRAMES 1 // A1TVBOX sends each frame 1 times +#define A1TVBOX_ADDRESS_OFFSET 1 // skip 1 bits +#define A1TVBOX_ADDRESS_LEN 8 // read 8 address bits +#define A1TVBOX_COMMAND_OFFSET 9 // skip 9 bits (start bit + address) +#define A1TVBOX_COMMAND_LEN 8 // read 8 command bits +#define A1TVBOX_COMPLETE_DATA_LEN 17 // complete length incl. start bit +#define A1TVBOX_FRAME_REPEAT_PAUSE_TIME 50.0e-3 // 50 msec pause between frames, don't know if it is correct + +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * MERLIN: + * See notes for A1TVBOX + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ +#define MERLIN_START_BIT_PULSE_TIME 210.0e-6 // 210 usec pulse +#define MERLIN_START_BIT_PAUSE_TIME 420.0e-6 // 429 usec pause +#define MERLIN_BIT_PULSE_TIME 210.0e-6 // 210 usec pulse +#define MERLIN_BIT_PAUSE_TIME 210.0e-6 // 210 usec pulse +#define MERLIN_STOP_BIT 0 // has no stop bit +#define MERLIN_LSB 0 // MSB...LSB +#define MERLIN_FLAGS (IRMP_PARAM_FLAG_IS_MANCHESTER | IRMP_PARAM_FLAG_1ST_PULSE_IS_1 ) // flags +#define MERLIN_FRAMES 1 // MERLIN sends each frame 1 times +#define MERLIN_ADDRESS_OFFSET 1 // skip 1 bits +#define MERLIN_ADDRESS_LEN 8 // read 8 address bits +#define MERLIN_COMMAND_OFFSET 8 // skip 9 bits (start bit + address) +#define MERLIN_COMMAND_LEN 10 // read 8 command bits +#define MERLIN_COMPLETE_DATA_LEN 19 // complete length incl. start bit +#define MERLIN_FRAME_REPEAT_PAUSE_TIME 50.0e-3 // 50 msec pause between frames, don't know if it is correct + +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * ORTEK (Hama): 6 address bits + 2 frame type bits + 6 command bits + 1 parity bit + 1 unknown bit + "1" + "0" + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ +#define ORTEK_START_BIT_PULSE_TIME 2000.0e-6 // 2000 usec pulse +#define ORTEK_START_BIT_PAUSE_TIME 1000.0e-6 // 1000 usec pause +#define ORTEK_BIT_TIME 500.0e-6 // 500 usec pulse/pause +#define ORTEK_FRAME_REPEAT_PAUSE_TIME 45.0e-3 // frame repeat after 45ms +#define ORTEK_ADDRESS_OFFSET 0 // skip 0 bits +#define ORTEK_ADDRESS_LEN 8 // read 6 address bits + 2 special bits +#define ORTEK_COMMAND_OFFSET 8 // skip 6 address bits + 2 special bits +#define ORTEK_COMMAND_LEN 6 // read 6 command bits +#define ORTEK_COMPLETE_DATA_LEN 18 // complete length +#define ORTEK_STOP_BIT 0 // has no stop bit +#define ORTEK_LSB 0 // MSB...LSB +#define ORTEK_FLAGS (IRMP_PARAM_FLAG_IS_MANCHESTER | IRMP_PARAM_FLAG_1ST_PULSE_IS_1) // flags + +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * TELEFUNKEN: + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ +#define TELEFUNKEN_START_BIT_PULSE_TIME 600.0e-6 // 600 usec pulse +#define TELEFUNKEN_START_BIT_PAUSE_TIME 1500.0e-6 // 1500 usec pause +#define TELEFUNKEN_PULSE_TIME 600.0e-6 // 600 usec pulse +#define TELEFUNKEN_1_PAUSE_TIME 1500.0e-6 // 1500 usec pause +#define TELEFUNKEN_0_PAUSE_TIME 600.0e-6 // 600 usec pause +#define TELEFUNKEN_FRAME_REPEAT_PAUSE_TIME 22.0e-3 // frame repeat after XX ms ????? +#define TELEFUNKEN_ADDRESS_OFFSET 0 // skip 0 bits +#define TELEFUNKEN_ADDRESS_LEN 0 // read 0 address bits +#define TELEFUNKEN_COMMAND_OFFSET 0 // skip 0 bits +#define TELEFUNKEN_COMMAND_LEN 15 // read 15 bits +#define TELEFUNKEN_COMPLETE_DATA_LEN 15 // complete length +#define TELEFUNKEN_STOP_BIT 1 // has stop bit +#define TELEFUNKEN_LSB 0 // LSB...MSB +#define TELEFUNKEN_FLAGS 0 // flags + +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * ROOMBA + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ +#define ROOMBA_START_BIT_PULSE_TIME 2790.0e-6 // 2790 usec pulse +#define ROOMBA_START_BIT_PAUSE_TIME 930.0e-6 // 930 usec pause +#define ROOMBA_0_PULSE_TIME 930.0e-6 // 930 usec pulse +#define ROOMBA_1_PULSE_TIME 2790.0e-6 // 2790 usec pulse +#define ROOMBA_0_PAUSE_TIME 2790.0e-6 // 2790 usec pause +#define ROOMBA_1_PAUSE_TIME 930.0e-6 // 930 usec pause +#define ROOMBA_FRAME_REPEAT_PAUSE_TIME 18.0e-3 // frame repeat after 18ms +#define ROOMBA_ADDRESS_OFFSET 0 // skip 0 bits +#define ROOMBA_ADDRESS_LEN 0 // read 0 address bits +#define ROOMBA_COMMAND_OFFSET 0 // skip 0 bits +#define ROOMBA_COMMAND_LEN 7 // read 7 bits +#define ROOMBA_COMPLETE_DATA_LEN 7 // complete length +#define ROOMBA_STOP_BIT 0 // has stop bit (fm: sure?) +#define ROOMBA_LSB 0 // MSB...LSB +#define ROOMBA_FLAGS 0 // flags +#define ROOMBA_FRAMES 8 // ROOMBA sends 8 frames (this is a lie, but more comfortable) + +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * RC-MM (32, 24, or 12 bit) + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ +#define RCMM32_START_BIT_PULSE_TIME 500.0e-6 // 500 usec pulse +#define RCMM32_START_BIT_PAUSE_TIME 220.0e-6 // 220 usec pause +#define RCMM32_PULSE_TIME 230.0e-6 // 230 usec pulse +#define RCMM32_00_PAUSE_TIME 220.0e-6 // 220 usec pause +#define RCMM32_01_PAUSE_TIME 370.0e-6 // 370 usec pause +#define RCMM32_10_PAUSE_TIME 540.0e-6 // 540 usec pause +#define RCMM32_11_PAUSE_TIME 720.0e-6 // 720 usec pause + +#define RCMM32_FRAME_REPEAT_PAUSE_TIME 80.0e-3 // frame repeat after 80 ms +#define RCMM32_ADDRESS_OFFSET 0 // skip 0 bits +#define RCMM32_ADDRESS_LEN 16 // read 16 address bits +#define RCMM32_COMMAND_OFFSET 17 // skip 17 bits +#define RCMM32_COMMAND_LEN 15 // read 15 bits +#define RCMM32_COMPLETE_DATA_LEN 32 // complete length +#define RCMM32_STOP_BIT 1 // has stop bit +#define RCMM32_LSB 0 // LSB...MSB +#define RCMM32_FLAGS 0 // flags + +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * PENTAX: + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ +#define PENTAX_START_BIT_PULSE_TIME 13000.0e-6 // 13 msec pulse +#define PENTAX_START_BIT_PAUSE_TIME 3000.0e-6 // 3 msec pause +#define PENTAX_PULSE_TIME 1000.0e-6 // 1 msec pulse +#define PENTAX_1_PAUSE_TIME 3000.0e-6 // 3 msec pause +#define PENTAX_0_PAUSE_TIME 1000.0e-6 // 1 msec pause +#define PENTAX_FRAME_REPEAT_PAUSE_TIME 60.0e-3 // frame repeat after 60ms +#define PENTAX_ADDRESS_OFFSET 0 // skip 0 bits +#define PENTAX_ADDRESS_LEN 0 // read 0 address bits +#define PENTAX_COMMAND_OFFSET 0 // skip 0 bits +#define PENTAX_COMMAND_LEN 6 // read 6 bits +#define PENTAX_COMPLETE_DATA_LEN 6 // complete length +#define PENTAX_STOP_BIT 1 // has stop bit +#define PENTAX_LSB 0 // LSB...MSB +#define PENTAX_FLAGS 0 // flags + +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * ACP24: Stiebel Eltron ACP24 air conditioner + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ +#define ACP24_START_BIT_PULSE_TIME 390.0e-6 // 390 usec pulse +#define ACP24_START_BIT_PAUSE_TIME 950.0e-6 // 950 usec pause +#define ACP24_PULSE_TIME 390.0e-6 // 390 usec pulse +#define ACP24_1_PAUSE_TIME 1300.0e-6 // 1300 usec pause +#define ACP24_0_PAUSE_TIME 950.0e-6 // 950 usec pause +#define ACP24_FRAME_REPEAT_PAUSE_TIME 22.0e-3 // frame repeat after 22ms? +#define ACP24_ADDRESS_OFFSET 0 // skip 0 bits +#define ACP24_ADDRESS_LEN 0 // read 6 address bits +#define ACP24_COMMAND_OFFSET 0 // skip 6 bits +#define ACP24_COMMAND_LEN 0 // read 0 bits (70 bits will be read and compressed by special routine) +#define ACP24_COMPLETE_DATA_LEN 70 // complete length +#define ACP24_STOP_BIT 1 // has stop bit +#define ACP24_LSB 0 // LSB...MSB +#define ACP24_FLAGS 0 // flags + +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * IRMP16: + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ +#define IRMP16_START_BIT_PULSE_TIME 842.0e-6 // 842 usec pulse (32 x 1/38kHz) +#define IRMP16_START_BIT_PAUSE_TIME 1052.0e-6 // 1052 usec pause (40 x 1/38kHz) +#define IRMP16_PULSE_TIME 421.0e-6 // 421 usec pulse (16 x 1/38kHz) +#define IRMP16_1_PAUSE_TIME 842.0e-6 // 842 usec pause (32 x 1/38kHz) +#define IRMP16_0_PAUSE_TIME 421.0e-6 // 421 usec pause (16 x 1/38kHz) +#define IRMP16_FRAME_REPEAT_PAUSE_TIME 40.0e-3 // frame repeat after 40ms +#define IRMP16_ADDRESS_OFFSET 0 // skip 0 bits +#define IRMP16_ADDRESS_LEN 0 // read 0 address bits +#define IRMP16_COMMAND_OFFSET 0 // skip 0 bits +#define IRMP16_COMMAND_LEN 16 // read 16 bits (12 command + 4 CRC) +#define IRMP16_COMPLETE_DATA_LEN 16 // complete length +#define IRMP16_STOP_BIT 1 // has stop bit +#define IRMP16_LSB 1 // LSB...MSB +#define IRMP16_FLAGS 0 // flags + +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * GREE - climate: + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ +#define GREE_START_BIT_PULSE_TIME 12000.0e-6 // 12000 usec pulse (32 x 1/38kHz) +#define GREE_START_BIT_PAUSE_TIME 6000.0e-6 // 6000 usec pause (40 x 1/38kHz) +#define GREE_PULSE_TIME 900.0e-6 // 900 usec pulse (16 x 1/38kHz) +#define GREE_1_PAUSE_TIME 700.0e-6 // 700 usec pause (32 x 1/38kHz) +#define GREE_0_PAUSE_TIME 2100.0e-6 // 2100 usec pause (16 x 1/38kHz) +#define GREE_FRAME_REPEAT_PAUSE_TIME 40.0e-3 // frame repeat after 40ms +#define GREE_ADDRESS_OFFSET 0 // skip 0 bits +#define GREE_ADDRESS_LEN 16 // read 16 address bits +#define GREE_COMMAND_OFFSET 16 // skip 16 bits +#define GREE_COMMAND_LEN 16 // read 16 bits +#define GREE_COMPLETE_DATA_LEN 32 // complete length +#define GREE_STOP_BIT 1 // has stop bit +#define GREE_LSB 1 // LSB...MSB +#define GREE_FLAGS 0 // flags + +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * RADIO1 - e.g. Tevion + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ +#define RADIO1_START_BIT_PULSE_TIME 3000.0e-6 // 3000 usec pulse +#define RADIO1_START_BIT_PAUSE_TIME 7000.0e-6 // 7000 usec pulse +#define RADIO1_0_PULSE_TIME 500.0e-6 // 500 usec pulse +#define RADIO1_0_PAUSE_TIME 1000.0e-6 // 1000 usec pause +#define RADIO1_1_PULSE_TIME 1000.0e-6 // 1000 usec pulse +#define RADIO1_1_PAUSE_TIME 500.0e-6 // 500 usec pause + +#define RADIO1_FRAME_REPEAT_PAUSE_TIME 25.0e-3 // frame repeat after 25ms +#define RADIO1_ADDRESS_OFFSET 4 // skip 4 bits +#define RADIO1_ADDRESS_LEN 16 // read 16 address bits +#define RADIO1_COMMAND_OFFSET 20 // skip 4 + 16 bits +#define RADIO1_COMMAND_LEN 3 // read 3 command bits +#define RADIO1_COMPLETE_DATA_LEN 23 // complete length +#define RADIO1_STOP_BIT 1 // has stop bit +#define RADIO1_LSB 1 // LSB...MSB? +#define RADIO1_FLAGS 0 // flags + +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * Frame Repetitions: + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ +#define AUTO_FRAME_REPETITION_TIME 80.0e-3 // SIRCS/SAMSUNG32/NUBERT: automatic repetition after 25-50ms + +#endif // _IRMP_PROTOCOLS_H_ diff --git a/drivers/media/rc/irmp/irmpsystem.h b/drivers/media/rc/irmp/irmpsystem.h new file mode 100644 index 000000000000..fadd49194707 --- /dev/null +++ b/drivers/media/rc/irmp/irmpsystem.h @@ -0,0 +1,219 @@ +/*--------------------------------------------------------------------------------------------------------------------------------------------------- + * irmpsystem.h - system specific includes and defines + * + * Copyright (c) 2009-2018 Frank Meyer - frank(at)fli4l.de + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + *--------------------------------------------------------------------------------------------------------------------------------------------------- + */ + +#ifndef _IRMPSYSTEM_H_ +#define _IRMPSYSTEM_H_ + +#if !defined(_IRMP_H_) && !defined(_IRSND_H_) +# error please include only irmp.h or irsnd.h, not irmpsystem.h +#endif + +#if defined(__18CXX) // Microchip PIC C18 compiler +# define PIC_C18 +#elif defined(__XC8) // PIC XC8 compiler +# include +# define PIC_C18 +#elif defined(__PCM__) || defined(__PCB__) || defined(__PCH__) // CCS PIC compiler +# define PIC_CCS +#elif defined(STM32L1XX_MD) || defined(STM32L1XX_MDP) || defined(STM32L1XX_HD) // ARM STM32 +# include +# define ARM_STM32 +# define ARM_STM32L1XX +# define F_CPU (SysCtlClockGet()) +#elif defined(STM32F10X_LD) || defined(STM32F10X_LD_VL) \ + || defined(STM32F10X_MD) || defined(STM32F10X_MD_VL) \ + || defined(STM32F10X_HD) || defined(STM32F10X_HD_VL) \ + || defined(STM32F10X_XL) || defined(STM32F10X_CL) // ARM STM32 +# include +# define ARM_STM32 +# define ARM_STM32F10X +# define F_CPU (SysCtlClockGet()) +#elif defined(STM32F4XX) // ARM STM32 +# include +# define ARM_STM32 +# define ARM_STM32F4XX +#elif defined(USE_HAL_DRIVER) // ARM STM32 with HAL Library +# include "gpio.h" +# if defined(_IRSND_H_) +# include"tim.h" +# endif +# define ARM_STM32_HAL +# define F_CPU SystemCoreClock +#elif defined(__SDCC_stm8) // STM8 +# define SDCC_STM8 +#elif defined(TARGET_IS_BLIZZARD_RA2) // TI Stellaris (tested on Stellaris Launchpad with Code Composer Studio) +# define STELLARIS_ARM_CORTEX_M4 +# define F_CPU (SysCtlClockGet()) +#elif defined(__xtensa__) // ESP8266 (Arduino) +# include "Arduino.h" +# include "ets_sys.h" +# include "osapi.h" +# include "gpio.h" +# include "os_type.h" +# include "c_types.h" +# define uint_fast8_t uint8_t +# define uint_fast16_t uint16_t +#elif defined(TEENSYDUINO) && (defined(__MK20DX256__) || defined(__MK20DX128__)) // Teensy 3.x (tested on Teensy 3.1 in Arduino 1.6.5 / Teensyduino 1.2.5) +# include +# define TEENSY_ARM_CORTEX_M4 +#elif defined(unix) || defined(WIN32) || defined(__APPLE__) // Unix/Linux or Windows or Apple +# define UNIX_OR_WINDOWS +#elif defined(__MBED__) // mbed platform +// #include "mbed.h" // if mbed.h is used, source must be compiled as cpp +#include "gpio_api.h" +#elif defined(IRMP_CHIBIOS_HAL) // ChibiOS HAL +# include "hal.h" +#elif defined(IRMP_PULSE_IR_DECODER) // use measured pulses +#else +# define ATMEL_AVR // ATMEL AVR +#endif + +#if !defined(IRMP_PULSE_IR_DECODER) +#include +#else +#include +#endif + +#ifdef UNIX_OR_WINDOWS // Analyze on Unix/Linux or Windows +# include +# include +# define F_CPU 8000000L +# define ANALYZE +# ifdef unix +# include +# else +typedef unsigned char uint8_t; +typedef unsigned short uint16_t; +# endif +#endif + + +#if defined(ATMEL_AVR) +# include +# include +# include +# include +# include +# include +# define IRSND_OC2 0 // OC2 +# define IRSND_OC2A 1 // OC2A +# define IRSND_OC2B 2 // OC2B +# define IRSND_OC0 3 // OC0 +# define IRSND_OC0A 4 // OC0A +# define IRSND_OC0B 5 // OC0B + +# define IRSND_XMEGA_OC0A 0 // OC0A +# define IRSND_XMEGA_OC0B 1 // OC0B +# define IRSND_XMEGA_OC0C 2 // OC0C +# define IRSND_XMEGA_OC0D 3 // OC0D +# define IRSND_XMEGA_OC1A 4 // OC1A +# define IRSND_XMEGA_OC1B 5 // OC1B + +#elif defined(STELLARIS_ARM_CORTEX_M4) + +# include "inc/hw_ints.h" +# include "inc/hw_memmap.h" +# include "inc/hw_types.h" +# include "inc/hw_gpio.h" +# include "driverlib/fpu.h" +# include "driverlib/sysctl.h" +# include "driverlib/interrupt.h" +# include "driverlib/gpio.h" +# include "driverlib/rom.h" +# include "driverlib/systick.h" +# include "driverlib/pin_map.h" +# include "driverlib/timer.h" +# define PROGMEM +# define memcpy_P memcpy +# define APP_SYSTICKS_PER_SEC 32 + +#elif defined(ARM_STM32F10X) + +# include "stm32f10x_gpio.h" +# include "stm32f10x_rcc.h" +# include "stm32f10x_tim.h" +# include "misc.h" +# define PROGMEM +# define memcpy_P memcpy + +#elif defined(SDCC_STM8) + +# include "stm8s.h" +# define PROGMEM +# define memcpy_P memcpy +# define __attribute__(x) +# define uint_fast8_t uint8_t +# define uint_fast16_t uint16_t + +#elif defined(TEENSY_ARM_CORTEX_M4) +# define PROGMEM +# define memcpy_P memcpy + +#elif defined(__xtensa__) +# define PROGMEM +# define memcpy_P memcpy + +#elif defined(__MBED__) +# define PROGMEM +# define memcpy_P memcpy + +#elif defined(IRMP_PULSE_IR_DECODER) +# define PROGMEM +# define memcpy_P memcpy + +#else +# define PROGMEM +# define memcpy_P memcpy + +#endif + +#if defined(PIC_CCS) || defined(PIC_C18) || defined(IRMP_PULSE_IR_DECODER) +typedef unsigned char uint8_t; +typedef unsigned short uint16_t; +typedef unsigned char uint_fast8_t; +typedef unsigned short uint_fast16_t; +#endif + +#if defined(IRMP_PULSE_IR_DECODER) +typedef unsigned int uint32_t; +#endif + +#if defined (PIC_C18) // PIC C18 or XC8 compiler +# include // main PIC18 h file +#ifndef __XC8 +# include // timer lib +# include // pwm lib +#endif +# define IRSND_PIC_CCP1 1 // PIC C18 RC2 = PWM1 module +# define IRSND_PIC_CCP2 2 // PIC C18 RC1 = PWM2 module +#endif + +#ifndef TRUE +# define TRUE 1 +# define FALSE 0 +#endif + +#if defined(PIC_C18) +#define IRMP_PACKED_STRUCT +#else +#define IRMP_PACKED_STRUCT __attribute__ ((__packed__)) +#endif + +typedef struct IRMP_PACKED_STRUCT +{ + uint8_t protocol; // protocol, e.g. NEC_PROTOCOL + uint16_t address; // address + uint16_t command; // command + uint8_t flags; // flags, e.g. repetition +} IRMP_DATA; + +#endif // _IRMPSYSTEM_H_ diff --git a/drivers/media/rc/meson-ir.c b/drivers/media/rc/meson-ir.c index 487619b43a12..846221e2ceb3 100644 --- a/drivers/media/rc/meson-ir.c +++ b/drivers/media/rc/meson-ir.c @@ -76,6 +76,7 @@ struct meson_ir { struct rc_dev *rc; int irq; spinlock_t lock; + struct timer_list flush_timer; }; static void meson_ir_set_mask(struct meson_ir *ir, unsigned int reg, @@ -103,6 +104,10 @@ static irqreturn_t meson_ir_irq(int irqno, void *dev_id) ir_raw_event_store_edge(ir->rc, (readl(ir->reg + IR_DEC_STATUS) & STATUS_IR_DEC_IN) ? IR_PULSE : IR_SPACE); + + mod_timer(&ir->flush_timer, + jiffies + nsecs_to_jiffies(ir->rc->timeout)); + ir_raw_event_handle(ir->rc); #else duration = readl(ir->reg + IR_DEC_REG1); @@ -120,6 +125,17 @@ static irqreturn_t meson_ir_irq(int irqno, void *dev_id) return IRQ_HANDLED; } +static void flush_timer(unsigned long arg) +{ + struct meson_ir *ir = (struct meson_ir *)arg; + DEFINE_IR_RAW_EVENT(rawir); + + rawir.timeout = true; + rawir.duration = ir->rc->timeout; + ir_raw_event_store(ir->rc, &rawir); + ir_raw_event_handle(ir->rc); +} + static int meson_ir_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -166,7 +182,9 @@ static int meson_ir_probe(struct platform_device *pdev) ir->rc->driver_type = RC_DRIVER_IR_RAW; ir->rc->allowed_protocols = RC_BIT_ALL; ir->rc->rx_resolution = US_TO_NS(MESON_TRATE); - ir->rc->timeout = MS_TO_NS(200); + ir->rc->min_timeout = 1; + ir->rc->timeout = MS_TO_NS(125); + ir->rc->max_timeout = MS_TO_NS(1250); ir->rc->driver_name = DRIVER_NAME; #if defined(CONFIG_ARCH_MESON64_ODROIDN2) pulse_inverted = of_property_read_bool(node, "pulse-inverted"); @@ -181,6 +199,8 @@ static int meson_ir_probe(struct platform_device *pdev) goto out_free; } + setup_timer(&ir->flush_timer, flush_timer, (unsigned long) ir); + ret = devm_request_irq(dev, ir->irq, meson_ir_irq, 0, "ir-meson", ir); if (ret) { dev_err(dev, "failed to request irq\n"); @@ -244,21 +264,51 @@ static int meson_ir_remove(struct platform_device *pdev) meson_ir_set_mask(ir, IR_DEC_REG1, REG1_ENABLE, 0); spin_unlock_irqrestore(&ir->lock, flags); + del_timer_sync(&ir->flush_timer); + rc_unregister_device(ir->rc); return 0; } +static void meson_ir_shutdown(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *node = dev->of_node; + struct meson_ir *ir = platform_get_drvdata(pdev); + unsigned long flags; + + spin_lock_irqsave(&ir->lock, flags); + + /* + * Set operation mode to NEC/hardware decoding to give + * bootloader a chance to power the system back on + */ + if (of_device_is_compatible(node, "amlogic,meson6-ir")) + meson_ir_set_mask(ir, IR_DEC_REG1, REG1_MODE_MASK, + DECODE_MODE_NEC << REG1_MODE_SHIFT); + else + meson_ir_set_mask(ir, IR_DEC_REG2, REG2_MODE_MASK, + DECODE_MODE_NEC << REG2_MODE_SHIFT); + + /* Set rate to default value */ + meson_ir_set_mask(ir, IR_DEC_REG0, REG0_RATE_MASK, 0x13); + + spin_unlock_irqrestore(&ir->lock, flags); +} + static const struct of_device_id meson_ir_match[] = { { .compatible = "amlogic,meson6-ir" }, { .compatible = "amlogic,meson8b-ir" }, { .compatible = "amlogic,meson-gxbb-ir" }, { }, }; +MODULE_DEVICE_TABLE(of, meson_ir_match); static struct platform_driver meson_ir_driver = { .probe = meson_ir_probe, .remove = meson_ir_remove, + .shutdown = meson_ir_shutdown, .driver = { .name = DRIVER_NAME, .of_match_table = meson_ir_match, diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c index aba77357ab23..a1757159f74c 100644 --- a/drivers/media/rc/rc-main.c +++ b/drivers/media/rc/rc-main.c @@ -813,6 +813,7 @@ static const struct { { RC_BIT_MCE_KBD, "mce_kbd", "ir-mce_kbd-decoder" }, { RC_BIT_XMP, "xmp", "ir-xmp-decoder" }, { RC_BIT_CEC, "cec", NULL }, + { RC_BIT_IRMP, "irmp", "ir-irmp-decoder" }, }; /** diff --git a/drivers/media/tuners/xc5000.c b/drivers/media/tuners/xc5000.c index e6e5e90d8d95..2f44e5c0a6c0 100644 --- a/drivers/media/tuners/xc5000.c +++ b/drivers/media/tuners/xc5000.c @@ -931,7 +931,7 @@ static void xc5000_config_tv(struct dvb_frontend *fe, static int xc5000_set_tv_freq(struct dvb_frontend *fe) { struct xc5000_priv *priv = fe->tuner_priv; - u16 pll_lock_status; + u16 pll_lock_status = 0; int ret; tune_channel: diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index 20eb4014953f..d9e78340f9b0 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -1131,7 +1131,10 @@ static int mmc_select_hs400(struct mmc_card *card) unsigned int max_dtr; int err = 0; u8 val; - +#ifdef CONFIG_AMLOGIC_MMC + u8 raw_driver_strength = card->ext_csd.raw_driver_strength; + u8 ds = (host->caps >> 23) & 0x7; +#endif /* * HS400 mode requires 8-bit bus width */ @@ -1175,13 +1178,25 @@ static int mmc_select_hs400(struct mmc_card *card) /* Switch card to HS400 */ #ifdef CONFIG_AMLOGIC_MMC - if (card->ext_csd.raw_driver_strength & (1 << 4)) { + if (ds) { + if (ds & (1 << 0)) { + raw_driver_strength &= (1 << 0); + pr_info("%s:use ds type0\n", + mmc_hostname(host)); + /*3 -> type4 -> MMC_CAP_DRIVER_TYPED*/ + } else if (ds & (1 << 2)) { + raw_driver_strength &= ~(1 << 1); + pr_info("%s:use ds type4\n", + mmc_hostname(host)); + } + } + if (raw_driver_strength & (1 << 1)) { val = (0x4 << EXT_CSD_DRV_STR_SHIFT) | EXT_CSD_TIMING_HS400; pr_info("%s: support driver strength type 4\n", mmc_hostname(host)); - } else if (card->ext_csd.raw_driver_strength & (1 << 1)) { + } else if (raw_driver_strength & (1 << 4)) { val = (0x1 << EXT_CSD_DRV_STR_SHIFT) | EXT_CSD_TIMING_HS400; @@ -1192,15 +1207,20 @@ static int mmc_select_hs400(struct mmc_card *card) pr_info("%s: no support driver strength type 1 and 4\n", mmc_hostname(host)); } + err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, + EXT_CSD_HS_TIMING, val, + card->ext_csd.generic_cmd6_time, + true, true, true); #else val = EXT_CSD_TIMING_HS400 | card->drive_strength << EXT_CSD_DRV_STR_SHIFT; -#endif err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING, val, card->ext_csd.generic_cmd6_time, true, false, true); +#endif + if (err) { pr_err("%s: switch to hs400 failed, err:%d\n", mmc_hostname(host), err); @@ -1211,9 +1231,11 @@ static int mmc_select_hs400(struct mmc_card *card) mmc_set_timing(host, MMC_TIMING_MMC_HS400); mmc_set_bus_speed(card); +#ifndef CONFIG_AMLOGIC_MMC err = mmc_switch_status(card); if (err) goto out_err; +#endif return 0; diff --git a/drivers/mtd/nand/nand_ids.c b/drivers/mtd/nand/nand_ids.c index 2af9869a115e..8eda039c87fd 100644 --- a/drivers/mtd/nand/nand_ids.c +++ b/drivers/mtd/nand/nand_ids.c @@ -182,6 +182,7 @@ struct nand_manufacturers nand_manuf_ids[] = { {NAND_MFR_SANDISK, "SanDisk"}, {NAND_MFR_INTEL, "Intel"}, {NAND_MFR_ATO, "ATO"}, + {NAND_MFR_ZETTA, "Zetta"}, {0x0, "Unknown"} }; diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-meson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-meson.c index d3073cdb03db..9910115d12ba 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-meson.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-meson.c @@ -34,6 +34,7 @@ /* if it's internal phy we will shutdown analog*/ static unsigned int is_internal_phy; /* Ethernet register for G12A PHY */ +#define REG_ETH_REG1_OFFSET 0x4 #define ETH_PLL_CTL0 0x44 #define ETH_PLL_CTL1 0x48 #define ETH_PLL_CTL2 0x4C @@ -227,10 +228,12 @@ static void __iomem *network_interface_setup(struct platform_device *pdev) return PREG_ETH_REG0; } -static int dwmac_meson_cfg_ctrl(void __iomem *base_addr) +static int dwmac_meson_cfg_ctrl(void __iomem *base_addr, + struct platform_device *pdev) { void __iomem *ETH_PHY_config_addr = base_addr; - + unsigned int led_setting = 0; + unsigned int phy_setting = 0x54147; /*config phyid should between a 0~0xffffffff*/ /*please don't use 44000181, this has been used by internal phy*/ writel(0x33010180, ETH_PHY_config_addr + ETH_PHY_CNTL0); @@ -238,9 +241,16 @@ static int dwmac_meson_cfg_ctrl(void __iomem *base_addr) /*use_phy_smi | use_phy_ip | co_clkin from eth_phy_top*/ writel(0x260, ETH_PHY_config_addr + ETH_PHY_CNTL2); /*led signal is inverted*/ - writel(0x41054147, ETH_PHY_config_addr + ETH_PHY_CNTL1); - writel(0x41014147, ETH_PHY_config_addr + ETH_PHY_CNTL1); - writel(0x41054147, ETH_PHY_config_addr + ETH_PHY_CNTL1); + if (of_property_read_u32(pdev->dev.of_node, + "led_setting", &led_setting)) + led_setting = 0x41; + else + pr_info("load led setting as 0x%x\n", led_setting); + + phy_setting = (led_setting << 24) + (phy_setting & ~(0xff << 24)); + writel(phy_setting, ETH_PHY_config_addr + ETH_PHY_CNTL1); + writel(phy_setting & ~(0x1 << 18), ETH_PHY_config_addr + ETH_PHY_CNTL1); + writel(phy_setting, ETH_PHY_config_addr + ETH_PHY_CNTL1); /*wait phy to reset cause Power Up Reset need 5.2~2.6 ms*/ mdelay(10); return 0; @@ -294,6 +304,7 @@ static void __iomem *g12a_network_interface_setup(struct platform_device *pdev) struct pinctrl *pin_ctl; struct resource *res = NULL; u32 mc_val; + u32 cali_val; void __iomem *addr = NULL; void __iomem *REG_ETH_reg0_addr = NULL; void __iomem *ETH_PHY_config_addr = NULL; @@ -357,7 +368,7 @@ static void __iomem *g12a_network_interface_setup(struct platform_device *pdev) /*PLL*/ dwmac_meson_cfg_pll(ETH_PHY_config_addr, pdev); dwmac_meson_cfg_analog(ETH_PHY_config_addr, pdev); - dwmac_meson_cfg_ctrl(ETH_PHY_config_addr); + dwmac_meson_cfg_ctrl(ETH_PHY_config_addr, pdev); pin_ctl = devm_pinctrl_get_select (&pdev->dev, "internal_eth_pins"); return REG_ETH_reg0_addr; @@ -376,6 +387,13 @@ static void __iomem *g12a_network_interface_setup(struct platform_device *pdev) /*switch to extern phy*/ writel(0x0, ETH_PHY_config_addr + ETH_PHY_CNTL2); + /*set PRG_ETH_REG1 for exphy delay*/ + if (of_property_read_u32(np, "cali_val", &cali_val)) + pr_info("Not set cali_val for REG1\n"); + else + writel(cali_val, REG_ETH_reg0_addr + + REG_ETH_REG1_OFFSET); + pin_ctl = devm_pinctrl_get_select (&pdev->dev, "external_eth_pins"); return REG_ETH_reg0_addr; diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c index b497aed4cd12..1ee7572990c7 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c @@ -127,13 +127,6 @@ static void dwmac1000_get_umac_addr(struct mac_device_info *hw, unsigned int reg_n) { void __iomem *ioaddr = hw->pcsr; - -#if defined(CONFIG_ARCH_MESON64_ODROID_COMMON) - odroid_get_ether_addr(addr); - if (is_valid_ether_addr(addr)) - return; -#endif - stmmac_get_mac_addr(ioaddr, addr, GMAC_ADDR_HIGH(reg_n), GMAC_ADDR_LOW(reg_n)); } diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 3e77065811c8..99e074a489bc 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -124,6 +124,15 @@ static void stmmac_exit_fs(struct net_device *dev); #define STMMAC_COAL_TIMER(x) (jiffies + usecs_to_jiffies(x)) +/*won't be valid unless enable amlogic priv code*/ +#ifdef CONFIG_AMLOGIC_ETH_PRIVE +#undef TX_MONITOR +#endif + +#ifdef TX_MONITOR +static struct workqueue_struct *moniter_tx_wq; +static struct delayed_work moniter_tx_worker; +#endif /** * stmmac_verify_args - verify the driver parameters. * Description: it checks the driver parameters and set a default in case of @@ -1451,8 +1460,9 @@ static void stmmac_tx_err(struct stmmac_priv *priv) priv->hw->desc->init_tx_desc(&priv->dma_tx[i], priv->mode, (i == DMA_TX_SIZE - 1)); - priv->dirty_tx = 0; - priv->cur_tx = 0; + //priv->dirty_tx = 0; + //priv->cur_tx = 0; + priv->cur_tx = priv->dirty_tx; netdev_reset_queue(priv->dev); priv->hw->dma->start_tx(priv->ioaddr); @@ -1874,7 +1884,9 @@ static int stmmac_open(struct net_device *dev) napi_enable(&priv->napi); netif_start_queue(dev); - +#ifdef TX_MONITOR + queue_delayed_work(moniter_tx_wq, &moniter_tx_worker, HZ); +#endif return 0; lpiirq_error: @@ -2717,12 +2729,18 @@ static int stmmac_poll(struct napi_struct *napi, int budget) * netdev structure and arrange for the device to be reset to a sane state * in order to transmit a new packet. */ +#ifdef TX_MONITOR +unsigned int timeout_err; +#endif static void stmmac_tx_timeout(struct net_device *dev) { struct stmmac_priv *priv = netdev_priv(dev); /* Clear Tx resources and restart transmitting again */ stmmac_tx_err(priv); +#ifdef TX_MONITOR + timeout_err = 1; +#endif } /** @@ -3260,6 +3278,23 @@ static int stmmac_hw_init(struct stmmac_priv *priv) return 0; } +#ifdef TX_MONITOR +struct stmmac_priv *priv_monitor; +static void moniter_tx_handler(struct work_struct *work) +{ + if (priv_monitor) { + if (timeout_err) { + pr_info("reset eth\n"); + stmmac_release(priv_monitor->dev); + stmmac_open(priv_monitor->dev); + timeout_err = 0; + } + } else { + pr_info("device not init yet!\n"); + } + queue_delayed_work(moniter_tx_wq, &moniter_tx_worker, HZ); +} +#endif /** * stmmac_dvr_probe * @device: device pointer @@ -3278,6 +3313,10 @@ int stmmac_dvr_probe(struct device *device, struct net_device *ndev = NULL; struct stmmac_priv *priv; +#ifdef TX_MONITOR + moniter_tx_wq = create_singlethread_workqueue("eth_moniter_tx_wq"); + INIT_DELAYED_WORK(&moniter_tx_worker, moniter_tx_handler); +#endif ndev = alloc_etherdev(sizeof(struct stmmac_priv)); if (!ndev) return -ENOMEM; @@ -3428,6 +3467,9 @@ int stmmac_dvr_probe(struct device *device, #ifdef CONFIG_DWMAC_MESON ret = gmac_create_sysfs( mdiobus_get_phy(priv->mii, priv->plat->phy_addr), priv->ioaddr); +#endif +#ifdef TX_MONITOR + priv_monitor = priv; #endif return ret; @@ -3499,6 +3541,9 @@ int stmmac_suspend(struct device *dev) struct stmmac_priv *priv = netdev_priv(ndev); unsigned long flags; +#ifdef TX_MONITOR + cancel_delayed_work_sync(&moniter_tx_worker); +#endif if (!ndev || !netif_running(ndev)) return 0; @@ -3604,7 +3649,6 @@ int stmmac_resume(struct device *dev) stmmac_init_tx_coalesce(priv); stmmac_set_rx_mode(ndev); - #ifdef CONFIG_AMLOGIC_ETH_PRIVE netif_device_attach(ndev); #endif @@ -3617,6 +3661,10 @@ int stmmac_resume(struct device *dev) if (priv->phydev) phy_start(priv->phydev); +#ifdef TX_MONITOR + queue_delayed_work(moniter_tx_wq, &moniter_tx_worker, HZ); + timeout_err = 1; +#endif return 0; } EXPORT_SYMBOL_GPL(stmmac_resume); diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 2bca9554752f..ec88e000fe4f 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -136,7 +136,7 @@ static int mdio_bus_phy_resume(struct device *dev) struct phy_device *phydev = to_phy_device(dev); int ret; - if (!mdio_bus_phy_may_suspend(phydev)) + if (!phydev->suspended) goto no_resume; ret = phy_resume(phydev); diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c index 173f5f628750..088a0e58afc2 100644 --- a/drivers/net/phy/realtek.c +++ b/drivers/net/phy/realtek.c @@ -233,7 +233,7 @@ int rtl8211f_resume(struct phy_device *phydev) phy_write(phydev, RTL8211F_PAGE_SELECT, 0); mutex_unlock(&phydev->lock); } else { - genphy_resume(phydev); + rtl8211f_config_init(phydev); } pr_debug("%s %d\n", __func__, __LINE__); diff --git a/drivers/of/of_reserved_mem.c b/drivers/of/of_reserved_mem.c index 186f267ba87b..d25d99811d44 100644 --- a/drivers/of/of_reserved_mem.c +++ b/drivers/of/of_reserved_mem.c @@ -161,6 +161,18 @@ static int __init __reserved_mem_alloc_size(unsigned long node, &prop); #ifdef CONFIG_AMLOGIC_MODIFY + #ifdef CONFIG_AMLOGIC_KASAN32 + { + unsigned long lowmem_size; + + /* fix for cma overlap 2 zone */ + lowmem_size = KMEM_END - PAGE_OFFSET; + lowmem_size += CONFIG_PHYS_OFFSET; + if (start < lowmem_size && end > lowmem_size) { + end = lowmem_size - SZ_4M; + } + } + #endif #ifdef CONFIG_PHYS_ADDR_T_64BIT pr_info("%s, start:%pa, end:%pa, len:%ld MiB\n", __func__, &start, &end, diff --git a/drivers/perf/arm_pmu.c b/drivers/perf/arm_pmu.c index f51759da76f2..9fd30396ea45 100644 --- a/drivers/perf/arm_pmu.c +++ b/drivers/perf/arm_pmu.c @@ -1013,6 +1013,517 @@ static int of_pmu_irq_cfg(struct arm_pmu *pmu) return 0; } + +#ifdef CONFIG_AMLOGIC_MODIFY +#include +#include + +struct amlpmu_context amlpmu_ctx; + +static enum hrtimer_restart amlpmu_relax_timer_func(struct hrtimer *timer) +{ + struct amlpmu_context *ctx = &amlpmu_ctx; + struct amlpmu_cpuinfo *ci; + + ci = per_cpu_ptr(ctx->cpuinfo, 0); + + pr_info("enable cpu0_irq %d again, irq cnt = %lu\n", + ci->irq_num, + ci->valid_irq_cnt); + enable_irq(ci->irq_num); + + return HRTIMER_NORESTART; +} + +void amlpmu_relax_timer_start(int other_cpu) +{ + struct amlpmu_cpuinfo *ci; + int cpu; + struct amlpmu_context *ctx = &amlpmu_ctx; + + cpu = smp_processor_id(); + WARN_ON(cpu != 0); + + ci = per_cpu_ptr(ctx->cpuinfo, 0); + + pr_warn("wait cpu %d fixup done timeout, main cpu irq cnt = %lu\n", + other_cpu, + ci->valid_irq_cnt); + + if (hrtimer_active(&ctx->relax_timer)) { + pr_alert("relax_timer already active, return!\n"); + return; + } + + disable_irq_nosync(ci->irq_num); + + hrtimer_start(&ctx->relax_timer, + ns_to_ktime(ctx->relax_timer_ns), + HRTIMER_MODE_REL); +} + +static void amlpmu_fix_setup_affinity(int irq) +{ + int cluster_index = 0; + int cpu; + int affinity_cpu = -1; + struct amlpmu_cpuinfo *ci = NULL; + struct amlpmu_context *ctx = &amlpmu_ctx; + s64 latest_next_stamp = S64_MAX; + + if (irq == ctx->irqs[0]) + cluster_index = 0; + else if (ctx->clusterb_enabled && irq == + ctx->irqs[1]) + cluster_index = 1; + else { + pr_err("amlpmu_fix_setup_affinity() bad irq = %d\n", irq); + return; + } + + /* + * find latest next_predicted_stamp cpu for affinity cpu + * if no cpu have predict time, select first cpu of cpumask + * todo: + * - if a cpu predict failed for continuous N times, + * try add some punishment. + * - if no cpu have predicted time, try recently most used cpu + * for affinity + * - try to keep and promote prediction accuracy + */ + for_each_cpu_and(cpu, + &ctx->cpumasks[cluster_index], + cpu_possible_mask) { + ci = per_cpu_ptr(ctx->cpuinfo, cpu); + //pr_info("cpu = %d, ci->next_predicted_stamp.tv64 = %lld\n", + // cpu, ci->next_predicted_stamp.tv64); + if (ci->next_predicted_stamp.tv64 && + ci->next_predicted_stamp.tv64 < latest_next_stamp) { + latest_next_stamp = ci->next_predicted_stamp.tv64; + affinity_cpu = cpu; + } + } + + if (affinity_cpu == -1) { + affinity_cpu = cpumask_first(&ctx->cpumasks[cluster_index]); + pr_debug("used first cpu: %d, cluster: 0x%lx\n", + affinity_cpu, + *cpumask_bits(&ctx->cpumasks[cluster_index])); + } else + pr_debug("find affinity cpu: %d, next_predicted_stamp: %lld\n", + affinity_cpu, + latest_next_stamp); + + if (irq_set_affinity(irq, cpumask_of(affinity_cpu))) + pr_err("irq_set_affinity() failed irq: %d, affinity_cpu: %d\n", + irq, + affinity_cpu); +} + +/* + * on pmu interrupt generated cpu, @irq_num is valid + * on other cpus(called by AML_PMU_IPI), @irq_num is -1 + */ +static int amlpmu_irq_fix(int irq_num) +{ + int i; + int cpu; + int cur_cpu; + int pmuirq_val; + int cluster_index = 0; + int fix_success = 0; + struct amlpmu_cpuinfo *ci; + struct amlpmu_context *ctx = &amlpmu_ctx; + struct call_single_data csd_stack; + int max_wait_cnt = ctx->max_wait_cnt; + + csd_stack.func = amlpmu_handle_irq_ipi; + csd_stack.info = NULL; + + cur_cpu = smp_processor_id(); + + if (irq_num == ctx->irqs[0]) + cluster_index = 0; + else if (ctx->clusterb_enabled && irq_num == ctx->irqs[1]) + cluster_index = 1; + else { + pr_err("amlpmu_irq_fix() bad irq = %d\n", irq_num); + return fix_success; + } + + if (!cpumask_test_cpu(cur_cpu, &ctx->cpumasks[cluster_index])) { + pr_warn("amlpmu_irq_fix() cur_cpu %d not in cluster: 0x%lx\n", + cur_cpu, + *cpumask_bits(&ctx->cpumasks[cluster_index])); + } + + pmuirq_val = readl(ctx->regs[cluster_index]); + pmuirq_val &= 0xf; + pmuirq_val <<= ctx->first_cpus[cluster_index]; + + pr_debug("amlpmu_irq_fix() val=0x%0x, first_cpu=%d, cluster=0x%lx\n", + readl(ctx->regs[cluster_index]), + ctx->first_cpus[cluster_index], + *cpumask_bits(&ctx->cpumasks[cluster_index])); + + for_each_cpu_and(cpu, + &ctx->cpumasks[cluster_index], + cpu_possible_mask) { + if (pmuirq_val & (1<cpuinfo, cpu); + WRITE_ONCE(ci->fix_done, 0); + WRITE_ONCE(ci->fix_overflowed, 0); + + csd_stack.flags = 0; + smp_call_function_single_async(cpu, &csd_stack); + + for (i = 0; i < max_wait_cnt; i++) { + if (READ_ONCE(ci->fix_done)) + break; + + udelay(1); + } + + if (i == ctx->max_wait_cnt) { + pr_err("wait for cpu %d done timeout\n", + cpu); + //amlpmu_relax_timer_start(cpu); + } + + if (READ_ONCE(ci->fix_overflowed)) + fix_success++; + } + } + + return fix_success; +} + +static void amlpmu_update_stats(int irq_num, + int has_overflowed, + int fix_success) +{ + int freq; + int i; + ktime_t stamp; + unsigned long time = jiffies; + struct amlpmu_cpuinfo *ci; + struct amlpmu_context *ctx = &amlpmu_ctx; + + ci = this_cpu_ptr(ctx->cpuinfo); + + if (!has_overflowed && !fix_success) { + pr_debug("empty_irq_cnt: %lu\n", ci->empty_irq_cnt); + ci->empty_irq_cnt++; + ci->empty_irq_time = time; + } + + if (fix_success) { + /* send IPI success */ + pr_debug("fix_irq_cnt: %lu, fix_success = %d\n", + ci->fix_irq_cnt, + fix_success); + ci->fix_irq_cnt++; + ci->fix_irq_time = time; + } + + if (has_overflowed) { + ci->valid_irq_cnt++; + ci->valid_irq_time = time; + + stamp = ktime_get(); + ci->stamp_deltas[ci->valid_irq_cnt % MAX_DELTA_CNT] = + stamp.tv64 - ci->last_stamp.tv64; + ci->last_stamp = stamp; + + /* update avg_delta if it's valid */ + ci->avg_delta = 0; + for (i = 0; i < MAX_DELTA_CNT; i++) + ci->avg_delta += ci->stamp_deltas[i]; + + ci->avg_delta /= MAX_DELTA_CNT; + for (i = 0; i < MAX_DELTA_CNT; i++) { + if (ci->stamp_deltas[i] > ci->avg_delta * 3/2 || + ci->stamp_deltas[i] < ci->avg_delta / 2) { + ci->avg_delta = 0; + break; + } + } + if (ci->avg_delta) + ci->next_predicted_stamp.tv64 = + ci->last_stamp.tv64 + ci->avg_delta; + else + ci->next_predicted_stamp.tv64 = 0; + + pr_debug("irq_num = %d, valid_irq_cnt = %lu\n", + irq_num, + ci->valid_irq_cnt); + pr_debug("cur_delta = %lld, avg_delta = %lld, next = %lld\n", + ci->stamp_deltas[ci->valid_irq_cnt % MAX_DELTA_CNT], + ci->avg_delta, + ci->next_predicted_stamp.tv64); + } + + if (time_after(ci->valid_irq_time, ci->last_valid_irq_time + 2*HZ)) { + freq = ci->empty_irq_cnt - ci->last_empty_irq_cnt; + freq *= HZ; + freq /= (ci->empty_irq_time - ci->last_empty_irq_time); + pr_info("######## empty_irq_cnt: %lu - %lu = %lu, freq = %d\n", + ci->empty_irq_cnt, + ci->last_empty_irq_cnt, + ci->empty_irq_cnt - ci->last_empty_irq_cnt, + freq); + + ci->last_empty_irq_cnt = ci->empty_irq_cnt; + ci->last_empty_irq_time = ci->empty_irq_time; + + + freq = ci->fix_irq_cnt - ci->last_fix_irq_cnt; + freq *= HZ; + freq /= (ci->fix_irq_time - ci->last_fix_irq_time); + pr_info("######## fix_irq_cnt: %lu - %lu = %lu, freq = %d\n", + ci->fix_irq_cnt, + ci->last_fix_irq_cnt, + ci->fix_irq_cnt - ci->last_fix_irq_cnt, + freq); + + ci->last_fix_irq_cnt = ci->fix_irq_cnt; + ci->last_fix_irq_time = ci->fix_irq_time; + + + freq = ci->valid_irq_cnt - ci->last_valid_irq_cnt; + freq *= HZ; + freq /= (ci->valid_irq_time - ci->last_valid_irq_time); + pr_info("######## valid_irq_cnt: %lu - %lu = %lu, freq = %d\n", + ci->valid_irq_cnt, + ci->last_valid_irq_cnt, + ci->valid_irq_cnt - ci->last_valid_irq_cnt, + freq); + + ci->last_valid_irq_cnt = ci->valid_irq_cnt; + ci->last_valid_irq_time = ci->valid_irq_time; + } +} + +int amlpmu_handle_irq(struct arm_pmu *cpu_pmu, int irq_num, int has_overflowed) +{ + int cpu; + int fix_success = 0; + struct amlpmu_cpuinfo *ci; + struct amlpmu_context *ctx = &amlpmu_ctx; + + ci = this_cpu_ptr(ctx->cpuinfo); + ci->irq_num = irq_num; + cpu = smp_processor_id(); + + pr_debug("amlpmu_handle_irq() irq_num = %d, overflowed = %d\n", + irq_num, has_overflowed); + + /* + * if current cpu is not overflowed, it's possible some other + * cpus caused the pmu interrupt. + * so if current cpu is interrupt generated cpu(irq_num != -1), + * call aml_pmu_fix() try to send IPI to other cpus and waiting + * for fix_done. + */ + if (!has_overflowed && irq_num != -1) + fix_success = amlpmu_irq_fix(irq_num); + + /* + * valid_irq, fix_irq and empty_irq status + * avg_delta time account to predict next interrupt time + */ + amlpmu_update_stats(irq_num, has_overflowed, fix_success); + + /* + * armv*pmu_getreset_flags() will clear interrupt. If current + * interrupt is IPI fix(irq_num = -1), interrupt generated cpu + * now is waiting for ci->fix_done=1(clear interrupt). + * we must set ci->fix_done to 1 after amlpmu_stat_account(), + * because interrupt generated cpu need this predict time info + * to setup interrupt affinity. + */ + if (irq_num == -1) { + WRITE_ONCE(ci->fix_overflowed, has_overflowed); + /* fix_overflowed must before fix_done */ + mb(); + WRITE_ONCE(ci->fix_done, 1); + } + + /* only interrupt generated cpu need setup affinity */ + if (irq_num != -1) + amlpmu_fix_setup_affinity(irq_num); + + /* + * when a pmu interrupt generated, if current cpu is not + * overflowed and some other cpus succeed in handling the + * interrupt by IPIs return true. + */ + return !has_overflowed && fix_success; +} + +static int amlpmu_init(struct platform_device *pdev, struct arm_pmu *pmu) +{ + int cpu; + int ret = 0; + int irq; + u32 cpumasks[MAX_CLUSTER_NR] = {0}; + struct amlpmu_context *ctx = &amlpmu_ctx; + struct amlpmu_cpuinfo *ci; + + memset(ctx, 0, sizeof(*ctx)); + + ctx->cpuinfo = __alloc_percpu_gfp( + sizeof(struct amlpmu_cpuinfo), + SMP_CACHE_BYTES, + GFP_KERNEL | __GFP_ZERO); + if (!ctx->cpuinfo) { + pr_err("alloc percpu failed\n"); + ret = -ENOMEM; + goto free; + } + + for_each_possible_cpu(cpu) { + ci = per_cpu_ptr(ctx->cpuinfo, cpu); + ci->last_valid_irq_time = INITIAL_JIFFIES; + ci->last_fix_irq_time = INITIAL_JIFFIES; + ci->last_empty_irq_time = INITIAL_JIFFIES; + } + + ctx->pmu = pmu; + + if (of_property_read_bool(pdev->dev.of_node, "clusterb-enabled")) + ctx->clusterb_enabled = 1; + + pr_info("clusterb_enabled = %d\n", ctx->clusterb_enabled); + + ret = of_property_read_u32_array(pdev->dev.of_node, + "cpumasks", + cpumasks, + ctx->clusterb_enabled ? MAX_CLUSTER_NR : 1); + if (ret) { + pr_err("read prop cpumasks failed, ret = %d\n", ret); + ret = -EINVAL; + goto free; + } + pr_info("cpumasks 0x%0x, 0x%0x\n", cpumasks[0], cpumasks[1]); + + ret = of_property_read_u32(pdev->dev.of_node, + "relax-timer-ns", + &ctx->relax_timer_ns); + if (ret) { + pr_err("read prop relax-timer-ns failed, ret = %d\n", ret); + ret = -EINVAL; + goto free; + } + + ret = of_property_read_u32(pdev->dev.of_node, + "max-wait-cnt", + &ctx->max_wait_cnt); + if (ret) { + pr_err("read prop max-wait-cnt failed, ret = %d\n", ret); + ret = -EINVAL; + goto free; + } + + irq = platform_get_irq(pdev, 0); + if (irq < 0) { + pr_err("get clusterA irq failed, %d\n", irq); + ret = -EINVAL; + goto free; + } + ctx->irqs[0] = irq; + pr_info("cluster A irq = %d\n", irq); + + ctx->regs[0] = of_iomap(pdev->dev.of_node, 0); + if (IS_ERR(ctx->regs[0])) { + pr_err("of_iomap() clusterA failed, base = %p\n", ctx->regs[0]); + ret = PTR_ERR(ctx->regs[0]); + goto free; + } + + cpumask_clear(&ctx->cpumasks[0]); + memcpy(cpumask_bits(&ctx->cpumasks[0]), + &cpumasks[0], + sizeof(cpumasks[0])); + if (!cpumask_intersects(&ctx->cpumasks[0], cpu_possible_mask)) { + pr_err("bad cpumasks[0] 0x%x\n", cpumasks[0]); + ret = -EINVAL; + goto free; + } + ctx->first_cpus[0] = cpumask_first(&ctx->cpumasks[0]); + + amlpmu_fix_setup_affinity(ctx->irqs[0]); + + hrtimer_init(&ctx->relax_timer, + CLOCK_MONOTONIC, + HRTIMER_MODE_REL); + ctx->relax_timer.function = amlpmu_relax_timer_func; + + if (!ctx->clusterb_enabled) + return 0; + + irq = platform_get_irq(pdev, 1); + if (irq < 0) { + pr_err("get clusterB irq failed, %d\n", irq); + ret = -EINVAL; + goto free; + } + ctx->irqs[1] = irq; + pr_info("cluster B irq = %d\n", irq); + + + ctx->regs[1] = of_iomap(pdev->dev.of_node, 1); + if (IS_ERR(ctx->regs[1])) { + pr_err("of_iomap() clusterA failed, base = %p\n", ctx->regs[1]); + ret = PTR_ERR(ctx->regs[1]); + goto free; + } + + cpumask_clear(&ctx->cpumasks[1]); + memcpy(cpumask_bits(&ctx->cpumasks[1]), + &cpumasks[1], + sizeof(cpumasks[1])); + if (!cpumask_intersects(&ctx->cpumasks[1], cpu_possible_mask)) { + pr_err("bad cpumasks[1] 0x%x\n", cpumasks[1]); + ret = -EINVAL; + goto free; + } else if (cpumask_intersects(&ctx->cpumasks[0], &ctx->cpumasks[1])) { + pr_err("cpumasks intersect 0x%x : 0x%x\n", + cpumasks[0], + cpumasks[1]); + ret = -EINVAL; + goto free; + } + ctx->first_cpus[1] = cpumask_first(&ctx->cpumasks[1]); + + amlpmu_fix_setup_affinity(ctx->irqs[1]); + + return 0; + +free: + if (ctx->cpuinfo) + free_percpu(ctx->cpuinfo); + + if (ctx->regs[0]) + iounmap(ctx->regs[0]); + + if (ctx->regs[1]) + iounmap(ctx->regs[1]); + + return ret; +} + +#endif + int arm_pmu_device_probe(struct platform_device *pdev, const struct of_device_id *of_table, const struct pmu_probe_info *probe_table) @@ -1029,6 +1540,13 @@ int arm_pmu_device_probe(struct platform_device *pdev, return -ENOMEM; } +#ifdef CONFIG_AMLOGIC_MODIFY + if (amlpmu_init(pdev, pmu)) { + pr_err("amlpmu_init() failed\n"); + return 1; + } +#endif + armpmu_init(pmu); pmu->plat_device = pdev; diff --git a/drivers/pwm/sysfs.c b/drivers/pwm/sysfs.c index 0850b11dfd83..4841a049de99 100644 --- a/drivers/pwm/sysfs.c +++ b/drivers/pwm/sysfs.c @@ -223,11 +223,52 @@ static ssize_t capture_show(struct device *child, return sprintf(buf, "%u %u\n", result.period, result.duty_cycle); } +#ifdef CONFIG_AMLOGIC_MODIFY +/* + * This interface is added to facilitate debugging the voltage- + * table in pwm regulator, which can output different percentages + * of waveforms in a fixed pwm cycle. + * example: + * echo 50 100 > sys/class/pwm/pwmchipx/pwmx/relative_duty + * output 50% duty pwm + */ +static ssize_t relative_duty_store(struct device *child, + struct device_attribute *attr, + const char *buf, size_t size) +{ + struct pwm_export *export = child_to_pwm_export(child); + struct pwm_device *pwm = export->pwm; + struct pwm_state state = pwm->state; + int scale, dutycycle, ret; + + ret = sscanf(buf, "%d %d", &dutycycle, &scale); + if (ret != 2) { + pr_err("Can't parse addr and scale,dutycycle:[dutycycle scale]\n"); + return -EINVAL; + } + + if (!scale || dutycycle > scale) { + pr_err("parameter error\n"); + return -EINVAL; + } + + mutex_lock(&export->lock); + pwm_set_relative_duty_cycle(&state, dutycycle, scale); + ret = pwm_apply_state(pwm, &state); + mutex_unlock(&export->lock); + + return ret ? : size; +} +#endif + static DEVICE_ATTR_RW(period); static DEVICE_ATTR_RW(duty_cycle); static DEVICE_ATTR_RW(enable); static DEVICE_ATTR_RW(polarity); static DEVICE_ATTR_RO(capture); +#ifdef CONFIG_AMLOGIC_MODIFY +static DEVICE_ATTR_WO(relative_duty); +#endif static struct attribute *pwm_attrs[] = { &dev_attr_period.attr, @@ -235,6 +276,9 @@ static struct attribute *pwm_attrs[] = { &dev_attr_enable.attr, &dev_attr_polarity.attr, &dev_attr_capture.attr, +#ifdef CONFIG_AMLOGIC_MODIFY + &dev_attr_relative_duty.attr, +#endif NULL }; ATTRIBUTE_GROUPS(pwm); diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 7e235d1b7c07..13c1a5901ef5 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -2224,8 +2224,12 @@ free_interfaces: device_enable_async_suspend(&intf->dev); ret = device_add(&intf->dev); #ifdef CONFIG_AMLOGIC_USB - if (((&intf->dev)->driver) == NULL) - dev_err(&dev->dev, "Unsupported device\n"); + if (((&intf->dev)->driver) == NULL) { + if (intf->cur_altsetting->desc.bInterfaceClass == 0x09) + dev_err(&dev->dev, "Unsupported the hub\n"); + else + dev_err(&dev->dev, "Unsupported device\n"); + } #endif if (ret != 0) { dev_err(&dev->dev, "device_add(%s) --> %d\n", diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index abd1c3ae8153..314238487d15 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -208,6 +208,11 @@ static int dwc3_core_soft_reset(struct dwc3 *dwc) reg |= DWC3_GUSB3PIPECTL_PHYSOFTRST; dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg); + /* Assert USB3 PHY reset */ + reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(1)); + reg |= DWC3_GUSB3PIPECTL_PHYSOFTRST; + dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(1), reg); + /* Assert USB2 PHY reset */ reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); reg |= DWC3_GUSB2PHYCFG_PHYSOFTRST; @@ -245,6 +250,11 @@ static int dwc3_core_soft_reset(struct dwc3 *dwc) reg &= ~DWC3_GUSB3PIPECTL_PHYSOFTRST; dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg); + /* Clear USB3 PHY reset */ + reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(1)); + reg &= ~DWC3_GUSB3PIPECTL_PHYSOFTRST; + dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(1), reg); + /* Clear USB2 PHY reset */ reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); reg &= ~DWC3_GUSB2PHYCFG_PHYSOFTRST; @@ -760,6 +770,7 @@ static int dwc3_core_init(struct dwc3 *dwc) ret = dwc3_phy_setup(dwc); if (ret) goto err0; + #ifdef CONFIG_AMLOGIC_USB reg = dwc3_readl(dwc->regs, DWC3_GUCTL1); reg |= DWC3_GUCTL_NAKPERENHHS; @@ -958,6 +969,7 @@ static int dwc3_core_get_phy(struct dwc3 *dwc) if (dwc->usb3_phy) if (dwc->usb3_phy->flags == AML_USB3_PHY_ENABLE) dwc->super_speed_support = 1; + #endif dwc->usb2_generic_phy = devm_phy_get(dev, "usb2-phy"); @@ -1554,7 +1566,9 @@ MODULE_DEVICE_TABLE(acpi, dwc3_acpi_match); #endif static struct platform_driver dwc3_driver = { +#ifndef CONFIG_AMLOGIC_USB .probe = dwc3_probe, +#endif .remove = dwc3_remove, #ifdef CONFIG_AMLOGIC_USB .shutdown = dwc3_shutdown, @@ -1567,7 +1581,16 @@ static struct platform_driver dwc3_driver = { }, }; +#ifdef CONFIG_AMLOGIC_USB +/* AMLOGIC DWC3 driver does not allow module unload */ +static int __init amlogic_dwc3_init(void) +{ + return platform_driver_probe(&dwc3_driver, dwc3_probe); +} +late_initcall(amlogic_dwc3_init); +#else module_platform_driver(dwc3_driver); +#endif MODULE_ALIAS("platform:dwc3"); MODULE_AUTHOR("Felipe Balbi "); diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c index 528876248227..266fbd7374fc 100644 --- a/drivers/usb/gadget/function/f_fs.c +++ b/drivers/usb/gadget/function/f_fs.c @@ -900,13 +900,7 @@ static void ffs_user_copy_worker(struct work_struct *work) if (io_data->read) kfree(io_data->to_free); - -#ifdef CONFIG_AMLOGIC_USB - if (io_data->aio) { - if (buffer) - release_ffs_buffer(io_data->ffs, buffer); - } -#else +#ifndef CONFIG_AMLOGIC_USB kfree(io_data->buf); #endif kfree(io_data); @@ -1012,7 +1006,6 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data) #ifdef CONFIG_AMLOGIC_USB struct ffs_ep *ep = epfile->ep; struct ffs_data_buffer *buffer = NULL; - int data_aio_flag = -1; #else struct ffs_ep *ep; #endif @@ -1114,7 +1107,6 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data) *reboot adb disconnect,so buffer aways used assign_ffs_buffer. */ buffer = assign_ffs_buffer(epfile->ffs); - data_aio_flag = 1; if (unlikely(!buffer)) { ret = -ENOMEM; spin_unlock_irq(&epfile->ffs->eps_lock); @@ -1161,9 +1153,6 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data) DECLARE_COMPLETION_ONSTACK(done); #endif bool interrupted = false; -#ifdef CONFIG_AMLOGIC_USB - data_aio_flag = 1; -#endif req = ep->req; req->buf = data; req->length = data_len; @@ -1201,9 +1190,6 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data) } else if (!(req = usb_ep_alloc_request(ep->ep, GFP_ATOMIC))) { ret = -ENOMEM; } else { -#ifdef CONFIG_AMLOGIC_USB - data_aio_flag = -1; -#endif req->buf = data; req->length = data_len; @@ -1235,10 +1221,8 @@ error_mutex: mutex_unlock(&epfile->mutex); error: #ifdef CONFIG_AMLOGIC_USB - if (data_aio_flag > 0) { - if (buffer) - release_ffs_buffer(epfile->ffs, buffer); - } + if (buffer) + release_ffs_buffer(epfile->ffs, buffer); #else kfree(data); #endif diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index 840351d5b27b..dae41a3f1e04 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -944,7 +944,7 @@ int xhci_disable_slot(struct xhci_hcd *xhci, struct xhci_command *command, if (!virt_dev) return -EINVAL; if (!command) - command = xhci_alloc_command(xhci, false, false, GFP_KERNEL); + command = xhci_alloc_command(xhci, false, false, GFP_ATOMIC); if (!command) return -ENOMEM; @@ -980,7 +980,6 @@ static void xhci_set_port_power(struct xhci_hcd *xhci, { __le32 __iomem **port_array; u32 temp; - unsigned long flags = 0; port_array = xhci->usb2_ports; temp = readl(port_array[index]); @@ -994,14 +993,6 @@ static void xhci_set_port_power(struct xhci_hcd *xhci, /* Power off */ writel(temp & ~PORT_POWER, port_array[index]); } - - spin_unlock_irqrestore(&xhci->lock, flags); - temp = usb_acpi_power_manageable(hcd->self.root_hub, - index); - if (temp) - usb_acpi_set_power_state(hcd->self.root_hub, - index, on); - spin_lock_irqsave(&xhci->lock, flags); } @@ -1070,7 +1061,6 @@ static int xhci_test_suspend_resume(struct usb_hcd *hcd, __le32 __iomem **port_array = xhci->usb2_ports; /* 15 second delay per the test spec */ - spin_unlock_irqrestore(&xhci->lock, flags); xhci_err(xhci, "into suspend\n"); spin_lock_irqsave(&xhci->lock, flags); @@ -1091,6 +1081,7 @@ static int xhci_test_suspend_resume(struct usb_hcd *hcd, temp = readl(port_array[wIndex]); if ((temp & PORT_PE) == 0 || (temp & PORT_RESET) || (temp & PORT_PLS_MASK) >= XDEV_U3) { + spin_unlock_irqrestore(&xhci->lock, flags); xhci_warn(xhci, "USB core suspending device not in U0/U1/U2.\n"); return -1; } @@ -1098,6 +1089,7 @@ static int xhci_test_suspend_resume(struct usb_hcd *hcd, slot_id = xhci_find_slot_id_by_port(hcd, xhci, wIndex + 1); if (!slot_id) { + spin_unlock_irqrestore(&xhci->lock, flags); xhci_warn(xhci, "slot_id is zero\n"); return -1; } @@ -1122,11 +1114,15 @@ static int xhci_test_suspend_resume(struct usb_hcd *hcd, temp = readl(port_array[wIndex]); xhci_dbg(xhci, "clear USB_PORT_FEAT_SUSPEND\n"); xhci_dbg(xhci, "PORTSC %04x\n", temp); - if (temp & PORT_RESET) + if (temp & PORT_RESET) { + spin_unlock_irqrestore(&xhci->lock, flags); return -1; + } if ((temp & PORT_PLS_MASK) == XDEV_U3) { - if ((temp & PORT_PE) == 0) + if ((temp & PORT_PE) == 0) { + spin_unlock_irqrestore(&xhci->lock, flags); return -1; + } xhci_set_link_state(xhci, port_array, wIndex, XDEV_RESUME); @@ -1138,6 +1134,7 @@ static int xhci_test_suspend_resume(struct usb_hcd *hcd, } xhci_ring_device(xhci, slot_id); + spin_unlock_irqrestore(&xhci->lock, flags); return 0; } #endif @@ -1426,8 +1423,11 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, else if (test_mode == 5) xhci_port_set_test_mode(xhci, test_mode, wIndex); - else + else { + spin_unlock_irqrestore(&xhci->lock, flags); retval = xhci_test_suspend_resume(hcd, wIndex); + spin_lock_irqsave(&xhci->lock, flags); + } break; #endif default: diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 08b719d7daed..40d2804ede72 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -3398,16 +3398,22 @@ int xhci_test_single_step(struct xhci_hcd *xhci, gfp_t mem_flags, struct xhci_td *td; unsigned long flags = 0; + spin_lock_irqsave(&xhci->lock, flags); + ep_ring = xhci_urb_to_transfer_ring(xhci, urb); - if (!ep_ring) + if (!ep_ring) { + spin_unlock_irqrestore(&xhci->lock, flags); return -EINVAL; + } /* * Need to copy setup packet into setup TRB, so we can't use the setup * DMA address. */ - if (!urb->setup_packet) + if (!urb->setup_packet) { + spin_unlock_irqrestore(&xhci->lock, flags); return -EINVAL; + } /* 1 TRB for setup, 1 for status */ num_trbs = 2; @@ -3421,8 +3427,10 @@ int xhci_test_single_step(struct xhci_hcd *xhci, gfp_t mem_flags, ret = prepare_transfer(xhci, xhci->devs[slot_id], ep_index, urb->stream_id, num_trbs, urb, 0, mem_flags); - if (ret < 0) + if (ret < 0) { + spin_unlock_irqrestore(&xhci->lock, flags); return ret; + } urb_priv = urb->hcpriv; td = urb_priv->td[0]; @@ -3527,14 +3535,12 @@ int xhci_test_single_step(struct xhci_hcd *xhci, gfp_t mem_flags, giveback_first_trb(xhci, slot_id, ep_index, 0, start_cycle, start_trb); - /* 15 second delay per the test spec */ - spin_unlock_irqrestore(&xhci->lock, flags); - xhci_err(xhci, "step 3\n"); - msleep(15000); - spin_lock_irqsave(&xhci->lock, flags); + /* 15 second delay per the test spec */ + spin_unlock_irqrestore(&xhci->lock, flags); + xhci_err(xhci, "step 3\n"); + msleep(15000); return 0; - } #endif diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 8127950cc487..f273d6743791 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -1455,14 +1455,18 @@ int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags) && (setup->wIndex != 0x0)) { if ((((setup->wIndex)>>8) & 0xff) == 7) { setup->wIndex = 0; + spin_unlock_irqrestore(&xhci->lock, flags); ret = xhci_test_single_step(xhci, GFP_ATOMIC, urb, slot_id, ep_index, 1); + spin_lock_irqsave(&xhci->lock, flags); } else if ((((setup->wIndex)>>8)&0xff) == 8) { setup->wIndex = 0; + spin_unlock_irqrestore(&xhci->lock, flags); ret = xhci_test_single_step(xhci, GFP_ATOMIC, urb, slot_id, ep_index, 2); + spin_lock_irqsave(&xhci->lock, flags); } } else #endif diff --git a/firmware/h264_enc.bin b/firmware/h264_enc.bin deleted file mode 100644 index 27c54d61c881..000000000000 Binary files a/firmware/h264_enc.bin and /dev/null differ diff --git a/firmware/video/video_ucode.bin b/firmware/video/video_ucode.bin old mode 100644 new mode 100755 index 24b752810f28..dd56ade8bfbd Binary files a/firmware/video/video_ucode.bin and b/firmware/video/video_ucode.bin differ diff --git a/firmware/video_ucode.bin b/firmware/video_ucode.bin deleted file mode 100755 index 24b752810f28..000000000000 Binary files a/firmware/video_ucode.bin and /dev/null differ diff --git a/fs/exfat/exfat_nls.c b/fs/exfat/exfat_nls.c index be7fbf92cc76..2f2f49137530 100644 --- a/fs/exfat/exfat_nls.c +++ b/fs/exfat/exfat_nls.c @@ -106,7 +106,7 @@ s32 nls_uniname_cmp(struct super_block *sb, u16 *a, u16 *b) for (i = 0; i < MAX_NAME_LENGTH; i++, a++, b++) { if (nls_upper(sb, *a) != nls_upper(sb, *b)) return 1; - if (*a == 0x0) + if ((*a == 0x0) || (*b == 0x0)) return 0; } return 0; diff --git a/fs/exfat/exfat_nls.h b/fs/exfat/exfat_nls.h index cdc175585411..ef88abc14cc6 100644 --- a/fs/exfat/exfat_nls.h +++ b/fs/exfat/exfat_nls.h @@ -48,11 +48,11 @@ #define DOS_PAR_DIR_NAME ".. " #ifdef __LITTLE_ENDIAN -#define UNI_CUR_DIR_NAME ".\0" -#define UNI_PAR_DIR_NAME ".\0.\0" +#define UNI_CUR_DIR_NAME ".\0\0\0" +#define UNI_PAR_DIR_NAME ".\0.\0\0\0" #else -#define UNI_CUR_DIR_NAME "\0." -#define UNI_PAR_DIR_NAME "\0.\0." +#define UNI_CUR_DIR_NAME "\0.\0\0" +#define UNI_PAR_DIR_NAME "\0.\0.\0\0" #endif /*----------------------------------------------------------------------*/ diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index 9efbc04e30f4..15e574e09dc5 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -2287,10 +2287,8 @@ int sanity_check_ckpt(struct f2fs_sb_info *sbi) unsigned int main_segs, blocks_per_seg; unsigned int sit_segs, nat_segs; unsigned int sit_bitmap_size, nat_bitmap_size; - unsigned int log_blocks_per_seg; - unsigned int segment_count_main; + unsigned int log_blocks_per_seg = 0; unsigned int cp_pack_start_sum, cp_payload; - block_t user_block_count; int i, j; total = le32_to_cpu(raw_super->segment_count); diff --git a/fs/f2fs/trace.c b/fs/f2fs/trace.c index cb696791044b..18f7c09d3aad 100644 --- a/fs/f2fs/trace.c +++ b/fs/f2fs/trace.c @@ -73,7 +73,7 @@ retry: radix_tree_delete(&pids, pid); if (radix_tree_insert(&pids, pid, current)) { - spin_unlock(&pids_lock); + spin_unlock((spinlock_t *)&pids_lock); radix_tree_preload_end(); cond_resched(); goto retry; diff --git a/fs/namespace.c b/fs/namespace.c index 77b46bf40f09..6224ff52544b 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -2734,6 +2734,17 @@ static long exact_copy_from_user(void *to, const void __user * from, if (!access_ok(VERIFY_READ, from, n)) return n; +#ifdef CONFIG_AMLOGIC_VMAP + /* addr from kernel space and in vmalloc range, avoid overflow */ + if (is_vmalloc_or_module_addr((void *)from)) { + unsigned long old = n; + + n = strlen(from) + 1; + pr_info("addr:%p is in kernel, size fix %ld->%ld, data:%s\n", + from, old, n, (char *)from); + } +#endif + while (n) { if (__get_user(c, f)) { memset(t, 0, n); diff --git a/fs/pstore/ftrace.c b/fs/pstore/ftrace.c index d4887705bb61..33fa1395e053 100644 --- a/fs/pstore/ftrace.c +++ b/fs/pstore/ftrace.c @@ -27,6 +27,10 @@ #include #include "internal.h" +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE +#include +#endif + static void notrace pstore_ftrace_call(unsigned long ip, unsigned long parent_ip, struct ftrace_ops *op, @@ -39,13 +43,16 @@ static void notrace pstore_ftrace_call(unsigned long ip, return; local_irq_save(flags); - rec.ip = ip; rec.parent_ip = parent_ip; +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE + rec.flag = PSTORE_FLAG_FUNC; + pstore_ftrace_save(&rec); +#else pstore_ftrace_encode_cpu(&rec, raw_smp_processor_id()); psinfo->write_buf(PSTORE_TYPE_FTRACE, 0, NULL, 0, (void *)&rec, 0, sizeof(rec), psinfo); - +#endif local_irq_restore(flags); } diff --git a/fs/pstore/inode.c b/fs/pstore/inode.c index 1781dc50762e..6f6f56c21524 100644 --- a/fs/pstore/inode.c +++ b/fs/pstore/inode.c @@ -37,6 +37,7 @@ #include #include #include +#include #include "internal.h" @@ -107,10 +108,13 @@ static int pstore_ftrace_seq_show(struct seq_file *s, void *v) struct pstore_ftrace_seq_data *data = v; struct pstore_ftrace_record *rec = (void *)(ps->data + data->off); +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE + pstore_ftrace_dump(rec, s); +#else seq_printf(s, "%d %08lx %08lx %pf <- %pF\n", pstore_ftrace_decode_cpu(rec), rec->ip, rec->parent_ip, (void *)rec->ip, (void *)rec->parent_ip); - +#endif return 0; } diff --git a/fs/pstore/internal.h b/fs/pstore/internal.h index e38a22b31282..cca4fefea880 100644 --- a/fs/pstore/internal.h +++ b/fs/pstore/internal.h @@ -17,8 +17,22 @@ struct pstore_ftrace_record { #ifndef PSTORE_CPU_IN_IP unsigned int cpu; #endif +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE + int pid; + unsigned long val1; + unsigned long val2; + unsigned long long time; + unsigned char comm[8]; + unsigned int flag; +#endif }; +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE +void notrace pstore_ftrace_save(struct pstore_ftrace_record *rec); +void notrace pstore_ftrace_dump(struct pstore_ftrace_record *rec, + struct seq_file *s); +#endif + static inline void pstore_ftrace_encode_cpu(struct pstore_ftrace_record *rec, unsigned int cpu) { diff --git a/fs/pstore/ram.c b/fs/pstore/ram.c index 8e151fb9bb76..aa3f123f3239 100644 --- a/fs/pstore/ram.c +++ b/fs/pstore/ram.c @@ -602,6 +602,9 @@ static int ramoops_probe(struct platform_device *pdev) cxt->size = pdata->mem_size; cxt->phys_addr = pdata->mem_address; cxt->memtype = pdata->mem_type; +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE + cxt->memtype |= (!!ramoops_io_en); +#endif cxt->record_size = pdata->record_size; cxt->console_size = pdata->console_size; cxt->ftrace_size = pdata->ftrace_size; @@ -621,7 +624,6 @@ static int ramoops_probe(struct platform_device *pdev) cxt->console_size, 0); if (err) goto fail_init_cprz; - err = ramoops_init_prz(dev, cxt, &cxt->fprz, &paddr, cxt->ftrace_size, LINUX_VERSION_CODE); if (err) @@ -679,6 +681,17 @@ static int ramoops_probe(struct platform_device *pdev) cxt->size, (unsigned long long)cxt->phys_addr, cxt->ecc_info.ecc_size, cxt->ecc_info.block_size); +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE + if (ramoops_ftrace_size) { + cxt->fprz->flags |= (PRZ_FLAG_NO_LOCK | PRZ_FLAG_BIG_LOCK); + ramoops_ftrace_en = !persistent_ram_old_size(cxt->fprz); + } + pr_info("ramoops_io_en:%d %d old:0x%lx ftrace_size:0x%lx", + ramoops_io_en, ramoops_ftrace_en, + (unsigned long)persistent_ram_old_size(cxt->fprz), + ramoops_ftrace_size); +#endif + return 0; fail_buf: diff --git a/fs/pstore/ram_core.c b/fs/pstore/ram_core.c index 11e558efd61e..d476f493e478 100644 --- a/fs/pstore/ram_core.c +++ b/fs/pstore/ram_core.c @@ -12,6 +12,7 @@ * */ +#define SKIP_IO_TRACE #define pr_fmt(fmt) "persistent_ram: " fmt #include @@ -49,7 +50,8 @@ static inline size_t buffer_start(struct persistent_ram_zone *prz) } /* increase and wrap the start pointer, returning the old value */ -static size_t buffer_start_add(struct persistent_ram_zone *prz, size_t a) +static size_t notrace buffer_start_add(struct persistent_ram_zone *prz, + size_t a) { int old; int new; @@ -71,7 +73,7 @@ static size_t buffer_start_add(struct persistent_ram_zone *prz, size_t a) } /* increase the size counter until it hits the max size */ -static void buffer_size_add(struct persistent_ram_zone *prz, size_t a) +static void notrace buffer_size_add(struct persistent_ram_zone *prz, size_t a) { size_t old; size_t new; @@ -310,6 +312,12 @@ int notrace persistent_ram_write(struct persistent_ram_zone *prz, int c = count; size_t start; +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE + unsigned long flags = 0; + + if (prz->flags & PRZ_FLAG_BIG_LOCK) + raw_spin_lock_irqsave(&prz->buffer_lock, flags); +#endif if (unlikely(c > prz->buffer_size)) { s += c - prz->buffer_size; c = prz->buffer_size; @@ -330,6 +338,10 @@ int notrace persistent_ram_write(struct persistent_ram_zone *prz, persistent_ram_update_header_ecc(prz); +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE + if (prz->flags & PRZ_FLAG_BIG_LOCK) + raw_spin_unlock_irqrestore(&prz->buffer_lock, flags); +#endif return count; } diff --git a/fs/sdcardfs/inode.c b/fs/sdcardfs/inode.c index 84df23ac0d5f..57bdc686094f 100644 --- a/fs/sdcardfs/inode.c +++ b/fs/sdcardfs/inode.c @@ -95,8 +95,10 @@ static int sdcardfs_create(struct inode *dir, struct dentry *dentry, err = -ENOMEM; goto out_unlock; } + copied_fs->umask = 0; + task_lock(current); current->fs = copied_fs; - current->fs->umask = 0; + task_unlock(current); err = vfs_create2(lower_dentry_mnt, d_inode(lower_parent_dentry), lower_dentry, mode, want_excl); if (err) goto out; @@ -110,7 +112,9 @@ static int sdcardfs_create(struct inode *dir, struct dentry *dentry, fixup_lower_ownership(dentry, dentry->d_name.name); out: + task_lock(current); current->fs = saved_fs; + task_unlock(current); free_fs_struct(copied_fs); out_unlock: unlock_dir(lower_parent_dentry); @@ -316,8 +320,10 @@ static int sdcardfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode unlock_dir(lower_parent_dentry); goto out_unlock; } + copied_fs->umask = 0; + task_lock(current); current->fs = copied_fs; - current->fs->umask = 0; + task_unlock(current); err = vfs_mkdir2(lower_mnt, d_inode(lower_parent_dentry), lower_dentry, mode); if (err) { @@ -377,7 +383,10 @@ static int sdcardfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode } } out: + task_lock(current); current->fs = saved_fs; + task_unlock(current); + free_fs_struct(copied_fs); out_unlock: sdcardfs_put_lower_path(dentry, &lower_path); diff --git a/include/dt-bindings/clock/amlogic,g12a-clkc.h b/include/dt-bindings/clock/amlogic,g12a-clkc.h index 6cf7109d2397..4084205b8e30 100644 --- a/include/dt-bindings/clock/amlogic,g12a-clkc.h +++ b/include/dt-bindings/clock/amlogic,g12a-clkc.h @@ -249,8 +249,12 @@ #define CLKID_VPU_CLKC_P1_GATE (CLKID_MEDIA_BASE + 67) #define CLKID_VPU_CLKC_P1_COMP (CLKID_MEDIA_BASE + 68) #define CLKID_VPU_CLKC_MUX (CLKID_MEDIA_BASE + 69) +#define CLKID_BT656_MUX (CLKID_MEDIA_BASE + 70) +#define CLKID_BT656_DIV (CLKID_MEDIA_BASE + 71) +#define CLKID_BT656_GATE (CLKID_MEDIA_BASE + 72) +#define CLKID_BT656_COMP (CLKID_MEDIA_BASE + 73) -#define CLKID_MISC_BASE (CLKID_MEDIA_BASE + 70) +#define CLKID_MISC_BASE (CLKID_MEDIA_BASE + 74) #define CLKID_SPICC0_MUX (CLKID_MISC_BASE + 0) #define CLKID_SPICC0_DIV (CLKID_MISC_BASE + 1) #define CLKID_SPICC0_GATE (CLKID_MISC_BASE + 2) @@ -259,7 +263,7 @@ #define CLKID_SPICC1_DIV (CLKID_MISC_BASE + 5) #define CLKID_SPICC1_GATE (CLKID_MISC_BASE + 6) #define CLKID_SPICC1_COMP (CLKID_MISC_BASE + 7) -#define CLKID_TS_COMP (CLKID_MISC_BASE + 8) +#define CLKID_TS_COMP (CLKID_MISC_BASE + 8) /*gpio 12M/24M */ #define CLKID_24M (CLKID_MISC_BASE + 9) @@ -289,7 +293,26 @@ #define CLKID_MIPI_CSI_PHY_MUX (CLKID_G12B_ADD_BASE + 16) #define CLKID_SYS1_PLL (CLKID_G12B_ADD_BASE + 17) -#define CLKID_AO_BASE (CLKID_G12B_ADD_BASE + 18) +#define CLKID_SM1_ADD_BASE (CLKID_G12B_ADD_BASE + 18) +#define CLKID_GP1_PLL (CLKID_SM1_ADD_BASE + 0) +#define CLKID_DSU_PRE_SRC0 (CLKID_SM1_ADD_BASE + 1) +#define CLKID_DSU_PRE_SRC1 (CLKID_SM1_ADD_BASE + 2) +#define CLKID_DSU_CLK_DIV0 (CLKID_SM1_ADD_BASE + 3) +#define CLKID_DSU_CLK_DIV1 (CLKID_SM1_ADD_BASE + 4) +#define CLKID_DSU_PRE_MUX0 (CLKID_SM1_ADD_BASE + 5) +#define CLKID_DSU_PRE_MUX1 (CLKID_SM1_ADD_BASE + 6) +#define CLKID_DSU_PRE_POST_MUX (CLKID_SM1_ADD_BASE + 7) +#define CLKID_DSU_PRE_CLK (CLKID_SM1_ADD_BASE + 8) +#define CLKID_DSU_CLK (CLKID_SM1_ADD_BASE + 9) +#define CLKID_CSI_DIG_CLK (CLKID_SM1_ADD_BASE + 10) +#define CLKID_NNA_CLK (CLKID_SM1_ADD_BASE + 11) +#define CLKID_PARSER1_CLK (CLKID_SM1_ADD_BASE + 12) +#define CLKID_CSI_HOST_CLK (CLKID_SM1_ADD_BASE + 13) +#define CLKID_CSI_ADPAT_CLK (CLKID_SM1_ADD_BASE + 14) +#define CLKID_TEMP_SENSOR_CLK (CLKID_SM1_ADD_BASE + 15) +#define CLKID_CSI_PHY_CLK (CLKID_SM1_ADD_BASE + 16) + +#define CLKID_AO_BASE (CLKID_SM1_ADD_BASE + 17) #define CLKID_AO_CLK81 (CLKID_AO_BASE + 0) #define CLKID_SARADC_MUX (CLKID_AO_BASE + 1) #define CLKID_SARADC_DIV (CLKID_AO_BASE + 2) diff --git a/include/dt-bindings/clock/amlogic,sm1-audio-clk.h b/include/dt-bindings/clock/amlogic,sm1-audio-clk.h new file mode 100644 index 000000000000..9ec20b6116f1 --- /dev/null +++ b/include/dt-bindings/clock/amlogic,sm1-audio-clk.h @@ -0,0 +1,92 @@ +/* + * include/dt-bindings/clock/amlogic,sm1-audio-clk.h + * + * Copyright (C) 2019 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 __SM1_AUDIO_CLK_H__ +#define __SM1_AUDIO_CLK_H__ + +/* + * CLKID audio index values + */ +/* Gate En0 */ +#define CLKID_AUDIO_GATE_DDR_ARB 0 +#define CLKID_AUDIO_GATE_PDM 1 +#define CLKID_AUDIO_GATE_TDMINA 2 +#define CLKID_AUDIO_GATE_TDMINB 3 +#define CLKID_AUDIO_GATE_TDMINC 4 +#define CLKID_AUDIO_GATE_TDMINLB 5 +#define CLKID_AUDIO_GATE_TDMOUTA 6 +#define CLKID_AUDIO_GATE_TDMOUTB 7 +#define CLKID_AUDIO_GATE_TDMOUTC 8 +#define CLKID_AUDIO_GATE_FRDDRA 9 +#define CLKID_AUDIO_GATE_FRDDRB 10 +#define CLKID_AUDIO_GATE_FRDDRC 11 +#define CLKID_AUDIO_GATE_TODDRA 12 +#define CLKID_AUDIO_GATE_TODDRB 13 +#define CLKID_AUDIO_GATE_TODDRC 14 +#define CLKID_AUDIO_GATE_LOOPBACKA 15 +#define CLKID_AUDIO_GATE_SPDIFIN 16 +#define CLKID_AUDIO_GATE_SPDIFOUT_A 17 +#define CLKID_AUDIO_GATE_RESAMPLEA 18 +#define CLKID_AUDIO_GATE_RESERVED0 19 +#define CLKID_AUDIO_GATE_TORAM 20 +#define CLKID_AUDIO_GATE_SPDIFOUT_B 21 +#define CLKID_AUDIO_GATE_EQDRC 22 +#define CLKID_AUDIO_GATE_RESERVED1 23 +#define CLKID_AUDIO_GATE_RESERVED2 24 +#define CLKID_AUDIO_GATE_RESERVED3 25 +#define CLKID_AUDIO_GATE_RESAMPLEB 26 +#define CLKID_AUDIO_GATE_TOVAD 27 +#define CLKID_AUDIO_GATE_AUDIOLOCKER 28 +#define CLKID_AUDIO_GATE_SPDIFIN_LB 29 +#define CLKID_AUDIO_GATE_RESERVED4 30 +#define CLKID_AUDIO_GATE_RESERVED5 31 + +/* Gate En1 */ +#define CLKID_AUDIO_GATE_FRDDRD 32 +#define CLKID_AUDIO_GATE_TODDRD 33 +#define CLKID_AUDIO_GATE_LOOPBACKB 34 +#define CLKID_AUDIO_GATE_EARCRX 35 + +#define CLKID_AUDIO_GATE_MAX 36 + +#define MCLK_BASE CLKID_AUDIO_GATE_MAX +#define CLKID_AUDIO_MCLK_A (MCLK_BASE + 0) +#define CLKID_AUDIO_MCLK_B (MCLK_BASE + 1) +#define CLKID_AUDIO_MCLK_C (MCLK_BASE + 2) +#define CLKID_AUDIO_MCLK_D (MCLK_BASE + 3) +#define CLKID_AUDIO_MCLK_E (MCLK_BASE + 4) +#define CLKID_AUDIO_MCLK_F (MCLK_BASE + 5) + +#define CLKID_AUDIO_SPDIFIN (MCLK_BASE + 6) +#define CLKID_AUDIO_SPDIFOUT_A (MCLK_BASE + 7) +#define CLKID_AUDIO_RESAMPLE_A (MCLK_BASE + 8) +#define CLKID_AUDIO_LOCKER_OUT (MCLK_BASE + 9) +#define CLKID_AUDIO_LOCKER_IN (MCLK_BASE + 10) +#define CLKID_AUDIO_PDMIN0 (MCLK_BASE + 11) +#define CLKID_AUDIO_PDMIN1 (MCLK_BASE + 12) +#define CLKID_AUDIO_SPDIFOUT_B (MCLK_BASE + 13) +#define CLKID_AUDIO_RESAMPLE_B (MCLK_BASE + 14) +#define CLKID_AUDIO_SPDIFIN_LB (MCLK_BASE + 15) +#define CLKID_AUDIO_EQDRC (MCLK_BASE + 16) +#define CLKID_AUDIO_VAD (MCLK_BASE + 17) +#define CLKID_EARCTX_CMDC (MCLK_BASE + 18) +#define CLKID_EARCTX_DMAC (MCLK_BASE + 19) +#define CLKID_EARCRX_CMDC (MCLK_BASE + 20) +#define CLKID_EARCRX_DMAC (MCLK_BASE + 21) + +#define NUM_AUDIO_CLKS (MCLK_BASE + 22) +#endif /* __SM1_AUDIO_CLK_H__ */ diff --git a/include/dt-bindings/clock/amlogic,tm2-audio-clk.h b/include/dt-bindings/clock/amlogic,tm2-audio-clk.h new file mode 100644 index 000000000000..a70cf1ef636b --- /dev/null +++ b/include/dt-bindings/clock/amlogic,tm2-audio-clk.h @@ -0,0 +1,97 @@ +/* + * include/dt-bindings/clock/amlogic,tm2-audio-clk.h + * + * Copyright (C) 2018 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 __TM2_AUDIO_CLK_H__ +#define __TM2_AUDIO_CLK_H__ + +/* + * CLKID audio index values + */ + +#define CLKID_AUDIO_GATE_DDR_ARB 0 +#define CLKID_AUDIO_GATE_PDM 1 +#define CLKID_AUDIO_GATE_TDMINA 2 +#define CLKID_AUDIO_GATE_TDMINB 3 +#define CLKID_AUDIO_GATE_TDMINC 4 +#define CLKID_AUDIO_GATE_TDMINLB 5 +#define CLKID_AUDIO_GATE_TDMOUTA 6 +#define CLKID_AUDIO_GATE_TDMOUTB 7 +#define CLKID_AUDIO_GATE_TDMOUTC 8 +#define CLKID_AUDIO_GATE_FRDDRA 9 +#define CLKID_AUDIO_GATE_FRDDRB 10 +#define CLKID_AUDIO_GATE_FRDDRC 11 +#define CLKID_AUDIO_GATE_TODDRA 12 +#define CLKID_AUDIO_GATE_TODDRB 13 +#define CLKID_AUDIO_GATE_TODDRC 14 +#define CLKID_AUDIO_GATE_LOOPBACKA 15 +#define CLKID_AUDIO_GATE_SPDIFIN 16 +#define CLKID_AUDIO_GATE_SPDIFOUT_A 17 +#define CLKID_AUDIO_GATE_RESAMPLEA 18 +#define CLKID_AUDIO_GATE_RESERVED0 19 +#define CLKID_AUDIO_GATE_RESERVED1 20 +#define CLKID_AUDIO_GATE_SPDIFOUT_B 21 +#define CLKID_AUDIO_GATE_EQDRC 22 +#define CLKID_AUDIO_GATE_RESERVED2 23 +#define CLKID_AUDIO_GATE_RESERVED3 24 +#define CLKID_AUDIO_GATE_RESERVED4 25 +#define CLKID_AUDIO_GATE_RESAMPLEB 26 +#define CLKID_AUDIO_GATE_TOVAD 27 +#define CLKID_AUDIO_GATE_AUDIOLOCKER 28 +#define CLKID_AUDIO_GATE_SPDIFIN_LB 29 +#define CLKID_AUDIO_GATE_FRATV 30 +#define CLKID_AUDIO_GATE_FRHDMIRX 31 + +/* Gate En1 */ +#define CLKID_AUDIO_GATE_FRDDRD 32 +#define CLKID_AUDIO_GATE_TODDRD 33 +#define CLKID_AUDIO_GATE_LOOPBACKB 34 +#define CLKID_AUDIO_GATE_FRDDRE 35 +#define CLKID_AUDIO_GATE_TODDRE 36 +#define CLKID_AUDIO_GATE_EARCTX 37 +#define CLKID_AUDIO_GATE_EARCRX 38 +#define CLKID_AUDIO_GATE_RESAMPLEB_OLD 39 +#define CLKID_AUDIO_GATE_LOCKER 40 + +#define CLKID_AUDIO_GATE_MAX 41 + +#define MCLK_BASE CLKID_AUDIO_GATE_MAX +#define CLKID_AUDIO_MCLK_A (MCLK_BASE + 0) +#define CLKID_AUDIO_MCLK_B (MCLK_BASE + 1) +#define CLKID_AUDIO_MCLK_C (MCLK_BASE + 2) +#define CLKID_AUDIO_MCLK_D (MCLK_BASE + 3) +#define CLKID_AUDIO_MCLK_E (MCLK_BASE + 4) +#define CLKID_AUDIO_MCLK_F (MCLK_BASE + 5) + +#define CLKID_AUDIO_SPDIFIN (MCLK_BASE + 6) +#define CLKID_AUDIO_SPDIFOUT_A (MCLK_BASE + 7) +#define CLKID_AUDIO_RESAMPLE_A (MCLK_BASE + 8) +#define CLKID_AUDIO_LOCKER_OUT (MCLK_BASE + 9) +#define CLKID_AUDIO_LOCKER_IN (MCLK_BASE + 10) +#define CLKID_AUDIO_PDMIN0 (MCLK_BASE + 11) +#define CLKID_AUDIO_PDMIN1 (MCLK_BASE + 12) +#define CLKID_AUDIO_SPDIFOUT_B (MCLK_BASE + 13) +#define CLKID_AUDIO_RESAMPLE_B (MCLK_BASE + 14) +#define CLKID_AUDIO_SPDIFIN_LB (MCLK_BASE + 15) +#define CLKID_AUDIO_EQDRC (MCLK_BASE + 16) +#define CLKID_AUDIO_VAD (MCLK_BASE + 17) +#define CLKID_EARCTX_CMDC (MCLK_BASE + 18) +#define CLKID_EARCTX_DMAC (MCLK_BASE + 19) +#define CLKID_EARCRX_CMDC (MCLK_BASE + 20) +#define CLKID_EARCRX_DMAC (MCLK_BASE + 21) + +#define NUM_AUDIO_CLKS (MCLK_BASE + 22) +#endif /* __TM2_AUDIO_CLK_H__ */ diff --git a/include/dt-bindings/clock/meson8b-clkc.h b/include/dt-bindings/clock/meson8b-clkc.h index d507af316c57..deba850570c6 100644 --- a/include/dt-bindings/clock/meson8b-clkc.h +++ b/include/dt-bindings/clock/meson8b-clkc.h @@ -1,5 +1,18 @@ /* - * Meson8b clock tree IDs + * include/dt-bindings/clock/meson8b-clkc.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. + * */ /* diff --git a/include/dt-bindings/iio/adc/amlogic-saradc.h b/include/dt-bindings/iio/adc/amlogic-saradc.h index 7611426912af..5d3769ca452c 100644 --- a/include/dt-bindings/iio/adc/amlogic-saradc.h +++ b/include/dt-bindings/iio/adc/amlogic-saradc.h @@ -1,5 +1,18 @@ /* - * This header provides constants for configuring the AMLOGIC SAR ADC + * include/dt-bindings/iio/adc/amlogic-saradc.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 _DT_BINDINGS_IIO_ADC_AMLOGIC_H diff --git a/include/dt-bindings/input/meson_rc.h b/include/dt-bindings/input/meson_rc.h index c572dba2bb39..82646d537023 100644 --- a/include/dt-bindings/input/meson_rc.h +++ b/include/dt-bindings/input/meson_rc.h @@ -1,3 +1,19 @@ +/* + * include/dt-bindings/input/meson_rc.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 _DT_BINDINGS_INPUT_MESON_RC_H #define _DT_BINDINGS_INPUT_MESON_RC_H @@ -21,6 +37,7 @@ #define REMOTE_TYPE_XMP_1 0x03 #define REMOTE_TYPE_RC5 0x04 #define REMOTE_TYPE_RC6 0x05 +#define REMOTE_TYPE_TOSHIBA 0x06 /*hardware decode one protocol by using legacy IR controller*/ #define REMOTE_TYPE_LEGACY_NEC 0xff @@ -39,5 +56,8 @@ *2. multi-format IR controller decode other protocol */ #define REMOTE_TYPE_NEC_RC6 ((REMOTE_TYPE_LEGACY_NEC << 8) | REMOTE_TYPE_RC6) +#define REMOTE_TYPE_NEC_RC5 ((REMOTE_TYPE_LEGACY_NEC << 8) | REMOTE_TYPE_RC5) +#define REMOTE_TYPE_NEC_TOSHIBA ((REMOTE_TYPE_LEGACY_NEC << 8) | \ + REMOTE_TYPE_TOSHIBA) #endif diff --git a/include/linux/amlogic/aml_atvdemod.h b/include/linux/amlogic/aml_atvdemod.h index 29519f089d9e..ad6914aaa3d1 100644 --- a/include/linux/amlogic/aml_atvdemod.h +++ b/include/linux/amlogic/aml_atvdemod.h @@ -124,6 +124,7 @@ extern void aml_fe_get_atvaudio_state(int *state); /* For attach tuner driver start*/ enum tuner_type { + AM_TUNER_NONE = 0, AM_TUNER_SI2176 = 1, AM_TUNER_SI2196 = 2, AM_TUNER_FQ1216 = 3, diff --git a/include/linux/amlogic/aml_cma.h b/include/linux/amlogic/aml_cma.h index 4acb96ffb455..c4727220a133 100644 --- a/include/linux/amlogic/aml_cma.h +++ b/include/linux/amlogic/aml_cma.h @@ -74,6 +74,8 @@ extern bool cma_page(struct page *page); extern unsigned long get_cma_allocated(void); extern unsigned long get_total_cmapages(void); extern spinlock_t cma_iso_lock; +extern bool cma_first_wm_low; +extern int cma_debug_level; extern int aml_cma_alloc_range(unsigned long start, unsigned long end); extern void aml_cma_free(unsigned long pfn, unsigned int nr_pages); @@ -81,6 +83,7 @@ extern void aml_cma_free(unsigned long pfn, unsigned int nr_pages); extern unsigned long reclaim_clean_pages_from_list(struct zone *zone, struct list_head *page_list); +extern void show_page(struct page *page); unsigned long isolate_freepages_range(struct compact_control *cc, unsigned long start_pfn, unsigned long end_pfn); @@ -91,4 +94,14 @@ isolate_migratepages_range(struct compact_control *cc, struct page *compaction_cma_alloc(struct page *migratepage, unsigned long data, int **result); + +#define cma_debug(l, p, format, args...) \ + { \ + if (l < cma_debug_level) { \ + show_page(p); \ + pr_info("%s, %d "format, __func__, __LINE__, ##args); \ + } \ + } + + #endif /* __AMLOGIC_CMA_H__ */ diff --git a/include/linux/amlogic/aml_ddr_bandwidth.h b/include/linux/amlogic/aml_ddr_bandwidth.h index bde095b91e8a..42346db0c6ec 100644 --- a/include/linux/amlogic/aml_ddr_bandwidth.h +++ b/include/linux/amlogic/aml_ddr_bandwidth.h @@ -134,6 +134,7 @@ struct ddr_bandwidth { unsigned short real_ports; char busy; char mode; + char bytes_per_cycle; int mali_port[2]; unsigned int threshold; unsigned int irq_num; diff --git a/include/linux/amlogic/aml_sd_emmc_internal.h b/include/linux/amlogic/aml_sd_emmc_internal.h index a63caf11129f..e28f9c306129 100644 --- a/include/linux/amlogic/aml_sd_emmc_internal.h +++ b/include/linux/amlogic/aml_sd_emmc_internal.h @@ -16,8 +16,8 @@ */ #ifndef __AML_SD_EMMC_INTERNAL_H__ - #define __AML_SD_EMMC_INTERNAL_H__ + extern int aml_emmc_clktree_init(struct amlsd_host *host); extern int meson_mmc_clk_init_v3(struct amlsd_host *host); diff --git a/include/linux/amlogic/aml_sd_emmc_v3.h b/include/linux/amlogic/aml_sd_emmc_v3.h index 8e9d96e02562..de6dab799145 100644 --- a/include/linux/amlogic/aml_sd_emmc_v3.h +++ b/include/linux/amlogic/aml_sd_emmc_v3.h @@ -29,15 +29,14 @@ irqreturn_t meson_mmc_irq_thread_v3(int irq, void *dev_id); int aml_post_hs400_timming(struct mmc_host *mmc); -/* extern ssize_t emmc_eyetest_show(struct device *dev, - * struct device_attribute *attr, char *buf); - */ +extern ssize_t emmc_eyetest_show(struct device *dev, + struct device_attribute *attr, char *buf); -/* extern ssize_t emmc_clktest_show(struct device *dev, - * struct device_attribute *attr, char *buf); - */ -/* DEVICE_ATTR(emmc_eyetest, S_IRUGO, emmc_eyetest_show, NULL);*/ -/*DEVICE_ATTR(emmc_clktest, S_IRUGO, emmc_clktest_show, NULL);*/ +extern ssize_t emmc_clktest_show(struct device *dev, + struct device_attribute *attr, char *buf); + +DEVICE_ATTR(emmc_eyetest, 0444, emmc_eyetest_show, NULL); +DEVICE_ATTR(emmc_clktest, 0444, emmc_clktest_show, NULL); #endif diff --git a/include/linux/amlogic/cpu_version.h b/include/linux/amlogic/cpu_version.h index 3aef138e0a6a..4cef9e0bf195 100644 --- a/include/linux/amlogic/cpu_version.h +++ b/include/linux/amlogic/cpu_version.h @@ -15,6 +15,9 @@ * */ +/* + * All of these api should be call after early_initcall stage + */ #ifndef __PLAT_MESON_CPU_H #define __PLAT_MESON_CPU_H @@ -31,8 +34,10 @@ #define MESON_CPU_MAJOR_ID_G12A 0x28 #define MESON_CPU_MAJOR_ID_G12B 0x29 +#define MESON_CPU_MAJOR_ID_SM1 0x2B #define MESON_CPU_MAJOR_ID_TL1 0x2E +#define MESON_CPU_MAJOR_ID_TM2 0x2F #define MESON_CPU_VERSION_LVL_MAJOR 0 #define MESON_CPU_VERSION_LVL_MINOR 1 @@ -150,6 +155,11 @@ static inline bool is_meson_txl_cpu(void) return get_cpu_type() == MESON_CPU_MAJOR_ID_TXL; } +static inline bool is_meson_txl_package_950(void) +{ + return is_meson_txl_cpu() && package_id_is(0x20); +} + static inline bool is_meson_txlx_cpu(void) { return get_cpu_type() == MESON_CPU_MAJOR_ID_TXLX; @@ -185,6 +195,15 @@ static inline bool is_meson_tl1_cpu(void) return get_cpu_type() == MESON_CPU_MAJOR_ID_TL1; } +static inline bool is_meson_sm1_cpu(void) +{ + return get_cpu_type() == MESON_CPU_MAJOR_ID_SM1; +} +static inline bool is_meson_tm2_cpu(void) +{ + return get_cpu_type() == MESON_CPU_MAJOR_ID_TM2; +} + static inline bool cpu_after_eq(unsigned int id) { return get_cpu_type() >= id; @@ -199,4 +218,20 @@ static inline bool is_meson_txlx_package_962E(void) { return is_meson_txlx_cpu() && package_id_is(0x20); } + +static inline bool is_meson_rev_a(void) +{ + return (get_meson_cpu_version(MESON_CPU_VERSION_LVL_MINOR) == 0xA); +} + +static inline bool is_meson_rev_b(void) +{ + return (get_meson_cpu_version(MESON_CPU_VERSION_LVL_MINOR) == 0xB); +} + +static inline bool is_meson_rev_c(void) +{ + return (get_meson_cpu_version(MESON_CPU_VERSION_LVL_MINOR) == 0xC); +} + #endif diff --git a/include/linux/amlogic/cpucore_cooling.h b/include/linux/amlogic/cpucore_cooling.h index 9039455b0d55..439974131761 100644 --- a/include/linux/amlogic/cpucore_cooling.h +++ b/include/linux/amlogic/cpucore_cooling.h @@ -20,6 +20,9 @@ #include #include + +#define MAX_CLUSTER 2 +#define CLUSTER_FLAG 0xF struct cpucore_cooling_device { int id; struct thermal_cooling_device *cool_dev; @@ -29,6 +32,7 @@ struct cpucore_cooling_device { int max_cpu_core_num; int cluster_id; int stop_flag; + int core_num[MAX_CLUSTER]; }; #define CPU_STOP 0x80000000 #ifdef CONFIG_AMLOGIC_CPUCORE_THERMAL diff --git a/include/linux/amlogic/debug_ftrace_ramoops.h b/include/linux/amlogic/debug_ftrace_ramoops.h new file mode 100644 index 000000000000..fa6d4c4921e9 --- /dev/null +++ b/include/linux/amlogic/debug_ftrace_ramoops.h @@ -0,0 +1,65 @@ +/* + * include/linux/amlogic/debug_ftrace_ramoops.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 __DEBUG_FTRACE_RAMOOPS_H__ +#define __DEBUG_FTRACE_RAMOOPS_H__ +#define __DEBUG_FTRACE_RAMOOPS_H__ +#include + +extern unsigned int ramoops_ftrace_en; +extern int ramoops_io_en; +extern unsigned int dump_iomap; + +#define PSTORE_FLAG_FUNC 0x1 +#define PSTORE_FLAG_IO_R 0x2 +#define PSTORE_FLAG_IO_W 0x3 +#define PSTORE_FLAG_IO_R_END 0x4 +#define PSTORE_FLAG_IO_W_END 0x5 +#define PSTORE_FLAG_IO_MAX 0x6 +#define PSTORE_FLAG_MASK 0xF + +void notrace pstore_io_save(unsigned long reg, unsigned long val, + unsigned long parant, unsigned int flag, + unsigned long *irq_flag); + +//#define SKIP_IO_TRACE +#if (defined CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE) && (!defined SKIP_IO_TRACE) +#define pstore_ftrace_io_wr(reg, val) \ +unsigned long irqflg; \ +pstore_io_save(reg, val, CALLER_ADDR0, PSTORE_FLAG_IO_W, &irqflg) + +#define pstore_ftrace_io_wr_end(reg, val) \ +pstore_io_save(reg, 0, CALLER_ADDR0, PSTORE_FLAG_IO_W_END, &irqflg) + +#define pstore_ftrace_io_rd(reg) \ +unsigned long irqflg; \ +pstore_io_save(reg, 0, CALLER_ADDR0, PSTORE_FLAG_IO_R, &irqflg) +#define pstore_ftrace_io_rd_end(reg) \ +pstore_io_save(reg, 0, CALLER_ADDR0, PSTORE_FLAG_IO_R_END, &irqflg) + +#define need_dump_iomap() (ramoops_io_en | dump_iomap) + +#else +#define pstore_ftrace_io_wr(reg, val) do { } while (0) +#define pstore_ftrace_io_rd(reg) do { } while (0) +#define need_dump_iomap() 0 +#define pstore_ftrace_io_wr_end(reg, val) do { } while (0) +#define pstore_ftrace_io_rd_end(reg) do { } while (0) + +#endif + +#endif diff --git a/include/linux/amlogic/debug_lockup.h b/include/linux/amlogic/debug_lockup.h index 353e71cae8c7..24c0f55e6afd 100644 --- a/include/linux/amlogic/debug_lockup.h +++ b/include/linux/amlogic/debug_lockup.h @@ -1,3 +1,20 @@ +/* + * include/linux/amlogic/debug_lockup.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 __debug_lockup_h_ #define __debug_lockup_h_ diff --git a/include/linux/amlogic/dhd_buf.h b/include/linux/amlogic/dhd_buf.h index 9822f5a1a80c..7ba9de6ec668 100644 --- a/include/linux/amlogic/dhd_buf.h +++ b/include/linux/amlogic/dhd_buf.h @@ -1,3 +1,20 @@ +/* + * include/linux/amlogic/dhd_buf.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 _BCMDHD_BUF_H #define _BCMDHD_BUF_H int bcmdhd_init_wlan_mem(void); diff --git a/include/linux/amlogic/iomap.h b/include/linux/amlogic/iomap.h index 41d885badb9a..663ad76e8777 100644 --- a/include/linux/amlogic/iomap.h +++ b/include/linux/amlogic/iomap.h @@ -26,8 +26,9 @@ enum{ IO_HIUBUS_BASE, IO_BUS_MAX, }; -extern int aml_reg_read(u32 bus_type, unsigned int reg, unsigned int *val); -extern int aml_reg_write(u32 bus_type, unsigned int reg, unsigned int val); + +extern inline int aml_reg_read(u32 bus_type, u32 reg, u32 *val); +extern inline int aml_reg_write(u32 bus_type, u32 reg, u32 val); extern int aml_regmap_update_bits(u32 bus_type, unsigned int reg, unsigned int mask, unsigned int val); diff --git a/include/linux/amlogic/irblaster.h b/include/linux/amlogic/irblaster.h new file mode 100644 index 000000000000..b9cbf432ef5e --- /dev/null +++ b/include/linux/amlogic/irblaster.h @@ -0,0 +1,121 @@ +/* + * include/linux/amlogic/irblaster.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 __LINUX_IRBLASTER_H +#define __LINUX_IRBLASTER_H + +#include +#include +#include +#ifdef CONFIG_AMLOGIC_IRBLASTER_PROTOCOL +#include +#endif + +#define MAX_PLUSE 256 +#define PS_SIZE 10 + +struct irblaster_chip; + +static DEFINE_MUTEX(irblaster_lock); +static LIST_HEAD(irblaster_chips); + +/** + * enum irblaster_idle - Whether the controller is occupied + * @IRBLASTER_EXPORTED: Controlled by the sysfs sys/class/irblaster + * @IRBLASTER_REQUESTED: Controlled by consumer driver + */ +enum irblaster_idle { + IRBLASTER_EXPORTED, + IRBLASTER_REQUESTED +}; + +/** + * struct irblaster_ops - irblaster controller operations + * @send: send raw level data + * @send_key: send key according to the protocol + * @set_freq: set irblaster freq + * @get_freq: get irblaster freq + * @set_duty: set irblaster duty + * @get_duty: get irblaster duty + */ +struct irblaster_ops { + int (*send)(struct irblaster_chip *chip, + unsigned int *data, unsigned int len); +#ifdef CONFIG_AMLOGIC_IRBLASTER_PROTOCOL + int (*send_key)(struct irblaster_chip *chip, + unsigned int addr, int commmand); + /* int (*set_protocol)(struct irblaster_chip *chip, */ + /* enum irblaster_protocol protocol);*/ +#endif + int (*set_freq)(struct irblaster_chip *chip, unsigned int freq); + unsigned int (*get_freq)(struct irblaster_chip *chip); + int (*set_duty)(struct irblaster_chip *chip, unsigned int duty); + unsigned int (*get_duty)(struct irblaster_chip *chip); +}; + +struct irblaster_state { + unsigned int freq; + unsigned int duty; + int enabled; + int idle; +#ifdef CONFIG_AMLOGIC_IRBLASTER_PROTOCOL + enum irblaster_protocol protocol; +#endif +}; + +/** + * struct irblaster_chip - abstract a irblaster controller + * @dev: device providing the irblaster + * @list: list node for internal use + * @ops: callbacks for this irblaster controller + * @base: number of first irblaster controlled by this chip + * @of_irblaster_n_cells: number of cells expected in the device tree + * irblaster specifier + * @state: irblaster controller status + * @buffer: data + * @buffer_len: data len + * @sum_time: total time + * @request: whether the controller is occupied + */ +struct irblaster_chip { + struct device *dev; + struct list_head list; + struct irblaster_ops *ops; +#ifdef CONFIG_AMLOGIC_IRBLASTER_PROTOCOL + struct irblaster_raw_handler *protocol; +#endif + struct irblaster_state state; + struct mutex sys_lock; /* use to sysfs */ + unsigned int base; + unsigned int of_irblaster_n_cells; + /* unsigned int buffer[MAX_PLUSE]; */ + unsigned int *buffer; + unsigned int buffer_len; + unsigned int sum_time; + atomic_t request; +}; + +/* irblaster sysfs APIs */ +void irblasterchip_sysfs_export(struct irblaster_chip *chip); +void irblasterchip_sysfs_unexport(struct irblaster_chip *chip); + +/* irblaster provider APIs */ +int irblasterchip_add(struct irblaster_chip *chip); +int irblasterchip_remove(struct irblaster_chip *chip); +void irblaster_chip_data_clear(struct irblaster_chip *chip); + +#endif /* __LINUX_IRBLASTER_H */ diff --git a/include/linux/amlogic/irblaster_consumer.h b/include/linux/amlogic/irblaster_consumer.h new file mode 100644 index 000000000000..48f65330f247 --- /dev/null +++ b/include/linux/amlogic/irblaster_consumer.h @@ -0,0 +1,55 @@ +/* + * include/linux/amlogic/irblaster_consumer.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 __LINUX_IRBLASTER_CONSUMER_H +#define __LINUX_IRBLASTER_CONSUMER_H + +#include +#include +#include +#ifdef CONFIG_AMLOGIC_IRBLASTER_PROTOCOL +#include +#endif + +struct irblaster_chip; + +/* irblaster user APIs */ +int irblaster_send(struct irblaster_chip *chip, + unsigned int *data, + unsigned int len); +int irblaster_set_freq(struct irblaster_chip *chip, + unsigned int freq); +unsigned int irblaster_get_freq(struct irblaster_chip *chip); +int irblaster_set_duty(struct irblaster_chip *chip, unsigned int duty); +unsigned int irblaster_get_duty(struct irblaster_chip *chip); +struct irblaster_chip *of_irblaster_get(struct device_node *np, + const char *con_id); +struct irblaster_chip *devm_of_irblaster_get(struct device *dev, + struct device_node *np, + const char *con_id); +void irblaster_put(struct irblaster_chip *chip); + +#ifdef CONFIG_AMLOGIC_IRBLASTER_PROTOCOL +int irblaster_send_key(struct irblaster_chip *chip, + unsigned int addr, + unsigned int commmand); +int irblaster_set_protocol(struct irblaster_chip *chip, + enum irblaster_protocol ir_protocol); +enum irblaster_protocol irblaster_get_protocol(struct irblaster_chip *chip); +#endif + +#endif /* __LINUX_IRBLASTER_CONSUMER_H */ diff --git a/include/linux/amlogic/irblaster_encoder.h b/include/linux/amlogic/irblaster_encoder.h new file mode 100644 index 000000000000..db0642f0fac4 --- /dev/null +++ b/include/linux/amlogic/irblaster_encoder.h @@ -0,0 +1,97 @@ +/* + * include/linux/amlogic/irblaster_encoder.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 __LINUX_ENCODER_H +#define __LINUX_ENCODER_H + +#include +#include +#include + +struct irblaster_chip; +int irblaster_send(struct irblaster_chip *chip, unsigned int *data, + unsigned int len); + +static DEFINE_MUTEX(irblaster_raw_handler_lock); +static LIST_HEAD(irblaster_raw_handler_list); + +/** + * enum irblaster_protocol - protocol of irblaster + * add a new protocol here + * @IRBLASTER_PROTOCOL_MAX: Maximum number of support protocol + * please add a new protocol before this + */ +enum irblaster_protocol { + IRBLASTER_PROTOCOL_NEC, + IRBLASTER_PROTOCOL_NECX, + IRBLASTER_PROTOCOL_NEC32, + IRBLASTER_PROTOCOL_RCA, + IRBLASTER_PROTOCOL_MAX +}; + +#define IRBLASTER_PROTOCOL_BIT_NEC BIT_ULL(IRBLASTER_PROTOCOL_NEC) +#define IRBLASTER_PROTOCOL_BIT_NECX BIT_ULL(IRBLASTER_PROTOCOL_NECX) +#define IRBLASTER_PROTOCOL_BIT_NEC32 BIT_ULL(IRBLASTER_PROTOCOL_NEC32) +#define IRBLASTER_PROTOCOL_BIT_RCA BIT_ULL(IRBLASTER_PROTOCOL_RCA) + +/** + * struct irblaster_raw_timings - pulse-length modulation timings + * @header_pulse: duration of header pulse in ns (0 for none) + * @bit_space: duration of bit space in ns + * @bit_pulse: duration of bit pulse (for logic 0 and 1) in ns + * @trailer_space: duration of trailer space in ns + * @msb_first: 1 if most significant bit is sent first + * @raw_nbits: raw bit len + * @data_size: the total length of the array + */ +struct irblaster_raw_timings { + unsigned int header_pulse; + unsigned int header_space; + unsigned int bit_pulse; + unsigned int bit_space[2]; + unsigned int trailer_pulse; + unsigned int trailer_space; + unsigned int msb_first:1; + unsigned int raw_nbits; + unsigned int data_size; +}; + +struct irblaster_raw_handler { + struct list_head list; + char *name; + int protocol; /* which are handled by this handler */ + int (*encode)(enum irblaster_protocol protocol, unsigned int addr, + unsigned int commmand, unsigned int *data); + struct irblaster_raw_timings *timing; + struct mutex encode_lock; /* use to function encode */ + u32 freq; + u32 duty; +}; + +/* irblaster encode APIs */ +int irblaster_raw_handler_register(struct irblaster_raw_handler + *ir_raw_handler); +void irblaster_raw_handler_unregister(struct irblaster_raw_handler + *ir_raw_handler); +int irblaster_raw_gen(unsigned int *data, + const struct irblaster_raw_timings *timings, + u32 raw); + +unsigned int protocol_store_select(const char *buf); +unsigned int protocol_show_select(struct irblaster_chip *chip, char *buf); + +#endif /* __LINUX_ENCODER_H */ diff --git a/include/linux/amlogic/major.h b/include/linux/amlogic/major.h index 1ce50430bb88..dbdf49510892 100644 --- a/include/linux/amlogic/major.h +++ b/include/linux/amlogic/major.h @@ -30,6 +30,7 @@ #define VFM_MAJOR (14+(AML_BASE)) #define IONVIDEO_MAJOR (15+(AML_BASE)) #define VAD_MAJOR (16+(AML_BASE)) +#define VIDEOSYNC_MAJOR (17+(AML_BASE)) /* *#define UIO_MAJOR 4+(AML_BASE) *#define USB_DEV_EP_MAJOR 5+(AML_BASE) diff --git a/include/linux/amlogic/media/amdolbyvision/dolby_vision.h b/include/linux/amlogic/media/amdolbyvision/dolby_vision.h index 370c01000bf2..59ba5231a739 100644 --- a/include/linux/amlogic/media/amdolbyvision/dolby_vision.h +++ b/include/linux/amlogic/media/amdolbyvision/dolby_vision.h @@ -1,3 +1,20 @@ +/* + * include/linux/amlogic/media/amdolbyvision/dolby_vision.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 _DV_H_ #define _DV_H_ @@ -31,9 +48,14 @@ extern int dolby_vision_update_setting(void); extern bool is_dolby_vision_stb_mode(void); extern bool is_meson_g12(void); extern bool is_meson_gxm(void); +extern bool is_meson_box(void); extern bool is_meson_txlx(void); extern bool is_meson_txlx_tvmode(void); extern bool is_meson_txlx_stbmode(void); +extern bool is_meson_tm2(void); +extern bool is_meson_tm2_tvmode(void); +extern bool is_meson_tm2_stbmode(void); +extern bool is_meson_tvmode(void); extern void tv_dolby_vision_crc_clear(int flag); extern char *tv_dolby_vision_get_crc(u32 *len); extern void tv_dolby_vision_insert_crc(bool print); diff --git a/include/linux/amlogic/media/amprime_sl/prime_sl.h b/include/linux/amlogic/media/amprime_sl/prime_sl.h new file mode 100644 index 000000000000..76bf489d3d4d --- /dev/null +++ b/include/linux/amlogic/media/amprime_sl/prime_sl.h @@ -0,0 +1,26 @@ +/* + * include/linux/amlogic/media/amprime_sl/prime_sl.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 _PRIMSE_SL_H_ +#define _PRIMSE_SL_H_ + +#include + +extern void prime_sl_process(struct vframe_s *vf); +extern bool is_dolby_vision_enable(void); + +#endif diff --git a/include/linux/amlogic/media/amvecm/amvecm.h b/include/linux/amlogic/media/amvecm/amvecm.h index 59e88fe6c5e2..1f8492bbb27c 100644 --- a/include/linux/amlogic/media/amvecm/amvecm.h +++ b/include/linux/amlogic/media/amvecm/amvecm.h @@ -32,7 +32,7 @@ #define FLAG_VADJ1_COLOR (1 << 30) #define FLAG_VE_DNLP (1 << 29) #define FLAG_VE_NEW_DNLP (1 << 28) -#define FLAG_RSV27 (1 << 27) +#define FLAG_VE_LC_CURV (1 << 27) #define FLAG_RSV26 (1 << 26) #define FLAG_3D_BLACK_DIS (1 << 25) #define FLAG_3D_BLACK_EN (1 << 24) @@ -135,9 +135,6 @@ enum pq_table_name_e { TABLE_NAME_MAX, }; -/*check pq_table length copy_from_user*/ -#define PQ_TABLE_MAX_LENGTH 10000 - #define _VE_CM 'C' #define AMVECM_IOC_G_HIST_AVG _IOW(_VE_CM, 0x22, struct ve_hist_s) @@ -146,12 +143,12 @@ enum pq_table_name_e { #define AMVECM_IOC_VE_NEW_DNLP _IOW(_VE_CM, 0x25, struct ve_dnlp_curve_param_s) #define AMVECM_IOC_G_HIST_BIN _IOW(_VE_CM, 0x26, struct vpp_hist_param_s) #define AMVECM_IOC_G_HDR_METADATA _IOW(_VE_CM, 0x27, struct hdr_metadata_info_s) - +/*vpp get color primary*/ +#define AMVECM_IOC_G_COLOR_PRI _IOR(_VE_CM, 0x28, enum color_primary_e) /* VPP.CM IOCTL command list */ #define AMVECM_IOC_LOAD_REG _IOW(_VE_CM, 0x30, struct am_regs_s) - /* VPP.GAMMA IOCTL command list */ #define AMVECM_IOC_GAMMA_TABLE_EN _IO(_VE_CM, 0x40) #define AMVECM_IOC_GAMMA_TABLE_DIS _IO(_VE_CM, 0x41) @@ -214,6 +211,15 @@ enum pc_mode_e { #define AMVECM_IOC_G_PIC_MODE _IOR(_VE_CM, 0x59, struct am_vdj_mode_s) #define AMVECM_IOC_S_PIC_MODE _IOW(_VE_CM, 0x60, struct am_vdj_mode_s) + +/*HDR TYPE command list*/ +#define AMVECM_IOC_G_HDR_TYPE _IOR(_VE_CM, 0x61, enum hdr_type_e) + + +/*Local contrast command list*/ +#define AMVECM_IOC_S_LC_CURVE _IOW(_VE_CM, 0x62, struct ve_lc_curve_parm_s) + + struct am_vdj_mode_s { int flag; int brightness; @@ -224,6 +230,14 @@ struct am_vdj_mode_s { int contrast2; }; +enum color_primary_e { + VPP_COLOR_PRI_NULL = 0, + VPP_COLOR_PRI_BT601, + VPP_COLOR_PRI_BT709, + VPP_COLOR_PRI_BT2020, + VPP_COLOR_PRI_MAX, +}; + enum vpp_matrix_csc_e { VPP_MATRIX_NULL = 0, VPP_MATRIX_RGB_YUV601 = 0x1, @@ -255,6 +269,14 @@ enum vpp_matrix_csc_e { VPP_MATRIX_DEFAULT_CSCTYPE = 0xffff, }; +enum hdr_type_e { + HDRTYPE_NONE = 0, + HDRTYPE_SDR = 0x1, + HDRTYPE_HDR10 = 0x2, + HDRTYPE_HLG = 0x4, + HDRTYPE_MAX, +}; + enum vpp_transfer_characteristic_e { VPP_ST_NULL = 0, VPP_ST709 = 0x1, @@ -284,14 +306,49 @@ enum ve_source_input_e { SOURCE_MAX, }; +/*pq_timing: + *SD/HD/FHD/UHD for DTV/MEPG, + *NTST_M/NTST_443/PAL_I/PAL_M/PAL_60/PAL_CN/SECAM/NTST_50 for AV/ATV + */ enum ve_pq_timing_e { TIMING_SD = 0, TIMING_HD, TIMING_FHD, TIMING_UHD, + TIMING_NTST_M, + TIMING_NTST_443, + TIMING_PAL_I, + TIMING_PAL_M, + TIMING_PAL_60, + TIMING_PAL_CN, + TIMING_SECAM, + TIMING_NTSC_50, TIMING_MAX, }; +enum vlock_hw_ver_e { + /*gxtvbb*/ + vlock_hw_org, + /* + *txl + *txlx + */ + vlock_hw_ver1, + /* tl1 later + * fix bug:i problem + * fix bug:affect ss function + * add: phase lock + */ + vlock_hw_ver2, +}; + +struct vecm_match_data_s { + u32 vlk_support; + u32 vlk_new_fsm; + enum vlock_hw_ver_e vlk_hwver; + u32 vlk_phlock_en; +}; + /*overscan: *length 0~31bit :number of crop; *src_timing: bit31: on: load/save all crop @@ -354,7 +411,6 @@ struct am_pq_parm_s { /* READ_CBUS_REG_BITS(x,start,length) */ /* #endif */ - static inline void WRITE_VPP_REG(uint32_t reg, const uint32_t value) { @@ -389,7 +445,10 @@ static inline uint32_t READ_VPP_REG_BITS(uint32_t reg, extern signed int vd1_brightness, vd1_contrast; extern bool gamma_en; -extern unsigned int hdr_source_type; + +extern unsigned int atv_source_flg; + +extern enum hdr_type_e hdr_source_type; #define CSC_FLAG_TOGGLE_FRAME 1 #define CSC_FLAG_CHECK_OUTPUT 2 @@ -415,11 +474,11 @@ struct hdr_metadata_info_s { extern void vpp_vd_adj1_saturation_hue(signed int sat_val, signed int hue_val, struct vframe_s *vf); extern void amvecm_sharpness_enable(int sel); - extern int metadata_read_u32(uint32_t *value); extern int metadata_wait(struct vframe_s *vf); extern int metadata_sync(uint32_t frame_id, uint64_t pts); extern void amvecm_wakeup_queue(void); +extern void lc_load_curve(struct ve_lc_curve_parm_s *p); #ifndef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA #define VSYNC_WR_MPEG_REG(adr, val) WRITE_VPP_REG(adr, val) diff --git a/include/linux/amlogic/media/amvecm/ve.h b/include/linux/amlogic/media/amvecm/ve.h index b891d3a6d550..9ddb492a49e0 100644 --- a/include/linux/amlogic/media/amvecm/ve.h +++ b/include/linux/amlogic/media/amvecm/ve.h @@ -53,6 +53,16 @@ struct ve_bext_s { unsigned char slope2; }; #if defined(CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM) +#define DNLP_SCURV_LEN 65 +#define GAIN_VAR_LUT_LEN 49 +#define WEXT_GAIN_LEN 48 +#define ADP_THRD_LEN 33 +#define REG_BLK_BOOST_LEN 13 +#define REG_ADP_OFSET_LEN 20 +#define REG_MONO_PROT_LEN 6 +#define TREND_WHT_EXP_LUT_LEN 9 +#define DNLP_PARM_MAX_NUM 100 +#define DNLP_VPP_HIST_BIN_NUM 64 struct ve_dnlp_s { unsigned int en; unsigned int rt; /* 0 ~ 255, */ @@ -71,17 +81,22 @@ struct vpp_hist_param_s { unsigned int vpp_hist_pow; unsigned int vpp_luma_sum; unsigned int vpp_pixel_sum; - unsigned short vpp_histgram[64]; + unsigned short vpp_histgram[DNLP_VPP_HIST_BIN_NUM]; }; struct ve_dnlp_curve_param_s { - unsigned int ve_dnlp_scurv_low[65]; - unsigned int ve_dnlp_scurv_mid1[65]; - unsigned int ve_dnlp_scurv_mid2[65]; - unsigned int ve_dnlp_scurv_hgh1[65]; - unsigned int ve_dnlp_scurv_hgh2[65]; - unsigned int ve_gain_var_lut49[49]; - unsigned int ve_wext_gain[48]; - unsigned int param[100]; + unsigned int ve_dnlp_scurv_low[DNLP_SCURV_LEN]; + unsigned int ve_dnlp_scurv_mid1[DNLP_SCURV_LEN]; + unsigned int ve_dnlp_scurv_mid2[DNLP_SCURV_LEN]; + unsigned int ve_dnlp_scurv_hgh1[DNLP_SCURV_LEN]; + unsigned int ve_dnlp_scurv_hgh2[DNLP_SCURV_LEN]; + unsigned int ve_gain_var_lut49[GAIN_VAR_LUT_LEN]; + unsigned int ve_wext_gain[WEXT_GAIN_LEN]; + unsigned int ve_adp_thrd[ADP_THRD_LEN]; + unsigned int ve_reg_blk_boost_12[REG_BLK_BOOST_LEN]; + unsigned int ve_reg_adp_ofset_20[REG_ADP_OFSET_LEN]; + unsigned int ve_reg_mono_protect[REG_MONO_PROT_LEN]; + unsigned int ve_reg_trend_wht_expand_lut8[TREND_WHT_EXP_LUT_LEN]; + unsigned int param[DNLP_PARM_MAX_NUM]; }; enum dnlp_param_e { ve_dnlp_enable = 0, @@ -141,6 +156,26 @@ enum dnlp_param_e { ve_dnlp_scurv_hgh1_th, ve_dnlp_scurv_hgh2_th, ve_dnlp_mtdrate_adp_en, + ve_dnlp_clahe_method, + ve_dnlp_ble_en, + ve_dnlp_norm, + ve_dnlp_scn_chg_th, + ve_dnlp_step_th, + ve_dnlp_iir_step_mux, + ve_dnlp_single_bin_bw, + ve_dnlp_single_bin_method, + ve_dnlp_reg_max_slop_1st, + ve_dnlp_reg_max_slop_mid, + ve_dnlp_reg_max_slop_fin, + ve_dnlp_reg_min_slop_1st, + ve_dnlp_reg_min_slop_mid, + ve_dnlp_reg_min_slop_fin, + ve_dnlp_reg_trend_wht_expand_mode, + ve_dnlp_reg_trend_blk_expand_mode, + ve_dnlp_ve_hist_cur_gain, + ve_dnlp_ve_hist_cur_gain_precise, + ve_dnlp_reg_mono_binrang_st, + ve_dnlp_reg_mono_binrang_ed, ve_dnlp_param_max, }; enum dnlp_curve_e { @@ -151,6 +186,11 @@ enum dnlp_curve_e { ve_scurv_hgh2, ve_curv_var_lut49, ve_curv_wext_gain, + ve_adp_thrd = 1013, + ve_reg_blk_boost_12, + ve_reg_adp_ofset_20, + ve_reg_mono_protect, + ve_reg_trend_wht_expand_lut8, }; #else struct ve_dnlp_s { @@ -159,6 +199,24 @@ struct ve_dnlp_s { unsigned char gamma[64]; }; #endif + +struct ve_lc_curve_parm_s { + unsigned int ve_lc_saturation[63]; + unsigned int ve_lc_yminval_lmt[12]; + unsigned int ve_lc_ypkbv_ymaxval_lmt[12]; + unsigned int ve_lc_ypkbv_ratio[4]; + unsigned int param[100]; +}; + +enum lc_alg_param_e { + lc_dbg_parm0 = 0, + lc_dbg_parm1, + lc_dbg_parm2, + lc_dbg_parm3, + lc_dbg_parm4, + lc_dbg_parm_max, +}; + struct ve_hsvs_s { unsigned char en; unsigned char peak_gain_h1; diff --git a/include/linux/amlogic/media/codec_mm/codec_mm_scatter.h b/include/linux/amlogic/media/codec_mm/codec_mm_scatter.h index 5a84e3c3a0c8..fa6d73a2f980 100644 --- a/include/linux/amlogic/media/codec_mm/codec_mm_scatter.h +++ b/include/linux/amlogic/media/codec_mm/codec_mm_scatter.h @@ -47,6 +47,53 @@ struct codec_mm_scatter { struct list_head list; /*hold list. */ }; +enum e_mmu_free_status { + MMU_FREE_START, + MMU_FREE_START_LOCK, + MMU_FREE_SCATTER_START, + MMU_FREE_SCATTER_START_LOCK, + MMU_FREE_SCATTER_START_DTS, + MMU_FREE_SCATTER_START_DTS_LOCK, + MMU_FREE_SCATTER_START_SMGT, + MMU_FREE_SCATTER_START_SMGT_LOCK, + MMU_FREE_SCATTER_START_SMGT_LOCK_DONE, + MMU_FREE_SCATTER_START_DTS_LOCK_DONE, + MMU_FREE_SCATTER_START_LOCK_DONE, + MMU_FREE_START_LOCK_DONE, +}; + +enum e_mmu_alloc_status { + MMU_ALLOC_START, + MMU_ALLOC_START_LOCK, + MMU_ALLOC_SCATTER_START, + MMU_ALLOC_SCATTER_START_LOCK, + MMU_ALLOC_SCATTER_START_LOCK_DONE, + MMU_ALLOC_SCATTER_ALLOC_NEW, + MMU_ALLOC_SCATTER_ALLOC_NEW_END, + MMU_ALLOC_SCATTER_ALLOC_WANT_PAGE_IN, + MMU_ALLOC_SCATTER_LOCK, + MMU_ALLOC_SCATTER_LOCK_END, + MMU_ALLOC_from_cache_scatter, + MMU_ALLOC_from_cache_scatter_1, + MMU_ALLOC_from_cache_scatter_2, + MMU_ALLOC_from_cache_scatter_3, + MMU_ALLOC_from_cache_scatter_4, + MMU_ALLOC_from_cache_scatter_5, + MMU_ALLOC_from_cache_scatter_end, + MMU_ALLOC_from_free_scatter, + MMU_ALLOC_from_free_scatter_end, + MMU_ALLOC_from_slot, + MMU_ALLOC_from_slot_end, + MMU_ALLOC_LIST_LOCK_START, + MMU_ALLOC_LIST_LOCK, + MMU_ALLOC_LIST_LOCK_END, + MMU_ALLOC_SCATTER_ALLOC_WANT_PAGE_IN_END, + MMU_ALLOC_SCATTER_ALLOC_WANT_PAGE_IN_2, + MMU_ALLOC_SCATTER_ALLOC_WANT_PAGE_IN_2_END, + MMU_ALLOC_START_LOCK_DONE, +}; + + int codec_mm_scatter_free_all_pages(struct codec_mm_scatter *mms); int codec_mm_scatter_free_tail_pages(struct codec_mm_scatter *mms, diff --git a/include/linux/amlogic/media/frame_provider/tvin/tvin.h b/include/linux/amlogic/media/frame_provider/tvin/tvin.h index 3fa257f72802..fe41e165f1e6 100644 --- a/include/linux/amlogic/media/frame_provider/tvin/tvin.h +++ b/include/linux/amlogic/media/frame_provider/tvin/tvin.h @@ -64,11 +64,13 @@ enum tvin_port_e { TVIN_PORT_VIU1_WB0_VD2, TVIN_PORT_VIU1_WB0_OSD1, TVIN_PORT_VIU1_WB0_OSD2, + TVIN_PORT_VIU1_WB0_VPP, TVIN_PORT_VIU1_WB0_POST_BLEND, TVIN_PORT_VIU1_WB1_VD1, TVIN_PORT_VIU1_WB1_VD2, TVIN_PORT_VIU1_WB1_OSD1, TVIN_PORT_VIU1_WB1_OSD2, + TVIN_PORT_VIU1_WB1_VPP, TVIN_PORT_VIU1_WB1_POST_BLEND, TVIN_PORT_VIU2 = 0x0000C000, TVIN_PORT_VIU2_VIDEO, @@ -76,11 +78,13 @@ enum tvin_port_e { TVIN_PORT_VIU2_WB0_VD2, TVIN_PORT_VIU2_WB0_OSD1, TVIN_PORT_VIU2_WB0_OSD2, + TVIN_PORT_VIU2_WB0_VPP, TVIN_PORT_VIU2_WB0_POST_BLEND, TVIN_PORT_VIU2_WB1_VD1, TVIN_PORT_VIU2_WB1_VD2, TVIN_PORT_VIU2_WB1_OSD1, TVIN_PORT_VIU2_WB1_OSD2, + TVIN_PORT_VIU2_WB1_VPP, TVIN_PORT_VIU2_WB1_POST_BLEND, TVIN_PORT_MIPI = 0x00010000, TVIN_PORT_ISP = 0x00020000, @@ -312,6 +316,15 @@ struct tvin_info_s { unsigned int is_dvi; }; +struct tvin_frontend_info_s { + enum tvin_scan_mode_e scan_mode; + enum tvin_color_fmt_e cfmt; + unsigned int fps; + unsigned int width; + unsigned int height; + unsigned int colordepth; +}; + struct tvin_buf_info_s { unsigned int vf_size; unsigned int buf_count; @@ -432,6 +445,10 @@ struct tvafe_pin_mux_s { enum tvin_force_color_range_e) #define TVIN_IOC_GAME_MODE _IOW(_TM_T, 0x4b, unsigned int) #define TVIN_IOC_SET_AUTO_RATIO_EN _IOW(_TM_T, 0x4c, unsigned int) +#define TVIN_IOC_GET_LATENCY_MODE _IOR(_TM_T, 0x4d,\ + struct tvin_latency_s) +#define TVIN_IOC_G_FRONTEND_INFO _IOR(_TM_T, 0x4e,\ + struct tvin_frontend_info_s) /* TVAFE */ #define TVIN_IOC_S_AFE_VGA_PARM _IOW(_TM_T, 0x16, struct tvafe_vga_parm_s) @@ -441,21 +458,19 @@ struct tvafe_pin_mux_s { #define TVIN_IOC_S_AFE_CVBS_STD _IOW(_TM_T, 0x1b, enum tvin_sig_fmt_e) #define TVIN_IOC_CALLMASTER_SET _IOW(_TM_T, 0x1c, enum tvin_port_e) #define TVIN_IOC_CALLMASTER_GET _IO(_TM_T, 0x1d) +#define TVIN_IOC_G_AFE_CVBS_STD _IOW(_TM_T, 0x1e, enum tvin_sig_fmt_e) #define TVIN_IOC_LOAD_REG _IOW(_TM_T, 0x20, struct am_regs_s) #define TVIN_IOC_S_AFE_SONWON _IO(_TM_T, 0x22) #define TVIN_IOC_S_AFE_SONWOFF _IO(_TM_T, 0x23) +#define TVIN_IOC_G_VDIN_HIST _IOW(_TM_T, 0x24, struct vdin_hist_s) +#define TVIN_IOC_S_VDIN_V4L2START _IOW(_TM_T, 0x25, struct vdin_v4l2_param_s) +#define TVIN_IOC_S_VDIN_V4L2STOP _IO(_TM_T, 0x26) +#define TVIN_IOC_S_AFE_SONWCFG _IOW(_TM_T, 0x27, unsigned int) /* *function defined applied for other driver */ -/* - *adc pll ctl, atv demod & tvafe use the same adc module - * module index: atv demod:0x01; tvafe:0x2 - */ - -/* extern void adc_set_pll_cntl(bool on, unsigned int module_sel);*/ - struct dfe_adcpll_para { unsigned int adcpllctl; unsigned int demodctl; @@ -464,7 +479,7 @@ struct dfe_adcpll_para { struct rx_audio_stat_s { /*audio packets received*/ - bool aud_rcv_flag; + int aud_rcv_packet; /*audio stable status*/ bool aud_stb_flag; /*audio sample rate*/ @@ -484,8 +499,24 @@ struct rx_audio_stat_s { int aud_type; /* indicate if audio fifo start threshold is crossed */ bool afifo_thres_pass; + /* + * 0 [ch1 ch2] + * 1,2,3 [ch1 ch2 ch3 ch4] + * 4,8 [ch1 ch2 ch5 ch6] + * 5,6,7,9,10,11 [ch1 ch2 ch3 ch4 ch5 ch6] + * 12,16,24,28 [ch1 ch2 ch5 ch6 ch7 ch8] + * 20 [ch1 ch2 ch7 ch8] + * 21,22,23[ch1 ch2 ch3 ch4 ch7 ch8] + * all others [all of 8ch] + */ + int aud_alloc; }; +extern void adc_pll_down(void); +/*ADC_EN_ATV_DEMOD 0x1*/ +/*ADC_EN_TVAFE 0x2*/ +/*ADC_EN_DTV_DEMOD 0x4*/ +/*ADC_EN_DTV_DEMODPLL 0x8*/ extern int adc_set_pll_cntl(bool on, unsigned int module_sel, void *pDtvPara); extern void tvafe_set_ddemod_default(void);/* add for dtv demod*/ extern void rx_get_audio_status(struct rx_audio_stat_s *aud_sts); diff --git a/include/linux/amlogic/media/frame_provider/tvin/tvin_v4l2.h b/include/linux/amlogic/media/frame_provider/tvin/tvin_v4l2.h index 493bc9a22051..b1233faf5e3d 100644 --- a/include/linux/amlogic/media/frame_provider/tvin/tvin_v4l2.h +++ b/include/linux/amlogic/media/frame_provider/tvin/tvin_v4l2.h @@ -742,6 +742,10 @@ enum cam_interface_e { CAM_MIPI, }; +#define PARAM_STATE_NULL 0x00000000 +#define PARAM_STATE_HISTGRAM 0x00000001 +#define PARAM_STATE_SCREENCAP 0x00000002 + /* *********************************************************************** */ /* *** IOCTL command definitions ***************************************** */ @@ -813,6 +817,7 @@ struct vdin_parm_s { unsigned short skip_count; /* for skip frame */ struct csi_parm_s csi_hw_info; + /*for reserved */ uintptr_t reserved; }; diff --git a/include/linux/amlogic/media/frame_sync/ptsserv.h b/include/linux/amlogic/media/frame_sync/ptsserv.h index d17f1aaec14f..5d981871d7e5 100644 --- a/include/linux/amlogic/media/frame_sync/ptsserv.h +++ b/include/linux/amlogic/media/frame_sync/ptsserv.h @@ -43,12 +43,13 @@ extern int get_last_checkin_pts(u8 type); extern int get_last_checkout_pts(u8 type); -extern int pts_lookup(u8 type, u32 *val, u32 pts_margin); +extern int pts_lookup(u8 type, u32 *val, u32 *frame_size, u32 pts_margin); -extern int pts_lookup_offset(u8 type, u32 offset, u32 *val, u32 pts_margin); +extern int pts_lookup_offset(u8 type, u32 offset, u32 *val, + u32 *frame_size, u32 pts_margin); extern int pts_lookup_offset_us64(u8 type, u32 offset, u32 *val, - u32 pts_margin, u64 *uS64); + u32 *frame_size, u32 pts_margin, u64 *uS64); extern int pts_pickout_offset_us64(u8 type, u32 offset, u32 *val, u32 pts_margin, diff --git a/include/linux/amlogic/media/frame_sync/tsync.h b/include/linux/amlogic/media/frame_sync/tsync.h index 2194d6a18609..edf83a71be44 100644 --- a/include/linux/amlogic/media/frame_sync/tsync.h +++ b/include/linux/amlogic/media/frame_sync/tsync.h @@ -157,6 +157,9 @@ extern int tsync_set_av_threshold_max(int max); extern void set_pts_realign(void); +extern void timestamp_set_pcrlatency(u32 latency); +extern u32 timestamp_get_pcrlatency(void); + static inline u32 tsync_vpts_discontinuity_margin(void) { return tsync_get_av_threshold_min(); diff --git a/include/linux/amlogic/media/ge2d/ge2d.h b/include/linux/amlogic/media/ge2d/ge2d.h index dbd935ad61dc..dd2cc301f82d 100644 --- a/include/linux/amlogic/media/ge2d/ge2d.h +++ b/include/linux/amlogic/media/ge2d/ge2d.h @@ -27,11 +27,17 @@ #include #endif +enum ge2d_memtype_s { + AML_GE2D_MEM_ION, + AML_GE2D_MEM_DMABUF, + AML_GE2D_MEM_INVALID, +}; + #define MAX_BITBLT_WORK_CONFIG 4 #define MAX_GE2D_CMD 32 /* 64 */ -/* #define CONFIG_GE2D_ADV_NUM */ +#define CONFIG_GE2D_ADV_NUM #define CONFIG_GE2D_SRC2 #define GE2D_STATE_IDLE 0 #define GE2D_STATE_RUNNING 1 @@ -234,6 +240,7 @@ #define GE2D_FMT_M24_YUV420B 0x2001f /* 00_00_0_11_1_11 */ #define GE2D_FMT_M24_YUV420SP 0x20207 +#define GE2D_FMT_M24_YUV422SP 0x20206 /* 01_00_0_00_1_11 nv12 &nv21, only works on m6. */ #define GE2D_FMT_M24_YUV420SPT 0x20217 /* 01_00_0_00_1_11 nv12 &nv21, only works on m6. */ @@ -289,6 +296,7 @@ #define GE2D_FORMAT_M24_RGB GE2D_FMT_M24_RGB #define GE2D_FORMAT_M24_YUV420T GE2D_FMT_M24_YUV420T #define GE2D_FORMAT_M24_YUV420B GE2D_FMT_M24_YUV420B +#define GE2D_FORMAT_M24_YUV422SP (GE2D_FMT_M24_YUV422SP | GE2D_COLOR_MAP_NV12) #define GE2D_FORMAT_S16_YUV422T (GE2D_FMT_S16_YUV422T | GE2D_COLOR_MAP_YUV422) #define GE2D_FORMAT_S16_YUV422B (GE2D_FMT_S16_YUV422B | GE2D_COLOR_MAP_YUV422) #define GE2D_FORMAT_S24_YUV444T (GE2D_FMT_S24_YUV444T | GE2D_COLOR_MAP_YUV444) @@ -540,6 +548,7 @@ struct ge2d_cmd_s { /* unsigned char src1_x_chr_phase; */ /* unsigned char src1_y_chr_phase; */ unsigned char src1_fill_color_en; + unsigned int src1_fmt; int src2_x_start; int src2_y_start; @@ -548,6 +557,7 @@ struct ge2d_cmd_s { unsigned char src2_x_rev; unsigned char src2_y_rev; unsigned char src2_fill_color_en; + unsigned int src2_fmt; int dst_x_start; int dst_y_start; @@ -556,6 +566,7 @@ struct ge2d_cmd_s { unsigned char dst_xy_swap; unsigned char dst_x_rev; unsigned char dst_y_rev; + unsigned int dst_fmt; int sc_prehsc_en; int sc_prevsc_en; @@ -598,6 +609,11 @@ struct ge2d_cmd_s { unsigned char hang_flag; }; +struct ge2d_dma_cfg_s { + int dma_used; + void *dma_cfg; +}; + struct ge2d_config_s { struct ge2d_gen_s gen; struct ge2d_src1_data_s src1_data; @@ -608,6 +624,22 @@ struct ge2d_config_s { unsigned int v_scale_coef_type; unsigned int h_scale_coef_type; unsigned int update_flag; + struct ge2d_dma_cfg_s src_dma_cfg; + struct ge2d_dma_cfg_s src2_dma_cfg; + struct ge2d_dma_cfg_s dst_dma_cfg; +}; + +struct ge2d_dma_buf_s { + dma_addr_t paddr; + void *vaddr; + int len; +}; + +enum ge2d_data_type_e { + AML_GE2D_SRC, + AML_GE2D_SRC2, + AML_GE2D_DST, + AML_GE2D_TYPE_INVALID, }; enum ge2d_src_dst_e { @@ -663,6 +695,7 @@ struct ge2d_manager_s { struct ge2d_context_s *last_wq; struct task_struct *ge2d_thread; struct ge2d_event_s event; + struct aml_dma_buffer *buffer; int irq_num; int ge2d_state; int process_queue_state; @@ -949,6 +982,79 @@ struct compat_config_para_ex_ion_s { struct compat_config_planes_ion_s dst_planes[4]; }; #endif + +struct config_para_ex_memtype_s { + int ge2d_magic; + struct config_para_ex_ion_s _ge2d_config_ex; + /* memtype*/ + unsigned int src1_mem_alloc_type; + unsigned int src2_mem_alloc_type; + unsigned int dst_mem_alloc_type; +}; + +struct config_ge2d_para_ex_s { + union { + struct config_para_ex_ion_s para_config_ion; + struct config_para_ex_memtype_s para_config_memtype; + }; +}; + + +#ifdef CONFIG_COMPAT +struct compat_config_para_ex_memtype_s { + int ge2d_magic; + struct compat_config_para_ex_ion_s _ge2d_config_ex; + /* memtype*/ + unsigned int src1_mem_alloc_type; + unsigned int src2_mem_alloc_type; + unsigned int dst_mem_alloc_type; +}; + +struct compat_config_ge2d_para_ex_s { + union { + struct compat_config_para_ex_ion_s para_config_ion; + struct compat_config_para_ex_memtype_s para_config_memtype; + }; +}; +#endif + +/* for ge2d dma buf define */ +struct ge2d_dmabuf_req_s { + int index; + unsigned int len; + unsigned int dma_dir; +}; + +struct ge2d_dmabuf_exp_s { + int index; + unsigned int flags; + int fd; +}; +/* end of ge2d dma buffer define */ + +enum { + CBUS_BASE, + AOBUS_BASE, + HIUBUS_BASE, + GEN_PWR_SLEEP0, + GEN_PWR_ISO0, + MEM_PD_REG0, +}; + +struct ge2d_ctrl_s { + unsigned int table_type; + unsigned int reg; + unsigned int val; + unsigned int start; + unsigned int len; + unsigned int udelay; +}; + +struct ge2d_power_table_s { + unsigned int table_size; + struct ge2d_ctrl_s *power_table; +}; + struct ge2d_device_data_s { int ge2d_rate; int src2_alp; @@ -956,6 +1062,9 @@ struct ge2d_device_data_s { int deep_color; int hang_flag; int fifo; + int has_self_pwr; + struct ge2d_power_table_s *poweron_table; + struct ge2d_power_table_s *poweroff_table; }; extern struct ge2d_device_data_s ge2d_meson_dev; @@ -990,6 +1099,21 @@ extern struct ge2d_device_data_s ge2d_meson_dev; _IOW(GE2D_IOC_MAGIC, 0x03, struct compat_config_para_ex_ion_s) #endif +#define GE2D_REQUEST_BUFF _IOW(GE2D_IOC_MAGIC, 0x04, struct ge2d_dmabuf_req_s) +#define GE2D_EXP_BUFF _IOW(GE2D_IOC_MAGIC, 0x05, struct ge2d_dmabuf_exp_s) +#define GE2D_FREE_BUFF _IOW(GE2D_IOC_MAGIC, 0x06, int) + +#define GE2D_CONFIG_EX_MEM \ + _IOW(GE2D_IOC_MAGIC, 0x07, struct config_ge2d_para_ex_s) + +#ifdef CONFIG_COMPAT +#define GE2D_CONFIG_EX32_MEM \ + _IOW(GE2D_IOC_MAGIC, 0x07, struct compat_config_ge2d_para_ex_s) +#endif + +#define GE2D_SYNC_DEVICE _IOW(GE2D_IOC_MAGIC, 0x08, int) +#define GE2D_SYNC_CPU _IOW(GE2D_IOC_MAGIC, 0x09, int) + extern void ge2d_set_src1_data(struct ge2d_src1_data_s *cfg); extern void ge2d_set_src1_gen(struct ge2d_src1_gen_s *cfg); extern void ge2d_set_src2_dst_data(struct ge2d_src2_dst_data_s *cfg); @@ -1010,6 +1134,8 @@ extern int ge2d_context_config_ex(struct ge2d_context_s *context, struct config_para_ex_s *ge2d_config); extern int ge2d_context_config_ex_ion(struct ge2d_context_s *context, struct config_para_ex_ion_s *ge2d_config); +extern int ge2d_context_config_ex_mem(struct ge2d_context_s *context, + struct config_para_ex_memtype_s *ge2d_config_mem); extern struct ge2d_context_s *create_ge2d_work_queue(void); extern int destroy_ge2d_work_queue(struct ge2d_context_s *wq); extern int ge2d_wq_remove_config(struct ge2d_context_s *wq); diff --git a/include/linux/amlogic/media/rdma/rdma_mgr.h b/include/linux/amlogic/media/rdma/rdma_mgr.h index 20207501aeee..8aeae1fd7075 100644 --- a/include/linux/amlogic/media/rdma/rdma_mgr.h +++ b/include/linux/amlogic/media/rdma/rdma_mgr.h @@ -24,6 +24,7 @@ struct rdma_op_s { }; #define RDMA_TRIGGER_VSYNC_INPUT 0x1 +#define RDMA_TRIGGER_LINE_INPUT (1 << 5) #define RDMA_TRIGGER_MANUAL 0x100 #define RDMA_TRIGGER_DEBUG1 0x101 #define RDMA_TRIGGER_DEBUG2 0x102 @@ -34,11 +35,18 @@ enum rdma_ver_e { RDMA_VER_2, }; +enum cpu_ver_e { + CPU_G12B, + CPU_NORMAL, +}; + struct rdma_device_data_s { + enum cpu_ver_e cpu_type; enum rdma_ver_e rdma_ver; u32 trigger_mask_len; }; +u32 is_meson_g12b_revb(void); /* * rdma_read_reg(), rdma_write_reg(), rdma_clear() can only be called * after rdma_register() is called and diff --git a/include/linux/amlogic/media/registers/regs/hevc_regs.h b/include/linux/amlogic/media/registers/regs/hevc_regs.h index 3258b90f752f..9eb5eed0e28a 100644 --- a/include/linux/amlogic/media/registers/regs/hevc_regs.h +++ b/include/linux/amlogic/media/registers/regs/hevc_regs.h @@ -357,6 +357,14 @@ #define HEVC_IQIT_STAT_GEN0 0x3708 #define HEVC_QP_WRITE 0x3709 #define HEVC_IQIT_STAT_GEN1 0x370a +#define HEVC_IQIT_BITDEPTH 0x370b +#define HEVC_IQIT_STAT_GEN2 0x370c +#define HEVC_IQIT_AVS2_WQP_0123 0x370d +#define HEVC_IQIT_AVS2_WQP_45 0x370e +#define HEVC_IQIT_AVS2_QP_DELTA 0x370f +#define HEVC_PIC_QUALITY_CTRL 0x3710 +#define HEVC_PIC_QUALITY_DATA 0x3711 + /**/ /*add from M8M2*/ diff --git a/include/linux/amlogic/media/registers/regs/parser_regs.h b/include/linux/amlogic/media/registers/regs/parser_regs.h index cb0f13370458..b340d6f64daa 100644 --- a/include/linux/amlogic/media/registers/regs/parser_regs.h +++ b/include/linux/amlogic/media/registers/regs/parser_regs.h @@ -24,57 +24,118 @@ * converted automatically based on * the platform at init. * #define PARSER_CONTROL 0x3860 + * parser A */ -#define PARSER_CONTROL 0x2960 -#define PARSER_FETCH_ADDR 0x2961 -#define PARSER_FETCH_CMD 0x2962 -#define PARSER_FETCH_STOP_ADDR 0x2963 -#define PARSER_FETCH_LEVEL 0x2964 -#define PARSER_CONFIG 0x2965 -#define PFIFO_WR_PTR 0x2966 -#define PFIFO_RD_PTR 0x2967 -#define PFIFO_DATA 0x2968 -#define PARSER_SEARCH_PATTERN 0x2969 -#define PARSER_SEARCH_MASK 0x296a -#define PARSER_INT_ENABLE 0x296b -#define PARSER_INT_STATUS 0x296c -#define PARSER_SCR_CTL 0x296d -#define PARSER_SCR 0x296e -#define PARSER_PARAMETER 0x296f -#define PARSER_INSERT_DATA 0x2970 -#define VAS_STREAM_ID 0x2971 -#define VIDEO_DTS 0x2972 -#define VIDEO_PTS 0x2973 -#define VIDEO_PTS_DTS_WR_PTR 0x2974 -#define AUDIO_PTS 0x2975 -#define AUDIO_PTS_WR_PTR 0x2976 -#define PARSER_ES_CONTROL 0x2977 -#define PFIFO_MONITOR 0x2978 -#define PARSER_VIDEO_START_PTR 0x2980 -#define PARSER_VIDEO_END_PTR 0x2981 -#define PARSER_VIDEO_WP 0x2982 -#define PARSER_VIDEO_RP 0x2983 -#define PARSER_VIDEO_HOLE 0x2984 -#define PARSER_AUDIO_START_PTR 0x2985 -#define PARSER_AUDIO_END_PTR 0x2986 -#define PARSER_AUDIO_WP 0x2987 -#define PARSER_AUDIO_RP 0x2988 -#define PARSER_AUDIO_HOLE 0x2989 -#define PARSER_SUB_START_PTR 0x298a -#define PARSER_SUB_END_PTR 0x298b -#define PARSER_SUB_WP 0x298c -#define PARSER_SUB_RP 0x298d -#define PARSER_SUB_HOLE 0x298e -#define PARSER_FETCH_INFO 0x298f -#define PARSER_STATUS 0x2990 -#define PARSER_AV_WRAP_COUNT 0x2991 -#define WRRSP_PARSER 0x2992 -#define PARSER_VIDEO2_START_PTR 0x2993 -#define PARSER_VIDEO2_END_PTR 0x2994 -#define PARSER_VIDEO2_WP 0x2995 -#define PARSER_VIDEO2_RP 0x2996 -#define PARSER_VIDEO2_HOLE 0x2997 -#define PARSER_AV2_WRAP_COUNT 0x2998 +#define PARSER_CONTROL 0x2960 +#define PARSER_FETCH_ADDR 0x2961 +#define PARSER_FETCH_CMD 0x2962 +#define PARSER_FETCH_STOP_ADDR 0x2963 +#define PARSER_FETCH_LEVEL 0x2964 +#define PARSER_CONFIG 0x2965 +#define PFIFO_WR_PTR 0x2966 +#define PFIFO_RD_PTR 0x2967 +#define PFIFO_DATA 0x2968 +#define PARSER_SEARCH_PATTERN 0x2969 +#define PARSER_SEARCH_MASK 0x296a +#define PARSER_INT_ENABLE 0x296b +#define PARSER_INT_STATUS 0x296c +#define PARSER_SCR_CTL 0x296d +#define PARSER_SCR 0x296e +#define PARSER_PARAMETER 0x296f +#define PARSER_INSERT_DATA 0x2970 +#define VAS_STREAM_ID 0x2971 +#define VIDEO_DTS 0x2972 +#define VIDEO_PTS 0x2973 +#define VIDEO_PTS_DTS_WR_PTR 0x2974 +#define AUDIO_PTS 0x2975 +#define AUDIO_PTS_WR_PTR 0x2976 +#define PARSER_ES_CONTROL 0x2977 +#define PFIFO_MONITOR 0x2978 +#define PARSER_VIDEO_START_PTR 0x2980 +#define PARSER_VIDEO_END_PTR 0x2981 +#define PARSER_VIDEO_WP 0x2982 +#define PARSER_VIDEO_RP 0x2983 +#define PARSER_VIDEO_HOLE 0x2984 +#define PARSER_AUDIO_START_PTR 0x2985 +#define PARSER_AUDIO_END_PTR 0x2986 +#define PARSER_AUDIO_WP 0x2987 +#define PARSER_AUDIO_RP 0x2988 +#define PARSER_AUDIO_HOLE 0x2989 +#define PARSER_SUB_START_PTR 0x298a +#define PARSER_SUB_END_PTR 0x298b +#define PARSER_SUB_WP 0x298c +#define PARSER_SUB_RP 0x298d +#define PARSER_SUB_HOLE 0x298e +#define PARSER_FETCH_INFO 0x298f +#define PARSER_STATUS 0x2990 +#define PARSER_AV_WRAP_COUNT 0x2991 +#define WRRSP_PARSER 0x2992 +#define PARSER_VIDEO2_START_PTR 0x2993 +#define PARSER_VIDEO2_END_PTR 0x2994 +#define PARSER_VIDEO2_WP 0x2995 +#define PARSER_VIDEO2_RP 0x2996 +#define PARSER_VIDEO2_HOLE 0x2997 +#define PARSER_AV2_WRAP_COUNT 0x2998 + +/* + * pay attention : the regs range has + * changed to 0x34xx in SM1, it was + * converted automatically based on + * the platform at init. + * #define PARSER_B_CONTROL 0x3460 + * parser B + */ + +#define PARSER_B_CONTROL 0x2560 +#define PARSER_B_FETCH_ADDR 0x2561 +#define PARSER_B_FETCH_CMD 0x2562 +#define PARSER_B_FETCH_STOP_ADDR 0x2563 +#define PARSER_B_FETCH_LEVEL 0x2564 +#define PARSER_B_CONFIG 0x2565 +#define PARSER_B_PFIFO_WR_PTR 0x2566 +#define PARSER_B_PFIFO_RD_PTR 0x2567 +#define PARSER_B_PFIFO_DATA 0x2568 +#define PARSER_B_SEARCH_PATTERN 0x2569 +#define PARSER_B_SEARCH_MASK 0x256a +#define PARSER_B_INT_ENABLE 0x256b +#define PARSER_B_INT_STATUS 0x256c +#define PARSER_B_SCR_CTL 0x256d +#define PARSER_B_SCR 0x256e +#define PARSER_B_PARAMETER 0x256f +#define PARSER_B_INSERT_DATA 0x2570 +#define PARSER_B_VAS_STREAM_ID 0x2571 +#define PARSER_B_VIDEO_DTS 0x2572 +#define PARSER_B_VIDEO_PTS 0x2573 +#define PARSER_B_VIDEO_PTS_DTS_WR_PTR 0x2574 +#define PARSER_B_AUDIO_PTS 0x2575 +#define PARSER_B_AUDIO_PTS_WR_PTR 0x2576 +#define PARSER_B_ES_CONTROL 0x2577 +#define PARSER_B_PFIFO_MONITOR 0x2578 +#define PARSER_B_VIDEO_START_PTR 0x2580 +#define PARSER_B_VIDEO_END_PTR 0x2581 +#define PARSER_B_VIDEO_WP 0x2582 +#define PARSER_B_VIDEO_RP 0x2583 +#define PARSER_B_VIDEO_HOLE 0x2584 +#define PARSER_B_AUDIO_START_PTR 0x2585 +#define PARSER_B_AUDIO_END_PTR 0x2586 +#define PARSER_B_AUDIO_WP 0x2587 +#define PARSER_B_AUDIO_RP 0x2588 +#define PARSER_B_AUDIO_HOLE 0x2589 +#define PARSER_B_SUB_START_PTR 0x258a +#define PARSER_B_SUB_END_PTR 0x258b +#define PARSER_B_SUB_WP 0x258c +#define PARSER_B_SUB_RP 0x258d +#define PARSER_B_SUB_HOLE 0x258e +#define PARSER_B_FETCH_INFO 0x258f +#define PARSER_B_STATUS 0x2590 +#define PARSER_B_AV_WRAP_COUNT 0x2591 +#define PARSER_B_WRRSP_PARSER 0x2592 +#define PARSER_B_VIDEO2_START_PTR 0x2593 +#define PARSER_B_VIDEO2_END_PTR 0x2594 +#define PARSER_B_VIDEO2_WP 0x2595 +#define PARSER_B_VIDEO2_RP 0x2596 +#define PARSER_B_VIDEO2_HOLE 0x2597 +#define PARSER_B_AV2_WRAP_COUNT 0x2598 #endif diff --git a/include/linux/amlogic/media/registers/regs/viu_regs.h b/include/linux/amlogic/media/registers/regs/viu_regs.h index 20d5df4647a6..9f0299c49089 100644 --- a/include/linux/amlogic/media/registers/regs/viu_regs.h +++ b/include/linux/amlogic/media/registers/regs/viu_regs.h @@ -213,5 +213,18 @@ #define G12_VD1_IF0_GEN_REG3 0x3216 #define G12_VD2_IF0_GEN_REG3 0x3236 +/* TL1 */ +#define AFBCDEC_IQUANT_ENABLE 0x1af2 +#define AFBCDEC_IQUANT_LUT_1 0x1af3 +#define AFBCDEC_IQUANT_LUT_2 0x1af4 +#define AFBCDEC_IQUANT_LUT_3 0x1af5 +#define AFBCDEC_IQUANT_LUT_4 0x1af6 + +#define VD2_AFBCDEC_IQUANT_ENABLE 0x3192 +#define VD2_AFBCDEC_IQUANT_LUT_1 0x3193 +#define VD2_AFBCDEC_IQUANT_LUT_2 0x3194 +#define VD2_AFBCDEC_IQUANT_LUT_3 0x3195 +#define VD2_AFBCDEC_IQUANT_LUT_4 0x3196 + #endif diff --git a/include/linux/amlogic/media/registers/regs/vpp_regs.h b/include/linux/amlogic/media/registers/regs/vpp_regs.h index c82b4bad29fe..af2df4329063 100644 --- a/include/linux/amlogic/media/registers/regs/vpp_regs.h +++ b/include/linux/amlogic/media/registers/regs/vpp_regs.h @@ -245,5 +245,15 @@ #define OSD1_BLEND_SRC_CTRL 0x1dfd #define OSD2_BLEND_SRC_CTRL 0x1dfe +#define VPP_POST_BLEND_BLEND_DUMMY_DATA 0x3968 +#define VPP_POST_BLEND_DUMMY_ALPHA 0x3969 + +/* after g12b */ +#define SRSHARP0_SHARP_SYNC_CTRL 0x3eb0 +#define SRSHARP1_SHARP_SYNC_CTRL 0x3fb0 + +#define VPU_RDARB_MODE_L2C1 0x279d +#define VPU_WRARB_MODE_L2C1 0x27a2 + #endif diff --git a/include/linux/amlogic/media/sound/auge_utils.h b/include/linux/amlogic/media/sound/auge_utils.h index 6b21c42745c1..1e4f6fd8d0b2 100644 --- a/include/linux/amlogic/media/sound/auge_utils.h +++ b/include/linux/amlogic/media/sound/auge_utils.h @@ -20,4 +20,5 @@ void auge_acodec_reset(void); void auge_toacodec_ctrl(int tdmout_id); +void auge_toacodec_ctrl_ext(int tdmout_id, int ch0_sel, int ch1_sel); #endif diff --git a/include/linux/amlogic/media/sound/misc.h b/include/linux/amlogic/media/sound/misc.h index 7f3edbfb5bcd..c9e9fbda9613 100644 --- a/include/linux/amlogic/media/sound/misc.h +++ b/include/linux/amlogic/media/sound/misc.h @@ -31,6 +31,15 @@ int aml_get_atv_audio_stable( #endif +#ifdef CONFIG_AMLOGIC_MEDIA_TVIN_AVDETECT +extern int tvin_get_av_status(void); +extern const struct soc_enum av_audio_status_enum; + +extern int aml_get_av_audio_stable( + struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol); +#endif + #ifdef CONFIG_AMLOGIC_MEDIA_TVIN_HDMI extern int update_spdifin_audio_type(int audio_type); @@ -62,6 +71,10 @@ extern int aml_get_atmos_audio_edid( struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); +extern int aml_get_hdmiin_audio_packet( + struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol); + #endif #endif diff --git a/include/linux/amlogic/media/sound/spdif_info.h b/include/linux/amlogic/media/sound/spdif_info.h index e9fec1776202..36df67a80f96 100644 --- a/include/linux/amlogic/media/sound/spdif_info.h +++ b/include/linux/amlogic/media/sound/spdif_info.h @@ -45,4 +45,10 @@ extern int spdif_format_get_enum( extern int spdif_format_set_enum( struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); +#ifdef CONFIG_AMLOGIC_HDMITX +int aml_get_hdmi_out_audio(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol); +int aml_set_hdmi_out_audio(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol); +#endif #endif diff --git a/include/linux/amlogic/media/utils/amstream.h b/include/linux/amlogic/media/utils/amstream.h index 5b44f40ec3b6..0d690f28fc18 100644 --- a/include/linux/amlogic/media/utils/amstream.h +++ b/include/linux/amlogic/media/utils/amstream.h @@ -90,6 +90,59 @@ #define AMSTREAM_IOC_GLOBAL_GET_VIDEO_OUTPUT _IOR((_A_M), 0x21, int) #define AMSTREAM_IOC_GLOBAL_SET_VIDEO_OUTPUT _IOW((_A_M), 0x22, int) #define AMSTREAM_IOC_GET_VIDEO_LAYER1_ON _IOR((_A_M), 0x23, int) +/*video pip IOCTL command list*/ +#define AMSTREAM_IOC_CLEAR_VIDEOPIP _IOW((_A_M), 0x24, int) +#define AMSTREAM_IOC_CLEAR_PIP_VBUF _IO((_A_M), 0x25) + +#define AMSTREAM_IOC_GLOBAL_GET_VIDEOPIP_OUTPUT _IOR((_A_M), 0x2b, int) +#define AMSTREAM_IOC_GLOBAL_SET_VIDEOPIP_OUTPUT _IOW((_A_M), 0x2c, int) +#define AMSTREAM_IOC_GET_VIDEOPIP_DISABLE _IOR((_A_M), 0x2d, int) +#define AMSTREAM_IOC_SET_VIDEOPIP_DISABLE _IOW((_A_M), 0x2e, int) +#define AMSTREAM_IOC_GET_VIDEOPIP_AXIS _IOR((_A_M), 0x2f, int) +#define AMSTREAM_IOC_SET_VIDEOPIP_AXIS _IOW((_A_M), 0x30, int) +#define AMSTREAM_IOC_GET_VIDEOPIP_CROP _IOR((_A_M), 0x31, int) +#define AMSTREAM_IOC_SET_VIDEOPIP_CROP _IOW((_A_M), 0x32, int) +#define AMSTREAM_IOC_GET_PIP_SCREEN_MODE _IOR((_A_M), 0x33, int) +#define AMSTREAM_IOC_SET_PIP_SCREEN_MODE _IOW((_A_M), 0x34, int) +#define AMSTREAM_IOC_GET_PIP_ZORDER _IOW((_A_M), 0x35, unsigned int) +#define AMSTREAM_IOC_SET_PIP_ZORDER _IOW((_A_M), 0x36, unsigned int) + +#define AMSTREAM_IOC_GET_ZORDER _IOW((_A_M), 0x37, unsigned int) +#define AMSTREAM_IOC_SET_ZORDER _IOW((_A_M), 0x38, unsigned int) + +#define AMSTREAM_IOC_QUERY_LAYER _IOW((_A_M), 0x39, unsigned int) +#define AMSTREAM_IOC_ALLOC_LAYER _IOW((_A_M), 0x3a, unsigned int) +#define AMSTREAM_IOC_FREE_LAYER _IOW((_A_M), 0x3b, unsigned int) + +/* VPP.3D IOCTL command list^M */ +#define AMSTREAM_IOC_SET_3D_TYPE _IOW((_A_M), 0x3c, unsigned int) +#define AMSTREAM_IOC_GET_3D_TYPE _IOW((_A_M), 0x3d, unsigned int) +#define AMSTREAM_IOC_GET_SOURCE_VIDEO_3D_TYPE _IOW((_A_M), 0x3e, unsigned int) + +#define AMSTREAM_IOC_GLOBAL_GET_VIDEOPIP_OUTPUT _IOR((_A_M), 0x2b, int) +#define AMSTREAM_IOC_GLOBAL_SET_VIDEOPIP_OUTPUT _IOW((_A_M), 0x2c, int) +#define AMSTREAM_IOC_GET_VIDEOPIP_DISABLE _IOR((_A_M), 0x2d, int) +#define AMSTREAM_IOC_SET_VIDEOPIP_DISABLE _IOW((_A_M), 0x2e, int) +#define AMSTREAM_IOC_GET_VIDEOPIP_AXIS _IOR((_A_M), 0x2f, int) +#define AMSTREAM_IOC_SET_VIDEOPIP_AXIS _IOW((_A_M), 0x30, int) +#define AMSTREAM_IOC_GET_VIDEOPIP_CROP _IOR((_A_M), 0x31, int) +#define AMSTREAM_IOC_SET_VIDEOPIP_CROP _IOW((_A_M), 0x32, int) +#define AMSTREAM_IOC_GET_PIP_SCREEN_MODE _IOR((_A_M), 0x33, int) +#define AMSTREAM_IOC_SET_PIP_SCREEN_MODE _IOW((_A_M), 0x34, int) +#define AMSTREAM_IOC_GET_PIP_ZORDER _IOW((_A_M), 0x35, unsigned int) +#define AMSTREAM_IOC_SET_PIP_ZORDER _IOW((_A_M), 0x36, unsigned int) + +#define AMSTREAM_IOC_GET_ZORDER _IOW((_A_M), 0x37, unsigned int) +#define AMSTREAM_IOC_SET_ZORDER _IOW((_A_M), 0x38, unsigned int) + +#define AMSTREAM_IOC_QUERY_LAYER _IOW((_A_M), 0x39, unsigned int) +#define AMSTREAM_IOC_ALLOC_LAYER _IOW((_A_M), 0x3a, unsigned int) +#define AMSTREAM_IOC_FREE_LAYER _IOW((_A_M), 0x3b, unsigned int) + +/* VPP.3D IOCTL command list^M */ +#define AMSTREAM_IOC_SET_3D_TYPE _IOW((_A_M), 0x3c, unsigned int) +#define AMSTREAM_IOC_GET_3D_TYPE _IOW((_A_M), 0x3d, unsigned int) +#define AMSTREAM_IOC_GET_SOURCE_VIDEO_3D_TYPE _IOW((_A_M), 0x3e, unsigned int) #define AMSTREAM_IOC_APTS _IOR((_A_M), 0x40, int) #define AMSTREAM_IOC_VPTS _IOR((_A_M), 0x41, int) @@ -108,11 +161,6 @@ #define AMSTREAM_IOC_SET_VIDEO_CROP _IOW((_A_M), 0x4e, int) #define AMSTREAM_IOC_PCRID _IOW((_A_M), 0x4f, int) -/* VPP.3D IOCTL command list^M */ -#define AMSTREAM_IOC_SET_3D_TYPE _IOW((_A_M), 0x3c, unsigned int) -#define AMSTREAM_IOC_GET_3D_TYPE _IOW((_A_M), 0x3d, unsigned int) -#define AMSTREAM_IOC_GET_SOURCE_VIDEO_3D_TYPE _IOW((_A_M), 0x3e, unsigned int) - #define AMSTREAM_IOC_SUB_NUM _IOR((_A_M), 0x50, int) #define AMSTREAM_IOC_SUB_INFO _IOR((_A_M), 0x51, int) #define AMSTREAM_IOC_GET_BLACKOUT_POLICY _IOR((_A_M), 0x52, int) @@ -121,20 +169,26 @@ #define AMSTREAM_IOC_UD_POC _IOR((_A_M), 0x55, int) #define AMSTREAM_IOC_UD_FLUSH_USERDATA _IOR((_A_M), 0x56, int) -#define AMSTREAM_IOC_UD_BUF_READ _IOR((_A_M), 0x57, struct userdata_param_t) +#define AMSTREAM_IOC_UD_BUF_READ _IOR((_A_M), 0x57, int) #define AMSTREAM_IOC_GET_SCREEN_MODE _IOR((_A_M), 0x58, int) #define AMSTREAM_IOC_SET_SCREEN_MODE _IOW((_A_M), 0x59, int) #define AMSTREAM_IOC_GET_VIDEO_DISCONTINUE_REPORT _IOR((_A_M), 0x5a, int) #define AMSTREAM_IOC_SET_VIDEO_DISCONTINUE_REPORT _IOW((_A_M), 0x5b, int) +#define AMSTREAM_IOC_UD_AVAILABLE_VDEC _IOR((_A_M), 0x5c, unsigned int) +#define AMSTREAM_IOC_GET_VDEC_ID _IOR((_A_M), 0x5d, int) + /* * #define AMSTREAM_IOC_UD_BUF_STATUS _IOR((_A_M), * 0x5c, struct userdata_buf_state_t) */ - #define AMSTREAM_IOC_VF_STATUS _IOR((_A_M), 0x60, int) + +#define AMSTREAM_IOC_GET_BLACKOUT_PIP_POLICY _IOR((_A_M), 0x62, int) +#define AMSTREAM_IOC_SET_BLACKOUT_PIP_POLICY _IOW((_A_M), 0x63, int) + #define AMSTREAM_IOC_CLEAR_VBUF _IO((_A_M), 0x80) #define AMSTREAM_IOC_APTS_LOOKUP _IOR((_A_M), 0x81, int) @@ -192,6 +246,9 @@ #define AMSTREAM_IOC_SET_EX _IOW((_A_M), 0xc4, struct am_ioctl_parm_ex) #define AMSTREAM_IOC_GET_PTR _IOWR((_A_M), 0xc5, struct am_ioctl_parm_ptr) #define AMSTREAM_IOC_SET_PTR _IOW((_A_M), 0xc6, struct am_ioctl_parm_ptr) +#define AMSTREAM_IOC_GET_AVINFO _IOR((_A_M), 0xc7, struct av_param_info_t) +#define AMSTREAM_IOC_GET_QOSINFO _IOR((_A_M), 0xc8, struct av_param_qosinfo_t) + #define TRICKMODE_NONE 0x00 #define TRICKMODE_I 0x01 @@ -271,12 +328,20 @@ struct buf_status { #define DECODER_ERROR_MASK (0xffff<<16) + +enum E_ASPECT_RATIO { + ASPECT_RATIO_4_3, + ASPECT_RATIO_16_9, + ASPECT_UNDEFINED = 255 +}; + struct vdec_status { unsigned int width; unsigned int height; unsigned int fps; unsigned int error_count; unsigned int status; + enum E_ASPECT_RATIO euAspectRatio; }; struct vdec_info { @@ -296,6 +361,7 @@ struct vdec_info { unsigned long long total_data; unsigned int samp_cnt; unsigned int offset; + unsigned int ratio_control; char reserved[32]; }; @@ -471,7 +537,7 @@ struct userdata_param_t { uint32_t instance_id; /*input, 0~9*/ uint32_t buf_len; /*input*/ uint32_t data_size; /*output*/ - unsigned long long pbuf_addr; /*input*/ + void *pbuf_addr; /*input*/ struct userdata_meta_info_t meta_info; /*output*/ }; @@ -653,6 +719,65 @@ struct am_ioctl_parm_ptr { u32 len; /*char reserved[4]; */ }; +struct vframe_qos_s { + int num; + int type; + int size; + int pts; + int max_qp; + int avg_qp; + int min_qp; + int max_skip; + int avg_skip; + int min_skip; + int max_mv; + int min_mv; + int avg_mv; + int decode_buffer; +} /*vframe_qos */; + +enum FRAME_FORMAT { + FRAME_FORMAT_UNKNOWN, + FRAME_FORMAT_PROGRESS, + FRAME_FORMAT_INTERLACE, +}; + +#define QOS_FRAME_NUM 60 +struct av_info_t { + /*auido info*/ + int sample_rate; + int channels; + int aformat_type; + unsigned int apts; + unsigned int apts_err; + /*video info*/ + unsigned int width; + unsigned int height; + unsigned int dec_error_count; + unsigned int first_pic_coming; + unsigned int fps; + unsigned int current_fps; + unsigned int vpts; + unsigned int vpts_err; + unsigned int ts_error; + unsigned int first_vpts; + int vformat_type; + enum FRAME_FORMAT frame_format; + unsigned int toggle_frame_count;/*toggle frame count*/ + unsigned int dec_err_frame_count;/*vdec error frame count*/ + unsigned int dec_frame_count;/*vdec frame count*/ + unsigned int dec_drop_frame_count;/*drop frame num*/ + int tsync_mode; +}; + +struct av_param_info_t { + struct av_info_t av_info; +}; +struct av_param_qosinfo_t { + struct vframe_qos_s vframe_qos[QOS_FRAME_NUM]; +}; + + #define SUPPORT_VDEC_NUM (20) int vcodec_profile_register(const struct codec_profile_t *vdec_profile); ssize_t vcodec_profile_read(char *buf); diff --git a/include/linux/amlogic/media/vfm/vframe.h b/include/linux/amlogic/media/vfm/vframe.h index c2936f3f3eca..132078c9af60 100644 --- a/include/linux/amlogic/media/vfm/vframe.h +++ b/include/linux/amlogic/media/vfm/vframe.h @@ -45,6 +45,8 @@ #define VIDTYPE_PIC 0x200000 #define VIDTYPE_SCATTER 0x400000 #define VIDTYPE_VD2 0x800000 +#define VIDTYPE_COMPRESS_LOSS 0x1000000 +#define VIDTYPE_COMB_MODE 0x2000000 #define DISP_RATIO_FORCECONFIG 0x80000000 #define DISP_RATIO_FORCE_NORMALWIDE 0x40000000 @@ -280,18 +282,21 @@ struct vframe_pic_mode_s { #define BITDEPTH_Y8 (0 << BITDEPTH_Y_SHIFT) #define BITDEPTH_Y9 (1 << BITDEPTH_Y_SHIFT) #define BITDEPTH_Y10 (2 << BITDEPTH_Y_SHIFT) +#define BITDEPTH_Y12 (3 << BITDEPTH_Y_SHIFT) #define BITDEPTH_YMASK (3 << BITDEPTH_Y_SHIFT) #define BITDEPTH_U_SHIFT 10 #define BITDEPTH_U8 (0 << BITDEPTH_U_SHIFT) #define BITDEPTH_U9 (1 << BITDEPTH_U_SHIFT) #define BITDEPTH_U10 (2 << BITDEPTH_U_SHIFT) +#define BITDEPTH_U12 (3 << BITDEPTH_U_SHIFT) #define BITDEPTH_UMASK (3 << BITDEPTH_U_SHIFT) #define BITDEPTH_V_SHIFT 12 #define BITDEPTH_V8 (0 << BITDEPTH_V_SHIFT) #define BITDEPTH_V9 (1 << BITDEPTH_V_SHIFT) #define BITDEPTH_V10 (2 << BITDEPTH_V_SHIFT) +#define BITDEPTH_V12 (3 << BITDEPTH_V_SHIFT) #define BITDEPTH_VMASK (3 << BITDEPTH_V_SHIFT) #define BITDEPTH_MASK (BITDEPTH_YMASK | BITDEPTH_UMASK | BITDEPTH_VMASK) @@ -385,7 +390,6 @@ struct vframe_s { u64 ready_jiffies64; /* ready from decode on jiffies_64 */ long long ready_clock[5];/*ns*/ long long ready_clock_hist[2];/*ns*/ - atomic_t use_cnt; u32 frame_dirty; /* *prog_proc_config: @@ -406,6 +410,9 @@ struct vframe_s { struct vframe_pic_mode_s pic_mode; unsigned long v4l_mem_handle; + + u32 sar_width; + u32 sar_height; } /*vframe_t */; #if 0 diff --git a/include/linux/amlogic/media/vfm/vframe_provider.h b/include/linux/amlogic/media/vfm/vframe_provider.h index 157359a5a021..014f16373fcc 100644 --- a/include/linux/amlogic/media/vfm/vframe_provider.h +++ b/include/linux/amlogic/media/vfm/vframe_provider.h @@ -92,6 +92,7 @@ extern int vf_notify_provider(const char *receiver_name, int event_type, extern int vf_notify_provider_by_name(const char *provider_name, int event_type, void *data); +void vf_light_reg_provider(struct vframe_provider_s *prov); void vf_light_unreg_provider(struct vframe_provider_s *prov); void vf_ext_light_unreg_provider(struct vframe_provider_s *prov); struct vframe_provider_s *vf_get_provider(const char *name); diff --git a/include/linux/amlogic/media/vfm/vframe_receiver.h b/include/linux/amlogic/media/vfm/vframe_receiver.h index eac4cd806c30..74ed8487f554 100644 --- a/include/linux/amlogic/media/vfm/vframe_receiver.h +++ b/include/linux/amlogic/media/vfm/vframe_receiver.h @@ -39,6 +39,7 @@ #define VFRAME_EVENT_PROVIDER_FR_HINT 13 #define VFRAME_EVENT_PROVIDER_FR_END_HINT 14 #define VFRAME_EVENT_PROVIDER_QUREY_DISPLAY_INFO 15 +#define VFRAME_EVENT_PROVIDER_PROPERTY_CHANGED 16 enum receviver_start_e { RECEIVER_STATE_NULL = -1, diff --git a/include/linux/amlogic/media/video_sink/video.h b/include/linux/amlogic/media/video_sink/video.h index 548fcea8d7fa..6004ec2b5009 100644 --- a/include/linux/amlogic/media/video_sink/video.h +++ b/include/linux/amlogic/media/video_sink/video.h @@ -17,7 +17,19 @@ #ifndef VIDEO_H #define VIDEO_H -#include "vpp.h" + +#define MAX_VD_LAYERS 2 + +#define LAYER1_BUSY (1 << 11) +#define LAYER1_AFBC (1 << 10) +#define LAYER1_SCALER (1 << 9) +#define LAYER1_AVAIL (1 << 8) +#define LAYER0_BUSY (1 << 3) +#define LAYER0_AFBC (1 << 2) +#define LAYER0_SCALER (1 << 1) +#define LAYER0_AVAIL (1 << 0) + +#define LAYER_BITS_SHFIT 8 enum { VIDEO_WIDEOPTION_NORMAL = 0, @@ -39,16 +51,6 @@ enum { VIDEO_WIDEOPTION_MAX = 16 }; -extern bool pre_scaler_en; -extern bool super_scaler; -#define VIDEO_NOTIFY_TRICK_WAIT 0x01 -#define VIDEO_NOTIFY_PROVIDER_GET 0x02 -#define VIDEO_NOTIFY_PROVIDER_PUT 0x04 -#define VIDEO_NOTIFY_FRAME_WAIT 0x08 -#define VIDEO_NOTIFY_POS_CHANGED 0x10 - -#if 1 /* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */ - /* TODO: move to register headers */ #define VPP_VADJ2_BLMINUS_EN (1 << 3) #define VPP_VADJ2_EN (1 << 2) @@ -97,7 +99,11 @@ extern bool super_scaler; #define VPP_POST_FG_SEL_MASK (1 << 4) #define VPP_POST_FG_OSD2 (1 << 4) #define VPP_POST_FG_OSD1 (0 << 4) +#define DNLP_SR1_CM (1 << 3) +#define SR1_AFTER_POSTBLEN (0 << 3) #define VPP_FIFO_RESET_DE (1 << 2) +#define PREBLD_SR0_VD1_SCALER (1 << 1) +#define SR0_AFTER_DNLP (0 << 1) #define VPP_OUT_SATURATE (1 << 0) #define VDIF_RESET_ON_GO_FIELD (1<<29) @@ -160,7 +166,7 @@ extern bool super_scaler; #define VPP_PHASECTL_TYPE_INTERLACE (1<<16) #define VPP_PHASECTL_VSL0B (1<<15) #define VPP_PHASECTL_DOUBLELINE_BIT 17 -#define VPP_PHASECTL_DOUBLELINE_WID 1 +#define VPP_PHASECTL_DOUBLELINE_WID 2 #define VPP_PHASECTL_INIRPTNUM_MASK 0x3 #define VPP_PHASECTL_INIRPTNUM_WID 2 #define VPP_PHASECTL_INIRPTNUMB_BIT 13 @@ -207,11 +213,7 @@ extern bool super_scaler; #define VPP_FORCE_FIELD_BOTTOM (1 << 16) #define VPP_FOURCE_GO_FIELD (1 << 15) #define VPP_FOURCE_GO_LINE (1 << 14) -#if 1 /* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */ #define VPP_OFIFO_SIZE_WID 13 -#else -#define VPP_OFIFO_SIZE_WID 12 -#endif /* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */ #define VPP_OFIFO_SIZE_MASK 0xfff #define VPP_OFIFO_SIZE_BIT 0 @@ -226,44 +228,6 @@ extern bool super_scaler; #define VPP_COEF_INDEX_MASK 0x7f #define VPP_COEF_INDEX_BIT 0 -#define P_VFIFO2VD_LINE_TOP_START P_ENCP_VFIFO2VD_LINE_TOP_START -#endif - -#if 0 /* MESON_CPU_TYPE < MESON_CPU_TYPE_MESON8 */ -#define READ_VCBUS_REG(r) READ_CBUS_REG(r) -#define WRITE_VCBUS_REG(r, val) WRITE_CBUS_REG(r, val) -#define WRITE_VCBUS_REG_BITS(r, val, from, size) \ - WRITE_CBUS_REG_BITS(r, val, from, size) -#define SET_VCBUS_REG_MASK(r, mask) SET_CBUS_REG_MASK(r, mask) -#define CLEAR_VCBUS_REG_MASK(r, mask) CLEAR_CBUS_REG_MASK(r, mask) -#endif - -#ifdef CONFIG_CLK81_DFS -extern int check_and_set_clk81(void); -#endif - -#ifdef CONFIG_GAMMA_PROC -extern int gamma_adjust(void); -#endif -#ifdef CONFIG_SCREEN_ON_EARLY -extern void osd_resume_early(void); -extern void vout_pll_resume_early(void); -extern void resume_vout_early(void); -extern int power_key_pressed; -#endif - -#ifdef CONFIG_AM_VIDEO2 -extern void set_clone_frame_rate(unsigned int frame_rate, unsigned int delay); -#endif -extern struct vframe_provider_s *vf_get_provider_by_name( - const char *provider_name); - -extern void prot_get_parameter(u32 wide_mode, struct vframe_s *vf, - struct vpp_frame_par_s *next_frame_par, - const struct vinfo_s *vinfo); -u32 get_blackout_policy(void); -int get_video0_frame_info(struct vframe_s *vf); - #define AMVIDEO_UPDATE_OSD_MODE 0x00000001 #ifdef CONFIG_AMLOGIC_MEDIA_VIDEO int amvideo_notifier_call_chain(unsigned long val, void *v); @@ -275,8 +239,13 @@ static inline int amvideo_notifier_call_chain(unsigned long val, void *v) #endif int query_video_status(int type, int *value); -int get_video0_frame_info(struct vframe_s *vf); -struct device *get_video_device(void); +u32 set_blackout_policy(int policy); +u32 get_blackout_policy(void); +u32 set_blackout_pip_policy(int policy); +u32 get_blackout_pip_policy(void); +void set_video_angle(u32 s_value); +u32 get_video_angle(void); extern unsigned int DI_POST_REG_RD(unsigned int addr); extern int DI_POST_WR_REG_BITS(u32 adr, u32 val, u32 start, u32 len); +extern void videosync_pcrscr_update(s32 inc, u32 base); #endif /* VIDEO_H */ diff --git a/include/linux/amlogic/media/video_sink/video_keeper.h b/include/linux/amlogic/media/video_sink/video_keeper.h index 159469038621..8794407be2dc 100644 --- a/include/linux/amlogic/media/video_sink/video_keeper.h +++ b/include/linux/amlogic/media/video_sink/video_keeper.h @@ -21,12 +21,17 @@ #include void video_keeper_new_frame_notify(void); +void video_pip_keeper_new_frame_notify(void); void try_free_keep_video(int flags); +void try_free_keep_videopip(int flags); int __init video_keeper_init(void); void __exit video_keeper_exit(void); unsigned int vf_keep_current( struct vframe_s *cur_dispbuf, struct vframe_s *cur_dispbuf2); +unsigned int vf_keep_pip_current_locked( + struct vframe_s *cur_dispbuf, + struct vframe_s *cur_dispbuf_el); #endif diff --git a/include/linux/amlogic/media/video_sink/vpp.h b/include/linux/amlogic/media/video_sink/vpp.h index b4293104c838..3520e9c9c49c 100644 --- a/include/linux/amlogic/media/video_sink/vpp.h +++ b/include/linux/amlogic/media/video_sink/vpp.h @@ -17,8 +17,13 @@ #ifndef VPP_H #define VPP_H + #include -#include + +#define TV_3D_FUNCTION_OPEN +#define TV_REVERSE + +extern bool super_scaler; #define VPP_FLAG_WIDEMODE_MASK 0x0000000F #define VPP_FLAG_INTERLACE_OUT 0x00000010 @@ -29,6 +34,7 @@ #define VPP_FLAG_AR_BITS 8 #define VPP_FLAG_PORTRAIT_MODE 0x00040000 #define VPP_FLAG_VSCALE_DISABLE 0x00080000 +#define VPP_FLAG_MORE_LOG 0x00100000 #define IDX_H (2 << 8) #define IDX_V_Y (1 << 13) @@ -43,6 +49,12 @@ #define SPEED_CHECK_HSKIP 1 #define SPEED_CHECK_VSKIP 2 +enum vppfilter_state_e { + VppFilter_Fail = -1, + VppFilter_Success = 0, + VppFilter_Success_and_Changed, +}; + enum f2v_vphase_type_e { F2V_IT2IT = 0, F2V_IB2IB, @@ -54,7 +66,7 @@ enum f2v_vphase_type_e { F2V_IB2P, F2V_P2P, F2V_TYPE_MAX -}; /* frame to video conversion type */ +}; /* frame to video conversion type */ struct f2v_vphase_s { s8 repeat_skip; @@ -140,33 +152,60 @@ struct vpp_frame_par_s { bool nocomp; + u8 sr0_position; + u8 sr1_position; + u8 sr_core_support; }; -#if 1 +struct disp_info_s { + u8 layer_id; -/* - *(MESON_CPU_TYPE==MESON_CPU_TYPE_MESON6TV)|| - *(MESON_CPU_TYPE==MESON_CPU_TYPE_MESONG9TV) - */ -#define TV_3D_FUNCTION_OPEN -#endif + u32 angle; + u32 custom_ar; -#define TV_REVERSE + bool reverse; + u32 proc_3d_type; + bool vpp_3d_scale; + u32 nonlinear_factor; -#ifdef TV_REVERSE -extern bool reverse; -#endif -extern bool platform_type; + u32 wide_mode; + u32 zoom_ratio; + s32 zoom_center_x; + s32 zoom_center_y; + s32 layer_top; + s32 layer_left; + s32 layer_width; + s32 layer_height; + u32 crop_top; + u32 crop_left; + u32 crop_bottom; + u32 crop_right; + s32 global_offset_x; + s32 global_offset_y; + u32 speed_check_width; + u32 speed_check_height; + + u32 zorder; + u32 cur_sel_port; + u32 last_sel_port; + + bool afbc_support; + bool pps_support; +}; enum select_scaler_path_e { - CORE0_PPS_CORE1 = 0, - CORE0_CORE1_PPS, + CORE0_PPS_CORE1 = 0, /*CORE0_PPS_CORE1_POSTBLEND*/ + CORE0_CORE1_PPS, /*CORE0_PPS_POSTBLEND_CORE1*/ /*gxlx only have core1,support below two mode*/ CORE1_BEFORE_PPS, CORE1_AFTER_PPS, /*txhd only have core0,support below two mode*/ CORE0_BEFORE_PPS, CORE0_AFTER_PPS, + /*tl1 have core0/core1, support below mode*/ + PPS_CORE0_CORE1, + PPS_CORE0_POSTBLEND_CORE1, + CORE0_PPS_POSTBLEND_CORE1, SCALER_PATH_MAX, }; /* @@ -184,7 +223,6 @@ enum select_scaler_path_e { #ifdef TV_3D_FUNCTION_OPEN - /*cmd use for 3d operation*/ #define MODE_3D_DISABLE 0x00000000 #define MODE_3D_ENABLE 0x00000001 @@ -219,11 +257,16 @@ enum select_scaler_path_e { #define MODE_3D_OUT_FA_MASK \ (MODE_3D_OUT_FA_L_FIRST | \ - MODE_3D_OUT_FA_R_FIRST|MODE_3D_OUT_FA_LB_FIRST|MODE_3D_OUT_FA_RB_FIRST) + MODE_3D_OUT_FA_R_FIRST | \ + MODE_3D_OUT_FA_LB_FIRST | \ + MODE_3D_OUT_FA_RB_FIRST) #define MODE_3D_TO_2D_MASK \ - (MODE_3D_TO_2D_L|MODE_3D_TO_2D_R|MODE_3D_OUT_FA_MASK | \ - MODE_FORCE_3D_TO_2D_LR | MODE_FORCE_3D_TO_2D_TB) + (MODE_3D_TO_2D_L | \ + MODE_3D_TO_2D_R | \ + MODE_3D_OUT_FA_MASK | \ + MODE_FORCE_3D_TO_2D_LR | \ + MODE_FORCE_3D_TO_2D_TB) #define VPP_3D_MODE_NULL 0x0 #define VPP_3D_MODE_LR 0x1 @@ -237,78 +280,43 @@ enum select_scaler_path_e { #define VPP_PIC0_FIRST 0x0 #define VPP_PIC1_FIRST 0x8 -extern -void vpp_set_3d_scale(bool enable); -extern -void get_vpp_3d_mode(u32 process_3d_type, u32 trans_fmt, u32 *vpp_3d_mode); +extern void get_vpp_3d_mode(u32 process_3d_type, + u32 trans_fmt, u32 *vpp_3d_mode); #endif -extern void -vpp_set_filters(u32 process_3d_type, u32 wide_mode, struct vframe_s *vf, - struct vpp_frame_par_s *next_frame_par, - const struct vinfo_s *vinfo, - bool bypass_sr); +extern int vpp_set_filters( + struct disp_info_s *input, + struct vframe_s *vf, + struct vpp_frame_par_s *next_frame_par, + const struct vinfo_s *vinfo, + bool bypass_sr, u32 op_flag); -extern void vpp_set_video_source_crop(u32 t, u32 l, u32 b, u32 r); +extern s32 vpp_set_nonlinear_factor( + struct disp_info_s *info, u32 f); -extern void vpp_get_video_source_crop(u32 *t, u32 *l, u32 *b, u32 *r); +extern u32 vpp_get_nonlinear_factor( + struct disp_info_s *info); -extern void vpp_set_video_layer_position(s32 x, s32 y, s32 w, s32 h); - -extern void vpp_get_video_layer_position(s32 *x, s32 *y, s32 *w, s32 *h); - -extern void vpp_set_global_offset(s32 x, s32 y); - -extern void vpp_get_global_offset(s32 *x, s32 *y); - -extern void vpp_set_zoom_ratio(u32 r); - -extern u32 vpp_get_zoom_ratio(void); - -extern void vpp_set_osd_layer_preblend(u32 *enable); - -extern void vpp_set_osd_layer_position(s32 *para); - -extern s32 vpp_set_nonlinear_factor(u32 f); - -extern u32 vpp_get_nonlinear_factor(void); - -extern void vpp_set_video_speed_check(u32 h, u32 w); - -extern void vpp_get_video_speed_check(u32 *h, u32 *w); +extern void vpp_disp_info_init( + struct disp_info_s *info, u8 id); extern void vpp_super_scaler_support(void); extern void vpp_bypass_ratio_config(void); -#ifdef CONFIG_AM_VIDEO2 -extern void -vpp2_set_filters(u32 wide_mode, struct vframe_s *vf, - struct vpp_frame_par_s *next_frame_par, - const struct vinfo_s *vinfo); - -extern void vpp2_set_video_layer_position(s32 x, s32 y, s32 w, s32 h); - -extern void vpp2_get_video_layer_position(s32 *x, s32 *y, s32 *w, s32 *h); - -extern void vpp2_set_zoom_ratio(u32 r); - -extern u32 vpp2_get_zoom_ratio(void); -#endif -extern int video_property_notify(int flag); - -extern int vpp_set_super_scaler_regs(int scaler_path_sel, - int reg_srscl0_enable, - int reg_srscl0_hsize, - int reg_srscl0_vsize, - int reg_srscl0_hori_ratio, - int reg_srscl0_vert_ratio, - int reg_srscl1_enable, - int reg_srscl1_hsize, - int reg_srscl1_vsize, - int reg_srscl1_hori_ratio, - int reg_srscl1_vert_ratio, - int vpp_postblend_out_width, - int vpp_postblend_out_height); +extern int vpp_set_super_scaler_regs( + int scaler_path_sel, + int reg_srscl0_enable, + int reg_srscl0_hsize, + int reg_srscl0_vsize, + int reg_srscl0_hori_ratio, + int reg_srscl0_vert_ratio, + int reg_srscl1_enable, + int reg_srscl1_hsize, + int reg_srscl1_vsize, + int reg_srscl1_hori_ratio, + int reg_srscl1_vert_ratio, + int vpp_postblend_out_width, + int vpp_postblend_out_height); #endif /* VPP_H */ diff --git a/include/linux/amlogic/media/vout/hdmi_tx/hdmi_common.h b/include/linux/amlogic/media/vout/hdmi_tx/hdmi_common.h index e6c8e9cc52f4..08a5a4789e42 100644 --- a/include/linux/amlogic/media/vout/hdmi_tx/hdmi_common.h +++ b/include/linux/amlogic/media/vout/hdmi_tx/hdmi_common.h @@ -30,6 +30,13 @@ #define HDMITX_VIC_MASK 0xff +/* Refer to http://standards-oui.ieee.org/oui/oui.txt */ +#define HDMI_IEEEOUI 0x000C03 +#define HF_IEEEOUI 0xC45DD8 +#define GET_OUI_BYTE0(oui) (oui & 0xff) /* Little Endian */ +#define GET_OUI_BYTE1(oui) ((oui >> 8) & 0xff) +#define GET_OUI_BYTE2(oui) ((oui >> 16) & 0xff) + enum hdmi_vic { /* Refer to CEA 861-D */ HDMI_Unknown = 0, diff --git a/include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_module.h b/include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_module.h index 173d0220b45b..f812e02607a1 100644 --- a/include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_module.h +++ b/include/linux/amlogic/media/vout/hdmi_tx/hdmi_tx_module.h @@ -42,6 +42,7 @@ #define MESON_CPU_ID_TXHD 9 #define MESON_CPU_ID_G12A 10 #define MESON_CPU_ID_G12B 11 +#define MESON_CPU_ID_SM1 12 /***************************** @@ -93,9 +94,9 @@ struct rx_cap { unsigned char AUD_count; unsigned char RxSpeakerAllocation; /*vendor*/ - unsigned int IEEEOUI; + unsigned int ieeeoui; unsigned char Max_TMDS_Clock1; /* HDMI1.4b TMDS_CLK */ - unsigned int HF_IEEEOUI; /* For HDMI Forum */ + unsigned int hf_ieeeoui; /* For HDMI Forum */ unsigned int Max_TMDS_Clock2; /* HDMI2.0 TMDS_CLK */ /* CEA861-F, Table 56, Colorimetry Data Block */ unsigned int colorimetry_data; @@ -109,6 +110,11 @@ struct rx_cap { unsigned int dc_30bit_420:1; unsigned int dc_36bit_420:1; unsigned int dc_48bit_420:1; + unsigned int max_frl_rate:4; + unsigned int fpap_start_loc:1; + unsigned int allm:1; + unsigned int mdelta:1; + unsigned int fva:1; unsigned int hdr_sup_eotf_sdr:1; unsigned int hdr_sup_eotf_hdr:1; unsigned int hdr_sup_eotf_smpte_st_2084:1; @@ -130,10 +136,10 @@ struct rx_cap { unsigned char edid_version; unsigned char edid_revision; unsigned char ColorDeepSupport; - unsigned int Video_Latency; - unsigned int Audio_Latency; - unsigned int Interlaced_Video_Latency; - unsigned int Interlaced_Audio_Latency; + unsigned int vLatency; + unsigned int aLatency; + unsigned int i_vLatency; + unsigned int i_aLatency; unsigned int threeD_present; unsigned int threeD_Multi_present; unsigned int hdmi_vic_LEN; @@ -300,9 +306,8 @@ struct hdmitx_dev { struct pinctrl_state *pinctrl_default; struct delayed_work work_hpd_plugin; struct delayed_work work_hpd_plugout; - struct delayed_work work_aud_hpd_plug; struct delayed_work work_rxsense; - struct work_struct work_internal_intr; + struct delayed_work work_internal_intr; struct work_struct work_hdr; struct delayed_work work_do_hdcp; #ifdef CONFIG_AML_HDMI_TX_14 @@ -323,6 +328,12 @@ struct hdmitx_dev { struct { void (*SetPacket)(int type, unsigned char *DB, unsigned char *HB); + /* In original SetPacket, there are many policys, like + * if ((DB[4] >> 4) == T3D_FRAME_PACKING) + * Need a only pure data packet to call + */ + void (*SetDataPacket)(int type, unsigned char *DB, + unsigned char *HB); void (*SetAudioInfoFrame)(unsigned char *AUD_DB, unsigned char *CHAN_STAT_BUF); int (*SetDispMode)(struct hdmitx_dev *hdmitx_device); @@ -409,6 +420,8 @@ struct hdmitx_dev { /* 0.1% clock shift, 1080p60hz->59.94hz */ unsigned int frac_rate_policy; unsigned int rxsense_policy; + /* allm_mode: 1/game, 2/graphcis, 3/photo, 4/cinema */ + unsigned int allm_mode; unsigned int sspll; /* configure for I2S: 8ch in, 2ch out */ /* 0: default setting 1:ch0/1 2:ch2/3 3:ch4/5 4:ch6/7 */ @@ -433,7 +446,9 @@ struct hdmitx_dev { unsigned int flag_3dfp:1; unsigned int flag_3dtb:1; unsigned int flag_3dss:1; + unsigned int dongle_mode:1; unsigned int drm_feature;/*Direct Rander Management*/ + unsigned int cec_func_config; }; #define CMD_DDC_OFFSET (0x10 << 24) @@ -494,6 +509,13 @@ struct hdmitx_dev { #define YCC_RANGE_LIM 0 #define YCC_RANGE_FUL 1 #define YCC_RANGE_RSVD 2 +#define CONF_ALLM_MODE (CMD_CONF_OFFSET + 0X2000 + 0x04) + #define SET_ALLM_GRAPHICS 0 + #define SET_ALLM_PHOTO 1 + #define SET_ALLM_CINEMA 2 + #define SET_ALLM_GAME 3 + #define CLEAR_ALLM_MODE 0xf + #define GET_ALLM_MODE 0x10 #define CONF_VIDEO_MUTE_OP (CMD_CONF_OFFSET + 0x1000 + 0x04) #define VIDEO_MUTE 0x1 #define VIDEO_UNMUTE 0x2 @@ -596,6 +618,42 @@ extern void hdmitx_edid_buf_compare_print(struct hdmitx_dev *hdmitx_device); extern const char *hdmitx_edid_get_native_VIC(struct hdmitx_dev *hdmitx_device); +/* VSIF: Vendor Specific InfoFrame + * It has multiple purposes: + * 1. HDMI1.4 4K, HDMI_VIC=1/2/3/4, 2160p30/25/24hz, smpte24hz, AVI.VIC=0 + * In CTA-861-G, matched with AVI.VIC=95/94/93/98 + * 2. 3D application, TB/SS/FP + * 3. DolbyVision, with Len=0x18 + * 4. HDR10plus + * 5. HDMI20 3D OSD disparity / 3D dual-view / 3D independent view / ALLM + * Some functions are exclusive, but some may compound. + * Consider various state transitions carefully, such as play 3D under HDMI14 + * 4K, exit 3D under 4K, play DV under 4K, enable ALLM under 3D dual-view + */ +enum vsif_type { + /* Below 4 functions are exclusive */ + VT_HDMI14_4K = 1, + VT_T3D_VIDEO, + VT_DOLBYVISION, + VT_HDR10PLUS, + /* Maybe compound 3D dualview + ALLM */ + VT_T3D_OSD_DISPARITY = 0x10, + VT_T3D_DUALVIEW, + VT_T3D_INDEPENDVEW, + VT_ALLM, + /* default: if non-HDMI4K, no any vsif; if HDMI4k, = VT_HDMI14_4K */ + VT_DEFAULT, + VT_MAX, +}; +int hdmitx_construct_vsif(struct hdmitx_dev *hdev, enum vsif_type type, int on, + void *param); + +/* if vic is 93 ~ 95, or 98 (HDMI14 4K), return 1 */ +bool is_hdmi14_4k(enum hdmi_vic vic); + +/* set vic to AVI.VIC */ +void hdmitx_set_avi_vic(enum hdmi_vic vic); + /* * HDMI Repeater TX I/F * RX downstream Information from rptx to rprx diff --git a/include/linux/amlogic/media/vout/lcd/aml_bl.h b/include/linux/amlogic/media/vout/lcd/aml_bl.h index 67b65e1072ce..4b33bcb24076 100644 --- a/include/linux/amlogic/media/vout/lcd/aml_bl.h +++ b/include/linux/amlogic/media/vout/lcd/aml_bl.h @@ -50,6 +50,8 @@ enum bl_chip_type_e { BL_CHIP_G12A, BL_CHIP_G12B, BL_CHIP_TL1, + BL_CHIP_SM1, + BL_CHIP_TM2, BL_CHIP_MAX, }; @@ -196,5 +198,14 @@ extern void bl_pwm_ctrl(struct bl_pwm_config_s *bl_pwm, int status); #define BL_GPIO_OUTPUT_HIGH 1 #define BL_GPIO_INPUT 2 +static inline unsigned int bl_do_div(unsigned long long num, unsigned int den) +{ + unsigned long long ret = num; + + do_div(ret, den); + + return (unsigned int)ret; +} + #endif diff --git a/include/linux/amlogic/media/vout/lcd/aml_ldim.h b/include/linux/amlogic/media/vout/lcd/aml_ldim.h index 72cf7efd8ca8..c066b0539e6e 100644 --- a/include/linux/amlogic/media/vout/lcd/aml_ldim.h +++ b/include/linux/amlogic/media/vout/lcd/aml_ldim.h @@ -81,10 +81,15 @@ struct ldim_dev_config_s { unsigned int init_on_cnt; unsigned int init_off_cnt; - struct bl_pwm_config_s pwm_config; + struct bl_pwm_config_s ldim_pwm_config; + struct bl_pwm_config_s analog_pwm_config; unsigned short bl_regnum; unsigned short bl_mapping[LD_BLKREGNUM]; + + void (*dim_range_update)(void); + int (*dev_reg_write)(unsigned char *buf, unsigned int len); + int (*dev_reg_read)(unsigned char *buf, unsigned int len); }; /*******global API******/ @@ -92,6 +97,7 @@ struct aml_ldim_driver_s { unsigned char valid_flag; unsigned char dev_index; unsigned char static_pic_flag; + unsigned char vsync_change_flag; unsigned char pinmux_flag; struct ldim_config_s *ldim_conf; diff --git a/include/linux/amlogic/media/vout/lcd/lcd_unifykey.h b/include/linux/amlogic/media/vout/lcd/lcd_unifykey.h index 2204c6c2f10b..c27f57fe2be4 100644 --- a/include/linux/amlogic/media/vout/lcd/lcd_unifykey.h +++ b/include/linux/amlogic/media/vout/lcd/lcd_unifykey.h @@ -18,7 +18,8 @@ #ifndef _INC_AML_LCD_UNIFYKEY_H__ #define _INC_AML_LCD_UNIFYKEY_H__ -#define LCD_UNIFYKEY_WAIT_TIMEOUT 300 +#define LCD_UNIFYKEY_WAIT_TIMEOUT 500 +#define LCD_UNIFYKEY_RETRY_INTERVAL 20 /* ms */ /* declare external unifykey function */ extern void *get_ukdev(void); diff --git a/include/linux/amlogic/media/vout/lcd/lcd_vout.h b/include/linux/amlogic/media/vout/lcd/lcd_vout.h index ebf689fd44db..60fc89d65e7a 100644 --- a/include/linux/amlogic/media/vout/lcd/lcd_vout.h +++ b/include/linux/amlogic/media/vout/lcd/lcd_vout.h @@ -24,6 +24,8 @@ #include #include +extern void lcd_vlock_m_update(unsigned int vlock_m); +extern void lcd_vlock_frac_update(unsigned int vlock_farc); /* ********************************** * debug print define @@ -67,6 +69,7 @@ extern unsigned char lcd_debug_print_flag; * ********************************** */ #define TTL_DELAY 13 +#define PRE_DE_DELAY 8 /* ********************************** @@ -89,6 +92,8 @@ enum lcd_chip_e { LCD_CHIP_G12A, /* 5 */ LCD_CHIP_G12B, /* 6 */ LCD_CHIP_TL1, /* 7 */ + LCD_CHIP_SM1, /* 8 */ + LCD_CHIP_TM2, /* 9 */ LCD_CHIP_MAX, }; @@ -133,17 +138,19 @@ struct lcd_basic_s { #define LCD_CLK_PLL_CHANGE (1 << 1) struct lcd_timing_s { unsigned char clk_auto; /* clk parameters auto generation */ + unsigned char fr_adjust_type; /* 0=clock, 1=htotal, 2=vtotal */ + unsigned char clk_change; /* internal used */ unsigned int lcd_clk; /* pixel clock(unit: Hz) */ unsigned int lcd_clk_dft; /* internal used */ + unsigned int bit_rate; /* Hz */ unsigned int h_period_dft; /* internal used */ unsigned int v_period_dft; /* internal used */ - unsigned char clk_change; /* internal used */ unsigned int pll_ctrl; /* pll settings */ unsigned int div_ctrl; /* divider settings */ unsigned int clk_ctrl; /* clock settings */ - - unsigned char fr_adjust_type; /* 0=clock, 1=htotal, 2=vtotal */ - unsigned char ss_level; + unsigned int ss_level; /* [15:12]: ss_freq, [11:8]: ss_mode, + * [7:0]: ss_level + */ unsigned int sync_duration_num; unsigned int sync_duration_den; @@ -234,7 +241,6 @@ struct vbyone_config_s { unsigned int byte_mode; unsigned int color_fmt; unsigned int phy_div; - unsigned int bit_rate; unsigned int phy_vswing; /*[4]:ext_pullup, [3:0]vswing*/ unsigned int phy_preem; unsigned int intr_en; @@ -291,7 +297,6 @@ struct dsi_config_s { unsigned char lane_num; unsigned int bit_rate_max; /* MHz */ unsigned int bit_rate_min; /* MHz*/ - unsigned int bit_rate; /* Hz */ unsigned int clk_factor; /* bit_rate/pclk */ unsigned int factor_numerator; unsigned int factor_denominator; /* 100 */ @@ -332,24 +337,28 @@ struct mlvds_config_s { /* internal used */ unsigned int pi_clk_sel; /* bit[9:0] */ - unsigned int bit_rate; /* Hz */ +}; + +enum p2p_type_e { + P2P_CEDS = 0, + P2P_CMPI, + P2P_ISP, + P2P_EPI, + P2P_CHPI = 0x10, /* low common mode */ + P2P_CSPI, + P2P_USIT, + P2P_MAX, }; struct p2p_config_s { - unsigned int channel_num; + unsigned int p2p_type; + unsigned int lane_num; unsigned int channel_sel0; unsigned int channel_sel1; - unsigned int clk_phase; /* [13:12]=clk01_pi_sel, - * [11:8]=pi2, [7:4]=pi1, [3:0]=pi0 - */ unsigned int pn_swap; unsigned int bit_swap; /* MSB/LSB reverse */ unsigned int phy_vswing; unsigned int phy_preem; - - /* internal used */ - unsigned int pi_clk_sel; /* bit[9:0] */ - unsigned int bit_rate; /* Hz */ }; struct lcd_control_config_s { @@ -371,6 +380,8 @@ enum lcd_power_type_e { LCD_POWER_TYPE_PMU, LCD_POWER_TYPE_SIGNAL, LCD_POWER_TYPE_EXTERN, + LCD_POWER_TYPE_WAIT_GPIO, + LCD_POWER_TYPE_CLK_SS, LCD_POWER_TYPE_MAX, }; @@ -383,6 +394,9 @@ enum lcd_pmu_gpio_e { LCD_PMU_GPIO_MAX, }; +#define LCD_CLK_SS_BIT_FREQ 0 +#define LCD_CLK_SS_BIT_MODE 4 + #define LCD_GPIO_MAX 0xff #define LCD_GPIO_OUTPUT_LOW 0 #define LCD_GPIO_OUTPUT_HIGH 1 diff --git a/include/linux/amlogic/media/vout/vdac_dev.h b/include/linux/amlogic/media/vout/vdac_dev.h index 69031fe1d853..90e409653c5d 100644 --- a/include/linux/amlogic/media/vout/vdac_dev.h +++ b/include/linux/amlogic/media/vout/vdac_dev.h @@ -27,6 +27,7 @@ enum vdac_cpu_type { VDAC_CPU_TXHD = 5, VDAC_CPU_G12AB = 6, VDAC_CPU_TL1 = 7, + VDAC_CPU_SM1 = 8, VDAC_CPU_MAX, }; diff --git a/include/linux/amlogic/media/vout/vinfo.h b/include/linux/amlogic/media/vout/vinfo.h index dfafcaf6d2a6..6ef397b9a0cb 100644 --- a/include/linux/amlogic/media/vout/vinfo.h +++ b/include/linux/amlogic/media/vout/vinfo.h @@ -23,7 +23,7 @@ /* the MSB is represent vmode set by vmode_init */ #define VMODE_INIT_BIT_MASK 0x8000 #define VMODE_MODE_BIT_MASK 0xff -#define VMODE_NULL_DISP_MAX 2 +#define VMODE_NULL_DISP_MAX 3 enum vmode_e { VMODE_HDMI = 0, @@ -31,6 +31,7 @@ enum vmode_e { VMODE_LCD, VMODE_NULL, /* null mode is used as temporary witch mode state */ VMODE_INVALID, + VMODE_DUMMY_LCD, VMODE_MAX, VMODE_INIT_NULL, VMODE_MASK = 0xFF, @@ -53,6 +54,13 @@ enum vout_fr_adj_type_e { VOUT_FR_ADJ_MAX, }; +enum vinfo_3d_e { + NON_3D = 0, + SS_3D, + FP_3D, + TB_3D, +}; + /*emp : extended metadata type*/ #define VENDOR_SPECIFIC_EM_DATA 0x0 #define COMPRESS_VIDEO_TRAMSPORT 0x1 @@ -233,6 +241,15 @@ struct vinfo_base_s { enum color_fmt_e viu_color_fmt; }; +#define LATENCY_INVALID_UNKNOWN 0 +#define LATENCY_NOT_SUPPORT 0xffff +struct rx_av_latency { + unsigned int vLatency; + unsigned int aLatency; + unsigned int i_vLatency; + unsigned int i_aLatency; +}; + struct vinfo_s { char *name; enum vmode_e mode; @@ -249,11 +266,13 @@ struct vinfo_s { u32 video_clk; u32 htotal; u32 vtotal; + enum vinfo_3d_e info_3d; enum vout_fr_adj_type_e fr_adj_type; enum color_fmt_e viu_color_fmt; enum viu_mux_e viu_mux; struct master_display_info_s master_display_info; struct hdr_info hdr_info; + struct rx_av_latency rx_latency; struct vout_device_s *vout_device; }; diff --git a/include/linux/amlogic/media/vpu/vpu.h b/include/linux/amlogic/media/vpu/vpu.h index 674b44bacb5f..067b0615d43f 100644 --- a/include/linux/amlogic/media/vpu/vpu.h +++ b/include/linux/amlogic/media/vpu/vpu.h @@ -22,24 +22,25 @@ /* VPU module define */ /* ************************************************ */ enum vpu_mod_e { - VPU_VIU_OSD1 = 0, /* reg0[1:0] //common */ - VPU_VIU_OSD2, /* reg0[3:2] //common */ - VPU_VIU_VD1, /* reg0[5:4] //common */ - VPU_VIU_VD2, /* reg0[7:6] //common */ - VPU_VIU_CHROMA, /* reg0[9:8] //common */ - VPU_VIU_OFIFO, /* reg0[11:10] //common */ - VPU_VIU_SCALE, /* reg0[13:12] //common */ - VPU_VIU_OSD_SCALE, /* reg0[15:14] //common */ - VPU_VIU_VDIN0, /* reg0[17:16] //common */ - VPU_VIU_VDIN1, /* reg0[19:18] //common */ - VPU_VIU_SRSCL, /* reg0[21:20] //GXBB, GXTVBB, TXLX */ - VPU_VIU_OSDSR, /* reg0[23:22] //GXBB */ - VPU_AFBC_DEC1, /* reg0[23:22] //GXTVBB, TXLX */ - VPU_VIU_DI_SCALE, /* reg0[25:24] //G12A */ - VPU_DI_PRE, /* reg0[27:26] //common */ - VPU_DI_POST, /* reg0[29:28] //common */ - VPU_SHARP, /* reg0[31:30] //common */ + VPU_VIU_OSD1 = 0, /* reg0[1:0], common */ + VPU_VIU_OSD2, /* reg0[3:2], common */ + VPU_VIU_VD1, /* reg0[5:4], common */ + VPU_VIU_VD2, /* reg0[7:6], common */ + VPU_VIU_CHROMA, /* reg0[9:8], common */ + VPU_VIU_OFIFO, /* reg0[11:10], common */ + VPU_VIU_SCALE, /* reg0[13:12], common */ + VPU_VIU_OSD_SCALE, /* reg0[15:14], common */ + VPU_VIU_VDIN0, /* reg0[17:16], common */ + VPU_VIU_VDIN1, /* reg0[19:18], common */ + VPU_VIU_SRSCL, /* reg0[21:20], GXBB, GXTVBB, TXLX */ + VPU_VIU_OSDSR, /* reg0[23:22], GXBB */ + VPU_AFBC_DEC1, /* reg0[23:22], GXTVBB, TXLX */ + VPU_VIU_DI_SCALE, /* reg0[25:24], G12A */ + VPU_DI_PRE, /* reg0[27:26], common */ + VPU_DI_POST, /* reg0[29:28], common */ + VPU_SHARP, /* reg0[31:30], common */ + VPU_VIU2, /* reg1[3:0], reg2[23:22], SM1 */ VPU_VIU2_OSD1, /* reg1[1:0] */ VPU_VIU2_OSD2, /* reg1[3:2] */ VPU_VIU2_VD1, /* reg1[5:4] */ @@ -47,42 +48,44 @@ enum vpu_mod_e { VPU_VIU2_OFIFO, /* reg1[9:8] */ VPU_VIU2_SCALE, /* reg1[11:10] */ VPU_VIU2_OSD_SCALE, /* reg1[13:12] */ - VPU_VKSTONE, /* reg1[5:4] //TXLX */ - VPU_DOLBY_CORE3, /* reg1[7:6] //TXLX */ - VPU_DOLBY0, /* reg1[9:8] //TXLX */ - VPU_DOLBY1A, /* reg1[11:10] //TXLX */ - VPU_DOLBY1B, /* reg1[13:12] //TXLX */ - VPU_VPU_ARB, /* reg1[15:14] //GXBB, GXTVBB, GXL, TXLX */ - VPU_AFBC_DEC, /* reg1[17:16] //GXBB, GXTVBB, TXL, TXLX */ - VPU_OSD_AFBCD, /* reg1[19:18] //TXLX */ - VPU_VD2_SCALE, /* reg1[19:18] //G12A */ - VPU_VENCP, /* reg1[21:20] //common */ - VPU_VENCL, /* reg1[23:22] //common */ - VPU_VENCI, /* reg1[25:24] //common */ - VPU_LS_STTS, /* reg1[27:26] //tl1 */ - VPU_LDIM_STTS, /* reg1[29:28] //GXTVBB, GXL, TXL, TXLX */ + VPU_VKSTONE, /* reg1[5:4], TXLX */ + VPU_DOLBY_CORE3, /* reg1[7:6], TXLX */ + VPU_DOLBY0, /* reg1[9:8], TXLX */ + VPU_DOLBY1A, /* reg1[11:10], TXLX */ + VPU_DOLBY1B, /* reg1[13:12], TXLX */ + VPU_VPU_ARB, /* reg1[15:14], GXBB, GXTVBB, GXL, TXLX */ + VPU_AFBC_DEC, /* reg1[17:16], GXBB, GXTVBB, TXL, TXLX */ + VPU_OSD_AFBCD, /* reg1[19:18], TXLX */ + VPU_VD2_SCALE, /* reg1[19:18], G12A */ + VPU_VENCP, /* reg1[21:20], common */ + VPU_VENCL, /* reg1[23:22], common */ + VPU_VENCI, /* reg1[25:24], common */ + VPU_LC_STTS, /* reg1[27:26], tl1 */ + VPU_LDIM_STTS, /* reg1[29:28], GXTVBB, GXL, TXL, TXLX */ VPU_TV_DEC_CVD2, /* reg1[29:28] */ - VPU_XVYCC_LUT, /* reg1[31:30] //GXTVBB, GXL, TXL, TXLX */ - VPU_VD2_OSD2_SCALE, /* reg1[31:30] //G12A */ + VPU_XVYCC_LUT, /* reg1[31:30], GXTVBB, GXL, TXL, TXLX */ + VPU_VD2_OSD2_SCALE, /* reg1[31:30], G12A */ - VPU_VIU_WM, /* reg2[1:0] //GXL, TXL, TXLX */ - VPU_TCON, /* reg2[3:2] //TXHD, TL1 */ - VPU_VIU_OSD3, /* reg2[5:4] //G12A */ - VPU_VIU_OSD4, /* reg2[7:6] //G12A */ - VPU_MAIL_AFBCD, /* reg2[9:8] //G12A */ - VPU_VD1_SCALE, /* reg2[11:10] //G12A */ - VPU_OSD_BLD34, /* reg2[13:12] //G12A */ - VPU_PRIME_DOLBY_RAM, /* reg2[15:14] //G12A */ - VPU_VD2_OFIFO, /* reg2[17:16] //G12A */ - VPU_DS, /* reg2[19:18] //TL1 */ - VPU_LUT3D, /* reg2[21:20] //G12B */ - VPU_VIU2_OSD_ROT, /* reg2[23:22] //G12B */ - VPU_VI_DIPRE, /* reg2[27:24] //TL1 */ - VPU_RDMA, /* reg2[31:30] //G12A */ + VPU_VIU_WM, /* reg2[1:0], GXL, TXL, TXLX */ + VPU_TCON, /* reg2[3:2], TXHD, TL1 */ + VPU_VIU_OSD3, /* reg2[5:4], G12A */ + VPU_VIU_OSD4, /* reg2[7:6], G12A */ + VPU_MAIL_AFBCD, /* reg2[9:8], G12A */ + VPU_VD1_SCALE, /* reg2[11:10], G12A */ + VPU_OSD_BLD34, /* reg2[13:12], G12A */ + VPU_PRIME_DOLBY_RAM, /* reg2[15:14], G12A */ + VPU_VD2_OFIFO, /* reg2[17:16], G12A */ + VPU_DS, /* reg2[19:18], TL1 */ + VPU_LUT3D, /* reg2[21:20], G12B */ + VPU_VIU2_OSD_ROT, /* reg2[23:22], G12B */ + VPU_DOLBY_S0, /* reg2[27:26], TM2 */ + VPU_DOLBY_S1, /* reg2[29:28], TM2 */ + VPU_RDMA, /* reg2[31:30], G12A */ - VPU_AXI_WR1, /* reg4[1:0] //TL1 */ - VPU_AXI_WR0, /* reg4[3:2] //TL1 */ - VPU_AFBCE, /* reg4[5:4] //TL1 */ + VPU_AXI_WR1, /* reg4[1:0], TL1 */ + VPU_AXI_WR0, /* reg4[3:2], TL1 */ + VPU_AFBCE, /* reg4[5:4], TL1 */ + VPU_DMA, /* reg4[7:4], TM2 */ VPU_MOD_MAX, diff --git a/include/linux/amlogic/page_trace.h b/include/linux/amlogic/page_trace.h index 7d724303841c..300e7ef0d4f7 100644 --- a/include/linux/amlogic/page_trace.h +++ b/include/linux/amlogic/page_trace.h @@ -92,7 +92,11 @@ static inline struct page_trace *find_page_base(struct page *page) { return NULL; } -static unsigned long find_back_trace(void) +static inline unsigned long find_back_trace(void) +{ + return 0; +} +static inline unsigned long get_page_trace(struct page *page) { return 0; } diff --git a/include/linux/amlogic/pm.h b/include/linux/amlogic/pm.h index 2d71273aec3c..dd1d1d3e108f 100644 --- a/include/linux/amlogic/pm.h +++ b/include/linux/amlogic/pm.h @@ -51,6 +51,8 @@ struct early_suspend { extern void register_early_suspend(struct early_suspend *handler); extern void unregister_early_suspend(struct early_suspend *handler); extern unsigned int lgcy_early_suspend_init(void); +extern unsigned int is_pm_freeze_mode(void); + #endif //CONFIG_AMLOGIC_LEGACY_EARLY_SUSPEND diff --git a/include/linux/amlogic/power_ctrl.h b/include/linux/amlogic/power_ctrl.h new file mode 100644 index 000000000000..3a09e58a52f0 --- /dev/null +++ b/include/linux/amlogic/power_ctrl.h @@ -0,0 +1,48 @@ +/* + * include/linux/amlogic/power_ctrl.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 _POWER_CTRL_H_ +#define _POWER_CTRL_H_ +#include + +#ifdef CONFIG_AMLOGIC_POWER +bool is_support_power_ctrl(void); +int power_ctrl_sleep(bool power_on, unsigned int shift); +int power_ctrl_sleep_mask(bool power_on, + unsigned int mask_val, unsigned int shift); +int power_ctrl_iso(bool power_on, unsigned int shift); +int power_ctrl_iso_mask(bool power_on, + unsigned int mask_val, unsigned int shift); +int power_ctrl_mempd0(bool power_on, unsigned int mask_val, unsigned int shift); +#else +static inline int power_ctrl_sleep(bool power_on, unsigned int shift) +{ + return -EINVAL; +} + +static inline int power_ctrl_iso(bool power_on, unsigned int shift) +{ + return -EINVAL; +} + +static inline int power_ctrl_mempd0(bool power_on, unsigned int mask_val, + unsigned int shift) +{ + return -EINVAL; +} +#endif +#endif /*_POWER_CTRL_H_*/ diff --git a/include/linux/amlogic/ramdump.h b/include/linux/amlogic/ramdump.h index 5dc0c4219e04..8782418c1113 100644 --- a/include/linux/amlogic/ramdump.h +++ b/include/linux/amlogic/ramdump.h @@ -20,7 +20,9 @@ #define SET_REBOOT_REASON 0x82000049 -extern int ramdump_disabled(void); +#define AMLOGIC_KERNEL_BOOTED 0x8000 +#define RAMDUMP_STICKY_DATA_MASK 0xFFFF + extern void ramdump_sync_data(void); #endif /* __RAMDUMP_H__ */ diff --git a/include/linux/amlogic/scpi_protocol.h b/include/linux/amlogic/scpi_protocol.h index 804dcf2278c7..a9d60eb74448 100644 --- a/include/linux/amlogic/scpi_protocol.h +++ b/include/linux/amlogic/scpi_protocol.h @@ -71,12 +71,22 @@ enum scpi_std_cmd { SCPI_CMD_WAKEUP_REASON_GET = 0x30, SCPI_CMD_WAKEUP_REASON_CLR = 0X31, SCPI_CMD_GET_ETHERNET_CALC = 0x32, + SCPI_CMD_GET_CPUINFO = 0x33, + SCPI_CMD_INIT_DSP = 0x34, SCPI_CMD_GET_CEC1 = 0xB4, SCPI_CMD_GET_CEC2 = 0xB5, SCPI_CMD_COUNT }; +enum scpi_get_pfm_type { + SCPI_CPUINFO_CLUSTER0, + SCPI_CPUINFO_CLUSTER1, + SCPI_CPUINFO_VERSION, + SCPI_CPUINFO_SLT, + SCPI_CPUINFO_NUMS +}; + struct scpi_opp_entry { u32 freq_hz; u32 volt_mv; @@ -88,7 +98,6 @@ struct scpi_dvfs_info { struct scpi_opp_entry *opp; } __packed; - unsigned long scpi_clk_get_val(u16 clk_id); int scpi_clk_set_val(u16 clk_id, unsigned long rate); int scpi_dvfs_get_idx(u8 domain); @@ -104,4 +113,6 @@ int scpi_get_wakeup_reason(u32 *wakeup_reason); int scpi_clr_wakeup_reason(void); int scpi_get_cec_val(enum scpi_std_cmd index, u32 *p_cec); u8 scpi_get_ethernet_calc(void); +int scpi_get_cpuinfo(enum scpi_get_pfm_type type, u32 *freq, u32 *vol); +int scpi_init_dsp_cfg0(u32 id, u32 addr, u32 cfg0); #endif /*_SCPI_PROTOCOL_H_*/ diff --git a/include/linux/amlogic/sd.h b/include/linux/amlogic/sd.h index 9fa73a8a99bf..a044f8924a34 100644 --- a/include/linux/amlogic/sd.h +++ b/include/linux/amlogic/sd.h @@ -188,9 +188,12 @@ enum mmc_chip_e { MMC_CHIP_GXLX = 0x26, MMC_CHIP_TXHD = 0x27, MMC_CHIP_G12A = 0x28, - MMC_CHIP_G12B = 0x29, + MMC_CHIP_G12B_A = 0x29, MMC_CHIP_GXLX2 = 0x2a, MMC_CHIP_TL1 = 0X2b, + MMC_CHIP_G12B = 0x29b, + MMC_CHIP_SM1 = 0X2C, + MMC_CHIP_TM2 = 0X2D, }; struct mmc_phase { @@ -279,6 +282,7 @@ struct amlsd_platform { unsigned int dly1; unsigned int dly2; unsigned int intf3; + unsigned int win_start; unsigned int irq_sdio_sleep; unsigned int clock; /* signalling voltage (1.8V or 3.3V) */ @@ -297,6 +301,7 @@ struct amlsd_platform { unsigned int gpio_power; unsigned int power_level; unsigned int calc_f; + unsigned int no_sduart; unsigned int auto_clk_close; unsigned int vol_switch; @@ -329,6 +334,7 @@ struct amlsd_platform { u64 align[10]; int base_line; unsigned int count; + unsigned int cmd_c; unsigned int delay_cell; /* int order; */ unsigned int rx_err; @@ -1540,7 +1546,7 @@ struct sd_emmc_config { /*[18] Spare, ??? need check*/ u32 spare:1; /*[19] Use this descriptor - *even if its owner bit is ???0???бь?ии. + *even if its owner bit is ???0???б??ии. */ u32 ignore_owner:1; /*[20] Check data strobe in HS400.*/ @@ -1573,7 +1579,7 @@ struct sd_emmc_status { *any one of blocks CRC error. */ u32 txd_err:1; - /*[9] SD/eMMC controller doesn???и║?ииt own descriptor. + /*[9] SD/eMMC controller doesn???и??ииt own descriptor. *The owner bit is set cfg_ignore_owner to ignore this error. */ u32 desc_err:1; @@ -1617,7 +1623,7 @@ struct sd_emmc_irq_en { u32 rxd_err:8; /*[8] TX data CRC error. */ u32 txd_err:1; - /*[9] SD/eMMC controller doesn???и║?ииt own descriptor. */ + /*[9] SD/eMMC controller doesn???и??ииt own descriptor. */ u32 desc_err:1; /*[10] Response CRC error.*/ u32 resp_err:1; diff --git a/include/linux/amlogic/tee.h b/include/linux/amlogic/tee.h index 46a518c02a39..224dde5cb3ee 100644 --- a/include/linux/amlogic/tee.h +++ b/include/linux/amlogic/tee.h @@ -21,5 +21,6 @@ extern bool tee_enabled(void); extern int is_secload_get(void); extern int tee_load_video_fw(uint32_t index, uint32_t vdec); +extern int tee_load_video_fw_swap(uint32_t index, uint32_t vdec, bool is_swap); #endif /* __TEE_H__ */ diff --git a/include/linux/amlogic/usb-v2.h b/include/linux/amlogic/usb-v2.h index b0be4770ec26..8b3092c0a92d 100644 --- a/include/linux/amlogic/usb-v2.h +++ b/include/linux/amlogic/usb-v2.h @@ -30,6 +30,8 @@ int aml_new_usb_v2_register_notifier(struct notifier_block *nb); int aml_new_usb_v2_unregister_notifier(struct notifier_block *nb); +int aml_new_otg_register_notifier(struct notifier_block *nb); +int aml_new_otg_unregister_notifier(struct notifier_block *nb); struct u2p_aml_regs_v2 { void __iomem *u2p_r_v2[2]; @@ -64,7 +66,7 @@ union u2p_r1_v2 { }; struct usb_aml_regs_v2 { - void __iomem *usb_r_v2[6]; + void __iomem *usb_r_v2[8]; }; union usb_r0_v2 { @@ -88,13 +90,10 @@ union usb_r1_v2 { struct { unsigned u3h_bigendian_gs:1; unsigned u3h_pme_en:1; - unsigned u3h_hub_port_overcurrent:3; - unsigned reserved_1:2; - unsigned u3h_hub_port_perm_attach:3; - unsigned reserved_2:2; - unsigned u3h_host_u2_port_disable:2; - unsigned reserved_3:2; - unsigned u3h_host_u3_port_disable:1; + unsigned u3h_hub_port_overcurrent:5; + unsigned u3h_hub_port_perm_attach:5; + unsigned u3h_host_u2_port_disable:3; + unsigned u3h_host_u3_port_disable:2; unsigned u3h_host_port_power_control_present:1; unsigned u3h_host_msi_enable:1; unsigned u3h_fladj_30mhz_reg:6; @@ -135,7 +134,11 @@ union usb_r4_v2 { unsigned p21_SLEEPM0:1; unsigned mem_pd:2; unsigned p21_only:1; - unsigned reserved:27; + unsigned reserved:12; + unsigned p31_lane0_tx2rx_loopback:1; + unsigned p31_lane0_ext_pclk_req:1; + unsigned p31_pcs_rx_los_mask_val:10; + unsigned reserve:3; } b; }; @@ -157,6 +160,22 @@ union usb_r5_v2 { } b; }; +union usb_r7_v2 { + /** raw register data */ + uint32_t d32; + /** register bits */ + struct { + unsigned p31_ssc_en:1; + unsigned p31_ssc_range:3; + unsigned p31_ssc_ref_clk_sel:9; + unsigned p31_ref_ssp_en:1; + unsigned reserved:2; + unsigned p31_pcs_tx_deemph_6db:6; + unsigned reserve:3; + unsigned p31_pcs_tx_swing_full:7; + } b; +}; + struct amlogic_usb_v2 { struct usb_phy phy; struct device *dev; @@ -168,7 +187,14 @@ struct amlogic_usb_v2 { void __iomem *phy3_cfg_r2; void __iomem *phy3_cfg_r4; void __iomem *phy3_cfg_r5; + void __iomem *phy31_cfg; + void __iomem *phy31_cfg_r1; + void __iomem *phy31_cfg_r2; + void __iomem *phy31_cfg_r4; + void __iomem *phy31_cfg_r5; void __iomem *usb2_phy_cfg; + void __iomem *power_base; + void __iomem *hhi_mem_pd_base; u32 pll_setting[8]; int phy_cfg_state[4]; /* Set VBus Power though GPIO */ @@ -179,7 +205,25 @@ struct amlogic_usb_v2 { int portnum; int suspend_flag; + int phy_version; + int pwr_ctl; + u32 u2_ctrl_sleep_shift; + u32 u2_hhi_mem_pd_mask; + u32 u2_ctrl_iso_shift; + u32 u2_hhi_mem_pd_shift; + u32 u30_ctrl_sleep_shift; + u32 u30_hhi_mem_pd_mask; + u32 u30_ctrl_iso_shift; + u32 u30_hhi_mem_pd_shift; + u32 usb30_ctrl_rst_bit; + u32 u31_ctrl_sleep_shift; + u32 u31_hhi_mem_pd_mask; + u32 u31_ctrl_iso_shift; + u32 u31_hhi_mem_pd_shift; + u32 usb31_ctrl_rst_bit; struct clk *clk; + struct clk *gate0_clk; + struct clk *gate1_clk; }; union phy3_r1 { diff --git a/include/linux/amlogic/vad_api.h b/include/linux/amlogic/vad_api.h new file mode 100644 index 000000000000..2abd5ae84487 --- /dev/null +++ b/include/linux/amlogic/vad_api.h @@ -0,0 +1,24 @@ +/* + * include/linux/amlogic/vad_api.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 __VAD_API_H__ +#define __VAD_API_H__ + +extern int register_vad_callback(int (*callback)(char *, int, int, int, int)); +extern void unregister_vad_callback(void); + +#endif /* __VAD_API_H__ */ diff --git a/include/linux/amlogic/vmap_stack.h b/include/linux/amlogic/vmap_stack.h index 1b4081ed2461..a8aa35ffdd04 100644 --- a/include/linux/amlogic/vmap_stack.h +++ b/include/linux/amlogic/vmap_stack.h @@ -20,7 +20,18 @@ #define STACK_SHRINK_THRESHOLD (PAGE_SIZE + 1024) #define STACK_SHRINK_SLEEP (HZ) +#ifdef CONFIG_64BIT #define VM_STACK_AREA_SIZE SZ_512M +#define VMAP_ADDR_START VMALLOC_START +#define VMAP_ADDR_END VMALLOC_END +#define VMAP_ALIGN VM_STACK_AREA_SIZE +#else +/* currently support max 6144 tasks on 32bit */ +#define VM_STACK_AREA_SIZE (SZ_64M - SZ_16M) +#define VMAP_ADDR_START MODULES_VADDR +#define VMAP_ADDR_END MODULES_END +#define VMAP_ALIGN SZ_64M +#endif #define STACK_TOP_PAGE_OFF (THREAD_SIZE - PAGE_SIZE) @@ -34,33 +45,32 @@ #define CACHE_MAINTAIN_DELAY (HZ) struct aml_vmap { + spinlock_t vmap_lock; unsigned int start_bit; int cached_pages; struct vm_struct *root_vm; unsigned long *bitmap; struct list_head list; - spinlock_t vmap_lock; - spinlock_t page_lock; struct delayed_work mwork; + spinlock_t page_lock; }; +#ifndef CONFIG_ARM64 +extern void *irq_stack[NR_CPUS]; +#endif + extern int handle_vmap_fault(unsigned long addr, unsigned int esr, struct pt_regs *regs); -extern DEFINE_PER_CPU(unsigned long [THREAD_SIZE/sizeof(long)], vmap_stack); -static inline bool on_vmap_stack(unsigned long sp, int cpu) -{ - /* variable names the same as kernel/stacktrace.c */ - unsigned long low = (unsigned long)per_cpu(vmap_stack, cpu); - unsigned long high = low + THREAD_START_SP; - - return (low <= sp && sp <= high); -} - +extern bool on_vmap_stack(unsigned long sp, int cpu); extern void __setup_vmap_stack(unsigned long off); extern void update_vmap_stack(int diff); extern int get_vmap_stack_size(void); +extern int is_vmap_addr(unsigned long addr); extern void aml_stack_free(struct task_struct *tsk); extern void *aml_stack_alloc(int node, struct task_struct *tsk); extern void aml_account_task_stack(struct task_struct *tsk, int account); +#ifdef CONFIG_ARM +extern int on_irq_stack(unsigned long sp, int cpu); +#endif #endif /* __VMAP_STACK_H__ */ diff --git a/include/linux/amlogic/watch_point.h b/include/linux/amlogic/watch_point.h new file mode 100644 index 000000000000..f28fa37eb8b4 --- /dev/null +++ b/include/linux/amlogic/watch_point.h @@ -0,0 +1,55 @@ +/* + * include/linux/amlogic/watch_point.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 __AML_WATCH_POINT_H__ +#define __AML_WATCH_POINT_H__ + +#include +#include +#include + +#define MAX_WATCH_POINTS 16 + +#ifdef CONFIG_ARM64 +extern u64 read_wb_reg(int reg, int n); +#else +extern u32 read_wb_reg(int n); +#endif + +#ifdef CONFIG_HAVE_HW_BREAKPOINT +extern int aml_watch_point_register(unsigned long addr, + unsigned int len, + unsigned int type, + perf_overflow_handler_t handle); + +extern void aml_watch_point_remove(unsigned long addr); +#else +static inline int aml_watch_point_register(unsigned long addr, + unsigned int len, + unsigned int type, + perf_overflow_handler_t handle) +{ + return -1; +} + +static inline void aml_watch_point_remove(unsigned long addr) +{ + +} +#endif + +#endif diff --git a/include/linux/meson_ion.h b/include/linux/meson_ion.h index ce19cb0753be..7d68d3d5c518 100644 --- a/include/linux/meson_ion.h +++ b/include/linux/meson_ion.h @@ -1 +1,18 @@ +/* + * include/linux/meson_ion.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. + * + */ + #include "../../drivers/amlogic/media/common/ion_dev/meson_ion.h" diff --git a/include/linux/mm.h b/include/linux/mm.h index d2dbfd694f9b..6038c8a17119 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -700,13 +700,25 @@ int alloc_set_pte(struct fault_env *fe, struct mem_cgroup *memcg, */ /* Page flags: | [SECTION] | [NODE] | ZONE | [LAST_CPUPID] | ... | FLAGS | */ -#define SECTIONS_PGOFF ((sizeof(unsigned long)*8) - SECTIONS_WIDTH) -#define NODES_PGOFF (SECTIONS_PGOFF - NODES_WIDTH) #if defined(CONFIG_AMLOGIC_PAGE_TRACE) && defined(CONFIG_64BIT) -#define ZONES_PGOFF ((sizeof(unsigned int) * 8) - ZONES_WIDTH) +/* + * We use high 32bit of page->flags for page trace, Make sure: + * __NR_PAGEFLAGS : about 21 bits + * ZONES_WIDTH : about 2 bits, MAX 4 zone types + * NODES_WIDTH : about 2 bits if open CONFIG_NUMA, else 0 bit + * SECTIONS_WIDTH : 0 bit if defined CONFIG_SPARSEMEM_VMEMMAP otherwise 18 + * bits on ARM64 + * LAST_CPUPID_SHIFT : 0 bit if not define CONFIG_NUMA_BALANCING, otherwise + * 8 + NR_CPUS_BITS + * All of these macros should be using less than 32bits in total, otherwise + * compile will fail + */ +#define SECTIONS_PGOFF ((sizeof(unsigned int)*8) - SECTIONS_WIDTH) #else -#define ZONES_PGOFF (NODES_PGOFF - ZONES_WIDTH) +#define SECTIONS_PGOFF ((sizeof(unsigned long)*8) - SECTIONS_WIDTH) #endif /* CONFIG_AMLOGIC_PAGE_TRACE */ +#define NODES_PGOFF (SECTIONS_PGOFF - NODES_WIDTH) +#define ZONES_PGOFF (NODES_PGOFF - ZONES_WIDTH) #define LAST_CPUPID_PGOFF (ZONES_PGOFF - LAST_CPUPID_WIDTH) /* diff --git a/include/linux/mmc/emmc_partitions.h b/include/linux/mmc/emmc_partitions.h index aea6f695827b..e9adda0e4819 100644 --- a/include/linux/mmc/emmc_partitions.h +++ b/include/linux/mmc/emmc_partitions.h @@ -25,6 +25,14 @@ #define SZ_1M 0x00100000 +#define MMC_PATTERN_NAME "pattern" +#define MMC_PATTERN_OFFSET ((SZ_1M*(36+3))/512) +#define MMC_MAGIC_NAME "magic" +#define MMC_MAGIC_OFFSET ((SZ_1M*(36+6))/512) +#define MMC_RANDOM_NAME "random" +#define MMC_RANDOM_OFFSET ((SZ_1M*(36+7))/512) +#define MMC_DTB_NAME "dtb" +#define MMC_DTB_OFFSET ((SZ_1M*(36+4))/512) /* the size of bootloader partition */ #define MMC_BOOT_PARTITION_SIZE (4*SZ_1M) diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h index 838e109107de..43496fb357be 100644 --- a/include/linux/mtd/nand.h +++ b/include/linux/mtd/nand.h @@ -929,6 +929,7 @@ static inline void nand_set_controller_data(struct nand_chip *chip, void *priv) #define NAND_MFR_INTEL 0x89 #define NAND_MFR_ATO 0x9b #define NAND_MFR_DOSILICON 0xf8 +#define NAND_MFR_ZETTA 0xba /* add extra flash manufacturer ID Codes */ #if defined(CONFIG_AMLOGIC_NAND) || defined(CONFIG_AMLOGIC_M8B_NAND) diff --git a/include/linux/perf/arm_pmu.h b/include/linux/perf/arm_pmu.h index 8462da266089..e3c724ba22fd 100644 --- a/include/linux/perf/arm_pmu.h +++ b/include/linux/perf/arm_pmu.h @@ -162,6 +162,99 @@ int arm_pmu_device_probe(struct platform_device *pdev, #define ARMV8_PMU_PDEV_NAME "armv8-pmu" +#ifdef CONFIG_AMLOGIC_MODIFY +#define MAX_DELTA_CNT 4 +struct amlpmu_cpuinfo { + int irq_num; + + /* + * In interrupt generated cpu(affinity cpu) + * If pmu no overflowed, then we need to send IPI to some other cpus to + * fix it. And before send IPI, set corresponding cpu's fix_done and + * fix_overflowed to zero, in corresponding cpu's IPI interrupt will set + * fix_done to inform source cpu and if indeed pmu overflowed then also + * set fix_overflowed to 1, then inerrupt generated cpu can feel that. + */ + int fix_done; + int fix_overflowed; + + /* for interrupt affinity prediction */ + ktime_t last_stamp; + s64 stamp_deltas[MAX_DELTA_CNT]; + s64 avg_delta; + ktime_t next_predicted_stamp; + + /* + * irq state account of this cpu + * + * - valid_irq_cnt: + * valid irq cnt.(pmu overflow happened) + * - fix_irq_cnt: + * when this cpu is pmu interrupt generated affinity cpu, a pmu + * interrupt if cpu affinity predict failed so no pmu overflow + * happened and succeeded send IPI to other cpu, then it's a send + * fix irq. So the lower is better. + * - empty_irq_cnt: + * when this cpu is pmu interrupt generated affinity cpu, a pmu + * interrupt that no overflow happened and also no fix IPI sended to + * other cpus, then it's a empty irq. + * when this cpu is not affinity cpu, a IPI interrupt(pmu fix from + * affinity cpu) that no pmu overflow happened, it's a empty irq. + * + * attention: + * A interrupt can be a valid_irq and also a fix_irq. + */ + unsigned long valid_irq_cnt; + unsigned long fix_irq_cnt; + unsigned long empty_irq_cnt; + + unsigned long valid_irq_time; + unsigned long fix_irq_time; + unsigned long empty_irq_time; + + unsigned long last_valid_irq_cnt; + unsigned long last_fix_irq_cnt; + unsigned long last_empty_irq_cnt; + + unsigned long last_valid_irq_time; + unsigned long last_fix_irq_time; + unsigned long last_empty_irq_time; +}; + + +#define MAX_CLUSTER_NR 2 +struct amlpmu_context { + struct amlpmu_cpuinfo __percpu *cpuinfo; + + /* struct arm_pmu */ + struct arm_pmu *pmu; + + int clusterb_enabled; + + unsigned int __iomem *regs[MAX_CLUSTER_NR]; + int irqs[MAX_CLUSTER_NR]; + struct cpumask cpumasks[MAX_CLUSTER_NR]; + int first_cpus[MAX_CLUSTER_NR]; + + /* + * In main pmu irq route wait for other cpu fix done may cause lockup, + * when lockup we disable main irq for a while. + * relax_timer will enable main irq again. + */ + struct hrtimer relax_timer; + + unsigned int relax_timer_ns; + unsigned int max_wait_cnt; +}; + +extern struct amlpmu_context amlpmu_ctx; + +int amlpmu_handle_irq(struct arm_pmu *cpu_pmu, int irq_num, int has_overflowed); + +/* defined int arch/arm(64)/kernel/perf_event(_v7).c */ +void amlpmu_handle_irq_ipi(void *arg); +#endif + #endif /* CONFIG_ARM_PMU */ #endif /* __ARM_PMU_H__ */ diff --git a/include/linux/pm_opp.h b/include/linux/pm_opp.h index f6bc76501912..21effa78c27f 100644 --- a/include/linux/pm_opp.h +++ b/include/linux/pm_opp.h @@ -207,6 +207,11 @@ static inline void dev_pm_opp_cpumask_remove_table(const struct cpumask *cpumask int dev_pm_opp_of_add_table(struct device *dev); void dev_pm_opp_of_remove_table(struct device *dev); int dev_pm_opp_of_cpumask_add_table(const struct cpumask *cpumask); +#ifdef CONFIG_AMLOGIC_MODIFY +int dev_pm_opp_of_add_table_indexed(struct device *dev, int index); +int dev_pm_opp_of_cpumask_add_table_indexed(const struct cpumask *cpumask, + int index); +#endif void dev_pm_opp_of_cpumask_remove_table(const struct cpumask *cpumask); int dev_pm_opp_of_get_sharing_cpus(struct device *cpu_dev, struct cpumask *cpumask); #else @@ -224,6 +229,18 @@ static inline int dev_pm_opp_of_cpumask_add_table(const struct cpumask *cpumask) return -ENOTSUPP; } +#ifdef CONFIG_AMLOGIC_MODIFY +int dev_pm_opp_of_add_table_indexed(struct device *dev, int index) +{ + return -ENOTSUPP; +} + +int dev_pm_opp_of_cpumask_add_table_indexed(const struct cpumask *cpumask, + int index) +{ + return -ENOTSUPP; +} +#endif static inline void dev_pm_opp_of_cpumask_remove_table(const struct cpumask *cpumask) { } diff --git a/include/linux/pstore_ram.h b/include/linux/pstore_ram.h index cb5edd64a3d3..6f8261547443 100644 --- a/include/linux/pstore_ram.h +++ b/include/linux/pstore_ram.h @@ -30,6 +30,7 @@ * PRZ_FLAG_NO_LOCK is used. For all other cases, locking is required. */ #define PRZ_FLAG_NO_LOCK BIT(0) +#define PRZ_FLAG_BIG_LOCK BIT(7) struct persistent_ram_buffer; struct rs_control; diff --git a/include/linux/sched.h b/include/linux/sched.h index 4634a6ddef1d..197dfd6b847c 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -3344,7 +3344,13 @@ static inline unsigned long *end_of_stack(const struct task_struct *task) #elif !defined(__HAVE_THREAD_FUNCTIONS) +#ifdef CONFIG_AMLOGIC_VMAP +#define task_thread_info(task) \ + ((struct thread_info *)(((unsigned long)(task)->stack) + \ + THREAD_INFO_OFFSET)) +#else #define task_thread_info(task) ((struct thread_info *)(task)->stack) +#endif #define task_stack_page(task) ((void *)(task)->stack) static inline void setup_thread_stack(struct task_struct *p, struct task_struct *org) @@ -3364,11 +3370,15 @@ static inline void setup_thread_stack(struct task_struct *p, struct task_struct */ static inline unsigned long *end_of_stack(struct task_struct *p) { +#ifdef CONFIG_AMLOGIC_VMAP + return p->stack; +#else /* CONFIG_AMLOGIC_VMAP */ #ifdef CONFIG_STACK_GROWSUP return (unsigned long *)((unsigned long)task_thread_info(p) + THREAD_SIZE) - 1; #else return (unsigned long *)(task_thread_info(p) + 1); #endif +#endif /* CONFIG_AMLOGIC_VMAP */ } #endif diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index c7dff69a4103..3890f0b0ae20 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -376,6 +376,11 @@ extern const struct earlycon_id *__earlycon_table_end[]; #define EARLYCON_DECLARE(_name, fn) OF_EARLYCON_DECLARE(_name, "", fn) +#ifdef CONFIG_AMLOGIC_MODIFY +#define EARLYCON_DECLARE_COMP(_name, fn) \ + _OF_EARLYCON_DECLARE(_name, "", fn, __LINE__ ## __COUNTER__) +#endif + extern int of_setup_earlycon(const struct earlycon_id *match, unsigned long node, const char *options); diff --git a/include/linux/smp.h b/include/linux/smp.h index c9b5fb366422..acba97e0eeab 100644 --- a/include/linux/smp.h +++ b/include/linux/smp.h @@ -73,13 +73,6 @@ extern void smp_send_stop(void); */ extern void smp_send_reschedule(int cpu); -#ifdef CONFIG_AMLOGIC_MODIFY -/* - * sends a 'aml pmu' event to another CPU: - */ -extern void smp_send_aml_pmu(int cpu); -#endif - /* * Prepare machine for booting other CPUs. */ diff --git a/include/media/rc-map.h b/include/media/rc-map.h index e1cc14cba391..d8e81a658b90 100644 --- a/include/media/rc-map.h +++ b/include/media/rc-map.h @@ -36,6 +36,7 @@ * @RC_TYPE_SHARP: Sharp protocol * @RC_TYPE_XMP: XMP protocol * @RC_TYPE_CEC: CEC protocol + * @RC_TYPE_IRMP: IRMP software IR decoder */ enum rc_type { RC_TYPE_UNKNOWN = 0, @@ -60,6 +61,7 @@ enum rc_type { RC_TYPE_SHARP = 19, RC_TYPE_XMP = 20, RC_TYPE_CEC = 21, + RC_TYPE_IRMP = 22, }; #define RC_BIT_NONE 0ULL @@ -85,6 +87,7 @@ enum rc_type { #define RC_BIT_SHARP (1ULL << RC_TYPE_SHARP) #define RC_BIT_XMP (1ULL << RC_TYPE_XMP) #define RC_BIT_CEC (1ULL << RC_TYPE_CEC) +#define RC_BIT_IRMP (1ULL << RC_TYPE_IRMP) #define RC_BIT_ALL (RC_BIT_UNKNOWN | RC_BIT_OTHER | \ RC_BIT_RC5 | RC_BIT_RC5X | RC_BIT_RC5_SZ | \ @@ -94,7 +97,7 @@ enum rc_type { RC_BIT_SANYO | RC_BIT_MCE_KBD | RC_BIT_RC6_0 | \ RC_BIT_RC6_6A_20 | RC_BIT_RC6_6A_24 | \ RC_BIT_RC6_6A_32 | RC_BIT_RC6_MCE | RC_BIT_SHARP | \ - RC_BIT_XMP | RC_BIT_CEC) + RC_BIT_XMP | RC_BIT_CEC | RC_BIT_IRMP) #define RC_SCANCODE_UNKNOWN(x) (x) diff --git a/include/trace/events/meson_atrace.h b/include/trace/events/meson_atrace.h index 84009695511f..96d5eea9f96d 100644 --- a/include/trace/events/meson_atrace.h +++ b/include/trace/events/meson_atrace.h @@ -1,5 +1,18 @@ /* - * meson_atrace.h + * include/trace/events/meson_atrace.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. + * */ /* @@ -53,13 +66,18 @@ TRACE_EVENT(tracing_mark_write, print_flags_delim(__entry->flags), __get_str(name), __entry->value) ); - +#ifdef CONFIG_AMLOGIC_DEBUG_ATRACE #define ATRACE_COUNTER(name, value) \ trace_tracing_mark_write(name, (1 << KERNEL_ATRACE_COUNTER), value) #define ATRACE_BEGIN(name) \ trace_tracing_mark_write(name, (1 << KERNEL_ATRACE_BEGIN), 0) #define ATRACE_END(name) \ trace_tracing_mark_write("", (1 << KERNEL_ATRACE_END), 1) +#else +#define ATRACE_COUNTER(name, value) +#define ATRACE_BEGIN(name) +#define ATRACE_END(name) +#endif #endif /* _TRACE_MESON_BASE_H */ diff --git a/include/trace/events/sched.h b/include/trace/events/sched.h index f5780473a5c1..efe4abd4a993 100644 --- a/include/trace/events/sched.h +++ b/include/trace/events/sched.h @@ -999,7 +999,11 @@ TRACE_EVENT(walt_update_task_ravg, __entry->cs = rq->curr_runnable_sum; __entry->ps = rq->prev_runnable_sum; __entry->util = rq->prev_runnable_sum << SCHED_CAPACITY_SHIFT; +#if defined(CONFIG_AMLOGIC_MODIFY) && defined(CONFIG_ARM64_A32) + div_u64(__entry->util, walt_ravg_window); +#else do_div(__entry->util, walt_ravg_window); +#endif __entry->curr_window = p->ravg.curr_window; __entry->prev_window = p->ravg.prev_window; __entry->nt_cs = rq->nt_curr_runnable_sum; diff --git a/include/uapi/linux/dvb/ca.h b/include/uapi/linux/dvb/ca.h index e7902227ece9..69ef406f730e 100644 --- a/include/uapi/linux/dvb/ca.h +++ b/include/uapi/linux/dvb/ca.h @@ -82,12 +82,26 @@ enum ca_cw_type { CA_CW_AES_EVEN, CA_CW_AES_ODD, CA_CW_AES_EVEN_IV, - CA_CW_AES_ODD_IV + CA_CW_AES_ODD_IV, + CA_CW_DES_EVEN, + CA_CW_DES_ODD, + CA_CW_SM4_EVEN, + CA_CW_SM4_ODD, + CA_CW_SM4_EVEN_IV, + CA_CW_SM4_ODD_IV, + CA_CW_TYPE_MAX +}; + +enum ca_dsc_mode { + CA_DSC_CBC = 1, + CA_DSC_ECB, + CA_DSC_IDSA }; struct ca_descr_ex { unsigned int index; enum ca_cw_type type; + enum ca_dsc_mode mode; int flags; #define CA_CW_FROM_KL 1 unsigned char cw[16]; diff --git a/kernel/compat.c b/kernel/compat.c index 333d364be29d..57ccf3c3d036 100644 --- a/kernel/compat.c +++ b/kernel/compat.c @@ -112,6 +112,11 @@ COMPAT_SYSCALL_DEFINE2(settimeofday, struct compat_timeval __user *, tv, struct timespec new_ts; struct timezone new_tz; +#ifdef CONFIG_AMLOGIC_MODIFY + new_ts.tv_sec = 0; + new_ts.tv_nsec = 0; +#endif + if (tv) { if (compat_get_timeval(&user_tv, tv)) return -EFAULT; diff --git a/kernel/fork.c b/kernel/fork.c index 91063407507f..bac18408acf3 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -484,21 +484,12 @@ int __weak arch_dup_task_struct(struct task_struct *dst, return 0; } -#ifdef CONFIG_AMLOGIC_VMAP -static bool first_magic __read_mostly; -#endif - void set_task_stack_end_magic(struct task_struct *tsk) { unsigned long *stackend; stackend = end_of_stack(tsk); -#ifdef CONFIG_AMLOGIC_VMAP - if (unlikely(!first_magic)) { - *stackend = STACK_END_MAGIC; /* for overflow detection */ - first_magic = 1; - } -#else +#ifndef CONFIG_AMLOGIC_VMAP *stackend = STACK_END_MAGIC; /* for overflow detection */ #endif } diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c index 2d0c99b3f34c..678e8fa9d466 100644 --- a/kernel/power/suspend.c +++ b/kernel/power/suspend.c @@ -360,6 +360,25 @@ static int suspend_enter(suspend_state_t state, bool *wakeup) if (suspend_test(TEST_PLATFORM)) goto Platform_wake; +#ifdef CONFIG_AMLOGIC_MODIFY + error = disable_nonboot_cpus(); + if (error || suspend_test(TEST_CPUS)) { + log_suspend_abort_reason("Disabling non-boot cpus failed"); + goto Enable_cpus; + } + /* + * PM_SUSPEND_FREEZE equals + * frozen processes + suspended devices + idle processors. + * Thus we should invoke freeze_enter() soon after + * all the devices are suspended. + */ + if (state == PM_SUSPEND_FREEZE) { + trace_suspend_resume(TPS("machine_suspend"), state, true); + freeze_enter(); + trace_suspend_resume(TPS("machine_suspend"), state, false); + goto Enable_cpus; + } +#else /* * PM_SUSPEND_FREEZE equals * frozen processes + suspended devices + idle processors. @@ -378,6 +397,7 @@ static int suspend_enter(suspend_state_t state, bool *wakeup) log_suspend_abort_reason("Disabling non-boot cpus failed"); goto Enable_cpus; } +#endif arch_suspend_disable_irqs(); BUG_ON(!irqs_disabled()); diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c index 2eb60968ddf9..5527d850b896 100644 --- a/kernel/printk/printk.c +++ b/kernel/printk/printk.c @@ -1199,7 +1199,11 @@ static size_t print_time(u64 ts, char *buf) rem_nsec = do_div(ts, 1000000000); if (!buf) +#ifdef CONFIG_AMLOGIC_MODIFY + return snprintf(NULL, 0, "[%5lu.000000@0] ", (unsigned long)ts); +#else return snprintf(NULL, 0, "[%5lu.000000] ", (unsigned long)ts); +#endif #if defined(CONFIG_SMP) && defined(CONFIG_AMLOGIC_DRIVER) return sprintf(buf, "[%5lu.%06lu@%d] ", diff --git a/kernel/sched/tune.c b/kernel/sched/tune.c index fbdd00a7aabf..7399e709f954 100644 --- a/kernel/sched/tune.c +++ b/kernel/sched/tune.c @@ -951,6 +951,9 @@ schedtune_add_cluster_nrg( * Assume we have EM data only at the CPU and * the upper CLUSTER level */ +#ifdef CONFIG_AMLOGIC_MODIFY + if (sd2->parent) +#endif BUG_ON(!cpumask_equal( sched_group_cpus(sg), sched_group_cpus(sd2->parent->groups) diff --git a/kernel/time/posix-cpu-timers.c b/kernel/time/posix-cpu-timers.c index 21a27bb73587..1ac61891f2fa 100644 --- a/kernel/time/posix-cpu-timers.c +++ b/kernel/time/posix-cpu-timers.c @@ -1222,6 +1222,10 @@ void set_process_cpu_timer(struct task_struct *tsk, unsigned int clock_idx, { unsigned long long now; +#ifdef CONFIG_AMLOGIC_MODIFY + now = 0; +#endif + WARN_ON_ONCE(clock_idx == CPUCLOCK_SCHED); cpu_timer_sample_group(clock_idx, tsk, &now); diff --git a/kernel/time/time.c b/kernel/time/time.c index a5b6d98ea7b1..9c2526a986dc 100644 --- a/kernel/time/time.c +++ b/kernel/time/time.c @@ -198,6 +198,11 @@ SYSCALL_DEFINE2(settimeofday, struct timeval __user *, tv, struct timespec new_ts; struct timezone new_tz; +#ifdef CONFIG_AMLOGIC_MODIFY + new_ts.tv_sec = 0; + new_ts.tv_nsec = 0; +#endif + if (tv) { if (copy_from_user(&user_tv, tv, sizeof(*tv))) return -EFAULT; diff --git a/lib/ioremap.c b/lib/ioremap.c index b9462037868d..e04366171cba 100644 --- a/lib/ioremap.c +++ b/lib/ioremap.c @@ -12,6 +12,10 @@ #include #include #include +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE +#include +#include +#endif #ifdef CONFIG_HAVE_ARCH_HUGE_VMAP static int __read_mostly ioremap_pud_capable; @@ -122,6 +126,19 @@ static inline int ioremap_pud_range(pgd_t *pgd, unsigned long addr, return 0; } +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE +bool is_normal_memory(pgprot_t p) +{ +#if defined(CONFIG_ARM) + return ((pgprot_val(p) & L_PTE_MT_MASK) == L_PTE_MT_WRITEALLOC); +#elif defined(CONFIG_ARM64) + return (pgprot_val(p) & PTE_ATTRINDX_MASK) == PTE_ATTRINDX(MT_NORMAL); +#else +#error "Unuspported architecture" +#endif +} +#endif + int ioremap_page_range(unsigned long addr, unsigned long end, phys_addr_t phys_addr, pgprot_t prot) { @@ -143,7 +160,12 @@ int ioremap_page_range(unsigned long addr, } while (pgd++, addr = next, addr != end); flush_cache_vmap(start, end); - +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE + if (need_dump_iomap() && !is_normal_memory(prot)) + pr_err("io__map pa:0x%lx,port:0x%lx\n", + start, end, (unsigned long)phys_addr, + (unsigned long)pgprot_val(prot)); +#endif return err; } EXPORT_SYMBOL_GPL(ioremap_page_range); diff --git a/mm/cma.c b/mm/cma.c index b59c2da8ce01..589d67d938ea 100644 --- a/mm/cma.c +++ b/mm/cma.c @@ -503,6 +503,7 @@ struct page *cma_alloc(struct cma *cma, size_t count, unsigned int align) int ret; #ifdef CONFIG_AMLOGIC_CMA int dummy; + unsigned long long tick; #endif /* CONFIG_AMLOGIC_CMA */ if (!cma || !cma->count) @@ -511,6 +512,11 @@ struct page *cma_alloc(struct cma *cma, size_t count, unsigned int align) pr_debug("%s(cma %p, count %zu, align %d)\n", __func__, (void *)cma, count, align); +#ifdef CONFIG_AMLOGIC_CMA + tick = sched_clock(); + cma_debug(0, NULL, "(cma %p, count %zu, align %d)\n", + (void *)cma, count, align); +#endif if (!count) return NULL; @@ -572,6 +578,8 @@ struct page *cma_alloc(struct cma *cma, size_t count, unsigned int align) #ifdef CONFIG_AMLOGIC_CMA aml_cma_alloc_post_hook(&dummy, count, page); + cma_debug(0, NULL, "return page:%lx, tick:%lld\n", + page ? page_to_pfn(page) : 0, sched_clock() - tick); #endif /* CONFIG_AMLOGIC_CMA */ pr_debug("%s(): returned %p\n", __func__, page); return page; diff --git a/mm/compaction.c b/mm/compaction.c index e35f49150e2b..665760fdc1f2 100644 --- a/mm/compaction.c +++ b/mm/compaction.c @@ -434,14 +434,34 @@ static unsigned long isolate_freepages_block(struct compact_control *cc, * contention, to give chance to IRQs. Abort if fatal signal * pending or async compaction detects need_resched() */ + #ifdef CONFIG_AMLOGIC_CMA + if (!(blockpfn % SWAP_CLUSTER_MAX) + && compact_unlock_should_abort(&cc->zone->lock, flags, + &locked, cc)) { + if (strict) + cma_debug(1, page, "abort, blk:%lx, swap:%ld\n", + blockpfn, SWAP_CLUSTER_MAX); + break; + } + #else if (!(blockpfn % SWAP_CLUSTER_MAX) && compact_unlock_should_abort(&cc->zone->lock, flags, &locked, cc)) break; + #endif nr_scanned++; + #ifdef CONFIG_AMLOGIC_CMA + if (!pfn_valid_within(blockpfn)) { + if (strict) + cma_debug(1, page, "invalid pfn:%lx\n", + blockpfn); + goto isolate_fail; + } + #else if (!pfn_valid_within(blockpfn)) goto isolate_fail; + #endif if (!valid_page) valid_page = page; @@ -459,12 +479,25 @@ static unsigned long isolate_freepages_block(struct compact_control *cc, blockpfn += (1UL << comp_order) - 1; cursor += (1UL << comp_order) - 1; } - + #ifdef CONFIG_AMLOGIC_CMA + if (strict) + cma_debug(1, page, "compound page:%lx\n", + page_to_pfn(page)); + #endif goto isolate_fail; } + #ifdef CONFIG_AMLOGIC_CMA + if (!PageBuddy(page)) { + if (strict) + cma_debug(1, page, " NO buddy page1:%lx\n", + page_to_pfn(page)); + goto isolate_fail; + } + #else if (!PageBuddy(page)) goto isolate_fail; + #endif /* * If we already hold the lock, we can skip some rechecking. @@ -484,19 +517,44 @@ static unsigned long isolate_freepages_block(struct compact_control *cc, */ locked = compact_trylock_irqsave(&cc->zone->lock, &flags, cc); + #ifdef CONFIG_AMLOGIC_CMA + if (!locked) { + if (strict) + cma_debug(1, page, " lock failed:%lx\n", + page_to_pfn(page)); + break; + } + /* Recheck this is a buddy page under lock */ + if (!PageBuddy(page)) { + if (strict) + cma_debug(1, page, " No buddy2:%lx\n", + page_to_pfn(page)); + goto isolate_fail; + } + #else if (!locked) break; /* Recheck this is a buddy page under lock */ if (!PageBuddy(page)) goto isolate_fail; + #endif } /* Found a free page, will break it into order-0 pages */ order = page_order(page); isolated = __isolate_free_page(page, order); + #ifdef CONFIG_AMLOGIC_CMA + if (!isolated) { + if (strict) + cma_debug(1, page, "iso free fail:%lx, o:%d\n", + page_to_pfn(page), order); + break; + } + #else if (!isolated) break; + #endif set_page_private(page, order); total_isolated += isolated; @@ -599,9 +657,17 @@ isolate_freepages_range(struct compact_control *cc, block_end_pfn = min(block_end_pfn, end_pfn); } + #ifdef CONFIG_AMLOGIC_CMA + if (!pageblock_pfn_to_page(block_start_pfn, + block_end_pfn, cc->zone)) { + cma_debug(1, NULL, " no page block\n"); + break; + } + #else if (!pageblock_pfn_to_page(block_start_pfn, block_end_pfn, cc->zone)) break; + #endif isolated = isolate_freepages_block(cc, &isolate_start_pfn, block_end_pfn, &freelist, true); @@ -611,8 +677,15 @@ isolate_freepages_range(struct compact_control *cc, * there are any holes in the block (ie. invalid PFNs or * non-free pages). */ + #ifdef CONFIG_AMLOGIC_CMA + if (!isolated) { + cma_debug(1, NULL, " isolate free page failed\n"); + break; + } + #else if (!isolated) break; + #endif /* * If we managed to isolate pages, it is always (1 << n) * @@ -626,6 +699,10 @@ isolate_freepages_range(struct compact_control *cc, if (pfn < end_pfn) { /* Loop terminated early, cleanup. */ + #ifdef CONFIG_AMLOGIC_CMA + cma_debug(1, NULL, "pfn:%lx, end:%lx, start:%lx\n", + pfn, end_pfn, start_pfn); + #endif release_freepages(&freelist); return 0; } diff --git a/mm/kasan/kasan.c b/mm/kasan/kasan.c index b3293d3807b3..17a4a9c86851 100644 --- a/mm/kasan/kasan.c +++ b/mm/kasan/kasan.c @@ -423,8 +423,18 @@ void kasan_cache_create(struct kmem_cache *cache, size_t *size, if (redzone_adjust > 0) *size += redzone_adjust; +#ifdef CONFIG_AMLOGIC_KASAN32 /* compile problem */ + { + size_t s1; + + s1 = max(*size, cache->object_size + + optimal_redzone(cache->object_size)); + *size = s1 >= KMALLOC_MAX_SIZE ? KMALLOC_MAX_SIZE : s1; + } +#else *size = min(KMALLOC_MAX_SIZE, max(*size, cache->object_size + optimal_redzone(cache->object_size))); +#endif /* * If the metadata doesn't fit, don't enable KASAN at all. @@ -576,8 +586,13 @@ bool kasan_slab_free(struct kmem_cache *cache, void *object) shadow_byte = READ_ONCE(*(s8 *)kasan_mem_to_shadow(object)); if (shadow_byte < 0 || shadow_byte >= KASAN_SHADOW_SCALE_SIZE) { + #ifdef CONFIG_AMLOGIC_KASAN32 /* for compile problems */ + kasan_report_double_free(cache, object, + __builtin_return_address(0)); + #else kasan_report_double_free(cache, object, __builtin_return_address(1)); + #endif return true; } @@ -739,6 +754,11 @@ static void register_global(struct kasan_global *global) { size_t aligned_size = round_up(global->size, KASAN_SHADOW_SCALE_SIZE); +#ifdef CONFIG_AMLOGIC_KASAN32 + /* avoid FUCKING close source ko panic here */ + if ((unsigned long)global->beg < MODULES_VADDR) + return; +#endif kasan_unpoison_shadow(global->beg, global->size); kasan_poison_shadow(global->beg + aligned_size, diff --git a/mm/migrate.c b/mm/migrate.c index b810ac1359f0..a22bf60ad542 100644 --- a/mm/migrate.c +++ b/mm/migrate.c @@ -415,6 +415,11 @@ int migrate_page_move_mapping(struct address_space *mapping, if (!mapping) { /* Anonymous page without mapping */ + #ifdef CONFIG_AMLOGIC_CMA + if (page_count(page) != expected_count) + cma_debug(2, page, " anon page cnt miss match, e:%d\n", + expected_count); + #endif if (page_count(page) != expected_count) return -EAGAIN; @@ -439,6 +444,10 @@ int migrate_page_move_mapping(struct address_space *mapping, if (page_count(page) != expected_count || radix_tree_deref_slot_protected(pslot, &mapping->tree_lock) != page) { spin_unlock_irq(&mapping->tree_lock); + #ifdef CONFIG_AMLOGIC_CMA + cma_debug(2, page, " file page cnt miss match, e:%d, p:%d\n", + expected_count, page_has_private(page)); + #endif return -EAGAIN; } @@ -1017,11 +1026,21 @@ static int __unmap_and_move(struct page *page, struct page *newpage, goto out_unlock_both; } } else if (page_mapped(page)) { + #ifdef CONFIG_AMLOGIC_CMA + int ret; + + ret = try_to_unmap(page, + TTU_MIGRATION | TTU_IGNORE_MLOCK | + TTU_IGNORE_ACCESS); + if (ret != SWAP_SUCCESS) + cma_debug(2, page, " unmap failed:%d\n", ret); + #else /* Establish migration ptes */ VM_BUG_ON_PAGE(PageAnon(page) && !PageKsm(page) && !anon_vma, page); try_to_unmap(page, TTU_MIGRATION|TTU_IGNORE_MLOCK|TTU_IGNORE_ACCESS); + #endif page_was_mapped = 1; } @@ -1355,6 +1374,9 @@ int migrate_pages(struct list_head *from, new_page_t get_new_page, switch(rc) { case -ENOMEM: nr_failed++; + #ifdef CONFIG_AMLOGIC_CMA + cma_debug(2, page, " NO MEM\n"); + #endif goto out; case -EAGAIN: retry++; @@ -1370,6 +1392,9 @@ int migrate_pages(struct list_head *from, new_page_t get_new_page, * retried in the next outer loop. */ nr_failed++; + #ifdef CONFIG_AMLOGIC_CMA + cma_debug(2, page, " failed:%d\n", rc); + #endif break; } } diff --git a/mm/page_alloc.c b/mm/page_alloc.c index cef29ab2bd76..f6ba0d2c1372 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -3007,8 +3007,21 @@ bool __zone_watermark_ok(struct zone *z, unsigned int order, unsigned long mark, * are not met, then a high-order request also cannot go ahead * even if a suitable page happened to be free. */ +#ifdef CONFIG_AMLOGIC_CMA + if (free_pages <= min + z->lowmem_reserve[classzone_idx]) { + /* do not using cma until water mark is low */ + if (unlikely(!cma_first_wm_low && free_pages > 0)) { + cma_first_wm_low = true; + pr_info("Now can use cma, free:%ld, wm:%ld\n", + free_pages, + min + z->lowmem_reserve[classzone_idx]); + } + return false; + } +#else if (free_pages <= min + z->lowmem_reserve[classzone_idx]) return false; +#endif /* If this is an order-0 request then the watermark is fine */ if (!order) diff --git a/mm/slab_common.c b/mm/slab_common.c index f2ae3cb69533..3325f80e5cfe 100644 --- a/mm/slab_common.c +++ b/mm/slab_common.c @@ -1045,7 +1045,7 @@ static inline void *aml_slub_alloc_large(size_t size, gfp_t flags, int order) unsigned long total_pages = 1 << order; unsigned long saved = 0; #ifdef CONFIG_AMLOGIC_PAGE_TRACE - unsigned long fun; + unsigned long fun = 0; #endif int i; diff --git a/mm/vmalloc.c b/mm/vmalloc.c index 6debb44a231e..655e3b8ac185 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c @@ -356,6 +356,21 @@ static void purge_vmap_area_lazy(void); static BLOCKING_NOTIFIER_HEAD(vmap_notify_list); +#ifdef CONFIG_AMLOGIC_MODIFY +static void dump_vmalloc(void) +{ + struct vmap_area *va, *next; + + spin_lock(&vmap_area_lock); + list_for_each_entry_safe(va, next, &vmap_area_list, list) { + pr_info("%s, va:%lx-%lx, size:%08ld KB, alloc:%pf\n", + __func__, va->va_start, va->va_end, + (va->va_end - va->va_start) >> 10, va->vm->caller); + } + spin_unlock(&vmap_area_lock); +} +#endif + /* * Allocate a region of KVA of the specified size and alignment, within the * vstart and vend. @@ -496,6 +511,9 @@ overflow: } } +#ifdef CONFIG_AMLOGIC_MODIFY + dump_vmalloc(); +#endif if (printk_ratelimit()) pr_warn("vmap allocation for size %lu failed: use vmalloc= to increase size\n", size); diff --git a/mm/vmscan.c b/mm/vmscan.c index 7c85bc567f88..75df45923258 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -1315,6 +1315,9 @@ static int filecache_need_migrate(struct page *page) if (!PageActive(page) && page_mapcount(page) >= INACTIVE_MIGRATE) return 1; + if (PageUnevictable(page)) + return 0; + return 0; } #endif diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 1d342f0acbf0..32db18e2dfe3 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -1440,7 +1440,7 @@ EXPORT_SYMBOL_GPL(ip6_update_pmtu); void ip6_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, __be32 mtu) { - int oif = sk->sk_bound_dev_if; +// int oif = sk->sk_bound_dev_if; struct dst_entry *dst; ip6_update_pmtu(skb, sock_net(sk), mtu, diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index cecf51a5aec4..f5afd24a8008 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -997,6 +997,10 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) struct hlist_head *list; struct path path = { NULL, NULL }; +#ifdef CONFIG_AMLOGIC_MODIFY + hash = 0; +#endif + err = -EINVAL; if (addr_len < offsetofend(struct sockaddr_un, sun_family) || sunaddr->sun_family != AF_UNIX) diff --git a/scripts/amlogic/mk_32dtb.sh b/scripts/amlogic/mk_32dtb.sh index a014162b9b76..88bb658130d1 100755 --- a/scripts/amlogic/mk_32dtb.sh +++ b/scripts/amlogic/mk_32dtb.sh @@ -13,6 +13,5 @@ make ARCH=arm txl_t962_p321.dtb make ARCH=arm txlx_t962e_r321.dtb make ARCH=arm txlx_t962x_r311_1g.dtb make ARCH=arm txlx_t962x_r311_2g.dtb - - +make ARCH=arm tm2_pxp.dtb diff --git a/scripts/amlogic/mk_dtb_gx.sh b/scripts/amlogic/mk_dtb_gx.sh index 28fb3d515729..6c559867bf16 100755 --- a/scripts/amlogic/mk_dtb_gx.sh +++ b/scripts/amlogic/mk_dtb_gx.sh @@ -36,6 +36,8 @@ make ARCH=arm64 axg_s420_v03.dtb || echo "Compile dtb Fail !!" make ARCH=arm64 g12a_pxp.dtb || echo "Compile dtb Fail!!" +make ARCH=arm64 sm1_pxp.dtb || echo "Compile dtb Fail!!" + make ARCH=arm64 g12a_s905d2_skt.dtb || echo "Compile dtb Fail!!" make ARCH=arm64 g12b_pxp.dtb || echo "Compile dtb Fail!!" @@ -43,3 +45,5 @@ make ARCH=arm64 g12b_pxp.dtb || echo "Compile dtb Fail!!" make ARCH=arm64 g12b_a311d_skt.dtb || echo "Compile dtb Fail!!" make ARCH=arm64 g12b_a311d_w400.dtb || echo "Compile dtb Fail!!" + +make ARCH=arm64 tm2_pxp.dtb || echo "Compile dtb Fail!!" diff --git a/sound/soc/amlogic/auge/Makefile b/sound/soc/amlogic/auge/Makefile index 4cf47bec8853..b8d6cc8eb8e8 100644 --- a/sound/soc/amlogic/auge/Makefile +++ b/sound/soc/amlogic/auge/Makefile @@ -4,6 +4,8 @@ obj-$(CONFIG_AMLOGIC_SND_SOC_AUGE) += audio_controller.o \ axg,clocks.o \ g12a,clocks.o \ tl1,clocks.o \ + sm1,clocks.o \ + tm2,clocks.o \ card.o \ card_utils.o \ tdm.o \ @@ -32,4 +34,6 @@ obj-$(CONFIG_AMLOGIC_SND_SOC_AUGE) += audio_controller.o \ frhdmirx_hw.o \ vad.o \ vad_hw.o \ - vad_dev.o + vad_dev.o \ + earc.o \ + earc_hw.o diff --git a/sound/soc/amlogic/auge/audio_clks.c b/sound/soc/amlogic/auge/audio_clks.c index 1f0dd6fc1b54..4aa82c362867 100644 --- a/sound/soc/amlogic/auge/audio_clks.c +++ b/sound/soc/amlogic/auge/audio_clks.c @@ -36,6 +36,14 @@ static const struct of_device_id audio_clocks_of_match[] = { .compatible = "amlogic, tl1-audio-clocks", .data = &tl1_audio_clks_init, }, + { + .compatible = "amlogic, sm1-audio-clocks", + .data = &sm1_audio_clks_init, + }, + { + .compatible = "amlogic, tm2-audio-clocks", + .data = &tm2_audio_clks_init, + }, {}, }; MODULE_DEVICE_TABLE(of, audio_clocks_of_match); diff --git a/sound/soc/amlogic/auge/audio_clks.h b/sound/soc/amlogic/auge/audio_clks.h index 359fbfc5560f..ede4ec982ced 100644 --- a/sound/soc/amlogic/auge/audio_clks.h +++ b/sound/soc/amlogic/auge/audio_clks.h @@ -93,6 +93,8 @@ struct audio_clk_init { extern struct audio_clk_init axg_audio_clks_init; extern struct audio_clk_init g12a_audio_clks_init; extern struct audio_clk_init tl1_audio_clks_init; +extern struct audio_clk_init sm1_audio_clks_init; +extern struct audio_clk_init tm2_audio_clks_init; struct clk_chipinfo { /* force clock source as oscin(24M) */ diff --git a/sound/soc/amlogic/auge/audio_controller.c b/sound/soc/amlogic/auge/audio_controller.c index 1b50eacb3ff0..04845c530853 100644 --- a/sound/soc/amlogic/auge/audio_controller.c +++ b/sound/soc/amlogic/auge/audio_controller.c @@ -104,6 +104,7 @@ static int register_audio_controller(struct platform_device *pdev, /* gate on all clks on bringup stage, need gate separately */ aml_audiobus_write(actrl, EE_AUDIO_CLK_GATE_EN0, 0xffffffff); + aml_audiobus_write(actrl, EE_AUDIO_CLK_GATE_EN1, 0xffffffff); return 0; } diff --git a/sound/soc/amlogic/auge/audio_utils.c b/sound/soc/amlogic/auge/audio_utils.c index 32dca83e41c3..505f9944bf75 100644 --- a/sound/soc/amlogic/auge/audio_utils.c +++ b/sound/soc/amlogic/auge/audio_utils.c @@ -42,6 +42,7 @@ struct snd_elem_info { static unsigned int loopback_enable; static unsigned int loopback_is_running; static unsigned int datain_datalb_total; +static unsigned int audio_inskew; static const char *const loopback_enable_texts[] = { "Disable", @@ -164,6 +165,7 @@ static int loopback_tdminlb_set_enum( return 0; } +#if 0 static int snd_int_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { @@ -278,6 +280,7 @@ static int snd_byte_set(struct snd_kcontrol *kcontrol, return 0; } +#endif #define SND_BYTE(xname, type, func, xshift, xmask) \ { \ @@ -625,10 +628,92 @@ static int audio_locker_set_enum( return 0; } +static const char *const audio_inskew_texts[] = { + "0", + "1", + "2", + "3", + "4", + "5", + "6", +}; + +static const struct soc_enum audio_inskew_enum = + SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(audio_inskew_texts), + audio_inskew_texts); + + +static int audio_inskew_get_enum( + struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + ucontrol->value.enumerated.item[0] = audio_inskew; + + return 0; +} + +static int audio_inskew_set_enum( + struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + unsigned int reg_in, off_set; + int inskew; + int id; + + id = (ucontrol->value.enumerated.item[0] >> 16) & 0xffff; + inskew = (int)(ucontrol->value.enumerated.item[0] & 0xffff); + audio_inskew = inskew; + off_set = EE_AUDIO_TDMIN_B_CTRL - EE_AUDIO_TDMIN_A_CTRL; + reg_in = EE_AUDIO_TDMIN_A_CTRL + off_set * id; + pr_info("id=%d set inskew=%d\n", id, inskew); + audiobus_update_bits(reg_in, 0x7 << 16, inskew << 16); + + return 0; +} + +static const char *const tdmout_c_binv_texts[] = { + "0", + "1", +}; + +static const struct soc_enum tdmout_c_binv_enum = + SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(tdmout_c_binv_texts), + tdmout_c_binv_texts); + + +static int tdmout_c_binv_get_enum( + struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + unsigned int val; + + val = audiobus_read(EE_AUDIO_CLK_TDMOUT_C_CTRL); + ucontrol->value.enumerated.item[0] = ((val >> 29) & 0x1); + + return 0; +} + +static int tdmout_c_binv_set_enum( + struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int binv; + + binv = ucontrol->value.enumerated.item[0]; + audiobus_update_bits(EE_AUDIO_CLK_TDMOUT_C_CTRL, 0x1 << 29, binv << 29); + + return 0; +} + + + #define SND_MIX(xname, type, xenum, xshift, xmask) \ SND_ENUM(xname, type, CTRL0, xenum, xshift, xmask) #define SND_SWAP(xname, type, xenum, xshift, xmask) \ + SND_ENUM(xname, type, SWAP0, xenum, xshift, xmask) + +#define SND_SPDIFOUT_SWAP(xname, type, xenum, xshift, xmask) \ SND_ENUM(xname, type, SWAP, xenum, xshift, xmask) #define TDM_MASK(xname, type, func) \ @@ -662,7 +747,7 @@ static const struct snd_kcontrol_new snd_auge_controls[] = { loopback_tdminlb_enum, loopback_tdminlb_get_enum, loopback_tdminlb_set_enum), - +#if 0 /*TDMIN_A swap*/ SND_SWAP("TDMIN_A Ch0 Swap", TDMIN_A, in_swap_channel_enum, 0, 0x7), SND_SWAP("TDMIN_A Ch1 Swap", TDMIN_A, in_swap_channel_enum, 4, 0x7), @@ -903,15 +988,16 @@ static const struct snd_kcontrol_new snd_auge_controls[] = { TDMOUT_C, lane2_mixer_enum, 22, 0x1), SND_MIX("TDMOUT_C Lane3 Mixer Channel", TDMOUT_C, lane3_mixer_enum, 23, 0x1), +#endif /* SPDIFIN Channel Status */ SPDIFIN_CHSTATUS("SPDIFIN Channel Status", spdif_channel_status_enum), /*SPDIFOUT swap*/ - SND_SWAP("SPDIFOUT Lane0 Left Channel Swap", + SND_SPDIFOUT_SWAP("SPDIFOUT Lane0 Left Channel Swap", SPDIFOUT, out_swap_channel_enum, 0, 0x7), - SND_SWAP("SPDIFOUT Lane0 Right Channel Swap", + SND_SPDIFOUT_SWAP("SPDIFOUT Lane0 Right Channel Swap", SPDIFOUT, out_swap_channel_enum, 4, 0x7), /*SPDIFOUT mixer*/ SND_MIX("SPDIFOUT Mixer Channel", @@ -925,6 +1011,17 @@ static const struct snd_kcontrol_new snd_auge_controls[] = { audio_locker_enum, audio_locker_get_enum, audio_locker_set_enum), + + /* audio inskew */ + SOC_ENUM_EXT("audio inskew set", + audio_inskew_enum, + audio_inskew_get_enum, + audio_inskew_set_enum), + /* tdmc out binv */ + SOC_ENUM_EXT("tdmout_c binv set", + tdmout_c_binv_enum, + tdmout_c_binv_get_enum, + tdmout_c_binv_set_enum), }; @@ -1492,6 +1589,20 @@ void auge_toacodec_ctrl(int tdmout_id) ); } +void auge_toacodec_ctrl_ext(int tdmout_id, int ch0_sel, int ch1_sel) +{ + // TODO: check skew for tl1/sm1 + audiobus_write(EE_AUDIO_TOACODEC_CTRL0, + 1 << 31 + | ((tdmout_id << 2) + ch1_sel) << 20 /* data 1 */ + | ((tdmout_id << 2) + ch0_sel) << 16 /* data 0 */ + | tdmout_id << 12 /* lrclk */ + | 1 << 9 /* Bclk_cap_inv*/ + | tdmout_id << 4 /* bclk */ + | tdmout_id << 0 /* mclk */ + ); +} + void fratv_enable(bool enable) { /* Need reset firstlry ? */ diff --git a/sound/soc/amlogic/auge/card.c b/sound/soc/amlogic/auge/card.c index 6d71f8fcccef..4550fbca4fbf 100644 --- a/sound/soc/amlogic/auge/card.c +++ b/sound/soc/amlogic/auge/card.c @@ -648,7 +648,7 @@ static int aml_card_dai_link_of(struct device_node *node, dai_link->ops = &aml_card_ops; dai_link->init = aml_card_dai_init; - + dai_link->nonatomic = 1; dev_dbg(dev, "\tname : %s\n", dai_link->stream_name); dev_dbg(dev, "\tformat : %04x\n", dai_link->dai_fmt); dev_dbg(dev, "\tcpu : %s / %d\n", @@ -877,6 +877,10 @@ static const struct of_device_id auge_of_match[] = { .compatible = "amlogic, tl1-sound-card", .data = &tl1_chipset_info, }, + { + .compatible = "amlogic, tm2-sound-card", + .data = &tl1_chipset_info, + }, {}, }; MODULE_DEVICE_TABLE(of, auge_of_match); @@ -919,9 +923,8 @@ static int aml_card_probe(struct platform_device *pdev) ret = aml_card_parse_of(np, priv); if (ret < 0) { - if (ret != -EPROBE_DEFER) - dev_err(dev, "%s, parse error %d\n", - __func__, ret); + dev_err(dev, "%s, parse error %d\n", + __func__, ret); goto err; } diff --git a/sound/soc/amlogic/auge/ddr_mngr.c b/sound/soc/amlogic/auge/ddr_mngr.c index 4d70dec390cd..8cd7392e88d4 100644 --- a/sound/soc/amlogic/auge/ddr_mngr.c +++ b/sound/soc/amlogic/auge/ddr_mngr.c @@ -67,6 +67,12 @@ static struct frddr_attach attach_aed; static void aml_check_aed(bool enable, int dst); static bool aml_check_aed_module(int dst); +static irqreturn_t aml_ddr_isr(int irq, void *devid) +{ + (void)devid; + return IRQ_WAKE_THREAD; +} + /* to DDRS */ static struct toddr *register_toddr_l(struct device *dev, struct aml_audio_controller *actrl, @@ -88,16 +94,17 @@ static struct toddr *register_toddr_l(struct device *dev, to = &toddrs[i]; /* irqs request */ - ret = request_irq(to->irq, handler, - 0, dev_name(dev), data); + ret = request_threaded_irq(to->irq, aml_ddr_isr, handler, + IRQF_SHARED, dev_name(dev), data); if (ret) { dev_err(dev, "failed to claim irq %u\n", to->irq); return NULL; } /* enable audio ddr arb */ mask_bit = i; - aml_audiobus_update_bits(actrl, EE_AUDIO_ARB_CTRL, - 1<<31|1<dev = dev; to->actrl = actrl; @@ -136,13 +143,14 @@ static int unregister_toddr_l(struct device *dev, void *data) /* disable audio ddr arb */ mask_bit = i; actrl = to->actrl; - aml_audiobus_update_bits(actrl, EE_AUDIO_ARB_CTRL, - 1<irq, data); to->dev = NULL; @@ -279,7 +287,7 @@ int aml_toddr_set_intrpt(struct toddr *to, unsigned int intrpt) reg = calc_toddr_address(EE_AUDIO_TODDR_A_INT_ADDR, reg_base); aml_audiobus_write(actrl, reg, intrpt); reg = calc_toddr_address(EE_AUDIO_TODDR_A_CTRL0, reg_base); - aml_audiobus_update_bits(actrl, reg, 0xff<<16, 4<<16); + aml_audiobus_update_bits(actrl, reg, 0xff << 16, 0x34 << 16); return 0; } @@ -317,7 +325,7 @@ unsigned int aml_toddr_get_addr(struct toddr *to, enum status_sel sel) /* reset to default, current write addr */ aml_audiobus_update_bits(actrl, reg_sel, 0xf << 8, - 0x0 << 8); + 0x2 << 8); return addr; } @@ -388,17 +396,17 @@ void aml_toddr_set_fifos(struct toddr *to, unsigned int thresh) if (to->chipinfo && to->chipinfo->src_sel_ctrl) { mask = 0xfff << 12 | 0xf << 8; - val = (thresh-1) << 12 | 2 << 8; + val = (thresh-2) << 12 | 2 << 8; } else { mask = 0xff << 16 | 0xf << 8; - val = (thresh-1) << 16 | 2 << 8; + val = (thresh-2) << 16 | 2 << 8; } aml_audiobus_update_bits(actrl, reg, mask, val); if (to->chipinfo && to->chipinfo->ugt) { reg = calc_toddr_address(EE_AUDIO_TODDR_A_CTRL0, reg_base); - aml_audiobus_update_bits(actrl, reg, 0x0 << 0, 0x1 << 0); + aml_audiobus_update_bits(actrl, reg, 0x1, 0x1); } } @@ -480,41 +488,78 @@ void aml_toddr_write(struct toddr *to, unsigned int val) aml_audiobus_write(actrl, reg, val); } -void aml_toddr_set_resample(struct toddr *to, bool enable) -{ - struct aml_audio_controller *actrl = to->actrl; - unsigned int reg_base = to->reg_base; - unsigned int reg; - - reg = calc_toddr_address(EE_AUDIO_TODDR_A_CTRL0, reg_base); - aml_audiobus_update_bits(actrl, reg, 1<<30, enable<<30); -} - -void aml_toddr_set_resample_ab(struct toddr *to, int asrc_src_sel, bool enable) +unsigned int aml_toddr_read1(struct toddr *to) { struct aml_audio_controller *actrl = to->actrl; unsigned int reg_base = to->reg_base; unsigned int reg; reg = calc_toddr_address(EE_AUDIO_TODDR_A_CTRL1, reg_base); - if (asrc_src_sel == 0) - aml_audiobus_update_bits(actrl, reg, 1 << 27, enable << 27); - else - aml_audiobus_update_bits(actrl, reg, 1 << 26, enable << 26); + + return aml_audiobus_read(actrl, reg); +} + +void aml_toddr_write1(struct toddr *to, unsigned int val) +{ + struct aml_audio_controller *actrl = to->actrl; + unsigned int reg_base = to->reg_base; + unsigned int reg; + + reg = calc_toddr_address(EE_AUDIO_TODDR_A_CTRL1, reg_base); + + aml_audiobus_write(actrl, reg, val); +} + +unsigned int aml_toddr_read_status2(struct toddr *to) +{ + struct aml_audio_controller *actrl = to->actrl; + unsigned int reg_base = to->reg_base; + unsigned int reg; + + reg = calc_toddr_address(EE_AUDIO_TODDR_A_STATUS2, reg_base); + + return aml_audiobus_read(actrl, reg); +} + +/* not for tl1 */ +static void aml_toddr_set_resample(struct toddr *to, bool enable) +{ + struct aml_audio_controller *actrl = to->actrl; + unsigned int reg_base = to->reg_base; + unsigned int reg; + + reg = calc_toddr_address(EE_AUDIO_TODDR_A_CTRL0, reg_base); + aml_audiobus_update_bits(actrl, reg, 1<<30, !!enable<<30); +} +/* tl1 after */ +static void aml_toddr_set_resample_ab(struct toddr *to, + enum resample_idx index, bool enable) +{ + struct aml_audio_controller *actrl = to->actrl; + unsigned int reg_base = to->reg_base; + unsigned int reg; + + reg = calc_toddr_address(EE_AUDIO_TODDR_A_CTRL1, reg_base); + if (index == RESAMPLE_A) + aml_audiobus_update_bits(actrl, reg, 1 << 27, !!enable << 27); + else if (index == RESAMPLE_B) + aml_audiobus_update_bits(actrl, reg, 1 << 26, !!enable << 26); } static void aml_resample_enable( + struct toddr *to, struct toddr_attach *p_attach_resample, bool enable) { - struct toddr *to = fetch_toddr_by_src(p_attach_resample->attach_module); - - if (!to) + if (!to || !p_attach_resample) { + pr_err("%s(), NULL pointer.", __func__); return; + } if (to->chipinfo && to->chipinfo->asrc_src_sel_ctrl) { /* fix asrc_src_sel */ + /* switch (p_attach_resample->attach_module) { case LOOPBACK_A: to->asrc_src_sel = ASRC_LOOPBACK_A; @@ -526,21 +571,24 @@ static void aml_resample_enable( to->asrc_src_sel = to->fifo_id; break; } + */ + to->asrc_src_sel = p_attach_resample->attach_module; } pr_info("toddr %d selects data to %s resample_%c for module:%s\n", to->fifo_id, enable ? "enable" : "disable", - (p_attach_resample->id == 0) ? 'a' : 'b', + (p_attach_resample->id == RESAMPLE_A) ? 'a' : 'b', toddr_src_get_str(p_attach_resample->attach_module) ); if (enable) { int bitwidth = to->bitdepth; /* channels and bit depth for resample */ + if (to->chipinfo && to->chipinfo->asrc_only_left_j - && (to->src == SPDIFIN) + /*&& (to->src == SPDIFIN)*/ && (bitwidth == 32)) { struct aml_audio_controller *actrl = to->actrl; unsigned int reg_base = to->reg_base; @@ -584,13 +632,14 @@ static void aml_resample_enable( aml_toddr_set_resample(to, enable); } -void aml_set_resample(int id, bool enable, int resample_module) +void aml_set_resample(enum resample_idx id, + bool enable, enum toddr_src resample_module) { struct toddr_attach *p_attach_resample; - + struct toddr *to; bool update_running = false; - if (id == 0) + if (id == RESAMPLE_A) p_attach_resample = &attach_resample_a; else p_attach_resample = &attach_resample_b; @@ -599,11 +648,12 @@ void aml_set_resample(int id, bool enable, int resample_module) p_attach_resample->id = id; p_attach_resample->attach_module = resample_module; + to = fetch_toddr_by_src( + p_attach_resample->attach_module); + if (enable) { if ((p_attach_resample->status == DISABLED) || (p_attach_resample->status == READY)) { - struct toddr *to = fetch_toddr_by_src( - p_attach_resample->attach_module); if (!to) { p_attach_resample->status = READY; @@ -620,8 +670,8 @@ void aml_set_resample(int id, bool enable, int resample_module) p_attach_resample->status = DISABLED; } - if (update_running) - aml_resample_enable(p_attach_resample, enable); + if (update_running && to) + aml_resample_enable(to, p_attach_resample, enable); } /* @@ -649,7 +699,7 @@ start_check: else p_attach_resample->status = DISABLED; - aml_resample_enable(p_attach_resample, enable); + aml_resample_enable(to, p_attach_resample, enable); } if ((!resample_b_check) @@ -830,12 +880,13 @@ static struct frddr *register_frddr_l(struct device *dev, /* enable audio ddr arb */ mask_bit = i + 4; - aml_audiobus_update_bits(actrl, EE_AUDIO_ARB_CTRL, - 1<<31|1<irq, handler, - 0, dev_name(dev), data); + ret = request_threaded_irq(from->irq, aml_ddr_isr, handler, + IRQF_SHARED, dev_name(dev), data); if (ret) { dev_err(dev, "failed to claim irq %u\n", from->irq); return NULL; @@ -871,13 +922,14 @@ static int unregister_frddr_l(struct device *dev, void *data) /* disable audio ddr arb */ mask_bit = i + 4; actrl = from->actrl; - aml_audiobus_update_bits(actrl, EE_AUDIO_ARB_CTRL, - 1<irq, data); from->dev = NULL; @@ -915,33 +967,6 @@ struct frddr *fetch_frddr_by_src(int frddr_src) return NULL; } -/* - * check frddr_src is used by other frddr for sharebuffer - * if used, disabled the other share frddr src, the module would - * for current frddr, and the checked frddr - */ -int aml_check_sharebuffer_valid(struct frddr *fr, int ss_sel) -{ - int current_fifo_id = fr->fifo_id; - unsigned int i; - int ret = 1; - - for (i = 0; i < DDRMAX; i++) { - if (frddrs[i].in_use - && (frddrs[i].fifo_id != current_fifo_id) - && (frddrs[i].dest == ss_sel)) { - - pr_info(" frddr:%d, ss_sel:%d used, invalid for share buffer\n", - i, - ss_sel); - ret = 0; - break; - } - } - - return ret; -} - struct frddr *aml_audio_register_frddr(struct device *dev, struct aml_audio_controller *actrl, irq_handler_t handler, void *data) @@ -970,6 +995,137 @@ static inline unsigned int return base + reg - EE_AUDIO_FRDDR_A_CTRL0; } +/* + * check frddr_src is used by other frddr for sharebuffer + * if used, disabled the other share frddr src, the module would + * for current frddr, and the checked frddr + */ +int aml_check_sharebuffer_valid(struct frddr *fr, int ss_sel) +{ + int current_fifo_id = fr->fifo_id; + unsigned int i; + int ret = 1; + + for (i = 0; i < DDRMAX; i++) { + if (frddrs[i].in_use + && (frddrs[i].fifo_id != current_fifo_id) + && (frddrs[i].dest == ss_sel)) { + + pr_debug("%s, ss_sel:%d used, not for share buffer at same time\n", + __func__, + ss_sel); + ret = 0; + break; + } + } + + return ret; +} + +/* select dst for same source + * sel: share buffer req_sel 1~2 + * sel 0 is aleardy used for reg_frddr_src_sel1 + * sel 1 is for reg_frddr_src_sel2 + * sel 2 is for reg_frddr_src_sel3 + */ +static void frddr_set_sharebuffer_enable( + struct frddr *fr, int dst, int sel, bool enable) +{ + struct aml_audio_controller *actrl = fr->actrl; + unsigned int reg_base = fr->reg_base; + unsigned int reg; + int s_v = 0, s_m = 0; + + if (fr->chipinfo + && fr->chipinfo->src_sel_ctrl) { + reg = calc_frddr_address(EE_AUDIO_FRDDR_A_CTRL2, + reg_base); + + switch (sel) { + case 1: + s_m = 0x17 << 8; + s_v = enable ? + (dst << 8 | 1 << 12) : 0 << 8; + break; + case 2: + s_m = 0x17 << 16; + s_v = enable ? + (dst << 16 | 1 << 20) : 0 << 16; + break; + default: + pr_warn_once("sel :%d is not supported for same source\n", + sel); + break; + } + s_m |= 0xff << 24; + if (enable) + s_v |= (fr->channels - 1) << 24; + else + s_v |= 0x0 << 24; + } else { + reg = calc_frddr_address(EE_AUDIO_FRDDR_A_CTRL0, + reg_base); + + switch (sel) { + case 1: + s_m = 0xf << 4; + s_v = enable ? + (dst << 4 | 1 << 7) : 0 << 4; + break; + case 2: + s_m = 0xf << 8; + s_v = enable ? + (dst << 8 | 1 << 11) : 0 << 8; + break; + default: + pr_warn_once("sel :%d is not supported for same source\n", + sel); + break; + } + } + pr_debug("%s sel:%d, dst_src:%d\n", + __func__, sel, dst); + fr->ss_dest = enable ? dst : 0; + fr->ss_en = enable; + + aml_audiobus_update_bits(actrl, reg, s_m, s_v); +} + +/* + * check frddr_src is used by other frddr for sharebuffer + * if used for share frddr src, release from sharebuffer + * and used for new frddr + */ +static int aml_check_and_release_sharebuffer(struct frddr *fr, int ss_sel) +{ + int current_fifo_id = fr->fifo_id; + unsigned int i; + int ret = 1; + + for (i = 0; i < DDRMAX; i++) { + struct frddr *from = &frddrs[i]; + + if (from->in_use + && (from->fifo_id != current_fifo_id) + && from->ss_en + && (from->ss_dest == ss_sel)) { + + frddr_set_sharebuffer_enable(from, + ss_sel, + 1, + false); + + pr_debug("%s, ss_sel:%d release from share buffer, use for new playback\n", + __func__, + ss_sel); + ret = 0; + break; + } + } + + return ret; +} + int aml_frddr_set_buf(struct frddr *fr, unsigned int start, unsigned int end) { @@ -1060,6 +1216,11 @@ void aml_frddr_select_dst(struct frddr *fr, enum frddr_dest dst) src_sel_en = 3; } + /* if sharebuffer in use, release it */ + if (fr->chipinfo + && fr->chipinfo->same_src_fn) + aml_check_and_release_sharebuffer(fr, dst); + aml_audiobus_update_bits(actrl, reg, 0x7, dst & 0x7); /* same source en */ @@ -1079,69 +1240,14 @@ void aml_frddr_select_dst(struct frddr *fr, enum frddr_dest dst) void aml_frddr_select_dst_ss(struct frddr *fr, enum frddr_dest dst, int sel, bool enable) { - struct aml_audio_controller *actrl = fr->actrl; - unsigned int reg_base = fr->reg_base; - unsigned int reg, ss_valid; - - ss_valid = aml_check_sharebuffer_valid(fr, dst); + unsigned int ss_valid = aml_check_sharebuffer_valid(fr, dst); /* same source en */ if (fr->chipinfo && fr->chipinfo->same_src_fn - && ss_valid) { - int s_v = 0, s_m = 0; - - if (fr->chipinfo - && fr->chipinfo->src_sel_ctrl) { - reg = calc_frddr_address(EE_AUDIO_FRDDR_A_CTRL2, - reg_base); - - switch (sel) { - case 1: - s_m = 0x17 << 8; - s_v = enable ? - (dst << 8 | 1 << 12) : 0 << 8; - break; - case 2: - s_m = 0x17 << 16; - s_v = enable ? - (dst << 16 | 1 << 20) : 0 << 16; - break; - default: - pr_warn_once("sel :%d is not supported for same source\n", - sel); - break; - } - s_m |= 0xff << 24; - if (enable) - s_v |= (fr->channels - 1) << 24; - else - s_v |= 0x0 << 24; - } else { - reg = calc_frddr_address(EE_AUDIO_FRDDR_A_CTRL0, - reg_base); - - switch (sel) { - case 1: - s_m = 0xf << 4; - s_v = enable ? - (dst << 4 | 1 << 7) : 0 << 4; - break; - case 2: - s_m = 0xf << 8; - s_v = enable ? - (dst << 8 | 1 << 11) : 0 << 8; - break; - default: - pr_warn_once("sel :%d is not supported for same source\n", - sel); - break; - } - } - pr_debug("%s sel:%d, dst_src:%d\n", - __func__, sel, dst); - aml_audiobus_update_bits(actrl, reg, s_m, s_v); - } + && ss_valid + ) + frddr_set_sharebuffer_enable(fr, dst, sel, enable); } void aml_frddr_set_fifos(struct frddr *fr, @@ -1157,8 +1263,8 @@ void aml_frddr_set_fifos(struct frddr *fr, (depth - 1)<<24 | (thresh - 1)<<16 | 2<<8); if (fr->chipinfo && fr->chipinfo->ugt) { - reg = calc_toddr_address(EE_AUDIO_FRDDR_A_CTRL0, reg_base); - aml_audiobus_update_bits(actrl, reg, 0x0 << 0, 0x1 << 0); + reg = calc_frddr_address(EE_AUDIO_FRDDR_A_CTRL0, reg_base); + aml_audiobus_update_bits(actrl, reg, 0x1, 0x1); } } @@ -1177,28 +1283,22 @@ void aml_frddr_set_format(struct frddr *fr, fr->type = frddr_type; } - static void aml_aed_enable(struct frddr_attach *p_attach_aed, bool enable) { struct frddr *fr = fetch_frddr_by_src(p_attach_aed->attach_module); - if (check_aed_v2()) { - if (fr->chipinfo - && fr->chipinfo->src_sel_ctrl) { - struct aml_audio_controller *actrl = fr->actrl; - unsigned int reg_base = fr->reg_base; - unsigned int reg; + struct aml_audio_controller *actrl = fr->actrl; + unsigned int reg_base = fr->reg_base; + unsigned int reg; - reg = calc_frddr_address(EE_AUDIO_FRDDR_A_CTRL2, - reg_base); - aml_audiobus_update_bits(actrl, - reg, 0x1 << 3, enable << 3); - } + reg = calc_frddr_address(EE_AUDIO_FRDDR_A_CTRL2, reg_base); + aml_audiobus_update_bits(actrl, + reg, 0x1 << 3, enable << 3); aed_set_ctrl(enable, 0, p_attach_aed->attach_module); - aed_set_format(fr->msb, fr->type); - aed_enable(enable, fr->dest, fr->fifo_id); + aed_set_format(fr->msb, fr->type, fr->fifo_id); + aed_enable(enable); } else { if (enable) { /* frddr type and bit depth for AED */ @@ -1322,13 +1422,13 @@ void frddr_deinit_without_mngr(unsigned int frddr_index) audiobus_write(reg, 0x0); } -static int toddr_src_idx = -1; +static enum toddr_src toddr_src_idx = TODDR_INVAL; static const char *const toddr_src_sel_texts[] = { "TDMIN_A", "TDMIN_B", "TDMIN_C", "SPDIFIN", "PDMIN", "FRATV", "TDMIN_LB", "LOOPBACK_A", "FRHDMIRX", "LOOPBACK_B", "SPDIFIN_LB", - "RESERVED", "RESERVED", "RESERVED", "RESERVED", + "EARCRX_DMAC", "RESERVED_0", "RESERVED_1", "RESERVED_2", "VAD" }; @@ -1336,14 +1436,14 @@ static const struct soc_enum toddr_input_source_enum = SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(toddr_src_sel_texts), toddr_src_sel_texts); -int toddr_src_get(void) +enum toddr_src toddr_src_get(void) { return toddr_src_idx; } -const char *toddr_src_get_str(int idx) +const char *toddr_src_get_str(enum toddr_src idx) { - if (idx < 0 || idx > 15) + if (idx < TDMIN_A || idx > VAD) return NULL; return toddr_src_sel_texts[idx]; @@ -1361,6 +1461,8 @@ static int toddr_src_enum_set(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { toddr_src_idx = ucontrol->value.enumerated.item[0]; + /* also update to resample src */ + //set_resample_source(toddr_src_idx); return 0; } @@ -1452,6 +1554,15 @@ static struct ddr_chipinfo tl1_ddr_chipinfo = { .wakeup = 2, }; +static struct ddr_chipinfo sm1_ddr_chipinfo = { + .same_src_fn = true, + .ugt = true, + .src_sel_ctrl = true, + .asrc_src_sel_ctrl = true, + .fifo_num = 4, + .wakeup = 2, +}; + static const struct of_device_id aml_ddr_mngr_device_id[] = { { .compatible = "amlogic, axg-audio-ddr-manager", @@ -1465,6 +1576,10 @@ static const struct of_device_id aml_ddr_mngr_device_id[] = { .compatible = "amlogic, tl1-audio-ddr-manager", .data = &tl1_ddr_chipinfo, }, + { + .compatible = "amlogic, sm1-audio-ddr-manager", + .data = &sm1_ddr_chipinfo, + }, {}, }; MODULE_DEVICE_TABLE(of, aml_ddr_mngr_device_id); @@ -1528,6 +1643,8 @@ static int aml_ddr_mngr_platform_probe(struct platform_device *pdev) && (p_ddr_chipinfo->fifo_num == 4)) { toddrs[DDR_D].irq = platform_get_irq_byname(pdev, "toddr_d"); frddrs[DDR_D].irq = platform_get_irq_byname(pdev, "frddr_d"); + if (toddrs[DDR_D].irq < 0 || frddrs[DDR_D].irq < 0) + dev_err(&pdev->dev, "check irq for DDR_D\n"); ddr_num = p_ddr_chipinfo->fifo_num; } diff --git a/sound/soc/amlogic/auge/ddr_mngr.h b/sound/soc/amlogic/auge/ddr_mngr.h index ab1c795b64b1..c787662707d0 100644 --- a/sound/soc/amlogic/auge/ddr_mngr.h +++ b/sound/soc/amlogic/auge/ddr_mngr.h @@ -42,18 +42,29 @@ enum ddr_types { * from tl1, add new source FRATV, FRHDMIRX, LOOPBACK_B, SPDIFIN_LB, VAD */ enum toddr_src { - TDMIN_A, - TDMIN_B, - TDMIN_C, - SPDIFIN, - PDMIN, - FRATV, /* NONE for axg, g12a, g12b */ - TDMIN_LB, - LOOPBACK_A, - FRHDMIRX, /* from tl1 chipset*/ - LOOPBACK_B, - SPDIFIN_LB, - VAD, + TODDR_INVAL = -1, + TDMIN_A = 0, + TDMIN_B = 1, + TDMIN_C = 2, + SPDIFIN = 3, + PDMIN = 4, + FRATV = 5, /* NONE for axg, g12a, g12b */ + TDMIN_LB = 6, + LOOPBACK_A = 7, + FRHDMIRX = 8, /* from tl1 chipset*/ + LOOPBACK_B = 9, + SPDIFIN_LB = 10, + EARCRX_DMAC = 11,/* from sm1 chipset */ + RESERVED_0 = 12, + RESERVED_1 = 13, + RESERVED_2 = 14, + VAD = 15, + TODDR_SRC_MAX = 16 +}; + +enum resample_idx { + RESAMPLE_A, + RESAMPLE_B }; enum resample_src { @@ -176,7 +187,7 @@ struct toddr { enum toddr_src src; unsigned int fifo_id; - unsigned int asrc_src_sel; + enum toddr_src asrc_src_sel; int is_lb; /* check whether for loopback */ int irq; @@ -193,7 +204,7 @@ enum status { struct toddr_attach { bool enable; - int id; + enum resample_idx id; int status; /* which module should be attached, * check which toddr in use should be attached @@ -214,9 +225,14 @@ struct frddr { //struct ddr_desc dscrpt; struct device *dev; enum frddr_dest dest; + + /* dest for same source, whether enable */ + enum frddr_dest ss_dest; + bool ss_en; + struct aml_audio_controller *actrl; unsigned int reg_base; - unsigned int fifo_id; + enum ddr_num fifo_id; unsigned int channels; unsigned int msb; @@ -251,9 +267,13 @@ void aml_toddr_set_format(struct toddr *to, struct toddr_fmt *fmt); void aml_toddr_insert_chanum(struct toddr *to); unsigned int aml_toddr_read(struct toddr *to); void aml_toddr_write(struct toddr *to, unsigned int val); +unsigned int aml_toddr_read1(struct toddr *to); +void aml_toddr_write1(struct toddr *to, unsigned int val); +unsigned int aml_toddr_read_status2(struct toddr *to); /* resample */ -void aml_set_resample(int id, bool enable, int resample_module); +void aml_set_resample(enum resample_idx id, + bool enable, enum toddr_src resample_module); /* power detect */ void aml_pwrdet_enable(bool enable, int pwrdet_module); /* Voice Activity Detection */ @@ -291,8 +311,8 @@ void aml_set_aed(bool enable, int aed_module); void frddr_init_without_mngr(unsigned int frddr_index, unsigned int src0_sel); void frddr_deinit_without_mngr(unsigned int frddr_index); -int toddr_src_get(void); -const char *toddr_src_get_str(int idx); +enum toddr_src toddr_src_get(void); +const char *toddr_src_get_str(enum toddr_src idx); int frddr_src_get(void); const char *frddr_src_get_str(int idx); diff --git a/sound/soc/amlogic/auge/earc.c b/sound/soc/amlogic/auge/earc.c new file mode 100644 index 000000000000..30b5f30d0aec --- /dev/null +++ b/sound/soc/amlogic/auge/earc.c @@ -0,0 +1,806 @@ +/* + * sound/soc/amlogic/auge/earc.c + * + * Copyright (C) 2019 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. + * + * Audio External Input/Out drirver + * such as fratv, frhdmirx + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ddr_mngr.h" +#include "earc_hw.h" + +#define DRV_NAME "EARC" + +struct earc { + struct aml_audio_controller *actrl; + struct device *dev; + + struct clk *clk_rx_gate; + struct clk *clk_rx_cmdc; + struct clk *clk_rx_dmac; + struct clk *clk_rx_cmdc_srcpll; + struct clk *clk_rx_dmac_srcpll; + struct clk *clk_tx_gate; + struct clk *clk_tx_cmdc; + struct clk *clk_tx_dmac; + struct clk *clk_tx_cmdc_srcpll; + struct clk *clk_tx_dmac_srcpll; + + struct toddr *tddr; + struct frddr *fddr; + + int irq_rx_cmdc; + int irq_rx_dmac; + int irq_tx_cmdc; + int irq_tx_dmac; + + int sysclk_freq; +}; + +#define PREALLOC_BUFFER_MAX (256 * 1024) + +#define EARC_RATES (SNDRV_PCM_RATE_8000_192000) +#define EARC_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ + SNDRV_PCM_FMTBIT_S24_LE |\ + SNDRV_PCM_FMTBIT_S32_LE) + +static const struct snd_pcm_hardware earc_hardware = { + .info = + SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_BLOCK_TRANSFER | + SNDRV_PCM_INFO_PAUSE, + + .formats = EARC_FORMATS, + + .period_bytes_min = 64, + .period_bytes_max = 128 * 1024, + .periods_min = 2, + .periods_max = 1024, + .buffer_bytes_max = 256 * 1024, + + .rate_min = 8000, + .rate_max = 192000, + .channels_min = 1, + .channels_max = 32, +}; + +static irqreturn_t earc_ddr_isr(int irq, void *devid) +{ + struct snd_pcm_substream *substream = + (struct snd_pcm_substream *)devid; + + if (!snd_pcm_running(substream)) + return IRQ_HANDLED; + + snd_pcm_period_elapsed(substream); + + return IRQ_HANDLED; +} + +static irqreturn_t earc_rx_cmdc_isr(int irq, void *devid) +{ + return IRQ_HANDLED; +} + +static irqreturn_t earc_rx_dmac_isr(int irq, void *devid) +{ + return IRQ_HANDLED; +} + +static irqreturn_t earc_tx_cmdc_isr(int irq, void *devid) +{ + return IRQ_HANDLED; +} + +static irqreturn_t earc_tx_dmac_isr(int irq, void *devid) +{ + return IRQ_HANDLED; +} + +static int earc_open(struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct device *dev = rtd->platform->dev; + struct earc *p_earc; + int ret = 0; + + pr_info("asoc debug: %s-%d\n", __func__, __LINE__); + + p_earc = (struct earc *)dev_get_drvdata(dev); + + snd_soc_set_runtime_hwparams(substream, &earc_hardware); + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + p_earc->fddr = aml_audio_register_frddr(dev, + p_earc->actrl, + earc_ddr_isr, substream); + if (p_earc->fddr == NULL) { + dev_err(dev, "failed to claim from ddr\n"); + return -ENXIO; + } + if (p_earc->irq_tx_cmdc > 0) { + ret = request_irq(p_earc->irq_tx_cmdc, + earc_tx_cmdc_isr, 0, "tx_cmdc", + p_earc); + if (ret) { + dev_err(p_earc->dev, "failed to claim irq_tx_cmdc %u\n", + p_earc->irq_tx_cmdc); + return ret; + } + } + if (p_earc->irq_tx_dmac > 0) { + ret = request_irq(p_earc->irq_tx_dmac, + earc_tx_dmac_isr, 0, "tx_dmac", + p_earc); + if (ret) { + dev_err(p_earc->dev, "failed to claim irq_tx_dmac %u\n", + p_earc->irq_tx_dmac); + return ret; + } + } + } else { + p_earc->tddr = aml_audio_register_toddr(dev, + p_earc->actrl, + earc_ddr_isr, substream); + if (p_earc->tddr == NULL) { + dev_err(dev, "failed to claim to ddr\n"); + return -ENXIO; + } + + ret = request_irq(p_earc->irq_rx_cmdc, + earc_rx_cmdc_isr, 0, "rx_cmdc", + p_earc); + if (ret) { + dev_err(p_earc->dev, "failed to claim irq_rx_cmdc %u\n", + p_earc->irq_rx_cmdc); + return ret; + } + ret = request_irq(p_earc->irq_rx_dmac, + earc_rx_dmac_isr, 0, "rx_dmac", + p_earc); + if (ret) { + dev_err(p_earc->dev, "failed to claim rx_dmac %u\n", + p_earc->irq_rx_dmac); + return ret; + } + } + + runtime->private_data = p_earc; + + return 0; +} + +static int earc_close(struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct earc *p_earc = runtime->private_data; + + pr_info("asoc debug: %s-%d\n", __func__, __LINE__); + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + aml_audio_unregister_frddr(p_earc->dev, substream); + + if (p_earc->irq_tx_cmdc > 0) + free_irq(p_earc->irq_tx_cmdc, p_earc); + + if (p_earc->irq_tx_dmac > 0) + free_irq(p_earc->irq_tx_dmac, p_earc); + } else { + aml_audio_unregister_toddr(p_earc->dev, substream); + free_irq(p_earc->irq_rx_cmdc, p_earc); + free_irq(p_earc->irq_rx_dmac, p_earc); + } + runtime->private_data = NULL; + + return 0; +} + +static int earc_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *hw_params) +{ + return snd_pcm_lib_malloc_pages(substream, + params_buffer_bytes(hw_params)); +} + +static int earc_hw_free(struct snd_pcm_substream *substream) +{ + snd_pcm_lib_free_pages(substream); + + return 0; +} + +static int earc_trigger(struct snd_pcm_substream *substream, int cmd) +{ + return 0; +} + +static int earc_prepare(struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct earc *p_earc = runtime->private_data; + unsigned int start_addr, end_addr, int_addr; + + start_addr = runtime->dma_addr; + end_addr = start_addr + runtime->dma_bytes - 8; + int_addr = frames_to_bytes(runtime, runtime->period_size) / 8; + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + struct frddr *fr = p_earc->fddr; + + aml_frddr_set_buf(fr, start_addr, end_addr); + aml_frddr_set_intrpt(fr, int_addr); + } else { + struct toddr *to = p_earc->tddr; + + aml_toddr_set_buf(to, start_addr, end_addr); + aml_toddr_set_intrpt(to, int_addr); + } + + return 0; +} + +static snd_pcm_uframes_t earc_pointer(struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct earc *p_earc = runtime->private_data; + unsigned int addr, start_addr; + snd_pcm_uframes_t frames; + + start_addr = runtime->dma_addr; + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + addr = aml_frddr_get_position(p_earc->fddr); + else + addr = aml_toddr_get_position(p_earc->tddr); + + frames = bytes_to_frames(runtime, addr - start_addr); + if (frames > runtime->buffer_size) + frames = 0; + + return frames; +} + +int earc_silence(struct snd_pcm_substream *substream, int channel, + snd_pcm_uframes_t pos, snd_pcm_uframes_t count) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + char *ppos; + int n; + + n = frames_to_bytes(runtime, count); + ppos = runtime->dma_area + frames_to_bytes(runtime, pos); + memset(ppos, 0, n); + + return 0; +} + +static int earc_mmap(struct snd_pcm_substream *substream, + struct vm_area_struct *vma) +{ + return snd_pcm_lib_default_mmap(substream, vma); +} + +static struct snd_pcm_ops earc_ops = { + .open = earc_open, + .close = earc_close, + .ioctl = snd_pcm_lib_ioctl, + .hw_params = earc_hw_params, + .hw_free = earc_hw_free, + .prepare = earc_prepare, + .trigger = earc_trigger, + .pointer = earc_pointer, + .silence = earc_silence, + .mmap = earc_mmap, +}; + +static int earc_new(struct snd_soc_pcm_runtime *rtd) +{ + return snd_pcm_lib_preallocate_pages_for_all( + rtd->pcm, SNDRV_DMA_TYPE_DEV, + rtd->card->snd_card->dev, + PREALLOC_BUFFER_MAX, + PREALLOC_BUFFER_MAX); +} + +struct snd_soc_platform_driver earc_platform = { + .ops = &earc_ops, + .pcm_new = earc_new, +}; + +static int earc_dai_probe(struct snd_soc_dai *cpu_dai) +{ + pr_info("asoc debug: %s-%d\n", __func__, __LINE__); + + return 0; +} + +static int earc_dai_remove(struct snd_soc_dai *cpu_dai) +{ + return 0; +} + +static int earc_dai_prepare( + struct snd_pcm_substream *substream, + struct snd_soc_dai *cpu_dai) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct earc *p_earc = snd_soc_dai_get_drvdata(cpu_dai); + unsigned int bit_depth = snd_pcm_format_width(runtime->format); + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + struct frddr *fr = p_earc->fddr; + enum frddr_dest dst = frddr_src_get(); + + pr_info("%s Expected frddr dst:%s\n", + __func__, + frddr_src_get_str(dst)); + + aml_frddr_select_dst(fr, dst); + aml_frddr_set_fifos(fr, 0x40, 0x20); + } else { + struct toddr *to = p_earc->tddr; + unsigned int msb = 0, lsb = 0, toddr_type = 0; + unsigned int src = EARCRX_DMAC; + struct toddr_fmt fmt; + + if (bit_depth == 32) + toddr_type = 3; + else if (bit_depth == 24) + toddr_type = 4; + else + toddr_type = 0; + + pr_info("%s Expected toddr src:%s\n", + __func__, + toddr_src_get_str(src)); + + msb = 28 - 1; + if (bit_depth == 16) + lsb = 28 - bit_depth; + else + lsb = 4; + + pr_info("%s m:%d, n:%d, toddr type:%d\n", + __func__, msb, lsb, toddr_type); + + fmt.type = toddr_type; + fmt.msb = msb; + fmt.lsb = lsb; + fmt.endian = 0; + fmt.bit_depth = bit_depth; + fmt.ch_num = runtime->channels; + fmt.rate = runtime->rate; + + aml_toddr_select_src(to, src); + aml_toddr_set_format(to, &fmt); + aml_toddr_set_fifos(to, 0x40); + + earcrx_cmdc_init(); + earcrx_dmac_init(); + earc_arc_init(); + + } + + return 0; +} + +static int earc_dai_trigger(struct snd_pcm_substream *substream, int cmd, + struct snd_soc_dai *cpu_dai) +{ + struct earc *p_earc = snd_soc_dai_get_drvdata(cpu_dai); + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + dev_info(substream->pcm->card->dev, "eARC/ARC TX enable\n"); + + aml_frddr_enable(p_earc->fddr, true); + } else { + dev_info(substream->pcm->card->dev, "eARC/ARC RX enable\n"); + + aml_toddr_enable(p_earc->tddr, true); + + earc_rx_enable(true); + } + break; + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + dev_info(substream->pcm->card->dev, "eARC/ARC TX disable\n"); + + aml_frddr_enable(p_earc->fddr, false); + } else { + dev_info(substream->pcm->card->dev, "eARC/ARC RX disable\n"); + + earc_rx_enable(false); + + aml_toddr_enable(p_earc->tddr, false); + } + break; + default: + return -EINVAL; + } + + return 0; +} + +static int earc_dai_hw_params( + struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *cpu_dai) +{ + struct earc *p_earc = snd_soc_dai_get_drvdata(cpu_dai); + unsigned int rate = params_rate(params); + int ret = 0; + + pr_info("%s:rate:%d, sysclk:%d\n", + __func__, + rate, + p_earc->sysclk_freq); + + return ret; +} + +static int earc_dai_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) +{ + struct earc *p_earc = snd_soc_dai_get_drvdata(cpu_dai); + + pr_info("asoc earc_dai_set_fmt, %#x, %p\n", fmt, p_earc); + + return 0; +} + +static int earc_dai_set_sysclk(struct snd_soc_dai *cpu_dai, + int clk_id, unsigned int freq, int dir) +{ + struct earc *p_earc = snd_soc_dai_get_drvdata(cpu_dai); + + p_earc->sysclk_freq = freq; + pr_info("earc_dai_set_sysclk, %d, %d, %d\n", + clk_id, freq, dir); + + clk_set_rate(p_earc->clk_rx_cmdc, 10000000); + clk_set_rate(p_earc->clk_rx_dmac, 250000000); + + pr_info("earc rx cmdc clk:%lu rx dmac clk:%lu\n", + clk_get_rate(p_earc->clk_rx_cmdc), + clk_get_rate(p_earc->clk_rx_dmac)); + + return 0; +} + +static int earc_dai_startup( + struct snd_pcm_substream *substream, + struct snd_soc_dai *cpu_dai) +{ + struct earc *p_earc = snd_soc_dai_get_drvdata(cpu_dai); + int ret; + + /* enable clock gate */ + if (!IS_ERR(p_earc->clk_rx_gate)) { + ret = clk_prepare_enable(p_earc->clk_rx_gate); + if (ret) { + pr_err("Can't enable earc rx_gate: %d\n", ret); + goto err; + } + } + + audiobus_update_bits(EE_AUDIO_CLK_GATE_EN1, 0x1 << 6, 0x1 << 6); + + /* enable clock */ + if (!IS_ERR(p_earc->clk_rx_cmdc)) { + ret = clk_prepare_enable(p_earc->clk_rx_cmdc); + if (ret) { + pr_err("Can't enable earc clk_rx_cmdc: %d\n", ret); + goto err; + } + } + if (!IS_ERR(p_earc->clk_rx_dmac)) { + ret = clk_prepare_enable(p_earc->clk_rx_dmac); + if (ret) { + pr_err("Can't enable earc clk_rx_dmac: %d\n", ret); + goto err; + } + } + if (!IS_ERR(p_earc->clk_tx_cmdc)) { + ret = clk_prepare_enable(p_earc->clk_tx_cmdc); + if (ret) { + pr_err("Can't enable earc clk_tx_cmdc: %d\n", ret); + goto err; + } + } + if (!IS_ERR(p_earc->clk_tx_dmac)) { + ret = clk_prepare_enable(p_earc->clk_tx_dmac); + if (ret) { + pr_err("Can't enable earc clk_tx_dmac: %d\n", ret); + goto err; + } + } + + return 0; +err: + pr_err("failed enable clock\n"); + return -EINVAL; +} + + +static void earc_dai_shutdown( + struct snd_pcm_substream *substream, + struct snd_soc_dai *cpu_dai) +{ + struct earc *p_earc = snd_soc_dai_get_drvdata(cpu_dai); + + /* disable clock and gate */ + if (!IS_ERR(p_earc->clk_rx_cmdc)) + clk_disable_unprepare(p_earc->clk_rx_cmdc); + if (!IS_ERR(p_earc->clk_rx_dmac)) + clk_disable_unprepare(p_earc->clk_rx_dmac); + if (!IS_ERR(p_earc->clk_tx_cmdc)) + clk_disable_unprepare(p_earc->clk_tx_cmdc); + if (!IS_ERR(p_earc->clk_tx_dmac)) + clk_disable_unprepare(p_earc->clk_tx_dmac); + if (!IS_ERR(p_earc->clk_rx_gate)) + clk_disable_unprepare(p_earc->clk_rx_gate); + + audiobus_update_bits(EE_AUDIO_CLK_GATE_EN1, 0x1 << 6, 0x0 << 6); +} + +static struct snd_soc_dai_ops earc_dai_ops = { + .prepare = earc_dai_prepare, + .trigger = earc_dai_trigger, + .hw_params = earc_dai_hw_params, + .set_fmt = earc_dai_set_fmt, + .set_sysclk = earc_dai_set_sysclk, + .startup = earc_dai_startup, + .shutdown = earc_dai_shutdown, +}; + +static struct snd_soc_dai_driver earc_dai[] = { + { + .name = "EARC/ARC", + .id = 0, + .probe = earc_dai_probe, + .remove = earc_dai_remove, + .playback = { + .channels_min = 1, + .channels_max = 32, + .rates = EARC_RATES, + .formats = EARC_FORMATS, + }, + .capture = { + .channels_min = 1, + .channels_max = 32, + .rates = EARC_RATES, + .formats = EARC_FORMATS, + }, + .ops = &earc_dai_ops, + }, +}; + +static const struct snd_kcontrol_new earc_controls[] = { + + +}; + +static const struct snd_soc_component_driver earc_component = { + .controls = earc_controls, + .num_controls = ARRAY_SIZE(earc_controls), + .name = DRV_NAME, +}; + +static const struct of_device_id earc_device_id[] = { + { + .compatible = "amlogic, sm1-snd-earc", + }, + { + .compatible = "amlogic, tm2-snd-earc", + }, + {}, +}; + +MODULE_DEVICE_TABLE(of, earc_device_id); + +static int earc_platform_probe(struct platform_device *pdev) +{ + struct device_node *node = pdev->dev.of_node; + struct device_node *node_prt = NULL; + struct platform_device *pdev_parent; + struct device *dev = &pdev->dev; + struct aml_audio_controller *actrl = NULL; + struct earc *p_earc = NULL; + int ret = 0; + + + p_earc = devm_kzalloc(dev, sizeof(struct earc), GFP_KERNEL); + if (!p_earc) + return -ENOMEM; + + p_earc->dev = dev; + dev_set_drvdata(dev, p_earc); + + /* get audio controller */ + node_prt = of_get_parent(node); + if (node_prt == NULL) + return -ENXIO; + + pdev_parent = of_find_device_by_node(node_prt); + of_node_put(node_prt); + actrl = (struct aml_audio_controller *) + platform_get_drvdata(pdev_parent); + p_earc->actrl = actrl; + + /* clock gate */ + p_earc->clk_rx_gate = devm_clk_get(&pdev->dev, "rx_gate"); + if (IS_ERR(p_earc->clk_rx_gate)) { + dev_err(&pdev->dev, + "Can't get earc gate\n"); + /*return PTR_ERR(p_earc->clk_rx_gate);*/ + } + /* RX */ + p_earc->clk_rx_cmdc = devm_clk_get(&pdev->dev, "rx_cmdc"); + if (IS_ERR(p_earc->clk_rx_cmdc)) { + dev_err(&pdev->dev, + "Can't get clk_rx_cmdc\n"); + return PTR_ERR(p_earc->clk_rx_cmdc); + } + p_earc->clk_rx_dmac = devm_clk_get(&pdev->dev, "rx_dmac"); + if (IS_ERR(p_earc->clk_rx_dmac)) { + dev_err(&pdev->dev, + "Can't get clk_rx_dmac\n"); + return PTR_ERR(p_earc->clk_rx_dmac); + } + p_earc->clk_rx_cmdc_srcpll = devm_clk_get(&pdev->dev, "rx_cmdc_srcpll"); + if (IS_ERR(p_earc->clk_rx_cmdc_srcpll)) { + dev_err(&pdev->dev, + "Can't get clk_rx_cmdc_srcpll\n"); + return PTR_ERR(p_earc->clk_rx_cmdc_srcpll); + } + p_earc->clk_rx_dmac_srcpll = devm_clk_get(&pdev->dev, "rx_dmac_srcpll"); + if (IS_ERR(p_earc->clk_rx_dmac_srcpll)) { + dev_err(&pdev->dev, + "Can't get clk_rx_dmac_srcpll\n"); + return PTR_ERR(p_earc->clk_rx_dmac_srcpll); + } + ret = clk_set_parent(p_earc->clk_rx_cmdc, p_earc->clk_rx_cmdc_srcpll); + if (ret) { + dev_err(dev, + "Can't set clk_rx_cmdc parent clock\n"); + ret = PTR_ERR(p_earc->clk_rx_cmdc); + return ret; + } + ret = clk_set_parent(p_earc->clk_rx_dmac, p_earc->clk_rx_dmac_srcpll); + if (ret) { + dev_err(dev, + "Can't set clk_rx_dmac parent clock\n"); + ret = PTR_ERR(p_earc->clk_rx_dmac); + return ret; + } + + /* TX */ + p_earc->clk_tx_cmdc = devm_clk_get(&pdev->dev, "tx_cmdc"); + if (IS_ERR(p_earc->clk_tx_cmdc)) { + dev_err(&pdev->dev, + "Check whether support eARC TX\n"); + } + p_earc->clk_tx_dmac = devm_clk_get(&pdev->dev, "tx_dmac"); + if (IS_ERR(p_earc->clk_tx_dmac)) { + dev_err(&pdev->dev, + "Check whether support eARC TX\n"); + } + p_earc->clk_tx_cmdc_srcpll = devm_clk_get(&pdev->dev, "tx_cmdc_srcpll"); + if (IS_ERR(p_earc->clk_tx_cmdc_srcpll)) { + dev_err(&pdev->dev, + "Check whether support eARC TX\n"); + } + p_earc->clk_tx_dmac_srcpll = devm_clk_get(&pdev->dev, "tx_dmac_srcpll"); + if (IS_ERR(p_earc->clk_tx_dmac_srcpll)) { + dev_err(&pdev->dev, + "Check whether support eARC TX\n"); + } + if (!IS_ERR(p_earc->clk_tx_cmdc) && + !IS_ERR(p_earc->clk_tx_cmdc_srcpll)) { + ret = clk_set_parent(p_earc->clk_tx_cmdc, + p_earc->clk_tx_cmdc_srcpll); + if (ret) { + dev_err(dev, + "Can't set clk_tx_cmdc parent clock\n"); + ret = PTR_ERR(p_earc->clk_tx_cmdc); + return ret; + } + } + if (!IS_ERR(p_earc->clk_tx_dmac) && + !IS_ERR(p_earc->clk_tx_dmac_srcpll)) { + ret = clk_set_parent(p_earc->clk_tx_dmac, + p_earc->clk_tx_dmac_srcpll); + if (ret) { + dev_err(dev, + "Can't set clk_tx_dmac parent clock\n"); + ret = PTR_ERR(p_earc->clk_tx_dmac); + return ret; + } + } + + /* irqs */ + p_earc->irq_rx_cmdc = + platform_get_irq_byname(pdev, "rx_cmdc"); + if (p_earc->irq_rx_cmdc < 0) { + dev_err(dev, "platform get irq rx_cmdc failed\n"); + return p_earc->irq_rx_cmdc; + } + p_earc->irq_rx_dmac = + platform_get_irq_byname(pdev, "rx_dmac"); + if (p_earc->irq_rx_dmac < 0) { + dev_err(dev, "platform get irq rx_dmac failed\n"); + return p_earc->irq_rx_dmac; + } + p_earc->irq_tx_cmdc = + platform_get_irq_byname(pdev, "tx_cmdc"); + if (p_earc->irq_tx_cmdc < 0) + dev_err(dev, "platform get irq tx_cmdc failed, Check whether support eARC TX\n"); + p_earc->irq_tx_dmac = + platform_get_irq_byname(pdev, "tx_dmac"); + if (p_earc->irq_tx_dmac < 0) + dev_err(dev, "platform get irq tx_dmac failed, Check whether support eARC TX\n"); + + ret = snd_soc_register_component(&pdev->dev, + &earc_component, + earc_dai, + ARRAY_SIZE(earc_dai)); + if (ret) { + dev_err(&pdev->dev, + "snd_soc_register_component failed\n"); + return ret; + } + + pr_info("%s, register soc platform\n", __func__); + + return devm_snd_soc_register_platform(dev, &earc_platform); +} + +struct platform_driver earc_driver = { + .driver = { + .name = DRV_NAME, + .of_match_table = earc_device_id, + }, + .probe = earc_platform_probe, +}; +module_platform_driver(earc_driver); + +MODULE_AUTHOR("Amlogic, Inc."); +MODULE_DESCRIPTION("Amlogic eARC/ARC TX/RX ASoc driver"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("Platform:" DRV_NAME); +MODULE_DEVICE_TABLE(of, earc_device_id); diff --git a/sound/soc/amlogic/auge/earc_hw.c b/sound/soc/amlogic/auge/earc_hw.c new file mode 100644 index 000000000000..0b217bb2cad0 --- /dev/null +++ b/sound/soc/amlogic/auge/earc_hw.c @@ -0,0 +1,126 @@ +/* + * sound/soc/amlogic/auge/earc_hw.c + * + * Copyright (C) 2019 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 + +#include "earc_hw.h" + + +void earcrx_cmdc_init(void) +{ + /* set irq mask */ + earcrx_top_write(EARCRX_CMDC_INT_MASK, + (0 << 15) | /* idle2_int */ + (0 << 14) | /* idle1_int */ + (0 << 13) | /* disc2_int */ + (0 << 12) | /* disc1_int */ + (0 << 11) | /* earc_int */ + (1 << 10) | /* hb_status_int */ + (0 << 9) | /* losthb_int */ + (0 << 8) | /* timeout_int */ + (0 << 7) | /* status_ch_int */ + (0 << 6) | /* int_rec_invalid_id */ + (0 << 5) | /* int_rec_invalid_offset */ + (0 << 4) | /* int_rec_unexp */ + (0 << 3) | /* int_rec_ecc_err */ + (0 << 2) | /* int_rec_parity_err */ + (0 << 1) | /* int_recv_packet */ + (0 << 0) /* int_rec_time_out */ + ); + + earcrx_top_write(EARCRX_ANA_CTRL0, 0x90884814); + earcrx_top_write(EARCRX_PLL_CTRL3, 0x242000); + earcrx_top_write(EARCRX_PLL_CTRL0, 0x10800400); +} + +void earcrx_dmac_init(void) +{ + earcrx_dmac_write(EARCRX_DMAC_SYNC_CTRL0, + (1 << 16) | /* reg_ana_buf_data_sel_en */ + (3 << 12) | /* reg_ana_buf_data_sel */ + (7 << 8) | /* reg_ana_clr_cnt */ + (7 << 4) /* reg_ana_set_cnt */ + ); + earcrx_dmac_write(EARCRX_DMAC_UBIT_CTRL0, + (47 << 16) | /* reg_fifo_thd */ + (1 << 12) | /* reg_user_lr */ + (29 << 0) /* reg_data_bit */ + ); + earcrx_dmac_write(EARCRX_ANA_RST_CTRL0, 1 << 31); +} + +void earc_arc_init(void) +{ + earcrx_dmac_write(EARCRX_SPDIFIN_CTRL0, + (1 << 31) | /* reg_work_en */ + (1 << 30) | /* reg_chnum_sel */ + (1 << 25) | /* reg_findpapb_en */ + (0xFFF<<12) /* reg_nonpcm2pcm_th */ + ); + earcrx_dmac_write(EARCRX_SPDIFIN_CTRL2, + (1 << 14) | /* reg_earc_auto */ + (1 << 13) /* reg_earcin_papb_lr */ + ); + earcrx_dmac_write(EARCRX_SPDIFIN_CTRL3, + (0xEC37<<16) | /* reg_earc_pa_value */ + (0x5A5A<<0) /* reg_earc_pb_value */ + ); +} + +void earc_rx_enable(bool enable) +{ + if (enable) { + earcrx_dmac_update_bits(EARCRX_DMAC_SYNC_CTRL0, + 1 << 30, /* reg_rst_afifo_out_n */ + 1 << 30); + + earcrx_dmac_update_bits(EARCRX_DMAC_SYNC_CTRL0, + 1 << 29, /* reg_rst_afifo_in_n */ + 0x1 << 29); + + earcrx_dmac_update_bits(EARCRX_ERR_CORRECT_CTRL0, + 1 << 29, /* reg_rst_afifo_out_n */ + 1 << 29 + ); + earcrx_dmac_update_bits(EARCRX_ERR_CORRECT_CTRL0, + 1 << 28, /* reg_rst_afifo_in_n */ + 1 << 28 /* reg_rst_afifo_in_n */ + ); + } else { + earcrx_dmac_update_bits(EARCRX_DMAC_SYNC_CTRL0, + 0x3 << 29, + 0x0 << 29); + + earcrx_dmac_update_bits(EARCRX_ERR_CORRECT_CTRL0, + 0x3 << 28, 0x0 << 28); + } + + earcrx_dmac_update_bits(EARCRX_DMAC_SYNC_CTRL0, + 1 << 31, /* reg_work_en */ + enable << 31); + + earcrx_dmac_update_bits(EARCRX_DMAC_UBIT_CTRL0, + 1 << 31, /* reg_work_enable */ + enable << 31); + + earcrx_dmac_update_bits(EARCRX_ERR_CORRECT_CTRL0, + 1 << 31, + enable << 31); /* reg_work_en */ + + earcrx_dmac_update_bits(EARCRX_DMAC_TOP_CTRL0, + 1 << 31, + enable << 31); /* reg_top_work_en */ +} diff --git a/sound/soc/amlogic/auge/earc_hw.h b/sound/soc/amlogic/auge/earc_hw.h new file mode 100644 index 000000000000..1630733add2f --- /dev/null +++ b/sound/soc/amlogic/auge/earc_hw.h @@ -0,0 +1,27 @@ +/* + * sound/soc/amlogic/auge/earc_hw.h + * + * Copyright (C) 2019 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 __EARC_HW_H__ +#define __EARC_HW_H__ + +#include "regs.h" +#include "iomap.h" + +extern void earcrx_cmdc_init(void); +extern void earcrx_dmac_init(void); +extern void earc_arc_init(void); +extern void earc_rx_enable(bool enable); +#endif diff --git a/sound/soc/amlogic/auge/effects_hw_v2.c b/sound/soc/amlogic/auge/effects_hw_v2.c index 6c1e1a60013f..b5db9d64587f 100644 --- a/sound/soc/amlogic/auge/effects_hw_v2.c +++ b/sound/soc/amlogic/auge/effects_hw_v2.c @@ -19,78 +19,113 @@ #include "effects_hw_v2.h" #include "regs.h" #include "iomap.h" - #include "tdm_hw.h" #include "spdif_hw.h" -void aed_set_ram_coeff(int len, int *params) +void aed_set_ram_coeff(int add, int len, unsigned int *params) { int i, ctrl_v; + unsigned int *p = params; - for (i = 0; i < len; i++) { - ctrl_v = (i << 2) | (0x1 << 1) | (0x1 << 0); - eqdrc_write(AED_COEF_RAM_DATA, params[i]); + for (i = 0; i < len; i++, p++) { + ctrl_v = ((add+i) << 2) | (0x1 << 1) | (0x1 << 0); + eqdrc_write(AED_COEF_RAM_DATA, *p); eqdrc_write(AED_COEF_RAM_CNTL, ctrl_v); } } -void aed_set_multiband_drc_coeff(int len, int *params) +void aed_get_ram_coeff(int add, int len, unsigned int *params) { - int band_len = len / 3, i, j; + int i, ctrl_v; + unsigned int *p = params; + + for (i = 0; i < len; i++, p++) { + ctrl_v = ((add+i) << 2) | (0x0 << 1) | (0x1 << 0); + eqdrc_write(AED_COEF_RAM_CNTL, ctrl_v); + *p = eqdrc_read(AED_COEF_RAM_DATA); + //pr_info("%s, params[%d] = %8.8x\n", __func__, i, *p); + } +} + +void aed_set_multiband_drc_coeff(int band, unsigned int *params) +{ + int i; int offset = AED_MDRC_RMS_COEF10 - AED_MDRC_RMS_COEF00; int reg = AED_MDRC_RMS_COEF00; - for (i = 0; i < 3; i++) - for (j = 0; j < band_len; j++) - eqdrc_write(reg + i * offset + j, - params[i * band_len + j]); - - eqdrc_write(AED_MDRC_THD0, 0xf6000000); - eqdrc_write(AED_MDRC_K0, 0x20000); - eqdrc_write(AED_MDRC_OFFSET0, 0x200); - eqdrc_write(AED_MDRC_LOW_GAIN, 0x40000); - - eqdrc_write(AED_MDRC_THD1, 0xfb000000); - eqdrc_write(AED_MDRC_K1, 0x26666); - eqdrc_write(AED_MDRC_OFFSET1, 0x200); - eqdrc_write(AED_MDRC_MID_GAIN, 0x40000); - - eqdrc_write(AED_MDRC_THD2, 0xf1000000); - eqdrc_write(AED_MDRC_K2, 0x2cccc); - eqdrc_write(AED_MDRC_OFFSET2, 0x200); - eqdrc_write(AED_MDRC_HIGH_GAIN, 0x40000); + for (i = 0; i < offset; i++) { + eqdrc_write(reg + band * offset + i, + params[band * offset + i]); + } } -void aed_set_fullband_drc_coeff(int len, int *params) +void aed_get_multiband_drc_coeff(int band, unsigned int *params) { int i; + int offset = AED_MDRC_RMS_COEF10 - AED_MDRC_RMS_COEF00; + int reg = AED_MDRC_RMS_COEF00; - for (i = 0; i < len; i++) - eqdrc_write(AED_DRC_RELEASE_COEF00 + i, - params[i]); - - eqdrc_write(AED_DRC_RMS_COEF0, 0x34ebb); - eqdrc_write(AED_DRC_RMS_COEF1, 0x7cb145); - eqdrc_write(AED_DRC_THD0, 0xf7000000); - eqdrc_write(AED_DRC_THD1, 0xf6000000); - eqdrc_write(AED_DRC_THD2, 0xec000000); - eqdrc_write(AED_DRC_THD3, 0xe2000000); - eqdrc_write(AED_DRC_THD4, 0xce000000); - eqdrc_write(AED_DRC_K0, 0x20000); - eqdrc_write(AED_DRC_K1, 0x46666); - eqdrc_write(AED_DRC_K2, 0x40000); - eqdrc_write(AED_DRC_K3, 0x39999); - eqdrc_write(AED_DRC_K4, 0x33333); - eqdrc_write(AED_DRC_K5, 0x4cccc); - eqdrc_write(AED_DRC_THD_OUT0, 0xf5e66667); - eqdrc_write(AED_DRC_THD_OUT1, 0xebe66667); - eqdrc_write(AED_DRC_THD_OUT2, 0xe2e66667); - eqdrc_write(AED_DRC_THD_OUT3, 0xd2e66667); - eqdrc_write(AED_DRC_OFFSET, 0x100); - eqdrc_write(AED_DRC_LOOPBACK_CNTL, (144 << 0)); + for (i = 0; i < offset; i++) { + *(params + band * offset + i) = + eqdrc_read(reg + band * offset + i); + } } -static void aed_set_mixer_params(void) +void aed_set_fullband_drc_coeff(int group, unsigned int *params) +{ + unsigned int *p = params; + + if (group == 0) { + eqdrc_write(AED_DRC_RELEASE_COEF00, *p++); + eqdrc_write(AED_DRC_RELEASE_COEF01, *p++); + eqdrc_write(AED_DRC_ATTACK_COEF00, *p++); + eqdrc_write(AED_DRC_ATTACK_COEF01, *p++); + eqdrc_write(AED_DRC_THD0, *p++); + eqdrc_write(AED_DRC_K0, *p++); + } else if (group == 1) { + eqdrc_write(AED_DRC_RELEASE_COEF10, *p++); + eqdrc_write(AED_DRC_RELEASE_COEF11, *p++); + eqdrc_write(AED_DRC_ATTACK_COEF10, *p++); + eqdrc_write(AED_DRC_ATTACK_COEF11, *p++); + eqdrc_write(AED_DRC_THD1, *p++); + eqdrc_write(AED_DRC_K2, *p++); + eqdrc_write(AED_DRC_THD_OUT0, eqdrc_read(AED_DRC_THD1)); + } else if (group == 2) { + eqdrc_write(AED_DRC_RMS_COEF0, *p++); + eqdrc_write(AED_DRC_RMS_COEF1, *p++); + eqdrc_write(AED_DRC_LOOPBACK_CNTL, *p++); + /*THD_OUT0 = THD1; K1 = 1.0*/ + eqdrc_write(AED_DRC_THD_OUT0, eqdrc_read(AED_DRC_THD1)); + eqdrc_write(AED_DRC_K1, 0x40000); + } +} + +void aed_get_fullband_drc_coeff(int len, unsigned int *params) +{ + unsigned int *p = params; + + *p++ = eqdrc_read(AED_DRC_RELEASE_COEF00); + *p++ = eqdrc_read(AED_DRC_RELEASE_COEF01); + *p++ = eqdrc_read(AED_DRC_ATTACK_COEF00); + *p++ = eqdrc_read(AED_DRC_ATTACK_COEF01); + *p++ = eqdrc_read(AED_DRC_THD0); + *p++ = eqdrc_read(AED_DRC_K0); + + *p++ = eqdrc_read(AED_DRC_RELEASE_COEF10); + *p++ = eqdrc_read(AED_DRC_RELEASE_COEF11); + *p++ = eqdrc_read(AED_DRC_ATTACK_COEF10); + *p++ = eqdrc_read(AED_DRC_ATTACK_COEF11); + *p++ = eqdrc_read(AED_DRC_THD1); + *p++ = eqdrc_read(AED_DRC_K2); + + *p++ = eqdrc_read(AED_DRC_RMS_COEF0); + *p++ = eqdrc_read(AED_DRC_RMS_COEF1); + *p++ = eqdrc_read(AED_DRC_LOOPBACK_CNTL); + *p++ = eqdrc_read(AED_DRC_THD_OUT0); + *p++ = eqdrc_read(AED_DRC_K1); +} + +void aed_set_mixer_params(void) { eqdrc_write(AED_MIX0_LL, 0x40000); eqdrc_write(AED_MIX0_RL, 0x0); @@ -129,28 +164,44 @@ void aed_nd_enable(bool enable) void aed_eq_enable(int idx, bool enable) { eqdrc_update_bits(AED_EQ_EN, 0x1 << idx, enable << idx); - eqdrc_update_bits(AED_EQ_TAP_CNTL, 0x1f << (5 * idx), 10 << (5 * idx)); } -void aed_multiband_drc_enable(bool enable) +void aed_eq_taps(unsigned int eq1_taps) { - eqdrc_write(AED_MDRC_CNTL, - (1 << 16) | /* mdrc_pow_sel */ - (enable << 8) | /* mdrc_all_en */ - (7 << 3) | /* mdrc_rms_mode[2:0] */ - (7 << 0) /* mdrc_en[2:0] */ - ); + if (eq1_taps > 20) { + pr_err("Error EQ1_Tap = %d\n", eq1_taps); + return; + } + eqdrc_update_bits(AED_EQ_TAP_CNTL, 0x1f, eq1_taps); + eqdrc_update_bits(AED_EQ_TAP_CNTL, 0x1f << 5, (20 - eq1_taps) << 5); } -void aed_fullband_drc_enable(bool enable) +void aed_set_multiband_drc_param(void) { - eqdrc_write(AED_DRC_CNTL, - (5 << 3) | /* drc_tap */ - (enable << 0) /* drc_en */ - ); + eqdrc_update_bits(AED_MDRC_CNTL, + (0x1 << 16) | (0x7 << 3) | (0x7 << 0), + (0x0 << 16) | (0x7 << 3) | (0x7 << 0)); } -void aed_set_EQ_volume( +void aed_set_fullband_drc_param(int tap) +{ + eqdrc_update_bits(AED_DRC_CNTL, + (0x7 << 3), (tap << 3)); +} + +void aed_set_multiband_drc_enable(bool enable) +{ + eqdrc_update_bits(AED_MDRC_CNTL, + (0x1 << 8), (enable << 8)); +} + +void aed_set_fullband_drc_enable(bool enable) +{ + eqdrc_update_bits(AED_DRC_CNTL, + (0x1 << 0), (enable << 0)); +} + +void aed_set_volume( unsigned int master_vol, unsigned int Lch_vol, unsigned int Rch_vol) @@ -161,18 +212,30 @@ void aed_set_EQ_volume( (Rch_vol << 8) | /* channel 2 volume: 0dB */ (Lch_vol << 0) /* channel 1 volume: 0dB */ ); - eqdrc_write(AED_EQ_VOLUME_SLEW_CNT, 0x40); + eqdrc_write(AED_EQ_VOLUME_SLEW_CNT, 0x2); /*40ms from -120dB~0dB*/ eqdrc_write(AED_MUTE, 0); } void aed_set_lane_and_channels(int lane_mask, int ch_mask) { + int ch_num = 0, i = 0; + int val = ch_mask & 0xff; + eqdrc_update_bits(AED_TOP_CTL, 0xff << 18 | 0xf << 14, ch_mask << 18 | lane_mask << 14); + + for (i = 0; i < 8; i++) { + if ((val & 0x1) == 0x1) + ch_num++; + val >>= 1; + } + + eqdrc_update_bits(AED_TOP_REQ_CTL, + 0xff << 12, (ch_num - 1) << 12); } -void aed_set_ctrl(bool enable, int sel, int module) +void aed_set_ctrl(bool enable, int sel, enum frddr_dest module) { int mask = 0, val = 0; @@ -194,28 +257,28 @@ void aed_set_ctrl(bool enable, int sel, int module) sel, module); return; } + eqdrc_update_bits(AED_TOP_REQ_CTL, mask, val); /* Effect Module */ - if (module >= 3) { - /* SPDIFOUT A/B */ - aml_spdifout_select_aed(enable, module - 3); - } else if (module < 3 && module >= 0) { + if (module <= TDMOUT_C && module >= TDMOUT_A) { /* TDMOUT A/B/C */ aml_tdmout_select_aed(enable, module); - } else - pr_err("unknown module:%d for AED\n", module); + } else { + /* SPDIFOUT A/B */ + aml_spdifout_select_aed(enable, module - SPDIFOUT_A); + } } -void aed_set_format(int msb, int frddr_type) +void aed_set_format(int msb, enum ddr_types frddr_type, enum ddr_num source) { eqdrc_update_bits(AED_TOP_CTL, - 0x7 << 11 | 0x1f << 6, - frddr_type << 11 | msb << 6); + 0x7 << 11 | 0x1f << 6 | 0x3 << 4, + frddr_type << 11 | msb << 6 | source << 4); } -void aed_enable(bool enable, int frddr_dst, int fifo_id) +void aed_enable(bool enable) { if (enable) { eqdrc_write(AED_ED_CNTL, 0x1); @@ -223,8 +286,6 @@ void aed_enable(bool enable, int frddr_dst, int fifo_id) eqdrc_update_bits(AED_TOP_CTL, 0x1 << 1, 0x1 << 1); eqdrc_update_bits(AED_TOP_CTL, 0x1 << 2, 0x1 << 2); - - aed_set_mixer_params(); } else eqdrc_update_bits(AED_TOP_CTL, 0x3 << 1, 0x0 << 1); @@ -234,3 +295,4 @@ void aed_enable(bool enable, int frddr_dst, int fifo_id) if (enable) eqdrc_update_bits(AED_TOP_CTL, 0x1 << 31, 0x1 << 31); } + diff --git a/sound/soc/amlogic/auge/effects_hw_v2.h b/sound/soc/amlogic/auge/effects_hw_v2.h index 7c13e7fe6436..cfa8e0fa78a8 100644 --- a/sound/soc/amlogic/auge/effects_hw_v2.h +++ b/sound/soc/amlogic/auge/effects_hw_v2.h @@ -17,21 +17,28 @@ #ifndef __EFFECTS_HW_V2_H__ #define __EFFECTS_HW_V2_H__ #include +#include "ddr_mngr.h" -void aed_set_ram_coeff(int len, int *params); -void aed_set_multiband_drc_coeff(int len, int *params); -void aed_set_fullband_drc_coeff(int len, int *params); +void aed_set_ram_coeff(int add, int len, unsigned int *params); +void aed_get_ram_coeff(int add, int len, unsigned int *params); +void aed_set_multiband_drc_coeff(int band, unsigned int *params); +void aed_get_multiband_drc_coeff(int band, unsigned int *params); +void aed_set_fullband_drc_coeff(int group, unsigned int *params); +void aed_get_fullband_drc_coeff(int len, unsigned int *params); void aed_dc_enable(bool enable); void aed_nd_enable(bool enable); void aed_eq_enable(int idx, bool enable); -void aed_multiband_drc_enable(bool enable); -void aed_fullband_drc_enable(bool enable); -void aed_set_EQ_volume( - unsigned int master_volume, - unsigned int Lch_vol, - unsigned int Rch_vol); +void aed_set_fullband_drc_enable(bool enable); +void aed_set_multiband_drc_enable(bool enable); +void aed_set_volume(unsigned int master_volume, + unsigned int Lch_vol, unsigned int Rch_vol); void aed_set_lane_and_channels(int lane_mask, int ch_mask); -void aed_set_ctrl(bool enable, int sel, int module); -void aed_set_format(int msb, int frddr_type); -void aed_enable(bool enable, int frddr_dst, int fifo_id); +void aed_set_ctrl(bool enable, int sel, enum frddr_dest module); +void aed_set_format(int msb, enum ddr_types frddr_type, enum ddr_num source); +void aed_enable(bool enable); +void aed_set_mixer_params(void); +void aed_eq_taps(unsigned int eq1_taps); +void aed_set_multiband_drc_param(void); +void aed_set_fullband_drc_param(int tap); + #endif diff --git a/sound/soc/amlogic/auge/effects_hw_v2_coeff.c b/sound/soc/amlogic/auge/effects_hw_v2_coeff.c deleted file mode 100644 index 903883f4c97c..000000000000 --- a/sound/soc/amlogic/auge/effects_hw_v2_coeff.c +++ /dev/null @@ -1,298 +0,0 @@ -/* - * sound/soc/amlogic/auge/effects_hw_v2_coeff.c - * - * Copyright (C) 2018 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 AED_EQ_LENGTH 225 -#define AED_MULTIBAND_DRC_LENGTH 18 -#define AED_FULLBAND_DRC_LENGTH 24 - -static int eq_coeff[] = { - /* 0 */ 0x7fd51b, - /* 1 */ 0x30055c9, - /* 2 */ 0x7fd51b, - /* 3 */ 0x30055e6, - /* 4 */ 0x7faa53, - /* 5 */ 0x7ed219, - /* 6 */ 0x3025bce, - /* 7 */ 0x7ed219, - /* 8 */ 0x3025e96, - /* 9 */ 0x7da6fb, - /* 10 */ 0x7ed219, - /* 11 */ 0x3025bce, - /* 12 */ 0x7ed219, - /* 13 */ 0x3025e96, - /* 14 */ 0x7da6fb, - /* 15 */ 0xdf71e0, - /* 16 */ 0x2411c40, - /* 17 */ 0xdf71e0, - /* 18 */ 0x304bd12, - /* 19 */ 0x7b58fb, - /* 20 */ 0x7d8252, - /* 21 */ 0x30bb7df, - /* 22 */ 0x771ba1, - /* 23 */ 0x30bb7df, - /* 24 */ 0x749df4, - /* 25 */ 0x79f87b, - /* 26 */ 0x31971e4, - /* 27 */ 0x6ddabe, - /* 28 */ 0x31971e4, - /* 29 */ 0x67d339, - /* 30 */ 0x84f8f3, - /* 31 */ 0x31d2c91, - /* 32 */ 0x62ebbf, - /* 33 */ 0x31d2c91, - /* 34 */ 0x67e4b1, - /* 35 */ 0x711f0e, - /* 36 */ 0x3543f10, - /* 37 */ 0x4ae2f0, - /* 38 */ 0x3543f10, - /* 39 */ 0x3c01ff, - /* 40 */ 0xaaf457, - /* 41 */ 0x3831bd5, - /* 42 */ 0xfb150, - /* 43 */ 0x3831bd5, - /* 44 */ 0x3aa5a8, - /* 45 */ 0x65b5d1, - /* 46 */ 0xe3390, - /* 47 */ 0x2226c8, - /* 48 */ 0xe3390, - /* 49 */ 0x7dc99, - /* 50 */ 0x358660, - /* 51 */ 0x6b0cc1, - /* 52 */ 0x358660, - /* 53 */ 0x3b418e, - /* 54 */ 0x1ad7f4, - /* 55 */ 0x800000, - /* 56 */ 0x0, - /* 57 */ 0x0, - /* 58 */ 0x0, - /* 59 */ 0x0, - /* 60 */ 0x800000, - /* 61 */ 0x0, - /* 62 */ 0x0, - /* 63 */ 0x0, - /* 64 */ 0x0, - /* 65 */ 0x800000, - /* 66 */ 0x0, - /* 67 */ 0x0, - /* 68 */ 0x0, - /* 69 */ 0x0, - /* 70 */ 0x800000, - /* 71 */ 0x0, - /* 72 */ 0x0, - /* 73 */ 0x0, - /* 74 */ 0x0, - /* 75 */ 0x800000, - /* 76 */ 0x0, - /* 77 */ 0x0, - /* 78 */ 0x0, - /* 79 */ 0x0, - /* 80 */ 0x800000, - /* 81 */ 0x0, - /* 82 */ 0x0, - /* 83 */ 0x0, - /* 84 */ 0x0, - /* 85 */ 0x800000, - /* 86 */ 0x0, - /* 87 */ 0x0, - /* 88 */ 0x0, - /* 89 */ 0x0, - /* 90 */ 0x800000, - /* 91 */ 0x0, - /* 92 */ 0x0, - /* 93 */ 0x0, - /* 94 */ 0x0, - /* 95 */ 0x800000, - /* 96 */ 0x0, - /* 97 */ 0x0, - /* 98 */ 0x0, - /* 99 */ 0x0, - /* 100 */ 0x800000, - /* 101 */ 0x0, - /* 102 */ 0x0, - /* 103 */ 0x0, - /* 104 */ 0x0, - /* 105 */ 0x7ed219, - /* 106 */ 0x3025bce, - /* 107 */ 0x7ed219, - /* 108 */ 0x3025e96, - /* 109 */ 0x7da6fb, - /* 110 */ 0x7ed219, - /* 111 */ 0x3025bce, - /* 112 */ 0x7ed219, - /* 113 */ 0x3025e96, - /* 114 */ 0x7da6fb, - /* 115 */ 0xdf71e0, - /* 116 */ 0x2411c40, - /* 117 */ 0xdf71e0, - /* 118 */ 0x304bd12, - /* 119 */ 0x7b58fb, - /* 120 */ 0x7d8252, - /* 121 */ 0x30bb7df, - /* 122 */ 0x771ba1, - /* 123 */ 0x30bb7df, - /* 124 */ 0x749df4, - /* 125 */ 0x79f87b, - /* 126 */ 0x31971e4, - /* 127 */ 0x6ddabe, - /* 128 */ 0x31971e4, - /* 129 */ 0x67d339, - /* 130 */ 0x84f8f3, - /* 131 */ 0x31d2c91, - /* 132 */ 0x62ebbf, - /* 133 */ 0x31d2c91, - /* 134 */ 0x67e4b1, - /* 135 */ 0x711f0e, - /* 136 */ 0x3543f10, - /* 137 */ 0x4ae2f0, - /* 138 */ 0x3543f10, - /* 139 */ 0x3c01ff, - /* 140 */ 0xaaf457, - /* 141 */ 0x3831bd5, - /* 142 */ 0xfb150, - /* 143 */ 0x3831bd5, - /* 144 */ 0x3aa5a8, - /* 145 */ 0x65b5d1, - /* 146 */ 0xe3390, - /* 147 */ 0x2226c8, - /* 148 */ 0xe3390, - /* 149 */ 0x7dc99, - /* 150 */ 0x358660, - /* 151 */ 0x6b0cc1, - /* 152 */ 0x358660, - /* 153 */ 0x3b418e, - /* 154 */ 0x1ad7f4, - /* 155 */ 0x800000, - /* 156 */ 0x0, - /* 157 */ 0x0, - /* 158 */ 0x0, - /* 159 */ 0x0, - /* 160 */ 0x800000, - /* 161 */ 0x0, - /* 162 */ 0x0, - /* 163 */ 0x0, - /* 164 */ 0x0, - /* 165 */ 0x800000, - /* 166 */ 0x0, - /* 167 */ 0x0, - /* 168 */ 0x0, - /* 169 */ 0x0, - /* 170 */ 0x800000, - /* 171 */ 0x0, - /* 172 */ 0x0, - /* 173 */ 0x0, - /* 174 */ 0x0, - /* 175 */ 0x800000, - /* 176 */ 0x0, - /* 177 */ 0x0, - /* 178 */ 0x0, - /* 179 */ 0x0, - /* 180 */ 0x800000, - /* 181 */ 0x0, - /* 182 */ 0x0, - /* 183 */ 0x0, - /* 184 */ 0x0, - /* 185 */ 0x800000, - /* 186 */ 0x0, - /* 187 */ 0x0, - /* 188 */ 0x0, - /* 189 */ 0x0, - /* 190 */ 0x800000, - /* 191 */ 0x0, - /* 192 */ 0x0, - /* 193 */ 0x0, - /* 194 */ 0x0, - /* 195 */ 0x800000, - /* 196 */ 0x0, - /* 197 */ 0x0, - /* 198 */ 0x0, - /* 199 */ 0x0, - /* 200 */ 0x800000, - /* 201 */ 0x0, - /* 202 */ 0x0, - /* 203 */ 0x0, - /* 204 */ 0x0, - /* 205 */ 0x25b, - /* 206 */ 0x4b5, - /* 207 */ 0x25b, - /* 208 */ 0x3045701, - /* 209 */ 0x7bb269, - /* 210 */ 0x7dd6da, - /* 211 */ 0x304524c, - /* 212 */ 0x7dd6da, - /* 213 */ 0x3045701, - /* 214 */ 0x7bb269, - /* 215 */ 0x7f3ee, - /* 216 */ 0xfe7dc, - /* 217 */ 0x7f3ee, - /* 218 */ 0x37f9f4a, - /* 219 */ 0x20306d, - /* 220 */ 0x482449, - /* 221 */ 0x36fb76e, - /* 222 */ 0x482449, - /* 223 */ 0x37f9f4a, - /* 224 */ 0x20306d, -}; - -static int multiband_drc_coeff[] = { - 0x34ebb, /* Low SMS coeff0 */ - 0x7f54e0, /* Low SMS coeff1 */ - 0x5188, /* Low RELEASE coeff0 */ - 0x7fae78, /* Low RELEASE coeff1 */ - 0x3263a, /* Low ATTACK coeff0 */ - 0x7cd9c6, /* Low ATTACK coeff1 */ - - 0x34ebb, /* Mid */ - 0x7f54e0, - 0x5188, - 0x7fae78, - 0x3263a, - 0x7cd9c6, - - 0x34ebb, /* High */ - 0x7f54e0, - 0x5188, - 0x7fae78, - 0x3263a, - 0x7cd9c6, -}; - -static int fullband_drc_coeff[] = { - 0x5188, /* RELEASE_COEF00 */ - 0x7fae78, /* RELEASE_COEF01 */ - 0x5188, - 0x7fae78, - 0x5188, - 0x7fae78, - 0x5188, - 0x7fae78, - 0x5188, - 0x7fae78, - 0x5188, /* RELEASE_COEF50 */ - 0x7fae78, /* RELEASE_COEF51 */ - 0x3263a, /* ATTACK_COEF00 */ - 0x7cd9c6, /* ATTACK_COEF01 */ - 0x3263a, - 0x7cd9c6, - 0x3263a, - 0x7cd9c6, - 0x3263a, - 0x7cd9c6, - 0x3263a, - 0x7cd9c6, - 0x3263a, /* ATTACK_COEF50 */ - 0x7cd9c6, /* ATTACK_COEF51 */ -}; diff --git a/sound/soc/amlogic/auge/effects_hw_v2_coeff.h b/sound/soc/amlogic/auge/effects_hw_v2_coeff.h new file mode 100644 index 000000000000..d0c943359719 --- /dev/null +++ b/sound/soc/amlogic/auge/effects_hw_v2_coeff.h @@ -0,0 +1,169 @@ +/* + * sound/soc/amlogic/auge/effects_hw_v2_coeff.h + * + * Copyright (C) 2018 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 __EFFECTS_HW_V2_COEFF_H__ +#define __EFFECTS_HW_V2_COEFF_H__ + +#define EQ_BAND (20) +#define FILTER_PARAM_SIZE (5) +#define DC_CUT_FILTER_RAM_ADD (0) +#define DC_CUT_FILTER_SIZE (5) +#define EQ_FILTER_RAM_ADD (5) +#define EQ_FILTER_SIZE_CH (100) +#define EQ_FILTER_SIZE (200) +#define CROSSOVER_FILTER_RAM_ADD (205) +#define CROSSOVER_FILTER_SIZE (20) +#define CROSSOVER_FILTER_BAND (4) + +#define FILTER_PARAM_BYTE (66) /*"0x%8.8x "*/ + +/* 20Hz, highpass filter */ +static unsigned int DC_CUT_COEFF[DC_CUT_FILTER_SIZE] = { + 0x007fc365, 0x03007935, 0x007fc365, 0x03007952, 0x007f86e7 +}; + +static unsigned int EQ_COEFF[EQ_FILTER_SIZE] = { + /*Ch1 EQ 0~19*/ + /*0~9 band*/ + 0x800000, 0x0, 0x0, 0x0, 0x0, + 0x800000, 0x0, 0x0, 0x0, 0x0, + 0x800000, 0x0, 0x0, 0x0, 0x0, + 0x800000, 0x0, 0x0, 0x0, 0x0, + 0x800000, 0x0, 0x0, 0x0, 0x0, + 0x800000, 0x0, 0x0, 0x0, 0x0, + 0x800000, 0x0, 0x0, 0x0, 0x0, + 0x800000, 0x0, 0x0, 0x0, 0x0, + 0x800000, 0x0, 0x0, 0x0, 0x0, + 0x800000, 0x0, 0x0, 0x0, 0x0, + /*10~19 band*/ + 0x800000, 0x0, 0x0, 0x0, 0x0, + 0x800000, 0x0, 0x0, 0x0, 0x0, + 0x800000, 0x0, 0x0, 0x0, 0x0, + 0x800000, 0x0, 0x0, 0x0, 0x0, + 0x800000, 0x0, 0x0, 0x0, 0x0, + 0x800000, 0x0, 0x0, 0x0, 0x0, + 0x800000, 0x0, 0x0, 0x0, 0x0, + 0x800000, 0x0, 0x0, 0x0, 0x0, + 0x800000, 0x0, 0x0, 0x0, 0x0, + 0x800000, 0x0, 0x0, 0x0, 0x0, + /*Ch2 EQ 0~19*/ + /*0~9 band*/ + 0x800000, 0x0, 0x0, 0x0, 0x0, + 0x800000, 0x0, 0x0, 0x0, 0x0, + 0x800000, 0x0, 0x0, 0x0, 0x0, + 0x800000, 0x0, 0x0, 0x0, 0x0, + 0x800000, 0x0, 0x0, 0x0, 0x0, + 0x800000, 0x0, 0x0, 0x0, 0x0, + 0x800000, 0x0, 0x0, 0x0, 0x0, + 0x800000, 0x0, 0x0, 0x0, 0x0, + 0x800000, 0x0, 0x0, 0x0, 0x0, + 0x800000, 0x0, 0x0, 0x0, 0x0, + /*10~19 band*/ + 0x800000, 0x0, 0x0, 0x0, 0x0, + 0x800000, 0x0, 0x0, 0x0, 0x0, + 0x800000, 0x0, 0x0, 0x0, 0x0, + 0x800000, 0x0, 0x0, 0x0, 0x0, + 0x800000, 0x0, 0x0, 0x0, 0x0, + 0x800000, 0x0, 0x0, 0x0, 0x0, + 0x800000, 0x0, 0x0, 0x0, 0x0, + 0x800000, 0x0, 0x0, 0x0, 0x0, + 0x800000, 0x0, 0x0, 0x0, 0x0, + 0x800000, 0x0, 0x0, 0x0, 0x0, +}; + +/*fiter1 fc: 150Hz; fiter2 fc: 5KHz*/ +static unsigned int CROSSOVER_COEFF[CROSSOVER_FILTER_SIZE] = { + /*low-pass filter1*/ + 0x00000319, 0x00000632, 0x00000319, 0x0304fa54, 0x007b1210, + /*high-pass filter1*/ + 0x007d85ef, 0x0304f422, 0x007d85ef, 0x0304fa54, 0x007b1210, + /*low-pass filter2*/ + 0x0008388a, 0x00107113, 0x0008388a, 0x0381c139, 0x001f20ee, + /*high-pass filter2*/ + 0x004757ed, 0x03715025, 0x004757ed, 0x0381c139, 0x001f20ee, +}; + +#define AED_SINGLE_BAND_DRC_SIZE (10) +#define AED_MULTIBAND_DRC_BANDS (3) +#define AED_MULTIBAND_DRC_SIZE (30) +#define MULTIBAND_DRC_PARAM_BYTE (120) /*"0x%8.8x "*/ +/*RMS:5ms, ATTACK:2ms, RELEASE:20ms*/ +static unsigned int multiband_drc_coeff[AED_MULTIBAND_DRC_SIZE] = { + 0x34ebb, /* Low RMS coeff0 */ + 0x7cb145, /* Low RMS coeff1 */ + 0x5188, /* Low RELEASE coeff0 */ + 0x7fae78, /* Low RELEASE coeff1 */ + 0x3263a, /* Low ATTACK coeff0 */ + 0x7cd9c6, /* Low ATTACK coeff1 */ + 0x0, /* Low THD0 coeff */ + 0x40000, /* Low K0 coeff */ + 0x40000, /* Low GAIN */ + 0x0, /* Low OFFSET coeff*/ + + 0x34ebb, /* Mid RMS coeff0 */ + 0x7cb145, /* Mid RMS coeff1 */ + 0x5188, /* Mid RELEASE coeff0 */ + 0x7fae78, /* Mid RELEASE coeff1 */ + 0x3263a, /* Mid ATTACK coeff0 */ + 0x7cd9c6, /* Mid ATTACK coeff1 */ + 0x0, /* Mid THD0 coeff */ + 0x40000, /* Mid K0 coeff */ + 0x0, /* Mid OFFSET coeff*/ + 0x40000, /* Mid GAIN */ + + 0x34ebb, /* High RMS coeff0 */ + 0x7cb145, /* High RMS coeff1 */ + 0x5188, /* High RELEASE coeff0 */ + 0x7fae78, /* High RELEASE coeff1 */ + 0x3263a, /* High ATTACK coeff0 */ + 0x7cd9c6, /* High ATTACK coeff1 */ + 0x0, /* High THD0 coeff */ + 0x40000, /* High K0 coeff */ + 0x0, /* High OFFSET coeff*/ + 0x40000, /* High GAIN */ +}; + +#define AED_FULLBAND_DRC_SIZE (17) +#define AED_FULLBAND_DRC_BYTES (70) +#define AED_FULLBAND_DRC_OFFSET (6) +#define AED_FULLBAND_DRC_GROUP_SIZE (3) +/*K0 = 0dB; THD0 = 0; K1 = 3.0; THD1 = -70dB*/ +/*RMS:5ms, ATTACK:2ms, RELEASE:20ms*/ +/*delay: 144 sample max:255*/ +static int fullband_drc_coeff[AED_FULLBAND_DRC_SIZE] = { + 0x5188, /* RELEASE_COEF00 */ + 0x7fae78, /* RELEASE_COEF01 */ + 0x3263a, /* ATTACK_COEF00 */ + 0x7cd9c6, /* ATTACK_COEF01 */ + 0x0, /* THD0 */ + 0x0, /* K0 */ + + 0x5188, /* RELEASE_COEF10 */ + 0x7fae78, /* RELEASE_COEF11 */ + 0x3263a, /* ATTACK_COEF10 */ + 0x7cd9c6, /* ATTACK_COEF11 */ + 0xdd000000, /* THD1 */ + 0xc0000, /* K2 */ + + 0x34ebb, /* RMS coeff0 */ + 0x7cb145, /* RMS coeff1 */ + 0x90, /* Delay time*/ + 0xdd000000, /* THD_OUT0 */ + 0x40000, /* K1 */ +}; + +#endif diff --git a/sound/soc/amlogic/auge/effects_v2.c b/sound/soc/amlogic/auge/effects_v2.c index 13e4184be61a..86a696b1df70 100644 --- a/sound/soc/amlogic/auge/effects_v2.c +++ b/sound/soc/amlogic/auge/effects_v2.c @@ -25,7 +25,7 @@ #include "effects_v2.h" #include "effects_hw_v2.h" -#include "effects_hw_v2_coeff.c" +#include "effects_hw_v2_coeff.h" #include "ddr_mngr.h" #include "regs.h" #include "iomap.h" @@ -70,7 +70,6 @@ struct audioeffect { bool eq_en; bool multiband_drc_en; bool fullband_drc_en; - int mask_en; int lane_mask; int ch_mask; @@ -175,152 +174,135 @@ static int mixer_aed_write(struct snd_kcontrol *kcontrol, return 0; } -static void check_set_aed_top( - struct audioeffect *p_effect, - int mask_new, bool enable) -{ - int mask_last = p_effect->mask_en; - bool update_aed_top = false; - - pr_info("%s, mask:0x%x\n", __func__, mask_new); - - if (enable) - p_effect->mask_en |= mask_new; - else - p_effect->mask_en &= ~mask_new; - - if (enable && (!mask_last) && p_effect->mask_en) - update_aed_top = true; /* to enable */ - else if ((!enable) && mask_last && (!p_effect->mask_en)) - update_aed_top = true; /* to disable */ - - if (update_aed_top) - aml_set_aed(enable, p_effect->effect_module); -} - -static int mixer_aed_enable_DC(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct audioeffect *p_effect = snd_kcontrol_chip(kcontrol); - - p_effect->dc_en = ucontrol->value.integer.value[0]; - - aed_dc_enable(p_effect->dc_en); - - check_set_aed_top(p_effect, - 0x1 << AED_DC, - p_effect->dc_en); - - return 0; -} - -static int mixer_aed_enable_ND(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct audioeffect *p_effect = snd_kcontrol_chip(kcontrol); - - p_effect->nd_en = ucontrol->value.integer.value[0]; - - aed_nd_enable(p_effect->nd_en); - - check_set_aed_top(p_effect, - 0x1 << AED_ND, - p_effect->nd_en); - - return 0; -} - -static int mixer_aed_enable_EQ(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct audioeffect *p_effect = snd_kcontrol_chip(kcontrol); - int *p_eq_coeff = eq_coeff; - int len = ARRAY_SIZE(eq_coeff); - - p_effect->eq_en = ucontrol->value.integer.value[0]; - - aed_set_ram_coeff(len, p_eq_coeff); - aed_eq_enable(0, p_effect->eq_en); - - check_set_aed_top(p_effect, - 0x1 << AED_EQ, - p_effect->eq_en); - - return 0; -} - -static int mixer_aed_enable_multiband_DRC(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct audioeffect *p_effect = snd_kcontrol_chip(kcontrol); - int *p_multiband_coeff = multiband_drc_coeff; - int len = ARRAY_SIZE(multiband_drc_coeff); - - if (!p_effect) - return -EINVAL; - - p_effect->multiband_drc_en = ucontrol->value.integer.value[0]; - - aed_set_multiband_drc_coeff(len, p_multiband_coeff); - aed_multiband_drc_enable(p_effect->multiband_drc_en); - - check_set_aed_top(p_effect, - 0x1 << AED_MDRC, - p_effect->multiband_drc_en); - - return 0; -} - -static int mixer_aed_enable_fullband_DRC(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct audioeffect *p_effect = snd_kcontrol_chip(kcontrol); - int *p_fullband_coeff = fullband_drc_coeff; - int len = ARRAY_SIZE(fullband_drc_coeff); - - if (!p_effect) - return -EINVAL; - - p_effect->fullband_drc_en = ucontrol->value.integer.value[0]; - - aed_set_fullband_drc_coeff(len, p_fullband_coeff); - aed_fullband_drc_enable(p_effect->fullband_drc_en); - - check_set_aed_top(p_effect, - 0x1 << AED_FDRC, - p_effect->fullband_drc_en); - - return 0; -} - static int mixer_get_EQ_params(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - int *val = (int *)ucontrol->value.bytes.data; - int *p = &eq_coeff[0]; + unsigned int *value = (unsigned int *)ucontrol->value.bytes.data; + unsigned int *p = &EQ_COEFF[0]; + int i; - memcpy(val, p, AED_EQ_LENGTH); + aed_get_ram_coeff(EQ_FILTER_RAM_ADD, EQ_FILTER_SIZE_CH, p); + + for (i = 0; i < EQ_FILTER_SIZE_CH; i++) + *value++ = cpu_to_be32(*p++); return 0; } +static int str2int(char *str, unsigned int *data, int size) +{ + int num = 0; + unsigned int temp = 0; + char *ptr = str; + unsigned int *val = data; + + while (size-- != 0) { + if ((*ptr >= '0') && (*ptr <= '9')) { + temp = temp * 16 + (*ptr - '0'); + } else if ((*ptr >= 'a') && (*ptr <= 'f')) { + temp = temp * 16 + (*ptr - 'a' + 10); + } else if (*ptr == ' ') { + *(val+num) = temp; + temp = 0; + num++; + } + ptr++; + } + + return num; +} static int mixer_set_EQ_params(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct soc_bytes_ext *params = (void *)kcontrol->private_value; - void *data; - int *val, *p = &eq_coeff[0]; + unsigned int tmp_data[FILTER_PARAM_SIZE + 1]; + unsigned int *p_data = &tmp_data[0]; + char tmp_string[FILTER_PARAM_BYTE]; + char *p_string = &tmp_string[0]; + unsigned int *p = &EQ_COEFF[0]; + int num, i, band_id; + char *val = (char *)ucontrol->value.bytes.data; - data = kmemdup(ucontrol->value.bytes.data, - params->max, GFP_KERNEL | GFP_DMA); - if (!data) + if (!val) return -ENOMEM; + memcpy(p_string, val, FILTER_PARAM_BYTE); - val = (int *)data; - memcpy(p, val, params->max / sizeof(int)); + num = str2int(p_string, p_data, FILTER_PARAM_BYTE); + band_id = tmp_data[0]; + if (num != (FILTER_PARAM_SIZE + 1) || band_id >= EQ_BAND) { + pr_info("Error: parma_num = %d, band_id = %d\n", + num, tmp_data[0]); + return 0; + } - kfree(data); + p_data = &tmp_data[1]; + p = &EQ_COEFF[band_id*FILTER_PARAM_SIZE]; + for (i = 0; i < FILTER_PARAM_SIZE; i++, p++, p_data++) { + *p = *p_data; + *(p + EQ_FILTER_SIZE_CH) = *p_data; + } + + p = &EQ_COEFF[band_id*FILTER_PARAM_SIZE]; + aed_set_ram_coeff((EQ_FILTER_RAM_ADD + + band_id*FILTER_PARAM_SIZE), + FILTER_PARAM_SIZE, p); + + p = &EQ_COEFF[band_id*FILTER_PARAM_SIZE + EQ_FILTER_SIZE_CH]; + aed_set_ram_coeff((EQ_FILTER_RAM_ADD + + EQ_FILTER_SIZE_CH + band_id*FILTER_PARAM_SIZE), + FILTER_PARAM_SIZE, p); + + return 0; +} + +static int mixer_get_crossover_params(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + unsigned int *value = (unsigned int *)ucontrol->value.bytes.data; + unsigned int *p = &CROSSOVER_COEFF[0]; + int i; + + aed_get_ram_coeff(CROSSOVER_FILTER_RAM_ADD, CROSSOVER_FILTER_SIZE, p); + + for (i = 0; i < CROSSOVER_FILTER_SIZE; i++) + *value++ = cpu_to_be32(*p++); + + return 0; +} + +static int mixer_set_crossover_params(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + unsigned int tmp_data[FILTER_PARAM_SIZE + 1]; + unsigned int *p_data = &tmp_data[0]; + char tmp_string[FILTER_PARAM_BYTE]; + char *p_string = &tmp_string[0]; + unsigned int *p = &CROSSOVER_COEFF[0]; + int num, i, band_id; + char *val = (char *)ucontrol->value.bytes.data; + + if (!val) + return -ENOMEM; + memcpy(p_string, val, FILTER_PARAM_BYTE); + + num = str2int(p_string, p_data, FILTER_PARAM_BYTE); + band_id = tmp_data[0]; + if (num != (FILTER_PARAM_SIZE + 1) || + band_id >= CROSSOVER_FILTER_BAND) { + pr_info("Error: parma_num = %d, band_id = %d\n", + num, tmp_data[0]); + return 0; + } + + p_data = &tmp_data[1]; + p = &CROSSOVER_COEFF[band_id*FILTER_PARAM_SIZE]; + for (i = 0; i < FILTER_PARAM_SIZE; i++) + *p++ = *p_data++; + + p = &CROSSOVER_COEFF[band_id*FILTER_PARAM_SIZE]; + aed_set_ram_coeff((CROSSOVER_FILTER_RAM_ADD + + band_id*FILTER_PARAM_SIZE), + FILTER_PARAM_SIZE, p); return 0; } @@ -328,10 +310,17 @@ static int mixer_set_EQ_params(struct snd_kcontrol *kcontrol, static int mixer_get_multiband_DRC_params(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - int *val = (int *)ucontrol->value.bytes.data; - int *p = &multiband_drc_coeff[0]; + unsigned int *value = (unsigned int *)ucontrol->value.bytes.data; + unsigned int *p = &multiband_drc_coeff[0]; + int i; - memcpy(val, p, AED_MULTIBAND_DRC_LENGTH); + for (i = 0; i < 3; i++) { + aed_get_multiband_drc_coeff(i, + p + i * AED_SINGLE_BAND_DRC_SIZE); + } + + for (i = 0; i < AED_MULTIBAND_DRC_SIZE; i++) + *value++ = cpu_to_be32(*p++); return 0; } @@ -339,19 +328,35 @@ static int mixer_get_multiband_DRC_params(struct snd_kcontrol *kcontrol, static int mixer_set_multiband_DRC_params(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct soc_bytes_ext *params = (void *)kcontrol->private_value; - void *data; - int *val, *p = &multiband_drc_coeff[0]; + unsigned int tmp_data[AED_SINGLE_BAND_DRC_SIZE + 1]; + unsigned int *p_data = &tmp_data[0]; + char tmp_string[MULTIBAND_DRC_PARAM_BYTE]; + char *p_string = &tmp_string[0]; + unsigned int *p = &multiband_drc_coeff[0]; + int num, i, band_id; + char *val = (char *)ucontrol->value.bytes.data; - data = kmemdup(ucontrol->value.bytes.data, - params->max, GFP_KERNEL | GFP_DMA); - if (!data) + if (!val) return -ENOMEM; + memcpy(p_string, val, MULTIBAND_DRC_PARAM_BYTE); - val = (int *)data; - memcpy(p, val, params->max / sizeof(int)); + num = str2int(p_string, p_data, MULTIBAND_DRC_PARAM_BYTE); + band_id = tmp_data[0]; + if (num != (AED_SINGLE_BAND_DRC_SIZE + 1) || + band_id >= AED_MULTIBAND_DRC_BANDS) { + pr_info("Error: parma_num = %d, band_id = %d\n", + num, tmp_data[0]); + return 0; + } - kfree(data); + /*Don't update offset and gain*/ + p_data = &tmp_data[1]; + p = &multiband_drc_coeff[band_id*AED_SINGLE_BAND_DRC_SIZE]; + for (i = 0; i < (AED_SINGLE_BAND_DRC_SIZE - 2) ; i++) + *p++ = *p_data++; + + p = &multiband_drc_coeff[0]; + aed_set_multiband_drc_coeff(band_id, p); return 0; } @@ -359,10 +364,14 @@ static int mixer_set_multiband_DRC_params(struct snd_kcontrol *kcontrol, static int mixer_get_fullband_DRC_params(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - int *val = (int *)ucontrol->value.bytes.data; - int *p = &fullband_drc_coeff[0]; + unsigned int *value = (unsigned int *)ucontrol->value.bytes.data; + unsigned int *p = &fullband_drc_coeff[0]; + int i; - memcpy(val, p, AED_FULLBAND_DRC_LENGTH); + aed_get_fullband_drc_coeff(AED_FULLBAND_DRC_SIZE, p); + + for (i = 0; i < AED_FULLBAND_DRC_SIZE; i++) + *value++ = cpu_to_be32(*p++); return 0; } @@ -370,19 +379,34 @@ static int mixer_get_fullband_DRC_params(struct snd_kcontrol *kcontrol, static int mixer_set_fullband_DRC_params(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct soc_bytes_ext *params = (void *)kcontrol->private_value; - void *data; - int *val, *p = &fullband_drc_coeff[0]; + unsigned int tmp_data[AED_FULLBAND_DRC_OFFSET + 1]; + unsigned int *p_data = &tmp_data[0]; + char tmp_string[AED_FULLBAND_DRC_BYTES]; + char *p_string = &tmp_string[0]; + unsigned int *p = &fullband_drc_coeff[0]; + int num, i, band_id; + char *val = (char *)ucontrol->value.bytes.data; - data = kmemdup(ucontrol->value.bytes.data, - params->max, GFP_KERNEL | GFP_DMA); - if (!data) + if (!val) return -ENOMEM; + memcpy(p_string, val, AED_FULLBAND_DRC_BYTES); - val = (int *)data; - memcpy(p, val, params->max / sizeof(int)); + num = str2int(p_string, p_data, AED_FULLBAND_DRC_BYTES); + band_id = tmp_data[0]; + if (num != (AED_FULLBAND_DRC_OFFSET + 1) || + band_id >= AED_FULLBAND_DRC_GROUP_SIZE) { + pr_info("Error: parma_num = %d, band_id = %d\n", + num, tmp_data[0]); + return 0; + } - kfree(data); + p_data = &tmp_data[1]; + p = &fullband_drc_coeff[band_id*AED_FULLBAND_DRC_OFFSET]; + for (i = 0; i < AED_FULLBAND_DRC_OFFSET; i++) + *p++ = *p_data++; + + p = &fullband_drc_coeff[band_id*AED_FULLBAND_DRC_OFFSET]; + aed_set_fullband_drc_coeff(band_id, p); return 0; } @@ -394,7 +418,6 @@ static const char *const aed_module_texts[] = { "TDMOUT_A", "TDMOUT_B", "TDMOUT_C", - "SPDIFIN", "SPDIFOUT_A", "SPDIFOUT_B", }; @@ -429,16 +452,43 @@ static int aed_module_set_enum( p_effect->effect_module = ucontrol->value.enumerated.item[0]; /* update info to ddr and modules */ - aed_set_ctrl( - p_effect->eq_en | - p_effect->multiband_drc_en | - p_effect->fullband_drc_en, - 0, - p_effect->effect_module); + aml_set_aed(1, p_effect->effect_module); return 0; } +static void aed_set_filter_data(void) +{ + int *p; + + /* set default filter param*/ + p = &DC_CUT_COEFF[0]; + aed_set_ram_coeff(DC_CUT_FILTER_RAM_ADD, DC_CUT_FILTER_SIZE, p); + p = &EQ_COEFF[0]; + aed_set_ram_coeff(EQ_FILTER_RAM_ADD, EQ_FILTER_SIZE, p); + p = &CROSSOVER_COEFF[0]; + aed_set_ram_coeff(CROSSOVER_FILTER_RAM_ADD, CROSSOVER_FILTER_SIZE, p); + +} + +static void aed_set_drc_data(void) +{ + unsigned int *p = &multiband_drc_coeff[0]; + int i; + + /*set MDRC default value*/ + for (i = 0; i < AED_MULTIBAND_DRC_BANDS; i++) + aed_set_multiband_drc_coeff(i, p); + + + /*set FDRC default value*/ + p = &fullband_drc_coeff[0]; + for (i = 0; i < AED_FULLBAND_DRC_GROUP_SIZE; i++) { + aed_set_fullband_drc_coeff(i, + p + i * AED_FULLBAND_DRC_OFFSET); + } +} + static const DECLARE_TLV_DB_SCALE(master_vol_tlv, -12276, 12, 1); static const DECLARE_TLV_DB_SCALE(lr_vol_tlv, -12750, 50, 1); @@ -446,36 +496,41 @@ static const struct snd_kcontrol_new snd_effect_controls[] = { SOC_SINGLE_EXT("AED DC cut enable", AED_DC_EN, 0, 0x1, 0, - mixer_aed_read, mixer_aed_enable_DC), + mixer_aed_read, mixer_aed_write), SOC_SINGLE_EXT("AED Noise Detect enable", AED_ND_CNTL, 0, 0x1, 0, - mixer_aed_read, mixer_aed_enable_ND), + mixer_aed_read, mixer_aed_write), SOC_SINGLE_EXT("AED EQ enable", AED_EQ_EN, 0, 0x1, 0, - mixer_aed_read, mixer_aed_enable_EQ), - - SOC_SINGLE_EXT("AED Multi-band DRC enable", - AED_MDRC_CNTL, 8, 0x1, 0, - mixer_aed_read, mixer_aed_enable_multiband_DRC), - - SOC_SINGLE_EXT("AED Full-band DRC enable", - AED_DRC_CNTL, 0, 0x1, 0, - mixer_aed_read, mixer_aed_enable_fullband_DRC), + mixer_aed_read, mixer_aed_write), SND_SOC_BYTES_EXT("AED EQ Parameters", - AED_EQ_LENGTH, + (EQ_FILTER_SIZE_CH * 4), mixer_get_EQ_params, mixer_set_EQ_params), + SOC_SINGLE_EXT("AED Multi-band DRC enable", + AED_MDRC_CNTL, 8, 0x1, 0, + mixer_aed_read, mixer_aed_write), + + SND_SOC_BYTES_EXT("AED Crossover Filter Parameters", + (CROSSOVER_FILTER_SIZE * 4), + mixer_get_crossover_params, + mixer_set_crossover_params), + SND_SOC_BYTES_EXT("AED Multi-band DRC Parameters", - AED_MULTIBAND_DRC_LENGTH, + (AED_MULTIBAND_DRC_SIZE * 4), mixer_get_multiband_DRC_params, mixer_set_multiband_DRC_params), + SOC_SINGLE_EXT("AED Full-band DRC enable", + AED_DRC_CNTL, 0, 0x1, 0, + mixer_aed_read, mixer_aed_write), + SND_SOC_BYTES_EXT("AED Full-band DRC Parameters", - AED_FULLBAND_DRC_LENGTH, + AED_FULLBAND_DRC_BYTES, mixer_get_fullband_DRC_params, mixer_set_fullband_DRC_params), @@ -484,14 +539,6 @@ static const struct snd_kcontrol_new snd_effect_controls[] = { aed_module_get_enum, aed_module_set_enum), - SOC_SINGLE_EXT("AED Lane mask", - AED_TOP_CTL, 14, 0xF, 0, - mixer_aed_read, mixer_aed_write), - - SOC_SINGLE_EXT("AED Channel mask", - AED_TOP_CTL, 18, 0xFF, 0, - mixer_aed_read, mixer_aed_write), - SOC_SINGLE_EXT_TLV("AED Lch volume", AED_EQ_VOLUME, 0, 0xFF, 1, mixer_aed_read, mixer_aed_write, @@ -529,15 +576,6 @@ int card_add_effect_v2_kcontrols(struct snd_soc_card *card) return 0; } -#if 0 -static const struct snd_soc_component_driver effect_component_drv = { - .name = DRV_NAME, - - .controls = snd_effect_controls, - .num_controls = ARRAY_SIZE(snd_effect_controls), -}; -#endif - static struct effect_chipinfo tl1_effect_chipinfo = { .v2 = true, }; @@ -567,7 +605,6 @@ static int effect_platform_probe(struct platform_device *pdev) bool multiband_drc_enable = false; bool fullband_drc_enable = false; int lane_mask = -1, channel_mask = -1, eqdrc_module = -1; - int ret; pr_info("%s, line:%d\n", __func__, __LINE__); @@ -619,16 +656,11 @@ static int effect_platform_probe(struct platform_device *pdev) return ret; } - eqdrc_clk_set(p_effect); - - eq_enable = of_property_read_bool(pdev->dev.of_node, - "eq_enable"); - - multiband_drc_enable = of_property_read_bool(pdev->dev.of_node, - "multiband_drc_enable"); - - fullband_drc_enable = of_property_read_bool(pdev->dev.of_node, - "fullband_drc_enable"); + ret = eqdrc_clk_set(p_effect); + if (ret < 0) { + dev_err(&pdev->dev, "set eq drc module clk fail!\n"); + return -EINVAL; + } ret = of_property_read_u32(pdev->dev.of_node, "eqdrc_module", @@ -654,11 +686,8 @@ static int effect_platform_probe(struct platform_device *pdev) return -EINVAL; } - pr_info("%s \t eq_en:%d, multi-band drc en:%d, full-band drc en:%d, module:%d, lane_mask:%d, ch_mask:%d\n", + pr_info("%s \t module:%d, lane_mask:%d, ch_mask:%d\n", __func__, - eq_enable, - multiband_drc_enable, - fullband_drc_enable, eqdrc_module, lane_mask, channel_mask @@ -672,8 +701,24 @@ static int effect_platform_probe(struct platform_device *pdev) p_effect->ch_mask = channel_mask; p_effect->effect_module = eqdrc_module; + /*set eq/drc module lane & channels*/ aed_set_lane_and_channels(lane_mask, channel_mask); - aed_set_EQ_volume(0xc0, 0x30, 0x30); + /*set master & channel volume gain to 0dB*/ + aed_set_volume(0xc0, 0x30, 0x30); + /*set default mixer gain*/ + aed_set_mixer_params(); + /*all 20 bands for EQ1*/ + aed_eq_taps(EQ_BAND); + /*set default filter param*/ + aed_set_filter_data(); + /*set multi-band drc param*/ + aed_set_multiband_drc_param(); + /*set multi/full-band drc data*/ + aed_set_drc_data(); + /*set full-band drc param, enable 2 band*/ + aed_set_fullband_drc_param(2); + /*set EQ/DRC module enable*/ + aml_set_aed(1, p_effect->effect_module); p_effect->dev = dev; s_effect = p_effect; diff --git a/sound/soc/amlogic/auge/extn.c b/sound/soc/amlogic/auge/extn.c index 55d3e46ec438..78ec04f952bd 100644 --- a/sound/soc/amlogic/auge/extn.c +++ b/sound/soc/amlogic/auge/extn.c @@ -37,11 +37,21 @@ #include "ddr_mngr.h" #include "audio_utils.h" #include "frhdmirx_hw.h" +#include "resample.h" #include #define DRV_NAME "EXTN" +#define MAX_INT 0x7ffffff + +struct extn_chipinfo { + /* try to check papb before fetch pcpd + * no nonpcm2pcm irq for tl1 + */ + bool no_nonpcm2pcm_clr; +}; + struct extn { struct aml_audio_controller *actrl; struct device *dev; @@ -69,9 +79,19 @@ struct extn { int arc_src; int arc_en; + /* check whether irq generating + * if not, reset + * 'cuase no irq from nonpcm2pcm, do it by sw. + */ + unsigned int frhdmirx_cnt; /* irq counter */ + unsigned int frhdmirx_last_cnt; + unsigned int frhdmirx_same_cnt; + bool nonpcm_flag; + + struct extn_chipinfo *chipinfo; }; -#define PREALLOC_BUFFER (128 * 1024) +#define PREALLOC_BUFFER (256 * 1024) #define PREALLOC_BUFFER_MAX (256 * 1024) #define EXTN_RATES (SNDRV_PCM_RATE_8000_192000) @@ -100,21 +120,58 @@ static const struct snd_pcm_hardware extn_hardware = { .channels_max = 32, }; +static void frhdmirx_nonpcm2pcm_clr_reset(struct extn *p_extn) +{ + p_extn->frhdmirx_cnt = 0; + p_extn->frhdmirx_last_cnt = 0; + p_extn->frhdmirx_same_cnt = 0; +} + static irqreturn_t extn_ddr_isr(int irq, void *devid) { struct snd_pcm_substream *substream = (struct snd_pcm_substream *)devid; + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct device *dev = rtd->platform->dev; + struct extn *p_extn = (struct extn *)dev_get_drvdata(dev); if (!snd_pcm_running(substream)) return IRQ_HANDLED; snd_pcm_period_elapsed(substream); + /* check pcm or nonpcm */ + if (p_extn && + p_extn->chipinfo && + p_extn->chipinfo->no_nonpcm2pcm_clr) { + if (p_extn->frhdmirx_last_cnt == p_extn->frhdmirx_cnt) { + + p_extn->frhdmirx_same_cnt++; + + if (p_extn->frhdmirx_same_cnt > 5) + frhdmirx_nonpcm2pcm_clr_reset(p_extn); + + if (p_extn->frhdmirx_cnt == 0) + p_extn->nonpcm_flag = false; + } else { + p_extn->frhdmirx_last_cnt = p_extn->frhdmirx_cnt; + p_extn->frhdmirx_same_cnt = 0; + p_extn->nonpcm_flag = true; + frhdmirx_clr_PAO_irq_bits(); + } + } + return IRQ_HANDLED; } static irqreturn_t frhdmirx_isr(int irq, void *devid) { + struct extn *p_extn = (struct extn *)devid; + + p_extn->frhdmirx_cnt++; + if (p_extn->frhdmirx_cnt > MAX_INT - 2) + frhdmirx_nonpcm2pcm_clr_reset(p_extn); + return IRQ_HANDLED; } @@ -177,8 +234,12 @@ static int extn_close(struct snd_pcm_substream *substream) else { aml_audio_unregister_toddr(p_extn->dev, substream); - if (toddr_src_get() == FRHDMIRX) + if (toddr_src_get() == FRHDMIRX) { + frhdmirx_nonpcm2pcm_clr_reset(p_extn); + if (p_extn->hdmirx_mode == 1) + frhdmirx_clr_PAO_irq_bits(); free_irq(p_extn->irq_frhdmirx, p_extn); + } } runtime->private_data = NULL; @@ -311,6 +372,9 @@ static int extn_dai_startup( struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai) { + if (get_audioresample(RESAMPLE_A)) + resample_set_inner_rate(RESAMPLE_A); + return 0; } @@ -318,6 +382,7 @@ static void extn_dai_shutdown( struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai) { + //resample_set(RESAMPLE_A, RATE_OFF); } static int extn_dai_prepare( @@ -341,7 +406,7 @@ static int extn_dai_prepare( } else { struct toddr *to = p_extn->tddr; unsigned int msb = 0, lsb = 0, toddr_type = 0; - unsigned int src = toddr_src_get(); + enum toddr_src src = toddr_src_get(); struct toddr_fmt fmt; if (bit_depth == 24) @@ -412,7 +477,7 @@ static int extn_dai_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *cpu_dai) { struct extn *p_extn = snd_soc_dai_get_drvdata(cpu_dai); - unsigned int src = toddr_src_get(); + enum toddr_src src = toddr_src_get(); switch (cmd) { case SNDRV_PCM_TRIGGER_START: @@ -639,7 +704,7 @@ static const struct sppdif_audio_info type_texts[] = { {3, 0xb, "DTS-I"}, {3, 0x0c, "DTS-II"}, {3, 0x0d, "DTS-III"}, - {3, 0x11, "DTS-IV"}, + {4, 0x11, "DTS-IV"}, {4, 0, "DTS-HD"}, {5, 0x16, "TRUEHD"}, {6, 0x103, "PAUSE"}, @@ -651,13 +716,16 @@ static const struct soc_enum hdmirx_audio_type_enum = SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(spdif_audio_type_texts), spdif_audio_type_texts); -static int hdmiin_check_audio_type(void) +static int hdmiin_check_audio_type(struct extn *p_extn) { int total_num = sizeof(type_texts)/sizeof(struct sppdif_audio_info); int pc = frhdmirx_get_chan_status_pc(); int audio_type = 0; int i; + if (!p_extn->nonpcm_flag) + return audio_type; + for (i = 0; i < total_num; i++) { if (pc == type_texts[i].pc) { audio_type = type_texts[i].aud_type; @@ -674,8 +742,12 @@ static int hdmirx_audio_type_get_enum( struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct extn *p_extn = dev_get_drvdata(component->dev); + ucontrol->value.enumerated.item[0] = - hdmiin_check_audio_type(); + hdmiin_check_audio_type(p_extn); + return 0; } #endif @@ -705,6 +777,13 @@ static const struct snd_kcontrol_new extn_controls[] = { NULL), #endif +#ifdef CONFIG_AMLOGIC_MEDIA_TVIN_AVDETECT + SOC_ENUM_EXT("AV audio stable", + av_audio_status_enum, + aml_get_av_audio_stable, + NULL), +#endif + #ifdef CONFIG_AMLOGIC_MEDIA_TVIN_HDMI SOC_ENUM_EXT("HDMIIN audio stable", hdmi_in_status_enum[0], @@ -726,10 +805,16 @@ static const struct snd_kcontrol_new extn_controls[] = { aml_get_hdmiin_audio_format, NULL), + SOC_ENUM_EXT("HDMIIN Audio Packet", + hdmi_in_status_enum[4], + aml_get_hdmiin_audio_packet, + NULL), + SOC_SINGLE_BOOL_EXT("HDMI ATMOS EDID Switch", 0, aml_get_atmos_audio_edid, aml_set_atmos_audio_edid), + SOC_ENUM_EXT("HDMIIN Audio Type", hdmirx_audio_type_enum, hdmirx_audio_type_get_enum, @@ -744,9 +829,18 @@ static const struct snd_soc_component_driver extn_component = { .name = DRV_NAME, }; +struct extn_chipinfo tl1_extn_chipinfo = { + .no_nonpcm2pcm_clr = true, +}; + static const struct of_device_id extn_device_id[] = { { .compatible = "amlogic, snd-extn", + .data = &tl1_extn_chipinfo, + }, + { + .compatible = "amlogic, tl1-snd-extn", + .data = &tl1_extn_chipinfo, }, {}, }; @@ -761,9 +855,9 @@ static int extn_platform_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct aml_audio_controller *actrl = NULL; struct extn *p_extn = NULL; + struct extn_chipinfo *p_chipinfo; int ret = 0; - p_extn = devm_kzalloc(dev, sizeof(struct extn), GFP_KERNEL); if (!p_extn) return -ENOMEM; @@ -771,6 +865,14 @@ static int extn_platform_probe(struct platform_device *pdev) p_extn->dev = dev; dev_set_drvdata(dev, p_extn); + /* match data */ + p_chipinfo = (struct extn_chipinfo *) + of_device_get_match_data(dev); + if (!p_chipinfo) + dev_warn_once(dev, "check whether to update chipinfo\n"); + else + p_extn->chipinfo = p_chipinfo; + /* get audio controller */ node_prt = of_get_parent(node); if (node_prt == NULL) @@ -793,8 +895,8 @@ static int extn_platform_probe(struct platform_device *pdev) /* Default ARC SRC */ p_extn->arc_src = 1; - /* Default: SPDIF in mode */ - p_extn->hdmirx_mode = 0; + /* Default: PAO mode */ + p_extn->hdmirx_mode = 1; ret = snd_soc_register_component(&pdev->dev, &extn_component, diff --git a/sound/soc/amlogic/auge/frhdmirx_hw.c b/sound/soc/amlogic/auge/frhdmirx_hw.c index 19c55f480522..1dd059365a71 100644 --- a/sound/soc/amlogic/auge/frhdmirx_hw.c +++ b/sound/soc/amlogic/auge/frhdmirx_hw.c @@ -15,6 +15,7 @@ * */ #include +#include #include "frhdmirx_hw.h" #include "regs.h" @@ -48,7 +49,7 @@ void frhdmirx_src_select(int src) (bool)src << 23); } -void frhdmirx_enable_irq_bits(int channels, int src) +static void frhdmirx_enable_irq_bits(int channels, int src) { int lane, int_bits = 0, i; @@ -59,10 +60,11 @@ void frhdmirx_enable_irq_bits(int channels, int src) /* interrupt bits */ if (src) { /* PAO mode */ - int_bits = (0x1 << 24 | /* PAO data: find papb */ - 0x1 << 16 /* PAO data: find pcpd changed */ + int_bits = ( + 0x1 << INT_PAO_PAPB_MASK | /* find papb */ + 0x1 << INT_PAO_PCPD_MASK /* find pcpd changed */ ); - } else { /* SPDIF Lane*/ + } else { /* SPDIF Lane */ int lane_irq_bits = (0x1 << 7 | /* lane: find papb */ 0x1 << 6 | /* lane: find papb */ 0x1 << 5 | /* lane: find nonpcm to pcm */ @@ -77,6 +79,39 @@ void frhdmirx_enable_irq_bits(int channels, int src) audiobus_write(EE_AUDIO_FRHDMIRX_CTRL2, int_bits); } +void frhdmirx_clr_irq_bits(int channels, int src) +{ + int lane, int_clr_mask = 0, i; + + if (channels % 2) + lane = channels / 2 + 1; + else + lane = channels / 2; + + /* interrupt bits */ + if (src) { /* PAO mode */ + int_clr_mask = ( + 0x1 << INT_PAO_PAPB_MASK | /* find papb */ + 0x1 << INT_PAO_PCPD_MASK /* find pcpd changed */ + ); + } else { /* SPDIF Lane */ + int lane_irq_bits = (0x1 << 7 | /* lane: find papb */ + 0x1 << 6 | /* lane: find valid changed; */ + 0x1 << 5 | /* lane: find nonpcm to pcm */ + 0x1 << 4 | /* lane: find pcpd changed */ + 0x1 << 3 | /* lane: find ch status changed */ + 0x1 << 1 /* lane: find parity error */ + ); + + for (i = 0; i < lane; i++) + int_clr_mask |= (lane_irq_bits << i); + } + audiobus_write(EE_AUDIO_FRHDMIRX_CTRL3, ~int_clr_mask); + audiobus_write(EE_AUDIO_FRHDMIRX_CTRL3, int_clr_mask); + audiobus_write(EE_AUDIO_FRHDMIRX_CTRL4, ~int_clr_mask); + audiobus_write(EE_AUDIO_FRHDMIRX_CTRL4, int_clr_mask); +} + void frhdmirx_ctrl(int channels, int src) { int lane, lane_mask = 0, i; @@ -84,30 +119,27 @@ void frhdmirx_ctrl(int channels, int src) /* PAO mode */ if (src) { audiobus_write(EE_AUDIO_FRHDMIRX_CTRL0, - 0x1 << 23 | /* slect pao mode */ 0x1 << 22 | /* capture input by fall edge*/ - 0x1 << 7 | /* start sending ch num info out */ 0x1 << 8 | /* start detect PAPB */ - 0x1 << 6 /* chan status sel: pao pc/pd value */); - return; + 0x4 << 4 /* chan status sel: pao pc/pd value */ + ); + } else { + if (channels % 2) + lane = channels / 2 + 1; + else + lane = channels / 2; + + for (i = 0; i < lane; i++) + lane_mask |= (1 << i); + + audiobus_update_bits(EE_AUDIO_FRHDMIRX_CTRL0, + 0x1 << 30 | 0xf << 24 | 0x1 << 22 | 0x3 << 11, + 0x1 << 30 | /* chnum_sel */ + lane_mask << 24 | /* chnum_sel */ + 0x1 << 22 | /* clk_inv */ + 0x0 << 11 /* req_sel, Sync 4 spdifin by which */ + ); } - - if (channels % 2) - lane = channels / 2 + 1; - else - lane = channels / 2; - - for (i = 0; i < lane; i++) - lane_mask |= (1 << i); - - audiobus_update_bits(EE_AUDIO_FRHDMIRX_CTRL0, - 0x1 << 30 | 0xf << 24 | 0x1 << 22 | 0x3 << 11, - 0x1 << 30 | /* chnum_sel */ - lane_mask << 24 | /* chnum_sel */ - 0x1 << 22 | /* clk_inv */ - 0x0 << 11 /* req_sel, Sync 4 spdifin by which */ - ); - /* nonpcm2pcm_th */ audiobus_write(EE_AUDIO_FRHDMIRX_CTRL1, 0xff << 20); @@ -115,6 +147,22 @@ void frhdmirx_ctrl(int channels, int src) frhdmirx_enable_irq_bits(channels, src); } +void frhdmirx_clr_PAO_irq_bits(void) +{ + audiobus_update_bits(EE_AUDIO_FRHDMIRX_CTRL4, + 0x1 << INT_PAO_PAPB_MASK | 0x1 << INT_PAO_PCPD_MASK, + 0x1 << INT_PAO_PAPB_MASK | 0x1 << INT_PAO_PCPD_MASK); + + audiobus_update_bits(EE_AUDIO_FRHDMIRX_CTRL4, + 0x1 << INT_PAO_PAPB_MASK | 0x1 << INT_PAO_PCPD_MASK, + 0x0 << INT_PAO_PAPB_MASK | 0x0 << INT_PAO_PCPD_MASK); +} + +unsigned int frhdmirx_get_ch_status0to31(void) +{ + return (unsigned int)audiobus_read(EE_AUDIO_FRHDMIRX_STAT0); +} + unsigned int frhdmirx_get_chan_status_pc(void) { unsigned int val; @@ -122,6 +170,3 @@ unsigned int frhdmirx_get_chan_status_pc(void) val = audiobus_read(EE_AUDIO_FRHDMIRX_STAT1); return (val >> 16) & 0xff; } - - - diff --git a/sound/soc/amlogic/auge/frhdmirx_hw.h b/sound/soc/amlogic/auge/frhdmirx_hw.h index e0ebfe46323e..7c83dd01c704 100644 --- a/sound/soc/amlogic/auge/frhdmirx_hw.h +++ b/sound/soc/amlogic/auge/frhdmirx_hw.h @@ -17,8 +17,13 @@ #ifndef __FRHDMIRX_HW_H__ #define __FRHDMIRX_HW_H__ +#define INT_PAO_PAPB_MASK 24 +#define INT_PAO_PCPD_MASK 16 + extern void frhdmirx_enable(bool enable); extern void frhdmirx_src_select(int src); extern void frhdmirx_ctrl(int channels, int src); +extern void frhdmirx_clr_PAO_irq_bits(void); +extern unsigned int frhdmirx_get_ch_status0to31(void); extern unsigned int frhdmirx_get_chan_status_pc(void); #endif diff --git a/sound/soc/amlogic/auge/iomap.c b/sound/soc/amlogic/auge/iomap.c index 58bef78704ad..e196591b3328 100644 --- a/sound/soc/amlogic/auge/iomap.c +++ b/sound/soc/amlogic/auge/iomap.c @@ -231,6 +231,87 @@ void vad_update_bits(unsigned int reg, } EXPORT_SYMBOL(vad_update_bits); +int earcrx_cmdc_read(unsigned int reg) +{ + int ret, val = 0; + + ret = aml_snd_read(IO_EARCRX_CMDC, reg, &val); + + if (ret) { + pr_err("read audio reg %x error %d\n", reg, ret); + return -1; + } + return val; +} +EXPORT_SYMBOL(earcrx_cmdc_read); + +void earcrx_cmdc_write(unsigned int reg, unsigned int val) +{ + aml_snd_write(IO_EARCRX_CMDC, reg, val); +} +EXPORT_SYMBOL(earcrx_cmdc_write); + +void earcrx_cmdc_update_bits(unsigned int reg, + unsigned int mask, unsigned int val) +{ + aml_snd_update_bits(IO_EARCRX_CMDC, reg, mask, val); +} +EXPORT_SYMBOL(earcrx_cmdc_update_bits); + +int earcrx_dmac_read(unsigned int reg) +{ + int ret, val = 0; + + ret = aml_snd_read(IO_EARCRX_DMAC, reg, &val); + + if (ret) { + pr_err("read audio reg %x error %d\n", reg, ret); + return -1; + } + return val; +} +EXPORT_SYMBOL(earcrx_dmac_read); + +void earcrx_dmac_write(unsigned int reg, unsigned int val) +{ + aml_snd_write(IO_EARCRX_DMAC, reg, val); +} +EXPORT_SYMBOL(earcrx_dmac_write); + +void earcrx_dmac_update_bits(unsigned int reg, + unsigned int mask, unsigned int val) +{ + aml_snd_update_bits(IO_EARCRX_DMAC, reg, mask, val); +} +EXPORT_SYMBOL(earcrx_dmac_update_bits); + +int earcrx_top_read(unsigned int reg) +{ + int ret, val = 0; + + ret = aml_snd_read(IO_EARCRX_TOP, reg, &val); + + if (ret) { + pr_err("read audio reg %x error %d\n", reg, ret); + return -1; + } + return val; +} +EXPORT_SYMBOL(earcrx_top_read); + +void earcrx_top_write(unsigned int reg, unsigned int val) +{ + aml_snd_write(IO_EARCRX_TOP, reg, val); +} +EXPORT_SYMBOL(earcrx_top_write); + +void earcrx_top_update_bits(unsigned int reg, + unsigned int mask, unsigned int val) +{ + aml_snd_update_bits(IO_EARCRX_TOP, reg, mask, val); +} +EXPORT_SYMBOL(earcrx_top_update_bits); + static int snd_iomap_probe(struct platform_device *pdev) { struct resource res; diff --git a/sound/soc/amlogic/auge/iomap.h b/sound/soc/amlogic/auge/iomap.h index ae3c9287cc48..07b8b54c2d89 100644 --- a/sound/soc/amlogic/auge/iomap.h +++ b/sound/soc/amlogic/auge/iomap.h @@ -25,6 +25,9 @@ enum{ IO_EQDRC_BUS, IO_RESET, IO_VAD, + IO_EARCRX_CMDC, + IO_EARCRX_DMAC, + IO_EARCRX_TOP, IO_MAX, }; @@ -58,4 +61,17 @@ extern int vad_read(unsigned int reg); extern void vad_write(unsigned int reg, unsigned int val); extern void vad_update_bits(unsigned int reg, unsigned int mask, unsigned int val); + +extern int earcrx_cmdc_read(unsigned int reg); +extern void earcrx_cmdc_write(unsigned int reg, unsigned int val); +extern void earcrx_cmdc_update_bits(unsigned int reg, + unsigned int mask, unsigned int val); +extern int earcrx_dmac_read(unsigned int reg); +extern void earcrx_dmac_write(unsigned int reg, unsigned int val); +extern void earcrx_dmac_update_bits(unsigned int reg, + unsigned int mask, unsigned int val); +extern int earcrx_top_read(unsigned int reg); +extern void earcrx_top_write(unsigned int reg, unsigned int val); +extern void earcrx_top_update_bits(unsigned int reg, + unsigned int mask, unsigned int val); #endif diff --git a/sound/soc/amlogic/auge/loopback_hw.c b/sound/soc/amlogic/auge/loopback_hw.c index 6e4538cd2f41..15144b9dde7e 100644 --- a/sound/soc/amlogic/auge/loopback_hw.c +++ b/sound/soc/amlogic/auge/loopback_hw.c @@ -71,8 +71,8 @@ void datalb_ctrl(struct loopback_cfg *lb_cfg) if (id >= 0 && id <= 2) { /* tdmout_a, tdmout_b, tdmout_c */ - reg_base = EE_AUDIO_TDMOUT_A_SWAP; - offset = EE_AUDIO_TDMOUT_B_SWAP - EE_AUDIO_TDMOUT_A_SWAP; + reg_base = EE_AUDIO_TDMOUT_A_SWAP0; + offset = EE_AUDIO_TDMOUT_B_SWAP0 - EE_AUDIO_TDMOUT_A_SWAP0; } else if (id < 6) { /*lb_cfg->datalb_src for pad tdm in, *pad from tdmin_a, tdmin_b, tdmin_c @@ -115,8 +115,8 @@ void datalb_ctrl(struct loopback_cfg *lb_cfg) audiobus_write( reg, lb_cfg->datalb_chmask); - reg_base = EE_AUDIO_TDMIN_A_SWAP; - offset = EE_AUDIO_TDMIN_B_SWAP - EE_AUDIO_TDMIN_A_SWAP; + reg_base = EE_AUDIO_TDMIN_A_SWAP0; + offset = EE_AUDIO_TDMIN_B_SWAP0 - EE_AUDIO_TDMIN_A_SWAP0; } else { pr_err("unsupport datalb_src\n"); return; @@ -124,7 +124,7 @@ void datalb_ctrl(struct loopback_cfg *lb_cfg) if (lb_cfg->datain_datalb_total > 8) { audiobus_write( - EE_AUDIO_TDMIN_LB_SWAP, + EE_AUDIO_TDMIN_LB_SWAP0, lb_cfg->datalb_chswap); audiobus_write(EE_AUDIO_TDMIN_LB_MASK0, 3); @@ -134,7 +134,7 @@ void datalb_ctrl(struct loopback_cfg *lb_cfg) } else { /*swap same as tdmout */ reg = reg_base + offset * id; - audiobus_write(EE_AUDIO_TDMIN_LB_SWAP, + audiobus_write(EE_AUDIO_TDMIN_LB_SWAP0, audiobus_read(reg)); /*mask same as datalb*/ diff --git a/sound/soc/amlogic/auge/pdm.c b/sound/soc/amlogic/auge/pdm.c index d4ef74f0e7b1..72540b46961f 100644 --- a/sound/soc/amlogic/auge/pdm.c +++ b/sound/soc/amlogic/auge/pdm.c @@ -30,6 +30,7 @@ #include "pdm.h" #include "pdm_hw.h" +#include "pdm_match_table.c" #include "audio_io.h" #include "iomap.h" #include "regs.h" @@ -54,7 +55,7 @@ static struct snd_pcm_hardware aml_pdm_hardware = { .rate_max = 96000, .channels_min = PDM_CHANNELS_MIN, - .channels_max = PDM_CHANNELS_MAX, + .channels_max = PDM_CHANNELS_LB_MAX, .buffer_bytes_max = 512 * 1024, .period_bytes_max = 256 * 1024, @@ -166,6 +167,46 @@ static int pdm_dclk_set_enum( return 0; } +static const char *const pdm_train_texts[] = { + "Disabled", + "Enable", +}; + +static const struct soc_enum pdm_train_enum = + SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(pdm_train_texts), + pdm_train_texts); + +static int pdm_train_get_enum( + struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol); + struct aml_pdm *p_pdm = snd_soc_dai_get_drvdata(cpu_dai); + + ucontrol->value.enumerated.item[0] = p_pdm->train_en; + + return 0; +} + +static int pdm_train_set_enum( + struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol); + struct aml_pdm *p_pdm = snd_soc_dai_get_drvdata(cpu_dai); + + if (!p_pdm->chipinfo || + !p_pdm->chipinfo->train || + (p_pdm->train_en == ucontrol->value.enumerated.item[0])) + return 0; + + p_pdm->train_en = ucontrol->value.enumerated.item[0]; + + if (p_pdm->clk_on) + pdm_train_en(p_pdm->train_en); + + return 0; +} static const struct snd_kcontrol_new snd_pdm_controls[] = { /* which set */ @@ -184,8 +225,14 @@ static const struct snd_kcontrol_new snd_pdm_controls[] = { pdm_dclk_enum, pdm_dclk_get_enum, pdm_dclk_set_enum), + + SOC_ENUM_EXT("PDM Train", + pdm_train_enum, + pdm_train_get_enum, + pdm_train_set_enum), }; +#if 0 static int pdm_mute_val_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { @@ -327,16 +374,24 @@ __error: return err; } - +#endif static irqreturn_t aml_pdm_isr_handler(int irq, void *data) { struct snd_pcm_substream *substream = (struct snd_pcm_substream *)data; + int train_sts = pdm_train_sts(); pr_debug("%s\n", __func__); snd_pcm_period_elapsed(substream); + if (train_sts) { + pr_debug("%s train result:0x%x\n", + __func__, + train_sts); + pdm_train_clr(); + } + return IRQ_HANDLED; } @@ -626,6 +681,7 @@ static int aml_pdm_dai_prepare( struct toddr *to = p_pdm->tddr; struct toddr_fmt fmt; unsigned int osr = 192; + struct pdm_info info; /* to ddr pdmin */ fmt.type = toddr_type; @@ -639,8 +695,12 @@ static int aml_pdm_dai_prepare( aml_toddr_set_format(to, &fmt); aml_toddr_set_fifos(to, 0x40); - aml_pdm_ctrl(p_pdm->actrl, - bitwidth, runtime->channels); + info.bitdepth = bitwidth; + info.channels = runtime->channels; + info.lane_masks = p_pdm->lane_mask_in; + info.dclk_idx = pdm_dclk; + info.bypass = p_pdm->bypass; + aml_pdm_ctrl(&info); /* filter for pdm */ if (pdm_dclk == 1) { @@ -830,12 +890,15 @@ int aml_pdm_dai_startup(struct snd_pcm_substream *substream, pr_err("Can't enable pcm clk_pdm_dclk clock: %d\n", ret); goto err; } - +#if 0 if (p_pdm->chipinfo && p_pdm->chipinfo->mute_fn) { struct snd_card *card = cpu_dai->component->card->snd_card; pdm_running_create_controls(card, p_pdm); } +#endif + + p_pdm->clk_on = true; return 0; err: @@ -847,12 +910,15 @@ void aml_pdm_dai_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai) { struct aml_pdm *p_pdm = snd_soc_dai_get_drvdata(cpu_dai); - +#if 0 if (p_pdm->chipinfo && p_pdm->chipinfo->mute_fn) { struct snd_card *card = cpu_dai->component->card->snd_card; pdm_running_destroy_controls(card, p_pdm); } +#endif + + p_pdm->clk_on = false; /* disable clock and gate */ clk_disable_unprepare(p_pdm->clk_pdm_dclk); @@ -877,7 +943,7 @@ struct snd_soc_dai_driver aml_pdm_dai[] = { .name = "PDM", .capture = { .channels_min = PDM_CHANNELS_MIN, - .channels_max = PDM_CHANNELS_MAX, + .channels_max = PDM_CHANNELS_LB_MAX, .rates = PDM_RATES, .formats = PDM_FORMATS, }, @@ -891,31 +957,25 @@ static const struct snd_soc_component_driver aml_pdm_component = { .name = DRV_NAME, }; -static struct pdm_chipinfo g12a_pdm_chipinfo = { - .mute_fn = true, - .truncate_data = false, -}; +static int snd_soc_of_get_slot_mask( + struct device_node *np, + const char *prop_name, + unsigned int *mask) +{ + u32 val; + const __be32 *of_slot_mask = of_get_property(np, prop_name, &val); + int i; -static struct pdm_chipinfo tl1_pdm_chipinfo = { - .mute_fn = true, - .truncate_data = false, -}; + if (!of_slot_mask) + return -EINVAL; -static const struct of_device_id aml_pdm_device_id[] = { - { - .compatible = "amlogic, axg-snd-pdm", - }, - { - .compatible = "amlogic, g12a-snd-pdm", - .data = &g12a_pdm_chipinfo, - }, - { - .compatible = "amlogic, tl1-snd-pdm", - .data = &tl1_pdm_chipinfo, - }, - {} -}; -MODULE_DEVICE_TABLE(of, aml_pdm_device_id); + val /= sizeof(u32); + for (i = 0; i < val; i++) + if (be32_to_cpup(&of_slot_mask[i])) + *mask |= (1 << i); + + return val; +} static int aml_pdm_platform_probe(struct platform_device *pdev) { @@ -1021,6 +1081,12 @@ static int aml_pdm_platform_probe(struct platform_device *pdev) goto err; } + ret = snd_soc_of_get_slot_mask(node, "lane-mask-in", + &p_pdm->lane_mask_in); + if (ret < 0) { + pr_warn("default set lane_mask_in as all lanes.\n"); + p_pdm->lane_mask_in = 0xf; + } ret = of_property_read_u32(node, "filter_mode", &p_pdm->filter_mode); diff --git a/sound/soc/amlogic/auge/pdm.h b/sound/soc/amlogic/auge/pdm.h index 60a0e1e46689..39bf6ab11efb 100644 --- a/sound/soc/amlogic/auge/pdm.h +++ b/sound/soc/amlogic/auge/pdm.h @@ -27,7 +27,9 @@ #define DEFAULT_FS_RATIO 256 #define PDM_CHANNELS_MIN 1 -#define PDM_CHANNELS_MAX (8 + 8) /* 8ch pdm in, 8 ch tdmin_lb */ +/* 8ch pdm in, 8 ch tdmin_lb */ +#define PDM_CHANNELS_LB_MAX (PDM_CHANNELS_MAX + 8) + #define PDM_RATES (SNDRV_PCM_RATE_96000 |\ SNDRV_PCM_RATE_64000 |\ @@ -52,6 +54,8 @@ struct pdm_chipinfo { bool mute_fn; /* truncate invalid data when filter init */ bool truncate_data; + /* train */ + bool train; }; struct aml_pdm { @@ -72,6 +76,19 @@ struct aml_pdm { * the group delay (latency) is from high to low. */ int filter_mode; + /* dclk index */ + int dclk_idx; + /* PCM or Raw Data */ + int bypass; + + /* lane mask in, each lane carries two channels */ + int lane_mask_in; + + /* PDM clk on/off, only clk on, pdm registers can be accessed */ + bool clk_on; + + /* train */ + bool train_en; struct pdm_chipinfo *chipinfo; struct snd_kcontrol *controls[PDM_RUN_MAX]; diff --git a/sound/soc/amlogic/auge/pdm_hw.c b/sound/soc/amlogic/auge/pdm_hw.c index d870dd0336c5..1b4d2e19e5b2 100644 --- a/sound/soc/amlogic/auge/pdm_hw.c +++ b/sound/soc/amlogic/auge/pdm_hw.c @@ -59,29 +59,54 @@ void pdm_fifo_reset(void) 0x1 << 16); } -void aml_pdm_ctrl( - struct aml_audio_controller *actrl, - int bitdepth, int channels) +void aml_pdm_ctrl(struct pdm_info *info) { int mode, i, ch_mask = 0, sample_count; + int pdm_chs, lane_chs = 0; + + if (!info) + return; /* sameple count */ - if (pdm_dclk == 1) + if (info->dclk_idx == 1) sample_count = 38; - else if (pdm_dclk == 2) + else if (info->dclk_idx == 2) sample_count = 48; else sample_count = 18; - if (bitdepth == 32) + if (info->bitdepth == 32) mode = 0; else mode = 1; - for (i = 0; i < channels; i++) - ch_mask |= (1 << i); + /* update pdm channels for loopback */ + pdm_chs = info->channels; + if (info->channels > PDM_CHANNELS_MAX) + pdm_chs = PDM_CHANNELS_MAX; - pr_info("%s, channels mask:%x\n", __func__, ch_mask); + if (pdm_chs > info->lane_masks * 2) + pr_warn("capturing channels more than lanes carried\n"); + + /* each lanes carries two channels */ + for (i = 0; i < PDM_LANE_MAX; i++) + if ((1 << i) & info->lane_masks) { + ch_mask |= (1 << (2 * i)); + lane_chs += 1; + if (lane_chs >= info->channels) + break; + ch_mask |= (1 << (2 * i + 1)); + lane_chs += 1; + if (lane_chs >= info->channels) + break; + } + + pr_info("%s, lane mask:0x%x, channels:%d, channels mask:0x%x, bypass:%d\n", + __func__, + info->lane_masks, + info->channels, + ch_mask, + info->bypass); aml_pdm_write(PDM_CLKG_CTRL, 1); @@ -96,7 +121,7 @@ void aml_pdm_ctrl( /* bypass mode. * 1: bypass all filter. 0: normal mode. */ - (0 << 28) | + (info->bypass << 28) | /* PDM channel reset. */ (ch_mask << 8) | /* PDM channel enable */ @@ -462,3 +487,24 @@ void pdm_init_truncate_data(int freq) aml_pdm_write(PDM_MASK_NUM, mask_val); } + +void pdm_train_en(bool en) +{ + aml_pdm_update_bits(PDM_CTRL, + 0x1 << 19, + en << 19); +} + +void pdm_train_clr(void) +{ + aml_pdm_update_bits(PDM_CTRL, + 0x1 << 18, + 0x1 << 18); +} + +int pdm_train_sts(void) +{ + int val = aml_pdm_read(PDM_STS); + + return ((val >> 4) & 0xff); +} diff --git a/sound/soc/amlogic/auge/pdm_hw.h b/sound/soc/amlogic/auge/pdm_hw.h index b7d19c025c71..b1d8424e8e7a 100644 --- a/sound/soc/amlogic/auge/pdm_hw.h +++ b/sound/soc/amlogic/auge/pdm_hw.h @@ -19,9 +19,19 @@ #define __AML_PDM_HW_H__ #include "audio_io.h" -extern void aml_pdm_ctrl( - struct aml_audio_controller *actrl, - int bitdepth, int channels); +#define PDM_CHANNELS_MAX 8 /* 8ch pdm in */ +#define PDM_LANE_MAX 4 /* 4 data pins, for 8ch maxs*/ + +struct pdm_info { + int bitdepth; + int channels; + int lane_masks; + + int dclk_idx; /* mapping for dclk value */ + int bypass; /* bypass all filter, capture raw data */ +}; + +extern void aml_pdm_ctrl(struct pdm_info *info); extern void aml_pdm_arb_config(struct aml_audio_controller *actrl); @@ -40,6 +50,10 @@ extern void pdm_set_mute_channel(int mute_chmask); extern void pdm_init_truncate_data(int freq); +extern void pdm_train_en(bool en); +extern void pdm_train_clr(void); +extern int pdm_train_sts(void); + extern int pdm_hcic_shift_gain; extern int pdm_dclk; diff --git a/sound/soc/amlogic/auge/pdm_match_table.c b/sound/soc/amlogic/auge/pdm_match_table.c new file mode 100644 index 000000000000..27ce1dd6b5e5 --- /dev/null +++ b/sound/soc/amlogic/auge/pdm_match_table.c @@ -0,0 +1,63 @@ +/* + * sound/soc/amlogic/auge/pdm_match_table.c + * + * Copyright (C) 2019 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. + * + */ + +static struct pdm_chipinfo g12a_pdm_chipinfo = { + .mute_fn = true, + .truncate_data = false, +}; + +static struct pdm_chipinfo tl1_pdm_chipinfo = { + .mute_fn = true, + .truncate_data = false, +}; + +static struct pdm_chipinfo sm1_pdm_chipinfo = { + .mute_fn = true, + .truncate_data = false, + .train = true, +}; + +static struct pdm_chipinfo tm2_pdm_chipinfo = { + .mute_fn = true, + .truncate_data = false, + .train = true, +}; + +static const struct of_device_id aml_pdm_device_id[] = { + { + .compatible = "amlogic, axg-snd-pdm", + }, + { + .compatible = "amlogic, g12a-snd-pdm", + .data = &g12a_pdm_chipinfo, + }, + { + .compatible = "amlogic, tl1-snd-pdm", + .data = &tl1_pdm_chipinfo, + }, + { + .compatible = "amlogic, sm1-snd-pdm", + .data = &sm1_pdm_chipinfo, + }, + { + .compatible = "amlogic, tm2-snd-pdm", + .data = &tm2_pdm_chipinfo, + }, + + {} +}; +MODULE_DEVICE_TABLE(of, aml_pdm_device_id); diff --git a/sound/soc/amlogic/auge/regs.h b/sound/soc/amlogic/auge/regs.h index 7bf3d4ed5690..2a97ec10431b 100644 --- a/sound/soc/amlogic/auge/regs.h +++ b/sound/soc/amlogic/auge/regs.h @@ -108,6 +108,10 @@ enum clk_sel { #define EE_AUDIO_CLK_SPDIFIN_LB_CTRL 0x02f #define EE_AUDIO_CLK_EQDRC_CTRL0 0x030 #define EE_AUDIO_VAD_CLK_CTRL 0x031 +#define EE_AUDIO_EARCTX_CMDC_CLK_CTRL 0x032 +#define EE_AUDIO_EARCTX_DMAC_CLK_CTRL 0x033 +#define EE_AUDIO_EARCRX_CMDC_CLK_CTRL 0x034 +#define EE_AUDIO_EARCRX_DMAC_CLK_CTRL 0x035 /* * AUDIO TODDR @@ -204,56 +208,93 @@ enum clk_sel { #define EE_AUDIO_LB_STS 0x0b6 #define EE_AUDIO_TDMIN_A_CTRL 0x0c0 -#define EE_AUDIO_TDMIN_A_SWAP 0x0c1 +#define EE_AUDIO_TDMIN_A_SWAP0 0x0c1 +#define EE_AUDIO_TDMIN_A_SWAP1 0x260 #define EE_AUDIO_TDMIN_A_MASK0 0x0c2 #define EE_AUDIO_TDMIN_A_MASK1 0x0c3 #define EE_AUDIO_TDMIN_A_MASK2 0x0c4 #define EE_AUDIO_TDMIN_A_MASK3 0x0c5 +#define EE_AUDIO_TDMIN_A_MASK4 0x261 +#define EE_AUDIO_TDMIN_A_MASK5 0x262 +#define EE_AUDIO_TDMIN_A_MASK6 0x263 +#define EE_AUDIO_TDMIN_A_MASK7 0x264 #define EE_AUDIO_TDMIN_A_STAT 0x0c6 #define EE_AUDIO_TDMIN_A_MUTE_VAL 0x0c7 #define EE_AUDIO_TDMIN_A_MUTE0 0x0c8 #define EE_AUDIO_TDMIN_A_MUTE1 0x0c9 #define EE_AUDIO_TDMIN_A_MUTE2 0x0ca #define EE_AUDIO_TDMIN_A_MUTE3 0x0cb +#define EE_AUDIO_TDMIN_A_MUTE4 0x265 +#define EE_AUDIO_TDMIN_A_MUTE5 0x266 +#define EE_AUDIO_TDMIN_A_MUTE6 0x267 +#define EE_AUDIO_TDMIN_A_MUTE7 0x268 #define EE_AUDIO_TDMIN_B_CTRL 0x0d0 -#define EE_AUDIO_TDMIN_B_SWAP 0x0d1 +#define EE_AUDIO_TDMIN_B_SWAP0 0x0d1 +#define EE_AUDIO_TDMIN_B_SWAP1 0x270 #define EE_AUDIO_TDMIN_B_MASK0 0x0d2 #define EE_AUDIO_TDMIN_B_MASK1 0x0d3 #define EE_AUDIO_TDMIN_B_MASK2 0x0d4 #define EE_AUDIO_TDMIN_B_MASK3 0x0d5 +#define EE_AUDIO_TDMIN_B_MASK4 0x271 +#define EE_AUDIO_TDMIN_B_MASK5 0x272 +#define EE_AUDIO_TDMIN_B_MASK6 0x273 +#define EE_AUDIO_TDMIN_B_MASK7 0x274 #define EE_AUDIO_TDMIN_B_STAT 0x0d6 #define EE_AUDIO_TDMIN_B_MUTE_VAL 0x0d7 #define EE_AUDIO_TDMIN_B_MUTE0 0x0d8 #define EE_AUDIO_TDMIN_B_MUTE1 0x0d9 #define EE_AUDIO_TDMIN_B_MUTE2 0x0da #define EE_AUDIO_TDMIN_B_MUTE3 0x0db +#define EE_AUDIO_TDMIN_B_MUTE4 0x275 +#define EE_AUDIO_TDMIN_B_MUTE5 0x276 +#define EE_AUDIO_TDMIN_B_MUTE6 0x277 +#define EE_AUDIO_TDMIN_B_MUTE7 0x278 #define EE_AUDIO_TDMIN_C_CTRL 0x0e0 +#define EE_AUDIO_TDMIN_C_SWAP0 0x0e1 +#define EE_AUDIO_TDMIN_C_SWAP1 0x280 #define EE_AUDIO_TDMIN_C_SWAP 0x0e1 #define EE_AUDIO_TDMIN_C_MASK0 0x0e2 #define EE_AUDIO_TDMIN_C_MASK1 0x0e3 #define EE_AUDIO_TDMIN_C_MASK2 0x0e4 #define EE_AUDIO_TDMIN_C_MASK3 0x0e5 +#define EE_AUDIO_TDMIN_C_MASK4 0x281 +#define EE_AUDIO_TDMIN_C_MASK5 0x282 +#define EE_AUDIO_TDMIN_C_MASK6 0x283 +#define EE_AUDIO_TDMIN_C_MASK7 0x284 #define EE_AUDIO_TDMIN_C_STAT 0x0e6 #define EE_AUDIO_TDMIN_C_MUTE_VAL 0x0e7 #define EE_AUDIO_TDMIN_C_MUTE0 0x0e8 #define EE_AUDIO_TDMIN_C_MUTE1 0x0e9 #define EE_AUDIO_TDMIN_C_MUTE2 0x0ea #define EE_AUDIO_TDMIN_C_MUTE3 0x0eb +#define EE_AUDIO_TDMIN_C_MUTE4 0x285 +#define EE_AUDIO_TDMIN_C_MUTE5 0x286 +#define EE_AUDIO_TDMIN_C_MUTE6 0x287 +#define EE_AUDIO_TDMIN_C_MUTE7 0x288 #define EE_AUDIO_TDMIN_LB_CTRL 0x0f0 -#define EE_AUDIO_TDMIN_LB_SWAP 0x0f1 +#define EE_AUDIO_TDMIN_LB_SWAP0 0x0f1 +#define EE_AUDIO_TDMIN_LB_SWAP1 0x290 #define EE_AUDIO_TDMIN_LB_MASK0 0x0f2 #define EE_AUDIO_TDMIN_LB_MASK1 0x0f3 #define EE_AUDIO_TDMIN_LB_MASK2 0x0f4 #define EE_AUDIO_TDMIN_LB_MASK3 0x0f5 +#define EE_AUDIO_TDMIN_LB_MASK4 0x291 +#define EE_AUDIO_TDMIN_LB_MASK5 0x292 +#define EE_AUDIO_TDMIN_LB_MASK6 0x293 +#define EE_AUDIO_TDMIN_LB_MASK7 0x294 #define EE_AUDIO_TDMIN_LB_STAT 0x0f6 #define EE_AUDIO_TDMIN_LB_MUTE_VAL 0x0f7 #define EE_AUDIO_TDMIN_LB_MUTE0 0x0f8 #define EE_AUDIO_TDMIN_LB_MUTE1 0x0f9 #define EE_AUDIO_TDMIN_LB_MUTE2 0x0fa #define EE_AUDIO_TDMIN_LB_MUTE3 0x0fb +#define EE_AUDIO_TDMIN_LB_MUTE4 0x295 +#define EE_AUDIO_TDMIN_LB_MUTE5 0x296 +#define EE_AUDIO_TDMIN_LB_MUTE6 0x297 +#define EE_AUDIO_TDMIN_LB_MUTE7 0x298 /* * AUDIO OUTPUT @@ -315,53 +356,89 @@ enum clk_sel { #define EE_AUDIO_TDMOUT_A_CTRL0 0x140 #define EE_AUDIO_TDMOUT_A_CTRL1 0x141 -#define EE_AUDIO_TDMOUT_A_SWAP 0x142 +#define EE_AUDIO_TDMOUT_A_CTRL2 0x2a0 +#define EE_AUDIO_TDMOUT_A_SWAP0 0x142 +#define EE_AUDIO_TDMOUT_A_SWAP1 0x2a1 #define EE_AUDIO_TDMOUT_A_MASK0 0x143 #define EE_AUDIO_TDMOUT_A_MASK1 0x144 #define EE_AUDIO_TDMOUT_A_MASK2 0x145 #define EE_AUDIO_TDMOUT_A_MASK3 0x146 +#define EE_AUDIO_TDMOUT_A_MASK4 0x2a4 +#define EE_AUDIO_TDMOUT_A_MASK5 0x2a5 +#define EE_AUDIO_TDMOUT_A_MASK6 0x2a6 +#define EE_AUDIO_TDMOUT_A_MASK7 0x2a7 #define EE_AUDIO_TDMOUT_A_STAT 0x147 #define EE_AUDIO_TDMOUT_A_GAIN0 0x148 #define EE_AUDIO_TDMOUT_A_GAIN1 0x149 +#define EE_AUDIO_TDMOUT_A_GAIN2 0x2a2 +#define EE_AUDIO_TDMOUT_A_GAIN3 0x2a3 #define EE_AUDIO_TDMOUT_A_MUTE_VAL 0x14a #define EE_AUDIO_TDMOUT_A_MUTE0 0x14b #define EE_AUDIO_TDMOUT_A_MUTE1 0x14c #define EE_AUDIO_TDMOUT_A_MUTE2 0x14d #define EE_AUDIO_TDMOUT_A_MUTE3 0x14e +#define EE_AUDIO_TDMOUT_A_MUTE4 0x2a8 +#define EE_AUDIO_TDMOUT_A_MUTE5 0x2a9 +#define EE_AUDIO_TDMOUT_A_MUTE6 0x2aa +#define EE_AUDIO_TDMOUT_A_MUTE7 0x2ab #define EE_AUDIO_TDMOUT_A_MASK_VAL 0x14f #define EE_AUDIO_TDMOUT_B_CTRL0 0x150 #define EE_AUDIO_TDMOUT_B_CTRL1 0x151 -#define EE_AUDIO_TDMOUT_B_SWAP 0x152 +#define EE_AUDIO_TDMOUT_B_CTRL2 0x2b0 +#define EE_AUDIO_TDMOUT_B_SWAP0 0x152 +#define EE_AUDIO_TDMOUT_B_SWAP1 0x2b1 #define EE_AUDIO_TDMOUT_B_MASK0 0x153 #define EE_AUDIO_TDMOUT_B_MASK1 0x154 #define EE_AUDIO_TDMOUT_B_MASK2 0x155 #define EE_AUDIO_TDMOUT_B_MASK3 0x156 +#define EE_AUDIO_TDMOUT_B_MASK4 0x2b4 +#define EE_AUDIO_TDMOUT_B_MASK5 0x2b5 +#define EE_AUDIO_TDMOUT_B_MASK6 0x2b6 +#define EE_AUDIO_TDMOUT_B_MASK7 0x2b7 #define EE_AUDIO_TDMOUT_B_STAT 0x157 #define EE_AUDIO_TDMOUT_B_GAIN0 0x158 #define EE_AUDIO_TDMOUT_B_GAIN1 0x159 +#define EE_AUDIO_TDMOUT_B_GAIN2 0x2b2 +#define EE_AUDIO_TDMOUT_B_GAIN3 0x2b3 #define EE_AUDIO_TDMOUT_B_MUTE_VAL 0x15a #define EE_AUDIO_TDMOUT_B_MUTE0 0x15b #define EE_AUDIO_TDMOUT_B_MUTE1 0x15c #define EE_AUDIO_TDMOUT_B_MUTE2 0x15d #define EE_AUDIO_TDMOUT_B_MUTE3 0x15e +#define EE_AUDIO_TDMOUT_B_MUTE4 0x2b8 +#define EE_AUDIO_TDMOUT_B_MUTE5 0x2b9 +#define EE_AUDIO_TDMOUT_B_MUTE6 0x2ba +#define EE_AUDIO_TDMOUT_B_MUTE7 0x2bb #define EE_AUDIO_TDMOUT_B_MASK_VAL 0x15f #define EE_AUDIO_TDMOUT_C_CTRL0 0x160 #define EE_AUDIO_TDMOUT_C_CTRL1 0x161 -#define EE_AUDIO_TDMOUT_C_SWAP 0x162 +#define EE_AUDIO_TDMOUT_C_CTRL2 0x2c0 +#define EE_AUDIO_TDMOUT_C_SWAP0 0x162 +#define EE_AUDIO_TDMOUT_C_SWAP1 0x2c1 #define EE_AUDIO_TDMOUT_C_MASK0 0x163 #define EE_AUDIO_TDMOUT_C_MASK1 0x164 #define EE_AUDIO_TDMOUT_C_MASK2 0x165 #define EE_AUDIO_TDMOUT_C_MASK3 0x166 +#define EE_AUDIO_TDMOUT_C_MASK4 0x2c4 +#define EE_AUDIO_TDMOUT_C_MASK5 0x2c5 +#define EE_AUDIO_TDMOUT_C_MASK6 0x2c6 +#define EE_AUDIO_TDMOUT_C_MASK7 0x2c7 #define EE_AUDIO_TDMOUT_C_STAT 0x167 #define EE_AUDIO_TDMOUT_C_GAIN0 0x168 #define EE_AUDIO_TDMOUT_C_GAIN1 0x169 +#define EE_AUDIO_TDMOUT_C_GAIN2 0x2c2 +#define EE_AUDIO_TDMOUT_C_GAIN3 0x2c3 #define EE_AUDIO_TDMOUT_C_MUTE_VAL 0x16a #define EE_AUDIO_TDMOUT_C_MUTE0 0x16b #define EE_AUDIO_TDMOUT_C_MUTE1 0x16c #define EE_AUDIO_TDMOUT_C_MUTE2 0x16d #define EE_AUDIO_TDMOUT_C_MUTE3 0x16e +#define EE_AUDIO_TDMOUT_C_MUTE4 0x2c8 +#define EE_AUDIO_TDMOUT_C_MUTE5 0x2c9 +#define EE_AUDIO_TDMOUT_C_MUTE6 0x2ca +#define EE_AUDIO_TDMOUT_C_MUTE7 0x2cb #define EE_AUDIO_TDMOUT_C_MASK_VAL 0x16f /* @@ -847,4 +924,184 @@ enum clk_sel { #define VAD_IN_SEL1 0x030 #define VAD_TO_DDR 0x031 +/* + * eARC + */ +/* eARC RX CMDC */ +#define EARC_RX_CMDC_TOP_CTRL0 0x000 +#define EARC_RX_CMDC_TOP_CTRL1 0x001 +#define EARC_RX_CMDC_TOP_CTRL2 0x002 +#define EARC_RX_CMDC_TIMER_CTRL0 0x003 +#define EARC_RX_CMDC_TIMER_CTRL1 0x004 +#define EARC_RX_CMDC_TIMER_CTRL2 0x005 +#define EARC_RX_CMDC_TIMER_CTRL3 0x006 +#define EARC_RX_CMDC_VSM_CTRL0 0x007 +#define EARC_RX_CMDC_VSM_CTRL1 0x008 +#define EARC_RX_CMDC_VSM_CTRL2 0x009 +#define EARC_RX_CMDC_VSM_CTRL3 0x00a +#define EARC_RX_CMDC_VSM_CTRL4 0x00b +#define EARC_RX_CMDC_VSM_CTRL5 0x00c +#define EARC_RX_CMDC_VSM_CTRL6 0x00d +#define EARC_RX_CMDC_VSM_CTRL7 0x00e +#define EARC_RX_CMDC_VSM_CTRL8 0x00f +#define EARC_RX_CMDC_VSM_CTRL9 0x010 +#define EARC_RX_CMDC_SENDER_CTRL0 0x011 +#define EARC_RX_CMDC_PACKET_CTRL0 0x012 +#define EARC_RX_CMDC_PACKET_CTRL1 0x013 +#define EARC_RX_CMDC_PACKET_CTRL2 0x014 +#define EARC_RX_CMDC_PACKET_CTRL3 0x015 +#define EARC_RX_CMDC_PACKET_CTRL4 0x016 +#define EARC_RX_CMDC_PACKET_CTRL5 0x017 +#define EARC_RX_CMDC_PACKET_CTRL6 0x018 +#define EARC_RX_CMDC_BIPHASE_CTRL0 0x019 +#define EARC_RX_CMDC_BIPHASE_CTRL1 0x01a +#define EARC_RX_CMDC_BIPHASE_CTRL2 0x01b +#define EARC_RX_CMDC_BIPHASE_CTRL3 0x01c +#define EARC_RX_CMDC_DEVICE_ID_CTRL 0x01d +#define EARC_RX_CMDC_DEVICE_WDATA 0x01e +#define EARC_RX_CMDC_DEVICE_RDATA 0x01f +#define EARC_RX_ANA_CTRL0 0x020 +#define EARC_RX_ANA_CTRL1 0x021 +#define EARC_RX_ANA_CTRL2 0x022 +#define EARC_RX_ANA_CTRL3 0x023 +#define EARC_RX_ANA_CTRL4 0x024 +#define EARC_RX_ANA_CTRL5 0x025 +#define EARC_RX_ANA_STAT0 0x026 +#define EARC_RX_CMDC_STATUS0 0x027 +#define EARC_RX_CMDC_STATUS1 0x028 +#define EARC_RX_CMDC_STATUS2 0x029 +#define EARC_RX_CMDC_STATUS3 0x02a +#define EARC_RX_CMDC_STATUS4 0x02b +#define EARC_RX_CMDC_STATUS5 0x02c +#define EARC_RX_CMDC_STATUS6 0x02d +/* eARC TX CMDC */ +#define EARC_TX_CMDC_TOP_CTRL0 0x030 +#define EARC_TX_CMDC_TOP_CTRL1 0x031 +#define EARC_TX_CMDC_TOP_CTRL2 0x032 +#define EARC_TX_CMDC_TIMER_CTRL0 0x033 +#define EARC_TX_CMDC_TIMER_CTRL1 0x034 +#define EARC_TX_CMDC_TIMER_CTRL2 0x035 +#define EARC_TX_CMDC_TIMER_CTRL3 0x036 +#define EARC_TX_CMDC_VSM_CTRL0 0x037 +#define EARC_TX_CMDC_VSM_CTRL1 0x038 +#define EARC_TX_CMDC_VSM_CTRL2 0x039 +#define EARC_TX_CMDC_VSM_CTRL3 0x03a +#define EARC_TX_CMDC_VSM_CTRL4 0x03b +#define EARC_TX_CMDC_VSM_CTRL5 0x03c +#define EARC_TX_CMDC_VSM_CTRL6 0x03d +#define EARC_TX_CMDC_VSM_CTRL7 0x03e +#define EARC_TX_CMDC_VSM_CTRL8 0x03f +#define EARC_TX_CMDC_VSM_CTRL9 0x041 +#define EARC_TX_CMDC_SENDER_CTRL0 0x042 +#define EARC_TX_CMDC_PACKET_CTRL0 0x043 +#define EARC_TX_CMDC_PACKET_CTRL1 0x044 +#define EARC_TX_CMDC_PACKET_CTRL2 0x045 +#define EARC_TX_CMDC_PACKET_CTRL3 0x046 +#define EARC_TX_CMDC_PACKET_CTRL4 0x047 +#define EARC_TX_CMDC_PACKET_CTRL5 0x048 +#define EARC_TX_CMDC_PACKET_CTRL6 0x049 +#define EARC_TX_CMDC_BIPHASE_CTRL0 0x04a +#define EARC_TX_CMDC_BIPHASE_CTRL1 0x04b +#define EARC_TX_CMDC_BIPHASE_CTRL2 0x04c +#define EARC_TX_CMDC_BIPHASE_CTRL3 0x04d +#define EARC_TX_CMDC_DEVICE_ID_CTRL 0x04e +#define EARC_TX_CMDC_DEVICE_WDATA 0x04f +#define EARC_TX_CMDC_DEVICE_RDATA 0x050 +#define EARC_TX_CMDC_MASTER_CTRL 0x051 +#define EARC_TX_ANA_CTRL0 0x052 +#define EARC_TX_ANA_CTRL1 0x053 +#define EARC_TX_ANA_CTRL2 0x054 +#define EARC_TX_ANA_CTRL3 0x055 +#define EARC_TX_ANA_CTRL4 0x056 +#define EARC_TX_ANA_CTRL5 0x057 +#define EARC_TX_ANA_STAT0 0x058 +#define EARC_TX_CMDC_STATUS0 0x059 +#define EARC_TX_CMDC_STATUS1 0x05a +#define EARC_TX_CMDC_STATUS2 0x05b +#define EARC_TX_CMDC_STATUS3 0x05c +#define EARC_TX_CMDC_STATUS4 0x05d +#define EARC_TX_CMDC_STATUS5 0x05e +#define EARC_TX_CMDC_STATUS6 0x05f +/* eARC RX DMAC */ +#define EARCRX_DMAC_TOP_CTRL0 0x000 +#define EARCRX_DMAC_SYNC_CTRL0 0x001 +#define EARCRX_DMAC_SYNC_STAT0 0x002 +#define EARCRX_SPDIFIN_SAMPLE_CTRL0 0x003 +#define EARCRX_SPDIFIN_SAMPLE_CTRL1 0x004 +#define EARCRX_SPDIFIN_SAMPLE_CTRL2 0x005 +#define EARCRX_SPDIFIN_SAMPLE_CTRL3 0x006 +#define EARCRX_SPDIFIN_SAMPLE_CTRL4 0x007 +#define EARCRX_SPDIFIN_SAMPLE_CTRL5 0x008 +#define EARCRX_SPDIFIN_SAMPLE_STAT0 0x009 +#define EARCRX_SPDIFIN_SAMPLE_STAT1 0x00a +#define EARCRX_SPDIFIN_MUTE_VAL 0x00b +#define EARCRX_SPDIFIN_CTRL0 0x00c +#define EARCRX_SPDIFIN_CTRL1 0x00d +#define EARCRX_SPDIFIN_CTRL2 0x00e +#define EARCRX_SPDIFIN_CTRL3 0x00f +#define EARCRX_SPDIFIN_STAT0 0x010 +#define EARCRX_SPDIFIN_STAT1 0x011 +#define EARCRX_SPDIFIN_STAT2 0x012 +#define EARCRX_DMAC_UBIT_CTRL0 0x013 +#define EARCRX_IU_RDATA 0x014 +#define EARCRX_DMAC_UBIT_STAT0 0x015 +#define EARCRX_ERR_CORRECT_CTRL0 0x016 +#define EARCRX_ERR_CORRECT_STAT0 0x017 +#define EARCRX_ANA_RST_CTRL0 0x018 +#define EARCRX_ANA_RST_CTRL1 0x019 +/* eARC TX DMAC */ +#define EARCTX_DMAC_TOP_CTRL0 0x000 +#define EARCTX_MUTE_VAL 0x001 +#define EARCTX_SPDIFOUT_GAIN0 0x002 +#define EARCTX_SPDIFOUT_GAIN1 0x003 +#define EARCTX_SPDIFOUT_CTRL0 0x004 +#define EARCTX_SPDIFOUT_CTRL1 0x005 +#define EARCTX_SPDIFOUT_PREAMB 0x006 +#define EARCTX_SPDIFOUT_SWAP 0x007 +#define EARCTX_ERR_CORRT_CTRL0 0x008 +#define EARCTX_ERR_CORRT_CTRL1 0x009 +#define EARCTX_ERR_CORRT_CTRL2 0x00a +#define EARCTX_ERR_CORRT_CTRL3 0x00b +#define EARCTX_ERR_CORRT_CTRL4 0x00c +#define EARCTX_ERR_CORRT_STAT0 0x00d +#define EARCTX_SPDIFOUT_CHSTS0 0x00e +#define EARCTX_SPDIFOUT_CHSTS1 0x00f +#define EARCTX_SPDIFOUT_CHSTS2 0x010 +#define EARCTX_SPDIFOUT_CHSTS3 0x011 +#define EARCTX_SPDIFOUT_CHSTS4 0x012 +#define EARCTX_SPDIFOUT_CHSTS5 0x013 +#define EARCTX_SPDIFOUT_CHSTS6 0x014 +#define EARCTX_SPDIFOUT_CHSTS7 0x015 +#define EARCTX_SPDIFOUT_CHSTS8 0x016 +#define EARCTX_SPDIFOUT_CHSTS9 0x017 +#define EARCTX_SPDIFOUT_CHSTSA 0x018 +#define EARCTX_SPDIFOUT_CHSTSB 0x019 +#define EARCTX_FE_CTRL0 0x01a +#define EARCTX_FE_STAT0 0x01b +#define EARCTX_SPDIFOUT_STAT 0x01c +/* eARC RX */ +#define EARCRX_TOP_CTRL0 0x000 +#define EARCRX_DMAC_INT_MASK 0x001 +#define EARCRX_DMAC_INT_PENDING 0x002 +#define EARCRX_CMDC_INT_MASK 0x003 +#define EARCRX_CMDC_INT_PENDING 0x004 +#define EARCRX_ANA_CTRL0 0x005 +#define EARCRX_ANA_CTRL1 0x006 +#define EARCRX_ANA_STAT0 0x007 +#define EARCRX_PLL_CTRL0 0x008 +#define EARCRX_PLL_CTRL1 0x009 +#define EARCRX_PLL_CTRL2 0x00a +#define EARCRX_PLL_CTRL3 0x00b +#define EARCRX_PLL_STAT0 0x00c +/* eARC TX */ +#define EARCTX_TOP_CTRL0 0x000 +#define EARCTX_DMAC_INT_MASK 0x001 +#define EARCTX_DMAC_INT_PENDING 0x002 +#define EARCTX_CMDC_INT_MASK 0x003 +#define EARCTX_CMDC_INT_PENDING 0x004 +#define EARCTX_ANA_CTRL0 0x005 +#define EARCTX_ANA_CTRL1 0x006 +#define EARCTX_ANA_CTRL2 0x007 +#define EARCTX_ANA_STAT0 0x008 + #endif diff --git a/sound/soc/amlogic/auge/resample.c b/sound/soc/amlogic/auge/resample.c index 7c56eb1cc200..f3a99483eec3 100644 --- a/sound/soc/amlogic/auge/resample.c +++ b/sound/soc/amlogic/auge/resample.c @@ -27,8 +27,6 @@ #include #include "resample.h" -#include "resample_hw.h" -#include "ddr_mngr.h" #include "regs.h" #include "iomap.h" @@ -38,12 +36,12 @@ /*#define __PTM_RESAMPLE_CLK__*/ -#define RESAMPLE_A 0 -#define RESAMPLE_B 1 +//#define RESAMPLE_A 0 +//#define RESAMPLE_B 1 struct resample_chipinfo { int num; /* support resample a/b */ - int id; + enum resample_idx id; bool dividor_fn; }; @@ -60,15 +58,15 @@ struct audioresample { struct resample_chipinfo *chipinfo; - int id; + enum resample_idx id; /*which module should be resampled */ - int resample_module; + enum toddr_src resample_module; /* resample to the rate */ int out_rate; /* sync with auge_resample_texts */ - int asrc_rate_idx; + enum samplerate_index asrc_rate_idx; bool enable; }; @@ -77,11 +75,11 @@ struct audioresample *s_resample_a; struct audioresample *s_resample_b; -static struct audioresample *get_audioresample(int id) +struct audioresample *get_audioresample(enum resample_idx id) { struct audioresample *p_resample; - p_resample = ((id == 0) ? s_resample_a : s_resample_b); + p_resample = ((id == RESAMPLE_A) ? s_resample_a : s_resample_b); if (!p_resample) { pr_debug("Not init audio resample\n"); @@ -93,7 +91,7 @@ static struct audioresample *get_audioresample(int id) int get_resample_module_num(void) { - struct audioresample *p_resample = get_audioresample(0); + struct audioresample *p_resample = get_audioresample(RESAMPLE_A); if (p_resample && p_resample->chipinfo) return p_resample->chipinfo->num; @@ -101,6 +99,32 @@ int get_resample_module_num(void) return 1; } +int set_resample_source(enum resample_idx id, enum toddr_src src) +{ + struct audioresample *p_resample = get_audioresample(id); + (void)p_resample; + (void)src; + //p_resample->resample_module = src; + return 0; +} + +static int set_resample_rate_index( + enum resample_idx id, enum samplerate_index index) +{ + struct audioresample *p_resample = get_audioresample(id); + + p_resample->asrc_rate_idx = index; + return 0; +} + +static enum samplerate_index get_resample_rate_index( + enum resample_idx id) +{ + struct audioresample *p_resample = get_audioresample(id); + + return p_resample->asrc_rate_idx; +} + static int resample_clk_set(struct audioresample *p_resample) { int ret = 0; @@ -126,7 +150,7 @@ static int resample_clk_set(struct audioresample *p_resample) clk_set_rate(p_resample->sclk, 48000 * CLK_RATIO); clk_set_rate(p_resample->clk, 48000 * CLK_RATIO); } - +#if 0 ret = clk_prepare_enable(p_resample->pll); if (ret) { pr_err("Can't enable pll clock: %d\n", ret); @@ -146,6 +170,7 @@ static int resample_clk_set(struct audioresample *p_resample) ret); return -EINVAL; } +#endif pr_info("%s, resample_pll:%lu, sclk:%lu, clk:%lu\n", __func__, @@ -153,9 +178,11 @@ static int resample_clk_set(struct audioresample *p_resample) clk_get_rate(p_resample->sclk), clk_get_rate(p_resample->clk)); } else { +#if 0 clk_disable_unprepare(p_resample->clk); clk_disable_unprepare(p_resample->sclk); clk_disable_unprepare(p_resample->pll); +#endif } return ret; @@ -194,25 +221,25 @@ static const char *const auge_resample_texts[] = { "Enable:192K", }; -static int resample_idx2rate(int index) +static int resample_idx2rate(enum samplerate_index index) { int rate = 0; - if (index == 0) + if (index == RATE_OFF) rate = 0; - else if (index == 1) + else if (index == RATE_32K) rate = 32000; - else if (index == 2) + else if (index == RATE_44K) rate = 44100; - else if (index == 3) + else if (index == RATE_48K) rate = 48000; - else if (index == 4) + else if (index == RATE_88K) rate = 88200; - else if (index == 5) + else if (index == RATE_96K) rate = 96000; - else if (index == 6) + else if (index == RATE_176K) rate = 176400; - else if (index == 7) + else if (index == RATE_192K) rate = 192000; return rate; @@ -238,38 +265,52 @@ static int resample_get_enum( return 0; } -int resample_set(int id, int index) +int resample_set(enum resample_idx id, enum samplerate_index index) { - int resample_rate = resample_idx2rate(index); + int resample_rate = 0; struct audioresample *p_resample = get_audioresample(id); + int ret = 0; if (!p_resample) return 0; + pr_info("%s resample_%c to %s, last %s\n", + __func__, + (id == RESAMPLE_A) ? 'a' : 'b', + auge_resample_texts[index], + auge_resample_texts[p_resample->asrc_rate_idx]); + +#if 0 if (index == p_resample->asrc_rate_idx) return 0; - +#endif p_resample->asrc_rate_idx = index; - pr_info("%s resample_%c %s\n", - __func__, - (id == 0) ? 'a' : 'b', - auge_resample_texts[index]); + resample_rate = resample_idx2rate(index); + ret = audio_resample_set(p_resample, (bool)index, resample_rate); + if (ret) + return ret; - if (audio_resample_set(p_resample, (bool)index, resample_rate)) - return 0; - - if ((index == 0) || (resample_rate == 0)) + if (index == RATE_OFF) resample_disable(p_resample->id); else { resample_init(p_resample->id, resample_rate); - resample_set_hw_param(p_resample->id, index - 1); + resample_set_hw_param(p_resample->id, index); } return 0; } +int resample_set_inner_rate(enum resample_idx id) +{ + enum samplerate_index index = get_resample_rate_index(id); + + pr_debug("%s() index %d\n", __func__, id); + + return resample_set(id, index); +} + static int resample_set_enum( struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) @@ -282,7 +323,8 @@ static int resample_set_enum( return 0; } - resample_set(p_resample->id, index); + set_resample_rate_index(p_resample->id, index); + resample_set_inner_rate(p_resample->id); return 0; } @@ -345,6 +387,10 @@ static const char *const auge_resample_module_texts[] = { "FRHDMIRX", /* from tl1 chipset*/ "LOOPBACK_B", "SPDIFIN_LB", + "RESERVED_0", + "RESERVED_1", + "RESERVED_2", + "RESERVED_3", "VAD", }; @@ -388,7 +434,6 @@ static int resample_module_set_enum( return 0; } - static const struct snd_kcontrol_new asrc_a_controls[] = { SOC_ENUM_EXT("Hardware resample enable", auge_resample_enum, @@ -399,7 +444,7 @@ static const struct snd_kcontrol_new asrc_a_controls[] = { mixer_audiobus_read, mixer_audiobus_write, NULL), SOC_SINGLE_EXT_TLV("Hw resample pause thd", - EE_AUDIO_RESAMPLEA_CTRL2, 0, 0xffffff, 0, + EE_AUDIO_RESAMPLEA_CTRL2, 11, 0x1fff, 0, mixer_audiobus_read, mixer_audiobus_write, NULL), SOC_ENUM_EXT("Hw resample module", @@ -418,7 +463,7 @@ static const struct snd_kcontrol_new asrc_b_controls[] = { mixer_audiobus_read, mixer_audiobus_write, NULL), SOC_SINGLE_EXT_TLV("Hw resample b pause thd", - EE_AUDIO_RESAMPLEB_CTRL2, 0, 0xffffff, 0, + EE_AUDIO_RESAMPLEB_CTRL2, 11, 0x1fff, 0, mixer_audiobus_read, mixer_audiobus_write, NULL), SOC_ENUM_EXT("Hw resample b module", @@ -566,6 +611,13 @@ static int resample_platform_probe(struct platform_device *pdev) return ret; } + ret = clk_prepare_enable(p_resample->clk); + if (ret) { + pr_err("Can't enable resample_clk clock: %d\n", + ret); + return ret; + } + p_resample->dev = dev; if (p_chipinfo && p_chipinfo->id == 1) diff --git a/sound/soc/amlogic/auge/resample.h b/sound/soc/amlogic/auge/resample.h index a86c8c0de831..b82aac34fc82 100644 --- a/sound/soc/amlogic/auge/resample.h +++ b/sound/soc/amlogic/auge/resample.h @@ -17,10 +17,18 @@ #ifndef __AML_AUDIO_RESAMPLE_H__ #define __AML_AUDIO_RESAMPLE_H__ +#include "resample_hw.h" + extern int card_add_resample_kcontrols(struct snd_soc_card *card); -extern int resample_set(int id, int index); +extern int resample_set(enum resample_idx id, enum samplerate_index index); extern int get_resample_module_num(void); +int set_resample_source(enum resample_idx id, enum toddr_src src); + +int resample_set_inner_rate(enum resample_idx id); + +struct audioresample *get_audioresample(enum resample_idx id); + #endif diff --git a/sound/soc/amlogic/auge/resample_hw.c b/sound/soc/amlogic/auge/resample_hw.c index 1722ce8eb82d..73c7dd32eef2 100644 --- a/sound/soc/amlogic/auge/resample_hw.c +++ b/sound/soc/amlogic/auge/resample_hw.c @@ -40,7 +40,7 @@ static u32 resample_coef_parameters_table[7][5] = { {0x00800000, 0x0, 0x0, 0x0, 0x0}, }; -void resample_enable(int id, bool enable) +void resample_enable(enum resample_idx id, bool enable) { int offset = EE_AUDIO_RESAMPLEB_CTRL0 - EE_AUDIO_RESAMPLEA_CTRL0; int reg = EE_AUDIO_RESAMPLEA_CTRL0 + offset * id; @@ -58,7 +58,7 @@ void resample_enable(int id, bool enable) enable << 28); } -int resample_init(int id, int input_sr) +int resample_init(enum resample_idx id, int input_sr) { u16 Avg_cnt_init = 0; unsigned int clk_rate = 167000000;//clk81; @@ -77,15 +77,15 @@ int resample_init(int id, int input_sr) Avg_cnt_init); audiobus_update_bits(reg, - 0x3 << 26 | 0x3ff << 16 | 0xffff << 0, + 0x3 << 26 | 0x3ff << 16 | 0xffff, 0x0 << 26 | /* method0 */ RESAMPLE_CNT_CONTROL << 16 | - Avg_cnt_init << 0); + Avg_cnt_init); return 0; } -int resample_disable(int id) +int resample_disable(enum resample_idx id) { int offset = EE_AUDIO_RESAMPLEB_CTRL0 - EE_AUDIO_RESAMPLEA_CTRL0; int reg = EE_AUDIO_RESAMPLEA_CTRL0 + offset * id; @@ -95,33 +95,39 @@ int resample_disable(int id) return 0; } -int resample_set_hw_param(int id, int index) +int resample_set_hw_param(enum resample_idx id, + enum samplerate_index rate_index) { int i, reg, offset; + if (rate_index < RATE_32K) { + pr_info("%s(), inval index %d", __func__, rate_index); + return -EINVAL; + } offset = EE_AUDIO_RESAMPLEB_COEF0 - EE_AUDIO_RESAMPLEA_COEF0; reg = EE_AUDIO_RESAMPLEA_COEF0 + offset * id; for (i = 0; i < 5; i++) { audiobus_write((reg + i), - resample_coef_parameters_table[index][i]); + resample_coef_parameters_table[rate_index - 1][i]); } offset = EE_AUDIO_RESAMPLEB_CTRL2 - EE_AUDIO_RESAMPLEA_CTRL2; reg = EE_AUDIO_RESAMPLEA_CTRL2 + offset * id; audiobus_update_bits(reg, 1 << 25, 1 << 25); + resample_set_hw_pause_thd(id, 128); return 0; } - +/* not avail for tl1 */ void resample_src_select(int src) { audiobus_update_bits(EE_AUDIO_RESAMPLEA_CTRL0, 0x3 << 29, src << 29); } - -void resample_src_select_ab(int id, int src) +/* for tl1 and after */ +void resample_src_select_ab(enum resample_idx id, enum toddr_src src) { int offset = EE_AUDIO_RESAMPLEB_CTRL3 - EE_AUDIO_RESAMPLEA_CTRL3; int reg = EE_AUDIO_RESAMPLEA_CTRL3 + offset * id; @@ -131,7 +137,7 @@ void resample_src_select_ab(int id, int src) src << 16); } -void resample_format_set(int id, int ch_num, int bits) +void resample_format_set(enum resample_idx id, int ch_num, int bits) { int offset = EE_AUDIO_RESAMPLEB_CTRL3 - EE_AUDIO_RESAMPLEA_CTRL3; int reg = EE_AUDIO_RESAMPLEA_CTRL3 + offset * id; @@ -140,7 +146,7 @@ void resample_format_set(int id, int ch_num, int bits) ch_num << 8 | (bits - 1) << 0); } -int resample_ctrl_read(int id) +int resample_ctrl_read(enum resample_idx id) { int offset = EE_AUDIO_RESAMPLEB_CTRL0 - EE_AUDIO_RESAMPLEA_CTRL0; int reg = EE_AUDIO_RESAMPLEA_CTRL0 + offset * id; @@ -148,10 +154,20 @@ int resample_ctrl_read(int id) return audiobus_read(reg); } -void resample_ctrl_write(int id, int value) +void resample_ctrl_write(enum resample_idx id, int value) { int offset = EE_AUDIO_RESAMPLEB_CTRL0 - EE_AUDIO_RESAMPLEA_CTRL0; int reg = EE_AUDIO_RESAMPLEA_CTRL0 + offset * id; audiobus_write(reg, value); } + +int resample_set_hw_pause_thd(enum resample_idx id, unsigned int thd) +{ + int offset = EE_AUDIO_RESAMPLEB_CTRL2 - EE_AUDIO_RESAMPLEA_CTRL2; + int reg = EE_AUDIO_RESAMPLEA_CTRL2 + offset * id; + + audiobus_write(reg, 1 << 24 | thd << 11); + + return 0; +} diff --git a/sound/soc/amlogic/auge/resample_hw.h b/sound/soc/amlogic/auge/resample_hw.h index 1ec4b16c871a..61b062921990 100644 --- a/sound/soc/amlogic/auge/resample_hw.h +++ b/sound/soc/amlogic/auge/resample_hw.h @@ -17,15 +17,30 @@ #ifndef __AML_AUDIO_RESAMPLE_HW_H__ #define __AML_AUDIO_RESAMPLE_HW_H__ -extern void resample_enable(int id, bool enable); -extern int resample_init(int id, int input_sr); -extern int resample_disable(int id); -extern int resample_set_hw_param(int id, int index); -extern void resample_src_select(int src); -extern void resample_src_select_ab(int id, int src); -extern void resample_format_set(int id, int ch_num, int bits); +#include "ddr_mngr.h" -extern int resample_ctrl_read(int id); -extern void resample_ctrl_write(int id, int value); +enum samplerate_index { + RATE_OFF, + RATE_32K, + RATE_44K, + RATE_48K, + RATE_88K, + RATE_96K, + RATE_176K, + RATE_192K, +}; + +extern void resample_enable(enum resample_idx id, bool enable); +extern int resample_init(enum resample_idx id, int input_sr); +extern int resample_disable(enum resample_idx id); +extern int resample_set_hw_param(enum resample_idx id, + enum samplerate_index rate_index); +extern void resample_src_select(int src); +extern void resample_src_select_ab(enum resample_idx id, enum toddr_src src); +extern void resample_format_set(enum resample_idx id, int ch_num, int bits); + +extern int resample_ctrl_read(enum resample_idx id); +extern void resample_ctrl_write(enum resample_idx id, int value); +int resample_set_hw_pause_thd(enum resample_idx id, unsigned int thd); #endif diff --git a/sound/soc/amlogic/auge/sharebuffer.c b/sound/soc/amlogic/auge/sharebuffer.c index f94fd2a03b0c..1a740c4a166a 100644 --- a/sound/soc/amlogic/auge/sharebuffer.c +++ b/sound/soc/amlogic/auge/sharebuffer.c @@ -24,7 +24,7 @@ #include "spdif_hw.h" static int sharebuffer_spdifout_prepare(struct snd_pcm_substream *substream, - struct frddr *fr, int spdif_id) + struct frddr *fr, int spdif_id, int lane_i2s) { struct snd_pcm_runtime *runtime = substream->runtime; int bit_depth; @@ -36,7 +36,8 @@ static int sharebuffer_spdifout_prepare(struct snd_pcm_substream *substream, aml_frddr_get_fifo_id(fr), bit_depth, runtime->channels, - true); + true, + lane_i2s); /* spdif to hdmitx */ spdifout_to_hdmitx_ctrl(spdif_id); @@ -63,12 +64,12 @@ static int sharebuffer_spdifout_free(struct snd_pcm_substream *substream, aml_frddr_get_fifo_id(fr), bit_depth, runtime->channels, - false); + false, 0); return 0; } -void sharebuffer_enable(int sel, bool enable) +void sharebuffer_enable(int sel, bool enable, bool reenable) { if (sel < 0) { pr_err("Not support same source\n"); @@ -77,12 +78,12 @@ void sharebuffer_enable(int sel, bool enable) // TODO: same with tdm } else if (sel < 5) { /* same source with spdif a/b */ - spdifout_enable(sel - 3, enable); + spdifout_enable(sel - 3, enable, reenable); } } int sharebuffer_prepare(struct snd_pcm_substream *substream, - void *pfrddr, int samesource_sel) + void *pfrddr, int samesource_sel, int lane_i2s) { struct frddr *fr = (struct frddr *)pfrddr; @@ -95,7 +96,7 @@ int sharebuffer_prepare(struct snd_pcm_substream *substream, } else if (samesource_sel < 5) { /* same source with spdif a/b */ sharebuffer_spdifout_prepare(substream, - fr, samesource_sel - 3); + fr, samesource_sel - 3, lane_i2s); } /* frddr, share buffer, src_sel1 */ @@ -127,18 +128,18 @@ int sharebuffer_free(struct snd_pcm_substream *substream, } -int sharebuffer_trigger(int cmd, int samesource_sel) +int sharebuffer_trigger(int cmd, int samesource_sel, bool reenable) { switch (cmd) { case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - sharebuffer_enable(samesource_sel, true); + sharebuffer_enable(samesource_sel, true, reenable); break; case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - sharebuffer_enable(samesource_sel, false); + sharebuffer_enable(samesource_sel, false, reenable); break; default: return -EINVAL; diff --git a/sound/soc/amlogic/auge/sharebuffer.h b/sound/soc/amlogic/auge/sharebuffer.h index 25dca7d09ef4..c8e39c591e6c 100644 --- a/sound/soc/amlogic/auge/sharebuffer.h +++ b/sound/soc/amlogic/auge/sharebuffer.h @@ -18,10 +18,10 @@ #define __AML_AUDIO_SHAREBUFFER_H__ extern int sharebuffer_prepare(struct snd_pcm_substream *substream, - void *pfrddr, int samesource_sel); + void *pfrddr, int samesource_sel, int lane_i2s); extern int sharebuffer_free(struct snd_pcm_substream *substream, void *pfrddr, int samesource_sel); -extern int sharebuffer_trigger(int cmd, int samesource_sel); +extern int sharebuffer_trigger(int cmd, int samesource_sel, bool reenable); extern void sharebuffer_get_mclk_fs_ratio(int samesource_sel, int *pll_mclk_ratio, int *mclk_fs_ratio); diff --git a/sound/soc/amlogic/auge/sm1,clocks.c b/sound/soc/amlogic/auge/sm1,clocks.c new file mode 100644 index 000000000000..6a234b2f3552 --- /dev/null +++ b/sound/soc/amlogic/auge/sm1,clocks.c @@ -0,0 +1,376 @@ +/* + * sound/soc/amlogic/auge/sm1,clocks.c + * + * Copyright (C) 2019 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. + * + */ +#undef pr_fmt +#define pr_fmt(fmt) "sm1_audio_clocks: " fmt + +#include + +#include "audio_clks.h" +#include "regs.h" + +static spinlock_t aclk_lock; + +static const char *const mclk_parent_names[] = { + "mpll0", "mpll1", "mpll2", "mpll3", "hifi_pll", + "fclk_div3", "fclk_div4", "fclk_div5"}; + +static const char *const audioclk_parent_names[] = { + "mclk_a", "mclk_b", "mclk_c", "mclk_d", "mclk_e", + "mclk_f", "i_slv_sclk_a", "i_slv_sclk_b", "i_slv_sclk_c", + "i_slv_sclk_d", "i_slv_sclk_e", "i_slv_sclk_f", "i_slv_sclk_g", + "i_slv_sclk_h", "i_slv_sclk_i", "i_slv_sclk_j"}; + +CLOCK_GATE(audio_ddr_arb, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 0); +CLOCK_GATE(audio_pdm, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 1); +CLOCK_GATE(audio_tdmina, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 2); +CLOCK_GATE(audio_tdminb, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 3); +CLOCK_GATE(audio_tdminc, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 4); +CLOCK_GATE(audio_tdminlb, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 5); +CLOCK_GATE(audio_tdmouta, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 6); +CLOCK_GATE(audio_tdmoutb, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 7); +CLOCK_GATE(audio_tdmoutc, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 8); +CLOCK_GATE(audio_frddra, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 9); +CLOCK_GATE(audio_frddrb, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 10); +CLOCK_GATE(audio_frddrc, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 11); +CLOCK_GATE(audio_toddra, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 12); +CLOCK_GATE(audio_toddrb, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 13); +CLOCK_GATE(audio_toddrc, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 14); +CLOCK_GATE(audio_loopbacka, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 15); +CLOCK_GATE(audio_spdifin, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 16); +CLOCK_GATE(audio_spdifout, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 17); +CLOCK_GATE(audio_resamplea, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 18); +CLOCK_GATE(audio_reserved0, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 19); +CLOCK_GATE(audio_toram, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 20); +CLOCK_GATE(audio_spdifoutb, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 21); +CLOCK_GATE(audio_eqdrc, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 22); +CLOCK_GATE(audio_reserved1, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 23); +CLOCK_GATE(audio_reserved2, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 24); +CLOCK_GATE(audio_reserved3, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 25); +CLOCK_GATE(audio_resampleb, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 26); +CLOCK_GATE(audio_tovad, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 27); +CLOCK_GATE(audio_audiolocker, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 28); +CLOCK_GATE(audio_spdifin_lb, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 29); +CLOCK_GATE(audio_reserved4, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 30); +CLOCK_GATE(audio_reserved5, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 31); + +CLOCK_GATE(audio_frddrd, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN1), 0); +CLOCK_GATE(audio_toddrd, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN1), 1); +CLOCK_GATE(audio_loopbackb, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN1), 2); +CLOCK_GATE(audio_earcrx, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN1), 6); + +static struct clk_gate *sm1_audio_clk_gates[] = { + &audio_ddr_arb, + &audio_pdm, + &audio_tdmina, + &audio_tdminb, + &audio_tdminc, + &audio_tdminlb, + &audio_tdmouta, + &audio_tdmoutb, + &audio_tdmoutc, + &audio_frddra, + &audio_frddrb, + &audio_frddrc, + &audio_toddra, + &audio_toddrb, + &audio_toddrc, + &audio_loopbacka, + &audio_spdifin, + &audio_spdifout, + &audio_resamplea, + &audio_reserved0, + &audio_toram, + &audio_spdifoutb, + &audio_eqdrc, + &audio_reserved1, + &audio_reserved2, + &audio_reserved3, + &audio_resampleb, + &audio_tovad, + &audio_audiolocker, + &audio_spdifin_lb, + &audio_reserved4, + &audio_reserved5, + + &audio_frddrd, + &audio_toddrd, + &audio_loopbackb, + &audio_earcrx, +}; + +/* Array of all clocks provided by this provider */ +static struct clk_hw *sm1_audio_clk_hws[] = { + [CLKID_AUDIO_GATE_DDR_ARB] = &audio_ddr_arb.hw, + [CLKID_AUDIO_GATE_PDM] = &audio_pdm.hw, + [CLKID_AUDIO_GATE_TDMINA] = &audio_tdmina.hw, + [CLKID_AUDIO_GATE_TDMINB] = &audio_tdminb.hw, + [CLKID_AUDIO_GATE_TDMINC] = &audio_tdminc.hw, + [CLKID_AUDIO_GATE_TDMINLB] = &audio_tdminlb.hw, + [CLKID_AUDIO_GATE_TDMOUTA] = &audio_tdmouta.hw, + [CLKID_AUDIO_GATE_TDMOUTB] = &audio_tdmoutb.hw, + [CLKID_AUDIO_GATE_TDMOUTC] = &audio_tdmoutc.hw, + [CLKID_AUDIO_GATE_FRDDRA] = &audio_frddra.hw, + [CLKID_AUDIO_GATE_FRDDRB] = &audio_frddrb.hw, + [CLKID_AUDIO_GATE_FRDDRC] = &audio_frddrc.hw, + [CLKID_AUDIO_GATE_TODDRA] = &audio_toddra.hw, + [CLKID_AUDIO_GATE_TODDRB] = &audio_toddrb.hw, + [CLKID_AUDIO_GATE_TODDRC] = &audio_toddrc.hw, + [CLKID_AUDIO_GATE_LOOPBACKA] = &audio_loopbacka.hw, + [CLKID_AUDIO_GATE_SPDIFIN] = &audio_spdifin.hw, + [CLKID_AUDIO_GATE_SPDIFOUT_A] = &audio_spdifout.hw, + [CLKID_AUDIO_GATE_RESAMPLEA] = &audio_resamplea.hw, + [CLKID_AUDIO_GATE_RESERVED0] = &audio_reserved0.hw, + [CLKID_AUDIO_GATE_TORAM] = &audio_toram.hw, + [CLKID_AUDIO_GATE_SPDIFOUT_B] = &audio_spdifoutb.hw, + [CLKID_AUDIO_GATE_EQDRC] = &audio_eqdrc.hw, + [CLKID_AUDIO_GATE_RESERVED1] = &audio_reserved1.hw, + [CLKID_AUDIO_GATE_RESERVED2] = &audio_reserved2.hw, + [CLKID_AUDIO_GATE_RESERVED3] = &audio_reserved3.hw, + [CLKID_AUDIO_GATE_RESAMPLEB] = &audio_resampleb.hw, + [CLKID_AUDIO_GATE_TOVAD] = &audio_tovad.hw, + [CLKID_AUDIO_GATE_AUDIOLOCKER] = &audio_audiolocker.hw, + [CLKID_AUDIO_GATE_SPDIFIN_LB] = &audio_spdifin_lb.hw, + [CLKID_AUDIO_GATE_RESERVED4] = &audio_reserved4.hw, + [CLKID_AUDIO_GATE_RESERVED5] = &audio_reserved5.hw, + + [CLKID_AUDIO_GATE_FRDDRD] = &audio_frddrd.hw, + [CLKID_AUDIO_GATE_TODDRD] = &audio_toddrd.hw, + [CLKID_AUDIO_GATE_LOOPBACKB] = &audio_loopbackb.hw, + [CLKID_AUDIO_GATE_EARCRX] = &audio_earcrx.hw, +}; + +static int sm1_clk_gates_init(struct clk **clks, void __iomem *iobase) +{ + int clkid; + + if (ARRAY_SIZE(sm1_audio_clk_gates) != MCLK_BASE) { + pr_err("check clk gates number\n"); + return -EINVAL; + } + + for (clkid = 0; clkid < MCLK_BASE; clkid++) { + sm1_audio_clk_gates[clkid]->reg = iobase; + clks[clkid] = clk_register(NULL, sm1_audio_clk_hws[clkid]); + WARN_ON(IS_ERR_OR_NULL(clks[clkid])); + } + + return 0; +} + +/* mclk_a */ +CLOCK_COM_MUX(mclk_a, AUD_ADDR_OFFSET(EE_AUDIO_MCLK_A_CTRL(1)), 0x7, 24); +CLOCK_COM_DIV(mclk_a, AUD_ADDR_OFFSET(EE_AUDIO_MCLK_A_CTRL(1)), 0, 16); +CLOCK_COM_GATE(mclk_a, AUD_ADDR_OFFSET(EE_AUDIO_MCLK_A_CTRL(1)), 31); +/* mclk_b */ +CLOCK_COM_MUX(mclk_b, AUD_ADDR_OFFSET(EE_AUDIO_MCLK_B_CTRL(1)), 0x7, 24); +CLOCK_COM_DIV(mclk_b, AUD_ADDR_OFFSET(EE_AUDIO_MCLK_B_CTRL(1)), 0, 16); +CLOCK_COM_GATE(mclk_b, AUD_ADDR_OFFSET(EE_AUDIO_MCLK_B_CTRL(1)), 31); +/* mclk_c */ +CLOCK_COM_MUX(mclk_c, AUD_ADDR_OFFSET(EE_AUDIO_MCLK_C_CTRL(1)), 0x7, 24); +CLOCK_COM_DIV(mclk_c, AUD_ADDR_OFFSET(EE_AUDIO_MCLK_C_CTRL(1)), 0, 16); +CLOCK_COM_GATE(mclk_c, AUD_ADDR_OFFSET(EE_AUDIO_MCLK_C_CTRL(1)), 31); +/* mclk_d */ +CLOCK_COM_MUX(mclk_d, AUD_ADDR_OFFSET(EE_AUDIO_MCLK_D_CTRL(1)), 0x7, 24); +CLOCK_COM_DIV(mclk_d, AUD_ADDR_OFFSET(EE_AUDIO_MCLK_D_CTRL(1)), 0, 16); +CLOCK_COM_GATE(mclk_d, AUD_ADDR_OFFSET(EE_AUDIO_MCLK_D_CTRL(1)), 31); +/* mclk_e */ +CLOCK_COM_MUX(mclk_e, AUD_ADDR_OFFSET(EE_AUDIO_MCLK_E_CTRL(1)), 0x7, 24); +CLOCK_COM_DIV(mclk_e, AUD_ADDR_OFFSET(EE_AUDIO_MCLK_E_CTRL(1)), 0, 16); +CLOCK_COM_GATE(mclk_e, AUD_ADDR_OFFSET(EE_AUDIO_MCLK_E_CTRL(1)), 31); +/* mclk_f */ +CLOCK_COM_MUX(mclk_f, AUD_ADDR_OFFSET(EE_AUDIO_MCLK_F_CTRL(1)), 0x7, 24); +CLOCK_COM_DIV(mclk_f, AUD_ADDR_OFFSET(EE_AUDIO_MCLK_F_CTRL(1)), 0, 16); +CLOCK_COM_GATE(mclk_f, AUD_ADDR_OFFSET(EE_AUDIO_MCLK_F_CTRL(1)), 31); +/* spdifin */ +CLOCK_COM_MUX(spdifin, AUD_ADDR_OFFSET(EE_AUDIO_CLK_SPDIFIN_CTRL), 0x7, 24); +CLOCK_COM_DIV(spdifin, AUD_ADDR_OFFSET(EE_AUDIO_CLK_SPDIFIN_CTRL), 0, 8); +CLOCK_COM_GATE(spdifin, AUD_ADDR_OFFSET(EE_AUDIO_CLK_SPDIFIN_CTRL), 31); +/* spdifout */ +CLOCK_COM_MUX(spdifout, AUD_ADDR_OFFSET(EE_AUDIO_CLK_SPDIFOUT_CTRL), 0x7, 24); +CLOCK_COM_DIV(spdifout, AUD_ADDR_OFFSET(EE_AUDIO_CLK_SPDIFOUT_CTRL), 0, 10); +CLOCK_COM_GATE(spdifout, AUD_ADDR_OFFSET(EE_AUDIO_CLK_SPDIFOUT_CTRL), 31); +/* audio resample_a */ +CLOCK_COM_MUX(resample_a, + AUD_ADDR_OFFSET(EE_AUDIO_CLK_RESAMPLEA_CTRL), 0xf, 24); +CLOCK_COM_DIV(resample_a, AUD_ADDR_OFFSET(EE_AUDIO_CLK_RESAMPLEA_CTRL), 0, 8); +CLOCK_COM_GATE(resample_a, AUD_ADDR_OFFSET(EE_AUDIO_CLK_RESAMPLEA_CTRL), 31); +/* audio locker_out */ +CLOCK_COM_MUX(locker_out, AUD_ADDR_OFFSET(EE_AUDIO_CLK_LOCKER_CTRL), 0xf, 24); +CLOCK_COM_DIV(locker_out, AUD_ADDR_OFFSET(EE_AUDIO_CLK_LOCKER_CTRL), 16, 8); +CLOCK_COM_GATE(locker_out, AUD_ADDR_OFFSET(EE_AUDIO_CLK_LOCKER_CTRL), 31); +/* audio locker_in */ +CLOCK_COM_MUX(locker_in, AUD_ADDR_OFFSET(EE_AUDIO_CLK_LOCKER_CTRL), 0xf, 8); +CLOCK_COM_DIV(locker_in, AUD_ADDR_OFFSET(EE_AUDIO_CLK_LOCKER_CTRL), 0, 8); +CLOCK_COM_GATE(locker_in, AUD_ADDR_OFFSET(EE_AUDIO_CLK_LOCKER_CTRL), 15); +/* pdmin0 */ +CLOCK_COM_MUX(pdmin0, AUD_ADDR_OFFSET(EE_AUDIO_CLK_PDMIN_CTRL0), 0x7, 24); +CLOCK_COM_DIV(pdmin0, AUD_ADDR_OFFSET(EE_AUDIO_CLK_PDMIN_CTRL0), 0, 16); +CLOCK_COM_GATE(pdmin0, AUD_ADDR_OFFSET(EE_AUDIO_CLK_PDMIN_CTRL0), 31); +/* pdmin1 */ +CLOCK_COM_MUX(pdmin1, AUD_ADDR_OFFSET(EE_AUDIO_CLK_PDMIN_CTRL1), 0x7, 24); +CLOCK_COM_DIV(pdmin1, AUD_ADDR_OFFSET(EE_AUDIO_CLK_PDMIN_CTRL1), 0, 16); +CLOCK_COM_GATE(pdmin1, AUD_ADDR_OFFSET(EE_AUDIO_CLK_PDMIN_CTRL1), 31); +/* spdifout b*/ +CLOCK_COM_MUX(spdifout_b, + AUD_ADDR_OFFSET(EE_AUDIO_CLK_SPDIFOUT_B_CTRL), 0x7, 24); +CLOCK_COM_DIV(spdifout_b, AUD_ADDR_OFFSET(EE_AUDIO_CLK_SPDIFOUT_B_CTRL), 0, 10); +CLOCK_COM_GATE(spdifout_b, AUD_ADDR_OFFSET(EE_AUDIO_CLK_SPDIFOUT_B_CTRL), 31); +/* audio resample_b */ +CLOCK_COM_MUX(resample_b, + AUD_ADDR_OFFSET(EE_AUDIO_CLK_RESAMPLEB_CTRL), 0xf, 24); +CLOCK_COM_DIV(resample_b, AUD_ADDR_OFFSET(EE_AUDIO_CLK_RESAMPLEB_CTRL), 0, 8); +CLOCK_COM_GATE(resample_b, AUD_ADDR_OFFSET(EE_AUDIO_CLK_RESAMPLEB_CTRL), 31); +/* spdifin_lb, div is a fake */ +CLOCK_COM_MUX(spdifin_lb, + AUD_ADDR_OFFSET(EE_AUDIO_CLK_SPDIFOUT_B_CTRL), 0x1, 30); +CLOCK_COM_DIV(spdifin_lb, AUD_ADDR_OFFSET(EE_AUDIO_CLK_SPDIFOUT_B_CTRL), 0, 29); +CLOCK_COM_GATE(spdifin_lb, AUD_ADDR_OFFSET(EE_AUDIO_CLK_SPDIFOUT_B_CTRL), 31); +/* audio eqdrc */ +CLOCK_COM_MUX(eqdrc, AUD_ADDR_OFFSET(EE_AUDIO_CLK_EQDRC_CTRL0), 0x7, 24); +CLOCK_COM_DIV(eqdrc, AUD_ADDR_OFFSET(EE_AUDIO_CLK_EQDRC_CTRL0), 0, 16); +CLOCK_COM_GATE(eqdrc, AUD_ADDR_OFFSET(EE_AUDIO_CLK_EQDRC_CTRL0), 31); +/* audio vad */ +CLOCK_COM_MUX(vad, AUD_ADDR_OFFSET(EE_AUDIO_VAD_CLK_CTRL), 0x7, 24); +CLOCK_COM_DIV(vad, AUD_ADDR_OFFSET(EE_AUDIO_VAD_CLK_CTRL), 0, 16); +CLOCK_COM_GATE(vad, AUD_ADDR_OFFSET(EE_AUDIO_VAD_CLK_CTRL), 31); +/* EARC TX CMDC */ +CLOCK_COM_MUX(earctx_cmdc, + AUD_ADDR_OFFSET(EE_AUDIO_EARCTX_CMDC_CLK_CTRL), 0x7, 24); +CLOCK_COM_DIV(earctx_cmdc, + AUD_ADDR_OFFSET(EE_AUDIO_EARCTX_CMDC_CLK_CTRL), 0, 16); +CLOCK_COM_GATE(earctx_cmdc, + AUD_ADDR_OFFSET(EE_AUDIO_EARCTX_CMDC_CLK_CTRL), 31); +/* EARC TX DMAC */ +CLOCK_COM_MUX(earctx_dmac, + AUD_ADDR_OFFSET(EE_AUDIO_EARCTX_DMAC_CLK_CTRL), 0x7, 24); +CLOCK_COM_DIV(earctx_dmac, + AUD_ADDR_OFFSET(EE_AUDIO_EARCTX_DMAC_CLK_CTRL), 0, 16); +CLOCK_COM_GATE(earctx_dmac, + AUD_ADDR_OFFSET(EE_AUDIO_EARCTX_DMAC_CLK_CTRL), 31); +/* EARC RX CMDC */ +CLOCK_COM_MUX(earcrx_cmdc, + AUD_ADDR_OFFSET(EE_AUDIO_EARCRX_CMDC_CLK_CTRL), 0x7, 24); +CLOCK_COM_DIV(earcrx_cmdc, + AUD_ADDR_OFFSET(EE_AUDIO_EARCRX_CMDC_CLK_CTRL), 0, 16); +CLOCK_COM_GATE(earcrx_cmdc, + AUD_ADDR_OFFSET(EE_AUDIO_EARCRX_CMDC_CLK_CTRL), 31); +/* EARC RX DMAC */ +CLOCK_COM_MUX(earcrx_dmac, + AUD_ADDR_OFFSET(EE_AUDIO_EARCRX_DMAC_CLK_CTRL), 0x7, 24); +CLOCK_COM_DIV(earcrx_dmac, + AUD_ADDR_OFFSET(EE_AUDIO_EARCRX_DMAC_CLK_CTRL), 0, 16); +CLOCK_COM_GATE(earcrx_dmac, + AUD_ADDR_OFFSET(EE_AUDIO_EARCRX_DMAC_CLK_CTRL), 31); + +static int sm1_clks_init(struct clk **clks, void __iomem *iobase) +{ + IOMAP_COM_CLK(mclk_a, iobase); + clks[CLKID_AUDIO_MCLK_A] = REGISTER_CLK_COM(mclk_a); + WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_MCLK_A])); + + IOMAP_COM_CLK(mclk_b, iobase); + clks[CLKID_AUDIO_MCLK_B] = REGISTER_CLK_COM(mclk_b); + WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_MCLK_B])); + + IOMAP_COM_CLK(mclk_c, iobase); + clks[CLKID_AUDIO_MCLK_C] = REGISTER_CLK_COM(mclk_c); + WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_MCLK_C])); + + IOMAP_COM_CLK(mclk_d, iobase); + clks[CLKID_AUDIO_MCLK_D] = REGISTER_CLK_COM(mclk_d); + WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_MCLK_D])); + + IOMAP_COM_CLK(mclk_e, iobase); + clks[CLKID_AUDIO_MCLK_E] = REGISTER_CLK_COM(mclk_e); + WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_MCLK_E])); + + IOMAP_COM_CLK(mclk_f, iobase); + clks[CLKID_AUDIO_MCLK_F] = REGISTER_CLK_COM(mclk_f); + WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_MCLK_F])); + + IOMAP_COM_CLK(spdifin, iobase); + clks[CLKID_AUDIO_SPDIFIN] = REGISTER_CLK_COM(spdifin); + WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_SPDIFIN])); + + IOMAP_COM_CLK(spdifout, iobase); + clks[CLKID_AUDIO_SPDIFOUT_A] = REGISTER_CLK_COM(spdifout); + WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_SPDIFOUT_A])); + + IOMAP_COM_CLK(resample_a, iobase); + clks[CLKID_AUDIO_RESAMPLE_A] = REGISTER_AUDIOCLK_COM(resample_a); + WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_RESAMPLE_A])); + + IOMAP_COM_CLK(locker_out, iobase); + clks[CLKID_AUDIO_LOCKER_OUT] = REGISTER_AUDIOCLK_COM(locker_out); + WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_LOCKER_OUT])); + + IOMAP_COM_CLK(locker_in, iobase); + clks[CLKID_AUDIO_LOCKER_IN] = REGISTER_AUDIOCLK_COM(locker_in); + WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_LOCKER_IN])); + + IOMAP_COM_CLK(pdmin0, iobase); + clks[CLKID_AUDIO_PDMIN0] = REGISTER_CLK_COM(pdmin0); + WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_PDMIN0])); + + IOMAP_COM_CLK(pdmin1, iobase); + clks[CLKID_AUDIO_PDMIN1] = REGISTER_CLK_COM(pdmin1); + WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_PDMIN1])); + + IOMAP_COM_CLK(spdifout_b, iobase); + clks[CLKID_AUDIO_SPDIFOUT_B] = REGISTER_CLK_COM(spdifout_b); + WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_SPDIFOUT_B])); + + IOMAP_COM_CLK(resample_b, iobase); + clks[CLKID_AUDIO_RESAMPLE_B] = REGISTER_AUDIOCLK_COM(resample_b); + WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_RESAMPLE_B])); + + IOMAP_COM_CLK(spdifin_lb, iobase); + clks[CLKID_AUDIO_SPDIFIN_LB] = REGISTER_CLK_COM(spdifin_lb); + WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_SPDIFIN_LB])); + + IOMAP_COM_CLK(eqdrc, iobase); + clks[CLKID_AUDIO_EQDRC] = REGISTER_CLK_COM(eqdrc); + WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_EQDRC])); + + IOMAP_COM_CLK(vad, iobase); + clks[CLKID_AUDIO_VAD] = REGISTER_CLK_COM(vad); + WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_VAD])); + + IOMAP_COM_CLK(earctx_cmdc, iobase); + clks[CLKID_EARCTX_CMDC] = REGISTER_CLK_COM(earctx_cmdc); + WARN_ON(IS_ERR_OR_NULL(clks[CLKID_EARCTX_CMDC])); + + IOMAP_COM_CLK(earctx_dmac, iobase); + clks[CLKID_EARCTX_DMAC] = REGISTER_CLK_COM(earctx_dmac); + WARN_ON(IS_ERR_OR_NULL(clks[CLKID_EARCTX_DMAC])); + + IOMAP_COM_CLK(earcrx_cmdc, iobase); + clks[CLKID_EARCRX_CMDC] = REGISTER_CLK_COM(earcrx_cmdc); + WARN_ON(IS_ERR_OR_NULL(clks[CLKID_EARCRX_CMDC])); + + IOMAP_COM_CLK(earcrx_dmac, iobase); + clks[CLKID_EARCRX_DMAC] = REGISTER_CLK_COM(earcrx_dmac); + WARN_ON(IS_ERR_OR_NULL(clks[CLKID_EARCRX_DMAC])); + + return 0; +} + +struct audio_clk_init sm1_audio_clks_init = { + .clk_num = NUM_AUDIO_CLKS, + .clk_gates = sm1_clk_gates_init, + .clks = sm1_clks_init, +}; diff --git a/sound/soc/amlogic/auge/spdif.c b/sound/soc/amlogic/auge/spdif.c index 5db566dd196a..ab6523a39b42 100644 --- a/sound/soc/amlogic/auge/spdif.c +++ b/sound/soc/amlogic/auge/spdif.c @@ -33,17 +33,14 @@ #include #include - #include "ddr_mngr.h" #include "spdif_hw.h" +#include "spdif_match_table.c" #include "audio_utils.h" #include "resample.h" #include "resample_hw.h" -#define DRV_NAME "aml_spdif" - -#define SPDIF_A 0 -#define SPDIF_B 1 +#define DRV_NAME "snd_spdif" /* Debug by PTM when bringup */ /*#define __PTM_SPDIF_CLK__*/ @@ -53,25 +50,14 @@ /*#define __SPDIFIN_AUDIO_TYPE_HW__*/ -struct spdif_chipinfo { - unsigned int id; +static int aml_dai_set_spdif_sysclk(struct snd_soc_dai *cpu_dai, + int clk_id, unsigned int freq, int dir); - /* add ch_cnt to ch_num */ - bool chnum_en; - /* - * axg, clear all irq bits - * after axg, such as g12a, clear each bits - * Reg_clr_interrupt[7:0] for each bit of irq_status[7:0]; - */ - bool clr_irq_all_bits; - /* no PaPb irq */ - bool irq_no_papb; - /* reg_hold_start_en; 1: add delay to match TDM out when share buff; */ - bool hold_start; - /* eq/drc */ - bool eq_drc_en; - /* pc, pd interrupt is separated. */ - bool pcpd_separated; +enum SPDIF_SRC { + SPDIFIN_PAD = 0, + SPDIFOUT, + NOAP, + HDMIRX }; struct aml_spdif { @@ -100,11 +86,11 @@ struct aml_spdif { /* * resample a/b do asrc for spdif in */ - unsigned int asrc_id; + enum resample_idx asrc_id; /* spdif in do asrc for pcm, * if raw data, disable it automatically. */ - unsigned int auto_asrc; + enum samplerate_index auto_asrc; /* check spdifin channel status for pcm or nonpcm */ struct timer_list timer; @@ -125,6 +111,10 @@ struct aml_spdif { /* last value for pc, pd */ int pc_last; int pd_last; + + /* mixer control vals */ + bool mute; + enum SPDIF_SRC spdifin_src; }; static const struct snd_pcm_hardware aml_spdif_hardware = { @@ -253,21 +243,44 @@ static int spdifin_audio_type_get_enum( return 0; } -/* For fake */ -static bool is_mute; -static int spdifin_src; static int aml_audio_set_spdif_mute(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - is_mute = - ucontrol->value.integer.value[0]; + struct snd_soc_dai *dai = snd_kcontrol_chip(kcontrol); + struct aml_spdif *p_spdif = snd_soc_dai_get_drvdata(dai); + struct pinctrl_state *state = NULL; + bool mute = !!ucontrol->value.integer.value[0]; + + if (IS_ERR_OR_NULL(p_spdif->pin_ctl)) { + pr_err("%s(), no pinctrl", __func__); + return 0; + } + if (mute) { + state = pinctrl_lookup_state + (p_spdif->pin_ctl, "spdif_pins_mute"); + + if (!IS_ERR_OR_NULL(state)) + pinctrl_select_state(p_spdif->pin_ctl, state); + } else { + state = pinctrl_lookup_state + (p_spdif->pin_ctl, "spdif_pins"); + + if (!IS_ERR_OR_NULL(state)) + pinctrl_select_state(p_spdif->pin_ctl, state); + } + + p_spdif->mute = mute; + return 0; } static int aml_audio_get_spdif_mute(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - ucontrol->value.integer.value[0] = is_mute; + struct snd_soc_dai *dai = snd_kcontrol_chip(kcontrol); + struct aml_spdif *p_spdif = snd_soc_dai_get_drvdata(dai); + + ucontrol->value.integer.value[0] = p_spdif->mute; return 0; } @@ -283,7 +296,11 @@ int spdifin_source_get_enum( struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - ucontrol->value.enumerated.item[0] = spdifin_src; + struct snd_soc_dai *dai = snd_kcontrol_chip(kcontrol); + struct aml_spdif *p_spdif = snd_soc_dai_get_drvdata(dai); + + ucontrol->value.enumerated.item[0] = p_spdif->spdifin_src; + return 0; } @@ -291,6 +308,8 @@ int spdifin_source_set_enum( struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { + struct snd_soc_dai *dai = snd_kcontrol_chip(kcontrol); + struct aml_spdif *p_spdif = snd_soc_dai_get_drvdata(dai); int src = ucontrol->value.enumerated.item[0]; if (src > 3) { @@ -298,20 +317,70 @@ int spdifin_source_set_enum( return -1; } spdifin_set_src(src); - spdifin_src = src; + p_spdif->spdifin_src = src; + + return 0; +} + +static int spdif_clk_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol); + struct aml_spdif *p_spdif = snd_soc_dai_get_drvdata(cpu_dai); + + ucontrol->value.enumerated.item[0] = + clk_get_rate(p_spdif->clk_spdifout); + return 0; +} + +static int spdif_clk_set(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol); + struct aml_spdif *p_spdif = snd_soc_dai_get_drvdata(cpu_dai); + unsigned int mpll_freq = 0; + int ret; + + int sysclk = p_spdif->sysclk_freq; + int value = ucontrol->value.enumerated.item[0]; + if (value > 2000000 || value < 0) { + pr_err("Fine spdif sysclk setting range(0~2000000), %d\n", + value); + return 0; + } + value = value - 1000000; + sysclk += value; + /* pr_info("spdif_set %d to %d,diff %d\n", + * p_spdif->sysclk_freq,sysclk,value); + */ + mpll_freq = sysclk * 4; + p_spdif->sysclk_freq = sysclk; + clk_set_rate(p_spdif->sysclk, mpll_freq); + clk_set_rate(p_spdif->clk_spdifout, p_spdif->sysclk_freq); + ret = clk_prepare_enable(p_spdif->sysclk); + if (ret) { + pr_err("Can't enable pcm sysclk clock: %d\n", ret); + return 0; + } + ret = clk_prepare_enable(p_spdif->clk_spdifout); + if (ret) { + pr_err("Can't enable clk_spdifout clock: %d\n", ret); + return 0; + } return 0; } static const struct snd_kcontrol_new snd_spdif_controls[] = { - SOC_ENUM_EXT("SPDIFIN audio samplerate", spdifin_sample_rate_enum, + SOC_ENUM_EXT("SPDIFIN audio samplerate", + spdifin_sample_rate_enum, spdifin_samplerate_get_enum, NULL), SOC_ENUM_EXT("SPDIFIN Audio Type", - spdif_audio_type_enum, - spdifin_audio_type_get_enum, - NULL), + spdif_audio_type_enum, + spdifin_audio_type_get_enum, + NULL), SOC_ENUM_EXT("Audio spdif format", spdif_format_enum, @@ -321,11 +390,22 @@ static const struct snd_kcontrol_new snd_spdif_controls[] = { SOC_SINGLE_BOOL_EXT("Audio spdif mute", 0, aml_audio_get_spdif_mute, aml_audio_set_spdif_mute), + SOC_ENUM_EXT("Audio spdifin source", spdifin_src_enum, spdifin_source_get_enum, spdifin_source_set_enum), +#ifdef CONFIG_AMLOGIC_HDMITX + SOC_SINGLE_BOOL_EXT("Audio hdmi-out mute", + 0, aml_get_hdmi_out_audio, + aml_set_hdmi_out_audio), +#endif + + SOC_SINGLE_EXT("SPDIF CLK Fine Setting", + 0, 0, 2000000, 0, + spdif_clk_get, + spdif_clk_set), }; static bool spdifin_check_audiotype_by_sw(struct aml_spdif *p_spdif) @@ -377,7 +457,7 @@ static void spdifin_audio_type_work_func(struct work_struct *work) if (val & 0x2) /* nonpcm, resample disable */ - resample_set(p_spdif->asrc_id, 0); + resample_set(p_spdif->asrc_id, RATE_OFF); else /* pcm, resample which rate ? */ resample_set(p_spdif->asrc_id, p_spdif->auto_asrc); @@ -588,7 +668,7 @@ static void spdifin_status_event(struct aml_spdif *p_spdif) #ifdef __SPDIFIN_AUDIO_TYPE_HW__ /* resample disable, by hw */ if (!spdifin_check_audiotype_by_sw(p_spdif)) - resample_set(p_spdif->asrc_id, 0); + resample_set(p_spdif->asrc_id, RATE_OFF); #endif #endif } @@ -860,7 +940,7 @@ static struct snd_pcm_ops aml_spdif_ops = { .mmap = aml_spdif_mmap, }; -#define PREALLOC_BUFFER (128 * 1024) +#define PREALLOC_BUFFER (256 * 1024) #define PREALLOC_BUFFER_MAX (256 * 1024) static int aml_spdif_new(struct snd_soc_pcm_runtime *rtd) { @@ -1011,7 +1091,7 @@ static void aml_dai_spdif_shutdown( #ifdef __SPDIFIN_AUDIO_TYPE_HW__ /* resample disabled, by hw */ if (!spdifin_check_audiotype_by_sw(p_spdif)) - resample_set(p_spdif->asrc_id, 0); + resample_set(p_spdif->asrc_id, RATE_OFF); #endif clk_disable_unprepare(p_spdif->clk_spdifin); clk_disable_unprepare(p_spdif->fixed_clk); @@ -1172,6 +1252,9 @@ static int aml_dai_spdif_trigger(struct snd_pcm_substream *substream, int cmd, if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { dev_info(substream->pcm->card->dev, "S/PDIF Playback enable\n"); aml_frddr_enable(p_spdif->fddr, 1); + udelay(100); + aml_spdif_mute(p_spdif->actrl, + substream->stream, p_spdif->id, false); } else { dev_info(substream->pcm->card->dev, "S/PDIF Capture enable\n"); aml_toddr_enable(p_spdif->tddr, 1); @@ -1333,7 +1416,7 @@ static struct snd_soc_dai_driver aml_spdif_dai[] = { .remove = aml_dai_spdif_remove, .playback = { .channels_min = 1, - .channels_max = 2, + .channels_max = 8, .rates = AML_DAI_SPDIF_RATES, .formats = AML_DAI_SPDIF_FORMATS, }, @@ -1449,68 +1532,6 @@ static int aml_spdif_parse_of(struct platform_device *pdev) return 0; } -struct spdif_chipinfo axg_spdif_chipinfo = { - .id = SPDIF_A, - .irq_no_papb = true, - .clr_irq_all_bits = true, - .pcpd_separated = true, -}; - -struct spdif_chipinfo g12a_spdif_a_chipinfo = { - .id = SPDIF_A, - .chnum_en = true, - .hold_start = true, - .eq_drc_en = true, - .pcpd_separated = true, -}; - -struct spdif_chipinfo g12a_spdif_b_chipinfo = { - .id = SPDIF_B, - .chnum_en = true, - .hold_start = true, - .eq_drc_en = true, - .pcpd_separated = true, -}; - -struct spdif_chipinfo tl1_spdif_a_chipinfo = { - .id = SPDIF_A, - .chnum_en = true, - .hold_start = true, - .eq_drc_en = true, -}; - -struct spdif_chipinfo tl1_spdif_b_chipinfo = { - .id = SPDIF_B, - .chnum_en = true, - .hold_start = true, - .eq_drc_en = true, -}; - -static const struct of_device_id aml_spdif_device_id[] = { - { - .compatible = "amlogic, axg-snd-spdif", - .data = &axg_spdif_chipinfo, - }, - { - .compatible = "amlogic, g12a-snd-spdif-a", - .data = &g12a_spdif_a_chipinfo, - }, - { - .compatible = "amlogic, g12a-snd-spdif-b", - .data = &g12a_spdif_b_chipinfo, - }, - { - .compatible = "amlogic, tl1-snd-spdif-a", - .data = &tl1_spdif_a_chipinfo, - }, - { - .compatible = "amlogic, tl1-snd-spdif-b", - .data = &tl1_spdif_b_chipinfo, - }, - {}, -}; -MODULE_DEVICE_TABLE(of, aml_spdif_device_id); - static int aml_spdif_platform_probe(struct platform_device *pdev) { struct device_node *node = pdev->dev.of_node; @@ -1521,6 +1542,7 @@ static int aml_spdif_platform_probe(struct platform_device *pdev) struct aml_spdif *aml_spdif = NULL; struct spdif_chipinfo *p_spdif_chipinfo; int ret = 0; + bool spdif_reenable = false; aml_spdif = devm_kzalloc(dev, sizeof(struct aml_spdif), GFP_KERNEL); @@ -1541,6 +1563,8 @@ static int aml_spdif_platform_probe(struct platform_device *pdev) aml_spdif->clk_cont = 1; aml_spdif->chipinfo = p_spdif_chipinfo; + + spdif_reenable = p_spdif_chipinfo->same_src_spdif_reen; } else dev_warn_once(dev, "check whether to update spdif chipinfo\n"); @@ -1563,7 +1587,7 @@ static int aml_spdif_platform_probe(struct platform_device *pdev) return -EINVAL; if (aml_spdif->clk_cont) - spdifout_play_with_zerodata(aml_spdif->id); + spdifout_play_with_zerodata(aml_spdif->id, spdif_reenable); ret = devm_snd_soc_register_component(dev, &aml_spdif_component, &aml_spdif_dai[aml_spdif->id], 1); diff --git a/sound/soc/amlogic/auge/spdif.h b/sound/soc/amlogic/auge/spdif.h new file mode 100644 index 000000000000..d6e6ba0f8af4 --- /dev/null +++ b/sound/soc/amlogic/auge/spdif.h @@ -0,0 +1,31 @@ +/* + * sound/soc/amlogic/auge/spdif.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 __AML_SPDIF_H__ +#define __AML_SPDIF_H__ +#include + +enum SPDIF_ID { + SPDIF_A, + SPDIF_B, + SPDIF_ID_CNT +}; + +int spdif_set_audio_clk(enum SPDIF_ID id, + struct clk *clk_src, int rate, bool same); + +#endif diff --git a/sound/soc/amlogic/auge/spdif_hw.c b/sound/soc/amlogic/auge/spdif_hw.c index d83fb6afda9a..930e723b126d 100644 --- a/sound/soc/amlogic/auge/spdif_hw.c +++ b/sound/soc/amlogic/auge/spdif_hw.c @@ -117,6 +117,22 @@ void aml_spdif_mute( } } +void aml_spdifout_mute_without_actrl( + int index, + bool is_mute) +{ + unsigned int offset, reg; + int mute_lr = 0; + + if (is_mute) + mute_lr = 0x3; + + offset = EE_AUDIO_SPDIFOUT_B_CTRL0 - EE_AUDIO_SPDIFOUT_CTRL0; + reg = EE_AUDIO_SPDIFOUT_CTRL0 + offset * index; + + audiobus_update_bits(reg, 0x3 << 21, mute_lr << 21); +} + void aml_spdif_arb_config(struct aml_audio_controller *actrl) { /* config ddr arb */ @@ -248,8 +264,8 @@ void aml_spdif_fifo_ctrl( reg = EE_AUDIO_SPDIFOUT_CTRL0 + offset * index; aml_audiobus_update_bits(actrl, reg, - 0x1<<29|0x1<<28|0x3<<21|0x1<<20|0x1<<19|0xff<<4, - 1<<29|1<<28|0x0<<21|0<<20|0<<19|0x3<<4); + 0x1<<29|0x1<<28|0x1<<20|0x1<<19|0xff<<4, + 1<<29|1<<28|0<<20|0<<19|0x3<<4); offset = EE_AUDIO_SPDIFOUT_B_CTRL1 - EE_AUDIO_SPDIFOUT_CTRL1; reg = EE_AUDIO_SPDIFOUT_CTRL1 + offset * index; @@ -359,7 +375,7 @@ void aml_spdifout_select_aed(bool enable, int spdifout_id) /* select eq_drc output */ offset = EE_AUDIO_SPDIFOUT_B_CTRL1 - EE_AUDIO_SPDIFOUT_CTRL1; reg = EE_AUDIO_SPDIFOUT_CTRL1 + offset * spdifout_id; - audiobus_update_bits(reg, 0x1 << 21, enable << 21); + audiobus_update_bits(reg, 0x1 << 31, enable << 31); } void aml_spdifout_get_aed_info(int spdifout_id, @@ -391,8 +407,8 @@ void spdifout_to_hdmitx_ctrl(int spdif_index) | spdif_index << 0 /* spdif_clk */ ); } - -void spdifout_clk_ctrl(int spdif_id, bool is_enable) +#if 0 +static void spdifout_clk_ctrl(int spdif_id, bool is_enable) { unsigned int offset, reg; @@ -402,28 +418,40 @@ void spdifout_clk_ctrl(int spdif_id, bool is_enable) /* select : mpll 0, 24m, so spdif clk:6m */ audiobus_write(reg, is_enable << 31 | 0x0 << 24 | 0x3 << 0); } - +#endif static void spdifout_fifo_ctrl(int spdif_id, - int fifo_id, int bitwidth, int channels) + int fifo_id, int bitwidth, int channels, int lane_i2s) { unsigned int frddr_type = spdifout_get_frddr_type(bitwidth); unsigned int offset, reg, i, chmask = 0; + unsigned int swap_masks = 0; + + /* spdif always masks two channel */ + if (lane_i2s * 2 >= channels) { + pr_err("invalid lane(%d) and channels(%d)\n", + lane_i2s, channels); + return; + } for (i = 0; i < channels; i++) chmask |= (1 << i); - pr_debug("spdif_%s fifo ctrl, frddr:%d type:%d, %d bits\n", + swap_masks = (2 * lane_i2s) | + (2 * lane_i2s + 1) << 4; + pr_debug("spdif_%s fifo ctrl, frddr:%d type:%d, %d bits, chmask %#x, swap %#x\n", (spdif_id == 0) ? "a":"b", fifo_id, frddr_type, - bitwidth); + bitwidth, + chmask, + swap_masks); /* mask lane 0 L/R channels */ offset = EE_AUDIO_SPDIFOUT_B_CTRL0 - EE_AUDIO_SPDIFOUT_CTRL0; reg = EE_AUDIO_SPDIFOUT_CTRL0 + offset * spdif_id; audiobus_update_bits(reg, - 0x3<<21|0x1<<20|0x1<<19|0xff<<4, - 0x0<<21|0<<20|0<<19|chmask<<4); + 0x1<<20|0x1<<19|0xff<<4, + 0<<20|0<<19|chmask<<4); offset = EE_AUDIO_SPDIFOUT_B_CTRL1 - EE_AUDIO_SPDIFOUT_CTRL1; reg = EE_AUDIO_SPDIFOUT_CTRL1 + offset * spdif_id; @@ -433,14 +461,7 @@ static void spdifout_fifo_ctrl(int spdif_id, offset = EE_AUDIO_SPDIFOUT_B_SWAP - EE_AUDIO_SPDIFOUT_SWAP; reg = EE_AUDIO_SPDIFOUT_SWAP + offset * spdif_id; - audiobus_write(reg, 1<<4); - - /* reset afifo */ - offset = EE_AUDIO_SPDIFOUT_B_CTRL0 - EE_AUDIO_SPDIFOUT_CTRL0; - reg = EE_AUDIO_SPDIFOUT_CTRL0 + offset * spdif_id; - audiobus_update_bits(reg, 3<<28, 0); - audiobus_update_bits(reg, 1<<29, 1<<29); - audiobus_update_bits(reg, 1<<28, 1<<28); + audiobus_write(reg, swap_masks); } static bool spdifout_is_enable(int spdif_id) @@ -454,7 +475,7 @@ static bool spdifout_is_enable(int spdif_id) return ((val >> 31) == 1); } -void spdifout_enable(int spdif_id, bool is_enable) +void spdifout_enable(int spdif_id, bool is_enable, bool reenable) { unsigned int offset, reg; @@ -467,15 +488,24 @@ void spdifout_enable(int spdif_id, bool is_enable) if (!is_enable) { /* share buffer, spdif should be active, so mute it */ - audiobus_update_bits(reg, 0x3 << 21, 0x3 << 21); + /*audiobus_update_bits(reg, 0x3 << 21, 0x3 << 21);*/ return; } + /* disable then for reset, to correct channel map */ + if (reenable) + audiobus_update_bits(reg, 1<<31, 0x0<<31); + + /* reset afifo */ + audiobus_update_bits(reg, 3<<28, 0); + audiobus_update_bits(reg, 1<<29, 1<<29); + audiobus_update_bits(reg, 1<<28, 1<<28); + audiobus_update_bits(reg, 1<<31, is_enable<<31); } void spdifout_samesource_set(int spdif_index, int fifo_id, - int bitwidth, int channels, bool is_enable) + int bitwidth, int channels, bool is_enable, int lane_i2s) { int spdif_id; @@ -484,27 +514,36 @@ void spdifout_samesource_set(int spdif_index, int fifo_id, else spdif_id = 0; - /* clk for spdif_b is always on */ - /*if (!spdif_id)*/ - spdifout_clk_ctrl(spdif_id, /*is_enable*/true); - if (is_enable) - spdifout_fifo_ctrl(spdif_id, fifo_id, bitwidth, channels); + spdifout_fifo_ctrl(spdif_id, + fifo_id, bitwidth, channels, lane_i2s); } int spdifin_get_sample_rate(void) { unsigned int val; + /*EE_AUDIO_SPDIFIN_STAT0*/ + /*r_width_max bit17:8 (the max width of two edge;)*/ + unsigned int max_width = 0; val = audiobus_read(EE_AUDIO_SPDIFIN_STAT0); /* NA when check min width of two edges */ if (((val >> 18) & 0x3ff) == 0x3ff) - return 0x7; + return 7; + + /*check the max width of two edge when spdifin sr=32kHz*/ + /*if max_width is more than 0x2f0(magic number),*/ + /*sr(32kHz) is unavailable*/ + max_width = ((val >> 8) & 0x3ff); + + if ((((val >> 28) & 0x7) == 0) && (max_width == 0x3ff)) + return 7; return (val >> 28) & 0x7; } + static int spdifin_get_channel_status(int sel) { unsigned int val; @@ -596,7 +635,7 @@ void spdif_set_channel_status_info( audiobus_write(reg, chsts->chstat1_r << 16 | chsts->chstat0_r); } -void spdifout_play_with_zerodata(unsigned int spdif_id) +void spdifout_play_with_zerodata(unsigned int spdif_id, bool reenable) { pr_debug("%s, spdif id:%d enable:%d\n", __func__, @@ -623,20 +662,17 @@ void spdifout_play_with_zerodata(unsigned int spdif_id) src0_sel = 3; /* spdif clk */ - spdifout_clk_ctrl(spdif_id, true); - + //spdifout_clk_ctrl(spdif_id, true); + /* spdif to hdmitx */ #if defined(CONFIG_ARCH_MESON64_ODROID_COMMON) /* ODROID spdif_b only to hdmitx */ if (spdif_id == 1) - spdifout_to_hdmitx_ctrl(spdif_id); -#else - /* spdif to hdmitx */ - spdifout_to_hdmitx_ctrl(spdif_id); #endif + spdifout_to_hdmitx_ctrl(spdif_id); /* spdif ctrl */ spdifout_fifo_ctrl(spdif_id, - frddr_index, bitwidth, runtime.channels); + frddr_index, bitwidth, runtime.channels, 0); /* channel status info */ spdif_get_channel_status_info(&chsts, sample_rate); @@ -649,7 +685,7 @@ void spdifout_play_with_zerodata(unsigned int spdif_id) frddr_init_without_mngr(frddr_index, src0_sel); /* spdif enable */ - spdifout_enable(spdif_id, true); + spdifout_enable(spdif_id, true, reenable); } } diff --git a/sound/soc/amlogic/auge/spdif_hw.h b/sound/soc/amlogic/auge/spdif_hw.h index 3e133f620fba..e15efa3abaab 100644 --- a/sound/soc/amlogic/auge/spdif_hw.h +++ b/sound/soc/amlogic/auge/spdif_hw.h @@ -40,6 +40,10 @@ extern void aml_spdif_mute( int index, bool is_mute); +extern void aml_spdifout_mute_without_actrl( + int index, + bool is_mute); + extern void aml_spdif_arb_config(struct aml_audio_controller *actrl); extern int aml_spdifin_status_check( @@ -74,8 +78,8 @@ extern void aml_spdifout_get_aed_info(int spdifout_id, extern void spdifout_to_hdmitx_ctrl(int spdif_index); extern void spdifout_samesource_set(int spdif_index, int fifo_id, - int bitwidth, int channels, bool is_enable); -extern void spdifout_enable(int spdif_id, bool is_enable); + int bitwidth, int channels, bool is_enable, int lane_i2s); +extern void spdifout_enable(int spdif_id, bool is_enable, bool reenable); extern int spdifin_get_sample_rate(void); @@ -86,7 +90,7 @@ extern int spdifin_get_audio_type(void); extern void spdif_set_channel_status_info( struct iec958_chsts *chsts, int spdif_id); -extern void spdifout_play_with_zerodata(unsigned int spdif_id); +extern void spdifout_play_with_zerodata(unsigned int spdif_id, bool reenable); extern void spdifout_play_with_zerodata_free(unsigned int spdif_id); extern void spdifin_set_src(int src); #endif diff --git a/sound/soc/amlogic/auge/spdif_match_table.c b/sound/soc/amlogic/auge/spdif_match_table.c new file mode 100644 index 000000000000..c88929e55561 --- /dev/null +++ b/sound/soc/amlogic/auge/spdif_match_table.c @@ -0,0 +1,148 @@ +/* + * sound/soc/amlogic/auge/spdif_match_table.c + * + * Copyright (C) 2019 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 SPDIF_A 0 +#define SPDIF_B 1 + +struct spdif_chipinfo { + unsigned int id; + + /* add ch_cnt to ch_num */ + bool chnum_en; + /* + * axg, clear all irq bits + * after axg, such as g12a, clear each bits + * Reg_clr_interrupt[7:0] for each bit of irq_status[7:0]; + */ + bool clr_irq_all_bits; + /* no PaPb irq */ + bool irq_no_papb; + /* reg_hold_start_en; 1: add delay to match TDM out when share buff; */ + bool hold_start; + /* eq/drc */ + bool eq_drc_en; + /* pc, pd interrupt is separated. */ + bool pcpd_separated; + /* same source, spdif re-enable */ + bool same_src_spdif_reen; +}; + +struct spdif_chipinfo axg_spdif_chipinfo = { + .id = SPDIF_A, + .irq_no_papb = true, + .clr_irq_all_bits = true, + .pcpd_separated = true, +}; + +struct spdif_chipinfo g12a_spdif_a_chipinfo = { + .id = SPDIF_A, + .chnum_en = true, + .hold_start = true, + .eq_drc_en = true, + .pcpd_separated = true, +}; + +struct spdif_chipinfo g12a_spdif_b_chipinfo = { + .id = SPDIF_B, + .chnum_en = true, + .hold_start = true, + .eq_drc_en = true, + .pcpd_separated = true, +}; + +struct spdif_chipinfo tl1_spdif_a_chipinfo = { + .id = SPDIF_A, + .chnum_en = true, + .hold_start = true, + .eq_drc_en = true, +}; + +struct spdif_chipinfo tl1_spdif_b_chipinfo = { + .id = SPDIF_B, + .chnum_en = true, + .hold_start = true, + .eq_drc_en = true, +}; + +struct spdif_chipinfo sm1_spdif_a_chipinfo = { + .id = SPDIF_A, + .chnum_en = true, + .hold_start = true, + .eq_drc_en = true, +}; + +struct spdif_chipinfo sm1_spdif_b_chipinfo = { + .id = SPDIF_B, + .chnum_en = true, + .hold_start = true, + .eq_drc_en = true, +}; + +struct spdif_chipinfo tm2_spdif_a_chipinfo = { + .id = SPDIF_A, + .chnum_en = true, + .hold_start = true, + .eq_drc_en = true, +}; + +struct spdif_chipinfo tm2_spdif_b_chipinfo = { + .id = SPDIF_B, + .chnum_en = true, + .hold_start = true, + .eq_drc_en = true, +}; + +static const struct of_device_id aml_spdif_device_id[] = { + { + .compatible = "amlogic, axg-snd-spdif", + .data = &axg_spdif_chipinfo, + }, + { + .compatible = "amlogic, g12a-snd-spdif-a", + .data = &g12a_spdif_a_chipinfo, + }, + { + .compatible = "amlogic, g12a-snd-spdif-b", + .data = &g12a_spdif_b_chipinfo, + }, + { + .compatible = "amlogic, tl1-snd-spdif-a", + .data = &tl1_spdif_a_chipinfo, + }, + { + .compatible = "amlogic, tl1-snd-spdif-b", + .data = &tl1_spdif_b_chipinfo, + }, + { + .compatible = "amlogic, sm1-snd-spdif-a", + .data = &sm1_spdif_a_chipinfo, + }, + { + .compatible = "amlogic, sm1-snd-spdif-b", + .data = &sm1_spdif_b_chipinfo, + }, + { + .compatible = "amlogic, tm2-snd-spdif-a", + .data = &tm2_spdif_a_chipinfo, + }, + { + .compatible = "amlogic, tm2-snd-spdif-b", + .data = &tm2_spdif_b_chipinfo, + }, + {}, +}; +MODULE_DEVICE_TABLE(of, aml_spdif_device_id); diff --git a/sound/soc/amlogic/auge/tdm.c b/sound/soc/amlogic/auge/tdm.c index 1e2b55b9837e..1b185f4048e7 100644 --- a/sound/soc/amlogic/auge/tdm.c +++ b/sound/soc/amlogic/auge/tdm.c @@ -40,16 +40,17 @@ #include "tdm_hw.h" #include "sharebuffer.h" #include "vad.h" +#include "spdif_hw.h" + +#include "tdm_match_table.c" /*#define __PTM_TDM_CLK__*/ -#define DRV_NAME "aml_tdm" +#define DRV_NAME "snd_tdm" -#define TDM_A 0 -#define TDM_B 1 -#define TDM_C 2 -#define LANE_MAX 4 +static int aml_dai_set_tdm_sysclk(struct snd_soc_dai *cpu_dai, + int clk_id, unsigned int freq, int dir); static void dump_pcm_setting(struct pcm_setting *setting) { @@ -74,26 +75,6 @@ static void dump_pcm_setting(struct pcm_setting *setting) pr_debug("\tlane_lb_mask_in(%#x)\n", setting->lane_lb_mask_in); } -struct tdm_chipinfo { - /* device id */ - unsigned int id; - - /* no eco, sclk_ws_inv for out */ - bool sclk_ws_inv; - - /* output en (oe) for pinmux */ - bool oe_fn; - - /* clk pad */ - bool clk_pad_ctl; - - /* same source */ - bool same_src_fn; - - /* ACODEC_ADC function */ - bool adc_fn; -}; - struct aml_tdm { struct pcm_setting setting; struct pinctrl *pin_ctl; @@ -102,7 +83,8 @@ struct aml_tdm { struct clk *clk; struct clk *clk_gate; struct clk *mclk; - struct clk *samesrc_sysclk; + struct clk *samesrc_srcpll; + struct clk *samesrc_clk; bool contns_clk; unsigned int id; /* bclk src selection */ @@ -113,12 +95,18 @@ struct aml_tdm { struct tdm_chipinfo *chipinfo; /* share buffer with module */ int samesource_sel; + /* share buffer lane setting from DTS */ + int lane_ss; + int mclk_pad; /* virtual link for i2s to hdmitx */ int i2s2hdmitx; int acodec_adc; uint last_mpll_freq; uint last_mclk_freq; uint last_fmt; + + bool en_share; + unsigned int lane_cnt; }; static const struct snd_pcm_hardware aml_tdm_hardware = { @@ -132,10 +120,10 @@ static const struct snd_pcm_hardware aml_tdm_hardware = { SNDRV_PCM_FMTBIT_S32_LE, .period_bytes_min = 64, - .period_bytes_max = 256 * 1024 * 2, + .period_bytes_max = 256 * 1024, .periods_min = 2, .periods_max = 1024, - .buffer_bytes_max = 512 * 1024 * 2, + .buffer_bytes_max = 1024 * 1024, .rate_min = 8000, .rate_max = 384000, @@ -143,6 +131,86 @@ static const struct snd_pcm_hardware aml_tdm_hardware = { .channels_max = 32, }; +static int tdm_clk_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol); + struct aml_tdm *p_tdm = snd_soc_dai_get_drvdata(cpu_dai); + + ucontrol->value.enumerated.item[0] = clk_get_rate(p_tdm->mclk); + return 0; +} + +static int tdm_clk_set(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol); + struct aml_tdm *p_tdm = snd_soc_dai_get_drvdata(cpu_dai); + + int mclk_rate = p_tdm->last_mclk_freq; + int value = ucontrol->value.enumerated.item[0]; + + if (value > 2000000 || value < 0) { + pr_err("Fine tdm clk setting range (0~2000000), %d\n", value); + return 0; + } + mclk_rate += (value - 1000000); + + aml_dai_set_tdm_sysclk(cpu_dai, 0, mclk_rate, 0); + + return 0; +} + +static int tdmin_clk_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int clk; + int value; + + clk = meson_clk_measure(70); + if (clk >= 11000000) + value = 3; + else if (clk >= 6000000) + value = 2; + else if (clk >= 2000000) + value = 1; + else + value = 0; + + + ucontrol->value.integer.value[0] = value; + + return 0; +} + +/* current sample mode and its sample rate */ +static const char *const i2sin_clk[] = { + "0", + "3000000", + "6000000", + "12000000" +}; + +static const struct soc_enum i2sin_clk_enum[] = { + SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(i2sin_clk), + i2sin_clk), +}; + + + +static const struct snd_kcontrol_new snd_tdm_controls[] = { + SOC_ENUM_EXT("I2SIn CLK", i2sin_clk_enum, + tdmin_clk_get, + NULL), + + SOC_SINGLE_EXT("TDM MCLK Fine Setting", + 0, 0, 2000000, 0, + tdm_clk_get, + tdm_clk_set), +}; + + + static irqreturn_t aml_tdm_ddr_isr(int irq, void *devid) { struct snd_pcm_substream *substream = (struct snd_pcm_substream *)devid; @@ -357,7 +425,7 @@ static struct snd_pcm_ops aml_tdm_ops = { .mmap = aml_tdm_mmap, }; -#define PREALLOC_BUFFER (128 * 1024) +#define PREALLOC_BUFFER (256 * 1024) #define PREALLOC_BUFFER_MAX (256 * 1024) static int aml_tdm_new(struct snd_soc_pcm_runtime *rtd) { @@ -390,9 +458,11 @@ static int aml_dai_tdm_prepare(struct snd_pcm_substream *substream, p_tdm->chipinfo->same_src_fn && (p_tdm->samesource_sel >= 0) && (aml_check_sharebuffer_valid(p_tdm->fddr, - p_tdm->samesource_sel))) { + p_tdm->samesource_sel)) + && p_tdm->en_share) { sharebuffer_prepare(substream, - fr, p_tdm->samesource_sel); + fr, p_tdm->samesource_sel, + p_tdm->lane_ss); } /* i2s source to hdmix */ @@ -400,8 +470,6 @@ static int aml_dai_tdm_prepare(struct snd_pcm_substream *substream, i2s_to_hdmitx_ctrl(p_tdm->id); aout_notifier_call_chain(AOUT_EVENT_IEC_60958_PCM, substream); - } else { - i2s_to_hdmitx_disable(); } fifo_id = aml_frddr_get_fifo_id(fr); @@ -518,9 +586,11 @@ static int aml_dai_tdm_trigger(struct snd_pcm_substream *substream, int cmd, && p_tdm->chipinfo->same_src_fn && (p_tdm->samesource_sel >= 0) && (aml_check_sharebuffer_valid(p_tdm->fddr, - p_tdm->samesource_sel))) { - sharebuffer_trigger(cmd, p_tdm->samesource_sel); - } + p_tdm->samesource_sel)) + && p_tdm->en_share) + sharebuffer_trigger(cmd, + p_tdm->samesource_sel, + p_tdm->chipinfo->same_src_spdif_reen); switch (cmd) { case SNDRV_PCM_TRIGGER_START: @@ -544,13 +614,25 @@ static int aml_dai_tdm_trigger(struct snd_pcm_substream *substream, int cmd, if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { dev_info(substream->pcm->card->dev, "tdm playback enable\n"); aml_frddr_enable(p_tdm->fddr, 1); + aml_tdm_enable(p_tdm->actrl, + substream->stream, p_tdm->id, true); + udelay(100); + aml_tdm_mute_playback(p_tdm->actrl, p_tdm->id, + false, p_tdm->lane_cnt); + if (p_tdm->chipinfo + && p_tdm->chipinfo->same_src_fn + && (p_tdm->samesource_sel >= 0) + && (aml_check_sharebuffer_valid(p_tdm->fddr, + p_tdm->samesource_sel)) + && p_tdm->en_share) { + aml_spdifout_mute_without_actrl(0, false); + } } else { dev_info(substream->pcm->card->dev, "tdm capture enable\n"); aml_toddr_enable(p_tdm->tddr, 1); + aml_tdm_enable(p_tdm->actrl, + substream->stream, p_tdm->id, true); } - aml_tdm_enable(p_tdm->actrl, - substream->stream, p_tdm->id, true); - break; case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_SUSPEND: @@ -563,16 +645,25 @@ static int aml_dai_tdm_trigger(struct snd_pcm_substream *substream, int cmd, break; } - aml_tdm_enable(p_tdm->actrl, - substream->stream, p_tdm->id, false); - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { dev_info(substream->pcm->card->dev, "tdm playback stop\n"); aml_frddr_enable(p_tdm->fddr, 0); + aml_tdm_mute_playback(p_tdm->actrl, p_tdm->id, + true, p_tdm->lane_cnt); + if (p_tdm->chipinfo + && p_tdm->chipinfo->same_src_fn + && (p_tdm->samesource_sel >= 0) + && (aml_check_sharebuffer_valid(p_tdm->fddr, + p_tdm->samesource_sel)) + && p_tdm->en_share) { + aml_spdifout_mute_without_actrl(0, true); + } } else { dev_info(substream->pcm->card->dev, "tdm capture stop\n"); aml_toddr_enable(p_tdm->tddr, 0); } + aml_tdm_enable(p_tdm->actrl, + substream->stream, p_tdm->id, false); break; default: return -EINVAL; @@ -610,30 +701,29 @@ static int aml_tdm_set_lanes(struct aml_tdm *p_tdm, unsigned int channels, int stream) { struct pcm_setting *setting = &p_tdm->setting; - unsigned int lanes, swap_val; + unsigned int lanes, swap_val = 0, swap_val1 = 0; unsigned int lane_mask; unsigned int set_num = 0; unsigned int i; - pr_debug("asoc channels:%d, slots:%d\n", channels, setting->slots); - - swap_val = 0; - // calc lanes by channels and slots + /* calc lanes by channels and slots */ lanes = (channels - 1) / setting->slots + 1; - if (lanes > 4) { - pr_err("lanes setting error\n"); + if (lanes > p_tdm->lane_cnt) { + pr_err("set lane error! asoc channels:%d, slots:%d, lane_cnt:%d\n", + channels, setting->slots, p_tdm->lane_cnt); return -EINVAL; } +#if 1 if (stream == SNDRV_PCM_STREAM_PLAYBACK) { - // set lanes mask acordingly + /* set lanes mask acordingly */ if (p_tdm->chipinfo && p_tdm->chipinfo->oe_fn && p_tdm->setting.lane_oe_mask_out) lane_mask = setting->lane_oe_mask_out; else lane_mask = setting->lane_mask_out; - for (i = 0; i < 4; i++) { + for (i = 0; i < p_tdm->lane_cnt; i++) { if (((1 << i) & lane_mask) && lanes) { aml_tdm_set_channel_mask(p_tdm->actrl, stream, p_tdm->id, i, setting->tx_mask); @@ -641,8 +731,10 @@ static int aml_tdm_set_lanes(struct aml_tdm *p_tdm, } } swap_val = 0x76543210; + if (p_tdm->lane_cnt > LANE_MAX1) + swap_val1 = 0xfedcba98; aml_tdm_set_lane_channel_swap(p_tdm->actrl, - stream, p_tdm->id, swap_val); + stream, p_tdm->id, swap_val, swap_val1); } else { if (p_tdm->chipinfo && p_tdm->chipinfo->oe_fn @@ -651,42 +743,107 @@ static int aml_tdm_set_lanes(struct aml_tdm *p_tdm, else lane_mask = setting->lane_mask_in; - for (i = 0; i < 4; i++) { + for (i = 0; i < p_tdm->lane_cnt; i++) { if (i < lanes) aml_tdm_set_channel_mask(p_tdm->actrl, stream, p_tdm->id, i, setting->rx_mask); - if ((1 << i) & lane_mask) { - // each lane only L/R masked - pr_info("tdmin set lane %d\n", i); - swap_val |= (i * 2) << (set_num++ * 4); - swap_val |= (i * 2 + 1) << (set_num++ * 4); + if (((1 << i) & lane_mask) && (i < LANE_MAX1)) { + /* each lane only L/R masked */ + pr_debug("tdmin set lane %d\n", i); + swap_val |= (i * 2) << + (set_num++ * LANE_MAX1); + swap_val |= (i * 2 + 1) << + (set_num++ * LANE_MAX1); + } + if (((1 << i) & lane_mask) && (i >= LANE_MAX1) + && (i < LANE_MAX3)) { + /* each lane only L/R masked */ + pr_debug("tdmin set lane %d\n", i); + swap_val1 |= (i * 2) << + (set_num++ * LANE_MAX1); + swap_val1 |= (i * 2 + 1) << + (set_num++ * LANE_MAX1); } } aml_tdm_set_lane_channel_swap(p_tdm->actrl, - stream, p_tdm->id, swap_val); + stream, p_tdm->id, swap_val, swap_val1); } +#else + if (stream == SNDRV_PCM_STREAM_PLAYBACK) { + if (p_tdm->chipinfo + && p_tdm->chipinfo->oe_fn + && p_tdm->setting.lane_oe_mask_out) + lane_mask = setting->lane_oe_mask_out; + else + lane_mask = setting->lane_mask_out; + } else { + if (p_tdm->chipinfo + && p_tdm->chipinfo->oe_fn + && p_tdm->setting.lane_oe_mask_in) + lane_mask = setting->lane_oe_mask_in; + else + lane_mask = setting->lane_mask_in; + } + /* lane mask */ + for (i = 0; i < 4; i++) { + if (((1 << i) & lane_mask) && lanes) { + aml_tdm_set_channel_mask(p_tdm->actrl, + stream, p_tdm->id, i, setting->tx_mask); + lanes--; + } + } + + /* channel swap */ + for (i = 0; i < p_tdm->lane_cnt; i++) { + if ((1 << i) & lane_mask) { + swap0_val |= (1 << (2 * i)) - 1; + lane_chs += 1; + if (lane_chs >= channels) + break; + swap0_val |= (1 << (2 * i + 1)) - 1; + lane_chs += 1; + if (lane_chs >= channels) + break; + + if (i >= LANE_MAX1) { + swap1_val |= (1 << (2 * (i - LANE_MAX1))) - 1; + lane_chs += 1; + if (lane_chs >= channels) + break; + swap1_val |= (1 << (2 * (i - LANE_MAX1) + 1)) + - 1; + lane_chs += 1; + if (lane_chs >= channels) + break; + } + } + } + aml_tdm_set_lane_channel_swap(p_tdm->actrl, + stream, p_tdm->id, swap0_val, swap1_val); +#endif return 0; } static int aml_tdm_set_clk_pad(struct aml_tdm *p_tdm) { - unsigned int mpad, mclk_sel; + int mpad_offset = 0; + /* mclk pad + * does mclk need? + * mclk from which mclk source, mclk_a/b/c/d/e/f + * mclk pad controlled by dts, mclk source according to id + */ + if (p_tdm->chipinfo && (!p_tdm->chipinfo->mclkpad_no_offset)) + mpad_offset = 1; - // TODO: update pad - if (p_tdm->id >= 1) { - mpad = p_tdm->id - 1; - mclk_sel = p_tdm->id; - } else { - mpad = 0; - mclk_sel = 0; - } - - /* clk pad */ - aml_tdm_clk_pad_select(p_tdm->actrl, mpad, mclk_sel, - p_tdm->id, p_tdm->clk_sel); + aml_tdm_clk_pad_select(p_tdm->actrl, + p_tdm->mclk_pad, + mpad_offset, + p_tdm->id, + p_tdm->id, + p_tdm->clk_sel); return 0; } @@ -723,7 +880,7 @@ static int aml_dai_tdm_hw_params(struct snd_pcm_substream *substream, if (ret) return ret; - if (p_tdm->chipinfo && p_tdm->chipinfo->clk_pad_ctl) { + if (p_tdm->chipinfo && (!p_tdm->chipinfo->no_mclkpad_ctrl)) { ret = aml_tdm_set_clk_pad(p_tdm); if (ret) return ret; @@ -740,19 +897,27 @@ static int aml_dai_tdm_hw_params(struct snd_pcm_substream *substream, && (p_tdm->chipinfo->same_src_fn) && (p_tdm->samesource_sel >= 0) && (aml_check_sharebuffer_valid(p_tdm->fddr, - p_tdm->samesource_sel))) { + p_tdm->samesource_sel)) + && p_tdm->en_share) { int mux = 0, ratio = 0; sharebuffer_get_mclk_fs_ratio(p_tdm->samesource_sel, &mux, &ratio); pr_info("samesource sysclk:%d\n", rate * ratio * mux); - if (p_tdm->samesrc_sysclk) - clk_set_rate(p_tdm->samesrc_sysclk, + if (!IS_ERR(p_tdm->samesrc_srcpll)) { + clk_set_rate(p_tdm->samesrc_srcpll, rate * ratio * mux); + clk_prepare_enable(p_tdm->samesrc_srcpll); + } + if (!IS_ERR(p_tdm->samesrc_clk)) { + clk_set_rate(p_tdm->samesrc_clk, + rate * ratio); + clk_prepare_enable(p_tdm->samesrc_clk); + } } if (!p_tdm->contns_clk && !IS_ERR(p_tdm->mclk)) { - pr_debug("%s(), enable mclk for %s", __func__, cpu_dai->name); + pr_debug("%s(), enable mclk for %s\n", __func__, cpu_dai->name); ret = clk_prepare_enable(p_tdm->mclk); if (ret) { pr_err("Can't enable mclk: %d\n", ret); @@ -785,7 +950,8 @@ static int aml_dai_tdm_hw_free(struct snd_pcm_substream *substream, && p_tdm->chipinfo->same_src_fn && (p_tdm->samesource_sel >= 0) && fr - && (aml_check_sharebuffer_valid(fr, p_tdm->samesource_sel))) { + && (aml_check_sharebuffer_valid(fr, p_tdm->samesource_sel)) + && p_tdm->en_share) { sharebuffer_free(substream, fr, p_tdm->samesource_sel); } @@ -828,6 +994,14 @@ static int aml_dai_set_tdm_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) aml_tdm_set_format(p_tdm->actrl, &(p_tdm->setting), p_tdm->clk_sel, p_tdm->id, fmt, 1, 1); + if (p_tdm->contns_clk && !IS_ERR(p_tdm->mclk)) { + int ret = clk_prepare_enable(p_tdm->mclk); + + if (ret) { + pr_err("Can't enable mclk: %d\n", ret); + return ret; + } + } capture: /* update skew for ACODEC_ADC */ @@ -970,6 +1144,7 @@ static int aml_dai_set_tdm_slot(struct snd_soc_dai *cpu_dai, lanes_lb_cnt); pr_debug("\tslots(%d), slot_width(%d)\n", slots, slot_width); + p_tdm->setting.tx_mask = tx_mask; p_tdm->setting.rx_mask = rx_mask; p_tdm->setting.slots = slots; @@ -1034,11 +1209,11 @@ static int aml_dai_set_tdm_slot(struct snd_soc_dai *cpu_dai, in_src = ACODEC_ADC; } - if (in_lanes >= 0 && in_lanes <= 4) + if (in_lanes > 0 && in_lanes <= LANE_MAX3) aml_tdm_set_slot_in(p_tdm->actrl, p_tdm->id, in_src, slot_width); - if (out_lanes >= 0 && out_lanes <= 4) + if (out_lanes > 0 && out_lanes <= LANE_MAX3) aml_tdm_set_slot_out(p_tdm->actrl, p_tdm->id, slots, slot_width, force_oe, oe_val); @@ -1052,8 +1227,14 @@ static int aml_dai_set_tdm_slot(struct snd_soc_dai *cpu_dai, static int aml_dai_tdm_probe(struct snd_soc_dai *cpu_dai) { + int ret = 0; struct aml_tdm *p_tdm = snd_soc_dai_get_drvdata(cpu_dai); + ret = snd_soc_add_dai_controls(cpu_dai, snd_tdm_controls, + ARRAY_SIZE(snd_tdm_controls)); + if (ret < 0) + pr_err("%s, failed add snd spdif controls\n", __func__); + /* config ddr arb */ aml_tdm_arb_config(p_tdm->actrl); @@ -1072,11 +1253,14 @@ static int aml_dai_tdm_mute_stream(struct snd_soc_dai *cpu_dai, struct aml_tdm *p_tdm = snd_soc_dai_get_drvdata(cpu_dai); if (stream == SNDRV_PCM_STREAM_PLAYBACK) { - pr_debug("tdm playback mute: %d\n", mute); - aml_tdm_mute_playback(p_tdm->actrl, p_tdm->id, mute); + pr_debug("tdm playback mute: %d, lane_cnt = %d\n", + mute, p_tdm->lane_cnt); + //aml_tdm_mute_playback(p_tdm->actrl, p_tdm->id, + // mute, p_tdm->lane_cnt); } else if (stream == SNDRV_PCM_STREAM_CAPTURE) { pr_debug("tdm capture mute: %d\n", mute); - aml_tdm_mute_capture(p_tdm->actrl, p_tdm->id, mute); + aml_tdm_mute_capture(p_tdm->actrl, p_tdm->id, + mute, p_tdm->lane_cnt); } return 0; } @@ -1126,7 +1310,7 @@ static struct snd_soc_dai_driver aml_tdm_dai[] = { .remove = aml_dai_tdm_remove, .playback = { .channels_min = 1, - .channels_max = 8, + .channels_max = 32, .rates = AML_DAI_TDM_RATES, .formats = AML_DAI_TDM_FORMATS, }, @@ -1146,7 +1330,7 @@ static struct snd_soc_dai_driver aml_tdm_dai[] = { .remove = aml_dai_tdm_remove, .playback = { .channels_min = 1, - .channels_max = 8, + .channels_max = 32, .rates = AML_DAI_TDM_RATES, .formats = AML_DAI_TDM_FORMATS, }, @@ -1165,109 +1349,50 @@ static const struct snd_soc_component_driver aml_tdm_component = { .name = DRV_NAME, }; -struct tdm_chipinfo axg_tdma_chipinfo = { - .id = TDM_A, -}; +static int check_channel_mask(const char *str) +{ + int ret = -1; -struct tdm_chipinfo axg_tdmb_chipinfo = { - .id = TDM_B, -}; + if (!strncmp(str, "i2s_0/1", 7)) + ret = 0; + else if (!strncmp(str, "i2s_2/3", 7)) + ret = 1; + else if (!strncmp(str, "i2s_4/5", 7)) + ret = 2; + else if (!strncmp(str, "i2s_6/7", 7)) + ret = 3; + return ret; +} -struct tdm_chipinfo axg_tdmc_chipinfo = { - .id = TDM_C, -}; +/* spdif same source with i2s */ +static void parse_samesrc_channel_mask(struct aml_tdm *p_tdm) +{ + struct device_node *node = p_tdm->dev->of_node; + struct device_node *np = NULL; + const char *str = NULL; + int ret = 0; -struct tdm_chipinfo g12a_tdma_chipinfo = { - .id = TDM_A, - .sclk_ws_inv = true, - .oe_fn = true, - .clk_pad_ctl = true, - .same_src_fn = true, -}; + /* channel mask */ + np = of_get_child_by_name(node, "Channel_Mask"); + if (np == NULL) { + pr_info("No channel mask node %s\n", + "Channel_Mask"); + return; + } -struct tdm_chipinfo g12a_tdmb_chipinfo = { - .id = TDM_B, - .sclk_ws_inv = true, - .oe_fn = true, - .clk_pad_ctl = true, - .same_src_fn = true, -}; + /* If spdif is same source to i2s, + * it can be muxed to i2s 2 channels + */ + ret = of_property_read_string(np, + "Spdif_samesource_Channel_Mask", &str); + if (ret) { + pr_err("error:read Spdif_samesource_Channel_Mask\n"); + return; + } + p_tdm->lane_ss = check_channel_mask(str); -struct tdm_chipinfo g12a_tdmc_chipinfo = { - .id = TDM_C, - .sclk_ws_inv = true, - .oe_fn = true, - .clk_pad_ctl = true, - .same_src_fn = true, -}; - -struct tdm_chipinfo tl1_tdma_chipinfo = { - .id = TDM_A, - .sclk_ws_inv = true, - .oe_fn = true, - .clk_pad_ctl = true, - .same_src_fn = true, - .adc_fn = true, -}; - -struct tdm_chipinfo tl1_tdmb_chipinfo = { - .id = TDM_B, - .sclk_ws_inv = true, - .oe_fn = true, - .clk_pad_ctl = true, - .same_src_fn = true, - .adc_fn = true, -}; - -struct tdm_chipinfo tl1_tdmc_chipinfo = { - .id = TDM_C, - .sclk_ws_inv = true, - .oe_fn = true, - .clk_pad_ctl = true, - .same_src_fn = true, - .adc_fn = true, -}; - -static const struct of_device_id aml_tdm_device_id[] = { - { - .compatible = "amlogic, axg-snd-tdma", - .data = &axg_tdma_chipinfo, - }, - { - .compatible = "amlogic, axg-snd-tdmb", - .data = &axg_tdmb_chipinfo, - }, - { - .compatible = "amlogic, axg-snd-tdmc", - .data = &axg_tdmc_chipinfo, - }, - { - .compatible = "amlogic, g12a-snd-tdma", - .data = &g12a_tdma_chipinfo, - }, - { - .compatible = "amlogic, g12a-snd-tdmb", - .data = &g12a_tdmb_chipinfo, - }, - { - .compatible = "amlogic, g12a-snd-tdmc", - .data = &g12a_tdmc_chipinfo, - }, - { - .compatible = "amlogic, tl1-snd-tdma", - .data = &tl1_tdma_chipinfo, - }, - { - .compatible = "amlogic, tl1-snd-tdmb", - .data = &tl1_tdmb_chipinfo, - }, - { - .compatible = "amlogic, tl1-snd-tdmc", - .data = &tl1_tdmc_chipinfo, - }, - {}, -}; -MODULE_DEVICE_TABLE(of, aml_tdm_device_id); + pr_info("Channel_Mask: lane_ss = %d\n", p_tdm->lane_ss); +} static int aml_tdm_platform_probe(struct platform_device *pdev) { @@ -1293,7 +1418,12 @@ static int aml_tdm_platform_probe(struct platform_device *pdev) } p_tdm->chipinfo = p_chipinfo; p_tdm->id = p_chipinfo->id; - pr_info("%s, tdm ID = %u\n", __func__, p_tdm->id); + if (!p_chipinfo->lane_cnt) + p_chipinfo->lane_cnt = LANE_MAX1; + + p_tdm->lane_cnt = p_chipinfo->lane_cnt; + pr_info("%s, tdm ID = %u, lane_cnt = %d\n", __func__, + p_tdm->id, p_tdm->lane_cnt); /* get audio controller */ node_prt = of_get_parent(node); @@ -1323,12 +1453,25 @@ static int aml_tdm_platform_probe(struct platform_device *pdev) if (ret < 0) p_tdm->samesource_sel = -1; else { - p_tdm->samesrc_sysclk = devm_clk_get(&pdev->dev, - "samesource_sysclk"); - if (IS_ERR(p_tdm->samesrc_sysclk)) { + p_tdm->samesrc_srcpll = devm_clk_get(&pdev->dev, + "samesource_srcpll"); + if (IS_ERR(p_tdm->samesrc_srcpll)) { dev_err(&pdev->dev, - "Can't retrieve samesrc_sysclk clock\n"); - return PTR_ERR(p_tdm->samesrc_sysclk); + "Can't retrieve samesrc_srcpll clock\n"); + return PTR_ERR(p_tdm->samesrc_srcpll); + } + p_tdm->samesrc_clk = devm_clk_get(&pdev->dev, + "samesource_clk"); + if (IS_ERR(p_tdm->samesrc_clk)) { + dev_err(&pdev->dev, + "Can't retrieve samesrc_clk clock\n"); + return PTR_ERR(p_tdm->samesrc_clk); + } + ret = clk_set_parent(p_tdm->samesrc_clk, + p_tdm->samesrc_srcpll); + if (ret) { + dev_err(dev, "can't set samesource clock\n"); + return ret; } pr_info("TDM id %d samesource_sel:%d\n", p_tdm->id, @@ -1383,6 +1526,11 @@ static int aml_tdm_platform_probe(struct platform_device *pdev) if (ret < 0) p_tdm->setting.lane_lb_mask_in = 0x0; + dev_info(&pdev->dev, + "lane_mask_out = %x, lane_oe_mask_out = %x\n", + p_tdm->setting.lane_mask_out, + p_tdm->setting.lane_oe_mask_out); + p_tdm->clk = devm_clk_get(&pdev->dev, "clk_srcpll"); if (IS_ERR(p_tdm->clk)) { dev_err(&pdev->dev, "Can't retrieve mpll2 clock\n"); @@ -1411,9 +1559,20 @@ static int aml_tdm_platform_probe(struct platform_device *pdev) /*return PTR_ERR(p_tdm->pin_ctl);*/ } + /* mclk pad ctrl */ + ret = of_property_read_u32(node, "mclk_pad", + &p_tdm->mclk_pad); + if (ret < 0) + p_tdm->mclk_pad = -1; /* not use mclk in defalut. */ + p_tdm->dev = dev; + /* For debug to disable share buffer */ + p_tdm->en_share = 1; dev_set_drvdata(dev, p_tdm); + /* spdif same source with i2s */ + parse_samesrc_channel_mask(p_tdm); + ret = devm_snd_soc_register_component(dev, &aml_tdm_component, &aml_tdm_dai[p_tdm->id], 1); if (ret) { diff --git a/sound/soc/amlogic/auge/tdm_hw.c b/sound/soc/amlogic/auge/tdm_hw.c index 83874c90c79e..97dc1d593438 100644 --- a/sound/soc/amlogic/auge/tdm_hw.c +++ b/sound/soc/amlogic/auge/tdm_hw.c @@ -545,11 +545,27 @@ void aml_tdm_set_channel_mask( unsigned int offset, reg; if (stream == SNDRV_PCM_STREAM_PLAYBACK) { - offset = EE_AUDIO_TDMOUT_B_MASK0 - EE_AUDIO_TDMOUT_A_MASK0; - reg = EE_AUDIO_TDMOUT_A_MASK0 + offset * index; + if (lane >= LANE_MAX1) { + offset = EE_AUDIO_TDMOUT_B_MASK4 + - EE_AUDIO_TDMOUT_A_MASK4; + reg = EE_AUDIO_TDMOUT_A_MASK4 + offset * index; + lane -= LANE_MAX1; + } else { + offset = EE_AUDIO_TDMOUT_B_MASK0 + - EE_AUDIO_TDMOUT_A_MASK0; + reg = EE_AUDIO_TDMOUT_A_MASK0 + offset * index; + } } else { - offset = EE_AUDIO_TDMIN_B_MASK0 - EE_AUDIO_TDMIN_A_MASK0; - reg = EE_AUDIO_TDMIN_A_MASK0 + offset * index; + if (lane >= LANE_MAX1) { + offset = EE_AUDIO_TDMIN_B_MASK4 + - EE_AUDIO_TDMIN_A_MASK4; + reg = EE_AUDIO_TDMIN_A_MASK4 + offset * index; + lane -= LANE_MAX1; + } else { + offset = EE_AUDIO_TDMIN_B_MASK0 + - EE_AUDIO_TDMIN_A_MASK0; + reg = EE_AUDIO_TDMIN_A_MASK0 + offset * index; + } } aml_audiobus_write(actrl, reg + lane, mask); @@ -557,27 +573,39 @@ void aml_tdm_set_channel_mask( void aml_tdm_set_lane_channel_swap( struct aml_audio_controller *actrl, - int stream, int index, int swap) + int stream, int index, int swap0, int swap1) { unsigned int offset, reg; + pr_debug("\t %s swap0 = %#x, swap1 = %#x\n", + (stream == SNDRV_PCM_STREAM_PLAYBACK) ? "tdmout" : "tdmin", + swap0, + swap1); + if (stream == SNDRV_PCM_STREAM_PLAYBACK) { - // set lanes mask acordingly - offset = EE_AUDIO_TDMOUT_B_MASK0 - EE_AUDIO_TDMOUT_A_MASK0; - reg = EE_AUDIO_TDMOUT_A_MASK0 + offset * index; + offset = EE_AUDIO_TDMOUT_B_SWAP0 + - EE_AUDIO_TDMOUT_A_SWAP0; + reg = EE_AUDIO_TDMOUT_A_SWAP0 + offset * index; + aml_audiobus_write(actrl, reg, swap0); - pr_debug("\ttdmout swap val = %#x\n", swap); - offset = EE_AUDIO_TDMOUT_B_SWAP - EE_AUDIO_TDMOUT_A_SWAP; - reg = EE_AUDIO_TDMOUT_A_SWAP + offset * index; - aml_audiobus_write(actrl, reg, swap); + if (swap1) { + offset = EE_AUDIO_TDMOUT_B_SWAP1 + - EE_AUDIO_TDMOUT_A_SWAP1; + reg = EE_AUDIO_TDMOUT_A_SWAP1 + offset * index; + aml_audiobus_write(actrl, reg, swap1); + } } else { - offset = EE_AUDIO_TDMIN_B_MASK0 - EE_AUDIO_TDMIN_A_MASK0; - reg = EE_AUDIO_TDMIN_A_MASK0 + offset * index; + offset = EE_AUDIO_TDMIN_B_SWAP0 + - EE_AUDIO_TDMIN_A_SWAP0; + reg = EE_AUDIO_TDMIN_A_SWAP0 + offset * index; + aml_audiobus_write(actrl, reg, swap0); - pr_debug("\ttdmin swap val = %#x\n", swap); - offset = EE_AUDIO_TDMIN_B_SWAP - EE_AUDIO_TDMIN_A_SWAP; - reg = EE_AUDIO_TDMIN_A_SWAP + offset * index; - aml_audiobus_write(actrl, reg, swap); + if (swap1) { + offset = EE_AUDIO_TDMIN_B_SWAP1 + - EE_AUDIO_TDMIN_A_SWAP1; + reg = EE_AUDIO_TDMIN_A_SWAP1 + offset * index; + aml_audiobus_write(actrl, reg, swap1); + } } } @@ -637,29 +665,51 @@ void aml_tdmout_get_aed_info(int tdmout_id, *frddrtype = (val >> 4) & 0x7; } +void aml_tdmout_enable_gain(int tdmout_id, int en) +{ + unsigned int reg, offset; + + offset = EE_AUDIO_TDMOUT_B_CTRL1 + - EE_AUDIO_TDMOUT_A_CTRL1; + reg = EE_AUDIO_TDMOUT_A_CTRL1 + offset * tdmout_id; + audiobus_update_bits(reg, 0x1 << 26, !!en << 26); +} + void aml_tdm_clk_pad_select( struct aml_audio_controller *actrl, - int mpad, int mclk_sel, + int mpad, int mpad_offset, int mclk_sel, int tdm_index, int clk_sel) { unsigned int reg, mask_offset, val_offset; - // TODO: fix mclk - if (mpad == 0) { - mask_offset = 0x7 << 0; - val_offset = mclk_sel << 0; - } else if (mpad == 1) { - mask_offset = 0x7 << 4; - val_offset = mclk_sel << 4; - } else { - pr_err("unknown tdm mpad:%d\n", mpad); - return; - } - reg = EE_AUDIO_MST_PAD_CTRL0(0); - aml_audiobus_update_bits(actrl, reg, - mask_offset, val_offset); + if (mpad >= 0) { + switch (mpad) { + case 0: + mask_offset = 0x7 << 0; + val_offset = mclk_sel << 0; + break; + case 1: + mask_offset = 0x7 << 4; + val_offset = mclk_sel << 4; + break; + default: + mask_offset = 0; + val_offset = 0; + pr_info("unknown tdm mpad:%d\n", mpad); + break; + } - reg = EE_AUDIO_MST_PAD_CTRL1(0); + reg = EE_AUDIO_MST_PAD_CTRL0(mpad_offset); + if (actrl) + aml_audiobus_update_bits(actrl, reg, + mask_offset, val_offset); + else + audiobus_update_bits(reg, + mask_offset, val_offset); + } else + pr_warn("mclk is not configured\n"); + + reg = EE_AUDIO_MST_PAD_CTRL1(mpad_offset); switch (tdm_index) { case 0: mask_offset = 0x7 << 16 | 0x7 << 0; @@ -674,12 +724,15 @@ void aml_tdm_clk_pad_select( val_offset = clk_sel << 24 | clk_sel << 8; break; default: - pr_err("unknown tdm index:%d\n", tdm_index); + pr_err("unknown mclk pad, tdm index:%d\n", tdm_index); return; } - aml_audiobus_update_bits(actrl, reg, - mask_offset, val_offset); - + if (actrl) + aml_audiobus_update_bits(actrl, reg, + mask_offset, val_offset); + else + audiobus_update_bits(reg, + mask_offset, val_offset); } void i2s_to_hdmitx_ctrl(int tdm_index) @@ -698,15 +751,17 @@ void i2s_to_hdmitx_disable(void) { audiobus_write(EE_AUDIO_TOHDMITX_CTRL0, 0); } + void aml_tdm_mute_playback( struct aml_audio_controller *actrl, int tdm_index, - bool mute) + bool mute, + int lane_cnt) { unsigned int offset, reg; unsigned int mute_mask = 0xffffffff; unsigned int mute_val = 0; - int i = 0, lanes = 4; + int i = 0; if (mute) mute_val = 0xffffffff; @@ -714,19 +769,29 @@ void aml_tdm_mute_playback( offset = EE_AUDIO_TDMOUT_B_MUTE0 - EE_AUDIO_TDMOUT_A_MUTE0; reg = EE_AUDIO_TDMOUT_A_MUTE0 + offset * tdm_index; - for (i = 0; i < lanes; i++) + for (i = 0; i < LANE_MAX1; i++) aml_audiobus_update_bits(actrl, reg + i, mute_mask, mute_val); + + if (lane_cnt > LANE_MAX1) { + offset = EE_AUDIO_TDMOUT_B_MUTE4 + - EE_AUDIO_TDMOUT_A_MUTE4; + reg = EE_AUDIO_TDMOUT_A_MUTE4 + offset * tdm_index; + for (i = 0; i < LANE_MAX1; i++) + aml_audiobus_update_bits(actrl, reg + i, + mute_mask, mute_val); + } } void aml_tdm_mute_capture( struct aml_audio_controller *actrl, int tdm_index, - bool mute) + bool mute, + int lane_cnt) { unsigned int offset, reg; unsigned int mute_mask = 0xffffffff; unsigned int mute_val = 0; - int i = 0, lanes = 4; + int i = 0; if (mute) mute_val = 0xffffffff; @@ -734,7 +799,17 @@ void aml_tdm_mute_capture( offset = EE_AUDIO_TDMIN_B_MUTE0 - EE_AUDIO_TDMIN_A_MUTE0; reg = EE_AUDIO_TDMIN_A_MUTE0 + offset * tdm_index; - for (i = 0; i < lanes; i++) - aml_audiobus_update_bits(actrl, reg + i, mute_mask, mute_val); + for (i = 0; i < LANE_MAX1; i++) + aml_audiobus_update_bits(actrl, reg + i, + mute_mask, mute_val); + + if (lane_cnt > LANE_MAX1) { + offset = EE_AUDIO_TDMIN_B_MUTE4 + - EE_AUDIO_TDMIN_A_MUTE4; + reg = EE_AUDIO_TDMIN_A_MUTE4 + offset * tdm_index; + for (i = 0; i < LANE_MAX1; i++) + aml_audiobus_update_bits(actrl, reg + i, + mute_mask, mute_val); + } } diff --git a/sound/soc/amlogic/auge/tdm_hw.h b/sound/soc/amlogic/auge/tdm_hw.h index 791ecaabbabe..b47bf1e7c793 100644 --- a/sound/soc/amlogic/auge/tdm_hw.h +++ b/sound/soc/amlogic/auge/tdm_hw.h @@ -21,6 +21,15 @@ #include "audio_io.h" #include "regs.h" +#define TDM_A 0 +#define TDM_B 1 +#define TDM_C 2 + +#define LANE_MAX0 2 +#define LANE_MAX1 4 +#define LANE_MAX2 6 +#define LANE_MAX3 8 + // TODO: fix me, now based by tl1 enum tdmin_src { PAD_TDMINA_DIN = 0, @@ -71,6 +80,7 @@ extern void aml_tdm_arb_config( extern void aml_tdm_fifo_reset( struct aml_audio_controller *actrl, int stream, int index); +void aml_tdmout_enable_gain(int tdmout_id, int en); extern int tdmout_get_frddr_type(int bitwidth); @@ -117,7 +127,7 @@ extern void aml_tdm_set_channel_mask( extern void aml_tdm_set_lane_channel_swap( struct aml_audio_controller *actrl, - int stream, int index, int swap); + int stream, int index, int swap0, int swap1); extern void aml_tdm_set_bclk_ratio( struct aml_audio_controller *actrl, @@ -138,7 +148,7 @@ extern void aml_tdmout_get_aed_info(int tdmout_id, extern void aml_tdm_clk_pad_select( struct aml_audio_controller *actrl, - int mpad, int mclk_sel, + int mpad, int mpad_offset, int mclk_sel, int tdm_index, int clk_sel); extern void i2s_to_hdmitx_ctrl(int tdm_index); @@ -146,9 +156,11 @@ extern void i2s_to_hdmitx_disable(void); void aml_tdm_mute_playback( struct aml_audio_controller *actrl, int index, - bool mute); + bool mute, + int lane_cnt); void aml_tdm_mute_capture( struct aml_audio_controller *actrl, int tdm_index, - bool mute); + bool mute, + int lane_cnt); #endif diff --git a/sound/soc/amlogic/auge/tdm_match_table.c b/sound/soc/amlogic/auge/tdm_match_table.c new file mode 100644 index 000000000000..4fb318c38857 --- /dev/null +++ b/sound/soc/amlogic/auge/tdm_match_table.c @@ -0,0 +1,225 @@ +/* + * sound/soc/amlogic/auge/tdm_match_table.c + * + * Copyright (C) 2019 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +struct tdm_chipinfo { + /* device id */ + unsigned int id; + + /* lane max count */ + unsigned int lane_cnt; + + /* no eco, sclk_ws_inv for out */ + bool sclk_ws_inv; + + /* output en (oe) for pinmux */ + bool oe_fn; + + /* clk pad */ + bool no_mclkpad_ctrl; + + /* same source */ + bool same_src_fn; + + /* same source, spdif re-enable */ + bool same_src_spdif_reen; + + /* ACODEC_ADC function */ + bool adc_fn; + + /* mclk pad offset */ + bool mclkpad_no_offset; +}; + + +struct tdm_chipinfo axg_tdma_chipinfo = { + .id = TDM_A, + .no_mclkpad_ctrl = true, +}; + +struct tdm_chipinfo axg_tdmb_chipinfo = { + .id = TDM_B, + .no_mclkpad_ctrl = true, +}; + +struct tdm_chipinfo axg_tdmc_chipinfo = { + .id = TDM_C, + .no_mclkpad_ctrl = true, +}; + +struct tdm_chipinfo g12a_tdma_chipinfo = { + .id = TDM_A, + .sclk_ws_inv = true, + .oe_fn = true, + .same_src_fn = true, + .mclkpad_no_offset = true, +}; + +struct tdm_chipinfo g12a_tdmb_chipinfo = { + .id = TDM_B, + .sclk_ws_inv = true, + .oe_fn = true, + .same_src_fn = true, + .mclkpad_no_offset = true, +}; + +struct tdm_chipinfo g12a_tdmc_chipinfo = { + .id = TDM_C, + .sclk_ws_inv = true, + .oe_fn = true, + .same_src_fn = true, + .mclkpad_no_offset = true, +}; + +struct tdm_chipinfo tl1_tdma_chipinfo = { + .id = TDM_A, + .sclk_ws_inv = true, + .oe_fn = true, + .same_src_fn = true, + .adc_fn = true, +}; + +struct tdm_chipinfo tl1_tdmb_chipinfo = { + .id = TDM_B, + .sclk_ws_inv = true, + .oe_fn = true, + .same_src_fn = true, + .adc_fn = true, +}; + +struct tdm_chipinfo tl1_tdmc_chipinfo = { + .id = TDM_C, + .sclk_ws_inv = true, + .oe_fn = true, + .same_src_fn = true, + .adc_fn = true, +}; + +struct tdm_chipinfo sm1_tdma_chipinfo = { + .id = TDM_A, + .sclk_ws_inv = true, + .oe_fn = true, + .same_src_fn = true, + .lane_cnt = LANE_MAX0, +}; + +struct tdm_chipinfo sm1_tdmb_chipinfo = { + .id = TDM_B, + .sclk_ws_inv = true, + .oe_fn = true, + .same_src_fn = true, + .lane_cnt = LANE_MAX3, +}; + +struct tdm_chipinfo sm1_tdmc_chipinfo = { + .id = TDM_C, + .sclk_ws_inv = true, + .oe_fn = true, + .same_src_fn = true, + .lane_cnt = LANE_MAX1, +}; + +struct tdm_chipinfo tm2_tdma_chipinfo = { + .id = TDM_A, + .sclk_ws_inv = true, + .oe_fn = true, + .same_src_fn = true, + .adc_fn = true, + .lane_cnt = LANE_MAX3, +}; + +struct tdm_chipinfo tm2_tdmb_chipinfo = { + .id = TDM_B, + .sclk_ws_inv = true, + .oe_fn = true, + .same_src_fn = true, + .adc_fn = true, + .lane_cnt = LANE_MAX1, +}; + +struct tdm_chipinfo tm2_tdmc_chipinfo = { + .id = TDM_C, + .sclk_ws_inv = true, + .oe_fn = true, + .same_src_fn = true, + .adc_fn = true, + .lane_cnt = LANE_MAX1, +}; + +static const struct of_device_id aml_tdm_device_id[] = { + { + .compatible = "amlogic, axg-snd-tdma", + .data = &axg_tdma_chipinfo, + }, + { + .compatible = "amlogic, axg-snd-tdmb", + .data = &axg_tdmb_chipinfo, + }, + { + .compatible = "amlogic, axg-snd-tdmc", + .data = &axg_tdmc_chipinfo, + }, + { + .compatible = "amlogic, g12a-snd-tdma", + .data = &g12a_tdma_chipinfo, + }, + { + .compatible = "amlogic, g12a-snd-tdmb", + .data = &g12a_tdmb_chipinfo, + }, + { + .compatible = "amlogic, g12a-snd-tdmc", + .data = &g12a_tdmc_chipinfo, + }, + { + .compatible = "amlogic, tl1-snd-tdma", + .data = &tl1_tdma_chipinfo, + }, + { + .compatible = "amlogic, tl1-snd-tdmb", + .data = &tl1_tdmb_chipinfo, + }, + { + .compatible = "amlogic, tl1-snd-tdmc", + .data = &tl1_tdmc_chipinfo, + }, + { + .compatible = "amlogic, sm1-snd-tdma", + .data = &sm1_tdma_chipinfo, + }, + { + .compatible = "amlogic, sm1-snd-tdmb", + .data = &sm1_tdmb_chipinfo, + }, + { + .compatible = "amlogic, sm1-snd-tdmc", + .data = &sm1_tdmc_chipinfo, + }, + { + .compatible = "amlogic, tm2-snd-tdma", + .data = &tm2_tdma_chipinfo, + }, + { + .compatible = "amlogic, tm2-snd-tdmb", + .data = &tm2_tdmb_chipinfo, + }, + { + .compatible = "amlogic, tm2-snd-tdmc", + .data = &tm2_tdmc_chipinfo, + }, + {}, +}; +MODULE_DEVICE_TABLE(of, aml_tdm_device_id); diff --git a/sound/soc/amlogic/auge/tm2,clocks.c b/sound/soc/amlogic/auge/tm2,clocks.c new file mode 100644 index 000000000000..aed576ec4ded --- /dev/null +++ b/sound/soc/amlogic/auge/tm2,clocks.c @@ -0,0 +1,392 @@ +/* + * sound/soc/amlogic/auge/tm2_clocks.c + * + * Copyright (C) 2019 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. + * + */ +#undef pr_fmt +#define pr_fmt(fmt) "tm2_audio_clocks: " fmt + +#include + +#include "audio_clks.h" +#include "regs.h" + +static spinlock_t aclk_lock; + +static const char *const mclk_parent_names[] = { + "mpll0", "mpll1", "mpll2", "mpll3", "hifi_pll", + "fclk_div3", "fclk_div4", "fclk_div5"}; + +static const char *const audioclk_parent_names[] = { + "mclk_a", "mclk_b", "mclk_c", "mclk_d", "mclk_e", + "mclk_f", "i_slv_sclk_a", "i_slv_sclk_b", "i_slv_sclk_c", + "i_slv_sclk_d", "i_slv_sclk_e", "i_slv_sclk_f", "i_slv_sclk_g", + "i_slv_sclk_h", "i_slv_sclk_i", "i_slv_sclk_j"}; + +CLOCK_GATE(audio_ddr_arb, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 0); +CLOCK_GATE(audio_pdm, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 1); +CLOCK_GATE(audio_tdmina, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 2); +CLOCK_GATE(audio_tdminb, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 3); +CLOCK_GATE(audio_tdminc, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 4); +CLOCK_GATE(audio_tdminlb, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 5); +CLOCK_GATE(audio_tdmouta, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 6); +CLOCK_GATE(audio_tdmoutb, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 7); +CLOCK_GATE(audio_tdmoutc, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 8); +CLOCK_GATE(audio_frddra, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 9); +CLOCK_GATE(audio_frddrb, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 10); +CLOCK_GATE(audio_frddrc, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 11); +CLOCK_GATE(audio_toddra, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 12); +CLOCK_GATE(audio_toddrb, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 13); +CLOCK_GATE(audio_toddrc, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 14); +CLOCK_GATE(audio_loopbacka, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 15); +CLOCK_GATE(audio_spdifin, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 16); +CLOCK_GATE(audio_spdifout, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 17); +CLOCK_GATE(audio_resamplea, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 18); +CLOCK_GATE(audio_reserved0, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 19); +CLOCK_GATE(audio_reserved1, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 20); +CLOCK_GATE(audio_spdifoutb, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 21); +CLOCK_GATE(audio_eqdrc, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 22); +CLOCK_GATE(audio_reserved2, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 23); +CLOCK_GATE(audio_reserved3, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 24); +CLOCK_GATE(audio_reserved4, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 25); +CLOCK_GATE(audio_resampleb, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 26); +CLOCK_GATE(audio_tovad, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 27); +CLOCK_GATE(audio_audiolocker, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 28); +CLOCK_GATE(audio_spdifin_lb, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 29); +CLOCK_GATE(audio_fratv, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 30); +CLOCK_GATE(audio_frhdmirx, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN0), 31); + +CLOCK_GATE(audio_frddrd, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN1), 0); +CLOCK_GATE(audio_toddrd, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN1), 1); +CLOCK_GATE(audio_loopbackb, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN1), 2); +CLOCK_GATE(audio_frddre, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN1), 3); +CLOCK_GATE(audio_toddre, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN1), 4); +CLOCK_GATE(audio_earctx, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN1), 5); +CLOCK_GATE(audio_earcrx, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN1), 6); +CLOCK_GATE(audio_resampleb_old, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN1), 7); +CLOCK_GATE(audio_locker, AUD_ADDR_OFFSET(EE_AUDIO_CLK_GATE_EN1), 8); + + +static struct clk_gate *tm2_audio_clk_gates[] = { + &audio_ddr_arb, + &audio_pdm, + &audio_tdmina, + &audio_tdminb, + &audio_tdminc, + &audio_tdminlb, + &audio_tdmouta, + &audio_tdmoutb, + &audio_tdmoutc, + &audio_frddra, + &audio_frddrb, + &audio_frddrc, + &audio_toddra, + &audio_toddrb, + &audio_toddrc, + &audio_loopbacka, + &audio_spdifin, + &audio_spdifout, + &audio_resamplea, + &audio_reserved0, + &audio_reserved1, + &audio_spdifoutb, + &audio_eqdrc, + &audio_reserved2, + &audio_reserved3, + &audio_reserved4, + &audio_resampleb, + &audio_tovad, + &audio_audiolocker, + &audio_spdifin_lb, + &audio_fratv, + &audio_frhdmirx, + + &audio_frddrd, + &audio_toddrd, + &audio_loopbackb, + &audio_frddre, + &audio_toddre, + &audio_earctx, + &audio_earcrx, + &audio_resampleb_old, + &audio_locker, +}; + +/* Array of all clocks provided by this provider */ +static struct clk_hw *tm2_audio_clk_hws[] = { + [CLKID_AUDIO_GATE_DDR_ARB] = &audio_ddr_arb.hw, + [CLKID_AUDIO_GATE_PDM] = &audio_pdm.hw, + [CLKID_AUDIO_GATE_TDMINA] = &audio_tdmina.hw, + [CLKID_AUDIO_GATE_TDMINB] = &audio_tdminb.hw, + [CLKID_AUDIO_GATE_TDMINC] = &audio_tdminc.hw, + [CLKID_AUDIO_GATE_TDMINLB] = &audio_tdminlb.hw, + [CLKID_AUDIO_GATE_TDMOUTA] = &audio_tdmouta.hw, + [CLKID_AUDIO_GATE_TDMOUTB] = &audio_tdmoutb.hw, + [CLKID_AUDIO_GATE_TDMOUTC] = &audio_tdmoutc.hw, + [CLKID_AUDIO_GATE_FRDDRA] = &audio_frddra.hw, + [CLKID_AUDIO_GATE_FRDDRB] = &audio_frddrb.hw, + [CLKID_AUDIO_GATE_FRDDRC] = &audio_frddrc.hw, + [CLKID_AUDIO_GATE_TODDRA] = &audio_toddra.hw, + [CLKID_AUDIO_GATE_TODDRB] = &audio_toddrb.hw, + [CLKID_AUDIO_GATE_TODDRC] = &audio_toddrc.hw, + [CLKID_AUDIO_GATE_LOOPBACKA] = &audio_loopbacka.hw, + [CLKID_AUDIO_GATE_SPDIFIN] = &audio_spdifin.hw, + [CLKID_AUDIO_GATE_SPDIFOUT_A] = &audio_spdifout.hw, + [CLKID_AUDIO_GATE_RESAMPLEA] = &audio_resamplea.hw, + [CLKID_AUDIO_GATE_RESERVED0] = &audio_reserved0.hw, + [CLKID_AUDIO_GATE_RESERVED1] = &audio_reserved1.hw, + [CLKID_AUDIO_GATE_SPDIFOUT_B] = &audio_spdifoutb.hw, + [CLKID_AUDIO_GATE_EQDRC] = &audio_eqdrc.hw, + [CLKID_AUDIO_GATE_RESERVED2] = &audio_reserved2.hw, + [CLKID_AUDIO_GATE_RESERVED3] = &audio_reserved3.hw, + [CLKID_AUDIO_GATE_RESERVED4] = &audio_reserved4.hw, + [CLKID_AUDIO_GATE_RESAMPLEB] = &audio_resampleb.hw, + [CLKID_AUDIO_GATE_TOVAD] = &audio_tovad.hw, + [CLKID_AUDIO_GATE_AUDIOLOCKER] = &audio_audiolocker.hw, + [CLKID_AUDIO_GATE_SPDIFIN_LB] = &audio_spdifin_lb.hw, + [CLKID_AUDIO_GATE_FRATV] = &audio_fratv.hw, + [CLKID_AUDIO_GATE_FRHDMIRX] = &audio_frhdmirx.hw, + + [CLKID_AUDIO_GATE_FRDDRD] = &audio_frddrd.hw, + [CLKID_AUDIO_GATE_TODDRD] = &audio_toddrd.hw, + [CLKID_AUDIO_GATE_LOOPBACKB] = &audio_loopbackb.hw, + [CLKID_AUDIO_GATE_FRDDRE] = &audio_frddre.hw, + [CLKID_AUDIO_GATE_TODDRE] = &audio_toddre.hw, + [CLKID_AUDIO_GATE_EARCTX] = &audio_earctx.hw, + [CLKID_AUDIO_GATE_EARCRX] = &audio_earcrx.hw, + [CLKID_AUDIO_GATE_RESAMPLEB_OLD] = &audio_resampleb_old.hw, + [CLKID_AUDIO_GATE_LOCKER] = &audio_locker.hw, +}; + +static int tm2_clk_gates_init(struct clk **clks, void __iomem *iobase) +{ + int clkid; + + if (ARRAY_SIZE(tm2_audio_clk_gates) != MCLK_BASE) { + pr_err("check clk gates number\n"); + return -EINVAL; + } + + for (clkid = 0; clkid < MCLK_BASE; clkid++) { + tm2_audio_clk_gates[clkid]->reg = iobase; + clks[clkid] = clk_register(NULL, tm2_audio_clk_hws[clkid]); + WARN_ON(IS_ERR_OR_NULL(clks[clkid])); + } + + return 0; +} + +/* mclk_a */ +CLOCK_COM_MUX(mclk_a, AUD_ADDR_OFFSET(EE_AUDIO_MCLK_A_CTRL(1)), 0x7, 24); +CLOCK_COM_DIV(mclk_a, AUD_ADDR_OFFSET(EE_AUDIO_MCLK_A_CTRL(1)), 0, 16); +CLOCK_COM_GATE(mclk_a, AUD_ADDR_OFFSET(EE_AUDIO_MCLK_A_CTRL(1)), 31); +/* mclk_b */ +CLOCK_COM_MUX(mclk_b, AUD_ADDR_OFFSET(EE_AUDIO_MCLK_B_CTRL(1)), 0x7, 24); +CLOCK_COM_DIV(mclk_b, AUD_ADDR_OFFSET(EE_AUDIO_MCLK_B_CTRL(1)), 0, 16); +CLOCK_COM_GATE(mclk_b, AUD_ADDR_OFFSET(EE_AUDIO_MCLK_B_CTRL(1)), 31); +/* mclk_c */ +CLOCK_COM_MUX(mclk_c, AUD_ADDR_OFFSET(EE_AUDIO_MCLK_C_CTRL(1)), 0x7, 24); +CLOCK_COM_DIV(mclk_c, AUD_ADDR_OFFSET(EE_AUDIO_MCLK_C_CTRL(1)), 0, 16); +CLOCK_COM_GATE(mclk_c, AUD_ADDR_OFFSET(EE_AUDIO_MCLK_C_CTRL(1)), 31); +/* mclk_d */ +CLOCK_COM_MUX(mclk_d, AUD_ADDR_OFFSET(EE_AUDIO_MCLK_D_CTRL(1)), 0x7, 24); +CLOCK_COM_DIV(mclk_d, AUD_ADDR_OFFSET(EE_AUDIO_MCLK_D_CTRL(1)), 0, 16); +CLOCK_COM_GATE(mclk_d, AUD_ADDR_OFFSET(EE_AUDIO_MCLK_D_CTRL(1)), 31); +/* mclk_e */ +CLOCK_COM_MUX(mclk_e, AUD_ADDR_OFFSET(EE_AUDIO_MCLK_E_CTRL(1)), 0x7, 24); +CLOCK_COM_DIV(mclk_e, AUD_ADDR_OFFSET(EE_AUDIO_MCLK_E_CTRL(1)), 0, 16); +CLOCK_COM_GATE(mclk_e, AUD_ADDR_OFFSET(EE_AUDIO_MCLK_E_CTRL(1)), 31); +/* mclk_f */ +CLOCK_COM_MUX(mclk_f, AUD_ADDR_OFFSET(EE_AUDIO_MCLK_F_CTRL(1)), 0x7, 24); +CLOCK_COM_DIV(mclk_f, AUD_ADDR_OFFSET(EE_AUDIO_MCLK_F_CTRL(1)), 0, 16); +CLOCK_COM_GATE(mclk_f, AUD_ADDR_OFFSET(EE_AUDIO_MCLK_F_CTRL(1)), 31); +/* spdifin */ +CLOCK_COM_MUX(spdifin, AUD_ADDR_OFFSET(EE_AUDIO_CLK_SPDIFIN_CTRL), 0x7, 24); +CLOCK_COM_DIV(spdifin, AUD_ADDR_OFFSET(EE_AUDIO_CLK_SPDIFIN_CTRL), 0, 8); +CLOCK_COM_GATE(spdifin, AUD_ADDR_OFFSET(EE_AUDIO_CLK_SPDIFIN_CTRL), 31); +/* spdifout */ +CLOCK_COM_MUX(spdifout, AUD_ADDR_OFFSET(EE_AUDIO_CLK_SPDIFOUT_CTRL), 0x7, 24); +CLOCK_COM_DIV(spdifout, AUD_ADDR_OFFSET(EE_AUDIO_CLK_SPDIFOUT_CTRL), 0, 10); +CLOCK_COM_GATE(spdifout, AUD_ADDR_OFFSET(EE_AUDIO_CLK_SPDIFOUT_CTRL), 31); +/* audio resample_a */ +CLOCK_COM_MUX(resample_a, + AUD_ADDR_OFFSET(EE_AUDIO_CLK_RESAMPLEA_CTRL), 0xf, 24); +CLOCK_COM_DIV(resample_a, AUD_ADDR_OFFSET(EE_AUDIO_CLK_RESAMPLEA_CTRL), 0, 8); +CLOCK_COM_GATE(resample_a, AUD_ADDR_OFFSET(EE_AUDIO_CLK_RESAMPLEA_CTRL), 31); +/* audio locker_out */ +CLOCK_COM_MUX(locker_out, AUD_ADDR_OFFSET(EE_AUDIO_CLK_LOCKER_CTRL), 0xf, 24); +CLOCK_COM_DIV(locker_out, AUD_ADDR_OFFSET(EE_AUDIO_CLK_LOCKER_CTRL), 16, 8); +CLOCK_COM_GATE(locker_out, AUD_ADDR_OFFSET(EE_AUDIO_CLK_LOCKER_CTRL), 31); +/* audio locker_in */ +CLOCK_COM_MUX(locker_in, AUD_ADDR_OFFSET(EE_AUDIO_CLK_LOCKER_CTRL), 0xf, 8); +CLOCK_COM_DIV(locker_in, AUD_ADDR_OFFSET(EE_AUDIO_CLK_LOCKER_CTRL), 0, 8); +CLOCK_COM_GATE(locker_in, AUD_ADDR_OFFSET(EE_AUDIO_CLK_LOCKER_CTRL), 15); +/* pdmin0 */ +CLOCK_COM_MUX(pdmin0, AUD_ADDR_OFFSET(EE_AUDIO_CLK_PDMIN_CTRL0), 0x7, 24); +CLOCK_COM_DIV(pdmin0, AUD_ADDR_OFFSET(EE_AUDIO_CLK_PDMIN_CTRL0), 0, 16); +CLOCK_COM_GATE(pdmin0, AUD_ADDR_OFFSET(EE_AUDIO_CLK_PDMIN_CTRL0), 31); +/* pdmin1 */ +CLOCK_COM_MUX(pdmin1, AUD_ADDR_OFFSET(EE_AUDIO_CLK_PDMIN_CTRL1), 0x7, 24); +CLOCK_COM_DIV(pdmin1, AUD_ADDR_OFFSET(EE_AUDIO_CLK_PDMIN_CTRL1), 0, 16); +CLOCK_COM_GATE(pdmin1, AUD_ADDR_OFFSET(EE_AUDIO_CLK_PDMIN_CTRL1), 31); +/* spdifout b*/ +CLOCK_COM_MUX(spdifout_b, + AUD_ADDR_OFFSET(EE_AUDIO_CLK_SPDIFOUT_B_CTRL), 0x7, 24); +CLOCK_COM_DIV(spdifout_b, AUD_ADDR_OFFSET(EE_AUDIO_CLK_SPDIFOUT_B_CTRL), 0, 10); +CLOCK_COM_GATE(spdifout_b, AUD_ADDR_OFFSET(EE_AUDIO_CLK_SPDIFOUT_B_CTRL), 31); +/* audio resample_b */ +CLOCK_COM_MUX(resample_b, + AUD_ADDR_OFFSET(EE_AUDIO_CLK_RESAMPLEB_CTRL), 0xf, 24); +CLOCK_COM_DIV(resample_b, AUD_ADDR_OFFSET(EE_AUDIO_CLK_RESAMPLEB_CTRL), 0, 8); +CLOCK_COM_GATE(resample_b, AUD_ADDR_OFFSET(EE_AUDIO_CLK_RESAMPLEB_CTRL), 31); +/* spdifin_lb, div is a fake */ +CLOCK_COM_MUX(spdifin_lb, + AUD_ADDR_OFFSET(EE_AUDIO_CLK_SPDIFOUT_B_CTRL), 0x1, 30); +CLOCK_COM_DIV(spdifin_lb, AUD_ADDR_OFFSET(EE_AUDIO_CLK_SPDIFOUT_B_CTRL), 0, 29); +CLOCK_COM_GATE(spdifin_lb, AUD_ADDR_OFFSET(EE_AUDIO_CLK_SPDIFOUT_B_CTRL), 31); +/* audio eqdrc */ +CLOCK_COM_MUX(eqdrc, AUD_ADDR_OFFSET(EE_AUDIO_CLK_EQDRC_CTRL0), 0x7, 24); +CLOCK_COM_DIV(eqdrc, AUD_ADDR_OFFSET(EE_AUDIO_CLK_EQDRC_CTRL0), 0, 16); +CLOCK_COM_GATE(eqdrc, AUD_ADDR_OFFSET(EE_AUDIO_CLK_EQDRC_CTRL0), 31); +/* audio vad */ +CLOCK_COM_MUX(vad, AUD_ADDR_OFFSET(EE_AUDIO_VAD_CLK_CTRL), 0x7, 24); +CLOCK_COM_DIV(vad, AUD_ADDR_OFFSET(EE_AUDIO_VAD_CLK_CTRL), 0, 16); +CLOCK_COM_GATE(vad, AUD_ADDR_OFFSET(EE_AUDIO_VAD_CLK_CTRL), 31); +/* EARC TX CMDC */ +CLOCK_COM_MUX(earctx_cmdc, + AUD_ADDR_OFFSET(EE_AUDIO_EARCTX_CMDC_CLK_CTRL), 0x7, 24); +CLOCK_COM_DIV(earctx_cmdc, + AUD_ADDR_OFFSET(EE_AUDIO_EARCTX_CMDC_CLK_CTRL), 0, 16); +CLOCK_COM_GATE(earctx_cmdc, + AUD_ADDR_OFFSET(EE_AUDIO_EARCTX_CMDC_CLK_CTRL), 31); +/* EARC TX DMAC */ +CLOCK_COM_MUX(earctx_dmac, + AUD_ADDR_OFFSET(EE_AUDIO_EARCTX_DMAC_CLK_CTRL), 0x7, 24); +CLOCK_COM_DIV(earctx_dmac, + AUD_ADDR_OFFSET(EE_AUDIO_EARCTX_DMAC_CLK_CTRL), 0, 16); +CLOCK_COM_GATE(earctx_dmac, + AUD_ADDR_OFFSET(EE_AUDIO_EARCTX_DMAC_CLK_CTRL), 31); +/* EARC RX CMDC */ +CLOCK_COM_MUX(earcrx_cmdc, + AUD_ADDR_OFFSET(EE_AUDIO_EARCRX_CMDC_CLK_CTRL), 0x7, 24); +CLOCK_COM_DIV(earcrx_cmdc, + AUD_ADDR_OFFSET(EE_AUDIO_EARCRX_CMDC_CLK_CTRL), 0, 16); +CLOCK_COM_GATE(earcrx_cmdc, + AUD_ADDR_OFFSET(EE_AUDIO_EARCRX_CMDC_CLK_CTRL), 31); +/* EARC RX DMAC */ +CLOCK_COM_MUX(earcrx_dmac, + AUD_ADDR_OFFSET(EE_AUDIO_EARCRX_DMAC_CLK_CTRL), 0x7, 24); +CLOCK_COM_DIV(earcrx_dmac, + AUD_ADDR_OFFSET(EE_AUDIO_EARCRX_DMAC_CLK_CTRL), 0, 16); +CLOCK_COM_GATE(earcrx_dmac, + AUD_ADDR_OFFSET(EE_AUDIO_EARCRX_DMAC_CLK_CTRL), 31); + +static int tm2_clks_init(struct clk **clks, void __iomem *iobase) +{ + IOMAP_COM_CLK(mclk_a, iobase); + clks[CLKID_AUDIO_MCLK_A] = REGISTER_CLK_COM(mclk_a); + WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_MCLK_A])); + + IOMAP_COM_CLK(mclk_b, iobase); + clks[CLKID_AUDIO_MCLK_B] = REGISTER_CLK_COM(mclk_b); + WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_MCLK_B])); + + IOMAP_COM_CLK(mclk_c, iobase); + clks[CLKID_AUDIO_MCLK_C] = REGISTER_CLK_COM(mclk_c); + WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_MCLK_C])); + + IOMAP_COM_CLK(mclk_d, iobase); + clks[CLKID_AUDIO_MCLK_D] = REGISTER_CLK_COM(mclk_d); + WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_MCLK_D])); + + IOMAP_COM_CLK(mclk_e, iobase); + clks[CLKID_AUDIO_MCLK_E] = REGISTER_CLK_COM(mclk_e); + WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_MCLK_E])); + + IOMAP_COM_CLK(mclk_f, iobase); + clks[CLKID_AUDIO_MCLK_F] = REGISTER_CLK_COM(mclk_f); + WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_MCLK_F])); + + IOMAP_COM_CLK(spdifin, iobase); + clks[CLKID_AUDIO_SPDIFIN] = REGISTER_CLK_COM(spdifin); + WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_SPDIFIN])); + + IOMAP_COM_CLK(spdifout, iobase); + clks[CLKID_AUDIO_SPDIFOUT_A] = REGISTER_CLK_COM(spdifout); + WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_SPDIFOUT_A])); + + IOMAP_COM_CLK(resample_a, iobase); + clks[CLKID_AUDIO_RESAMPLE_A] = REGISTER_AUDIOCLK_COM(resample_a); + WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_RESAMPLE_A])); + + IOMAP_COM_CLK(locker_out, iobase); + clks[CLKID_AUDIO_LOCKER_OUT] = REGISTER_AUDIOCLK_COM(locker_out); + WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_LOCKER_OUT])); + + IOMAP_COM_CLK(locker_in, iobase); + clks[CLKID_AUDIO_LOCKER_IN] = REGISTER_AUDIOCLK_COM(locker_in); + WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_LOCKER_IN])); + + IOMAP_COM_CLK(pdmin0, iobase); + clks[CLKID_AUDIO_PDMIN0] = REGISTER_CLK_COM(pdmin0); + WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_PDMIN0])); + + IOMAP_COM_CLK(pdmin1, iobase); + clks[CLKID_AUDIO_PDMIN1] = REGISTER_CLK_COM(pdmin1); + WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_PDMIN1])); + + IOMAP_COM_CLK(spdifout_b, iobase); + clks[CLKID_AUDIO_SPDIFOUT_B] = REGISTER_CLK_COM(spdifout_b); + WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_SPDIFOUT_B])); + + IOMAP_COM_CLK(resample_b, iobase); + clks[CLKID_AUDIO_RESAMPLE_B] = REGISTER_AUDIOCLK_COM(resample_b); + WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_RESAMPLE_B])); + + IOMAP_COM_CLK(spdifin_lb, iobase); + clks[CLKID_AUDIO_SPDIFIN_LB] = REGISTER_CLK_COM(spdifin_lb); + WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_SPDIFIN_LB])); + + IOMAP_COM_CLK(eqdrc, iobase); + clks[CLKID_AUDIO_EQDRC] = REGISTER_CLK_COM(eqdrc); + WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_EQDRC])); + + IOMAP_COM_CLK(vad, iobase); + clks[CLKID_AUDIO_VAD] = REGISTER_CLK_COM(vad); + WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_VAD])); + + IOMAP_COM_CLK(earctx_cmdc, iobase); + clks[CLKID_EARCTX_CMDC] = REGISTER_CLK_COM(earctx_cmdc); + WARN_ON(IS_ERR_OR_NULL(clks[CLKID_EARCTX_CMDC])); + + IOMAP_COM_CLK(earctx_dmac, iobase); + clks[CLKID_EARCTX_DMAC] = REGISTER_CLK_COM(earctx_dmac); + WARN_ON(IS_ERR_OR_NULL(clks[CLKID_EARCTX_DMAC])); + + IOMAP_COM_CLK(earcrx_cmdc, iobase); + clks[CLKID_EARCRX_CMDC] = REGISTER_CLK_COM(earcrx_cmdc); + WARN_ON(IS_ERR_OR_NULL(clks[CLKID_EARCRX_CMDC])); + + IOMAP_COM_CLK(earcrx_dmac, iobase); + clks[CLKID_EARCRX_DMAC] = REGISTER_CLK_COM(earcrx_dmac); + WARN_ON(IS_ERR_OR_NULL(clks[CLKID_EARCRX_DMAC])); + + return 0; +} + +struct audio_clk_init tm2_audio_clks_init = { + .clk_num = NUM_AUDIO_CLKS, + .clk_gates = tm2_clk_gates_init, + .clks = tm2_clks_init, +}; diff --git a/sound/soc/amlogic/auge/vad.c b/sound/soc/amlogic/auge/vad.c index 6738fdf63b97..8a260bbb7b5d 100644 --- a/sound/soc/amlogic/auge/vad.c +++ b/sound/soc/amlogic/auge/vad.c @@ -32,10 +32,17 @@ #include #include +#include +#include +#include + #include #include #include +#include +#include + #include "vad_hw_coeff.c" #include "vad_hw.h" #include "vad.h" @@ -44,6 +51,12 @@ #define DMA_BUFFER_BYTES_MAX (2 * 1024 * 1024) + +#define VAD_READ_FRAME_COUNT (1024 / 2) + +/*#define __VAD_DUMP_DATA__*/ +#define VAD_DUMP_FILE_NAME "/mnt/vaddump.pcm" + enum vad_level { LEVEL_USER, LEVEL_KERNEL, @@ -52,6 +65,7 @@ enum vad_level { struct vad { struct aml_audio_controller *actrl; struct device *dev; + struct input_dev *input_device; struct clk *gate; struct clk *pll; @@ -59,13 +73,13 @@ struct vad { struct toddr *tddr; - struct tasklet_struct tasklet; + char *buf; + struct task_struct *thread; struct snd_dma_buffer dma_buffer; unsigned int start_last; unsigned int end_last; unsigned int addr; - int switch_buffer; /* vad flag interrupt */ @@ -92,6 +106,15 @@ struct vad { * 0: check hot word in user space */ enum vad_level level; + + int (*callback)(char *buf, int frames, int rate, + int channels, int bitdepth); + +#ifdef __VAD_DUMP_DATA__ + struct file *fp; + mm_segment_t fs; + loff_t pos; +#endif }; static struct vad *s_vad; @@ -110,6 +133,34 @@ static struct vad *get_vad(void) return p_vad; } +static void vad_key_report(void) +{ + struct vad *p_vad = get_vad(); + + if (!p_vad) + return; + pr_info("%s\n", __func__); + + input_event(p_vad->input_device, EV_KEY, KEY_POWER, 1); + input_sync(p_vad->input_device); + input_event(p_vad->input_device, EV_KEY, KEY_POWER, 0); + input_sync(p_vad->input_device); +} + +static void vad_input_device_init(struct vad *pvad) +{ + pvad->input_device->name = "vad_keypad"; + pvad->input_device->phys = "vad_keypad/input3"; + pvad->input_device->dev.parent = pvad->dev; + pvad->input_device->id.bustype = BUS_ISA; + pvad->input_device->id.vendor = 0x0001; + pvad->input_device->id.product = 0x0001; + pvad->input_device->id.version = 0x0100; + pvad->input_device->evbit[0] = BIT_MASK(EV_KEY); + pvad->input_device->keybit[BIT_WORD(BTN_0)] = BIT_MASK(BTN_0); + set_bit(KEY_POWER, pvad->input_device->keybit); +} + static bool vad_is_enable(void) { struct vad *p_vad = get_vad(); @@ -156,46 +207,200 @@ bool vad_pdm_is_running(void) return false; } -static void vad_notify_user_space(struct device *dev) +static void vad_notify_user_space(struct vad *p_vad) { pr_info("Notify to wake up user space\n"); - pm_wakeup_event(dev, 2000); + pm_wakeup_event(p_vad->dev, 2000); + p_vad->addr = 0; + vad_key_report(); } -static int vad_engine_check(void) +/* For test */ +static int vad_in_kernel_test; +static int vad_wakeup_count; + +int register_vad_callback(int (*callback)(char *, int, int, int, int)) { - return 1; + struct vad *p_vad = get_vad(); + + if (!p_vad) + return -1; + + p_vad->callback = callback; + return 0; +} +EXPORT_SYMBOL(register_vad_callback); + +void unregister_vad_callback(void) +{ + struct vad *p_vad = get_vad(); + + if (!p_vad) + return; + + p_vad->callback = NULL; +} +EXPORT_SYMBOL(unregister_vad_callback); + +/* transfer audio data to algorithm + * 0: no wake word found + * 1: contained wake word, should wake up system + */ +static int vad_transfer_data_to_algorithm( + struct vad *p_vad, char *buf, int frames, + int rate, int channels, int bitdepth) +{ + int ret = 0; + /* TODO: for test */ + if (vad_in_kernel_test) { + + if (vad_wakeup_count < 50) + return 0; + + vad_wakeup_count = 0; + return 1; + } + + /* Do check by algorithm */ + if (p_vad->callback != NULL) + ret = p_vad->callback(buf, frames, rate, channels, bitdepth); + + return ret; } /* Check buffer in kernel for VAD */ -static void vad_transfer_buffer_output(struct vad *p_vad) +static int vad_engine_check(struct vad *p_vad) { + unsigned char *hwbuf; + int bytes, read_bytes; + int start, end, size, last_addr, curr_addr; + int chnum, bytes_per_sample; + int frame_count = VAD_READ_FRAME_COUNT; - for (;;) { - if (vad_engine_check()) { - vad_notify_user_space(p_vad->dev); - break; + if (!p_vad->tddr || !p_vad->tddr->actrl || + !p_vad->tddr->in_use) + return 0; + + hwbuf = p_vad->dma_buffer.area; + size = p_vad->dma_buffer.bytes - 8; + start = p_vad->dma_buffer.addr; + end = start + size; + last_addr = p_vad->addr; + curr_addr = aml_toddr_get_position(p_vad->tddr); + + if (curr_addr < start || curr_addr > end || + last_addr < start || last_addr > end) { + pr_info("%s line:%d, start:%x,end:%x, addr:%x, curr_addr=%x\n", + __func__, __LINE__, + start, + end, + p_vad->addr, + curr_addr); + p_vad->addr = curr_addr; + return 0; + } + + bytes = (curr_addr - last_addr + size) % size; + chnum = p_vad->tddr->channels; + /* bytes for each sample */ + bytes_per_sample = p_vad->tddr->bitdepth >> 3; + + read_bytes = frame_count * chnum * bytes_per_sample; + if (bytes < read_bytes) { + pr_debug("%s line:%d, %d bytes, need more data\n", + __func__, __LINE__, bytes); + return 0; + } + + if (!p_vad->buf) { + p_vad->buf = kzalloc(read_bytes, GFP_KERNEL); + if (!p_vad->buf) { + pr_err("%s failed to allocate buffer for vad\n", + __func__); + return -ENOMEM; } } + memset(p_vad->buf, 0x0, read_bytes); + + pr_debug("start:%x,end:%x, curr_addr:%x, last_addr:%x, offset:%d, read_bytes:%d\n", + start, + end, + curr_addr, + last_addr, + bytes, + read_bytes); + + + if (last_addr + read_bytes <= end) { + memcpy(p_vad->buf, + hwbuf + last_addr - start, + read_bytes); + p_vad->addr = last_addr + read_bytes; + } else { + int tmp_bytes = end - last_addr; + + memcpy(p_vad->buf, + hwbuf + last_addr - start, + tmp_bytes); + memcpy(p_vad->buf + tmp_bytes, + hwbuf, + read_bytes - tmp_bytes); + p_vad->addr = start + read_bytes - tmp_bytes; + } + +#ifdef __VAD_DUMP_DATA__ + vfs_write(p_vad->fp, p_vad->buf, read_bytes, &p_vad->pos); +#endif + + return vad_transfer_data_to_algorithm(p_vad, + p_vad->buf, frame_count, + p_vad->tddr->rate, + p_vad->tddr->channels, + p_vad->tddr->bitdepth); } -static void vad_tasklet(unsigned long data) +static int vad_freeze_thread(void *data) { - struct vad *p_vad = (struct vad *)data; + struct vad *p_vad = data; - vad_transfer_buffer_output(p_vad); + if (!p_vad) + return 0; + + current->flags |= PF_NOFREEZE; + + for (;;) { + msleep_interruptible(10); + if (kthread_should_stop()) { + pr_info("%s line:%d\n", __func__, __LINE__); + + break; + } + + if (!p_vad || !p_vad->en || !p_vad->callback || + !p_vad->tddr || !p_vad->switch_buffer) { + msleep_interruptible(10); + continue; + } + + if (vad_engine_check(p_vad) > 0) + vad_notify_user_space(p_vad); + } + + dev_info(p_vad->dev, "vad: freeze thread exit\n"); + return 0; } + static irqreturn_t vad_wakeup_isr(int irq, void *data) { struct vad *p_vad = (struct vad *)data; - pr_info("%s\n", __func__); - - if (p_vad->level == LEVEL_KERNEL) - tasklet_schedule(&p_vad->tasklet); - + if (vad_in_kernel_test) { + pr_info("%s vad_wakeup_count:%d\n", __func__, vad_wakeup_count); + if ((p_vad->level == LEVEL_KERNEL) && p_vad->switch_buffer) + vad_wakeup_count++; + } return IRQ_HANDLED; } @@ -253,8 +458,33 @@ static int vad_init(struct vad *p_vad) if (p_vad->level == LEVEL_KERNEL) { flag = IRQF_SHARED | IRQF_NO_SUSPEND; - tasklet_init(&p_vad->tasklet, vad_tasklet, - (unsigned long)p_vad); + /* Start Micro/Audio Dock firmware loader thread */ + if (!p_vad->thread) { + p_vad->thread = + kthread_create(vad_freeze_thread, p_vad, + "vad_freeze_thread"); + if (IS_ERR(p_vad->thread)) { + int err = PTR_ERR(p_vad->thread); + + p_vad->thread = NULL; + dev_info(p_vad->dev, + "vad freeze: Creating thread failed\n"); + return err; + } + wake_up_process(p_vad->thread); + vad_wakeup_count = 0; + } + +#ifdef __VAD_DUMP_DATA__ + p_vad->fp = filp_open(VAD_DUMP_FILE_NAME, O_RDWR | O_CREAT, 0666); + if (IS_ERR(p_vad->fp)) { + pr_err("create file %s error/n", VAD_DUMP_FILE_NAME); + return -1; + } + p_vad->fs = get_fs(); + p_vad->pos = 0; + set_fs(KERNEL_DS); +#endif } else if (p_vad->level == LEVEL_USER) flag = IRQF_SHARED; @@ -285,8 +515,20 @@ static int vad_init(struct vad *p_vad) static void vad_deinit(struct vad *p_vad) { - if (p_vad->level == LEVEL_KERNEL) - tasklet_kill(&p_vad->tasklet); + if (p_vad->level == LEVEL_KERNEL) { +#ifdef __VAD_DUMP_DATA__ + if (p_vad->fp) { + set_fs(p_vad->fs); + filp_close(p_vad->fp, NULL); + } +#endif + if (p_vad->thread) { + kthread_stop(p_vad->thread); + p_vad->thread = NULL; + } + kfree(p_vad->buf); + p_vad->buf = NULL; + } /* free irq */ free_irq(p_vad->irq_wakeup, p_vad); @@ -302,13 +544,16 @@ static void vad_deinit(struct vad *p_vad) void vad_update_buffer(int isvad) { struct vad *p_vad = get_vad(); - unsigned int start, end, addr; + unsigned int start, end; unsigned int rd_th; - if (!p_vad || !p_vad->en || !p_vad->tddr) + if (!p_vad || !p_vad->en || !p_vad->tddr || + !p_vad->tddr->in_use || !p_vad->tddr->actrl) return; - addr = aml_toddr_get_position(p_vad->tddr); + if (p_vad->switch_buffer == isvad) + return; + p_vad->switch_buffer = isvad; if (isvad) { /* switch to vad buffer */ struct toddr *tddr = p_vad->tddr; @@ -319,34 +564,27 @@ void vad_update_buffer(int isvad) rd_th = 0x100; pr_debug("Switch to VAD buffer\n"); - pr_debug("\t ASAL start:%d, end:%d, bytes:%d, current:%d\n", + pr_debug("\t ASAL start:%x, end:%x, bytes:%d\n", tddr->start_addr, tddr->end_addr, - tddr->end_addr - tddr->start_addr, addr); + tddr->end_addr - tddr->start_addr); start = p_vad->dma_buffer.addr; end = start + p_vad->dma_buffer.bytes - 8; - pr_debug("\t VAD start:%d, end:%d, bytes:%d\n", + pr_debug("\t VAD start:%x, end:%x, bytes:%d\n", start, end, end - start); } else { pr_debug("Switch to ALSA buffer\n"); - - //addr = aml_toddr_get_addr(p_vad->tddr, VAD_WAKEUP_ADDR); - addr = aml_toddr_get_position(p_vad->tddr); - start = p_vad->start_last; end = p_vad->end_last; - rd_th = 0x40; - vad_set_trunk_data_readable(true); } - - p_vad->addr = addr; aml_toddr_set_buf(p_vad->tddr, start, end); aml_toddr_force_finish(p_vad->tddr); aml_toddr_update_fifos_rd_th(p_vad->tddr, rd_th); + p_vad->addr = 0; } int vad_transfer_chunk_data(unsigned long data, int frames) @@ -483,6 +721,9 @@ static int vad_set_enable_enum( return 0; } + if (p_vad->en == ucontrol->value.integer.value[0]) + return 0; + p_vad->en = ucontrol->value.integer.value[0]; if (p_vad->en) { @@ -576,14 +817,31 @@ static int vad_set_switch_enum( return 0; } - p_vad->switch_buffer = ucontrol->value.integer.value[0]; - if (p_vad->en) - vad_update_buffer(p_vad->switch_buffer); + vad_update_buffer(ucontrol->value.integer.value[0]); return 0; } +static int vad_test_get_enum( + struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + ucontrol->value.integer.value[0] = vad_in_kernel_test; + + return 0; +} + +static int vad_test_set_enum( + struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + vad_in_kernel_test = ucontrol->value.integer.value[0]; + + return 0; +} + + static const struct snd_kcontrol_new vad_controls[] = { SOC_SINGLE_BOOL_EXT("VAD enable", 0, @@ -600,6 +858,10 @@ static const struct snd_kcontrol_new vad_controls[] = { vad_get_switch_enum, vad_set_switch_enum), + SOC_SINGLE_BOOL_EXT("VAD Test", + 0, + vad_test_get_enum, + vad_test_set_enum), }; int card_add_vad_kcontrols(struct snd_soc_card *card) @@ -722,6 +984,18 @@ static int vad_platform_probe(struct platform_device *pdev) p_vad->src, p_vad->level); + p_vad->input_device = input_allocate_device(); + if (!p_vad->input_device) { + kfree(p_vad); + return -ENOMEM; + } + vad_input_device_init(p_vad); + if (input_register_device(p_vad->input_device)) { + input_free_device(p_vad->input_device); + kfree(p_vad); + return -EINVAL; + } + s_vad = p_vad; device_init_wakeup(dev, 1); diff --git a/sound/soc/amlogic/auge/vad_dev.c b/sound/soc/amlogic/auge/vad_dev.c index 9af68606481a..178632629c48 100644 --- a/sound/soc/amlogic/auge/vad_dev.c +++ b/sound/soc/amlogic/auge/vad_dev.c @@ -155,7 +155,7 @@ static int __init vad_init(void) goto err2; } - pr_info("Register %s", DRV_NAME); + pr_info("Register %s\n", DRV_NAME); return 0; err2: diff --git a/sound/soc/amlogic/common/misc.c b/sound/soc/amlogic/common/misc.c index 42d7e23438d1..1b4670564d6e 100644 --- a/sound/soc/amlogic/common/misc.c +++ b/sound/soc/amlogic/common/misc.c @@ -47,6 +47,20 @@ int aml_get_atv_audio_stable( } #endif /* CONFIG_AMLOGIC_ATV_DEMOD */ +#ifdef CONFIG_AMLOGIC_MEDIA_TVIN_AVDETECT + +const struct soc_enum av_audio_status_enum = + SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(audio_is_stable), + audio_is_stable); + +int aml_get_av_audio_stable(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + ucontrol->value.integer.value[0] = tvin_get_av_status(); + return 0; +} +#endif /* CONFIG_AMLOGIC_MEDIA_TVIN_AVDETECT */ + #ifdef CONFIG_AMLOGIC_MEDIA_TVIN_HDMI int hdmiin_fifo_disable_count; @@ -162,6 +176,16 @@ static const char * const hdmi_in_format[] = { "WMA_PRO" }; +static const char * const hdmi_in_audio_packet[] = { + "None", + "AUDS", + "OBA", + "DST", + "HBR", + "OBM", + "MAS" +}; + const struct soc_enum hdmi_in_status_enum[] = { SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(audio_is_stable), audio_is_stable), @@ -170,7 +194,9 @@ const struct soc_enum hdmi_in_status_enum[] = { SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(hdmi_in_channels), hdmi_in_channels), SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(hdmi_in_format), - hdmi_in_format) + hdmi_in_format), + SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(hdmi_in_audio_packet), + hdmi_in_audio_packet) }; int aml_get_hdmiin_audio_stable( @@ -180,7 +206,8 @@ int aml_get_hdmiin_audio_stable( struct rx_audio_stat_s aud_sts; rx_get_audio_status(&aud_sts); - ucontrol->value.integer.value[0] = aud_sts.aud_rcv_flag; + ucontrol->value.integer.value[0] = + (aud_sts.aud_rcv_packet == 0) ? 0 : 1; return 0; } @@ -222,6 +249,7 @@ int aml_get_hdmiin_audio_format( return 0; } + /* call HDMI CEC API to enable arc audio */ int aml_set_atmos_audio_edid( struct snd_kcontrol *kcontrol, @@ -245,4 +273,44 @@ int aml_get_atmos_audio_edid( return 0; } +int aml_get_hdmiin_audio_packet( + struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct rx_audio_stat_s aud_sts; + int val; + + rx_get_audio_status(&aud_sts); + + switch (aud_sts.aud_rcv_packet) { + case 0: + val = 0; + break; + case 1: + val = 1; + break; + case 2: + val = 2; + break; + case 4: + val = 3; + break; + case 8: + val = 4; + break; + case 16: + val = 5; + break; + case 32: + val = 6; + break; + default: + val = 0; + break; + } + ucontrol->value.integer.value[0] = val; + + return 0; +} + #endif diff --git a/sound/soc/amlogic/common/spdif_info.c b/sound/soc/amlogic/common/spdif_info.c index 85bd5e2bb092..5caeee5768c2 100644 --- a/sound/soc/amlogic/common/spdif_info.c +++ b/sound/soc/amlogic/common/spdif_info.c @@ -20,6 +20,9 @@ #include #include +#ifdef CONFIG_AMLOGIC_HDMITX +#include +#endif /* * 0 -- other formats except(DD,DD+,DTS) @@ -35,8 +38,7 @@ bool spdif_is_4x_clk(void) { bool is_4x = false; - if (IEC958_mode_codec == 4 || IEC958_mode_codec == 5 || - IEC958_mode_codec == 7 || IEC958_mode_codec == 8) { + if (IEC958_mode_codec == 7 || IEC958_mode_codec == 8) { is_4x = true; } @@ -53,7 +55,6 @@ void spdif_get_channel_status_info( pr_err("Unsupport sample rate\n"); return; } - if (IEC958_mode_codec && IEC958_mode_codec != 9) { if (IEC958_mode_codec == 1) { /* dts, use raw sync-word mode */ @@ -76,6 +77,10 @@ void spdif_get_channel_status_info( chsts->chstat1_l = 0Xe00; chsts->chstat1_r = 0Xe00; } + } else if (IEC958_mode_codec == 8 || IEC958_mode_codec == 7) { + /* DTS-HD MA, TrueHD */ + chsts->chstat1_l = 0x900; + chsts->chstat1_r = 0x900; } else { /* DTS,DD */ if (rate_bit == SNDRV_PCM_RATE_32000) { @@ -191,3 +196,29 @@ int spdif_format_set_enum( IEC958_mode_codec = index; return 0; } + +#ifdef CONFIG_AMLOGIC_HDMITX +unsigned int aml_audio_hdmiout_mute_flag; +/* call HDMITX API to enable/disable internal audio out */ +int aml_get_hdmi_out_audio(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + ucontrol->value.integer.value[0] = !hdmitx_ext_get_audio_status(); + + aml_audio_hdmiout_mute_flag = + ucontrol->value.integer.value[0]; + return 0; +} + +int aml_set_hdmi_out_audio(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + bool mute = ucontrol->value.integer.value[0]; + + if (aml_audio_hdmiout_mute_flag != mute) { + hdmitx_ext_set_audio_output(!mute); + aml_audio_hdmiout_mute_flag = mute; + } + return 0; +} +#endif diff --git a/sound/soc/amlogic/meson/dmic.h b/sound/soc/amlogic/meson/dmic.h index 69afdf5a9b17..15540fdfd644 100644 --- a/sound/soc/amlogic/meson/dmic.h +++ b/sound/soc/amlogic/meson/dmic.h @@ -1,3 +1,20 @@ +/* + * sound/soc/amlogic/meson/dmic.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 __DMIC_H__ #define __DMIC_H__ diff --git a/sound/soc/amlogic/meson/spdif_codec.c b/sound/soc/amlogic/meson/spdif_codec.c index 299c46c43a02..fc48405a92a3 100644 --- a/sound/soc/amlogic/meson/spdif_codec.c +++ b/sound/soc/amlogic/meson/spdif_codec.c @@ -166,29 +166,6 @@ static int aml_audio_get_spdif_mute(struct snd_kcontrol *kcontrol, } #ifdef CONFIG_AMLOGIC_HDMITX -/* call HDMITX API to enable/disable internal audio out */ -static int aml_get_hdmi_out_audio(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - ucontrol->value.integer.value[0] = !hdmitx_ext_get_audio_status(); - - v_spdif_codec.aml_audio_hdmiout_mute_flag = - ucontrol->value.integer.value[0]; - return 0; -} - -static int aml_set_hdmi_out_audio(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - bool mute = ucontrol->value.integer.value[0]; - - if (v_spdif_codec.aml_audio_hdmiout_mute_flag != mute) { - hdmitx_ext_set_audio_output(!mute); - v_spdif_codec.aml_audio_hdmiout_mute_flag = mute; - } - return 0; -} - static const char * const hdmi_out_channel_mask_texts[] = { "SPDIF", "2CH_I2S_0/1", diff --git a/sound/soc/amlogic/meson/tv.c b/sound/soc/amlogic/meson/tv.c index 6c184fd8497a..7f6c4df9f7f1 100644 --- a/sound/soc/amlogic/meson/tv.c +++ b/sound/soc/amlogic/meson/tv.c @@ -285,9 +285,17 @@ static int aml_get_spdif_audio_type( int audio_type = 0; int i; int total_num = sizeof(type_texts)/sizeof(struct spdif_audio_info); - int pc = aml_audin_read(AUDIN_SPDIF_NPCM_PCPD)>>16; + int pc_ori = aml_audin_read(AUDIN_SPDIF_NPCM_PCPD)>>16; + int pc = 0; - pc = pc&0xfff; + /* data type is 0~4 bit*/ + pc = pc_ori&0x1f; + /* check whether it has stop bit + * refer to IEC61937-1 table 9 + */ + if (pc == 0) { + pc = pc_ori&0xfff; + } for (i = 0; i < total_num; i++) { if (pc == type_texts[i].pc) { audio_type = type_texts[i].aud_type; @@ -562,22 +570,6 @@ static int aml_set_arc_audio(struct snd_kcontrol *kcontrol, } #endif -#ifdef CONFIG_TVIN_VDIN -static const char *const av_audio_is_stable[] = { - "false", - "true" -}; -static const struct soc_enum av_audio_status_enum = - SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(av_audio_is_stable), - av_audio_is_stable); -static int aml_get_av_audio_stable(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - ucontrol->value.integer.value[0] = tvin_get_av_status(); - return 0; -} -#endif /* CONFIG_TVIN_VDIN */ - static const struct snd_kcontrol_new av_controls[] = { SOC_ENUM_EXT("AudioIn Switch", audio_in_switch_enum, @@ -632,6 +624,9 @@ static const struct snd_kcontrol_new aml_tv_controls[] = { SOC_ENUM_EXT("HDMIIN audio format", hdmi_in_status_enum[3], aml_get_hdmiin_audio_format, NULL), + SOC_ENUM_EXT("HDMIIN Audio Packet", hdmi_in_status_enum[4], + aml_get_hdmiin_audio_packet, + NULL), SOC_SINGLE_BOOL_EXT("HDMI ATMOS EDID Switch", 0, aml_get_atmos_audio_edid, aml_set_atmos_audio_edid), @@ -641,7 +636,7 @@ static const struct snd_kcontrol_new aml_tv_controls[] = { aml_get_atv_audio_stable, NULL), #endif -#ifdef CONFIG_TVIN_VDIN +#ifdef CONFIG_AMLOGIC_MEDIA_TVIN_AVDETECT SOC_ENUM_EXT("AV audio stable", av_audio_status_enum, aml_get_av_audio_stable, NULL), diff --git a/sound/soc/codecs/amlogic/Kconfig b/sound/soc/codecs/amlogic/Kconfig index b4cd38258572..f0573fc444cf 100644 --- a/sound/soc/codecs/amlogic/Kconfig +++ b/sound/soc/codecs/amlogic/Kconfig @@ -101,6 +101,18 @@ config AMLOGIC_SND_CODEC_TL1_ACODEC #Third part codecs # Amlogic add codecs + +config AMLOGIC_SND_SOC_TAS5782M + bool "Texas Instruments TAS5782M amplifier" + depends on AMLOGIC_SND_SOC_CODECS + depends on I2C + default n + help + Enable support for Texas Instruments TAS5782M CODEC. + Select this if your TAS5782M is connected via an I2C bus. + Enable support for Texas Instruments TAS5782M CODEC. + Select this if your TAS5782M is connected via an I2C bus. + config AMLOGIC_SND_SOC_TAS5707 bool "Texas Instruments TAS5707 amplifier" depends on AMLOGIC_SND_SOC_CODECS diff --git a/sound/soc/codecs/amlogic/Makefile b/sound/soc/codecs/amlogic/Makefile index e1fdb3b653d7..348a63471f87 100644 --- a/sound/soc/codecs/amlogic/Makefile +++ b/sound/soc/codecs/amlogic/Makefile @@ -12,6 +12,7 @@ snd-soc-aml_codec_txlx_acodec-objs := aml_codec_txlx_acodec.o snd-soc-aml_codec_tl1_acodec-objs := aml_codec_tl1_acodec.o #Third part codecs +snd-soc-tas5782m-objs := tas5782m.o snd-soc-tas5707-objs := tas5707.o snd-soc-tlv320adc3101-objs := tlv320adc3101.o snd-soc-pcm186x-objs := pcm186x.o pcm186x-i2c.o pcm186x-spi.o @@ -31,6 +32,7 @@ obj-$(CONFIG_AMLOGIC_SND_CODEC_TXLX_ACODEC) += snd-soc-aml_codec_txlx_acodec.o obj-$(CONFIG_AMLOGIC_SND_CODEC_TL1_ACODEC) += snd-soc-aml_codec_tl1_acodec.o #Third part codecs +obj-$(CONFIG_AMLOGIC_SND_SOC_TAS5782M) += snd-soc-tas5782m.o obj-$(CONFIG_AMLOGIC_SND_SOC_TAS5707) += snd-soc-tas5707.o obj-$(CONFIG_AMLOGIC_SND_SOC_TLV320ADC3101) += snd-soc-tlv320adc3101.o obj-$(CONFIG_AMLOGIC_SND_SOC_PCM186X) += snd-soc-pcm186x.o diff --git a/sound/soc/codecs/amlogic/ad82584f.c b/sound/soc/codecs/amlogic/ad82584f.c index 88fea3497960..3fd69a66ea92 100644 --- a/sound/soc/codecs/amlogic/ad82584f.c +++ b/sound/soc/codecs/amlogic/ad82584f.c @@ -36,15 +36,15 @@ static const DECLARE_TLV_DB_SCALE(mvol_tlv, -10300, 50, 1); static const DECLARE_TLV_DB_SCALE(chvol_tlv, -10300, 50, 1); static const struct snd_kcontrol_new ad82584f_snd_controls[] = { - SOC_SINGLE_TLV("AMP Master Volume", MVOL, 0, + SOC_SINGLE_TLV("Master Volume", MVOL, 0, 0xff, 1, mvol_tlv), - SOC_SINGLE_TLV("AMP Ch1 Volume", C1VOL, 0, + SOC_SINGLE_TLV("Ch1 Volume", C1VOL, 0, 0xff, 1, chvol_tlv), - SOC_SINGLE_TLV("AMP Ch2 Volume", C2VOL, 0, + SOC_SINGLE_TLV("Ch2 Volume", C2VOL, 0, 0xff, 1, chvol_tlv), - SOC_SINGLE("AMP Ch1 Switch", MUTE, 5, 1, 1), - SOC_SINGLE("AMP Ch2 Switch", MUTE, 4, 1, 1), + SOC_SINGLE("Ch1 Switch", MUTE, 5, 1, 1), + SOC_SINGLE("Ch2 Switch", MUTE, 4, 1, 1), }; static int ad82584f_reg_init(struct snd_soc_codec *codec); @@ -728,7 +728,7 @@ static struct snd_soc_dai_driver ad82584f_dai = { .playback = { .stream_name = "HIFI Playback", .channels_min = 2, - .channels_max = 8, + .channels_max = 16, .rates = AD82584F_RATES, .formats = AD82584F_FORMATS, }, @@ -808,17 +808,32 @@ static int ad82584f_reg_init(struct snd_soc_codec *codec) } static int ad82584f_init(struct snd_soc_codec *codec) { + struct ad82584f_priv *ad82584f = snd_soc_codec_get_drvdata(codec); + reset_ad82584f_GPIO(codec); dev_info(codec->dev, "ad82584f_init!\n"); ad82584f_reg_init(codec); - /*eq and drc*/ + /* Bclk system */ + if (ad82584f->pdata->no_mclk) + snd_soc_write(codec, + 0x01, + 0x1 << 7 | /* Bclk system enable */ + 0x1 << 0 /* 64x bclk/fs */ + ); + + /* eq and drc */ ad82584f_set_eq_drc(codec); - /*unmute,default power-on is mute.*/ - /*snd_soc_write(codec, 0x02, 0x00);*/ + /* for de-pop */ + udelay(100); + + snd_soc_write(codec, MVOL, 0x11); + + /* unmute, default power-on is mute. */ + snd_soc_write(codec, MUTE, 0x00); return 0; } @@ -945,6 +960,12 @@ static int ad82584f_parse_dt( } ad82584f->pdata->reset_pin = reset_pin; + ad82584f->pdata->no_mclk = of_property_read_bool( + np, + "no_mclk"); + if (ad82584f->pdata->no_mclk) + pr_info("%s mclk is not connected.\n", __func__); + return ret; } diff --git a/sound/soc/codecs/amlogic/ad82584f.h b/sound/soc/codecs/amlogic/ad82584f.h index fd149b8bbf0c..21207cc98632 100644 --- a/sound/soc/codecs/amlogic/ad82584f.h +++ b/sound/soc/codecs/amlogic/ad82584f.h @@ -16,6 +16,7 @@ struct ad82584f_platform_data { int reset_pin; + bool no_mclk; }; #endif diff --git a/sound/soc/codecs/amlogic/aml_codec_t9015.c b/sound/soc/codecs/amlogic/aml_codec_t9015.c index 7d6aee2c6ad0..533f0f4192bf 100644 --- a/sound/soc/codecs/amlogic/aml_codec_t9015.c +++ b/sound/soc/codecs/amlogic/aml_codec_t9015.c @@ -46,7 +46,13 @@ struct aml_T9015_audio_priv { /* codec is used by meson or auge arch */ bool is_auge_arch; + /* tocodec ctrl supports in and out data */ + bool tocodec_inout; + /* attach which tdm when play */ int tdmout_index; + /* channel map */ + int ch0_sel; + int ch1_sel; }; static const struct reg_default t9015_init_list[] = { @@ -72,26 +78,20 @@ static int aml_DAC_Gain_get_enum( struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { -#if 0 struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); struct snd_soc_codec *codec = snd_soc_component_to_codec(component); - u32 add, val, val1, val2; -#endif - /*TODO: return 0 for tmp, this wolud modified later */ - return 0; -#if 0 - if (codec == NULL) - return -1; + u32 reg_addr = ADC_VOL_CTR_PGA_IN_CONFIG; + u32 val = snd_soc_read(codec, reg_addr); + u32 val1 = (val & (0x1 << DAC_GAIN_SEL_L)) + >> DAC_GAIN_SEL_L; + u32 val2 = (val & (0x1 << DAC_GAIN_SEL_H)) + >> (DAC_GAIN_SEL_H); - add = ADC_VOL_CTR_PGA_IN_CONFIG; - val = snd_soc_read(codec, add); - val1 = (val & (0x1 << DAC_GAIN_SEL_L)) >> DAC_GAIN_SEL_L; - val2 = (val & (0x1 << DAC_GAIN_SEL_H)) >> (DAC_GAIN_SEL_H - 1); + val = val1 | (val2 << 1); - val = val1 | val2; ucontrol->value.enumerated.item[0] = val; + return 0; - #endif } static int aml_DAC_Gain_set_enum( @@ -100,8 +100,8 @@ static int aml_DAC_Gain_set_enum( { struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); struct snd_soc_codec *codec = snd_soc_component_to_codec(component); - u32 add = ADC_VOL_CTR_PGA_IN_CONFIG; - u32 val = snd_soc_read(codec, add); + u32 addr = ADC_VOL_CTR_PGA_IN_CONFIG; + u32 val = snd_soc_read(codec, addr); if (ucontrol->value.enumerated.item[0] == 0) { val &= ~(0x1 << DAC_GAIN_SEL_H); @@ -120,7 +120,7 @@ static int aml_DAC_Gain_set_enum( pr_info("It has risk of distortion!\n"); } - snd_soc_write(codec, val, add); + snd_soc_write(codec, addr, val); return 0; } @@ -407,9 +407,15 @@ static int aml_T9015_audio_probe(struct snd_soc_codec *codec) aml_T9015_audio_start_up(codec); aml_T9015_audio_reg_init(codec); - if (T9015_audio && T9015_audio->is_auge_arch) - auge_toacodec_ctrl(T9015_audio->tdmout_index); - else + if (T9015_audio && T9015_audio->is_auge_arch) { + if (T9015_audio->tocodec_inout) + auge_toacodec_ctrl_ext( + T9015_audio->tdmout_index, + T9015_audio->ch0_sel, + T9015_audio->ch1_sel); + else + auge_toacodec_ctrl(T9015_audio->tdmout_index); + } else aml_write_cbus(AIU_ACODEC_CTRL, (1 << 4) |(1 << 6) @@ -474,7 +480,7 @@ struct snd_soc_dai_driver aml_T9015_audio_dai[] = { .playback = { .stream_name = "HIFI Playback", .channels_min = 2, - .channels_max = 8, + .channels_max = 16, .rates = T9015_AUDIO_STEREO_RATES, .formats = T9015_AUDIO_FORMATS, }, @@ -546,12 +552,27 @@ static int aml_T9015_audio_codec_probe(struct platform_device *pdev) T9015_audio->is_auge_arch = of_property_read_bool( pdev->dev.of_node, "is_auge_used"); + + T9015_audio->tocodec_inout = of_property_read_bool( + pdev->dev.of_node, + "tocodec_inout"); + of_property_read_u32( pdev->dev.of_node, "tdmout_index", &T9015_audio->tdmout_index); - pr_info("aml_codec_T9015 is used by %s chipset, tdmout:%d\n", + of_property_read_u32( + pdev->dev.of_node, + "ch0_sel", + &T9015_audio->ch0_sel); + + of_property_read_u32( + pdev->dev.of_node, + "ch1_sel", + &T9015_audio->ch1_sel); + + pr_info("T9015 acodec used by %s, tdmout:%d\n", T9015_audio->is_auge_arch ? "auge" : "meson", T9015_audio->tdmout_index); diff --git a/sound/soc/codecs/amlogic/tas5782m.c b/sound/soc/codecs/amlogic/tas5782m.c new file mode 100644 index 000000000000..d7bbfe383f13 --- /dev/null +++ b/sound/soc/codecs/amlogic/tas5782m.c @@ -0,0 +1,903 @@ +/* + * sound/soc/codecs/amlogic/tas5782m.c + * + * Copyright (C) 2019 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "tas5782m.h" + +#define DEV_NAME "tas5782m" + +#ifdef CONFIG_HAS_EARLYSUSPEND +#include +static void tas5782m_early_suspend(struct early_suspend *h); +static void tas5782m_late_resume(struct early_suspend *h); +#endif + +#define tas5782m_RATES (SNDRV_PCM_RATE_8000 | \ + SNDRV_PCM_RATE_11025 | \ + SNDRV_PCM_RATE_16000 | \ + SNDRV_PCM_RATE_22050 | \ + SNDRV_PCM_RATE_32000 | \ + SNDRV_PCM_RATE_44100 | \ + SNDRV_PCM_RATE_48000) + +#define tas5782m_FORMATS \ + (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE | \ + SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S20_3BE | \ + SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_BE | \ + SNDRV_PCM_FMTBIT_S32_LE) + +#define TAS5782M_REG_00 (0x00) +#define TAS5782M_REG_03 (0x03) +#define TAS5782M_REG_7F (0x7F) +#define TAS5782M_REG_28 (0x28) +#define TAS5782M_REG_29 (0x29) +#define TAS5782M_REG_3D (0x3D) +#define TAS5782M_REG_3E (0x3E) + + + +enum BITSIZE_MODE { + BITSIZE_MODE_16BITS = 0, + BITSIZE_MODE_20BITS = 1, + BITSIZE_MODE_24BITS = 2, + BITSIZE_MODE_32BITS = 3, +}; + +/* codec private data */ +struct tas5782m_priv { + struct i2c_client *i2c; + struct regmap *regmap; + struct snd_soc_codec *codec; + struct tas57xx_platform_data *pdata; + struct work_struct work; + + unsigned int work_mode; + unsigned int chip_offset; + + /*Platform provided EQ configuration */ + int num_eq_conf_texts; + const char **eq_conf_texts; + int eq_cfg; + struct soc_enum eq_conf_enum; + unsigned char Ch1_vol; + unsigned char Ch2_vol; + unsigned char Ch1_mute; + unsigned char Ch2_mute; + unsigned char master_vol; + unsigned int mclk; + unsigned int EQ_enum_value; + unsigned int DRC_enum_value; +#ifdef CONFIG_HAS_EARLYSUSPEND + struct early_suspend early_suspend; +#endif +}; + +static int g_sample_bitsize = 32; + +static int tas5782m_ch1_vol_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->access = SNDRV_CTL_ELEM_ACCESS_TLV_READ + | SNDRV_CTL_ELEM_ACCESS_READWRITE; + uinfo->count = 1; + + uinfo->value.integer.min = 0; + uinfo->value.integer.max = 0xff; + uinfo->value.integer.step = 1; + + return 0; +} + +static int tas5782m_ch2_vol_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->access = SNDRV_CTL_ELEM_ACCESS_TLV_READ + | SNDRV_CTL_ELEM_ACCESS_READWRITE; + uinfo->count = 1; + + uinfo->value.integer.min = 0; + uinfo->value.integer.max = 0xff; + uinfo->value.integer.step = 1; + + return 0; +} + + +static int tas5782m_ch1_mute_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->access = SNDRV_CTL_ELEM_ACCESS_TLV_READ + | SNDRV_CTL_ELEM_ACCESS_READWRITE; + uinfo->count = 1; + + uinfo->value.integer.min = 0; + uinfo->value.integer.max = 1; + uinfo->value.integer.step = 1; + + return 0; +} + +static int tas5782m_ch2_mute_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->access = SNDRV_CTL_ELEM_ACCESS_TLV_READ + | SNDRV_CTL_ELEM_ACCESS_READWRITE; + uinfo->count = 1; + + uinfo->value.integer.min = 0; + uinfo->value.integer.max = 1; + uinfo->value.integer.step = 1; + + return 0; +} + + + +static int tas5782m_ch1_vol_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + struct tas5782m_priv *tas5782m = snd_soc_codec_get_drvdata(codec); + + ucontrol->value.integer.value[0] = tas5782m->Ch1_vol; + + return 0; +} + +static int tas5782m_ch2_vol_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + struct tas5782m_priv *tas5782m = snd_soc_codec_get_drvdata(codec); + + ucontrol->value.integer.value[0] = tas5782m->Ch2_vol; + + return 0; +} + + +static int tas5782m_ch1_mute_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + struct tas5782m_priv *tas5782m = snd_soc_codec_get_drvdata(codec); + + ucontrol->value.integer.value[0] = tas5782m->Ch1_mute; + + return 0; +} + +static int tas5782m_ch2_mute_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + struct tas5782m_priv *tas5782m = snd_soc_codec_get_drvdata(codec); + + ucontrol->value.integer.value[0] = tas5782m->Ch2_mute; + + return 0; +} + + +static void tas5782m_set_volume(struct snd_soc_codec *codec, + int value, int ch_num) +{ + unsigned char buf[2]; + int write_count = 0; + struct tas5782m_priv *tas5782m = snd_soc_codec_get_drvdata(codec); + + if (value < 0) + value = 0; + if (value > 255) + value = 255; + + buf[0] = TAS5782M_REG_00, buf[1] = 0x00; + write_count = 2; + if (write_count != i2c_master_send(tas5782m->i2c, buf, write_count)) + pr_err("%s %d !!!!! i2c_master_send error !!!!!\n", + __func__, __LINE__); + + buf[0] = TAS5782M_REG_7F, buf[1] = 0x00; + write_count = 2; + if (write_count != i2c_master_send(tas5782m->i2c, buf, write_count)) + pr_err("%s %d !!!!! i2c_master_send error !!!!!\n", + __func__, __LINE__); + + buf[0] = TAS5782M_REG_00, buf[1] = 0x00; + write_count = 2; + if (write_count != i2c_master_send(tas5782m->i2c, buf, write_count)) + pr_err("%s %d !!!!! i2c_master_send error !!!!!\n", + __func__, __LINE__); + + buf[0] = (ch_num == 0) ? TAS5782M_REG_3D : TAS5782M_REG_3E; + buf[1] = value; + write_count = 2; + if (write_count != i2c_master_send(tas5782m->i2c, buf, write_count)) + pr_err("%s %d !!!!! i2c_master_send error !!!!!\n", + __func__, __LINE__); + +} + +static int tas5782m_ch1_vol_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + struct tas5782m_priv *tas5782m = snd_soc_codec_get_drvdata(codec); + int value; + + value = ucontrol->value.integer.value[0]; + tas5782m->Ch1_vol = value; + value = 255 - value; + tas5782m_set_volume(codec, value, 0); + + return 0; +} + +static int tas5782m_ch2_vol_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + struct tas5782m_priv *tas5782m = snd_soc_codec_get_drvdata(codec); + int value; + + value = ucontrol->value.integer.value[0]; + tas5782m->Ch2_vol = value; + value = 255 - value; + tas5782m_set_volume(codec, value, 1); + + return 0; +} + +static void tas5782m_set_mute(struct snd_soc_codec *codec, + unsigned char left_mute, + unsigned char right_mute) +{ + unsigned char buf[2]; + int write_count = 0; + struct tas5782m_priv *tas5782m = snd_soc_codec_get_drvdata(codec); + + + buf[0] = TAS5782M_REG_00, buf[1] = 0x00; + write_count = 2; + if (write_count != i2c_master_send(tas5782m->i2c, buf, write_count)) + pr_err("%s %d !!!!! i2c_master_send error !!!!!\n", + __func__, __LINE__); + + buf[0] = TAS5782M_REG_7F, buf[1] = 0x00; + write_count = 2; + if (write_count != i2c_master_send(tas5782m->i2c, buf, write_count)) + pr_err("%s %d !!!!! i2c_master_send error !!!!!\n", + __func__, __LINE__); + + buf[0] = TAS5782M_REG_00, buf[1] = 0x00; + write_count = 2; + if (write_count != i2c_master_send(tas5782m->i2c, buf, write_count)) + pr_err("%s %d !!!!! i2c_master_send error !!!!!\n", + __func__, __LINE__); + + buf[0] = TAS5782M_REG_03; + buf[1] = left_mute << 4 | right_mute; + write_count = 2; + if (write_count != i2c_master_send(tas5782m->i2c, buf, write_count)) + pr_err("%s %d !!!!! i2c_master_send error !!!!!\n", + __func__, __LINE__); + +} + + +static int tas5782m_ch1_mute_set(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + struct tas5782m_priv *tas5782m = snd_soc_codec_get_drvdata(codec); + int value; + + value = ucontrol->value.integer.value[0]; + tas5782m->Ch1_mute = value; + tas5782m_set_mute(codec, tas5782m->Ch1_mute, tas5782m->Ch2_mute); + + return 0; +} + +static int tas5782m_ch2_mute_set(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + struct tas5782m_priv *tas5782m = snd_soc_codec_get_drvdata(codec); + int value; + + value = ucontrol->value.integer.value[0]; + tas5782m->Ch2_mute = value; + tas5782m_set_mute(codec, tas5782m->Ch1_mute, tas5782m->Ch2_mute); + + return 0; +} + + + +static const struct snd_kcontrol_new tas5782m_snd_controls[] = { + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Ch1 Volume", + .info = tas5782m_ch1_vol_info, + .get = tas5782m_ch1_vol_get, + .put = tas5782m_ch1_vol_put, + }, + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Ch2 Volume", + .info = tas5782m_ch2_vol_info, + .get = tas5782m_ch2_vol_get, + .put = tas5782m_ch2_vol_put, + }, + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Ch1 Mute", + .info = tas5782m_ch1_mute_info, + .get = tas5782m_ch1_mute_get, + .put = tas5782m_ch1_mute_set, + }, + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Ch2 Mute", + .info = tas5782m_ch2_mute_info, + .get = tas5782m_ch2_mute_get, + .put = tas5782m_ch2_mute_set, + } + +}; + +static int tas5782m_set_dai_sysclk(struct snd_soc_dai *codec_dai, + int clk_id, unsigned int freq, int dir) +{ + return 0; +} + +static int tas5782m_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) +{ + + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { + case SND_SOC_DAIFMT_CBS_CFS: + break; + default: + return 0;//-EINVAL; + } + + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_I2S: + case SND_SOC_DAIFMT_RIGHT_J: + case SND_SOC_DAIFMT_LEFT_J: + break; + default: + return 0;//-EINVAL; + } + + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { + case SND_SOC_DAIFMT_NB_NF: + break; + case SND_SOC_DAIFMT_NB_IF: + break; + default: + return 0;//-EINVAL; + } + + return 0; +} + +static int tas5782m_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) +{ + unsigned int rate; + + rate = params_rate(params); + + pr_debug("rate: %u\n", rate); + + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S24_LE: + case SNDRV_PCM_FORMAT_S24_BE: + pr_debug("24bit\n"); + /* fall through */ + case SNDRV_PCM_FORMAT_S32_LE: + case SNDRV_PCM_FORMAT_S20_3LE: + case SNDRV_PCM_FORMAT_S20_3BE: + pr_debug("20bit\n"); + + break; + case SNDRV_PCM_FORMAT_S16_LE: + case SNDRV_PCM_FORMAT_S16_BE: + pr_debug("16bit\n"); + + break; + default: + return -EINVAL; + } + + return 0; +} + +static int tas5782m_set_bias_level(struct snd_soc_codec *codec, + enum snd_soc_bias_level level) +{ + pr_debug("level = %d\n", level); + + switch (level) { + case SND_SOC_BIAS_ON: + break; + + case SND_SOC_BIAS_PREPARE: + /* Full power on */ + break; + + case SND_SOC_BIAS_STANDBY: + break; + + case SND_SOC_BIAS_OFF: + /* The chip runs through the power down sequence for us. */ + break; + } + codec->component.dapm.bias_level = level; + + return 0; +} + +static const struct snd_soc_dai_ops tas5782m_dai_ops = { + .hw_params = tas5782m_hw_params, + .set_sysclk = tas5782m_set_dai_sysclk, + .set_fmt = tas5782m_set_dai_fmt, +}; + +static struct snd_soc_dai_driver tas5782m_dai = { + .name = DEV_NAME, + .playback = { + .stream_name = "HIFI Playback", + .channels_min = 2, + .channels_max = 8, + .rates = tas5782m_RATES, + .formats = tas5782m_FORMATS, + }, + .ops = &tas5782m_dai_ops, +}; + + +static int reset_tas5782m_GPIO(struct snd_soc_codec *codec) +{ + struct tas5782m_priv *tas5782m = snd_soc_codec_get_drvdata(codec); + struct tas57xx_platform_data *pdata = tas5782m->pdata; + int ret = 0; + + if (pdata->reset_pin < 0) + return 0; + + ret = devm_gpio_request_one(codec->dev, pdata->reset_pin, + GPIOF_OUT_INIT_LOW, "tas5782m-reset-pin"); + + if (ret < 0) { + pr_err("failed!!! devm_gpio_request_one = %d!\n", ret); + return -1; + } + + gpio_direction_output(pdata->reset_pin, GPIOF_OUT_INIT_HIGH); + udelay(1000); + gpio_direction_output(pdata->reset_pin, GPIOF_OUT_INIT_LOW); + udelay(1000); + gpio_direction_output(pdata->reset_pin, GPIOF_OUT_INIT_HIGH); + msleep(20); + + return 0; +} + +static int tas5782m_init_i2s_tdm_mode(struct snd_soc_codec *codec, int bit_size) +{ + struct tas5782m_priv *tas5782m = snd_soc_codec_get_drvdata(codec); + int work_mod = tas5782m->work_mode; + + int tdm_aofs = 0; + unsigned char buf[8] = {0}; + int write_count = 0; + enum BITSIZE_MODE bit_value = BITSIZE_MODE_32BITS; + + write_count = 2; + buf[0] = TAS5782M_REG_00, buf[1] = 0x00; + if (write_count != i2c_master_send(tas5782m->i2c, buf, write_count)) + pr_err("%s %d !!!!! i2c_master_send error !!!!!\n", + __func__, __LINE__); + + buf[0] = TAS5782M_REG_7F, buf[1] = 0x00; + write_count = 2; + if (write_count != i2c_master_send(tas5782m->i2c, buf, write_count)) + pr_err("%s %d !!!!! i2c_master_send error !!!!!\n", + __func__, __LINE__); + + buf[0] = TAS5782M_REG_00, buf[1] = 0x00; + write_count = 2; + if (write_count != i2c_master_send(tas5782m->i2c, buf, write_count)) + pr_err("%s %d !!!!! i2c_master_send error !!!!!\n", + __func__, __LINE__); + + if (bit_size == 16) + bit_value = BITSIZE_MODE_16BITS; + else if (bit_size == 20) + bit_value = BITSIZE_MODE_20BITS; + else if (bit_size == 24) + bit_value = BITSIZE_MODE_24BITS; + else if (bit_size == 32) + bit_value = BITSIZE_MODE_32BITS; + + buf[0] = TAS5782M_REG_28, buf[1] = (work_mod << 4) | bit_value; + write_count = 2; + if (write_count != i2c_master_send(tas5782m->i2c, buf, write_count)) { + pr_err("%s %d !!!!! i2c_master_send error !!!!!\n", + __func__, __LINE__); + } else { + pr_debug("%s %d reg:0x%x, chip_offset:%d reg_off:0x%x data:0x%x\n", + __func__, __LINE__, tas5782m->i2c->addr, + tas5782m->chip_offset, buf[0], buf[1]); + } + + if (work_mod == WORK_MODE_TDM) { + buf[0] = TAS5782M_REG_00, buf[1] = 0x00; + write_count = 2; + if (write_count != i2c_master_send(tas5782m->i2c, buf, + write_count)) + pr_err("%s %d !!!!! i2c_master_send error !!!!!\n", + __func__, __LINE__); + + buf[0] = TAS5782M_REG_7F, buf[1] = 0x00; + write_count = 2; + if (write_count != i2c_master_send(tas5782m->i2c, buf, + write_count)) + pr_err("%s %d !!!!! i2c_master_send error !!!!!\n", + __func__, __LINE__); + + buf[0] = TAS5782M_REG_00, buf[1] = 0x00; + write_count = 2; + if (write_count != i2c_master_send(tas5782m->i2c, buf, + write_count)) + pr_err("%s %d !!!!! i2c_master_send error !!!!!\n", + __func__, __LINE__); + + tdm_aofs = bit_size * 2 * (tas5782m->chip_offset - 1); + + buf[0] = TAS5782M_REG_29, buf[1] = tdm_aofs; + write_count = 2; + if (write_count != i2c_master_send(tas5782m->i2c, buf, + write_count)) { + pr_err("%s %d !!!!! i2c_master_send error !!!!!\n", + __func__, __LINE__); + } else { + pr_debug("%s %d reg:0x%x, chip_offset:%d reg_off:0x%x", + __func__, __LINE__, tas5782m->i2c->addr, + tas5782m->chip_offset, buf[0]); + pr_debug("tdm_aofs:0x%x SCLKS\n", tdm_aofs); + } + } + + return 0; +} + +static void tas5782m_init_func(struct work_struct *p_work) +{ + struct tas5782m_priv *tas5782m; + struct snd_soc_codec *codec; + struct i2c_client *i2c; + int i = 0, j = 0, k = 0; + int value_count; + unsigned char buf[64] = {0}; + int write_count = 0; + int data_row = 0; + + tas5782m = container_of( + p_work, struct tas5782m_priv, work); + + codec = tas5782m->codec; + + reset_tas5782m_GPIO(codec); + + //init register + tas5782m = snd_soc_codec_get_drvdata(codec); + dev_info(codec->dev, "tas5782m_init id=%d\n", tas5782m->chip_offset); + + i2c = tas5782m->i2c; + value_count = ARRAY_SIZE(tas5782m_reg_defaults); + for (i = 0; i < value_count;) { + if (tas5782m_reg_defaults[i].reg == CFG_META_BURST) { + if (tas5782m_reg_defaults[i].def == 2) { + data_row = 1; + write_count = + tas5782m_reg_defaults[i].def; + } else { + data_row = + (tas5782m_reg_defaults[i].def + + 2) >> 1; + write_count = + tas5782m_reg_defaults[i].def + + 1; + } + i++; + + j = 0, k = 0; + for (k = 0; k < data_row; k++) { + buf[j++] = + tas5782m_reg_defaults[i+k].reg; + buf[j++] = + tas5782m_reg_defaults[i+k].def; + } + + i += data_row; + + //dump_buf(buf, k); + if (write_count != + i2c_master_send(i2c, buf, + write_count)) { + pr_err("%s %d !!!!! i2c_master_send error !!!!!\n", + __func__, __LINE__); + break; + } + } else { + i++; + pr_info("%s %d warning: register value error!\n", + __func__, __LINE__); + } + } + + tas5782m_init_i2s_tdm_mode(codec, g_sample_bitsize); +} + +static int tas5782m_probe(struct snd_soc_codec *codec) +{ + struct tas5782m_priv *tas5782m; + +#ifdef CONFIG_HAS_EARLYSUSPEND + tas5782m->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN; + tas5782m->early_suspend.suspend = tas5782m_early_suspend; + tas5782m->early_suspend.resume = tas5782m_late_resume; + tas5782m->early_suspend.param = codec; + register_early_suspend(&(tas5782m->early_suspend)); +#endif + + tas5782m = snd_soc_codec_get_drvdata(codec); + tas5782m->codec = codec; + + INIT_WORK(&tas5782m->work, tas5782m_init_func); + schedule_work(&tas5782m->work); + + return 0; +} + +static int tas5782m_remove(struct snd_soc_codec *codec) +{ + struct tas5782m_priv *tas5782m; + +#ifdef CONFIG_HAS_EARLYSUSPEND + struct tas5782m_priv *tas5782m = snd_soc_codec_get_drvdata(codec); + + unregister_early_suspend(&(tas5782m->early_suspend)); +#endif + tas5782m = snd_soc_codec_get_drvdata(codec); + + cancel_work_sync(&tas5782m->work); + + return 0; +} + +#ifdef CONFIG_PM +static int tas5782m_suspend(struct snd_soc_codec *codec) +{ + struct tas57xx_platform_data *pdata = dev_get_platdata(codec->dev); + + dev_info(codec->dev, "tas5782m_suspend!\n"); + + if (pdata && pdata->suspend_func) + pdata->suspend_func(); + + return 0; +} + +static int tas5782m_resume(struct snd_soc_codec *codec) +{ + struct tas57xx_platform_data *pdata = dev_get_platdata(codec->dev); + struct tas5782m_priv *tas5782m; + + dev_info(codec->dev, "tas5782m_resume!\n"); + + if (pdata && pdata->resume_func) + pdata->resume_func(); + + tas5782m = snd_soc_codec_get_drvdata(codec); + tas5782m->codec = codec; + + INIT_WORK(&tas5782m->work, tas5782m_init_func); + schedule_work(&tas5782m->work); + + + return 0; +} +#endif + +#ifdef CONFIG_HAS_EARLYSUSPEND +static void tas5782m_early_suspend(struct early_suspend *h) +{ +} + +static void tas5782m_late_resume(struct early_suspend *h) +{ +} +#endif + +static const struct snd_soc_dapm_widget tas5782m_dapm_widgets[] = { + SND_SOC_DAPM_DAC("DAC", "HIFI Playback", SND_SOC_NOPM, 0, 0), +}; + +static const struct snd_soc_codec_driver soc_codec_dev_tas5782m = { + .probe = tas5782m_probe, + .remove = tas5782m_remove, +#ifdef CONFIG_PM + .suspend = tas5782m_suspend, + .resume = tas5782m_resume, +#endif + .set_bias_level = tas5782m_set_bias_level, + .component_driver = { + .controls = tas5782m_snd_controls, + .num_controls = ARRAY_SIZE(tas5782m_snd_controls), + .dapm_widgets = tas5782m_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(tas5782m_dapm_widgets), + } +}; + +/* + *static const struct regmap_config tas5782m_regmap = { + * .reg_bits = 8, + * .val_bits = 8, + * + * .max_register = tas5782m_REGISTER_COUNT, + * .reg_defaults = tas5782m_reg_defaults, + * .num_reg_defaults = + * sizeof(tas5782m_reg_defaults)/sizeof(tas5782m_reg_defaults[0]), + * .cache_type = REGCACHE_RBTREE, + *}; + */ + +static int tas5782m_parse_dts(struct tas5782m_priv *tas5782m, + struct device_node *np) +{ + int ret = 0; + int reset_pin = -1; + + reset_pin = of_get_named_gpio(np, "reset_pin", 0); + if (reset_pin < 0) { + pr_err("%s fail to get reset pin from dts!\n", __func__); + ret = -1; + } else { + pr_debug("%s pdata->reset_pin = %d!\n", __func__, reset_pin); + } + tas5782m->pdata->reset_pin = reset_pin; + + ret = of_property_read_u32(np, "work_mode", &tas5782m->work_mode); + pr_debug("tas5782m->work_mode:%d(%s)!\n", tas5782m->work_mode, + (tas5782m->work_mode == WORK_MODE_I2S)?"i2s":"tdm"); + + ret = of_property_read_u32(np, "chip_offset", &tas5782m->chip_offset); + pr_debug("tas5782m->chip_offset:%d!\n", tas5782m->chip_offset); + + return ret; +} + +static int tas5782m_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) +{ + struct tas5782m_priv *tas5782m; + struct tas57xx_platform_data *pdata; + int ret; + const char *codec_name = NULL; + + pr_debug("i2c->addr=0x%x\n", i2c->addr); + + tas5782m = devm_kzalloc(&i2c->dev, + sizeof(struct tas5782m_priv), GFP_KERNEL); + if (!tas5782m) + return -ENOMEM; + + + tas5782m->i2c = i2c; + /* + * tas5782m->regmap = devm_regmap_init_i2c(i2c, &tas5782m_regmap); + * if (IS_ERR(tas5782m->regmap)) { + * ret = PTR_ERR(tas5782m->regmap); + * dev_err(&i2c->dev, + * "Failed to allocate register map: %d\n", ret); + * return ret; + * } + */ + pdata = devm_kzalloc(&i2c->dev, + sizeof(struct tas57xx_platform_data), GFP_KERNEL); + if (!pdata) + return -ENOMEM; + + tas5782m->pdata = pdata; + + tas5782m_parse_dts(tas5782m, i2c->dev.of_node); + + if (of_property_read_string(i2c->dev.of_node, + "codec_name", &codec_name)) { + pr_info("no codec name\n"); + ret = -1; + } + pr_debug("aux name = %s\n", codec_name); + if (codec_name) + dev_set_name(&i2c->dev, "%s", codec_name); + + i2c_set_clientdata(i2c, tas5782m); + + ret = snd_soc_register_codec(&i2c->dev, + &soc_codec_dev_tas5782m, &tas5782m_dai, 1); + if (ret != 0) + dev_err(&i2c->dev, "Failed to register codec (%d)\n", ret); + + return ret; +} + +static int tas5782m_i2c_remove(struct i2c_client *client) +{ + snd_soc_unregister_codec(&client->dev); + + return 0; +} + +static const struct i2c_device_id tas5782m_i2c_id[] = { + { "tas5782m", 0 }, + {} +}; + +static const struct of_device_id tas5782m_of_id[] = { + {.compatible = "ti, tas5782m",}, + { /* senitel */ } +}; +MODULE_DEVICE_TABLE(of, tas5782m_of_id); + +static struct i2c_driver tas5782m_i2c_driver = { + .driver = { + .name = DEV_NAME, + .of_match_table = tas5782m_of_id, + .owner = THIS_MODULE, + }, + .probe = tas5782m_i2c_probe, + .remove = tas5782m_i2c_remove, + .id_table = tas5782m_i2c_id, +}; + +module_i2c_driver(tas5782m_i2c_driver); + + +MODULE_DESCRIPTION("ASoC tas5782m driver"); +MODULE_AUTHOR("AML MM team"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/amlogic/tas5782m.h b/sound/soc/codecs/amlogic/tas5782m.h new file mode 100644 index 000000000000..6cc83d0e5cc0 --- /dev/null +++ b/sound/soc/codecs/amlogic/tas5782m.h @@ -0,0 +1,1521 @@ +/* + * sound/soc/codecs/amlogic/tas5782m.c + * + * Copyright (C) 2019 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 _TAS5782M_H +#define _TAS5782M_H + +#include + + +#define CFG_META_SWITCH (255) +#define CFG_META_DELAY (254) +#define CFG_META_BURST (253) + +#define WORK_MODE_I2S 0 +#define WORK_MODE_TDM 1 + +#define WORK_MODE WORK_MODE_I2S + +static const struct reg_default tas5782m_reg_defaults[] = { + //program memory + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x02, 0x11 }, + { CFG_META_BURST, 2 }, + { 0x01, 0x11 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x03, 0x11 }, + { CFG_META_BURST, 2 }, + { 0x2a, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x25, 0x18 }, + { CFG_META_BURST, 2 }, + { 0x0d, 0x10 }, + { CFG_META_BURST, 2 }, + { 0x02, 0x00 }, + + //Sample rate update + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x02, 0x80 }, + + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x00 }, + + // speed 03-48k 04-96k + //dynamically reading speed + { CFG_META_BURST, 2 }, + { 0x22, 0x03 }, + + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x02, 0x00 }, + + //write coefficients of various components + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1e }, + { CFG_META_BURST, 5 }, + { 0x1c, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 5 }, + { 0x28, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 5 }, + { 0x34, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 5 }, + { 0x40, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1f }, + { CFG_META_BURST, 5 }, + { 0x24, 0x00 }, + { 0x20, 0xc4 }, + { 0x9c, 0x00 }, + { CFG_META_BURST, 5 }, + { 0x30, 0x7f }, + { 0xff, 0xff }, + { 0xff, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x11 }, + { CFG_META_BURST, 21 }, + { 0x58, 0x7f }, + { 0xff, 0xff }, + { 0xff, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x12 }, + { CFG_META_BURST, 21 }, + { 0x44, 0xff }, + { 0x84, 0x59 }, + { 0x16, 0xff }, + { 0x84, 0x59 }, + { 0x16, 0xff }, + { 0x84, 0x59 }, + { 0x16, 0x70 }, + { 0x46, 0x2b }, + { 0x3b, 0x9d }, + { 0x85, 0x0d }, + { 0xe2, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x13 }, + { CFG_META_BURST, 21 }, + { 0x30, 0x7f }, + { 0xff, 0xff }, + { 0xff, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x13 }, + { CFG_META_BURST, 21 }, + { 0x58, 0x4f }, + { 0x9d, 0xf9 }, + { 0x35, 0xb0 }, + { 0x62, 0x06 }, + { 0xcb, 0x4f }, + { 0x9d, 0xf9 }, + { 0x35, 0x49 }, + { 0xe6, 0x9d }, + { 0x16, 0xd5 }, + { 0x55, 0x55 }, + { 0x56, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x14 }, + { CFG_META_BURST, 21 }, + { 0x08, 0x7c }, + { 0xb6, 0xa4 }, + { 0xbc, 0x83 }, + { 0x49, 0x5b }, + { 0x44, 0x7c }, + { 0xb6, 0xa4 }, + { 0xbc, 0x7c }, + { 0xb1, 0x2c }, + { 0x1e, 0x86 }, + { 0x87, 0xc5 }, + { 0x49, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x14 }, + { CFG_META_BURST, 21 }, + { 0x1c, 0x05 }, + { 0xb7, 0x5c }, + { 0x1f, 0x05 }, + { 0xb7, 0x5c }, + { 0x1f, 0x05 }, + { 0xb7, 0x5c }, + { 0x1f, 0x49 }, + { 0xe6, 0x9d }, + { 0x16, 0xd5 }, + { 0x55, 0x55 }, + { 0x56, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x14 }, + { CFG_META_BURST, 21 }, + { 0x58, 0x7f }, + { 0xff, 0xff }, + { 0xff, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x14 }, + { CFG_META_BURST, 21 }, + { 0x6c, 0x7f }, + { 0xff, 0xff }, + { 0xff, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x15 }, + { CFG_META_BURST, 21 }, + { 0x08, 0x7f }, + { 0xff, 0xff }, + { 0xff, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x15 }, + { CFG_META_BURST, 21 }, + { 0x1c, 0x7f }, + { 0xff, 0xff }, + { 0xff, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x15 }, + { CFG_META_BURST, 21 }, + { 0x30, 0x7f }, + { 0xff, 0xff }, + { 0xff, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x15 }, + { CFG_META_BURST, 21 }, + { 0x44, 0x7f }, + { 0xff, 0xff }, + { 0xff, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x15 }, + { CFG_META_BURST, 21 }, + { 0x58, 0x7f }, + { 0xff, 0xff }, + { 0xff, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x15 }, + { CFG_META_BURST, 21 }, + { 0x6c, 0x7f }, + { 0xff, 0xff }, + { 0xff, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x16 }, + { CFG_META_BURST, 21 }, + { 0x08, 0x7f }, + { 0xff, 0xff }, + { 0xff, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x16 }, + { CFG_META_BURST, 21 }, + { 0x1c, 0x7f }, + { 0xff, 0xff }, + { 0xff, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x16 }, + { CFG_META_BURST, 21 }, + { 0x30, 0x7f }, + { 0xff, 0xff }, + { 0xff, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x16 }, + { CFG_META_BURST, 21 }, + { 0x44, 0x7f }, + { 0xff, 0xff }, + { 0xff, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x16 }, + { CFG_META_BURST, 21 }, + { 0x58, 0x7f }, + { 0xff, 0xff }, + { 0xff, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x16 }, + { CFG_META_BURST, 21 }, + { 0x6c, 0x7f }, + { 0xff, 0xff }, + { 0xff, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x17 }, + { CFG_META_BURST, 21 }, + { 0x08, 0x7f }, + { 0xff, 0xff }, + { 0xff, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x17 }, + { CFG_META_BURST, 21 }, + { 0x1c, 0x7f }, + { 0xff, 0xff }, + { 0xff, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x17 }, + { CFG_META_BURST, 21 }, + { 0x30, 0x7f }, + { 0xff, 0xff }, + { 0xff, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x17 }, + { CFG_META_BURST, 21 }, + { 0x44, 0x7f }, + { 0xff, 0xff }, + { 0xff, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x17 }, + { CFG_META_BURST, 21 }, + { 0x58, 0x7f }, + { 0xff, 0xff }, + { 0xff, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x17 }, + { CFG_META_BURST, 21 }, + { 0x6c, 0x7f }, + { 0xff, 0xff }, + { 0xff, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x18 }, + { CFG_META_BURST, 21 }, + { 0x08, 0x08 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x18 }, + { CFG_META_BURST, 21 }, + { 0x1c, 0x7f }, + { 0xff, 0xff }, + { 0xff, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x18 }, + { CFG_META_BURST, 21 }, + { 0x30, 0x7f }, + { 0xff, 0xff }, + { 0xff, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x18 }, + { CFG_META_BURST, 21 }, + { 0x44, 0x7f }, + { 0xff, 0xff }, + { 0xff, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x18 }, + { CFG_META_BURST, 21 }, + { 0x58, 0x7f }, + { 0xff, 0xff }, + { 0xff, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x18 }, + { CFG_META_BURST, 21 }, + { 0x6c, 0x7f }, + { 0xff, 0xff }, + { 0xff, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x19 }, + { CFG_META_BURST, 21 }, + { 0x08, 0x7f }, + { 0xff, 0xff }, + { 0xff, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x19 }, + { CFG_META_BURST, 21 }, + { 0x1c, 0x7f }, + { 0xff, 0xff }, + { 0xff, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x19 }, + { CFG_META_BURST, 21 }, + { 0x30, 0x7f }, + { 0xff, 0xff }, + { 0xff, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x19 }, + { CFG_META_BURST, 21 }, + { 0x44, 0x7f }, + { 0xff, 0xff }, + { 0xff, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x19 }, + { CFG_META_BURST, 21 }, + { 0x58, 0x7f }, + { 0xff, 0xff }, + { 0xff, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x19 }, + { CFG_META_BURST, 21 }, + { 0x6c, 0x7f }, + { 0xff, 0xff }, + { 0xff, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1a }, + { CFG_META_BURST, 21 }, + { 0x08, 0x7f }, + { 0xff, 0xff }, + { 0xff, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1a }, + { CFG_META_BURST, 21 }, + { 0x1c, 0x7f }, + { 0xff, 0xff }, + { 0xff, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1a }, + { CFG_META_BURST, 21 }, + { 0x30, 0x7f }, + { 0xff, 0xff }, + { 0xff, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1a }, + { CFG_META_BURST, 21 }, + { 0x44, 0x08 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1a }, + { CFG_META_BURST, 5 }, + { 0x58, 0x00 }, + { 0xe2, 0xc4 }, + { 0x6b, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1a }, + { CFG_META_BURST, 21 }, + { 0x6c, 0x00 }, + { 0x06, 0xd3 }, + { 0x72, 0x00 }, + { 0x02, 0xbb }, + { 0x06, 0x00 }, + { 0x03, 0x69 }, + { 0xc5, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1b }, + { CFG_META_BURST, 21 }, + { 0x08, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0xf9 }, + { 0xda, 0xbc }, + { 0x21, 0xfc }, + { 0x58, 0x8b }, + { 0x89, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1b }, + { CFG_META_BURST, 41 }, + { 0x1c, 0x00 }, + { 0x06, 0xd3 }, + { 0x72, 0x00 }, + { 0x02, 0xbb }, + { 0x06, 0x00 }, + { 0x03, 0x69 }, + { 0xc5, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0xf9 }, + { 0xda, 0xbc }, + { 0x21, 0xfc }, + { 0x58, 0x8b }, + { 0x89, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1b }, + { CFG_META_BURST, 41 }, + { 0x44, 0x00 }, + { 0x06, 0xd3 }, + { 0x72, 0x00 }, + { 0x02, 0xbb }, + { 0x06, 0x00 }, + { 0x03, 0x69 }, + { 0xc5, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0xf9 }, + { 0xda, 0xbc }, + { 0x21, 0xfc }, + { 0x58, 0x8b }, + { 0x89, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1c }, + { CFG_META_BURST, 21 }, + { 0x6c, 0x7f }, + { 0xff, 0xff }, + { 0xff, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1d }, + { CFG_META_BURST, 21 }, + { 0x08, 0x7f }, + { 0xff, 0xff }, + { 0xff, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1d }, + { CFG_META_BURST, 5 }, + { 0x1c, 0x00 }, + { 0x06, 0xd3 }, + { 0x72, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1d }, + { CFG_META_BURST, 5 }, + { 0x20, 0x1c }, + { 0x1b, 0xf0 }, + { 0x41, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1d }, + { CFG_META_BURST, 5 }, + { 0x24, 0x04 }, + { 0x0c, 0x37 }, + { 0x14, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1d }, + { CFG_META_BURST, 5 }, + { 0x2c, 0x00 }, + { 0x80, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1d }, + { CFG_META_BURST, 5 }, + { 0x34, 0x40 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1d }, + { CFG_META_BURST, 5 }, + { 0x38, 0x40 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1d }, + { CFG_META_BURST, 5 }, + { 0x40, 0x00 }, + { 0x80, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1d }, + { CFG_META_BURST, 5 }, + { 0x44, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1d }, + { CFG_META_BURST, 5 }, + { 0x48, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1d }, + { CFG_META_BURST, 5 }, + { 0x58, 0x00 }, + { 0x00, 0x00 }, + { 0x01, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1d }, + { CFG_META_BURST, 5 }, + { 0x5c, 0x00 }, + { 0x80, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1d }, + { CFG_META_BURST, 5 }, + { 0x60, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1d }, + { CFG_META_BURST, 5 }, + { 0x64, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1d }, + { CFG_META_BURST, 5 }, + { 0x68, 0x00 }, + { 0x80, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1d }, + { CFG_META_BURST, 5 }, + { 0x74, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1d }, + { CFG_META_BURST, 5 }, + { 0x78, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1d }, + { CFG_META_BURST, 5 }, + { 0x7c, 0x00 }, + { 0x80, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1e }, + { CFG_META_BURST, 5 }, + { 0x08, 0x00 }, + { 0x80, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1e }, + { CFG_META_BURST, 5 }, + { 0x0c, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1e }, + { CFG_META_BURST, 5 }, + { 0x10, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1e }, + { CFG_META_BURST, 5 }, + { 0x14, 0x00 }, + { 0x80, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1e }, + { CFG_META_BURST, 5 }, + { 0x18, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1e }, + { CFG_META_BURST, 5 }, + { 0x1c, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1e }, + { CFG_META_BURST, 5 }, + { 0x20, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1e }, + { CFG_META_BURST, 5 }, + { 0x24, 0x00 }, + { 0x80, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1e }, + { CFG_META_BURST, 5 }, + { 0x28, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1e }, + { CFG_META_BURST, 5 }, + { 0x2c, 0x00 }, + { 0x80, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1e }, + { CFG_META_BURST, 5 }, + { 0x30, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1e }, + { CFG_META_BURST, 5 }, + { 0x34, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1e }, + { CFG_META_BURST, 5 }, + { 0x38, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1e }, + { CFG_META_BURST, 5 }, + { 0x3c, 0x00 }, + { 0x80, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1e }, + { CFG_META_BURST, 5 }, + { 0x40, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1e }, + { CFG_META_BURST, 5 }, + { 0x44, 0x00 }, + { 0x00, 0x00 }, + { 0x1b, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1e }, + { CFG_META_BURST, 5 }, + { 0x48, 0x00 }, + { 0x00, 0x00 }, + { 0x1b, 0x00 }, + + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1e }, + { CFG_META_BURST, 5 }, + { 0x50, 0x40 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1e }, + { CFG_META_BURST, 5 }, + { 0x54, 0x04 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1e }, + { CFG_META_BURST, 5 }, + { 0x58, 0x04 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1f }, + { CFG_META_BURST, 5 }, + { 0x14, 0x00 }, + { 0xce, 0xc0 }, + { 0x8a, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1f }, + { CFG_META_BURST, 5 }, + { 0x18, 0x0a }, + { 0x0a, 0xae }, + { 0xd2, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1f }, + { CFG_META_BURST, 5 }, + { 0x1c, 0x00 }, + { 0x03, 0x69 }, + { 0xd0, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1f }, + { CFG_META_BURST, 5 }, + { 0x20, 0x40 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1f }, + { CFG_META_BURST, 5 }, + { 0x28, 0x75 }, + { 0xf5, 0x51 }, + { 0x2e, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x1f }, + { CFG_META_BURST, 5 }, + { 0x2c, 0x00 }, + { 0x00, 0x57 }, + { 0x62, 0x00 }, + + //swap command + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x8c }, + { CFG_META_BURST, 2 }, + { 0x00, 0x23 }, + { CFG_META_BURST, 5 }, + { 0x14, 0x00 }, + { 0x00, 0x00 }, + { 0x01, 0x00 }, + + //register tuning + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x07, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x08, 0x20 }, + { CFG_META_BURST, 2 }, + { 0x55, 0x07 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x3d, 0x30 }, + { CFG_META_BURST, 2 }, + { 0x3e, 0x30 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x01 }, + { CFG_META_BURST, 2 }, + { 0x02, 0x00 }, + + //Unmute the device + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x03, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x2a, 0x11 }, + + //start set volume + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x3d, 0x4f }, + + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x7f, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x00, 0x00 }, + { CFG_META_BURST, 2 }, + { 0x3e, 0x4f }, + //end set volume +}; + +#endif diff --git a/sound/soc/codecs/amlogic/tas5805.c b/sound/soc/codecs/amlogic/tas5805.c index 36f11cf2c519..e6f8d21c10a1 100644 --- a/sound/soc/codecs/amlogic/tas5805.c +++ b/sound/soc/codecs/amlogic/tas5805.c @@ -24,10 +24,11 @@ #include #include #include +#include #include "tas5805.h" -#define TAS5805M_DRV_NAME "tas5805m" +#define TAS5805M_DRV_NAME "tas5805" #define TAS5805M_RATES (SNDRV_PCM_RATE_8000 | \ SNDRV_PCM_RATE_11025 | \ @@ -52,6 +53,7 @@ #define TAS5805M_REG_2A (0x2a) #define TAS5805M_REG_2B (0x2b) #define TAS5805M_REG_35 (0x35) +#define TAS5805M_DIG_VAL_CTL (0x4c) #define TAS5805M_REG_7F (0x7f) #define TAS5805M_PAGE_00 (0x00) @@ -60,7 +62,7 @@ #define TAS5805M_BOOK_00 (0x00) #define TAS5805M_BOOK_8C (0x8c) -#define TAS5805M_VOLUME_MAX (158) +#define TAS5805M_VOLUME_MAX (578) #define TAS5805M_VOLUME_MIN (0) const uint32_t tas5805m_volume[] = { @@ -144,94 +146,520 @@ const uint32_t tas5805m_volume[] = { 0x0002DD96, //77, -33dB 0x00033718, //78, -32dB 0x00039B87, //79, -31dB - 0x00040C37, //80, -30dB - 0x00048AA7, //81, -29dB - 0x00051884, //82, -28dB - 0x0005B7B1, //83, -27dB - 0x00066A4A, //84, -26dB - 0x000732AE, //85, -25dB - 0x00081385, //86, -24dB - 0x00090FCC, //87, -23dB - 0x000A2ADB, //88, -22dB - 0x000B6873, //89, -21dB - 0x000CCCCD, //90, -20dB - 0x000E5CA1, //91, -19dB - 0x00101D3F, //92, -18dB - 0x0012149A, //93, -17dB - 0x00144961, //94, -16dB - 0x0016C311, //95, -15dB - 0x00198A13, //96, -14dB - 0x001CA7D7, //97, -13dB - 0x002026F3, //98, -12dB - 0x00241347, //99, -11dB - 0x00287A27, //100, -10dB - 0x002D6A86, //101, -9dB - 0x0032F52D, //102, -8dB - 0x00392CEE, //103, -7dB - 0x004026E7, //104, -6dB - 0x0047FACD, //105, -5dB - 0x0050C336, //106, -4dB - 0x005A9DF8, //107, -3dB - 0x0065AC8C, //108, -2dB - 0x00721483, //109, -1dB - 0x00800000, //110, 0dB - 0x008F9E4D, //111, 1dB - 0x00A12478, //112, 2dB - 0x00B4CE08, //113, 3dB - 0x00CADDC8, //114, 4dB - 0x00E39EA9, //115, 5dB - 0x00FF64C1, //116, 6dB - 0x011E8E6A, //117, 7dB - 0x0141857F, //118, 8dB - 0x0168C0C6, //119, 9dB - 0x0194C584, //120, 10dB - 0x01C62940, //121, 11dB - 0x01FD93C2, //122, 12dB - 0x023BC148, //123, 13dB - 0x02818508, //124, 14dB - 0x02CFCC01, //125, 15dB - 0x0327A01A, //126, 16dB - 0x038A2BAD, //127, 17dB - 0x03F8BD7A, //128, 18dB - 0x0474CD1B, //129, 19dB - 0x05000000, //130, 20dB - 0x059C2F02, //131, 21dB - 0x064B6CAE, //132, 22dB - 0x07100C4D, //133, 23dB - 0x07ECA9CD, //134, 24dB - 0x08E43299, //135, 25dB - 0x09F9EF8E, //136, 26dB - 0x0B319025, //137, 27dB - 0x0C8F36F2, //138, 28dB - 0x0E1787B8, //139, 29dB - 0x0FCFB725, //140, 30dB - 0x11BD9C84, //141, 31dB - 0x13E7C594, //142, 32dB - 0x16558CCB, //143, 33dB - 0x190F3254, //144, 34dB - 0x1C1DF80E, //145, 35dB - 0x1F8C4107, //146, 36dB - 0x2365B4BF, //147, 37dB - 0x27B766C2, //148, 38dB - 0x2C900313, //149, 39dB - 0x32000000, //150, 40dB - 0x3819D612, //151, 41dB - 0x3EF23ECA, //152, 42dB - 0x46A07B07, //153, 43dB - 0x4F3EA203, //154, 44dB - 0x58E9F9F9, //155, 45dB - 0x63C35B8E, //156, 46dB - 0x6FEFA16D, //157, 47dB - 0x7D982575, //158, 48dB + 0x00040C37, //80 -30 + 0x00041B3C, //81 -29.875 + 0x00042A79, //82 -29.75 + 0x000439EE, //83 -29.625 + 0x0004499D, //84 -29.5 + 0x00045986, //85 -29.375 + 0x000469AA, //86 -29.25 + 0x00047A0A, //87 -29.125 + 0x00048AA7, //88 -29 + 0x00049B81, //89 -28.875 + 0x0004AC9A, //90 -28.75 + 0x0004BDF2, //91 -28.625 + 0x0004CF8B, //92 -28.5 + 0x0004E165, //93 -28.375 + 0x0004F381, //94 -28.25 + 0x000505E0, //95 -28.125 + 0x00051884, //96 -28 + 0x00052B6D, //97 -27.875 + 0x00053E9C, //98 -27.75 + 0x00055212, //99 -27.625 + 0x000565D0, //100 -27.5 + 0x000579D8, //101 -27.375 + 0x00058E2A, //102 -27.25 + 0x0005A2C7, //103 -27.125 + 0x0005B7B1, //104 -27 + 0x0005CCE8, //105 -26.875 + 0x0005E26E, //106 -26.75 + 0x0005F844, //107 -26.625 + 0x00060E6C, //108 -26.5 + 0x000624E5, //109 -26.375 + 0x00063BB1, //110 -26.25 + 0x000652D3, //111 -26.125 + 0x00066A4A, //112 -26 + 0x00068218, //113 -25.875 + 0x00069A3E, //114 -25.75 + 0x0006B2BF, //115 -25.625 + 0x0006CB9A, //116 -25.5 + 0x0006E4D1, //117 -25.375 + 0x0006FE66, //118 -25.25 + 0x0007185A, //119 -25.125 + 0x000732AE, //120 -25 + 0x00074D63, //121 -24.875 + 0x0007687C, //122 -24.75 + 0x000783FA, //123 -24.625 + 0x00079FDD, //124 -24.5 + 0x0007BC28, //125 -24.375 + 0x0007D8DC, //126 -24.25 + 0x0007F5FA, //127 -24.125 + 0x00081385, //128 -24 + 0x0008317D, //129 -23.875 + 0x00084FE4, //130 -23.75 + 0x00086EBC, //131 -23.625 + 0x00088E07, //132 -23.5 + 0x0008ADC6, //133 -23.375 + 0x0008CDFA, //134 -23.25 + 0x0008EEA6, //135 -23.125 + 0x00090FCB, //136 -23 + 0x0009316C, //137 -22.875 + 0x00095389, //138 -22.75 + 0x00097624, //139 -22.625 + 0x00099940, //140 -22.5 + 0x0009BCDF, //141 -22.375 + 0x0009E101, //142 -22.25 + 0x000A05AA, //143 -22.125 + 0x000A2ADA, //144 -22 + 0x000A5095, //145 -21.875 + 0x000A76DC, //146 -21.75 + 0x000A9DB0, //147 -21.625 + 0x000AC515, //148 -21.5 + 0x000AED0C, //149 -21.375 + 0x000B1597, //150 -21.25 + 0x000B3EB9, //151 -21.125 + 0x000B6873, //152 -21 + 0x000B92C8, //153 -20.875 + 0x000BBDBA, //154 -20.75 + 0x000BE94C, //155 -20.625 + 0x000C157F, //156 -20.5 + 0x000C4256, //157 -20.375 + 0x000C6FD4, //158 -20.25 + 0x000C9DFB, //159 -20.125 + 0x000CCCCC, //160 -20 + 0x000CFC4C, //161 -19.875 + 0x000D2C7B, //162 -19.75 + 0x000D5D5E, //163 -19.625 + 0x000D8EF6, //164 -19.5 + 0x000DC146, //165 -19.375 + 0x000DF451, //166 -19.25 + 0x000E2819, //167 -19.125 + 0x000E5CA1, //168 -19 + 0x000E91EC, //169 -18.875 + 0x000EC7FD, //170 -18.75 + 0x000EFED6, //171 -18.625 + 0x000F367B, //172 -18.5 + 0x000F6EEF, //173 -18.375 + 0x000FA834, //174 -18.25 + 0x000FE24E, //175 -18.125 + 0x00101D3F, //176 -18 + 0x0010590B, //177 -17.875 + 0x001095B4, //178 -17.75 + 0x0010D33F, //179 -17.625 + 0x001111AE, //180 -17.5 + 0x00115105, //181 -17.375 + 0x00119147, //182 -17.25 + 0x0011D278, //183 -17.125 + 0x0012149A, //184 -17 + 0x001257B2, //185 -16.875 + 0x00129BC2, //186 -16.75 + 0x0012E0CF, //187 -16.625 + 0x001326DD, //188 -16.5 + 0x00136DEE, //189 -16.375 + 0x0013B607, //190 -16.25 + 0x0013FF2C, //191 -16.125 + 0x00144960, //192 -16 + 0x001494A8, //193 -15.875 + 0x0014E107, //194 -15.75 + 0x00152E81, //195 -15.625 + 0x00157D1A, //196 -15.5 + 0x0015CCD8, //197 -15.375 + 0x00161DBD, //198 -15.25 + 0x00166FCE, //199 -15.125 + 0x0016C310, //200 -15 + 0x00171787, //201 -14.875 + 0x00176D38, //202 -14.75 + 0x0017C426, //203 -14.625 + 0x00181C57, //204 -14.5 + 0x001875CF, //205 -14.375 + 0x0018D093, //206 -14.25 + 0x00192CA8, //207 -14.125 + 0x00198A13, //208 -14 + 0x0019E8D8, //209 -13.875 + 0x001A48FD, //210 -13.75 + 0x001AAA87, //211 -13.625 + 0x001B0D7B, //212 -13.5 + 0x001B71DD, //213 -13.375 + 0x001BD7B5, //214 -13.25 + 0x001C3F06, //215 -13.125 + 0x001CA7D7, //216 -13 + 0x001D122D, //217 -12.875 + 0x001D7E0D, //218 -12.75 + 0x001DEB7D, //219 -12.625 + 0x001E5A84, //220 -12.5 + 0x001ECB27, //221 -12.375 + 0x001F3D6B, //222 -12.25 + 0x001FB158, //223 -12.125 + 0x002026F3, //224 -12 + 0x00209E42, //225 -11.875 + 0x0021174C, //226 -11.75 + 0x00219217, //227 -11.625 + 0x00220EA9, //228 -11.5 + 0x00228D0A, //229 -11.375 + 0x00230D40, //230 -11.25 + 0x00238F52, //231 -11.125 + 0x00241346, //232 -11 + 0x00249924, //233 -10.875 + 0x002520F3, //234 -10.75 + 0x0025AABA, //235 -10.625 + 0x00263680, //236 -10.5 + 0x0026C44D, //237 -10.375 + 0x00275427, //238 -10.25 + 0x0027E618, //239 -10.125 + 0x00287A26, //240 -10 + 0x0029105A, //241 -9.875 + 0x0029A8BB, //242 -9.75 + 0x002A4351, //243 -9.625 + 0x002AE025, //244 -9.5 + 0x002B7F3F, //245 -9.375 + 0x002C20A8, //246 -9.25 + 0x002CC467, //247 -9.125 + 0x002D6A86, //248 -9 + 0x002E130D, //249 -8.875 + 0x002EBE06, //250 -8.75 + 0x002F6B79, //251 -8.625 + 0x00301B70, //252 -8.5 + 0x0030CDF4, //253 -8.375 + 0x0031830E, //254 -8.25 + 0x00323AC8, //255 -8.125 + 0x0032F52C, //256 -8 + 0x0033B244, //257 -7.875 + 0x0034721A, //258 -7.75 + 0x003534B7, //259 -7.625 + 0x0035FA26, //260 -7.5 + 0x0036C272, //261 -7.375 + 0x00378DA5, //262 -7.25 + 0x00385BCB, //263 -7.125 + 0x00392CED, //264 -7 + 0x003A0117, //265 -6.875 + 0x003AD855, //266 -6.75 + 0x003BB2B1, //267 -6.625 + 0x003C9038, //268 -6.5 + 0x003D70F5, //269 -6.375 + 0x003E54F3, //270 -6.25 + 0x003F3C40, //271 -6.125 + 0x004026E7, //272 -6 + 0x004114F4, //273 -5.875 + 0x00420675, //274 -5.75 + 0x0042FB77, //275 -5.625 + 0x0043F405, //276 -5.5 + 0x0044F02E, //277 -5.375 + 0x0045EFFE, //278 -5.25 + 0x0046F384, //279 -5.125 + 0x0047FACC, //280 -5 + 0x004905E6, //281 -4.875 + 0x004A14DF, //282 -4.75 + 0x004B27C5, //283 -4.625 + 0x004C3EA8, //284 -4.5 + 0x004D5995, //285 -4.375 + 0x004E789C, //286 -4.25 + 0x004F9BCD, //287 -4.125 + 0x0050C335, //288 -4 + 0x0051EEE6, //289 -3.875 + 0x00531EEF, //290 -3.75 + 0x00545361, //291 -3.625 + 0x00558C4B, //292 -3.5 + 0x0056C9BE, //293 -3.375 + 0x00580BCB, //294 -3.25 + 0x00595283, //295 -3.125 + 0x005A9DF7, //296 -3 + 0x005BEE3A, //297 -2.875 + 0x005D435C, //298 -2.75 + 0x005E9D70, //299 -2.625 + 0x005FFC88, //300 -2.5 + 0x006160B7, //301 -2.375 + 0x0062CA10, //302 -2.25 + 0x006438A6, //303 -2.125 + 0x0065AC8C, //304 -2 + 0x006725D6, //305 -1.875 + 0x0068A498, //306 -1.75 + 0x006A28E6, //307 -1.625 + 0x006BB2D6, //308 -1.5 + 0x006D427B, //309 -1.375 + 0x006ED7EB, //310 -1.25 + 0x0070733B, //311 -1.125 + 0x00721482, //312 -1 + 0x0073BBD6, //313 -0.875 + 0x0075694C, //314 -0.75 + 0x00771CFC, //315 -0.625 + 0x0078D6FC, //316 -0.5 + 0x007A9765, //317 -0.375 + 0x007C5E4E, //318 -0.25 + 0x007E2BCE, //319 -0.125 + 0x00800000, //320 0 + 0x0081DAFA, //321 0.125 + 0x0083BCD7, //322 0.25 + 0x0085A5B1, //323 0.375 + 0x008795A0, //324 0.5 + 0x00898CBF, //325 0.625 + 0x008B8B2A, //326 0.75 + 0x008D90FA, //327 0.875 + 0x008F9E4C, //328 1 + 0x0091B33C, //329 1.125 + 0x0093CFE5, //330 1.25 + 0x0095F464, //331 1.375 + 0x009820D7, //332 1.5 + 0x009A555A, //333 1.625 + 0x009C920D, //334 1.75 + 0x009ED70C, //335 1.875 + 0x00A12477, //336 2 + 0x00A37A6E, //337 2.125 + 0x00A5D90F, //338 2.25 + 0x00A8407C, //339 2.375 + 0x00AAB0D4, //340 2.5 + 0x00AD2A39, //341 2.625 + 0x00AFACCC, //342 2.75 + 0x00B238B0, //343 2.875 + 0x00B4CE07, //344 3 + 0x00B76CF4, //345 3.125 + 0x00BA159B, //346 3.25 + 0x00BCC81F, //347 3.375 + 0x00BF84A6, //348 3.5 + 0x00C24B54, //349 3.625 + 0x00C51C4F, //350 3.75 + 0x00C7F7BE, //351 3.875 + 0x00CADDC7, //352 4 + 0x00CDCE92, //353 4.125 + 0x00D0CA46, //354 4.25 + 0x00D3D10B, //355 4.375 + 0x00D6E30C, //356 4.5 + 0x00DA0072, //357 4.625 + 0x00DD2966, //358 4.75 + 0x00E05E15, //359 4.875 + 0x00E39EA8, //360 5 + 0x00E6EB4E, //361 5.125 + 0x00EA4431, //362 5.25 + 0x00EDA980, //363 5.375 + 0x00F11B69, //364 5.5 + 0x00F49A1B, //365 5.625 + 0x00F825C5, //366 5.75 + 0x00FBBE96, //367 5.875 + 0x00FF64C1, //368 6 + 0x01031876, //369 6.125 + 0x0106D9E8, //370 6.25 + 0x010AA94A, //371 6.375 + 0x010E86CF, //372 6.5 + 0x011272AB, //373 6.625 + 0x01166D15, //374 6.75 + 0x011A7643, //375 6.875 + 0x011E8E6A, //376 7 + 0x0122B5C2, //377 7.125 + 0x0126EC84, //378 7.25 + 0x012B32EA, //379 7.375 + 0x012F892C, //380 7.5 + 0x0133EF86, //381 7.625 + 0x01386634, //382 7.75 + 0x013CED72, //383 7.875 + 0x0141857E, //384 8 + 0x01462E96, //385 8.125 + 0x014AE8F9, //386 8.25 + 0x014FB4E8, //387 8.375 + 0x015492A3, //388 8.5 + 0x0159826D, //389 8.625 + 0x015E8488, //390 8.75 + 0x01639939, //391 8.875 + 0x0168C0C5, //392 9 + 0x016DFB71, //393 9.125 + 0x01734985, //394 9.25 + 0x0178AB48, //395 9.375 + 0x017E2104, //396 9.5 + 0x0183AB02, //397 9.625 + 0x0189498F, //398 9.75 + 0x018EFCF5, //399 9.875 + 0x0194C583, //400 10 + 0x019AA387, //401 10.125 + 0x01A09751, //402 10.25 + 0x01A6A131, //403 10.375 + 0x01ACC179, //404 10.5 + 0x01B2F87D, //405 10.625 + 0x01B94691, //406 10.75 + 0x01BFAC0A, //407 10.875 + 0x01C62940, //408 11 + 0x01CCBE8A, //409 11.125 + 0x01D36C42, //410 11.25 + 0x01DA32C2, //411 11.375 + 0x01E11266, //412 11.5 + 0x01E80B8C, //413 11.625 + 0x01EF1E92, //414 11.75 + 0x01F64BD9, //415 11.875 + 0x01FD93C1, //416 12 + 0x0204F6AE, //417 12.125 + 0x020C7504, //418 12.25 + 0x02140F28, //419 12.375 + 0x021BC582, //420 12.5 + 0x0223987A, //421 12.625 + 0x022B887B, //422 12.75 + 0x023395F0, //423 12.875 + 0x023BC147, //424 13 + 0x02440AEE, //425 13.125 + 0x024C7356, //426 13.25 + 0x0254FAF2, //427 13.375 + 0x025DA234, //428 13.5 + 0x02666992, //429 13.625 + 0x026F5184, //430 13.75 + 0x02785A83, //431 13.875 + 0x02818508, //432 14 + 0x028AD191, //433 14.125 + 0x0294409B, //434 14.25 + 0x029DD2A7, //435 14.375 + 0x02A78836, //436 14.5 + 0x02B161CD, //437 14.625 + 0x02BB5FF1, //438 14.75 + 0x02C5832A, //439 14.875 + 0x02CFCC01, //440 15 + 0x02DA3B02, //441 15.125 + 0x02E4D0BA, //442 15.25 + 0x02EF8DB9, //443 15.375 + 0x02FA7292, //444 15.5 + 0x03057FD7, //445 15.625 + 0x0310B61F, //446 15.75 + 0x031C1602, //447 15.875 + 0x0327A01A, //448 16 + 0x03335504, //449 16.125 + 0x033F355F, //450 16.25 + 0x034B41CC, //451 16.375 + 0x03577AEF, //452 16.5 + 0x0363E16D, //453 16.625 + 0x037075EF, //454 16.75 + 0x037D3920, //455 16.875 + 0x038A2BAC, //456 17 + 0x03974E44, //457 17.125 + 0x03A4A19A, //458 17.25 + 0x03B22662, //459 17.375 + 0x03BFDD55, //460 17.5 + 0x03CDC72C, //461 17.625 + 0x03DBE4A4, //462 17.75 + 0x03EA367D, //463 17.875 + 0x03F8BD79, //464 18 + 0x04077A5E, //465 18.125 + 0x04166DF2, //466 18.25 + 0x04259902, //467 18.375 + 0x0434FC5C, //468 18.5 + 0x044498CF, //469 18.625 + 0x04546F30, //470 18.75 + 0x04648056, //471 18.875 + 0x0474CD1B, //472 19 + 0x0485565C, //473 19.125 + 0x04961CFA, //474 19.25 + 0x04A721D8, //475 19.375 + 0x04B865DE, //476 19.5 + 0x04C9E9F5, //477 19.625 + 0x04DBAF0C, //478 19.75 + 0x04EDB613, //479 19.875 + 0x05000000, //480 20 + 0x05128DCA, //481 20.125 + 0x0525606D, //482 20.25 + 0x053878EA, //483 20.375 + 0x054BD842, //484 20.5 + 0x055F7F7E, //485 20.625 + 0x05736FA7, //486 20.75 + 0x0587A9CD, //487 20.875 + 0x059C2F01, //488 21 + 0x05B1005B, //489 21.125 + 0x05C61EF5, //490 21.25 + 0x05DB8BEE, //491 21.375 + 0x05F14868, //492 21.5 + 0x0607558B, //493 21.625 + 0x061DB482, //494 21.75 + 0x0634667C, //495 21.875 + 0x064B6CAD, //496 22 + 0x0662C84F, //497 22.125 + 0x067A7A9D, //498 22.25 + 0x069284DB, //499 22.375 + 0x06AAE84D, //500 22.5 + 0x06C3A63F, //501 22.625 + 0x06DCC001, //502 22.75 + 0x06F636E8, //503 22.875 + 0x07100C4D, //504 23 + 0x072A418F, //505 23.125 + 0x0744D811, //506 23.25 + 0x075FD13C, //507 23.375 + 0x077B2E7F, //508 23.5 + 0x0796F14D, //509 23.625 + 0x07B31B1F, //510 23.75 + 0x07CFAD73, //511 23.875 + 0x07ECA9CD, //512 24 + 0x080A11B5, //513 24.125 + 0x0827E6BD, //514 24.25 + 0x08462A77, //515 24.375 + 0x0864DE80, //516 24.5 + 0x08840477, //517 24.625 + 0x08A39E04, //518 24.75 + 0x08C3ACD3, //519 24.875 + 0x08E43298, //520 25 + 0x0905310C, //521 25.125 + 0x0926A9EF, //522 25.25 + 0x09489F07, //523 25.375 + 0x096B1222, //524 25.5 + 0x098E0512, //525 25.625 + 0x09B179B2, //526 25.75 + 0x09D571E3, //527 25.875 + 0x09F9EF8E, //528 26 + 0x0A1EF4A1, //529 26.125 + 0x0A448314, //530 26.25 + 0x0A6A9CE4, //531 26.375 + 0x0A914416, //532 26.5 + 0x0AB87AB7, //533 26.625 + 0x0AE042DB, //534 26.75 + 0x0B089E9E, //535 26.875 + 0x0B319024, //536 27 + 0x0B5B1998, //537 27.125 + 0x0B853D2F, //538 27.25 + 0x0BAFFD24, //539 27.375 + 0x0BDB5BBC, //540 27.5 + 0x0C075B43, //541 27.625 + 0x0C33FE0E, //542 27.75 + 0x0C61467B, //543 27.875 + 0x0C8F36F2, //544 28 + 0x0CBDD1E0, //545 28.125 + 0x0CED19C0, //546 28.25 + 0x0D1D1113, //547 28.375 + 0x0D4DBA63, //548 28.5 + 0x0D7F1845, //549 28.625 + 0x0DB12D58, //550 28.75 + 0x0DE3FC43, //551 28.875 + 0x0E1787B8, //552 29 + 0x0E4BD272, //553 29.125 + 0x0E80DF37, //554 29.25 + 0x0EB6B0D7, //555 29.375 + 0x0EED4A2D, //556 29.5 + 0x0F24AE1D, //557 29.625 + 0x0F5CDF98, //558 29.75 + 0x0F95E199, //559 29.875 + 0x0FCFB724, //560 30 + 0x11BD9C84, //561 31dB + 0x13E7C594, //562 32dB + 0x16558CCB, //563 33dB + 0x190F3254, //564 34dB + 0x1C1DF80E, //565 35dB + 0x1F8C4107, //566 36dB + 0x2365B4BF, //567 37dB + 0x27B766C2, //568 38dB + 0x2C900313, //569 39dB + 0x32000000, //570 40dB + 0x3819D612, //571 41dB + 0x3EF23ECA, //572 42dB + 0x46A07B07, //573 43dB + 0x4F3EA203, //574 44dB + 0x58E9F9F9, //575 45dB + 0x63C35B8E, //576 46dB + 0x6FEFA16D, //577 47dB + 0x7D982575, //578 48dB }; +#define TAS5805_EQPARAM_LENGTH 610 +#define TAS5805_EQ_LENGTH 245 +#define FILTER_PARAM_BYTE 244 +static int m_eq_tab[TAS5805_EQPARAM_LENGTH][2] = {0}; +#define TAS5805_DRC_PARAM_LENGTH 29 +#define TAS5805_DRC_PARAM_COUNT 58 +static int m_drc_tab[TAS5805_DRC_PARAM_LENGTH][2] = {0}; struct tas5805m_priv { struct regmap *regmap; - - struct mutex lock; - + struct tas5805m_platform_data *pdata; int vol; int mute; + struct snd_soc_codec *codec; }; const struct regmap_config tas5805m_regmap = { @@ -276,9 +704,7 @@ static int tas5805m_vol_locked_get(struct snd_kcontrol *kcontrol, struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); struct tas5805m_priv *tas5805m = snd_soc_codec_get_drvdata(codec); - mutex_lock(&tas5805m->lock); ucontrol->value.integer.value[0] = tas5805m->vol; - mutex_unlock(&tas5805m->lock); return 0; } @@ -339,13 +765,10 @@ static int tas5805m_vol_locked_put(struct snd_kcontrol *kcontrol, struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); struct tas5805m_priv *tas5805m = snd_soc_codec_get_drvdata(codec); - mutex_lock(&tas5805m->lock); tas5805m->vol = ucontrol->value.integer.value[0]; tas5805m_set_volume(codec, tas5805m->vol); - mutex_unlock(&tas5805m->lock); - return 0; } @@ -353,7 +776,6 @@ static int tas5805m_mute(struct snd_soc_codec *codec, int mute) { u8 reg03_value = 0; u8 reg35_value = 0; -// struct snd_soc_codec *codec = dai->codec; if (mute) { //mute both left & right channels @@ -380,13 +802,9 @@ static int tas5805m_mute_locked_put(struct snd_kcontrol *kcontrol, struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); struct tas5805m_priv *tas5805m = snd_soc_codec_get_drvdata(codec); - mutex_lock(&tas5805m->lock); - tas5805m->mute = ucontrol->value.integer.value[0]; tas5805m_mute(codec, tas5805m->mute); - mutex_unlock(&tas5805m->lock); - return 0; } @@ -395,18 +813,114 @@ static int tas5805m_mute_locked_get(struct snd_kcontrol *kcontrol, { struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); struct tas5805m_priv *tas5805m = snd_soc_codec_get_drvdata(codec); - - mutex_lock(&tas5805m->lock); ucontrol->value.integer.value[0] = tas5805m->mute; - mutex_unlock(&tas5805m->lock); - return 0; } +static int tas5805_set_EQ_enum(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + return 0; +} + +static int tas5805_get_EQ_enum(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + return 0; +} + +static int tas5805_set_DRC_enum(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + return 0; +} + +static int tas5805_get_DRC_enum(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + return 0; +} + +static int tas5805_set_DRC_param(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + void *data; + char tmp_string[TAS5805_DRC_PARAM_COUNT]; + char *p_string = &tmp_string[0]; + u8 *val; + unsigned int i = 0; + + data = kmemdup(ucontrol->value.bytes.data, + TAS5805_DRC_PARAM_COUNT, GFP_KERNEL | GFP_DMA); + if (!data) + return -ENOMEM; + + val = (u8 *)data; + memcpy(p_string, val, TAS5805_DRC_PARAM_COUNT); + + for (i = 0; i < TAS5805_DRC_PARAM_COUNT/2; i++) { + m_drc_tab[i][0] = tmp_string[2*i]; + m_drc_tab[i][1] = tmp_string[2*i+1]; + } + + for (i = 0; i < TAS5805_DRC_PARAM_LENGTH; i++) + snd_soc_write(codec, m_drc_tab[i][0], m_drc_tab[i][1]); + + kfree(data); + return 0; +} + +static int tas5805_get_DRC_param(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + return 0; +} + + +static int tas5805_set_EQ_param(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + void *data; + char tmp_string[TAS5805_EQ_LENGTH]; + char *p_string = &tmp_string[0]; + u8 *val; + int band_id; + unsigned int i = 0, j = 0; + + data = kmemdup(ucontrol->value.bytes.data, + TAS5805_EQ_LENGTH, GFP_KERNEL | GFP_DMA); + if (!data) + return -ENOMEM; + + val = (u8 *) data; + memcpy(p_string, val, TAS5805_EQ_LENGTH); + band_id = tmp_string[0]; + for (j = 0, i = band_id * FILTER_PARAM_BYTE / 2; + j < FILTER_PARAM_BYTE / 2; i++, j++) { + m_eq_tab[i][0] = tmp_string[2*j+1]; + m_eq_tab[i][1] = tmp_string[2*j+2]; + } + if (band_id == 4) { + for (i = 0; i < TAS5805_EQPARAM_LENGTH; i++) + snd_soc_write(codec, m_eq_tab[i][0], m_eq_tab[i][1]); + } + kfree(data); + return 0; +} + +static int tas5805_get_EQ_param(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + return 0; +} + + static const struct snd_kcontrol_new tas5805m_vol_control[] = { { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Master Playback Volume", + .name = "Master Volume", .info = tas5805m_vol_info, .get = tas5805m_vol_locked_get, .put = tas5805m_vol_locked_put, @@ -417,24 +931,207 @@ static const struct snd_kcontrol_new tas5805m_vol_control[] = { .info = tas5805m_mute_info, .get = tas5805m_mute_locked_get, .put = tas5805m_mute_locked_put, - } + }, + SOC_SINGLE_BOOL_EXT("Set EQ Enable", 0, + tas5805_get_EQ_enum, tas5805_set_EQ_enum), + SOC_SINGLE_BOOL_EXT("Set DRC Enable", 0, + tas5805_get_DRC_enum, tas5805_set_DRC_enum), + SND_SOC_BYTES_EXT("EQ table", TAS5805_EQ_LENGTH, + tas5805_get_EQ_param, tas5805_set_EQ_param), + SND_SOC_BYTES_EXT("DRC table", TAS5805_DRC_PARAM_COUNT, + tas5805_get_DRC_param, tas5805_set_DRC_param), }; -static int tas5805m_snd_probe(struct snd_soc_codec *codec) +static int tas5805m_set_bias_level(struct snd_soc_codec *codec, + enum snd_soc_bias_level level) +{ + pr_debug("level = %d\n", level); + + switch (level) { + case SND_SOC_BIAS_ON: + break; + + case SND_SOC_BIAS_PREPARE: + /* Full power on */ + break; + + case SND_SOC_BIAS_STANDBY: + break; + + case SND_SOC_BIAS_OFF: + /* The chip runs through the power down sequence for us. */ + break; + } + codec->component.dapm.bias_level = level; + + return 0; +} + +static int tas5805m_trigger(struct snd_pcm_substream *substream, int cmd, + struct snd_soc_dai *codec_dai) +{ + struct tas5805m_priv *tas5805m = snd_soc_dai_get_drvdata(codec_dai); + struct snd_soc_codec *codec = tas5805m->codec; + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + pr_debug("%s(), start\n", __func__); + snd_soc_write(codec, TAS5805M_REG_00, TAS5805M_PAGE_00); + snd_soc_write(codec, TAS5805M_REG_7F, TAS5805M_BOOK_00); + snd_soc_write(codec, TAS5805M_REG_00, TAS5805M_PAGE_00); + snd_soc_write(codec, TAS5805M_DIG_VAL_CTL, 0x30); + break; + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + pr_debug("%s(), stop\n", __func__); + snd_soc_write(codec, TAS5805M_REG_00, TAS5805M_PAGE_00); + snd_soc_write(codec, TAS5805M_REG_7F, TAS5805M_BOOK_00); + snd_soc_write(codec, TAS5805M_REG_00, TAS5805M_PAGE_00); + snd_soc_write(codec, TAS5805M_DIG_VAL_CTL, 0xff); + break; + } + } + return 0; +} +static int reset_tas5805m_GPIO(struct device *dev) +{ + struct tas5805m_priv *tas5805m = dev_get_drvdata(dev); + struct tas5805m_platform_data *pdata = tas5805m->pdata; + int ret = 0; + + if (pdata->reset_pin < 0) + return 0; + + ret = devm_gpio_request_one(dev, pdata->reset_pin, + GPIOF_OUT_INIT_LOW, + "tas5805m-reset-pin"); + if (ret < 0) + return -1; + + gpio_direction_output(pdata->reset_pin, GPIOF_OUT_INIT_LOW); + mdelay(1); + gpio_direction_output(pdata->reset_pin, GPIOF_OUT_INIT_HIGH); + mdelay(5); + + return 0; +} + +static int tas5805m_snd_suspend(struct snd_soc_codec *codec) +{ + struct tas5805m_priv *tas5805m = snd_soc_codec_get_drvdata(codec); + struct tas5805m_platform_data *pdata = tas5805m->pdata; + dev_info(codec->dev, "tas5805m_suspend!\n"); + tas5805m_set_bias_level(codec, SND_SOC_BIAS_OFF); + + if (pdata->reset_pin) + gpio_direction_output(pdata->reset_pin, GPIOF_OUT_INIT_LOW); + udelay(10); + return 0; +} + + +static int tas5805m_reg_init(struct snd_soc_codec *codec) +{ + int i, j = 0; + + for (j = 0; j < ARRAY_SIZE(tas5805m_reset); j++) { + snd_soc_write(codec, tas5805m_reset[j][0], + tas5805m_reset[j][1]); + }; + mdelay(10); + for (i = 0; i < ARRAY_SIZE(tas5805m_init_sequence); i++) { + snd_soc_write(codec, tas5805m_init_sequence[i][0], + tas5805m_init_sequence[i][1]); + }; + return 0; + +} + +static int tas5805m_snd_resume(struct snd_soc_codec *codec) { int ret; + struct tas5805m_priv *tas5805m = snd_soc_codec_get_drvdata(codec); + struct tas5805m_platform_data *pdata = tas5805m->pdata; + dev_info(codec->dev, "tas5805m_snd_resume!\n"); - ret = snd_soc_add_codec_controls(codec, tas5805m_vol_control, 2); + if (pdata->reset_pin) + gpio_direction_output(pdata->reset_pin, GPIOF_OUT_INIT_HIGH); + mdelay(3); + + ret = tas5805m_reg_init(codec); +// regmap_register_patch(tas5805m->regmap, tas5805m_init_sequence, +// ARRAY_SIZE(tas5805m_init_sequence)); + if (ret != 0) { + dev_err(codec->dev, "Failed to initialize TAS5805M: %d\n", ret); + goto err; + } + + tas5805m_set_volume(codec, tas5805m->vol); + tas5805m_set_bias_level(codec, SND_SOC_BIAS_STANDBY); + + return 0; +err: return ret; } + + + +static int tas5805m_probe(struct snd_soc_codec *codec) +{ + int ret; + struct tas5805m_priv *tas5805m = snd_soc_codec_get_drvdata(codec); + +// ret = +// regmap_register_patch(tas5805m->regmap, tas5805m_init_sequence, +// ARRAY_SIZE(tas5805m_init_sequence)); + mdelay(20); + ret = tas5805m_reg_init(codec); + if (ret != 0) + goto err; + + if (tas5805m) + tas5805m_set_volume(codec, tas5805m->vol); + + snd_soc_add_codec_controls(codec, tas5805m_vol_control, + ARRAY_SIZE(tas5805m_vol_control)); + tas5805m->codec = codec; + return 0; + +err: + return ret; + +} + +static int tas5805m_remove(struct snd_soc_codec *codec) +{ + struct tas5805m_priv *tas5805m = snd_soc_codec_get_drvdata(codec); + struct tas5805m_platform_data *pdata = tas5805m->pdata; + + if (pdata->reset_pin) + gpio_direction_output(pdata->reset_pin, GPIOF_OUT_INIT_LOW); + + udelay(10); + + return 0; +} + static struct snd_soc_codec_driver soc_codec_tas5805m = { - .probe = tas5805m_snd_probe, + .probe = tas5805m_probe, + .remove = tas5805m_remove, + .suspend = tas5805m_snd_suspend, + .resume = tas5805m_snd_resume, + .set_bias_level = tas5805m_set_bias_level, }; static const struct snd_soc_dai_ops tas5805m_dai_ops = { //.digital_mute = tas5805m_mute, + .trigger = tas5805m_trigger, }; static struct snd_soc_dai_driver tas5805m_dai = { @@ -449,42 +1146,24 @@ static struct snd_soc_dai_driver tas5805m_dai = { .ops = &tas5805m_dai_ops, }; -static int tas5805m_probe(struct device *dev, struct regmap *regmap) +static int tas5805m_parse_dt( + struct tas5805m_priv *tas5805m, + struct device_node *np) { - struct tas5805m_priv *tas5805m; - int ret; - - tas5805m = devm_kzalloc(dev, sizeof(struct tas5805m_priv), GFP_KERNEL); - if (!tas5805m) - return -ENOMEM; - - dev_set_drvdata(dev, tas5805m); - tas5805m->regmap = regmap; - tas5805m->vol = 100; //100, -10dB - - mutex_init(&tas5805m->lock); - - ret = - regmap_register_patch(regmap, tas5805m_init_sequence, - ARRAY_SIZE(tas5805m_init_sequence)); - if (ret != 0) { - dev_err(dev, "Failed to initialize TAS5805M: %d\n", ret); - goto err; + int ret = 0; + int reset_pin = -1; + reset_pin = of_get_named_gpio(np, "reset_pin", 0); + if (reset_pin < 0) { + pr_err("%s fail to get reset pin from dts!\n", __func__); + ret = -1; + } else { + pr_info("%s pdata->reset_pin = %d!\n", __func__, + tas5805m->pdata->reset_pin); } + tas5805m->pdata->reset_pin = reset_pin; - ret = - snd_soc_register_codec(dev, &soc_codec_tas5805m, &tas5805m_dai, 1); - if (ret != 0) { - dev_err(dev, "Failed to register CODEC: %d\n", ret); - goto err; - } - - return 0; - -err: return ret; - } static int tas5805m_i2c_probe(struct i2c_client *i2c, @@ -492,24 +1171,48 @@ static int tas5805m_i2c_probe(struct i2c_client *i2c, { struct regmap *regmap; struct regmap_config config = tas5805m_regmap; + struct tas5805m_priv *tas5805m; + struct tas5805m_platform_data *pdata; + int ret = 0; + + tas5805m = devm_kzalloc(&i2c->dev, + sizeof(struct tas5805m_priv), GFP_KERNEL); + if (!tas5805m) + return -ENOMEM; regmap = devm_regmap_init_i2c(i2c, &config); if (IS_ERR(regmap)) return PTR_ERR(regmap); - return tas5805m_probe(&i2c->dev, regmap); -} + pdata = devm_kzalloc(&i2c->dev, + sizeof(struct tas5805m_platform_data), + GFP_KERNEL); + if (!pdata) { + pr_err("%s failed to kzalloc for tas5805 pdata\n", __func__); + return -ENOMEM; + } + tas5805m->pdata = pdata; -static int tas5805m_remove(struct device *dev) -{ - snd_soc_unregister_codec(dev); + tas5805m_parse_dt(tas5805m, i2c->dev.of_node); + tas5805m->regmap = regmap; + tas5805m->vol = 100; //100, -10dB - return 0; + dev_set_drvdata(&i2c->dev, tas5805m); + + ret = + snd_soc_register_codec(&i2c->dev, &soc_codec_tas5805m, + &tas5805m_dai, 1); + if (ret != 0) + return -ENOMEM; + + reset_tas5805m_GPIO(&i2c->dev); + + return ret; } static int tas5805m_i2c_remove(struct i2c_client *i2c) { - tas5805m_remove(&i2c->dev); + devm_kfree(&i2c->dev, i2c_get_clientdata(i2c)); return 0; } diff --git a/sound/soc/codecs/amlogic/tas5805.h b/sound/soc/codecs/amlogic/tas5805.h index ba6066204b12..46a211548eb3 100644 --- a/sound/soc/codecs/amlogic/tas5805.h +++ b/sound/soc/codecs/amlogic/tas5805.h @@ -1,1880 +1,1172 @@ #include -static const struct reg_sequence tas5805m_init_sequence[] = { - {0x00, 0x00}, - {0x7f, 0x00}, - {0x03, 0x02}, - {0x01, 0x11}, - {0x00, 0x00}, - {0x00, 0x00}, - {0x00, 0x00}, - {0x00, 0x00}, - {0x29, 0x7c}, - {0x03, 0x02}, - {0x00, 0x00}, - {0x00, 0x00}, - {0x00, 0x00}, - {0x00, 0x00}, - {0x00, 0x00}, - {0x29, 0x00}, - {0x00, 0x00}, - {0x7f, 0x00}, - {0x46, 0x11}, - {0x03, 0x0f}, - {0x00, 0x00}, - {0x00, 0x00}, - {0x00, 0x00}, - {0x00, 0x00}, - {0x00, 0x00}, - {0x7f, 0x00}, - {0x00, 0x00}, - {0x66, 0x85}, - {0x00, 0x00}, - {0x7f, 0x8c}, - {0x00, 0x2a}, - {0x24, 0x00}, - {0x25, 0x28}, - {0x26, 0x7a}, - {0x27, 0x27}, - {0x00, 0x00}, - {0x7f, 0x8c}, - {0x00, 0x2a}, - {0x28, 0x00}, - {0x29, 0x28}, - {0x2a, 0x7a}, - {0x2b, 0x27}, - {0x00, 0x00}, - {0x7f, 0x8c}, - {0x00, 0x0b}, - {0x28, 0x00}, - {0x29, 0x80}, - {0x2a, 0x00}, - {0x2b, 0x00}, - {0x00, 0x00}, - {0x7f, 0x8c}, - {0x00, 0x0b}, - {0x2c, 0x00}, - {0x2d, 0x00}, - {0x2e, 0x00}, - {0x2f, 0x00}, - {0x00, 0x00}, - {0x7f, 0x8c}, - {0x00, 0x29}, - {0x18, 0x00}, - {0x19, 0x80}, - {0x1a, 0x00}, - {0x1b, 0x00}, - {0x00, 0x00}, - {0x7f, 0x8c}, - {0x00, 0x29}, - {0x1c, 0x00}, - {0x1d, 0x00}, - {0x1e, 0x00}, - {0x1f, 0x00}, - {0x00, 0x00}, - {0x7f, 0x8c}, - {0x00, 0x29}, - {0x20, 0x00}, - {0x21, 0x00}, - {0x22, 0x00}, - {0x23, 0x00}, - {0x00, 0x00}, - {0x7f, 0x8c}, - {0x00, 0x29}, - {0x24, 0x00}, - {0x25, 0x80}, - {0x26, 0x00}, - {0x27, 0x00}, - {0x00, 0x00}, - {0x7f, 0x8c}, - {0x00, 0x2a}, - {0x24, 0x00}, - {0x25, 0x28}, - {0x26, 0x7a}, - {0x27, 0x27}, - {0x00, 0x00}, - {0x7f, 0x8c}, - {0x00, 0x2a}, - {0x28, 0x00}, - {0x29, 0x28}, - {0x2a, 0x7a}, - {0x2b, 0x27}, - {0x00, 0x00}, - {0x7f, 0x8c}, - {0x00, 0x2a}, - {0x30, 0x00}, - {0x31, 0xe2}, - {0x32, 0xc4}, - {0x33, 0x6b}, - {0x00, 0x00}, - {0x7f, 0x8c}, - {0x00, 0x2c}, - {0x0c, 0x00}, - {0x0d, 0x00}, - {0x0e, 0x00}, - {0x0f, 0x00}, - {0x00, 0x00}, - {0x7f, 0x8c}, - {0x00, 0x2c}, - {0x10, 0x00}, - {0x11, 0x00}, - {0x12, 0x00}, - {0x13, 0x00}, - {0x00, 0x00}, - {0x7f, 0x8c}, - {0x00, 0x2c}, - {0x14, 0x00}, - {0x15, 0x80}, - {0x16, 0x00}, - {0x17, 0x00}, - {0x00, 0x00}, - {0x7f, 0x8c}, - {0x00, 0x2c}, - {0x18, 0x00}, - {0x19, 0x00}, - {0x1a, 0x00}, - {0x1b, 0x00}, - {0x00, 0x00}, - {0x7f, 0x8c}, - {0x00, 0x2c}, - {0x1c, 0x00}, - {0x1d, 0x80}, - {0x1e, 0x00}, - {0x1f, 0x00}, - {0x00, 0x00}, - {0x7f, 0x8c}, - {0x00, 0x2c}, - {0x20, 0x00}, - {0x21, 0x00}, - {0x22, 0x00}, - {0x23, 0x00}, - {0x00, 0x00}, - {0x7f, 0x8c}, - {0x00, 0x2c}, - {0x28, 0x00}, - {0x29, 0x00}, - {0x2a, 0x00}, - {0x2b, 0x00}, - {0x00, 0x00}, - {0x7f, 0x8c}, - {0x00, 0x2c}, - {0x2c, 0x00}, - {0x2d, 0x80}, - {0x2e, 0x00}, - {0x2f, 0x00}, - {0x00, 0x00}, - {0x7f, 0x8c}, - {0x00, 0x2c}, - {0x34, 0x00}, - {0x35, 0x80}, - {0x36, 0x00}, - {0x37, 0x00}, - {0x00, 0x00}, - {0x7f, 0x8c}, - {0x00, 0x2c}, - {0x38, 0x00}, - {0x39, 0x00}, - {0x3a, 0x00}, - {0x3b, 0x00}, - {0x00, 0x00}, - {0x7f, 0x8c}, - {0x00, 0x2c}, - {0x48, 0x00}, - {0x49, 0x00}, - {0x4a, 0x00}, - {0x4b, 0x00}, - {0x00, 0x00}, - {0x7f, 0x8c}, - {0x00, 0x2c}, - {0x4c, 0x00}, - {0x4d, 0x80}, - {0x4e, 0x00}, - {0x4f, 0x00}, - {0x00, 0x00}, - {0x7f, 0x8c}, - {0x00, 0x2c}, - {0x5c, 0x00}, - {0x5d, 0x00}, - {0x5e, 0x57}, - {0x5f, 0x62}, - {0x00, 0x00}, - {0x7f, 0x8c}, - {0x00, 0x2c}, - {0x60, 0x00}, - {0x61, 0x03}, - {0x62, 0x69}, - {0x63, 0xd0}, - {0x00, 0x00}, - {0x7f, 0x8c}, - {0x00, 0x2c}, - {0x64, 0x00}, - {0x65, 0xce}, - {0x66, 0xc0}, - {0x67, 0x8a}, - {0x00, 0x00}, - {0x7f, 0x8c}, - {0x00, 0x2c}, - {0x68, 0x40}, - {0x69, 0x00}, - {0x6a, 0x00}, - {0x6b, 0x00}, - {0x00, 0x00}, - {0x7f, 0x8c}, - {0x00, 0x2c}, - {0x6c, 0x05}, - {0x6d, 0x1f}, - {0x6e, 0x97}, - {0x6f, 0x37}, - {0x00, 0x00}, - {0x7f, 0x8c}, - {0x00, 0x2d}, - {0x18, 0x7a}, - {0x19, 0xe0}, - {0x1a, 0x68}, - {0x1b, 0xc9}, - {0x00, 0x00}, - {0x7f, 0x8c}, - {0x00, 0x2d}, - {0x1c, 0x00}, - {0x1d, 0x00}, - {0x1e, 0xae}, - {0x1f, 0xc3}, - {0x00, 0x00}, - {0x7f, 0x8c}, - {0x00, 0x2d}, - {0x20, 0x00}, - {0x21, 0x00}, - {0x22, 0x00}, - {0x23, 0x00}, - {0x00, 0x00}, - {0x7f, 0x8c}, - {0x00, 0x2d}, - {0x24, 0x00}, - {0x25, 0x00}, - {0x26, 0x00}, - {0x27, 0x00}, - {0x00, 0x00}, - {0x7f, 0x8c}, - {0x00, 0x2d}, - {0x28, 0x00}, - {0x29, 0x00}, - {0x2a, 0x00}, - {0x2b, 0x00}, - {0x00, 0x00}, - {0x7f, 0x8c}, - {0x00, 0x2d}, - {0x2c, 0x00}, - {0x2d, 0x80}, - {0x2e, 0x00}, - {0x2f, 0x00}, - {0x00, 0x00}, - {0x7f, 0x8c}, - {0x00, 0x31}, - {0x48, 0x40}, - {0x49, 0x00}, - {0x4a, 0x00}, - {0x4b, 0x00}, - {0x4c, 0x00}, - {0x4d, 0x00}, - {0x4e, 0x00}, - {0x4f, 0x00}, - {0x50, 0x00}, - {0x51, 0x00}, - {0x52, 0x00}, - {0x53, 0x00}, - {0x54, 0x00}, - {0x55, 0x00}, - {0x56, 0x00}, - {0x57, 0x00}, - {0x58, 0x00}, - {0x59, 0x00}, - {0x5a, 0x00}, - {0x5b, 0x00}, - {0x5c, 0x00}, - {0x5d, 0x00}, - {0x5e, 0x00}, - {0x5f, 0x00}, - {0x60, 0x00}, - {0x61, 0x00}, - {0x62, 0x00}, - {0x63, 0x00}, - {0x64, 0x00}, - {0x65, 0x00}, - {0x66, 0x00}, - {0x67, 0x00}, - {0x68, 0x00}, - {0x69, 0x00}, - {0x6a, 0x00}, - {0x6b, 0x00}, - {0x6c, 0x00}, - {0x6d, 0x00}, - {0x6e, 0x00}, - {0x6f, 0x00}, - {0x70, 0x00}, - {0x71, 0x00}, - {0x72, 0x00}, - {0x73, 0x00}, - {0x74, 0x00}, - {0x75, 0x00}, - {0x76, 0x00}, - {0x77, 0x00}, - {0x78, 0x00}, - {0x79, 0x00}, - {0x7a, 0x00}, - {0x7b, 0x00}, - {0x7c, 0x00}, - {0x7d, 0x00}, - {0x7e, 0x00}, - {0x7f, 0x00}, - {0x00, 0x00}, - {0x7f, 0x8c}, - {0x00, 0x32}, - {0x08, 0x00}, - {0x09, 0x00}, - {0x0a, 0x00}, - {0x0b, 0x00}, - {0x0c, 0x00}, - {0x0d, 0x00}, - {0x0e, 0x00}, - {0x0f, 0x00}, - {0x10, 0x00}, - {0x11, 0x00}, - {0x12, 0x00}, - {0x13, 0x00}, - {0x14, 0x00}, - {0x15, 0x00}, - {0x16, 0x00}, - {0x17, 0x00}, - {0x18, 0x00}, - {0x19, 0x00}, - {0x1a, 0x00}, - {0x1b, 0x00}, - {0x1c, 0x00}, - {0x1d, 0x00}, - {0x1e, 0x00}, - {0x1f, 0x00}, - {0x20, 0x00}, - {0x21, 0x00}, - {0x22, 0x00}, - {0x23, 0x00}, - {0x24, 0x00}, - {0x25, 0x00}, - {0x26, 0x00}, - {0x27, 0x00}, - {0x28, 0x00}, - {0x29, 0x00}, - {0x2a, 0x00}, - {0x2b, 0x00}, - {0x2c, 0x00}, - {0x2d, 0x00}, - {0x2e, 0x00}, - {0x2f, 0x00}, - {0x30, 0x00}, - {0x31, 0x00}, - {0x32, 0x00}, - {0x33, 0x00}, - {0x34, 0x00}, - {0x35, 0x00}, - {0x36, 0x00}, - {0x37, 0x00}, - {0x38, 0x00}, - {0x39, 0x00}, - {0x3a, 0x00}, - {0x3b, 0x00}, - {0x3c, 0x00}, - {0x3d, 0x00}, - {0x3e, 0x00}, - {0x3f, 0x00}, - {0x40, 0x00}, - {0x41, 0x00}, - {0x42, 0x00}, - {0x43, 0x00}, - {0x44, 0x00}, - {0x45, 0x00}, - {0x46, 0x00}, - {0x47, 0x00}, - {0x48, 0x00}, - {0x49, 0x00}, - {0x4a, 0x00}, - {0x4b, 0x00}, - {0x4c, 0x00}, - {0x4d, 0x00}, - {0x4e, 0x00}, - {0x4f, 0x00}, - {0x50, 0x00}, - {0x51, 0x00}, - {0x52, 0x00}, - {0x53, 0x00}, - {0x54, 0x00}, - {0x55, 0x00}, - {0x56, 0x00}, - {0x57, 0x00}, - {0x58, 0x00}, - {0x59, 0x00}, - {0x5a, 0x00}, - {0x5b, 0x00}, - {0x5c, 0x00}, - {0x5d, 0x00}, - {0x5e, 0x00}, - {0x5f, 0x00}, - {0x60, 0x00}, - {0x61, 0x00}, - {0x62, 0x00}, - {0x63, 0x00}, - {0x64, 0x00}, - {0x65, 0x00}, - {0x66, 0x00}, - {0x67, 0x00}, - {0x68, 0x00}, - {0x69, 0x00}, - {0x6a, 0x00}, - {0x6b, 0x00}, - {0x6c, 0x00}, - {0x6d, 0x00}, - {0x6e, 0x00}, - {0x6f, 0x00}, - {0x70, 0x00}, - {0x71, 0x00}, - {0x72, 0x00}, - {0x73, 0x00}, - {0x74, 0x00}, - {0x75, 0x00}, - {0x76, 0x00}, - {0x77, 0x00}, - {0x78, 0x00}, - {0x79, 0x00}, - {0x7a, 0x00}, - {0x7b, 0x00}, - {0x7c, 0x00}, - {0x7d, 0x00}, - {0x7e, 0x00}, - {0x7f, 0x00}, - {0x00, 0x00}, - {0x7f, 0x8c}, - {0x00, 0x33}, - {0x08, 0x00}, - {0x09, 0x00}, - {0x0a, 0x00}, - {0x0b, 0x00}, - {0x0c, 0x00}, - {0x0d, 0x00}, - {0x0e, 0x00}, - {0x0f, 0x00}, - {0x10, 0x00}, - {0x11, 0x00}, - {0x12, 0x00}, - {0x13, 0x00}, - {0x14, 0x00}, - {0x15, 0x00}, - {0x16, 0x00}, - {0x17, 0x00}, - {0x18, 0x00}, - {0x19, 0x00}, - {0x1a, 0x00}, - {0x1b, 0x00}, - {0x1c, 0x00}, - {0x1d, 0x00}, - {0x1e, 0x00}, - {0x1f, 0x00}, - {0x20, 0x00}, - {0x21, 0x00}, - {0x22, 0x00}, - {0x23, 0x00}, - {0x24, 0x00}, - {0x25, 0x00}, - {0x26, 0x00}, - {0x27, 0x00}, - {0x28, 0x00}, - {0x29, 0x00}, - {0x2a, 0x00}, - {0x2b, 0x00}, - {0x2c, 0x00}, - {0x2d, 0x00}, - {0x2e, 0x00}, - {0x2f, 0x00}, - {0x30, 0x00}, - {0x31, 0x00}, - {0x32, 0x00}, - {0x33, 0x00}, - {0x34, 0x00}, - {0x35, 0x00}, - {0x36, 0x00}, - {0x37, 0x00}, - {0x38, 0x00}, - {0x39, 0x00}, - {0x3a, 0x00}, - {0x3b, 0x00}, - {0x3c, 0x00}, - {0x3d, 0x00}, - {0x3e, 0x00}, - {0x3f, 0x00}, - {0x40, 0x00}, - {0x41, 0x00}, - {0x42, 0x00}, - {0x43, 0x00}, - {0x44, 0x00}, - {0x45, 0x00}, - {0x46, 0x00}, - {0x47, 0x00}, - {0x48, 0x00}, - {0x49, 0x00}, - {0x4a, 0x00}, - {0x4b, 0x00}, - {0x4c, 0x00}, - {0x4d, 0x00}, - {0x4e, 0x00}, - {0x4f, 0x00}, - {0x50, 0x00}, - {0x51, 0x00}, - {0x52, 0x00}, - {0x53, 0x00}, - {0x54, 0x00}, - {0x55, 0x00}, - {0x56, 0x00}, - {0x57, 0x00}, - {0x58, 0x00}, - {0x59, 0x00}, - {0x5a, 0x00}, - {0x5b, 0x00}, - {0x5c, 0x00}, - {0x5d, 0x00}, - {0x5e, 0x00}, - {0x5f, 0x00}, - {0x60, 0x00}, - {0x61, 0x00}, - {0x62, 0x00}, - {0x63, 0x00}, - {0x64, 0x00}, - {0x65, 0x00}, - {0x66, 0x00}, - {0x67, 0x00}, - {0x68, 0x00}, - {0x69, 0x00}, - {0x6a, 0x00}, - {0x6b, 0x00}, - {0x6c, 0x00}, - {0x6d, 0x00}, - {0x6e, 0x00}, - {0x6f, 0x00}, - {0x70, 0x00}, - {0x71, 0x00}, - {0x72, 0x00}, - {0x73, 0x00}, - {0x74, 0x00}, - {0x75, 0x00}, - {0x76, 0x00}, - {0x77, 0x00}, - {0x78, 0x00}, - {0x79, 0x00}, - {0x7a, 0x00}, - {0x7b, 0x00}, - {0x7c, 0x00}, - {0x7d, 0x00}, - {0x7e, 0x00}, - {0x7f, 0x00}, - {0x00, 0x00}, - {0x7f, 0x8c}, - {0x00, 0x34}, - {0x08, 0x00}, - {0x09, 0x00}, - {0x0a, 0x00}, - {0x0b, 0x00}, - {0x0c, 0x00}, - {0x0d, 0x00}, - {0x0e, 0x00}, - {0x0f, 0x00}, - {0x10, 0x00}, - {0x11, 0x00}, - {0x12, 0x00}, - {0x13, 0x00}, - {0x14, 0x00}, - {0x15, 0x00}, - {0x16, 0x00}, - {0x17, 0x00}, - {0x18, 0x00}, - {0x19, 0x00}, - {0x1a, 0x00}, - {0x1b, 0x00}, - {0x1c, 0x00}, - {0x1d, 0x00}, - {0x1e, 0x00}, - {0x1f, 0x00}, - {0x20, 0x00}, - {0x21, 0x00}, - {0x22, 0x00}, - {0x23, 0x00}, - {0x24, 0x00}, - {0x25, 0x00}, - {0x26, 0x00}, - {0x27, 0x00}, - {0x28, 0x00}, - {0x29, 0x00}, - {0x2a, 0x00}, - {0x2b, 0x00}, - {0x2c, 0x00}, - {0x2d, 0x00}, - {0x2e, 0x00}, - {0x2f, 0x00}, - {0x30, 0x00}, - {0x31, 0x00}, - {0x32, 0x00}, - {0x33, 0x00}, - {0x34, 0x00}, - {0x35, 0x00}, - {0x36, 0x00}, - {0x37, 0x00}, - {0x38, 0x00}, - {0x39, 0x00}, - {0x3a, 0x00}, - {0x3b, 0x00}, - {0x3c, 0x00}, - {0x3d, 0x00}, - {0x3e, 0x00}, - {0x3f, 0x00}, - {0x40, 0x00}, - {0x41, 0x00}, - {0x42, 0x00}, - {0x43, 0x00}, - {0x44, 0x00}, - {0x45, 0x00}, - {0x46, 0x00}, - {0x47, 0x00}, - {0x48, 0x00}, - {0x49, 0x00}, - {0x4a, 0x00}, - {0x4b, 0x00}, - {0x4c, 0x00}, - {0x4d, 0x00}, - {0x4e, 0x00}, - {0x4f, 0x00}, - {0x50, 0x00}, - {0x51, 0x00}, - {0x52, 0x00}, - {0x53, 0x00}, - {0x54, 0x00}, - {0x55, 0x00}, - {0x56, 0x00}, - {0x57, 0x00}, - {0x58, 0x00}, - {0x59, 0x00}, - {0x5a, 0x00}, - {0x5b, 0x00}, - {0x5c, 0x00}, - {0x5d, 0x00}, - {0x5e, 0x00}, - {0x5f, 0x00}, - {0x60, 0x00}, - {0x61, 0x00}, - {0x62, 0x00}, - {0x63, 0x00}, - {0x64, 0x00}, - {0x65, 0x00}, - {0x66, 0x00}, - {0x67, 0x00}, - {0x68, 0x00}, - {0x69, 0x00}, - {0x6a, 0x00}, - {0x6b, 0x00}, - {0x6c, 0x00}, - {0x6d, 0x00}, - {0x6e, 0x00}, - {0x6f, 0x00}, - {0x70, 0x00}, - {0x71, 0x00}, - {0x72, 0x00}, - {0x73, 0x00}, - {0x74, 0x00}, - {0x75, 0x00}, - {0x76, 0x00}, - {0x77, 0x00}, - {0x78, 0x00}, - {0x79, 0x00}, - {0x7a, 0x00}, - {0x7b, 0x00}, - {0x7c, 0x00}, - {0x7d, 0x00}, - {0x7e, 0x00}, - {0x7f, 0x00}, - {0x00, 0x00}, - {0x7f, 0x8c}, - {0x00, 0x35}, - {0x08, 0x00}, - {0x09, 0x00}, - {0x0a, 0x00}, - {0x0b, 0x00}, - {0x0c, 0x00}, - {0x0d, 0x00}, - {0x0e, 0x00}, - {0x0f, 0x00}, - {0x10, 0x00}, - {0x11, 0x00}, - {0x12, 0x00}, - {0x13, 0x00}, - {0x14, 0x00}, - {0x15, 0x00}, - {0x16, 0x00}, - {0x17, 0x00}, - {0x18, 0x00}, - {0x19, 0x00}, - {0x1a, 0x00}, - {0x1b, 0x00}, - {0x1c, 0x00}, - {0x1d, 0x00}, - {0x1e, 0x00}, - {0x1f, 0x00}, - {0x20, 0x00}, - {0x21, 0x00}, - {0x22, 0x00}, - {0x23, 0x00}, - {0x24, 0x00}, - {0x25, 0x00}, - {0x26, 0x00}, - {0x27, 0x00}, - {0x28, 0x00}, - {0x29, 0x00}, - {0x2a, 0x00}, - {0x2b, 0x00}, - {0x2c, 0x00}, - {0x2d, 0x00}, - {0x2e, 0x00}, - {0x2f, 0x00}, - {0x30, 0x00}, - {0x31, 0x00}, - {0x32, 0x00}, - {0x33, 0x00}, - {0x34, 0x00}, - {0x35, 0x00}, - {0x36, 0x00}, - {0x37, 0x00}, - {0x38, 0x00}, - {0x39, 0x00}, - {0x3a, 0x00}, - {0x3b, 0x00}, - {0x3c, 0x00}, - {0x3d, 0x00}, - {0x3e, 0x00}, - {0x3f, 0x00}, - {0x40, 0x00}, - {0x41, 0x00}, - {0x42, 0x00}, - {0x43, 0x00}, - {0x44, 0x00}, - {0x45, 0x00}, - {0x46, 0x00}, - {0x47, 0x00}, - {0x48, 0x00}, - {0x49, 0x00}, - {0x4a, 0x00}, - {0x4b, 0x00}, - {0x4c, 0x00}, - {0x4d, 0x00}, - {0x4e, 0x00}, - {0x4f, 0x00}, - {0x50, 0x00}, - {0x51, 0x00}, - {0x52, 0x00}, - {0x53, 0x00}, - {0x54, 0x00}, - {0x55, 0x00}, - {0x56, 0x00}, - {0x57, 0x00}, - {0x58, 0x00}, - {0x59, 0x00}, - {0x5a, 0x00}, - {0x5b, 0x00}, - {0x5c, 0x00}, - {0x5d, 0x00}, - {0x5e, 0x00}, - {0x5f, 0x00}, - {0x60, 0x00}, - {0x61, 0x00}, - {0x62, 0x00}, - {0x63, 0x00}, - {0x64, 0x00}, - {0x65, 0x00}, - {0x66, 0x00}, - {0x67, 0x00}, - {0x00, 0x00}, - {0x7f, 0xaa}, - {0x00, 0x24}, - {0x18, 0x08}, - {0x19, 0x00}, - {0x1a, 0x00}, - {0x1b, 0x00}, - {0x1c, 0x00}, - {0x1d, 0x00}, - {0x1e, 0x00}, - {0x1f, 0x00}, - {0x20, 0x00}, - {0x21, 0x00}, - {0x22, 0x00}, - {0x23, 0x00}, - {0x24, 0x00}, - {0x25, 0x00}, - {0x26, 0x00}, - {0x27, 0x00}, - {0x28, 0x00}, - {0x29, 0x00}, - {0x2a, 0x00}, - {0x2b, 0x00}, - {0x00, 0x00}, - {0x7f, 0xaa}, - {0x00, 0x24}, - {0x2c, 0x08}, - {0x2d, 0x00}, - {0x2e, 0x00}, - {0x2f, 0x00}, - {0x30, 0x00}, - {0x31, 0x00}, - {0x32, 0x00}, - {0x33, 0x00}, - {0x34, 0x00}, - {0x35, 0x00}, - {0x36, 0x00}, - {0x37, 0x00}, - {0x38, 0x00}, - {0x39, 0x00}, - {0x3a, 0x00}, - {0x3b, 0x00}, - {0x3c, 0x00}, - {0x3d, 0x00}, - {0x3e, 0x00}, - {0x3f, 0x00}, - {0x00, 0x00}, - {0x7f, 0xaa}, - {0x00, 0x24}, - {0x40, 0x08}, - {0x41, 0x00}, - {0x42, 0x00}, - {0x43, 0x00}, - {0x44, 0x00}, - {0x45, 0x00}, - {0x46, 0x00}, - {0x47, 0x00}, - {0x48, 0x00}, - {0x49, 0x00}, - {0x4a, 0x00}, - {0x4b, 0x00}, - {0x4c, 0x00}, - {0x4d, 0x00}, - {0x4e, 0x00}, - {0x4f, 0x00}, - {0x50, 0x00}, - {0x51, 0x00}, - {0x52, 0x00}, - {0x53, 0x00}, - {0x00, 0x00}, - {0x7f, 0xaa}, - {0x00, 0x24}, - {0x54, 0x08}, - {0x55, 0x00}, - {0x56, 0x00}, - {0x57, 0x00}, - {0x58, 0x00}, - {0x59, 0x00}, - {0x5a, 0x00}, - {0x5b, 0x00}, - {0x5c, 0x00}, - {0x5d, 0x00}, - {0x5e, 0x00}, - {0x5f, 0x00}, - {0x60, 0x00}, - {0x61, 0x00}, - {0x62, 0x00}, - {0x63, 0x00}, - {0x64, 0x00}, - {0x65, 0x00}, - {0x66, 0x00}, - {0x67, 0x00}, - {0x00, 0x00}, - {0x7f, 0xaa}, - {0x00, 0x24}, - {0x68, 0x08}, - {0x69, 0x00}, - {0x6a, 0x00}, - {0x6b, 0x00}, - {0x6c, 0x00}, - {0x6d, 0x00}, - {0x6e, 0x00}, - {0x6f, 0x00}, - {0x70, 0x00}, - {0x71, 0x00}, - {0x72, 0x00}, - {0x73, 0x00}, - {0x74, 0x00}, - {0x75, 0x00}, - {0x76, 0x00}, - {0x77, 0x00}, - {0x78, 0x00}, - {0x79, 0x00}, - {0x7a, 0x00}, - {0x7b, 0x00}, - {0x00, 0x00}, - {0x7f, 0xaa}, - {0x00, 0x24}, - {0x7c, 0x08}, - {0x7d, 0x00}, - {0x7e, 0x00}, - {0x7f, 0x00}, - {0x00, 0x00}, - {0x7f, 0xaa}, - {0x00, 0x25}, - {0x08, 0x00}, - {0x09, 0x00}, - {0x0a, 0x00}, - {0x0b, 0x00}, - {0x0c, 0x00}, - {0x0d, 0x00}, - {0x0e, 0x00}, - {0x0f, 0x00}, - {0x10, 0x00}, - {0x11, 0x00}, - {0x12, 0x00}, - {0x13, 0x00}, - {0x14, 0x00}, - {0x15, 0x00}, - {0x16, 0x00}, - {0x17, 0x00}, - {0x00, 0x00}, - {0x7f, 0xaa}, - {0x00, 0x25}, - {0x18, 0x08}, - {0x19, 0x00}, - {0x1a, 0x00}, - {0x1b, 0x00}, - {0x1c, 0x00}, - {0x1d, 0x00}, - {0x1e, 0x00}, - {0x1f, 0x00}, - {0x20, 0x00}, - {0x21, 0x00}, - {0x22, 0x00}, - {0x23, 0x00}, - {0x24, 0x00}, - {0x25, 0x00}, - {0x26, 0x00}, - {0x27, 0x00}, - {0x28, 0x00}, - {0x29, 0x00}, - {0x2a, 0x00}, - {0x2b, 0x00}, - {0x00, 0x00}, - {0x7f, 0xaa}, - {0x00, 0x25}, - {0x2c, 0x08}, - {0x2d, 0x00}, - {0x2e, 0x00}, - {0x2f, 0x00}, - {0x30, 0x00}, - {0x31, 0x00}, - {0x32, 0x00}, - {0x33, 0x00}, - {0x34, 0x00}, - {0x35, 0x00}, - {0x36, 0x00}, - {0x37, 0x00}, - {0x38, 0x00}, - {0x39, 0x00}, - {0x3a, 0x00}, - {0x3b, 0x00}, - {0x3c, 0x00}, - {0x3d, 0x00}, - {0x3e, 0x00}, - {0x3f, 0x00}, - {0x00, 0x00}, - {0x7f, 0xaa}, - {0x00, 0x25}, - {0x40, 0x08}, - {0x41, 0x00}, - {0x42, 0x00}, - {0x43, 0x00}, - {0x44, 0x00}, - {0x45, 0x00}, - {0x46, 0x00}, - {0x47, 0x00}, - {0x48, 0x00}, - {0x49, 0x00}, - {0x4a, 0x00}, - {0x4b, 0x00}, - {0x4c, 0x00}, - {0x4d, 0x00}, - {0x4e, 0x00}, - {0x4f, 0x00}, - {0x50, 0x00}, - {0x51, 0x00}, - {0x52, 0x00}, - {0x53, 0x00}, - {0x00, 0x00}, - {0x7f, 0xaa}, - {0x00, 0x25}, - {0x54, 0x08}, - {0x55, 0x00}, - {0x56, 0x00}, - {0x57, 0x00}, - {0x58, 0x00}, - {0x59, 0x00}, - {0x5a, 0x00}, - {0x5b, 0x00}, - {0x5c, 0x00}, - {0x5d, 0x00}, - {0x5e, 0x00}, - {0x5f, 0x00}, - {0x60, 0x00}, - {0x61, 0x00}, - {0x62, 0x00}, - {0x63, 0x00}, - {0x64, 0x00}, - {0x65, 0x00}, - {0x66, 0x00}, - {0x67, 0x00}, - {0x00, 0x00}, - {0x7f, 0xaa}, - {0x00, 0x25}, - {0x68, 0x08}, - {0x69, 0x00}, - {0x6a, 0x00}, - {0x6b, 0x00}, - {0x6c, 0x00}, - {0x6d, 0x00}, - {0x6e, 0x00}, - {0x6f, 0x00}, - {0x70, 0x00}, - {0x71, 0x00}, - {0x72, 0x00}, - {0x73, 0x00}, - {0x74, 0x00}, - {0x75, 0x00}, - {0x76, 0x00}, - {0x77, 0x00}, - {0x78, 0x00}, - {0x79, 0x00}, - {0x7a, 0x00}, - {0x7b, 0x00}, - {0x00, 0x00}, - {0x7f, 0xaa}, - {0x00, 0x25}, - {0x7c, 0x08}, - {0x7d, 0x00}, - {0x7e, 0x00}, - {0x7f, 0x00}, - {0x00, 0x00}, - {0x7f, 0xaa}, - {0x00, 0x26}, - {0x08, 0x00}, - {0x09, 0x00}, - {0x0a, 0x00}, - {0x0b, 0x00}, - {0x0c, 0x00}, - {0x0d, 0x00}, - {0x0e, 0x00}, - {0x0f, 0x00}, - {0x10, 0x00}, - {0x11, 0x00}, - {0x12, 0x00}, - {0x13, 0x00}, - {0x14, 0x00}, - {0x15, 0x00}, - {0x16, 0x00}, - {0x17, 0x00}, - {0x00, 0x00}, - {0x7f, 0xaa}, - {0x00, 0x26}, - {0x18, 0x08}, - {0x19, 0x00}, - {0x1a, 0x00}, - {0x1b, 0x00}, - {0x1c, 0x00}, - {0x1d, 0x00}, - {0x1e, 0x00}, - {0x1f, 0x00}, - {0x20, 0x00}, - {0x21, 0x00}, - {0x22, 0x00}, - {0x23, 0x00}, - {0x24, 0x00}, - {0x25, 0x00}, - {0x26, 0x00}, - {0x27, 0x00}, - {0x28, 0x00}, - {0x29, 0x00}, - {0x2a, 0x00}, - {0x2b, 0x00}, - {0x00, 0x00}, - {0x7f, 0xaa}, - {0x00, 0x26}, - {0x2c, 0x08}, - {0x2d, 0x00}, - {0x2e, 0x00}, - {0x2f, 0x00}, - {0x30, 0x00}, - {0x31, 0x00}, - {0x32, 0x00}, - {0x33, 0x00}, - {0x34, 0x00}, - {0x35, 0x00}, - {0x36, 0x00}, - {0x37, 0x00}, - {0x38, 0x00}, - {0x39, 0x00}, - {0x3a, 0x00}, - {0x3b, 0x00}, - {0x3c, 0x00}, - {0x3d, 0x00}, - {0x3e, 0x00}, - {0x3f, 0x00}, - {0x00, 0x00}, - {0x7f, 0xaa}, - {0x00, 0x26}, - {0x40, 0x08}, - {0x41, 0x00}, - {0x42, 0x00}, - {0x43, 0x00}, - {0x44, 0x00}, - {0x45, 0x00}, - {0x46, 0x00}, - {0x47, 0x00}, - {0x48, 0x00}, - {0x49, 0x00}, - {0x4a, 0x00}, - {0x4b, 0x00}, - {0x4c, 0x00}, - {0x4d, 0x00}, - {0x4e, 0x00}, - {0x4f, 0x00}, - {0x50, 0x00}, - {0x51, 0x00}, - {0x52, 0x00}, - {0x53, 0x00}, - {0x00, 0x00}, - {0x7f, 0xaa}, - {0x00, 0x26}, - {0x54, 0x08}, - {0x55, 0x00}, - {0x56, 0x00}, - {0x57, 0x00}, - {0x58, 0x00}, - {0x59, 0x00}, - {0x5a, 0x00}, - {0x5b, 0x00}, - {0x5c, 0x00}, - {0x5d, 0x00}, - {0x5e, 0x00}, - {0x5f, 0x00}, - {0x60, 0x00}, - {0x61, 0x00}, - {0x62, 0x00}, - {0x63, 0x00}, - {0x64, 0x00}, - {0x65, 0x00}, - {0x66, 0x00}, - {0x67, 0x00}, - {0x00, 0x00}, - {0x7f, 0xaa}, - {0x00, 0x26}, - {0x68, 0x08}, - {0x69, 0x00}, - {0x6a, 0x00}, - {0x6b, 0x00}, - {0x6c, 0x00}, - {0x6d, 0x00}, - {0x6e, 0x00}, - {0x6f, 0x00}, - {0x70, 0x00}, - {0x71, 0x00}, - {0x72, 0x00}, - {0x73, 0x00}, - {0x74, 0x00}, - {0x75, 0x00}, - {0x76, 0x00}, - {0x77, 0x00}, - {0x78, 0x00}, - {0x79, 0x00}, - {0x7a, 0x00}, - {0x7b, 0x00}, - {0x00, 0x00}, - {0x7f, 0xaa}, - {0x00, 0x26}, - {0x7c, 0x08}, - {0x7d, 0x00}, - {0x7e, 0x00}, - {0x7f, 0x00}, - {0x00, 0x00}, - {0x7f, 0xaa}, - {0x00, 0x27}, - {0x08, 0x00}, - {0x09, 0x00}, - {0x0a, 0x00}, - {0x0b, 0x00}, - {0x0c, 0x00}, - {0x0d, 0x00}, - {0x0e, 0x00}, - {0x0f, 0x00}, - {0x10, 0x00}, - {0x11, 0x00}, - {0x12, 0x00}, - {0x13, 0x00}, - {0x14, 0x00}, - {0x15, 0x00}, - {0x16, 0x00}, - {0x17, 0x00}, - {0x00, 0x00}, - {0x7f, 0xaa}, - {0x00, 0x27}, - {0x18, 0x08}, - {0x19, 0x00}, - {0x1a, 0x00}, - {0x1b, 0x00}, - {0x1c, 0x00}, - {0x1d, 0x00}, - {0x1e, 0x00}, - {0x1f, 0x00}, - {0x20, 0x00}, - {0x21, 0x00}, - {0x22, 0x00}, - {0x23, 0x00}, - {0x24, 0x00}, - {0x25, 0x00}, - {0x26, 0x00}, - {0x27, 0x00}, - {0x28, 0x00}, - {0x29, 0x00}, - {0x2a, 0x00}, - {0x2b, 0x00}, - {0x00, 0x00}, - {0x7f, 0xaa}, - {0x00, 0x27}, - {0x2c, 0x08}, - {0x2d, 0x00}, - {0x2e, 0x00}, - {0x2f, 0x00}, - {0x30, 0x00}, - {0x31, 0x00}, - {0x32, 0x00}, - {0x33, 0x00}, - {0x34, 0x00}, - {0x35, 0x00}, - {0x36, 0x00}, - {0x37, 0x00}, - {0x38, 0x00}, - {0x39, 0x00}, - {0x3a, 0x00}, - {0x3b, 0x00}, - {0x3c, 0x00}, - {0x3d, 0x00}, - {0x3e, 0x00}, - {0x3f, 0x00}, - {0x00, 0x00}, - {0x7f, 0xaa}, - {0x00, 0x27}, - {0x40, 0x08}, - {0x41, 0x00}, - {0x42, 0x00}, - {0x43, 0x00}, - {0x44, 0x00}, - {0x45, 0x00}, - {0x46, 0x00}, - {0x47, 0x00}, - {0x48, 0x00}, - {0x49, 0x00}, - {0x4a, 0x00}, - {0x4b, 0x00}, - {0x4c, 0x00}, - {0x4d, 0x00}, - {0x4e, 0x00}, - {0x4f, 0x00}, - {0x50, 0x00}, - {0x51, 0x00}, - {0x52, 0x00}, - {0x53, 0x00}, - {0x00, 0x00}, - {0x7f, 0xaa}, - {0x00, 0x27}, - {0x54, 0x08}, - {0x55, 0x00}, - {0x56, 0x00}, - {0x57, 0x00}, - {0x58, 0x00}, - {0x59, 0x00}, - {0x5a, 0x00}, - {0x5b, 0x00}, - {0x5c, 0x00}, - {0x5d, 0x00}, - {0x5e, 0x00}, - {0x5f, 0x00}, - {0x60, 0x00}, - {0x61, 0x00}, - {0x62, 0x00}, - {0x63, 0x00}, - {0x64, 0x00}, - {0x65, 0x00}, - {0x66, 0x00}, - {0x67, 0x00}, - {0x00, 0x00}, - {0x7f, 0xaa}, - {0x00, 0x27}, - {0x68, 0x08}, - {0x69, 0x00}, - {0x6a, 0x00}, - {0x6b, 0x00}, - {0x6c, 0x00}, - {0x6d, 0x00}, - {0x6e, 0x00}, - {0x6f, 0x00}, - {0x70, 0x00}, - {0x71, 0x00}, - {0x72, 0x00}, - {0x73, 0x00}, - {0x74, 0x00}, - {0x75, 0x00}, - {0x76, 0x00}, - {0x77, 0x00}, - {0x78, 0x00}, - {0x79, 0x00}, - {0x7a, 0x00}, - {0x7b, 0x00}, - {0x00, 0x00}, - {0x7f, 0xaa}, - {0x00, 0x27}, - {0x7c, 0x08}, - {0x7d, 0x00}, - {0x7e, 0x00}, - {0x7f, 0x00}, - {0x00, 0x00}, - {0x7f, 0xaa}, - {0x00, 0x28}, - {0x08, 0x00}, - {0x09, 0x00}, - {0x0a, 0x00}, - {0x0b, 0x00}, - {0x0c, 0x00}, - {0x0d, 0x00}, - {0x0e, 0x00}, - {0x0f, 0x00}, - {0x10, 0x00}, - {0x11, 0x00}, - {0x12, 0x00}, - {0x13, 0x00}, - {0x14, 0x00}, - {0x15, 0x00}, - {0x16, 0x00}, - {0x17, 0x00}, - {0x00, 0x00}, - {0x7f, 0xaa}, - {0x00, 0x28}, - {0x18, 0x08}, - {0x19, 0x00}, - {0x1a, 0x00}, - {0x1b, 0x00}, - {0x1c, 0x00}, - {0x1d, 0x00}, - {0x1e, 0x00}, - {0x1f, 0x00}, - {0x20, 0x00}, - {0x21, 0x00}, - {0x22, 0x00}, - {0x23, 0x00}, - {0x24, 0x00}, - {0x25, 0x00}, - {0x26, 0x00}, - {0x27, 0x00}, - {0x28, 0x00}, - {0x29, 0x00}, - {0x2a, 0x00}, - {0x2b, 0x00}, - {0x00, 0x00}, - {0x7f, 0xaa}, - {0x00, 0x28}, - {0x2c, 0x08}, - {0x2d, 0x00}, - {0x2e, 0x00}, - {0x2f, 0x00}, - {0x30, 0x00}, - {0x31, 0x00}, - {0x32, 0x00}, - {0x33, 0x00}, - {0x34, 0x00}, - {0x35, 0x00}, - {0x36, 0x00}, - {0x37, 0x00}, - {0x38, 0x00}, - {0x39, 0x00}, - {0x3a, 0x00}, - {0x3b, 0x00}, - {0x3c, 0x00}, - {0x3d, 0x00}, - {0x3e, 0x00}, - {0x3f, 0x00}, - {0x00, 0x00}, - {0x7f, 0xaa}, - {0x00, 0x28}, - {0x40, 0x08}, - {0x41, 0x00}, - {0x42, 0x00}, - {0x43, 0x00}, - {0x44, 0x00}, - {0x45, 0x00}, - {0x46, 0x00}, - {0x47, 0x00}, - {0x48, 0x00}, - {0x49, 0x00}, - {0x4a, 0x00}, - {0x4b, 0x00}, - {0x4c, 0x00}, - {0x4d, 0x00}, - {0x4e, 0x00}, - {0x4f, 0x00}, - {0x50, 0x00}, - {0x51, 0x00}, - {0x52, 0x00}, - {0x53, 0x00}, - {0x00, 0x00}, - {0x7f, 0xaa}, - {0x00, 0x28}, - {0x54, 0x08}, - {0x55, 0x00}, - {0x56, 0x00}, - {0x57, 0x00}, - {0x58, 0x00}, - {0x59, 0x00}, - {0x5a, 0x00}, - {0x5b, 0x00}, - {0x5c, 0x00}, - {0x5d, 0x00}, - {0x5e, 0x00}, - {0x5f, 0x00}, - {0x60, 0x00}, - {0x61, 0x00}, - {0x62, 0x00}, - {0x63, 0x00}, - {0x64, 0x00}, - {0x65, 0x00}, - {0x66, 0x00}, - {0x67, 0x00}, - {0x00, 0x00}, - {0x7f, 0xaa}, - {0x00, 0x28}, - {0x68, 0x08}, - {0x69, 0x00}, - {0x6a, 0x00}, - {0x6b, 0x00}, - {0x6c, 0x00}, - {0x6d, 0x00}, - {0x6e, 0x00}, - {0x6f, 0x00}, - {0x70, 0x00}, - {0x71, 0x00}, - {0x72, 0x00}, - {0x73, 0x00}, - {0x74, 0x00}, - {0x75, 0x00}, - {0x76, 0x00}, - {0x77, 0x00}, - {0x78, 0x00}, - {0x79, 0x00}, - {0x7a, 0x00}, - {0x7b, 0x00}, - {0x00, 0x00}, - {0x7f, 0xaa}, - {0x00, 0x28}, - {0x7c, 0x08}, - {0x7d, 0x00}, - {0x7e, 0x00}, - {0x7f, 0x00}, - {0x00, 0x00}, - {0x7f, 0xaa}, - {0x00, 0x29}, - {0x08, 0x00}, - {0x09, 0x00}, - {0x0a, 0x00}, - {0x0b, 0x00}, - {0x0c, 0x00}, - {0x0d, 0x00}, - {0x0e, 0x00}, - {0x0f, 0x00}, - {0x10, 0x00}, - {0x11, 0x00}, - {0x12, 0x00}, - {0x13, 0x00}, - {0x14, 0x00}, - {0x15, 0x00}, - {0x16, 0x00}, - {0x17, 0x00}, - {0x00, 0x00}, - {0x7f, 0x8c}, - {0x00, 0x2e}, - {0x08, 0x00}, - {0x09, 0x80}, - {0x0a, 0x00}, - {0x0b, 0x00}, - {0x00, 0x00}, - {0x7f, 0x8c}, - {0x00, 0x2e}, - {0x0c, 0x00}, - {0x0d, 0x00}, - {0x0e, 0x00}, - {0x0f, 0x00}, - {0x00, 0x00}, - {0x7f, 0x8c}, - {0x00, 0x2e}, - {0x10, 0x00}, - {0x11, 0x00}, - {0x12, 0x00}, - {0x13, 0x00}, - {0x00, 0x00}, - {0x7f, 0xaa}, - {0x00, 0x2a}, - {0x48, 0x7f}, - {0x49, 0xff}, - {0x4a, 0xff}, - {0x4b, 0xff}, - {0x4c, 0x00}, - {0x4d, 0x00}, - {0x4e, 0x00}, - {0x4f, 0x00}, - {0x50, 0x00}, - {0x51, 0x00}, - {0x52, 0x00}, - {0x53, 0x00}, - {0x54, 0x00}, - {0x55, 0x00}, - {0x56, 0x00}, - {0x57, 0x00}, - {0x58, 0x00}, - {0x59, 0x00}, - {0x5a, 0x00}, - {0x5b, 0x00}, - {0x00, 0x00}, - {0x7f, 0x8c}, - {0x00, 0x2d}, - {0x58, 0x00}, - {0x59, 0x06}, - {0x5a, 0xd3}, - {0x5b, 0x72}, - {0x5c, 0x00}, - {0x5d, 0x02}, - {0x5e, 0xbb}, - {0x5f, 0x06}, - {0x60, 0x00}, - {0x61, 0x03}, - {0x62, 0x69}, - {0x63, 0xc5}, - {0x64, 0x00}, - {0x65, 0x00}, - {0x66, 0x00}, - {0x67, 0x00}, - {0x68, 0x00}, - {0x69, 0x00}, - {0x6a, 0x00}, - {0x6b, 0x00}, - {0x6c, 0x00}, - {0x6d, 0x00}, - {0x6e, 0x00}, - {0x6f, 0x00}, - {0x70, 0xf9}, - {0x71, 0xda}, - {0x72, 0xbc}, - {0x73, 0x21}, - {0x74, 0xfc}, - {0x75, 0x58}, - {0x76, 0x8b}, - {0x77, 0x89}, - {0x78, 0x00}, - {0x79, 0x00}, - {0x7a, 0x00}, - {0x7b, 0x00}, - {0x7c, 0x00}, - {0x7d, 0x00}, - {0x7e, 0x00}, - {0x7f, 0x00}, - {0x00, 0x00}, - {0x7f, 0x8c}, - {0x00, 0x2b}, - {0x34, 0x00}, - {0x35, 0x06}, - {0x36, 0xd3}, - {0x37, 0x72}, - {0x38, 0x00}, - {0x39, 0x02}, - {0x3a, 0xbb}, - {0x3b, 0x06}, - {0x3c, 0x00}, - {0x3d, 0x03}, - {0x3e, 0x69}, - {0x3f, 0xc5}, - {0x40, 0x00}, - {0x41, 0x00}, - {0x42, 0x00}, - {0x43, 0x00}, - {0x44, 0x00}, - {0x45, 0x00}, - {0x46, 0x00}, - {0x47, 0x00}, - {0x48, 0x00}, - {0x49, 0x00}, - {0x4a, 0x00}, - {0x4b, 0x00}, - {0x4c, 0xf9}, - {0x4d, 0xda}, - {0x4e, 0xbc}, - {0x4f, 0x21}, - {0x50, 0xfc}, - {0x51, 0x58}, - {0x52, 0x8b}, - {0x53, 0x89}, - {0x54, 0x00}, - {0x55, 0x00}, - {0x56, 0x00}, - {0x57, 0x00}, - {0x58, 0x00}, - {0x59, 0x00}, - {0x5a, 0x00}, - {0x5b, 0x00}, - {0x00, 0x00}, - {0x7f, 0xaa}, - {0x00, 0x2a}, - {0x34, 0x7f}, - {0x35, 0xff}, - {0x36, 0xff}, - {0x37, 0xff}, - {0x38, 0x00}, - {0x39, 0x00}, - {0x3a, 0x00}, - {0x3b, 0x00}, - {0x3c, 0x00}, - {0x3d, 0x00}, - {0x3e, 0x00}, - {0x3f, 0x00}, - {0x40, 0x00}, - {0x41, 0x00}, - {0x42, 0x00}, - {0x43, 0x00}, - {0x44, 0x00}, - {0x45, 0x00}, - {0x46, 0x00}, - {0x47, 0x00}, - {0x00, 0x00}, - {0x7f, 0x8c}, - {0x00, 0x2d}, - {0x30, 0x00}, - {0x31, 0x06}, - {0x32, 0xd3}, - {0x33, 0x72}, - {0x34, 0x00}, - {0x35, 0x02}, - {0x36, 0xbb}, - {0x37, 0x06}, - {0x38, 0x00}, - {0x39, 0x03}, - {0x3a, 0x69}, - {0x3b, 0xc5}, - {0x3c, 0x00}, - {0x3d, 0x00}, - {0x3e, 0x00}, - {0x3f, 0x00}, - {0x40, 0x00}, - {0x41, 0x00}, - {0x42, 0x00}, - {0x43, 0x00}, - {0x44, 0x00}, - {0x45, 0x00}, - {0x46, 0x00}, - {0x47, 0x00}, - {0x48, 0xf9}, - {0x49, 0xda}, - {0x4a, 0xbc}, - {0x4b, 0x21}, - {0x4c, 0xfc}, - {0x4d, 0x58}, - {0x4e, 0x8b}, - {0x4f, 0x89}, - {0x50, 0x00}, - {0x51, 0x00}, - {0x52, 0x00}, - {0x53, 0x00}, - {0x54, 0x00}, - {0x55, 0x00}, - {0x56, 0x00}, - {0x57, 0x00}, - {0x00, 0x00}, - {0x7f, 0xaa}, - {0x00, 0x2a}, - {0x5c, 0x7f}, - {0x5d, 0xff}, - {0x5e, 0xff}, - {0x5f, 0xff}, - {0x60, 0x00}, - {0x61, 0x00}, - {0x62, 0x00}, - {0x63, 0x00}, - {0x64, 0x00}, - {0x65, 0x00}, - {0x66, 0x00}, - {0x67, 0x00}, - {0x68, 0x00}, - {0x69, 0x00}, - {0x6a, 0x00}, - {0x6b, 0x00}, - {0x6c, 0x00}, - {0x6d, 0x00}, - {0x6e, 0x00}, - {0x6f, 0x00}, - {0x00, 0x00}, - {0x7f, 0xaa}, - {0x00, 0x2a}, - {0x70, 0x7f}, - {0x71, 0xff}, - {0x72, 0xff}, - {0x73, 0xff}, - {0x74, 0x00}, - {0x75, 0x00}, - {0x76, 0x00}, - {0x77, 0x00}, - {0x78, 0x00}, - {0x79, 0x00}, - {0x7a, 0x00}, - {0x7b, 0x00}, - {0x7c, 0x00}, - {0x7d, 0x00}, - {0x7e, 0x00}, - {0x7f, 0x00}, - {0x00, 0x00}, - {0x7f, 0xaa}, - {0x00, 0x2b}, - {0x08, 0x00}, - {0x09, 0x00}, - {0x0a, 0x00}, - {0x0b, 0x00}, - {0x00, 0x00}, - {0x7f, 0xaa}, - {0x00, 0x2b}, - {0x0c, 0x7f}, - {0x0d, 0xff}, - {0x0e, 0xff}, - {0x0f, 0xff}, - {0x10, 0x00}, - {0x11, 0x00}, - {0x12, 0x00}, - {0x13, 0x00}, - {0x14, 0x00}, - {0x15, 0x00}, - {0x16, 0x00}, - {0x17, 0x00}, - {0x18, 0x00}, - {0x19, 0x00}, - {0x1a, 0x00}, - {0x1b, 0x00}, - {0x1c, 0x00}, - {0x1d, 0x00}, - {0x1e, 0x00}, - {0x1f, 0x00}, - {0x00, 0x00}, - {0x7f, 0xaa}, - {0x00, 0x2b}, - {0x20, 0x7f}, - {0x21, 0xff}, - {0x22, 0xff}, - {0x23, 0xff}, - {0x24, 0x00}, - {0x25, 0x00}, - {0x26, 0x00}, - {0x27, 0x00}, - {0x28, 0x00}, - {0x29, 0x00}, - {0x2a, 0x00}, - {0x2b, 0x00}, - {0x2c, 0x00}, - {0x2d, 0x00}, - {0x2e, 0x00}, - {0x2f, 0x00}, - {0x30, 0x00}, - {0x31, 0x00}, - {0x32, 0x00}, - {0x33, 0x00}, - {0x00, 0x00}, - {0x7f, 0xaa}, - {0x00, 0x2e}, - {0x40, 0x7f}, - {0x41, 0xff}, - {0x42, 0xff}, - {0x43, 0xff}, - {0x44, 0x00}, - {0x45, 0x00}, - {0x46, 0x00}, - {0x47, 0x00}, - {0x48, 0x00}, - {0x49, 0x00}, - {0x4a, 0x00}, - {0x4b, 0x00}, - {0x4c, 0x00}, - {0x4d, 0x00}, - {0x4e, 0x00}, - {0x4f, 0x00}, - {0x50, 0x00}, - {0x51, 0x00}, - {0x52, 0x00}, - {0x53, 0x00}, - {0x00, 0x00}, - {0x7f, 0xaa}, - {0x00, 0x2e}, - {0x54, 0x7f}, - {0x55, 0xff}, - {0x56, 0xff}, - {0x57, 0xff}, - {0x58, 0x00}, - {0x59, 0x00}, - {0x5a, 0x00}, - {0x5b, 0x00}, - {0x5c, 0x00}, - {0x5d, 0x00}, - {0x5e, 0x00}, - {0x5f, 0x00}, - {0x60, 0x00}, - {0x61, 0x00}, - {0x62, 0x00}, - {0x63, 0x00}, - {0x64, 0x00}, - {0x65, 0x00}, - {0x66, 0x00}, - {0x67, 0x00}, - {0x00, 0x00}, - {0x7f, 0x8c}, - {0x00, 0x2e}, - {0x18, 0x00}, - {0x19, 0x80}, - {0x1a, 0x00}, - {0x1b, 0x00}, - {0x00, 0x00}, - {0x7f, 0x8c}, - {0x00, 0x2e}, - {0x1c, 0x40}, - {0x1d, 0x00}, - {0x1e, 0x00}, - {0x1f, 0x00}, - {0x00, 0x00}, - {0x7f, 0x8c}, - {0x00, 0x2e}, - {0x20, 0x40}, - {0x21, 0x00}, - {0x22, 0x00}, - {0x23, 0x00}, -//Register Tuning - {0x00, 0x00}, - {0x7f, 0x00}, - {0x00, 0x00}, - {0x30, 0x00}, - {0x60, 0x00}, - {0x62, 0x00}, - {0x00, 0x00}, - {0x7f, 0x00}, - {0x00, 0x00}, - {0x4c, 0x30}, - {0x4d, 0x30}, - {0x00, 0x00}, - {0x7f, 0x00}, - {0x00, 0x00}, - {0x02, 0x00}, - {0x00, 0x00}, - {0x7f, 0x00}, - {0x00, 0x00}, - {0x03, 0x03}, - {0x35, 0x11}, +//#define TAS5805_REGISTER_COUNT 1879 + +static const int tas5805m_reset[][2] = { +//RESET + { 0x00, 0x00 }, + { 0x7f, 0x00 }, + { 0x03, 0x02 }, + { 0x01, 0x11 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x7f, 0x00 }, + { 0x03, 0x02 }, }; + +static const int tas5805m_init_sequence[][2] = { + { 0x00, 0x00 }, + { 0x7f, 0x00 }, + { 0x03, 0x00 }, + { 0x00, 0x00 }, + { 0x7f, 0x00 }, + { 0x46, 0x11 }, + + { 0x00, 0x00 }, + { 0x7f, 0x00 }, + { 0x03, 0x02 }, + { 0x00, 0x00 }, + { 0x7f, 0x00 }, + { 0x78, 0x80 }, + + { 0x00, 0x00 }, + { 0x7f, 0x00 }, + { 0x61, 0x0b }, + { 0x60, 0x01 }, + + { 0x00, 0x00 }, + { 0x02, 0x11 },//Fsw=384kHz, BD Mode, 1SPW Mode + { 0x66, 0x85 }, + { 0x6b, 0x03 },//Enable SS + { 0x6c, 0x03 },//Set Tri-freq to 24Hz, SS range 336~432kHz + { 0x3a, 0xf8 }, + { 0x53, 0x00 }, + { 0x54, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + { 0x00, 0x00 }, + + { 0x00, 0x00 }, + { 0x7f, 0x00 }, + { 0x66, 0x87 }, + { 0x7f, 0x8c }, + { 0x00, 0x29 }, + { 0x18, 0x00 }, + { 0x19, 0x80 }, + { 0x1a, 0x00 }, + { 0x1b, 0x00 }, + { 0x1c, 0x00 }, + { 0x1d, 0x00 }, + { 0x1e, 0x00 }, + { 0x1f, 0x00 }, + { 0x20, 0x00 }, + { 0x21, 0x00 }, + { 0x22, 0x00 }, + { 0x23, 0x00 }, + { 0x24, 0x00 }, + { 0x25, 0x80 }, + { 0x26, 0x00 }, + { 0x27, 0x00 }, + { 0x00, 0x2a }, + { 0x24, 0x00 }, + { 0x25, 0x28 }, + { 0x26, 0x7a }, + { 0x27, 0x27 }, + { 0x28, 0x00 }, + { 0x29, 0x28 }, + { 0x2a, 0x7a }, + { 0x2b, 0x27 }, + { 0x30, 0x00 }, + { 0x31, 0xe2 }, + { 0x32, 0xc4 }, + { 0x33, 0x6b }, + { 0x00, 0x2c }, + { 0x0c, 0x00 }, + { 0x0d, 0x00 }, + { 0x0e, 0x00 }, + { 0x0f, 0x00 }, + { 0x10, 0x00 }, + { 0x11, 0x00 }, + { 0x12, 0x00 }, + { 0x13, 0x00 }, + { 0x14, 0x00 }, + { 0x15, 0x80 }, + { 0x16, 0x00 }, + { 0x17, 0x00 }, + { 0x18, 0x00 }, + { 0x19, 0x00 }, + { 0x1a, 0x00 }, + { 0x1b, 0x00 }, + { 0x1c, 0x00 }, + { 0x1d, 0x80 }, + { 0x1e, 0x00 }, + { 0x1f, 0x00 }, + { 0x20, 0x00 }, + { 0x21, 0x00 }, + { 0x22, 0x00 }, + { 0x23, 0x00 }, + { 0x28, 0x00 }, + { 0x29, 0x00 }, + { 0x2a, 0x00 }, + { 0x2b, 0x00 }, + { 0x2c, 0x00 }, + { 0x2d, 0x80 }, + { 0x2e, 0x00 }, + { 0x2f, 0x00 }, + { 0x34, 0x00 }, + { 0x35, 0x80 }, + { 0x36, 0x00 }, + { 0x37, 0x00 }, + { 0x38, 0x00 }, + { 0x39, 0x00 }, + { 0x3a, 0x00 }, + { 0x3b, 0x00 }, + { 0x48, 0x00 }, + { 0x49, 0x00 }, + { 0x4a, 0x00 }, + { 0x4b, 0x00 }, + { 0x4c, 0x00 }, + { 0x4d, 0x80 }, + { 0x4e, 0x00 }, + { 0x4f, 0x00 }, + { 0x5c, 0x00 }, + { 0x5d, 0x00 }, + { 0x5e, 0xae }, + { 0x5f, 0xc3 }, + { 0x60, 0x01 }, + { 0x61, 0x12 }, + { 0x62, 0x6e }, + { 0x63, 0x98 }, + { 0x64, 0x08 }, + { 0x65, 0x13 }, + { 0x66, 0x85 }, + { 0x67, 0x62 }, + { 0x68, 0x40 }, + { 0x69, 0x00 }, + { 0x6a, 0x00 }, + { 0x6b, 0x00 }, + { 0x6c, 0x04 }, + { 0x6d, 0xc1 }, + { 0x6e, 0xff }, + { 0x6f, 0x93 }, + { 0x00, 0x2d }, + { 0x18, 0x7b }, + { 0x19, 0x3e }, + { 0x1a, 0x00 }, + { 0x1b, 0x6d }, + { 0x1c, 0x00 }, + { 0x1d, 0x00 }, + { 0x1e, 0xae }, + { 0x1f, 0xc3 }, + { 0x20, 0x00 }, + { 0x21, 0x00 }, + { 0x22, 0x00 }, + { 0x23, 0x00 }, + { 0x24, 0x00 }, + { 0x25, 0x00 }, + { 0x26, 0x00 }, + { 0x27, 0x00 }, + { 0x28, 0x00 }, + { 0x29, 0x00 }, + { 0x2a, 0x00 }, + { 0x2b, 0x00 }, + { 0x2c, 0x00 }, + { 0x2d, 0x80 }, + { 0x2e, 0x00 }, + { 0x2f, 0x00 }, + { 0x00, 0x00 }, + { 0x7f, 0xaa }, + { 0x00, 0x24 }, + { 0x18, 0x08 }, + { 0x19, 0x00 }, + { 0x1a, 0x00 }, + { 0x1b, 0x00 }, + { 0x1c, 0x00 }, + { 0x1d, 0x00 }, + { 0x1e, 0x00 }, + { 0x1f, 0x00 }, + { 0x20, 0x00 }, + { 0x21, 0x00 }, + { 0x22, 0x00 }, + { 0x23, 0x00 }, + { 0x24, 0x00 }, + { 0x25, 0x00 }, + { 0x26, 0x00 }, + { 0x27, 0x00 }, + { 0x28, 0x00 }, + { 0x29, 0x00 }, + { 0x2a, 0x00 }, + { 0x2b, 0x00 }, + { 0x2c, 0x08 }, + { 0x2d, 0x00 }, + { 0x2e, 0x00 }, + { 0x2f, 0x00 }, + { 0x30, 0x00 }, + { 0x31, 0x00 }, + { 0x32, 0x00 }, + { 0x33, 0x00 }, + { 0x34, 0x00 }, + { 0x35, 0x00 }, + { 0x36, 0x00 }, + { 0x37, 0x00 }, + { 0x38, 0x00 }, + { 0x39, 0x00 }, + { 0x3a, 0x00 }, + { 0x3b, 0x00 }, + { 0x3c, 0x00 }, + { 0x3d, 0x00 }, + { 0x3e, 0x00 }, + { 0x3f, 0x00 }, + { 0x40, 0x08 }, + { 0x41, 0x00 }, + { 0x42, 0x00 }, + { 0x43, 0x00 }, + { 0x44, 0x00 }, + { 0x45, 0x00 }, + { 0x46, 0x00 }, + { 0x47, 0x00 }, + { 0x48, 0x00 }, + { 0x49, 0x00 }, + { 0x4a, 0x00 }, + { 0x4b, 0x00 }, + { 0x4c, 0x00 }, + { 0x4d, 0x00 }, + { 0x4e, 0x00 }, + { 0x4f, 0x00 }, + { 0x50, 0x00 }, + { 0x51, 0x00 }, + { 0x52, 0x00 }, + { 0x53, 0x00 }, + { 0x54, 0x08 }, + { 0x55, 0x00 }, + { 0x56, 0x00 }, + { 0x57, 0x00 }, + { 0x58, 0x00 }, + { 0x59, 0x00 }, + { 0x5a, 0x00 }, + { 0x5b, 0x00 }, + { 0x5c, 0x00 }, + { 0x5d, 0x00 }, + { 0x5e, 0x00 }, + { 0x5f, 0x00 }, + { 0x60, 0x00 }, + { 0x61, 0x00 }, + { 0x62, 0x00 }, + { 0x63, 0x00 }, + { 0x64, 0x00 }, + { 0x65, 0x00 }, + { 0x66, 0x00 }, + { 0x67, 0x00 }, + { 0x68, 0x08 }, + { 0x69, 0x00 }, + { 0x6a, 0x00 }, + { 0x6b, 0x00 }, + { 0x6c, 0x00 }, + { 0x6d, 0x00 }, + { 0x6e, 0x00 }, + { 0x6f, 0x00 }, + { 0x70, 0x00 }, + { 0x71, 0x00 }, + { 0x72, 0x00 }, + { 0x73, 0x00 }, + { 0x74, 0x00 }, + { 0x75, 0x00 }, + { 0x76, 0x00 }, + { 0x77, 0x00 }, + { 0x78, 0x00 }, + { 0x79, 0x00 }, + { 0x7a, 0x00 }, + { 0x7b, 0x00 }, + { 0x7c, 0x08 }, + { 0x7d, 0x00 }, + { 0x7e, 0x00 }, + { 0x7f, 0x00 }, + { 0x00, 0x25 }, + { 0x08, 0x00 }, + { 0x09, 0x00 }, + { 0x0a, 0x00 }, + { 0x0b, 0x00 }, + { 0x0c, 0x00 }, + { 0x0d, 0x00 }, + { 0x0e, 0x00 }, + { 0x0f, 0x00 }, + { 0x10, 0x00 }, + { 0x11, 0x00 }, + { 0x12, 0x00 }, + { 0x13, 0x00 }, + { 0x14, 0x00 }, + { 0x15, 0x00 }, + { 0x16, 0x00 }, + { 0x17, 0x00 }, + { 0x18, 0x08 }, + { 0x19, 0x00 }, + { 0x1a, 0x00 }, + { 0x1b, 0x00 }, + { 0x1c, 0x00 }, + { 0x1d, 0x00 }, + { 0x1e, 0x00 }, + { 0x1f, 0x00 }, + { 0x20, 0x00 }, + { 0x21, 0x00 }, + { 0x22, 0x00 }, + { 0x23, 0x00 }, + { 0x24, 0x00 }, + { 0x25, 0x00 }, + { 0x26, 0x00 }, + { 0x27, 0x00 }, + { 0x28, 0x00 }, + { 0x29, 0x00 }, + { 0x2a, 0x00 }, + { 0x2b, 0x00 }, + { 0x2c, 0x08 }, + { 0x2d, 0x00 }, + { 0x2e, 0x00 }, + { 0x2f, 0x00 }, + { 0x30, 0x00 }, + { 0x31, 0x00 }, + { 0x32, 0x00 }, + { 0x33, 0x00 }, + { 0x34, 0x00 }, + { 0x35, 0x00 }, + { 0x36, 0x00 }, + { 0x37, 0x00 }, + { 0x38, 0x00 }, + { 0x39, 0x00 }, + { 0x3a, 0x00 }, + { 0x3b, 0x00 }, + { 0x3c, 0x00 }, + { 0x3d, 0x00 }, + { 0x3e, 0x00 }, + { 0x3f, 0x00 }, + { 0x40, 0x08 }, + { 0x41, 0x00 }, + { 0x42, 0x00 }, + { 0x43, 0x00 }, + { 0x44, 0x00 }, + { 0x45, 0x00 }, + { 0x46, 0x00 }, + { 0x47, 0x00 }, + { 0x48, 0x00 }, + { 0x49, 0x00 }, + { 0x4a, 0x00 }, + { 0x4b, 0x00 }, + { 0x4c, 0x00 }, + { 0x4d, 0x00 }, + { 0x4e, 0x00 }, + { 0x4f, 0x00 }, + { 0x50, 0x00 }, + { 0x51, 0x00 }, + { 0x52, 0x00 }, + { 0x53, 0x00 }, + { 0x54, 0x08 }, + { 0x55, 0x00 }, + { 0x56, 0x00 }, + { 0x57, 0x00 }, + { 0x58, 0x00 }, + { 0x59, 0x00 }, + { 0x5a, 0x00 }, + { 0x5b, 0x00 }, + { 0x5c, 0x00 }, + { 0x5d, 0x00 }, + { 0x5e, 0x00 }, + { 0x5f, 0x00 }, + { 0x60, 0x00 }, + { 0x61, 0x00 }, + { 0x62, 0x00 }, + { 0x63, 0x00 }, + { 0x64, 0x00 }, + { 0x65, 0x00 }, + { 0x66, 0x00 }, + { 0x67, 0x00 }, + { 0x68, 0x08 }, + { 0x69, 0x00 }, + { 0x6a, 0x00 }, + { 0x6b, 0x00 }, + { 0x6c, 0x00 }, + { 0x6d, 0x00 }, + { 0x6e, 0x00 }, + { 0x6f, 0x00 }, + { 0x70, 0x00 }, + { 0x71, 0x00 }, + { 0x72, 0x00 }, + { 0x73, 0x00 }, + { 0x74, 0x00 }, + { 0x75, 0x00 }, + { 0x76, 0x00 }, + { 0x77, 0x00 }, + { 0x78, 0x00 }, + { 0x79, 0x00 }, + { 0x7a, 0x00 }, + { 0x7b, 0x00 }, + { 0x7c, 0x08 }, + { 0x7d, 0x00 }, + { 0x7e, 0x00 }, + { 0x7f, 0x00 }, + { 0x00, 0x26 }, + { 0x08, 0x00 }, + { 0x09, 0x00 }, + { 0x0a, 0x00 }, + { 0x0b, 0x00 }, + { 0x0c, 0x00 }, + { 0x0d, 0x00 }, + { 0x0e, 0x00 }, + { 0x0f, 0x00 }, + { 0x10, 0x00 }, + { 0x11, 0x00 }, + { 0x12, 0x00 }, + { 0x13, 0x00 }, + { 0x14, 0x00 }, + { 0x15, 0x00 }, + { 0x16, 0x00 }, + { 0x17, 0x00 }, + { 0x18, 0x08 }, + { 0x19, 0x00 }, + { 0x1a, 0x00 }, + { 0x1b, 0x00 }, + { 0x1c, 0x00 }, + { 0x1d, 0x00 }, + { 0x1e, 0x00 }, + { 0x1f, 0x00 }, + { 0x20, 0x00 }, + { 0x21, 0x00 }, + { 0x22, 0x00 }, + { 0x23, 0x00 }, + { 0x24, 0x00 }, + { 0x25, 0x00 }, + { 0x26, 0x00 }, + { 0x27, 0x00 }, + { 0x28, 0x00 }, + { 0x29, 0x00 }, + { 0x2a, 0x00 }, + { 0x2b, 0x00 }, + { 0x2c, 0x08 }, + { 0x2d, 0x00 }, + { 0x2e, 0x00 }, + { 0x2f, 0x00 }, + { 0x30, 0x00 }, + { 0x31, 0x00 }, + { 0x32, 0x00 }, + { 0x33, 0x00 }, + { 0x34, 0x00 }, + { 0x35, 0x00 }, + { 0x36, 0x00 }, + { 0x37, 0x00 }, + { 0x38, 0x00 }, + { 0x39, 0x00 }, + { 0x3a, 0x00 }, + { 0x3b, 0x00 }, + { 0x3c, 0x00 }, + { 0x3d, 0x00 }, + { 0x3e, 0x00 }, + { 0x3f, 0x00 }, + { 0x40, 0x08 }, + { 0x41, 0x00 }, + { 0x42, 0x00 }, + { 0x43, 0x00 }, + { 0x44, 0x00 }, + { 0x45, 0x00 }, + { 0x46, 0x00 }, + { 0x47, 0x00 }, + { 0x48, 0x00 }, + { 0x49, 0x00 }, + { 0x4a, 0x00 }, + { 0x4b, 0x00 }, + { 0x4c, 0x00 }, + { 0x4d, 0x00 }, + { 0x4e, 0x00 }, + { 0x4f, 0x00 }, + { 0x50, 0x00 }, + { 0x51, 0x00 }, + { 0x52, 0x00 }, + { 0x53, 0x00 }, + { 0x54, 0x08 }, + { 0x55, 0x00 }, + { 0x56, 0x00 }, + { 0x57, 0x00 }, + { 0x58, 0x00 }, + { 0x59, 0x00 }, + { 0x5a, 0x00 }, + { 0x5b, 0x00 }, + { 0x5c, 0x00 }, + { 0x5d, 0x00 }, + { 0x5e, 0x00 }, + { 0x5f, 0x00 }, + { 0x60, 0x00 }, + { 0x61, 0x00 }, + { 0x62, 0x00 }, + { 0x63, 0x00 }, + { 0x64, 0x00 }, + { 0x65, 0x00 }, + { 0x66, 0x00 }, + { 0x67, 0x00 }, + { 0x68, 0x08 }, + { 0x69, 0x00 }, + { 0x6a, 0x00 }, + { 0x6b, 0x00 }, + { 0x6c, 0x00 }, + { 0x6d, 0x00 }, + { 0x6e, 0x00 }, + { 0x6f, 0x00 }, + { 0x70, 0x00 }, + { 0x71, 0x00 }, + { 0x72, 0x00 }, + { 0x73, 0x00 }, + { 0x74, 0x00 }, + { 0x75, 0x00 }, + { 0x76, 0x00 }, + { 0x77, 0x00 }, + { 0x78, 0x00 }, + { 0x79, 0x00 }, + { 0x7a, 0x00 }, + { 0x7b, 0x00 }, + { 0x7c, 0x08 }, + { 0x7d, 0x00 }, + { 0x7e, 0x00 }, + { 0x7f, 0x00 }, + { 0x00, 0x27 }, + { 0x08, 0x00 }, + { 0x09, 0x00 }, + { 0x0a, 0x00 }, + { 0x0b, 0x00 }, + { 0x0c, 0x00 }, + { 0x0d, 0x00 }, + { 0x0e, 0x00 }, + { 0x0f, 0x00 }, + { 0x10, 0x00 }, + { 0x11, 0x00 }, + { 0x12, 0x00 }, + { 0x13, 0x00 }, + { 0x14, 0x00 }, + { 0x15, 0x00 }, + { 0x16, 0x00 }, + { 0x17, 0x00 }, + { 0x18, 0x08 }, + { 0x19, 0x00 }, + { 0x1a, 0x00 }, + { 0x1b, 0x00 }, + { 0x1c, 0x00 }, + { 0x1d, 0x00 }, + { 0x1e, 0x00 }, + { 0x1f, 0x00 }, + { 0x20, 0x00 }, + { 0x21, 0x00 }, + { 0x22, 0x00 }, + { 0x23, 0x00 }, + { 0x24, 0x00 }, + { 0x25, 0x00 }, + { 0x26, 0x00 }, + { 0x27, 0x00 }, + { 0x28, 0x00 }, + { 0x29, 0x00 }, + { 0x2a, 0x00 }, + { 0x2b, 0x00 }, + { 0x2c, 0x08 }, + { 0x2d, 0x00 }, + { 0x2e, 0x00 }, + { 0x2f, 0x00 }, + { 0x30, 0x00 }, + { 0x31, 0x00 }, + { 0x32, 0x00 }, + { 0x33, 0x00 }, + { 0x34, 0x00 }, + { 0x35, 0x00 }, + { 0x36, 0x00 }, + { 0x37, 0x00 }, + { 0x38, 0x00 }, + { 0x39, 0x00 }, + { 0x3a, 0x00 }, + { 0x3b, 0x00 }, + { 0x3c, 0x00 }, + { 0x3d, 0x00 }, + { 0x3e, 0x00 }, + { 0x3f, 0x00 }, + { 0x40, 0x08 }, + { 0x41, 0x00 }, + { 0x42, 0x00 }, + { 0x43, 0x00 }, + { 0x44, 0x00 }, + { 0x45, 0x00 }, + { 0x46, 0x00 }, + { 0x47, 0x00 }, + { 0x48, 0x00 }, + { 0x49, 0x00 }, + { 0x4a, 0x00 }, + { 0x4b, 0x00 }, + { 0x4c, 0x00 }, + { 0x4d, 0x00 }, + { 0x4e, 0x00 }, + { 0x4f, 0x00 }, + { 0x50, 0x00 }, + { 0x51, 0x00 }, + { 0x52, 0x00 }, + { 0x53, 0x00 }, + { 0x54, 0x08 }, + { 0x55, 0x00 }, + { 0x56, 0x00 }, + { 0x57, 0x00 }, + { 0x58, 0x00 }, + { 0x59, 0x00 }, + { 0x5a, 0x00 }, + { 0x5b, 0x00 }, + { 0x5c, 0x00 }, + { 0x5d, 0x00 }, + { 0x5e, 0x00 }, + { 0x5f, 0x00 }, + { 0x60, 0x00 }, + { 0x61, 0x00 }, + { 0x62, 0x00 }, + { 0x63, 0x00 }, + { 0x64, 0x00 }, + { 0x65, 0x00 }, + { 0x66, 0x00 }, + { 0x67, 0x00 }, + { 0x68, 0x08 }, + { 0x69, 0x00 }, + { 0x6a, 0x00 }, + { 0x6b, 0x00 }, + { 0x6c, 0x00 }, + { 0x6d, 0x00 }, + { 0x6e, 0x00 }, + { 0x6f, 0x00 }, + { 0x70, 0x00 }, + { 0x71, 0x00 }, + { 0x72, 0x00 }, + { 0x73, 0x00 }, + { 0x74, 0x00 }, + { 0x75, 0x00 }, + { 0x76, 0x00 }, + { 0x77, 0x00 }, + { 0x78, 0x00 }, + { 0x79, 0x00 }, + { 0x7a, 0x00 }, + { 0x7b, 0x00 }, + { 0x7c, 0x08 }, + { 0x7d, 0x00 }, + { 0x7e, 0x00 }, + { 0x7f, 0x00 }, + { 0x00, 0x28 }, + { 0x08, 0x00 }, + { 0x09, 0x00 }, + { 0x0a, 0x00 }, + { 0x0b, 0x00 }, + { 0x0c, 0x00 }, + { 0x0d, 0x00 }, + { 0x0e, 0x00 }, + { 0x0f, 0x00 }, + { 0x10, 0x00 }, + { 0x11, 0x00 }, + { 0x12, 0x00 }, + { 0x13, 0x00 }, + { 0x14, 0x00 }, + { 0x15, 0x00 }, + { 0x16, 0x00 }, + { 0x17, 0x00 }, + { 0x18, 0x08 }, + { 0x19, 0x00 }, + { 0x1a, 0x00 }, + { 0x1b, 0x00 }, + { 0x1c, 0x00 }, + { 0x1d, 0x00 }, + { 0x1e, 0x00 }, + { 0x1f, 0x00 }, + { 0x20, 0x00 }, + { 0x21, 0x00 }, + { 0x22, 0x00 }, + { 0x23, 0x00 }, + { 0x24, 0x00 }, + { 0x25, 0x00 }, + { 0x26, 0x00 }, + { 0x27, 0x00 }, + { 0x28, 0x00 }, + { 0x29, 0x00 }, + { 0x2a, 0x00 }, + { 0x2b, 0x00 }, + { 0x2c, 0x08 }, + { 0x2d, 0x00 }, + { 0x2e, 0x00 }, + { 0x2f, 0x00 }, + { 0x30, 0x00 }, + { 0x31, 0x00 }, + { 0x32, 0x00 }, + { 0x33, 0x00 }, + { 0x34, 0x00 }, + { 0x35, 0x00 }, + { 0x36, 0x00 }, + { 0x37, 0x00 }, + { 0x38, 0x00 }, + { 0x39, 0x00 }, + { 0x3a, 0x00 }, + { 0x3b, 0x00 }, + { 0x3c, 0x00 }, + { 0x3d, 0x00 }, + { 0x3e, 0x00 }, + { 0x3f, 0x00 }, + { 0x40, 0x08 }, + { 0x41, 0x00 }, + { 0x42, 0x00 }, + { 0x43, 0x00 }, + { 0x44, 0x00 }, + { 0x45, 0x00 }, + { 0x46, 0x00 }, + { 0x47, 0x00 }, + { 0x48, 0x00 }, + { 0x49, 0x00 }, + { 0x4a, 0x00 }, + { 0x4b, 0x00 }, + { 0x4c, 0x00 }, + { 0x4d, 0x00 }, + { 0x4e, 0x00 }, + { 0x4f, 0x00 }, + { 0x50, 0x00 }, + { 0x51, 0x00 }, + { 0x52, 0x00 }, + { 0x53, 0x00 }, + { 0x54, 0x08 }, + { 0x55, 0x00 }, + { 0x56, 0x00 }, + { 0x57, 0x00 }, + { 0x58, 0x00 }, + { 0x59, 0x00 }, + { 0x5a, 0x00 }, + { 0x5b, 0x00 }, + { 0x5c, 0x00 }, + { 0x5d, 0x00 }, + { 0x5e, 0x00 }, + { 0x5f, 0x00 }, + { 0x60, 0x00 }, + { 0x61, 0x00 }, + { 0x62, 0x00 }, + { 0x63, 0x00 }, + { 0x64, 0x00 }, + { 0x65, 0x00 }, + { 0x66, 0x00 }, + { 0x67, 0x00 }, + { 0x68, 0x08 }, + { 0x69, 0x00 }, + { 0x6a, 0x00 }, + { 0x6b, 0x00 }, + { 0x6c, 0x00 }, + { 0x6d, 0x00 }, + { 0x6e, 0x00 }, + { 0x6f, 0x00 }, + { 0x70, 0x00 }, + { 0x71, 0x00 }, + { 0x72, 0x00 }, + { 0x73, 0x00 }, + { 0x74, 0x00 }, + { 0x75, 0x00 }, + { 0x76, 0x00 }, + { 0x77, 0x00 }, + { 0x78, 0x00 }, + { 0x79, 0x00 }, + { 0x7a, 0x00 }, + { 0x7b, 0x00 }, + { 0x7c, 0x08 }, + { 0x7d, 0x00 }, + { 0x7e, 0x00 }, + { 0x7f, 0x00 }, + { 0x00, 0x29 }, + { 0x08, 0x00 }, + { 0x09, 0x00 }, + { 0x0a, 0x00 }, + { 0x0b, 0x00 }, + { 0x0c, 0x00 }, + { 0x0d, 0x00 }, + { 0x0e, 0x00 }, + { 0x0f, 0x00 }, + { 0x10, 0x00 }, + { 0x11, 0x00 }, + { 0x12, 0x00 }, + { 0x13, 0x00 }, + { 0x14, 0x00 }, + { 0x15, 0x00 }, + { 0x16, 0x00 }, + { 0x17, 0x00 }, + { 0x00, 0x2e }, + { 0x7c, 0x08 }, + { 0x7d, 0x00 }, + { 0x7e, 0x00 }, + { 0x7f, 0x00 }, + { 0x00, 0x2f }, + { 0x08, 0x00 }, + { 0x09, 0x00 }, + { 0x0a, 0x00 }, + { 0x0b, 0x00 }, + { 0x0c, 0x00 }, + { 0x0d, 0x00 }, + { 0x0e, 0x00 }, + { 0x0f, 0x00 }, + { 0x10, 0x00 }, + { 0x11, 0x00 }, + { 0x12, 0x00 }, + { 0x13, 0x00 }, + { 0x14, 0x00 }, + { 0x15, 0x00 }, + { 0x16, 0x00 }, + { 0x17, 0x00 }, + { 0x1c, 0x08 }, + { 0x1d, 0x00 }, + { 0x1e, 0x00 }, + { 0x1f, 0x00 }, + { 0x20, 0x00 }, + { 0x21, 0x00 }, + { 0x22, 0x00 }, + { 0x23, 0x00 }, + { 0x24, 0x00 }, + { 0x25, 0x00 }, + { 0x26, 0x00 }, + { 0x27, 0x00 }, + { 0x28, 0x00 }, + { 0x29, 0x00 }, + { 0x2a, 0x00 }, + { 0x2b, 0x00 }, + { 0x2c, 0x00 }, + { 0x2d, 0x00 }, + { 0x2e, 0x00 }, + { 0x2f, 0x00 }, + { 0x00, 0x2a }, + { 0x48, 0x00 }, + { 0x49, 0x05 }, + { 0x4a, 0x83 }, + { 0x4b, 0x2a }, + { 0x4c, 0x00 }, + { 0x4d, 0x05 }, + { 0x4e, 0x83 }, + { 0x4f, 0x2a }, + { 0x50, 0x00 }, + { 0x51, 0x05 }, + { 0x52, 0x83 }, + { 0x53, 0x2a }, + { 0x54, 0x7d }, + { 0x55, 0xa1 }, + { 0x56, 0x77 }, + { 0x57, 0x3d }, + { 0x58, 0x84 }, + { 0x59, 0xa7 }, + { 0x5a, 0x04 }, + { 0x5b, 0xdf }, + { 0x00, 0x00 }, + { 0x7f, 0x8c }, + { 0x00, 0x2b }, + { 0x34, 0x00 }, + { 0x35, 0x1b }, + { 0x36, 0x4b }, + { 0x37, 0x98 }, + { 0x38, 0x00 }, + { 0x39, 0x1b }, + { 0x3a, 0x4b }, + { 0x3b, 0x98 }, + { 0x3c, 0x00 }, + { 0x3d, 0x0d }, + { 0x3e, 0xa6 }, + { 0x3f, 0x86 }, + { 0x40, 0x00 }, + { 0x41, 0x00 }, + { 0x42, 0x00 }, + { 0x43, 0x00 }, + { 0x44, 0x00 }, + { 0x45, 0x00 }, + { 0x46, 0x00 }, + { 0x47, 0x00 }, + { 0x48, 0xff }, + { 0x49, 0x81 }, + { 0x4a, 0x47 }, + { 0x4b, 0xae }, + { 0x4c, 0xf9 }, + { 0x4d, 0x06 }, + { 0x4e, 0x21 }, + { 0x4f, 0xa9 }, + { 0x50, 0xfe }, + { 0x51, 0x01 }, + { 0x52, 0xc0 }, + { 0x53, 0x79 }, + { 0x54, 0x00 }, + { 0x55, 0x00 }, + { 0x56, 0x00 }, + { 0x57, 0x00 }, + { 0x58, 0x00 }, + { 0x59, 0x00 }, + { 0x5a, 0x00 }, + { 0x5b, 0x00 }, + { 0x00, 0x2d }, + { 0x58, 0x02 }, + { 0x59, 0xa3 }, + { 0x5a, 0x9a }, + { 0x5b, 0xcc }, + { 0x5c, 0x02 }, + { 0x5d, 0xa3 }, + { 0x5e, 0x9a }, + { 0x5f, 0xcc }, + { 0x60, 0x00 }, + { 0x61, 0x44 }, + { 0x62, 0x32 }, + { 0x63, 0x13 }, + { 0x64, 0x00 }, + { 0x65, 0x00 }, + { 0x66, 0x00 }, + { 0x67, 0x00 }, + { 0x68, 0x00 }, + { 0x69, 0x00 }, + { 0x6a, 0x00 }, + { 0x6b, 0x00 }, + { 0x6c, 0xff }, + { 0x6d, 0x81 }, + { 0x6e, 0x47 }, + { 0x6f, 0xae }, + { 0x70, 0xf9 }, + { 0x71, 0x06 }, + { 0x72, 0x21 }, + { 0x73, 0xa9 }, + { 0x74, 0xfe }, + { 0x75, 0x01 }, + { 0x76, 0xc0 }, + { 0x77, 0x79 }, + { 0x78, 0x00 }, + { 0x79, 0x00 }, + { 0x7a, 0x00 }, + { 0x7b, 0x00 }, + { 0x7c, 0x00 }, + { 0x7d, 0x00 }, + { 0x7e, 0x00 }, + { 0x7f, 0x00 }, + { 0x00, 0x00 }, + { 0x7f, 0xaa }, + { 0x00, 0x2e }, + { 0x40, 0x06 }, + { 0x41, 0x55 }, + { 0x42, 0xaf }, + { 0x43, 0xd8 }, + { 0x44, 0x06 }, + { 0x45, 0x55 }, + { 0x46, 0xaf }, + { 0x47, 0xd8 }, + { 0x48, 0x06 }, + { 0x49, 0x55 }, + { 0x4a, 0xaf }, + { 0x4b, 0xd8 }, + { 0x4c, 0x51 }, + { 0x4d, 0xe5 }, + { 0x4e, 0x7f }, + { 0x4f, 0x65 }, + { 0x50, 0xc2 }, + { 0x51, 0xde }, + { 0x52, 0x41 }, + { 0x53, 0xd5 }, + { 0x00, 0x2b }, + { 0x20, 0x58 }, + { 0x21, 0x3b }, + { 0x22, 0x2f }, + { 0x23, 0x3d }, + { 0x24, 0xa7 }, + { 0x25, 0xc4 }, + { 0x26, 0xd0 }, + { 0x27, 0xc3 }, + { 0x28, 0x58 }, + { 0x29, 0x3b }, + { 0x2a, 0x2f }, + { 0x2b, 0x3d }, + { 0x2c, 0x51 }, + { 0x2d, 0xe5 }, + { 0x2e, 0x7f }, + { 0x2f, 0x65 }, + { 0x30, 0xc2 }, + { 0x31, 0xde }, + { 0x32, 0x41 }, + { 0x33, 0xd5 }, + { 0x0c, 0x58 }, + { 0x0d, 0x3b }, + { 0x0e, 0x2f }, + { 0x0f, 0x3d }, + { 0x10, 0xa7 }, + { 0x11, 0xc4 }, + { 0x12, 0xd0 }, + { 0x13, 0xc3 }, + { 0x14, 0x58 }, + { 0x15, 0x3b }, + { 0x16, 0x2f }, + { 0x17, 0x3d }, + { 0x18, 0x51 }, + { 0x19, 0xe5 }, + { 0x1a, 0x7f }, + { 0x1b, 0x65 }, + { 0x1c, 0xc2 }, + { 0x1d, 0xde }, + { 0x1e, 0x41 }, + { 0x1f, 0xd5 }, + { 0x00, 0x2a }, + { 0x34, 0x00 }, + { 0x35, 0x05 }, + { 0x36, 0x83 }, + { 0x37, 0x2a }, + { 0x38, 0x00 }, + { 0x39, 0x05 }, + { 0x3a, 0x83 }, + { 0x3b, 0x2a }, + { 0x3c, 0x00 }, + { 0x3d, 0x05 }, + { 0x3e, 0x83 }, + { 0x3f, 0x2a }, + { 0x40, 0x7d }, + { 0x41, 0xa1 }, + { 0x42, 0x77 }, + { 0x43, 0x3d }, + { 0x44, 0x84 }, + { 0x45, 0xa7 }, + { 0x46, 0x04 }, + { 0x47, 0xdf }, + { 0x00, 0x00 }, + { 0x7f, 0x8c }, + { 0x00, 0x2d }, + { 0x30, 0x02 }, + { 0x31, 0xa3 }, + { 0x32, 0x9a }, + { 0x33, 0xcc }, + { 0x34, 0x02 }, + { 0x35, 0xa3 }, + { 0x36, 0x9a }, + { 0x37, 0xcc }, + { 0x38, 0x00 }, + { 0x39, 0x06 }, + { 0x3a, 0xd3 }, + { 0x3b, 0x72 }, + { 0x3c, 0x00 }, + { 0x3d, 0x00 }, + { 0x3e, 0x00 }, + { 0x3f, 0x00 }, + { 0x40, 0x00 }, + { 0x41, 0x00 }, + { 0x42, 0x00 }, + { 0x43, 0x00 }, + { 0x44, 0xff }, + { 0x45, 0x81 }, + { 0x46, 0x47 }, + { 0x47, 0xae }, + { 0x48, 0xf9 }, + { 0x49, 0x06 }, + { 0x4a, 0x21 }, + { 0x4b, 0xa9 }, + { 0x4c, 0xfe }, + { 0x4d, 0x01 }, + { 0x4e, 0xc0 }, + { 0x4f, 0x79 }, + { 0x50, 0x00 }, + { 0x51, 0x00 }, + { 0x52, 0x00 }, + { 0x53, 0x00 }, + { 0x54, 0x00 }, + { 0x55, 0x00 }, + { 0x56, 0x00 }, + { 0x57, 0x00 }, + { 0x00, 0x00 }, + { 0x7f, 0xaa }, + { 0x00, 0x2a }, + { 0x5c, 0x7d }, + { 0x5d, 0xa6 }, + { 0x5e, 0xfa }, + { 0x5f, 0x66 }, + { 0x60, 0x82 }, + { 0x61, 0x59 }, + { 0x62, 0x05 }, + { 0x63, 0x9a }, + { 0x64, 0x7d }, + { 0x65, 0xa6 }, + { 0x66, 0xfa }, + { 0x67, 0x66 }, + { 0x68, 0x7d }, + { 0x69, 0xa1 }, + { 0x6a, 0x77 }, + { 0x6b, 0x3d }, + { 0x6c, 0x84 }, + { 0x6d, 0xa7 }, + { 0x6e, 0x04 }, + { 0x6f, 0xdf }, + { 0x70, 0x7d }, + { 0x71, 0xa6 }, + { 0x72, 0xfa }, + { 0x73, 0x66 }, + { 0x74, 0x82 }, + { 0x75, 0x59 }, + { 0x76, 0x05 }, + { 0x77, 0x9a }, + { 0x78, 0x7d }, + { 0x79, 0xa6 }, + { 0x7a, 0xfa }, + { 0x7b, 0x66 }, + { 0x7c, 0x7d }, + { 0x7d, 0xa1 }, + { 0x7e, 0x77 }, + { 0x7f, 0x3d }, + { 0x00, 0x2b }, + { 0x08, 0x84 }, + { 0x09, 0xa7 }, + { 0x0a, 0x04 }, + { 0x0b, 0xdf }, + { 0x00, 0x2e }, + { 0x54, 0x06 }, + { 0x55, 0x55 }, + { 0x56, 0xaf }, + { 0x57, 0xd8 }, + { 0x58, 0x06 }, + { 0x59, 0x55 }, + { 0x5a, 0xaf }, + { 0x5b, 0xd8 }, + { 0x5c, 0x06 }, + { 0x5d, 0x55 }, + { 0x5e, 0xaf }, + { 0x5f, 0xd8 }, + { 0x60, 0x51 }, + { 0x61, 0xe5 }, + { 0x62, 0x7f }, + { 0x63, 0x65 }, + { 0x64, 0xc2 }, + { 0x65, 0xde }, + { 0x66, 0x41 }, + { 0x67, 0xd5 }, + { 0x00, 0x00 }, + { 0x7f, 0x8c }, + { 0x00, 0x2e }, + { 0x10, 0x00 }, + { 0x11, 0x80 }, + { 0x12, 0x00 }, + { 0x13, 0x00 }, + { 0x0c, 0x00 }, + { 0x0d, 0x80 }, + { 0x0e, 0x00 }, + { 0x0f, 0x00 }, + { 0x08, 0x00 }, + { 0x09, 0x80 }, + { 0x0a, 0x00 }, + { 0x0b, 0x00 }, + { 0x18, 0x00 }, + { 0x19, 0x80 }, + { 0x1a, 0x00 }, + { 0x1b, 0x00 }, + { 0x1c, 0x40 }, + { 0x1d, 0x00 }, + { 0x1e, 0x00 }, + { 0x1f, 0x00 }, + { 0x20, 0x40 }, + { 0x21, 0x00 }, + { 0x22, 0x00 }, + { 0x23, 0x00 }, + +//Register Tuning + { 0x00, 0x00 }, + { 0x7f, 0x00 }, + { 0x30, 0x00 }, + { 0x4c, 0x30 }, + { 0x03, 0x03 }, + { 0x02, 0x11 },//Fsw=384kHz, 1SPW Mode + + { 0x00, 0x00 }, + { 0x7f, 0x00 }, + { 0x78, 0x80 }, +}; + +struct tas5805m_platform_data { + int reset_pin; +}; +